#include #include #include #include #include #include #include #include #include #include #include "ping.h" #include "abwm.h" /* include reatime libraries */ #include #include pthread_t thread; double divergeThreshhold = 0.0002; int maxIteration = 3; double bwLow, bwHigh; double intervalStep; double interval; // the time interval btw probing msgs of current round int reqID; // sequence number for the probing msg double bwAvailble; // the estimated results double bwPrevious; // previous round's measurement result double errorMargin; // how precise we want it to be int probingResponderID; int iteration; int test; int tableCount = 1; double iterationEndTime; boolean roundNotFinished = false; boolean alighFlag = false; boolean reportValid = true; boolean resultFlag = false; double result; int refPkID = 1; //to indicate which packet is used as reference pk for diverge comparison int *trendBeginPoint; int *trendEndPoint; double *absGapDiffDirivative; double *ABWArray; double *bandwidthReq; double variance=0.0; double stdVar; /* ICMP packet declaration */ struct sockaddr_in whereto; /* Who to ping */ struct sockaddr_in from; /* Our (source) address */ static int icmp_socket; /* Socket file descriptor */ hrtime_t last_time; hrtime_t this_time; hrtime_t recv_time; /* round trip time of packet */ hrtime_t rtt = (hw_time_t) 0; /* rtt of each packet */ hrtime_t rtts[MAX_PROBES]; /* dparture time of each packet */ hrtime_t depart[MAX_PROBES]; /* arrival time of each packet */ hrtime_t arrive[MAX_PROBES]; int bytes[MAX_PROBES]; /* size of each packet */ u_char packets[MAX_PROBES][MAXPACKET]; /* Incoming packet */ u_char outpack[MAXPACKET]; /* Outgoing packet */ int datalen = 1480 - ICMP_MINLEN; /* How much data (was 64) */ /* did this packet come in order ?*/ int orderOK[MAX_PROBES] = {0,0,0,0,0,0,0,0,0,0}; int returned[MAX_PROBES] = {0,0,0,0,0,0,0,0,0,0}; int npackets; int numPaths = 0; /* how many paths did the packets take ? */ int routeData = 0; /* did we find RR data ? */ int inOrder = 1; /* were the packets in order ? */ int duplicatePkts = 0; /* were there any duplicate packets ? */ int packet_id; int TRUE = 1; int FALSE = 0; u_char optval[MAX_IPOPTLEN]; optstr *sumopt = NULL, *curopt; /* BC for RR option */ volatile int TimeOutFlag; #define MAX_PROBES 100 int equalBWTimeGap = 1; int msgSize = 1000; /* in terms of bytes!!! */ int noOfMsgs = 10; /* */ /* Temporarly hard coded debug on */ int debug = 0; /* 0=off 1=on */ /* */ int iteration = 0; int packetSize[MAX_PROBES]; double sendingTime[MAX_PROBES]; /* sending time of each packet */ double receivingTime[MAX_PROBES]; /* receiving time of each packet */ double receivingTimeAA[MAX_PROBES]; /* receiving time of each packet */ double sendingTimeGap[MAX_PROBES]; /* sending time gap of each packet */ double absSendingTimeGap[MAX_PROBES];/* absolute sending time gap */ double receivingTimeGap[MAX_PROBES]; double absReceivingTimeGap[MAX_PROBES]; double gapDifference[MAX_PROBES]; double absGapDifference[MAX_PROBES]; double bwrLowerBound, bwrUpperBound; BWRange bwr; BWRange curBWR; //struct timeval tv1, tv2, stv[100], etv[100], starttv; struct timespec rttv, rtstarttv, rtstv[100],rtetv[100]; char *cp, *ap; char *HostName, *hostname, *my_name; int fp; struct protoent *proto; /* the following shared memory code is in Advanced Unix Programming p. 194 */ #define MAXMSG 4096 #define MAXOPEN 20 #define BADADDR (char *) (-1) int sndsid, rcvsid, segid; char *addr; int findinfo(int key, int *sndsidp, int *rcvsidp, char **addrp, int *segidp) /* added variable declaration - dsk */ { static struct { int segid; /* segment id */ int key; /* key */ char *addr; /* addr of shared memory segment */ int sndsid; /* semaphore-ID for writing totalBytes */ int rcvsid; /* semaphore-ID for reading totalBytes */ } sems[MAXOPEN]; int i, avail; // extern int errno; // ask about this one and the next line // char *shmat(); avail = -1; for (i=0; i v2) return v1; else return v2; } void findBWRange(void) { int divergePoint = noOfMsgs+1; boolean notDiverge = true; boolean refNotFound = true; boolean foundFlag = false; int nearestPoint1; int nearestPoint2; double abs, abs1; double ABW1, ABW2; int i; int k; int trend=1; if (debug) rtl_printf("findBWRange\n"); bandwidthReq[1] = curBWR.lowerBound; for(i=2; i<=noOfMsgs-1; i++) bandwidthReq[i] = msgSize*8/sendingTimeGap[i-1]; for (i=1; i= 0) { k=i+1; while((k<=noOfMsgs-1) & (refNotFound)) { if(absGapDifference[k] > divergeThreshhold) { if(k <= noOfMsgs-2) { //to see whether the trend keep for at least 2 packets, // if not, it's not a divergent point if (absGapDifference[k+1] >= absGapDifference[k]) { // divergePoint = k; refNotFound = false; refPkID = i; } } else { //k=9 or 10 // divergePoint = k; refNotFound = false; refPkID = i; } } k++; } } i++; }//end of while ( for(k=2; k<=noOfMsgs-1; k++) //2, 10 absGapDiffDirivative[k]=absGapDifference[k]-absGapDifference[k-1]; trendBeginPoint[1] = refPkID; for(k=refPkID+1; k<=noOfMsgs-2; k++) { //2, 9 if((absGapDiffDirivative[k]>0) && (absGapDiffDirivative[k+1] <= 0)) { //trend finish trendEndPoint[trend] = k; trend++; trendBeginPoint[trend] = k+1; } if(k == noOfMsgs-2) trendEndPoint[trend] = k+1; } for(i=1; i<=trend; i++) { // net.println("trend "+i+" start from "+trendBeginPoint[i]+ // " and end at "+trendEndPoint[i]); if (debug) rtl_printf("trend %d start from %d and end at %d\n", i, trendBeginPoint[i], trendEndPoint[i]); notDiverge = true; k=trendBeginPoint[i]; while((k<=trendEndPoint[i]) & (notDiverge)) { if(absGapDiffDirivative[k] > 0) { notDiverge = false; divergePoint = k; } k++; } if(!notDiverge) { if (debug) rtl_printf("Diverge Point=%d\n", divergePoint); for(k=trendBeginPoint[i]; k<=trendEndPoint[i]; k++) { if(divergePoint == 2) ABWArray[k] = (curBWR.lowerBound+msgSize*8/sendingTimeGap[divergePoint-1])/2; else ABWArray[k] = ( msgSize*8/sendingTimeGap[divergePoint-2] + msgSize*8/sendingTimeGap[divergePoint-1] ) / 2; } } else //only possible in the last trend if (debug) rtl_printf("Not diverge in last trend, need another iteration.\n"); } if(refPkID > 1) { //handle the points before refPk for(i=1; i<=noOfMsgs-1; i++) if (debug) rtl_printf("absGapDifference[%d] = %f\n", i, absGapDifference[i]); for(i=1; i 1) for(i=1;i<=noOfMsgs-1;i++) if (debug) rtl_printf("ABWArray[%d]=%f\n", i, ABWArray[i]); if (notDiverge) { //if the last trend is not diverged, that means the result is not valid bwr.upperBound = 2*curBWR.upperBound; bwr.lowerBound = curBWR.upperBound/2; bwr.reportValid = false; } else { bwr.reportValid = true; } for(i=1; i<=noOfMsgs-1; i++) bwr.reportValue += (1/(noOfMsgs+0.0))*ABWArray[i]; if (debug) rtl_printf("report Value = %f\n", bwr.reportValue); if (bwr.reportValid) { if (debug) rtl_printf("reportValid is true\n"); } else { if (debug) rtl_printf("reportValid is fasle\n"); } for(i=1; i<=noOfMsgs-1; i++) variance += (ABWArray[i] - bwr.reportValue) * (ABWArray[i] -bwr.reportValue); stdVar = sqrt(variance/(noOfMsgs-2)); bwr.accuracy = stdVar/bwr.reportValue; if (debug) rtl_printf("Accuracy is %f\n", bwr.accuracy); i=1; foundFlag = false; while( (i<=noOfMsgs-2) & (foundFlag==false)) { if(bwr.reportValue>=bandwidthReq[i] && bwr.reportValue= noOfMsgs-2) bwr.upperBound = bandwidthReq[noOfMsgs]; /* Chow: error here should be bandwidthReq[i+1] narrower else bwr.upperBound = bandwidthReq[i+2]; */ else bwr.upperBound = bandwidthReq[i+1]; } i++; } if (debug) rtl_printf("!! iteration=%d, next round bwr.upperBound=%f,lowerBound=%f\n", iteration, bwr.upperBound, bwr.lowerBound); bwrLowerBound = bwr.lowerBound; bwrUpperBound = bwr.upperBound; } /* * Print an IP header with options. */ void pr_iph(struct ip *ip) { int hlen; unsigned char *uchp; struct in_addr bobsInAddr; char *bobString1, *bobString2; hlen = ip->ip_hl << 2; uchp = (unsigned char *) ip + 20; /* point to options */ rtl_printf("Vr HL TOS Len ID Flg off TTL Pro cks Src Dst Data\n"); rtl_printf(" %1d %2d %02x %04d %04x", ip->ip_v, ip->ip_hl, ip->ip_tos, ip->ip_len, ip->ip_id); rtl_printf(" %1x %04x", ((ip->ip_off) & 0xe000) >> 13, (ip->ip_off) & 0x1fff); rtl_printf(" %3d %3d %04x", ip->ip_ttl, ip->ip_p, ip->ip_sum); bobsInAddr.s_addr = ip->ip_src.s_addr; bobString1 = inet_ntoa(bobsInAddr); bobsInAddr.s_addr = ip->ip_dst.s_addr; bobString2 = inet_ntoa(bobsInAddr); rtl_printf(" %-15s %-15s ", bobString1, bobString2); /* rtl_printf(" %-15s %-15s ", inet_ntoa(ip->ip_src.s_addr), inet_ntoa(ip->ip_dst.s_addr)); */ /* dump and option bytes */ while (hlen-- > 20) { rtl_printf("%02x", *uchp++); } rtl_printf("\n"); } /* * Dump some info on a returned (via ICMP) IP packet. */ void pr_retip(struct ip *ip) { int hlen; unsigned char *chp; pr_iph(ip); hlen = ip->ip_hl << 2; chp = (unsigned char *) ip + hlen; if (ip->ip_p == 6) { rtl_printf("TCP: from port %d, to port %d (decimal)\n", (*chp * 256 + *(chp + 1)), (*(chp + 2) * 256 + *(chp + 3))); } else if (ip->ip_p == 17) { rtl_printf("UDP: from port %d, to port %d (decimal)\n", (*chp * 256 + *(chp + 1)), (*(chp + 2) * 256 + *(chp + 3))); } } /* * * Subtract 2 hw_time_t's (which are in microseconds). * Clock rolls over every 40*2^32 ns (171 sec) so this * routine is not guaranteed if measurements are more * than 171 sec apart. * */ hw_time_t timesub(hw_time_t *first, hw_time_t *second) { hw_time_t result; /* since this is a 32 bit counter, wraparound works fine */ result = *first - *second; return result; } /* * Return an ascii host address * as a dotted quad and optionally with a hostname */ char * pr_addr(struct in_addr addr) { struct hostent *hp; static char buf[80]; if ((hp = gethostbyaddr(&addr.s_addr, 4, AF_INET)) == NULL) sprintf(buf, "%s", inet_ntoa(addr)); else sprintf(buf, "%s (%s)", hp->h_name, inet_ntoa(addr)); return (buf); } void print_ip_msg(u_char buf[], int count) { register int i; for (i=0; iicmp_type, icp->icmp_code, icp->icmp_cksum, icp->icmp_seq, icp->icmp_id, *((hw_time_t *) icp+8)); } /* Parse a numeric IP address or symbolic host name and return a sockaddr_in */ char * a2sockaddr(struct sockaddr_in *addr, char *cp, char *name) { static struct hostent *hp; static char buf[80]; #undef HOST_NOT_FOUND #define HOST_NOT_FOUND 0 #define h_nerr 1 const char *h_errlist[h_nerr] = { "unknown host" }; bzero((caddr_t) addr, sizeof(*addr)); addr->sin_family = AF_INET; addr->sin_addr.s_addr = inet_addr(cp); if (addr->sin_addr.s_addr == -1) { hp = (struct hostent *)NULL; hp = gethostbyname(cp); if (hp) { addr->sin_family = hp->h_addrtype; bcopy(hp->h_addr, (caddr_t) & addr->sin_addr, hp->h_length); cp = hp->h_name; } else { sprintf(buf, "%s: %s", h_errlist[h_errno < h_nerr ? h_errno : HOST_NOT_FOUND], cp); return buf; } } if (name) { strncpy(name, cp, MAXHOSTNAMELEN); } return (char *) 0; } /* * tvsub -- * Subtract 2 timeval structs: out = out - in. Out is assumed to * be >= in. */ void tvsub(register struct timespec *out, register struct timespec *in) { if ((out->tv_nsec -= in->tv_nsec) < 0) { --out->tv_sec; out->tv_nsec += 1000000; } out->tv_sec -= in->tv_sec; } /* * I N _ C K S U M * * Checksum routine for Internet Protocol family headers (C Version) * */ u_short in_cksum(u_short *addr, int len) { register int nleft = len; register u_short *w = addr; register u_short answer; register int sum = 0; /* * Our algorithm is simple, using a 32 bit accumulator (sum), * we add sequential 16 bit words to it, and at the end, fold * back all the carry bits from the top 16 bits into the lower * 16 bits. */ while (nleft > 1) { sum += *w++; nleft -= 2; } /* mop up an odd byte, if necessary */ if (nleft == 1) { sum += *(u_char *) w; } /* * add back carry outs from top 16 bits to low 16 bits */ sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ sum += (sum >> 16); /* add carry */ answer = ~sum; /* truncate to 16 bits */ return (answer); } /* * P R _ P A C K * * Print out the packet, if it came from us. This logic is necessary * because ALL readers of the ICMP socket get a copy of ALL ICMP packets * which arrive ('tis only fair). This permits multiple copies of this * program to be run without having intermingled output (or statistics!). */ int recv_icmp(int s, u_char *buf, int len, int i) { int cc; struct sockaddr_in from; int fromlen = (sizeof from); struct ip *ip; register struct icmp *icp; int hlen; if ((cc = recvfrom(s, buf, len, 0, &from, &fromlen)) < 0) { if (errno != EINTR) fprintf(stderr, "ping: recvfrom"); return (cc); } /* Chow: this_time is relative to starttv and in 1 usec */ clock_gettime(CLOCK_REALTIME, &rtetv[i]); ip = (struct ip *) buf; hlen = ip->ip_hl << 2; /* Is this packet the right length? */ if (cc < hlen + ICMP_MINLEN) { /* fprintf(stderr, "packet too short (%d bytes) from %s\n", cc, inet_ntoa(from.sin_addr)); */ return (-1); } cc -= hlen; icp = (struct icmp *) (buf + hlen); if (debug) { rtl_printf("%d bytes (not including ip header %d bytes) from %s:\n", cc, hlen, pr_addr(from.sin_addr)); rtl_printf("msg received in hexadecimal:\n"); print_ip_msg(buf, cc+hlen); rtl_printf("\n"); print_icmp_msg(icp); } /* is this packet the right type? */ if (icp->icmp_type != ICMP_ECHOREPLY && icp->icmp_type != ICMP_TSTAMPREPLY) { /* fprintf(stderr, "wrong type: len=%d addr=%s: ", cc, pr_addr(from.sin_addr)); */ pr_icmph(icp); return (-1); } /* was it our ECHO? */ if (icp->icmp_id != out_icmp->icmp_id) return (-1); /* move the rest of the code to packetAnalysis() executed after after all packets received. It avoids missing the next sending time */ /* calculate this packet's rtt in ms */ packet_id = icp->icmp_seq; return (cc+hlen); } /* * Print a descriptive string about an ICMP header. */ void pr_icmph(struct icmp *icp) { switch (icp->icmp_type) { case ICMP_ECHOREPLY: rtl_printf("Echo Reply\n"); /* XXX ID + Seq + Data */ break; case ICMP_UNREACH: switch (icp->icmp_code) { case ICMP_UNREACH_NET: rtl_printf("Destination Net Unreachable\n"); break; case ICMP_UNREACH_HOST: rtl_printf("Destination Host Unreachable\n"); break; case ICMP_UNREACH_PROTOCOL: rtl_printf("Destination Protocol Unreachable\n"); break; case ICMP_UNREACH_PORT: rtl_printf("Destination Port Unreachable\n"); break; case ICMP_UNREACH_NEEDFRAG: rtl_printf("frag needed and DF set\n"); break; case ICMP_UNREACH_SRCFAIL: rtl_printf("Source Route Failed\n"); break; default: rtl_printf("Dest Unreachable, Bad Code: %d\n", icp->icmp_code); break; } /* Print returned IP header information */ pr_retip((struct ip *)icp->icmp_data); break; case ICMP_SOURCEQUENCH: rtl_printf("Source Quench\n"); pr_retip((struct ip *)icp->icmp_data); break; case ICMP_REDIRECT: switch (icp->icmp_code) { case ICMP_REDIRECT_NET: rtl_printf("Redirect Network"); break; case ICMP_REDIRECT_HOST: rtl_printf("Redirect Host"); break; case ICMP_REDIRECT_TOSNET: rtl_printf("Redirect Type of Service and Network"); break; case ICMP_REDIRECT_TOSHOST: rtl_printf("Redirect Type of Service and Host"); break; default: rtl_printf("Redirect, Bad Code: %d", icp->icmp_code); break; } rtl_printf(" (New addr: 0x%08x)\n", icp->icmp_hun.ih_gwaddr); pr_retip((struct ip *)icp->icmp_data); break; case ICMP_ECHO: rtl_printf("Echo Request\n"); /* XXX ID + Seq + Data */ break; case ICMP_TIMXCEED: switch (icp->icmp_code) { case ICMP_TIMXCEED_INTRANS: rtl_printf("Time to live exceeded\n"); break; case ICMP_TIMXCEED_REASS: rtl_printf("Frag reassembly time exceeded\n"); break; default: rtl_printf("Time exceeded, Bad Code: %d\n", icp->icmp_code); break; } pr_retip((struct ip *)icp->icmp_data); break; case ICMP_PARAMPROB: rtl_printf("Parameter problem: pointer = 0x%02x\n", icp->icmp_hun.ih_pptr); pr_retip((struct ip *)icp->icmp_data); break; case ICMP_TSTAMP: rtl_printf("Timestamp\n"); /* XXX ID + Seq + 3 timestamps */ break; case ICMP_TSTAMPREPLY: rtl_printf("Timestamp Reply\n"); /* XXX ID + Seq + 3 timestamps */ break; case ICMP_IREQ: rtl_printf("Information Request\n"); /* XXX ID + Seq */ break; case ICMP_IREQREPLY: rtl_printf("Information Reply\n"); /* XXX ID + Seq */ break; case ICMP_MASKREQ: rtl_printf("Address Mask Request\n"); break; case ICMP_MASKREPLY: rtl_printf("Address Mask Reply\n"); break; default: rtl_printf("Bad ICMP type: %d\n", icp->icmp_type); } } void finish(void) { /* set TimeOutFlag to stop spinning on recv socket */ TimeOutFlag = 1; if (debug) rtl_printf("Timeout exceeded.\n"); return; } void help_msg(void) { rtl_printf("format: abwm -[dn:l:u:s:] hostname \n"); rtl_printf(" option: d set debug mode\n"); rtl_printf(" option: n set number of messages sent\n"); rtl_printf(" option: l set lower bound of probing bandwidth\n"); rtl_printf(" option: u set upper bound of probing bandwidth\n"); rtl_printf(" option: s set message size\n"); } void printsockaddr(struct sockaddr_in *arg) { struct hostent *hp; rtl_printf(" sockaddr_in: "); rtl_printf("Domain=%d, ", arg->sin_family); hp=gethostbyaddr((const char *)&(arg->sin_addr), sizeof(arg->sin_addr), AF_INET); rtl_printf("Hostname=%s, ", hp->h_name); rtl_printf("Port=%d, ", ntohs(arg->sin_port)); rtl_printf("Address=%s,\n", inet_ntoa(arg->sin_addr)); } /* old version void waitRelativeTime(int time) { while (1) { (void) gettimeofday(&tv2, &tz); if ((tv2.tv_sec-starttv.tv_sec)*1000000+(tv2.tv_usec-starttv.tv_usec)- time>=-4) break; } } */ void setupICMPacket(void){ /* Init packet fields */ // out_icmp->icmp_id = (getpid() & 0xFFFF); /* ask about this one */ out_icmp->icmp_id = 2; /* hardcoded this value */ out_icmp->icmp_type = ICMP_ECHO; out_icmp->icmp_code = 0; /******** rtl_printf("get socket address %s\n", HostName); ********/ /* get Internet address from hostname or dot-notation */ // if (cp = (a2sockaddr(&whereto, HostName, hostname))) if ((test = (inet_pton(AF_INET, HostName, &whereto.sin_addr))) < 0) { fprintf(stderr, "%s: %d\n", my_name, test); // exit(1); } if (debug) printsockaddr(&whereto); /******** rtl_printf("fill packet\n"); ********/ /* fill outgoing packet with position info */ for (fp = 0; fp < MAXDATA; fp++) { out_pattern[fp] = fp + sizeof(struct timeval); } /******** rtl_printf("open the socket\n"); ********/ /* open the socket */ if ((proto = getprotobyname("icmp")) == NULL) { fprintf(stderr, "icmp: unknown protocol\n"); // exit(10); } if ((icmp_socket = socket(AF_INET, SOCK_RAW, proto->p_proto)) < 0) { fprintf(stderr, "rpr: socket"); // exit(5); } /******** rtl_printf("set RR options\n"); ********/ /* BC 5-30-95 : add record route options from Ping+ */ /* RR IP_OPTIONS */ /* Chow: disable RR option difficult to pass most routers */ bzero(optval, sizeof(optval)); optval[IPOPT_OPTVAL] = (char) IPOPT_RR; optval[IPOPT_OLEN] = (char) MAX_IPOPTLEN - 1, optval[IPOPT_OFFSET] = (char) IPOPT_MINOFF; optval[MAX_IPOPTLEN - 1] = (char) IPOPT_EOL; if ((proto = getprotobyname("ip")) == NULL) { fprintf(stderr, "ip: unknown protocol\n"); // exit(8); } if (setsockopt(icmp_socket, proto->p_proto, IP_OPTIONS, optval, MAX_IPOPTLEN) < 0) { perror("setsockopt: IP_OPTIONS"); // exit(42); } /* */ /* RR IP_OPTIONS */ // ap is never used, this code was not ported to RT // (void) gettimeofday(&starttv, &tz); // ap = asctime(localtime((const time_t *)&starttv.tv_sec)); // ap[strlen(ap) -1] = '\0' ; } void sendMsg(int reqID, hw_time_t this_time){ /* send probing msg out */ datalen = packetSize[reqID]; bytes[reqID] = datalen; returned[reqID] = 0; if (debug) rtl_printf("sendMsg(): ready to send icmp msg reqID=%d, this_time=%d\n", reqID, this_time); send_icmp(icmp_socket, reqID, &whereto); if (debug) rtl_printf("sendMsg(): icmp msg sent, reqID=%d, this_time=%d\n", reqID, this_time); reqID++; } /* * P I N G E R * * Compose and transmit an ICMP ECHO REQUEST packet. The IP packet * will be added on by the kernel. The ID field is our UNIX process ID, * and the sequence number is an ascending integer. The first 8 bytes * of the data portion are used to hold a UNIX "timeval" struct in VAX * byte-order, to compute the round-trip time. */ void send_icmp(int s, int seq, struct sockaddr_in *addr) { int i, cc; out_icmp->icmp_cksum = 0; out_icmp->icmp_seq = seq; cc = datalen + ICMP_MINLEN; /* skips ICMP portion */ /* put current time into the packet header */ /* Chow: this_time is relative to starttv and in 1 usec */ clock_gettime(CLOCK_REALTIME, &rttv); tvsub(&rttv, &rtstarttv); this_time = rttv.tv_sec * 1000000 + rttv.tv_nsec; *out_tp = this_time; depart[seq] = this_time; /* Compute ICMP checksum here */ out_icmp->icmp_cksum = in_cksum((u_short *)out_icmp, cc); last_time = this_time; /* Note that now this_time is different from what in the ICMP packet header since it include the checksum calculation time. This may lead to some calculation error. */ if (debug){ rtl_printf("sending...%d bytes", cc); print_icmp_msg(out_icmp); } i = sendto(s, outpack, cc, 0, addr,sizeof(*addr)); if (i != cc) { fprintf(stderr, "error: tried to write %d chars to %s, ret=%d\n", cc, inet_ntoa(addr->sin_addr), i); } } void setupNextIteration(double bwrLowerBound, double bwrUpperBound) { int i; /* initialize receiving time vector */ for (i = 1; i< noOfMsgs; i++) { receivingTimeGap[i] = 0; receivingTime[i] = 0; } /* initialize sendingTime Vector */ sendingTime[1] = 0.01; /* startProbeTime */ sendingTimeGap[0] = 0.01; if (debug) { rtl_printf("sendingTime[1]=%f\n", sendingTime[1]); rtl_printf("msgSize=%d bytes\n", msgSize); rtl_printf("!! setup iteration %d, bwr.lb=%f, bwr.ub=%f\n", iteration, bwrLowerBound, bwrUpperBound); } for (i = 1; i< noOfMsgs; i++) { if (equalBWTimeGap) { sendingTimeGap[i]= msgSize*8/(bwrLowerBound+i*(bwrUpperBound-bwrLowerBound)/(noOfMsgs-1)); sendingTime[i+1] = sendingTime[i]+sendingTimeGap[i]; if (debug) { rtl_printf("eqTgap: sendingTime[%d]=%f, sendingTimeGap[%d]=%f, bandwidth[%d]=%f\n", i+1, sendingTime[i+1], i, sendingTimeGap[i]*1000, i, msgSize*8/sendingTimeGap[i]); } } else { double intervalStepA = msgSize*8*(bwrUpperBound-bwrLowerBound)/(bwrUpperBound*bwrLowerBound*(noOfMsgs-2)); sendingTimeGap[i]= msgSize*8/bwrLowerBound-intervalStepA*(i-1); sendingTime[i+1] = sendingTime[i]+sendingTimeGap[i]; if (debug) rtl_printf("noneqTgap: sendingTime[%d]=%f\n",i+1, sendingTime[i+1]); } } for (i=1; i<=noOfMsgs; i++) { absSendingTimeGap[i] = sendingTime[i]-sendingTime[1]; } for (i=1; i