Spyridon Mastorakis | 95be509 | 2015-08-26 15:07:37 -0700 | [diff] [blame] | 1 | Simulating real NDN applications |
| 2 | ================================ |
Alexander Afanasyev | 5dee361 | 2015-08-25 16:09:04 -0700 | [diff] [blame] | 3 | |
Xinyu Ma | fc8956c | 2019-04-08 23:17:52 -0700 | [diff] [blame] | 4 | The version of `ndn-cxx library <https://named-data.net/doc/ndn-cxx/>`__ bundled with ndnSIM includes |
Spyridon Mastorakis | 95be509 | 2015-08-26 15:07:37 -0700 | [diff] [blame] | 5 | a modified version of :ndnsim:`ndn::Face` to directly send and receive Interest and Data packets to |
| 6 | and from the simulated instances of NFD. With this modification, ndnSIM enables support to simulate |
| 7 | real NDN applications written against the ndn-cxx, if they satisfy requirements listed in this guide |
| 8 | or can be modified to satisfy these requirements. |
| 9 | |
| 10 | |
| 11 | Requirements |
| 12 | ++++++++++++ |
| 13 | |
| 14 | #. **Source code of the application must be available** |
| 15 | |
| 16 | The application (parts of the application) needs to be compiled against the ndnSIM version of |
| 17 | ndn-cxx library. |
| 18 | |
| 19 | #. **Source code should separate** ``main`` **function from the functional components of the |
| 20 | application that will be simulated** |
| 21 | |
| 22 | The entry point to the application (its functional component) will be NS-3 application class, |
| 23 | which should be able to create and destroy an instance of the simulated component when scheduled |
| 24 | by the scenario. |
| 25 | |
| 26 | #. **The application should not use global variables, if they define a state for the application |
| 27 | instance** |
| 28 | |
| 29 | ndnSIM should be able to create multiple different instances of the application, e.g., for each |
| 30 | simulated node. |
| 31 | |
| 32 | Exception to this requirement is :ndnsim:`ndn::Scheduler <ndn::util::scheduler::Scheduler>`: its |
| 33 | implementation has been rewired to use NS-3's scheduling routines. |
| 34 | |
| 35 | #. **The application MUST NOT contain any GUI or command-line terminal interactions** |
| 36 | |
| 37 | #. **The application SHOULD NOT use disk operations, unless application instances access unique |
| 38 | parts of the file system** |
| 39 | |
| 40 | In the simulated environment, all application instances will be accessing the same local file |
| 41 | system, which can result in undefined behavior if not properly handled. |
| 42 | |
| 43 | #. **The application MUST use a subset of** :ndnsim:`ndn::Face` **API:** |
| 44 | |
| 45 | - If the application create :ndnsim:`ndn::Face`, it MUST BE created either with a default |
| 46 | constructor or constructor that accepts a single ``boost::asio::io_service`` parameter. |
| 47 | |
| 48 | .. code-block:: c++ |
| 49 | |
| 50 | // Supported |
| 51 | ndn::Face face1(); |
| 52 | ndn::Face face2(ioService); |
| 53 | |
| 54 | // Not supported in ndnSIM |
| 55 | ndn::Face face4(host_name, port_number) |
| 56 | ndn::Face face3(transport); |
| 57 | // and others |
| 58 | |
| 59 | - :ndnsim:`ndn::Face::getIoService()` should be used only to obtain a reference to |
| 60 | ``boost::asio::io_service``. **Application MUST NOT use any methods of** |
| 61 | ``boost::asio::io_service``, **otherwise the simulation will crash.** |
| 62 | |
| 63 | .. code-block:: c++ |
| 64 | |
| 65 | ndn::Face face; |
| 66 | ... |
| 67 | // Supported (the rewired Scheduler implementation does not access io_service methods) |
| 68 | Scheduler scheduler(face.getIoService()); |
| 69 | |
| 70 | // Not supported in ndnSIM and will result in crash |
| 71 | face.getIoService().stop(); |
| 72 | |
| 73 | |
| 74 | - Application should avoid use of :ndnsim:`Face::processEvents` or use it with caution |
| 75 | |
| 76 | In real applications, processEvents blocks until some data is received or the timeout callback |
| 77 | is called. In this case, any variables created before calling this method will still exist |
| 78 | after the method returns. However, in ndnSIM, such an assumption cannot be made, since the |
| 79 | scope of a variable is local. |
| 80 | |
| 81 | .. code-block:: c++ |
| 82 | |
| 83 | void |
| 84 | foo |
| 85 | { |
| 86 | ndn::Face face; |
| 87 | face.expressInterest(...); |
| 88 | face.setInterestFilter(...); |
| 89 | |
| 90 | // ndnSIM version of processEvents will not block! |
| 91 | face.processEvents(); |
| 92 | } |
| 93 | // after existing foo scope, face variable is deallocated and all scheduled operations |
| 94 | // will be canceled |
| 95 | |
| 96 | #. **Application (simulated component) MUST NOT create instances of** ``boost::asio::io_service`` |
| 97 | **and use their methods** |
| 98 | |
| 99 | ``boost::asio::io_service`` is inherently incompatible with NS-3, as both are providing mechanisms |
| 100 | for asynchronous event processing. |
| 101 | |
| 102 | #. We also recommend that functional part of the application accepts reference to the |
| 103 | :ndnsim:`KeyChain` instance, instead of creating instance itself. |
| 104 | |
| 105 | When simulating non-security aspects of the application, in simulation scenario it will be |
| 106 | possible to use a dummy implementation of the :ndnsim:`KeyChain` that does not perform crypto |
| 107 | operations, but signs Data and Interests with fake signatures. |
| 108 | |
| 109 | For example, this can be achieved by enabling the constructor of the real application to accept a reference |
| 110 | to the :ndnsim:`KeyChain`: |
| 111 | |
| 112 | .. code-block:: c++ |
| 113 | |
| 114 | // Real applications should accept a reference to the KeyChain instance |
| 115 | RealApp::RealApp(KeyChain& keyChain) |
| 116 | : m_keyChain(keyChain) |
| 117 | { |
| 118 | } |
| 119 | |
| 120 | |
| 121 | How to simulate real applications using ndnSIM |
| 122 | ++++++++++++++++++++++++++++++++++++++++++++++ |
| 123 | |
| 124 | To simulate a real application, the simulation scenario should contain a class derived from |
| 125 | ``ns3::Application``. This class needs to create an instance of the :ndnsim:`ndn::Face` and/or real |
| 126 | application in the overloaded ``StartApplication`` method. This class also need to ensure that the |
| 127 | created instance is not deallocated until ``StopApplication`` method is called. |
| 128 | |
| 129 | For example, if the functional class of the real application looks like: |
| 130 | |
| 131 | .. literalinclude:: ../../examples/ndn-cxx-simple/real-app.hpp |
| 132 | :language: c++ |
| 133 | :linenos: |
| 134 | :lines: 23-75 |
| 135 | |
| 136 | |
| 137 | The corresponding NS-3 "entry point" application class can be like this: |
| 138 | |
| 139 | .. literalinclude:: ../../examples/ndn-cxx-simple/real-app-starter.hpp |
| 140 | :language: c++ |
| 141 | :linenos: |
| 142 | :lines: 25-65 |
| 143 | |
| 144 | .. note:: |
| 145 | There is a requirement that :ndnsim:`ndn::Face` MUST BE created within the context of a specific |
| 146 | ``ns3::Node``. In simple words this means that :ndnsim:`ndn::Face` constructor must be called |
| 147 | somewhere within the overloaded ``StartApplication`` method. |
| 148 | |
| 149 | Attempt to create a :ndnsim:`ndn::Face` outside ``ns3::Node`` (e.g., if the example included |
| 150 | member variable ``Face m_face`` in ``RealAppStarter`` class) will result in simulation crash. |
| 151 | |
| 152 | The final step is to actually write a simulation scenario that defines network topology, routing |
| 153 | information between nodes, on which nodes the application should be installed and when it should be |
| 154 | started and stopped. |
| 155 | |
| 156 | For the trivial example, let us assume that we have only one simulation node and we want to start |
| 157 | the application at time moment 6.5 seconds. This scenario can look like: |
| 158 | |
| 159 | .. literalinclude:: ../../examples/ndn-cxx-simple.cpp |
| 160 | :language: c++ |
| 161 | :linenos: |
| 162 | :lines: 20- |
| 163 | |
| 164 | |
| 165 | Example of a real application simulation |
| 166 | ++++++++++++++++++++++++++++++++++++++++ |
| 167 | |
| 168 | To demonstrate functionality of ndnSIM in a more complex and realistic case, we will use the NDN |
| 169 | ping application included as part of `NDN Essential Tools`_. |
| 170 | |
| 171 | For this example, we used a `scenario template repository`_ as a base to write simulation-specific |
| 172 | extensions and define scenarios, and the `final version of the scenario is available in GitHub |
| 173 | <https://github.com/named-data-ndnSIM/scenario-ndn-ping>`__. |
| 174 | |
| 175 | The following lists steps we did to simulate `ndnping` and `ndnpingserver` apps on a simple |
| 176 | three-node topology: |
| 177 | |
| 178 | - forked `scenario template repository`_ |
| 179 | |
| 180 | - imported the latest version of `NDN Essential Tools`_ source code as a git submodule |
| 181 | |
| 182 | - updated the build script (``wscript``) to compile the source code of ``ndnping`` and |
| 183 | ``ndnpingserver`` (with the exception of compilation units that contain ``main`` function) against |
| 184 | ndnSIM |
| 185 | |
| 186 | `View changes <https://github.com/named-data-ndnSIM/scenario-ndn-ping/commit/74269dc4de6afe2b6e13a0bcc8c0faac350d8fa3>`__ |
| 187 | |
| 188 | - defined ``PingClient`` and ``PingServer`` classes to hold state of application instances |
| 189 | |
| 190 | `View changes <https://github.com/named-data-ndnSIM/scenario-ndn-ping/commit/4f087a16e3171af38c05b53c6cfd9e752e7cda72>`__ |
| 191 | |
| 192 | - defined ``PingClientApp`` and ``PingServerApp`` NS-3 applications, that create and destroy |
| 193 | instances of ``PingClient`` and ``PingServer`` per NS-3 logic. |
| 194 | |
| 195 | `View changes <https://github.com/named-data-ndnSIM/scenario-ndn-ping/commit/2b317860f55b71b34ffdccac31444246d9b804fe>`__ |
| 196 | |
| 197 | - defined a simple scenario that creates a three node topology, installs NDN stacks, and installs |
| 198 | ``PingClientApp`` and ``PingServerApp`` applications on different simulation nodes. |
| 199 | |
| 200 | `View changes <https://github.com/named-data-ndnSIM/scenario-ndn-ping/commit/2b317860f55b71b34ffdccac31444246d9b804fe>`__ |
| 201 | |
| 202 | After all these steps, the repository is ready to run the simulation (see `README.md |
| 203 | <https://github.com/named-data-ndnSIM/scenario-ndn-ping/blob/master/README.md>`__ for more details). |
| 204 | |
| 205 | |
| 206 | .. note:: |
| 207 | The listed steps did not include any modification of `NDN Essential Tools`_ source code. |
| 208 | However, this was not the case when we initially attempted to run the simulation, as the source |
| 209 | code was violating a few requirements of this guide. `The changes that we made |
| 210 | <https://github.com/named-data/ndn-tools/commit/1e7a7b20c93014e86639e3d07f357c95b48b34ac>`__ are |
| 211 | an example of how to adapt the source code to be compatible with ndnSIM simulations. |
| 212 | |
| 213 | |
Xinyu Ma | fc8956c | 2019-04-08 23:17:52 -0700 | [diff] [blame] | 214 | .. _NDN Essential Tools: https://github.com/named-data/ndn-tools |
Spyridon Mastorakis | 95be509 | 2015-08-26 15:07:37 -0700 | [diff] [blame] | 215 | |
| 216 | .. _scenario template repository: https://github.com/named-data-ndnSIM/scenario-template |