[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

7.1 Background

As mentioned in the Using the Tracing System section, the whole point of running an ns-3 simulation is to generate output for study. You have two basic strategies to work with in ns-3: using generic pre-defined bulk output mechanisms and parsing their content to extract interesting information; or somehow developing an output mechanism that conveys exactly (and perhaps only) the information wanted.

Using pre-defined bulk output mechanisms has the advantage of not requiring any changes to ns-3, but it does require programming. Often, pcap or NS_LOG output messages are gathered during simulation runs and separately run through scripts that use grep, sed or awk to parse the messages and reduce and transform the data to a manageable form. Programs must be written to do the transformation, so this does not come for free. Of course, if the information of interest in does not exist in any of the pre-defined output mechanisms, this approach fails.

If you need to add some tidbit of information to the pre-defined bulk mechanisms, this can certainly be done; and if you use one of the ns-3 mechanisms, you may get your code added as a contribution.

ns-3 provides another mechanism, called Tracing, that avoids some of the problems inherent in the bulk output mechanisms. It has several important advantages. First, you can reduce the amount of data you have to manage by only tracing the events of interest to you (for large simulations, dumping everything to disk for post-processing can create I/O bottlenecks). Second, if you use this method, you can control the format of the output directly so you avoid the postprocessing step with sed or awk script. If you desire, your output can be formatted directly into a form acceptable by gnuplot, for example. You can add hooks in the core which can then be accessed by other users, but which will produce no information unless explicitly asked to do so. For these reasons, we believe that the ns-3 tracing system is the best way to get information out of a simulation and is also therefore one of the most important mechanisms to understand in ns-3.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

7.1.1 Blunt Instruments

There are many ways to get information out of a program. The most straightforward way is to just directly print the information to the standard output, as in,

  #include <iostream>
  ...
  void
  SomeFunction (void)
  {
    uint32_t x = SOME_INTERESTING_VALUE;
    ...
    std::cout << "The value of x is " << x << std::endl;
    ...
  } 

Nobody is going to prevent you from going deep into the core of ns-3 and adding print statements. This is insanely easy to do and, after all, you have complete control of your own ns-3 branch. This will probably not turn out to be very satisfactory in the long term, though.

As the number of print statements increases in your programs, the task of dealing with the large number of outputs will become more and more complicated. Eventually, you may feel the need to control what information is being printed in some way; perhaps by turning on and off certain categories of prints, or increasing or decreasing the amount of information you want. If you continue down this path you may discover that you have re-implemented the NS_LOG mechanism. In order to avoid that, one of the first things you might consider is using NS_LOG itself.

We mentioned above that one way to get information out of ns-3 is to parse existing NS_LOG output for interesting information. If you discover that some tidbit of information you need is not present in existing log output, you could edit the core of ns-3 and simply add your interesting information to the output stream. Now, this is certainly better than adding your own print statements since it follows ns-3 coding conventions and could potentially be useful to other people as a patch to the existing core.

Let’s pick a random example. If you wanted to add more logging to the ns-3 TCP socket (tcp-socket-impl.cc) you could just add a new message down in the implementation. Notice that in TcpSocketImpl::ProcessAction() there is no log message for the ACK_TX case. You could simply add one, changing the code from:

  bool TcpSocketImpl::ProcessAction (Actions_t a)
  { // These actions do not require a packet or any TCP Headers
    NS_LOG_FUNCTION (this << a);
    switch (a)
    {
      case NO_ACT:
        NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action: NO_ACT");
        break;
      case ACK_TX:
        SendEmptyPacket (TcpHeader::ACK);
        break;
      ...

to add a new NS_LOG_LOGIC in the appropriate case statement:

  bool TcpSocketImpl::ProcessAction (Actions_t a)
  { // These actions do not require a packet or any TCP Headers
    NS_LOG_FUNCTION (this << a);
    switch (a)
    {
      case NO_ACT:
        NS_LOG_LOGIC ("TcpSocketImpl " << this << " Action: NO_ACT");
        break;
      case ACK_TX:
        NS_LOG_LOGIC ("TcpSocketImpl " << this << " Action: ACK_TX");
        SendEmptyPacket (TcpHeader::ACK);
        break;
      ...

This may seem fairly simple and satisfying at first glance, but something to consider is that you will be writing code to add the NS_LOG statement and you will also have to write code (as in grep, sed or awk scripts) to parse the log output in order to isolate your information. This is because even though you have some control over what is output by the logging system, you only have control down to the log component level.

If you are adding code to an existing module, you will also have to live with the output that every other developer has found interesting. You may find that in order to get the small amount of information you need, you may have to wade through huge amounts of extraneous messages that are of no interest to you. You may be forced to save huge log files to disk and process them down to a few lines whenever you want to do anything.

Since there are no guarantees in ns-3 about the stability of NS_LOG output, you may also discover that pieces of log output on which you depend disappear or change between releases. If you depend on the structure of the output, you may find other messages being added or deleted which may affect your parsing code.

For these reasons, we consider prints to std::cout and NS_LOG messages to be quick and dirty ways to get more information out of ns-3.

It is desirable to have a stable facility using stable APIs that allow one to reach into the core system and only get the information required. It is desirable to be able to do this without having to change and recompile the core system. Even better would be a system that notified the user when an item of interest changed or an interesting event happened so the user doesn’t have to actively poke around in the system looking for things.

The ns-3 tracing system is designed to work along those lines and is well-integrated with the Attribute and Config subsystems allowing for relatively simple use scenarios.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]

This document was generated on August 20, 2010 using texi2html 1.82.