Examples¶
Note
!!! This page only shows up examples of how to config topology and perform basic operations in ndnSIM (an example equivalent to “Hello, world1”) !!! These are **NOT** examples of real experimentations (just like “Hello, world!” is not a real program).
Note
If you compiled ndnSIM with examples (./waf configure --enable-examples
) you can
directly run the example without putting scenario into scratch/
folder.
Note
A few mobile simulation scenarios are available. The project code may require a custom version of ndnSIM (see project commits for further details).
Simple scenario¶
The first example (ndn-simple.cpp
) shows very basics of ndnSIM. In the simulated
topology there are 3 nodes, connected with point-to-point links, one
NDN consumer, and one NDN producer:
Consumer is simulated using ConsumerCbr reference application and generates Interests towards the producer with frequency of 10 Interests per second (see ndnSIM applications).
Producer is simulated using Producer class, which is used to satisfy all incoming Interests with virtual payload data (1024 bytes).
FIB on every node is populated using default routes (see ndnSIM helpers) and the content store structure of the original ndnSIM is used.
The following code represents all that is necessary to run such a simple scenario
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 | // ndn-simple.cpp
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/ndnSIM-module.h"
namespace ns3 {
int
main(int argc, char* argv[])
{
// setting default parameters for PointToPoint links and channels
Config::SetDefault("ns3::PointToPointNetDevice::DataRate", StringValue("1Mbps"));
Config::SetDefault("ns3::PointToPointChannel::Delay", StringValue("10ms"));
Config::SetDefault("ns3::QueueBase::MaxSize", StringValue("20p"));
// Read optional command-line parameters (e.g., enable visualizer with ./waf --run=<> --visualize
CommandLine cmd;
cmd.Parse(argc, argv);
// Creating nodes
NodeContainer nodes;
nodes.Create(3);
// Connecting nodes using two links
PointToPointHelper p2p;
p2p.Install(nodes.Get(0), nodes.Get(1));
p2p.Install(nodes.Get(1), nodes.Get(2));
// Install NDN stack on all nodes
ndn::StackHelper ndnHelper;
ndnHelper.SetDefaultRoutes(true);
ndnHelper.InstallAll();
// Choosing forwarding strategy
ndn::StrategyChoiceHelper::InstallAll("/prefix", "/localhost/nfd/strategy/multicast");
// Installing applications
// Consumer
ndn::AppHelper consumerHelper("ns3::ndn::ConsumerCbr");
// Consumer will request /prefix/0, /prefix/1, ...
consumerHelper.SetPrefix("/prefix");
consumerHelper.SetAttribute("Frequency", StringValue("10")); // 10 interests a second
auto apps = consumerHelper.Install(nodes.Get(0)); // first node
apps.Stop(Seconds(10.0)); // stop the consumer app at 10 seconds mark
// Producer
ndn::AppHelper producerHelper("ns3::ndn::Producer");
// Producer will reply to all requests starting with /prefix
producerHelper.SetPrefix("/prefix");
producerHelper.SetAttribute("PayloadSize", StringValue("1024"));
producerHelper.Install(nodes.Get(2)); // last node
Simulator::Stop(Seconds(20.0));
Simulator::Run();
Simulator::Destroy();
return 0;
}
} // namespace ns3
int
main(int argc, char* argv[])
{
return ns3::main(argc, argv);
}
|
If this code is placed into scratch/ndn-simple.cpp
and NS-3 is compiled in debug mode, you
can run and see progress of the simulation using the following command (in optimized mode
nothing will be printed out):
NS_LOG=ndn.Consumer:ndn.Producer ./waf --run=ndn-simple
Note
If you compiled ndnSIM with examples (./waf configure --enable-examples
) you can
directly run the example without putting scenario into scratch/
folder.
9-node grid example¶
This scenario (ndn-grid.cpp
) simulates a grid topology, which is constructed using
PointToPointLayout NS-3 module.
FIB is populated using GlobalRoutingHelper (see ndnSIM helpers). The content store structure of NFD is used in all the nodes.
Consumer is simulated using ConsumerCbr reference application and generates Interests towards the producer with frequency of 100 interests per second (see ndnSIM applications).
Producer is simulated using Producer class, which is used to satisfy all incoming Interests with virtual payload data (1024 bytes).
The following code represents all that is necessary to run such a simple scenario
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 | // ndn-grid.cpp
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/point-to-point-layout-module.h"
#include "ns3/ndnSIM-module.h"
namespace ns3 {
int
main(int argc, char* argv[])
{
// Setting default parameters for PointToPoint links and channels
Config::SetDefault("ns3::PointToPointNetDevice::DataRate", StringValue("1Mbps"));
Config::SetDefault("ns3::PointToPointChannel::Delay", StringValue("10ms"));
Config::SetDefault("ns3::QueueBase::MaxSize", StringValue("10p"));
// Read optional command-line parameters (e.g., enable visualizer with ./waf --run=<> --visualize
CommandLine cmd;
cmd.Parse(argc, argv);
// Creating 3x3 topology
PointToPointHelper p2p;
PointToPointGridHelper grid(3, 3, p2p);
grid.BoundingBox(100, 100, 200, 200);
// Install NDN stack on all nodes
ndn::StackHelper ndnHelper;
ndnHelper.InstallAll();
// Set BestRoute strategy
ndn::StrategyChoiceHelper::InstallAll("/", "/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> producer = grid.GetNode(2, 2);
NodeContainer consumerNodes;
consumerNodes.Add(grid.GetNode(0, 0));
// Install NDN applications
std::string prefix = "/prefix";
ndn::AppHelper consumerHelper("ns3::ndn::ConsumerCbr");
consumerHelper.SetPrefix(prefix);
consumerHelper.SetAttribute("Frequency", StringValue("100")); // 100 interests a second
consumerHelper.Install(consumerNodes);
ndn::AppHelper producerHelper("ns3::ndn::Producer");
producerHelper.SetPrefix(prefix);
producerHelper.SetAttribute("PayloadSize", StringValue("1024"));
producerHelper.Install(producer);
// Add /prefix origins to ndn::GlobalRouter
ndnGlobalRoutingHelper.AddOrigins(prefix, producer);
// Calculate and install FIBs
ndn::GlobalRoutingHelper::CalculateRoutes();
Simulator::Stop(Seconds(20.0));
Simulator::Run();
Simulator::Destroy();
return 0;
}
} // namespace ns3
int
main(int argc, char* argv[])
{
return ns3::main(argc, argv);
}
|
If this code is placed into scratch/ndn-grid.cpp
and NS-3 is compiled in debug mode, you
can run and see progress of the simulation using the following command (in optimized mode
nothing will be printed out):
NS_LOG=ndn.Consumer:ndn.Producer ./waf --run=ndn-grid
Note
If you compiled ndnSIM with examples (./waf configure --enable-examples
) you can
directly run the example without putting scenario into scratch/
folder.
9-node grid example using topology plugin¶
Instead of defining topology directly as in Simple scenario or using specialized helpers as in 9-node grid example, ndnSIM provides experimental extended versions of TopologyReader classes: AnnotatedTopologyReader and RocketfuelWeightsReader.
While RocketfuelWeightsReader is a specialized version intended to be used with Rocketfuel topology and link weights files (examples will be provided later), AnnotatedTopologyReader is a more general-use class that uses simple user-readable format.
AnnotatedTopologyReader expects the following format:
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 | # topo-grid-3x3.txt
# any empty lines and lines starting with '#' symbol is ignored
#
# The file should contain exactly two sections: router and link, each starting with the corresponding keyword
#
# router section defines topology nodes and their relative positions (e.g., to use in visualizer)
router
# each line in this section represents one router and should have the following data
# node comment yPos xPos
Node0 NA 3 1
Node1 NA 3 2
Node2 NA 3 3
Node3 NA 2 1
Node4 NA 2 2
Node5 NA 2 3
Node6 NA 1 1
Node7 NA 1 2
Node8 NA 1 3
# Note that `node` can be any string. It is possible to access to the node by name using Names::Find, see examples.
# link section defines point-to-point links between nodes and characteristics of these links
link
# Each line should be in the following format (only first two are required, the rest can be omitted)
# srcNode dstNode bandwidth metric delay queue
# bandwidth: link bandwidth
# metric: routing metric
# delay: link delay
# queue: MaxPackets for transmission queue on the link (both directions)
Node0 Node1 1Mbps 1 10ms 10
Node0 Node3 1Mbps 1 10ms 10
Node1 Node2 1Mbps 1 10ms 10
Node1 Node4 1Mbps 1 10ms 10
Node2 Node5 1Mbps 1 10ms 10
Node3 Node4 1Mbps 1 10ms 10
Node3 Node6 1Mbps 1 10ms 10
Node4 Node5 1Mbps 1 10ms 10
Node4 Node7 1Mbps 1 10ms 10
Node5 Node8 1Mbps 1 10ms 10
Node6 Node7 1Mbps 1 10ms 10
Node7 Node8 1Mbps 1 10ms 10
|
This scenario (ndn-grid-topo-plugin.cpp
) duplicates the functionality of
9-node grid example but with the use of AnnotatedTopologyReader.
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 | // ndn-grid-topo-plugin.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("", 25);
topologyReader.SetFileName("src/ndnSIM/examples/topologies/topo-grid-3x3.txt");
topologyReader.Read();
// Install NDN stack on all nodes
ndn::StackHelper ndnHelper;
ndnHelper.InstallAll();
// Set BestRoute strategy
ndn::StrategyChoiceHelper::InstallAll("/", "/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> producer = Names::Find<Node>("Node8");
NodeContainer consumerNodes;
consumerNodes.Add(Names::Find<Node>("Node0"));
// Install NDN applications
std::string prefix = "/prefix";
ndn::AppHelper consumerHelper("ns3::ndn::ConsumerCbr");
consumerHelper.SetPrefix(prefix);
consumerHelper.SetAttribute("Frequency", StringValue("100")); // 100 interests a second
consumerHelper.Install(consumerNodes);
ndn::AppHelper producerHelper("ns3::ndn::Producer");
producerHelper.SetPrefix(prefix);
producerHelper.SetAttribute("PayloadSize", StringValue("1024"));
producerHelper.Install(producer);
// Add /prefix origins to ndn::GlobalRouter
ndnGlobalRoutingHelper.AddOrigins(prefix, producer);
// Calculate and install FIBs
ndn::GlobalRoutingHelper::CalculateRoutes();
Simulator::Stop(Seconds(20.0));
Simulator::Run();
Simulator::Destroy();
return 0;
}
} // namespace ns3
int
main(int argc, char* argv[])
{
return ns3::main(argc, argv);
}
|
As you can see, scenario code became more compact and more readable.
AnnotatedTopologyReader provides two ways to access topology nodes. First, you can use the method AnnotatedTopologyReader::GetNodes() which returns NodeContainer.
Alternatively, nodes can be accessed by name using Names::Find<Node> (“nodename”) call, as in the above example. For this purpose,:ndnsim:AnnotatedTopologyReader automatically registers all created nodes with names specified in topology file. For more information about Names class, please refer to NS-3 documentation.
If the topology file is placed into src/ndnSIM/examples/topologies/topo-grid-3x3.txt
and
the code is placed into scratch/ndn-grid-topo-plugin.cpp
, you can run and see progress of
the simulation using the following command (in optimized mode nothing will be printed out):
NS_LOG=ndn.Consumer:ndn.Producer ./waf --run=ndn-grid-topo-plugin
Note
If you compiled ndnSIM with examples (./waf configure --enable-examples
) you can
directly run the example without putting scenario into scratch/
folder.
6-node bottleneck topology¶
This scenario (ndn-congestion-topo-plugin.cpp
) can be used for congestion-related scenarios
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | # topo-6-node.txt
router
# node comment yPos xPos
Src1 NA 1 3
Src2 NA 3 3
Rtr1 NA 2 5
Rtr2 NA 2 7
Dst1 NA 1 9
Dst2 NA 3 9
link
# srcNode dstNode bandwidth metric delay queue
Src1 Rtr1 10Mbps 1 10ms 20
Src2 Rtr1 10Mbps 1 10ms 20
Rtr1 Rtr2 1Mbps 1 10ms 20
Dst1 Rtr2 10Mbps 1 10ms 20
Dst2 Rtr2 10Mbps 1 10ms 20
|
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 | // ndn-congestion-topo-plugin.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("", 25);
topologyReader.SetFileName("src/ndnSIM/examples/topologies/topo-6-node.txt");
topologyReader.Read();
// Install NDN stack on all nodes
ndn::StackHelper ndnHelper;
ndnHelper.setPolicy("nfd::cs::lru");
ndnHelper.setCsSize(10000);
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> consumer1 = Names::Find<Node>("Src1");
Ptr<Node> consumer2 = Names::Find<Node>("Src2");
Ptr<Node> producer1 = Names::Find<Node>("Dst1");
Ptr<Node> producer2 = Names::Find<Node>("Dst2");
ndn::AppHelper consumerHelper("ns3::ndn::ConsumerCbr");
consumerHelper.SetAttribute("Frequency", StringValue("100")); // 100 interests a second
// on the first consumer node install a Consumer application
// that will express interests in /dst1 namespace
consumerHelper.SetPrefix("/dst1");
consumerHelper.Install(consumer1);
// on the second consumer node install a Consumer application
// that will express interests in /dst2 namespace
consumerHelper.SetPrefix("/dst2");
consumerHelper.Install(consumer2);
ndn::AppHelper producerHelper("ns3::ndn::Producer");
producerHelper.SetAttribute("PayloadSize", StringValue("1024"));
// Register /dst1 prefix with global routing controller and
// install producer that will satisfy Interests in /dst1 namespace
ndnGlobalRoutingHelper.AddOrigins("/dst1", producer1);
producerHelper.SetPrefix("/dst1");
producerHelper.Install(producer1);
// Register /dst2 prefix with global routing controller and
// install producer that will satisfy Interests in /dst2 namespace
ndnGlobalRoutingHelper.AddOrigins("/dst2", producer2);
producerHelper.SetPrefix("/dst2");
producerHelper.Install(producer2);
// Calculate and install FIBs
ndn::GlobalRoutingHelper::CalculateRoutes();
Simulator::Stop(Seconds(20.0));
Simulator::Run();
Simulator::Destroy();
return 0;
}
} // namespace ns3
int
main(int argc, char* argv[])
{
return ns3::main(argc, argv);
}
|
To run this scenario and see what is happening, use the following command:
NS_LOG=ndn.Consumer:ndn.Producer ./waf --run=ndn-congestion-topo-plugin
Note
If you compiled ndnSIM with examples (./waf configure --enable-examples
) you can
directly run the example without putting scenario into scratch/
folder.
11-node 2-bottleneck topology¶
Firstly, we define a meaningful topology:
The corresponding topology file (topo-11-node-two-bottlenecks.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 | # topo-11-node-two-bottlenecks.txt
router
#name city latitude longitude
c1 NA 50 30
c2 NA 30 30
c3 NA 10 30
c4 NA 10 40
n1 NA 40 40
n12 NA 30 60
n2 NA 40 80
p1 NA 50 90
p2 NA 30 90
p3 NA 10 90
p4 NA 10 80
link
#x y capacity(kbps) OSPF Delay MaxPackets
c1 n1 10Mbps 1 50ms 200
c2 n1 10Mbps 1 10ms 200
c3 n1 10Mbps 1 100ms 200
c4 n1 10Mbps 1 1ms 200
n1 n2 1Mbps 1176 20ms 20
n1 n12 1Mbps 587 1ms 20
n12 n2 1Mbps 846 1ms 20
n2 p1 10Mbps 260 1ms 200
n2 p2 10Mbps 700 1ms 200
n2 p3 10Mbps 1 1ms 200
n2 p4 10Mbps 1 1ms 200
|
After that, we define the simulation scenario:
Example simulation (ndn-congestion-alt-topo-plugin.cpp
) scenario:
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 | // ndn-congestion-alt-topo-plugin.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-11-node-two-bottlenecks.txt");
topologyReader.Read();
// Install NDN stack on all nodes
ndn::StackHelper ndnHelper;
ndnHelper.setPolicy("nfd::cs::lru");
ndnHelper.setCsSize(1);
ndnHelper.InstallAll();
// Set BestRoute strategy
ndn::StrategyChoiceHelper::InstallAll("/", "/localhost/nfd/strategy/best-route");
// Getting containers for the consumer/producer
Ptr<Node> consumers[4] = {Names::Find<Node>("c1"), Names::Find<Node>("c2"),
Names::Find<Node>("c3"), Names::Find<Node>("c4")};
Ptr<Node> producers[4] = {Names::Find<Node>("p1"), Names::Find<Node>("p2"),
Names::Find<Node>("p3"), Names::Find<Node>("p4")};
if (consumers[0] == 0 || consumers[1] == 0 || consumers[2] == 0 || consumers[3] == 0
|| producers[0] == 0 || producers[1] == 0 || producers[2] == 0 || producers[3] == 0) {
NS_FATAL_ERROR("Error in topology: one nodes c1, c2, c3, c4, p1, p2, p3, or p4 is missing");
}
for (int i = 0; i < 4; i++) {
std::string prefix = "/data/" + Names::FindName(producers[i]);
/////////////////////////////////////////////////////////////////////////////////
// install consumer app on consumer node c_i to request data from producer p_i //
/////////////////////////////////////////////////////////////////////////////////
ndn::AppHelper consumerHelper("ns3::ndn::ConsumerCbr");
consumerHelper.SetAttribute("Frequency", StringValue("10")); // 100 interests a second
consumerHelper.SetPrefix(prefix);
ApplicationContainer consumer = consumerHelper.Install(consumers[i]);
consumer.Start(Seconds(i)); // start consumers at 0s, 1s, 2s, 3s
consumer.Stop(Seconds(19 - i)); // stop consumers at 19s, 18s, 17s, 16s
///////////////////////////////////////////////
// install producer app on producer node p_i //
///////////////////////////////////////////////
ndn::AppHelper producerHelper("ns3::ndn::Producer");
producerHelper.SetAttribute("PayloadSize", StringValue("1024"));
// install producer that will satisfy Interests in /dst1 namespace
producerHelper.SetPrefix(prefix);
ApplicationContainer producer = producerHelper.Install(producers[i]);
// when Start/Stop time is not specified, the application is running throughout the simulation
}
// Manually configure FIB routes
ndn::FibHelper::AddRoute("c1", "/data", "n1", 1); // link to n1
ndn::FibHelper::AddRoute("c2", "/data", "n1", 1); // link to n1
ndn::FibHelper::AddRoute("c3", "/data", "n1", 1); // link to n1
ndn::FibHelper::AddRoute("c4", "/data", "n1", 1); // link to n1
ndn::FibHelper::AddRoute("n1", "/data", "n2", 1); // link to n2
ndn::FibHelper::AddRoute("n1", "/data", "n12", 2); // link to n12
ndn::FibHelper::AddRoute("n12", "/data", "n2", 1); // link to n2
ndn::FibHelper::AddRoute("n2", "/data/p1", "p1", 1); // link to p1
ndn::FibHelper::AddRoute("n2", "/data/p2", "p2", 1); // link to p2
ndn::FibHelper::AddRoute("n2", "/data/p3", "p3", 1); // link to p3
ndn::FibHelper::AddRoute("n2", "/data/p4", "p4", 1); // link to p4
// Schedule simulation time and run the simulation
Simulator::Stop(Seconds(20.0));
Simulator::Run();
Simulator::Destroy();
return 0;
}
} // namespace ns3
int
main(int argc, char* argv[])
{
return ns3::main(argc, argv);
}
|
To run this scenario and see what is happening, use the following command:
NS_LOG=ndn.Consumer:ndn.Producer ./waf --run=ndn-congestion-alt-topo-plugin
You can also run using visualizer module to verify that both bottleneck links are utilized:
./waf --run=ndn-congestion-alt-topo-plugin --visualize
Note
If you compiled ndnSIM with examples (./waf configure --enable-examples
) you can
directly run the example without putting scenario into scratch/
folder.
6-node topology with custom NFD forwarding strategy¶
This scenario simulates a load balancer topology (using topology reader module). The
corresponding topology file (topo-load-balancer.txt
):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | # each line in this section represents one router and should have the following data
# node comment yPos xPos
CSU-1 NA 3 5
CSU-HUB NA 5 3
UCLA-HUB NA 3 1
UCLA-1 NA 0 0
UCLA-2 NA 0 2
# Each line should be in the following format (only first two are required, the rest can be omitted)
# srcNode dstNode bandwidth metric delay queue
# bandwidth: link bandwidth
# metric: routing metric
# delay: link delay
# queue: MaxPackets for transmission queue on the link (both directions)
CSU-1 CSU-HUB 1Mbps 1 10ms 10
CSU-HUB UCLA-HUB 1Mbps 1 10ms 10
UCLA-HUB UCLA-1 1Mbps 1 10ms 10
UCLA-HUB UCLA-2 1Mbps 1 10ms 10
|
After that, we define the simulation scenario:
Example simulation (ndn-load-balancer.cpp
) scenario:
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 | // ndn-load-balancer.cpp
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/ndnSIM-module.h"
#include "ndn-load-balancer/random-load-balancer-strategy.hpp"
using ns3::ndn::StackHelper;
using ns3::ndn::AppHelper;
using ns3::ndn::GlobalRoutingHelper;
using ns3::ndn::StrategyChoiceHelper;
using ns3::AnnotatedTopologyReader;
int
main(int argc, char* argv[])
{
CommandLine cmd;
cmd.Parse(argc, argv);
AnnotatedTopologyReader topologyReader("", 25);
topologyReader.SetFileName("src/ndnSIM/examples/topologies/topo-load-balancer.txt");
topologyReader.Read();
// Install NDN stack on all nodes
StackHelper ndnHelper;
ndnHelper.InstallAll();
// Installing global routing interface on all nodes
GlobalRoutingHelper ndnGlobalRoutingHelper;
ndnGlobalRoutingHelper.InstallAll();
// Getting containers for the consumer/producer
Ptr<Node> producer1 = Names::Find<Node>("UCLA-1");
Ptr<Node> producer2 = Names::Find<Node>("UCLA-2");
NodeContainer consumerNodes;
consumerNodes.Add(Names::Find<Node>("CSU-1"));
// Install NDN applications
std::string prefix = "/ucla/hello";
// Install random-load-balancer forwarding strategy in
// node UCLA-HUB
StrategyChoiceHelper::Install<nfd::fw::RandomLoadBalancerStrategy>(Names::Find<Node>("UCLA-HUB"),
prefix);
AppHelper consumerHelper("ns3::ndn::ConsumerCbr");
consumerHelper.SetPrefix(prefix);
consumerHelper.SetAttribute("Frequency", StringValue("100")); // 100 interests a second
consumerHelper.Install(consumerNodes);
AppHelper producerHelper("ns3::ndn::Producer");
producerHelper.SetPrefix(prefix);
producerHelper.SetAttribute("PayloadSize", StringValue("1024"));
producerHelper.Install(producer1);
producerHelper.Install(producer2);
// Add /prefix origins to ndn::GlobalRouter
ndnGlobalRoutingHelper.AddOrigins(prefix, producer1);
ndnGlobalRoutingHelper.AddOrigins(prefix, producer2);
// Calculate and install FIBs
GlobalRoutingHelper::CalculateRoutes();
Simulator::Stop(Seconds(1.0));
Simulator::Run();
Simulator::Destroy();
return 0;
}
|
In this simulation scenario, the node called “UCLA-HUB” implements a random load balancing strategy for the name prefix “/ucla/hello”. In this way, the Interest packets will be forwarded randomly either to the producer node called “UCLA-1” or the producer node called “UCLA-2”.
To run this scenario and see what is happening, use the following command:
NS_LOG=ndn.Consumer:ndn.Producer ./waf --run=ndn-load-balancer
Note
If you compiled ndnSIM with examples (./waf configure --enable-examples
) you can
directly run the example without putting scenario into scratch/
folder.
9-node grid topology with different forwarding strategies per name prefix¶
This scenario simulates a grid topology (using PointToPointGrid module). In this scenario, thanks to NFD, we can choose a different forwarding strategy for each prefix in each node.
Consumer requests data from producer with frequency 100 interests per second (interests contain constantly increasing sequence number).
For every received interest, producer replies with a data packet, containing 1024 bytes of virtual payload.
In this scenario, we choose the multicast strategy to be installed for the name prefix “/prefix1” in all the nodes, while for the name prefix “/prefix2”, the best-route strategy will be installed in all the topology nodes.
Example simulation (ndn-different-strategy-per-prefix.cpp
) scenario:
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 | // ndn-different-strategy-per-prefix.cpp
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/point-to-point-layout-module.h"
#include "ns3/ndnSIM-module.h"
using namespace ns3;
using ns3::ndn::StackHelper;
using ns3::ndn::AppHelper;
using ns3::ndn::GlobalRoutingHelper;
using ns3::ndn::StrategyChoiceHelper;
int
main(int argc, char* argv[])
{
// Setting default parameters for PointToPoint links and channels
Config::SetDefault("ns3::PointToPointNetDevice::DataRate", StringValue("1Mbps"));
Config::SetDefault("ns3::PointToPointChannel::Delay", StringValue("10ms"));
Config::SetDefault("ns3::QueueBase::MaxSize", StringValue("10p"));
// Read optional command-line parameters
CommandLine cmd;
cmd.Parse(argc, argv);
// Creating 3x3 topology
PointToPointHelper p2p;
PointToPointGridHelper grid(3, 3, p2p);
grid.BoundingBox(100, 100, 200, 200);
// Install NDN stack on all nodes
StackHelper ndnHelper;
ndnHelper.InstallAll();
// Installing global routing interface on all nodes
GlobalRoutingHelper ndnGlobalRoutingHelper;
ndnGlobalRoutingHelper.InstallAll();
// Getting pointers to the producer/consumer nodes
Ptr<Node> producer1 = grid.GetNode(2, 2);
Ptr<Node> producer2 = grid.GetNode(0, 2);
Ptr<Node> consumer1 = grid.GetNode(0, 0);
Ptr<Node> consumer2 = grid.GetNode(2, 0);
// Define two name prefixes
std::string prefix1 = "/prefix1";
std::string prefix2 = "/prefix2";
// Install different forwarding strategies for prefix1, prefix2
StrategyChoiceHelper::InstallAll(prefix1, "/localhost/nfd/strategy/multicast");
StrategyChoiceHelper::InstallAll(prefix2, "/localhost/nfd/strategy/best-route");
// Install NDN applications
AppHelper consumerHelper("ns3::ndn::ConsumerCbr");
consumerHelper.SetPrefix(prefix1);
consumerHelper.SetAttribute("Frequency", StringValue("100")); // 100 interests a second
consumerHelper.Install(consumer1);
consumerHelper.SetPrefix(prefix2);
consumerHelper.Install(consumer2);
AppHelper producerHelper("ns3::ndn::Producer");
producerHelper.SetPrefix(prefix1);
producerHelper.SetAttribute("PayloadSize", StringValue("1024"));
producerHelper.Install(producer1);
producerHelper.SetPrefix(prefix2);
producerHelper.Install(producer2);
// Add /prefix1 and /prefix2 origins to ndn::GlobalRouter
ndnGlobalRoutingHelper.AddOrigins(prefix1, producer1);
ndnGlobalRoutingHelper.AddOrigins(prefix2, producer2);
// Calculate and install FIBs
GlobalRoutingHelper::CalculateRoutes();
Simulator::Stop(Seconds(20.0));
Simulator::Run();
Simulator::Destroy();
return 0;
}
|
To run this scenario and see what is happening, use the following command:
NS_LOG=ndn.Consumer:ndn.Producer ./waf --run=ndn-different-strategy-per-prefix
9-node grid topology with different forwarding strategy for each node¶
This scenario simulates a grid topology (using PointToPointGrid module). The first six nodes use the best route forwarding strategy, whereas the three remaining nodes use the multicast forwarding strategy.
Consumer requests data from producer with frequency 100 interests per second (interests contain constantly increasing sequence number).
For every received interest, producer replies with a data packet, containing 1024 bytes of virtual payload.
Example simulation (ndn-grid-multiple-strategies.cpp
) scenario:
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 | // ndn-grid-multiple-strategies.cpp
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/point-to-point-layout-module.h"
#include "ns3/ndnSIM-module.h"
using namespace ns3;
using ns3::ndn::StackHelper;
using ns3::ndn::AppHelper;
using ns3::ndn::GlobalRoutingHelper;
using ns3::ndn::StrategyChoiceHelper;
int
main(int argc, char* argv[])
{
// Setting default parameters for PointToPoint links and channels
Config::SetDefault("ns3::PointToPointNetDevice::DataRate", StringValue("1Mbps"));
Config::SetDefault("ns3::PointToPointChannel::Delay", StringValue("10ms"));
Config::SetDefault("ns3::QueueBase::MaxSize", StringValue("10p"));
// Read optional command-line parameters (e.g., enable visualizer with ./waf --run=<> --visualize
CommandLine cmd;
cmd.Parse(argc, argv);
// Creating 3x3 topology
PointToPointHelper p2p;
PointToPointGridHelper grid(3, 3, p2p);
grid.BoundingBox(100, 100, 200, 200);
// Install NDN stack on all nodes
StackHelper ndnHelper;
ndnHelper.InstallAll();
// Installing global routing interface on all nodes
GlobalRoutingHelper ndnGlobalRoutingHelper;
ndnGlobalRoutingHelper.InstallAll();
// Getting containers for the consumer/producer
Ptr<Node> producer = grid.GetNode(2, 2);
NodeContainer consumerNodes;
consumerNodes.Add(grid.GetNode(0, 0));
// Install NDN applications
std::string prefix = "/prefix";
// Install different forwarding strategies
for (int row = 0; row < 3; row++) {
for (int column = 0; column < 3; column++) {
if (row < 2)
StrategyChoiceHelper::Install(grid.GetNode(row, column), "/prefix",
"/localhost/nfd/strategy/best-route");
else
StrategyChoiceHelper::Install(grid.GetNode(row, column), "/prefix",
"/localhost/nfd/strategy/multicast");
}
}
AppHelper consumerHelper("ns3::ndn::ConsumerCbr");
consumerHelper.SetPrefix(prefix);
consumerHelper.SetAttribute("Frequency", StringValue("100")); // 100 interests a second
consumerHelper.Install(consumerNodes);
AppHelper producerHelper("ns3::ndn::Producer");
producerHelper.SetPrefix(prefix);
producerHelper.SetAttribute("PayloadSize", StringValue("1024"));
producerHelper.Install(producer);
// Add /prefix origins to ndn::GlobalRouter
ndnGlobalRoutingHelper.AddOrigins(prefix, producer);
// Calculate and install FIBs
GlobalRoutingHelper::CalculateRoutes();
Simulator::Stop(Seconds(20.0));
Simulator::Run();
Simulator::Destroy();
return 0;
}
|
To run this scenario and see what is happening, use the following command:
NS_LOG=ndn.Consumer:ndn.Producer ./waf --run=ndn-grid-multiple-strategies
Simple parallel scenario using MPI¶
3-level binary tree with packet-level trace helpers¶
3-level binary tree with content store trace helper¶
3-level binary tree with application-level Interest-Data delay tracer¶
1-node topology with custom application¶
Simple scenario with pcap dump¶
The following example (ndn-simple-with-pcap.cpp
) demonstrates how to dump all simulated
traffic in pcap-formatted data, which can be used for later analysis by conventional tools,
like tcpdump and wireshark.
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 | // ndn-simple-with-pcap.cpp
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/ndnSIM-module.h"
/**
* This scenario demonstrates how to dump raw NDN packets into tcpdump-format
*
* Run scenario:
*
* ./waf --run ndn-simple-with-pcap
*
* After simulation finishes, it produces `ndn-simple-trace.pcap` that can be read
* using tcpdump or ndndump tools:
*
* ndndump -r ndn-simple-trace.pcap not ip
* tcpdump -r ndn-simple-trace.pcap
*/
namespace ns3 {
class PcapWriter {
public:
PcapWriter(const std::string& file)
{
PcapHelper helper;
m_pcap = helper.CreateFile(file, std::ios::out, PcapHelper::DLT_PPP);
}
void
TracePacket(Ptr<const Packet> packet)
{
static PppHeader pppHeader;
pppHeader.SetProtocol(0x0077);
m_pcap->Write(Simulator::Now(), pppHeader, packet);
}
private:
Ptr<PcapFileWrapper> m_pcap;
};
int
main(int argc, char* argv[])
{
// setting default parameters for PointToPoint links and channels
Config::SetDefault("ns3::PointToPointNetDevice::DataRate", StringValue("1Mbps"));
Config::SetDefault("ns3::PointToPointChannel::Delay", StringValue("10ms"));
Config::SetDefault("ns3::QueueBase::MaxSize", StringValue("20p"));
// Read optional command-line parameters (e.g., enable visualizer with ./waf --run=<> --visualize
CommandLine cmd;
cmd.Parse(argc, argv);
// Creating nodes
NodeContainer nodes;
nodes.Create(3);
// Connecting nodes using two links
PointToPointHelper p2p;
p2p.Install(nodes.Get(0), nodes.Get(1));
p2p.Install(nodes.Get(1), nodes.Get(2));
// Install NDN stack on all nodes
ndn::StackHelper ndnHelper;
ndnHelper.SetDefaultRoutes(true);
ndnHelper.InstallAll();
// Installing applications
// Consumer
ndn::AppHelper consumerHelper("ns3::ndn::ConsumerCbr");
// Consumer will request /prefix/0, /prefix/1, ...
consumerHelper.SetPrefix("/prefix");
consumerHelper.SetAttribute("Frequency", StringValue("10")); // 10 interests a second
consumerHelper.Install(nodes.Get(0)); // first node
// Producer
ndn::AppHelper producerHelper("ns3::ndn::Producer");
// Producer will reply to all requests starting with /prefix
producerHelper.SetPrefix("/prefix");
producerHelper.SetAttribute("PayloadSize", StringValue("1024"));
producerHelper.SetAttribute("Signature", UintegerValue(100));
producerHelper.SetAttribute("KeyLocator", StringValue("/unique/key/locator"));
producerHelper.Install(nodes.Get(2)); // last node
PcapWriter trace("ndn-simple-trace.pcap");
Config::ConnectWithoutContext("/NodeList/*/DeviceList/*/$ns3::PointToPointNetDevice/MacTx",
MakeCallback(&PcapWriter::TracePacket, &trace));
Simulator::Stop(Seconds(20.0));
Simulator::Run();
Simulator::Destroy();
return 0;
}
} // namespace ns3
int
main(int argc, char* argv[])
{
return ns3::main(argc, argv);
}
|
If this code is placed into scratch/ndn-simple-with-pcap.cpp
and NS-3 is compiled in debug
mode, you can run and see progress of the simulation using the following command (in optimized
mode nothing will be printed out):
NS_LOG=ndn.Consumer:ndn.Producer ./waf --run=ndn-simple-with-pcap
This will generate ndn-simple-trace.pcap
, which can be fed to tcpdump:
tcpdump -r ndn-simple-trace.pcap
Note
If you compiled ndnSIM with examples (./waf configure --enable-examples
) you can
directly run the example without putting scenario into scratch/
folder.
Simple scenario with link failures¶
The following example (ndn-simple-with-link-failure.cpp
) shows how to “fail” links in
ndnSIM simulation. The basic idea is to set ndn::Faces that correspond to the failed link to
DOWN state. ndnSIM now includes a simple helper that simplifies this process.
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 | // ndn-simple-with-link-failure.cpp
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/ndnSIM-module.h"
// for LinkStatusControl::FailLinks and LinkStatusControl::UpLinks
#include "ns3/ndnSIM/helper/ndn-link-control-helper.hpp"
namespace ns3 {
int
main(int argc, char* argv[])
{
// setting default parameters for PointToPoint links and channels
Config::SetDefault("ns3::PointToPointNetDevice::DataRate", StringValue("1Mbps"));
Config::SetDefault("ns3::PointToPointChannel::Delay", StringValue("10ms"));
Config::SetDefault("ns3::QueueBase::MaxSize", StringValue("20p"));
// Read optional command-line parameters (e.g., enable visualizer with ./waf --run=<> --visualize
CommandLine cmd;
cmd.Parse(argc, argv);
// Creating nodes
NodeContainer nodes;
nodes.Create(3);
// Connecting nodes using two links
PointToPointHelper p2p;
p2p.Install(nodes.Get(0), nodes.Get(1));
p2p.Install(nodes.Get(1), nodes.Get(2));
// Install NDN stack on all nodes
ndn::StackHelper ndnHelper;
ndnHelper.SetDefaultRoutes(true);
ndnHelper.InstallAll();
// Installing applications
// Consumer
ndn::AppHelper consumerHelper("ns3::ndn::ConsumerCbr");
// Consumer will request /prefix/0, /prefix/1, ...
consumerHelper.SetPrefix("/prefix");
consumerHelper.SetAttribute("Frequency", StringValue("10")); // 10 interests a second
consumerHelper.Install(nodes.Get(0)); // first node
// Producer
ndn::AppHelper producerHelper("ns3::ndn::Producer");
// Producer will reply to all requests starting with /prefix
producerHelper.SetPrefix("/prefix");
producerHelper.SetAttribute("PayloadSize", StringValue("1024"));
producerHelper.Install(nodes.Get(2)); // last node
// The failure of the link connecting consumer and router will start from seconds 10.0 to 15.0
Simulator::Schedule(Seconds(10.0), ndn::LinkControlHelper::FailLink, nodes.Get(0), nodes.Get(1));
Simulator::Schedule(Seconds(15.0), ndn::LinkControlHelper::UpLink, nodes.Get(0), nodes.Get(1));
Simulator::Stop(Seconds(20.0));
Simulator::Run();
Simulator::Destroy();
return 0;
}
} // namespace ns3
int
main(int argc, char* argv[])
{
return ns3::main(argc, argv);
}
|
If this code is placed into scratch/ndn-simple-with-link-failure.cpp
and NS-3 is compiled
in debug mode, you can run and see progress of the simulation using the following command (in
optimized mode nothing will be printed out):
NS_LOG=ndn.Consumer:ndn.Producer:ndn.LinkControlHelper ./waf --run=ndn-simple-with-link-failure
Note
If you compiled ndnSIM with examples (./waf configure --enable-examples
) you can
directly run the example without putting scenario into scratch/
folder.
25-node tree topology with L2Tracer¶
LFID (Loop-Free Inport-Dependent) Routing for ndnSIM¶
LFID (Loop-Free Inport-Dependent) Routing extends the ndnSIM route calculation to provide loop-free and on average shorter loop-free paths than existing work. For details see the tech report.
LFID provides a better trade-off than the existing route calculation algorithms:
CalculateRoutes():
Only provides a single shortest path nexthop.CalculateAllPossibleRoutes():
Provides all possible nexthops, but many of them lead to loops.
LFID, on the other hand, maximizes the nexthop choice while also completely avoiding loops.
We provide two example topologies (abilene and grid) to compare against the existing route calculation methods:
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 | int
main(int argc, char* argv[])
{
bool grid = false; // Use grid topology?
std::string routing = "lfid";
CommandLine cmd;
cmd.AddValue("grid", "use grid topology (instead of abilene)", grid);
cmd.AddValue("routing", "which route computation to use (lfid, sp, allroutes)", routing);
cmd.Parse(argc, argv);
std::string topoName = "abilene";
if (grid) {
topoName = "grid";
}
std::cout << "Using " << topoName << " topology\n\n";
AnnotatedTopologyReader topologyReader{};
topologyReader.SetFileName("src/ndnSIM/examples/topologies/topo-" + topoName + ".txt");
topologyReader.Read();
ndn::StackHelper stackHelper{};
stackHelper.InstallAll();
// IMPORTANT: Has to be run after StackHelper!
topologyReader.ApplyOspfMetric();
const std::string prefix{"/prefix"};
Ptr<Node> consumerN = Names::Find<Node>("router0");
Ptr<Node> producerN = Names::Find<Node>("producer");
NS_ABORT_MSG_UNLESS(consumerN && producerN, "consumer or producer name does not exist in topo file!");
ndn::GlobalRoutingHelper routingHelper;
routingHelper.InstallAll(); // Fills GlobalRouter with incidencies.
routingHelper.AddOrigin(prefix, producerN);
if (routing == "lfid") {
routingHelper.CalculateLfidRoutes();
}
else if (routing == "sp") {
routingHelper.CalculateRoutes();
}
else if (routing == "allroutes") {
routingHelper.CalculateAllPossibleRoutes();
}
else {
NS_FATAL_ERROR("Unknown route calculation! Use --routing {lfid|sp|allroutes}");
}
// IMPORTANT: Some strategy needs to be installed for displayRoutes() to work.
ndn::StrategyChoiceHelper strategyHelper;
strategyHelper.InstallAll<nfd::fw::BestRouteStrategy2>("/");
// TODO: Needs RandomStrategy for test to work!
// Uncomment after NFD version has been updated.
// strategyHelper.InstallAll<nfd::fw::RandomStrategy>("/");
displayRoutes(topologyReader.GetNodes(), prefix);
// Installing applications
ndn::AppHelper consumerHelperX{"ns3::ndn::ConsumerCbr"};
consumerHelperX.SetPrefix(prefix);
consumerHelperX.SetAttribute("Frequency", DoubleValue(100.0));
consumerHelperX.Install(consumerN);
ndn::AppHelper producerHelper0{"ns3::ndn::Producer"};
producerHelper0.SetPrefix(prefix);
producerHelper0.Install(producerN);
Simulator::Stop(Seconds(30));
Simulator::Run();
Simulator::Destroy();
return 0;
}
} // namespace ns3
|
Simply run:
./waf --run "lfid [--grid] [--routing={lfid|sp|allroutes}]"
The output will show the nexthops at each node for the given name prefix, and any loops during forwarding.