Friday, October 8, 2010

Analyze ns-2 trace file

Ns-2 has two options to generate traces with different fomats. Basically, you could use
$ns use-newtrace
to 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:

Unknown said...

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