cleaning up tutorial

This commit is contained in:
Craig Dowell
2008-06-29 22:14:22 -07:00
parent df2984b28c
commit 2f840a4f54
2 changed files with 189 additions and 180 deletions

View File

@@ -11,7 +11,7 @@
@menu
* Key Abstractions::
* A First ns-3 script
* A First ns-3 script::
@end menu
The first thing we need to do before actually starting to look at or write

View File

@@ -28,25 +28,25 @@
@section Using the Logging Module
@cindex logging
We have already taken a brief look at the ns-3 logging module while going
over the @code{first.cc} script. We will now take a closer look and see what
kind of use-cases the logging subsystem was designed to cover.
We have already taken a brief look at the @command{ns-3} logging module while
going over the @code{first.cc} script. We will now take a closer look and
see what kind of use-cases the logging subsystem was designed to cover.
@node Logging Overview
@subsection Logging Overview
Many large systems support some kind of message logging facility, and ns-3
is not an exception. In some cases, only error messages are logged to the
``operator console'' (which is typically @code{stderr} in Unix-based systems).
In other systems, warning messages may be output as well as more detailed
informational messages. In some cases, logging facilities are used to output
debug messages which can quickly turn the output into a blur.
Many large systems support some kind of message logging facility, and
@command{ns-3} is not an exception. In some cases, only error messages are
logged to the ``operator console'' (which is typically @code{stderr} in Unix-
based systems). In other systems, warning messages may be output as well as
more detailed informational messages. In some cases, logging facilities are
used to output debug messages which can quickly turn the output into a blur.
ns-3 takes the view that all of these verbosity levels are useful and se
provides a selectable, multi-level approach to message logging. Logging can
be disabled completely, enabled on a component-by-component basis, enabled
globally and has selectable verbosity levels. The ns-3 log module provides
a straightforward, relatively easy to use way to get some kinds of information
out of your simulation.
@command{Ns-3} takes the view that all of these verbosity levels are useful
and we provide a selectable, multi-level approach to message logging. Logging
can be disabled completely, enabled on a component-by-component basis, enabled
globally and has selectable verbosity levels. The @command{ns-3} log module
provides a straightforward, relatively easy to use way to get some kinds of
information out of your simulation.
You should understand that we do provide a general purpose mechanism ---
tracing --- to get data out of your models which should be preferred for
@@ -64,7 +64,7 @@ defined in the system.
@item NS_LOG_DEBUG --- Log relatively rare, ad-hoc debugging messages;
@item NS_LOG_INFO --- Log informational messages about program progress;
@item NS_LOG_FUNCTION --- Log a message describing each function called;
@item NS_LOG_LOGIC -- Log messages describing logical flow in a function;
@item NS_LOG_LOGIC -- Log messages describing logical flow within a function;
@item NS_LOG_ALL --- Log everything.
@end itemize
@@ -72,13 +72,14 @@ We also provide an unconditional logging level that is always displayed,
irrespective of logging levels or component selection.
@itemize @bullet
NS_LOG_UNCOND -- Log the associated message unconditionally.
@item NS_LOG_UNCOND -- Log the associated message unconditionally.
@end itemize
Each level can be requested singly or cumulatively; and can be set using a
shell environment variable (NS_LOG) or by logging system function call. As
was seen earlier in the tutorial, the logging system has Doxygen documentation
so now would be a good time to peruse the Logging Module documentation.
Each level can be requested singly or cumulatively; and logging can be set
up using a shell environment variable (NS_LOG) or by logging system function
call. As was seen earlier in the tutorial, the logging system has Doxygen
documentation so now would be a good time to peruse the Logging Module
documentation.
Now that you have read the documentation in great detail, we can get some
interesting information out of the @code{first.cc} example script you dropped
@@ -107,7 +108,7 @@ ask the client application, for example, to print more information by setting
its logging level via the NS_LOG environment variable. I am going to assume
from here on that are using an sh-like shell that uses the``VARIABLE=value''
syntax. If you are using a csh-like shell, then you will have to convert to
``setenv VARIABLE value'' syntax.
the ``setenv VARIABLE value'' syntax required by those shells.
Let's ask the UDP echo client application to print a little more information.
Right now, it is responding to the following line of code in @code{first.cc},
@@ -158,19 +159,26 @@ output:
@end verbatim
The only additional debug information provided by the application is from
the NS_LOG_FUNCTION level. You can now see a log of the function calls that
were made to the application. If you look closely you will notice a single
colon between the string @code{UdpEchoClientApplication} and the method name
where you might have expected a C++ scope operator (@code{::}). This is
intentional. The name is not actually a class name, it is a logging component
name. When there is a one-to-one correspondence between a source file and a
class, this will generally be the class name but you should understand that
it is not actually a class name, and there is a single colon to separate the
logging component name from the function name that is printed.
the NS_LOG_FUNCTION level. Note that there are no requirements in the
@command{ns-3} system that logging components must support any particular
logging functionality. The decision regarding how much information is logged
is left to the individual developer.
You can now see a log of the function calls that were made to the application.
If you look closely you will notice a single colon between the string
@code{UdpEchoClientApplication} and the method name where you might have
expected a C++ scope operator (@code{::}). This is intentional.
The name is not actually a class name, it is a logging component name. When
there is a one-to-one correspondence between a source file and a class, this
will generally be the class name but you should understand that it is not
actually a class name, and there is a single colon there instead of a double
colon to remind you in a relatively subtle way to conceptually separate the
logging component name from the class name.
It turns out that in come cases, it can be hard to determine which method
actually generates a log message. If you look in the text above, you may
wonder where the string ``@code{Received 1024 bytes from 10.1.1.1}'' comes
wonder where the string ``@code{Received 1024 bytes from 10.1.1.2}'' comes
from. You can resolve this by ORing the @code{prefix_func} level into the
@code{NS_LOG} environment variable. Try doing the following,
@@ -178,8 +186,8 @@ from. You can resolve this by ORing the @code{prefix_func} level into the
export 'NS_LOG=UdpEchoClientApplication=level_all|prefix_func'
@end verbatim
Note that the single quotes are required since the vertical bar is a Unix
pipe connector.
Note that the quotes are required since the vertical bar we use to indicate an
OR operation is also a Unix pipe connector.
Now, if you run the script you will see that the logging system makes sure
that every message from the given log component is prefixed with the component
@@ -204,9 +212,11 @@ name.
@end verbatim
You can now see all of the messages coming from the UDP echo client application
are identified as such. The remaining message must be coming from the UDP
echo server application. We can enable that component by entering a colon
separated list of components in the NS_LOG environment variable.
are identified as such. The message ``Received 1024 bytes from 10.1.1.2'' is
now clearly identified as coming from the echo client application. The
remaining message must be coming from the UDP echo server application. We
can enable that component by entering a colon separated list of components in
the NS_LOG environment variable.
@verbatim
export 'NS_LOG=UdpEchoClientApplication=level_all|prefix_func:
@@ -307,11 +317,11 @@ turning on all of the logging components in the system. Try setting the
export 'NS_LOG=*=level_all|prefix_func|prefix_time'
@end verbatim
The asterisk is the logging component wildcard. This will turn on all of the
logging in all of the components in the system. I won't reproduce the output
here (as of this writing it produces 772 lines of output for the single packet
echo) but you can redirect this information into a file and look through it
with your favorite editor if you like,
The asterisk above is the logging component wildcard. This will turn on all
of the logging in all of the components used in the simulation. I won't
reproduce the output here (as of this writing it produces 772 lines of output
for the single packet echo) but you can redirect this information into a file
and look through it with your favorite editor if you like,
@verbatim
~/repos/ns-3-tutorial > ./waf --run scratch/first >& log.out
@@ -322,8 +332,10 @@ have no idea where things are going wrong. I can follow the progress of the
code quite easily without having to set breakpoints and step through code
in a debugger. When I have a general idea about what is going wrong, I
transition into a debugger for fine-grained examination of the problem. This
output can be especially useful when your script does something completely
unexpected.
kind of output can be especially useful when your script does something
completely unexpected. If you are stepping using a debugger you may miss an
unexpected excursion completely. Logging the excursion makes it quickly
visible.
@node Adding Logging to your Code
@subsection Adding Logging to your Code
@@ -332,7 +344,7 @@ You can add new logging to your simulations by making calls to the log
component via several macros. Let's do so in the @code{first.cc} script we
have in the @code{scratch} directory.
Recall that we have defined a logging component in that script.
Recall that we have defined a logging component in that script:
@verbatim
NS_LOG_COMPONENT_DEFINE ("FirstScriptExample");
@@ -340,10 +352,10 @@ Recall that we have defined a logging component in that script.
You now know that you can enable all of the logging for this component by
setting the @code{NS_LOG} environment variable to the various levels. Let's
add some logging. The macro to add an informational level log message is
@code{NS_LOG_INFO}. Add one just before we start creating the nodes that
tells you that the script is ``Creating Topology.'' This is done as in this
code snippet,
go ahead add some logging to the script. The macro used to add an
informational level log message is @code{NS_LOG_INFO}. Go ahead and add one
just before we start creating the nodes that tells you that the script is
``Creating Topology.'' This is done as in this code snippet,
@verbatim
NS_LOG_INFO ("Creating Topology");
@@ -357,17 +369,18 @@ off the torrent of logging we previously enabled:
@end verbatim
Now, if you run the script, you will not see your new message since its
associated logging component has not been enabled. In order to see your
message you will have to enable the @code{FirstScriptExample} logging
component with a level greater than or equal to @code{NS_LOG_INFO}. If
you just want to see this particular level of logging, you can enable that
by,
associated logging component (@code{FirstScriptExample}) has not been enabled.
In order to see your message you will have to enable the
@code{FirstScriptExample} logging component with a level greater than or equal
to @code{NS_LOG_INFO}. If you just want to see this particular level of
logging, you can enable it by,
@verbatim
~/repos/ns-3-tutorial > export NS_LOG=FirstScriptExample=info
@end verbatim
If you now run the script you will see your new logging message,
If you now run the script you will see your new ``Creating Topology'' log
message,
@verbatim
~/repos/ns-3-tutorial > ./waf --run scratch/first
@@ -380,13 +393,6 @@ If you now run the script you will see your new logging message,
~/repos/ns-3-tutorial >
@end verbatim
As previously described, this does not also enable the lower levels of logging
but selects out the single infomational level.
As we outlined in the Logging Overview, there are currently seven levels of
logging verbosity you can use and you can also prefix your various log messages
with component name and simulation time.
@c ========================================================================
@c Using Command Line Arguments
@c ========================================================================
@@ -395,10 +401,10 @@ with component name and simulation time.
@subsection Overriding Default Attributes
@cindex command line arguments
Another way you can change the way that ns-3 scripts behave without editing
and building scripts is via @emph{command line arguments.} We provide a
mechanism to parse command line arguments and automatically set local and
global variables based on those arguments.
Another way you can change how @command}ns-3} scripts behave without editing
and building is via @emph{command line arguments.} We provide a mechanism to
parse command line arguments and automatically set local and global variables
based on those arguments.
The first step in using the command line argument system is to declare the
command line parser. This is done quite simply (in your main program) as
@@ -418,18 +424,19 @@ in the following code,
@end verbatim
This simple two line snippet is actually very useful by itself. It opens the
door to the ns-3 global variable and attribute systems. Go ahead and add that
two lines of code to the @code{first.cc} script at the start of @code{main}.
Go ahead and build the script and run it, but ask the script for help in the
following way,
door to the @command{ns-3} global variable and attribute systems. Go ahead
and add that two lines of code to the @code{first.cc} script at the start of
@code{main}. Go ahead and build the script and run it, but ask the script
for help in the following way,
@verbatim
~/repos/ns-3-tutorial > ./waf --run "scratch/first --PrintHelp"
@end verbatim
This will ask way to run the @code{scratch/first} script and pass the command
line argument @code{--PrintHelp} to the script. The command line parser will
now see the @code{PrintHelp} argument and respond with,
This will ask Waf to run the @code{scratch/first} script and pass the command
line argument @code{--PrintHelp} to the script. The quotes are required to
sort out which program gets which argument. The command line parser will
now see the @code{--PrintHelp} argument and respond with,
@verbatim
~/repos/ns-3-tutorial > ./waf --run ``scratch/first --PrintHelp''
@@ -445,8 +452,8 @@ now see the @code{PrintHelp} argument and respond with,
@end verbatim
Let's focus on the @code{--PrintAttributes} option. We have already hinted
at the attribute system while walking through the @code{first.cc} script. We
looked at the following lines of code,
at the @command{ns-3} attribute system while walking through the
@code{first.cc} script. We looked at the following lines of code,
@verbatim
PointToPointHelper pointToPoint;
@@ -457,9 +464,9 @@ looked at the following lines of code,
and mentioned that @code{DataRate} was actually an @code{Attribute} of the
@code{PointToPointNetDevice}. Let's use the command line argument parser
to take a look at the attributes of the PointToPointNetDevice. The help
listing says that we should provide a typeid. This corresponds to the class
name of the class to which the attributes belong. In this case it will be
@code{ns3::PointToPointNetDevice}. Let's go ahead and type in,
listing says that we should provide a @code{TypeId}. This corresponds to the
class name of the class to which the attributes belong. In this case it will
be @code{ns3::PointToPointNetDevice}. Let's go ahead and type in,
@verbatim
./waf --run "scratch/first --PrintAttributes=ns3::PointToPointNetDevice"
@@ -470,18 +477,18 @@ Among the attributes you will see listed is,
@verbatim
--ns3::PointToPointNetDevice::DataRate=[32768bps]:
The default data rate fo r point to point links
The default data rate for point to point links
@end verbatim
This is the default value that will be used when a PointToPointNetDevice is
created in the system. We overrode this default with the parameter setting
in the PointToPointHelper above. Let's use the default values for the
PointToPoint devices and channels by deleting the SetDeviceParameter call and
the SetChannelParameter call from the @code{first.cc} we have in the scratch
directory.
This is the default value that will be used when a @code{PointToPointNetDevice}
is created in the system. We overrode this default with the ``parameter''
setting in the @code{PointToPointHelper} above. Let's use the default values
for the point-to-point devices and channels by deleting the
@code{SetDeviceParameter} call and the @code{SetChannelParameter} call from
the @code{first.cc} we have in the scratch directory.
Your script should now just declare the PointToPointHelper and not do any
sets as in the following example,
Your script should now just declare the @code{PointToPointHelper} and not do
any @code{set} operations as in the following example,
@verbatim
...
@@ -497,8 +504,9 @@ sets as in the following example,
...
@end verbatim
Go ahead and build the new script with waf. Now let's go back and enable some
logging from the UDP echo server application and turn on the time prefix.
Go ahead and build the new script with Waf (@code{./waf}) and let's go back
and enable some logging from the UDP echo server application and turn on the
time prefix.
@verbatim
export 'NS_LOG=UdpEchoServerApplication=level_all|prefix_time'
@@ -529,23 +537,25 @@ the data rate of the @code{PointToPointNetDevice} down to its default of
32768 bits per second from five megabits per second.
If we were to provide a new @code{DataRate} using the command line, we could
speed our simulation up again,
speed our simulation up again. We do this in the following way, according to
the formula implied by the help item:
@verbatim
./waf --run "scratch/first --ns3::PointToPointNetDevice::DataRate=5Mbps"
@end verbatim
This will set the default value of the @code{DataRate} attribute back to
five megabits per second. To get the old behavior back, we will have to set
the speed-of-light delay of the channel. We can ask the command line system
to print out the @code{Attributes} of the channel just like we did the net
device:
five megabits per second. To get the original behavior of the script back,
we will have to set the speed-of-light delay of the channel. We can ask the
command line system to print out the @code{Attributes} of the channel just
like we did the net device:
@verbatim
./waf --run "scratch/first --PrintAttributes=ns3::PointToPointChannel"
@end verbatim
and we discover the @code{Delay} attribute.
We discover the @code{Delay} attribute of the channel is set in the following
way:
@verbatim
--ns3::PointToPointChannel::Delay=[0ns]:
@@ -560,7 +570,7 @@ We can then set both of these default values through the command line system,
--ns3::PointToPointChannel::Delay=2ms"
@end verbatim
In which case we recover the timing we had when we explicitly set the
in which case we recover the timing we had when we explicitly set the
@code{DataRate} and @code{Delay} in the script:
@verbatim
@@ -576,7 +586,7 @@ In which case we recover the timing we had when we explicitly set the
UdpEchoServerApplication:~UdpEchoServer()
@end verbatim
Note that the packet is received by the server at 2.0036864 seconds. We
Note that the packet is again received by the server at 2.0036864 seconds. We
could actually set any of the attributes used in the script in this way. In
particular we could set the @code{UdpEchoClient} attribute @code{MaxPackets}
to some other value than one.
@@ -603,9 +613,9 @@ quite simply by using the @code{AddValue} method to the command line parser.
Let's use this facility to specify the number of packets to echo in a
completely different way. Let's add a local variable called @code{nPackets}
to the main function. We'll initialize it to one to match our previous
to the @code{main} function. We'll initialize it to one to match our previous
default behavior. To allow the command line parser to change this value, we
need to hook the value into the parser. Do this by adding a call to
need to hook the value into the parser. We do this by adding a call to
@code{AddValue}. Go ahead and change the @code{scratch/first.cc} script to
start with the following code,
@@ -624,7 +634,7 @@ start with the following code,
Scroll down to the point in the script where we set the @code{MaxPackets}
attribute and change it so that it is set to the variable @code{nPackets}
instead of the constant @code{1} as below.
instead of the constant @code{1} as is shown below.
@verbatim
echoClient.SetAppAttribute ("MaxPackets", UintegerValue (nPackets));
@@ -649,7 +659,7 @@ should see your new @code{User Argument} listed in the help.
@end verbatim
If you want to specify the number of packets to echo, you can now do so by
setting the @code{nPackets} argument,
setting the @code{--nPackets} argument in the command line,
@verbatim
~/repos/ns-3-tutorial > ./waf --run "scratch/first --nPackets=2"
@@ -664,12 +674,14 @@ setting the @code{nPackets} argument,
~/repos/ns-3-tutorial >
@end verbatim
If you are an ns-3 user, you can use the command line argument system to
control global values and attributes. If you are a model author, you can
add new attributes to your Objects and they will automatically be available
for setting by your users through the command line system. If you are a
script author, you can add new variables to your scripts and hook them into
the command line system quite painlessly.
You have now echoed two packets.
If you are an @command{ns-3} user, you can use the command line argument
system to control global values and attributes. If you are a model author,
you can add new attributes to your Objects and they will automatically be
available for setting by your users through the command line system. If you
are a script author, you can add new variables to your scripts and hook them
into the command line system quite painlessly.
@c ========================================================================
@c Using the Tracing System
@@ -707,17 +719,17 @@ and sinks.
@end itemize
The @command{ns-3} tracing system is built on the concepts of independent
tracing sources and tracing sinks and a uniform mechanism for connecting
tracing sources and tracing sinks, and 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 for interested trace sinks.
device and provide access to the packet contents for interested trace sinks.
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 sink. Trace sinks are consumers of the events and data
provided by the trace sources. For example, one could create a trace sink t
hat would (when connected to the trace source of the previous example) print
provided by the trace sources. For example, one could create a trace sink
that would (when connected to the trace source of the previous example) print
out interesting parts of the received packet.
The rationale for this explicit division is to allow users to attach new
@@ -727,10 +739,6 @@ a user could define a new tracing sink in her script and attach it to an
existing tracing source defined in the simulation core editing only the
user script.
What remains to be defined is a way for users to find these hooks (tracing
sources) and attach sinks to them. A tracing namespace is defined for
this purpose.
In this tutorial, we will walk through some pre-defined sources and sinks and
show how they may be customized with little user effort. See the ns-3 manual
or how-to sections for information on advanced tracing configuration including
@@ -739,12 +747,12 @@ extending the tracing namespace and creating new tracing sources.
@cindex tracing
@cindex ASCII tracing
@subsection ASCII Tracing
ns-3 provides an ASCII trace helper that is a wrapper around low-level
tracing system. This helper lets you configure some useful and easily
understood packet traces easily. The output of a trace of a simulation run
is an ASCII file --- thus the name. For those familiar with @command{ns-2}
output, this type of trace is analogous to the @command{out.tr} generated
by many scripts.
@command{Ns-3} provides an ASCII trace helper that is a wrapper around the
low-level tracing system. This helper lets you configure some useful and
easily understood packet traces easily. The output of a trace of a simulation
run is an ASCII file --- thus the name. For those familiar with
@command{ns-2} output, this type of trace is analogous to the @command{out.tr}
generated by many scripts.
@cindex tracing packets
Let's just jump right in and add some ASCII tracing output to our
@@ -760,11 +768,11 @@ following code to the script just before the call to @code{Simulator::Run ()}.
The first two lines are just vanilla C++ code to open a stream that will be
written to a file named ``first.tr.'' See your favorite C++ tutorial if you
are unfamiliar with this code. The last line of code in the snippet above
tells ns-3 that you want to enable ASCII tracing on all point-to-point devices
in your simulation; and you want the (provided) trace sinks to write out
information about packet movement in ASCII format to the stream provided.
For those familiar with @command{ns-2}, the traced events are equivalent
to the popular trace points that log "+", "-", "d", and "r" events.
tells @command{ns-3} that you want to enable ASCII tracing on all
point-to-point devices in your simulation; and you want the (provided) trace
sinks to write out information about packet movement in ASCII format to the
stream provided. For those familiar with @command{ns-2}, the traced events are
equivalent to the popular trace points that log "+", "-", "d", and "r" events.
Since we have used a @code{std::ofstream} object, we also need to include the
appropriate header. Add the following line to the script (I typically add it
@@ -783,26 +791,28 @@ You can now build the script and run it from the command line:
@cindex first.tr
Just as you have seen previously, you may see some messages from Waf and then
the ``Compilation finished successfully'' message. The following messages are
from the running program. When it ran, the program will have created a file
named @code{first.tr}. Because of the way that Waf works, the file is not
created in the local directory, it is created at the top-level directory of
the repository by default. If you want to control where the traces are saved
you can use the @code{--cwd} option of Waf to specify this. We have not done
so, thus we need to change into the top level directory of our repo and take a
look at the file @code{first.tr} in your favorite editor.
from the running program.
When it ran, the program will have created a file named @code{first.tr}.
Because of the way that Waf works, the file is not created in the local
directory, it is created at the top-level directory of the repository by
default. If you want to control where the traces are saved you can use the
@code{--cwd} option of Waf to specify this. We have not done so, thus we
need to change into the top level directory of our repo and take a look at
the file @code{first.tr} in your favorite editor.
@subsubsection Parsing Ascii Traces
@cindex parsing ascii traces
There's a lot of information there in a pretty dense form, but the first thing
to notice is that there are a number of distinct lines in this file. It may
be difficult to see this clearly unless you widen your windows considerably.
be difficult to see this clearly unless you widen your window considerably.
Each line in the file corresponds to a @emph{trace event}. In this case
we are tracing events on the @emph{device queue} present in every net device
on every node in the simulation. The device queue is a queue through which
every packet destined for a channel must pass --- it is the device
@emph{transmit} queue. Note that each line in the trace file begins with a
lone character (has a space after it). This character will have the following
meaning:
we are tracing events on the @emph{transmit queue} present in every net device
on every node in the simulation. The transmit queue is a queue through which
every packet destined for a channel must pass. Note that each line in the
trace file begins with a lone character (has a space after it). This
character will have the following meaning:
@cindex ascii trace enqueue operation
@cindex ascii trace dequeue operation
@@ -815,9 +825,9 @@ meaning:
@item @code{r}: A packet was received by the net device.
@end itemize
Let's take a more detailed view of the first line. I'll break it down into
sections (indented for clarity) with a two digit reference number on the
left side:
Let's take a more detailed view of the first line in the trace file. I'll
break it down into sections (indented for clarity) with a two digit reference
number on the left side:
@verbatim
00 +
@@ -836,40 +846,40 @@ left side:
@cindex trace event
@cindex simulation time
The first line of this expanded trace event (reference number 00) is the
queue operation. We have a @code{+} character, so this corresponds to an
@emph{enqueue} operation. The second line (reference 01) is the simulation
time expressed in seconds. You may recall that we asked the
@code{UdpEchoClient} to start sending packets at two seconds. Here we again
see confirmation that this is, indeed, happening.
operation. We have a @code{+} character, so this corresponds to an
@emph{enqueue} operation on the transmit queue. The second line (reference 01)
is the simulation time expressed in seconds. You may recall that we asked the
@code{UdpEchoClientApplication} to start sending packets at two seconds. Here
we see confirmation that this is, indeed, happening.
@cindex node number
@cindex net device number
@cindex smart pointer
The next line of the example listing (reference 02) tell us the trace source
The next line of the example trace (reference 02) tell us the trace source
that originated this even expressed in the tracing namespace. You can think
of the tracing womewhat like you would a filesystem namespace. The root of
the namespace is the @code{NodeList}. This corresponds to a container in the
ns-3 code that contains all of the nodes that were created in the system.
Just as a filesystem has may have directories under the root, we have node
numbers in the @code{NodeList}. The string @code{/NodeList/0} therefore
refers to the zeroth node in the @code{NodeList} which we can think of as
``node 0.'' In each node there is a list of devices that have been installed.
This list appears next. You can see that this trace event comes from
@code{DeviceList/0} which is the zeroth device installed in the node.
of the tracing namespace somewhat like you would a filesystem namespace. The
root of the namespace is the @code{NodeList}. This corresponds to a container
managed in the @command{ns-3} core code that contains all of the nodes that are
created in a script. Just as a filesystem may have directories under the
root, we may have node numbers in the @code{NodeList}. The string
@code{/NodeList/0} therefore refers to the zeroth node in the @code{NodeList}
which we typically think of as ``node 0.'' In each node there is a list of
devices that have been installed. This list appears next in the namespace.
You can see that this trace event comes from @code{DeviceList/0} which is the
zeroth device installed in the node.
The next string, @code{$ns3::PointToPointNetDevice} tells you what kind of
device it is that is in the zeroth position of the device list for node zero.
This should by now be completely expected. Recall that the operation @code{+}
found at reference 00 means an enqueue operation on the transmit queue of the
device. This is reflected in the final segments of the ``trace path'' which
are @code{TxQueue/Enqueue}.
Recall that the operation @code{+} found at reference 00 means an enqueue
operation happened on the transmit queue of the device. This is reflected in
the final segments of the ``trace path'' which are @code{TxQueue/Enqueue}.
The remaining lines in the trace should be fairly intuitive. References 03-04
indicate that the packet is encapulated in the point-to-point protocol.
References 05-07 show that the packet has an IP version four header and has
originated from IP address 10.1.1.1 and is destined for 10.1.1.2. References
08-09 show that this is a UDP packet from and finally reference 10 shows that
the payload is the expected 1024 bytes.
08-09 show that this packet has a UDP header and, finally, reference 10 shows
that the payload is the expected 1024 bytes.
The next line in the trace file shows the same packet being dequeued from the
transmit queue on the same node.
@@ -894,9 +904,8 @@ device on the node with the echo server. I have reproduced that event below.
Notice that the trace operation is now @code{r} and the simulation time has
increased to 2.25732 seconds. If you have been following the tutorial steps
closely this means that you have left the @code{DataRate} of the net devices
set to their default value of 32768 bps with a channel @code{Delay} of two
milliseconds. This time should be familiar as you have seen it before in a
previous section.
and the channel @code{Delay} set to their default values. This time should
be familiar as you have seen it before in a previous section.
The trace source namespace entry (reference 02) has changed to reflect that
this event is coming from node 1 (@code{/NodeList/1}) and the packet reception
@@ -904,17 +913,17 @@ trace source (@code{/Rx}). It should be quite easy for you to follow the
progress of the packet through the topology by looking at the rest of the
traces in the file.
@subsection PCAP Trace Helper
@subsection PCAP Tracing
@cindex pcap
@cindex Wireshark
The @command{ns-3} @emph{pcap trace helper} is used to create trace files in
The @command{ns-3} device helpers can be used to create trace files in the
@code{.pcap} format. The acronym pcap (usually written in lower case) stands
for @emph{p}acket @emph{cap}ture, and is actually an API that includes the
definition of a @code{.pcap} file format. The most popular program that can
read and display this format is Wireshark (formerly called Ethereal).
However, there are many traffic trace analyzers that use this packet format.
We encourage users to exploit the many tools available for analyzing pcap
traces. In this tutorial, we show how tcpdump and Wireshark can be used.
traces. In this tutorial, we concentrate on viewing pcap traces with tcpdump.
@cindex pcap tracing
The code used to enable pcap tracing is a one-liner.
@@ -924,18 +933,18 @@ The code used to enable pcap tracing is a one-liner.
@end verbatim
Go ahead and insert this line of code after the ASCII tracing code we just
added to @code{scratch/first.cc}. Notice that we only gave the pcap trace
helper call the string, ``first,'' and not ``first.pcap'' or something
similar. This is because the parameter is a prefix, not a complete file name.
The pcap trace helper will actually create a trace file for every device in
the simulation that generates a traced event. The file names will be built
using the prefix, the node number, the device number and a ``.pcap'' suffix.
added to @code{scratch/first.cc}. Notice that we only passed the string
``first,'' and not ``first.pcap'' or something similar. This is because the
parameter is a prefix, not a complete file name. The helper will actually
create a trace file for every point-to-point device in the simulation. The
file names will be built using the prefix, the node number, the device number
and a ``.pcap'' suffix.
In our example script, we will see a files named ``first-0-0.pcap'' and
``first.1-0.pcap'' which are the pcap traces for node 0, device 0 and node 1,
device 1, respectively.
``first.1-0.pcap'' which are the pcap traces for node 0-device 0 and
node 1-device 1, respectively.
You can now run the script as you have been:
You can now run the script in the usual way:
@verbatim
./waf --run scratch/first