From a9b0bc855ad3a5e5cf4c10b256b0be38b080a8bf Mon Sep 17 00:00:00 2001 From: Craig Dowell Date: Tue, 15 Sep 2009 00:05:36 -0700 Subject: [PATCH] add some words about tracing to the manual --- doc/manual/manual.texi | 6 +- doc/manual/tracing.texi | 325 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 329 insertions(+), 2 deletions(-) create mode 100644 doc/manual/tracing.texi diff --git a/doc/manual/manual.texi b/doc/manual/manual.texi index ba1a18a59..6899029b3 100644 --- a/doc/manual/manual.texi +++ b/doc/manual/manual.texi @@ -82,8 +82,9 @@ see @uref{http://www.nsnam.org/docs/manual.pdf}. @menu * Random variables:: * Callbacks:: -* Attributes:: * Object model:: +* Attributes:: +* Tracing:: * RealTime:: * Emulation:: * Packets:: @@ -100,8 +101,9 @@ see @uref{http://www.nsnam.org/docs/manual.pdf}. @include random.texi @include callbacks.texi -@include attributes.texi @include objects.texi +@include attributes.texi +@include tracing.texi @include realtime.texi @include emulation.texi @include packets.texi diff --git a/doc/manual/tracing.texi b/doc/manual/tracing.texi new file mode 100644 index 000000000..d445dfc12 --- /dev/null +++ b/doc/manual/tracing.texi @@ -0,0 +1,325 @@ +@node Tracing +@chapter Tracing + +The tracing subsystem is one of the most important mechansisms to understand in +@command{ns-3}. In most cases, @command{ns-3} users will have a brilliant idea +for some new and improved networking feature. In order to verify that this +idea works, the researcher will make changes to an existing system and then run +experiments to see how the new feature behaves by gathering some form of statistic +that captures the behavior of the feature. + +In other words, the whole point of running a simulation is to generate output for +further study. In @command{ns-3}, the subsystem that enables a researcher to do +this is the tracing subsystem. + +@menu +* Motivation:: +* Overview:: +* Using the Tracing API:: +* Implementation details:: +@end menu + +@node Motivation +@section Motivation + +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 + ... + int main () + { + ... + std::cout << ``The value of x is `` << x << std::endl; + ... + } +@end verbatim + +This is workable in small environments, but as your simulations get more and more +compliated, you end up with more and more prints and the task of parsing and +performing computations on the output begins to get harder and harder. + +Another thing to consider is that every time a new tidbit is needed, the software +core must be edited and another print introduced. There is no standardized way +to control all of this output, so the amount of output tends to grow without +bounds. Eventually, the bandwidth required for simply outputting this information +begins to limit the running time of the simulation. The output files grow to +enormous sizes and parsing them becomes a problem. + +@command{ns-3} provides a simple mechanism for logging and providing some control +over output via @emph{Log Components}, but the level of control is not very fine +grained at all. The logging module is a relatively blunt instrument. + +It is desirable to have a facility that allows one to reach into the core system +and only get the information required 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. + +The @command{ns-3} tracing system is designed to work along those lines and is +well-integrated with the Attribute and Config substems allowing for relatively +simple use scenarios. + +@node Overview +@section Overview + +The tracing subsystem relies heavily on the @code{ns-3} Callback and Attribute +mechanisms. You should read and understand the corresponding sections of the +manual before attempting to understand the tracing system. + +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. Unless +a user connects a trace sink to one of these sources, nothing is output. This +arrangement allows relatively unsophisticated users to attach new types of sinks +to existing tracing sources, without requiring editing and recompiling the core +or models of the simulator. + +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. + +The ``transport protocol'' for this conceptual point-to-multipoint link as an +@code{ns-3} @code{Callback}. + +Recall from the Callback Section that callback facility is a way to allow two +modules in the system to communicate via function calls while at the same time +decoupling the calling function from the called class completely. This is the +same requirement as outlined above for the tracing system. + +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 +held by the trace source. When an interesting event happens, the trace source +invokes its @code{operator()} providing zero or more parameters. This tells +the source to go through its list of callbacks invoking each one in turn. In +this way, the parameter(s) are communicated to the trace sinks, which are just +functions. + +@subsection The Simplest Example + +It will be useful to go walk a quick example just to reinforce what we've said. + +@verbose + #include ``ns3/object.h'' + #include ``ns3/uinteger.h'' + #include ``ns3/traced-value.h'' + #include ``ns3/trace-source-accessor.h'' + + #include + + using namespace ns3; +@end verbose + +The first thing to do is include the required files. As mentioned above, the +trace system makes heavy use of the Object and Attribute systems. The first +two includes bring in the declarations for those systems. The file, +@code{traced-value.h} brings in the required declarations for tracing 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 means is that you will be able to trace changes to an object +made using those operators. + +@verbatim + class MyObject : public Object + { + public: + static TypeId GetTypeId (void) + { + static TypeId tid = TypeId ("MyObject") + .SetParent (Object::GetTypeId ()) + .AddConstructor () + .AddTraceSource ("MyInteger", + "An integer value to trace.", + MakeTraceSourceAccessor (&MyObject::m_myInt)) + ; + return tid; + } + + MyObject () {} + TracedValue m_myInt; + }; +@end verbatim + +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 two important lines of code are the @code{.AddTraceSource} and +the @code{TracedValue} declaration. + +The @code{.AddTraceSource} provides the ``hooks'' used for connecting the trace +source to the outside world. The @code{TracedValue} declaration provides the +infrastructure that overloads the operators above and drives the callback +process. + +@verbatim + void + IntTrace (Int oldValue, Int 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. This function will be called whenever one of the operators of the +@code{TracedValue} is executed. + +@verbatim + int + main (int argc, char *argv[]) + { + Ptr myObject = CreateObject (); + + myObject->TraceConnectWithoutContext ("MyInt", MakeCallback(&IntTrace)); + + myObject->m_myInt = 1234; + } +@end verbatim + +In this snippet, the first thing that needs to be done is to 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. Recall from the Callback section that this creates the +specialized functor responsible for providing the overloaded @code{operator()} +used to ``fire'' the callback. The @code{TraceConnectWithoutContext}, takes +a string parameter that provides the name of the Attribute assigned to the +trace source. 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. + +@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}. + +For example, one might find something that looks like the following in the system +(taken from @code{examples/tcp-large-transfer.cc}) + +@verbatim + void CwndTracer (uint32_t oldval, uint32_t newval) {} + + ... + + Config::ConnectWithoutContext ( + "/NodeList/0/$ns3::TcpL4Protocol/SocketList/0/CongestionWindow", + MakeCallback (&CwndTracer)); +@end verbatim + +This should look very familiar. It is the same thing as the previous example, +except that a static member function of @code{Config} is being called instead of +a method on @code{Object}, and instead of an @code{Attribute} name, a path is +being provided. + +The first thing to do is to read the path backward. The last segment of the path +must be an @code{Attribute} of an @code{Object}. In fact, if you had a pointer to +the @code{Object} that has the @code{Attribute} handy, you could write this just like +the previous example: + +@verbatim + void CwndTracer (uint32_t oldval, uint32_t newval) {} + + ... + + object->TraceConnectWithoutContext ("CongestionWindow", MakeCallback (&CwndTracer)); +@end verbatim + +And it turns out that @code{Config::ConnectWithoutContext} does exactly that. This +function takes a path that represents a chain of @code{Object} pointers and follows +them until it gets to the end of the path and interprets the last segment as an +@code{Attribute} on the last object. + +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/0'' refers to the zeroth node in the list of nodes created by +the simulation. This node is actually a @code{Ptr} and so is a subclass of +an @code{ns3::Object}. + +As described in the Object Model section, @code{ns-3} supports an object aggregation +model. The next path segment begins with the ``$'' character which indicates a +@code{GetObject} call should be made looking for the type that follows. When a +node is initialized by an @code{InternetStackHelper} a number of interfaces are +aggregated to the node. One of these is the TCP level four protocol. The runtime +type of this protocol object is ``ns3::TcpL4Protocol''. When the @code{GetObject} +is executed, it returns a pointer to the object of this type. + +The @code{TcpL4Protocol} class defines an Attribute called ``SocketList'' which is +a list of sockets. Each socket is actually an @code{ns3::Object} with its own +@code{Attributes}. The items in the list of sockets are referred to by index just +as in the NodeList, so ``SocketList/0'' refers to the zeroth socket in the list +of sockets on the zeroth node in the NodeList -- the first node constructed in the +simulation. + +This socket, the type of which turns out to be an @code{ns3::TcpSocketImpl} defines +an attribute called ``CongestionWindow'' which is a @code{TracedValue}. +The @code{Config::ConnectWithoutContext} now does a, + +@verbatim + object->TraceConnectWithoutContext ("CongestionWindow", MakeCallback (&CwndTracer)); +@end verbatim + +using the object pointer from ``SocketList/0'' which makes the connection between +the trace source defined in the socket to the callback -- @code{CwndTracer}. + +Now, whenever a change is made to the @code{TracedValue} representing the +congestion window in the TCP socket, the registered callback will be executed and +the function @code{Cwndtracer} will be called printing out the old and new values +of the TCP congestion window. + +@node Using the Tracing API +@section Using the Tracing API + + There +are three levels of interaction with the tracing system: + +@itemize @bullet +@item Beginning user can easily control which objects are participating in tracing; +@item Intermediate users can extend the tracing system to modify the output format +generated or use existing trace sources in different ways, without modifying the +core of the simulator; +@item Advanced users can modify the simulator core to add new tracing sources and +sinks. + +@node Implementation details +@section Implementation details