ndnSIM applications¶
ndnSIM includes a few reference applications that can be used as a base for NDN simulations.
Reference applications¶
ConsumerCbr¶
ConsumerCbr an application that generates Interest traffic with predefined pattern (constant frequency, constant average rate with inter-Interest gap distributed uniformly at random, exponentially at random, etc.).
// Create application using the app helper
AppHelper helper("ns3::ndn::ConsumerCbr");
This applications has the following attributes:
Frequency
Note
default:
1.0
(1 per second)Either exact (for contant version) or expected (for randomized version) frequency with which Interests are generated
// Set attribute using the app helper helper.SetAttribute("Frequency", DoubleValue (1.0));
Randomize
Note
default:
"none"
Specify whether to do randomization for inter-Interest gap or not. The following variants are currently supported:
"none"
: no randomization"uniform"
: uniform distribution in range (0, 1/Frequency)"exponential"
: exponential distribution with mean 1/Frequency
// Set attribute using the app helper helper.SetAttribute("Randomize", StringValue("uniform"));
ConsumerZipfMandelbrot¶
Note
Author: Xiaoke Jiang
An app that requests contents (names in the requests) following Zipf-Mandelbrot distribution (number of Content frequency Distribution). This class is a subclass of ConsumerCbr.
// Create application using the app helper
ndn::AppHelper helper("ns3::ndn::ConsumerZipfMandelbrot");
Frequency
and Randomize
attributes can be used in the same way as in the base ConsumerCbr applications.
Additional attributes:
NumberOfContents
Note
default: 100
Number of different content (sequence numbers) that will be requested by the applications
THE following pictures show basic comparison of the generated stream of Interests versus theoretical Zipf-Mandelbrot function (NumberOfContents
set to 100 and Frequency
set to 100)
ConsumerBatches¶
ConsumerBatches is an on-off-style application generating a specified number of Interests at specified points of simulation.
// Create application using the app helper
ndn::AppHelper consumerHelper("ns3::ndn::ConsumerBatches");
This applications has the following attributes:
Batches
Note
default: Empty
Specify exact pattern of Interest packets, specifying when and how many Interest packets should be sent. The following example defines that 1 Interest should be requested at time 1s, 5 Interests at time 2s, and 2 Interests at time 10s.
// Set attribute using the app helper consumerHelper.SetAttribute("Batches", StringValue("1s 1 2s 5 10s 2"));
Note that the specified batch of Interests is not sent out at the specified time at once. ConsumerBatches starts each batch at the specified time, while each Interests is separated in time by the estimated retransmission time. For example, the above could result in following Interest sending timeline:
1s 0 ndn.Consumer:SendPacket(): [INFO ] > Interest for 0 2s 0 ndn.Consumer:SendPacket(): [INFO ] > Interest for 1 2s 0 ndn.Consumer:SendPacket(): [INFO ] > Interest for 2 2.2s 0 ndn.Consumer:SendPacket(): [INFO ] > Interest for 3 2.4s 0 ndn.Consumer:SendPacket(): [INFO ] > Interest for 4 2.6s 0 ndn.Consumer:SendPacket(): [INFO ] > Interest for 5 10s 0 ndn.Consumer:SendPacket(): [INFO ] > Interest for 6 10.2s 0 ndn.Consumer:SendPacket(): [INFO ] > Interest for 7
ConsumerWindow¶
ConsumerWindow is an application generating a variable rate Interest traffic. It implements a simple sliding-window-based Interest generation mechanism.
// Create application using the app helper
AppHelper consumerHelper("ns3::ndn::ConsumerWindow");
This applications has the following attributes:
Window
Note
default:
1
Initial number of Interests that will be send out without waiting for the data (number of outstanding Interests)
PayloadSize
Note
default:
1040
Expected size of the Data payload (necessary only when Size is specified)
Size
Note
default:
-1
Amount of data to be requested (will stop issuing Interests after
Size
data is received)If
Size
is set to -1, Interests will be requested till the end of the simulation.
Custom applications¶
Applications interact with the core of the system using AppFace realization of Face abstraction. To simplify implementation of specific NDN application, ndnSIM provides a base App class that takes care of creating AppFace and registering it inside the NDN protocol stack, as well as provides default processing for incoming Interest and Data packets.
Customer example¶
The following code shows how a simple ndnSIM application can be created, and how an application can send Interests and respond with ContentObjects to incoming interests.
When this application starts it sets “interest filter” (install FIB entry) for /prefix/sub, as well as sends Interest for this prefix. When an Interest is received, it is replied with a ContentObject with 1024-byte fake payload.
For more details refer examples/ndn-custom-apps/custom-app.hpp
, examples/ndn-custom-apps/custom-app.cpp
and API documentation of ndnSIM and NS-3.
Header file examples/ndn-custom-apps/custom-app.hpp
:
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 | // custom-app.hpp
#ifndef CUSTOM_APP_H_
#define CUSTOM_APP_H_
#include "ns3/ndnSIM/apps/ndn-app.hpp"
namespace ns3 {
class CustomApp : public ndn::App {
public:
// register NS-3 type "CustomApp"
static TypeId
GetTypeId();
// (overridden from ndn::App) Processing upon start of the application
virtual void
StartApplication();
// (overridden from ndn::App) Processing when application is stopped
virtual void
StopApplication();
// (overridden from ndn::App) Callback that will be called when Interest arrives
virtual void
OnInterest(std::shared_ptr<const ndn::Interest> interest);
// (overridden from ndn::App) Callback that will be called when Data arrives
virtual void
OnData(std::shared_ptr<const ndn::Data> contentObject);
private:
void
SendInterest();
};
} // namespace ns3
#endif // CUSTOM_APP_H_
|
Source file examples/ndn-custom-apps/custom-app.cpp
:
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 | // custom-app.cpp
#include "custom-app.hpp"
#include "ns3/ptr.h"
#include "ns3/log.h"
#include "ns3/simulator.h"
#include "ns3/packet.h"
#include "ns3/ndnSIM/helper/ndn-stack-helper.hpp"
#include "ns3/ndnSIM/helper/ndn-fib-helper.hpp"
#include "ns3/random-variable-stream.h"
NS_LOG_COMPONENT_DEFINE("CustomApp");
namespace ns3 {
NS_OBJECT_ENSURE_REGISTERED(CustomApp);
// register NS-3 type
TypeId
CustomApp::GetTypeId()
{
static TypeId tid = TypeId("CustomApp").SetParent<ndn::App>().AddConstructor<CustomApp>();
return tid;
}
// Processing upon start of the application
void
CustomApp::StartApplication()
{
// initialize ndn::App
ndn::App::StartApplication();
// Add entry to FIB for `/prefix/sub`
ndn::FibHelper::AddRoute(GetNode(), "/prefix/sub", m_face, 0);
// Schedule send of first interest
Simulator::Schedule(Seconds(1.0), &CustomApp::SendInterest, this);
}
// Processing when application is stopped
void
CustomApp::StopApplication()
{
// cleanup ndn::App
ndn::App::StopApplication();
}
void
CustomApp::SendInterest()
{
/////////////////////////////////////
// Sending one Interest packet out //
/////////////////////////////////////
// Create and configure ndn::Interest
auto interest = std::make_shared<ndn::Interest>("/prefix/sub");
Ptr<UniformRandomVariable> rand = CreateObject<UniformRandomVariable>();
interest->setNonce(rand->GetValue(0, std::numeric_limits<uint32_t>::max()));
interest->setInterestLifetime(ndn::time::seconds(1));
NS_LOG_DEBUG("Sending Interest packet for " << *interest);
// Call trace (for logging purposes)
m_transmittedInterests(interest, this, m_face);
m_face->onReceiveInterest(*interest);
}
// Callback that will be called when Interest arrives
void
CustomApp::OnInterest(std::shared_ptr<const ndn::Interest> interest)
{
ndn::App::OnInterest(interest);
NS_LOG_DEBUG("Received Interest packet for " << interest->getName());
// Note that Interests send out by the app will not be sent back to the app !
auto data = std::make_shared<ndn::Data>(interest->getName());
data->setFreshnessPeriod(ndn::time::milliseconds(1000));
data->setContent(std::make_shared< ::ndn::Buffer>(1024));
ndn::StackHelper::getKeyChain().sign(*data);
NS_LOG_DEBUG("Sending Data packet for " << data->getName());
// Call trace (for logging purposes)
m_transmittedDatas(data, this, m_face);
m_face->onReceiveData(*data);
}
// Callback that will be called when Data arrives
void
CustomApp::OnData(std::shared_ptr<const ndn::Data> data)
{
NS_LOG_DEBUG("Receiving Data packet for " << data->getName());
std::cout << "DATA received for name " << data->getName() << std::endl;
}
} // namespace ns3
|
Example how to use custom app in a scenario (ndn-simple-with-custom-app.cpp
):
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 | // ndn-custom-apps.cpp
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/ndnSIM-module.h"
namespace ns3 {
int
main(int argc, char* argv[])
{
// Read optional command-line parameters (e.g., enable visualizer with ./waf --run=<> --visualize
CommandLine cmd;
cmd.Parse(argc, argv);
// Creating nodes
Ptr<Node> node = CreateObject<Node>();
// Install NDN stack on all nodes
ndn::StackHelper ndnHelper;
ndnHelper.SetDefaultRoutes(true);
ndnHelper.InstallAll();
// App1
ndn::AppHelper app1("CustomApp");
app1.Install(node);
// App2
ndn::AppHelper app2("Hijacker");
app2.Install(node); // 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);
}
|
To run this scenario, use the following command:
NS_LOG=CustomApp ./waf --run=ndn-custom-apps
Producer example (Interest hijacker)¶
The following code demonstrates how to implement a basic producer application that “hijacks” all incoming Interests.
Header file examples/ndn-custom-apps/hijacker.hpp
:
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 | // hijacker.hpp
#ifndef HIJACKER_H_
#define HIJACKER_H_
#include "ns3/ndnSIM/apps/ndn-app.hpp"
namespace ns3 {
class Hijacker : public ndn::App {
public:
static TypeId
GetTypeId();
Hijacker();
// Receive all Interests but do nothing in response
void
OnInterest(std::shared_ptr<const ndn::Interest> interest);
protected:
// inherited from Application base class.
virtual void
StartApplication();
virtual void
StopApplication();
};
} // namespace ns3
#endif // HIJACKER_H_
|
Source file examples/ndn-custom-apps/hijacker.cpp
:
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 | // hijacker.cpp
#include "hijacker.hpp"
#include "ns3/log.h"
#include "ns3/ndnSIM/helper/ndn-fib-helper.hpp"
NS_LOG_COMPONENT_DEFINE("Hijacker");
namespace ns3 {
// Necessary if you are planning to use ndn::AppHelper
NS_OBJECT_ENSURE_REGISTERED(Hijacker);
TypeId
Hijacker::GetTypeId()
{
static TypeId tid = TypeId("Hijacker").SetParent<ndn::App>().AddConstructor<Hijacker>();
return tid;
}
Hijacker::Hijacker()
{
}
void
Hijacker::OnInterest(std::shared_ptr<const ndn::Interest> interest)
{
ndn::App::OnInterest(interest); // forward call to perform app-level tracing
// do nothing else (hijack interest)
NS_LOG_DEBUG("Do nothing for incoming interest for" << interest->getName());
}
void
Hijacker::StartApplication()
{
App::StartApplication();
// equivalent to setting interest filter for "/prefix" prefix
ndn::FibHelper::AddRoute(GetNode(), "/prefix/sub", m_face, 0);
}
void
Hijacker::StopApplication()
{
App::StopApplication();
}
} // namespace ns3
|
After defining this class, you can use it with ndn::AppHelper. For example:
...
ndn::AppHelper producerHelper("Hijacker");
producerHelper.Install(producerNode);
...