[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[ns] Extracting end-to-end packet loss, average delay and jitter.



Hi,

The objective is to post-process the ns-2 output trace file out.tr to
obtain the packet loss, average delay and jitter, end-to-end, for flow f
from source node s to sink node t.

When out.tr is very large, however, parsing programs written in Perl and Awk
tend to be prohibitively slow. They can hardly be used when multiple repetetive
extractions of automated series of large ns-2 simulations are necessary, and
then one may look for solutions in compiled languages.

Here are two short C++ programs, A.cc and B.cc, that work together. In each of
them, the values for the source node s, the sink node t, and the flow id f
have to be entered first.

The first program, A.cc, takes in the ns-2 output trace file out.tr and
creates
file called 'selected'. The second program, B.cc, takes the file selected and
prints packet loss, average delay and jitter to the standard output.

The particular program files included below have source node, sink node, and
flow id preset to 4, 11, and 3, respectively. (One can either edit these for
other values, or have an interactive setup, for entering at the standard
input.)

This program tandem worked for me for very large simulations, for many months.


---
Dr. Miroslav I. Klun
Network Infrastructure Laboratory
GTE Laboratories Inc.
Waltham, MA 02451
(781) 466-3830
[email protected]


==============================================================================



//// A.cc:
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// The program reads all the lines of the out.tr file, selects those that
// refer to flow f packets that are sent from source node s to sink node t,
// and that either are just entering the queue at node s or are just
// arriving at node t.  The selected lines are placed in the file "selected".
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

#include <iostream.h>
#include <string.h>
#include <fstream.h>
#include <stdlib.h>
#include <iomanip.h>
#include <math.h>

int main()
{
  // Packet type to be excluded - e.g., ack in case of TCP, etc.:
  char *Type;
  Type = "ack";

  cout << "\n" << "The packet type that will be excluded: " << Type << "\n\n";

  // The constants s, t, and f must be set via STANDARD INPUT:
  int s = 4; // Source node.
  int t = 11; // Sink node.
  int f = 3;  // Flow id.


  // Here we get the number N of rows in the input data file:

  ifstream count_file("out.tr");
  int i = 0;
  char buff[100];
  while (count_file) {
    count_file.getline(buff, 100);
    i++;
  }
  int N = i-1;
  count_file.close();

  ifstream in_file("out.tr");
  ofstream out_file("selected");

  char line[100];
  char *vector[12];
  char *tokenPtr;
  char buffer[100];

  int n = 0;

//while (in_file) {
  while (n < N)
  {
    n++;
    in_file.getline(line, 100);
    // Each "line" is a row of characters in the original file out.tr.
    // These characters form 12 words separated by 11 blank delimiters.
    // Thus, each character array "line" yields a 12-word array "vector".
    // The following parses ("tokenizes") "line" into "vector":
//  buffer = line;
    strcpy (buffer, line);
    // It is necessary to use a _copy_ of "line", "buffer", instead of "line"
    // itself, since an application of "strtok" function modifies its first
    // argument!
    tokenPtr = strtok(buffer, " ");
    for (int j=0; j < 11; j++) {
      vector[j] = tokenPtr;
      tokenPtr = strtok(NULL, " ");
    }
    vector[11] = tokenPtr;
    // Now we are ready to examine each line of our out.tr file. We first need
    // some labels:
    char *sign;
    sign = vector[0];
    float time_stamp = atof(vector[1]);
    int from_node = atoi(vector[2]);
    int to_node = atoi(vector[3]);
    char *type;
    type = vector[4];
    int flow  = atoi(vector[7]);
    int source_node = atoi(vector[8]);
    int sink_node = atoi(vector[9]);
    int packet_id = atoi(vector[11]);

    // Finally, here is the criterion for finding the desirable lines of the
    // file out.tr and placing them into a new file called "selected".
    if ((((*sign == '+') && (from_node == s) && (flow == f) && (source_node
== s) && (sink_node == t)) || ((*sign == 'r') && (to_node == t) && (flow ==
f) && (source_node == s) && (sink_node == t))) && (strcmp(type,Type)!=0)) {
      out_file << line << "\n";
    }
  }
  in_file.close();
  out_file.close();

 return 0;
}

===============================================================================


//// B.cc
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// The program reads the file "selected", and records the delays of all the  //
// packets belonging to flow f that start from a source at node s and are    //
// received at a sink at node t. It also records the precentage of the lost
//
// packets and the jitter. It prints all the statistics to the standard      //
// output.                                                                   //
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

#include <iostream.h>
#include <string.h>
#include <fstream.h>
#include <stdlib.h>
#include <iomanip.h>
#include <math.h>

int main()
{
  // The constants s, t, and f must be set at the beginning.
  int s = 4; // Source node.
  int t = 11; // Sink node.
  int f = 3;  // Flow id.

  ifstream in_file("selected");
  int i = 0;
  char buffer[100];
  while (in_file) {
    in_file.getline(buffer, 100);
    i++;
  }
  // From here we get the number M of rows in the input data file
  // (i.e., the size of the character array "data" defined below):
  int M = i-1;
  in_file.close();

  char sign[M][2];
  float time_stamp[M];
  int packet_id[M];

  ifstream inn_file("selected");
  i = 0;
  while (i < M){
    char data[100];
    inn_file.getline(data, 100);
    strcpy(buffer, data);
    char *tokenPtr;
    tokenPtr = strtok(buffer, " ");
    strcpy(sign[i], tokenPtr);
    tokenPtr = strtok(NULL, " ");
    time_stamp[i] = atof(tokenPtr);
    for (int j=1; j < 11; j++) {
      tokenPtr = strtok(NULL, " ");
    }
    packet_id[i] = atoi(tokenPtr);
    i++;
  }
  inn_file.close();

  // The array "delay" shall have plenty of zeros at the tail...
  float delay[M];
  int k = 0;
  int l = 0;
  for (int i=0; i < M; i++) {
    if ((*sign[i] == '+')) {
      k++;
      for (int j=0; j < M; j++) {
	if ((*sign[j] == 'r') && (packet_id[j] == packet_id[i])) {
	  delay[l] = time_stamp[j] - time_stamp[i];
	  l++;
	}
      }
    }
  }

  int T = k; // The number of packets transmitted.
  int R = l; // The number of packets received.
  int L = T - R; // The number of packets lost.
  cout << "\n\n";
  cout << "The number of packets transmitted T = " << T << ".\n";
  cout << "The number of packets received R = " << R << ".\n";
  cout << "The number of packets lost L = " << L << ".\n";

  ///////////////////////////////////////////////////////////////////
  // The following computes the percentage, truncated at two decimals,
  // of the lost packets:
  double loss_ratio = floor(10000*L/T)/100;
  cout << "\n" << loss_ratio << "% of all packets of flow " << f << " sent
from node " << s << " to node " << t << " were lost." << "\n\n";

  ///////////////////////////////////////////////////////////////////////
  // This computes delay sample mean and prints it to the standard output:
  double sigma = 0;
  for (l=0; l < R; l++){
    sigma = sigma + delay[l];
  }
  double delay_mean = sigma/R;
  cout << "Delay mean for flow " << f << " = " << 1000*delay_mean << " ms"
<< "\n\n";

  ///////////////////////////////
  // This computes delay variance:
  double quad = 0;
  for (l=0; l < R; l++){
    quad = quad + pow(delay[l] - delay_mean,2);
  }
  double delay_variance = quad/R;

  /////////////////////////////////////////////////////////////
  // This computes delay sample standard variation and prints it
  // to the standard output:
  double delay_standard_deviation = sqrt(delay_variance);
  cout << "Jitter for flow " << f << " = " << 1000*delay_standard_deviation
<< " ms" << "\n\n";

  return 0;
}

///////////////////////////////////////////////////////////////////////////////