$ns use-newtraceto generate the new trace and the detailed explanation could be found in Ns Manual. A very good reference about the trace is the ns-2 wiki page. See: http://nsnam.isi.edu/nsnam/index.php/NS-2_Trace_Formats
By default, old trace format is used. The source code ./trace/cmu-trace.cc needs to be read to understand it completely. For instance, the function format_ip will explain the trace of IP part.
void
CMUTrace::format_ip(Packet *p, int offset)
{
struct hdr_cmn *ch = HDR_CMN(p);
struct hdr_ip *ih = HDR_IP(p);
// hack the IP address to convert pkt format to hostid format
// for now until port ids are removed from IP address. -Padma.
int src = Address::instance().get_nodeaddr(ih->saddr());
int dst = Address::instance().get_nodeaddr(ih->daddr());
............
}
void
CMUTrace::format_mac(Packet *p, int offset)
{
else {
sprintf(pt_->buffer() + offset,
" [%x %x %x %x] ",
//*((u_int16_t*) &mh->dh_fc),
mh->dh_duration,
ETHER_ADDR(mh->dh_ra),
ETHER_ADDR(mh->dh_ta),
GET_ETHER_TYPE(mh->dh_body));
}
......
} |
A typical trace for a CBR traffic is:
s 20.000000000 _0_ AGT --- 6 cbr 512 [0 0 0 0] ------- [0:0 1:0 32 0] [0] 0 0 r 20.000000000 _0_ RTR --- 6 cbr 512 [0 0 0 0] ------- [0:0 1:0 32 0] [0] 0 0 s 20.000000000 _0_ RTR --- 6 cbr 532 [0 0 0 0] ------- [0:0 1:0 32 1] [0] 0 0 s 20.000275000 _0_ MAC --- 6 cbr 584 [13a 1 0 800] ------- [0:0 1:0 32 1] [0] 0 0 r 20.004947063 _1_ MAC --- 6 cbr 532 [13a 1 0 800] ------- [0:0 1:0 32 1] [0] 1 0 s 20.004957063 _1_ MAC --- 0 ACK 38 [0 0 0 0] r 20.004972063 _1_ AGT --- 6 cbr 532 [13a 1 0 800] ------- [0:0 1:0 32 1] [0] 1 0 r 20.005261125 _0_ MAC --- 0 ACK 38 [0 0 0 0]
An AWK script example to analyze the trace and calculate throughput
For a topology involve 4 flows with distinguishing source and destination nodes, this following awk script gets throughout data and put in wu.dat file
BEGIN {counter1 = 0; counter2 = 0; counter3 = 0; counter4 = 0;} $1~/r/ && $2>50 && $2< 100 && /_12_/ && /AGT/ { counter1 += ($8- 20) size = $8 - 20 } $1~/r/ && $2>50 && $2 <100 && /_13_/ && /AGT/ { counter2 += ($8- 20) size = $8 - 20 } $1~/r/ && $2>50 && $2<100 && /_14_/ && /AGT/ { counter3 += ($8- 20) size = $8 - 20 } $1~/r/ && $2>50 && $2<100 && /_15_/ && /AGT/ { counter4 += ($8- 20) size = $8 - 20 } throughout END { print (size , counter1*8/(50), counter2*8/50, counter3*8/(50), counter4*8/50, (counter1+counter2+counter3+counter4)*8/50 ) >> "wu.dat"} |
To analyze the throughout or delay in a finite time duration, we need extract sending and receiving time from the trace file
$2>100 && $2 < 150 && (/_6_/ || /_2_/) && /AGT/ { print $1, $2, $6 > "dst2.tr" } $2>100 && $2 <150 && (/_0_/ || /_9_/) && /AGT/ { print $1, $2, $6 > "dst9.tr" } $2>100 && $2 <150 && (/_12_/ || /_3_/) && /AGT/ { print $1, $2, $6 > "dst3.tr" } $2>100 && $2 <150 && (/_10_/ || /_4_/) && /AGT/ { print $1, $2, $6 > "dst4.tr" } $2>100 && $2 <150 && (/_11_/ || /_8_/) && /AGT/ { print $1, $2, $6 > "dst8.tr" } |
The respective new trace files such as "dst2.tr" will keep the sending or receiving time, "s'" or "r" label and, node's MAC address. From those data, we could use a program to calculate the average throughputor mean value of end-to-end delay of the flow.
The C source file (delay.c) to calculate delay is given as below:
#include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { FILE *fin, *fout, *fout2; int pkt_index[1000]; double pkt_send_time[1000]; int head; //int tail; /* make sure it is large enough to hold all temprary data! */ int i,j,num; double tm, tm_delay, total_delay, avg_delay, var_delay; int idx; char type; int flag; int num_sent; head = 0; for ( i=0; i<1000; i++) { pkt_index[i] = -1; pkt_send_time[i] = 0.0f; } fin = fopen(argv[1], "r"); fout = fopen (argv[2], "w"); fout2 = fopen ( argv[3],"a"); if(fin==NULL) { printf("Error: can't open file.\n"); return 1; } else { printf("File opened successfully.\n"); i = 0 ; num = 0; num_sent = 0; while(!feof(fin)) { /* loop through and store the numbers into the array */ fscanf(fin, "%c %lf %d \n", &type,&tm, &idx); //printf( "%f\n", tm); if ( type == 's' ) { //addentry(idx, tm); pkt_index[head] = idx; pkt_send_time[head] = tm; head++; if ( head == 1000 ) head = 0; num_sent++; } else if ( type == 'r' ) { flag = 0; for ( j=0; j< 1000; j++) { if ( pkt_index[j] == idx ) { //printf("match,%f, %f\n!" ,tm, pkt_send_time[j]); tm_delay = tm - pkt_send_time[j]; flag = 1; break; } } //addentry to output if ( flag == 1) { fprintf( fout,"%d %lf \n", idx, tm_delay ); total_delay += tm_delay; num++; } } i++; } avg_delay = total_delay / num ; fprintf(fout2,"Number of entries read: %d\n", i); fprintf(fout2,"Number of entries sent: %d\n", num_sent); fprintf(fout2,"Number of entries received: %d\n", num); fprintf(fout2,"average delay of entries : %lf\n", avg_delay); fclose(fin); fclose(fout); //finally, calcualte variance fout = fopen ( argv[2], "r") ; if ( fout == NULL ) return -1; var_delay = 0; while (!feof(fout)) { fscanf(fout, "%d %lf\n", &idx ,&tm); var_delay += ( tm - avg_delay ) * (tm - avg_delay); } var_delay /= num; fprintf(fout2, "variance of delay is : %lf\n", var_delay); fclose (fout); fclose (fout2); return 0; } }
To use this C code:
$ gcc delay.c -o delaycal $ ./delaycal dst2.tr wu0.dat wu1.dat |
1 comment:
Hi,
I found this article very useful, it explains every detail, good job!
I've developed the tool NS2 Visual Trace Analyzer, I hope it helps someone too. You can visit its blog at:
http://nsvisualtraceanalyzer.wordpress.com/
Best regards,
Fernando Rocha
Post a Comment