ndnSIM applications

ndnSIM includes a few reference applications that can be used as a base for NDN simulations.

Reference applications

ConsumerCbr

:ndnsim:`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 :ndnsim:`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 :ndnsim:`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)

Comparsion between simulation and theory with simulation duration 10 seconds Comparsion between simulation and theory with simulation duration 50 seconds Comparsion between simulation and theory with simulation duration 100 seconds Comparsion between simulation and theory with simulation duration 1000 seconds

ConsumerBatches

:ndnsim:`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. :ndnsim:`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

:ndnsim:`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.

ConsumerPcon

:ndnsim:`ConsumerPcon` is an application generating variable-rate Interest traffic. It implements a window-based rate control that adjusts window size using the PCON congestion control mechanism developed by K. Schneider et al. (https://named-data.net/publications/practical_congestion_control_scheme/). It is derived from :ndnsim:`ConsumerWindow`.

// Create application using the app helper
AppHelper consumerHelper("ns3::ndn::ConsumerPcon");

The application has the same attributes as :ndnsim:`ConsumerWindow`, in addition to the following:

  • CcAlgorithm

    Note

    default: AIMD

    Which window adaptation algorithm to use (AIMD, BIC, or CUBIC)

  • Beta

    Note

    default: 0.5

    TCP Multiplicative Decrease factor

  • CubicBeta

    Note

    default: 0.8

    TCP CUBIC Multiplicative Decrease factor

  • AddRttSupress

    Note

    default: 0.5

    Minimum number of RTTs (1 + this factor) between window decreases

  • ReactToCongestionMarks

    Note

    default: true

    If true, process received congestion marks; otherwise, ignore them

  • UseCwa

    Note

    default: true

    If true, use Conservative Window Adaptation

  • UseCubicFastConvergence

    Note

    default: true

    If true, use TCP CUBIC Fast Convergence

Producer

:ndnsim:`Producer` a simple Interest-sink application, which replying every incoming Interest with Data packet with a specified size and name same as in Interest.

// Create application using the app helper
AppHelper consumerHelper("ns3::ndn::Producer");

Custom applications

Applications interact with the core of the system using :ndnsim:`AppLinkService` realization of link service abstraction. To simplify implementation of specific NDN application, ndnSIM provides a base :ndnsim:`App` class that takes care of creating :ndnsim:`AppLinkService` 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_appLink->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_appLink->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 :ndnsim:`ndn::AppHelper`. For example:

...
ndn::AppHelper producerHelper("Hijacker");
producerHelper.Install(producerNode);
...