Skip to Content.
Sympa Menu

ndt-dev - [ndt-dev] [ndt] r721 committed - Define all test heuristics, classify protocol/I_O functionality into a...

Subject: NDT-DEV email list created

List archive

[ndt-dev] [ndt] r721 committed - Define all test heuristics, classify protocol/I_O functionality into a...


Chronological Thread 
  • From:
  • To:
  • Subject: [ndt-dev] [ndt] r721 committed - Define all test heuristics, classify protocol/I_O functionality into a...
  • Date: Sun, 16 Oct 2011 22:37:56 +0000

Revision: 721
Author:

Date: Sun Oct 16 15:37:17 2011
Log: Define all test heuristics, classify protocol/I_O functionality into appropriate places , declare constant output types
http://code.google.com/p/ndt/source/detail?r=721

Added:
/branches/kkumar_code_organize/src/heuristics.c
/branches/kkumar_code_organize/src/heuristics.h
Modified:
/branches/kkumar_code_organize/src/Makefile.am
/branches/kkumar_code_organize/src/logging.c
/branches/kkumar_code_organize/src/logging.h
/branches/kkumar_code_organize/src/utils.h
/branches/kkumar_code_organize/src/web100-pcap.c
/branches/kkumar_code_organize/src/web100srv.c
/branches/kkumar_code_organize/src/web100srv.h

=======================================
--- /dev/null
+++ /branches/kkumar_code_organize/src/heuristics.c Sun Oct 16 15:37:17
2011
@@ -0,0 +1,684 @@
+/**
+ * This file contains algorithms and heuristics used to arrive various results in NDT
+ *
+ *
+ * Created : Oct 15, 2011
+ * Author:

+ */
+#include <string.h>
+#include <math.h>
+
+#include "utils.h"
+#include "logging.h"
+
+#define log_lvl_heur 0
+/**
+ * Compute link speed.
+ *
+ * Throughput is quantized into one of a group
+ * of pre-defined bins by incrementing the counter for that bin.
+ * Once the test is complete, determine link speed according to the bin
+ * with the largest counter value.
+ *
+ * The bins are defined in mbits/second.
+ *
+ * Value of bin Index : Value's meaning
+ * 0: 0 < inter-packet throughput (mbits/second) <= 0.01 - RTT
+ * 1: 0.01 < inter-packet throughput (mbits/second) <= 0.064 - Dial-up Modem
+ * 2: 0.064 < inter-packet throughput (mbits/second) <= 1.5 - Cable/DSL modem
+ * 3: 1.5 < inter-packet throughput (mbits/second) <= 10 - 10 Mbps Ethernet or WiFi 11b subnet
+ * 4: 10 < inter-packet throughput (mbits/second) <= 40 - 45 Mbps T3/DS3 or WiFi 11 a/g subnet
+ * 5: 40 < inter-packet throughput (mbits/second) <= 100 - 100 Mbps Fast Ethernet subnet
+ * 6: 100 < inter-packet throughput (mbits/second) <= 622 - a 622 Mbps OC-12 subnet
+ * 7: 622 < inter-packet throughput (mbits/second) <= 1000 - 1.0 Gbps Gigabit Ethernet subnet
+ * 8: 1000 < inter-packet throughput (mbits/second) <= 2400 - 2.4 Gbps OC-48 subnet
+ * 9: 2400 < inter-packet throughput (mbits/second) <= 10000 - 10 Gbps 10 Gigabit Ethernet/OC-192 subnet
+ * 10: bits cannot be determined - Retransmissions (this bin counts the duplicated or invalid packets and does not denote a real link type)
+ * otherwise - ?
+ *
+ * @param spds speed string array used ad speeb counter bins
+ * @param spd_index speed index indicating indices of the speend bin array
+ * @param c2sdata Data link speed as detected by server data
+ * @param c2sack Data link speed(type) as detected by server acknowledgements
+ * @param s2cdata Data link speed as detected by client data
+ * @param s2cack Data link speed as detected by client acknowledgements
+ * @param runave average run time?
+ * @param dec_cnt number of times window sizes have been decremented
+ * @param same_cnt number of times window sizes remained the same
+ * @param inc_cnt number of times window sizes have been incremented
+ * @param timeout number of times a timeout occured (based on network packet pair times)
+ * @param dupack number of times duplicate acks were received
+ * @param is_c2stest is this a C->S test?
+ *
+ * */
+void calc_linkspeed(char spds[4][256], int spd_index, int *c2sdata, int *c2sack,
+ int* s2cdata, int *s2cack, float runave[4], u_int32_t
*dec_cnt,
+ u_int32_t *same_cnt, u_int32_t *inc_cnt, int *timeout, int
*dupack,
+ int is_c2stest) {
+
+ int index = 0; // speed array indices
+ int links[16]; // link speed bin values
+ int n = 0, j = 0; // temporary iterator variables
+ int max; // max speed bin counter value
+ int total; // total of the bin counts, used to calculate percentage
+ int ifspeedlocal; // local if-speed indicator
+ FILE * fp; // log file pointer
+
+ for (n = 0; n < spd_index; n++) {
+ sscanf(spds + n,
+ "%d %d %d %d %d %d %d %d %d %d %d %d %f %d %d %d
%d %d %d",
+ &links[0], &links[1], &links[2], &links[3],
&links[4],
+ &links[5], &links[6], &links[7], &links[8],
&links[9],
+ &links[10], &links[11], runave + n, &inc_cnt,
&dec_cnt,
+ &same_cnt, &timeout, &dupack, &ifspeedlocal);
+ log_println(log_lvl_heur, " **First ele: spd=%s, runave=%f",
spds[n],
+ runave[n]);
+ max = 0;
+ index = 0;
+ total = 0;
+
+ if ((ifspeedlocal == -1) || (ifspeedlocal == 0) || (ifspeedlocal
> 10))
+ ifspeedlocal = 10; // ifspeed was probably not
collected in these cases
+
+ // get the ifspeed bin with the biggest counter value.
+ // NDT determines link speed using this
+ for (j = 0; j <= ifspeedlocal; j++) {
+ total += links[j];
+ if (max < links[j]) {
+ max = links[j];
+ index = j;
+ }
+ }
+
+ // speed data was not collected correctly
+ if (links[index] == -1)
+ index = -1;
+
+ // log
+ fp = fopen(get_logfile(), "a");
+ if (fp == NULL) {
+ log_println(
+ 0,
+ "Unable to open log file '%s', continuing
on without logging",
+ get_logfile());
+ } else {
+ // also print the percentage of the speed w.r.t total
speed bin counter
+ fprintf(fp, "spds[%d] = '%s' max=%d [%0.2f%%]\n", n,
spds[n], max,
+ (float) max * 100 / total);
+ fclose(fp);
+ }
+
+ // Assign values based on whether C2S or S2C test
+ // Note: spd[0] , [1] contains C->S test results
+ // spd[2] , spd [3] contains S->C test results
+ switch (n + (is_c2stest ? 0 : 2)) {
+ case 0:
+ *c2sdata = index;
+ log_print(log_lvl_heur, "Client --> Server data detects
link = ");
+ break;
+ case 1:
+ *c2sack = index;
+ log_print(log_lvl_heur, "Client <-- Server Ack's detect
link = ");
+ break;
+ case 2:
+ *s2cdata = index;
+ log_print(log_lvl_heur, "Server --> Client data detects
link = ");
+ break;
+ case 3:
+ *s2cack = index;
+ log_print(1, "Server <-- Client Ack's detect link =
");
+ break;
+ }
+
+ // classify link speed based on the max ifspeed seen
+ switch (index) {
+ case -1:
+ log_println(1, "System Fault");
+ break;
+ case 0:
+ log_println(1, "RTT");
+ break;
+ case 1:
+ log_println(1, "Dial-up");
+ break;
+ case 2:
+ log_println(1, "T1");
+ break;
+ case 3:
+ log_println(1, "Ethernet");
+ break;
+ case 4:
+ log_println(1, "T3");
+ break;
+ case 5:
+ log_println(1, "FastEthernet");
+ break;
+ case 6:
+ log_println(1, "OC-12");
+ break;
+ case 7:
+ log_println(1, "Gigabit Ethernet");
+ break;
+ case 8:
+ log_println(1, "OC-48");
+ break;
+ case 9:
+ log_println(1, "10 Gigabit Enet");
+ break;
+ case 10:
+ log_println(1, "Retransmissions");
+ break;
+ }
+ } //end section to determine speed.
+
+} //end method calc_linkspeed
+
+/**
+ * Calculate average round-trip-time in milliseconds.
+ * @param sumRTT - The sum of all sampled round trip times
+ * @param countRTT - The number of round trip time samples
+ * @return average round trip time
+ * */
+
+double calc_avg_rtt(int sumRTT, int countRTT, double *avgRTT) {
+ *avgRTT = (double) sumRTT / countRTT;
+ log_println(log_lvl_heur,
+ "-- Average round trip time= SumRTT (%d) over countRTT
(%d)=%f",
+ sumRTT, countRTT, (*avgRTT) * .001);
+ return ((*avgRTT) * .001);
+}
+
+/**
+ * Calculate packet loss as the percentage of the lost packets vs total txed segments
+ * during the Server-To-Client throughput test.
+ *
+ * To avoid possible division by zero, sets the packet loss percentages
+ * to certain values when the CongestionSignals is 0:
+ *
+ * 0.0000000001 - link-type detected by the Bottleneck Link Detection algorithm
+ * using the C-S data packets' inter-packet arrival times indicates > 100 Mbps Fast Ethernet subnet.
+ * 0.000001 - otherwise
+
+ * @param congsnsignals - number of multiplicative
+ * downward congestion window adjustments due to all
+ * forms of congestion signals
+ * @param pktsout total number Txed segments
+ * @param c2sdatalinkspd Integer indicative of link speed, ad collected in the C->S test
+ * @return packet loss value
+ * */
+double calc_packetloss(int congsnsignals, int pktsout, int c2sdatalinkspd) {
+ double packetloss = (double) congsnsignals / pktsout;
+ if (packetloss == 0) {
+ if (c2sdatalinkspd > 5)
+ packetloss = .0000000001; // set to 10^-10 for links
faster than FastE
+ else
+ packetloss = .000001; // set to 10^-6 otherwise
+ }
+ log_println(log_lvl_heur, "--packetloss=%d over %d=%f. Link spd=%d",
+ congsnsignals, pktsout, packetloss, c2sdatalinkspd);
+ return packetloss;
+}
+
+/**
+ * Calculate the percentage of packets arriving out of order.
+ * This is equal to the ratio of #duplicate acks over
+ * #actual acks recieved.
+ * @param dupackcount number of duplicate ACKs received
+ * @param actualackcount number of non-duplicate ACKs received
+ * @return percentage of packets out of order
+ * */
+double calc_packets_outoforder(int dupackcount, int actualackcount) {
+ log_println(log_lvl_heur, "--packets out of order: %f",
+ (double) dupackcount / actualackcount);
+ return ((double) dupackcount / actualackcount);
+}
+
+/**
+ * Calculate maximum theoretical throughput in bits using the Mathis equation.
+ *
+ * The Theoretical Maximum Throughput should be computed to receive
+ * Mbps instead of Mibps. This is the only variable in the NDT that is kept in
+ * Mibps, so it might lead to the inconsistent results when comparing it with the other values.
+ *
+ * @param currentMSS current maximum segment size (MSS), in octets
+ * @param rttsec average round trip time (Latency/Jitter) in seconds
+ * @param packetloss Packet loss
+ * @return maximum theoretical bandwidth
+ * */
+double calc_max_theoretical_thruput(int currentMSS, double rttsec,
+ double packetloss) {
+ double maxthruput;
+ maxthruput = (currentMSS / (rttsec * sqrt(packetloss))) * BITS_8 / KILO_BITS
+ / KILO_BITS;
+ log_println(log_lvl_heur, "--max_theoretical_thruput: %f. From
%d,%f,%f",
+ maxthruput, currentMSS, rttsec, packetloss);
+ return maxthruput;
+}
+
+/**
+ * Finalize some window sizes based on web100 values obtained
+ *
+ * @param SndWinScale SendWinScale web100 var value
+ * @param SendBuf SendBuf web100 var value
+ * @param MaxRwinRcvd MaxRwinRcvd web100 var value
+ * @param rwin Receive window value in bytes
+ * @param swin Send window value in bytes
+ * @param cwin congestion window value in bytes
+ *
+ * */
+void calc_window_sizes(int *SndWinScale, int *RcvWinScale, int SendBuf,
+ int MaxRwinRcvd, int MaxCwnd, double *rwin, double *swin,
double *cwin) {
+ if ((*SndWinScale > WINDOW_SCALE_THRESH) || (SendBuf < MAX_TCP_PORT))
+ *SndWinScale = 0;
+ if ((*RcvWinScale > WINDOW_SCALE_THRESH) || (MaxRwinRcvd <
MAX_TCP_PORT))
+ *RcvWinScale = 0;
+
+ *rwin = (double) (MaxRwinRcvd * BITS_8 / KILO_BITS / KILO_BITS );
+ *swin = (double) SendBuf * 8 / 1024 / 1024;
+ *cwin = (double) (MaxCwnd * BITS_8 / KILO_BITS / KILO_BITS );
+ log_println(
+ log_lvl_heur,
+ "--window sizes: SndWinScale= %d, RcvwinScale=%d, rwin=%f, swin=%f, cwin=%f",
+ SndWinScale, RcvWinScale, rwin, swin, cwin);
+}
+
+/**
+ * Calculate the fraction of idle time spent waiting for packets to arrive.
+ * Current retransmit timeout * timeout count = idle time spent waiting for packets to arrive.
+ * When divided by total test time, they indicate fraction of time spent idle due to RTO
+ * @param timeouts number of timeouts
+ * @param currentRTO current retransmit timeout
+ * @param totaltime total test time
+ * @return idle time fraction
+ * */
+double calc_RTOIdle(int timeouts, int currentRTO, double totaltime) {
+ double idlewaitingforpackets = (timeouts * ((double) currentRTO /
1000))
+ / totaltime;
+ log_println(log_lvl_heur, "--RTOIdle:%f", idlewaitingforpackets);
+ return idlewaitingforpackets;
+}
+
+/**
+ * Get total test time used by the Server-To-Client throughput test.
+ *
+ * @param SndLimTimeRwin SndLimTimeRwin web100 var value, cumulative time spent
+ * in the 'Receiver Limited' state during the S->C throughput
test
+ * @param SndLimTimeCwnd SndLimTimeCwnd web100 var value, cumulative time spent in
+ * 'Congestion Limited' state
+ * @param SndLimTimeSender SndLimTimeSender web100 var value, total time spend in the
+ * 'sender limited' state
+ * @return Total test time
+ * */
+int calc_totaltesttime(int SndLimTimeRwin, int SndLimTimeCwnd,
+ int SndLimTimeSender) {
+ int totaltime = SndLimTimeRwin + SndLimTimeCwnd + SndLimTimeSender;
+ log_println(log_lvl_heur, "--Total test time: %d+%d+%d=%d ", SndLimTimeRwin,
+ SndLimTimeCwnd, SndLimTimeSender, totaltime);
+ return (totaltime);
+}
+
+/**
+ * get 'Sender Limited' state time ratio
+ * @param SndLimTimeSender cumulative time spent in the 'Sender Limited' state due to own fault
+ * @param totaltime Total test time
+ * @return sender limited time ratio
+ *
+ */
+double calc_sendlimited_sndrfault(int SndLimTimeSender, int totaltime) {
+ double sendlimitedtime = (double) SndLimTimeSender / totaltime;
+ log_println(log_lvl_heur, "--Send limited time: %d over %d=%f ",
+ SndLimTimeSender, totaltime, sendlimitedtime);
+ return sendlimitedtime;
+}
+
+/**
+ * get ratio of time spent in 'send Limited' state due to receiver end limitations
+ * @param SndLimTimeRwin cumulative time spent in the 'send Limited' state due
+ * to the receiver window limits
+ * @param totaltime Total test time
+ * @return sender limited time ratio
+ *
+ */
+double calc_sendlimited_rcvrfault(int SndLimTimeRwin, int totaltime) {
+ double sendlimitedtime = (double) SndLimTimeRwin / totaltime;
+ log_println(log_lvl_heur, "--Send limited time: %d over %d=%f ",
+ SndLimTimeRwin, totaltime, sendlimitedtime);
+ return sendlimitedtime;
+}
+
+/**
+ * get ratio of time spent in 'Sender Limited' state time due to congestion
+ * @param SndLimTimeSender cumulative time spent in the 'Sender Limited' state due to congestion
+ * @param totaltime Total test time
+ * @return sender limited time ratio
+ */
+double calc_sendlimited_cong(int SndLimTimeCwnd, int totaltime) {
+ double sendlimitedtime = (double) SndLimTimeCwnd / totaltime;
+ log_println(log_lvl_heur, "--Send limited time: %d over %d=%f ",
+ SndLimTimeCwnd, totaltime, sendlimitedtime);
+ return sendlimitedtime;
+}
+
+/**
+ * Calculate actual throughput in Mbps as the ratio of total transmitted bytes
+ * over total test time
+ *
+ * @param DataBytesOut Number of bytes sent out
+ * @param totaltime Total test time in microseconds
+ * @return Actual throughput
+ */
+double calc_real_thruput(int DataBytesOut, int totaltime) {
+ double realthruput = ((double) DataBytesOut / (double) totaltime) * BITS_8;
+ log_println(log_lvl_heur, "--Actual observed throughput: %f ", realthruput);
+ return realthruput;
+}
+
+/**
+ * Calculate total time spent waiting for packets to arrive
+ *
+ * @param CurrentRTO web100 value indicating current value of the retransmit timer RTO.
+ * @param Timeouts web100 value indicating # of times the retransmit timeout has
+ * expired when the RTO backoff multiplier is
equal to one
+ * @return Actual throughput
+ */
+double cal_totalwaittime(int currentRTO, int timeoutcounters) {
+ double waitarrivetime = (double) (currentRTO * timeoutcounters) /
KILO;
+ log_println(log_lvl_heur, "--Total wait time: %f ", waitarrivetime);
+ return waitarrivetime;
+}
+
+/**
+ * Check if the S->C throughput as calculated by the midbox test , with a limited
+ * cwnd value, is better than that calculated by the S->C test.
+ *
+ * @param midboxs2cspd S->C throughput calculated by midbox tests wiht limited cwnd
+ * @param s2ctestresult throughput calculated by the s2c tests
+ * @return 1 (true) if midboxs2cspd > s2cspd, else 0.
+ */
+int is_limited_cwnd_thruput_better(int midboxs2cspd, int s2cspd) {
+ int thruputmismatch = 0;
+ if (midboxs2cspd > s2cspd)
+ thruputmismatch = 1;
+ return thruputmismatch;
+
+}
+
+/**
+ * Check if there is a possible duplex mismatch condition. This is done by checking
+ * if the S->C throughput as calculated by the C->S throughput tests is greater than
+ * that calculated by the S->C test.
+ *
+ * @param c2stestresult throughput calculated by the c2s tests
+ * @param s2ctestresult throughput calculated by the c2s tests
+ * @return 1 (true) if c2stestresult > s2ctestresult, else 0.
+ */
+int is_c2s_thruputbetter(int c2stestresult, int s2ctestresult) {
+ int c2sbetter_yes = 0;
+ if (c2stestresult > s2ctestresult)
+ c2sbetter_yes = 1;
+ return c2sbetter_yes;
+}
+
+/**
+ * Check if Multiple test mode is enabled.
+ * @param multiple value of the "multiple test mode" setting
+ * @return 1(true) if multiple test mode is on, else 0
+ */
+int isNotMultipleTestMode(int multiple) {
+ log_println(log_lvl_heur, "--multiple: %f ", multiple);
+ return (multiple == 0);
+}
+
+/**
+ * Calculate duplex mismatch in network link. The conditions to determine this:
+ *
+ * -'Congestion Limited' state time share > 90%
+ * -Theoretical Maximum Throughput > 2Mibps
+ * - # of segments transmitted containing some retransmitted data > 2 per second
+ * - Maximum slow start threshold > 0
+ * - Cumulative expired retransmit timeouts RTO > 1% of the total test time
+ * - link type detected is not wireless link
+ * - throughput measured during Middlebox test (with a limited CWND) >
+ * throughput measured during S->C test
+ * - throughput measured during C->S test > throughput measured during the S2C test
+ * @param cwndtime Time spent send limited due to congestion
+ * @param bwtheoretcl theoreticallly calculated bandwidth
+ * @param pktsretxed # of segments with retransmitted packets
+ * @param maxsstartthresh Maximum slow start threshold
+ * @param idleRTO Cumulative expired retransmit timeouts RTO
+ * @param int s2cspd Throughput calculated during S->C tests
+ * @param midboxspd Throughput calculated during middlebox tests
+ * @param multiple is multiple test mode on?
+ * @return int 1 if duplex mismatch is found, 0 if not.
+ * */
+int detect_duplexmismatch(double cwndtime, double bwtheoretcl, int pktsretxed,
+ double timesec, int maxsstartthresh, double idleRTO, int link,
+ int s2cspd, int midboxspd, int multiple) {
+ int duplex_mismatch_yes = 0;
+ if ((cwndtime > .9) // more than 90% time spent being receiver window limited
+ && (bwtheoretcl > 2) // theoretical max goodput > 2mbps
+ && (pktsretxed / timesec > 2)
+ // #of segments with pkt-retransmissions> 2
+ && (maxsstartthresh > 0) // max slow start threshold
> 0
+ && (idleRTO > .01) // cumulative RTO time > 1% test duration
+ && (link > 2) // not wireless link
+ && is_limited_cwnd_thruput_better(midboxspd, s2cspd) //S->C throughput calculated
+ // by server < client value
+ && isNotMultipleTestMode(multiple)) {
+
+ duplex_mismatch_yes = 1;
+ } //end if
+ log_println(log_lvl_heur, "--duplexmismatch?: %d ",
duplex_mismatch_yes);
+ return duplex_mismatch_yes;
+}
+
+/** Check if internal link is duplex mismatched
+ * @param s2cspd Throughput calculated during the S->C test
+ * @param realthruput actual observed throuput
+ * @param rwintime time spend limited sending due to receive window limitations
+ * @param packetloss packet loss during S->C tests
+ * return 1 if internal duplex mismatch is found, else 0
+ * */
+int detect_internal_duplexmismatch(double s2cspd, double realthruput,
+ double rwintime, double packetloss) {
+ int duplex_mismatch_yes = 0;
+ if ((s2cspd > 50) // S->C goodput > 50 Mbps
+ && (realthruput < 5) // actual send throughput < 5 Mbps
+ && (rwintime > .9) // receive window limited for >90% of the time
+ && (packetloss < .01)) {
+ duplex_mismatch_yes = 1;
+ }
+ log_println(log_lvl_heur, "--internal duplexmismatch?: %d ",
+ duplex_mismatch_yes);
+ return duplex_mismatch_yes;
+}
+
+/**
+ * Determine whether faulty hardware is affecting performance by observing some
+ * threshold values. Particularly, see if
+ * - connection is losing more than 15 packets/second
+ * - connections spends > 60% in congestion window limited state
+ * - packet loss < 1% of packets txed
+ * - connection entered TCP slow start stage
+ *
+ * This heuristic seems to in error:
+ * 1) Instead of obtaining
+ * packet per second loss rate = count_lost_packets / test_duration, the loss rate is multiplied times 100.
+ * If "packet loss" is less than 1% (3rd condition), then the packet loss multiplied by 100 and divided by the
+ * total test time in seconds will be less than 1 anyway.
+ * 2) 'Congestion Limited' state time ratio need not be divided by the total_test
+ * time_in_seconds , but be directly compared to "0.6".
+ * @param packetloss packetloss calculated
+ * @param cwndtime congestion window limited time
+ * @param timesec total test time
+ * @param maxslowstartthresh max slow start threshold value
+ * @return 1 is fault hardware suspected, 0 otherwise
+ * */
+int detect_faultyhardwarelink(double packetloss, double cwndtime,
+ double timesec, int maxslowstartthresh) {
+ int faultyhw_found = 0;
+ if (((packetloss * 100) / timesec > 15) && (cwndtime / timesec > .6)
+ && (packetloss < .01) && (maxslowstartthresh > 0)) {
+ faultyhw_found = 1;
+ }
+ log_println(log_lvl_heur, "--faulty hardware?: %d ", faultyhw_found);
+ return faultyhw_found;
+
+}
+
+/**
+ * Determine whether link is an ethernet link:
+ * the WiFi and DSL/Cable modem are not detected,
+ * the total Send Throughput is in the range [3 , 9.5] (not inclusive)
+ * and the connection is very stable.
+ *
+ * This specific conditions are:
+ * - actual measured throughput < 9.5 Mbps, but > 3 Mbps
+ * - S->C throughput < 9.5 Mbps
+ * - packet loss < 1%
+ * - out of order packets proportion < .35
+ * - the heuristics for WiFi and DSL/Cable modem links give negative results
+ * @param realthruput Actual calculated throughput
+ * @param s2cspd S->C throuhput
+ * @param packetloss packet loss seen
+ * @param oo_order out-pf-order packet ration
+ * @param link integer indicative of link type
+ * @return 1 if ethernet link, 0 otherwise
+ * */
+int detect_ethernetlink(double realthruput, double s2cspd, double packetloss,
+ double oo_order, int link) {
+ int is_ethernet = 0;
+ if ((realthruput < 9.5) && (realthruput > 3.0) && ((s2cspd / 1000) <
9.5)
+ && (packetloss < .01) && (oo_order < .035) && (link >
0)) {
+ is_ethernet = 1;
+ }
+ log_println(log_lvl_heur, "--Is ethernet?: %d ", is_ethernet);
+ return is_ethernet;
+}
+
+/**
+ * Determine whether link is a wireless link:
+ * DSL/Cable modem are not detected, the NDT Client
+ * is a bottleneck and actual observed Throughput < 5 Mbps,
+ * but the Theoretical Maximum Throughput is > 50 Mibps.
+ *
+ * This specific conditions are:
+ * - The cumulative time spent in the 'Sender Limited' state is 0 ms
+ * - The actual (real, measured) throughput < 5 Mbps
+ * - theoretical bw calculated > 50 Mibps
+ * - # of transitions into 'Receiver Limited' state == # of transitions
+ * into'Congestion Limited' state
+ * - 'Receiver Limited' state time ratio is greater than 90%
+ * - the heuristics for WiFi and DSL/Cable modem links give negative results
+ * @param sendtime cumulative time spent in "sender limited" state
+ * @param realthruput Actual calculated throughput
+ * @param bw_theortcl Theoretical bandwidth
+ * @param sndlimtrans_rwin # of transitions into rcvr-limited state
+ * @param sndlimtrans_cwnd # of transitions into cwnd-limited state
+ * @param double rwindowtime "receive window limited" cumulative time
+ * @param link integer indicative of link type
+ * @return 1 if wireless link, 0 otherwise
+ * */
+int detect_wirelesslink(double sendtime, double realthruput, double bw_theortcl,
+ int sndlimtrans_rwin, int sndlimtrans_cwnd, double
rwindowtime,
+ int link) {
+ int is_wireless = 0;
+ if ((sendtime == 0) && (realthruput < 5) && (bw_theortcl > 50)
+ && ((sndlimtrans_rwin / sndlimtrans_cwnd) == 1)
+ && (rwindowtime > .90) && (link > 0)) {
+ is_wireless = 1;
+ }
+ log_println(log_lvl_heur, "--Is wireless?: %d ", is_wireless);
+ return is_wireless;
+}
+
+/**
+ *
+ * The link is treated as a DSL/Cable modem when the NDT Server isn't a
+ * bottleneck and the Total Send Throughput is less than 2 Mbps and
+ * less than the Theoretical Maximum Throughput.
+ *
+ * The specific conditions used:
+ * - The cumulative time spent in the 'Sender Limited' state is less than 0.6 ms
+ * - The number of transitions into the 'Sender Limited' state is 0
+ * - The Total Send Throughput is less than 2 Mbps
+ * - The Total Send Throughput is less than Theoretical Maximum Throughput
+ *
+ * @param sndlimtimesender cumulative time spent in the 'Sender Limited' state
+ * @param sndlimtranssender # of transitions into sender limited state
+ * @param realthruput Actual calculated throughput
+ * @param bw_theoretical Theoretical bandwidth
+ * @param link integer indicative of link type
+ * @return 1 if wireless link, 0 otherwise
+ * */
+int detect_DSLCablelink(int sndlim_timesender, int sndlim_transsender,
+ double realthruput, double bw_theoretical, int link) {
+ int is_dslorcable = 0;
+ if ((sndlim_timesender < 600) && (sndlim_transsender == 0)
+ && (realthruput < 2) && (realthruput < bw_theoretical)
+ && (link > 0)) {
+ is_dslorcable = 1;
+ }
+ log_println(log_lvl_heur, "--Is DSL/Cable?: %d ", is_dslorcable);
+ return is_dslorcable;
+
+}
+
+/**
+ * Determine if there is a half-duplex link in the path by looking at
+ * web100 variables. Look for a connection that toggles rapidly
+ * between the sender buffer limited and receiver buffer limited states, but
+ * does not remain in the sender-buffer-limited-state and instead spends
95%
+ * time in rcvr-buffer-limited state.
+ *
+ * The specific conditions used:
+ * - 'Receiver Limited' state time ratio > 95%
+ * - # of transitions into the 'Receiver Limited' state > 30 per second
+ * - # of transitions into the 'Sender Limited' state > 30 per second
+ *
+ * @param rwintime 'Receiver Limited' state time ratio
+ * @param sndlim_transrwin # of transitions into receiver limited state
+ * @param sndlim_transsender # of transitions into sender limited state
+ * @param totaltesttime total test time
+ * @return 1 if half_duplex link suspected, 0 otherwise
+ * */
+int detect_halfduplex(double rwintime, int sndlim_transrwin,
+ int sndlim_transsender, double totaltesttime) {
+ int is_halfduplex = 0;
+ if ((rwintime > .95) && (sndlim_transrwin / totaltesttime > 30)
+ && (sndlim_transsender / totaltesttime > 30)) {
+ is_halfduplex = 1;
+ }
+ log_println(log_lvl_heur, "--Is Half_duplex detected? %d ", is_halfduplex);
+ return is_halfduplex;
+}
+
+/**
+ * Congestion is detected when the connection is
+ * congestion limited a non-trivial percent of the time,
+ * there isn't a duplex mismatch detected and the NDT
+ * Client's receive window is not the limiting factor.
+ *
+ * The specific conditions used:
+ * - 'Congestion Limited' state time share is greater than 2%
+ * - Duplex mismatch condition heuristic gives negative results
+ * - Max window advertisement received > than the maximum
+ * congestion window used during Slow Start
+ *
+ * @param cwndtime time spent in being send-limited due to congestion window
+ * @param mismatch id duplex_mismatch detected?
+ * @param cwin congestion window size
+ * @param rwin max window size advertisement rcvd
+ * @param rttsec total round-trip time
+ * @return 1 if congestion detected, 0 otherwise
+ * */
+int detect_congestionwindow(double cwndtime, int mismatch, double cwin,
+ double rwin, double rttsec) {
+ int is_congested = 0;
+ if ((cwndtime > .02) && (mismatch == 0)
+ && ((cwin / rttsec) < (rwin / rttsec))) {
+ is_congested = 1;
+ }
+ log_println(log_lvl_heur, "--Is congested? %d ", is_congested);
+ return is_congested;
+}
=======================================
--- /dev/null
+++ /branches/kkumar_code_organize/src/heuristics.h Sun Oct 16 15:37:17
2011
@@ -0,0 +1,95 @@
+/*
+ * This file contains function declarations for heuristics and algorithms.
+ *
+ * Created : Oct 2011
+ * Author:

+ */
+
+#ifndef HEURISTICS_H_
+#define HEURISTICS_H_
+
+// link speed algorithms
+void calc_linkspeed(char *spds, int spd_index, int *c2sdata, int *c2sack,
+ int* s2cdata, int *s2cack, float runave[4], u_int32_t
*dec_cnt,
+ u_int32_t *same_cnt, u_int32_t *inc_cnt, int *timeout, int
*dupack,
+ int isc2stest);
+
+// calculate average round trip time
+double calc_avg_rtt(int sumRTT, int countRTT, double * avgRTT);
+
+// calculate packet loss percentage
+double calc_packetloss(int congsnsignals, int pktsout, int c2sdatalinkspd);
+
+// Calculate the percentage of packets arriving out of order
+double calc_packets_outoforder(int dupackcount, int actualackcount);
+
+// calculate theoretical maximum goodput in bits
+double calc_max_theoretical_thruput(int currentMSS, double rttsec,
+ double packetloss);
+
+// finalize some window sizes
+void calc_window_sizes(int *SndWinScale, int *RcvWinScale, int SendBuf,
+ int MaxRwinRcvd, int MaxCwnd, double *rwin, double *swin,
double *cwin);
+
+// calculate RTO Idle time
+double calc_RTOIdle (int timeouts, int CurrentRTO, double totaltime);
+
+// calculate total test time for S_C test
+int calc_totaltesttime(int SndLimTimeRwin, int SndLimTimeCwnd,
+ int SndLimTimeSender);
+
+// get time ratio of 'Sender Limited' time due to congestion
+double calc_sendlimited_cong(int SndLimTimeCwnd, int totaltime);
+
+// get time ratio of 'Sender Limited' time due to receivers fault
+double calc_sendlimited_rcvrfault(int SndLimTimeRwin, int totaltime);
+
+// get time ratio of 'Sender Limited' time due to sender's fault
+double calc_sendlimited_sndrfault(int SndLimTimeSender, int totaltime);
+
+// Calculate actual throughput in Mbps
+double calc_real_thruput(int DataBytesOut, int totaltime);
+
+// Calculate total time spent waiting for packets to arrive
+double cal_totalwaittime(int currentRTO, int timeoutcounters);
+
+// Is throughput measured greater in value during the C->S than S->C test?
+int is_c2s_thruputbetter(int c2stestresult, int s2ctestresult);
+
+// Check if the S->C throughput computed with a limited
+// cwnd value throughput test is better than that calculated by the S->C test.
+int is_limited_cwnd_thruput_better(int midboxs2cspd, int s2cspd);
+
+// Is Multiple test mode enabled?
+int isNotMultipleTestMode(int multiple);
+
+// detect duplex mismatch mode
+int detect_duplexmismatch(double cwndtime, double bwtheoretcl, int pktsretxed,
+ double timesec, int maxsstartthresh, double idleRTO, int link,
+ int s2cspd, int midboxspd, int multiple);
+
+// detect if faulty hardware may exist
+int detect_faultyhardwarelink(double packetloss, double cwndtime,
+ double timesec, int maxslowstartthresh);
+
+// Is this an ethernet link?
+int detect_ethernetlink(double realthruput, double s2cspd, double packetloss,
+ double oo_order, int link);
+
+// Is wireless link?
+int detect_wirelesslink(double sendtime, double realthruput, double bw_theortcl,
+ int sndlimtrans_rwin, int sndlimtrans_cwnd, double
rwindowtime,
+ int link);
+
+// Is DSL/Cable modem?
+int detect_DSLCablelink(int sndlim_timesender, int sndlim_transsender,
+ double realthruput, double bw_theoretical, int link);
+
+// Is a half_duplex link present?
+int detect_halfduplex(double rwintime, int sndlim_transrwin,
+ int sndlim_transsender, double totaltesttime);
+
+// Is congestion detected?
+int detect_congestionwindow(double cwndtime, int mismatch, double cwin,
+ double rwin, double rttsec);
+#endif /* HEURISTICS_H_ */
=======================================
--- /branches/kkumar_code_organize/src/Makefile.am Fri Sep 30 21:38:03
2011
+++ /branches/kkumar_code_organize/src/Makefile.am Sun Oct 16 15:37:17
2011
@@ -34,7 +34,7 @@
endif

web100clt_SOURCES = web100clt.c network.c usage.c logging.c utils.c protocol.c runningtest.c ndtptestconstants.c \
- test_sfw_clt.c test_mid_clt.c test_c2s_clt.c test_s2c_clt.c test_meta_clt.c
+ test_sfw_clt.c test_mid_clt.c test_c2s_clt.c test_s2c_clt.c test_meta_clt.c strlutils.c
web100clt_LDADD = $(I2UTILLIBDEPS) -lpthread $(ZLIB)
web100clt_CPPFLAGS ='-DBASEDIR="$(ndtdir)"'
web100clt_DEPENDENCIES = $(I2UTILLIBDEPS)
@@ -43,28 +43,28 @@
genplot_LDADD = $(NDTLIBS) $(I2UTILLIBDEPS)
genplot_CPPFLAGS ='-DBASEDIR="$(ndtdir)"'

-analyze_SOURCES = analyze.c usage.c logging.c runningtest.c ndtptestconstants.c
+analyze_SOURCES = analyze.c usage.c logging.c runningtest.c ndtptestconstants.c strlutils.c
analyze_LDADD = $(NDTLIBS) $(I2UTILLIBDEPS) $(ZLIB)
analyze_CPPFLAGS ='-DBASEDIR="$(ndtdir)"'

fakewww_SOURCES = fakewww.c troute.c troute6.c tr-tree.c tr-tree6.c network.c usage.c logging.c \
- runningtest.c ndtptestconstants.c
+ runningtest.c ndtptestconstants.c strlutils.c
fakewww_LDADD = $(I2UTILLIBDEPS) $(ZLIB)
fakewww_CPPFLAGS ='-DBASEDIR="$(ndtdir)"'

web100srv_SOURCES = web100srv.c web100-util.c web100-pcap.c web100-admin.c runningtest.c \
network.c usage.c utils.c mrange.c logging.c testoptions.c ndtptestconstants.c \
- protocol.c test_sfw_srv.c test_meta_srv.c ndt_odbc.c
+ protocol.c test_sfw_srv.c test_meta_srv.c ndt_odbc.c strlutils.c heuristics.c
web100srv_LDFLAGS = $(NDTLDFLAGS) $(I2UTILLDFLAGS)
web100srv_LDADD = $(NDTLIBS) $(I2UTILLIBS) $(I2UTILLIBDEPS) -lpthread $(ZLIB)
web100srv_CPPFLAGS ='-DBASEDIR="$(ndtdir)"'
web100srv_DEPENDENCIES = $(I2UTILLIBDEPS)

-viewtrace_SOURCES = viewtrace.c usage.c logging.c utils.c runningtest.c ndtptestconstants.c
+viewtrace_SOURCES = viewtrace.c usage.c logging.c utils.c runningtest.c ndtptestconstants.c strlutils.c
viewtrace_LDADD = $(NDTLIBS) $(I2UTILLIBDEPS) $(ZLIB)
viewtrace_CPPFLAGS ='-DBASEDIR="$(ndtdir)"'

-tr_mkmap_SOURCES = tr-mkmap.c tr-tree.c tr-tree6.c usage.c logging.c runningtest.c ndtptestconstants.c
+tr_mkmap_SOURCES = tr-mkmap.c tr-tree.c tr-tree6.c usage.c logging.c runningtest.c ndtptestconstants.c strlutils.c
tr_mkmap_LDADD = $(NDTLIBS) $(I2UTILLIBDEPS) $(ZLIB)
tr_mkmap_CPPFLAGS ='-DBASEDIR="$(ndtdir)"'

=======================================
--- /branches/kkumar_code_organize/src/logging.c Fri Oct 14 13:52:19
2011
+++ /branches/kkumar_code_organize/src/logging.c Sun Oct 16 15:37:17
2011
@@ -817,6 +817,7 @@
size_t tmpstrlen = sizeof(tmpstr);
socklen_t len;
DIR *dp;
+ char metafilesuffix[256] = "meta";

/* Get the clients domain name and same in metadata file
* changed to use getnameinfo 7/24/09
@@ -848,57 +849,10 @@
// reset tmpstr
memset(tmpstr, 0, tmpstrlen);

- // The following section of code creates a log directory to record meta data,
- // if one is not already present with the details needed. The log file location,
- // and name themselves record the year, month, date, time and client
name.
- // The "primary" location for this log file is obtained as a command line option
- // from the user, or is the default location of BASE_DIR+LOG_DIR of the NDT installation
-//TODO : Move this into a new method??
- //strncpy(tmpstr, DataDirName, strlen(DataDirName));
- strlcpy(tmpstr, DataDirName, sizeof(tmpstr));
- // Open the directory or create one if not yet present
- if ((dp = opendir(tmpstr)) == NULL && errno == ENOENT)
- mkdir(tmpstr, 0755);
- closedir(dp); // close opened directory
- get_YYYY(dir); // get current year
- //strncat(tmpstr, dir, 4);
- strlcat(tmpstr, dir, sizeof(tmpstr));
- if ((dp = opendir(tmpstr)) == NULL && errno == ENOENT)
- mkdir(tmpstr, 0755); // create directory with year appended
- closedir(dp); // close the opened directory
- //strncat(tmpstr, "/", 1);
- strlcat(tmpstr, "/", sizeof(tmpstr));
- get_MM(dir); // get month info
- //strncat(tmpstr, dir, 2); // append month info to the directory name
- strlcat(tmpstr, dir, sizeof(tmpstr)); // append month info to the directory name
- if ((dp = opendir(tmpstr)) == NULL && errno == ENOENT)
- mkdir(tmpstr, 0755);
- closedir(dp);
- //strncat(tmpstr, "/", 1);
- strlcat(tmpstr, "/", sizeof(tmpstr));
- get_DD(dir); // get date
- //strncat(tmpstr, dir, 2); // append date info to directory name
- strlcat(tmpstr, dir, sizeof(tmpstr)); // append date info to directory name
- if ((dp = opendir(tmpstr)) == NULL && errno == ENOENT)
- mkdir(tmpstr, 0755);
- closedir(dp);
-
- // end block creating log directory
-//end creating dir
-
- memcpy(tmp2str, tmpstr, tmpstrlen); // tmp2str now contains the dir name intended
- // tmpstr will henceforth refer to the log file's name
- //strncat(tmpstr, "/", 1);
- strlcat(tmpstr, "/", sizeof(tmpstr));
- // todo remove debug stmt
- log_println(0, " ***meta.client_ip now: %s",
- meta.client_ip);
- sprintf(dir, "%s_%s:%d.meta", get_ISOtime(isoTime,sizeof(isoTime)), meta.client_ip,
- meta.ctl_port); // now get ISO time, the client's
name and port
- //strncat(tmpstr, dir, strlen(dir)); // append above details to log filename
- strlcat(tmpstr, dir, sizeof(tmpstr)); // append above details to log filename
- log_println(0, " ** meta.client_ip now: %s",
- meta.client_ip); //todo remove debug
stmt
+ // Create metadata file
+ create_client_logdir((struct sockaddr *) &meta.c_addr, len,
+ tmpstr, sizeof(tmpstr), metafilesuffix, sizeof(metafilesuffix));
+

log_println(6, "Should compress snaplog and tcpdump files
compress=%d",
compress);
@@ -1068,8 +1022,66 @@
return j - 1;
}

-
-/** Method to create directories for snap log files
+/** Create directories for snap/tcp trace log files, and meta files.
+ *
+ *
+* The log file location, and name themselves record the year, month, date,
+* time and client name.
+*
+* The "primary" location for this log file is obtained as a command line option
+* from the user, or is the default location of BASE_DIR+LOG_DIR of the NDT installation
+*
+* @param direnamedestarg location to store final directory name
+* @param destnamearrsize Size of dest name string
+* @param finalsuffix string constant suffix (C2S/S2C IP:port.ndttrace etc)
+*
+*
+*/
+void create_named_logdir(char *dirnamedestarg, int destnamearrsize,
+ char *finalsuffix) {
+
+ char namebuf[256];
+ size_t namebuflen = 255;
+ char dir[128];
+ DIR *dp;
+
+ strlcpy(dirnamedestarg, DataDirName, destnamearrsize);
+ if ((dp = opendir(dirnamedestarg)) == NULL && errno == ENOENT)
+ mkdir(dirnamedestarg, 0755);
+ closedir(dp);
+ get_YYYY(dir);
+
+ strlcat(dirnamedestarg, dir, destnamearrsize);
+ if ((dp = opendir(dirnamedestarg)) == NULL && errno == ENOENT)
+ mkdir(dirnamedestarg, 0755);
+ closedir(dp);
+
+ strlcat(dirnamedestarg, "/", destnamearrsize);
+ get_MM(dir);
+
+ strlcat(dirnamedestarg, dir, destnamearrsize);
+ if ((dp = opendir(dirnamedestarg)) == NULL && errno == ENOENT)
+ mkdir(dirnamedestarg, 0755);
+ closedir(dp);
+
+ strlcat(dirnamedestarg, "/", destnamearrsize);
+ get_DD(dir);
+
+ strlcat(dirnamedestarg, dir, destnamearrsize);
+ if ((dp = opendir(dirnamedestarg)) == NULL && errno == ENOENT)
+ mkdir(dirnamedestarg, 0755);
+ closedir(dp);
+
+ strlcat(dirnamedestarg, "/", destnamearrsize);
+ sprintf(dir, "%s", finalsuffix);
+ strlcat(dirnamedestarg, dir, destnamearrsize);
+
+}
+
+/** Create directories for snap/tcp trace log files, and meta files.
+ * Gets the endpoint name and port details and then builds the logfile name.
+ * Calls the create_named_logdir(..) method with the endpoint details.
+ *
* @param namebufarg string containing ip address/name of client
* @param socketaddrarg string containing socket address
* @param direnamedestarg location to store final directory name
@@ -1091,41 +1103,11 @@
I2AddrNodeName(sockAddr, namebuf, &namebuflen);
socketaddrport = I2AddrPort(sockAddr);

-
- //strncpy(dirnamedestarg, DataDirName, strlen(DataDirName));
- strlcpy(dirnamedestarg, DataDirName, destnamearrsize);
- if ((dp = opendir(dirnamedestarg)) == NULL && errno == ENOENT)
- mkdir(dirnamedestarg, 0755);
- closedir(dp);
- get_YYYY(dir);
- //strncat(dirnamedestarg, dir, 4);
- strlcat(dirnamedestarg, dir, destnamearrsize);
- if ((dp = opendir(dirnamedestarg)) == NULL && errno == ENOENT)
- mkdir(dirnamedestarg, 0755);
- closedir(dp);
- //strncat(dirnamedestarg, "/", 1);
- strlcat(dirnamedestarg, "/", destnamearrsize);
- get_MM(dir);
- //strncat(dirnamedestarg, dir, 2);
- strlcat(dirnamedestarg, dir, destnamearrsize);
- if ((dp = opendir(dirnamedestarg)) == NULL && errno == ENOENT)
- mkdir(dirnamedestarg, 0755);
- closedir(dp);
- //strncat(dirnamedestarg, "/", 1);
- strlcat(dirnamedestarg, "/", destnamearrsize);
- get_DD(dir);
- //strncat(dirnamedestarg, dir, 2);
- strlcat(dirnamedestarg, dir, destnamearrsize);
- if ((dp = opendir(dirnamedestarg)) == NULL && errno == ENOENT)
- mkdir(dirnamedestarg, 0755);
- closedir(dp);
- //strncat(dirnamedestarg, "/", 1);
- strlcat(dirnamedestarg, "/", destnamearrsize);
sprintf(dir, "%s_%s:%d.%s", get_ISOtime(isoTime, sizeof(isoTime)), namebuf, socketaddrport, finalsuffix);
- //strncpy(finalsuffix, dir, strlen(dir));
strlcpy(finalsuffix, dir, finalsuffixsize);
- //strncat(dirnamedestarg, dir, strlen(dir));
- strlcat(dirnamedestarg, dir, destnamearrsize);
+
+ create_named_logdir(dirnamedestarg, destnamearrsize,finalsuffix);

I2AddrFree(sockAddr);
-}
+
+}
=======================================
--- /branches/kkumar_code_organize/src/logging.h Fri Oct 14 13:52:19
2011
+++ /branches/kkumar_code_organize/src/logging.h Sun Oct 16 15:37:17
2011
@@ -20,6 +20,7 @@
#define PROTOLOGFILE "web100srvprotocol.log" /* Name of protocol validation log file */
#define PROTOLOGPREFIX "web100srvprotocol_" /* prefix for protocol validation log file */
#define PROTOLOGSUFFIX ".log" /* suffix for protocol validation log file */
+#define FILENAME_SIZE 256 // This could have been in utils.h, but will be used immediately here

void log_init(char* progname, int debuglvl);
void set_debuglvl(int debuglvl);
@@ -58,10 +59,10 @@
* meta data file created for every session
* */
struct metadata {
- char c2s_snaplog[256]; // C->S test Snaplog file name, changed to 256 to avoid truncation
- char c2s_ndttrace[256]; // C->S NDT trace file name, changed to 256 to avoid truncation
- char s2c_snaplog[256]; // S->C test Snaplog file name, changed to 256 to avoid truncation
- char s2c_ndttrace[256]; // S->C NDT trace file name, changed to 256 to avoid truncation
+ char c2s_snaplog[FILENAME_SIZE]; // C->S test Snaplog file name, changed to 256 to avoid truncation
+ char c2s_ndttrace[FILENAME_SIZE]; // C->S NDT trace file name, changed to 256 to avoid truncation
+ char s2c_snaplog[FILENAME_SIZE]; // S->C test Snaplog file name, changed to 256 to avoid truncation
+ char s2c_ndttrace[FILENAME_SIZE]; // S->C NDT trace file name, changed to 256 to avoid truncation
char CPU_time[64]; // CPU time file
char summary[256]; // Summary data
char date[32]; // Date and,
@@ -87,7 +88,10 @@
//char *createprotologfilename (char* textappendarg);
void enableprotocollogging();
char *createprotologfilename (char* client_ip, char* textappendarg);
-
+void create_named_logdir(char *dirnamedestarg, int destnamearrsize,
+ char *finalsuffix);
+void create_client_logdir(struct sockaddr *cliaddrarg, socklen_t clilenarg, char *dirnamedestarg, int destnamearrsize,
+ char *finalsuffix, int finalsuffixsize) ;

void protolog_printgeneric(const char* key, const char* val);
void protolog_status(int pid, enum TEST_ID testid, enum TEST_STATUS_INT teststatus);
=======================================
--- /branches/kkumar_code_organize/src/utils.h Tue Sep 13 07:04:10 2011
+++ /branches/kkumar_code_organize/src/utils.h Sun Oct 16 15:37:17 2011
@@ -26,3 +26,37 @@
#define MIN_TCP_PORT 1
#define RESERVED_PORT "0"
#define MAX_TCP_PORT_STR "65535"
+#define KILO_BITS 1024
+#define BITS_8 8
+#define WINDOW_SCALE_THRESH 15
+#define MEGA 1000000
+#define KILO 1000
+
+// duplex indicators
+#define DUPLEX_OK_INDICATOR 0;
+#define DUPLEX_OLD_ALGO_INDICATOR 1;
+#define DUPLEX_SWITCH_FULL_HOST_HALF 2;
+
+// link indicators
+#define CANNOT_DETERMINE_LINK 100
+#define LINK_ALGO_FAILED 0
+#define LINK_ETHERNET 10
+#define LINK_WIRELESS 3
+#define LINK_DSLORCABLE 2
+
+// half duplex condition indicators
+#define NO_HALF_DUPLEX 0
+#define POSSIBLE_HALF_DUPLEX 1
+
+// congestion condition indicators
+#define NO_CONGESTION 0
+#define POSSIBLE_CONGESTION 1
+
+// bad cable indicators
+#define NO_BAD_CABLE 0
+#define POSSIBLE_BAD_CABLE 1
+
+
+// generic system wide retry counts
+#define RETRY_COUNT 5
+
=======================================
--- /branches/kkumar_code_organize/src/web100-pcap.c Fri Oct 14 13:52:19 2011
+++ /branches/kkumar_code_organize/src/web100-pcap.c Sun Oct 16 15:37:17 2011
@@ -689,6 +689,9 @@
DIR *dip;
int rc;

+ char logdir[256];
+ char logfilesuffix[256] = "ndttrace"; // logfile suffix
+
cnt = -1; /* read forever, or until end of file */
sig1 = 0;
sig2 = 0;
@@ -700,6 +703,7 @@
sockAddr = I2AddrBySAddr(get_errhandle(), sock_addr, saddrlen, 0, 0);
sock_addr = I2AddrSAddr(sockAddr, 0);
src_addr = I2AddrSAddr(srcAddr, 0);
+
/* special check for localhost, set device accordingly */
if (I2SockAddrIsLoopback(sock_addr, saddrlen) > 0)
//strncpy(device, "lo", 3);
@@ -825,6 +829,7 @@
memset(cmdbuf, 0, 256);
sprintf(cmdbuf, "host %s and port %d", namebuf, I2AddrPort(sockAddr));

+
log_println(1, "installing pkt filter for '%s'", cmdbuf);
log_println(1, "Initial pkt src data = %x", (int) fwd.saddr);

@@ -838,45 +843,15 @@
return;
}

- if (dumptrace == 1) { //todo call create_client_log
- fprintf(stderr, "Creating trace file for connection\n");
- memset(cmdbuf, 0, 256);
- //strncpy(cmdbuf, DataDirName, strlen(DataDirName));
- strlcpy(cmdbuf, DataDirName, sizeof(cmdbuf));
- if ((dip = opendir(cmdbuf)) == NULL && errno == ENOENT)
- mkdir(cmdbuf, 0755);
- closedir(dip);
- get_YYYY(dir);
- //strncat(cmdbuf, dir, 4);
- strlcat(cmdbuf, dir, sizeof(cmdbuf));
- if ((dip = opendir(cmdbuf)) == NULL && errno == ENOENT)
- mkdir(cmdbuf, 0755);
- closedir(dip);
- //strncat(cmdbuf, "/", 1);
- strlcat(cmdbuf, "/", sizeof(cmdbuf));
- get_MM(dir);
- //strncat(cmdbuf, dir, 2);
- strlcat(cmdbuf, dir, sizeof(cmdbuf));
- if ((dip = opendir(cmdbuf)) == NULL && errno == ENOENT)
- mkdir(cmdbuf, 0755);
- closedir(dip);
- //strncat(cmdbuf, "/", 1);
- strlcat(cmdbuf, "/", sizeof(cmdbuf));
- get_DD(dir);
- //strncat(cmdbuf, dir, 2);
- strlcat(cmdbuf, dir, sizeof(cmdbuf));
- if ((dip = opendir(cmdbuf)) == NULL && errno == ENOENT)
- mkdir(cmdbuf, 0755);
- closedir(dip);
- //strncat(cmdbuf, "/", 1);
- strlcat(cmdbuf, "/", sizeof(cmdbuf));
- sprintf(dir, "%s_%s:%d.%s_ndttrace", get_ISOtime(isoTime, sizeof(isoTime)), namebuf, I2AddrPort(sockAddr), direction);
- //strncat(cmdbuf, dir, strlen(dir));
- strlcat(cmdbuf, dir, sizeof(cmdbuf));
- pdump = pcap_dump_open(pd, cmdbuf);
- fprintf(stderr, "Opening '%s' log fine\n", cmdbuf);
+ if (dumptrace == 1) {
+ // Create log file
+ sprintf(dir, "%s_%s:%d.%s_ndttrace", get_ISOtime(isoTime, sizeof(isoTime)), namebuf, I2AddrPort(sockAddr), direction);
+ create_named_logdir(
+ logdir, sizeof(logdir), dir);
+ pdump = pcap_dump_open(pd, logdir);
+ fprintf(stderr, "Opening '%s' log fine\n", logdir);
if (pdump == NULL) {
- fprintf(stderr, "Unable to create trace file '%s'\n", cmdbuf);
+ fprintf(stderr, "Unable to create trace file '%s'\n", logdir);
dumptrace = 0;
}
}
=======================================
--- /branches/kkumar_code_organize/src/web100srv.c Fri Oct 14 13:52:19
2011
+++ /branches/kkumar_code_organize/src/web100srv.c Sun Oct 16 15:37:17
2011
@@ -83,20 +83,21 @@
#include "ndt_odbc.h"
#include "runningtest.h"
#include "strlutils.h"
-
-static char lgfn[256];
-static char wvfn[256];
-static char apfn[256];
-static char slfa[256];
-static char logd[256];
-static char portbuf[10];
-static char devicebuf[100];
-static char dbDSNbuf[256];
-static char dbUIDbuf[256];
-static char dbPWDbuf[256];
-
-/* list of global variables used throughout this program. */
-int window = 64000;
+#include "heuristics.h"
+
+static char lgfn[FILENAME_SIZE]; // log file name
+static char wvfn[FILENAME_SIZE]; // file name of web100-variables list
+static char apfn[FILENAME_SIZE]; // admin file name
+static char slfa[256]; // syslog facility
+static char logd[256]; // log dir name
+static char portbuf[10]; // port number user option store
+static char devicebuf[100]; // device name buf (seems unused)
+static char dbDSNbuf[256]; // DB datasource name
+static char dbUIDbuf[256]; // DB UID
+static char dbPWDbuf[256]; // DB Password
+
+// list of global variables used throughout this program.
+int window = 64000; // TCP buffer size
int randomize=0;
int count_vars=0;
int dumptrace=0;
@@ -610,12 +611,10 @@
}
else if (strncasecmp(key, "protocol_log", 12) == 0) {
sprintf(lgfn, "%s", val);
- printf("protocol_log calling set_protocoldir from: %s\n", val); //todo remove printf
set_protologdir(lgfn);
continue;
}
else if (strncasecmp(key, "enableprotolog", 11) == 0) {
- printf("enabling protocol logging from: %s\n", val); //todo remove printf
enableprotocollogging();
continue;
}
@@ -861,8 +860,7 @@
/**
* Capture CPU time details
*
- * @param arg* void pointer to the log file sued to record CPU time details
- * @param void* NULL
+ * @param arg* void pointer to the log file used to record CPU time details
* */
void*
cputimeWorker(void* arg)
@@ -904,13 +902,13 @@
run_test(web100_agent* agent, int ctlsockfd, TestOptions* testopt, char *test_suite)
{

- char date[32];
- char spds[4][256];
- char logstr1[4096], logstr2[1024];
+ char date[32]; // date
indicator
+ char spds[4][256]; // speed "bin" array containing counters for speeds
+ char logstr1[4096], logstr2[1024]; // log
char tmpstr[256];
char isoTime[64];

- int n; // todo what is n?
+ //int n; // temporary iterator variable --// commented out -> calc_linkspeed
int Timeouts, SumRTT, CountRTT, PktsRetrans, FastRetran, DataPktsOut;
int AckPktsOut, CurrentMSS, DupAcksIn, AckPktsIn, MaxRwinRcvd, Sndbuf;
int CurrentCwnd, SndLimTimeRwin, SndLimTimeCwnd, SndLimTimeSender, DataBytesOut;
@@ -919,42 +917,56 @@
int CongAvoid, CongestionOverCount, MaxRTT, OtherReductions, CurTimeoutCount;
int AbruptTimeouts, SendStall, SlowStart, SubsequentTimeouts, ThruBytesAcked;
int RcvWinScale, SndWinScale;
- int link=100, mismatch=0, bad_cable=0, half_duplex=0, congestion=0, totaltime;
+ int link=CANNOT_DETERMINE_LINK; // local temporary variable indicative of link speed. Transmitted
+ // but unused at client end , which has a similar link speed variable
+ int mismatch=0, bad_cable=0;
+ int half_duplex = NO_HALF_DUPLEX;
+ int congestion=0, totaltime;
int ret, spd_index;
- int index, links[16], max;
- int total; // total ifspeed ? todo
+ //int index; // commented out -> calc_linkspeed
+ //int links[16]; // commented out -> calc_linkspeed
+ // int max; // commented out -> calc_linkspeed
+ // int total;// commented out -> calc_linkspeed
int c2sdata = 0; // C->S data link speed indicator determined using results
int c2sack = 0; //
int s2cdata = 0; // S->C data link speed indicator determined using results
int s2cack = 0;
- int j;
+ //int j; // commented out -> calc_linkspeed
int totalcnt;
int autotune;
- int dec_cnt, same_cnt, inc_cnt, timeout, dupack;
- int ifspeed;
+ int dec_cnt, same_cnt, inc_cnt, timeout, dupack; // values collected from the sped tests
+ //int ifspeed;

time_t stime;

- double rttsec, rwin, swin, cwin;
- double rwintime, cwndtime, sendtime;
+ double rttsec; // average round trip time
+ double swin, cwin; //send, congestion window sizes respectively
+ double rwin; // max window size advertisement rcvd
+ double rwintime; // time spent being limited due to rcvr end
+ double cwndtime; // time spent being limited due to congestion
+ double sendtime; // time spent being limited due to sender's own fault
+
double oo_order; // out-of-order packet ratio
double waitsec;
- double bw2;
- double avgrtt; // Average roundtrip time
- double timesec;
- double loss2; // Packet loss as calculated from S->c tests. TODO change name. There also is no "loss"
- double RTOidle;
- double s2cspd; // average throughput
- double c2sspd;
- double s2c2spd;
- double spd; // total send throughput in S->C
- double acks, aspd = 0, tmouts, rtran, dack;
+ double bw_theortcl; // theoretical bandwidth
+ double avgrtt; // Average round-trip time
+ double timesec; // Total test time in microseconds
+ double packetloss_s2c; // Packet loss as calculated from S->c tests.
+ double RTOidle; // Proportion of idle time spent waiting for packets to arrive
+ double s2cspd; // average throughput as calculated by S->C test
+ double c2sspd; // average throughput as calculated by C->S test
+ double s2c2spd; // average throughput as calculated by midbox test
+ double realthruput; // total send throughput in S->C
+ double acksratio; // ratio of acks over packets sent
+ double aspd = 0;
+ double tmoutsratio; // timeouts fraction
+ double rtranratio, dackratio; // ratio of retransmissions and duplicate acks over packets sent
float runave[4];

FILE *fp;

web100_connection* conn;
- // protocol logging addition
+
// start with a clean slate of currently running test and direction
setCurrentTest(TEST_NONE);
printf ("Remote host= %s", get_remotehost());
@@ -963,7 +975,7 @@
log_println(4, "Child process %d started", getpid());
testopt->child0 = getpid();

- // initialize speed_index array. todo. what is this spd index?
+ // initialize speeds array
for (spd_index=0; spd_index<4; spd_index++)
for (ret=0; ret<256; ret++)
spds[spd_index][ret] = 0x00;
@@ -977,7 +989,7 @@
sprintf(buff, "v%s", VERSION);
send_msg(ctlsockfd, MSG_LOGIN, buff, strlen(buff));

- // initiate test with MSG_LOGIN message. TODO test_suite
+ // initiate test with MSG_LOGIN message.
log_println(3, "run_test() routine, asking for test_suite = %s", test_suite);
send_msg(ctlsockfd, MSG_LOGIN, test_suite, strlen(test_suite));
/* if ((n = initialize_tests(ctlsockfd, &testopt, conn_options))) {
@@ -1034,8 +1046,9 @@

/* alarm(25); */
log_println(6, "Starting s2c throughput test");
- if ((ret = test_s2c(ctlsockfd, agent, &*testopt, conn_options, &s2cspd, set_buff, window, autotune,
- device, &options, spds, &spd_index, count_vars, &peaks)) != 0) {
+ if ((ret = test_s2c(ctlsockfd, agent, &*testopt, conn_options,
+ &s2cspd, set_buff, window, autotune,
+ device, &options, spds, &spd_index, count_vars,
&peaks)) != 0) {
if (ret < 0)
log_println(6, "S2C test failed with rc=%d", ret);
log_println(0, "S2C throughput test FAILED!, rc=%d", ret);
@@ -1051,83 +1064,13 @@
}

// Compute variable values from test results and deduce results
- log_println(4, "Finished testing C2S = %0.2f Mbps, S2C = %0.2f Mbps", c2sspd/1000, s2cspd/1000);
-
- // The section below helps determine link speeds.
- // NDT quantizes throughput into one of a group of pre-defined bins/buckets that contain
- // counters. Get values of these bins (12 in number) and other key stats
- for (n=0; n<spd_index; n++) {
- sscanf(spds[n], "%d %d %d %d %d %d %d %d %d %d %d %d %f %d %d %d %d %d %d", &links[0],
- &links[1], &links[2], &links[3], &links[4], &links[5], &links[6],
- &links[7], &links[8], &links[9], &links[10], &links[11], &runave[n],
- &inc_cnt, &dec_cnt, &same_cnt, &timeout, &dupack, &ifspeed);
- max = 0;
- index = 0;
- total = 0;
- /* for (j=0; j<10; j++) { */
-
- if ((ifspeed == -1) || (ifspeed == 0) || (ifspeed > 10))
- ifspeed = 10; // ifspeed was probably not collected in these cases
-
- // get the ifspeed bin with the biggest counter value.
- // NDT determines link speed using this
- for (j=0; j<=ifspeed; j++) {
- total += links[j];
- if (max < links[j]) {
- max = links[j];
- index = j;
- }
- }
-
- // speed data was not collected correctly
- if (links[index] == -1)
- index = -1;
-
- // log
- fp = fopen(get_logfile(),"a");
- if (fp == NULL) {
- log_println(0, "Unable to open log file '%s', continuing on without logging", get_logfile());
- }
- else {
- fprintf(fp, "spds[%d] = '%s' max=%d [%0.2f%%]\n", n, spds[n],
- max, (float) max*100/total);
- fclose(fp);
- }
-
- // When the C2S test is disabled, we have to skip the results
- // Note: spd[0] , [1] contains C->S test results
- // spd[2] , spd [3] contains S->C test results
- switch (n + (testopt->c2sopt ? 0 : 2)) {
- case 0: c2sdata = index;
- log_print(1, "Client --> Server data detects link = ");
- break;
- case 1: c2sack = index;
- log_print(1, "Client <-- Server Ack's detect link = ");
- break;
- case 2: s2cdata = index;
- log_print(1, "Server --> Client data detects link = ");
- break;
- case 3: s2cack = index;
- log_print(1, "Server <-- Client Ack's detect link = ");
- }
-
- // classify link speed based on the max ifspeed seen
- switch (index) {
- case -1: log_println(1, "System Fault"); break;
- case 0: log_println(1, "RTT"); break;
- case 1: log_println(1, "Dial-up"); break;
- case 2: log_println(1, "T1"); break;
- case 3: log_println(1, "Ethernet"); break;
- case 4: log_println(1, "T3"); break;
- case 5: log_println(1, "FastEthernet"); break;
- case 6: log_println(1, "OC-12"); break;
- case 7: log_println(1, "Gigabit Ethernet"); break;
- case 8: log_println(1, "OC-48"); break;
- case 9: log_println(1, "10 Gigabit Enet"); break;
- case 10: log_println(1, "Retransmissions"); break;
- }
- } //end section to determine speed. TODO - break into new function? calc_link_speed
-
+ log_println(4, "Finished testing C2S = %0.2f Mbps, S2C = %0.2f Mbps",
+ c2sspd/1000, s2cspd/1000);
+
+ // Determine link speed
+ calc_linkspeed (spds, spd_index, &c2sdata, &c2sack,
+ &s2cdata, &s2cack, runave, &dec_cnt, &same_cnt, &inc_cnt,
+ &timeout, &dupack , testopt->c2sopt);
// Get web100 vars

// ...determine number of times congestion window has been changed
@@ -1158,72 +1101,55 @@
// section to calculate duplex mismatch

// Calculate average round trip time and convert to seconds
- avgrtt = (double) SumRTT/CountRTT;
- rttsec = avgrtt * .001;
- /* loss = (double)(PktsRetrans- FastRetran)/(double)(DataPktsOut-AckPktsOut); */
+ rttsec = calc_avg_rtt(SumRTT,CountRTT, &avgrtt);

// Calculate packet loss
- loss2 = (double)CongestionSignals/PktsOut;
- if (loss2 == 0) {
- if (c2sdata > 5)
- loss2 = .0000000001; // set to 10^-10 for links faster than FastE
- else
- loss2 = .000001; // set to 10^-6 for now
- }
+ packetloss_s2c = calc_packetloss(CongestionSignals, PktsOut, c2sdata);

// Calculate ratio of packets arriving out of order
- oo_order = (double)DupAcksIn/AckPktsIn;
+ oo_order = calc_packets_outoforder(DupAcksIn,AckPktsIn);

// calculate theoretical maximum goodput in bits
- // todo constants for 1024, 8.
- bw2 = (CurrentMSS / (rttsec * sqrt(loss2))) * 8 / 1024 / 1024;
-
- //
- if ((SndWinScale > 15) || (Sndbuf < 65535))
- SndWinScale = 0;
- if ((RcvWinScale > 15) || (MaxRwinRcvd < 65535))
- RcvWinScale = 0;
- /* MaxRwinRcvd <<= RcvWinScale; */
- /* if ((SndWinScale > 0) && (RcvWinScale > 0))
- * Sndbuf = (64 * 1024) << RcvWinScale;
- */
- /* MaxCwnd <<= RcvWinScale; */
-
- rwin = (double)MaxRwinRcvd * 8 / 1024 / 1024;
- swin = (double)Sndbuf * 8 / 1024 / 1024;
- cwin = (double)MaxCwnd * 8 / 1024 / 1024;
+ bw_theortcl = calc_max_theoretical_thruput(CurrentMSS,rttsec,packetloss_s2c);
+
+ //get window sizes
+ calc_window_sizes(&SndWinScale, &RcvWinScale, &Sndbuf, &MaxRwinRcvd, &MaxCwnd,
+ &rwin, &swin, &cwin);

// Total test time
- totaltime = SndLimTimeRwin + SndLimTimeCwnd + SndLimTimeSender;
-
- // time spent being send-limited due to congestion window
- rwintime = (double)SndLimTimeRwin/totaltime;
-
- // time spent in being receive limited due to client's recv window
- cwndtime = (double)SndLimTimeCwnd/totaltime;
+ totaltime = calc_totaltesttime(SndLimTimeRwin , SndLimTimeCwnd , SndLimTimeSender);
+
+ // time spent being send-limited due to client's recv window
+ rwintime = calc_sendlimited_rcvrfault(SndLimTimeRwin,totaltime);
+
+ // time spent in being send-limited due to congestion window
+ cwndtime = calc_sendlimited_cong(SndLimTimeCwnd,totaltime);

// time spent in being send-limited due to own fault
- sendtime = (double)SndLimTimeSender/totaltime;
- timesec = totaltime/1000000; // microsecs
-
- // Current retransmit timeoutX timeout count = idle time spent waiting for packets to arrive
- // When divided by total test time, they indicate fraction of time spent idle due to RTO
- RTOidle = (Timeouts * ((double)CurrentRTO/1000))/timesec;
- tmouts = (double)Timeouts / PktsOut; // timeout fraction //todo rename all 4
- rtran = (double)PktsRetrans / PktsOut; // retrans fraction
- acks = (double)AckPktsIn / PktsOut; // Fraction of acks recived for sent data
- dack = (double)DupAcksIn / (double)AckPktsIn; // duplicate acks fraction
-
- // actual throughput in Mbps (totaltime is in microseconds)
- spd = ((double)DataBytesOut / (double)totaltime) * 8;
- // todo rename spd to "calculated total send throughput"
+ sendtime = calc_sendlimited_sndrfault(SndLimTimeSender,totaltime);
+
+ timesec = totaltime/MEGA; // total time in get microsecs
+
+
+ // get fraction of total test time waiting for packets to arrive
+ RTOidle = calc_RTOIdle(Timeouts , CurrentRTO, timesec);
+
+ // get timeout, retransmission, acks and dup acks ratios.
+ tmoutsratio = (double)Timeouts / PktsOut;
+ rtranratio = (double)PktsRetrans / PktsOut;
+ acksratio = (double)AckPktsIn / PktsOut;
+ dackratio = (double)DupAcksIn / (double)AckPktsIn;
+
+ // get actual throughput in Mbps (totaltime is in microseconds)
+ realthruput = calc_real_thruput(DataBytesOut, totaltime);

// total time spent waiting
- waitsec = (double) (CurrentRTO * Timeouts)/1000;
+ waitsec = cal_totalwaittime( CurrentRTO, Timeouts);
+
log_println(2, "CWND limited test = %0.2f while unlimited = %0.2f", s2c2spd, s2cspd);

- // Is goodput measured from from S->C as reported by client > as reported by server?
- if ((s2c2spd > s2cspd) && (multiple == 0))
+ // Is thruput measured with limited cwnd(midbox test) > as reported S->C test
+ if (is_limited_cwnd_thruput_better(s2c2spd, s2cspd) && isNotMultipleTestMode(multiple))
log_println(2, "Better throughput when CWND is limited, may be duplex mismatch");
else
log_println(2, "Better throughput without CWND limits - normal operation");
@@ -1234,85 +1160,75 @@

// client link duplex mismatch detection heuristic
old_mismatch = 1;
+
if (old_mismatch == 1) {
- if ((cwndtime > .9) // more than 90% time spent being receiver window limited
- && (bw2 > 2) // theoretical max goodput > 2mbps
- && (PktsRetrans/timesec > 2)
- // #of segments with pkt-retransmissions> 2
- && (MaxSsthresh > 0) // max slow start
threshold > 0
- && (RTOidle > .01) // cumulative RTO
time > 1% test duration
- && (link > 2) // not
wireless link
- && (s2cspd < s2c2spd)
//S->C throughput calculated
-
// by server < client value
- && (multiple
== 0))
- {
- if (s2cspd < c2sspd) // also, S->C throughput is lesser than C->S throughput
- mismatch = 1;
- else
- mismatch = 2;
- link = 0;
- }
-
- // test for uplink with duplex mismatch condition
- if (((s2cspd/1000) > 50) // S->C goodput > 50 Mbps
- && (spd < 5) // actual send throughput
< 5 Mbps
- && (rwintime > .9) // receive window limited for
>90% of the time
- && (loss2 < .01)) // packet loss < 1%
- {
- mismatch = 2;
- link = 0;
- }
- } else {
- /* This section of code is being held up for non-technical reasons.
- * Once those issues are resolved a new mismatch detection algorim
- * will be placed here.
- * RAC 5-11-06
- */
- }
+ if (detect_duplexmismatch(cwndtime, bw_theortcl, PktsRetrans,
timesec,
+ MaxSsthresh, RTOidle, link, s2cspd, s2c2spd,
multiple)) {
+ if (is_c2s_thruputbetter(c2sspd, s2cspd)) { // also, S->C throughput is lesser than C->S throughput
+ mismatch = DUPLEX_OLD_ALGO_INDICATOR;
+ // possible duplex, from Old Duplex-Mismatch
logic
+ } else {
+ mismatch = DUPLEX_SWITCH_FULL_HOST_HALF;
+ // switch full, host half
+ }
+ link = LINK_ALGO_FAILED;
+ }
+
+ // test for uplink with duplex mismatch condition
+ if (detect_internal_duplexmismatch(
+ (s2cspd / 1000), realthruput, rwintime,
packetloss_s2c )) {
+ mismatch = DUPLEX_SWITCH_FULL_HOST_HALF; // switch
full, host half
+ link = LINK_ALGO_FAILED;
+ }
+ } else {
+ /* This section of code is being held up for non-technical
reasons.
+ * Once those issues are resolved a new mismatch detection
algorim
+ * will be placed here.
+ * RAC 5-11-06
+ */
+ }
+
// end section calculating duplex mismatch

+
+
// Section to deduce if there is faulty hardware links

// estimate is less than actual throughput, something is wrong
- if (bw2 < spd)
- link = 0;
-
- // Faulty hardware link heuristic. todo read about error here
- if (((loss2*100)/timesec > 15) && (cwndtime/timesec > .6) &&
- (loss2 < .01) && (MaxSsthresh > 0))
- bad_cable = 1;
+ if (bw_theortcl < realthruput)
+ link = LINK_ALGO_FAILED;
+
+ // Faulty hardware link heuristic.
+ if (detect_faultyhardwarelink( packetloss_s2c, cwndtime,
+ timesec, MaxSsthresh))
+ bad_cable = POSSIBLE_BAD_CABLE;

// test for Ethernet link (assume Fast E.)
- if ((spd < 9.5) && (spd > 3.0) && ((s2cspd/1000) < 9.5) &&
- (loss2 < .01) && (oo_order < .035) && (link > 0))
- link = 10;
+ if ( detect_ethernetlink (realthruput, s2cspd, packetloss_s2c, oo_order, link) )
+ link = LINK_ETHERNET;

// test for wireless link
- if ((sendtime == 0) && (spd < 5) && (bw2 > 50) &&
- ((SndLimTransRwin/SndLimTransCwnd) == 1) &&
- (rwintime > .90) && (link > 0))
- link = 3;
+ if ( detect_wirelesslink( sendtime, realthruput, bw_theortcl,
+ SndLimTransRwin, SndLimTransCwnd, rwintime, link) )
+ link = LINK_WIRELESS;

// test for DSL/Cable modem link
- if ((SndLimTimeSender < 600) && (SndLimTransSender == 0) && (spd < 2) &&
- (spd < bw2) && (link > 0))
- link = 2;
+ if( detect_DSLCablelink ( SndLimTimeSender, SndLimTransSender,
+ realthruput, bw_theortcl, link) )
+ link = LINK_DSLORCABLE;

// full/half link duplex setting heuristic:
// receiver-limited- time > 95%,
// .. number of transitions into the 'Receiver Limited' state is greater than 30 ps
// ...and the number of transitions into the 'Sender Limited' state is greater than 30 per second

- if ((rwintime > .95) && (SndLimTransRwin/timesec > 30) &&
- (SndLimTransSender/timesec > 30))
- half_duplex = 1;
+ if ( detect_halfduplex( rwintime, SndLimTransRwin, SndLimTransSender,
+ timesec) )
+ half_duplex = POSSIBLE_HALF_DUPLEX;

// congestion detection heuristic
- // ..Congestion-limited time share > 2%,
- // ...no duplex mismatch ,
- // ....max window advt received is > max congestion window used during Slow Start
- if ((cwndtime > .02) && (mismatch == 0) && ((cwin/rttsec) < (rwin/rttsec)))
- congestion = 1;
+ if (detect_congestionwindow( cwndtime, mismatch, cwin, rwin, rttsec))
+ congestion = POSSIBLE_CONGESTION;

// Send results and variable values to clients
sprintf(buff, "c2sData: %d\nc2sAck: %d\ns2cData: %d\ns2cAck: %d\n",
@@ -1320,11 +1236,11 @@
send_msg(ctlsockfd, MSG_RESULTS, buff, strlen(buff));

sprintf(buff, "half_duplex: %d\nlink: %d\ncongestion: %d\nbad_cable: %d\nmismatch: %d\nspd: %0.2f\n",
- half_duplex, link, congestion, bad_cable, mismatch, spd);
+ half_duplex, link, congestion, bad_cable, mismatch, realthruput);
send_msg(ctlsockfd, MSG_RESULTS, buff, strlen(buff));

sprintf(buff, "bw: %0.2f\nloss: %0.9f\navgrtt: %0.2f\nwaitsec: %0.2f\ntimesec: %0.2f\norder: %0.4f\n",
- bw2, loss2, avgrtt, waitsec, timesec, oo_order);
+ bw_theortcl, packetloss_s2c, avgrtt, waitsec, timesec, oo_order);
send_msg(ctlsockfd, MSG_RESULTS, buff, strlen(buff));

sprintf(buff, "rwintime: %0.4f\nsendtime: %0.4f\ncwndtime: %0.4f\nrwin: %0.4f\nswin: %0.4f\n",
@@ -1341,13 +1257,14 @@
// Signal end of test results to client
send_msg(ctlsockfd, MSG_LOGOUT, "", 0);

- // Copy collected values into the meta data structures
+ // Copy collected values into the meta data structures. This section
+ // seems most readable, easy to debug here.
sprintf(meta.date, "%s", get_ISOtime(isoTime,sizeof(isoTime)));
-//todo remove debug
- log_println(0, "meta.date=%s, meta.clientip =%s:%s:%d", meta.date, meta.client_ip, rmt_host,strlen(rmt_host));
+
+ log_println(9, "meta.date=%s, meta.clientip =%s:%s:%d", meta.date, meta.client_ip, rmt_host,strlen(rmt_host));
memcpy(meta.client_ip, rmt_host, strlen(rmt_host));
- log_println(0, "2. meta.clientip =%s:%s:%d", meta.client_ip, rmt_host);
-//todo remove debug
+ log_println(9, "2. meta.clientip =%s:%s:%d", meta.client_ip, rmt_host);
+
memset(tmpstr, 0, 255);
sprintf(tmpstr,"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,",
(int)s2c2spd,(int)s2cspd,(int)c2sspd, Timeouts, SumRTT, CountRTT, PktsRetrans,
@@ -1358,27 +1275,27 @@
MaxRwinRcvd, Sndbuf, MaxCwnd, SndLimTimeRwin, SndLimTimeCwnd,
SndLimTimeSender, DataBytesOut, SndLimTransRwin, SndLimTransCwnd,
SndLimTransSender, MaxSsthresh, CurrentRTO, CurrentRwinRcvd);
- //strncat(meta.summary, tmpstr, strlen(tmpstr));
+
strlcat(meta.summary, tmpstr, sizeof(meta.summary));
memset(tmpstr, 0, 255);
sprintf(tmpstr,"%d,%d,%d,%d,%d",
link, mismatch, bad_cable, half_duplex, congestion);
- //strncat(meta.summary, tmpstr, strlen(tmpstr));
+
strlcat(meta.summary, tmpstr, sizeof(meta.summary));
memset(tmpstr, 0, 255);
sprintf(tmpstr, ",%d,%d,%d,%d,%d,%d,%d,%d,%d", c2sdata, c2sack, s2cdata, s2cack,
CongestionSignals, PktsOut, MinRTT, RcvWinScale, autotune);
- //strncat(meta.summary, tmpstr, strlen(tmpstr));
+
strlcat(meta.summary, tmpstr, sizeof(meta.summary));
memset(tmpstr, 0, 255);
sprintf(tmpstr, ",%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", CongAvoid, CongestionOverCount, MaxRTT,
OtherReductions, CurTimeoutCount, AbruptTimeouts, SendStall, SlowStart,
SubsequentTimeouts, ThruBytesAcked);
- //strncat(meta.summary, tmpstr, strlen(tmpstr));
+
strlcat(meta.summary, tmpstr, sizeof(meta.summary));
memset(tmpstr, 0, 255);
sprintf(tmpstr, ",%d,%d,%d", peaks.min, peaks.max, peaks.amount);
- //strncat(meta.summary, tmpstr, strlen(tmpstr));
+
strlcat(meta.summary, tmpstr, sizeof(meta.summary));
writeMeta(options.compress, cputime, options.snaplog, dumptrace);

@@ -1463,7 +1380,10 @@
}

/**
- * main method
+ * Initializes data structures,
+ * web100 structures and logging systems. Read/load configuration, get process
+ * execution options. Accept test requests and manage their execution order and
+ * initiate tests. Keep track of running processes.
* @param argc Number of arguments
* @param argv string command line arguments
* */
@@ -1967,9 +1887,10 @@
* if (mchild != head_ptr) {
*/
tmp_ptr = mchild;
+
// Update queued clients, send message to client when it moves
// up in the queue enough to get closer to running a test. This happens
- // when the client falls into the next lower maxquee bin
+ // when the client falls into the next lower maxqueue bin
// RAC 3/21/10

int rac;
@@ -2063,7 +1984,7 @@
FD_ZERO(&rfd);
FD_SET(listenfd, &rfd);
if (waiting > 0) { // there are clients waiting
- sel_tv.tv_sec = 3; // todo 3 seconds == WAIT_TIME_SRVR
+ sel_tv.tv_sec = 3; // 3 seconds == WAIT_TIME_SRVR
sel_tv.tv_usec = 0;
log_println(3, "Waiting for new connection, timer running");
sel_11:
@@ -2118,7 +2039,7 @@
}
}
}
- for (i=0;i<5;i++) {
+ for (i=0;i<RETRY_COUNT;i++) {
ctlsockfd = 0;
ctlsockfd = accept(listenfd, (struct sockaddr *) &cli_addr, &clilen);

@@ -2144,11 +2065,11 @@
else { // accept worked, log protocol validation log to indicate that client tried connecting
procstatusenum = PROCESS_STARTED;
proctypeenum = CONNECT_TYPE;
- protolog_procstatus(getpid(), getCurrentTest(), proctypeenum, procstatusenum); // todo pid?
+ protolog_procstatus(getpid(), getCurrentTest(), proctypeenum, procstatusenum);
}

// the specially crafted data that kicks off the old clients
- for (i=0; i<5; i++) { // todo 5==SOCKET_IO_RETRY_COUNT
+ for (i=0; i<RETRY_COUNT; i++) {
rc = write(ctlsockfd, "123456 654321", 13);
if ((rc == -1) && (errno == EINTR)) // interrupted, retry
continue;
@@ -2180,8 +2101,6 @@
memset(new_child, 0, sizeof(struct ndtchild));
tt = time(0);
name = tmpstr;
- //todo remove debug log
- log_println(" CLIENT CLIENT CLIENT IP=%s",tmpstr);

rmt_host = tmpstr;

@@ -2221,7 +2140,7 @@
((multiple == 1) && (waiting >= ((4*max_clients)-1)))) {
log_println(0, "Too many clients/mclients (%d) waiting to be served, Please try again later.",
chld_pid);
- sprintf(tmpstr, "9988"); //TODO 9988= server_BUSY_OR_ERROR
+ sprintf(tmpstr, "9988"); // 9988 = server_BUSY_OR_ERROR
send_msg(ctlsockfd, SRV_QUEUE, tmpstr, strlen(tmpstr));
close(chld_pipe[0]);
close(chld_pipe[1]);
@@ -2272,7 +2191,7 @@
new_child->running = 0;
new_child->ctlsockfd = ctlsockfd;
if (t_opts & TEST_STATUS)
- new_child->oldclient = 1; //todo what does oldclient mean?
+ new_child->oldclient = 1;
else
new_child->oldclient = 0;
memset(new_child->tests, 0, sizeof(test_suite));
@@ -2388,7 +2307,7 @@
tmp_ptr = tmp_ptr->next;
j--;
}
- if ((waiting > 5) && (zombie_check == 0)) { // todo why specifically 5 clients for killing zombies?
+ if ((waiting > 5) && (zombie_check == 0)) { // more then 5 clients waiting, killing zombies
zombie_check = -1;
log_println(4, "More than 5 clients in the queue, remove
zombies");
if (pthread_create(&zombieThreadId, NULL, zombieWorker, (void *)head_ptr)) {
@@ -2661,7 +2580,9 @@
}
}

-/** Method to get remote hots's address.
+/**
+ * Method to get remote host's address.
+ * @return remote host name
* */
char *get_remotehost() {
return rmt_host;
=======================================
--- /branches/kkumar_code_organize/src/web100srv.h Thu Oct 13 10:32:49
2011
+++ /branches/kkumar_code_organize/src/web100srv.h Sun Oct 16 15:37:17
2011
@@ -71,7 +71,7 @@
// Congestion window peak information
typedef struct CwndPeaks {
int min; // trough of peak value
- int max; // maximun peak value
+ int max; // maximum peak value
int amount; // number of transitions between peaks
} CwndPeaks;

@@ -82,8 +82,8 @@
char avoidSndBlockUp; // flag set to indicate avoiding send buffer blocking in the S2C test
char snaplog; // enable collecting snap log
char cwndDecrease; // enable analysis of the cwnd changes (S2C test)
- char s2c_logname[128]; // S2C log file name
- char c2s_logname[128]; // C2S log file name
+ char s2c_logname[256]; // S2C log file name - size changed to 256
+ char c2s_logname[256]; // C2S log file name - size changed to 256
int compress; // enable compressing log files
} Options;

@@ -107,49 +107,51 @@
struct ndtchild *next; // next process in queue
};

+/* structure used to collect speed data in bins */
struct spdpair {
- int family;
+ int family; // Address family
#if defined(AF_INET6)
- u_int32_t saddr[4];
- u_int32_t daddr[4];
+ u_int32_t saddr[4]; // source address
+ u_int32_t daddr[4]; // dest address
#else
- u_int32_t saddr;
- u_int32_t daddr;
+ u_int32_t saddr; // source address
+ u_int32_t daddr; // dest address
#endif
- u_int16_t sport;
- u_int16_t dport;
- u_int32_t seq;
- u_int32_t ack;
- u_int32_t win;
- int links[16];
- u_int32_t sec;
- u_int32_t usec;
+ u_int16_t sport; // source port
+ u_int16_t dport; // destination port
+ u_int32_t seq; // seq number
+ u_int32_t ack; // number of acked bytes
+ u_int32_t win; // window size
+ int links[16]; // bins for link speeds
+ u_int32_t sec; // time indicator
+ u_int32_t usec; // time indicator, microsecs
u_int32_t st_sec;
u_int32_t st_usec;
- u_int32_t inc_cnt;
- u_int32_t dec_cnt;
- u_int32_t same_cnt;
- u_int32_t timeout;
- u_int32_t dupack;
- double time;
- double totalspd;
- double totalspd2;
- u_int32_t totalcount;
+ u_int32_t inc_cnt; // count of times window size was incremented
+ u_int32_t dec_cnt; // count of times window size was decremented
+ u_int32_t same_cnt; // count of times window size remained same
+ u_int32_t timeout; // # of timeouts
+ u_int32_t dupack; // # of duplicate acks
+ double time; // time, often sec+usec from above
+ double totalspd; // speed observed
+ double totalspd2; // running average (spd of current calculated (total speed) and prior value)
+ u_int32_t totalcount; // total number of valid speed data bins
};

struct spdpair fwd, rev;

+
struct web100_variables {
- char name[256];
- char value[256];
+ char name[256]; // key
+ char value[256]; // value
} web_vars[WEB100_VARS];

struct pseudo_hdr { /* used to compute TCP checksum */
- unsigned long s_addr;
- unsigned long d_addr;
- char pad;
- unsigned char protocol;
- unsigned short len;
+ unsigned long s_addr; // source addr
+ unsigned long d_addr; // destination address
+ char pad; // padding characterr
+ unsigned char protocol; // protocol indicator
+ unsigned short len; // header length
};

int32_t gmt2local(time_t);


  • [ndt-dev] [ndt] r721 committed - Define all test heuristics, classify protocol/I_O functionality into a..., ndt, 10/16/2011

Archive powered by MHonArc 2.6.16.

Top of Page