Skip to content

What Makes ns-3 a Complex Thing to Understand and Use? 

While starting to learn ns-3, most of us find it very difficult to understand. Particularly, if the student is already familiar with ns-2 or Omnet++ then it will even become much harder for him to understand/grasp ‘what ns-3 really is’.  The student’s or scholar’s preconceived expectation in a simulator will make him misunderstand ns-3. Another major obstacle/misconception in using ns-3 is the way in which Python is frequently used along with C++. (Thank Mr Tom Henderson for announcing recent news regarding the removal of python bindings from ns-3 -because it will reduce some of these obstacles )

Of course, the ns-3 Documentations and Manual pages are providing explanations for each and every aspect of this wonderful simulator. But they are huge and their hugeness itself makes it impossible to grasp the very fine, basic aspects of this simulator; at least for someone within a few months or even years.
Often, the developer of ns-3 also generously provides answers to the questions of students/learners of ns-3 through the official ns-3 user group.  Even with this kind of help and support, it makes it impossible for someone to learn and understand ns-3; at least for someone within a few months or even years.

This article tries to explain why it is ambiguously hard to understand ns-3 and an ns-3 simulation (I mean, in most cases, even the student can not able to express the reason for their poor understanding/misunderstanding on ns-3).

The following article is an outcome of this article:

Ns-3 – Is it a Network Simulator or a Network Simulation(/Simulator) Library?

How ns-3 is different from most of the other simulators?

In most of the popular simulators (except ns-3), the simulator will be a different entity and the simulation script that the user will write for that simulator will be a separate entity. While running the simulation script, the simulator will just run/interpret the lines that the user created.

For example,

  • Under ns-2, the simulation will be presented in the form of TCL script and the core simulator which is made up of C++ and TCL objects will simply interpret the lines of the TCL simulation script.
  • Under Omnet ++, the simulation script will be a custom format text file (not like any programming language) core simulator which is made up of C++ objects will simply interpret the lines of the simulation script.
  • Even most of the non-free simulators are following the same ideology (Simulator is different from simulation script)

If a researcher needs to add a new protocol/application agent (for example in the case of ns-2), then they will write code for that protocol/application agent, by adopting the standards of the core simulator and compiling the core simulator itself with the added new protocol/application agent model.  After that, a user can use that new object within their simulations. The simulation script can be modified as per the requirement and can be run without recompiling the core simulator code.

So in other simulators, the simulator will interpret/run the simulation script.

So there will be only one “main()” function through which the core simulator starts running and start interpreting/running the simulation script. No other C++ code module will have “main()” function.

The Organization of ns-2 Simulator and an ns-3 Simulation

A. The ns-2 Way of Doing Simulation and Analysis

a. The Simulator

The following pseudo code explains ns-2’s  architecture :
The ns-2  (made up of C++ and TCL Object)

main() {
//the core simulator
// and some core functionalities
}
OtherProtocolModule1() {
//the protocol module code
}
OtherProtocolModule2() {
//the protocol module code
}


ANewCustomProtocolModule() {
//the protocol module code added by the user/researcher
}

b. The Simulation

A Typical User-level Simulation Code (made up of TCL)

// The simulation script will Use the above ns-2 modules and do the following:

//Initializing some common simulation parameters
//Creating simulation Object
//Initializing event trace logs and nam Trace ouput
//Configuring Nodes and Protocols
//Setting Traffic Flows
//Tunning the simulation

c) The Trace Analysis

Trace Analysis is generally done separately using a scripting language (using scripting languages/ or [advanced filters from UNIX perspective] such as tcl, awk, perl, shell etc.,)

A Typical Trace Analysis Script

// Read the even trace output that was generated during the simulation
// Phrase them line by line and get statistics out of it
// Prepare tables and graphs using the extracted statistics
So, generally, under ns-2, the simulator is a different entity – so without compiling its code, again and again, a tcl level simulation script can be modified and run several times.  Further, as a standard, the trace analysis will be done by another independent script, and it can be run again and again (with little modification during trial and error) without even disturbing or running the simulation code.

The ns-3 Way of Doing Simulation and Analysis

ns-3’s way is entirely different. Here, the simulation script that we write in C++ will itself become a separate simulator because it will have the “main()” function. In other words, each and every simulation script that we write under ns-3 will become a separate simulator. So whenever we need to change a single line in our simulation script (C++ code), we must recompile our simulator.

a. The Simulation Modules

The following is the way in which the ns-3 modules and other modules can be visualized. Here, there is no module with a main() function. One model can inherit from another and may use the functionalities of another module.

CoreSimulatorModule{
//the core simulator modules
// and some core functionalities
}
OtherProtocolModule1() {
//the protocol module code
// functionalities inherited from other modules
}
OtherProtocolModule2() {
//the protocol module code
// may also contain some minor modifications done by a user/researcher
}


ANewCustomProtocolModule() {
//the protocol module code added by the user/researcher
}

b) The Simulation or the Custom Simulator

A Typical ns-3 Simulation Script (made up of ns-3 Standard c++ Code). Here, it is the gateway of the start of an ns-3 simulation.

// The simulation script will Use the above ns-3 core modules and other modules and do the following:
main() {
//Initializing some common simulation parameters
//Creating simulation Objects
//Configuring Nodes and Protocols
//Setting Traffic Flows
//Initializing different kinds of trace logs and NetAnim Trace output
//running the simulation
}
So, after compiling this ns-3 simulation script(C++  code), the compiled output itself will become an independent simulator on its own.  (Omnet++ simulations can also be compiled and used as separate custom simulators – but ns-2 simulation script will always depend on the core simulator and only can be run through that)

c) The Trace Analysis

There are so many standards (non-standards) in doing trace analysis in the case of ns-3.  These standards (non-standards) is another main obstacle in front of a student or researcher that makes it difficult to understand and do research under ns-3.

One may do trace analysis in the following ways :

1) We can use the default logging functionality of ns-3 protocol agents /models to log different events of simulation in a text file and then do Trace Analysis just like in the case of ns-2. Like analyzing the trace logs separately using a scripting language (using scripting languages/(advanced filters from a UNIX perspective) such as tcl, awk, perl, shell etc.,). This approach mostly fails or will not be reliable because of the standards (non-standards) in triggering event logs by different ns-3 protocol agents /models. Further, such creation of logs by a particular protocol agent may differ from one ns-3 version to another. (my articles  “Event Trace File Generation in a ns-3 Simulation” and “Trace Analysis of ns-3 Ascii Traces using TraceMetrics Tool – An elementary Trace Analysis Solution for ns-3 are dealing with this kind of tracing and analysis.)

2) We can generate tcpdump format trace outputs while running a simulation, and later we may do trace analysis using tcpdump analysers such as “Wireshark”. This approach also will not be useful in most cases of a scholarly research-level simulation – because, in such cases, the trace analysis should be done on the output trace files of several batch runs of the simulation.  So applying Wireshark-based trace analysis on that huge number of separate trace files will become a meaningless operation. So, this kind of approach of trace analysis will be helpful in understanding an event from a single run of simulation – for example, while teaching something in a classroom/lab or finding a critical event that may be causing unexpected behaviour in a simulation.
3) The most reliable way of doing trace analysis on a batch of ns-3 simulations is using the FlowMonitor facility of ns-3. Further, that can also be done in more than one way.
i)  The most often used way is: using FlowMonitor inside the ns-3 simulation, iterating FlowMonitor::FlowStats with a for loop and calculating and logging throughput, delay etc.,  using different parameters of FlowMonitor::FlowStats. Again, this will need additional scripting to collect and parse output from the logged outputs of several batch runs of the simulation.

ii) Another way of using FlowMonitor is: to instruct the FlowMonitor to log all the events in an XML file and we may later do trace analysis on such  XML flow monitor log files using Python scripting or by any other scripting language. This way is much more suitable for doing scholarly research. (my article  “Trace Analysis of TCP Flows Under ns-3 MANET/ FANET/ VANET/ WSN Scenario”

uses this approach)

iii) There may be some other technique to use FlowMonitor inside a simulation and using the XML file of FlowMonitor outside the simulation – I do not know – the researcher may explore it as per their need of analysis of the outputs of batch runs of the simulation.

So, what is ns-3 now?

ns-3 is nothing but a collection of C++ objects of Protocols/Application Agents and the simulation core modules. So the separate code of these objects of Protocols/Application Agents and the simulation core modules, will not have a “main()” function.  So ns-3 is technically a collection of Network Simulation related objects – not a simulator by itself.  (please correct me if I am wrong)

So, simply, the simulation script (the C++ code) that we write will have the main() function, which will be the gateway/starting point of the simulator. So, simply, after compiling our code, using all other referred/used modules of ns-3(including the core simulator modules),  our code itself gets compiled and will become a new simulator. (please correct me if I am wrong)

Unlike ns-2, what we conventionally call ns-3 is not at all a simulator by itself. The simulation script that we write itself will become a custom simulator. So each and every simulation script that we write will become a separate, custom network simulator. (please correct me if I am wrong)

Why ns-3 simulation run faster than most of the simulators?

The main reason is; the simulation code is not interpreted by any other external entity. The simulation code itself is the simulator. So it will run at the native speed of the hardware and software – just like other running executable code of the operating system.

Another important reason is: While writing the ns-3 simulation script, we will only add the C++ objects of Protocols/Application Agents that are needed for that particular simulation. So, the final compiled version of the simulator (compiled version of our code) will only have the used/referred modules. So, each final compiled version of the simulator (compiled version of our code) will be smaller in size and the size may vary according to the number of used/referred C++ objects of Protocols/Application Agents in each simulation script (our main C++ simulation code)

Other obstacles in front of Understanding ns-3

The more advanced way of handling C++ objects/functions/constants/variables makes it even harder to understand or grasp a typical ns-3 simulation model and even a simple ns-3 simulation script.

Even though some of these kinds of advanced C++ conventions are taught in an object-oriented programming classroom here and there, they are not commonly practised in programming; at least by a student or an amateur programmer.

For example, the following line will set the default WifiMacQueue delay

Config::SetDefault(“ns3::WifiMacQueue::MaxDelay”, TimeValue(Seconds(WifiMacQueueMaxDelay)));

Of course, from the Object-Oriented Programming Point of View, there may be a good reason for doing things like this. Of course, I can understand the existence of a complex hierarchy of classes/objects in ns-3. But these kinds of long, explicit references in declarations simply make it impossible to grasp what actually we are doing here(and where). Further, if a typo mistake is made anywhere in this line the compiler will raise an error message in a “foreign language” which will not be at all in human-readable form. It may advise you to use gdb to trace that error – then again the gdb will raise another error message in another “foreign language” which will not also be at all in human-readable form.  (Please think about a poor learner who is trying to learn ns-3 here)

What restricts the developers to use simple conventions/declarations like the following? In this case, understanding the line and even tracking an error may be an easy task for a human.

WifiMacQueue->MaxDelay=10
or
WifiMacQueue.MaxDelay=10
or even
WifiMacQueue.SetMaxDelay(10)

Of course, this kind of declaration may lead to some errors/problems from an Object-Oriented Programming Point of View.  But will be a more human-understandable way of doing things in a computer programme.

To understand it further, I hereby give another example :

An XML way of handling data may be easy for a machine to handle and parse data. But definitely, the same XML format data will not be good for human understanding of that data.

So, from this perspective, an ns-3 simulation script is more friendly towards a machine-readable form. Definitely not friendly towards a human-readable form.

While developing a huge system like ns-3 using Object-Oriented Programming techniques, the level of abstraction and hierarchy of organizing/doing things should hide the complex things behind the scene from the end-user (the ns-3 simulation writer/student/researcher).  The interfaces that are provided to handle the objects and change the properties of the objects should be human-understandable forms.  But according to my view, from the first day of development itself, the developers ignored this point and now ns-3 becomes a huge, complex machine/compiler only understandable form.

Let us try to figure out some of the ns-3 lines for fun:

Ptr dev = DynamicCast (MobileAdhocNodes.Get(0)->GetDevice (0));

Ptr taPositionAlloc = pos.Create ()->GetObject ();

std::map stats = flowMonitor->GetFlowStats ();

There may be no other ‘elegant’  human-understandable way to do the above things. Or I may be missing to or unable to understand the elegance in those lines.

Once I heard that Unix was originally developed by programmers for programmers.

Just like that, I think, ns-3 was developed by brilliant developers for brilliant developers.

 

The ns-3 Coding style guideline says “Each statement should be put on a separate line to increase readability”. But the problem here is, even those single lines may not be readable/understandable because of these complex object references used in the state-of-the-art object-oriented programing conventions.

But I think, changing the way ns-3 does these kinds of things can not be altered/rectified now – because ns-3 become huge enough with all kinds of these complexities.  Just expressing my feelings/disabilities that’s all.  And I think, there is nothing that can be done to reduce this kind of complexity in lines of code – we simply learn to live with it.

Solution(?):

And I think, using ns-3 within an IDE like Eclipse or QTCreator may hide some of this complexity related to syntax. But, definitely, it also will make a user not to understand what is really happening in a particular line of code.

Or a  brilliant programmer can try to develop a simple intermediate language to represent an ns-3 simulation, and his convertor program may convert that simply readable language into the complex  ns-3 simulation code. (Just Joking – learn ns-3 as it is 🙂 )

Final Note

One may be free to mail me their views on this problem so that I can add a few more points to this article.

The scope of this article is only to make the beginner realize why he/she is having a strange feeling while learning ns-3. This is not for offending the generous developers who are sacrificing their precious time on the development and maintenance of ns-3 – just telling my opinion from my idiotic point of view -that’s all.

References

  1. https://www.nsnam.org/develop/contributing-code/coding-style/
  2. https://www.nsnam.org/releases/ns-3-35/documentation/

Reply/Comments Received at ns-3-users Group

(one may check the original discussion @ ns-3-users Group)

Follow the Opinions and Comments of ns3-users and Developers in green text below

Mr. Gabriel Ferreira  Posted the Following Comments on the ns-3 User Group

Just my opinion on a few points:

> Why ns-3 simulation run faster than most of the simulators?
> The main reason is; the simulation code is not interpreted by any other entity.
As far as I know, other simulators parse the simulation script and schedule a few events, which is exactly what the Python interpreter did with the help of the ns-3 bindings.
The reason simulators are slow include:
1) the compiler and the processor don’t know at compile time nor at runtime which paths will really be taken by each simulation, so their prediction fails more often than normal programs, which results in more branch and cache misses, pipeline stalls, etc;
2) how things are organized in memory can drastically affect performance due to cache collisions and misses, etc.
Even ns-3 has these problems. This is where profile guided optimizations (PGO), link time optimization (LTO),  multi-level JIT, software speculation and other techniques may help.
Regarding trace results: there is work on that front. 
And SEM probably does what you want: https://github.com/signetlabdei/sem
> Config::SetDefault(“ns3::WifiMacQueue::MaxDelay”, TimeValue(Seconds(WifiMacQueueMaxDelay)));
> What restricts the developers to using simple conventions/declarations like the following? In this case, understanding the line and even tracking an error may be an easy task for a human.
> WifiMacQueue->SetMaxDelay=10
> So, from this perspective, an ns-3 simulation script is more friendly towards a machine-readable form. Definitely not friendly towards a human-readable form.
As far as I know you can do it both ways. The first one will make that value the default value for instances created after it is called and the latter will only change for the instance/object that called it.
> And I think, using ns-3 within an IDE like Eclipse or QTCreator may hide some of this complexity.
We are working on that.
>  But, definitely, it also will make a user not to understand what is really happening in a particular line of code.
How so? Some IDEs bring up the docs, expand macros showing the underlying code, highlight orthographic and syntax mistakes, plus additional c++ checks.
It can also help you understand the chain of events as you can click to go to the definition of specific functions. 

Bindings are usually wrappers written in a different language which call a standard API (in the case of ns-3 it is c++). 

The python bindings are doing nothing more than loading the c++ libraries, calling functions (just like any linked program would do), but it needs to translate the compiled types into to something Python can represent and from Python back to the compiled structures to use with the C++ calls. 

These wrappers can be written by hand or be scanned and built (semi-)automatically. 
The current generator being used is pybindgen, which doesn’t support a few features being used, so maintainers need to use workarounds to keep it working. This is what is changing if there isn’t any demand for it. 
I’m working on a replacement for the python based buildsystem (waf). It still needs a lot of testing, some refactoring and updating the documentation, but using IDEs and some other tools will be easier. However, this has nothing to do with the python bindings. 
There’s no python code in the simulator itself, so no reduction in complexity. 
Neither the removal of the python bindings nor the replacement of the buildsystem will affect the simulator performance in any way. 
In the best case scenario, the build phase of the project will be a bit faster. 
On Wed, Nov 24, 2021 at 8:58 AM Charles Pandian <igs…@gmail.com> wrote:

Thank you, Mr. Gabriel for sharing your insights.
It will help me and others to understand ns-3 and bring us a little closer to it.

 Mr Tom Henderson recently posted a news regarding the removal of python bindings .
Could you elaborate what is “removal of Python bindings?”

Is it meaning entire removal of Python? (including the python based build process?)

Will it improve the performance of the simulator and will it reduce some of the python related complexities in the code (I mean, users are trying to learn both and simply wasting their time – of course, before settling with C++ only conventions)

Mr. Tom Henderson Posted the Following Comments on the ns-3 User Group

 

Charles, thanks for your thoughts; some responses inline below.
On 11/23/21 12:39 AM, igs…@gmail.com wrote:

Dear all,
I am trying to make a post/article on “What Makes ns-3 a Complex Thing to Understand and Use? 

The following is the thing that I discussed in that article/post.
(Sorry. I could not format this text here – to see formatted text use the above link)

Please share your insights to improve and incorporate things in that article. I think it may be useful for newcomers to understand ns-3.

Please share your experience so that I may fulfil the scope of that post/article

Charles Pandian
——————————————-
What Makes ns-3 a Complex Thing to Understand and Use? 

Article Written by:  CharlesPandian November 23, 2021 |  Edit This

While starting to learn ns-3, most of us find it very difficult to understand. Particularly, if the student already knows to use ns-2 or Omnet++ then it will even become much harder for him to understand/grasp what ns-3 really is.  The student’s or scholar’s preconceived expectation in a simulator will make him misunderstand ns-3. Another major obstacle/misconception in using ns-3 is the way in which python is frequently used along with C++. (Thank Mr Tom Henderson for recent news regarding the removal of python bindings -because it will reduce some of these obstacles )

Of course, the ns-3 Documentations and Manual pages are providing explanations for each and every aspect of this wonderful simulator. But they are huge and their hugeness itself makes it impossible to grasp the very fine, basic aspects of this simulator.
Often, the developer of ns-3 also generously provide answers to the questions or students/learners of ns-3 through the official ns-3 user group.  Even with this kind of help and support, it still, it makes impossible for someone to learn and understand ns-3.

‘impossible’ is a bit drastic, but I will grant you that it can have a steep learning curve.  My impression is that it is no worse than ns-2, however.

This article tries to explain why it is ambiguously hard to understand ns-3 and an ns-3 simulation (I mean, in most cases, even the student can not express the reason for his poor understanding/misunderstanding on ns-3).

How ns-3 is different from most of the other simulators?

In most of the popular simulators (except ns-3), the simulator will be a different entity and the simulation script that the user will write for that simulator will be a separate entity. While running the simulation script, the simulator will just run/interpret the lines that the user created.

For example,

  • Under ns-2, the simulation will be presented in the form of TCL script and the core simulator which is made up of C++ and TCL objects will simply interpret the lines of the TCL simulation script.

With ns-3, the idea was that Python could take the place of OTcl, but unlike ns-2, it was possible to write directly in C++.  Over time, there hasn’t been much use of the Python API, however.

  • Under Omnet ++, the simulation script will be a custom format text file (not like any programming language) core simulator which is made up of C++ objects will simply interpret the lines of the simulation script.
  • Even most of the non-free simulators are following the same ideology (Simulator is different from simulation script)

Many simulators have a high-level modeling language, and a GUI for simulation composition.  ns-3 did not preclude adding this, but the decision early on was to just code directly into C++, assuming that typical users would need to know C++ anyway to modify or write new models.  A GUI or high-level language could be added on top of ns-3, and it would be very helpful to new users or those less skilled with C++; the problem is that this is a lot of work to develop and maintain.

If a researcher needs to add a new protocol/application agent (for example in the case of ns-2), then they will write code for that protocol/application agent, by adopting the standards of the core simulator and compiling the core simulator itself with the added new protocol/application agent model.  After that, a user can use that new object within their simulations. The simulation script can be modified as per the requirement and can be run without recompiling the core simulator code.

So in other simulators, the simulator will interpret/run the simulation script.

I am not really following how an interpreted vs. compiled script is making things difficult for ns-3.  In any case, we do (at the moment) have Python for this if you want.

So there will be only one “main()” function through which the core simulator starts running and start interpreting/running the simulation script. No other C++ code module will have “main()” function.

The Organization of ns-2 Simulator and an ns-3 SimulationA. The ns-2 Way of Doing Simulation and Analysis

a. The Simulator

The following explains psuedo code explain’s simulator ns-2’s  architecture :
The ns-2 Simulator (made up of C++ and TCL Object)

main() {
//the core simulator
// and some core functionalities
}
OtherProtocolModule1() {
//the protocol module code
}
OtherProtocolModule2() {
//the protocol module code
}


ANewCustomProtocolModule() {
//the protocol module code added by the user/researcher
}

b. The Simulation

A Typical User-level Simulation Code (made up of TCL)

// The simulation script will Use the above ns-2 modules and do the following:

//Initializing some common simulation parameters
//Creating simulation Object
//Initializing event trace logs and nam Trace ouput
//Configuring Nodes and Protocols
//Setting traffic Flows
//Tunning the simulation

c) The Trace Analysis

Trace Analysis is generally done separately using a scripting language (using scripting languages/(advance filters from UNIX perspective) such as tcl, awk, perl, shell etc.,)

A Typical Trace Analysis Script

// Read the even trace output that was generated during the simulation
// Phrase them line by line and get statistics out of it
// prepare tables and graphs using the extracted statistics
So, generally, under ns-2, the simulator is a different entity – so without compiling its code, again and again, a tcl level simulation script can be modified and run several times.

It is not hard to use ns-3 command-line arguments to avoid recompiling the program when conducting a large simulation campaign, though.

Further, as a standard, the trace analysis done by another independent script, it can be run again and again (with little modification during trial and error) without even disturbing or running the simulation code.

The ns-3 Way of Doing Simulation and Analysis

ns-3’s way is entirely different. Here, the simulation script that we write in C++ will itself become a separate simulator because it will have the “main()” function. In other words, each and every simulation script that we write under ns-3 will become a separate simulator. So whenever we need to change a single line in our simulation script (C++ code), then we need to recompile our simulator.

Please keep in mind that the simulator is really a set of shared libraries that are less frequently compiled.  I am not sure that calling every simulation script a separate ‘simulator’ is a helpful way to put it.

a. The Simulation Modules

The following is the way in which the ns-3 modules and other modules can be visualized. Here, there is no module with a main() function. One model can inherit from another and may use the functionalities of another module.

CoreSimulatorModule{
//the core simulator modules
// and some core functionalities
}
OtherProtocolModule1() {
//the protocol module code
// functionalities inherited from other modules
}
OtherProtocolModule2() {
//the protocol module code
// may also contain some minor modification done by a user/researcher
}


ANewCustomProtocolModule() {
//the protocol module code added by the user/researcher
}

b) The Simulation or the Custom Simulator

A Typical ns-3 Simulation Script (made up of ns-3 Standard c++ Code). Here, it is the gate way of start of a ns-3 simulation.

// The simulation script will Use the above ns-3 core modules and other modules and do the following:
main() {
//Initializing some common simulation parameters
//Creating simulation Objects
//Configuring Nodes and Protocols
//Setting traffic Flows
//Initializing different kinds of trace logs and NetAnim Trace ouput
//running the simulation
}
So, after compiling this ns-3 simulation script(C++  code), the compiled output itself will become an independent simulator on its own.  (Omnet++ simulations can also be compiled and used as separate custom simulators – but ns-2 simulation script will always depend on the core simulator and only can be run through that)

c) The Trace Analysis

There are so many standards (non-standards) in doing trace analysis in the case of ns-3.  These standards (non-standards) is another main obstacle in front of a student or researcher that makes it difficult to understand and do research under ns-3.

We have felt that the ‘non-standards’ was a feature, not an obstacle.  There are many choices, some built-in (ascii, pcap, flowmon) and the rest (trace sources, logs) customizable.

One may do trace analysis in the following ways :

1) We can use the default logging functionality of ns-3 protocol agents /models to log different events of simulation in a text file and then do Trace Analysis just like in the case of ns-2. Like analyzing the trace logs separately using a scripting language (using scripting languages/(advance filters from UNIX perspective) such as tcl, awk, perl, shell etc.,). This approach mostly fails or will not be reliable because of the standards (non-standards) in triggering event logs by different ns-3 protocol agents /models. Further, such creation of logs by a particular protocol agent may differ from one ns-3 version to another. (my articles  “Event Trace File Generation in a ns-3 Simulation” and “Trace Analysis of ns-3 Ascii Traces using TraceMetrics Tool – An elementary Trace Analysis Solution for ns-3 are dealing with this kind of tracking and analysis.)

2) We can generate tcpdump format trace outputs while running a simulation, and later we may do trace analysis using tcpdump analysers such as “Wireshark”. This approach also will not be useful in most cases of a scholarly research-level simulation – because, in such cases, the trace analysis should be done on the output trace files of several batch runs of the simulation.  So applying Wireshark based trace analysis on that huge number of separate trace files will become a meaningless operation. So, this kind of approach of trace analysis will be useful in understanding an event from a single run of simulation – for example while teaching something in classroom/lab or finding a critical event that may be causing unexpected behaviour in a simulation.
3) The most reliable way of doing trace analysis on a batch of ns-3 simulations is using the FlowMonitor facility of ns-3. Further, that cal also is done more than one way.
i)  The most often used way is: using FlowMonitor inside the ns-3 simulation, and iterating FlowMonitor::FlowStats with a for loop and calculate and to log throughput, delay etc.,  using different parameters of FlowMonitor::FlowStats. Again, this will need additional scripting to collect and parse output from the logged outputs of several batch runs of the simulation.

ii) Another way using FlowMonitor is: to instruct the FlowMonitor to log all the events in an XML file and we may later do trace analysis on such  XML flow monitor log files. This way is much suitable for doing scholarly research. (my article  ”

Trace Analysis of TCP Flows Under ns-3 MANET/ FANET/ VANET/ WSN Scenario” uses this approach)

iii) There may be some other technique to use FlowMonitor inside a simulation and using the XML file of FlowMonitor outside the simulation – I do not know – the researcher may explore it as per their need of analysis of the ouputs of batch runs of the simulation.

So, what is ns-3 now?

ns-3 is nothing but a collection of C++ objects of Protocols/Application Agents and the simulation core modules. So the separate code of all of these objects of Protocols/Application Agents and the simulation core modules, will not have “main()” function.  So ns-3 is technically a collection of Network Simulation objects – not a simulator by itself.  (please correct me if I am wrong)

ns-3 is a set of simulation libraries that can be linked to many simulation programs that configure the scenario, run the simulation, and perform any necessary post-processing.  I think you can clearly call ns-3 a simulator; I don’t think people would object to that term.

So, simply, the simulation script (the C++ code) that we write will have the main() function, which will be the gateway/starting point of the simulator. So, simply, after compiling our code, using all other referred/used modules of ns-3(including the core simulator modules),  our code itself gets compiled and will become a new simulator. (please correct me if I am wrong)

Technically, what we conventionally call ns-3 is not at all a simulator by itself. The simulation script that we write itself will become a custom simulator. So each and every simulation script that we write will become a separate, custom network simulator. (please correct me if I am wrong)

I’m sorry but I do not really understand the emphasis here on whether or not to call ns-3 or its programs a simulator.

Why ns-3 simulation run faster than most of the simulators?

The main reason is; the simulation code is not interpreted by any other entity. The simulation code itself is the simulator. So it will run at the native speed of the hardware and software – just like other running executable code/process of the operating system.

Another important reason is: While writing the ns-3 simulation script, we will only add the C++ objects of Protocols/Application Agents that are needed for that particular simulation. So, the final compiled version of the simulator (compiled version of our code) will only have the used/referred modules. So, each final compiled version of the simulator (compiled version of our code) will be smaller in size and the size may vary according to the number of used/referred C++ objects of Protocols/Application Agents in each simulation scripts (our main c++ simulation code)

 

I think Gabriel had some feedback on these performance points.

Other obstacles in front of Understanding ns-3

The more advanced way of handling C++ objects/functions/constants/variables makes it even harder to understand or grasp a typical ns-3 simulation model and even a simple ns-3 simulation script.

Even though some of these kinds of advanced C++ conventions are taught during an object-oriented programming classroom, here and there, they are not commonly practised in programming; at least by a student or an amateur programmer.

For example, the following line will set the default WifiMacQueue delay

Config::SetDefault(“ns3::WifiMacQueue::MaxDelay”, TimeValue(Seconds(WifiMacQueueMaxDelay)));

Of course, there may a good reason for doing like this from the Object-Oriented Programming Point of View. But these kinds of long, explicit references in declarations simply make it impossible to grasp what actually we are doing here(and where). Further, if a typo mistake is made anywhere in this line the compiler will raise an error message in a “foreign language” which will not be at all inhuman readable form. It may advise you to use gdb to trace that error – then again the gdb will raise another error message in another “foreign language” which will not also be at all inhuman readable form.  (Please think about a poor learner who is trying to learn ns-3 here).

This is a consequence of the low-level C++ that users need to deal with.  However, most typos are easily deduced and fixed, in my experience.

What restricts the developers to using simple conventions/declarations like the following? In this case, understanding the line and even tracking an error may be an easy task for a human.

WifiMacQueue->MaxDelay=10
or
WifiMacQueue.MaxDelay=10
or even
WifiMacQueue.SetMaxDelay(10)

Of course, this kind of declaration may lead to some errors/problems from an Object-Oriented Programming Point of View.  But will be a more human-understandable way of doing things in a computer programme.

I agree, but as Gabriel pointed out, you can do this with similar syntax already if you just need to change the value on a single queue.   But of course, ’10’ is imprecise, so you need units, and then you need to parse the strings like ‘ms’ that make up the units, and for various reasons we found that it was much more solid to encode time in integers within an ns3::Time class, leading to the use of time objects.  This means that you can, in fact, write:

wifiMacQueue->SetMaxDelay (MilliSeconds (10));

which is close to what you are suggesting.

I think that there is a facility that provides more friendly syntax for the default values, which is the ConfigStore subsystem:

https://www.nsnam.org/docs/release/3.35/manual/html/attributes.html#configstore

To understand it further, I hereby give another example :

An XML way of handling data may be easy for a machine to handle and parse data. But definitely, the same XML format data will not be good for human understanding.

So, from this perspective, an ns-3 simulation script is more friendly towards a machine-readable form. Definitely not friendly towards a human-readable form.

ConfigStore allows formatting attribute values in either XML or text formats.

While developing a huge system like ns-3 using Object-Oriented Programming techniques, the level of abstraction and hierarchy of organizing/doing things should hide the complex things behind the scene from the end-user (the ns-3 simulation writer/student/researcher).  The interfaces that are provided to handle the objects and change the properties of the objects should be human-understandable forms.  But according to my view, from the first day of development itself, the developers ignored this point and now the ns-3 becomes a huge, complex machine only understandable form.

Once I heard that Unix was originally developed by programmers for programmers.

Just like that, I think, ns-3 was developed by brilliant developers for brilliant developers.

I would phrase it as ‘ns-3 was developed by and for power users’; specifically, people who are inclined to do networking research.  That is definitely true.  The idea was that at some point, more could be added on top of the low level, command-line API to make it simpler for more beginning students, and a GUI can be provided, etc.

The other key thing to remember is that ns-3 is fully open source and contribution driven; there is no company behind it.  Therefore, things get done by virtue of what is contributed, not what any maintainer is told to work on.  We are on the verge of adding CMake build system because a contributor (Gabriel) showed up with the patches and perseverance to get it done– no one asked him to do this work (as far as I know).  The main contributors of ns-3 are generally people who work on networking research either in academia or industry.  Therefore, the type of code contributions reflect this, and we acknowledge that it could be easier to use if contributors had more time to focus on usability and more examples, etc.  We also seldom get example programs contributed from the community; we are usually trying to come up with (basic) examples ourselves.

But I think, changing the way ns-3 does these kinds of things can not be altered/rectified now – because, ns-3 become huge with all kinds of these complexities.  Just expressing my feelings/disabilities that’s all.

Solution(?):

And I think, using ns-3 within an IDE like Eclipse or QTCreator may hide some of this complexity. But, definitely, it also will make a user not to understand what is really happening in a particular line of code.

As Gabriel mentioned, this is around the corner once we add CMake support.

(Final Note: My scope is not offending the generous developers who are sacrificing their precious time on the development and maintenance of ns-3 – just telling my  opinion from my idiotic point of view -that’s all)

I take no offense at what you wrote.  In fact, I welcome feedback on the usability of ns-3, and it is a concern of mine– I actually plan to be focusing more on usability once some of my current efforts wrap up.  I wish more people gave us constructive criticism or suggestions for improvements.

– Tom

Ms Yufei Yan Posted the Following Comments on the ns-3 User Group

 

Finally, I’m glad that not only me who thinks NS3 is almost impossible to learn.

To understand every bit of NS3 is impossible in my mind, because it’s just a so huge project and the program is written so well in C++ in terms of efficiency, such that many many modern advanced C++ programing techniques are used. Only in case that you are extremely proficient in C++, you will really have a hard time understanding the underlying architecture and how each module communicates with other. That being said, if you want to implement some new protocols, you will need to spend a really good amount of time.
However, writing some scripts to run simulation with already existing protocols won’t be that intimidating. As long as the modules are already in there, take some time to learn the language and study the examples in the tutorial, 8 of 10 times, you will fine.
That’s just my two cents.

Yes. as mentioned by Yufei Yan, the ns-3 code and its flow is very hard to understand because it is using many modern advanced C++ programming techniques and concepts in its design. I realized the same fact while trying to develop a ‘Simple Mobility Model’ for ns-3. In fact, ns-3 is the only software in which I am seeing the usage of a lot of modern features and concepts of modern C++.

Yufei Yan, thank you for your wonderful comments and feedback.

Charles Pandian

WhatsApp Discuss Through WhatsApp