Obtaining metrics

To obtain simulation results, you would need to connect to one or more trace sources provided by ndnSIM classes.

It is also possible to use existing trace helpers, which collects and aggregates requested statistical information in text files.

Packet-level trace helpers

  • ndn::L3RateTracer

    Tracing the rate in bytes and in number of packets of Interest/Data packets forwarded by an NDN node

    The following example enables tracing on all simulation nodes:

    // the following should be put just before calling Simulator::Run in the scenario
    
    L3RateTracer::InstallAll("rate-trace.txt", Seconds(1.0));
    
    Simulator::Run();
    
    ...
    

    Output file format is tab-separated values, with first row specifying names of the columns. Refer to the following table for the description of the columns:

    Column Description
    Time simulation time
    Node node id, globally unique
    FaceId interface ID (-1 for combined metric)
    Type

    Type of measurements:

    • InInterests measurements of incoming Interests
    • OutInterests measurements of outgoing Interests
    • InData measurements of incoming Data
    • OutData measurements of outgoing Data
    • SatisfiedInterests measurements of satisfied Interests (totals for all faces)
    • TimedOutInterests measurements of timed out Interests (totals for all faces)
    • InSatisfiedInterests measurements of incoming satisfied Interests (per incoming face)
    • InTimedOutInterests measurements of incoming timed out Interests (per incoming face)
    • OutSatisfiedInterests measurements of outgoing satisfied Interests (per outgoing face)
    • OutTimedOutInterests measurements of outgoing satisfied Interests (per outgoing face)
    Packets estimated rate (EWMA average) of packets within the last averaging period (number of packets/s).
    Kilobytes estimated rate (EWMA average) within last averaging period (kilobytes/s)
    PacketsRaw absolute number of packets within last averaging period (number of packets).
    KilobytesRaw absolute number of kilobytes transferred within the last averaging period (number of packets).
  • L2Tracer

    This tracer is similar in spirit to ndn::L3RateTracer, but it currently traces only packet drop on layer 2 (e.g., due to transmission queue overflow).

    The following example enables tracing on all simulation nodes:

    // the following should be put just before calling Simulator::Run in the scenario
    
    L2RateTracer::InstallAll("drop-trace.txt", Seconds(0.5));
    
    Simulator::Run();
    
    ...
    

    Output file format is tab-separated values, with first row specifying names of the columns. Refer to the following table for the description of the columns:

    Column Description
    Time simulation time
    Node node id, globally unique
    Interface interface name (currently only “combined”)
    Type

    Type of measurements:

    • Drop measurements of dropped packets
    Packets estimated rate (EWMA average) of packets within the last averaging period (number of packets/s).
    Kilobytes estimated rate (EWMA average) within last averaging period (kilobytes/s)
    PacketsRaw absolute number of packets within last averaging period (number of packets).
    KilobytesRaw absolute number of kilobytes transferred within the last averaging period (number of packets).

Note

A number of other tracers are available in plugins/tracers-broken folder, but they do not yet work with the current code. Eventually, we will port most of them to the current code, but it is not our main priority at the moment and would really appreciate help with writing new tracers and porting the old ones.

Example of packet-level trace helpers

This example (ndn-tree-tracers.cpp) demonstrates basic usage of Packet-level trace helpers.

In this scenario we will use a tree-like topology, where consumers are installed on leaf nodes and producer is in the root of the tree:

The corresponding topology file (topo-tree.txt):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
# topo-tree.txt

router

#node	city	y	x	mpi-partition
leaf-1	NA	80	40	1
leaf-2	NA	80	20	3
leaf-3	NA	80	0	2
leaf-4	NA	80	-20	4
rtr-1	NA	60	20	1
rtr-2	NA	60	0	2
root	NA	40	10	0

link

# from	    to		capacity	metric	delay	queue
leaf-1	    rtr-1	10Mbps		1	1ms	100
leaf-2	    rtr-1	10Mbps		1	1ms	100
leaf-3	    rtr-2	10Mbps		1	1ms	100
leaf-4	    rtr-2	10Mbps		1	1ms	100
rtr-1	    root	10Mbps		1	1ms	100
rtr-2	    root	10Mbps		1	1ms	100

Example simulation (ndn-tree-tracers.cpp) scenario that utilizes trace helpers:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
// ndn-tree-tracers.cpp

#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/ndnSIM-module.h"

namespace ns3 {

int
main(int argc, char* argv[])
{
  CommandLine cmd;
  cmd.Parse(argc, argv);

  AnnotatedTopologyReader topologyReader("", 1);
  topologyReader.SetFileName("src/ndnSIM/examples/topologies/topo-tree.txt");
  topologyReader.Read();

  // Install NDN stack on all nodes
  ndn::StackHelper ndnHelper;
  ndnHelper.InstallAll();

  // Choosing forwarding strategy
  ndn::StrategyChoiceHelper::InstallAll("/prefix", "/localhost/nfd/strategy/best-route");

  // Installing global routing interface on all nodes
  ndn::GlobalRoutingHelper ndnGlobalRoutingHelper;
  ndnGlobalRoutingHelper.InstallAll();

  // Getting containers for the consumer/producer
  Ptr<Node> consumers[4] = {Names::Find<Node>("leaf-1"), Names::Find<Node>("leaf-2"),
                            Names::Find<Node>("leaf-3"), Names::Find<Node>("leaf-4")};
  Ptr<Node> producer = Names::Find<Node>("root");

  for (int i = 0; i < 4; i++) {
    ndn::AppHelper consumerHelper("ns3::ndn::ConsumerCbr");
    consumerHelper.SetAttribute("Frequency", StringValue("100")); // 100 interests a second

    // Each consumer will express unique interests /root/<leaf-name>/<seq-no>
    consumerHelper.SetPrefix("/root/" + Names::FindName(consumers[i]));
    consumerHelper.Install(consumers[i]);
  }

  ndn::AppHelper producerHelper("ns3::ndn::Producer");
  producerHelper.SetAttribute("PayloadSize", StringValue("1024"));

  // Register /root prefix with global routing controller and
  // install producer that will satisfy Interests in /root namespace
  ndnGlobalRoutingHelper.AddOrigins("/root", producer);
  producerHelper.SetPrefix("/root");
  producerHelper.Install(producer);

  // Calculate and install FIBs
  ndn::GlobalRoutingHelper::CalculateRoutes();

  Simulator::Stop(Seconds(20.0));

  ndn::L3RateTracer::InstallAll("rate-trace.txt", Seconds(0.5));

  Simulator::Run();
  Simulator::Destroy();

  return 0;
}

} // namespace ns3

int
main(int argc, char* argv[])
{
  return ns3::main(argc, argv);
}

To run this scenario, use the following command:

./waf --run=ndn-tree-tracers

The successful run will create rate-trace.txt files in the current directly, which can be analyzed manually or used as input to some graph/stats packages.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# Copyright (c) 2012,2015  Alexander Afanasyev <alexander.afanasyev@ucla.edu>

# install.packages('ggplot2')
library(ggplot2)
# install.packages('scales')
library(scales)

# install.packages('doBy')
library(doBy)

#########################
# Rate trace processing #
#########################
data = read.table("rate-trace.txt", header=T)
data$Node = factor(data$Node)
data$FaceId <- factor(data$FaceId)
data$Kilobits <- data$Kilobytes * 8
data$Type = factor(data$Type)

# exlude irrelevant types
data = subset(data, Type %in% c("InInterests", "OutInterests", "InData", "OutData"))

# combine stats from all faces
data.combined = summaryBy(. ~ Time + Node + Type, data=data, FUN=sum)

data.root = subset (data.combined, Node == "root")
data.leaves = subset(data.combined, Node %in% c("leaf-1", "leaf-2", "leaf-3", "leaf-4"))

# graph rates on all nodes in Kilobits
g.all <- ggplot(data.combined) +
  geom_point(aes (x=Time, y=Kilobits.sum, color=Type), size=1) +
  ylab("Rate [Kbits/s]") +
  facet_wrap(~ Node)

print(g.all)

# graph rates on the root nodes in Packets
g.root <- ggplot(data.root) +
  geom_point(aes (x=Time, y=Kilobits.sum, color=Type), size=2) +
  geom_line(aes (x=Time, y=Kilobits.sum, color=Type), size=0.5) +
  ylab("Rate [Kbits/s]")

print(g.root)

png("src/ndnSIM/docs/source/_static/root-rates.png", width=500, height=250)
print(g.root)
retval <- dev.off()

For more information about R and ggplot2, please refer to R language manual and ggplot2 module manual.

Rscript src/ndnSIM/examples/graphs/rate-graph.R

Example of packet drop tracer (L2Tracer)

This example (ndn-tree-with-l2tracer.cpp) demonstrates basic usage of Packet-level trace helpers.

The corresponding topology file (topo-tree-25-node.txt):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
router

# node   comment  yPos    xPos
Rtr1     NA        3        9
Rtr2     NA        9        9
Rtr3     NA        15       9
Rtr7     NA        9        15
Rtr4     NA        3        21
Rtr5     NA        9        21
Rtr6     NA        15       21
Src1     NA        1        3
Src2     NA        3        3
Src3     NA        5        3
Src4     NA        7        3
Src5     NA        9        3
Src6     NA        11       3
Src7     NA        13       3
Src8     NA        15       3
Src9     NA        17       3
Dst1     NA        1        27
Dst2     NA        3        27
Dst3     NA        5        27
Dst4     NA        7        27
Dst5     NA        9        27
Dst6     NA        11       27
Dst7     NA        13       27
Dst8     NA        15       27
Dst9     NA        17       27

link
# srcNode   dstNode     bandwidth   metric    delay   queue
Src1        Rtr1        100Mbps      1        10ms     10
Src2        Rtr1        100Mbps      1        10ms     10
Src3        Rtr1        100Mbps      1        10ms     10
Src4        Rtr2        100Mbps      1        10ms     10
Src5        Rtr2        100Mbps      1        10ms     10
Src6        Rtr2        100Mbps      1        10ms     10
Src7        Rtr3        100Mbps      1        10ms     10
Src8        Rtr3        100Mbps      1        10ms     10
Src9        Rtr3        100Mbps      1        10ms     10
Rtr1        Rtr7        10Mbps       1        10ms     10
Rtr2        Rtr7        10Mbps       1        10ms     10
Rtr3        Rtr7        10Mbps       1        10ms     10
Rtr4        Rtr7        10Mbps       1        10ms     10
Rtr5        Rtr7        10Mbps       1        10ms     10
Rtr6        Rtr7        10Mbps       1        10ms     10
Dst1        Rtr4        100Mbps      1        10ms     10
Dst2        Rtr4        100Mbps      1        10ms     10
Dst3        Rtr4        100Mbps      1        10ms     10
Dst4        Rtr5        100Mbps      1        10ms     10
Dst5        Rtr5        100Mbps      1        10ms     10
Dst6        Rtr5        100Mbps      1        10ms     10
Dst7        Rtr6        100Mbps      1        10ms     10
Dst8        Rtr6        100Mbps      1        10ms     10
Dst9        Rtr6        100Mbps      1        10ms     10

Example simulation (ndn-tree-with-l2tracer.cpp) scenario that utilizes trace helpers:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
// ndn-simple-withl2tracer.cpp

#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/ndnSIM-module.h"

namespace ns3 {

int
main(int argc, char* argv[])
{
  CommandLine cmd;
  cmd.Parse(argc, argv);

  AnnotatedTopologyReader topologyReader("", 10);
  topologyReader.SetFileName("src/ndnSIM/examples/topologies/topo-tree-25-node.txt");
  topologyReader.Read();

  /****************************************************************************/
  // Install NDN stack on all nodes
  ndn::StackHelper ndnHelper;
  ndnHelper.SetOldContentStore("ns3::ndn::cs::Lru", "MaxSize", "1000");
  ndnHelper.InstallAll();
  /****************************************************************************/
  // Installing global routing interface on all nodes
  ndn::GlobalRoutingHelper ndnGlobalRoutingHelper;
  ndnGlobalRoutingHelper.InstallAll();
  /****************************************************************************/
  // Getting containers for the consumer/producer
  Ptr<Node> consumer1 = Names::Find<Node>("Src1");
  Ptr<Node> consumer2 = Names::Find<Node>("Src2");
  Ptr<Node> consumer3 = Names::Find<Node>("Src3");
  Ptr<Node> consumer4 = Names::Find<Node>("Src4");
  Ptr<Node> consumer5 = Names::Find<Node>("Src5");
  Ptr<Node> consumer6 = Names::Find<Node>("Src6");
  Ptr<Node> consumer7 = Names::Find<Node>("Src7");
  Ptr<Node> consumer8 = Names::Find<Node>("Src8");
  Ptr<Node> consumer9 = Names::Find<Node>("Src9");

  Ptr<Node> producer1 = Names::Find<Node>("Dst1");
  Ptr<Node> producer2 = Names::Find<Node>("Dst2");
  Ptr<Node> producer3 = Names::Find<Node>("Dst3");
  Ptr<Node> producer4 = Names::Find<Node>("Dst4");
  Ptr<Node> producer5 = Names::Find<Node>("Dst5");
  Ptr<Node> producer6 = Names::Find<Node>("Dst6");
  Ptr<Node> producer7 = Names::Find<Node>("Dst7");
  Ptr<Node> producer8 = Names::Find<Node>("Dst8");
  Ptr<Node> producer9 = Names::Find<Node>("Dst9");
  /****************************************************************************/
  ndn::AppHelper consumerHelper("ns3::ndn::ConsumerCbr");
  consumerHelper.SetAttribute("Frequency", StringValue("1000")); // interests per Second
  consumerHelper.SetAttribute("Randomize", StringValue("uniform"));
  /****************************************************************************/
  // on the first to ninth consumer node install a Consumer application
  // that will express interests in /dst1 to /dst9 namespace
  consumerHelper.SetPrefix("/dst9");
  consumerHelper.Install(consumer1);

  consumerHelper.SetPrefix("/dst8");
  consumerHelper.Install(consumer2);

  consumerHelper.SetPrefix("/dst7");
  consumerHelper.Install(consumer3);

  consumerHelper.SetPrefix("/dst6");
  consumerHelper.Install(consumer4);

  consumerHelper.SetPrefix("/dst5");
  consumerHelper.Install(consumer5);

  consumerHelper.SetPrefix("/dst4");
  consumerHelper.Install(consumer6);

  consumerHelper.SetPrefix("/dst3");
  consumerHelper.Install(consumer7);

  consumerHelper.SetPrefix("/dst2");
  consumerHelper.Install(consumer8);

  consumerHelper.SetPrefix("/dst1");
  consumerHelper.Install(consumer9);

  /****************************************************************************/
  ndn::AppHelper producerHelper("ns3::ndn::Producer");
  producerHelper.SetAttribute("PayloadSize", StringValue("1024"));
  /****************************************************************************/
  // Register /dst1 to /dst9 prefix with global routing controller and
  // install producer that will satisfy Interests in /dst1 to /dst9 namespace
  ndnGlobalRoutingHelper.AddOrigins("/dst1", producer1);
  producerHelper.SetPrefix("/dst1");
  producerHelper.Install(producer1);

  ndnGlobalRoutingHelper.AddOrigins("/dst2", producer2);
  producerHelper.SetPrefix("/dst2");
  producerHelper.Install(producer2);

  ndnGlobalRoutingHelper.AddOrigins("/dst3", producer3);
  producerHelper.SetPrefix("/dst3");
  producerHelper.Install(producer3);

  ndnGlobalRoutingHelper.AddOrigins("/dst4", producer4);
  producerHelper.SetPrefix("/dst4");
  producerHelper.Install(producer4);

  ndnGlobalRoutingHelper.AddOrigins("/dst5", producer5);
  producerHelper.SetPrefix("/dst5");
  producerHelper.Install(producer5);

  ndnGlobalRoutingHelper.AddOrigins("/dst6", producer6);
  producerHelper.SetPrefix("/dst6");
  producerHelper.Install(producer6);

  ndnGlobalRoutingHelper.AddOrigins("/dst7", producer7);
  producerHelper.SetPrefix("/dst7");
  producerHelper.Install(producer7);

  ndnGlobalRoutingHelper.AddOrigins("/dst8", producer8);
  producerHelper.SetPrefix("/dst8");
  producerHelper.Install(producer8);

  ndnGlobalRoutingHelper.AddOrigins("/dst9", producer9);
  producerHelper.SetPrefix("/dst9");
  producerHelper.Install(producer9);

  /*****************************************************************************/
  // Calculate and install FIBs
  ndn::GlobalRoutingHelper::CalculateRoutes();

  Simulator::Stop(Seconds(10.0));

  /****************************************************************************/
  // Tracer:

  L2RateTracer::InstallAll("drop-trace.txt", Seconds(0.5));

  Simulator::Run();
  Simulator::Destroy();

  return 0;
}

} // namespace ns3

int
main(int argc, char* argv[])
{
  return ns3::main(argc, argv);
}

To run this scenario, use the following command:

./waf --run=ndn-tree-with-l2tracer

The successful run will create drop-trace.txt file in the current directly, which can be analyzed manually or used as input to some graph/stats packages.

For example, the following R script will build a number of nice graphs:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#!/usr/bin/env Rscript
# Copyright (c) 2012-2015  Alexander Afanasyev <alexander.afanasyev@ucla.edu>


# install.packages ('ggplot2')
library(ggplot2)
## # install.packages ('scales')
## library (scales)

#########################
# Rate trace processing #
#########################
data = read.table("drop-trace.txt", header=T)
data$Node = factor(data$Node)
data$Kilobits <- data$Kilobytes * 8
data$Type = factor(data$Type)

## data.rtr = data[grep("Rtr", data$Node),]

# graph rates on all nodes in Kilobits
g.all <- ggplot(data, aes(x=Time, y=Kilobits, color=Type)) +
  geom_point(size=2) +
  geom_line() +
  ylab("Packet drop rate [Kbits/s]") +
  facet_wrap(~ Node) +
  theme_bw()

png("src/ndnSIM/docs/source/_static/l2-rate-tracer.png", width=800, height=500)
print(g.all)
x = dev.off()

Run R script:

Rscript src/ndnSIM/examples/graphs/drop-graph.R
Packet drop rates on routers

Content store trace helper

NOTE: This tracer works ONLY when the content store structure of ndnSIM is used!

  • ndn::CsTracer

    With the use of ndn::CsTracer it is possible to obtain statistics of cache hits/cache misses on simulation nodes.

    The following code enables content store tracing:

    // the following should be put just before calling Simulator::Run in the scenario
    
    CsTracer::InstallAll("cs-trace.txt", Seconds(1));
    
    Simulator::Run();
    
    ...
    

    Output file format is tab-separated values, with first row specifying names of the columns. Refer to the following table for the description of the columns:

    Column Description
    Time simulation time
    Node node id, globally unique
    Type

    Type of counter for the time period. Possible values are:

    • CacheHits: the Packets column specifies the number of Interests that were satisfied from the cache
    • CacheMisses: the Packets column specifies the number of Interests that were not satisfied from the cache
    Packets The number of packets for the time period, meaning depends on Type column

Example of content store trace helper

This example (ndn-tree-cs-tracers.cpp) demonstrates basic usage of content store tracer.

In this scenario we will use the same tree-like topology as in previous example, where consumers are installed on leaf nodes and producer is in the root of the tree. The main difference is that each client request data from the same namespace: /root/1, /root/2, ... Another small difference is that in this scenario we start our application not at the same time, but 10 ms apart.

Example simulation (ndn-tree-cs-tracers.cpp) scenario that utilizes trace helpers:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
// ndn-tree-cs-tracers.cpp

#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/ndnSIM-module.h"

namespace ns3 {

int
main(int argc, char* argv[])
{
  CommandLine cmd;
  cmd.Parse(argc, argv);

  AnnotatedTopologyReader topologyReader("", 1);
  topologyReader.SetFileName("src/ndnSIM/examples/topologies/topo-tree.txt");
  topologyReader.Read();

  // Install NDN stack on all nodes
  ndn::StackHelper ndnHelper;
  ndnHelper.SetOldContentStore("ns3::ndn::cs::Lru", "MaxSize",
                               "100"); // default ContentStore parameters
  ndnHelper.InstallAll();

  // Choosing forwarding strategy
  ndn::StrategyChoiceHelper::InstallAll("/prefix", "/localhost/nfd/strategy/best-route");

  // Installing global routing interface on all nodes
  ndn::GlobalRoutingHelper ndnGlobalRoutingHelper;
  ndnGlobalRoutingHelper.InstallAll();

  // Getting containers for the consumer/producer
  Ptr<Node> consumers[4] = {Names::Find<Node>("leaf-1"), Names::Find<Node>("leaf-2"),
                            Names::Find<Node>("leaf-3"), Names::Find<Node>("leaf-4")};
  Ptr<Node> producer = Names::Find<Node>("root");

  for (int i = 0; i < 4; i++) {
    ndn::AppHelper consumerHelper("ns3::ndn::ConsumerCbr");
    consumerHelper.SetAttribute("Frequency", StringValue("10")); // 100 interests a second

    // Each consumer will express the same data /root/<seq-no>
    consumerHelper.SetPrefix("/root");
    ApplicationContainer app = consumerHelper.Install(consumers[i]);
    app.Start(Seconds(0.01 * i));
  }

  ndn::AppHelper producerHelper("ns3::ndn::Producer");
  producerHelper.SetAttribute("PayloadSize", StringValue("1024"));

  // Register /root prefix with global routing controller and
  // install producer that will satisfy Interests in /root namespace
  ndnGlobalRoutingHelper.AddOrigins("/root", producer);
  producerHelper.SetPrefix("/root");
  producerHelper.Install(producer);

  // Calculate and install FIBs
  ndn::GlobalRoutingHelper::CalculateRoutes();

  Simulator::Stop(Seconds(20.0));

  ndn::CsTracer::InstallAll("cs-trace.txt", Seconds(1));

  Simulator::Run();
  Simulator::Destroy();

  return 0;
}

} // namespace ns3

int
main(int argc, char* argv[])
{
  return ns3::main(argc, argv);
}

To run this scenario, use the following command:

./waf --run=ndn-tree-cs-tracers

The successful run will create cs-trace.txt, which similarly to trace file from the tracing example can be analyzed manually or used as input to some graph/stats packages.

Application-level trace helper

  • ndn::AppDelayTracer

    With the use of ndn::AppDelayTracer it is possible to obtain data about for delays between issuing Interest and receiving corresponding Data packet.

    The following code enables application-level Interest-Data delay tracing:

    // the following should be put just before calling Simulator::Run in the scenario
    
    AppDelayTracer::InstallAll("app-delays-trace.txt");
    
    Simulator::Run();
    
    ...
    

    Output file format is tab-separated values, with first row specifying names of the columns. Refer to the following table for the description of the columns:

    Column Description
    Time simulation time when SeqNo was receivied
    Node node id, global unique
    AppId app id, local unique on the node, not global
    SeqNo seq number of the Interest-Data
    Type

    Type of delay:

    • LastDelay means that DelayS and DelayUS represent delay between last Interest sent and Data packet received
    • FullDelay means that DelayS and DelayUS represent delay between first Interest sent and Data packet received (i.e., includes time of Interest retransmissions)
    DelayS delay value, specified in seconds
    DelayUS delay value, specified in microseconds (10^-6)
    RetxCount number of Interest retransmissions (for LastDelay always equal to 1)
    HopCount

    the number of network hops that the retrieved Data packet traveled on the way back from producer application or cache.

    Note that semantics of HopCount field has changed compared to ndnSIM 1.0.

Example of application-level trace helper

This example (ndn-tree-app-delay-tracer.cpp) demonstrates basic usage of application-level Interest-Data delay tracer.

In this scenario we will use the same tree-like topology as in packet trace helper example, where consumers are installed on leaf nodes and producer is in the root of the tree and clients request data from the same namespace: /root/1, /root/2, ...

Example simulation (ndn-tree-app-delay-tracer.cpp) scenario that utilizes trace helpers:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// ndn-tree-app-delay-tracer.cpp

#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/ndnSIM-module.h"

namespace ns3 {

int
main(int argc, char* argv[])
{
  CommandLine cmd;
  cmd.Parse(argc, argv);

  AnnotatedTopologyReader topologyReader("", 1);
  topologyReader.SetFileName("src/ndnSIM/examples/topologies/topo-tree.txt");
  topologyReader.Read();

  // Install CCNx stack on all nodes
  ndn::StackHelper ndnHelper;
  ndnHelper.InstallAll();

  // Choosing forwarding strategy
  ndn::StrategyChoiceHelper::InstallAll("/prefix", "/localhost/nfd/strategy/best-route");

  // Installing global routing interface on all nodes
  ndn::GlobalRoutingHelper ndnGlobalRoutingHelper;
  ndnGlobalRoutingHelper.InstallAll();

  // Getting containers for the consumer/producer
  Ptr<Node> consumers[4] = {Names::Find<Node>("leaf-1"), Names::Find<Node>("leaf-2"),
                            Names::Find<Node>("leaf-3"), Names::Find<Node>("leaf-4")};
  Ptr<Node> producer = Names::Find<Node>("root");

  ndn::AppHelper consumerHelper("ns3::ndn::ConsumerBatches");
  consumerHelper.SetPrefix("/root");
  consumerHelper.SetAttribute("Batches", StringValue("1s 1 10s 1"));
  consumerHelper.Install(consumers[0]);

  consumerHelper.SetAttribute("Batches", StringValue("11s 1"));
  consumerHelper.Install(consumers[1]);

  consumerHelper.SetAttribute("Batches", StringValue("11s 1"));
  consumerHelper.Install(consumers[2]);

  ndn::AppHelper producerHelper("ns3::ndn::Producer");
  producerHelper.SetAttribute("PayloadSize", StringValue("1024"));

  // Register /root prefix with global routing controller and
  // install producer that will satisfy Interests in /root namespace
  ndnGlobalRoutingHelper.AddOrigins("/root", producer);
  producerHelper.SetPrefix("/root");
  producerHelper.Install(producer).Start(Seconds(9));

  // Calculate and install FIBs
  ndn::GlobalRoutingHelper::CalculateRoutes();

  Simulator::Stop(Seconds(20.0));

  ndn::AppDelayTracer::InstallAll("app-delays-trace.txt");

  Simulator::Run();
  Simulator::Destroy();

  return 0;
}

} // namespace ns3

int
main(int argc, char* argv[])
{
  return ns3::main(argc, argv);
}

To run this scenario, use the following command:

./waf --run=ndn-tree-app-delay-tracer

The successful run will create app-delays-trace.txt, which similarly to trace file from the packet trace helper example can be analyzed manually or used as input to some graph/stats packages.