Merge with ns-3-dev.
authorSebastien Vincent <vincent@clarinet.u-strasbg.fr>
Fri, 09 Oct 2009 19:44:13 +0200
changeset 5401 2281804d6a02
parent 5400 56737002c3c7 (current diff)
parent 5399 73f6b9cbad86 (diff)
child 5402 b73b6da8ead6
Merge with ns-3-dev.
--- a/doc/main.h	Fri Oct 09 19:31:39 2009 +0200
+++ b/doc/main.h	Fri Oct 09 19:44:13 2009 +0200
@@ -27,9 +27,7 @@
  * ns-3 requires Doxygen version 1.5.4 or greater to fully build all items,
  * although earlier versions of Doxygen will mostly work.
  * 
- * Type "./waf --check" followed by "./waf --doxygen" to build the documentation.
- * There is a program that runs during "./waf --check" that builds pieces of
- * the documentation through introspection.  The doc/ directory contains
+ * Type "./waf doxygen" to build the documentation.  The doc/ directory contains
  * configuration for Doxygen (doxygen.conf and main.txt).  The Doxygen 
  * build process puts html files into the doc/html/ directory, and latex 
  * filex into the doc/latex/ directory.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/tutorial/tracing.texi	Fri Oct 09 19:44:13 2009 +0200
@@ -0,0 +1,1105 @@
+
+@c ============================================================================
+@c Begin document body here
+@c ============================================================================
+
+@c ============================================================================
+@c PART:  The Tracing System
+@c ============================================================================
+@c The below chapters are under the major heading "The Tracing System"
+@c This is similar to the Latex \part command
+@c
+@c ============================================================================
+@c The Tracing System
+@c ============================================================================
+@node The Tracing System
+@chapter The Tracing System
+
+@menu
+* Background::
+@end menu
+
+@c ============================================================================
+@c Background
+@c ============================================================================
+@node Background
+@section Background
+
+As mentioned in the Using the Tracing System section, the whole point of running
+an @code{ns-3} simulation is to generate output for study.  You have two basic 
+strategies to work with in @code{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 mechansims has the advantage of not requiring any
+changes to @code{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 @code{ns-3} mechanisms, 
+you may get your code added as a contribution.
+
+@code{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.  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 @code{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 @command{ns-3}.
+
+@subsection 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,
+
+@verbatim
+  #include <iostream>
+  ...
+  void
+  SomeFunction (void)
+  {
+    uint32_t x = SOME_INTERESTING_VALUE;
+    ...
+    std::cout << "The value of x is " << x << std::endl;
+    ...
+  } 
+@end verbatim
+
+Nobody is going to prevent you from going deep into the core of @code{ns-3} and
+adding print statements.  This is insanely easy to do and, after all, you have 
+complete control of your own @code{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 @code{NS_LOG}
+mechanism.  In order to avoid that, one of the first things you might consider
+is using @code{NS_LOG} itself.
+
+We mentioned above that one way to get information out of @code{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 @code{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 @code{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 
+@code{ns-3} TCP socket (@code{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 @code{ACK_TX} case.  You could simply add one, 
+changing the code from:
+
+@verbatim
+  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;
+      ...
+@end verbatim
+
+to add a new @code{NS_LOG_LOGIC} in the appropriate @code{case} statement:
+
+@verbatim
+  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;
+      ...
+@end verbatim
+
+This may seem fairly simple and satisfying at first glance, but something to
+consider is that you will be writing code to add the @code{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 @code{ns-3} about the stability of @code{NS_LOG}
+messages, 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 @code{std::cout} and NS_LOG messages 
+simple ways to get more information out of @code{ns-3}, but they are really 
+unstable and quite blunt instruments.
+
+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 go poke around in the system looking for things.
+
+The @command{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.
+
+@node Overview
+@section Overview
+
+The ns-3 tracing system is built on the concepts of independent tracing sources
+and tracing sinks; along with a uniform mechanism for connecting sources to sinks.
+
+Trace sources are entities that can signal events that happen in a simulation and 
+provide access to interesting underlying data.  For example, a trace source could
+indicate when a packet is received by a net device and provide access to the 
+packet contents for interested trace sinks.  A trace source might also indicate 
+when an iteresting state change happens in a model.  For example, the congestion
+window of a TCP model is a prime candidate for a trace source.
+
+Trace sources are not useful by themselves; they must be connected to other pieces
+of code that actually do something useful with the information provided by the source.
+The entities that consume trace information are called trace sinks.  Trace sources 
+are generators of events and trace sinks are consumers.  This explicit division 
+allows for large numbers of trace sources to be scattered around the system in 
+places which model authors believe might be useful.  
+
+There can be zero or more consumers of trace events generated by a trace source.  
+One can think of a trace source as a kind of point-to-multipoint information link.  
+Your code looking for trace events from a particular piece of core code could 
+happily coexist with other code doing something entirely different from the same
+information.
+
+Unless a user connects a trace sink to one of these sources, nothing is output.  By
+using the tracing system, both you and other people at the same trace source are 
+getting exactly what they want and only what they want out of the system.  Neither
+of you are impacting any other user by changing what information is output by the 
+system.  If you happen to add a trace source, your work as a good open-source 
+citizen may allow other users to provide new utilities that are perhaps very useful
+overall, without making any changes to the @code{ns-3} core.  
+
+@node A Simple Low-Level Example
+@subsection A Simple Low-Level Example
+
+Let's take a few minutes and walk through a simple tracing example.  We are going
+to need a little background on Callbacks to understand what is happening in the
+example, so we have to take a small detour right away.
+
+@node Callbacks
+@subsubsection Callbacks
+
+The goal of the Callback system in @code{ns-3} is to allow one piece of code to 
+call a function (or method in C++) without any specific inter-module dependency.
+This ultimately means you need some kind of indirection -- you treat the address
+of the called function as a variable.  This variable is called a pointer-to-function
+variable.  The relationship between function and pointer-to-function pointer is 
+really no different that that of object and pointer-to-object.
+
+In C the canonical example of a pointer-to-function is a 
+pointer-to-function-returning-integer (PFI).  For a PFI taking one int parameter,
+this could be declared like,
+
+@verbatim
+  int (*pfi)(int arg) = 0;
+@end verbatim
+
+What you get from this is a variable named simply ``pfi'' that is initialized
+to the value 0.  If you want to initialize this pointer to something meaningful,
+you have to have a function with a matching signature.  In this case, you could
+provide a function that looks like,
+
+@verbatim
+  int MyFunction (int arg) {}
+@end verbatim
+
+If you have this target, you can initialize the variable to point to your
+function:
+
+@verbatim
+  pfi = MyFunction;
+@end verbatim
+
+You can then call MyFunction indirectly using the more suggestive form of
+the call,
+
+@verbatim
+  int result = (*pfi) (1234);
+@end verbatim
+
+This is suggestive since it looks like you are dereferencing the function
+pointer just like you would dereference any pointer.  Typically, however,
+people take advantage of the fact that the compiler knows what is going on
+and will just use a shorter form,
+
+@verbatim
+  int result = pfi (1234);
+@end verbatim
+
+This looks like you are calling a function named ``pfi,'' but the compiler is
+smart enough to know to call through the variable @code{pfi} indirectly to
+the function @code{MyFunction}.
+
+Conceptually, this is almost exactly how the tracing system will work.
+Basically, a trace source @emph{is} a callback.  When a trace sink expresses
+interest in receiving trace events, it adds a Callback to a list of Callbacks
+internally held by the trace source.  When an interesting event happens, the 
+trace source invokes its @code{operator()} providing zero or more parameters.
+The @code{operator()} eventually wanders down into the system and does something
+remarkably like the indirect call you just saw.  It provides zero or more 
+parameters (the call to ``pfi'' above passed one parameter to the target function
+@code{MyFunction}.
+
+The important difference that the tracing system adds is that for each trace
+source there is an internal list of Callbacks.  Instead of just making one 
+indirect call, a trace source may invoke any number of Callbacks.  When a trace
+sink expresses interest in notifications from a trace source, it basically just
+arranges to add its own function to the callback list.
+
+If you are interested in more details about how this is actually arranged in 
+@code{ns-3}, feel free to peruse the Callback section of the manual.
+
+@node Example Code
+@subsubsection Example Code
+
+We have provided some code to implement what is really the simplest example
+of tracing that can be assembled.  You can find this code in the tutorial
+directory as @code{fourth.cc}.  Let's walk through it.
+
+@verbatim
+  /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+  /*
+   * This program is free software; you can redistribute it and/or modify
+   * it under the terms of the GNU General Public License version 2 as
+   * published by the Free Software Foundation;
+   *
+   * This program is distributed in the hope that it will be useful,
+   * but WITHOUT ANY WARRANTY; without even the implied warranty of
+   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   * GNU General Public License for more details.
+   *
+   * You should have received a copy of the GNU General Public License
+   * along with this program; if not, write to the Free Software
+   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+   */
+  
+  #include "ns3/object.h"
+  #include "ns3/uinteger.h"
+  #include "ns3/traced-value.h"
+  #include "ns3/trace-source-accessor.h"
+  
+  #include <iostream>
+  
+  using namespace ns3;
+@end verbatim
+
+Most of this code should be quite familiar to you.  As mentioned above, the
+trace system makes heavy use of the Object and Attribute systems, so you will 
+need to include them.  The first two includes above bring in the declarations
+for those systems explicitly.  You could use the core module header, but this
+illustrates how simple this all really is.  
+
+The file, @code{traced-value.h} brings in the required declarations for tracing
+of data that obeys value semantics.  In general, value semantics just means that
+you can pass the object around, not an address.  In order to use value semantics
+at all you have to have an object with an associated copy constructor and 
+assignment operator available.  We extend the requirements to talk about the set
+of operators that are pre-defined for plain-old-data (POD) types.  Operator=, 
+operator++, operator---, operator+, operator==, etc.
+
+What this all really means is that you will be able to trace changes to a C++
+object made using those operators.
+
+Since the tracing system is integrated with Attributes, and Attributes work
+with Objects, there must be an @command{ns-3} @code{Object} for the trace source
+to live in.  The next code snippet declares and defines a simple Object we can
+work with.
+
+@verbatim
+  class MyObject : public Object
+  {
+  public:
+    static TypeId GetTypeId (void)
+    {
+      static TypeId tid = TypeId ("MyObject")
+        .SetParent (Object::GetTypeId ())
+        .AddConstructor<MyObject> ()
+        .AddTraceSource ("MyInteger",
+                         "An integer value to trace.",
+                         MakeTraceSourceAccessor (&MyObject::m_myInt))
+        ;
+      return tid;
+    }
+    
+    MyObject () {}
+    TracedValue<int32_t> m_myInt;
+  };
+@end verbatim
+
+The two important lines of code, above, with respect to tracing are the 
+@code{.AddTraceSource} and the @code{TracedValue} declaration of @code{m_myInt}.
+
+The @code{.AddTraceSource} provides the ``hooks'' used for connecting the trace
+source to the outside world through the config system.  The @code{TracedValue} 
+declaration provides the infrastructure that overloads the operators mentioned 
+above and drives the callback process.
+
+@verbatim
+  void
+  IntTrace (int32_t oldValue, int32_t newValue)
+  {
+    std::cout << "Traced " << oldValue << " to " << newValue << std::endl;
+  }
+@end verbatim
+
+This is the definition of the trace sink.  It corresponds directly to a callback
+function.  Once it is connected, this function will be called whenever one of the
+overloaded operators of the @code{TracedValue} is executed.
+
+We have now seen the trace source and the trace sink.  What remains is code to
+connect the source to the sink.
+
+@verbatim
+  int
+  main (int argc, char *argv[])
+  {
+    Ptr<MyObject> myObject = CreateObject<MyObject> ();
+    myObject->TraceConnectWithoutContext ("MyInteger", MakeCallback(&IntTrace));
+  
+    myObject->m_myInt = 1234;
+  }
+@end verbatim
+
+Here we first create the Object in which the trace source lives.
+
+The next step, the @code{TraceConnectWithoutContext}, forms the connection
+between the trace source and the trace sink.  Notice the @code{MakeCallback}
+template function.  This function does the magic required to create the
+underlying @code{ns-3} Callback object and associate it with the function
+@code{IntTrace}.  TraceConnect makes the association between your provided
+function and the overloaded @code{operator()} in the traced variable referred 
+to by the ``MyInteger'' Attribute.  After this association is made, the trace
+source will ``fire'' your provided callback function.
+
+The code to make all of this happen is, of course, non-trivial, but the essence
+is that you are arranging for something that looks just like the @code{pfi()}
+example above to be called by the trace source.  The declaration of the 
+@code{TracedValue<int32_t> m_myInt;} in the Object itself performs the magic 
+needed to provide the overloaded operators (++, ---, etc.) that will use the
+@code{operator()} to actually invoke the Callback with the desired parameters.
+The @code{.AddTraceSource} performs the magic to connect the Callback to the 
+Config system, and @code{TraceConnectWithoutContext} performs the magic to
+connect your function to the trace source, which is specified by Attribute
+name.
+
+Let's ignore the bit about context for now.
+
+Finally, the line,
+
+@verbatim
+   myObject->m_myInt = 1234;
+@end verbatim
+
+should be interpreted as an invocation of @code{operator=} on the member 
+variable @code{m_myInt} with the integer @code{1234} passed as a parameter.
+
+It turns out that this operator is defined (by @code{TracedValue}) to execute
+a callback that returns void and takes two integer values as parameters --- 
+an old value and a new value for the integer in question.  That is exactly 
+the function signature for the callback function we provided --- @code{IntTrace}.
+
+To summarize, a trace source is, in essence, a variable that holds a list of
+callbacks.  A trace sink is a function used as the target of a callback.  The
+Attribute and object type information systems are used to provide a way to 
+connect trace sources to trace sinks.  The act of ``hitting'' a trace source
+is executing an operator on the trace source which fires callbacks.  This 
+results in the trace sink callbacks registering interest in the source being 
+called with the parameters provided by the source.
+
+If you now build and run this example,
+
+@verbatim
+  ./waf --run fourth
+@end verbatim
+
+you will see the output from the @code{IntTrace} function execute as soon as the
+trace source is hit:
+
+@verbatim
+  Traced 0 to 1234
+@end verbatim
+
+When we executed the code, @code{myObject->m_myInt = 1234;}, the trace source 
+fired and automatically provided the before and after values to the trace sink.
+The function @code{IntTrace} then printed this to the standard output.  No 
+problem.
+
+@subsection Using the Config Subsystem to Connect to Trace Sources
+
+The @code{TraceConnectWithoutContext} call shown above in the simple example is
+actually very rarely used in the system.  More typically, the @code{Config}
+subsystem is used to allow selecting a trace source in the system using what is
+called a @emph{config path}.  We saw an example of this in the previous section
+where we hooked the ``CourseChange'' event when we were playing with 
+@code{third.cc}.
+
+Recall that we defined a trace sink to print course change information from the
+mobility models of our simulation.  It should now be a lot more clear to you 
+what this function is doing.
+
+@verbatim
+  void
+  CourseChange (std::string context, Ptr<const MobilityModel> model)
+  {
+    Vector position = model->GetPosition ();
+    NS_LOG_UNCOND (context << 
+      " x = " << position.x << ", y = " << position.y);
+  }
+@end verbatim
+
+When we connected the ``CourseChange'' trace source to the above trace sink,
+we used what is called a ``Config Path'' to specify the source when we
+arranged a connection between the pre-defined trace source and the new trace 
+sink:
+
+@verbatim
+  std::ostringstream oss;
+  oss <<
+    "/NodeList/" << wifiStaNodes.Get (nWifi - 1)->GetId () <<
+    "/$ns3::MobilityModel/CourseChange";
+
+  Config::Connect (oss.str (), MakeCallback (&CourseChange));
+@end verbatim
+
+Let's try and make some sense of what is sometimes considered relatively
+mysterious code.  For the purposes of discussion, assume that the node 
+number returned by the @code{GetId()} is ``7''.  In this case, the path
+above turns out to be,
+
+@verbatim
+  "/NodeList/7/$ns3::MobilityModel/CourseChange"
+@end verbatim
+
+The last segment of a config path must be an @code{Attribute} of an 
+@code{Object}.  In fact, if you had a pointer to the @code{Object} that has the
+``CourseChange'' @code{Attribute} handy, you could write this just like we did 
+in the previous example.  You know by now that we typically store pointers to 
+our nodes in a NodeContainer.  In the @code{third.cc} example, the Nodes of
+interest are stored in the @code{wifiStaNodes} NodeContainer.  In fact, while
+putting the path together, we used this container to get a Ptr<Node> which we
+used to call GetId() on.  We could have used this Ptr<Node> directly to call
+a connect method directly:
+
+@verbatim
+  Ptr<Object> theObject = wifiStaNodes.Get (nWifi - 1);
+  theObject->TraceConnectWithoutContext ("CourseChange", MakeCallback (&CourseChange));
+@end verbatim
+
+In the @code{third.cc} example, we actually want an additional ``context'' to 
+be delivered along with the Callback parameters (which will be explained below) so we 
+could actually use the following equivalent code,
+
+@verbatim
+  Ptr<Object> theObject = wifiStaNodes.Get (nWifi - 1);
+  theObject->TraceConnect ("CourseChange", MakeCallback (&CourseChange));
+@end verbatim
+
+It turns out that the internal code for @code{Config::ConnectWithoutContext} and
+@code{Config::Connect} actually do find a Ptr<Object> and call the appropriate
+TraceConnect method at the lowest level.
+
+The @code{Config} functions take a path that represents a chain of @code{Object} 
+pointers.  Each segment of a path corresponds to an Object Attribute.  The last 
+segment is the Attribute of interest, and prior segments must be typed to contain
+or find Objects.  The @code{Config} code parses and ``walks'' this path until it 
+gets to the final segment of the path.  It then interprets the last segment as
+an @code{Attribute} on the last Object it found while walking the path.  The  
+@code{Config} functions then call the appropriate @code{TraceConnect} or 
+@code{TraceConnectWithoutContext} method on the final Object.  Let's see what 
+happens in a bit more detail when the above path is walked.
+
+The leading ``/'' character in the path refers to a so-called namespace.  One 
+of the predefined namespaces in the config system is ``NodeList'' which is a 
+list of all of the nodes in the simulation.  Items in the list are referred to
+by indices into the list, so ``/NodeList/7'' refers to the eighth node in the
+list of nodes created during the simulation.  This reference is actually a 
+@code{Ptr<Node>} and so is a subclass of an @code{ns3::Object}.  
+
+As described in the Object Model section of the @code{ns-3} manual, we support
+Object Aggregation.  This allows us to form an association between different 
+Objects without any programming.  Each Object in an Aggregation can be reached 
+from the other Objects.  
+
+The next path segment being walked begins with the ``$'' character.  This 
+indicates to the config system that a @code{GetObject} call should be made 
+looking for the type that follows.  It turns out that the MobilityHelper used in 
+@code{third.cc} arranges to Aggregate, or associate, a mobility model to each of 
+the wireless Nodes.  When you add the ``$'' you are asking for another Object that
+has presumably been previously aggregated.  You can think of this as switching
+pointers from the original Ptr<Node> as specified by ``/NodeList/7'' to its 
+associated mobility model --- which is of type ``$ns3::MobilityModel''.  If you
+are familiar with @code{GetObject}, we have asked the system to do the following:
+
+@verbatim
+  Ptr<MobilityModel> mobilityModel = node->GetObject<MobilityModel> ()
+@end verbatim
+
+We are now at the last Object in the path, so we turn our attention to the 
+Attributes of that Object.  The @code{MobilityModel} class defines an Attribute 
+called ``CourseChange.''  You can see this by looking at the source code in
+@code{src/mobility/mobility-model.cc} and searching for ``CourseChange'' in your
+favorite editor.  You should find,
+
+@verbatim
+  .AddTraceSource (``CourseChange'',
+                   ``The value of the position and/or velocity vector changed'',
+                   MakeTraceSourceAccessor (&MobilityModel::m_courseChangeTrace))
+@end verbatim
+
+which should look very familiar at this point.  
+
+If you look for the corresponding declaration of the underlying traced variable 
+in @code{mobility-model.h} you will find
+
+@verbatim
+  TracedCallback<Ptr<const MobilityModel> > m_courseChangeTrace;
+@end verbatim
+
+The type declaration @code{TracedCallback} identifies @code{m_courseChangeTrace}
+as a special list of Callbacks that can be hooked using the Config functions 
+described above.
+
+The @code{MobilityModel} class is designed to be a base class providing a common
+interface for all of the specific subclasses.  If you search down to the end of 
+the file, you will see a method defined called @code{NotifyCourseChange()}:
+
+@verbatim
+  void
+  MobilityModel::NotifyCourseChange (void) const
+  {
+    m_courseChangeTrace(this);
+  }
+@end verbatim
+
+Derived classes will call into this method whenever they do a course change to
+support tracing.  This method invokes @code{operator()} on the underlying 
+@code{m_courseChangeTrace}, which will, in turn, invoke all of the registered
+Callbacks, calling all of the trace sinks that have registered interest in the
+trace source by calling a Config function.
+
+So, in the @code{third.cc} example we looked at, whenever a course change is 
+made in one of the @code{RandomWalk2dMobilityModel} instances installed, there
+will be a @code{NotifyCourseChange()} call which calls up into the 
+@code{MobilityModel} base class.  As seen above, this invokes @code{operator()}
+on @code{m_courseChangeTrace}, which in turn, calls any registered trace sinks.
+In the example, the only code registering an interest was the code that provided
+the config path.  Therefore, the @code{CourseChange} function that was hooked 
+from Node number seven will be the only Callback called.
+
+The final piece of the puzzle is the ``context.''  Recall that we saw an output 
+looking something like the following from @code{third.cc}:
+
+@verbatim
+  /NodeList/7/$ns3::MobilityModel/CourseChange x = 7.27897, y = 2.22677
+@end verbatim
+
+The first part of the output is the context.  It is simply the path through
+which the config code located the trace source.  In the case we have been looking at
+there can be any number of trace sources in the system corresponding to any number
+of nodes with mobility models.  There needs to be some way to identify which trace
+source is actually the one that fired the Callback.  An easy way is to request a 
+trace context when you @code{Config::Connect}.
+
+@subsection How to Find and Connect Trace Sources, and Discover Callback Signatures
+
+The first question that inevitably comes up for new users of the Tracing system is,
+``okay, I know that there must be trace sources in the simulation core, but how do
+I find out what trace sources are available to me''?  
+
+The second question is, ``okay, I found a trace source, how do I figure out the
+config path to use when I connect to it''? 
+
+The third question is, ``okay, I found a trace source, how do I figure out what 
+the return type and formal arguments of my callback function need to be''?
+
+The fourth question is, ``okay, I typed that all in and got this incredibly bizarre
+error message, what in the world does it mean''?
+
+@subsection What Trace Sources are Available?
+
+The answer to this question is found in the @code{ns-3} Doxygen.  Go to the 
+@code{ns-3} web site @uref{http://www.nsnam.org/getting_started.html,,``here''}
+and select the ``Doxygen (stable)'' link ``Documentation'' on the navigation
+bar to the left side of the page.  Expand the ``Modules'' book in the NS-3 
+documentation tree a the upper left by clicking the ``+'' box.  Now, expand
+the ``Core'' book in the tree by clicking its ``+'' box.  You should now
+see three extremely useful links:
+
+@itemize @bullet
+@item The list of all trace sources
+@item The list of all attributes
+@item The list of all global values
+@end itemize
+
+The list of interest to us here is ``the list of all trace sources.''  Go 
+ahead and select that link.  You will see, perhaps not too surprisingly, a
+list of all of the trace sources available in the @code{ns-3} core.
+
+As an example, scroll down to @code{ns3::MobilityModel}.  You will find
+an entry for
+
+@verbatim
+  CourseChange: The value of the position and/or velocity vector changed 
+@end verbatim
+
+You should recognize this as the trace source we used in the @code{third.cc}
+example.  Perusing this list will be helpful.
+
+@subsection What String do I use to Connect?
+
+The easiest way to do this is to grep around in the @code{ns-3} codebase for someone
+who has already figured it out,  You should always try to copy someone else's
+working code before you start to write your own.  Try something like:
+
+@verbatim
+  find . -name '*.cc' | xargs grep CourseChange | grep Connect
+@end verbatim
+
+and you may find your answer along with working code.  For example, in this
+case, @code{./ns-3-dev/examples/wireless/mixed-wireless.cc} has something
+just waiting for you to use:
+
+@verbatim
+  Config::Connect (``/NodeList/*/$ns3::MobilityModel/CourseChange'', 
+    MakeCallback (&CourseChangeCallback));
+@end verbatim
+
+If you cannot find any examples in the distribution, you can find this out
+from the @code{ns-3} Doxygen.  It will probably be simplest just to walk 
+through the ``CourseChanged'' example.
+
+Let's assume that you have just found the ``CourseChanged'' trace source in 
+``The list of all trace sources'' and you want to figure out how to connect to
+it.  You know that you are using (again, from the @code{third.cc} example) an
+@code{ns3::RandomWalk2dMobilityModel}.  So open the ``Class List'' book in
+the NS-3 documentation tree by clicking its ``+'' box.  You will now see a
+list of all of the classes in @code{ns-3}.  Scroll down until you see the
+entry for @code{ns3::RandomWalk2dMobilityModel} and follow that link.
+You should now be looking at the ``ns3::RandomWalk2dMobilityModel Class 
+Reference.''
+
+If you now scroll down to the ``Member Function Documentation'' section, you
+will see documentation for the @code{GetTypeId} function.  You constructed one
+of these in the simple tracing example above:
+
+@verbatim
+    static TypeId GetTypeId (void)
+    {
+      static TypeId tid = TypeId ("MyObject")
+        .SetParent (Object::GetTypeId ())
+        .AddConstructor<MyObject> ()
+        .AddTraceSource ("MyInteger",
+                         "An integer value to trace.",
+                         MakeTraceSourceAccessor (&MyObject::m_myInt))
+        ;
+      return tid;
+    }
+@end verbatim
+
+As mentioned above, this is the bit of code that connected the Config 
+and Attribute systems to the underlying trace source.  This is also the
+place where you should start looking for information about the way to 
+connect. 
+
+You are looking at the same information for the RandomWalk2dMobilityModel; and
+the information you want is now right there in front of you in the Doxygen:
+
+@verbatim
+  This object is accessible through the following paths with Config::Set and Config::Connect: 
+
+  /NodeList/[i]/$ns3::MobilityModel/$ns3::RandomWalk2dMobilityModel 
+@end verbatim
+
+The documentation tells you how to get to the @code{RandomWalk2dMobilityModel} 
+Object.  Compare the string above with the string we actually used in the 
+example code:
+
+@verbatim
+  "/NodeList/7/$ns3::MobilityModel"
+@end verbatim
+
+The difference is due to the fact that two @code{GetObject} calls are implied 
+in the string found in the documentation.  The first, for @code{$ns3::MobilityModel}
+will query the aggregation for the base class.  The second implied 
+@code{GetObject} call, for @code{$ns3::RandomWalk2dMobilityModel}, is used to ``cast''
+the base class to the concrete imlementation class.  The documentation shows 
+both of these operations for you.  It turns out that the actual Attribute you are
+going to be looking for is found in the base class as we have seen.
+
+Look further down in the @code{GetTypeId} doxygen.  You will find,
+
+@verbatim
+  No TraceSources defined for this type.
+  TraceSources defined in parent class ns3::MobilityModel:
+
+  CourseChange: The value of the position and/or velocity vector changed 
+  Reimplemented from ns3::MobilityModel
+@end verbatim
+
+This is exactly what you need to know.  The trace source of interest is found in
+@code{ns3::MobilityModel} (which you knew anyway).  The interesting thing this
+bit of Doxygen tells you is that you don't need that extra cast in the config
+path above to get to the concrete class, since the trace source is actually in
+the base class.  Therefore the additional @code{GetObject} is not required and
+you simply use the path:
+
+@verbatim
+  /NodeList/[i]/$ns3::MobilityModel
+@end verbatim
+
+which perfectly matches the example path:
+
+@verbatim
+  /NodeList/7/$ns3::MobilityModel
+@end verbatim
+
+@subsection What Return Value and Formal Arguments?
+
+The easiest way to do this is to grep around in the @code{ns-3} codebase for someone
+who has already figured it out,  You should always try to copy someone else's
+working code.  Try something like:
+
+@verbatim
+  find . -name '*.cc' | xargs grep CourseChange | grep Connect
+@end verbatim
+
+and you may find your answer along with working code.  For example, in this
+case, @code{./ns-3-dev/examples/wireless/mixed-wireless.cc} has something
+just waiting for you to use.  You will find
+
+@verbatim
+  Config::Connect (``/NodeList/*/$ns3::MobilityModel/CourseChange'', 
+    MakeCallback (&CourseChangeCallback));
+@end verbatim
+
+as a result of your grep.  The @code{MakeCallback} should indicate to you that
+there is a callback function there which you can use.  Sure enough, there is:
+
+@verbatim
+  static void
+  CourseChangeCallback (std::string path, Ptr<const MobilityModel> model)
+  {
+    ...
+  }
+@end verbatim
+
+@subsubsection Take my Word for It
+
+If there are no examples to work from, this can be, well, challenging to 
+actually figure out from the source code.
+
+Before embarking on a walkthrough of the code, I'll be kind and just tell you
+a simple way to figure this out:  The return value of your callback will always 
+be void.  The formal parameter list for a @code{TracedCallback} can be found 
+from the template parameter list in the declaration.  Recall that for our
+current example, this is in @code{mobility-model.h}, where we have previously
+found:
+
+@verbatim
+  TracedCallback<Ptr<const MobilityModel> > m_courseChangeTrace;
+@end verbatim
+
+There is a one-to-one correspondence between the template parameter list in 
+the declaration and the formal arguments of the callback function.  Here,
+there is one template parameter, which is a @code{Ptr<const MobilityModel>}.
+This tells you that you need a function that returns void and takes a
+a @code{Ptr<const MobilityModel>}.  For example,
+
+@verbatim
+  void
+  CourseChangeCallback (Ptr<const MobilityModel> model)
+  {
+    ...
+  }
+@end verbatim
+
+That's all you need if you want to @code{Config::ConnectWithoutContext}.  If
+you want a context, you need to @code{Config::Connect} and use a Callback 
+function that takes a string context, then the required argument.
+
+@verbatim
+  void
+  CourseChangeCallback (std::string path, Ptr<const MobilityModel> model)
+  {
+    ...
+  }
+@end verbatim
+
+If you want to ensure that your @code{CourseChangeCallback} is only visible
+in your local file, you can add the keyword @code{static} and come up with:
+
+@verbatim
+  static void
+  CourseChangeCallback (std::string path, Ptr<const MobilityModel> model)
+  {
+    ...
+  }
+@end verbatim
+
+which is exactly what we used in the @code{third.cc} example.
+
+@subsubsection The Hard Way
+
+This section is entirely optional.  It is going to be a bumpy ride, especially
+for those unfamiliar with the details of templates.  However, if you get through
+this, you will have a very good handle on a lot of the @code{ns-3} low level
+idioms.
+
+So, again, let's figure out what signature of callback function is required for
+the ``CourseChange'' Attribute.  This is going to be painful, but you only need
+to do this once.  After you get through this, you will be able to just look at
+a @code{TracedCallback} and understand it.
+
+The first thing we need to look at is the declaration of the trace source.
+Recall that this is in @code{mobility-model.h}, where we have previously
+found:
+
+@verbatim
+  TracedCallback<Ptr<const MobilityModel> > m_courseChangeTrace;
+@end verbatim
+
+This declaration is for a template.  The template parameter is inside the
+angle-brackets, so we are really interested in finding out what that
+@code{TracedCallback<>} is.  If you have absolutely no idea where this might
+be found, grep is your friend.
+
+We are probably going to be interested in some kind of declaration in the 
+@code{ns-3} source, so first change into the @code{src} directory.  Then, 
+we know this declaration is going to have to be in some kind of header file,
+so just grep for it using:
+
+@verbatim
+  find . -name '*.h' | xargs grep TracedCallback
+@end verbatim
+
+You'll see 124 lines fly by (I piped this through wc to see how bad it was).
+Although that may seem like it, that's not really a lot.  Just pipe the output
+through more and start scanning through it.  On the first page, you will see
+some very suspiciously template-looking stuff.
+
+@verbatim
+  TracedCallback<T1,T2,T3,T4,T5,T6,T7,T8>::TracedCallback ()
+  TracedCallback<T1,T2,T3,T4,T5,T6,T7,T8>::ConnectWithoutContext (c ...
+  TracedCallback<T1,T2,T3,T4,T5,T6,T7,T8>::Connect (const CallbackB ...
+  TracedCallback<T1,T2,T3,T4,T5,T6,T7,T8>::DisconnectWithoutContext ...
+  TracedCallback<T1,T2,T3,T4,T5,T6,T7,T8>::Disconnect (const Callba ...
+  TracedCallback<T1,T2,T3,T4,T5,T6,T7,T8>::operator() (void) const ...
+  TracedCallback<T1,T2,T3,T4,T5,T6,T7,T8>::operator() (T1 a1) const ...
+  TracedCallback<T1,T2,T3,T4,T5,T6,T7,T8>::operator() (T1 a1, T2 a2 ...
+  TracedCallback<T1,T2,T3,T4,T5,T6,T7,T8>::operator() (T1 a1, T2 a2 ...
+  TracedCallback<T1,T2,T3,T4,T5,T6,T7,T8>::operator() (T1 a1, T2 a2 ...
+  TracedCallback<T1,T2,T3,T4,T5,T6,T7,T8>::operator() (T1 a1, T2 a2 ...
+  TracedCallback<T1,T2,T3,T4,T5,T6,T7,T8>::operator() (T1 a1, T2 a2 ...
+  TracedCallback<T1,T2,T3,T4,T5,T6,T7,T8>::operator() (T1 a1, T2 a2 ...
+@end verbatim
+
+It turns out that all of this comes from the header file 
+@code{traced-callback.h} which sounds very promising.  You can then take a
+look at @code{mobility-model.h} and see that there is a line which confirms
+this hunch:
+
+@verbatim
+  #include "ns3/traced-callback.h"
+@end verbatim
+
+Of course, you could have gone at this from the other direction and started
+by looking at the includes in @code{mobility-model.h} and noticing the 
+include of @code{traced-callback.h} and inferring that this must be the file
+you want.
+
+In either case, the next step is to take a look at @code{src/core/traced-callback.h}
+in your favorite editor to see what is happening.
+
+You will see a comment at the top of the file that should be comforting:
+
+@verbatim
+  An ns3::TracedCallback has almost exactly the same API as a normal ns3::Callback but
+  instead of forwarding calls to a single function (as an ns3::Callback normally does),
+  it forwards calls to a chain of ns3::Callback.
+@end verbatim
+
+This should sound very familiar and let you know you are on the right track.
+
+Just after this comment, you will find,
+
+@verbatim
+  template<typename T1 = empty, typename T2 = empty, 
+           typename T3 = empty, typename T4 = empty,
+           typename T5 = empty, typename T6 = empty,
+           typename T7 = empty, typename T8 = empty>
+  class TracedCallback 
+  {
+    ...
+@end verbatim
+
+This tells you that TracedCallback is a templated class.  It has eight possible
+type parameters with default values.  Go back and compare this with the 
+declaration you are trying to understand:
+
+@verbatim
+  TracedCallback<Ptr<const MobilityModel> > m_courseChangeTrace;
+@end verbatim
+
+The @code{typename T1} in the templated class declaration corresponds to the 
+@code{Ptr<const MobilityModel>} in the declaration above.  All of the other
+type parameters are left as defaults.  Looking at the constructor really
+doesn't tell you much.  The one place where you have seen a connection made
+between your Callback function and the tracing system is in the @code{Connect}
+and @code{ConnectWithoutContext} functions.  If you scroll down, you will see
+a @code{ConnectWithoutContext} method here:
+
+@verbatim
+  template<typename T1, typename T2, 
+           typename T3, typename T4,
+           typename T5, typename T6,
+           typename T7, typename T8>
+  void 
+  TracedCallback<T1,T2,T3,T4,T5,T6,T7,T8>::ConnectWithoutContext ...
+  {
+    Callback<void,T1,T2,T3,T4,T5,T6,T7,T8> cb;
+    cb.Assign (callback);
+    m_callbackList.push_back (cb);
+  }
+@end verbatim
+
+You are now in the belly of the beast.  When the template is instantiated for
+the declaration above, the compiler will replace @code{T1} with 
+@code{Ptr<const MobilityModel>}.  
+
+@verbatim
+  void 
+  TracedCallback<Ptr<const MobilityModel>::ConnectWithoutContext ... cb
+  {
+    Callback<void, Ptr<const MobilityModel> > cb;
+    cb.Assign (callback);
+    m_callbackList.push_back (cb);
+  }
+@end verbatim
+
+You can now see the implementation of everything we've been talking about.  The
+code creates a Callback of the right type and assigns your function to it.  This
+is the equivalent of the @code{pfi = MyFunction} we discussed at the start of
+this section.  The code then adds the Callback to the list of Callbacks for 
+this source.  The only thing left is to look at the definition of Callback.
+Using the same grep trick as we used to find @code{TracedCallback}, you will be
+able to find that the file @code{./core/callback.h} is the one we need to look at.
+
+If you look down through the file, you will see a lot of probably almost
+incomprehensible template code.  You will eventually come to some Doxygen for
+the Callback template class, though.  Fortunately, there is some English:
+
+@verbatim
+  This class template implements the Functor Design Pattern.
+  It is used to declare the type of a Callback:
+   - the first non-optional template argument represents
+     the return type of the callback.
+   - the second optional template argument represents
+     the type of the first argument to the callback.
+   - the third optional template argument represents
+     the type of the second argument to the callback.
+   - the fourth optional template argument represents
+     the type of the third argument to the callback.
+   - the fifth optional template argument represents
+     the type of the fourth argument to the callback.
+   - the sixth optional template argument represents
+     the type of the fifth argument to the callback.
+@end verbatim
+
+We are trying to figure out what the
+
+@verbatim
+    Callback<void, Ptr<const MobilityModel> > cb;
+@end verbatim
+
+declaration means.  Now we are in a position to understand that the first
+(non-optional) parameter, @code{void}, represents the return type of the 
+Callback.  The second (non-optional) parameter, @code{Ptr<const MobilityModel>} 
+represents the first argument to the callback.
+
+The Callback in question is your function to receive the trace events.  From
+this you can infer that you need a function that returns @code{void} and takes
+a @code{Ptr<const MobilityModel>}.  For example,
+
+@verbatim
+  void
+  CourseChangeCallback (Ptr<const MobilityModel> model)
+  {
+    ...
+  }
+@end verbatim
+
+That's all you need if you want to @code{Config::ConnectWithoutContext}.  If
+you want a context, you need to @code{Config::Connect} and use a Callback 
+function that takes a string context.  This is because the @code{Connect}
+function will provide the context for you.  You'll need:
+
+@verbatim
+  void
+  CourseChangeCallback (std::string path, Ptr<const MobilityModel> model)
+  {
+    ...
+  }
+@end verbatim
+
+If you want to ensure that your @code{CourseChangeCallback} is only visible
+in your local file, you can add the keyword @code{static} and come up with:
+
+@verbatim
+  static void
+  CourseChangeCallback (std::string path, Ptr<const MobilityModel> model)
+  {
+    ...
+  }
+@end verbatim
+
+which is exactly what we used in the @code{third.cc} example.  Perhaps you
+should now go back and reread the previous section (Take My Word for It).
+
+If you are interested in more details regarding the implementation of 
+Callbacks, feel free to take a look at the @code{ns-3} manual.  They are one
+of the most frequently used constructs in the low-level parts of @code{ns-3}.
+It is, in my opinion, a quite elegant thing.
+
+
+
+
+
+
+
+
--- a/doc/tutorial/tutorial.texi	Fri Oct 09 19:31:39 2009 +0200
+++ b/doc/tutorial/tutorial.texi	Fri Oct 09 19:44:13 2009 +0200
@@ -84,6 +84,7 @@
 * Conceptual Overview::
 * Tweaking ns-3::
 * Building Topologies::
+* The Tracing System::
 @end menu
 
 @include introduction.texi
--- a/src/common/pcap-file-test-suite.cc	Fri Oct 09 19:31:39 2009 +0200
+++ b/src/common/pcap-file-test-suite.cc	Fri Oct 09 19:44:13 2009 +0200
@@ -18,6 +18,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <sstream>
+#include <cstring>
 
 #include "ns3/test.h"
 #include "ns3/pcap-file.h"
@@ -175,6 +176,7 @@
   // data.
   //
   uint8_t buffer[128];
+  memset(buffer, 0, sizeof(buffer));
   err = f.Write (0, 0, buffer, 128);
   NS_TEST_ASSERT_MSG_EQ (err, false, "Write (write-only-file " << m_testFilename << ") returns error");
 
@@ -370,6 +372,7 @@
   // We should be able to write to it since it was opened in "a" mode.
   //
   uint8_t buffer[128];
+  memset(buffer, 0, sizeof(buffer));
   err = f.Write (0, 0, buffer, 128);
   NS_TEST_ASSERT_MSG_EQ (err, false, "Write (append-mode-file " << m_testFilename << ") returns error");
 
--- a/src/helper/application-container.h	Fri Oct 09 19:31:39 2009 +0200
+++ b/src/helper/application-container.h	Fri Oct 09 19:44:13 2009 +0200
@@ -157,7 +157,7 @@
    * \brief Append the contents of another ApplicationContainer to the end of
    * this container.
    *
-   * \param The ApplicationContainer to append.
+   * \param other The ApplicationContainer to append.
    */
   void Add (ApplicationContainer other);
 
@@ -202,9 +202,9 @@
    * down and stop doing their thing (Stop) at a common time.
    *
    * This method simply iterates through the contained Applications and calls
-   * their Start() methods with the provided Time.
+   * their Stop() methods with the provided Time.
    *
-   * \param start The Time at which each of the applications should start.
+   * \param stop The Time at which each of the applications should stop.
    */
   void Stop (Time stop);
 
--- a/src/helper/dot11s-installer.h	Fri Oct 09 19:31:39 2009 +0200
+++ b/src/helper/dot11s-installer.h	Fri Oct 09 19:44:13 2009 +0200
@@ -54,7 +54,7 @@
 
   /**
    * \brief Install an 802.11s stack.
-   * \param The Ptr<MeshPointDevice> to use when setting up the PMP.
+   * \param mp The Ptr<MeshPointDevice> to use when setting up the PMP.
    */
   bool InstallStack (Ptr<MeshPointDevice> mp);
  
--- a/src/helper/flame-installer.h	Fri Oct 09 19:31:39 2009 +0200
+++ b/src/helper/flame-installer.h	Fri Oct 09 19:44:13 2009 +0200
@@ -58,7 +58,7 @@
   
   /**
    * \brief Install a flame stack on the given MeshPointDevice
-   * \param The Ptr<MeshPointDevice> to use.
+   * \param mp The Ptr<MeshPointDevice> to use.
    */
   bool InstallStack (Ptr<MeshPointDevice> mp);
 
--- a/src/helper/flow-monitor-helper.h	Fri Oct 09 19:31:39 2009 +0200
+++ b/src/helper/flow-monitor-helper.h	Fri Oct 09 19:44:13 2009 +0200
@@ -46,7 +46,7 @@
   /// \param nodes A NodeContainer holding the set of nodes to work with.
   Ptr<FlowMonitor> Install (NodeContainer nodes);
   /// \brief Enable flow monitoring on a single node
-  /// \param nodes A Ptr<Node> to the node on which to enable flow monitoring.
+  /// \param node A Ptr<Node> to the node on which to enable flow monitoring.
   Ptr<FlowMonitor> Install (Ptr<Node> node);
   /// \brief Enable flow monitoring on all nodes
   Ptr<FlowMonitor> InstallAll ();
--- a/src/helper/ipv4-interface-container.h	Fri Oct 09 19:31:39 2009 +0200
+++ b/src/helper/ipv4-interface-container.h	Fri Oct 09 19:44:13 2009 +0200
@@ -79,12 +79,11 @@
    * Manually add an entry to the container consisting of a previously composed 
    * entry std::pair.
    *
-   * \param ipv4 pointer to Ipv4 object
-   * \param interface interface index of the Ipv4Interface to add to the container
+   * \param ipInterfacePair the pair of a pointer to Ipv4 object and interface index of the Ipv4Interface to add to the container
    *
    * @see Ipv4InterfaceContainer
    */
-  void Add (std::pair<Ptr<Ipv4>, uint32_t>);
+  void Add (std::pair<Ptr<Ipv4>, uint32_t> ipInterfacePair);
 
   /**
    * Manually add an entry to the container consisting of the individual parts
--- a/src/helper/net-device-container.h	Fri Oct 09 19:31:39 2009 +0200
+++ b/src/helper/net-device-container.h	Fri Oct 09 19:44:13 2009 +0200
@@ -175,14 +175,14 @@
    * \brief Append the contents of another NetDeviceContainer to the end of
    * this container.
    *
-   * \param The NetDeviceContainer to append.
+   * \param other The NetDeviceContainer to append.
    */
   void Add (NetDeviceContainer other);
 
   /**
    * \brief Append a single Ptr<NetDevice> to this container.
    *
-   * \param application The Ptr<NetDevice> to append.
+   * \param device The Ptr<NetDevice> to append.
    */
   void Add (Ptr<NetDevice> device);
 
@@ -190,7 +190,7 @@
    * \brief Append to this container the single Ptr<NetDevice> referred to
    * via its object name service registered name.
    *
-   * \param name The name of the NetDevice Object to add to the container.
+   * \param deviceName The name of the NetDevice Object to add to the container.
    */
   void Add (std::string deviceName);
 
--- a/src/helper/node-container.h	Fri Oct 09 19:31:39 2009 +0200
+++ b/src/helper/node-container.h	Fri Oct 09 19:44:13 2009 +0200
@@ -58,7 +58,7 @@
    * instantiated and assigned a name using the Object Name Service.  This 
    * Node is then specified by its assigned name. 
    *
-   * \param name The name of the Node Object to add to the container.
+   * \param nodeName The name of the Node Object to add to the container.
    */
   NodeContainer (std::string nodeName);
 
@@ -240,7 +240,7 @@
    * \brief Append the contents of another NodeContainer to the end of
    * this container.
    *
-   * \param The NodeContainer to append.
+   * \param other The NodeContainer to append.
    */
   void Add (NodeContainer other);
 
--- a/src/helper/udp-echo-helper.h	Fri Oct 09 19:31:39 2009 +0200
+++ b/src/helper/udp-echo-helper.h	Fri Oct 09 19:44:13 2009 +0200
@@ -121,7 +121,7 @@
    * packet (what is sent as data to the server) to the contents of the fill
    * string (including the trailing zero terminator).
    *
-   * \warn The size of resulting echo packets will be automatically adjusted
+   * \warning The size of resulting echo packets will be automatically adjusted
    * to reflect the size of the fill string -- this means that the PacketSize
    * attribute may be changed as a result of this call.
    *
@@ -137,7 +137,7 @@
    *
    * The fill byte will be used to initialize the contents of the data packet.
    * 
-   * \warn The size of resulting echo packets will be automatically adjusted
+   * \warning The size of resulting echo packets will be automatically adjusted
    * to reflect the dataLength parameter -- this means that the PacketSize
    * attribute may be changed as a result of this call.
    *
@@ -156,7 +156,7 @@
    * by providing a complete buffer with fillLength set to your desired 
    * dataLength
    *
-   * \warn The size of resulting echo packets will be automatically adjusted
+   * \warning The size of resulting echo packets will be automatically adjusted
    * to reflect the dataLength parameter -- this means that the PacketSize
    * attribute of the Application may be changed as a result of this call.
    *
@@ -183,7 +183,7 @@
    * is provided as a string name of a Node that has been previously 
    * associated using the Object Name Service.
    *
-   * \param node The name of the node on which to create the UdpEchoClientApplication
+   * \param nodeName The name of the node on which to create the UdpEchoClientApplication
    *
    * \returns An ApplicationContainer that holds a Ptr<Application> to the 
    *          application created
--- a/src/simulator/cairo-wideint-private.h	Fri Oct 09 19:31:39 2009 +0200
+++ b/src/simulator/cairo-wideint-private.h	Fri Oct 09 19:44:13 2009 +0200
@@ -36,10 +36,12 @@
 #define cairo_private 
 #define HAVE_UINT64_T 1
 
-/*for compatibility with MacOS*/
+/*for compatibility with MacOS and Cygwin*/
 #ifndef HAVE_STDINT_H
 #ifdef __APPLE__
 #define HAVE_STDINT_H 1
+#elif defined(WIN32)
+#define HAVE_STDINT_H 1
 #endif
 #endif
 
--- a/test.py	Fri Oct 09 19:31:39 2009 +0200
+++ b/test.py	Fri Oct 09 19:44:13 2009 +0200
@@ -119,6 +119,7 @@
     ("tutorial/hello-simulator", "True"),
     ("tutorial/second", "True"),
     ("tutorial/third", "True"),
+    ("tutorial/fourth", "True"),
 
     ("udp/udp-echo", "True"),
 
--- a/wscript	Fri Oct 09 19:31:39 2009 +0200
+++ b/wscript	Fri Oct 09 19:44:13 2009 +0200
@@ -137,16 +137,6 @@
                    action="store_true", default=False,
                    dest='lcov_report')
 
-    opt.add_option('--doxygen',
-                   help=('Run doxygen to generate html documentation from source comments'),
-                   action="store_true", default=False,
-                   dest='doxygen')
-    opt.add_option('--doxygen-no-build',
-                   help=('Run doxygen to generate html documentation from source comments, '
-                         'but do not wait for ns-3 to finish the full build.'),
-                   action="store_true", default=False,
-                   dest='doxygen_no_build')
-
     opt.add_option('--run',
                    help=('Run a locally built program; argument can be a program name,'
                          ' or a command starting with the program name.'),
@@ -590,25 +580,12 @@
             raise Utils.WafError("Cannot run regression tests: building the ns-3 examples is not enabled"
                                  " (regression tests are based on examples)")
 
-#    if Options.options.check:
-#        Options.options.compile_targets += ',run-tests'
-#        if env['ENABLE_PYTHON_BINDINGS']:
-#            Options.options.compile_targets += ',ns3module,pybindgen-command'
-#        _run_check(bld)
-
-    if Options.options.doxygen_no_build:
-        doxygen()
-        raise SystemExit(0)
-
 def shutdown(ctx):
     bld = wutils.bld
     if wutils.bld is None:
         return
     env = bld.env
 
-    #if Options.commands['check']:
-    #    _run_waf_check()
-
     if Options.options.lcov_report:
         lcov_report()
 
@@ -626,25 +603,14 @@
     if Options.options.check:
         raise Utils.WafError("Please run `./test.py' now, instead of `./waf --check'")
 
-    if Options.options.doxygen:
-        doxygen()
-        raise SystemExit(0)
-
     check_shell(bld)
 
-    if Options.options.doxygen:
-        doxygen()
-        raise SystemExit(0)
-
-
 check_context = Build.BuildContext
 
 def check(bld):
     """run the equivalent of the old ns-3 unit tests using test.py"""
-    bld = wutils.bld
-    env = bld.env
-    wutils.run_python_program("test.py -c core", env)
-
+    env = wutils.bld.env
+    wutils.run_python_program("test.py -n -c core", env)
 
 class print_introspected_doxygen_task(Task.TaskBase):
     after = 'cc cxx cc_link cxx_link'
@@ -696,111 +662,6 @@
         wutils.run_argv([self.bld.env['PYTHON'], os.path.join("..", "utils", "python-unit-tests.py")],
                         self.bld.env, proc_env, force_no_valgrind=True)
 
-#class run_a_unit_test_task(Task.TaskBase):
-#    after = 'cc cxx cc_link cxx_link'
-#    color = 'BLUE'
-#
-#    def __init__(self, bld, name_of_test):
-#        self.bld = bld
-#        super(run_a_unit_test_task, self).__init__(generator=self)
-#        self.name_of_test = name_of_test
-#        try:
-#            program_obj = wutils.find_program("run-tests", self.bld.env)
-#        except ValueError, ex:
-#            raise Utils.WafError(str(ex))
-#        program_node = program_obj.path.find_or_declare(ccroot.get_target_name(program_obj))
-#        self.program_path = program_node.abspath(self.bld.env)
-#
-#    def __str__(self):
-#        return 'run-unit-test(%s)\n' % self.name_of_test
-#
-#    def runnable_status(self):
-#        return Task.RUN_ME
-#
-#    def run(self):
-#        #print repr([self.program_path, self.name_of_test])
-#        try:
-#            self.retval = wutils.run_argv([self.program_path, self.name_of_test], self.bld.env)
-#        except Utils.WafError:
-#            self.retval = 1
-#        #print "running test %s: exit with %i" % (self.name_of_test, retval)
-#        return 0
-#
-#class get_list_of_unit_tests_task(Task.TaskBase):
-#    after = 'cc cxx cc_link cxx_link'
-#    color = 'BLUE'
-#
-#    def __init__(self, bld):
-#        self.bld = bld
-#        super(get_list_of_unit_tests_task, self).__init__(generator=self)
-#        self.tests = []
-#
-#    def __str__(self):
-#        return 'get-unit-tests-list\n'
-#
-#    def runnable_status(self):
-#        return Task.RUN_ME
-#
-#    def run(self):
-#        try:
-#            program_obj = wutils.find_program("run-tests", self.bld.env)
-#        except ValueError, ex:
-#            raise Utils.WafError(str(ex))
-#        program_node = program_obj.path.find_or_declare(ccroot.get_target_name(program_obj))
-#        program_path = program_node.abspath(self.bld.env)
-#        proc = subprocess.Popen([program_path, "--ListTests"], stdout=subprocess.PIPE,
-#                                env=wutils.get_proc_env())
-#        self.tests = [l.rstrip() for l in proc.stdout.readlines()]
-#        retval = proc.wait()
-#        if retval:
-#            return retval
-#        test_tasks = []
-#        for name_of_test in self.tests:
-#            test_tasks.append(run_a_unit_test_task(self.bld, name_of_test))
-#        collector = collect_unit_test_results_task(self.bld, list(test_tasks))
-#        collector.run_after = list(test_tasks)
-#        self.more_tasks = [collector] + test_tasks
-#        
-#
-#class collect_unit_test_results_task(Task.TaskBase):
-#    after = 'run_a_unit_test_task'
-#    color = 'BLUE'
-#
-#    def __init__(self, bld, test_tasks):
-#        self.bld = bld
-#        super(collect_unit_test_results_task, self).__init__(generator=self)
-#        self.test_tasks = test_tasks
-#
-#    def __str__(self):
-#        return 'collect-unit-tests-results\n'
-#
-#    def runnable_status(self):
-#        for t in self.run_after:
-#            if not t.hasrun:
-#                return Task.ASK_LATER
-#        return Task.RUN_ME
-#
-#    def run(self):
-#        failed_tasks = []
-#        for task in self.test_tasks:
-#            if task.retval:
-#                failed_tasks.append(task)
-#        if failed_tasks:
-#            print "C++ UNIT TESTS: %i tests passed, %i failed (%s)." % \
-#                (len(self.test_tasks) - len(failed_tasks), len(failed_tasks),
-#                 ', '.join(t.name_of_test for t in failed_tasks))
-#            return 1
-#        else:
-#            print "C++ UNIT TESTS: all %i tests passed." % (len(self.test_tasks),)
-#            return 0
-#
-#
-#def _run_check(bld):
-#    task = get_list_of_unit_tests_task(bld)
-#    print_introspected_doxygen_task(bld)
-#    if bld.env['ENABLE_PYTHON_BINDINGS']:
-#        run_python_unit_tests_task(bld)
-
 def check_shell(bld):
     if 'NS3_MODULE_PATH' not in os.environ:
         return
@@ -835,11 +696,26 @@
     env = wutils.bld.env
     wutils.run_argv([shell], env, {'NS3_MODULE_PATH': os.pathsep.join(env['NS3_MODULE_PATH'])})
 
-def doxygen():
-    if not os.path.exists('doc/introspected-doxygen.h'):
-        Logs.warn("doc/introspected-doxygen.h does not exist; run waf check to generate it.")
+def doxygen(bld):
+    """do a full build, generate the introspected doxygen and then the doxygen"""
+    Scripting.build(bld)
+    env = wutils.bld.env
+    proc_env = wutils.get_proc_env()
 
-    ## run doxygen
+    try:
+        program_obj = wutils.find_program('print-introspected-doxygen', env)
+    except ValueError: 
+        Logs.warn("print-introspected-doxygen does not exist")
+        raise SystemExit(1)
+        return
+
+    prog = program_obj.path.find_or_declare(ccroot.get_target_name(program_obj)).abspath(env)
+    out = open(os.path.join('doc', 'introspected-doxygen.h'), 'w')
+
+    if subprocess.Popen([prog], stdout=out, env=proc_env).wait():
+        raise SystemExit(1)
+    out.close()
+
     doxygen_config = os.path.join('doc', 'doxygen.conf')
     if subprocess.Popen(['doxygen', doxygen_config]).wait():
         raise SystemExit(1)
@@ -876,9 +752,6 @@
     finally:
         os.chdir("..")
 
-
-
-
 ##
 ## The default WAF DistDir implementation is rather slow, because it
 ## first copies everything and only later removes unwanted files and