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
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