UDP: End to End Delay Measurement (More Scenarios)

 

[topology]

term_0 (UDP Sender)----P2Plink(10Mbps,1ms)--- router_0 ---P2Plink(10Mbps,1ms)--- router_1---P2Plink(10Mbps,1ms)--- term_1 (UDP Sink)

 

After simulation, I will show how to parse the trace file to get the end to end delay.

 

P2plink1.cc (put this file under scratch)

#include "ns3/core-module.h"

#include "ns3/global-route-manager.h"

#include "ns3/network-module.h"

#include "ns3/internet-module.h"

#include "ns3/bridge-module.h"

#include "ns3/point-to-point-module.h"

#include "ns3/applications-module.h"

#include "ns3/packet-sink.h"

#include "ns3/packet-sink-helper.h"

 

using namespace ns3;

 

Ptr<PacketSink> sink;                         /* Pointer to the packet sink application */

uint64_t lastTotalRx = 0;                     /* The value of the last total received bytes */

 

void

CalculateThroughput ()

{

  Time now = Simulator::Now ();                                         /* Return the simulator's virtual time. */

  double cur = (sink->GetTotalRx () - lastTotalRx) * (double) 8 / 1e3;     /* Convert Application RX Packets to kBits. */

  std::cout << now.GetSeconds () << "\t" << cur << std::endl;

  lastTotalRx = sink->GetTotalRx ();

  Simulator::Schedule (MilliSeconds (1000), &CalculateThroughput);

}

 

int main(int argc, char *argv[])

{

  CommandLine cmd;

  cmd.Parse (argc, argv);

 

  /* Configuration. */

 

  /* Build nodes. */

  NodeContainer term_0;

  term_0.Create (1);

  NodeContainer term_1;

  term_1.Create (1);

  NodeContainer router_0;

  router_0.Create (1);

  NodeContainer router_1;

  router_1.Create (1);

 

  /* Build link. */

  PointToPointHelper p2p_p2p_0;

  p2p_p2p_0.SetDeviceAttribute ("DataRate", StringValue ("10Mbps"));

  p2p_p2p_0.SetChannelAttribute ("Delay", StringValue ("1ms"));

  PointToPointHelper p2p_p2p_1;

  p2p_p2p_1.SetDeviceAttribute ("DataRate", StringValue ("10Mbps"));

  p2p_p2p_1.SetChannelAttribute ("Delay", StringValue ("1ms"));

  PointToPointHelper p2p_p2p_2;

  p2p_p2p_2.SetDeviceAttribute ("DataRate", StringValue ("10Mbps"));

  p2p_p2p_2.SetChannelAttribute ("Delay", StringValue ("1ms"));

 

  /* Build link net device container. */

  NodeContainer all_p2p_0;

  all_p2p_0.Add (router_0);

  all_p2p_0.Add (term_0);

  NetDeviceContainer ndc_p2p_0 = p2p_p2p_0.Install (all_p2p_0);

  NodeContainer all_p2p_1;

  all_p2p_1.Add (router_0);

  all_p2p_1.Add (router_1);

  NetDeviceContainer ndc_p2p_1 = p2p_p2p_1.Install (all_p2p_1);

  NodeContainer all_p2p_2;

  all_p2p_2.Add (router_1);

  all_p2p_2.Add (term_1);

  NetDeviceContainer ndc_p2p_2 = p2p_p2p_2.Install (all_p2p_2);

 

  /* Install the IP stack. */

  InternetStackHelper internetStackH;

  internetStackH.Install (term_0);

  internetStackH.Install (term_1);

  internetStackH.Install (router_0);

  internetStackH.Install (router_1);

 

  /* IP assign. */

  Ipv4AddressHelper ipv4;

  ipv4.SetBase ("10.0.0.0", "255.255.255.0");

  Ipv4InterfaceContainer iface_ndc_p2p_0 = ipv4.Assign (ndc_p2p_0);

  ipv4.SetBase ("10.0.1.0", "255.255.255.0");

  Ipv4InterfaceContainer iface_ndc_p2p_1 = ipv4.Assign (ndc_p2p_1);

  ipv4.SetBase ("10.0.2.0", "255.255.255.0");

  Ipv4InterfaceContainer iface_ndc_p2p_2 = ipv4.Assign (ndc_p2p_2);

 

  /* Generate Route. */

  Ipv4GlobalRoutingHelper::PopulateRoutingTables ();

 

  /* Generate Application. */

  PacketSinkHelper sinkHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), 9));

  ApplicationContainer sinkApp = sinkHelper.Install (term_1.Get(0));

  sink = StaticCast<PacketSink> (sinkApp.Get (0));

 

  InetSocketAddress sinkSocket (iface_ndc_p2p_2.GetAddress (1), 9);

  OnOffHelper server ("ns3::UdpSocketFactory", sinkSocket);

  server.SetAttribute ("PacketSize", UintegerValue (160));

  server.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]"));

  server.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));

  server.SetAttribute ("DataRate", DataRateValue (DataRate ("64Kbps")));

  ApplicationContainer serverApp = server.Install (term_0.Get(0));

 

  sinkApp.Start (Seconds (0.0));

  serverApp.Start (Seconds (0.1));

  Simulator::Schedule (Seconds (1.0), &CalculateThroughput);

 

  /* Simulation. */

  /* Pcap output. */

  /* Stop the simulation after x seconds. */

  uint32_t stopTime = 11;

  Simulator::Stop (Seconds (stopTime));

  AsciiTraceHelper ascii;

  p2p_p2p_0.EnableAsciiAll(ascii.CreateFileStream("p2plink1-1.tr"));

  //generate the same results. so use the first one.

  //p2p_p2p_1.EnableAsciiAll(ascii.CreateFileStream("p2plink1-2.tr"));

  //p2p_p2p_2.EnableAsciiAll(ascii.CreateFileStream("p2plink1-3.tr"));

  /* Start and clean simulation. */

  Simulator::Run ();

  Simulator::Destroy ();

}

 

getDelay2.awk

BEGIN {

src="10.0.0.2";

dst="10.0.2.2)";

srcNode="/NodeList/0";

dstNode="/NodeList/1";

highest_pkt_id = 0;

}

 

{

 event=$1  #+:enque -:deque r:receive

 time=$2   #event time

 #$3: /NodeList/0/DeviceList/0/$ns3::PointToPointNetDevice/TxQueue/Enqueue ns3::PppHeader

 id=$19    #pkt id

 sip=$29   #source ip

 dip=$31   #destination ip

 

 if (id>highest_pkt_id)

   highest_pkt_id=id

 

 if (event=="+" && sip==src && dip==dst && match($3, srcNode)){

   sendtime[$19]=$2

 }

 

 if (event=="r" && sip==src && dip==dst && match($3, dstNode)){

   recvtime[$19]=$2

 }

}

 

END {

 for(id=0; id<=highest_pkt_id;id++){

   stime=sendtime[id];

   rtime=recvtime[id];

   if( stime < rtime) printf("%d %f %f\n", id, stime, rtime-stime);

 }

}

 

 

Execution

 

 

[topology]

term_0 (UDP Sender)----CSMALink(10Mbps,1ms)--- router_0 ---P2Plink(10Mbps,2ms)---- term_1 (UDP Sink)

 

p2plink2.cc

#include "ns3/core-module.h"

#include "ns3/global-route-manager.h"

#include "ns3/network-module.h"

#include "ns3/internet-module.h"

#include "ns3/bridge-module.h"

#include "ns3/csma-module.h"

#include "ns3/point-to-point-module.h"

#include "ns3/packet-sink.h"

#include "ns3/packet-sink-helper.h"

#include "ns3/applications-module.h"

 

using namespace ns3;

 

Ptr<PacketSink> sink;                         /* Pointer to the packet sink application */

uint64_t lastTotalRx = 0;                     /* The value of the last total received bytes */

 

void

CalculateThroughput ()

{

  Time now = Simulator::Now ();                                         /* Return the simulator's virtual time. */

  double cur = (sink->GetTotalRx () - lastTotalRx) * (double) 8 / 1e3;     /* Convert Application RX Packets to kBits. */

  std::cout << now.GetSeconds () << "\t" << cur << std::endl;

  lastTotalRx = sink->GetTotalRx ();

  Simulator::Schedule (MilliSeconds (1000), &CalculateThroughput);

}

 

int main(int argc, char *argv[])

{

  CommandLine cmd;

  cmd.Parse (argc, argv);

 

  /* Configuration. */

 

  /* Build nodes. */

  NodeContainer router_0;

  router_0.Create (1);

  NodeContainer term_0;

  term_0.Create (1);

  NodeContainer term_1;

  term_1.Create (1);

 

  /* Build link. */

  CsmaHelper csma_hub_0;

  csma_hub_0.SetChannelAttribute ("DataRate", StringValue ("10Mbps"));

  csma_hub_0.SetChannelAttribute ("Delay",  StringValue ("1ms"));

  PointToPointHelper p2p_p2p_0;

  p2p_p2p_0.SetDeviceAttribute ("DataRate", StringValue ("10Mbps"));

  p2p_p2p_0.SetChannelAttribute ("Delay", StringValue ("2ms"));

 

  /* Build link net device container. */

  NodeContainer all_hub_0;

  all_hub_0.Add (router_0);

  all_hub_0.Add (term_0);

  NetDeviceContainer ndc_hub_0 = csma_hub_0.Install (all_hub_0);

  NodeContainer all_p2p_0;

  all_p2p_0.Add (router_0);

  all_p2p_0.Add (term_1);

  NetDeviceContainer ndc_p2p_0 = p2p_p2p_0.Install (all_p2p_0);

 

  /* Install the IP stack. */

  InternetStackHelper internetStackH;

  internetStackH.Install (router_0);

  internetStackH.Install (term_0);

  internetStackH.Install (term_1);

 

  /* IP assign. */

  Ipv4AddressHelper ipv4;

  ipv4.SetBase ("10.0.0.0", "255.255.255.0");

  Ipv4InterfaceContainer iface_ndc_hub_0 = ipv4.Assign (ndc_hub_0);

  ipv4.SetBase ("10.0.1.0", "255.255.255.0");

  Ipv4InterfaceContainer iface_ndc_p2p_0 = ipv4.Assign (ndc_p2p_0);

 

  /* Generate Route. */

  Ipv4GlobalRoutingHelper::PopulateRoutingTables ();

 

  /* Generate Application. */

  PacketSinkHelper sinkHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), 9));

  ApplicationContainer sinkApp = sinkHelper.Install (term_1.Get(0));

  sink = StaticCast<PacketSink> (sinkApp.Get (0));

 

  InetSocketAddress sinkSocket (iface_ndc_p2p_0.GetAddress (1), 9);

  OnOffHelper server ("ns3::UdpSocketFactory", sinkSocket);

  server.SetAttribute ("PacketSize", UintegerValue (160));

  server.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]"));

  server.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));

  server.SetAttribute ("DataRate", DataRateValue (DataRate ("64Kbps")));

  ApplicationContainer serverApp = server.Install (term_0.Get(0));

 

  sinkApp.Start (Seconds (0.0));

  serverApp.Start (Seconds (0.1));

  Simulator::Schedule (Seconds (1.0), &CalculateThroughput);

 

  /* Simulation. */

  /* Pcap output. */

  /* Stop the simulation after x seconds. */

  uint32_t stopTime = 11;

  Simulator::Stop (Seconds (stopTime));

  AsciiTraceHelper ascii;

  p2p_p2p_0.EnableAsciiAll(ascii.CreateFileStream("p2plink2-p2p.tr"));

  csma_hub_0.EnableAsciiAll(ascii.CreateFileStream("p2plink2-csma.tr"));

  /* Start and clean simulation. */

  Simulator::Run ();

  Simulator::Destroy ();

}

 

getDelay3.awk

BEGIN {

srcNode="/NodeList/1";  # term_0 Node

dstNode="/NodeList/2";  # term_1 Node

highest_pkt_id = 0;

}

 

{

 event=$1  #+:enque -:deque r:receive

 time=$2   #event time

 #$3: /NodeList/0/DeviceList/0/$ns3::PointToPointNetDevice/TxQueue/Enqueue ns3::PppHeader

 id=$4    #pkt id

 

 if (id>highest_pkt_id)

   highest_pkt_id=id

 

 if (event=="+" && match($3, srcNode) && sendtime[$4]==0){

   sendtime[$4]=$2

 }

 

 if (event=="r" && match($3, dstNode)){

   recvtime[$4]=$2

 }

}

 

END {

 printf("highest_pkt_id: %d\n", highest_pkt_id=id);

 for(id=0; id<=highest_pkt_id;id++){

   stime=sendtime[id];

   rtime=recvtime[id];

   if( stime < rtime) printf("%d %f %f\n", id, stime, rtime-stime);

 }

}

 

Execution

After simulation, you will get p2plink2-p2p.tr and p2plink2-csma.tr. Before parsing the trace files, we need to do some processing first.

 

 

You will get different traces under different networks. So you have to prepare different awk files to parse them. Luckily, if you use UdpServerHelper and UdpClientHelper, you don’t need to write any awk program. Because UdpClientHelper application has added SeqTsHeader before sending out packets. Then we can use the SeqTsHeader to calculate the end-to-end delay.

 

delay-udp2.cc

#include <fstream>

#include <string.h>

 

#include "ns3/core-module.h"

#include "ns3/internet-module.h"

#include "ns3/point-to-point-module.h"

#include "ns3/error-model.h"

#include "ns3/flow-monitor-module.h"

#include "ns3/applications-module.h"

 

using namespace ns3;

NS_LOG_COMPONENT_DEFINE ("DelayUDP2");

                        

uint64_t TotalRx = 0; 

uint64_t TotalTx = 0;

uint64_t TotalLoss = 0;  

 

void

APPRxCallback(std::string context, Ptr<const Packet> p)

{

  Ptr<Packet> aCopy = p->Copy ();

  SeqTsHeader seqTs;

  aCopy->RemoveHeader (seqTs);

  Time t=seqTs.GetTs();

  std::cout << "Seq:" << seqTs.GetSeq () << " Delay:" <<Simulator::Now ().GetSeconds ()-t.GetSeconds () << std::endl;

}

 

int

main (int argc, char *argv[])

{

  NS_LOG_INFO ("Create nodes.");

  NodeContainer n;

  n.Create (2);

 

  InternetStackHelper internet;

  internet.Install (n);

 

  NS_LOG_INFO ("Create channels.");

 

  PointToPointHelper pointToPoint;

  pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));

  pointToPoint.SetChannelAttribute ("Delay", StringValue ("1ms"));

  pointToPoint.SetDeviceAttribute("Mtu", UintegerValue(1400));  

  NetDeviceContainer p2pDevices;

  p2pDevices = pointToPoint.Install (n);    

 

  Ptr<RateErrorModel> em = CreateObject<RateErrorModel> ();

  em->SetAttribute ("ErrorRate", DoubleValue (0.01));

  em->SetAttribute ("ErrorUnit", StringValue ("ERROR_UNIT_PACKET"));

  p2pDevices.Get (1)->SetAttribute ("ReceiveErrorModel", PointerValue (em));

 

  Ipv4AddressHelper ipv4;

 

  NS_LOG_INFO ("Assign IP Addresses.");

  ipv4.SetBase ("10.1.1.0", "255.255.255.0");

  Ipv4InterfaceContainer i = ipv4.Assign (p2pDevices);

 

  NS_LOG_INFO ("Create Applications.");

  uint16_t port = 4000;

  UdpServerHelper server (port);

  ApplicationContainer apps = server.Install (n.Get (1));

  Config::Connect ("/NodeList/1/ApplicationList/*/$ns3::UdpServer/Rx", MakeCallback (&APPRxCallback));

  apps.Start (Seconds (1.0));

  apps.Stop (Seconds (10.0));

 

  uint32_t MaxPacketSize = 1024;

  Time interPacketInterval = Seconds (0.05);

  uint32_t maxPacketCount = 100;

  Address serverAddress = Address (i.GetAddress (1));

  UdpClientHelper client (serverAddress, port);

  client.SetAttribute ("MaxPackets", UintegerValue (maxPacketCount));

  client.SetAttribute ("Interval", TimeValue (interPacketInterval));

  client.SetAttribute ("PacketSize", UintegerValue (MaxPacketSize));

  apps = client.Install (n.Get (0));

  apps.Start (Seconds (2.0));

  apps.Stop (Seconds (10.0));

 

  FlowMonitorHelper flowmon;

  Ptr<FlowMonitor> monitor = flowmon.InstallAll ();

 

  Simulator::Stop (Seconds (100.0));

  pointToPoint.EnablePcapAll("delay-udp2");

  NS_LOG_INFO ("Run Simulation.");

  Simulator::Run ();

 

  Ptr<Ipv4FlowClassifier> classifier = DynamicCast<Ipv4FlowClassifier>(flowmon.GetClassifier());

  std::map<FlowId, FlowMonitor::FlowStats> stats = monitor->GetFlowStats();

 

  for(std::map<FlowId, FlowMonitor::FlowStats>::const_iterator set = stats.begin(); set != stats.end(); set++)

  {

    Ipv4FlowClassifier::FiveTuple t = classifier->FindFlow(set->first);

    std::cout << "Flow " << set->first << " (" << t.sourceAddress << " -> " << t.destinationAddress << ")" << std::endl;

    std::cout << "Tx packets:" << set->second.txPackets << std::endl;

    std::cout << "Rx packets:" << set->second.rxPackets << std::endl;

    std::cout << "Loss Rate:" <<  (double)(set->second.txPackets-set->second.rxPackets)/set->second.txPackets << std::endl;

  }

 

  Simulator::Destroy ();

  NS_LOG_INFO ("Done.");

 

}

 

Execution

 

Back to NS3 Learning Guide

Last Modified: 2022/2/7 done

 

[Author]

Dr. Chih-Heng Ke

Department of Computer Science and Information Engineering, National Quemoy University, Kinmen, Taiwan

Email: smallko@gmail.com