diff -c ../6.0.0a5/ns.c ./ns.c *** ../6.0.0a5/ns.c Mon Apr 16 13:17:20 2001 --- ./ns.c Wed Jun 6 10:18:33 2001 *************** *** 1,6 **** --- 1,11 ---- /* * Kevin Lahey (kml@novell.com) * Novell, Inc. + * + * SACK support added by Daikichi Osuga (osuga@mml.yrp.nttdocomo.co.jp) + * + * NOTE : In official release ns2, trace file doesn't have SACK infomation. + * to visualize SACK blocks ns2 trace format function must be modefied. */ static char const rcsid[] = *************** *** 16,31 **** --- 21,58 ---- #ifdef GROK_NS + /* constants */ + #define MAXLINE 300 + #define NSA 3 + + /* data structures */ + struct sackblk { + tcp_seq start; /* start seq no. of sack block */ + tcp_seq end; /* end seq no. */ + }; + + struct sackopt { + unsigned char nop1; + unsigned char nop2; + unsigned char kind; + unsigned char length; + struct sackblk sackblk[1]; + }; /* static buffers for reading */ static struct ether_header *pep; static int *pip_buf; static struct ip *ipb; static struct tcphdr *tcpb; + static struct sackopt *sackoptb; + static char line[MAXLINE]; /* for debugging */ static unsigned linenum; + /* prototypes */ + int fgetline(FILE *fp, char s[], int lim); + /* return the next packet header */ /* currently only works for ETHERNET */ static int *************** *** 42,49 **** double c, d, e; while (1) { - /* read the packet info */ char tt; double timestamp; int junk; --- 69,77 ---- double c, d, e; while (1) { + /* read the packet info */ + int i; char tt; double timestamp; int junk; *************** *** 54,64 **** int is_ack; int is_tcp; int rlen; ++linenum; ! /* correct NS output line would have 14 fields: */ ! rlen = fscanf(stdin, "%c %lg %d %d %s %d %s %d %d.%hu %d.%hu %d %hu\n", &tt, ×tamp, &junk, --- 82,115 ---- int is_ack; int is_tcp; int rlen; + u_long src_addr; + u_long dst_addr; + u_short src_port; + u_short dst_port; + u_short ip_id; + + /* read and discard. not used. */ + int ackno; + int hex_flags; + int hlen; + + /* for SACK option */ + int sa_len; + int sb[NSA][2]; + int optlen = 0; ++linenum; ! if (fgetline(stdin, line, sizeof(line)) == 0) ! return 0; ! ! /* ! * correct NS output line would have 14 fields: ! * or 24 fields with additional SACK infomation ! */ ! rlen = sscanf(line, "%c %lg %d %d %s %d %s %d %d.%hu %d.%hu %d %hu" ! " %d %x %d" ! " %d %d %d %d %d %d %d", &tt, ×tamp, &junk, *************** *** 67,91 **** plen, flags, &iteration, ! &ipb->ip_src.s_addr, ! &tcpb->th_sport, ! &ipb->ip_dst.s_addr, ! &tcpb->th_dport, &seq, ! &ipb->ip_id); ! /* if we can't match all 14 fields, we give up on the file */ ! if (rlen != 14) { fprintf(stderr,"Bad ns packet header in line %u\n", linenum); return(0); } - if (rlen == EOF) { - return(0); - } - - tcpb->th_sport = tcpb->th_dport = iteration; - is_tcp = strcmp(type, "tcp") == 0; is_ack = strcmp(type, "ack") == 0; --- 118,147 ---- plen, flags, &iteration, ! &src_addr, ! &src_port, ! &dst_addr, ! &dst_port, &seq, ! &ip_id, ! &ackno, ! &hex_flags, ! &hlen, ! &sa_len, ! &sb[0][0], ! &sb[0][1], ! &sb[1][0], ! &sb[1][1], ! &sb[2][0], ! &sb[2][1] ! ); ! /* if we can't match all 24 or 14 fields, we give up on the file */ ! if (rlen != 14 && rlen != 24) { fprintf(stderr,"Bad ns packet header in line %u\n", linenum); return(0); } is_tcp = strcmp(type, "tcp") == 0; is_ack = strcmp(type, "ack") == 0; *************** *** 93,101 **** if (!is_tcp && !is_ack) continue; ! if (packlen == 0 && is_tcp) ! packlen = *plen - sizeof(struct ip) - sizeof(struct tcphdr); ipb->ip_len = htons(*plen); if (is_tcp) { --- 149,178 ---- if (!is_tcp && !is_ack) continue; ! ipb->ip_src.s_addr = htonl(src_addr); ! tcpb->th_sport = htons(src_port); ! ipb->ip_dst.s_addr = htonl(dst_addr); ! tcpb->th_dport = htons(dst_port); ! ! if (is_ack && rlen == 24 && sa_len) { ! /* build sack option */ ! sackoptb->nop1 = TCPOPT_NOP; ! sackoptb->nop2 = TCPOPT_NOP; ! sackoptb->kind = TCPOPT_SACK; ! for (i = 0; i < sa_len; i++) { ! /* fill sack block */ ! sackoptb->sackblk[i].start = htonl(sb[i][0] * packlen); ! sackoptb->sackblk[i].end = htonl(sb[i][1] * packlen); ! } ! sackoptb->length = 2 + sa_len * 8; ! optlen = 4 + sa_len * 8; ! *plen += 4; /* ns doesn't consider NOP, NOP, SACK, len */ ! } + if (packlen == 0 && is_tcp) { + packlen = *plen - sizeof(struct ip) - sizeof(struct tcphdr) + - optlen; + } ipb->ip_len = htons(*plen); if (is_tcp) { *************** *** 114,120 **** ipb->ip_ttl = 64; /* nice round number */ ipb->ip_p = 6; /* TCP */ ipb->ip_sum = 0; /* IP checksum, hope it doesn't get checked! */ ! ipb->ip_id = htons(ipb->ip_id); /* is the transport "ECN-Capable"? */ if (strchr(flags, 'N') != NULL) --- 191,197 ---- ipb->ip_ttl = 64; /* nice round number */ ipb->ip_p = 6; /* TCP */ ipb->ip_sum = 0; /* IP checksum, hope it doesn't get checked! */ ! ipb->ip_id = htons(ip_id); /* is the transport "ECN-Capable"? */ if (strchr(flags, 'N') != NULL) *************** *** 125,131 **** ipb->ip_tos |= IPTOS_CE; /* make up a reasonable TCP segment header */ ! tcpb->th_off = 5; /* no options, normal length of 20 */ tcpb->th_flags = TH_ACK; /* sdo: what about first SYN?? */ tcpb->th_x2 = 0; tcpb->th_sum = 0; --- 202,208 ---- ipb->ip_tos |= IPTOS_CE; /* make up a reasonable TCP segment header */ ! tcpb->th_off = 5 + optlen / 4; /* now only consider sack option */ tcpb->th_flags = TH_ACK; /* sdo: what about first SYN?? */ tcpb->th_x2 = 0; tcpb->th_sum = 0; *************** *** 195,200 **** --- 272,278 ---- ipb = (struct ip *) pip_buf; tcpb = (struct tcphdr *) (ipb + 1); + sackoptb = (struct sackopt *) (tcpb + 1); /* Set up the stuff that shouldn't change */ pep->ether_type = ETHERTYPE_IP; *************** *** 203,207 **** --- 281,298 ---- linenum = 0; return(pread_ns); + } + + static int fgetline(FILE *fp, char s[], int lim) + { + int c, i; + + i = 0; + while (--lim > 0 && (c = getc(fp)) != EOF && c != '\n') + s[i++] = c; + if (c == '\n') + s[i++] = c; + s[i] = '\0'; + return i; } #endif /* GROK_NS */