--- a/doc/tutorial/Makefile Sun Jan 02 22:57:04 2011 -0800
+++ b/doc/tutorial/Makefile Sun Jan 02 22:57:32 2011 -0800
@@ -1,39 +1,150 @@
-TEXI2HTML = texi2html
-TEXI2PDF = texi2dvi --pdf
-EPSTOPDF = epstopdf
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS =
+SPHINXBUILD = sphinx-build
+PAPER =
+BUILDDIR = build
+
+# Internal variables.
+PAPEROPT_a4 = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
+
+# Additional variables for figures, not sphinx default:
DIA = dia
-CONVERT = convert
-CSS = --css-include=tutorial.css
-SPLIT = --split section
+EPSTOPDF = epstopdf
+FIGURES = source/figures
+IMAGES_EPS = \
+
+IMAGES_PNG = ${IMAGES_EPS:.eps=.png}
+IMAGES_PDF = ${IMAGES_EPS:.eps=.pdf}
+
+IMAGES = $(IMAGES_EPS) $(IMAGES_PNG) $(IMAGES_PDF)
+
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
+
+%.eps : %.dia; $(DIA) -t eps $< -e $@
+%.png : %.dia; $(DIA) -t png $< -e $@
+%.pdf : %.eps; $(EPSTOPDF) $< -o=$@
-DIA_SOURCES = pp.dia dumbbell.dia star.dia
+help:
+ @echo "Please use \`make <target>' where <target> is one of"
+ @echo " html to make standalone HTML files"
+ @echo " dirhtml to make HTML files named index.html in directories"
+ @echo " singlehtml to make a single large HTML file"
+ @echo " pickle to make pickle files"
+ @echo " json to make JSON files"
+ @echo " htmlhelp to make HTML files and a HTML help project"
+ @echo " qthelp to make HTML files and a qthelp project"
+ @echo " devhelp to make HTML files and a Devhelp project"
+ @echo " epub to make an epub"
+ @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+ @echo " latexpdf to make LaTeX files and run them through pdflatex"
+ @echo " text to make text files"
+ @echo " man to make manual pages"
+ @echo " changes to make an overview of all changed/added/deprecated items"
+ @echo " linkcheck to check all external links for integrity"
+ @echo " doctest to run all doctests embedded in the documentation (if enabled)"
-DIA_EPS = ${DIA_SOURCES:.dia=.eps}
-DIA_PNG = ${DIA_SOURCES:.dia=.png}
-DIA_PDF = ${DIA_SOURCES:.dia=.pdf}
+clean:
+ -rm -rf $(BUILDDIR)/*
+
+frag: pickle
+ @if test ! -d $(BUILDDIR)/frag; then mkdir $(BUILDDIR)/frag; fi
+ pushd $(BUILDDIR)/frag && ../../pickle-to-xml.py ../pickle/index.fpickle > navigation.xml && popd
+ cp -r $(BUILDDIR)/pickle/_images $(BUILDDIR)/frag
-all: html split-html pdf
+html: $(IMAGES)
+ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml: $(IMAGES)
+ $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+singlehtml: $(IMAGES)
+ $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+ @echo
+ @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
-# Note: tgif requires a valid x display to convert from .obj to .png.
-# If running this makefile on a remote console, the X virtual frame
-# buffer may be needed (xorg-x11-server-Xvfb) to provide a "fake"
-# display
-images:
- cd figures/; $(DIA) -t png $(DIA_SOURCES)
- cd figures/; $(DIA) -t eps $(DIA_SOURCES)
- cd figures/; $(foreach FILE,$(DIA_EPS),$(EPSTOPDF) $(FILE);)
+pickle: $(IMAGES)
+ $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+ @echo
+ @echo "Build finished; now you can process the pickle files."
+
+json: $(IMAGES)
+ $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+ @echo
+ @echo "Build finished; now you can process the JSON files."
+
+htmlhelp: $(IMAGES)
+ $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+ @echo
+ @echo "Build finished; now you can run HTML Help Workshop with the" \
+ ".hhp project file in $(BUILDDIR)/htmlhelp."
-html:
- $(TEXI2HTML) ${CSS} tutorial.texi
+qthelp: $(IMAGES)
+ $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+ @echo
+ @echo "Build finished; now you can run "qcollectiongenerator" with the" \
+ ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+ @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/ns-3.qhcp"
+ @echo "To view the help file:"
+ @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/ns-3.qhc"
+
+devhelp: $(IMAGES)
+ $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+ @echo
+ @echo "Build finished."
+ @echo "To view the help file:"
+ @echo "# mkdir -p $$HOME/.local/share/devhelp/ns-3"
+ @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/ns-3"
+ @echo "# devhelp"
+
+epub: $(IMAGES)
+ $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+ @echo
+ @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
-split-html:
- $(TEXI2HTML) ${CSS} ${SPLIT} --output tutorial tutorial.texi
+latex: $(IMAGES)
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo
+ @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+ @echo "Run \`make' in that directory to run these through (pdf)latex" \
+ "(use \`make latexpdf' here to do that automatically)."
-pdf:
- $(TEXI2PDF) tutorial.texi
+latexpdf: $(IMAGES)
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo "Running LaTeX files through pdflatex..."
+ make -C $(BUILDDIR)/latex all-pdf
+ @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+text: $(IMAGES)
+ $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+ @echo
+ @echo "Build finished. The text files are in $(BUILDDIR)/text."
-figures-clean:
- cd figures/; rm -rf $(DIA_EPS); rm -rf $(DIA_PNG); rm -rf $(DIA_PDF)
+man: $(IMAGES)
+ $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+ @echo
+ @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+changes: $(IMAGES)
+ $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+ @echo
+ @echo "The overview file is in $(BUILDDIR)/changes."
-clean: # figures-clean
- rm -rf tutorial.aux tutorial.cp tutorial.cps tutorial.fn tutorial.ky tutorial.pg tutorial.tp tutorial.vr tutorial.toc tutorial.log tutorial.pdf tutorial.html tutorial/
+linkcheck: $(IMAGEs)
+ $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+ @echo
+ @echo "Link check complete; look for any errors in the above output " \
+ "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest: $(IMAGES)
+ $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+ @echo "Testing of doctests in the sources finished, look at the " \
+ "results in $(BUILDDIR)/doctest/output.txt."
--- a/doc/tutorial/building-topologies.texi Sun Jan 02 22:57:04 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1458 +0,0 @@
-
-@c ========================================================================
-@c Begin document body here
-@c ========================================================================
-
-@c ========================================================================
-@c PART: Building Topologies
-@c ========================================================================
-@c The below chapters are under the major heading "Building Topologies"
-@c This is similar to the Latex \part command
-@c
-@c ========================================================================
-@c Building Topologies
-@c ========================================================================
-@node Building Topologies
-@chapter Building Topologies
-
-@menu
-* Building a Bus Network Topology::
-* Building a Wireless Network Topology::
-@end menu
-
-@c ========================================================================
-@c Building a Bus Network Topology
-@c ========================================================================
-@node Building a Bus Network Topology
-@section Building a Bus Network Topology
-
-@cindex topology
-@cindex bus network topology
-In this section we are going to expand our mastery of @command{ns-3} network
-devices and channels to cover an example of a bus network. @command{Ns-3}
-provides a net device and channel we call CSMA (Carrier Sense Multiple Access).
-
-The @command{ns-3} CSMA device models a simple network in the spirit of
-Ethernet. A real Ethernet uses CSMA/CD (Carrier Sense Multiple Access with
-Collision Detection) scheme with exponentially increasing backoff to contend
-for the shared transmission medium. The @command{ns-3} CSMA device and
-channel models only a subset of this.
-
-Just as we have seen point-to-point topology helper objects when constructing
-point-to-point topologies, we will see equivalent CSMA topology helpers in
-this section. The appearance and operation of these helpers should look
-quite familiar to you.
-
-We provide an example script in our @code{examples/tutorial} directory. This script
-builds on the @code{first.cc} script and adds a CSMA network to the
-point-to-point simulation we've already considered. Go ahead and open
-@code{examples/tutorial/second.cc} in your favorite editor. You will have already seen
-enough @command{ns-3} code to understand most of what is going on in this
-example, but we will go over the entire script and examine some of the output.
-
-Just as in the @code{first.cc} example (and in all ns-3 examples) the file
-begins with an emacs mode line and some GPL boilerplate.
-
-The actual code begins by loading module include files just as was done in the
-@code{first.cc} example.
-
-@verbatim
- #include "ns3/core-module.h"
- #include "ns3/simulator-module.h"
- #include "ns3/node-module.h"
- #include "ns3/helper-module.h"
-@end verbatim
-
-One thing that can be surprisingly useful is a small bit of ASCII art that
-shows a cartoon of the network topology constructed in the example. You will
-find a similar ``drawing'' in most of our examples.
-
-In this case, you can see that we are going to extend our point-to-point
-example (the link between the nodes n0 and n1 below) by hanging a bus network
-off of the right side. Notice that this is the default network topology
-since you can actually vary the number of nodes created on the LAN. If you
-set nCsma to one, there will be a total of two nodes on the LAN (CSMA
-channel) --- one required node and one ``extra'' node. By default there are
-three ``extra'' nodes as seen below:
-
-@verbatim
-// Default Network Topology
-//
-// 10.1.1.0
-// n0 -------------- n1 n2 n3 n4
-// point-to-point | | | |
-// ================
-// LAN 10.1.2.0
-@end verbatim
-
-Then the ns-3 namespace is @code{used} and a logging component is defined.
-This is all just as it was in @code{first.cc}, so there is nothing new yet.
-
-@verbatim
- using namespace ns3;
-
- NS_LOG_COMPONENT_DEFINE ("SecondScriptExample");
-@end verbatim
-
-The main program begins with a slightly different twist. We use a verbose
-flag to determine whether or not the @code{UdpEchoClientApplication} and
-@code{UdpEchoServerApplication} logging components are enabled. This flag
-defaults to true (the logging components are enabled) but allows us to turn
-off logging during regression testing of this example.
-
-You will see some familiar code that will allow you to change the number
-of devices on the CSMA network via command line argument. We did something
-similar when we allowed the number of packets sent to be changed in the section
-on command line arguments. The last line makes sure you have at least one
-``extra'' node.
-
-The code consists of variations of previously covered API so you should be
-entirely comfortable with the following code at this point in the tutorial.
-
-@verbatim
- bool verbose = true;
- uint32_t nCsma = 3;
-
- CommandLine cmd;
- cmd.AddValue (``nCsma'', ``Number of \"extra\" CSMA nodes/devices'', nCsma);
- cmd.AddValue (``verbose'', ``Tell echo applications to log if true'', verbose);
-
- cmd.Parse (argc,argv);
-
- if (verbose)
- {
- LogComponentEnable(``UdpEchoClientApplication'', LOG_LEVEL_INFO);
- LogComponentEnable(``UdpEchoServerApplication'', LOG_LEVEL_INFO);
- }
-
- nCsma = nCsma == 0 ? 1 : nCsma;
-@end verbatim
-
-The next step is to create two nodes that we will connect via the
-point-to-point link. The @code{NodeContainer} is used to do this just as was
-done in @code{first.cc}.
-
-@verbatim
- NodeContainer p2pNodes;
- p2pNodes.Create (2);
-@end verbatim
-
-Next, we declare another @code{NodeContainer} to hold the nodes that will be
-part of the bus (CSMA) network. First, we just instantiate the container
-object itself.
-
-@verbatim
- NodeContainer csmaNodes;
- csmaNodes.Add (p2pNodes.Get (1));
- csmaNodes.Create (nCsma);
-@end verbatim
-
-The next line of code @code{Gets} the first node (as in having an index of one)
-from the point-to-point node container and adds it to the container of nodes
-that will get CSMA devices. The node in question is going to end up with a
-point-to-point device @emph{and} a CSMA device. We then create a number of
-``extra'' nodes that compose the remainder of the CSMA network. Since we
-already have one node in the CSMA network -- the one that will have both a
-point-to-point and CSMA net device, the number of ``extra'' nodes means the
-number nodes you desire in the CSMA section minus one.
-
-The next bit of code should be quite familiar by now. We instantiate a
-@code{PointToPointHelper} and set the associated default @code{Attributes} so
-that we create a five megabit per second transmitter on devices created using
-the helper and a two millisecond delay on channels created by the helper.
-
-@verbatim
- PointToPointHelper pointToPoint;
- pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
- pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
-
- NetDeviceContainer p2pDevices;
- p2pDevices = pointToPoint.Install (p2pNodes);
-@end verbatim
-
-We then instantiate a @code{NetDeviceContainer} to keep track of the
-point-to-point net devices and we @code{Install} devices on the
-point-to-point nodes.
-
-We mentioned above that you were going to see a helper for CSMA devices and
-channels, and the next lines introduce them. The @code{CsmaHelper} works just
-like a @code{PointToPointHelper}, but it creates and connects CSMA devices and
-channels. In the case of a CSMA device and channel pair, notice that the data
-rate is specified by a @emph{channel} @code{Attribute} instead of a device
-@code{Attribute}. This is because a real CSMA network does not allow one to mix,
-for example, 10Base-T and 100Base-T devices on a given channel. We first set
-the data rate to 100 megabits per second, and then set the speed-of-light delay
-of the channel to 6560 nano-seconds (arbitrarily chosen as 1 nanosecond per foot
-over a 100 meter segment). Notice that you can set an @code{Attribute} using
-its native data type.
-
-@verbatim
- CsmaHelper csma;
- csma.SetChannelAttribute ("DataRate", StringValue ("100Mbps"));
- csma.SetChannelAttribute ("Delay", TimeValue (NanoSeconds (6560)));
-
- NetDeviceContainer csmaDevices;
- csmaDevices = csma.Install (csmaNodes);
-@end verbatim
-
-Just as we created a @code{NetDeviceContainer} to hold the devices created by
-the @code{PointToPointHelper} we create a @code{NetDeviceContainer} to hold
-the devices created by our @code{CsmaHelper}. We call the @code{Install}
-method of the @code{CsmaHelper} to install the devices into the nodes of the
-@code{csmaNodes NodeContainer}.
-
-We now have our nodes, devices and channels created, but we have no protocol
-stacks present. Just as in the @code{first.cc} script, we will use the
-@code{InternetStackHelper} to install these stacks.
-
-@verbatim
- InternetStackHelper stack;
- stack.Install (p2pNodes.Get (0));
- stack.Install (csmaNodes);
-@end verbatim
-
-Recall that we took one of the nodes from the @code{p2pNodes} container and
-added it to the @code{csmaNodes} container. Thus we only need to install
-the stacks on the remaining @code{p2pNodes} node, and all of the nodes in the
-@code{csmaNodes} container to cover all of the nodes in the simulation.
-
-Just as in the @code{first.cc} example script, we are going to use the
-@code{Ipv4AddressHelper} to assign IP addresses to our device interfaces.
-First we use the network 10.1.1.0 to create the two addresses needed for our
-two point-to-point devices.
-
-@verbatim
- Ipv4AddressHelper address;
- address.SetBase ("10.1.1.0", "255.255.255.0");
- Ipv4InterfaceContainer p2pInterfaces;
- p2pInterfaces = address.Assign (p2pDevices);
-@end verbatim
-
-Recall that we save the created interfaces in a container to make it easy to
-pull out addressing information later for use in setting up the applications.
-
-We now need to assign IP addresses to our CSMA device interfaces. The
-operation works just as it did for the point-to-point case, except we now
-are performing the operation on a container that has a variable number of
-CSMA devices --- remember we made the number of CSMA devices changeable by
-command line argument. The CSMA devices will be associated with IP addresses
-from network number 10.1.2.0 in this case, as seen below.
-
-@verbatim
- address.SetBase ("10.1.2.0", "255.255.255.0");
- Ipv4InterfaceContainer csmaInterfaces;
- csmaInterfaces = address.Assign (csmaDevices);
-@end verbatim
-
-Now we have a topology built, but we need applications. This section is
-going to be fundamentally similar to the applications section of
-@code{first.cc} but we are going to instantiate the server on one of the
-nodes that has a CSMA device and the client on the node having only a
-point-to-point device.
-
-First, we set up the echo server. We create a @code{UdpEchoServerHelper} and
-provide a required @code{Attribute} value to the constructor which is the server
-port number. Recall that this port can be changed later using the
-@code{SetAttribute} method if desired, but we require it to be provided to
-the constructor.
-
-@verbatim
- UdpEchoServerHelper echoServer (9);
-
- ApplicationContainer serverApps = echoServer.Install (csmaNodes.Get (nCsma));
- serverApps.Start (Seconds (1.0));
- serverApps.Stop (Seconds (10.0));
-@end verbatim
-
-Recall that the @code{csmaNodes NodeContainer} contains one of the
-nodes created for the point-to-point network and @code{nCsma} ``extra'' nodes.
-What we want to get at is the last of the ``extra'' nodes. The zeroth entry of
-the @code{csmaNodes} container will be the point-to-point node. The easy
-way to think of this, then, is if we create one ``extra'' CSMA node, then it
-will be at index one of the @code{csmaNodes} container. By induction,
-if we create @code{nCsma} ``extra'' nodes the last one will be at index
-@code{nCsma}. You see this exhibited in the @code{Get} of the first line of
-code.
-
-The client application is set up exactly as we did in the @code{first.cc}
-example script. Again, we provide required @code{Attributes} to the
-@code{UdpEchoClientHelper} in the constructor (in this case the remote address
-and port). We tell the client to send packets to the server we just installed
-on the last of the ``extra'' CSMA nodes. We install the client on the
-leftmost point-to-point node seen in the topology illustration.
-
-@verbatim
- UdpEchoClientHelper echoClient (csmaInterfaces.GetAddress (nCsma), 9);
- echoClient.SetAttribute ("MaxPackets", UintegerValue (1));
- echoClient.SetAttribute ("Interval", TimeValue (Seconds (1.)));
- echoClient.SetAttribute ("PacketSize", UintegerValue (1024));
-
- ApplicationContainer clientApps = echoClient.Install (p2pNodes.Get (0));
- clientApps.Start (Seconds (2.0));
- clientApps.Stop (Seconds (10.0));
-@end verbatim
-
-Since we have actually built an internetwork here, we need some form of
-internetwork routing. @command{ns-3} provides what we call global routing to
-help you out. Global routing takes advantage of the fact that the entire
-internetwork is accessible in the simulation and runs through the all of the
-nodes created for the simulation --- it does the hard work of setting up routing
-for you without having to configure routers.
-
-Basically, what happens is that each node behaves as if it were an OSPF router
-that communicates instantly and magically with all other routers behind the
-scenes. Each node generates link advertisements and communicates them
-directly to a global route manager which uses this global information to
-construct the routing tables for each node. Setting up this form of routing
-is a one-liner:
-
-@verbatim
- Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
-@end verbatim
-
-Next we enable pcap tracing. The first line of code to enable pcap tracing
-in the point-to-point helper should be familiar to you by now. The second
-line enables pcap tracing in the CSMA helper and there is an extra parameter
-you haven't encountered yet.
-
-@verbatim
- pointToPoint.EnablePcapAll ("second");
- csma.EnablePcap ("second", csmaDevices.Get (1), true);
-@end verbatim
-
-The CSMA network is a multi-point-to-point network. This means that there
-can (and are in this case) multiple endpoints on a shared medium. Each of
-these endpoints has a net device associated with it. There are two basic
-alternatives to gathering trace information from such a network. One way
-is to create a trace file for each net device and store only the packets
-that are emitted or consumed by that net device. Another way is to pick
-one of the devices and place it in promiscuous mode. That single device
-then ``sniffs'' the network for all packets and stores them in a single
-pcap file. This is how @code{tcpdump}, for example, works. That final
-parameter tells the CSMA helper whether or not to arrange to capture
-packets in promiscuous mode.
-
-In this example, we are going to select one of the devices on the CSMA
-network and ask it to perform a promiscuous sniff of the network, thereby
-emulating what @code{tcpdump} would do. If you were on a Linux machine
-you might do something like @code{tcpdump -i eth0} to get the trace.
-In this case, we specify the device using @code{csmaDevices.Get(1)},
-which selects the first device in the container. Setting the final
-parameter to true enables promiscuous captures.
-
-The last section of code just runs and cleans up the simulation just like
-the @code{first.cc} example.
-
-@verbatim
- Simulator::Run ();
- Simulator::Destroy ();
- return 0;
- }
-@end verbatim
-
-In order to run this example, copy the @code{second.cc} example script into
-the scratch directory and use waf to build just as you did with
-the @code{first.cc} example. If you are in the top-level directory of the
-repository you just type,
-
-@verbatim
- cp examples/tutorial/second.cc scratch/mysecond.cc
- ./waf
-@end verbatim
-
-Warning: We use the file @code{second.cc} as one of our regression tests to
-verify that it works exactly as we think it should in order to make your
-tutorial experience a positive one. This means that an executable named
-@code{second} already exists in the project. To avoid any confusion
-about what you are executing, please do the renaming to @code{mysecond.cc}
-suggested above.
-
-If you are following the tutorial religiously (you are, aren't you) you will
-still have the NS_LOG variable set, so go ahead and clear that variable and
-run the program.
-
-@verbatim
- export NS_LOG=
- ./waf --run scratch/mysecond
-@end verbatim
-
-Since we have set up the UDP echo applications to log just as we did in
-@code{first.cc}, you will see similar output when you run the script.
-
-@verbatim
- Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
- Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
- 'build' finished successfully (0.415s)
- Sent 1024 bytes to 10.1.2.4
- Received 1024 bytes from 10.1.1.1
- Received 1024 bytes from 10.1.2.4
-@end verbatim
-
-Recall that the first message, ``@code{Sent 1024 bytes to 10.1.2.4},'' is the
-UDP echo client sending a packet to the server. In this case, the server
-is on a different network (10.1.2.0). The second message, ``@code{Received 1024
-bytes from 10.1.1.1},'' is from the UDP echo server, generated when it receives
-the echo packet. The final message, ``@code{Received 1024 bytes from 10.1.2.4},''
-is from the echo client, indicating that it has received its echo back from
-the server.
-
-If you now go and look in the top level directory, you will find three trace
-files:
-
-@verbatim
- second-0-0.pcap second-1-0.pcap second-2-0.pcap
-@end verbatim
-
-Let's take a moment to look at the naming of these files. They all have the
-same form, @code{<name>-<node>-<device>.pcap}. For example, the first file
-in the listing is @code{second-0-0.pcap} which is the pcap trace from node
-zero, device zero. This is the point-to-point net device on node zero. The
-file @code{second-1-0.pcap} is the pcap trace for device zero on node one,
-also a point-to-point net device; and the file @code{second-2-0.pcap} is the
-pcap trace for device zero on node two.
-
-If you refer back to the topology illustration at the start of the section,
-you will see that node zero is the leftmost node of the point-to-point link
-and node one is the node that has both a point-to-point device and a CSMA
-device. You will see that node two is the first ``extra'' node on the CSMA
-network and its device zero was selected as the device to capture the
-promiscuous-mode trace.
-
-Now, let's follow the echo packet through the internetwork. First, do a
-tcpdump of the trace file for the leftmost point-to-point node --- node zero.
-
-@verbatim
- tcpdump -nn -tt -r second-0-0.pcap
-@end verbatim
-
-You should see the contents of the pcap file displayed:
-
-@verbatim
- reading from file second-0-0.pcap, link-type PPP (PPP)
- 2.000000 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024
- 2.007602 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024
-@end verbatim
-
-The first line of the dump indicates that the link type is PPP (point-to-point)
-which we expect. You then see the echo packet leaving node zero via the
-device associated with IP address 10.1.1.1 headed for IP address
-10.1.2.4 (the rightmost CSMA node). This packet will move over the
-point-to-point link and be received by the point-to-point net device on node
-one. Let's take a look:
-
-@verbatim
- tcpdump -nn -tt -r second-1-0.pcap
-@end verbatim
-
-You should now see the pcap trace output of the other side of the point-to-point
-link:
-
-@verbatim
-reading from file second-1-0.pcap, link-type PPP (PPP)
-2.003686 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024
-2.003915 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024
-@end verbatim
-
-Here we see that the link type is also PPP as we would expect. You see the
-packet from IP address 10.1.1.1 (that was sent at 2.000000 seconds) headed
-toward IP address 10.1.2.4 appear on this interface. Now, internally to this
-node, the packet will be forwarded to the CSMA interface and we should see it
-pop out on that device headed for its ultimate destination.
-
-Remember that we selected node 2 as the promiscuous sniffer node for the CSMA
-network so let's then look at second-2-0.pcap and see if its there.
-
-@verbatim
- tcpdump -nn -tt -r second-2-0.pcap
-@end verbatim
-
-You should now see the promiscuous dump of node two, device zero:
-
-@verbatim
- reading from file second-2-0.pcap, link-type EN10MB (Ethernet)
- 2.003696 arp who-has 10.1.2.4 (ff:ff:ff:ff:ff:ff) tell 10.1.2.1
- 2.003707 arp reply 10.1.2.4 is-at 00:00:00:00:00:06
- 2.003801 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024
- 2.003811 arp who-has 10.1.2.1 (ff:ff:ff:ff:ff:ff) tell 10.1.2.4
- 2.003822 arp reply 10.1.2.1 is-at 00:00:00:00:00:03
- 2.003915 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024
-@end verbatim
-
-As you can see, the link type is now ``Ethernet''. Something new has appeared,
-though. The bus network needs @code{ARP}, the Address Resolution Protocol.
-Node one knows it needs to send the packet to IP address 10.1.2.4, but it
-doesn't know the MAC address of the corresponding node. It broadcasts on the
-CSMA network (ff:ff:ff:ff:ff:ff) asking for the device that has IP address
-10.1.2.4. In this case, the rightmost node replies saying it is at MAC address
-00:00:00:00:00:06. Note that node two is not directly involved in this
-exchange, but is sniffing the network and reporting all of the traffic it sees.
-
-This exchange is seen in the following lines,
-
-@verbatim
- 2.003696 arp who-has 10.1.2.4 (ff:ff:ff:ff:ff:ff) tell 10.1.2.1
- 2.003707 arp reply 10.1.2.4 is-at 00:00:00:00:00:06
-@end verbatim
-
-Then node one, device one goes ahead and sends the echo packet to the UDP echo
-server at IP address 10.1.2.4.
-
-@verbatim
- 2.003801 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024
-@end verbatim
-
-The server receives the echo request and turns the packet around trying to send
-it back to the source. The server knows that this address is on another network
-that it reaches via IP address 10.1.2.1. This is because we initialized global
-routing and it has figured all of this out for us. But, the echo server node
-doesn't know the MAC address of the first CSMA node, so it has to ARP for it
-just like the first CSMA node had to do.
-
-@verbatim
- 2.003811 arp who-has 10.1.2.1 (ff:ff:ff:ff:ff:ff) tell 10.1.2.4
- 2.003822 arp reply 10.1.2.1 is-at 00:00:00:00:00:03
-@end verbatim
-
-The server then sends the echo back to the forwarding node.
-
-@verbatim
- 2.003915 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024
-@end verbatim
-
-Looking back at the rightmost node of the point-to-point link,
-
-@verbatim
- tcpdump -nn -tt -r second-1-0.pcap
-@end verbatim
-
-You can now see the echoed packet coming back onto the point-to-point link as
-the last line of the trace dump.
-
-@verbatim
-reading from file second-1-0.pcap, link-type PPP (PPP)
-2.003686 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024
-2.003915 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024
-@end verbatim
-
-Lastly, you can look back at the node that originated the echo
-@verbatim
- tcpdump -nn -tt -r second-0-0.pcap
-@end verbatim
-
-and see that the echoed packet arrives back at the source at 2.007602 seconds,
-
-@verbatim
- reading from file second-0-0.pcap, link-type PPP (PPP)
- 2.000000 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024
- 2.007602 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024
-@end verbatim
-
-Finally, recall that we added the ability to control the number of CSMA devices
-in the simulation by command line argument. You can change this argument in
-the same way as when we looked at changing the number of packets echoed in the
-@code{first.cc} example. Try running the program with the number of ``extra''
-devices set to four:
-
-@verbatim
- ./waf --run "scratch/mysecond --nCsma=4"
-@end verbatim
-
-You should now see,
-
-@verbatim
- Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
- Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
- 'build' finished successfully (0.405s)
- Sent 1024 bytes to 10.1.2.5
- Received 1024 bytes from 10.1.1.1
- Received 1024 bytes from 10.1.2.5
-@end verbatim
-
-Notice that the echo server has now been relocated to the last of the CSMA
-nodes, which is 10.1.2.5 instead of the default case, 10.1.2.4.
-
-It is possible that you may not be satisfied with a trace file generated by
-a bystander in the CSMA network. You may really want to get a trace from
-a single device and you may not be interested in any other traffic on the
-network. You can do this fairly easily.
-
-Let's take a look at @code{scratch/mysecond.cc} and add that code enabling us
-to be more specific. @code{ns-3} helpers provide methods that take a node
-number and device number as parameters. Go ahead and replace the
-@code{EnablePcap} calls with the calls below.
-
-@verbatim
- pointToPoint.EnablePcap ("second", p2pNodes.Get (0)->GetId (), 0);
- csma.EnablePcap ("second", csmaNodes.Get (nCsma)->GetId (), 0, false);
- csma.EnablePcap ("second", csmaNodes.Get (nCsma-1)->GetId (), 0, false);
-@end verbatim
-
-We know that we want to create a pcap file with the base name "second" and
-we also know that the device of interest in both cases is going to be zero,
-so those parameters are not really interesting.
-
-In order to get the node number, you have two choices: first, nodes are
-numbered in a monotonically increasing fashion starting from zero in the
-order in which you created them. One way to get a node number is to figure
-this number out ``manually'' by contemplating the order of node creation.
-If you take a look at the network topology illustration at the beginning of
-the file, we did this for you and you can see that the last CSMA node is
-going to be node number @code{nCsma + 1}. This approach can become
-annoyingly difficult in larger simulations.
-
-An alternate way, which we use here, is to realize that the
-@code{NodeContainers} contain pointers to @command{ns-3} @code{Node} Objects.
-The @code{Node} Object has a method called @code{GetId} which will return that
-node's ID, which is the node number we seek. Let's go take a look at the
-Doxygen for the @code{Node} and locate that method, which is further down in
-the @command{ns-3} core code than we've seen so far; but sometimes you have to
-search diligently for useful things.
-
-Go to the Doxygen documentation for your release (recall that you can find it
-on the project web site). You can get to the @code{Node} documentation by
-looking through at the ``Classes'' tab and scrolling down the ``Class List''
-until you find @code{ns3::Node}. Select @code{ns3::Node} and you will be taken
-to the documentation for the @code{Node} class. If you now scroll down to the
-@code{GetId} method and select it, you will be taken to the detailed
-documentation for the method. Using the @code{GetId} method can make
-determining node numbers much easier in complex topologies.
-
-Let's clear the old trace files out of the top-level directory to avoid confusion
-about what is going on,
-
-@verbatim
- rm *.pcap
- rm *.tr
-@end verbatim
-
-If you build the new script and run the simulation setting @code{nCsma} to 100,
-
-@verbatim
- ./waf --run "scratch/mysecond --nCsma=100"
-@end verbatim
-
-you will see the following output:
-
-@verbatim
- Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
- Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
- 'build' finished successfully (0.407s)
- Sent 1024 bytes to 10.1.2.101
- Received 1024 bytes from 10.1.1.1
- Received 1024 bytes from 10.1.2.101
-@end verbatim
-
-Note that the echo server is now located at 10.1.2.101 which corresponds to
-having 100 ``extra'' CSMA nodes with the echo server on the last one. If you
-list the pcap files in the top level directory you will see,
-
-@verbatim
- second-0-0.pcap second-100-0.pcap second-101-0.pcap
-@end verbatim
-
-The trace file @code{second-0-0.pcap} is the ``leftmost'' point-to-point device
-which is the echo packet source. The file @code{second-101-0.pcap} corresponds
-to the rightmost CSMA device which is where the echo server resides. You may
-have noticed that the final parameter on the call to enable pcap tracing on the
-echo server node was false. This means that the trace gathered on that node
-was in non-promiscuous mode.
-
-To illustrate the difference between promiscuous and non-promiscuous traces, we
-also requested a non-promiscuous trace for the next-to-last node. Go ahead and
-take a look at the @code{tcpdump} for @code{second-100-0.pcap}.
-
-@verbatim
- tcpdump -nn -tt -r second-100-0.pcap
-@end verbatim
-
-You can now see that node 100 is really a bystander in the echo exchange. The
-only packets that it receives are the ARP requests which are broadcast to the
-entire CSMA network.
-
-@verbatim
- reading from file second-100-0.pcap, link-type EN10MB (Ethernet)
- 2.003696 arp who-has 10.1.2.101 (ff:ff:ff:ff:ff:ff) tell 10.1.2.1
- 2.003811 arp who-has 10.1.2.1 (ff:ff:ff:ff:ff:ff) tell 10.1.2.101
-@end verbatim
-
-Now take a look at the @code{tcpdump} for @code{second-101-0.pcap}.
-
-@verbatim
- tcpdump -nn -tt -r second-101-0.pcap
-@end verbatim
-
-You can now see that node 101 is really the participant in the echo exchange.
-
-@verbatim
- reading from file second-101-0.pcap, link-type EN10MB (Ethernet)
- 2.003696 arp who-has 10.1.2.101 (ff:ff:ff:ff:ff:ff) tell 10.1.2.1
- 2.003696 arp reply 10.1.2.101 is-at 00:00:00:00:00:67
- 2.003801 IP 10.1.1.1.49153 > 10.1.2.101.9: UDP, length 1024
- 2.003801 arp who-has 10.1.2.1 (ff:ff:ff:ff:ff:ff) tell 10.1.2.101
- 2.003822 arp reply 10.1.2.1 is-at 00:00:00:00:00:03
- 2.003822 IP 10.1.2.101.9 > 10.1.1.1.49153: UDP, length 1024
-@end verbatim
-
-@c ========================================================================
-@c Models, Attributes and Reality
-@c ========================================================================
-@node Models, Attributes and Reality
-@section Models, Attributes and Reality
-
-This is a convenient place to make a small excursion and make an important
-point. It may or may not be obvious to you, but whenever one is using a
-simulation, it is important to understand exactly what is being modeled and
-what is not. It is tempting, for example, to think of the CSMA devices
-and channels used in the previous section as if they were real Ethernet
-devices; and to expect a simulation result to directly reflect what will
-happen in a real Ethernet. This is not the case.
-
-A model is, by definition, an abstraction of reality. It is ultimately the
-responsibility of the simulation script author to determine the so-called
-``range of accuracy'' and ``domain of applicability'' of the simulation as
-a whole, and therefore its constituent parts.
-
-In some cases, like @code{Csma}, it can be fairly easy to determine what is
-@emph{not} modeled. By reading the model description (@code{csma.h}) you
-can find that there is no collision detection in the CSMA model and decide
-on how applicable its use will be in your simulation or what caveats you
-may want to include with your results. In other cases, it can be quite easy
-to configure behaviors that might not agree with any reality you can go out
-and buy. It will prove worthwhile to spend some time investigating a few
-such instances, and how easily you can swerve outside the bounds of reality
-in your simulations.
-
-As you have seen, @command{ns-3} provides @code{Attributes} which a user
-can easily set to change model behavior. Consider two of the @code{Attributes}
-of the @code{CsmaNetDevice}: @code{Mtu} and @code{EncapsulationMode}.
-The @code{Mtu} attribute indicates the Maximum Transmission Unit to the
-device. This is the size of the largest Protocol Data Unit (PDU) that the
-device can send.
-
-The MTU defaults to 1500 bytes in the @code{CsmaNetDevice}. This default
-corresponds to a number found in RFC 894, ``A Standard for the Transmission
-of IP Datagrams over Ethernet Networks.'' The number is actually derived
-from the maximum packet size for 10Base5 (full-spec Ethernet) networks --
-1518 bytes. If you subtract the DIX encapsulation overhead for Ethernet
-packets (18 bytes) you will end up with a maximum possible data size (MTU)
-of 1500 bytes. One can also find that the @code{MTU} for IEEE 802.3 networks
-is 1492 bytes. This is because LLC/SNAP encapsulation adds an extra eight
-bytes of overhead to the packet. In both cases, the underlying hardware can
-only send 1518 bytes, but the data size is different.
-
-In order to set the encapsulation mode, the @code{CsmaNetDevice} provides
-an @code{Attribute} called @code{EncapsulationMode} which can take on the
-values @code{Dix} or @code{Llc}. These correspond to Ethernet and LLC/SNAP
-framing respectively.
-
-If one leaves the @code{Mtu} at 1500 bytes and changes the encapsulation mode
-to @code{Llc}, the result will be a network that encapsulates 1500 byte PDUs
-with LLC/SNAP framing resulting in packets of 1526 bytes, which would be
-illegal in many networks, since they can transmit a maximum of 1518 bytes per
-packet. This would most likely result in a simulation that quite subtly does
-not reflect the reality you might be expecting.
-
-Just to complicate the picture, there exist jumbo frames (1500 < MTU <= 9000 bytes)
-and super-jumbo (MTU > 9000 bytes) frames that are not officially sanctioned
-by IEEE but are available in some high-speed (Gigabit) networks and NICs. One
-could leave the encapsulation mode set to @code{Dix}, and set the @code{Mtu}
-@code{Attribute} on a @code{CsmaNetDevice} to 64000 bytes -- even though an
-associated @code{CsmaChannel DataRate} was set at 10 megabits per second.
-This would essentially model an Ethernet switch made out of vampire-tapped
-1980s-style 10Base5 networks that support super-jumbo datagrams. This is
-certainly not something that was ever made, nor is likely to ever be made,
-but it is quite easy for you to configure.
-
-In the previous example, you used the command line to create a simulation that
-had 100 @code{Csma} nodes. You could have just as easily created a simulation
-with 500 nodes. If you were actually modeling that 10Base5 vampire-tap network,
-the maximum length of a full-spec Ethernet cable is 500 meters, with a minimum
-tap spacing of 2.5 meters. That means there could only be 200 taps on a
-real network. You could have quite easily built an illegal network in that
-way as well. This may or may not result in a meaningful simulation depending
-on what you are trying to model.
-
-Similar situations can occur in many places in @command{ns-3} and in any
-simulator. For example, you may be able to position nodes in such a way that
-they occupy the same space at the same time, or you may be able to configure
-amplifiers or noise levels that violate the basic laws of physics.
-
-@command{ns-3} generally favors flexibility, and many models will allow freely
-setting @code{Attributes} without trying to enforce any arbitrary consistency
-or particular underlying spec.
-
-The thing to take home from this is that @command{ns-3} is going to provide a
-super-flexible base for you to experiment with. It is up to you to understand
-what you are asking the system to do and to make sure that the simulations you
-create have some meaning and some connection with a reality defined by you.
-
-@c ========================================================================
-@c Building a Wireless Network Topology
-@c ========================================================================
-@node Building a Wireless Network Topology
-@section Building a Wireless Network Topology
-
-@cindex topology
-@cindex wireless network topology
-In this section we are going to further expand our knowledge of @command{ns-3}
-network devices and channels to cover an example of a wireless network.
-@command{Ns-3} provides a set of 802.11 models that attempt to provide an
-accurate MAC-level implementation of the 802.11 specification and a
-``not-so-slow'' PHY-level model of the 802.11a specification.
-
-Just as we have seen both point-to-point and CSMA topology helper objects when
-constructing point-to-point topologies, we will see equivalent @code{Wifi}
-topology helpers in this section. The appearance and operation of these
-helpers should look quite familiar to you.
-
-We provide an example script in our @code{examples/tutorial} directory. This script
-builds on the @code{second.cc} script and adds a Wifi network. Go ahead and
-open @code{examples/tutorial/third.cc} in your favorite editor. You will have already
-seen enough @command{ns-3} code to understand most of what is going on in
-this example, but there are a few new things, so we will go over the entire
-script and examine some of the output.
-
-Just as in the @code{second.cc} example (and in all @command{ns-3} examples)
-the file begins with an emacs mode line and some GPL boilerplate.
-
-Take a look at the ASCII art (reproduced below) that shows the default network
-topology constructed in the example. You can see that we are going to
-further extend our example by hanging a wireless network off of the left side.
-Notice that this is a default network topology since you can actually vary the
-number of nodes created on the wired and wireless networks. Just as in the
-@code{second.cc} script case, if you change @code{nCsma}, it will give you a
-number of ``extra'' CSMA nodes. Similarly, you can set @code{nWifi} to
-control how many @code{STA} (station) nodes are created in the simulation.
-There will always be one @code{AP} (access point) node on the wireless
-network. By default there are three ``extra'' CSMA nodes and three wireless
-@code{STA} nodes.
-
-The code begins by loading module include files just as was done in the
-@code{second.cc} example. There are a couple of new includes corresponding
-to the Wifi module and the mobility module which we will discuss below.
-
-@verbatim
-#include "ns3/core-module.h"
-#include "ns3/simulator-module.h"
-#include "ns3/node-module.h"
-#include "ns3/helper-module.h"
-#include "ns3/wifi-module.h"
-#include "ns3/mobility-module.h"
-@end verbatim
-
-The network topology illustration follows:
-
-@verbatim
- // Default Network Topology
- //
- // Wifi 10.1.3.0
- // AP
- // * * * *
- // | | | | 10.1.1.0
- // n5 n6 n7 n0 -------------- n1 n2 n3 n4
- // point-to-point | | | |
- // ================
- // LAN 10.1.2.0
-@end verbatim
-
-You can see that we are adding a new network device to the node on the left
-side of the point-to-point link that becomes the access point for the wireless
-network. A number of wireless STA nodes are created to fill out the new
-10.1.3.0 network as shown on the left side of the illustration.
-
-After the illustration, the @code{ns-3} namespace is @code{used} and a logging
-component is defined. This should all be quite familiar by now.
-
-@verbatim
- using namespace ns3;
-
- NS_LOG_COMPONENT_DEFINE ("ThirdScriptExample");
-@end verbatim
-
-The main program begins just like @code{second.cc} by adding some command line
-parameters for enabling or disabling logging components and for changing the
-number of devices created.
-
-@verbatim
- bool verbose = true;
- uint32_t nCsma = 3;
- uint32_t nWifi = 3;
-
- CommandLine cmd;
- cmd.AddValue (``nCsma'', ``Number of \"extra\" CSMA nodes/devices'', nCsma);
- cmd.AddValue (``nWifi'', ``Number of wifi STA devices'', nWifi);
- cmd.AddValue (``verbose'', ``Tell echo applications to log if true'', verbose);
-
- cmd.Parse (argc,argv);
-
- if (verbose)
- {
- LogComponentEnable(``UdpEchoClientApplication'', LOG_LEVEL_INFO);
- LogComponentEnable(``UdpEchoServerApplication'', LOG_LEVEL_INFO);
- }
-@end verbatim
-
-Just as in all of the previous examples, the next step is to create two nodes
-that we will connect via the point-to-point link.
-
-@verbatim
- NodeContainer p2pNodes;
- p2pNodes.Create (2);
-@end verbatim
-
-Next, we see an old friend. We instantiate a @code{PointToPointHelper} and
-set the associated default @code{Attributes} so that we create a five megabit
-per second transmitter on devices created using the helper and a two millisecond
-delay on channels created by the helper. We then @code{Intall} the devices
-on the nodes and the channel between them.
-
-@verbatim
- PointToPointHelper pointToPoint;
- pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
- pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
-
- NetDeviceContainer p2pDevices;
- p2pDevices = pointToPoint.Install (p2pNodes);
-@end verbatim
-
-Next, we declare another @code{NodeContainer} to hold the nodes that will be
-part of the bus (CSMA) network.
-
-@verbatim
- NodeContainer csmaNodes;
- csmaNodes.Add (p2pNodes.Get (1));
- csmaNodes.Create (nCsma);
-@end verbatim
-
-The next line of code @code{Gets} the first node (as in having an index of one)
-from the point-to-point node container and adds it to the container of nodes
-that will get CSMA devices. The node in question is going to end up with a
-point-to-point device and a CSMA device. We then create a number of ``extra''
-nodes that compose the remainder of the CSMA network.
-
-We then instantiate a @code{CsmaHelper} and set its @code{Attributes} as we did
-in the previous example. We create a @code{NetDeviceContainer} to keep track of
-the created CSMA net devices and then we @code{Install} CSMA devices on the
-selected nodes.
-
-@verbatim
- CsmaHelper csma;
- csma.SetChannelAttribute ("DataRate", StringValue ("100Mbps"));
- csma.SetChannelAttribute ("Delay", TimeValue (NanoSeconds (6560)));
-
- NetDeviceContainer csmaDevices;
- csmaDevices = csma.Install (csmaNodes);
-@end verbatim
-
-Next, we are going to create the nodes that will be part of the Wifi network.
-We are going to create a number of ``station'' nodes as specified by the
-command line argument, and we are going to use the ``leftmost'' node of the
-point-to-point link as the node for the access point.
-
-@verbatim
- NodeContainer wifiStaNodes;
- wifiStaNodes.Create (nWifi);
- NodeContainer wifiApNode = p2pNodes.Get (0);
-@end verbatim
-
-The next bit of code constructs the wifi devices and the interconnection
-channel between these wifi nodes. First, we configure the PHY and channel
-helpers:
-
-@verbatim
- YansWifiChannelHelper channel = YansWifiChannelHelper::Default ();
- YansWifiPhyHelper phy = YansWifiPhyHelper::Default ();
-@end verbatim
-
-For simplicity, this code uses the default PHY layer configuration and
-channel models which are documented in the API doxygen documentation for
-the @code{YansWifiChannelHelper::Default} and @code{YansWifiPhyHelper::Default}
-methods. Once these objects are created, we create a channel object
-and associate it to our PHY layer object manager to make sure
-that all the PHY layer objects created by the @code{YansWifiPhyHelper}
-share the same underlying channel, that is, they share the same
-wireless medium and can communication and interfere:
-
-@verbatim
- phy.SetChannel (channel.Create ());
-@end verbatim
-
-Once the PHY helper is configured, we can focus on the MAC layer. Here we choose to
-work with non-Qos MACs so we use a NqosWifiMacHelper object to set MAC parameters.
-
-@verbatim
- WifiHelper wifi = WifiHelper::Default ();
- wifi.SetRemoteStationManager ("ns3::AarfWifiManager");
-
- NqosWifiMacHelper mac = NqosWifiMacHelper::Default ();
-@end verbatim
-
-The @code{SetRemoteStationManager} method tells the helper the type of
-rate control algorithm to use. Here, it is asking the helper to use the AARF
-algorithm --- details are, of course, available in Doxygen.
-
-Next, we configure the type of MAC, the SSID of the infrastructure network we
-want to setup and make sure that our stations don't perform active probing:
-
-@verbatim
- Ssid ssid = Ssid ("ns-3-ssid");
- mac.SetType ("ns3::StaWifiMac",
- "Ssid", SsidValue (ssid),
- "ActiveProbing", BooleanValue (false));
-@end verbatim
-
-This code first creates an 802.11 service set identifier (SSID) object
-that will be used to set the value of the ``Ssid'' @code{Attribute} of
-the MAC layer implementation. The particular kind of MAC layer that
-will be created by the helper is specified by @code{Attribute} as
-being of the "ns3::StaWifiMac" type. The use of
-@code{NqosWifiMacHelper} will ensure that the ''QosSupported''
-@code{Attribute} for created MAC objects is set false. The combination
-of these two configurations means that the MAC instance next created
-will be a non-QoS non-AP station (STA) in an infrastructure BSS (i.e.,
-a BSS with an AP). Finally, the ``ActiveProbing'' @code{Attribute} is
-set to false. This means that probe requests will not be sent by MACs
-created by this helper.
-
-Once all the station-specific parameters are fully configured, both at the
-MAC and PHY layers, we can invoke our now-familiar @code{Install} method to
-create the wifi devices of these stations:
-
-@verbatim
- NetDeviceContainer staDevices;
- staDevices = wifi.Install (phy, mac, wifiStaNodes);
-@end verbatim
-
-We have configured Wifi for all of our STA nodes, and now we need to
-configure the AP (access point) node. We begin this process by changing
-the default @code{Attributes} of the @code{NqosWifiMacHelper} to reflect the
-requirements of the AP.
-
-@verbatim
- mac.SetType ("ns3::ApWifiMac",
- "Ssid", SsidValue (ssid),
- "BeaconGeneration", BooleanValue (true),
- "BeaconInterval", TimeValue (Seconds (2.5)));
-@end verbatim
-
-In this case, the @code{NqosWifiMacHelper} is going to create MAC
-layers of the ``ns3::ApWifiMac'', the latter specifying that a MAC
-instance configured as an AP should be created, with the helper type
-implying that the ''QosSupported'' @code{Attribute} should be set to
-false - disabling 802.11e/WMM-style QoS support at created APs. We
-set the ``BeaconGeneration'' @code{Attribute} to true and also set an
-interval between beacons of 2.5 seconds.
-
-The next lines create the single AP which shares the same set of PHY-level
-@code{Attributes} (and channel) as the stations:
-
-@verbatim
- NetDeviceContainer apDevices;
- apDevices = wifi.Install (phy, mac, wifiApNode);
-@end verbatim
-
-Now, we are going to add mobility models. We want the STA nodes to be mobile,
-wandering around inside a bounding box, and we want to make the AP node
-stationary. We use the @code{MobilityHelper} to make this easy for us.
-First, we instantiate a @code{MobilityHelper} object and set some
-@code{Attributes} controlling the ``position allocator'' functionality.
-
-@verbatim
- MobilityHelper mobility;
-
- mobility.SetPositionAllocator ("ns3::GridPositionAllocator",
- "MinX", DoubleValue (0.0),
- "MinY", DoubleValue (0.0),
- "DeltaX", DoubleValue (5.0),
- "DeltaY", DoubleValue (10.0),
- "GridWidth", UintegerValue (3),
- "LayoutType", StringValue ("RowFirst"));
-@end verbatim
-
-This code tells the mobility helper to use a two-dimensional grid to initially
-place the STA nodes. Feel free to explore the Doxygen for class
-@code{ns3::GridPositionAllocator} to see exactly what is being done.
-
-We have arranged our nodes on an initial grid, but now we need to tell them
-how to move. We choose the @code{RandomWalk2dMobilityModel} which has the
-nodes move in a random direction at a random speed around inside a bounding
-box.
-
-@verbatim
- mobility.SetMobilityModel ("ns3::RandomWalk2dMobilityModel",
- "Bounds", RectangleValue (Rectangle (-50, 50, -50, 50)));
-@end verbatim
-
-We now tell the @code{MobilityHelper} to install the mobility models on the
-STA nodes.
-
-@verbatim
- mobility.Install (wifiStaNodes);
-@end verbatim
-
-We want the access point to remain in a fixed position during the simulation.
-We accomplish this by setting the mobility model for this node to be the
-@code{ns3::ConstantPositionMobilityModel}:
-
-@verbatim
- mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
- mobility.Install (wifiApNode);
-@end verbatim
-
-We now have our nodes, devices and channels created, and mobility models
-chosen for the Wifi nodes, but we have no protocol stacks present. Just as
-we have done previously many times, we will use the @code{InternetStackHelper}
-to install these stacks.
-
-@verbatim
- InternetStackHelper stack;
- stack.Install (csmaNodes);
- stack.Install (wifiApNode);
- stack.Install (wifiStaNodes);
-@end verbatim
-
-Just as in the @code{second.cc} example script, we are going to use the
-@code{Ipv4AddressHelper} to assign IP addresses to our device interfaces.
-First we use the network 10.1.1.0 to create the two addresses needed for our
-two point-to-point devices. Then we use network 10.1.2.0 to assign addresses
-to the CSMA network and then we assign addresses from network 10.1.3.0 to
-both the STA devices and the AP on the wireless network.
-
-@verbatim
- Ipv4AddressHelper address;
-
- address.SetBase ("10.1.1.0", "255.255.255.0");
- Ipv4InterfaceContainer p2pInterfaces;
- p2pInterfaces = address.Assign (p2pDevices);
-
- address.SetBase ("10.1.2.0", "255.255.255.0");
- Ipv4InterfaceContainer csmaInterfaces;
- csmaInterfaces = address.Assign (csmaDevices);
-
- address.SetBase ("10.1.3.0", "255.255.255.0");
- address.Assign (staDevices);
- address.Assign (apDevices);
-@end verbatim
-
-We put the echo server on the ``rightmost'' node in the illustration at the
-start of the file. We have done this before.
-
-@verbatim
- UdpEchoServerHelper echoServer (9);
-
- ApplicationContainer serverApps = echoServer.Install (csmaNodes.Get (nCsma));
- serverApps.Start (Seconds (1.0));
- serverApps.Stop (Seconds (10.0));
-@end verbatim
-
-And we put the echo client on the last STA node we created, pointing it to
-the server on the CSMA network. We have also seen similar operations before.
-
-@verbatim
- UdpEchoClientHelper echoClient (csmaInterfaces.GetAddress (nCsma), 9);
- echoClient.SetAttribute ("MaxPackets", UintegerValue (1));
- echoClient.SetAttribute ("Interval", TimeValue (Seconds (1.)));
- echoClient.SetAttribute ("PacketSize", UintegerValue (1024));
-
- ApplicationContainer clientApps =
- echoClient.Install (wifiStaNodes.Get (nWifi - 1));
- clientApps.Start (Seconds (2.0));
- clientApps.Stop (Seconds (10.0));
-@end verbatim
-
-Since we have built an internetwork here, we need to enable internetwork routing
-just as we did in the @code{second.cc} example script.
-
-@verbatim
- Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
-@end verbatim
-
-One thing that can surprise some users is the fact that the simulation we just
-created will never ``naturally'' stop. This is because we asked the wireless
-access point to generate beacons. It will generate beacons forever, and this
-will result in simulator events being scheduled into the future indefinitely,
-so we must tell the simulator to stop even though it may have beacon generation
-events scheduled. The following line of code tells the simulator to stop so that
-we don't simulate beacons forever and enter what is essentially an endless
-loop.
-
-@verbatim
- Simulator::Stop (Seconds (10.0));
-@end verbatim
-
-We create just enough tracing to cover all three networks:
-
-@verbatim
- pointToPoint.EnablePcapAll ("third");
- phy.EnablePcap ("third", apDevices.Get (0));
- csma.EnablePcap ("third", csmaDevices.Get (0), true);
-@end verbatim
-
-These three lines of code will start pcap tracing on both of the point-to-point
-nodes that serves as our backbone, will start a promiscuous (monitor) mode
-trace on the Wifi network, and will start a promiscuous trace on the CSMA
-network. This will let us see all of the traffic with a minimum number of
-trace files.
-
-Finally, we actually run the simulation, clean up and then exit the program.
-
-@verbatim
- Simulator::Run ();
- Simulator::Destroy ();
- return 0;
- }
-@end verbatim
-
-In order to run this example, you have to copy the @code{third.cc} example
-script into the scratch directory and use Waf to build just as you did with
-the @code{second.cc} example. If you are in the top-level directory of the
-repository you would type,
-
-@verbatim
- cp examples/third.cc scratch/mythird.cc
- ./waf
- ./waf --run scratch/mythird
-@end verbatim
-
-Again, since we have set up the UDP echo applications just as we did in the
-@code{second.cc} script, you will see similar output.
-
-@verbatim
- Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
- Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
- 'build' finished successfully (0.407s)
- Sent 1024 bytes to 10.1.2.4
- Received 1024 bytes from 10.1.3.3
- Received 1024 bytes from 10.1.2.4
-@end verbatim
-
-Recall that the first message, ``@code{Sent 1024 bytes to 10.1.2.4},'' is the
-UDP echo client sending a packet to the server. In this case, the client
-is on the wireless network (10.1.3.0). The second message,
-``@code{Received 1024 bytes from 10.1.3.3},'' is from the UDP echo server,
-generated when it receives the echo packet. The final message,
-``@code{Received 1024 bytes from 10.1.2.4},'' is from the echo client, indicating
-that it has received its echo back from the server.
-
-If you now go and look in the top level directory, you will find four trace
-files from this simulation, two from node zero and two from node one:
-
-@verbatim
-third-0-0.pcap third-0-1.pcap third-1-0.pcap third-1-1.pcap
-@end verbatim
-
-The file ``third-0-0.pcap'' corresponds to the point-to-point device on node
-zero -- the left side of the ``backbone''. The file ``third-1-0.pcap''
-corresponds to the point-to-point device on node one -- the right side of the
-``backbone''. The file ``third-0-1.pcap'' will be the promiscuous (monitor
-mode) trace from the Wifi network and the file ``third-1-1.pcap'' will be the
-promiscuous trace from the CSMA network. Can you verify this by inspecting
-the code?
-
-Since the echo client is on the Wifi network, let's start there. Let's take
-a look at the promiscuous (monitor mode) trace we captured on that network.
-
-@verbatim
- tcpdump -nn -tt -r third-0-1.pcap
-@end verbatim
-
-You should see some wifi-looking contents you haven't seen here before:
-
-@verbatim
- reading from file third-0-1.pcap, link-type IEEE802_11 (802.11)
- 0.000025 Beacon () [6.0* 9.0 12.0 18.0 24.0 36.0 48.0 54.0 Mbit] IBSS
- 0.000263 Assoc Request () [6.0 9.0 12.0 18.0 24.0 36.0 48.0 54.0 Mbit]
- 0.000279 Acknowledgment RA:00:00:00:00:00:07
- 0.000357 Assoc Response AID(0) :: Succesful
- 0.000501 Acknowledgment RA:00:00:00:00:00:0a
- 0.000748 Assoc Request () [6.0 9.0 12.0 18.0 24.0 36.0 48.0 54.0 Mbit]
- 0.000764 Acknowledgment RA:00:00:00:00:00:08
- 0.000842 Assoc Response AID(0) :: Succesful
- 0.000986 Acknowledgment RA:00:00:00:00:00:0a
- 0.001242 Assoc Request () [6.0 9.0 12.0 18.0 24.0 36.0 48.0 54.0 Mbit]
- 0.001258 Acknowledgment RA:00:00:00:00:00:09
- 0.001336 Assoc Response AID(0) :: Succesful
- 0.001480 Acknowledgment RA:00:00:00:00:00:0a
- 2.000112 arp who-has 10.1.3.4 (ff:ff:ff:ff:ff:ff) tell 10.1.3.3
- 2.000128 Acknowledgment RA:00:00:00:00:00:09
- 2.000206 arp who-has 10.1.3.4 (ff:ff:ff:ff:ff:ff) tell 10.1.3.3
- 2.000487 arp reply 10.1.3.4 is-at 00:00:00:00:00:0a
- 2.000659 Acknowledgment RA:00:00:00:00:00:0a
- 2.002169 IP 10.1.3.3.49153 > 10.1.2.4.9: UDP, length 1024
- 2.002185 Acknowledgment RA:00:00:00:00:00:09
- 2.009771 arp who-has 10.1.3.3 (ff:ff:ff:ff:ff:ff) tell 10.1.3.4
- 2.010029 arp reply 10.1.3.3 is-at 00:00:00:00:00:09
- 2.010045 Acknowledgment RA:00:00:00:00:00:09
- 2.010231 IP 10.1.2.4.9 > 10.1.3.3.49153: UDP, length 1024
- 2.011767 Acknowledgment RA:00:00:00:00:00:0a
- 2.500000 Beacon () [6.0* 9.0 12.0 18.0 24.0 36.0 48.0 54.0 Mbit] IBSS
- 5.000000 Beacon () [6.0* 9.0 12.0 18.0 24.0 36.0 48.0 54.0 Mbit] IBSS
- 7.500000 Beacon () [6.0* 9.0 12.0 18.0 24.0 36.0 48.0 54.0 Mbit] IBSS
-@end verbatim
-
-You can see that the link type is now 802.11 as you would expect. You can
-probably understand what is going on and find the IP echo request and response
-packets in this trace. We leave it as an exercise to completely parse the
-trace dump.
-
-Now, look at the pcap file of the right side of the point-to-point link,
-
-@verbatim
- tcpdump -nn -tt -r third-0-0.pcap
-@end verbatim
-
-Again, you should see some familiar looking contents:
-
-@verbatim
- reading from file third-0-0.pcap, link-type PPP (PPP)
- 2.002169 IP 10.1.3.3.49153 > 10.1.2.4.9: UDP, length 1024
- 2.009771 IP 10.1.2.4.9 > 10.1.3.3.49153: UDP, length 1024
-@end verbatim
-
-This is the echo packet going from left to right (from Wifi to CSMA) and back
-again across the point-to-point link.
-
-Now, look at the pcap file of the right side of the point-to-point link,
-
-@verbatim
- tcpdump -nn -tt -r third-1-0.pcap
-@end verbatim
-
-Again, you should see some familiar looking contents:
-
-@verbatim
- reading from file third-1-0.pcap, link-type PPP (PPP)
- 2.005855 IP 10.1.3.3.49153 > 10.1.2.4.9: UDP, length 1024
- 2.006084 IP 10.1.2.4.9 > 10.1.3.3.49153: UDP, length 1024
-@end verbatim
-
-This is also the echo packet going from left to right (from Wifi to CSMA) and
-back again across the point-to-point link with slightly different timings
-as you might expect.
-
-The echo server is on the CSMA network, let's look at the promiscuous trace
-there:
-
-@verbatim
- tcpdump -nn -tt -r third-1-1.pcap
-@end verbatim
-
-You should see some familiar looking contents:
-
-@verbatim
- reading from file third-1-1.pcap, link-type EN10MB (Ethernet)
- 2.005855 arp who-has 10.1.2.4 (ff:ff:ff:ff:ff:ff) tell 10.1.2.1
- 2.005877 arp reply 10.1.2.4 is-at 00:00:00:00:00:06
- 2.005877 IP 10.1.3.3.49153 > 10.1.2.4.9: UDP, length 1024
- 2.005980 arp who-has 10.1.2.1 (ff:ff:ff:ff:ff:ff) tell 10.1.2.4
- 2.005980 arp reply 10.1.2.1 is-at 00:00:00:00:00:03
- 2.006084 IP 10.1.2.4.9 > 10.1.3.3.49153: UDP, length 1024
-@end verbatim
-
-This should be easily understood. If you've forgotten, go back and look at
-the discussion in @code{second.cc}. This is the same sequence.
-
-Now, we spent a lot of time setting up mobility models for the wireless network
-and so it would be a shame to finish up without even showing that the STA
-nodes are actually moving around during the simulation. Let's do this by hooking
-into the @code{MobilityModel} course change trace source. This is just a sneak
-peek into the detailed tracing section which is coming up, but this seems a very
-nice place to get an example in.
-
-As mentioned in the ``Tweaking ns-3'' section, the @command{ns-3} tracing system
-is divided into trace sources and trace sinks, and we provide functions to
-connect the two. We will use the mobility model predefined course change
-trace source to originate the trace events. We will need to write a trace
-sink to connect to that source that will display some pretty information for
-us. Despite its reputation as being difficult, it's really quite simple.
-Just before the main program of the @code{scratch/mythird.cc} script, add the
-following function:
-
-@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
-
-This code just pulls the position information from the mobility model and
-unconditionally logs the x and y position of the node. We are
-going to arrange for this function to be called every time the wireless
-node with the echo client changes its position. We do this using the
-@code{Config::Connect} function. Add the following lines of code to the
-script just before the @code{Simulator::Run} call.
-
-@verbatim
- std::ostringstream oss;
- oss <<
- "/NodeList/" << wifiStaNodes.Get (nWifi - 1)->GetId () <<
- "/$ns3::MobilityModel/CourseChange";
-
- Config::Connect (oss.str (), MakeCallback (&CourseChange));
-@end verbatim
-
-What we do here is to create a string containing the tracing namespace path
-of the event to which we want to connect. First, we have to figure out which
-node it is we want using the @code{GetId} method as described earlier. In the
-case of the default number of CSMA and wireless nodes, this turns out to be
-node seven and the tracing namespace path to the mobility model would look
-like,
-
-@verbatim
- /NodeList/7/$ns3::MobilityModel/CourseChange
-@end verbatim
-
-Based on the discussion in the tracing section, you may infer that this trace
-path references the seventh node in the global NodeList. It specifies
-what is called an aggregated object of type @code{ns3::MobilityModel}. The
-dollar sign prefix implies that the MobilityModel is aggregated to node seven.
-The last component of the path means that we are hooking into the
-``CourseChange'' event of that model.
-
-We make a connection between the trace source in node seven with our trace
-sink by calling @code{Config::Connect} and passing this namespace path. Once
-this is done, every course change event on node seven will be hooked into our
-trace sink, which will in turn print out the new position.
-
-If you now run the simulation, you will see the course changes displayed as
-they happen.
-
-@verbatim
- Build finished successfully (00:00:01)
- /NodeList/7/$ns3::MobilityModel/CourseChange x = 10, y = 0
- /NodeList/7/$ns3::MobilityModel/CourseChange x = 9.41539, y = -0.811313
- /NodeList/7/$ns3::MobilityModel/CourseChange x = 8.46199, y = -1.11303
- /NodeList/7/$ns3::MobilityModel/CourseChange x = 7.52738, y = -1.46869
- /NodeList/7/$ns3::MobilityModel/CourseChange x = 6.67099, y = -1.98503
- /NodeList/7/$ns3::MobilityModel/CourseChange x = 5.6835, y = -2.14268
- /NodeList/7/$ns3::MobilityModel/CourseChange x = 4.70932, y = -1.91689
- Sent 1024 bytes to 10.1.2.4
- Received 1024 bytes from 10.1.3.3
- Received 1024 bytes from 10.1.2.4
- /NodeList/7/$ns3::MobilityModel/CourseChange x = 5.53175, y = -2.48576
- /NodeList/7/$ns3::MobilityModel/CourseChange x = 4.58021, y = -2.17821
- /NodeList/7/$ns3::MobilityModel/CourseChange x = 4.18915, y = -1.25785
- /NodeList/7/$ns3::MobilityModel/CourseChange x = 4.7572, y = -0.434856
- /NodeList/7/$ns3::MobilityModel/CourseChange x = 4.62404, y = 0.556238
- /NodeList/7/$ns3::MobilityModel/CourseChange x = 4.74127, y = 1.54934
- /NodeList/7/$ns3::MobilityModel/CourseChange x = 5.73934, y = 1.48729
- /NodeList/7/$ns3::MobilityModel/CourseChange x = 6.18521, y = 0.59219
- /NodeList/7/$ns3::MobilityModel/CourseChange x = 6.58121, y = 1.51044
- /NodeList/7/$ns3::MobilityModel/CourseChange x = 7.27897, y = 2.22677
- /NodeList/7/$ns3::MobilityModel/CourseChange x = 6.42888, y = 1.70014
- /NodeList/7/$ns3::MobilityModel/CourseChange x = 7.40519, y = 1.91654
- /NodeList/7/$ns3::MobilityModel/CourseChange x = 6.51981, y = 1.45166
- /NodeList/7/$ns3::MobilityModel/CourseChange x = 7.34588, y = 2.01523
- /NodeList/7/$ns3::MobilityModel/CourseChange x = 7.81046, y = 2.90077
- /NodeList/7/$ns3::MobilityModel/CourseChange x = 6.89186, y = 3.29596
- /NodeList/7/$ns3::MobilityModel/CourseChange x = 7.46617, y = 2.47732
- /NodeList/7/$ns3::MobilityModel/CourseChange x = 7.05492, y = 1.56579
- /NodeList/7/$ns3::MobilityModel/CourseChange x = 8.00393, y = 1.25054
- /NodeList/7/$ns3::MobilityModel/CourseChange x = 7.00968, y = 1.35768
- /NodeList/7/$ns3::MobilityModel/CourseChange x = 7.33503, y = 2.30328
- /NodeList/7/$ns3::MobilityModel/CourseChange x = 7.18682, y = 3.29223
- /NodeList/7/$ns3::MobilityModel/CourseChange x = 7.96865, y = 2.66873
-@end verbatim
--- a/doc/tutorial/conceptual-overview.texi Sun Jan 02 22:57:04 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,847 +0,0 @@
-
-@c ========================================================================
-@c Begin document body here
-@c ========================================================================
-
-@c ========================================================================
-@c Conceptual Overview
-@c ========================================================================
-@node Conceptual Overview
-@chapter Conceptual Overview
-
-@menu
-* Key Abstractions::
-* A First ns-3 Script::
-@end menu
-
-The first thing we need to do before actually starting to look at or write
-@command{ns-3} code is to explain a few core concepts and abstractions in the
-system. Much of this may appear transparently obvious to some, but we
-recommend taking the time to read through this section just to ensure you
-are starting on a firm foundation.
-
-@node Key Abstractions
-@section Key Abstractions
-
-In this section, we'll review some terms that are commonly used in
-networking, but have a specific meaning in @command{ns-3}.
-
-@subsection Node
-@cindex Node
-In Internet jargon, a computing device that connects to a network is called
-a @emph{host} or sometimes an @emph{end system}. Because @command{ns-3} is a
-@emph{network} simulator, not specifically an @emph{Internet} simulator, we
-intentionally do not use the term host since it is closely associated with
-the Internet and its protocols. Instead, we use a more generic term also
-used by other simulators that originates in Graph Theory --- the @emph{node}.
-
-@cindex class Node
-In @command{ns-3} the basic computing device abstraction is called the
-node. This abstraction is represented in C++ by the class @code{Node}. The
-@code{Node} class provides methods for managing the representations of
-computing devices in simulations.
-
-You should think of a @code{Node} as a computer to which you will add
-functionality. One adds things like applications, protocol stacks and
-peripheral cards with their associated drivers to enable the computer to do
-useful work. We use the same basic model in @command{ns-3}.
-
-@subsection Application
-@cindex Application
-Typically, computer software is divided into two broad classes. @emph{System
-Software} organizes various computer resources such as memory, processor
-cycles, disk, network, etc., according to some computing model. System
-software usually does not use those resources to complete tasks that directly
-benefit a user. A user would typically run an @emph{application} that acquires
-and uses the resources controlled by the system software to accomplish some
-goal.
-
-@cindex system call
-Often, the line of separation between system and application software is made
-at the privilege level change that happens in operating system traps.
-In @command{ns-3} there is no real concept of operating system and especially
-no concept of privilege levels or system calls. We do, however, have the
-idea of an application. Just as software applications run on computers to
-perform tasks in the ``real world,'' @command{ns-3} applications run on
-@command{ns-3} @code{Nodes} to drive simulations in the simulated world.
-
-@cindex class Application
-In @command{ns-3} the basic abstraction for a user program that generates some
-activity to be simulated is the application. This abstraction is represented
-in C++ by the class @code{Application}. The @code{Application} class provides
-methods for managing the representations of our version of user-level
-applications in simulations. Developers are expected to specialize the
-@code{Application} class in the object-oriented programming sense to create new
-applications. In this tutorial, we will use specializations of class
-@code{Application} called @code{UdpEchoClientApplication} and
-@code{UdpEchoServerApplication}. As you might expect, these applications
-compose a client/server application set used to generate and echo simulated
-network packets
-
-@subsection Channel
-@cindex Channel
-
-In the real world, one can connect a computer to a network. Often the media
-over which data flows in these networks are called @emph{channels}. When
-you connect your Ethernet cable to the plug in the wall, you are connecting
-your computer to an Ethernet communication channel. In the simulated world
-of @command{ns-3}, one connects a @code{Node} to an object representing a
-communication channel. Here the basic communication subnetwork abstraction
-is called the channel and is represented in C++ by the class @code{Channel}.
-
-The @code{Channel} class provides methods for managing communication
-subnetwork objects and connecting nodes to them. @code{Channels} may also be
-specialized by developers in the object oriented programming sense. A
-@code{Channel} specialization may model something as simple as a wire. The
-specialized @code{Channel} can also model things as complicated as a large
-Ethernet switch, or three-dimensional space full of obstructions in the case
-of wireless networks.
-
-We will use specialized versions of the @code{Channel} called
-@code{CsmaChannel}, @code{PointToPointChannel} and @code{WifiChannel} in this
-tutorial. The @code{CsmaChannel}, for example, models a version of a
-communication subnetwork that implements a @emph{carrier sense multiple
-access} communication medium. This gives us Ethernet-like functionality.
-
-@subsection Net Device
-@cindex NetDevice
-@cindex Ethernet
-It used to be the case that if you wanted to connect a computers to a network,
-you had to buy a specific kind of network cable and a hardware device called
-(in PC terminology) a @emph{peripheral card} that needed to be installed in
-your computer. If the peripheral card implemented some networking function,
-they were called Network Interface Cards, or @emph{NICs}. Today most
-computers come with the network interface hardware built in and users don't
-see these building blocks.
-
-A NIC will not work without a software driver to control the hardware. In
-Unix (or Linux), a piece of peripheral hardware is classified as a
-@emph{device}. Devices are controlled using @emph{device drivers}, and network
-devices (NICs) are controlled using @emph{network device drivers}
-collectively known as @emph{net devices}. In Unix and Linux you refer
-to these net devices by names such as @emph{eth0}.
-
-In @command{ns-3} the @emph{net device} abstraction covers both the software
-driver and the simulated hardware. A net device is ``installed'' in a
-@code{Node} in order to enable the @code{Node} to communicate with other
-@code{Nodes} in the simulation via @code{Channels}. Just as in a real
-computer, a @code{Node} may be connected to more than one @code{Channel} via
-multiple @code{NetDevices}.
-
-The net device abstraction is represented in C++ by the class @code{NetDevice}.
-The @code{NetDevice} class provides methods for managing connections to
-@code{Node} and @code{Channel} objects; and may be specialized by developers
-in the object-oriented programming sense. We will use the several specialized
-versions of the @code{NetDevice} called @code{CsmaNetDevice},
-@code{PointToPointNetDevice}, and @code{WifiNetDevice} in this tutorial.
-Just as an Ethernet NIC is designed to work with an Ethernet network, the
-@code{CsmaNetDevice} is designed to work with a @code{CsmaChannel}; the
-@code{PointToPointNetDevice} is designed to work with a
-@code{PointToPointChannel} and a @code{WifiNetNevice} is designed to work with
-a @code{WifiChannel}.
-
-@subsection Topology Helpers
-@cindex helper
-@cindex topology
-@cindex topology helper
-In a real network, you will find host computers with added (or built-in)
-NICs. In @command{ns-3} we would say that you will find @code{Nodes} with
-attached @code{NetDevices}. In a large simulated network you will need to
-arrange many connections between @code{Nodes}, @code{NetDevices} and
-@code{Channels}.
-
-Since connecting @code{NetDevices} to @code{Nodes}, @code{NetDevices}
-to @code{Channels}, assigning IP addresses, etc., are such common tasks
-in @command{ns-3}, we provide what we call @emph{topology helpers} to make
-this as easy as possible. For example, it may take many distinct
-@command{ns-3} core operations to create a NetDevice, add a MAC address,
-install that net device on a @code{Node}, configure the node's protocol stack,
-and then connect the @code{NetDevice} to a @code{Channel}. Even more
-operations would be required to connect multiple devices onto multipoint
-channels and then to connect individual networks together into internetworks.
-We provide topology helper objects that combine those many distinct operations
-into an easy to use model for your convenience.
-
-@c ========================================================================
-@c A First ns-3 script
-@c ========================================================================
-@node A First ns-3 Script
-@section A First ns-3 Script
-@cindex first script
-If you downloaded the system as was suggested above, you will have a release
-of @command{ns-3} in a directory called @code{repos} under your home
-directory. Change into that release directory, and you should find a
-directory structure something like the following:
-
-@verbatim
- AUTHORS doc/ README src/ waf.bat*
- bindings/ examples/ RELEASE_NOTES utils/ wscript
- build/ LICENSE samples/ VERSION wutils.py
- CHANGES.html ns3/ scratch/ waf* wutils.pyc
-@end verbatim
-
-@cindex first.cc
-Change into the @code{examples/tutorial} directory. You should see a file named
-@code{first.cc} located there. This is a script that will create a simple
-point-to-point link between two nodes and echo a single packet between the
-nodes. Let's take a look at that script line by line, so go ahead and open
-@code{first.cc} in your favorite editor.
-
-@subsection Boilerplate
-The first line in the file is an emacs mode line. This tells emacs about the
-formatting conventions (coding style) we use in our source code.
-
-@verbatim
- /* -*- Mode:C++; c-file-style:''gnu''; indent-tabs-mode:nil; -*- */
-@end verbatim
-
-This is always a somewhat controversial subject, so we might as well get it
-out of the way immediately. The @code{ns-3} project, like most large
-projects, has adopted a coding style to which all contributed code must
-adhere. If you want to contribute your code to the project, you will
-eventually have to conform to the @command{ns-3} coding standard as described
-in the file @code{doc/codingstd.txt} or shown on the project web page
-@uref{http://www.nsnam.org/codingstyle.html,,here}.
-
-We recommend that you, well, just get used to the look and feel of @code{ns-3}
-code and adopt this standard whenever you are working with our code. All of
-the development team and contributors have done so with various amounts of
-grumbling. The emacs mode line above makes it easier to get the formatting
-correct if you use the emacs editor.
-
-The @command{ns-3} simulator is licensed using the GNU General Public
-License. You will see the appropriate GNU legalese at the head of every file
-in the @command{ns-3} distribution. Often you will see a copyright notice for
-one of the institutions involved in the @code{ns-3} project above the GPL
-text and an author listed below.
-
-@verbatim
- /*
- * 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
- */
-@end verbatim
-
-@subsection Module Includes
-The code proper starts with a number of include statements.
-
-@verbatim
- #include "ns3/core-module.h"
- #include "ns3/simulator-module.h"
- #include "ns3/node-module.h"
- #include "ns3/helper-module.h"
-@end verbatim
-
-To help our high-level script users deal with the large number of include
-files present in the system, we group includes according to relatively large
-modules. We provide a single include file that will recursively load all of
-the include files used in each module. Rather than having to look up exactly
-what header you need, and possibly have to get a number of dependencies right,
-we give you the ability to load a group of files at a large granularity. This
-is not the most efficient approach but it certainly makes writing scripts much
-easier.
-
-Each of the @command{ns-3} include files is placed in a directory called
-@code{ns3} (under the build directory) during the build process to help avoid
-include file name collisions. The @code{ns3/core-module.h} file corresponds
-to the ns-3 module you will find in the directory @code{src/core} in your
-downloaded release distribution. If you list this directory you will find a
-large number of header files. When you do a build, Waf will place public
-header files in an @code{ns3} directory under the appropriate
-@code{build/debug} or @code{build/optimized} directory depending on your
-configuration. Waf will also automatically generate a module include file to
-load all of the public header files.
-
-Since you are, of course, following this tutorial religiously, you will
-already have done a
-
-@verbatim
- ./waf -d debug configure
-@end verbatim
-
-in order to configure the project to perform debug builds. You will also have
-done a
-
-@verbatim
- ./waf
-@end verbatim
-
-to build the project. So now if you look in the directory
-@code{../../build/debug/ns3} you will find the four module include files shown
-above. You can take a look at the contents of these files and find that they
-do include all of the public include files in their respective modules.
-
-@subsection Ns3 Namespace
-The next line in the @code{first.cc} script is a namespace declaration.
-
-@verbatim
- using namespace ns3;
-@end verbatim
-
-The @command{ns-3} project is implemented in a C++ namespace called
-@code{ns3}. This groups all @command{ns-3}-related declarations in a scope
-outside the global namespace, which we hope will help with integration with
-other code. The C++ @code{using} statement introduces the @code{ns-3}
-namespace into the current (global) declarative region. This is a fancy way
-of saying that after this declaration, you will not have to type @code{ns3::}
-scope resolution operator before all of the @code{ns-3} code in order to use
-it. If you are unfamiliar with namespaces, please consult almost any C++
-tutorial and compare the @code{ns3} namespace and usage here with instances of
-the @code{std} namespace and the @code{using namespace std;} statements you
-will often find in discussions of @code{cout} and streams.
-
-@subsection Logging
-The next line of the script is the following,
-
-@verbatim
- NS_LOG_COMPONENT_DEFINE ("FirstScriptExample");
-@end verbatim
-
-We will use this statement as a convenient place to talk about our Doxygen
-documentation system. If you look at the project web site,
-@uref{http://www.nsnam.org,,ns-3 project}, you will find a link to ``Doxygen
-(ns-3-dev)'' in the navigation bar. If you select this link, you will be
-taken to our documentation page for the current development release. There
-is also a link to ``Doxygen (stable)'' that will take you to the documentation
-for the latest stable release of @code{ns-3}.
-
-Along the left side, you will find a graphical representation of the structure
-of the documentation. A good place to start is the @code{NS-3 Modules}
-``book'' in the @code{ns-3} navigation tree. If you expand @code{Modules}
-you will see a list of @command{ns-3} module documentation. The concept of
-module here ties directly into the module include files discussed above. It
-turns out that the @command{ns-3} logging subsystem is part of the @code{core}
-module, so go ahead and expand that documentation node. Now, expand the
-@code{Debugging} book and then select the @code{Logging} page.
-
-You should now be looking at the Doxygen documentation for the Logging module.
-In the list of @code{#define}s at the top of the page you will see the entry
-for @code{NS_LOG_COMPONENT_DEFINE}. Before jumping in, it would probably be
-good to look for the ``Detailed Description'' of the logging module to get a
-feel for the overall operation. You can either scroll down or select the
-``More...'' link under the collaboration diagram to do this.
-
-Once you have a general idea of what is going on, go ahead and take a look at
-the specific @code{NS_LOG_COMPONENT_DEFINE} documentation. I won't duplicate
-the documentation here, but to summarize, this line declares a logging
-component called @code{FirstScriptExample} that allows you to enable and
-disable console message logging by reference to the name.
-
-@subsection Main Function
-The next lines of the script you will find are,
-
-@verbatim
- int
- main (int argc, char *argv[])
- {
-@end verbatim
-
-This is just the declaration of the main function of your program (script).
-Just as in any C++ program, you need to define a main function that will be
-the first function run. There is nothing at all special here. Your
-@command{ns-3} script is just a C++ program.
-
-The next two lines of the script are used to enable two logging components that
-are built into the Echo Client and Echo Server applications:
-
-@verbatim
- LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_INFO);
- LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_INFO);
-@end verbatim
-
-If you have read over the Logging component documentation you will have seen
-that there are a number of levels of logging verbosity/detail that you can
-enable on each component. These two lines of code enable debug logging at the
-INFO level for echo clients and servers. This will result in the application
-printing out messages as packets are sent and received during the simulation.
-
-Now we will get directly to the business of creating a topology and running
-a simulation. We use the topology helper objects to make this job as
-easy as possible.
-
-@subsection Topology Helpers
-@subsubsection NodeContainer
-The next two lines of code in our script will actually create the
-@command{ns-3} @code{Node} objects that will represent the computers in the
-simulation.
-
-@verbatim
- NodeContainer nodes;
- nodes.Create (2);
-@end verbatim
-
-Let's find the documentation for the @code{NodeContainer} class before we
-continue. Another way to get into the documentation for a given class is via
-the @code{Classes} tab in the Doxygen pages. If you still have the Doxygen
-handy, just scroll up to the top of the page and select the @code{Classes}
-tab. You should see a new set of tabs appear, one of which is
-@code{Class List}. Under that tab you will see a list of all of the
-@command{ns-3} classes. Scroll down, looking for @code{ns3::NodeContainer}.
-When you find the class, go ahead and select it to go to the documentation for
-the class.
-
-You may recall that one of our key abstractions is the @code{Node}. This
-represents a computer to which we are going to add things like protocol stacks,
-applications and peripheral cards. The @code{NodeContainer} topology helper
-provides a convenient way to create, manage and access any @code{Node} objects
-that we create in order to run a simulation. The first line above just
-declares a NodeContainer which we call @code{nodes}. The second line calls the
-@code{Create} method on the @code{nodes} object and asks the container to
-create two nodes. As described in the Doxygen, the container calls down into
-the @command{ns-3} system proper to create two @code{Node} objects and stores
-pointers to those objects internally.
-
-The nodes as they stand in the script do nothing. The next step in
-constructing a topology is to connect our nodes together into a network.
-The simplest form of network we support is a single point-to-point link
-between two nodes. We'll construct one of those links here.
-
-@subsubsection PointToPointHelper
-We are constructing a point to point link, and, in a pattern which will become
-quite familiar to you, we use a topology helper object to do the low-level
-work required to put the link together. Recall that two of our key
-abstractions are the @code{NetDevice} and the @code{Channel}. In the real
-world, these terms correspond roughly to peripheral cards and network cables.
-Typically these two things are intimately tied together and one cannot expect
-to interchange, for example, Ethernet devices and wireless channels. Our
-Topology Helpers follow this intimate coupling and therefore you will use a
-single @code{PointToPointHelper} to configure and connect @command{ns-3}
-@code{PointToPointNetDevice} and @code{PointToPointChannel} objects in this
-script.
-
-The next three lines in the script are,
-
-@verbatim
- PointToPointHelper pointToPoint;
- pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
- pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
-@end verbatim
-
-The first line,
-
-@verbatim
- PointToPointHelper pointToPoint;
-@end verbatim
-
-instantiates a @code{PointToPointHelper} object on the stack. From a
-high-level perspective the next line,
-
-@verbatim
- pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
-@end verbatim
-
-tells the @code{PointToPointHelper} object to use the value ``5Mbps''
-(five megabits per second) as the ``DataRate'' when it creates a
-@code{PointToPointNetDevice} object.
-
-From a more detailed perspective, the string ``DataRate'' corresponds
-to what we call an @code{Attribute} of the @code{PointToPointNetDevice}.
-If you look at the Doxygen for class @code{ns3::PointToPointNetDevice} and
-find the documentation for the @code{GetTypeId} method, you will find a list
-of @code{Attributes} defined for the device. Among these is the ``DataRate''
-@code{Attribute}. Most user-visible @command{ns-3} objects have similar lists of
-@code{Attributes}. We use this mechanism to easily configure simulations without
-recompiling as you will see in a following section.
-
-Similar to the ``DataRate'' on the @code{PointToPointNetDevice} you will find a
-``Delay'' @code{Attribute} associated with the @code{PointToPointChannel}. The
-final line,
-
-@verbatim
- pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
-@end verbatim
-
-tells the @code{PointToPointHelper} to use the value ``2ms'' (two milliseconds)
-as the value of the transmission delay of every point to point channel it
-subsequently creates.
-
-@subsubsection NetDeviceContainer
-At this point in the script, we have a @code{NodeContainer} that contains
-two nodes. We have a @code{PointToPointHelper} that is primed and ready to
-make @code{PointToPointNetDevices} and wire @code{PointToPointChannel} objects
-between them. Just as we used the @code{NodeContainer} topology helper object
-to create the @code{Nodes} for our simulation, we will ask the
-@code{PointToPointHelper} to do the work involved in creating, configuring and
-installing our devices for us. We will need to have a list of all of the
-NetDevice objects that are created, so we use a NetDeviceContainer to hold
-them just as we used a NodeContainer to hold the nodes we created. The
-following two lines of code,
-
-@verbatim
- NetDeviceContainer devices;
- devices = pointToPoint.Install (nodes);
-@end verbatim
-
-will finish configuring the devices and channel. The first line declares the
-device container mentioned above and the second does the heavy lifting. The
-@code{Install} method of the @code{PointToPointHelper} takes a
-@code{NodeContainer} as a parameter. Internally, a @code{NetDeviceContainer}
-is created. For each node in the @code{NodeContainer} (there must be exactly
-two for a point-to-point link) a @code{PointToPointNetDevice} is created and
-saved in the device container. A @code{PointToPointChannel} is created and
-the two @code{PointToPointNetDevices} are attached. When objects are created
-by the @code{PointToPointHelper}, the @code{Attributes} previously set in the
-helper are used to initialize the corresponding @code{Attributes} in the
-created objects.
-
-After executing the @code{pointToPoint.Install (nodes)} call we will have
-two nodes, each with an installed point-to-point net device and a single
-point-to-point channel between them. Both devices will be configured to
-transmit data at five megabits per second over the channel which has a two
-millisecond transmission delay.
-
-@subsubsection InternetStackHelper
-We now have nodes and devices configured, but we don't have any protocol stacks
-installed on our nodes. The next two lines of code will take care of that.
-
-@verbatim
- InternetStackHelper stack;
- stack.Install (nodes);
-@end verbatim
-
-The @code{InternetStackHelper} is a topology helper that is to internet stacks
-what the @code{PointToPointHelper} is to point-to-point net devices. The
-@code{Install} method takes a @code{NodeContainer} as a parameter. When it is
-executed, it will install an Internet Stack (TCP, UDP, IP, etc.) on each of
-the nodes in the node container.
-
-@subsubsection Ipv4AddressHelper
-Next we need to associate the devices on our nodes with IP addresses. We
-provide a topology helper to manage the allocation of IP addresses. The only
-user-visible API is to set the base IP address and network mask to use when
-performing the actual address allocation (which is done at a lower level
-inside the helper).
-
-The next two lines of code in our example script, @code{first.cc},
-
-@verbatim
- Ipv4AddressHelper address;
- address.SetBase ("10.1.1.0", "255.255.255.0");
-@end verbatim
-
-declare an address helper object and tell it that it should begin allocating IP
-addresses from the network 10.1.1.0 using the mask 255.255.255.0 to define
-the allocatable bits. By default the addresses allocated will start at one
-and increase monotonically, so the first address allocated from this base will
-be 10.1.1.1, followed by 10.1.1.2, etc. The low level @command{ns-3} system
-actually remembers all of the IP addresses allocated and will generate a
-fatal error if you accidentally cause the same address to be generated twice
-(which is a very hard to debug error, by the way).
-
-The next line of code,
-
-@verbatim
- Ipv4InterfaceContainer interfaces = address.Assign (devices);
-@end verbatim
-
-performs the actual address assignment. In @command{ns-3} we make the
-association between an IP address and a device using an @code{Ipv4Interface}
-object. Just as we sometimes need a list of net devices created by a helper
-for future reference we sometimes need a list of @code{Ipv4Interface} objects.
-The @code{Ipv4InterfaceContainer} provides this functionality.
-
-Now we have a point-to-point network built, with stacks installed and IP
-addresses assigned. What we need at this point are applications to generate
-traffic.
-
-@subsection Applications
-Another one of the core abstractions of the ns-3 system is the
-@code{Application}. In this script we use two specializations of the core
-@command{ns-3} class @code{Application} called @code{UdpEchoServerApplication}
-and @code{UdpEchoClientApplication}. Just as we have in our previous
-explanations, we use helper objects to help configure and manage the
-underlying objects. Here, we use @code{UdpEchoServerHelper} and
-@code{UdpEchoClientHelper} objects to make our lives easier.
-
-@subsubsection UdpEchoServerHelper
-The following lines of code in our example script, @code{first.cc}, are used
-to set up a UDP echo server application on one of the nodes we have previously
-created.
-
-@verbatim
- UdpEchoServerHelper echoServer (9);
-
- ApplicationContainer serverApps = echoServer.Install (nodes.Get (1));
- serverApps.Start (Seconds (1.0));
- serverApps.Stop (Seconds (10.0));
-@end verbatim
-
-The first line of code in the above snippet declares the
-@code{UdpEchoServerHelper}. As usual, this isn't the application itself, it
-is an object used to help us create the actual applications. One of our
-conventions is to place @emph{required} @code{Attributes} in the helper constructor.
-In this case, the helper can't do anything useful unless it is provided with
-a port number that the client also knows about. Rather than just picking one
-and hoping it all works out, we require the port number as a parameter to the
-constructor. The constructor, in turn, simply does a @code{SetAttribute}
-with the passed value. If you want, you can set the ``Port'' @code{Attribute}
-to another value later using @code{SetAttribute}.
-
-Similar to many other helper objects, the @code{UdpEchoServerHelper} object
-has an @code{Install} method. It is the execution of this method that actually
-causes the underlying echo server application to be instantiated and attached
-to a node. Interestingly, the @code{Install} method takes a
-@code{NodeContainter} as a parameter just as the other @code{Install} methods
-we have seen. This is actually what is passed to the method even though it
-doesn't look so in this case. There is a C++ @emph{implicit conversion} at
-work here that takes the result of @code{nodes.Get (1)} (which returns a smart
-pointer to a node object --- @code{Ptr<Node>}) and uses that in a constructor
-for an unnamed @code{NodeContainer} that is then passed to @code{Install}.
-If you are ever at a loss to find a particular method signature in C++ code
-that compiles and runs just fine, look for these kinds of implicit conversions.
-
-We now see that @code{echoServer.Install} is going to install a
-@code{UdpEchoServerApplication} on the node found at index number one of the
-@code{NodeContainer} we used to manage our nodes. @code{Install} will return
-a container that holds pointers to all of the applications (one in this case
-since we passed a @code{NodeContainer} containing one node) created by the
-helper.
-
-Applications require a time to ``start'' generating traffic and may take an
-optional time to ``stop''. We provide both. These times are set using the
-@code{ApplicationContainer} methods @code{Start} and @code{Stop}. These
-methods take @code{Time} parameters. In this case, we use an @emph{explicit}
-C++ conversion sequence to take the C++ double 1.0 and convert it to an
-@command{ns-3} @code{Time} object using a @code{Seconds} cast. Be aware that
-the conversion rules may be controlled by the model author, and C++ has its
-own rules, so you can't always just assume that parameters will be happily
-converted for you. The two lines,
-
-@verbatim
- serverApps.Start (Seconds (1.0));
- serverApps.Stop (Seconds (10.0));
-@end verbatim
-
-will cause the echo server application to @code{Start} (enable itself) at one
-second into the simulation and to @code{Stop} (disable itself) at ten seconds
-into the simulation. By virtue of the fact that we have declared a simulation
-event (the application stop event) to be executed at ten seconds, the simulation
-will last @emph{at least} ten seconds.
-
-@subsubsection UdpEchoClientHelper
-
-The echo client application is set up in a method substantially similar to
-that for the server. There is an underlying @code{UdpEchoClientApplication}
-that is managed by an @code{UdpEchoClientHelper}.
-
-@verbatim
- UdpEchoClientHelper echoClient (interfaces.GetAddress (1), 9);
- echoClient.SetAttribute ("MaxPackets", UintegerValue (1));
- echoClient.SetAttribute ("Interval", TimeValue (Seconds (1.)));
- echoClient.SetAttribute ("PacketSize", UintegerValue (1024));
-
- ApplicationContainer clientApps = echoClient.Install (nodes.Get (0));
- clientApps.Start (Seconds (2.0));
- clientApps.Stop (Seconds (10.0));
-@end verbatim
-
-For the echo client, however, we need to set five different @code{Attributes}.
-The first two @code{Attributes} are set during construction of the
-@code{UdpEchoClientHelper}. We pass parameters that are used (internally to
-the helper) to set the ``RemoteAddress'' and ``RemotePort'' @code{Attributes}
-in accordance with our convention to make required @code{Attributes} parameters
-in the helper constructors.
-
-Recall that we used an @code{Ipv4InterfaceContainer} to keep track of the IP
-addresses we assigned to our devices. The zeroth interface in the
-@code{interfaces} container is going to correspond to the IP address of the
-zeroth node in the @code{nodes} container. The first interface in the
-@code{interfaces} container corresponds to the IP address of the first node
-in the @code{nodes} container. So, in the first line of code (from above), we
-are creating the helper and telling it so set the remote address of the client
-to be the IP address assigned to the node on which the server resides. We
-also tell it to arrange to send packets to port nine.
-
-The ``MaxPackets'' @code{Attribute} tells the client the maximum number of
-packets we allow it to send during the simulation. The ``Interval''
-@code{Attribute} tells the client how long to wait between packets, and the
-``PacketSize'' @code{Attribute} tells the client how large its packet payloads
-should be. With this particular combination of @code{Attributes}, we are
-telling the client to send one 1024-byte packet.
-
-Just as in the case of the echo server, we tell the echo client to @code{Start}
-and @code{Stop}, but here we start the client one second after the server is
-enabled (at two seconds into the simulation).
-
-@subsection Simulator
-What we need to do at this point is to actually run the simulation. This is
-done using the global function @code{Simulator::Run}.
-
-@verbatim
- Simulator::Run ();
-@end verbatim
-
-When we previously called the methods,
-
-@verbatim
- serverApps.Start (Seconds (1.0));
- serverApps.Stop (Seconds (10.0));
- ...
- clientApps.Start (Seconds (2.0));
- clientApps.Stop (Seconds (10.0));
-@end verbatim
-
-we actually scheduled events in the simulator at 1.0 seconds, 2.0 seconds and
-two events at 10.0 seconds. When @code{Simulator::Run} is called, the system
-will begin looking through the list of scheduled events and executing them.
-First it will run the event at 1.0 seconds, which will enable the echo server
-application (this event may, in turn, schedule many other events). Then it
-will run the event scheduled for t=2.0 seconds which will start the echo client
-application. Again, this event may schedule many more events. The start event
-implementation in the echo client application will begin the data transfer phase
-of the simulation by sending a packet to the server.
-
-The act of sending the packet to the server will trigger a chain of events
-that will be automatically scheduled behind the scenes and which will perform
-the mechanics of the packet echo according to the various timing parameters
-that we have set in the script.
-
-Eventually, since we only send one packet (recall the @code{MaxPackets}
-@code{Attribute} was set to one), the chain of events triggered by
-that single client echo request will taper off and the simulation will go
-idle. Once this happens, the remaining events will be the @code{Stop} events
-for the server and the client. When these events are executed, there are
-no further events to process and @code{Simulator::Run} returns. The simulation
-is then complete.
-
-All that remains is to clean up. This is done by calling the global function
-@code{Simulator::Destroy}. As the helper functions (or low level
-@command{ns-3} code) executed, they arranged it so that hooks were inserted in
-the simulator to destroy all of the objects that were created. You did not
-have to keep track of any of these objects yourself --- all you had to do
-was to call @code{Simulator::Destroy} and exit. The @command{ns-3} system
-took care of the hard part for you. The remaining lines of our first
-@command{ns-3} script, @code{first.cc}, do just that:
-
-@verbatim
- Simulator::Destroy ();
- return 0;
- }
-@end verbatim
-
-@subsection Building Your Script
-We have made it trivial to build your simple scripts. All you have to do is
-to drop your script into the scratch directory and it will automatically be
-built if you run Waf. Let's try it. Copy @code{examples/tutorial/first.cc} into
-the @code{scratch} directory after changing back into the top level directory.
-
-@verbatim
- cd ..
- cp examples/tutorial/first.cc scratch/myfirst.cc
-@end verbatim
-
-Now build your first example script using waf:
-
-@verbatim
- ./waf
-@end verbatim
-
-You should see messages reporting that your @code{myfirst} example was built
-successfully.
-
-@verbatim
- Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
- [614/708] cxx: scratch/myfirst.cc -> build/debug/scratch/myfirst_3.o
- [706/708] cxx_link: build/debug/scratch/myfirst_3.o -> build/debug/scratch/myfirst
- Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
- 'build' finished successfully (2.357s)
-@end verbatim
-
-You can now run the example (note that if you build your program in the scratch
-directory you must run it out of the scratch directory):
-
-@verbatim
- ./waf --run scratch/myfirst
-@end verbatim
-
-You should see some output:
-
-@verbatim
- Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
- Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
- 'build' finished successfully (0.418s)
- Sent 1024 bytes to 10.1.1.2
- Received 1024 bytes from 10.1.1.1
- Received 1024 bytes from 10.1.1.2
-@end verbatim
-
-Here you see that the build system checks to make sure that the file has been
-build and then runs it. You see the logging component on the echo client
-indicate that it has sent one 1024 byte packet to the Echo Server on
-10.1.1.2. You also see the logging component on the echo server say that
-it has received the 1024 bytes from 10.1.1.1. The echo server silently
-echoes the packet and you see the echo client log that it has received its
-packet back from the server.
-
-@c ========================================================================
-@c Browsing ns-3
-@c ========================================================================
-
-@node Ns-3 Source Code
-@section Ns-3 Source Code
-
-Now that you have used some of the @command{ns-3} helpers you may want to
-have a look at some of the source code that implements that functionality.
-The most recent code can be browsed on our web server at the following link:
-@uref{http://code.nsnam.org/ns-3-dev}. There, you will see the Mercurial
-summary page for our @command{ns-3} development tree.
-
-At the top of the page, you will see a number of links,
-
-@verbatim
- summary | shortlog | changelog | graph | tags | files
-@end verbatim
-
-Go ahead and select the @code{files} link. This is what the top-level of
-most of our @emph{repositories} will look:
-
-@verbatim
-drwxr-xr-x [up]
-drwxr-xr-x bindings python files
-drwxr-xr-x doc files
-drwxr-xr-x examples files
-drwxr-xr-x ns3 files
-drwxr-xr-x samples files
-drwxr-xr-x scratch files
-drwxr-xr-x src files
-drwxr-xr-x utils files
--rw-r--r-- 2009-07-01 12:47 +0200 560 .hgignore file | revisions | annotate
--rw-r--r-- 2009-07-01 12:47 +0200 1886 .hgtags file | revisions | annotate
--rw-r--r-- 2009-07-01 12:47 +0200 1276 AUTHORS file | revisions | annotate
--rw-r--r-- 2009-07-01 12:47 +0200 30961 CHANGES.html file | revisions | annotate
--rw-r--r-- 2009-07-01 12:47 +0200 17987 LICENSE file | revisions | annotate
--rw-r--r-- 2009-07-01 12:47 +0200 3742 README file | revisions | annotate
--rw-r--r-- 2009-07-01 12:47 +0200 16171 RELEASE_NOTES file | revisions | annotate
--rw-r--r-- 2009-07-01 12:47 +0200 6 VERSION file | revisions | annotate
--rwxr-xr-x 2009-07-01 12:47 +0200 88110 waf file | revisions | annotate
--rwxr-xr-x 2009-07-01 12:47 +0200 28 waf.bat file | revisions | annotate
--rw-r--r-- 2009-07-01 12:47 +0200 35395 wscript file | revisions | annotate
--rw-r--r-- 2009-07-01 12:47 +0200 7673 wutils.py file | revisions | annotate
-@end verbatim
-
-Our example scripts are in the @code{examples} directory. If you click on @code{examples}
-you will see a list of files. One of the files in that directory is @code{first.cc}. If
-you click on @code{first.cc} you will find the code you just walked through.
-
-The source code is mainly in the @code{src} directory. You can view source
-code either by clicking on the directory name or by clicking on the @code{files}
-link to the right of the directory name. If you click on the @code{src}
-directory, you will be taken to the listing of the @code{src} subdirectories. If you
-then click on @code{core} subdirectory, you will find a list of files. The first file
-you will find (as of this writing) is @code{abort.h}. If you click on the
-@code{abort.h} link, you will be sent to the source file for @code{abort.h} which
-contains useful macros for exiting scripts if abnormal conditions are detected.
-
-The source code for the helpers we have used in this chapter can be found in the
-@code{src/helper} directory. Feel free to poke around in the directory tree to
-get a feel for what is there and the style of @command{ns-3} programs.
--- a/doc/tutorial/conclusion.texi Sun Jan 02 22:57:04 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-@c ============================================================================
-@c Begin document body here
-@c ============================================================================
-
-@c ============================================================================
-@c PART: Closing Remarks
-@c ============================================================================
-@c The below chapters are under the major heading "Closing Remarks"
-@c This is similar to the Latex \part command
-@c
-@c ============================================================================
-@c Closing Remarks
-@c ============================================================================
-@node Closing Remarks
-@chapter Closing Remarks
-
-@menu
-* Futures::
-* Closing::
-@end menu
-
-@c ============================================================================
-@c Futures
-@c ============================================================================
-@node
-@section Futures
-
-This document is a work in process. We hope and expect it to grow over time
-to cover more and more of the nuts and bolts of @command{ns-3}.
-
-We hope to add the following chapters over the next few releases:
-
-@itemize @bullet
-@item The Callback System
-@item The Object System and Memory Management
-@item The Routing System
-@item Adding a New NetDevice and Channel
-@item Adding a New Protocol
-@item Working with Real Networks and Hosts
-@end itemize
-
-Writing manual and tutorial chapters is not something we all get excited about,
-but it is very important to the project. If you are an expert in one of these
-areas, please consider contributing to @command{ns-3} by providing one of these
-chapters; or any other chapter you may think is important.
-
-@c ============================================================================
-@c Closing
-@c ============================================================================
-@node
-@section Closing
-
-@code{ns-3} is a large and complicated system. It is impossible to cover all
-of the things you will need to know in one small tutorial.
-
-We have really just scratched the surface of @command{ns-3} in this tutorial,
-but we hope to have covered enough to get you started doing useful networking
-research using our favorite simulator.
-
--- The @command{ns-3} development team.
--- a/doc/tutorial/getting-started.texi Sun Jan 02 22:57:04 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,559 +0,0 @@
-
-@c ========================================================================
-@c Begin document body here
-@c ========================================================================
-
-@c ========================================================================
-@c PART: Getting Started
-@c ========================================================================
-@c The below chapters are under the major heading "Getting Started"
-@c This is similar to the Latex \part command
-@c
-@c ========================================================================
-@c Getting Started
-@c ========================================================================
-@node Getting Started
-@chapter Getting Started
-
-@menu
-* Downloading ns-3::
-* Building ns-3::
-* Testing ns-3::
-* Running a Script::
-@end menu
-
-@c ========================================================================
-@c Downloading ns-3
-@c ========================================================================
-
-@node Downloading ns-3
-@section Downloading ns-3
-
-@cindex Prerequisites
-@cindex Dependencies
-The @command{ns-3} system as a whole is a fairly complex system and has a
-number of dependencies on other components. Along with the systems you will
-most likely deal with every day (the GNU toolchain, Mercurial, you programmer
-editor) you will need to ensure that a number of additional libraries are
-present on your system before proceeding. @command{ns-3} provides a wiki
-for your reading pleasure that includes pages with many useful hints and tips.
-One such page is the ``Installation'' page,
-@uref{http://www.nsnam.org/wiki/index.php/Installation}.
-
-The ``Prerequisites'' section of this wiki page explains which packages are
-required to support common @command{ns-3} options, and also provides the
-commands used to install them for common Linux variants. Cygwin users will
-have to use the Cygwin installer (if you are a Cygwin user, you used it to
-install Cygwin).
-
-You may want to take this opportunity to explore the @command{ns-3} wiki
-a bit since there really is a wealth of information there.
-
-@cindex Linux
-@cindex Cygwin
-@cindex GNU
-@cindex toolchain
-@cindex Mercurial
-@cindex Waf
-From this point forward, we are going to assume that the reader is working in
-Linux or a Linux emulation environment (Linux, Cygwin, etc.) and has the GNU
-toolchain installed and verified along with the prerequisites mentioned
-above. We are also going to assume that you have Mercurial and Waf installed
-and running on the target system as described in the ``Getting Started'' section
-of the @command{ns-3} web site:
-@uref{http://www.nsnam.org/getting_started.html}.
-
-@cindex tarball
-The @command{ns-3} code is available in Mercurial repositories on the server
-@uref{http://code.nsnam.org}. You can also download a tarball release at
-@uref{http://www.nsnam.org/releases/}, or you can work with repositories
-using Mercurial. We recommend using Mercurial unless there's a good reason
-not to. See the end of this section for instructions on how to get a tarball
-release.
-
-@cindex repository
-The simplest way to get started using Mercurial repositories is to use the
-@code{ns-3-allinone} environment. This is a set of scripts that manages the
-downloading and building of various subsystems of @command{ns-3} for you. We
-recommend that you begin your @command{ns-3} adventures in this environment
-as it can really simplify your life at this point.
-
-@subsection Downloading ns-3 Using Mercurial
-One practice is to create a directory called @code{repos} in one's home
-directory under which one can keep local Mercurial repositories.
-@emph{Hint: we will assume you do this later in the tutorial.} If you adopt
-that approach, you can get a copy of @code{ns-3-allinone} by typing the
-following into your Linux shell (assuming you have installed Mercurial):
-
-@verbatim
- cd
- mkdir repos
- cd repos
- hg clone http://code.nsnam.org/ns-3-allinone
-@end verbatim
-
-As the hg (Mercurial) command executes, you should see something like the
-following displayed,
-
-@verbatim
- destination directory: ns-3-allinone
- requesting all changes
- adding changesets
- adding manifests
- adding file changes
- added 31 changesets with 45 changes to 7 files
- 7 files updated, 0 files merged, 0 files removed, 0 files unresolved
-@end verbatim
-
-After the clone command completes, you should have a directory called
-@code{ns-3-allinone} under your @code{~/repos} directory, the contents of which should
-look something like the following:
-
-@verbatim
- build.py* constants.py dist.py* download.py* README util.py
-@end verbatim
-
-Notice that you really just downloaded some Python scripts. The next step
-will be to use those scripts to download and build the @command{ns-3}
-distribution of your choice.
-
-@cindex repository
-If you go to the following link: @uref{http://code.nsnam.org/},
-you will see a number of repositories. Many are the private repositories of
-the @command{ns-3} development team. The repositories of interest to you will
-be prefixed with ``ns-3''. Official releases of @command{ns-3} will be
-numbered as @code{ns-3.<release>.<hotfix>}. For example, a second hotfix to a
-still hypothetical release nine of @command{ns-3} would be numbered as
-@code{ns-3.9.2}.
-
-The current development snapshot (unreleased) of @command{ns-3} may be found
-at @uref{http://code.nsnam.org/ns-3-dev/}. The
-developers attempt to keep these repository in consistent, working states but
-they are in a development area with unreleased code present, so you may want
-to consider staying with an official release if you do not need newly-
-introduced features.
-
-Since the release numbers are going to be changing, I will stick with
-the more constant ns-3-dev here in the tutorial, but you can replace the
-string ``ns-3-dev'' with your choice of release (e.g., ns-3.6) in the
-text below. You can find the latest version of the
-code either by inspection of the repository list or by going to the
-@uref{http://www.nsnam.org/getting_started.html,,``Getting Started''}
-web page and looking for the latest release identifier.
-
-Go ahead and change into the @code{ns-3-allinone} directory you created when
-you cloned that repository. We are now going to use the @code{download.py}
-script to pull down the various pieces of @command{ns-3} you will be using.
-
-Go ahead and type the following into your shell (remember you can substitute
-the name of your chosen release number instead of @code{ns-3-dev} -- like
-@code{"ns-3.6"} if you want to work with a
-stable release).
-
-@verbatim
- ./download.py -n ns-3-dev
-@end verbatim
-
-Note that the default for the @code{-n} option is @code{ns-3-dev} and so the
-above is actually redundant. We provide this example to illustrate how to
-specify alternate repositories. In order to download @code{ns-3-dev} you
-can actually use the defaults and simply type,
-
-@verbatim
- ./download.py
-@end verbatim
-
-As the hg (Mercurial) command executes, you should see something like the
-following,
-
-@verbatim
- #
- # Get NS-3
- #
-
- Cloning ns-3 branch
- => hg clone http://code.nsnam.org/ns-3-dev ns-3-dev
- requesting all changes
- adding changesets
- adding manifests
- adding file changes
- added 4634 changesets with 16500 changes to 1762 files
- 870 files updated, 0 files merged, 0 files removed, 0 files unresolved
-@end verbatim
-
-This is output by the download script as it fetches the actual @code{ns-3}
-code from the repository.
-
-The download script is smart enough to know that on some platforms various
-pieces of ns-3 are not supported. On your platform you may not see some
-of these pieces come down. However, on most platforms, the process should
-continue with something like,
-
-@verbatim
- #
- # Get PyBindGen
- #
-
- Required pybindgen version: 0.10.0.640
- Trying to fetch pybindgen; this will fail if no network connection is available. Hit Ctrl-C to skip.
- => bzr checkout -rrevno:640 https://launchpad.net/pybindgen pybindgen
- Fetch was successful.
-@end verbatim
-
-This was the download script getting the Python bindings generator for you.
-Note that you will need bazaar (bzr), a version control system, to download
-PyBindGen. Next you should see (modulo platform variations) something along
-the lines of,
-
-@verbatim
- #
- # Get NSC
- #
-
- Required NSC version: nsc-0.5.0
- Retrieving nsc from https://secure.wand.net.nz/mercurial/nsc
- => hg clone https://secure.wand.net.nz/mercurial/nsc nsc
- requesting all changes
- adding changesets
- adding manifests
- adding file changes
- added 273 changesets with 17565 changes to 15175 files
- 10622 files updated, 0 files merged, 0 files removed, 0 files unresolved
-@end verbatim
-
-This part of the process is the script downloading the Network Simulation
-Cradle for you. Note that NSC is not supported on OSX or Cygwin and works
-best with gcc-3.4 or gcc-4.2 or greater series.
-
-After the download.py script completes, you should have several new directories
-under @code{~/repos/ns-3-allinone}:
-
-@verbatim
- build.py* constants.pyc download.py* nsc/ README util.pyc
- constants.py dist.py* ns-3-dev/ pybindgen/ util.py
-@end verbatim
-
-Go ahead and change into @code{ns-3-dev} under your @code{~/repos/ns-3-allinone}
-directory. You should see something like the following there:
-
-@verbatim
- AUTHORS examples/ RELEASE_NOTES utils/ wscript
- bindings/ LICENSE samples/ VERSION wutils.py
- CHANGES.html ns3/ scratch/ waf*
- doc/ README src/ waf.bat*
-@end verbatim
-
-You are now ready to build the @command{ns-3} distribution.
-
-@subsection Downloading ns-3 Using a Tarball
-The process for downloading @command{ns-3} via tarball is simpler than the
-Mercurial process since all of the pieces are pre-packaged for you. You just
-have to pick a release, download it and decompress it.
-
-As mentioned above, one practice is to create a directory called @code{repos}
-in one's home directory under which one can keep local Mercurial repositories.
-One could also keep a @code{tarballs} directory. @emph{Hint: the tutorial
-will assume you downloaded into a @code{repos} directory, so remember the
-placekeeper.} If you adopt the @code{tarballs} directory approach, you can
-get a copy of a release by typing the following into your Linux shell
-(substitute the appropriate version numbers, of course):
-
-@verbatim
- cd
- mkdir tarballs
- cd tarballs
- wget http://www.nsnam.org/releases/ns-allinone-3.6.tar.bz2
- tar xjf ns-allinone-3.6.tar.bz2
-@end verbatim
-
-If you change into the directory @code{ns-allinone-3.6} you should see a
-number of files:
-
-@verbatim
-build.py* ns-3.6/ pybindgen-0.12.0.700/ util.py
-constants.py nsc-0.5.1/ README
-@end verbatim
-
-You are now ready to build the @command{ns-3} distribution.
-
-@c ========================================================================
-@c Building ns-3
-@c ========================================================================
-
-@node Building ns-3
-@section Building ns-3
-
-@subsection Building with build.py
-@cindex building with build.py
-The first time you build the @command{ns-3} project you should build using the
-@command{allinone} environment. This will get the project configured for you
-in the most commonly useful way.
-
-Change into the directory you created in the download section above. If you
-downloaded using Mercurial you should have a directory called
-@code{ns-3-allinone} under your @code{~/repos} directory. If you downloaded
-using a tarball you should have a directory called something like
-@code{ns-allinone-3.6} under your @code{~/tarballs} directory. Take a deep
-breath and type the following:
-
-@verbatim
- ./build.py
-@end verbatim
-
-You will see lots of typical compiler output messages displayed as the build
-script builds the various pieces you downloaded. Eventually you should see the
-following magic words:
-
-@verbatim
- Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
- 'build' finished successfully (2m30.586s)
-@end verbatim
-
-Once the project has built you can say goodbye to your old friends, the
-@code{ns-3-allinone} scripts. You got what you needed from them and will now
-interact directly with Waf and we do it in the @code{ns-3-dev} directory,
-not in the @code{ns-3-allinone} directory. Go ahead and change into the
-@code{ns-3-dev} directory (or the directory for the appropriate release you
-downloaded.
-
-@verbatim
- cd ns-3-dev
-@end verbatim
-
-@subsection Building with Waf
-@cindex building with Waf
-@cindex configuring Waf
-@cindex building debug version with Waf
-@cindex compiling with Waf
-@cindex unit tests with Waf
-We use Waf to configure and build the @command{ns-3} project. It's not
-strictly required at this point, but it will be valuable to take a slight
-detour and look at how to make changes to the configuration of the project.
-Probably the most useful configuration change you can make will be to
-build the optimized version of the code. By default you have configured
-your project to build the debug version. Let's tell the project to do
-make an optimized build. To explain to Waf that it should do optimized
-builds you will need to execute the following command,
-
-@verbatim
- ./waf -d optimized configure
-@end verbatim
-
-This runs Waf out of the local directory (which is provided as a convenience
-for you). As the build system checks for various dependencies you should see
-output that looks similar to the following,
-
-@verbatim
- Checking for program g++ : ok /usr/bin/g++
- Checking for program cpp : ok /usr/bin/cpp
- Checking for program ar : ok /usr/bin/ar
- Checking for program ranlib : ok /usr/bin/ranlib
- Checking for g++ : ok
- Checking for program pkg-config : ok /usr/bin/pkg-config
- Checking for -Wno-error=deprecated-declarations support : yes
- Checking for -Wl,--soname=foo support : yes
- Checking for header stdlib.h : ok
- Checking for header signal.h : ok
- Checking for header pthread.h : ok
- Checking for high precision time implementation : 128-bit integer
- Checking for header stdint.h : ok
- Checking for header inttypes.h : ok
- Checking for header sys/inttypes.h : not found
- Checking for library rt : ok
- Checking for header netpacket/packet.h : ok
- Checking for pkg-config flags for GSL : ok
- Checking for header linux/if_tun.h : ok
- Checking for pkg-config flags for GTK_CONFIG_STORE : ok
- Checking for pkg-config flags for LIBXML2 : ok
- Checking for library sqlite3 : ok
- Checking for NSC location : ok ../nsc (guessed)
- Checking for library dl : ok
- Checking for NSC supported architecture x86_64 : ok
- Checking for program python : ok /usr/bin/python
- Checking for Python version >= 2.3 : ok 2.5.2
- Checking for library python2.5 : ok
- Checking for program python2.5-config : ok /usr/bin/python2.5-config
- Checking for header Python.h : ok
- Checking for -fvisibility=hidden support : yes
- Checking for pybindgen location : ok ../pybindgen (guessed)
- Checking for Python module pybindgen : ok
- Checking for pybindgen version : ok 0.10.0.640
- Checking for Python module pygccxml : ok
- Checking for pygccxml version : ok 0.9.5
- Checking for program gccxml : ok /usr/local/bin/gccxml
- Checking for gccxml version : ok 0.9.0
- Checking for program sudo : ok /usr/bin/sudo
- Checking for program hg : ok /usr/bin/hg
- Checking for program valgrind : ok /usr/bin/valgrind
- ---- Summary of optional NS-3 features:
- Threading Primitives : enabled
- Real Time Simulator : enabled
- Emulated Net Device : enabled
- GNU Scientific Library (GSL) : enabled
- Tap Bridge : enabled
- GtkConfigStore : enabled
- XmlIo : enabled
- SQlite stats data output : enabled
- Network Simulation Cradle : enabled
- Python Bindings : enabled
- Python API Scanning Support : enabled
- Use sudo to set suid bit : not enabled (option --enable-sudo not selected)
- Build examples and samples : enabled
- Static build : not enabled (option --enable-static not selected)
- 'configure' finished successfully (2.870s)
-@end verbatim
-
-Note the last part of the above output. Some ns-3 options are not enabled by
-default or require support from the underlying system to work properly.
-For instance, to enable XmlTo, the library libxml-2.0 must be found on the
-system. If this library were not found, the corresponding @command{ns-3} feature
-would not be enabled and a message would be displayed. Note further that there is
-a feature to use the program @code{sudo} to set the suid bit of certain programs.
-This is not enabled by default and so this feature is reported as ``not enabled.''
-
-Now go ahead and switch back to the debug build.
-
-@verbatim
- ./waf -d debug configure
-@end verbatim
-
-The build system is now configured and you can build the debug versions of
-the @command{ns-3} programs by simply typing,
-
-@verbatim
- ./waf
-@end verbatim
-
-Some waf commands are meaningful during the build phase and some commands are valid
-in the configuration phase. For example, if you wanted to use the emulation
-features of @command{ns-3} you might want to enable setting the suid bit using
-sudo as described above. This turns out to be a configuration-time command, and so
-you could reconfigure using the following command
-
-@verbatim
- ./waf -d debug --enable-sudo configure
-@end verbatim
-
-If you do this, waf will have run sudo to change the socket creator programs of the
-emulation code to run as root. There are many other configure- and build-time options
-available in waf. To explore these options, type:
-
-@verbatim
- ./waf --help
-@end verbatim
-
-We'll use some of the testing-related commands in the next section.
-
-Okay, sorry, I made you build the @command{ns-3} part of the system twice,
-but now you know how to change the configuration and build optimized code.
-
-@c ========================================================================
-@c Testing ns-3
-@c ========================================================================
-
-@node Testing ns-3
-@section Testing ns-3
-
-@cindex unit tests
-You can run the unit tests of the @command{ns-3} distribution by running the
-``./test.py -c core'' script,
-
-@verbatim
- ./test.py -c core
-@end verbatim
-
-These tests are run in parallel by waf. You should eventually
-see a report saying that,
-
-@verbatim
- 47 of 47 tests passed (47 passed, 0 failed, 0 crashed, 0 valgrind errors)
-@end verbatim
-
-This is the important message.
-
-You will also see output from the test runner and the output will actually look something like,
-
-@verbatim
- Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
- Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
- 'build' finished successfully (1.799s)
- PASS: TestSuite ns3-wifi-interference
- PASS: TestSuite histogram
- PASS: TestSuite sample
- PASS: TestSuite ipv4-address-helper
- PASS: TestSuite devices-wifi
- PASS: TestSuite propagation-loss-model
-
- ...
-
- PASS: TestSuite attributes
- PASS: TestSuite config
- PASS: TestSuite global-value
- PASS: TestSuite command-line
- PASS: TestSuite basic-random-number
- PASS: TestSuite object
- PASS: TestSuite random-number-generators
- 47 of 47 tests passed (47 passed, 0 failed, 0 crashed, 0 valgrind errors)
-@end verbatim
-
-This command is typically run by @code{users} to quickly verify that an
-@command{ns-3} distribution has built correctly.
-
-@c ========================================================================
-@c Running a Script
-@c ========================================================================
-
-@node Running a Script
-@section Running a Script
-@cindex running a script with Waf
-We typically run scripts under the control of Waf. This allows the build
-system to ensure that the shared library paths are set correctly and that
-the libraries are available at run time. To run a program, simply use the
-@code{--run} option in Waf. Let's run the @command{ns-3} equivalent of the
-ubiquitous hello world program by typing the following:
-
-@verbatim
- ./waf --run hello-simulator
-@end verbatim
-
-Waf first checks to make sure that the program is built correctly and
-executes a build if required. Waf then executes the program, which
-produces the following output.
-
-@verbatim
- Hello Simulator
-@end verbatim
-
-@emph{Congratulations. You are now an ns-3 user.}
-
-@emph{What do I do if I don't see the output?}
-
-If you don't see @code{waf} messages indicating that the build was
-completed successfully, but do not see the ``Hello Simulator'' output,
-chances are that you have switched your build mode to ``optimized'' in
-the ``Building with Waf'' section, but have missed the change back to
-``debug'' mode. All of the console output used in this tutorial uses a
-special @command{ns-3} logging component that is useful for printing
-user messages to the console. Output from this component is
-automatically disabled when you compile optimized code -- it is
-``optimized out.'' If you don't see the ``Hello Simulator'' output,
-type the following,
-
-@verbatim
- ./waf -d debug configure
-@end verbatim
-
-to tell @code{waf} to build the debug versions of the @command{ns-3}
-programs. You must still build the actual debug version of the code by
-typing,
-
-@verbatim
- ./waf
-@end verbatim
-
-Now, if you run the @code{hello-simulator} program, you should see the
-expected output.
-
-If you want to run programs under another tool such as gdb or valgrind,
-see this @uref{http://www.nsnam.org/wiki/index.php/User_FAQ#How_to_run_NS-3_programs_under_another_tool,,wiki entry}.
-
--- a/doc/tutorial/in-process/Makefile Sun Jan 02 22:57:04 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-TEXI2HTML = texi2html
-TEXI2PDF = texi2dvi --pdf
-EPSTOPDF = epstopdf
-TGIF = tgif
-DIA = dia
-CONVERT = convert
-CSS = --css-include=tutorial.css
-SPLIT = --split section
-
-DIA_SOURCES = pp.dia dumbbell.dia star.dia
-TGIF_SOURCES = helpers.obj
-
-DIA_EPS = ${DIA_SOURCES:.dia=.eps}
-DIA_PNG = ${DIA_SOURCES:.dia=.png}
-DIA_PDF = ${DIA_SOURCES:.dia=.pdf}
-
-TGIF_EPS = ${TGIF_SOURCES:.obj=.eps}
-TGIF_PNG = ${TGIF_SOURCES:.obj=.png}
-TGIF_PDF = ${TGIF_SOURCES:.obj=.pdf}
-
-all: images html split-html pdf
-
-# Note: tgif requires a valid x display to convert from .obj to .png.
-# If running this makefile on a remote console, the X virtual frame
-# buffer may be needed (xorg-x11-server-Xvfb) to provide a "fake"
-# display
-images:
- cd figures/; $(DIA) -t png $(DIA_SOURCES)
- cd figures/; $(DIA) -t eps $(DIA_SOURCES)
- cd figures/; $(foreach FILE,$(DIA_EPS),$(EPSTOPDF) $(FILE);)
- cd figures/; $(TGIF) -print -png $(TGIF_SOURCES)
- cd figures/; $(TGIF) -print -eps $(TGIF_SOURCES)
- cd figures/; $(foreach FILE,$(TGIF_EPS),$(EPSTOPDF) $(FILE);)
-
-html: images
- $(TEXI2HTML) ${CSS} tutorial.texi
-
-split-html: images
- $(TEXI2HTML) ${CSS} ${SPLIT} tutorial.texi
-
-pdf: images
- $(TEXI2PDF) tutorial.texi
-
-figures-clean:
- cd figures/; rm -rf $(DIA_EPS); rm -rf $(DIA_PNG); rm -rf $(DIA_PDF)
- cd figures/; rm -rf $(TGIF_EPS); rm -rf $(TGIF_PNG); rm -rf $(TGIF_PDF)
-
-clean: figures-clean
- rm -rf tutorial.aux tutorial.cp tutorial.cps tutorial.fn tutorial.ky tutorial.pg tutorial.tp tutorial.vr tutorial.toc tutorial.log tutorial.pdf tutorial.html tutorial/
--- a/doc/tutorial/in-process/attributes.texi Sun Jan 02 22:57:04 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,535 +0,0 @@
-@node ns-3 Attributes
-@chapter ns-3 Attributes
-@anchor{chap:Attributes}
-
-In ns-3 simulations, there are two main aspects to configuration:
-@itemize @bullet
-@item the simulation topology and how objects are connected
-@item the values used by the models instantiated in the topology
-@end itemize
-
-This chapter focuses on the second item above: how the many values
-in use in ns-3 are organized, documented, and modifiable by ns-3 users.
-The ns-3 attribute system is also the underpinning of how traces
-and statistics are gathered in the simulator.
-
-Before delving into details of the attribute value system,
-it will help to review some basic properties of @code{class ns3::Object}.
-
-@node Object Overview
-@section Object Overview
-
-ns-3 is fundamentally a C++ object-based system. By this we mean that
-new C++ classes (types) can be declared, defined, and subclassed
-as usual.
-
-Many ns-3 objects inherit from the @code{ns3::Object} base class. These
-objects have some additional properties that we exploit for
-organizing the system and improving the memory management
-of our objects:
-
-@itemize @bullet
-@item a "metadata" system that links the class name to a lot of
-meta-information about the object, including the base class of the subclass,
-the set of accessible constructors in the subclass, and the set of
-"attributes" of the subclass
-@item a reference counting smart pointer implementation, for memory
-management.
-@end itemize
-
-ns-3 objects that use the attribute system derive from either
-@code{ns3::Object} or @code{ns3::ObjectBase}. Most ns-3 objects
-we will discuss derive from @code{ns3::Object}, but a few that
-are outside the smart pointer memory management framework derive
-from @code{ns3::ObjectBase}.
-
-Let's review a couple of properties of these objects.
-
-@node Smart pointers
-@subsection Smart pointers
-
-As introduced above in @ref{Smart Pointers 101}, ns-3 objects
-are memory managed by a
-@uref{http://en.wikipedia.org/wiki/Smart_pointer,,reference counting smart pointer implementation}, @code{class ns3::Ptr}.
-
-Smart pointers are used extensively in the ns-3 APIs, to avoid passing
-references to heap-allocated objects that may cause memory leaks.
-For most basic usage (syntax), treat a smart pointer like a regular pointer:
-@verbatim
- Ptr<WifiNetDevice> nd = ...;
- nd->CallSomeFunction ();
- // etc.
-@end verbatim
-
-@node CreateObject
-@subsection CreateObject
-
-As we discussed above in @ref{Object Creation},
-at the lowest-level API, objects of type @code{ns3::Object} are
-not instantiated using @code{operator new} as usual but instead by
-a templated function called @code{CreateObject()}.
-
-A typical way to create such an object is as follows:
-@verbatim
- Ptr<WifiNetDevice> nd = CreateObject<WifiNetDevice> ();
-@end verbatim
-
-You can think of this as being functionally equivalent to:
-@verbatim
- WifiNetDevice* nd = new WifiNetDevice ();
-@end verbatim
-
-Objects that derive from @code{ns3::Object} must be allocated
-on the heap using CreateObject(). Those deriving from
-@code{ns3::ObjectBase}, such as ns-3 helper functions and packet
-headers and trailers, can be allocated on the stack.
-
-In some scripts, you may not see a lot of CreateObject() calls
-in the code;
-this is because there are some helper objects in effect that
-are doing the CreateObject()s for you.
-
-@node TypeId
-@subsection TypeId
-
-ns-3 classes that derive from class ns3::Object can include
-a metadata class called @code{TypeId} that records meta-information
-about the class, for use in the object aggregation and component
-manager systems:
-@itemize @bullet
- @item a unique string identifying the class
- @item the base class of the subclass, within the metadata system
- @item the set of accessible constructors in the subclass
-@end itemize
-
-@node Object Summary
-@subsection Object Summary
-
-Putting all of these concepts together, let's look at a specific
-example: @code{class ns3::Node}.
-
-The public header file node.h has a declaration that includes
-a static GetTypeId function call:
-@verbatim
-class Node : public Object
-{
-public:
- static TypeId GetTypeId (void);
- ...
-@end verbatim
-
-This is defined in the node.cc file as follows:
-@verbatim
-TypeId
-Node::GetTypeId (void)
-{
- static TypeId tid = TypeId ("ns3::Node")
- .SetParent<Object> ()
- return tid;
-}
-@end verbatim
-Finally, when users want to create Nodes, they call:
-@verbatim
- Ptr<Node> n = CreateObject<Node> n;
-@end verbatim
-
-We next discuss how attributes (values associated with member variables
-or functions of the class) are plumbed into the above TypeId.
-
-@node Attribute Overview
-@section Attribute Overview
-
-The goal of the attribute system is to organize the access of
-internal member objects of a simulation. This goal arises because,
-typically in simulation, users will cut and paste/modify existing
-simulation scripts, or will use higher-level simulation constructs,
-but often will be interested in studying or tracing particular
-internal variables. For instance, use cases such as:
-@itemize @bullet
-@item "I want to trace the packets on the wireless interface only on
-the first access point"
-@item "I want to trace the value of the TCP congestion window (every
-time it changes) on a particular TCP socket"
-@item "I want a dump of all values that were used in my simulation."
-@end itemize
-
-Similarly, users may want fine-grained access to internal
-variables in the simulation, or may want to broadly change the
-initial value used for a particular parameter in all subsequently
-created objects. Finally, users may wish to know what variables
-are settable and retrievable in a simulation configuration. This
-is not just for direct simulation interaction on the command line;
-consider also a (future) graphical user interface
-that would like to be able to provide a feature whereby a user
-might right-click on an node on the canvas and see a hierarchical,
-organized list of parameters that are settable on the node and its
-constituent member objects, and help text and default values for
-each parameter.
-
-@node Functional overview
-@subsection Functional overview
-
-We provide a way for users to access values deep in the system, without
-having to plumb accessors (pointers) through the system and walk
-pointer chains to get to them. Consider a class DropTailQueue that
-has a member variable that is an unsigned integer @code{m_maxPackets};
-this member variable controls the depth of the queue.
-
-If we look at the declaration of DropTailQueue, we see the following:
-@verbatim
-class DropTailQueue : public Queue {
-public:
- static TypeId GetTypeId (void);
- ...
-
-private:
- std::queue<Ptr<Packet> > m_packets;
- uint32_t m_maxPackets;
-};
-@end verbatim
-
-Let's consider things that a user may want to do with the value of
-m_maxPackets:
-
-@itemize @bullet
-@item Set a default value for the system, such that whenever a new
-DropTailQueue is created, this member is initialized to that default.
-@item Set or get the value on an already instantiated queue.
-@end itemize
-
-The above things typically require providing Set() and Get() functions,
-and some type of global default value.
-
-In the ns-3 attribute system, these value definitions and accessor
-functions are moved into the TypeId class; e.g.:
-@verbatim
-TypeId DropTailQueue::GetTypeId (void)
-{
- static TypeId tid = TypeId ("ns3::DropTailQueue")
- .SetParent<Queue> ()
- .AddConstructor<DropTailQueue> ()
- .AddAttribute ("MaxPackets", "The maximum number of packets accepted by this DropTailQueue.",
- Uinteger (100),
- MakeUintegerAccessor (&DropTailQueue::m_maxPackets),
- MakeUintegerChecker<uint32_t> ())
- ;
-
- return tid;
-}
-@end verbatim
-
-The AddAttribute() method is performing a number of things with this
-value:
-@itemize @bullet
-@item Binding the variable m_maxPackets to a string "MaxPackets"
-@item Providing a default value (100 packets)
-@item Providing some help text defining the value
-@item Providing a "checker" (not used in this example) that can be used to set
-bounds on the allowable range of values
-@end itemize
-
-The key point is that now the value of this variable and its default
-value are accessible in the attribute namespace, which is based on
-strings such as "MaxPackets" and TypeId strings. In the next
-section, we will provide an example script that shows how users
-may manipulate these values.
-
-@node Basic usage
-@subsection Basic usage
-
-Let's look at how a user script might access these values.
-This is based on the script found at @code{samples/main-attribute-value.cc},
-with some details stripped out.
-@verbatim
-//
-// This is a basic example of how to use the attribute system to
-// set and get a value in the underlying system; namely, an unsigned
-// integer of the maximum number of packets in a queue
-//
-
-int
-main (int argc, char *argv[])
-{
-
- // By default, the MaxPackets attribute has a value of 100 packets
- // (this default can be observed in the function DropTailQueue::GetTypeId)
- //
- // Here, we set it to 80 packets. We could use one of two value types:
- // a string-based value or a Uinteger value
- Config::SetDefault ("ns3::DropTailQueue::MaxPackets", String ("80"));
- // The below function call is redundant
- Config::SetDefault ("ns3::DropTailQueue::MaxPackets", Uinteger(80));
-
- // Allow the user to override any of the defaults and the above
- // SetDefaults() at run-time, via command-line arguments
- CommandLine cmd;
- cmd.Parse (argc, argv);
-@end verbatim
-
-The main thing to notice in the above are the two calls to
-@code{Config::SetDefault}. This is how we set the default value
-for all subsequently instantiated DropTailQueues. We illustrate
-that two types of Value classes, a String and a Uinteger class,
-can be used to assign the value to the attribute named by
-"ns3::DropTailQueue::MaxPackets".
-
-Now, we will create a few objects using the low-level API; here,
-our newly created queues will not have a m_maxPackets initialized to
-100 packets but to 80 packets, because of what we did above with
-default values.
-@verbatim
- Ptr<Node> n0 = CreateObject<Node> ();
-
- Ptr<PointToPointNetDevice> net0 = CreateObject<PointToPointNetDevice> ();
- n0->AddDevice (net0);
-
- Ptr<Queue> q = CreateObject<DropTailQueue> ();
- net0->AddQueue(q);
-@end verbatim
-
-At this point, we have created a single node (Node 0) and a
-single PointToPointNetDevice (NetDevice 0) and added a
-DropTailQueue to it.
-
-Now, we can manipulate the MaxPackets value of the already
-instantiated DropTailQueue. Here are various ways to do that.
-
-@subsubsection Pointer-based access
-
-We assume that a smart pointer (Ptr) to a relevant network device is
-in hand; here, it is the net0 pointer.
-
-One way to change the value is to access a pointer to the
-underlying queue and modify its attribute.
-
-First, we observe that we can get a pointer to the (base class)
-queue via the PointToPointNetDevice attributes, where it is called
-TxQueue
-@verbatim
- Ptr<Queue> txQueue = net0->GetAttribute ("TxQueue");
-@end verbatim
-
-Using the GetObject function, we can perform a safe downcast
-to a DropTailQueue, where MaxPackets is a member
-@verbatim
- Ptr<DropTailQueue> dtq = txQueue->GetObject <DropTailQueue> ();
- NS_ASSERT (dtq);
-@end verbatim
-
-Next, we can get the value of an attribute on this queue
-We have introduced wrapper "Value" classes for the underlying
-data types, similar to Java wrappers around these types, since
-the attribute system stores values and not disparate types.
-Here, the attribute value is assigned to a Uinteger, and
-the Get() method on this value produces the (unwrapped) uint32_t.
-@verbatim
- Uinteger limit = dtq->GetAttribute ("MaxPackets");
- NS_LOG_INFO ("1. dtq limit: " << limit.Get () << " packets");
-@end verbatim
-
-Note that the above downcast is not really needed; we could have
-done the same using the Ptr<Queue> even though the attribute
-is a member of the subclass
-@verbatim
- limit = txQueue->GetAttribute ("MaxPackets");
- NS_LOG_INFO ("2. txQueue limit: " << limit.Get () << " packets");
-@end verbatim
-
-Now, let's set it to another value (60 packets)
-@verbatim
- txQueue->SetAttribute("MaxPackets", Uinteger (60));
- limit = txQueue->GetAttribute ("MaxPackets");
- NS_LOG_INFO ("3. txQueue limit changed: " << limit.Get () << " packets");
-@end verbatim
-
-@subsubsection Namespace-based access
-
-An alternative way to get at the attribute is to use the configuration
-namespace. Here, this attribute resides on a known path in this
-namespace; this approach is useful if one doesn't have access to
-the underlying pointers and would like to configure a specific
-attribute with a single statement.
-@verbatim
- Config::Set ("/NodeList/0/DeviceList/0/TxQueue/MaxPackets", Uinteger (25));
- limit = txQueue->GetAttribute ("MaxPackets");
- NS_LOG_INFO ("4. txQueue limit changed through namespace: " <<
- limit.Get () << " packets");
-@end verbatim
-
-We could have also used wildcards to set this value for all nodes
-and all net devices (which in this simple example has the same
-effect as the previous Set())
-@verbatim
- Config::Set ("/NodeList/*/DeviceList/*/TxQueue/MaxPackets", Uinteger (15));
- limit = txQueue->GetAttribute ("MaxPackets");
- NS_LOG_INFO ("5. txQueue limit changed through wildcarded namespace: " <<
- limit.Get () << " packets");
-@end verbatim
-
-@node Setting through constructors and helper classes
-@subsection Setting through constructors helper classes
-
-Arbitrary combinations of attributes can be set and fetched from
-the helper and low-level APIs; either from the constructors themselves:
-@verbatim
-Ptr<Object> p = CreateObject<MyNewObject> ("n1", v1, "n2", v2, ...);
-@end verbatim
-or from the higher-level helper APIs, such as:
-@verbatim
- mobility.SetPositionAllocator ("GridPositionAllocator",
- "MinX", FpValue (-100.0),
- "MinY", FpValue (-100.0),
- "DeltaX", FpValue (5.0),
- "DeltaY", FpValue (20.0),
- "GridWidth", UintValue (20),
- "LayoutType", "RowFirst");
-@end verbatim
-
-@node Value classes
-@subsection Value classes
-Readers will note the new Value classes. These can be thought of as
-an intermediate class that can be used to convert from raw types to the
-Values that are used by the system. Recall that this database is holding
-objects of many types with a single generic type. Conversions to this
-type can either be done using an intermediate class (IntValue, FpValue for
-"floating point") or via strings. Direct implicit conversion of types
-to Value is not really practical. So in the above, users have a choice
-of using strings or values:
-@verbatim
-p->Set ("cwnd", "100"); // string-based setter
-p->Set ("cwnd", IntValue(100)); // value-based setter
-@end verbatim
-
-The system provides some macros that help users declare and define
-new Value subclasses for new types that they want to introduce into
-the attribute system.
-
-@node Extending attributes
-@section Extending attributes
-
-The ns-3 system will place a number of internal values under the
-attribute system, but undoubtedly users will want to extend this
-to pick up ones we have missed, or to add their own classes to this.
-
-@subsection Adding an existing internal variable to the metadata system
-
-// XXX revise me
-
-Consider this variable in class TcpSocket:
-@verbatim
- uint32_t m_cWnd; // Congestion window
-@end verbatim
-
-Suppose that someone working with Tcp wanted to get or set the
-value of that variable using the metadata system. If it were not
-already provided by ns-3, the user could declare the following addition
-in the metadata system (to the TypeId declaration for TcpSocket):
-@verbatim
- .AddParameter ("Congestion window",
- "Tcp congestion window (bytes)",
- MakeUIntParamSpec (&TcpSocket::m_cWnd, 1));
-
-@end verbatim
-
-Now, the user with a pointer to the TcpSocket can perform operations
-such as setting and getting the value, without having to add these
-functions explicitly. Furthermore, access controls can be applied, such
-as allowing the parameter to be read and not written, or bounds
-checking on the permissible values can be applied.
-
-@subsection Adding a new TypeId
-
-Here, we discuss the impact on a user who wants to add a new class to
-ns-3; what additional things must be done to hook it into this system.
-
-We've already introduced what a TypeId definition looks like:
-@verbatim
-TypeId
-RandomWalk2dMobilityModel::GetTypeId (void)
-{
- static TypeId tid = TypeId ("RandomWalkMobilityModel")
- .SetParent<MobilityModel> ()
- .SetGroupName ("Mobility")
- .AddConstructor<RandomWalk2dMobilityModel> ()
- // followed by a number of Parameters
- .AddParameter ("bounds",
- "Bounds of the area to cruise.",
- MakeRectangleParamSpec (&RandomWalk2dMobilityModel::m_bounds, Rectangle (0.0, 0.0, 100.0, 100.0)))
- .AddParameter ("time",
- "Change current direction and speed after moving for this delay.",
- MakeTimeParamSpec (&RandomWalk2dMobilityModel::m_modeTime,
- Seconds (1.0)))
-
- // etc (more parameters).
-@end verbatim
-
-The declaration for this in the class declaration is one-line public
-member method:
-@verbatim
- public:
- static TypeId GetTypeId (void);
-@end verbatim
-
-@section Adding new class type to the Value system
-
-From the perspective of the user who writes a new class in the system and
-wants to hook it in to the attribute system, there is mainly the matter
-of writing
-the conversions to/from strings and Values. Most of this can be
-copy/pasted with macro-ized code. For instance, consider class
-Rectangle in the @code{src/mobility/} directory:
-
-One line is added to the class declaration:
-@verbatim
-/**
- * \brief a 2d rectangle
- */
-class Rectangle
-{
-...
-
- VALUE_HELPER_HEADER_1 (Rectangle);
-};
-@end verbatim
-
-One templatized declaration, and two operators, are added below the
-class declaration:
-
-@verbatim
-std::ostream &operator << (std::ostream &os, const Rectangle &rectangle);
-std::istream &operator >> (std::istream &is, Rectangle &rectangle);
-
-VALUE_HELPER_HEADER_2 (Rectangle);
-@end verbatim
-
-In the class definition, the code looks like this:
-
-@verbatim
-VALUE_HELPER_CPP (Rectangle);
-
-std::ostream &
-operator << (std::ostream &os, const Rectangle &rectangle)
-{
- os << rectangle.xMin << "|" << rectangle.xMax << "|" << rectangle.yMin << "|" << rectangle.yMax;
- return os;
-}
-std::istream &
-operator >> (std::istream &is, Rectangle &rectangle)
- {
- char c1, c2, c3;
- is >> rectangle.xMin >> c1 >> rectangle.xMax >> c2 >> rectangle.yMin >> c3 >> rectangle.yMax;
- if (c1 != '|' ||
- c2 != '|' ||
- c3 != '|')
- {
- is.setstate (std::ios_base::failbit);
- }
- return is;
-}
-@end verbatim
-
-These stream operators simply convert from a string representation of the
-Rectangle ("xMin|xMax|yMin|yMax") to the underlying Rectangle, and the
-modeler must specify these operators and the string syntactical representation
-of an instance of the new class.
-
--- a/doc/tutorial/in-process/helpers.texi Sun Jan 02 22:57:04 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,20 +0,0 @@
-@node Helper Functions
-@chapter Helper Functions
-@anchor{chap:Helpers}
-This chapter describes an intermediate API for the simulator; what we
-call the "helper API". The helper API is implemented in
-@code{src/helper/} directory; it depends on (and wraps) the low-level
-API which is implemented everywhere else in @code{src/}. The following
-figure shows this relationship.
-@center @image{figures/helpers,,,,png}
-
-The use of the helper API is optional. It has two main goals:
-@itemize @bullet
-@item Provide "syntactic sugar" to wrap a number of related low-level
-API calls together, that would normally be grouped together often, into
-something that is more user-friendly.
-@item Handle configuration of larger topological units (e.g., a set
-of nodes or a set of nodes on a particular link) .
-@end itemize
-
-(more to follow)
--- a/doc/tutorial/in-process/introduction.texi Sun Jan 02 22:57:04 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2034 +0,0 @@
-
-@c ========================================================================
-@c Begin document body here
-@c ========================================================================
-
-@c ========================================================================
-@c Tutorial Goals
-@c ========================================================================
-
-@node Tutorial Goals
-@unnumbered Tutorial Goals
-
-@c This is an unnumbered section, like a preface. Numbering
-@c starts with section 1 (Introduction)
-
-The goal of this ns-3 tutorial is to introduce new users of ns-3 to enough
-of the system to enable them to author simple simulation scripts and extract
-useful information from the simulations. We begin by introducing some of the
-other important resources that are available to those interested in using or
-writing scripts, models and even those interested in making contributions to
-the core ns-3 system. We provide an overview of some of the
-important abstractions, design patterns and idioms used when writing
-ns-3 scripts, and then dig right in by beginning to write simulation
-scripts, run them and interpret results.
-
-After completing this tutorial, one should be able to:
-@itemize @bullet
-@item Find documentation resources in the distribution and on the web;
-@item Download and compile the ns-3 system;
-@item Understand the key software conventions of ns-3;
-@item Modify configuration parameters of existing scripts;
-@item Change the simulation output (tracing, logging, statistics);
-@item Extend the simulator to use new objects
-@item Write new ns-3 applications;
-@item See how to port code from ns-2;
-@item ... (more to follow)
-@end itemize
-
-@c ========================================================================
-@c PART: Introduction
-@c ========================================================================
-@c The below chapters are under the major heading "Introduction"
-@c This is similar to the Latex \part command
-@c
-@c ========================================================================
-@c Overview
-@c ========================================================================
-@node Overview
-@chapter Overview
-
-@menu
-* For ns-2 users::
-* Contributing::
-* Tutorial organization::
-@end menu
-
-The ns-3 simulator is a discrete-event network
-simulator targeted primarily for research and educational use.
-The @uref{http://www.nsnam.org,,ns-3 project}, started in
-2006, is an open-source project. The goal of the project is to
-build a new network simulator primarily for research and educational use.
-
-Primary documentation for the ns-3 project is available in
-three forms:
-@itemize @bullet
-@item @uref{http://www.nsnam.org/doxygen/index.html,,ns-3 Doxygen/Manual}: Documentation of the public APIs of the simulator
-@item Tutorial (this document)
-@item @uref{http://www.nsnam.org/wiki/index.php,, ns-3 wiki}
-@end itemize
-
-The purpose of this tutorial is to introduce new ns-3 users to the
-system in a structured way. It is sometimes difficult for new users to
-glean essential information from detailed manuals and to convert this
-information into working simulations. In this tutorial, we will build
-several example simulations, introducing and explaining key concepts and
-features as we go.
-
-As the tutorial unfolds, we will introduce the full ns-3
-documentation
-and provide pointers to source code for those interested in delving deeper
-into the workings of the system.
-
-A few key points are worth noting at the onset:
-@itemize @bullet
-@item ns-3 is not an extension of @uref{http://www.isi.edu/nsnam/ns,,ns-2};
-it is a new
-simulator. The two simulators are both written in C++ but ns-3
-is a new simulator that does not support the ns-2 APIs.
-Some models from ns-2 have already been ported from ns-2
-to ns-3. The project will continue to maintain ns-2 while
-ns-3 is being built, and will study transition and
-integration mechanisms.
-@item ns-3 is open-source, and the project strives to maintain
-an open environment for researchers to contribute and share their
-software.
-@end itemize
-
-@node For ns-2 users
-@section For ns-2 users
-
-For those familiar with ns-2, the most visible outward change
-when moving to ns-3 is the choice of scripting language.
-ns-2 is typically scripted in Tcl and results of simulations can
-be visualized using the Network Animator @command{nam}. In
-ns-3 there is currently no visualization module, and Python
-bindings have been developed (Tcl bindings have been prototyped
-using @uref{http://www.swig.org,,SWIG}, but are not supported by the
-current development team).
-In this tutorial, we will concentrate on
-scripting directly in C++ and interpreting results via trace files.
-
-But there are similarities as well (both, for example, are based
-on C++ objects, and some code from ns-2 has already been ported
-to ns-3). We will try to highlight differences between ns-2 and ns-3
-as we proceed in this tutorial.
-
-@node Contributing
-@section Contributing
-
-@cindex software configuration management
-ns-3 is a research and educational simulator, by and for the
-research community. It will rely on the ongoing contributions of
-the community to develop new models, debug or maintain
-existing ones, and share results. There are a few policies
-that we hope will encourage people to contribute to ns-3 like they
-have for ns-2:
-@itemize @bullet
-@item open source licensing based on GNU GPLv2 compatibility
-@item @uref{http://www.nsnam.org/wiki/index.php,,wiki}
-@item @uref{http://www.nsnam.org/wiki/index.php/Contributed_Code,,Contributed Code} page, similar to ns-2's popular
-@uref{http://nsnam.isi.edu/nsnam/index.php/Contributed_Code,,Contributed Code}
-page
-@item @code{src/contrib} directory (we will host your contributed code)
-@item open @uref{http://www.nsnam.org/bugzilla,,bug tracker}
-@item ns-3 developers will gladly help potential contributors to get
-started with the simulator (please contact @uref{http://www.nsnam.org/people.html,,one of us})
-@end itemize
-
-If you are an ns user, please consider to provide your feedback,
-bug fixes, or code to the project.
-
-@node Tutorial organization
-@section Tutorial organization
-
-The tutorial assumes that new users might follow a path such as follows:
-
-@itemize @bullet
-@item browse the source code and documentation, to get a feel for
-the simulator and what it might be like to handle;
-@item try to download and build a copy;
-@item try to run a few sample programs, and perhaps change some configurations;
-@item look at simulation output, and try to adjust it
-@item study the software architecture of the system, to consider hacking it or
-extending it;
-@item write new models or port existing code to ns-3, and eventually post those
-models back to the community.
-@end itemize
-
-As a result, we have tried to organize the tutorial along the above
-broad sequences of events.
-
-@c ========================================================================
-@c Browsing ns-3
-@c ========================================================================
-
-@node Browsing
-@chapter Browsing ns-3
-
-@menu
-* Source code::
-* Doxygen::
-* Other documentation::
-@end menu
-
-@node Source code
-@section Source code
-
-The most recent code can be browsed on our web server at the following link:
-@uref{http://code.nsnam.org/?sort=lastchange}. If you click on the bold
-repository names on the left of the page, you will see changelogs for
-these repositories, and links to the @emph{manifest}. From the manifest
-links, one can browse the source tree.
-
-The top-level directory will look something like:
-@verbatim
- AUTHORS RELEASE_NOTES examples/ src/ waf*
- LICENSE VERSION ns3/ tutorial/ waf.bat*
- README doc/ samples/ utils/ wscript
-@end verbatim
-The source code is mainly in the @code{src} directory. Example
-scripts are in the @code{examples} directory. Both are good directories
-to start browsing some code.
-
-For ns-2 users, who may be familiar with the @code{simple.tcl} example script
-in the ns-2 documentation, an analogous script is found in
-@code{examples/simple-point-to-point.cc} with a Python equivalent found
-in @emph{(pending Python merge)}.
-
-@node Doxygen
-@section Doxygen
-
-We document all of APIs using @uref{http://www.stack.nl/~dimitri/doxygen/,,Doxygen}. Current builds of this documentation are available at:
-@uref{http://www.nsnam.org/doxygen/index.html}, which are worth an initial
-look.
-
-@node Other documentation
-@section Other documentation
-
-See: @uref{http://www.nsnam.org/documents.html}.
-
-@c ========================================================================
-@c Resources
-@c ========================================================================
-
-@node Resources
-@chapter Resources
-
-@menu
-* The-Web::
-* Mercurial::
-* Waf::
-* Environment-Idioms-Design-Patterns::
-* Socket-Programming::
-@end menu
-
-@node The-Web
-@section The Web
-
-@cindex www.nsnam.org
-There are several important resources of which any ns-3 user must be
-aware. The main web site is located at @uref{http://www.nsnam.org}
-and provides access to basic information about the ns-3 system.
-Detailed documentation is available through the main web site at
-@uref{http://www.nsnam.org/documents.html}.
-
-@cindex documentation
-@cindex architecture
-You can find documents relating to the system architecture from this page,
-and also gain access to the detailed software documentation. The software
-system is documented in great detail using
-@uref{http://www.stack.nl/~dimitri/doxygen/,,Doxygen}. There is a Wiki that
-complements the main ns-3 web site which you will find at
-@uref{http://www.nsnam.org/wiki/}.
-
-You will find user and developer FAQs there as well as troubleshooting guides,
-third-party contributed code, papers, etc. The source code may be found
-and browsed at @uref{http://code.nsnam.org/}.
-
-@cindex repository!ns-3-dev
-@cindex repository!releases
-There you will find the current development tree in the repository named
-@code{ns-3-dev}. Past releases and experimental repositories of the core
-developers may also be found there.
-
-@node Mercurial
-@section Mercurial
-
-Complex software systems need some way to manage the organization and
-changes to the underlying code and documentation. There are many ways to
-perform this feat, and you may have heard of some of the systems that are
-currently used to do this. The Concurrent Version System (CVS) is probably
-the most well known.
-
-@cindex software configuration management
-@cindex Mercurial
-The ns-3 project uses Mercurial as its source code management system.
-Although you do not need to know much about Mercurial in order to complete
-this tutorial, we recommend becoming familiar with Mercurial and using it
-to access the source code. Mercurial has a web site at
-@uref{http://www.selenic.com/mercurial/},
-from which you can get binary or source releases of this Software
-Configuration Management (SCM) system. Selenic (the developer of Mercurial)
-also provides a tutorial at
-@uref{http://www.selenic.com/mercurial/wiki/index.cgi/Tutorial/},
-and a QuickStart guide at
-@uref{http://www.selenic.com/mercurial/wiki/index.cgi/QuickStart/}.
-
-You can also find vital information about using Mercurial and ns-3
-on the main ns-3 web site.
-
-@node Waf
-@section Waf
-
-@cindex Waf
-@cindex make
-@cindex build
-Once you have source code downloaded to your local system, you will need
-to compile that source to produce usable programs. Just as in the case of
-source code management, there are many tools available to perform this
-function. Probably the most famous of these tools is @code{make}. Along
-with being the most famous, @code{make} is probably the most difficult to
-use in a very large and highly configurable system. Because of this, many
-alternatives have been developed. Recently these systems have been developed
-using the Python language.
-
-The build system @code{Waf} is used on the ns-3 project. It is one
-of the new generation of Python-based build systems. You will not need to
-understand any Python to build the existing ns-3 system, and will
-only have to understand a tiny and intuitively obvious subset of Python in
-order to extend the system in most cases.
-
-For those interested in the gory details of Waf, the main web site can be
-found at @uref{http://freehackers.org/\~tnagy/waf.html}.
-
-@node Environment-Idioms-Design-Patterns
-@section Environment, Idioms, and Design Patterns
-
-@cindex C++
-As mentioned above, scripting in ns-3 is done in C++. A working
-knowledge of C++ and object-oriented concepts is assumed in this document.
-We will take some time to review some of the more advanced concepts or
-possibly unfamiliar language features, idioms and design patterns as they
-appear. We don't want this tutorial to devolve into a C++ tutorial, though,
-so we do expect a basic command of the language. There are an almost
-unimaginable number of sources of information on C++ available on the web or
-in print.
-
-If you are new to C++, you may want to find a tutorial- or cookbook-based
-book or web site and work through at least the basic features of the language
-before proceeding.
-
-@subsection Environment
-
-@cindex toolchain
-@cindex GNU
-The ns-3 system uses the GNU ``toolchain'' for development.
-A software toolchain is the set of programming tools available in the given
-environment. For a quick review of what is included in the GNU toolchain see,
-@uref{http://en.wikipedia.org/wiki/GNU_toolchain}.
-
-@cindex Linux
-Typically an ns-3 author will work in Linux or a Linux-like
-environment. For those running under Windows, there do exist environments
-which simulate the Linux environment to various degrees. The ns-3
-project supports development in the Cygwin and the MinGW environments for
-these users. See @uref{http://www.cygwin.com/} and
-@uref{http://www.mingw.org/} for details on downloading and using these
-systems. Cygwin provides many of the popular Linux system commands.
-It can, however, sometimes be problematic due to the way it
-actually does its emulation, and sometimes interactions with other Windows
-software can cause problems.
-
-@cindex Cygwin
-@cindex MinGW
-If you do use Cygwin or MinGW; and use Logitech products, we will save you
-quite a bit of heartburn right off the bat and encourage you to take a look
-at the @uref{http://www.mingw.org/MinGWiki/index.php/FAQ,,MinGW FAQ}.
-
-@cindex Logitech
-Search for ``Logitech'' and read the FAQ entry, ``why does make often
-crash creating a sh.exe.stackdump file when I try to compile my source code.''
-Believe it or not, the @code{Logitech Process Monitor} insinuates itself into
-every DLL in the system when it is running. It can cause your Cygwin or
-MinGW DLLs to die in mysterious ways and often prevents debuggers from
-running. Beware of Logitech.
-
-@subsection Idioms and Design Patterns
-
-@cindex idiom
-In any system, there are a number of problems to be solved that happen
-repeatedly. Often the solutions to these problems can be generalized and
-applied in a similar way across the system. These solutions are called
-Design Patterns. The ns-3 system relies on several classic design
-patterns.
-
-@cindex design pattern
-Also, in any language, there are constructs that, while they aren't part of the
-language per se, are commonly found and useful. For example, at the lowest
-level a C programmer should be able to immediately recognize the purpose and
-intent of the following code without having to reflect on the details:
-
-@verbatim
- for (;;)
-@end verbatim
-
-These low-level constructs, or idioms, extend upward in complexity, eventually
-becoming implementations of design patterns. As you are exposed to more
-and more of the ns-3 system, you will begin to recognize and be
-comfortable with the C++ implementations (idioms) of several important design
-patterns.
-
-@cindex functor
-@cindex callback
-@cindex smart pointer
-The ns-3 code relies heavily on
-@emph{Generalized Functors, Callbacks,
-Smart Pointers, Singletons, and Object Factories}. Although we will
-not assume any detailed knowledge of the idioms and design patterns used
-in the ns-3
-system, it will be useful for readers who intend to delve deeply into the
-system to understand some important related concepts. We recommend two
-resources: @uref{http://www.amazon.com/Design-Patterns-Object-Oriented-Addison-Wesley-Professional/dp/0201633612/,,Design Patterns: Elements of Reusable Object-Oriented Software, Gamma et. al.} and
-@uref{http://www.amazon.com/exec/obidos/ASIN/0201704315,,Modern C++ Design: Generic Programming and Design Patterns Applied, Alexandrescu}.
-
-Gamma addresses the abstract design patterns, and Alexandrescu addresses the
-C++ idioms you will often see throughout the ns-3 code.
-
-@cindex template
-Almost any use of ns-3 will require some basic knowledge of C++
-templates.
-We will discuss the high-level uses in this tutorial. However, if you venture
-deeply into the source code, you will see fairly heavy use of relatively
-sophisticated C++ templates in some of low-level modules of the system. The
-You don't have to be a template guru to complete this tutorial but if you
-expect to work in ns-3 within the simulation core, you will have to be
-somewhat fluent
-with templates. If you want to truly grok C++ templates we recommend,
-@uref{http://www.amazon.com/Templates-Complete-Guide-David-Vandevoorde/dp/0201734842/,,C++ Templates: The Complete Guide, Vandevoorde and Josuttis}.
-
-@node Socket-Programming
-@section Socket Programming
-
-@cindex sockets
-We will assume a basic facility with the Berkeley Sockets API in the examples
-used in this tutorial. If you are new to sockets, we recommend reviewing the
-API and some common usage cases. For a good overview of programming TCP/IP
-sockets we recommend @uref{http://www.elsevier.com/wps/product/cws_home/680765,,Practical TCP/IP Sockets in C, Donahoo and Calvert}.
-
-There is an associated web site that includes source for the examples in the
-book, which you can find at:
-@uref{http://cs.baylor.edu/~donahoo/practical/CSockets/}.
-
-If you understand the first four chapters of the book (or for those who do
-not have access to a copy of the book, the echo clients and servers shown in
-the website above) you will be in good shape to understand the tutorial.
-There is a similar book on Multicast Sockets,
-@uref{http://www.elsevier.com/wps/product/cws_home/700736,,Multicast Sockets, Makofske and Almeroth}.
-that covers material you may need to understand for the multicast examples.
-
-@c ========================================================================
-@c Downloading and Compiling
-@c ========================================================================
-
-@node Downloading and Compiling
-@chapter Downloading and Compiling
-
-@cindex Linux
-@cindex Cygwin
-@cindex GNU
-@cindex toolchain
-From this point forward, we are going to assume that the reader is working in
-Linux or a Linux emulation environment (Linux, Cygwin, etc.) and has the GNU
-toolchain installed and verified.
-
-@cindex Mercurial
-@cindex Waf
-We are going to assume that you have Mercurial and Waf installed and running
-on the target system as described in the Getting Started section of the
-ns-3 web site: @uref{http://www.nsnam.org/getting_started.html}.
-
-@section Downloading
-@cindex tarball
-The ns-3 code is available in Mercurial repositories on the server
-code.nsnam.org. You can download a tarball, but we recommend working with
-Mercurial --- it will make your life easier in the long run.
-
-@cindex repository
-If you go to the following link: @uref{http://code.nsnam.org/},
-you will see a number of repositories. Many are the private repositories of
-the ns-3 development team. The repositories of interest to you
-will be
-prefixed with ``ns-3''. The current development snapshot (unreleased) of
-ns-3 may be found at: @uref{http://code.nsnam.org/ns-3-dev/}.
-
-The developers attempt to keep this repository in a consistent, working state
-but it is a development area with unreleased code present, so you may want to
-consider downloading an official release.
-
-There will be a number of released repositories present at code.nsnam.org.
-These repos will have names like ns-3.0.1 --- which referes to release 3.0.1
-of the network simulator (or if you like, release 0.1 of ns-3).
-Since the releases are changing at a rate of one per month, I will stick with
-the more constant ns-3-dev here, but you can replace the string ns-3-dev with
-your choice of release (e.g., ns-3.0.5) below. You can find the latest
-version of the code either by inspection of the repository list or by going
-to the ``Getting Started'' web page and looking for the latest release
-identifier.
-
-One practice is to create a directory called @code{repos} in one's home
-directory under which one can keep local Mercurial repositories.
-@emph{Hint: we will
-assume you do this later in the tutorial.} If you adopt that approach, you
-can get a copy of any of the development versions of ns-3 by typing
-the following into your Linux shell (assuming you have installed Mercurial):
-
-@verbatim
- cd
- mkdir repos
- cd !$
- hg clone http://code.nsnam.org/ns-3-dev
-@end verbatim
-
-As the hg command executes, you should see something like the following,
-
-@verbatim
- destination directory: ns-3-dev
- requesting all changes
- adding changesets
- adding manifests
- adding file changes
- added 1513 changesets with 5687 changes to 733 files
- 358 files updated, 0 files merged, 0 files removed, 0 files unresolved
-@end verbatim
-
-After the clone command completes, you should have a directory called
-ns-3-dev under your @code{~/repos} directory, the contents of which should
-look something like the following:
-
-@verbatim
- AUTHORS RELEASE_NOTES examples/ src/ waf*
- LICENSE VERSION ns3/ tutorial/ waf.bat*
- README doc/ samples/ utils/ wscript
-@end verbatim
-
-You are now ready to build the ns-3 distribution.
-
-@section Building
-@cindex Waf!build
-@cindex Waf!configure
-@cindex Waf!debug
-@cindex Waf!compile
-We use Waf to build the ns-3 project. The first thing you
-will need to do is to configure the build. For reasons that will become clear
-later, we are going to work with debug builds in the tutorial. To explain to
-Waf that it should do debug builds you will need to execute the following
-command,
-
-@verbatim
- ./waf -d debug configure
-@end verbatim
-
-This runs the copy of Waf in the local directory (which is provided as a
-convenience for you). As the build system checks for various dependencies
-you should see output that looks similar to the following,
-
-@verbatim
- ~/repos/ns-3-dev >./waf -d debug configure
- Checking for program g++ : ok /usr/bin/g++
- Checking for program cpp : ok /usr/bin/cpp
- Checking for program ar : ok /usr/bin/ar
- Checking for program ranlib : ok /usr/bin/ranlib
- Checking for compiler could create programs : ok
- Checking for compiler could create shared libs : ok
- Checking for compiler could create static libs : ok
- Checking for flags -Wall : ok
- Checking for flags -O2 : ok
- Checking for flags -g -DDEBUG : ok
- Checking for flags -g3 -O0 -DDEBUG : ok
- Checking for g++ : ok
- Checking for header stdlib.h : ok
- Checking for header stdlib.h : ok
- Checking for header signal.h : ok
- Checking for high precision time implementation: 128-bit integer
- Checking for header stdint.h : ok
- Checking for header inttypes.h : ok
- Checking for header sys/inttypes.h : not found
- Configuration finished successfully; project is now ready to build.
- ~/repos/ns-3-dev >
-@end verbatim
-
-The build system is now configured and you can build the debug versions of
-the ns-3 programs by simply typing,
-
-@verbatim
- ./waf --check
-@end verbatim
-
-You will see many Waf status messages displayed as the system compiles. The
-most important is the last one,
-
-@verbatim
- Compilation finished successfully
-@end verbatim
-
-and you will see a number of software unit tests subsequently execute.
-
-@section Running a Script
-@cindex Waf!run
-We typically run scripts under the control of Waf. This allows the build
-system to ensure that the shared library paths are set correctly and that
-the libraries are available at run time. To run a program, simply use the
-@code{run} option in Waf. Let's run the ns-3 equivalent of the hello
-world program by typing the following:
-
-@verbatim
- ./waf --run hello-simulator
-@end verbatim
-
-Waf first checks to make sure that the program is built correctly and
-executes a build if required. Waf then then executes the program, which
-produces the following output.
-
-@verbatim
- Hello Simulator
-@end verbatim
-
-If you want to run programs under another tool such as gdb or valgrind,
-see this @uref{http://www.nsnam.org/wiki/index.php/User_FAQ#How_to_run_NS-3_programs_under_another_tool,,wiki entry}.
-
-@emph{Congratulations. You are now an ns-3 user.}
-
-@c ========================================================================
-@c Some Prerequisites
-@c ========================================================================
-
-@node Some-Prerequisites
-@chapter Some Prerequisites
-
-The first thing we need to do before actually starting to code is to explain
-a few core concepts, abstractions and idioms in the system. Much of this may
-appear transparently obvious to some, but we recommend taking the time to read
-through this chapter just to ensure you are starting on a firm foundation.
-
-@section Abstractions
-
-In this section, we'll review some terms that are commonly used in
-networking, but have a specific meaning in ns-3.
-
-@subsection Node
-@cindex Node
-In Internet jargon, a computing device that connects to a network is called
-a @emph{host} or sometimes an @emph{end system}. Because ns-3 is a
-@emph{network} simulator, not specifically an @emph{Internet} simulator, we
-intentionally do not use the term host since it is closely associated with
-the Internet and its protocols. Instead, we use a more generic term also
-used by other simulators that originates in Graph Theory --- the @emph{node}.
-
-@cindex Node!class
-In ns-3 the basic computing device abstraction is called the
-node. This abstraction is represented in C++ by the class @code{Node}. The
-@code{Node} class provides methods for managing the representations of
-computing devices in simulations. Developers are expected to specialize the
-@code{Node} in the object-oriented programming sense to create new computing
-device models. In this tutorial, we will use a specialization of class
-@code{Node} called @code{InternetNode}. As you might expect, the
-@code{InternetNode} is a class that represents a host in the Internet sense,
-and automatically provides core IPv4 networking protocols.
-
-You should think of a @code{Node} as a computer to which you will add
-functionality. One adds things like applications, protocol stacks and
-peripheral cards with their associated drivers to enable the computer to do
-useful work. We use the same basic model in ns-3.
-
-@subsection Application
-@cindex Application
-Typically, computer software is divided into two broad classes. @emph{System
-Software} organizes various computer resources such as memory, processor
-cycles, disk, network, etc., according to some computing model. System
-software usually does not use those resources to complete tasks that directly
-benefit a user. A user would typically run an @emph{application} that acquires
-and uses the resources controlled by the system software to accomplish some
-goal.
-
-@cindex system call
-Often, the line of separation between system and application software is made
-at the privilege level change that happens in operating system traps.
-In ns-3 there is no real concept of operating system and especially
-no concept of privilege levels or system calls. We do, however, have the
-idea of an application. Just as software applications run on computers to
-perform tasks in the ``real world,'' ns-3 applications run on
-ns-3 @code{Node}s to drive simulations in the simulated world.
-
-@cindex Application!class
-In ns-3 the basic abstraction for a user program that generates some
-activity to be simulated is the application. This abstraction is represented
-in C++ by the class @code{Application}. The @code{Application} class provides
-methods for managing the representations of our version of user-level
-applications in simulations. Developers are expected to specialize the
-@code{Application} in the object-oriented programming sense to create new
-applications. In this tutorial, we will use specializations of class
-@code{Application} called @code{UdpEchoClient} and @code{UdpEchoServer}.
-As you might expect, these applications compose a client/server application set
-used to generate and echo simulated network packets
-
-@subsection Channel
-@cindex Channel
-
-In the real world, one can connect a computer to a network. Often the media
-over which data flows in these networks are called @emph{channels}. When
-you connect your Ethernet cable to the plug in the wall, you are connecting
-your computer to an Ethernet communication channel. In the simulated world
-of ns-3 one connects a @code{Node} to an object representing a
-communication channel. Here the basic communication subnetwork abstraction
-is called the channel and is represented in C++ by the class @code{Channel}.
-
-The @code{Channel} class provides methods for managing communication
-subnetwork objects and connecting nodes to them. They may also be specialized
-by developers in the object oriented programming sense. A @code{Channel}
-specialization may model something as simple as a wire. The specialized
-@code{Channel} can also model things as complicated as a large Ethernet
-switch, or three-dimensional space in the case of wireless networks.
-
-We will use specialized versions of the @code{Channel} called
-@code{CsmaChannel} and @code{PointToPointChannel} in this tutorial. The
-@code{CsmaChannel}, for example, models a version of a communication subnetwork
-that implements a @emph{carrier sense multiple access} communication medium.
-This gives us Ethernet-like functionality.
-
-@subsection Net Device
-@cindex NetDevice
-@cindex Ethernet
-
-It used to be the case that if you wanted to connect a computers to a network,
-you had to buy a specific kind of network cable and a hardware device called
-(in PC terminology) a @emph{peripheral card} that needed to be installed in
-your computer. These cards were called Network Interface Cards, or
-@emph{NIC}s. Today most computers come with the network controller hardware
-built in and users don't see these building blocks.
-
-A NIC will not work without a software driver to control the hardware. In
-Unix (or Linux), a piece of peripheral hardware is classified as a
-@emph{device}. Devices are controlled using @emph{device drivers}, and network
-devices (NICs) are controlled using @emph{network device drivers}
-collectively known as @emph{net devices}. In Unix and Linux you refer
-to these net devices by names such as @emph{eth0}.
-
-In ns-3 the @emph{net device} abstraction covers both the software
-driver and the simulated hardware. A net device is ``attached'' to a
-@code{Node} in order to enable the @code{Node} to communicate with other
-@code{Node}s in the simulation via @code{Channel}s. Just as in a real
-computer, a @code{Node} may be connected to more than one @code{Channel} via
-multiple @code{NetDevice}s.
-
-The net device abstraction is represented in C++ by the class @code{NetDevice}.
-The @code{NetDevice} class provides methods for managing connections to
-@code{Node} and @code{Channel} objects; and may be specialized by developers
-in the object-oriented programming sense. We will use the specialized version
-of the @code{NetDevice} called the @code{CsmaNetDevice} in this tutorial.
-Just as an Ethernet NIC is designed to work with an Ethernet network, the
-@code{CsmaNetDevice} is designed to work with a @code{CsmaChannel}.
-
-@subsection Topology Helpers
-In a real network, you will find host computers with added (or built-in)
-NICs. In ns-3 we would say that you will find @code{Nodes} with
-attached @code{NetDevices}. In a large simulated network you will need to
-arrange many connections between @code{Node}s, @code{NetDevice}s and
-@code{Channel}s.
-
-Since connecting a @code{NetDevice} to a @code{Node}, and a @code{NetDevice}
-to a @code{Channel} is such a common task in ns-3 we provide what we
-call @emph{topology helpers} to make this as easy as possible. Topology
-helpers perform much of the dirty work of creating and connecting net devices.
-For example, it may take several distinct method calls to create a NetDevice,
-add a MAC address, connect the net device to a @code{Node} and configure
-the protocol stack, and then connect the @code{NetDevice} to a @code{Channel}.
-We use topology helper functions to compose those distinct operations into
-an easy to use model.
-
-Topology helper functions use the abstractions (described above) of Network
-Interface Cards and Cables. When you think of adding a new kind of network,
-you may think of going out to the local computer retailer and buying a kit.
-This kit might include a network cable and some number of peripheral cards and
-their associated software drivers. You can think of topology helpers in
-roughly the same way. Instead of buying a kit for a given type of network,
-you will use a topology helper class for a given type of network, to accomplish
-the equivalent of installing the network ``kit.''
-
-@section Important Idioms
-Now that we have identified that there are C++ classes in the system called
-@code{Node} and @code{InternetNode}, we need to understand how to bring
-objects of these classes into existence, and manage their lifetimes. Let's
-examine this in some detail here.
-
-@cindex InternetNode
-@cindex CreateObject
-@cindex Ptr
-In ns-3, if we want to create an @code{InternetNode} in a
-script, we will
-typically do something like the following example:
-
-@verbatim
- Ptr<Node> p = CreateObject<InternetNode> ();
-@end verbatim
-
-@cindex smart pointer
-To some, it may seem intuitively obvious that we're creating an
-@code{InternetNode} object and assigning responsibility for managing the
-object to a smart pointer named @code{p}. For the rest of us, there may be
-a lot in that line that is unfamiliar, so let's look at what this line means
-in some detail.
-
-@subsection Templates 101
-@cindex template
-If you are familiar with C++ templates, you may skip this section as it is
-just a cursory introduction to function and class templates.
-
-Referring back to the example line of code, reproduced below for your
-convenience, the angle brackets you see in the code indicate that we are
-using C++ @emph{templates}.
-
-@verbatim
- Ptr<Node> p = CreateObject<InternetNode> ();
-@end verbatim
-
-The purpose of templates is to allow a programmer to write one version of code
-that is applicable over multiple types. Some people consider templates to be
-an enhancement of the C preprocessor macro functionality. At some level
-this comparison reveal some similarities, but C++ templates are really
-quite different.
-
-@cindex template!declaration
-@cindex template!definition
-@cindex template!use
-In C++, just as with most language constructs, templates are @emph{declared},
-@emph{defined} and @emph{used}. A declaration of a template might look
-something like,
-
-@verbatim
- template <typename T> T Add (T first, T second);
-@end verbatim
-
-@cindex template!typename
-This line uses the keyword @code{template} followed by a declaration of a
-type name (in this case @code{T}) in angle brackets. The angle brackets
-should indicate to you that a template is being declared, defined or used.
-The type name @code{T} can be thought of as a string that will be substitited
-during the use phase of the template. For example, the @code{T} may be
-replaced by the word @code{int}. It is this substitution that leads people
-to compare templates with macros.
-
-Without going into too much more detail, this snippet declares that a piece
-of code exists that will be able to call a function @code{Add} that will
-add arbitrary types together. The @code{T} will be eventually replaced by
-a C++ data type name. For example,
-
-@verbatim
- T Add (T first, T second);
-@end verbatim
-
-might eventually become
-
-@verbatim
- int Add (int first, int second);
-@end verbatim
-
-If the template has been declared, we need to @emph{define} what that piece of
-code will actually do. That might look something like,
-
-@verbatim
- template <typename T>
- T Add (T first, T second)
- {
- return first + second;
- }
-@end verbatim
-
-All we've done here is to provide an implementation of the template that
-adds the two variables together and returns the result. Note that this
-implementation works for any type that provides an @code{operator+}.
-
-The puzzle all comes together when you understand that @emph{using} a template
-causes the compiler to automatically instantiate code for a specific function
-according to the given template parameters. You might use the above template
-like,
-
-@verbatim
- int x, y, z;
- z = Add<int> (x, y);
-@end verbatim
-
-@cindex template!instantiate
-When the compiler sees @code{Add<int>} it understands that it needs to make
-sure that code is instantiated (created) to perform the @code{Add} using the
-specified type @code{<int>}. To a first approximation, the compiler will
-replace the typename @code{T} with the specified type @code{int} and
-automagically generate code equivalent to,
-
-@verbatim
- int Add (int first, int second)
- {
- return first + second;
- }
-@end verbatim
-
-A user of the template definition could just as easily have provided a use
-that assigned the type float. This would simply be done like,
-
-@verbatim
- float x, y, z;
- z = Add<float> (x, y);
-@end verbatim
-
-In this case, the compiler would automatically generate code that looked like,
-
-@verbatim
- float Add (float first, float second)
- {
- return first + second;
- }
-@end verbatim
-
-@cindex template!function
-This particular kind of template programming uses what are called
-@emph{function templates}. They are called function templates since you
-are @emph{templating} function declarations and definitions.
-
-@cindex template!class
-Templates can also be used in conjunction with classes, in which case you are
-said to be using, not too surprisingly, @emph{class templates}. The syntax and
-use is similar. To declare a class template you might use something like,
-
-@verbatim
- template <typename T>
- class MyStack
- {
- void Push (T data);
- T Pop (void);
- };
-@end verbatim
-
-The methods can be defined separately in a method similar to function template
-definitions,
-
-@verbatim
- template <typename T> void MyStack<T>::Push (T data)
- {
- ...
- };
-@end verbatim
-
-You can then use the new templated class in the following way,
-
-@verbatim
- int x, y;
-
- MyStack<int> stack;
- stack.Push (x);
- y = stack.Pop ();
-@end verbatim
-
-Similarly to the function template case, the compiler knows that it has to
-automatically generate code to fill out the class and method declarations
-and definitions using the appropriate type specified by @code{<int>}.
-
-@node Smart Pointers 101
-@subsection Smart Pointers 101
-If you are familiar with C++ smart pointers, you may skip this section as it
-is just a cursory introduction to smart pointers and intrusive reference
-counting.
-
-@cindex smart pointer
-Referring back to the example line of code, partially reproduced below for
-your convenience below, the left hand side is the declaration and
-initialization of a class template that implements a @emph{smart pointer}.
-
-@verbatim
- Ptr<Node> p = ...
-@end verbatim
-
-To a first approximation, you can think of @code{Ptr<Node>} as the a new kind
-of declaration of a pointer to a @code{Node} object. The difference is that
-a smart pointer is a user-defined data type (instantiated via a templated
-class) that @emph{simulates} a classical pointer but provides additional
-features. As an aside, you typically pronounce @code{Ptr<Node>} as
-``pooter node'' where pooter rhymes with footer.
-
-@cindex memory management
-One of the most important ``additional feature'' provided by smart pointers is
-automatic memory management. Since you now understand class templates, you
-will understand how the template allows us to write the pointer code once, but
-allows us to point to many different kinds of objects. Later in the tutorial
-you will see variations such as @code{Ptr<Ipv4>} and @code{Ptr<Channel>},
-which are smart pointers to an IP version 4 object and a channel object,
-respectively.
-
-The use of built-in pointers in C and C++ is a major source of bugs. Constant
-allocation of, passing of responsibility for, and deallocation of underlying
-data makes it very likely that errors will occur. In one of these errors,
-the usual problem is that the responsibility for deallocating a memory block
-is misplaced. This may result in a memory leak or a duplicate deallocation.
-Smart pointers try to prevent this kind of problem by working with the
-@emph{scope} and @emph{extent} rules of the language to make memory
-deallocation automatic.
-
-The scope of a variable defines where in a program a given variable may be
-referred to. The extent of a variable defines when in the program's execution
-the variable has a valid value. Consider a simple subroutine that contains a
-smart pointer.
-
-@verbatim
- void SimpleSubroutine (void)
- {
- Ptr<Node> p;
- }
-@end verbatim
-
-@cindex scope
-The variable named @code{p} has a scope limited to the subroutine itself. The
-variable is said to @emph{come into scope} as the subroutine is entered during
-execution. At this time, the constructor of the underlying class is executed
-and a valid variable is available for use. When the subroutine is done
-executing, the variable is said to @emph{go out of scope}. This causes the
-destructor of the underlying class to be executed and the variable no longer
-has a valid value. This is not a problem since it is no longer valid to refer
-to the parameter. Smart pointers take advantage of these defined actions at
-points where variables must be valid and become discardable to determine when
-underlying data can be freed.
-
-@cindex reference counting!intrusive
-The ns-3 smart pointer mechanism uses a mechanism called intrusive
-reference counting to determine when a memory block should be automatically
-deallocated. The term ``intrusive'' means that a reference count (a count of
-variables required to have valid data) is stored in the object being managed
-instead of in a proxy object. This means that each piece of memory managed by
-a ns-3 smart pointer includes a reference count. When a smart
-pointer to a reference counted object is created, this reference count is
-incremented. This indicates that a new variable requires a valid data object
-be present. When a smart pointer to a reference counted object is destroyed
-(for example, when going out of scope) the reference count of the managed
-object is decremented. When the reference count goes to zero it means that
-all smart pointers to the underlying object have gone out of scope and the
-object is no longer needed by any past ``users'' of the object. This in turn
-means that the object can be safely deallocated, and this is done
-automatically for you as the ``last'' smart pointer goes out of scope.
-
-Consider how this might work as you pass a smart pointer to an object down
-a protocol stack. At each level of the stack, you pass the smart pointer
-by value. This causes a copy of the smart pointer to be made, which
-increments the reference count of the underlying object. When the
-@emph{calling} method is done executing, the calling smart pointer goes out of
-scope and the reference count is decremented. This leaves the single smart
-pointer in the @emph{called} method with a reference to the underlying object.
-When the smart pointer in the called method goes out of scope, the destructor
-for the smart pointer is called. The destructor checks the reference count
-of the underlying object and sees that it becomes zero. This indicates that
-the object can be deallocated, and the destructor does so. This results in
-the lifetime management of the underlying object being automatically managed,
-a boon if you have experience with ``manual'' memory management and finding
-memory leaks.
-
-Now, we want to make this feature available as widely as possible to objects
-in the ns-3 system. The basic operations of the smart pointer class
-are the same across any intrusively reference counted object. C++ provides a
-mechanism to achieve this kind of generic behavior --- the template. Let's
-examine the declaration of the smart pointer in more detail. First consider
-the way you might declare and use a built-in pointer. For the sake of
-simplicity, just assume that a C++ object of the class @code{MyClass} exists.
-Further assume that @code{MyClass} provides one method called @code{method}.
-Using built-in pointers, you could do something like the following:
-
-@verbatim
- MyClass *p = ...
- p->method ();
-@end verbatim
-
-@cindex smart pointer
-One of the key design points of smart pointers is that they should simulate
-built-in pointers. In C++ this is done by overloading @code{operator->},
-@code{operator=} and @code{operator*}. To implement a smart pointer we need
-to provide a generic class that implements these operators. This generic
-class should allow operations that appear as if it were a built-in pointer
-to the reference counted object. Typically this is accomplished via a
-relatively simple C++ class template. If you are interested in the details
-of how this may be accomplished, see Alexandrescu for a good treatment,
-
-@cindex template
-Taking the template as given, in order to declare a smart pointer you will
-need to create a smart pointer object and provide the template parameter
-needed to instantiate the required code. This parameter will be the name
-of the reference counted class to which you want to point. The smart
-pointer class overrides @code{operator=} which allows initialization of the
-smart pointer just as if it were a built-in pointer. The end result is that
-you use smart pointers just as if they were built-in pointers:
-
-@verbatim
- SmartPointer<MyClass> p = ...
- p->method ();
-@end verbatim
-
-@node Object Creation
-@subsection Object Creation
-@cindex CreateObject
-On the right hand side of the line of code we're examining (reproduced below
-for convenience) is the creation of an @code{InternetNode} object.
-
-@verbatim
- ... = CreateObject<InternetNode> ();
-@end verbatim
-
-@cindex template!function
-This turns out to be an instance of use of a C++ @emph{function template}. The
-definition of the @code{CreateObject<typename T>()} template calls the new
-operator to create an object of the type T. It then creates a new smart
-pointer of the appropriate type (i.e., @code{Ptr<T>}). This new smart
-pointer is assigned initial responsibility for the new object which has its
-reference count set to one.
-
-Since the underlying creation mechanism is via the @code{new} operator, and
-you can pass parameters to the constructor for an object, we provide several
-templates that you can use for passing parameters to the object constructors.
-If the constructor for the object requires a parameter, you simply pass that
-parameter to the @code{Create} function like this,
-
-@verbatim
- int parm = 1;
- ... = CreateObject<MyClass> (parm);
-@end verbatim
-
-We provide Create templates with up to seven parameters, so you could
-conceivably use the @code{Create} template in situations such as,
-
-@verbatim
- int parm = 1;
- ... = CreateObject<MyClass> (p1, p2, p3, p4, p5, p6, p7);
-@end verbatim
-
-@subsection Type Safety
-Lets take one final look at the now infamous example line of code that we
-have been examining for some time (again reproduced below).
-
-@verbatim
- Ptr<Node> p = CreateObject<InternetNode> ();
-@end verbatim
-
-@cindex smart pointer
-@cindex Node
-@cindex Create
-You may have noticed that the smart pointer on the left hand side of the
-assignment is associated with the type @code{Node} and the @code{Create}
-template on the right hand side creates an @code{InternetNode} object and
-returns a @code{Ptr<InternetNode>} smart pointer. For this assignment of a
-@code{Ptr<InternetNode>} to a @code{Ptr<Node>} to work, there must be some
-kind of type conversion going on.
-
-@cindex implicit conversion
-Many programmers use @code{implicit conversions} without even realizing it
-since they are sometimes so intuitive. For example, in the following code,
-
-@verbatim
- int i = 1;
- double d = 2.;
- if (n == d) ...
-@end verbatim
-
-@cindex standard conversion
-the integer (1) is implicitly converted to a double (1.) before the comparison
-takes place. This conversion is performed using what is known as a C++
-@emph{standard conversion}. There are a number of standard conversions defined
-by the C++ standard. Among them are,
-
-@itemize @bullet
-@item Integral Promotions
-@item Integral Conversions
-@item Floating Conversions
-@item Pointer Conversions
-@item Reference Conversions
-@end itemize
-
-@cindex assignment operator
-@cindex Ptr
-For the case of interest here, we need to know what happens in the
-assignment operator (@code{operator=}) of our smart pointer @code{Ptr<Node>}.
-This operator takes a reference to a @code{Ptr<Node>} and not a reference to
-a @code{Ptr<InternetNode>}. The one situation where this works automatically
-in C++ is if the ``destination'' reference is to a visible, unambiguous base
-class of the ``source'' reference. In this case, the underlying pointer is
-@emph{cast} from one type to the other automatically.
-
-To summarize: The magic happens in the assignment operator. Class
-@code{InternetNode} inherits from class @code{Node}. The reference to the
-@code{InternetNode} object in question is, in essence, a pointer to an
-@code{InternetNode} object. The @code{InternetNode} class inherits from the
-@code{Node} base class in a way that makes @code{Node} visible and unambiguous.
-Therefore, there exists a standard conversion from an @code{InternetNode *}
-to a @code{Node *} and by extension from an @code{InternetNode &} to a
-@code{Node &}. This conversion is applied automatically (and invisibly)
-during parameter passing in the assignment operator we are examining.
-
-@cindex base class
-This is a rather involved way of saying there's an invisible pointer cast
-to a base class happening in the assignment. That means that
-
-@verbatim
- Ptr<Node> p = CreateObject<InternetNode> ();
-@end verbatim
-
-or,
-
-@verbatim
- Ptr<Channel> p = CreateObject<CsmaChannel> ();
-@end verbatim
-
-will work just fine. Of course, if you try something @emph{bad} (TM), like:
-
-@verbatim
- Ptr<Node> p = CreateObject<CsmaChannel> ();
-@end verbatim
-
-the compiler will quite appropriately complain that there is no conversion
-between these completely unrelated objects (CsmaChannel and Node).
-
-@subsection Summary
-Going back to our infamous first line of ns-3 code, we said that if
-we want to create an InternetNode in a script, we will typically do something
-like:
-
-@verbatim
- Ptr<Node> p = CreateObject<InternetNode> ();
-@end verbatim
-
-@cindex Create
-@cindex InternetNode
-@cindex smart pointer
-Now we know that this is really a simple statement. We create an
-@code{InternetNode} object on the heap (indirectly using operator @code{new}
-and passing no parameters to its constructor) and assign responsibility for
-managing the new object's lifetime to a smart pointer. This smart pointer is
-a pointer to a @code{Node} object, so there was a hidden cast from
-@code{InternetNode} to a @code{Node} done via a standard C++ conversion.
-
-This may have been quite a hurdle to get past that first line of code, but
-we have covered quite a few of the important idioms that you'll encounter in
-this tutorial.
-
-@c ========================================================================
-@c A First ns-3 script
-@c ========================================================================
-
-@node A-First-ns-3-Script
-@chapter A First ns-3 script
-@cindex design pattern
-@cindex idiom
-Lets build a simple network using the ns-3 design patterns, idioms,
-classes and helpers we have just looked at. If you downloaded the system as
-was suggested above, you will have a release of ns-3 in a directory
-called @code{repos} under your home directory. Change into that directory,
-where you should see a directory structure something like the following.
-
-@verbatim
- AUTHORS RELEASE_NOTES examples/ src/ waf*
- LICENSE VERSION ns3/ tutorial/ waf.bat*
- README doc/ samples/ utils/ wscript
-@end verbatim
-
-@cindex hello-simulator.cc
-Change into the tutorial directory. You should see a file named
-@code{hello-simulator.cc} located there. Copy this file into one named
-@code{simple.cc}. If you open this new file in your favorite editor you will
-see some copyright information and the following C++ code:
-
-@verbatim
- #include "ns3/log.h"
-
- NS_LOG_COMPONENT_DEFINE ("HelloSimulator");
-
- using namespace ns3;
-
- int
- main (int argc, char *argv[])
- {
- LogComponentEnable ("HelloSimulator", LOG_LEVEL_INFO);
-
- NS_LOG_INFO ("Hello Simulator");
- }
-@end verbatim
-
-This is the ns-3 version of the ubiquitous hello-world program. It
-uses the ns-3 Log module to print ``Hello Simulator'' into the
- standard error output stream.
-
-@cindex logging
-Log components are named objects that provide for controlling the verbosity of
-debugging output in the system. We'll have a lot more to say about logging
-later on, but for now you can just consider the macro @code{NS_LOG_INFO} to be
-a kind of fancy printf to the standard error.
-
-@section A Simple Network
-@cindex InternetNode
-Let's create a simple network of @code{InternetNode} elements. In order to
-actually create an @code{InternetNode}, you will have to include some header
-files. Put the following code after the include statement in @code{simple.cc}.
-
-@verbatim
- #include "ns3/ptr.h"
- #include "ns3/internet-stack.h"
-@end verbatim
-
-@cindex include files
-The ns-3 build system places the core include files it needs into a
-directory called @code{ns-3} and so whenever you need to include one of the
-core files you need to explicitly code this. The file @code{ptr.h} defines
-the generic smart pointer that we use. The file @code{internet-stack.h}
-defines the class InternetNode which, as described above, represents an IP
-version 4-based computing element in the simulator.
-
-So let's create a few new @code{InternetNode}s by adding the following lines
-of code after the call to @code{NS_LOG_INFO} in the simple.cc file right
-after the call to @code{NS_LOG_INFO}.
-
-@verbatim
- Ptr<Node> n0 = CreateObject<InternetNode> ();
- Ptr<Node> n1 = CreateObject<InternetNode> ();
- Ptr<Node> n2 = CreateObject<InternetNode> ();
- Ptr<Node> n3 = CreateObject<InternetNode> ();
-@end verbatim
-
-As we now understand, this will create four @code{InternetNode} objects on
-the heap and create four @code{Ptr<Node>} smart pointer objects on the stack
-to manage them. You should remember that by using the smart pointers you are
-freed from the responsibility to delete the objects you assign to them.
-
-@cindex Channel
-@cindex CsmaChannel
-The next step is to create a channel over which these nodes can communicate.
-Let's use the CsmaChannel and create a local area network that will allow us
-to hook up nodes similarly to an Ethernet.
-
-As usual, we'll need to include the file that provides the appropriate class
-declarations:
-
-@verbatim
- #include "ns3/csma-channel.h"
-@end verbatim
-
-Next, Add the following line of code (typically done after node creation) to
-create a channel with a five megabit per second data rate and a two
-millisecond speed-of-light delay between all nodes. The idiom for creating
-the channel is similar to that of the node, but the actual @code{Create}
-function is hidden from us in the topology code. Observe that we are
-using a Csma topology helper function to free us from the details regarding
-how the Carrier Sense Multiple Access Channel is actually brought into
-existence and initialized.
-
-@verbatim
- Ptr<CsmaChannel> lan =
- CsmaTopology::CreateCsmaChannel (DataRate (5000000), MilliSeconds (2));
-@end verbatim
-
-@cindex idiom!unnamed parameter
-You may be unfamiliar with the @emph{unnamed parameter} idiom used here.
-When added to a list of parameters, the code @code{DataRate (5000000)}
-constructs a DataRate object on the stack using the appropriate constructor.
-The resulting object has no name, and therefore cannot be referenced
-elsewhere, but is passed to the callee method where it has a valid name and
-can be used. This idiom is essentially a shorthand version of the following:
-
-@verbatim
- DataRate rate (5000000);
- Time latency (MilliSeconds (2));
- Ptr<CsmaChannel> lan = CsmaTopology::CreateCsmaChannel (rate, latency);
-@end verbatim
-
-@cindex constructor
-@cindex constructor!Time
-We should pause for a moment and discuss the constructor to the @code{Time}
-data type. There are a number of different constructors for these objects, and
-so there are a number of ways that this initialization could have been done.
-There is a constructor that takes a string argument, consisting of expressions
-using the units @code{s, ms, us, ns, ps} or @code{fs}, so this could have been
-written,
-
-@verbatim
- Time latency ("2ms");
-@end verbatim
-
-There are also helper functions available that create time units (one of these
-was used in the example):
-
-@itemize @bullet
-@item @code{Seconds (double)}
-@item @code{MilliSeconds (uint64_t)}
-@item @code{MicroSeconds (uint64_t)}
-@item @code{NanoSeconds (uint64_t)}
-@item @code{PicoSeconds (uint64_t)}
-@item @code{FemtoSeconds (uint64_t)}
-@end itemize
-
-C++ will attempt to promote parameters appropriately, but you will typically
-see constructions that respect the type correctness of the constructor, as
-in @code{Seconds (1.)} and @code{MilliSeconds (2)}. Notice that the code
-@code{Seconds (1)} will work just as well as @code{Seconds (1.)} since the
-integer 1 will be automatically promoted to a double 1. in the former code.
-The converse will not work --- i.e., you cannot write code that says
-@code{MilliSeconds (2.)} since a @emph{type demotion} would be required that
-could lose information and the compiler will not do such things ``behind your
-back.'' Don't be thrown off by this kind of automatic conversion.
-
-@cindex MAC!address
-Okay, now we have code to create four nodes and a local area network. The
-next step is to wire the network together. We do this by adding net devices
-to the node. When we add the net device, we also specify the network to which
-the net device is connected and provide a MAC address appropriate to the
-device and network types. Since we're creating an IP version 4 network using
-a Csma channel, you may expect that we'll be using topology helpers
-appropriate to those types --- the CsmaIpv4Topology helper. As you may expect,
-we'll need to include some files to get the appropriate definitions:
-
-@verbatim
- #include "ns3/mac48-address.h"
- #include "ns3/csma-net-device.h"
- #include "ns3/csma-topology.h"
- #include "ns3/csma-ipv4-topology.h"
-@end verbatim
-
-Now, all that is left is to do the ``wiring'':
-
-@verbatim
- uint32_t nd0 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n0, lan,
- Mac48Address("08:00:2e:00:00:00"));
-@end verbatim
-
-[Note the additional unnamed parameter idiom usage here.]
-
-This code calls the topology helper relating to Csma channels and IP version
-four nodes. It asks to install a Csma net device ``into'' node zero
-(@code{n0}) connecting the device to the channel named (@code{lan}). It also
-assigns a MAC address to the net device. You can add similar lines of code
-connecting the other nodes to the lan (remembering to assign new MAC
-addresses).
-
-@verbatim
- uint32_t nd1 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n1, lan,
- Mac48Address("08:00:2e:00:00:01"));
-
- uint32_t nd2 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n2, lan,
- Mac48Address("08:00:2e:00:00:02"));
-
- uint32_t nd3 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n3, lan,
- Mac48Address("08:00:2e:00:00:03"));
-@end verbatim
-
-@cindex IP!address
-@cindex IP!network mask
-@cindex multihome
-Finally, we need to add IP addresses to our nodes. The pointers to the
-nodes are stored in n0, n1, n2 and n3. We added net devices to each of
-the nodes and remembered the net device index numbers as nd0, nd1, nd2 and
-nd3. You can add multiple net devices to each node resulting in a situation
-similar to a multi-homed host. Each time you add a net device, you will get
-a new index. Since the IP address for a multi-homed host is associated with
-a net device, we need to provide that index (which we have saved) to the
-topology helper. We provide an IP version four address via the ns-3
-class @code{Ipv4Address} which takes a dotted decimal string as a constructor
-parameter. We also provide a network mask using the ns-3 class
-@code{Ipv4Mask} which also takes a dotted decimal string. The code to
-perform the IP address assignment, then, looks like the following:
-
-@verbatim
- CsmaIpv4Topology::AddIpv4Address (n0, nd0, Ipv4Address ("10.1.1.1"),
- Ipv4Mask ("255.255.255.0"));
-
- CsmaIpv4Topology::AddIpv4Address (n1, nd1, Ipv4Address ("10.1.1.2"),
- Ipv4Mask ("255.255.255.0"));
-
- CsmaIpv4Topology::AddIpv4Address (n2, nd2, Ipv4Address ("10.1.1.3"),
- Ipv4Mask ("255.255.255.0"));
-
- CsmaIpv4Topology::AddIpv4Address (n3, nd3, Ipv4Address ("10.1.1.4"),
- Ipv4Mask ("255.255.255.0"));
-@end verbatim
-
-We have now constructed a simulated network. Your code should now look
-something like the following,
-
-@verbatim
- #include "ns3/log.h"
- #include "ns3/ptr.h"
- #include "ns3/internet-stack.h"
- #include "ns3/csma-channel.h"
- #include "ns3/mac48-address.h"
- #include "ns3/csma-net-device.h"
- #include "ns3/csma-topology.h"
- #include "ns3/csma-ipv4-topology.h"
-
- NS_LOG_COMPONENT_DEFINE ("HelloSimulator");
-
- using namespace ns3;
-
- int
- main (int argc, char *argv[])
- {
- LogComponentEnable ("HelloSimulator", LOG_LEVEL_INFO);
-
- NS_LOG_INFO ("Hello Simulator");
-
- Ptr<Node> n0 = CreateObject<InternetNode> ();
- Ptr<Node> n1 = CreateObject<InternetNode> ();
- Ptr<Node> n2 = CreateObject<InternetNode> ();
- Ptr<Node> n3 = CreateObject<InternetNode> ();
-
- Ptr<CsmaChannel> lan =
- CsmaTopology::CreateCsmaChannel (DataRate (5000000), MilliSeconds (2));
-
- uint32_t nd0 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n0, lan,
- Mac48Address("08:00:2e:00:00:00"));
-
- uint32_t nd1 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n1, lan,
- Mac48Address("08:00:2e:00:00:01"));
-
- uint32_t nd2 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n2, lan,
- Mac48Address("08:00:2e:00:00:02"));
-
- uint32_t nd3 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n3, lan,
- Mac48Address("08:00:2e:00:00:03"));
-
- CsmaIpv4Topology::AddIpv4Address (n0, nd0, Ipv4Address ("10.1.1.1"),
- Ipv4Mask ("255.255.255.0"));
-
- CsmaIpv4Topology::AddIpv4Address (n1, nd1, Ipv4Address ("10.1.1.2"),
- Ipv4Mask ("255.255.255.0"));
-
- CsmaIpv4Topology::AddIpv4Address (n2, nd2, Ipv4Address ("10.1.1.3"),
- Ipv4Mask ("255.255.255.0"));
-
- CsmaIpv4Topology::AddIpv4Address (n3, nd3, Ipv4Address ("10.1.1.4"),
- Ipv4Mask ("255.255.255.0"));
- }
-@end verbatim
-
-This script won't actually do anything yet. The next trick will be to
-convince our nodes to try and send some data over the network.
-
-@section Using Applications
-@cindex Create
-As mentioned above, we use @code{Application}s in ns-3 to generate
-the data used to drive simulations. An @code{Application} is added to a
-ns-3 node conceptually just as if you would add an application to a
-computer. When an application is created (using the @code{Create} template)
-we tell the application which @code{Node} it belongs to (and therefore on
-which node it is running) by passing a smart pointer to that @code{Node} in
-the constructor arguments.
-
-@subsection A UDP Echo Client Application
-To use an application, we first have to load the header file in which it is
-defined. For the UDP echo client, this would mean adding the line,
-
-@verbatim
-#include "ns3/udp-echo-client.h"
-@end verbatim
-
-In order to create the UDP echo client application we will need to add the
-following code:
-
-@verbatim
- uint32_t packetSize = 1024;
- uint16_t port = 7;
- uint32_t maxPacketCount = 1;
- Time interPacketInterval = Seconds (1.);
-
- Ptr<UdpEchoClient> client = CreateObject<UdpEchoClient> (n0, "10.1.1.2",
- port, maxPacketCount, interPacketInterval, packetSize);
-@end verbatim
-
-@cindex packet
-The first four lines have broken out the configuration parameters for the
-application as named parameters for clarity. We are telling the application
-to generate 1024 byte packets (@code{packetSize = 1024}); and to send these
-packets to port 7 (@code{port = 7;}). The application is told to send at most
-one packet (@code{maxPacketCount = 1;}); and to delay for one second between
-packet sends (@code{interPacketInterval = Seconds(1.)}) which is not used since
-only one packet is sent. We will defer addressing the type @code{Time} until
-we discuss the simulator engine. For now just understand the semantics are
-to wait for one second.
-
-The code to actually create the @code{UdpEchoClient} application uses the
-same creation idiom as we have used previously. Notice that we have a case
-where the @code{Create} template is used to pass parameters to the constructor
-of the underlying object.
-
-@cindex implicit conversion sequence
-Notice that a string is passed as the second parameter. The formal parameter
-to the constructor of the @code{UdpEchoClient} object is actually an
-@code{Ipv4Address}. We get away with this since C++ allows what are called
-@emph{implicit conversion sequences} to occur between the argument in the
-function call and the corresponding parameter in the function declaration.
-Basically, C++ will try to figure out a way to convert parameters for you
-transparently.
-
-In this case the conversion sequence is based on the constructor for the
-Ipv4Address that takes a @code{char const *} as a parameter. C++ notices
-that @code{"10.1.1.2"} refers to a @code{char const *} and knows that it
-needs to get from there to an @code{Ipv4Address}. The compiler notices that
-there is an @code{Ipv4Address} constructor that takes a @code{char const *}
-and so it uses that constructor transparently to arrange for the conversion.
-
-You therefore have several options for passing this value. You can use an
-explicit named variable as in the following:
-
-@verbatim
- Ipv4Address addr ("10.1.1.2");
- ...
-
- Ptr<UdpEchoClient> client = CreateObject<UdpEchoClient> (n0, addr, port,
- maxPacketCount, interPacketInterval, packetSize);
-@end verbatim
-
-@cindex idiom|unnamed parameter
-You can use the unnamed parameter idiom that we have previously seen:
-
-@verbatim
- Ptr<UdpEchoClient> client = CreateObject<UdpEchoClient> (n0,
- Ipv4Address ("10.1.1.2"), port, maxPacketCount, interPacketInterval,
- packetSize);
-@end verbatim
-
-Or you can rely on implicit conversion sequences as we just saw:
-
-@verbatim
- Ptr<UdpEchoClient> client = CreateObject<UdpEchoClient> (n0, "10.1.1.2",
- port, maxPacketCount, interPacketInterval, packetSize);
-@end verbatim
-
-Which approach to take is a matter of style, really, and you will probably
-see all three approaches taken in the ns-3 code. You should be
-comfortable seeing and using all three methods.
-
-@subsection A UDP Echo Server Application
-As usual, to use the UDP echo server we need to add a line to define the
-application:
-
-@verbatim
-#include "ns3/udp-echo-server.h"
-@end verbatim
-
-In order to create the UDP echo server application we will need to add the
-following code:
-
-@verbatim
- Ptr<UdpEchoServer> server = CreateObject<UdpEchoServer> (n1, port);
-@end verbatim
-
-We only need to tell the application which node to reside on and which port
-to listen on for UDP packets. The code to actually create the
-@code{UdpEchoServer} application uses the now quite familiar ns-3 object
-creation idiom.
-
-@subsection A UDP Echo Client-Server Simulation
-Now we're getting somewhere. Your code should look something like the
-following (let's change the log component name and program banner from
-``Hello Simulator''to something more descriptive while we're at it).
-
-@verbatim
- #include "ns3/log.h"
- #include "ns3/ptr.h"
- #include "ns3/internet-stack.h"
- #include "ns3/csma-channel.h"
- #include "ns3/mac48-address.h"
- #include "ns3/csma-net-device.h"
- #include "ns3/csma-topology.h"
- #include "ns3/csma-ipv4-topology.h"
- #include "ns3/udp-echo-client.h"
- #include "ns3/udp-echo-server.h"
-
- NS_LOG_COMPONENT_DEFINE ("UdpEchoSimulation");
-
- using namespace ns3;
-
- int
- main (int argc, char *argv[])
- {
- LogComponentEnable ("UdpEchoSimulation", LOG_LEVEL_INFO);
-
- NS_LOG_INFO ("UDP Echo Simulation");
-
- Ptr<Node> n0 = CreateObject<InternetNode> ();
- Ptr<Node> n1 = CreateObject<InternetNode> ();
- Ptr<Node> n2 = CreateObject<InternetNode> ();
- Ptr<Node> n3 = CreateObject<InternetNode> ();
-
- Ptr<CsmaChannel> lan =
- CsmaTopology::CreateCsmaChannel (DataRate (5000000), MilliSeconds (2));
-
- uint32_t nd0 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n0, lan,
- Mac48Address("08:00:2e:00:00:00"));
-
- uint32_t nd1 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n1, lan,
- Mac48Address("08:00:2e:00:00:01"));
-
- uint32_t nd2 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n2, lan,
- Mac48Address("08:00:2e:00:00:02"));
-
- uint32_t nd3 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n3, lan,
- Mac48Address("08:00:2e:00:00:03"));
-
- CsmaIpv4Topology::AddIpv4Address (n0, nd0, Ipv4Address ("10.1.1.1"),
- Ipv4Mask ("255.255.255.0"));
-
- CsmaIpv4Topology::AddIpv4Address (n1, nd1, Ipv4Address ("10.1.1.2"),
- Ipv4Mask ("255.255.255.0"));
-
- CsmaIpv4Topology::AddIpv4Address (n2, nd2, Ipv4Address ("10.1.1.3"),
- Ipv4Mask ("255.255.255.0"));
-
- CsmaIpv4Topology::AddIpv4Address (n3, nd3, Ipv4Address ("10.1.1.4"),
- Ipv4Mask ("255.255.255.0"));
-
- uint32_t packetSize = 1024;
- uint16_t port = 7;
- uint32_t maxPacketCount = 1;
- Time interPacketInterval = Seconds (1.);
-
- Ptr<UdpEchoClient> client = CreateObject<UdpEchoClient> (n0, "10.1.1.2",
- port, maxPacketCount, interPacketInterval, packetSize);
-
- Ptr<UdpEchoServer> server = CreateObject<UdpEchoServer> (n1, port);
-
- }
-@end verbatim
-
-@section Using the Simulation Engine
-@cindex model
-@cindex simulation executive
-You could say that the heart of the ns-3 system is the
-@emph{simulation engine} (sometimes called the simulation executive in other
-systems).
-
-In a computer simulation, a computer @emph{model} of a real world @emph{system}
-is constructed. This is typically done to minimize cost since you do not have
-to actually buy, install and maintain physical hardware. In the case of
-ns-3, a model is a representation of a networking component that is
-designed to imitate some number of important behaviors or characteristics of
-an actual component in a real network. A system is a collection of models
-arranged for the purpose of analyzing some behavior.
-
-@section Models
-@cindex CsmaNetDevice
-@cindex CsmaChannel
-@cindex InternetNode
-@cindex NIC
-@cindex CSMA
-We have already encountered several ns-3 models without specifically
-calling them so. The @code{InternetNode}, @code{CsmaNetDevice} and
-@code{CsmaChannel} objects are models of an Internet computing node, a CSMA
-network interface card (NIC), and a network cable able to move data to and
-from other CSMA NICs.
-
-@cindex model
-@cindex CSMA/CD
-It is important to note that the @code{Csma} net devices and the @code{Csma}
-channel do not correspond to any real world hardware that you can actually go
-out and buy. These models implement an approximation, or subset, of the
-behaviors that a real CSMA/CD network would have. In this case, the
-@code{CsmaNetDevice} does not simulate collision detection (CD). It does
-implement carrier sense and performs collision @emph{avoidance} using global
-spatial knowledge available in the channel. This would be impossible in any
-channel residing in our universe.
-
-@cindex Ethernet
-No model will fully implement @emph{all} of the behaviors of a piece of
-hardware. It is important to understand what is being modeled by the
-ns-3 components you are using and what is not. For example, the Csma
-components we use in this tutorial model a highly abstract multiple access
-network that is topologically equivalent to an Ethernet. It is not necessarily
-true that results found in a simulation using the Csma models will apply to
-a real-world Ethernet network. You must understand what behaviors are
-simulated in each of the models before trusting that any results can be
-associated with real-world systems.
-
-@section Time, Events and Callbacks
-@cindex time
-@cindex event
-In a @emph{discrete event simulator} time is not something that @emph{flows},
-nor is it something to be measured --- it is the driving force behind the
-progress of the simulation. Time is progressed forward by the simulation
-engine and anything that happens in the simulation is ultimately caused by
-an @emph{event}. An event is some action in the system that is
-@emph{scheduled} to happen at a certain time by the simulation engine. Time
-does not flow continuously but steps discretely (in possibly large jumps)
-from one scheduled event to another.
-
-@cindex packet
-For example, to start the flow of a packet through the system, one would have
-to schedule an event with the simulation engine @emph{before} the simulation
-was started. This is important since the simulation engine only jumps time
-forward if there is a next event to process. The simulation stops if there
-are no more events, which is equivalent to a state where there is ``nothing
-more to do.'' Before the simulation starts, one schedules driving events in
-terms of absolute time. For example, one could schedule an event to start
-the flow of a first packet at, say, ten simulated seconds. In this case, the
-simulation would start its clock at zero seconds and look for the first event
-in its @emph{event queue}. It would immediately jump time forward by ten
-seconds and @emph{fire} the scheduled event --- that is, make the event happen.
-
-@cindex functor
-@cindex function object
-@cindex callback
-@cindex Callback
-In ns-3 an event is basically a pre-packaged function call called a
-@emph{functor}. Functors are also known as @emph{function objects}, which is
-a more descriptive term --- an object (in the object-oriented programming
-sense) that can be called as if it was a function. Typically one uses a
-functor to implement @emph{deferred execution} of a function or method. The
-most commonly encountered form of deferred execution is in a @emph{callback}
-from an I/O system. In this case, the goal would be to start an I/O
-operation and return immediately, without having to wait for the operation
-to complete. One asks the I/O subsystem to notify you when an operation is
-complete by calling some function you provide. This provided function is
-known as a callback function. [Imagine calling someone on the telephone and
-asking them to do something for you. You also ask them to @emph{call you back}
-when they are done.] Events in the ns-3 system work conceptually
-the same way, except that instead of an I/O completion driving the process,
-the arrival of some simulated time drives the process. The ns-3
-deferred execution mechanism is via a class called @code{Callback}.
-
-@cindex Time
-@cindex Callback
-The internal details of the classes representing @code{Time} and
-@code{Callback} abstractions will be introduced as required. We won't see
-events directly for some time, but you should know that they are happening
-``under the sheets'' of the simulations you will be writing.
-
-@section Driving the Simulation
-@cindex Application
-As mentioned previously, time is the driving force behind the progress of
-a ns-3 simulation. Events are scheduled to happen at certain times
-by calling methods of the simulation engine, either directly or indirectly
-through, for example, an @code{Application}.
-
-In order to get the simulation engine set up and running in our code, we must
-first include the language definitions required to describe time- and
-simulator-specific classes:
-
-@verbatim
- #include "ns3/simulator.h"
- #include "ns3/nstime.h"
-@end verbatim
-
-@cindex Application
-As we have seen, we need to ``seed'' the simulation with at least one event.
-In the case of an @code{Application}, a method to do this is provided. This
-method must be implemented by each specialization of the class and we must
-call this method in our script before the simulation starts. We can also
-provide an event (indirectly) to stop the output of the application at a
-certain time. This is done by adding the following lines to our script:
-
-@verbatim
- server->Start(Seconds(1.));
- client->Start(Seconds(2.));
-
- server->Stop (Seconds(10.));
- client->Stop (Seconds(10.));
-@end verbatim
-
-@cindex Application
-@cindex time
-@cindex Time
-@cindex socket
-@cindex event
-In the case of the UdpEchoServer, the call to @code{server->Start ()} gives
-the @code{Application} the chance to schedule an event that will perform the
-usual @emph{sockets} server sequence of socket creation, binding and
-recvfrom (see Donahoo's UDPEchoServer.c).
-
-In the case of the UdpEchoClient, the call to @code{client->Start ()} gives
-the @code{Application} the chance to schedule an event that will perform the
-usual @emph{sockets} client sequence of socket creation, sendto and recvfrom
-(see Donahoo's UDPEchoClient.c).
-
-@cindex event
-Note that the start event for the server is scheduled to happen before the
-start event of the client, just as you would start a server application before
-you would attempt to start a client application in the real world.
-
-@cindex socket!sendto
-The ns-3 equivalent of the call to @code{sendo} in the client will
-schedule (immediately) the transmission of a UDP packet over the just created
-socket. This will cause the packet to percolate down the protocol stack and
-eventually into the channel. The channel will schedule a reception event in
-the net device on the destination node. This event will eventually percolate
-up into the server application. The server application will create a reply
-packet and send it back down its stack and eventually back to the channel.
-The channel will schedule a reception event back in the client and this will
-cause the reply to be sent back up the protocol stack to the client
-application.
-
-The calls to @code{Stop ()} for both applications cause the sockets to be
-torn down and therefore the sending and receiving of packets will be stopped
-irrespective of other application settings (such as max packets and interval
-in the client).
-
-Finally, we need to run the simulation and when the simulation run is complete,
-clean up any resources allocated during the run. This is done by the calling
-the following static methods:
-
-@verbatim
- Simulator::Run ();
- Simulator::Destroy ();
-@end verbatim
-
-We now have the makings of a complete ns-3 network simulation. The
-source code for the script should look like the following:
-
-@verbatim
- #include "ns3/log.h"
- #include "ns3/ptr.h"
- #include "ns3/internet-stack.h"
- #include "ns3/csma-channel.h"
- #include "ns3/mac48-address.h"
- #include "ns3/csma-net-device.h"
- #include "ns3/csma-topology.h"
- #include "ns3/csma-topology.h"
- #include "ns3/csma-ipv4-topology.h"
- #include "ns3/udp-echo-client.h"
- #include "ns3/udp-echo-server.h"
- #include "ns3/simulator.h"
- #include "ns3/nstime.h"
-
- NS_LOG_COMPONENT_DEFINE ("UdpEchoSimulation");
-
- using namespace ns3;
-
- int
- main (int argc, char *argv[])
- {
- LogComponentEnable ("UdpEchoSimulation", LOG_LEVEL_INFO);
-
- NS_LOG_INFO ("UDP Echo Simulation");
-
- Ptr<Node> n0 = CreateObject<InternetNode> ();
- Ptr<Node> n1 = CreateObject<InternetNode> ();
- Ptr<Node> n2 = CreateObject<InternetNode> ();
- Ptr<Node> n3 = CreateObject<InternetNode> ();
-
- Ptr<CsmaChannel> lan =
- CsmaTopology::CreateCsmaChannel (DataRate (5000000), MilliSeconds (2));
-
- uint32_t nd0 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n0, lan,
- Mac48Address("08:00:2e:00:00:00"));
-
- uint32_t nd1 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n1, lan,
- Mac48Address("08:00:2e:00:00:01"));
-
- uint32_t nd2 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n2, lan,
- Mac48Address("08:00:2e:00:00:02"));
-
- uint32_t nd3 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n3, lan,
- Mac48Address("08:00:2e:00:00:03"));
-
- CsmaIpv4Topology::AddIpv4Address (n0, nd0, Ipv4Address ("10.1.1.1"),
- Ipv4Mask ("255.255.255.0"));
-
- CsmaIpv4Topology::AddIpv4Address (n1, nd1, Ipv4Address ("10.1.1.2"),
- Ipv4Mask ("255.255.255.0"));
-
- CsmaIpv4Topology::AddIpv4Address (n2, nd2, Ipv4Address ("10.1.1.3"),
- Ipv4Mask ("255.255.255.0"));
-
- CsmaIpv4Topology::AddIpv4Address (n3, nd3, Ipv4Address ("10.1.1.4"),
- Ipv4Mask ("255.255.255.0"));
-
- uint32_t packetSize = 1024;
- uint16_t port = 7;
- uint32_t maxPacketCount = 1;
- Time interPacketInterval = Seconds (1.);
-
- Ptr<UdpEchoClient> client = CreateObject<UdpEchoClient> (n0, "10.1.1.2",
- port, maxPacketCount, interPacketInterval, packetSize);
-
- Ptr<UdpEchoServer> server = CreateObject<UdpEchoServer> (n1, port);
-
- server->Start(Seconds(1.));
- client->Start(Seconds(2.));
-
- server->Stop (Seconds(10.));
- client->Stop (Seconds(10.));
-
- Simulator::Run ();
- Simulator::Destroy ();
- }
-@end verbatim
-
-@cindex tutorial-csma-echo.cc
-Just to make sure you don't get caught up in debugging typographical errors
-we have provided this source code for you (along with a copyright header) in
-the @code{tutorial} subdirectory of the ns-3 distribution as
-@code{tutorial-csma-echo.cc}. We used this opportunity to do some ``clean up''
-of some of our example cases by passing parameters using implicit conversion
-sequences and removing some of the named parameters. [These were used for
-pedagogic purposes and were not actually necessary.]
-
-@section Building the Script
-@cindex Waf
-C++ is a compiled language, so you know it had to happen. We have to build
-the script before we run it. As mentioned before, we use the Waf build system
-which is Python-based. We have to change gears slightly and switch ourselves
-to Python mode in order to proceed.
-
-In each subdirectory of the ns-3 distribution in which there are
-source files, you will find two files: one will be named @code{waf} and one
-will be named @code{wscript}. The former, @code{waf}, is a link that allows
-one to start the build process from any subdirectory. We can ignore that one.
-The file we need to deal with is @code{wscript}.
-
-@cindex wscript
-Open the file @code{ns-3-dev/tutorial/wscript} in your favorite editor
-[remember I'm assuming that you have the distribution saved in a
-repository under a directory called @code{repos} in you home directory.]
-
-@cindex Python
-You should see the following Python code (after an emacs mode line).
-
-@verbatim
- def build(bld):
- obj = bld.create_ns3_program('hello-simulator')
- obj.source = 'hello-simulator.cc'
-@end verbatim
-
-These are the only instructions required to build a simulation (I told you
-it wasn't going to be too bad). The line with the method
-@code{bld.create_ns3_program} tells the build system to create an object
-file that is a program (executable) named @code{hello-simulator}. The
-following line, with the method @code{obj.source} tells the build system that
-the source file for the program is the file @code{hello-simulator.cc'} in the
-local directory. The required libraries are linked for you for free.
-
-All that needed to be done in order to build the new simulation using the new
-source file was to copy the two lines describing the @code{hello-simulator}
-program and change the names to @code{tutorial-csma-echo}. You can see these
-lines in the @code{wscript} file,
-
-@verbatim
- def build(bld):
- obj = bld.create_ns3_program('hello-simulator')
- obj.source = 'hello-simulator.cc'
-
- obj = bld.create_ns3_program('tutorial-csma-echo')
- obj.source = 'tutorial-csma-echo.cc'
-
- ...
-@end verbatim
-
-When you built the system above, you actually already built this new
-simulation and a number of other examples. Since you have already configured
-@code{Waf} and built the @code{tutorial-csma-echo} script, you can run the
-simulation in the same way as you ran the @code{hello-simulator} script using
-the @code{waf --run} command:
-
-@verbatim
-~/repos/ns-3-dev/tutorial > waf --run tutorial-csma-echo
-Entering directory `~/repos/ns-3-dev/build'
-Compilation finished successfully
-UDP Echo Simulation
-~/repos/ns-3-dev/tutorial >
-@end verbatim
--- a/doc/tutorial/in-process/log.texi Sun Jan 02 22:57:04 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,24 +0,0 @@
-@node Logging
-@chapter Logging
-@anchor{chap:Logging}
-
-This chapter is the first in a series of chapters discussing things that
-one can do to modify the input or output of existing ns-3 scripts.
-
-Examples:
-@itemize @bullet
-@item Enable or disable the generation of log messages, with fine granularity
-@item Set default values for configuration values in the system
-@item Generate a report of all configuration values used during a simulation
-run (not yet implemented)
-@item Set or get values of member variables on objects already instantiated
-@item Customizing the tracing output of the script
-@item Generate statistics on (not yet implemented)
-@item Perform a large number of independent runs of the same simulation
-@end itemize
-
-@node Logging Basics
-@section Logging Basics
-
-@node Enabling Log Output
-@section Enabling Log Output
--- a/doc/tutorial/in-process/other.texi Sun Jan 02 22:57:04 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2189 +0,0 @@
-@c ========================================================================
-@c Other Network Topologies
-@c ========================================================================
-
-@node Other-network-topologies
-@chapter Other Network Topologies
-@cindex topology
-@cindex Channel
-@cindex NetDevice
-@cindex topology!bus
-@cindex topology!point-to-point
-@cindex PointToPointChannel
-@cindex PointToPointNetDevice
-
-@emph{Network topology} is the study of the arrangement of of the elements
-(in @command{ns-3} represented by the classes @code{Channel} and @code{Node})
-of a network. Two fundamental types of physical topologies are the
-@emph{point-to-point} and @emph{bus} topologies. We have already been exposed
-to the @command{ns-3} channel specialization named @code{CsmaChannel}. This is
-a simulation of a bus network. We also provide a simulation of a
-point-to-point channel with associated net devices. As described previously,
-the associated C++ classes specialize the @command{ns-3} base classes
-@code{NetDevice} and @code{Channel} and are called @code{PointToPointNetDevice}
-and @code{PointToPointChannel} respectively.
-
-We will use combinations of these bus and point-to-point topology elements
-to show how to create several commonly seen network topologies.
-
-@section A Point-to-Point Network
-We're going to take what might be seen as a step backward and look at a simple
-point-to-point network. We will be building the simplest network you can
-imagine. A serial link (point to point) between two computers. When you
-see this point-to-point network, you can think of an RS-422 (or RS-232 for
-you old-timers) cable. This topology is shown below.
-
-@sp 1
-@center @image{figures/pp,,,,png}
-
-@cindex CreateObject
-@cindex InternetNode
-We have provided a file for you in the @code{tutorial}
-directory called @code{tutorial-point-to-point.cc}. You should now be
-familiar enough with the system to pick out fairly easily what has been
-changed. Let's focus on the following lines:
-
-@verbatim
- Ptr<Node> n0 = CreateObject<InternetNode> ();
- Ptr<Node> n1 = CreateObject<InternetNode> ();
-
- Ptr<PointToPointChannel> link = PointToPointTopology::AddPointToPointLink (
- n0, n1, DataRate (38400), MilliSeconds (20));
-
- PointToPointTopology::AddIpv4Addresses (link, n0, "10.1.1.1",
- n1, "10.1.1.2");
-@end verbatim
-
-You can see that we created two @code{InternetNode} objects in the usual way.
-Then, instead of creating a @code{CsmaChannel} we create a
-@code{PointToPointChannel}. This point-to-point channel, which we call
-@code{link}, connects node zero (@code{n0}) and node one (@code{n1}) over a
-simulated link that runs at 38400 bits per second and has a 20 millisecond
-simulated speed-of-light delay. This call also creates appropriate net devices
-and attaches them to nodes zero and one.
-
-We then add IP addresses to the net devices we just created using the topology
-helper @code{AddIpv4Addresses}. Node zero gets the IP address 10.1.1.1 and
-node one gets the IP address 10.1.1.2 assigned.
-
-The alert tutorial user may wonder what the network number or prefix is of
-those IP addresses. The point-to-point topology assumes that you want a
-@code{/30} subnet and assigns an appropriate net mask for you. It then then
-@emph{asserts} that the network numbers of the two net devices match. So there
-is an implicit network mask created down in the topology code that looks like,
-
-@verbatim
- Ipv4Mask netmask("255.255.255.252");
-@end verbatim
-
-The rest of the code you should recognize and understand. We are just going
-to echo one packet across the point-to-point link. You should be now be able
-to build and run this example and to locate and interpret the ASCII trace
-file. This is left as an exercise for you.
-
-The file @code{tutorial-point-to-point.cc} is reproduced here for your
-convenience:
-
-@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/log.h"
-#include "ns3/ptr.h"
-#include "ns3/internet-stack.h"
-#include "ns3/point-to-point-channel.h"
-#include "ns3/mac48-address.h"
-#include "ns3/point-to-point-net-device.h"
-#include "ns3/point-to-point-topology.h"
-#include "ns3/udp-echo-client.h"
-#include "ns3/udp-echo-server.h"
-#include "ns3/simulator.h"
-#include "ns3/nstime.h"
-#include "ns3/ascii-trace.h"
-#include "ns3/pcap-trace.h"
-#include "ns3/global-route-manager.h"
-
-NS_LOG_COMPONENT_DEFINE ("PointToPointSimulation");
-
-using namespace ns3;
-
-// Network topology
-//
-// point to point
-// +--------------+
-// | |
-// n0 n1
-//
-int
-main (int argc, char *argv[])
-{
- LogComponentEnable ("PointToPointSimulation", LOG_LEVEL_INFO);
-
- NS_LOG_INFO ("Point to Point Topology Simulation");
-
- Ptr<Node> n0 = CreateObject<InternetNode> ();
- Ptr<Node> n1 = CreateObject<InternetNode> ();
-
- Ptr<PointToPointChannel> link = PointToPointTopology::AddPointToPointLink (
- n0, n1, DataRate (38400), MilliSeconds (20));
-
- PointToPointTopology::AddIpv4Addresses (link, n0, "10.1.1.1",
- n1, "10.1.1.2");
-
- uint16_t port = 7;
-
- Ptr<UdpEchoClient> client = CreateObject<UdpEchoClient> (n0, "10.1.1.2",
- port, 1, Seconds(1.), 1024);
-
- Ptr<UdpEchoServer> server = CreateObject<UdpEchoServer> (n1, port);
-
- server->Start(Seconds(1.));
- client->Start(Seconds(2.));
-
- server->Stop (Seconds(10.));
- client->Stop (Seconds(10.));
-
- AsciiTrace asciitrace ("tutorial.tr");
- asciitrace.TraceAllQueues ();
- asciitrace.TraceAllNetDeviceRx ();
-
- Simulator::Run ();
- Simulator::Destroy ();
-}
-@end verbatim
-
-@section A Star Network
-A point-to-point network is considered a special case of a star network. As
-you might expect, the process of constructing a star network is an extension
-of the very simple process used for a point-to-point link. We have provided
-a file for you in the @code{tutorial} directory called @code{tutorial-star.cc}
-that implements a simple star network as seen below.
-
-@sp 1
-@center @image{figures/star,,,,png}
-
-In order to create a star network, we need to be able to instantiate some
-number (greater than one) of net devices on a node. In the name of simplicity
-of use, the @code{PointToPointTopology} topology helper does not allow one to
-do this. We provided a separate topology helper class, the
-@code{PointToPointIpv4Topology} helper class that provides the slightly finer
-granularity we need to accomplish a star network. In order to use this new
-helper we have to load the definitions by including the appropriate file.
-
-@verbatim
- #include "ns3/point-to-point-ipv4-topology.h"
-@end verbatim
-
-The star that we're going to create has a node in the center (@code{n0}) with
-six nodes surrounding (@code{n1} - @code{n6}). You should be able to easily
-find and understand the code that creates these nodes.
-
-@verbatim
- Ptr<Node> n0 = CreateObject<InternetNode> ();
- Ptr<Node> n1 = CreateObject<InternetNode> ();
- Ptr<Node> n2 = CreateObject<InternetNode> ();
- Ptr<Node> n3 = CreateObject<InternetNode> ();
- Ptr<Node> n4 = CreateObject<InternetNode> ();
- Ptr<Node> n5 = CreateObject<InternetNode> ();
- Ptr<Node> n6 = CreateObject<InternetNode> ();
-@end verbatim
-
-Next, we get into the differences between the @code{PointToPointTopology}
-helper and the @code{PointToPointIpv4Topology} helper. The
-@code{PointToPointIpv4Topology} helper looks and feels a little like the
-@code{CsmaIpv4Topology} helper. Just like you created a CSMA channel
-previously, you need to create a point-to-point channel. The following
-code creates a @code{PointToPointChannel} and calls it @code{link01}. You can
-interpret this name as being the channel (or @emph{link}) from node zero to
-node one.
-
-@verbatim
- Ptr<PointToPointChannel> link01 =
- PointToPointIpv4Topology::CreateChannel (DataRate (38400),
- MilliSeconds (20));
-@end verbatim
-
-You need to provide a data rate for the channel which we set at 38400 bits
-per second. You must also provide a speed-of-light delay which we set at
-20 milliseconds.
-
-Just as you added a net device to the nodes in the CSMA tutorial section, you
-do the same here but with a point-to-point net device. The following code
-illustrates how we do that:
-
-@verbatim
- uint32_t nd01 = PointToPointIpv4Topology::AddNetDevice (n0,
- link01);
-@end verbatim
-
-We call the @code{PointToPointIpv4Topology} helper and ask it to add a net
-device to node zero (@code{n0}) and connect it to the appropriate
-point-to-point link (@code{link01}) which you will recall is the serial link
-from node zero to node one.
-
-If you look at the following code, you will see the same calls are repeated
-to create the remaining five point-to-point channels and connect them
-to net devices on node zero.
-
-The next new code is found after the ``spokes'' of the star have been created.
-It looks like the following:
-
-@verbatim
- uint32_t nd1 = PointToPointIpv4Topology::AddNetDevice (n1, link01);
- uint32_t nd2 = PointToPointIpv4Topology::AddNetDevice (n2, link02);
- uint32_t nd3 = PointToPointIpv4Topology::AddNetDevice (n3, link03);
- uint32_t nd4 = PointToPointIpv4Topology::AddNetDevice (n4, link04);
- uint32_t nd5 = PointToPointIpv4Topology::AddNetDevice (n5, link05);
- uint32_t nd6 = PointToPointIpv4Topology::AddNetDevice (n6, link06);
-@end verbatim
-
-Here we are creating the net devices on the nodes surrounding the center node.
-In the first call, we are adding a net device on node one (@code{n1}) and
-connecting that net device to the channel named @code{link01}. Remember that
-we created the channel @code{link01} as the channel connecting node zero and
-node one. We previously created a net device on node zero and attached that
-device to @code{link01}. Here we are connecting the other side of that link
-to node one. The return value from this call is the net device index of the
-created net device.
-
-The next section of code adds addresses to the net devices we just created.
-The first call adds the IP address 10.1.1.1 to the net device going from
-node zero to node one. Recall that we first created a node named @code{n0}
-and a channel called @code{link01}. We added a net device to @code{n0} and
-remembered the net device index as the @code{uint32_t nd01}. This meant
-the net device @emph{nd} on node @emph{0} that we connected to node @emph{1}.
-We call @code{AddAddress} to add an IP address (10.1.1.1) to the net device
-on node zero identified by the net device index @code{nd01}. We provide a
-net mask suitable for a point to point network. This is typically a /30
-address but we don't force that in this API.
-
-After setting up the address on node zero, we do the same for the node on
-the other end of the ``spoke'' --- in this case node one, with its single
-net device. Note that the network number is the same on both sides of this
-network.
-
-@verbatim
- PointToPointIpv4Topology::AddAddress (n0, nd01, "10.1.1.1",
- ``255.255.255.252'');
-
- PointToPointIpv4Topology::AddAddress (n1, nd1, "10.1.1.2",
- ``255.255.255.252'');
-@end verbatim
-
-The following code repeats this pattern assining similar IP addresses to the
-remaining net devices. Note that there are no @code{Mac48Address} address
-assignments --- they are not required.
-
-The rest of the code you should recognize and understand. We are just going
-to echo one packet across the point-to-point link. You should be now be able
-to build and run this example and to locate and interpret the ASCII trace
-file. This is left as an exercise for you.
-
-The file @code{tutorial-star.cc} is reproduced here for your convenience:
-
-@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/log.h"
-#include "ns3/ptr.h"
-#include "ns3/internet-stack.h"
-#include "ns3/point-to-point-channel.h"
-#include "ns3/mac48-address.h"
-#include "ns3/point-to-point-net-device.h"
-#include "ns3/point-to-point-ipv4-topology.h"
-#include "ns3/udp-echo-client.h"
-#include "ns3/udp-echo-server.h"
-#include "ns3/simulator.h"
-#include "ns3/nstime.h"
-#include "ns3/ascii-trace.h"
-#include "ns3/pcap-trace.h"
-#include "ns3/global-route-manager.h"
-
-NS_LOG_COMPONENT_DEFINE ("StarSimulation");
-
-using namespace ns3;
-
-// Network topology
-//
-// n3 n2
-// | /
-// | /
-// n4 --- n0 --- n1
-// / |
-// / |
-// n5 n6
-
-int
-main (int argc, char *argv[])
-{
- LogComponentEnable ("StarSimulation", LOG_LEVEL_INFO);
-
- NS_LOG_INFO ("Star Topology Simulation");
-
- Ptr<Node> n0 = CreateObject<InternetNode> ();
- Ptr<Node> n1 = CreateObject<InternetNode> ();
- Ptr<Node> n2 = CreateObject<InternetNode> ();
- Ptr<Node> n3 = CreateObject<InternetNode> ();
- Ptr<Node> n4 = CreateObject<InternetNode> ();
- Ptr<Node> n5 = CreateObject<InternetNode> ();
- Ptr<Node> n6 = CreateObject<InternetNode> ();
-
- Ptr<PointToPointChannel> link01 =
- PointToPointIpv4Topology::CreateChannel (DataRate (38400),
- MilliSeconds (20));
-
- uint32_t nd01 = PointToPointIpv4Topology::AddNetDevice (n0,
- link01);
-
- Ptr<PointToPointChannel> link02 =
- PointToPointIpv4Topology::CreateChannel (DataRate (38400),
- MilliSeconds (20));
-
- uint32_t nd02 = PointToPointIpv4Topology::AddNetDevice (n0,
- link02);
-
- Ptr<PointToPointChannel> link03 =
- PointToPointIpv4Topology::CreateChannel (DataRate (38400),
- MilliSeconds (20));
-
- uint32_t nd03 = PointToPointIpv4Topology::AddNetDevice (n0,
- link03);
-
- Ptr<PointToPointChannel> link04 =
- PointToPointIpv4Topology::CreateChannel (DataRate (38400),
- MilliSeconds (20));
-
- uint32_t nd04 = PointToPointIpv4Topology::AddNetDevice (n0,
- link04);
-
- Ptr<PointToPointChannel> link05 =
- PointToPointIpv4Topology::CreateChannel (DataRate (38400),
- MilliSeconds (20));
-
- uint32_t nd05 = PointToPointIpv4Topology::AddNetDevice (n0,
- link05);
-
- Ptr<PointToPointChannel> link06 =
- PointToPointIpv4Topology::CreateChannel (DataRate (38400),
- MilliSeconds (20));
-
- uint32_t nd06 = PointToPointIpv4Topology::AddNetDevice (n0, link06);
-
- uint32_t nd1 = PointToPointIpv4Topology::AddNetDevice (n1, link01);
- uint32_t nd2 = PointToPointIpv4Topology::AddNetDevice (n2, link02);
- uint32_t nd3 = PointToPointIpv4Topology::AddNetDevice (n3, link03);
- uint32_t nd4 = PointToPointIpv4Topology::AddNetDevice (n4, link04);
- uint32_t nd5 = PointToPointIpv4Topology::AddNetDevice (n5, link05);
- uint32_t nd6 = PointToPointIpv4Topology::AddNetDevice (n6, link06);
-
- PointToPointIpv4Topology::AddAddress (n0, nd01, "10.1.1.1",
- "255.255.255.252");
-
- PointToPointIpv4Topology::AddAddress (n1, nd1, "10.1.1.2",
- "255.255.255.252");
-
- PointToPointIpv4Topology::AddAddress (n0, nd02, "10.1.2.1",
- "255.255.255.252");
-
- PointToPointIpv4Topology::AddAddress (n2, nd2, "10.1.2.2",
- "255.255.255.252");
-
- PointToPointIpv4Topology::AddAddress (n0, nd03, "10.1.3.1",
- "255.255.255.252");
-
- PointToPointIpv4Topology::AddAddress (n3, nd3, "10.1.2.2",
- "255.255.255.252");
-
- PointToPointIpv4Topology::AddAddress (n0, nd04, "10.1.4.1",
- "255.255.255.252");
-
- PointToPointIpv4Topology::AddAddress (n4, nd4, "10.1.4.2",
- "255.255.255.252");
-
- PointToPointIpv4Topology::AddAddress (n0, nd05, "10.1.5.1",
- "255.255.255.252");
-
- PointToPointIpv4Topology::AddAddress (n5, nd5, "10.1.5.2",
- "255.255.255.252");
-
- PointToPointIpv4Topology::AddAddress (n0, nd06, "10.1.6.1",
- "255.255.255.252");
-
- PointToPointIpv4Topology::AddAddress (n6, nd6, "10.1.6.2",
- "255.255.255.252");
-
- uint16_t port = 7;
-
- Ptr<UdpEchoClient> client = CreateObject<UdpEchoClient> (n0, "10.1.1.2",
- port, 1, Seconds(1.), 1024);
-
- Ptr<UdpEchoServer> server = CreateObject<UdpEchoServer> (n1, port);
-
- server->Start(Seconds(1.));
- client->Start(Seconds(2.));
-
- server->Stop (Seconds(10.));
- client->Stop (Seconds(10.));
-
- AsciiTrace asciitrace ("tutorial.tr");
- asciitrace.TraceAllQueues ();
- asciitrace.TraceAllNetDeviceRx ();
-
- Simulator::Run ();
- Simulator::Destroy ();
-}
-@end verbatim
-
-@subsection Routing
-If you are really excited about this simulator you may have already tried to
-modify the scripts outside the tutorial. I know that one of the first things
-that would have occurred to me when I saw the star network would have been to
-start trying to add applications to echo packets from nodes other than zero.
-If you tried, for example, to start the echo client on node one instead of
-node zero, you would have found an empty trace file. The reason for this
-is that you have now created an internetwork. This means you will need to
-enable internetwork routing.
-
-We have provided a file for you in the @code{tutorial} directory called
-@code{tutorial-star-routing.cc} to show you how this is done. This extremely
-tricky and difficult change is shown below:
-
-@verbatim
- GlobalRouteManager::PopulateRoutingTables ();
-@end verbatim
-
-This one-line addition, located just before the simulation runs, tells the
-@command{ns-3} @emph{global route manager} to walk the topology you created and
-build internetwork routing tables for all of the nodes in the simulation.
-We changed the client application so that it runs on node four:
-
-@verbatim
- Ptr<UdpEchoClient> client = CreateObject<UdpEchoClient> (n4, "10.1.1.2",
- port, 1, Seconds(1.), 1024);
-@end verbatim
-
-Now if you build and run @code{tutorial-star-routing.cc} you can examine the
-@code{tutorial.tr} file and see that your UDP echo packets are now correctly
-routed through the topology.
-
-@section A Dumbbell Network
-One of the most interesting simple topologies (from a phenomenological point of
-view) is commonly called a dumbbell network. The name derives from a
-superficial similarity in form to a piece of exercise equipment.
-
-The dumbbell model is typically composed of two bus or star network elements
-connected via a point-to-point link. The point-to-point link is usually
-configured with a lower bandwidth than the bus elements to provide a
-@emph{choke point}.
-
-The following is a representation of the topology.
-
-@sp 1
-@center @image{figures/dumbbell,,,,png}
-
-We have provided a file that constructs this dumbbell network and creates
-enough data flowing across the choke point that some packets will be dropped.
-The file is called @code{tutorial-linear-dumbbell.cc} and is located in the
-@code{tutorial} directory. We have already covered all of the code used to
-create this network, so we will just quickly go over the main sections of the
-script.
-
-The first section creates a CSMA lan that will become the left side of the
-dumbbell network. This code should be very familiar since we used the same
-process to create our first example.
-
-@verbatim
-//
-// Create the lan on the left side of the dumbbell.
-//
- Ptr<Node> n0 = CreateObject<InternetNode> ();
- Ptr<Node> n1 = CreateObject<InternetNode> ();
- Ptr<Node> n2 = CreateObject<InternetNode> ();
- Ptr<Node> n3 = CreateObject<InternetNode> ();
-
- Ptr<CsmaChannel> lan1 =
- CsmaTopology::CreateCsmaChannel (DataRate (10000000), MilliSeconds (2));
-
- uint32_t nd0 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n0, lan1,
- "08:00:2e:00:00:00");
-
- uint32_t nd1 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n1, lan1,
- "08:00:2e:00:00:01");
-
- uint32_t nd2 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n2, lan1,
- "08:00:2e:00:00:02");
-
- uint32_t nd3 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n3, lan1,
- "08:00:2e:00:00:03");
-
- CsmaIpv4Topology::AddIpv4Address (n0, nd0, "10.1.1.1", "255.255.255.0");
- CsmaIpv4Topology::AddIpv4Address (n1, nd1, "10.1.1.2", "255.255.255.0");
- CsmaIpv4Topology::AddIpv4Address (n2, nd2, "10.1.1.3", "255.255.255.0");
- CsmaIpv4Topology::AddIpv4Address (n3, nd3, "10.1.1.4", "255.255.255.0");
-@end verbatim
-
-The code to generate the CSMA lan on the right side is similar; only the names
-have been changed.
-
-@verbatim
-//
-// Create the lan on the right side of the dumbbell.
-//
- Ptr<Node> n4 = CreateObject<InternetNode> ();
- Ptr<Node> n5 = CreateObject<InternetNode> ();
- Ptr<Node> n6 = CreateObject<InternetNode> ();
- Ptr<Node> n7 = CreateObject<InternetNode> ();
-
- Ptr<CsmaChannel> lan2 =
- CsmaTopology::CreateCsmaChannel (DataRate (10000000), MilliSeconds (2));
-
- uint32_t nd4 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n4, lan2,
- "08:00:2e:00:00:04");
-
- uint32_t nd5 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n5, lan2,
- "08:00:2e:00:00:05");
-
- uint32_t nd6 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n6, lan2,
- "08:00:2e:00:00:06");
-
- uint32_t nd7 = CsmaIpv4Topology::AddIpv4CsmaNetDevice (n7, lan2,
- "08:00:2e:00:00:07");
-
- CsmaIpv4Topology::AddIpv4Address (n4, nd4, "10.1.2.1", "255.255.255.0");
- CsmaIpv4Topology::AddIpv4Address (n5, nd5, "10.1.2.2", "255.255.255.0");
- CsmaIpv4Topology::AddIpv4Address (n6, nd6, "10.1.2.3", "255.255.255.0");
- CsmaIpv4Topology::AddIpv4Address (n7, nd7, "10.1.2.4", "255.255.255.0");
-@end verbatim
-
-Next, we create a point to point link to connect the two lans. We connect
-the point-to-point channel between nodes three (on the left lan) and four
-(on the right lan). You should recognize this as substantially similar to
-the link setup from the @code{point-to-point} example.
-
-@verbatim
-//
-// Create the point-to-point link to connect the two lans.
-//
- Ptr<PointToPointChannel> link = PointToPointTopology::AddPointToPointLink (
- n3, n4, DataRate (38400), MilliSeconds (20));
-
- PointToPointTopology::AddIpv4Addresses (link, n3, "10.1.3.1",
- n4, "10.1.3.2");
-@end verbatim
-
-Then we configure data flows. We create four echo clients that send UDP
-packets from the left side lan to servers created on the right side lan.
-Notice that we send 100 packets with an inter-packet gap of ten milliseconds
-instead of the single packet we have previously used. This data rate is
-sufficient to saturate the point-to-point link and will cause packets to be
-dropped when the queue on the link net devices overflows (the default maximum
-queue depth is 100 packets). Note that we stagger the start of the echo
-clients to slowly bring up the data rates.
-
-@verbatim
-//
-// Create data flows across the link:
-// n0 ==> n4 ==> n0
-// n1 ==> n5 ==> n1
-// n2 ==> n6 ==> n2
-// n3 ==> n7 ==> n3
-//
- uint16_t port = 7;
-
- Ptr<UdpEchoClient> client0 = CreateObject<UdpEchoClient> (n0, "10.1.2.1",
- port, 100, Seconds(.01), 1024);
- Ptr<UdpEchoClient> client1 = CreateObject<UdpEchoClient> (n1, "10.1.2.2",
- port, 100, Seconds(.01), 1024);
- Ptr<UdpEchoClient> client2 = CreateObject<UdpEchoClient> (n2, "10.1.2.3",
- port, 100, Seconds(.01), 1024);
- Ptr<UdpEchoClient> client3 = CreateObject<UdpEchoClient> (n3, "10.1.2.4",
- port, 100, Seconds(.01), 1024);
-
- Ptr<UdpEchoServer> server4 = CreateObject<UdpEchoServer> (n4, port);
- Ptr<UdpEchoServer> server5 = CreateObject<UdpEchoServer> (n5, port);
- Ptr<UdpEchoServer> server6 = CreateObject<UdpEchoServer> (n6, port);
- Ptr<UdpEchoServer> server7 = CreateObject<UdpEchoServer> (n7, port);
-
- server4->Start(Seconds(1.));
- server5->Start(Seconds(1.));
- server6->Start(Seconds(1.));
- server7->Start(Seconds(1.));
-
- client0->Start(Seconds(2.));
- client1->Start(Seconds(2.1));
- client2->Start(Seconds(2.2));
- client3->Start(Seconds(2.3));
-
- server4->Stop (Seconds(10.));
- server5->Stop (Seconds(10.));
- server6->Stop (Seconds(10.));
- server7->Stop (Seconds(10.));
-
- client0->Stop (Seconds(10.));
- client1->Stop (Seconds(10.));
- client2->Stop (Seconds(10.));
- client3->Stop (Seconds(10.));
-@end verbatim
-
-The remainder of the file should be quite familiar to you. Go ahead and
-run @code{tutorial-linear-dumbbell}. Now take a look at the trace
-(@code{tutorial.tr}) file. You will now see trace lines that begin with
-@code{d}. Alternatively you can search for the string ``queue-drop'' which
-is the expansion of the drop code ('d').
-
-Interpretation of a dropped packet is straightforward. We have expanded
-the first @code{queue-drop} trace for you below. See the section on ASCII
-tracing for details.
-
-@verbatim
- 00 d
- 01 2.40938
- 02 nodeid=3
- 03 device=1
- 04 queue-drop
- 05 pkt-uid=124
- 06 LLCSNAP(type 0x800)
- 07 IPV4(
- 08 tos 0x0
- 09 ttl 63
- 10 id 20
- 11 offset 0
- 12 flags [none]
- 13 length: 1052) 10.1.1.3 > 10.1.2.3
- 14 UDP(length: 1032)
- 15 49153 > 7
- 16 DATA (length 1024)
-@end verbatim
-
-We leave it as an exercise to examine the trace files in more detail.
-
-@c ========================================================================
-@c Nonlinear Thinking
-@c ========================================================================
-
-@node Nonlinear-Thinking
-@chapter Nonlinear Thinking
-
-One thing that all of our examples so far have in common is that they are
-composed of a linear collection of calls into the @command{ns-3} system. The
-programmers among the readers may have wondered why there is not as much
-as a for-loop in all of the examples. The answer is that we wanted to
-introduce you to @command{ns-3} scripting with a minimum of conceptual
-overhead. We're going to remedy that situation shortly.
-
-We have written a number of @command{ns-3} scripts in C++. Although we have
-been perfectly linear in our script implementations, just like any other C++
-program, an @command{ns-3} script can use any features of the language you
-desire. If you will look back at the @code{tutorial-linear-dumbbell.cc}
-example, you may notice that the code to create the left and right sides of
-the dumbbell is operationally identical --- only the names change. An obvious
-improvement of this program would be to use subroutines to create the sides.
-Since we are working with C++, we should probably do this in an
-object-oriented way. Since object-oriented design is somewhat of a black art
-to some people, we'll take some time here and outline a simple methodology
-you can follow.
-
-@section Object Design 101 --- Class Ipv4BusNetwork
-If you are a master of object oriented design, feel free to skip or skim this
-section, in which we derive a simplistic but fully operational bus network
-class.
-
-So you want to create a BusNetwork class. Often the biggest hurdle in a
-design is figuring out how to get started. One of the simplest and most
-straightforward ways to do an object decomposition of a problem is to simply
-write down a description of the problem and take a look at the words
-you used. Let's take some time and do that, first at a very high level.
-
-@example
-A bus network is an implementation of a particular network topology that
-contains some number of nodes. Each of these nodes is attached to a single
-multi-drop channel. The network itself has some attributes independent of
-the topology such as a network mask, network number (prefix) and base IP
-address.
-@end example
-
-The first thing to do is to focus on the nouns and adjectives. These will
-give you a starting point for required classes and member variables.
-
-Immediately we can notice that at the highest level we are talking about the
-noun @emph{network}. This probably won't surprise you. We also have an
-adjective that modifies the noun --- @emph{bus}. This should lead us to our
-first class definition. Usually class names are constructed in the same way
-as an English language sentence would be spoken. For example, one would speak
-of a @emph{bus network} in conversation, so we would normally create a
-@code{class BusNetwork} to represent it.
-
-One thing to note is that we have used two words in our description quite
-naturally: @emph{is} and @emph{has}. When you see these words should should
-immediately think of the object-oriented concepts of @emph{ISA} (inheritance)
-and @emph{HASA} (containment) respectively. We wrote that a bus network
-@emph{is} an implementation of a particular network topology. Perhaps you
-will agree that there is a natural base class called @code{Network} that
-@emph{has} the attributes discussed above. The fact that a @code{BusNetwork}
-@emph{ISA} kind of @code{Network} suggests inheritance. Let's capture that
-thought right away remembering that we're focused on IP version four here:
-
-@verbatim
- class Ipv4Network
- {
- public:
- Ipv4Address m_network;
- Ipv4Mask m_mask;
- Ipv4Address m_baseAddress;
- };
-
- class Ipv4BusNetwork : public Ipv4Network
- {
- };
-@end verbatim
-
-Let's take a look at the @emph{HASA} relationships of the bus network. Clearly
-it will @emph{have} a reference to the underlying channel that implements the
-actual communications medium. We use smart pointers for those references, so
-one member variable is obvious:
-
-@verbatim
- Ptr<CsmaChannel> m_channel;
-@end verbatim
-
-A bus network will also need to contain references to all of the nodes we
-eventually want to create. If you are working in C++ and see the words contain
-or container, you should immediately think of the Standard Template Library
-or STL. A quick search of the available containers there will probably lead
-you to consider the vector class. A vector is a container that looks like an
-array. This is just what we need here. Again, we want to use smart pointers
-to reference our nodes, so the declaration of the vector would look like,
-
-@verbatim
- std::vector<Ptr<Node> > m_nodes;
-@end verbatim
-
-It will save you headaches in the future if you notice that the space between
-the two right brackets is required to differentiate this situation from a
-right-shift operator. So we have a pretty good start already after just a
-little work. Now we need to turn our attention to actions. Let's write
-another little description of the things you consider doing to a Bus network.
-
-@example
-We need to be able to create a bus network. We need to be able to delete a
-bus network. We need to be able to get a handle to a node in order to add
-applications. We need to be able to set the network, mask and base address
-somehow, specify how many nodes to create and provide the underlying channel
-its required bandwidth and delay parameters.
-@end example
-
-We now look at the @emph{verbs} in that sentence. These will give a good
-starting point for the methods of the classes. For example, the verbs
-@emph{create} and @emph{delete} should suggest @emph{constructor} and
-@emph{destructor}. The verb @emph{get} leads us to providing a method called
-@code{GetNode}. We have to provide a number of parameters so we can either
-provide @emph{setters} or we can simply pass them in as parameters to our
-constructors. Since this is a simple example, we won't bother to implement
-getters and setters (methods to get and set member variables to enhance data
-hiding). Let's use this guidance to finish up our class declarations:
-
-@verbatim
- class Ipv4Network
- {
- public:
- Ipv4Network (Ipv4Address network, Ipv4Mask mask, Ipv4Address address);
- virtual ~Ipv4Network ();
-
- Ipv4Address m_network;
- Ipv4Mask m_mask;
- Ipv4Address m_baseAddress;
- };
-
- class Ipv4BusNetwork : public Ipv4Network
- {
- public:
- Ipv4BusNetwork (
- Ipv4Address network,
- Ipv4Mask mask,
- Ipv4Address startAddress,
- DataRate bps,
- Time delay,
- uint32_t n);
-
- virtual ~Ipv4BusNetwork ();
-
- Ptr<Node> GetNode (uint32_t n);
-
- private:
- std::vector<Ptr<Node> > m_nodes;
- Ptr<CsmaChannel> m_channel;
- };
-@end verbatim
-
-That's it. We have actually already walked through almost all of the code
-required to construct a bus network in our @code{tutorial-csma-echo.cc}
-example, so let's just jump forward and take a look at an implementation
-of this thing. We provide an implementation for you in the files
-@code{ipv4-bus-network.h} and @code{ipv4-bus-network.cc} located in the
-@code{tutorial} directory. We also provide an example that uses the new
-class in the file @code{tutorial-bus-network.cc}.
-
-The interesting method from our current perspective is the Ipv4BusNetwork
-constructor, shown below:
-
-@verbatim
- Ipv4BusNetwork::Ipv4BusNetwork (
- Ipv4Address network,
- Ipv4Mask mask,
- Ipv4Address baseAddress,
- DataRate bps,
- Time delay,
- uint32_t n)
- :
- Ipv4Network (network, mask, baseAddress)
- {
- Ipv4AddressGenerator::SeedNetwork (mask, network);
- Ipv4AddressGenerator::SeedAddress (mask, baseAddress);
-
- m_channel = CsmaTopology::CreateCsmaChannel (bps, delay);
-
- for (uint32_t i = 0; i < n; ++i)
- {
- Ptr<Node> node = CreateObject<InternetNode> ();
- uint32_t nd = CsmaIpv4Topology::AddIpv4CsmaNetDevice (node, m_channel,
- Mac48Address::Allocate ());
- Ipv4Address address = Ipv4AddressGenerator::AllocateAddress (mask,
- network);
- CsmaIpv4Topology::AddIpv4Address (node, nd, address, mask);
- m_nodes.push_back (node);
- }
- }
-@end verbatim
-
-Notice that we do the simple and straightforward thing and pass all of our
-parameters to the constructor. For those unfamiliar with C++, the line after
-the colon and before the opening brace (shown below),
-
-@verbatim
- :
- Ipv4Network (network, mask, baseAddress)
- {
-@end verbatim
-
-Passes the appropriate parameters to the constructor of the base class
-@code{Ipv4Network}. There are two new calls that we haven't seen immediately
-after this initialization. They are:
-
-@verbatim
- Ipv4AddressGenerator::SeedNetwork (mask, network);
- Ipv4AddressGenerator::SeedAddress (mask, baseAddress);
-@end verbatim
-
-We provide an IP address generator class to allow us to programmatically
-allocate IP addresses. The first call to @code{SeedNetwork} gives the
-address generator a starting network number to use when generating addresses.
-The second call to @code{SeedAddress} gives the address generator a starting
-IP address to use. There is a starting network and starting address for each
-of the 32 possible network masks. Later in the for loop, you will see a
-call to @code{AllocateAddress} in which the IP address for each node created
-in the loop is actually generated.
-
-The only unfamiliar call in the reset of the constructor will be:
-
-@verbatim
- m_nodes.push_back (node);
-@end verbatim
-
-This is the STL code to add the newly created node to the vector of nodes
-attached to the bus.
-
-For your convenience, we reproduce the entire bus network implementation below:
-
-@verbatim
- /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
- /*
- * Copyright (c) 2007 University of Washington
- *
- * 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/mac48-address.h"
- #include "ns3/csma-net-device.h"
- #include "ns3/csma-topology.h"
- #include "ns3/csma-ipv4-topology.h"
-
- #include "ipv4-bus-network.h"
- #include "ipv4-address-generator.h"
-
- namespace ns3 {
-
- Ipv4Network::Ipv4Network (
- Ipv4Address network,
- Ipv4Mask mask,
- Ipv4Address address)
- :
- m_network (network), m_mask (mask), m_baseAddress (address)
- {
- }
-
- Ipv4Network::~Ipv4Network ()
- {
- }
-
- Ipv4BusNetwork::Ipv4BusNetwork (
- Ipv4Address network,
- Ipv4Mask mask,
- Ipv4Address baseAddress,
- DataRate bps,
- Time delay,
- uint32_t n)
- :
- Ipv4Network (network, mask, baseAddress)
- {
- Ipv4AddressGenerator::SeedNetwork (mask, network);
- Ipv4AddressGenerator::SeedAddress (mask, baseAddress);
-
- m_channel = CsmaTopology::CreateCsmaChannel (bps, delay);
-
- for (uint32_t i = 0; i < n; ++i)
- {
- Ptr<Node> node = CreateObject<InternetNode> ();
- uint32_t nd = CsmaIpv4Topology::AddIpv4CsmaNetDevice (node, m_channel,
- Mac48Address::Allocate ());
- Ipv4Address address = Ipv4AddressGenerator::AllocateAddress (mask,
- network);
- CsmaIpv4Topology::AddIpv4Address (node, nd, address, mask);
- m_nodes.push_back (node);
- }
- }
-
- Ipv4BusNetwork::~Ipv4BusNetwork ()
- {
- }
-
- Ptr<Node>
- Ipv4BusNetwork::GetNode (uint32_t n)
- {
- return m_nodes[n];
- }
-
- }; // namespace ns3
-@end verbatim
-
-@section Using Ipv4BusNetwork
-If all you ever want to do with a bus network can be captured in a topology
-with four nodes on the bus, the preceeding section may seem like a colossal
-waste of time. This is probably not the case, though. Now that we have a
-relatively abstract bus class, we can create bus networks with 4, 40 or 4000
-nodes with no additional effort.
-
-A use of the bus network class is shown in the file
-@code{bus-network.cc} located in the @code{tutorial} directory. The
-interesting code is,
-
-@verbatim
- Ipv4BusNetwork bus ("10.1.0.0", "255.255.0.0", "0.0.0.3",
- DataRate(10000000), MilliSeconds(20), 10);
-@end verbatim
-
-Here we create a bus network with the network number ``10.1.0.0'' and the
-network mask ``255.255.0.0'' that completes the IP network definition. You
-can consider these together as ``10.1.0.0/16'' if you prefer. The next
-parameter tells the bus to start numbering IP addresses of contained nodes at
-``10.1.0.3'' (remember the network number will be combined). We provided a
-data rate of 10 megabits per second and a latency of 20 milliseconds.
-Finally, we ask the @code{Ipv4BusNetwork} object to create ten nodes in the
-network.
-
-If you are feeling brave, go ahead and change the number of nodes to be 100,
-1000, 10,000 or more to generate larger and larger networks. Before you go
-too far, remember that a trace file will be generated when you run your
-resulting program and ee asked the trace facility to trace all net device
-receive events. This will include the reception of the broadcast ARP request
-by all of the nodes in the simulation, so this can add up quickly.
-
-@c ========================================================================
-@c Summary
-@c ========================================================================
-
-@node Summary
-@chapter Summary
-
-This concludes the first part of the tutorial. We have focused on
-using the @command{ns-3} system to construct various network topologies and to
-simulate sendng data across the networks; and we've shown you how to use the
-trace facility to get access to simulation results.
-
-We now encourage you to play with the system a little. Experiment with what
-we have provided. Build a hierarchical network simulation. Perhaps exercise
-your object design skills and create a new @code{Ipv4DumbbellNetwork} class
-to create dumbbell networks using the Ipv4BusNetwork class we just created.
-Hint: An Ipv4DumbbellNetwork @emph{has} two @code{Ipv4BusNetwork} objects;
-a left side and a right side.
-
-In the next part of the tutorial we are going to drop down a level and begin
-examining the lower levels of the system in more detail. We are going to
-explain how to change the behavior of the system and eventually how to write
-new models and applications. This is a good time to make sure that you
-thoroughly understand what we've gone over so far.
-
-@c ========================================================================
-@c Object Model
-@c ========================================================================
-
-@node Object-Model
-@chapter Object Model
-
-@cindex Object Model
-There are two distinctly different meanings associated with the term Object
-Model. The first speaks to the implementation of an object system --- a system
-view; and the second speaks to the application programming interface (classes
-or objects) one uses to access some service or system --- an application view.
-
-As an example of the system view sense of the term, the C++ language has an
-associated object model that describes how objects are laid out in memory,
-how virtual functions work, how inheritance is implemented, constructor and
-destructor execution ordering, template instantiation, etc.
-
-@cindex API
-@cindex DOM
-@cindex Document Object Model
-In the case of the application view, the Document Object Model is a good
-example. In the words of W3C, the Document Object Model (DOM) is an
-application programming interface (API) for HTML and XML documents. It defines
-the logical structure of documents and the way a document is accessed and
-manipulated.
-
-@cindex API
-@cindex COM
-@cindex Component Object Model
-The Component Object Model (COM) from Microsoft actually spans both meanings
-of the term and extends further into policy statements. From a system
-perspective, COM specifies an interface definition language, the layout of
-objects virtual function tables, the formats of Globally Unique Identifiers
-and also specifies lifetime management mechanisms for objects via reference
-counting. From the point of view of the API, COM specifies a number of
-Interfaces as well as functions such as CoCreateInstance and various
-threading models. The COM specification extends to policy by disallowing
-implementation inheritance.
-
-@cindex Feynman
-The @command{ns-3} object model takes the C++ language (system level) object
-model as its basis, and extends that model by providing an API for software
-componentry. You may find terms like Component, Interface and QueryInterface
-in the following discussion, or used informally in other discussions about
-@command{ns-3}. It is important to understand from the outset that this is
-the @command{ns-3} object model, and not any other object model.
-Richard Feynman (an American physicist) once described the behavior of matter
-and light on a very small scale in the following way,
-
-@quotation
-``They do not behave like waves, they do not behave like particles, they do
-not behave like clouds, or billiard balls, or weights on springs, or like
-anything that you have ever seen.''
-@end quotation
-
-Just as students of quantum mechanics must rid themselves of preconceptions
-regarding the behavior of matter at small scales, you should rid yourself of
-any preconceptions you may have about components, interfaces and APIs for
-software componentry before continuing. To paraphrase Feynman, @command{ns-3}
-components do not behave like COM Components, or Java Beans, or CORBA
-objects, or clouds or weights on springs, or like anything that you have
-ever seen --- they are @command{ns-3} components.
-
-@section The C++ Object Model is the Root of all Things
-@command{Ns-3} is primarily a C++ system. The system is written in C++ and
-one can use standard C++ mechanisms for creating and using ns-3 objects. We
-do not change this at all, nor do we make any pronouncements about the
-superiority of one mechanism or another. What we will do is provide
-convenience functions that we think will make creating and managing simulation
-objects easier.
-
-@cindex CreateObject
-Previously, you have seen objects created using the template function
-@code{CreateObject} as in the following example:
-
-@verbatim
- Ptr<Node> n0 = CreateObject<InternetNode> ();
-@end verbatim
-
-This line of code, while it may be unfamiliar to some, is pure C++. If you
-were to look in the header file ptr.h, you would find the following definition
-of the @code{CreateObject} template.
-
-@verbatim
- template <typename T>
- Ptr<T> CreateObject (void)
- {
- Ptr<T> p = Ptr<T> (new T (), false);
- p->SetTypeId (T::GetTypeId ());
- return p;
- }
-@end verbatim
-
-@cindex template
-As you can see, this template creates objects of type @code{T} using the
-operator @code{new}. Its a little harder to find the corresponding delete ---
-it's in the file @code{object.cc} inside the method @code{Object::MaybeDelete},
-but when that @code{Ptr} which you see above goes out of scope it will call
-@code{Unref} and ultimately the C++ @code{delete} operator will be called.
-
-@cindex new
-@cindex delete
-The ns-3 system uses the C++ @code{new} and @code{delete} operators, so there
-is really no reason that you as a user of the ns-3 system are forbidden from
-using these or any other C++ mechanism. If you so desire, you can take on
-the responsibility for managing object lifetime (i.e., do not use the
-@code{Ptr} smart pointer), work directly with the @code{new} and @code{delete}
-operators and call methods like any C++ object as in the following example:
-
-@verbatim
- MyClass *obj = new MyClass ();
- obj->Method();
- delete obj;
-@end verbatim
-
-@cindex model
-You, as a competent model author, are encouraged to use whatever methods you
-think are appropriate in your private code. Remember, however, that the
-public ns-3 APIs do use smart pointers to pass objects around in an effort to
-reduce the burden of object lifetime management. If you do intend to export
-an API publicly, you should use the same object lifetime management approaches
-as those found in the ns-3 public API if only for consistency.
-
-These APIs are there for convenience and consistency, but do not change the
-fact that in ns-3 all of the objects are really just C++ objects, ultimately
-created using the C++ new operator with C++ constructor semantics and are
-ultimately deleted using the C++ delete operator, following C++ destructor
-semantics. Although it may sometimes appear so, there is really no system-
-level magic going on in ns-3. Ns-3 components and interfaces are C++ objects
-just like any other object and our object model is simply a collection of APIs
-built on the normal C++ object model.
-
-@cindex Interface
-@cindex Abstract Data Type
-@cindex ADT
-@cindex Abstract Base Class
-@cindex ABC
-@section Interface
-There are many different ideas floating around of what exactly the term
-@emph{interface} means. Originally an interface just meant a communication
-boundary between two entities. As the concepts of object oriented programming
-(OOP) were surfacing in the 1980s, the term interface was applied to the
-collection of access methods for the modular entities that were being defined.
-
-@cindex OOP
-@cindex Object Oriented Programming
-Two distinct approaches developed regarding specifying access mechanisms for
-objects. The OOP purists were very concerned about object reuse and were led
-to Abstract Data Types (ADT). These were eventually implemented in the case
-of C++, as pure virtual methods in Abstract Base Classes (ABC). Another group
-of folks was more interested in simply specifying object access methods in one
-place and using inheritance as the primary reuse mechanism.
-
-Bjarne Stroustroup, the creator of C++, embraced both approaches. He makes
-the following interesting observation:
-
-@quotation
-``Many classes [@dots{}] are useful both as themselves and also as bases for
-derived classes. [@dots{}] Some classes, such as class @strong{Shape},
-represent abstract concepts for which objects cannot exist.''
-@end quotation
-
-@cindex PIMPL
-@command{Ns-3} does not pick and enforce a particular approach. In
-@command{ns-3} an interface is determined completely by a class declaration
-just as any C++ object interface is declared. If you think of an object as
-an abstract concept that should be implemented by derived classes, by all
-means, use the Abstract Base Class approach to interface declaration. If you
-think that an object should be completely concrete and you foresee no need
-to ever modify its behavior, feel free to avoid declaring any methods virtual.
-If you think that an object could be useful as a base class, feel free to
-declare its methods virtual. If you like to use the PIMPL idiom, again, feel
-free. If you want to use any combination of these techniques, feel free.
-We make no restrictions.
-
-@cindex API
-When we speak of an ns-3 interface, we do not worry about interface definition
-languages, or pure virtual classes, or registries we just think about C++
-object declarations and their associated methods. We tend to think of
-interfaces to objects as simply a private or public API. When we instantiate
-an @command{ns-3} interface, it is the C++ object model that dictates how that
-object is brought into existence. When a method is called on an @command{ns-3}
-Interface, it is the C++ object model that dictates how that method is
-dispatched.
-
-We do, however, provide a base class that endows vanilla C++ objects with
-capabilities that can be seen as conceptually similar to those provided by
-Microsoft Component Model @emph{Interfaces}.
-
-@section The Ns-3 Object and GetObject
-@cindex Component Object Model
-One thing that Microsoft arguably got right in the Component Object Model was
-the idea of Interface aggregation and discovery via QueryInterface. We have
-embraced these ideas in @command{ns-3}. This was done primarily to address a
-common problem in large software systems. A good example of this problem
-happens in the @command{ns-3} Node class.
-
-@cindex OOP
-@cindex weak base class
-@cindex base class bloat
-@cindex Swiss Army Knife class
-@cindex Node
-If one were to take the standard OOP view of specializing a @code{Node} into
-an internet host, for example, one would typically inherit from the @code{Node}
-base class and include functionality to implement such things as internet
-routing and a TCP/IP protocol stack. Other types of @code{Node}s might
-inherit from the node class and specialize in different ways, or further
-specialize the internet host class, treating it as a base class. This can
-result in a complicated inheritance tree in which some specializations are
-simply not available to other branches of the tree which can make reuse
-difficult or impossible. This is known as the @emph{weak base class} problem
-and creates pressure to drive functionality up the inheritance tree into the
-base classes. This, in turn, results in @emph{base class bloat} and the
-resulting @emph{swiss army knife} base classes which end up trying to do
-everything in one place.
-
-Even if one successfully avoided these swiss army knife base classes, one
-would also want to be able to treat new specializations of @code{Node}
-generically in the system. This means one would pass references to the base
-class (@code{Node}) across public APIs. This introduces @emph{upcasts} prior
-to passing across public APIs and corresponding @emph{downcasts} on the other
-side in order to gain access to required specialized functions. As the
-inheritance tree becomes more complicated, this approach can cause another
-related problem known as the @emph{fragile base class} problem. This happens
-when changes to the base class cause unexpected problems in the various and
-sundry subclasses.
-
-These effects seem always to result in a positive feedback loop driving
-everything into the base class and destroying much of the encapsulation which
-is a hallmark of the object oriented approach.
-
-@subsection Interface Composition
-@cindex Node
-There is a completely different way to address the Node specialization
-problem. Instead of approaching the situation using inheritance, one can
-look at the problem as one of composition. We can look at the @code{Node}
-class as a container of sorts that holds other objects. In this case, the
-objects would be instances of the classes implementing the internetwork
-routing code, or the TCP/IP protocol stack described above. This approach
-preserves the encapsulation and solves the weak base class, base class bloat
-and fragile base class problems; but the question of method dispatch
-immediately comes to mind.
-
-@cindex delegation
-In many systems, @emph{delegation} is used. The base class, @code{Node},
-in this approach would provide methods that simply forward to the objects
-implementing the desired functionality. This situation clearly does not
-address the base class bloat problem since dispatch methods must be added
-to the base class. The situation is mitigated somewhat by pushing the
-implementation of the dispatch methods to contained objects, but the
-fundamental problems are still present. What is really needed is a way
-to compose objects but at the same time keep the interfaces to those
-objects separated.
-
-@cindex aggregation
-Composition, usually called @emph{aggregation}, along with runtime Interface
-discovery is the solution that Microsoft originally championed and that
-@command{ns-3} has adopted --- albeit with many simplifications and a few name
-changes.
-
-@subsection Objects and Interfaces
-@cindex COM
-@cindex QueryInterface
-Now that we have mentioned Microsoft COM and are almost obligated to mention
-the terms Interface and QueryInterface. For those familiar with COM, loosely
-speaking, QueryInterface is to COM as GetObject is to @command{ns-3}.
-The analogy, while good conceptually, is superficial from an implementation
-point of view.
-
-@cindex Node
-Addressing our current example of a @code{Node}, generically speaking, each
-node needs to aggregate an object that will implement internetwork routing
-and TCP/IP. The system will need to provide a mechanism for locating the
-aggregated objects and allow a client to discover them.
-
-@cindex aggregation
-@cindex Object
-These aggregated objects have interfaces in the C++ sense of collections of
-method signatures. In @command{ns-3}, when objects are capable of
-participating in this aggregation process, they are called @command{ns-3}
-@code{Objects}. @code{Objects} receive the functionality required for this
- participation by inheriting from the @command{ns-3} base class @code{Object}.
-
-Note well that when we write the word @code{Object} (note the uppercase 'O' in
-the spelling and the change of font) we are referring to a kind of C++ object
-that has inherited the capability of participating in an aggregation. The
-@command{ns-3}-specific word @code{Object} can have a significantly different
-meaning than that of a vanilla C++ object outside the aforementioned
-inheritance tree, and the difference is only readily apparent via context.
-In this tutorial we will always write the @command{ns-3}-specific kind of
-@code{Object} in a fixed font; and will write the vanilla C++ term object in
-normal font. In conversation, you will need to be careful to understand which
-term is meant: object or @code{Object}.
-
-Once an object has inherited from class @code{Object} it has the ability to
-@emph{host} an aggregation. This means that it has the ability to add other
-@code{Objects} to its aggregation via the method @code{AggregateObject}. It
-also means that it can provide a service to @emph{discover} other objects in
-its aggregation via the method @code{GetObject}.
-
-@cindex base class
-Technically, the class named @code{Object} is simply a base class that you
-will inherit from if you want your @code{Objects} to support aggregation and
-discovery. Many systems have a base class that implements common
-functionality and these base classes are typically called something like
-Object. The @command{ns-3} version of this base class relates primarily to
-@code{Object} aggregation and discovery, although it does also provide methods
-to help with intrusive reference counting and tracing as well.
-
-When a C++ object inherits from the ns-3 Object base class, it is conceptually
-promoted to an ns-3 @code{Object} irrespective of how the object was declared
-(e.g., as an abstract base class, concrete class, with virtual methods, etc.).
-In ns-3, you should associate inheritance from the class named @code{Object}
-with promotion of an object to the status of some locatable @code{Object}
-rather than with the form of the class declaration.
-
-@cindex COM
-@cindex CORBA
-@cindex ORBit
-For those of you unfamiliar with Microsoft COM, CORBA or ORBit, this might
-sound obvious. For those of with such a background, the point we are making
-is that there is no such thing in @command{ns-3} as a separate Interface
-declaration, no such thing as an Interface Definition Language, no such thing
-as a UUID or GUID, etc. In @command{ns-3} we just work with C++ objects that
-may be given some very useful abilities by inheriting from the @command{ns-3}
-base class @code{Object}. @command{Ns-3} @code{Objects} are not required to
-inherit from classes composed of pure virtual methods in order to define an
-Interface. It's all really just ``plain old C++.''
-
-To summarize, when you instantiate an object that inherits from the
-@code{Object} class, you will have a C++ object that has four important
-properties:
-
-@cindex AggregateObject
-@cindex GetObject
-@itemize @bullet
-@item The @code{Object} has a C++ interface defined by the collection of method signatures in its inheritance tree;
-@item The @code{Object} has some way to identify its underlying class uniquely;
-@item The @code{Object} is a kind of container that has the ability to aggregate other @code{Objects} using the method @code{AggregateObject};
-@item The @code{Object} exports a method called @code{GetObject} that allows for discovery of other aggregated @code{Objects}.
-@end itemize
-
-@cindex base class
-@cindex Object
-It is crucially important to understand what we have described here
-(especially for those coming from other systems that provide similar
-functionality). A given C++ class has an object access interface that is
-essentially the collection of method signatures specified in its inheritance
-tree. This is a C++ object model thing. Ns-3 provides a base class from
-which the class in question can inherit and be promoted to the status of
-@code{Object}. Once a class becomes an @code{Object} it has inherited the
-ability to aggregate and search for other @code{Objects} that are added to
-its aggregation.
-
-That last detail is important. In @command{ns-3} @code{Objects} are both
-containers and specifications for a object method access. We have previously
-mentioned that the @code{Node} class acts as a container. In fact, the
-@code{Node} class inherits from @code{Object} and is itself an @command{ns-3}
-@code{Object}. So, when the @code{Node} object is created it is really an
-aggregation of one @code{Object} and you can call @code{AggregateObject} or
-@code{GetObject} on the resulting @code{Node} object. Along with being an
-aggregation, the @code{Node} class also describes a public interface. This
-public interface (API) is declared just as any C++ object is declared, via its
-class methods as specified in the inheritance tree. For those steeped in
-COM or CORBA, this is where the concept of Interface works in @command{ns-3}.
-Remember that it is generally true that @code{Objects} are both aggregations
-and APIs.
-
-@subsection Aggregations
-@cindex aggregate
-The figure below shows how an @code{Object} could be illustrated in detail.
-The line with the circle at the top of the diagram represents the appearance
-of the @code{Object} API to the external world. This circle and line are
-together called a lollipop because of its superficial similarity to a kind of
-childs candy.
-
-@sp 1
-@center @image{oneobj,,,,png}
-
-@cindex API
-You could declare this API and associated @code{Object} quite simply using a
-non-virtual class as follows,
-
-@verbatim
- class A : public Object {
- public:
- static ns3::TypeId GetTypeId (void)
- {
- static ns3::TypeId tid = ns3::TypeId ("A")
- .SetParent (Object::GetTypeId ())
- .AddConstructor<A> ();
- return tid;
- }
-
- A ()
- {
- }
-
- void MethodA (void);
- };
-@end verbatim
-
-The methods that are then available via the API labeled @code{A} in the
-figure above are the methods inherited from the @code{Object} base class
-(@code{GetObject}, @code{Ref}, and @code{Unref}) and those from class
-@code{A} (@code{MethodA}).
-
-Note that you must declare a @code{TypeId} in your @code{Object} class, and
-it must be declared static to make it class-wide in scope. This @code{TypeId}
-is a unifying element in the @command{ns-3} object model and uniquely
-identifies @code{Objects} at run-time as being instantiated from a particular
-class. We'll have much more to say about @code{TypiId} shortly.
-
-You can think of the arc and arrow device coming off each side of the
-illustrated @code{Objects} as part of a connector. These connectors allow
-@code{GetObject} to search aggregations for an instance of a class type.
-The figure below shows an aggregation of three @code{Objects}: A, B and C.
-The class declarations for classes @code{B} and @code{C} are substantially
-similar to that of class @code{A}.
-
-@sp 1
-@center @image{threeobj,,,,png}
-
-You can visualize these @code{Objects} as being snapped together like Lego
-building blocks if you like. When @code{Objects} are aggregated, a
-@code{GetObject} search path is formed through the connectors. In order
-to create this aggregation you will first need to create the @code{Objects}.
-These are just normal, everyday C++ objects that we can create using the
-@code{CreateObject} template function and manage using smart pointers. The
-following code should be obvious to you by now:
-
-@verbatim
- Ptr<A> a = CreateObject<A> ();
- Ptr<B> b = CreateObject<B> ();
- Ptr<C> c = CreateObject<C> ();
-@end verbatim
-
-@cindex aggregation
-When you create an aggregation, you pick one of the @code{Objects} of the
-aggregation to think of as the container. In this case well pick @code{Object}
-A. In order to aggregate an @code{Object}, you simply call the method
-@code{AggregateObject} that your class has inherited from class @code{Object}.
-The following code will aggregate @code{Object B} and @code{Object C} onto
-the @code{Object} (and container/aggregation) @code{A}.
-
-@cindex AggregateObject
-@cindex GetObject
-@cindex Object
-@verbatim
- a->AggregateObject (b);
- a->AggregateObject (c);
-@end verbatim
-
-Thats all there is to it. Now that you have those connectors snapped
-together, you can ask each of the @code{Objects} in the aggregation for any of
-the other @code{Objects} in the aggregation. Lets look at a simple example:
-
-@verbatim
- Ptr<B> newB = a->GetObject<B> ();
-@end verbatim
-
-Now, the explanation of what this snippet does is not as simple as writing it.
-The left hand side of this assignment declares a smart pointer to the class
-@code{B} to help with memory management of the returned @code{Object} pointer.
-You should be very familiar with smart pointers at this stage of the tutorial.
-
-The right hand side illustrates how @code{GetObject} is acutally used.
-The method @code{GetObject} is templated. The assocated template parameter
-(between the brackets) specifies the @emph{class} that is being requested.
-This is important. Since it is the class type that specifies the search
-criterion, there can be only one instance of a particular class present in an
-aggregation. Looking back a little, although the parameter to
-@code{AggregateObject} appears to be a vanilla C++ object (@code{b} or @code{c}
-above), it actually represents (is an instance of) a class that has an
-associated @code{TypeId} and inherits from @code{Object}. When you call
-@code{GetObject} you specify the search criterion (using the template
-parameter) as a class name. This referenced class must also have an
-associated @code{TypeId} and must also have inherited from @code{Object}.
-
-This may be summarized by saying that @code{AggregateObject} takes an
-@emph{instance} of an object of a particular class that inherits from
-@code{Object}. GetObject looks for a @emph{class} of a particular type
-(that again inherits from @code{Object}) and possibly returns an aggregated
-object instance of that type.
-
-Now that you have those conceptual connectors snapped together, you can ask
-each of the @code{Objects} in the aggregation for any of the @code{Objects}
-in the aggregation. For example we could walk the @code{Objects} asking each
-for the next in the aggregation. First we would ask the @code{Object} pointed
-to by the smart pointer @code{a} to look for the @code{Object} @code{class B}:
-
-@verbatim
- Ptr<B> newB = a->GetObject<B> ();
-@end verbatim
-
-Next, we can ask the @code{Object} pointed to by the smart pointer @code{newB}
-to look for the @code{Object} representing @code{class C}:
-
-@verbatim
- Ptr<C> newC = newB->GetObject<C> ();
-@end verbatim
-
-@cindex Object
-Then, we can ask the @code{Object} pointed to by the smart pointer @code{newC}
-to look for the @code{Object} representing @code{class A} and complete our
-circuit of the aggregation:
-
-@verbatim
- Ptr<A> newA = newC->GetObject<A> ();
-@end verbatim
-
-@cindex GetObject
-@code{GetObject} has some important properties that we need to go over.
-Technically, @code{GetObject} is a @emph{symmetric}, @emph{reflexive} and
-@emph{transitive} operation with respect to the set of aggregated
-@code{Objects}.
-
-@subsubsection Symmetry
-@cindex symmetry
-The symmetric nature of @code{GetObject} guarantees that if one performs a
-@code{GetObject} on a given @code{Object} for the class of that same
-@code{Object}, that @code{GetObject} must succeed. In other words, the
-fact that you accessed the aggregation via an instance of an @code{Object A}
-in the aggregation implies the reachability of that @code{Object} in the
-aggregation. This is usually written (by Microsoft) as,
-
-@center must succeed (A >> A)
-
-We can illustrate this property with the code snippet,
-
-@verbatim
- Ptr<A> symmetricA = a->GetObject<A> ();
- NS_ASSERT (symmetricA);
-@end verbatim
-
-Here we take as given an interface (smart) pointer --- named @code{a} --- on
-which we perform a @code{GetObject} looking for the class that represents that
-same @code{Object}. This call must always succeed and a smart pointer to the
-aggregated instance of that class is returned.
-
-@subsubsection Reflexivity
-@cindex reflexivity
-Calls to @code{GetObject} must also be reflexive. This means that if you
-successfully @code{GetObject} for @code{Object B} from @code{Object A}, then
-you must always be able to @code{GetObject} for @code{A} from @code{B}. This
-is usually written as,
-
-@center must succeed (A >> B, then B >> A)
-
-This property can be illustrated with the code snippet,
-
-@verbatim
- Ptr<B> b = a->GetObject<B> ();
- Ptr<A> reflexiveA = b->GetObject<A> ();
- NS_ASSERT (reflexiveA);
-@end verbatim
-
-If the first @code{GetObject} on @code{Object A} looking for @code{Object B}
-succeeds, then a @code{GetObject} on @code{Object B} looking @code{Object A}
-must succeed.
-
-@subsubsection Transitivity
-@cindex transitivity
-@code{GetObject} must also be transitive. This means that if one can
-find @code{Object B} from @code{Object A}, and @code{Object C} from
-@code{Object B}, then one must also be able to find @code{Object C} from
-@code{Object A}. This is usually written as,
-
-@center must succeed (A >> B, and B >> C, then A >> C)
-
-This property can be illustrated with the code snippet,
-
-@verbatim
- Ptr<B> b = a->GetObject<B> ();
- Ptr<C> c = b->GetObject<C> ();
- Ptr<C> transitiveC = a->GetObject<C> ();
- NS_ASSERT (transitiveC);
-@end verbatim
-
-If you can get to @code{Object B} from @code{Object A}, and you can get to
-@code{Object C} from @code{Object B}, then a @code{GetObject} on
-@code{Object A} looking for @code{Object C} must also succeed.
-
-@subsection Creating the TypeId
-@cindex TypeId
-@cindex GetTypeId
-The final piece of this puzzle is the @code{TypeId}. Recall that the
-declaration our example object above included the following code
-
-@verbatim
- static ns3::TypeId GetTypeId (void)
- {
- static ns3::TypeId tid = ns3::TypeId ("A")
- .SetParent (Object::GetTypeId ())
- .AddConstructor<A> ();
- return tid;
- }
-@end verbatim
-
-This is the bit of code that ties this all together. For those unfamiliar
-with the idioms involved, this declaration can be rather dense. First, let's
-examine the function declaration itself. The following code,
-
-@verbatim
- static ns3::TypeId GetTypeId (void) ...
-@end verbatim
-
-declares a function that will be associated with all of the instances of the
-given class. This is a function, not a method, in that it can be accessed
-without a @emph{this} pointer; but it is associated with the class in a
-namespace sense. The use of this kind of declaration allows one to write,
-
-@verbatim
- return A::GetTypeId (void);
-@end verbatim
-
-if the @code{TypeId} is needed for our @code{class A}. More generically the
-class name can be substituted in a template, as is done deep in the
-@command{ns-3} object system.
-
-From this perspective, if you leave out the middle of the function definition,
-the boundaries should make sense to you.
-
-@verbatim
- static ns3::TypeId GetTypeId (void)
- {
- return tid;
- }
-@end verbatim
-
-@cindex function-local variable
-You are obviously looking at a global function associated with your class
-that simply returns a @code{TypeId}. Now, what about the rest. The code
-
-@verbatim
- static ns3::TypeId tid = ns3::TypeId ("A")
- .SetParent (Object::GetTypeId ())
- .AddConstructor<A> ();
-@end verbatim
-
-when found inside the function declaration is called a function-local variable
-with associated initialization. It'll be easier to pick this statement apart
-piece by piece as well. The first line,
-
-@verbatim
- static ns3::TypeId tid = ...
-@end verbatim
-
-is the declaration of the function-local variable tid. This is essentially
-an initialized global variable, the scope of which has been reduced to within
-the enclosing method. You can think of this as a kind of global variable
-that can only be accessed right there where it is created. If the variable
-is initialized, this amounts to the same behavior as if a global static
-initializer was declared in a namespace of the same name as your class.
-Global static initializers are guaranteed by the C++ language definition to
-be executed before your main procedure is entered. So are function-local
-variables.
-
-The variable that is being initialized is of type @code{ns3::TypeId}, is
-named @code{A::tid} since it is inside the class declaration for
-@code{class A}, and is initialized by a call to the constructor for the class
-@code{TypeId}. The constructor for @code{TypeId} takes a @code{std::string}
-that can be used to locate the type information for your class. We usually
-privide the class name as the string.
-
-Hopefully, this much of the declaration is now clear:
-
-@verbatim
- static ns3::TypeId GetTypeId (void)
- {
- static ns3::TypeId tid = ns3::TypeId ("A")
- ...
- return tid;
- }
-@end verbatim
-
-All that is left now are the lines including @code{SetParent} and
-@code{AddConstructor}.
-
-@verbatim
- static ns3::TypeId tid = ns3::TypeId ("A")
- .SetParent (Object::GetTypeId ())
- .AddConstructor<A> ();
-@end verbatim
-
-The last bit may seem quite odd at first glance, but don't let the way the
-code is broken up over several lines throw you. If you saw something like,
-
-@verbatim
- pointer->TypeId()->SetParent()->AddConstructor();
-@end verbatim
-
-you probably wouldn't hesitate at all. Clearly, you would think, a method
-called @code{TypeId} is called using the pointer called @code{pointer} as
-shown below.
-
-@verbatim
- pointer->TypeId()
-@end verbatim
-
-The method @code{TypeId} must further return a pointer to an object that has
-a method called @code{SetParent}. Just as clearly, @code{SetParent} must
-return a pointer to an object that has a method called @code{AddConstructor}.
-The same sort of thing is happening in our code snipped, except we are using
-references instead of pointers. Perhaps if we rearrange this code to live on
-one line it will be clearer.
-
-@verbatim
- ns3::TypeId ("A").SetParent (Object::GetTypeId ()).AddConstructor<A> ();
-@end verbatim
-
-It's just a string of method calls. The remaining question is then, what do
-those three methods do.
-
-The first, @code{ns3::TypeId ("A")}, simply allocates a new type in the system
-and allows you to refer to it in the future by a string. We have mentioned
-inheritance trees often in the previous discussion. The second method,
-@code{SetParent} associates the class being defined with its parents in the
-tree. Finally, the @code{AddConstructor} method allows you to specify a
-constructor to be used when an instance of your class is created using
-@code{CreateObject}.
-
-@verbatim
- AddConstructor<A> ();
-@end verbatim
-
-You can interpret this as explaining to the @command{ns-3} object system that
-you have a constructor named @code{A::A} which takes no parameters. You are
-saying that this constructor should be used when @code{CreateObject} is called
-with no parameters.
-
-By including the structure of the inheritance tree, in @command{ns-3} we can
-use implementation inheritance to easily create new @code{Objects}. You are
-prevented from doing so in Microsoft COM, but this was almost universally
-identified as a problem.
-
-So, looking at the entire @code{GetTypeId} declaration again,
-
-@verbatim
- static ns3::TypeId GetTypeId (void)
- {
- static ns3::TypeId tid = ns3::TypeId ("A")
- .SetParent (Object::GetTypeId ())
- .AddConstructor<A> ();
- return tid;
- }
-@end verbatim
-
-it should be clear what is happening.
-
-@subsection A Very Real Example
-@cindex Node
-@cindex AggregateObject
-@cindex GetObject
-@cindex Object
-At this point you may be asking yourself what the point of all of this is,
-since you already had those pointers laying around when you created the
-objects. The typical case is that one will create and aggregate some number
-of @code{Objects} in a constructor and return only a pointer to a single
-@code{Object} as in our canonical example with @code{class Node}. In this
-case, the @code{Node} would be created and the @code{Node} constructor might
-create and call @code{AggregateObject} to aggregate the @code{Objects} for
-internetwork routing and TCP/IP. From an external point of view, these
-aggregated objects may be discovered at run-time using @code{GetObject}.
-
-Generally one tends to think of one of the @code{Objects} in the aggregation
-as being the container and other @code{Objects} being aggregated to that
-container. In the case of a Node, for example, it is quite natural to think
-of the Node as being the container which contains protocol stacks, internet
-routing, etc. So, lets start thinking about a real example by calling the
-container @code{Object Node} instead of @code{A} as we have been. The
-creation of this @code{Object} is found all over our example programs. For
-example, you will find code like the following in
-@code{samples/simple-point-to-point.cc}:
-
-@verbatim
- Ptr<Node> n = CreateObject<InternetNode> ();
-@end verbatim
-
-It may appear obvious to you now that the @code{InternetNode} class name
-provided to the template function @code{CreateObject} means that
-@code{InternetNode} is an @command{ns-3} @code{Object} and you will be able to
-call @code{GetObject} on the resulting smart pointer. Well, I'm afraid that's
-not entirely true. It's slightly more complicated.
-
-Take a look at @code{src/internet-stack/internet-stack.h} and find the class
-declaration for @code{InternetNode}.
-
-@verbatim
- class InternetNode : public Node
- {
- public:
- InternetNode();
- ...
- };
-@end verbatim
-
-@cindex GetTypeId
-@cindex TypeId
-@cindex Object
-There is no declaration of a @code{static TypeId GetTypeId (void)} in this
-class. This means that the @code{InternetNode} is really not an @code{Object}
-for which you can @code{GetObject}. It turns out that the @code{InternetNode}
-is an @emph{implementation class} of the @code{Node Object}.
-
-You may recall that there can be an implicit cast in a smart pointer
-assignment if the cast is to a visible, unambiguous base class. That is, in
-fact, what is happening here. Now, take a look at @code{src/node/node.h} and
-find the class declaration for @code{class Node}. There you will find,
-
-@verbatim
- class Node : public Object
- {
- public:
- static TypeId GetTypeId (void);
- ...
- };
-@end verbatim
-
-Class @code{InternetNode} inherits from class @code{Node} that, in turn,
-inherits from class @code{Object}. It is @code{Node} that provides a
-@code{GetTypeId} method. Therefore it is @code{Node} that is an
-@command{ns-3} @code{Object}. Note well that @code{InternetNode} is not an
-@code{Object} in the sense that one should call @code{GetObject} on an
-aggregation looking for an @code{InternetNode} class. That is, you should not
-do,
-
-@verbatim
- Ptr<InternetNode> i = node->GetObject<InternetNode> ();
-@end verbatim
-
-since there really is not InternetNode::GetTypeId. It is @code{Node} that is
-the @emph{proper} @code{Object} in this case and you should view
-@code{InternetNode} as an implementation of the @code{Node Object}. This may
-become clearer as we look a little deeper.
-
-We spoke of a protocol stack that is aggregated to a @code{Node} in our
-discussions above, what we see in the real @command{ns-3} code is that this
-is represented by the @code{Ipv4 Object}. If you look in
-@code{src/node/ipv4.h} you will find,
-
-@verbatim
- class Ipv4 : public Object
- {
- public:
- static TypeId GetTypeId (void);
- ...
- };
-@end verbatim
-
-Since class @code{Ipv4} inherits from class @code{Object} and has a
-@code{GetTypeId}, it is an @command{ns-3} @code{Object}. If you look in
-@code{src/node/ipv4.cc} you will find,
-
-@verbatim
-TypeId
-Ipv4::GetTypeId (void)
-{
- static TypeId tid = TypeId ("Ipv4")
- .SetParent<Object> ();
- return tid;
-}
-@end verbatim
-
-After all of this reading you know that this code snippet is asking the
-system to create a unique @code{TypeId} for the @code{Ipv4} class and
-declares that @code{Ipv4} inherits from class @code{Object}. This is what
-makes an @code{Ipv4} an @code{Object}.
-
-@cindex Ipv4
-It turns out that the Ipv4 class is an abstract base class (ABC). There are
-a number of pure virtual methods declared in that class. This means that
-an @code{Ipv4} object may not be instantiated. This is reflected by the fact
-that there are no constructors registered in the @code{GetTypeId} method above.
-What is instantiated in the real system is an implementation class, called
-@code{Ipv4Impl}. This class inherits from @code{Ipv4} and provides the
-required virtual methods. This is where understanding what is an
-@code{Object} and what is not can get tricky. The @code{Object} is the
-@code{Ipv4} class since that is where the @code{GetTypeId} is found. The fact
-that you see @code{GetTypeId} there tells you that the @code{Ipv4} class is
-the class for which you can @code{GetObject}.
-
-@cindex implementation class
-The class @code{Ipv4Impl} provides an implementation for the pure virtual
-methods in @code{Ipv4}. Since class @code{Ipv4} cannot be instantiated, one
-instantiates the @code{Ipv4Impl} class to create an @code{Ipv4} @code{Object}.
-You will use the @code{CreateObject} template function to create an object that
-implements the methods of an @code{Object}. You can probably see how this
-gets even more tricky in conversation.
-
-Once the @code{Ipv4Impl} object is instantiated, the resulting pointer is
-immediately cast to an @code{Ipv4} pointer. Clients will then use the
-methods specified in the @code{Ipv4} class to access the @code{Ipv4 Object}
-methods which are, in turn, implemented in the @code{Ipv4Impl} object.
-
-If you now look in the file, @code{src/internet-stack/internet-stack.cc} you
-will see the following code in @code{InternetNode::Construct} that creates the
-@code{Ipv4} Interface and aggregates it.
-
-@verbatim
- Ptr<Ipv4Impl> ipv4Impl = CreateObject<Ipv4Impl> (ipv4);
- ...
- Object::AggregateObject (ipv4Impl);
-@end verbatim
-
-Note that the parameter @code{ipv4} passed to the @code{CreateObject} template
-function is actually a pointer to an @code{Ipv4L3Protocol} which you can
-ignore at this point --- it doesn't really have anything to do with the
-@code{Ipv4} Interface.
-
-This is exactly the same thing that is happening in the case of the
-@code{InternetNode}.
-
-@verbatim
- Ptr<Node> n = CreateObject<InternetNode> ();
-@end verbatim
-
-@cindex implementation object
-@code{CreateObject} is being called to create an implementation object,
-in this case @code{InternetNode}, which implements the methods of the
-@code{Node Object}. It is the resulting @code{Node Object} which you would
-use as the container and it is the @code{Node} class that you would use as
-the template parameter when calling @code{GetObject}. In the same way, you
-would @emph{not} want to do,
-
-@verbatim
- Ptr<Ipv4> ipv4 = node->GetObject<Ipv4Impl> ();
-@end verbatim
-
-Rather you should understand that the @emph{proper} @code{Object} is the
-@code{Ipv4} not the @code{Ipv4Impl} and do the following,
-
-@verbatim
- Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
-@end verbatim
-
-@cindex CreateObject
-This does illustrate that the fact that whether an object created by
-@code{CreateObject} is or is not an @code{Object} in the usual sense can be
-quite well hidden if you are casually looking at the object creation code.
-The designers of the system had long and involved discussions on this issue
-and in the end decided that mnemonic aids such as Hungarian notation were a
-stylistic thing and you should just refer to the system documentation to
-determine what objects are @command{ns-3} @code{Objects} and what the APIs
-of those @code{Objects} actually are (RTFM --- as in Read the Fine Manual,
-of course).
-
-@cindex AggregateObject
-@cindex Object
-In the case of @code{Ipv4Impl}, you know that the class inherits somehow
-from @code{Object} since there is a call to @code{AggregateObject} that
-refers to an instance of an @code{Ipv4Impl}. You will have to go to
-the header file @code{src/internet-stack/ipv4-impl.h} and find that
-@code{Ipv4Impl} inherits from class @code{Ipv4}. You will then have go to
-the file @code{src/node/ipv4.h} and see that it inherits from @code{Object} and
-defines a @code{GetTypeId}. Thus the @code{Object} for which you can
-@code{GetObject} is really the @code{Ipv4 Object}.
-
-Returning to some real @command{ns-3} example code, lets take a look at
-@code{examples/simple-point-to-point.cc}. You will find the following
-code in this file:
-
-@verbatim
- Ptr<Node> n0 = CreateObject<InternetNode> ();
- ...
- Ptr<Ipv4> ipv4;
- ipv4 = n0->GetObject<Ipv4> ();
- ipv4->SetDefaultRoute (Ipv4Address (``10.1.1.2''), 1);
-@end verbatim
-
-@cindex InternetNode
-@cindex Node
-@cindex Object
-@cindex GetObject
-The first line creates an @code{InternetNode} implementation object and casts
-the resulting smart pointer to a @code{Node} as we have discussed extensively.
-The next line shown declares a smart pointer to an @code{Ipv4 Object}. We
-then do a @code{GetObject} on the @code{Node} looking for the
-@code{Ipv4 Object}. You know since you've read every line of this tutorial
-in detail exactly how that @code{Ipv4 Object} got into every @code{Node}. You
-know that the @code{GetObject} will return a smart pointer to its aggregated
-@code{Ipv4} Interface. Once we have the @code{Ipv4} smart pointer, we simply
-use it as if it were any other C++ object. The last line shows this by
-setting the default route for the node.
-
-@section Caveats
-There are a few things that you should remember but which may not be
-immediately obvious.
-
-@subsection Ns-3 Objects are Associated with Classes not C++ objects
-@cindex Object
-@cindex GetObject
-@cindex iterate
-@cindex aggregation
-@cindex GetNDevices
-Okay, you can see some of the problems with the terminology popping up again.
-We are reminding you that when you do a GetObject you are providing the key
-to the lookup by giving a class name and not anything that is unique to a
-C++ object.
-
-You cannot add more than one @code{Object} of a given type (class name) to an
-aggregation. If you need to contain a number of @code{Objects} of the same
-type in the same aggregation, you will need to provide a separate container
-over which you can iterate. For example, the @code{Node} class provides
-methods,
-
-@verbatim
- uint32_t GetNDevices (void) const;
- Ptr<NetDevice> GetDevice (uint32_t index) const;
-@end verbatim
-
-that are used iterate over the multiple @code{NetDevice} @code{Objects}
-associated with it.
-
-@emph{Remember: Object types do not identify objects.}
-
-@subsection Dont use GetObject to Check Your Own Type.
-@cindex GetObject
-It is tempting to use @code{GetObject} as a form of runtime type
-information. Dont do it. You have no control over what @emph{other}
-object may be added to your aggregation. Someone else may have
-appropriated (reimplemented) your type and aggregated themselves onto the
-aggregation.
-
-Consider a socket factory implementation. Sockets can be either UDP sockets
-or TCP sockets. A socket factory will have a generic @code{SocketFactory}
-Object and either a UDP specific interface for setting UDP parameters or a
-similar TCP-specific interface.
-
-Consider what might happen if you declared your socket factory as a partially
-abstract base class, and then provided separate implementations for UDP and
-TCP specific methods of this factory in separate concrete classes. Now
-consider what might happen if you used @code{GetObject} in your base class
-to determine if you were a UDP or a TCP factory.
-
-If a factory, say the UDP version, were not aggregated to any other
-@code{Object}, the base class could @code{GetObject} on itself for the
-UDP-specific class name. If the @code{GetObject} succeeded, it could then
-infer that it was a UDP implementation and would then do any UDP-specific
-tasks it could. [Experienced C++ folks are cringing about how
-horrible this design is, but bear with me --- its a simple illustration of
-a specific and perhaps not-too-obvious problem.]
-
-If another factory, say the TCP version, were not aggregated to any other
-Interface, the base class could @code{GetObject} on itself for the UDP-specific
-interface. If this failed, it could then infer that it had a TCP
-implementation and would then do any TCP-specific tasks it could.
-
-Now, what happens when these two working objects are aggregated together by
-some innocent end-user. Since the @code{Objects} are conceptually snapped
-together, the TCP implementation would suddenly begin finding the UDP
-Interface from the other class factory and think it was the UPD implementation.
-
-@emph{Objects should not be used as run-time type information.}
-
-@section Connecting the Dots
-@cindex Object
-@cindex GetObject
-@cindex AggregateObject
-@cindex GetTypeId
-@cindex API
-This may all sound very complicated to you if this is your first exposure to
-these concepts. It may be annoying if I tell you that its really not as hard
-as it sounds. Rest assured that if you take some time, look at and understand
-the examples and write a little test code it will all come together for you.
-Grep around the system for @code{AggregateObject} and @code{GetObject} and
-take a look at how we have used them. This will also give you a good idea of
-what our core @code{Objects} and associated APIs are. If you grep for
-@code{GetTypeId} you will find most, if not all of the @code{Object} API
-interface declarations in the system. The more you see this idiom in
-use, the more comfortable you will be with the idea and the more you will see
-how this addresses the weak base class, swiss army knife base class, and
-fragile base class problems I explained at the beginning.
-
-As I alluded to earlier, the developers had long discussions regarding how to
-make navigating the @code{Object} environment easier. The primary issue was
-how we could make it easier to convey to you, the model writer, that an object
-was an @code{Object}. We originally used similar terminology as Microsoft
-COM and used QueryInterface instead of @code{GetObject}. One suggestion was
-to adopt the convention that classes that implemented Interfaces must begin
-with the letter I. Microsoft does this, as exemplified by the class IUnknown.
-We also toyed with the idea of beginning our header files with ``i-'' as in
-``i-ipv4.h.'' We considered forcing some structure on Interfaces with a pure
-virtual class specification, the names of which begin with an I; and
-corresponding implementations, the names of which begin with a C. This all
-got out of hand fairly quickly.
-
-In the end we decided that we were really discussing issues of programming
-style, and we really could not come up with a strong reason to impose any
-particular solution. No matter what direction we took, we ended up with some
-form of extra confusion or extra complexity somewhere in the system. The
-resulting system is extremely flexible and easy to use. It is, unfortunately,
-sometimes hard to document and talk about.
-
-@cindex Feynman
-If it helps you to think in terms of Microsoft COM and Interfaces, by all means
-do so, just be aware that even though @command{ns-3} @code{Objects} descend
-from COM in some sense, there are subtle differences that may get you lost or
-into trouble. So to paraphrase Feynman one more time,
-
-@quotation
-``@command{Ns-3} @code{Objects} do not behave like COM Components, or Java
-Beans, or CORBA objects, or clouds or weights on springs, or like anything
-that you have ever seen --- they are @command{ns-3} components.''
-@end quotation
-
-Just get very familiar with the @command{ns-3} object model. It is the heart
-of the system and if you do not understand it you will not understand how to
-write an @command{ns-3} model properly.
-
-@c ========================================================================
-@c Doxygen
-@c ========================================================================
-
-@node The-Doxygen-Documentation-System
-@chapter The Doxygen Documentation System
-
-@node How-To-Change-Things
-@chapter How to Change Things
-
-@node How-To-Set-Default-Values
-@chapter How to Set Default Values
-
-@node How-To-Write-A-New-Application
-@chapter How to Write a New Application
-
--- a/doc/tutorial/in-process/output.texi Sun Jan 02 22:57:04 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,462 +0,0 @@
-
-@c ========================================================================
-@c Simulation Output
-@c ========================================================================
-
-@node Simulation Output
-@chapter Simulation Output
-
-At this point, you should be able to execute any of the built-in
-programs distributed with @command{ns-3}. Next, we will look at
-how to generate and tailor the simulation output, before turning
-to how to modify simulation scripts to do different things.
-
-@node Tracing Basics
-@section Tracing Basics
-
-The whole point of simulation is to generate output for further
-study, and the @command{ns-3} tracing system is a primary
-mechanism for this.
-Since @command{ns-3} is a C++ program, standard facilities for
-generating output from C++ programs apply:
-
-@verbatim
-#include <iostream>
-...
-int main ()
-{
- ...
- std::cout << "The value of x is " << x << std::endl;
- ...
-}
-@end verbatim
-
-The goal of the @command{ns-3} tracing system is to
-provide a structured way to configure the simulator to output results
-in standard or modifiable formats.
-@itemize @bullet
-@item For basic tasks, the tracing system should allow the user to
-generate standard tracing for popular tracing sources, and to customize
-which objects generate the tracing.
-@item Intermediate users will be able to extend the tracing system to
-modify the output format generated, or to insert new tracing sources,
-without modifying the core of the simulator.
-@item Advanced users can modify the simulator core to add new
-tracing sources and sinks.
-@end itemize
-
-The @command{ns-3} tracing system is fundamentally built on the
-concept of separating tracing sources from sinks.
-@enumerate
-@item Trace sources (e.g., provide access to every packet received)
-@item Trace sinks (e.g., print out the packet)
-@item A mechanism to tie together sources and sinks
-@end enumerate
-The rationale for this division is to allow users to attach new
-types of sinks to existing tracing sources, without requiring
-users to edit and recompile the core of the simulator.
-Thus, in the example above, a user could write a new tracing sink
-and attach it to an existing tracing source. What remains to
-be defined is a way for users to find these hooks (tracing sources)
-and attach sinks to them. A new tracing namespace is defined for
-this purpose.
-
-We will first walk through how some pre-defined sources and sinks
-are provided and may be customized with little user effort. We
-return later in this chapter to advanced tracing configuration including
-extending the tracing namespace and creating new tracing sources.
-
-@subsection ASCII tracing
-@cindex ASCII
-For Internet nodes, the ASCII trace wrapper is a wrapper around
-the @command{ns-3} low-level
-tracing system that lets you get access to underlying trace events easily.
-The output of a trace of a simulation run is an ASCII file --- thus the name.
-In the spirit of keeping things simple, you won't be able to control or
-configure the output at this stage.
-
-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. As usual, we need to include the definitions
-related to using ASCII tracing (don't edit any files quite yet):
-
-@verbatim
- #include "ns3/ascii-trace.h"
-@end verbatim
-
-We then need to add the code to the script to actually enable the ASCII tracing
-code. The following code must be inserted before the call to
-@code{Simulator::Run ();}:
-
-@verbatim
- AsciiTrace asciitrace ("tutorial.tr");
- asciitrace.TraceAllQueues ();
- asciitrace.TraceAllNetDeviceRx ();
-@end verbatim
-
-The first line declares an object of type @code{AsciiTrace} named
-@code{asciitrace} and passes a string parameter to its constructor. This
-parameter is a file name to which all of the trace information will be written.
-The second line, @code{asciitrace.TraceAllQueues ();} asks the trace object to
-arrange that all queue operations (enqueue, dequeue, drop) on the queues
-in all of the nodes of the system be traced. On the receive side,
-@code{asciitrace.TraceAlllNetDeviceRx ()} traces packets received by
-a NetDevice. For those familiar with @command{ns-2}, these are equivalent
-to the popular trace points that log "+", "-", "d", and "r" events.
-
-Try running the following program from the command line:
-@verbatim
- ./waf --run tutorial-csma-echo-ascii-trace
-@end verbatim
-
-@cindex tutorial.tr
-Just as you have seen previously, you will see some messages from @emph{Waf}
-and then the ``Compilation finished successfully'' message. The
-next message, @code{UDP Echo Simulation} is from the running program. When
-it ran, the program will have created a file named @code{tutorial.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. So,
-change into the top level directory and take a look at the file
-@code{tutorial.tr} in your favorite editor.
-
-@subsubsection Parsing Ascii Traces
-@cindex parsing ascii traces
-
-This section parses in detail the structure of the ascii tracing
-output. If you find this output format self explanatory (it
-resembles tcpdump output), you may skip to the next
-section on pcap tracing.
-
-@cindex trace event
-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.
-Each line in the file corresponds to a @emph{trace event}. A trace event
-happens whenever specific conditions happen in the simulation. 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:
-
-@cindex enqueue
-@cindex dequeue
-@cindex drop
-@itemize @bullet
-@item @code{+}: An enqueue operation occurred on the device queue;
-@item @code{-}: A dequeue operation occurred on the device queue;
-@item @code{d}: A packet was dropped, typically because the queue was full.
-@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:
-
-@verbatim
- 00 +
- 01 2
- 02 nodeid=0
- 03 device=0
- 04 queue-enqueue
- 05 pkt-uid=9
- 06 ETHERNET
- 07 length/type=0x806,
- 08 source=08:00:2e:00:00:00,
- 09 destination=ff:ff:ff:ff:ff:ff
- 10 ARP(request
- 11 source mac: 08:00:2e:00:00:00
- 12 source ipv4: 10.1.1.1
- 13 dest ipv4: 10.1.1.2)
- 14 ETHERNET fcs=0
-@end verbatim
-
-@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 see
-confirmation that this is, indeed, happening.
-
-@cindex node number
-@cindex net device number
-@cindex smart pointer
-The next lines of the example listing (references 02 and 03) tell us that
-this trace event originated in a given node and net device. Each time a node
-is created it is given an identifying number that monotonically increases from
-zero. Therefore, @code{nodeid=0} means that the node in which the given trace
-event originated is the first node we created. In the case of our script,
-this first node is is the node pointed to by the smart pointer @code{n0}. Not
-too surprisingly, this is also the node to which we attached the
-@code{UdpEchoClient}. The device number is local to each node, and so the
-device given by @code{device=0} is the first net device that we added to the
-node in question. In our simulation, this corresponds to the
-@code{CsmaNetDevice} we added to node zero (@code{n0}).
-
-@cindex uid
-@cindex unique ID
-@cindex packet
-The next line (reference 04) is a more readable form of the operation code
-seen in the first line --- i.e., the character @code{+} means
-@code{queue-enqueue}. Reference number 05 indicates that the @emph{unique id}
-of the packet being enqueued is @code{9}. The fact that the first packet we
-see has a unique ID of 9 should indicates to you that other things have
-happened in the protocol stack before we got to this point. This will become
-clear momentarily.
-
-@cindex Ethernet
-@cindex MAC address
-Reference items 06 and 14 indicate that this is an Ethernet packet with
-a zero (not computed) checksum (note the indentation to make parsing this
-trace event a little easier). Reference 08 and 09 are the source and
-destination addresses of this packet. The packet is from the MAC address we
-assigned to the node zero net device in the script, and is destined for the
-broadcast address --- this is a broadcast packet.
-
-@cindex Address Resolution Protocol
-@cindex ARP
-@cindex ARP|request
-Reference items 10 through 13 make clear what is happening. This is an ARP
-(Address Resolution Protocol) request for the MAC address of the node on
-which the @code{UdpEchoServer} resides. The protocol stack can't send a UDP
-packet to be echoed until it knows (resolves) the MAC address; and this trace
-event corresponds to an ARP request being queued for transmission to the local
-network. The next line in the trace file (partially expanded),
-
-@verbatim
- 00 -
- 01 2
- 02 nodeid=0
- 03 device=0
- 04 queue-dequeue
- 05 pkt-uid=9
- ...
-@end verbatim
-
-shows the (same) ARP request packet being dequeued from the device queue by
-the net device and (implicitly) being sent down the channel to the broadcast
-MAC address. We are not tracing net device reception events so we don't
-actually see all of the net devices receiving the broadcast packet. We do,
-however see the following in the third line of the trace file:
-
-@verbatim
- 00 +
- 01 2.00207
- 02 nodeid=1
- 03 device=0
- 04 queue-enqueue
- 05 pkt-uid=10
- 06 ETHERNET
- 07 length/type=0x806,
- 08 source=08:00:2e:00:00:01,
- 09 destination=08:00:2e:00:00:00,
- 10 ARP(reply
- 11 source mac: 08:00:2e:00:00:01
- 12 source ipv4: 10.1.1.2
- 13 dest mac: 08:00:2e:00:00:00
- 14 dest ipv4: 10.1.1.1)
- 15 ETHERNET fcs=0
-@end verbatim
-
-@cindex simulation time
-@cindex ARP|response
-Notice that this is a queue-enqueue operation (references 00 and 04) happening
-on node one (reference 02) at simulation time 2.00207 seconds (reference 01).
-Looking at the packet payload (references 10-14) we see that this is an ARP
-reply to the request sent by node one. Note that the simulation time
-(reference 01) is now 2.00207 seconds. This is direct result of the data rate
-(5 mb/s) and latency (2 ms) parameters that we passed to the
-@code{CsmaChannel} when we created it. Clearly the ARP request packet was
-sent over the channel and received approximately 2 ms later by node one. A
-corresponding ARP response packet was created and enqueued on node one's net
-device. It is this enqueue trace event that has being logged.
-
-@cindex queue
-@cindex queue|transmit
-@cindex echo
-Given the current state of affairs, the next thing you may expect to see is
-this ARP request being received by node zero, but remember we are only looking
-at trace events on the device @emph{transmit} queue. The reception of the ARP
-response by node zero will not directly trigger any trace event in this case,
-but it will enable the protocol stack to continue what it was originally doing
-(trying to send an echo packet). Thus, the next line we see in the trace file
-(@code{tutorial.tr}) is the first UDP echo packet being sent to the net device.
-
-@verbatim
- 00 +
- 01 2.00415
- 02 nodeid=0
- 03 device=0
- 04 queue-enqueue
- 05 pkt-uid=7
- 06 ETHERNET
- 07 length/type=0x800,
- 08 source=08:00:2e:00:00:00,
- 09 destination=08:00:2e:00:00:01
- 10 IPV4(
- 11 tos 0x0
- 12 ttl 64
- 13 id 0
- 14 offset 0
- 15 flags [none]
- 16 length: 1052) 10.1.1.1 > 10.1.1.2
- 17 UDP(length: 1032)
- 18 49153 > 7
- 19 DATA (length 1024)
- 20 ETHERNET fcs=0
-@end verbatim
-
-@cindex simulation time
-@cindex echo
-@cindex ARP
-@cindex ARP|request
-@cindex ARP|response
-@cindex IP
-@cindex Ipv4
-I won't go into too much detail about this packet, but I will point out a
-few key items in the trace. First, the packet was enqueued at simulation time
-of 2.00415 seconds. This time reflects the fact that the echo client
-application started at 2. seconds and there were two ARP packets transmitted
-across the network (two milliseconds + data transmission time each way). The
-packet unique identifier (reference 05) is 7. Notice that this is a lower
-number than the ARP request packet, which had a unique ID of 9. This tells
-us that the UDP packet was actually created before the ARP request packet ---
-which makes perfect sense since it was the attempt to send packet 7 that
-triggered sending the ARP request packet 9. Note that this an Ethernet
-packet (reference 06) like all other packets in this simulation, however this
-particular packet carries an IPV4 payload and therefore has an IP version 4
-header (indicated by references 10-16). This Ipv4 in turn contains a UDP
-header (references 17, 18) and finally 1024 bytes of data (reference 20).
-Clearly, this is the UDP echo packet emitted by the
-@code{UdpEchoClient Application}.
-
-The next trace event is an ARP request from node one. We can infer that node
-one has received the UDP echo packet and the @code{UdpEchoServer Application}
-on that node has turned the packet around. Just as node zero needed to ARP
-for the MAC address of node one, now node one must ARP for the MAC address of
-node zero. We see the ARP request enqueued on the transmit queue of node one;
-then we see the ARP request dequeued from the transmit queue of node one (and
-implicitly transmitted to node zero). Then we see an ARP response enqueued
-on the transmit queue of node zero; and finally the ARP response dequeued (and
-implicitly transmitted back to node one).
-
-This exchange is summarized in the following trace event excerpts,
-
-@verbatim
- + 2.00786 nodeid=1 ... ARP(request ...
- - 2.00786 nodeid=1 ... ARP(request ...
- + 2.00994 nodeid=0 ... ARP(reply ...
- - 2.00994 nodeid=0 ... ARP(reply ...
-@end verbatim
-
-The final two trace events in the @code{tutorial.tr} file correspond to the
-echoed packet being enqueued for transmission on the net device for node one,
-and that packet being dequeued (and implicitly transmitted back to node zero).
-
-@cindex AsciiTrace!TraceAllNetDeviceRx
-@cindex ARP!request
-If you look at the trace file (@code{tutorial.tr}) you will also see some
-entries with an @code{r} event, indicating a
-@emph{receive} trace event. Recall that the first packet sent on the network
-was a broadcast ARP request. We should then see all four nodes receive a
-copy of this request. This is the case, as the first four receive trace
-events are,
-
-@verbatim
- r 2.00207 nodeid=0 device=0 dev-rx pkt-uid=9 ARP(request ...
- r 2.00207 nodeid=1 device=0 dev-rx pkt-uid=9 ARP(request ...
- r 2.00207 nodeid=2 device=0 dev-rx pkt-uid=9 ARP(request ...
- r 2.00207 nodeid=3 device=0 dev-rx pkt-uid=9 ARP(request ...
-@end verbatim
-
-@cindex unique ID
-You can see that a copy of the broadcast packet with unique ID 9 was received
-by the net devices on nodes 0, 1, 2 and 3. We leave it up to you to parse the
-rest of the trace file and understand the remaining reception events.
-
-@subsection PCAP Trace Wrapper
-@cindex pcap
-@cindex Wireshark
-The @command{ns-3} @emph{pcap trace wrapper} is used to create trace files in
-@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, including X, Y, and Z. We encourage users to exploit the
-many tools available for analyzing pcap traces; below, we show how
-tcpdump and Wireshark can be used..
-
-@cindex tutorial-csma-echo-ascii-trace.cc
-@cindex tutorial-csma-echo-pcap-trace.cc
-The code used to enable pcap tracing is similar to that for ASCII tracing.
-We have provided another file, @code{tutorial-csma-echo-pcap-trace.cc} that
-uses the pcap trace wrapper. We have added the code to include the pcap
-trace wrapper definitions:
-
-@verbatim
- #include "ns3/pcap-trace.h"
-@end verbatim
-
-And then added the following code below the AsciiTrace methods:
-
-@cindex PcapTrace
-@cindex PcapTrace!TraceAllIp
-@verbatim
- PcapTrace pcaptrace ("tutorial.pcap");
- pcaptrace.TraceAllIp ();
-@end verbatim
-
-The first line of the code immediately above declares an object of type
-@code{PcapTrace} named @code{pcaptrace} and passes a string parameter to its
-constructor. This object is used to hide the details of the actual tracing
-subsystem. The parameter is a base file name from which the actual trace file
-names will be built. The second line of code tells the @code{PcamTrace}
-object to trace all IP activity in all of the nodes present in the simulation.
-
-@cindex interface index
-Trace files are not created until trace activity is detected. Each file name
-is composed of the base file name, followed by a @code{'-'}, a node id followed
-by a @code{'-}', and an IP interface index. You will soon see a file named
-@code{tutorial.pcap-0-1}, for example. This will be the trace file generated
-as events are detected on node zero, interface index one. N.B. Interface
-indices are different that net device indices --- interface index zero
-corresponds to the loopback interface and interface index one corresponds to
-the first net device you added to a node.
-
-You may run the new program just like all of the others so far:
-
-@cindex Waf
-@verbatim
- ./waf --run tutorial-csma-echo-pcap-trace
-@end verbatim
-
-If you look at the top level directory of your distribution, you should now
-see three log files: @code{tutorial.tr} is the ASCII trace file we have
-previously examined. @code{tutorial.pcap-0-1} and @code{tutorial.pcap-1-1}
-are the new pcap files we just generated. There will not be files
-corresponding to nodes two and three since we have not sent any IP packets to
-those nodes.
-
-@subsubsection Reading output with tcpdump
-@cindex tcpdump
-
-@subsubsection Reading output with Wireshark
-@cindex Wireshark
-If you are unfamiliar with Wireshark, there is a web site available from which
-you can download programs and documentation: @uref{http://www.wireshark.org/}.
-
-If you have Wireshark available, you can open each of the trace files and
-display the contents as if you had captured the packets using a
-@emph{packet sniffer}. Note that only IP packets are traced using this
-wrapper, so you will not see the ARP exchanges that were logged when using
-the ASCII trace wrapper. You are encouraged to take a look at the contents
-of these pcap files using your favorite pcap software (or Wireshark).
-
-@node Advanced Tracing
-@section Advanced Tracing
-
--- a/doc/tutorial/in-process/statistics.texi Sun Jan 02 22:57:04 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-@node Statistics
-@chapter Statistics
-@anchor{chap:Statistics}
-
-ns-3 does not presently have support for statistics (automatically generated
-statistical output). This is planned
-for development later in 2008. If you are interested in contributing,
-please see @uref{http://www.nsnam.org/wiki/index.php/Suggested_Projects,,our suggested projects page} or contact the ns-developers
-list.
--- a/doc/tutorial/in-process/troubleshoot.texi Sun Jan 02 22:57:04 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-@node Troubleshooting
-@chapter Troubleshooting
-
-This chapter posts some information about possibly common errors in building
-or running ns-3 programs.
-
-Please note that the wiki (@uref{http://www.nsnam.org/wiki/index.php/Troubleshooting}) may have contributed items.
-
-@node Build errors
-@section Build errors
-
-@node Run-time errors
-@section Run-time errors
-
-Sometimes, errors can occur with a program after a successful build. These
-are run-time errors, and can commonly occur when memory is corrupted or
-pointer values are unexpectedly null.
-
-Here is an example of what might occur:
-
-@verbatim
-ns-old:~/ns-3-nsc$ ./waf --run tcp-point-to-point
-Entering directory `/home/tomh/ns-3-nsc/build'
-Compilation finished successfully
-Command ['/home/tomh/ns-3-nsc/build/debug/examples/tcp-point-to-point'] exited with code -11
-@end verbatim
-
-The error message says that the program terminated unsuccessfully, but it is
-not clear from this information what might be wrong. To examine more
-closely, try running it under the @uref{http://sources.redhat.com/gdb/,,gdb debugger}:
-
-@verbatim
-ns-old:~/ns-3-nsc$ ./waf --run tcp-point-to-point --command-template="gdb %s"
-Entering directory `/home/tomh/ns-3-nsc/build'
-Compilation finished successfully
-GNU gdb Red Hat Linux (6.3.0.0-1.134.fc5rh)
-Copyright 2004 Free Software Foundation, Inc.
-GDB is free software, covered by the GNU General Public License, and you are
-welcome to change it and/or distribute copies of it under certain conditions.
-Type "show copying" to see the conditions.
-There is absolutely no warranty for GDB. Type "show warranty" for details.
-This GDB was configured as "i386-redhat-linux-gnu"...Using host libthread_db library "/lib/libthread_db.so.1".
-
-(gdb) run
-Starting program: /home/tomh/ns-3-nsc/build/debug/examples/tcp-point-to-point
-Reading symbols from shared object read from target memory...done.
-Loaded system supplied DSO at 0xf5c000
-
-Program received signal SIGSEGV, Segmentation fault.
-0x0804aa12 in main (argc=1, argv=0xbfdfefa4)
- at ../examples/tcp-point-to-point.cc:136
-136 Ptr<Socket> localSocket = socketFactory->CreateSocket ();
-(gdb) p localSocket
-$1 = {m_ptr = 0x3c5d65}
-(gdb) p socketFactory
-$2 = {m_ptr = 0x0}
-(gdb) quit
-The program is running. Exit anyway? (y or n) y
-@end verbatim
-
-Note first the way the program was invoked-- pass the command to run as
-an argument to the command template "gdb %s".
-
-This tells us that there was an attempt to dereference a null pointer
-socketFactory.
-
-Let's look around line 136 of tcp-point-to-point, as gdb suggests:
-@verbatim
- Ptr<SocketFactory> socketFactory = n2->GetObject<SocketFactory> (Tcp::iid);
- Ptr<Socket> localSocket = socketFactory->CreateSocket ();
- localSocket->Bind ();
-@end verbatim
-
-The culprit here is that the return value of GetObject is not being
-checked and may be null.
-
-Sometimes you may need to use the @uref{http://valgrind.org,,valgrind memory
-checker} for more subtle errors. Again, you invoke the use of valgrind
-similarly:
-@verbatim
-ns-old:~/ns-3-nsc$ ./waf --run tcp-point-to-point --command-template="valgrind %s"
-@end verbatim
--- a/doc/tutorial/in-process/tutorial.css Sun Jan 02 22:57:04 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,156 +0,0 @@
-body {
- font-family: "Trebuchet MS", "Bitstream Vera Sans", verdana, lucida, arial, helvetica, sans-serif;
- background: white;
- color: black;
- font-size: 11pt;
-}
-
-h1, h2, h3, h4, h5, h6 {
-# color: #990000;
- color: #009999;
-}
-
-pre {
- font-size: 10pt;
- background: #e0e0e0;
- color: black;
-}
-
-a:link, a:visited {
- font-weight: normal;
- text-decoration: none;
- color: #0047b9;
-}
-
-a:hover {
- font-weight: normal;
- text-decoration: underline;
- color: #0047b9;
-}
-
-img {
- border: 0px;
-}
-
-#main th {
- font-size: 12pt;
- background: #b0b0b0;
-}
-
-.odd {
- font-size: 12pt;
- background: white;
-}
-
-.even {
- font-size: 12pt;
- background: #e0e0e0;
-}
-
-.answer {
- font-size: large;
- font-weight: bold;
-}
-
-.answer p {
- font-size: 12pt;
- font-weight: normal;
-}
-
-.answer ul {
- font-size: 12pt;
- font-weight: normal;
-}
-
-#container {
- position: absolute;
- width: 100%;
- height: 100%;
- top: 0px;
-}
-
-#feedback {
- color: #b0b0b0;
- font-size: 9pt;
- font-style: italic;
-}
-
-#header {
- position: absolute;
- margin: 0px;
- top: 10px;
- height:96px;
- left: 175px;
- right: 10em;
- bottom: auto;
- background: white;
- clear: both;
-}
-
-#middle {
- position: absolute;
- left: 0;
- height: auto;
- width: 100%;
-}
-
-#main {
- position: absolute;
- top: 50px;
- left: 175px;
- right: 100px;
- background: white;
- padding: 0em 0em 0em 0em;
-}
-
-#navbar {
- position: absolute;
- top: 75px;
- left: 0em;
- width: 146px;
- padding: 0px;
- margin: 0px;
- font-size: 10pt;
-}
-
-#navbar a:link, #navbar a:visited {
- font-weight: normal;
- text-decoration: none;
- color: #0047b9;
-}
-
-#navbar a:hover {
- font-weight: normal;
- text-decoration: underline;
- color: #0047b9;
-}
-
-#navbar dl {
- width: 146px;
- padding: 0;
- margin: 0 0 10px 0px;
- background: #99ffff url(images/box_bottom2.gif) no-repeat bottom left;
-}
-
-#navbar dt {
- padding: 6px 10px;
- font-size: 100%;
- font-weight: bold;
- background: #009999;
- margin: 0px;
- border-bottom: 1px solid #fff;
- color: white;
- background: #009999 url(images/box_top2.gif) no-repeat top left;
-}
-
-#navbar dd {
- font-size: 100%;
- margin: 0 0 0 0px;
- padding: 6px 10px;
- color: #0047b9;
-}
-
-dd#selected {
- background: #99ffff url(images/arrow.gif) no-repeat;
- background-position: 4px 10px;
-}
--- a/doc/tutorial/in-process/tutorial.texi Sun Jan 02 22:57:04 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,105 +0,0 @@
-\input texinfo @c -*-texinfo-*-
-@c %**start of header
-@setfilename ns-3.info
-@settitle ns-3 tutorial
-@c @setchapternewpage odd
-@c %**end of header
-
-@ifinfo
-Primary documentation for the @command{ns-3} project is available in
-three forms:
-@itemize @bullet
-@item @uref{http://www.nsnam.org/doxygen/index.html,,ns-3 Doxygen/Manual}: Documentation of the public APIs of the simulator
-@item Tutorial (this document)
-@item @uref{http://www.nsnam.org/wiki/index.php,, ns-3 wiki}
-@end itemize
-
-This document is written in GNU Texinfo and is to be maintained in
-revision control on the @command{ns-3} code server. Both PDF and HTML versions
-should be available on the server. Changes to
-the document should be discussed on the ns-developers@@isi.edu mailing list.
-@end ifinfo
-
-@copying
-
-This is an @command{ns-3} tutorial.
-Primary documentation for the @command{ns-3} project is available in
-three forms:
-@itemize @bullet
-@item @uref{http://www.nsnam.org/doxygen/index.html,,ns-3 Doxygen/Manual}: Documentation of the public APIs of the simulator
-@item Tutorial (this document)
-@item @uref{http://www.nsnam.org/wiki/index.php,, ns-3 wiki}
-@end itemize
-
-This document is written in GNU Texinfo and is to be maintained in
-revision control on the @command{ns-3} code server. Both PDF and HTML
-versions should be available on the server. Changes to
-the document should be discussed on the ns-developers@@isi.edu mailing list.
-
-This software is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This software 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, see @uref{http://www.gnu.org/licenses/}.
-@end copying
-
-@titlepage
-@title ns-3 Tutorial
-@author ns-3 project
-@author feedback: ns-developers@@isi.edu
-@today{}
-
-@c @page
-@vskip 0pt plus 1filll
-@insertcopying
-@end titlepage
-
-@c So the toc is printed at the start.
-@anchor{Full Table of Contents}
-@contents
-
-@ifnottex
-@node Top, Overview, Full Table of Contents
-@top ns-3 Tutorial (html version)
-
-For a pdf version of this tutorial,
-see @uref{http://www.nsnam.org/docs/tutorial.pdf}.
-
-@insertcopying
-@end ifnottex
-
-@menu
-* Tutorial Goals::
-Part 1: Getting Started with ns-3
-* Overview::
-* Browsing::
-* Resources::
-* Downloading and Compiling::
-* Some-Prerequisites::
-Part 2: Reading ns-3 Programs
-* A-First-ns-3-Script::
-Part 3: Reconfiguring Existing ns-3 Scripts
-* Logging::
-* ns-3 Attributes::
-* Tracing::
-* Statistics::
-Part 4: Creating New or Revised Topologies
-* Helper Functions::
-@end menu
-
-@include introduction.texi
-@include log.texi
-@include attributes.texi
-@include statistics.texi
-@include helpers.texi
-
-@printindex cp
-
-@bye
--- a/doc/tutorial/introduction.texi Sun Jan 02 22:57:04 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,310 +0,0 @@
-
-@c ========================================================================
-@c Begin document body here
-@c ========================================================================
-
-@c ========================================================================
-@c PART: Introduction
-@c ========================================================================
-@c The below chapters are under the major heading "Introduction"
-@c This is similar to the Latex \part command
-@c
-@c ========================================================================
-@c Introduction
-@c ========================================================================
-@node Introduction
-@chapter Introduction
-
-@menu
-* For ns-2 Users::
-* Contributing::
-* Tutorial Organization::
-@end menu
-
-The @command{ns-3} simulator is a discrete-event network simulator targeted
-primarily for research and educational use. The
-@uref{http://www.nsnam.org,,ns-3 project},
-started in 2006, is an open-source project developing @command{ns-3}.
-
-Primary documentation for the @command{ns-3} project is available in four
-forms:
-@itemize @bullet
-@item @uref{http://www.nsnam.org/doxygen/index.html,,ns-3 Doxygen/Manual}:
-Documentation of the public APIs of the simulator
-@item Tutorial (this document)
-@item @uref{http://www.nsnam.org/docs/manual.html,,Reference Manual}: Reference Manual
-@item @uref{http://www.nsnam.org/wiki/index.php,, ns-3 wiki}
-@end itemize
-
-The purpose of this tutorial is to introduce new @command{ns-3} users to the
-system in a structured way. It is sometimes difficult for new users to
-glean essential information from detailed manuals and to convert this
-information into working simulations. In this tutorial, we will build
-several example simulations, introducing and explaining key concepts and
-features as we go.
-
-As the tutorial unfolds, we will introduce the full @command{ns-3} documentation
-and provide pointers to source code for those interested in delving deeper
-into the workings of the system.
-
-A few key points are worth noting at the onset:
-@itemize @bullet
-@item Ns-3 is not an extension of @uref{http://www.isi.edu/nsnam/ns,,ns-2};
-it is a new simulator. The two simulators are both written in C++ but
-@command{ns-3} is a new simulator that does not support the ns-2 APIs. Some
-models from ns-2 have already been ported from ns-2 to @command{ns-3}. The
-project will continue to maintain ns-2 while @command{ns-3} is being built,
-and will study transition and integration mechanisms.
-@item @command{Ns-3} is open-source, and the project strives to maintain an
-open environment for researchers to contribute and share their software.
-@end itemize
-
-@node For ns-2 Users
-@section For ns-2 Users
-
-For those familiar with ns-2, the most visible outward change when moving to
-@command{ns-3} is the choice of scripting language. Ns-2 is
-scripted in OTcl and results of simulations can be visualized using the
-Network Animator @command{nam}. It is not possible to run a simulation
-in ns-2 purely from C++ (i.e., as a main() program without any OTcl).
-Moreover, some components of ns-2 are written in C++ and others in OTcl.
-In @command{ns-3}, the simulator is written entirely in C++, with optional
-Python bindings. Simulation scripts can therefore be written in C++
-or in Python. The results of some simulations can be visualized by
-@command{nam}, but new animators are under development. Since @command{ns-3}
-generates pcap packet trace files, other utilities can be used to
-analyze traces as well.
-In this tutorial, we will first concentrate on scripting
-directly in C++ and interpreting results via trace files.
-
-But there are similarities as well (both, for example, are based on C++
-objects, and some code from ns-2 has already been ported to @command{ns-3}).
-We will try to highlight differences between ns-2 and @command{ns-3}
-as we proceed in this tutorial.
-
-A question that we often hear is "Should I still use ns-2 or move to
-@command{ns-3}?" The answer is that it depends. @command{ns-3} does not have
-all of the models that ns-2 currently has, but on the other hand, @command{ns-3}
-does have new capabilities (such as handling multiple interfaces on nodes
-correctly, use of IP addressing and more alignment with Internet
-protocols and designs, more detailed 802.11 models, etc.). ns-2
-models can usually be ported to @command{ns-3} (a porting guide is under
-development). There is active development on multiple fronts for
-@command{ns-3}. The @command{ns-3} developers believe (and certain early users
-have proven) that @command{ns-3} is ready for active use, and should be an
-attractive alternative for users looking to start new simulation projects.
-
-@node Contributing
-@section Contributing
-
-@cindex contributing
-@command{Ns-3} is a research and educational simulator, by and for the
-research community. It will rely on the ongoing contributions of the
-community to develop new models, debug or maintain existing ones, and share
-results. There are a few policies that we hope will encourage people to
-contribute to @command{ns-3} like they have for ns-2:
-@itemize @bullet
-@item Open source licensing based on GNU GPLv2 compatibility;
-@item @uref{http://www.nsnam.org/wiki/index.php,,wiki};
-@item @uref{http://www.nsnam.org/wiki/index.php/Contributed_Code,,Contributed Code} page, similar to ns-2's popular
-@uref{http://nsnam.isi.edu/nsnam/index.php/Contributed_Code,,Contributed Code}
-page;
-@item @code{src/contrib} directory (we will host your contributed code);
-@item Open @uref{http://www.nsnam.org/bugzilla,,bug tracker};
-@item @command{Ns-3} developers will gladly help potential contributors to get
-started with the simulator (please contact @uref{http://www.nsnam.org/people.html,,one of us}).
-@end itemize
-
-We realize that if you are reading this document, contributing back to
-the project is probably not your foremost concern at this point, but
-we want you to be aware that contributing is in the spirit of the project and
-that even the act of dropping us a note about your early experience
-with @command{ns-3} (e.g. "this tutorial section was not clear..."),
-reports of stale documentation, etc. are much appreciated.
-
-@node Tutorial Organization
-@section Tutorial Organization
-
-The tutorial assumes that new users might initially follow a path such as the
-following:
-
-@itemize @bullet
-@item Try to download and build a copy;
-@item Try to run a few sample programs;
-@item Look at simulation output, and try to adjust it.
-@end itemize
-
-As a result, we have tried to organize the tutorial along the above
-broad sequences of events.
-
-@c ========================================================================
-@c Resources
-@c ========================================================================
-
-@node Resources
-@chapter Resources
-
-@menu
-* The Web::
-* Mercurial::
-* Waf::
-* Development Environment::
-* Socket Programming::
-@end menu
-
-@node The Web
-@section The Web
-
-@cindex www.nsnam.org
-@cindex documentation
-@cindex architecture
-There are several important resources of which any @command{ns-3} user must be
-aware. The main web site is located at @uref{http://www.nsnam.org} and
-provides access to basic information about the @command{ns-3} system. Detailed
-documentation is available through the main web site at
-@uref{http://www.nsnam.org/documents.html}. You can also find documents
-relating to the system architecture from this page.
-
-There is a Wiki that complements the main @command{ns-3} web site which you will
-find at @uref{http://www.nsnam.org/wiki/}. You will find user and developer
-FAQs there, as well as troubleshooting guides, third-party contributed code,
-papers, etc.
-
-@cindex mercurial repository
-@cindex ns-3-dev repository
-@cindex release repository
-The source code may be found and browsed at @uref{http://code.nsnam.org/}.
-There you will find the current development tree in the repository named
-@code{ns-3-dev}. Past releases and experimental repositories of the core
-developers may also be found there.
-
-@node Mercurial
-@section Mercurial
-
-Complex software systems need some way to manage the organization and
-changes to the underlying code and documentation. There are many ways to
-perform this feat, and you may have heard of some of the systems that are
-currently used to do this. The Concurrent Version System (CVS) is probably
-the most well known.
-
-@cindex software configuration management
-@cindex Mercurial
-The @command{ns-3} project uses Mercurial as its source code management system.
-Although you do not need to know much about Mercurial in order to complete
-this tutorial, we recommend becoming familiar with Mercurial and using it
-to access the source code. Mercurial has a web site at
-@uref{http://www.selenic.com/mercurial/},
-from which you can get binary or source releases of this Software
-Configuration Management (SCM) system. Selenic (the developer of Mercurial)
-also provides a tutorial at
-@uref{http://www.selenic.com/mercurial/wiki/index.cgi/Tutorial/},
-and a QuickStart guide at
-@uref{http://www.selenic.com/mercurial/wiki/index.cgi/QuickStart/}.
-
-You can also find vital information about using Mercurial and @command{ns-3}
-on the main @command{ns-3} web site.
-
-@node Waf
-@section Waf
-
-@cindex Waf
-@cindex make
-@cindex build
-Once you have source code downloaded to your local system, you will need
-to compile that source to produce usable programs. Just as in the case of
-source code management, there are many tools available to perform this
-function. Probably the most well known of these tools is @code{make}. Along
-with being the most well known, @code{make} is probably the most difficult to
-use in a very large and highly configurable system. Because of this, many
-alternatives have been developed. Recently these systems have been developed
-using the Python language.
-
-The build system @code{Waf} is used on the @command{ns-3} project. It is one
-of the new generation of Python-based build systems. You will not need to
-understand any Python to build the existing @command{ns-3} system, and will
-only have to understand a tiny and intuitively obvious subset of Python in
-order to extend the system in most cases.
-
-For those interested in the gory details of Waf, the main web site can be
-found at @uref{http://code.google.com/p/waf/}.
-
-@node Development Environment
-@section Development Environment
-
-@cindex C++
-@cindex Python
-As mentioned above, scripting in @command{ns-3} is done in C++ or Python.
-As of ns-3.2, most of the @command{ns-3} API is available in Python, but the
-models are written in C++ in either case. A working
-knowledge of C++ and object-oriented concepts is assumed in this document.
-We will take some time to review some of the more advanced concepts or
-possibly unfamiliar language features, idioms and design patterns as they
-appear. We don't want this tutorial to devolve into a C++ tutorial, though,
-so we do expect a basic command of the language. There are an almost
-unimaginable number of sources of information on C++ available on the web or
-in print.
-
-If you are new to C++, you may want to find a tutorial- or cookbook-based
-book or web site and work through at least the basic features of the language
-before proceeding. For instance,
-@uref{http://www.cplusplus.com/doc/tutorial/,,this tutorial}.
-
-@cindex toolchain
-@cindex GNU
-The @command{ns-3} system uses several components of the GNU ``toolchain''
-for development. A
-software toolchain is the set of programming tools available in the given
-environment. For a quick review of what is included in the GNU toolchain see,
-@uref{http://en.wikipedia.org/wiki/GNU_toolchain}. @command{ns-3} uses gcc,
-GNU binutils, and gdb. However, we do not use the GNU build system tools,
-neither make nor autotools. We use Waf for these functions.
-
-@cindex Linux
-Typically an @command{ns-3} author will work in Linux or a Linux-like
-environment. For those running under Windows, there do exist environments
-which simulate the Linux environment to various degrees. The @command{ns-3}
-project supports development in the Cygwin environment for
-these users. See @uref{http://www.cygwin.com/}
-for details on downloading (MinGW is presently not officially supported,
-although some of the project maintainers to work with it). Cygwin provides
-many of the popular Linux system commands. It can, however, sometimes be
-problematic due to the way it actually does its emulation, and sometimes
-interactions with other Windows software can cause problems.
-
-@cindex Cygwin
-@cindex MinGW
-If you do use Cygwin or MinGW; and use Logitech products, we will save you
-quite a bit of heartburn right off the bat and encourage you to take a look
-at the @uref{http://oldwiki.mingw.org/index.php/FAQ,,MinGW FAQ}.
-
-@cindex Logitech
-Search for ``Logitech'' and read the FAQ entry, ``why does make often
-crash creating a sh.exe.stackdump file when I try to compile my source code.''
-Believe it or not, the @code{Logitech Process Monitor} insinuates itself into
-every DLL in the system when it is running. It can cause your Cygwin or
-MinGW DLLs to die in mysterious ways and often prevents debuggers from
-running. Beware of Logitech software when using Cygwin.
-
-Another alternative to Cygwin is to install a virtual machine environment
-such as VMware server and install a Linux virtual machine.
-
-@node Socket Programming
-@section Socket Programming
-
-@cindex sockets
-We will assume a basic facility with the Berkeley Sockets API in the examples
-used in this tutorial. If you are new to sockets, we recommend reviewing the
-API and some common usage cases. For a good overview of programming TCP/IP
-sockets we recommend @uref{http://www.elsevier.com/wps/find/bookdescription.cws_home/717656/description#description,,TCP/IP Sockets in C, Donahoo and Calvert}.
-
-There is an associated web site that includes source for the examples in the
-book, which you can find at:
-@uref{http://cs.baylor.edu/~donahoo/practical/CSockets/}.
-
-If you understand the first four chapters of the book (or for those who do
-not have access to a copy of the book, the echo clients and servers shown in
-the website above) you will be in good shape to understand the tutorial.
-There is a similar book on Multicast Sockets,
-@uref{http://www.elsevier.com/wps/find/bookdescription.cws_home/700736/description#description,,Multicast Sockets, Makofske and Almeroth}.
-that covers material you may need to understand if you look at the multicast
-examples in the distribution.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/tutorial/pickle-to-xml.py Sun Jan 02 22:57:32 2011 -0800
@@ -0,0 +1,42 @@
+#!/usr/bin/python
+
+
+# output xml format:
+# <pages>
+# <page url="xx"><prev url="yyy">zzz</prev><next url="hhh">lll</next><fragment>file.frag</fragment></page>
+# ...
+# </pages>
+
+import pickle
+import os
+import codecs
+
+def dump_pickles(out, dirname, filename, path):
+ f = open(os.path.join(dirname, filename), 'r')
+ data = pickle.load(f)
+ fragment_file = codecs.open(data['current_page_name'] + '.frag', mode='w', encoding='utf-8')
+ fragment_file.write(data['body'])
+ fragment_file.close()
+ out.write(' <page url="%s">\n' % path)
+ out.write(' <fragment>%s.frag</fragment>\n' % data['current_page_name'])
+ if data['prev'] is not None:
+ out.write(' <prev url="%s">%s</prev>\n' %
+ (os.path.normpath(os.path.join(path, data['prev']['link'])),
+ data['prev']['title']))
+ if data['next'] is not None:
+ out.write(' <next url="%s">%s</next>\n' %
+ (os.path.normpath(os.path.join(path, data['next']['link'])),
+ data['next']['title']))
+ out.write(' </page>\n')
+ f.close()
+ if data['next'] is not None:
+ next_path = os.path.normpath(os.path.join(path, data['next']['link']))
+ next_filename = os.path.basename(next_path) + '.fpickle'
+ dump_pickles(out, dirname, next_filename, next_path)
+ return
+
+import sys
+
+sys.stdout.write('<pages>\n')
+dump_pickles(sys.stdout, os.path.dirname(sys.argv[1]), os.path.basename(sys.argv[1]), '/')
+sys.stdout.write('</pages>')
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/tutorial/source/building-topologies.rst Sun Jan 02 22:57:32 2011 -0800
@@ -0,0 +1,1429 @@
+.. include:: replace.txt
+
+
+Building Topologies
+-------------------
+
+Building a Bus Network Topology
+*******************************
+
+In this section we are going to expand our mastery of |ns3| network
+devices and channels to cover an example of a bus network. |ns3|
+provides a net device and channel we call CSMA (Carrier Sense Multiple Access).
+
+The |ns3| CSMA device models a simple network in the spirit of
+Ethernet. A real Ethernet uses CSMA/CD (Carrier Sense Multiple Access with
+Collision Detection) scheme with exponentially increasing backoff to contend
+for the shared transmission medium. The |ns3| CSMA device and
+channel models only a subset of this.
+
+Just as we have seen point-to-point topology helper objects when constructing
+point-to-point topologies, we will see equivalent CSMA topology helpers in
+this section. The appearance and operation of these helpers should look
+quite familiar to you.
+
+We provide an example script in our examples/tutorial} directory. This script
+builds on the ``first.cc`` script and adds a CSMA network to the
+point-to-point simulation we've already considered. Go ahead and open
+``examples/tutorial/second.cc`` in your favorite editor. You will have already seen
+enough |ns3| code to understand most of what is going on in this
+example, but we will go over the entire script and examine some of the output.
+
+Just as in the ``first.cc`` example (and in all ns-3 examples) the file
+begins with an emacs mode line and some GPL boilerplate.
+
+The actual code begins by loading module include files just as was done in the
+``first.cc`` example.
+
+::
+
+ #include "ns3/core-module.h"
+ #include "ns3/simulator-module.h"
+ #include "ns3/node-module.h"
+ #include "ns3/helper-module.h"
+
+One thing that can be surprisingly useful is a small bit of ASCII art that
+shows a cartoon of the network topology constructed in the example. You will
+find a similar "drawing" in most of our examples.
+
+In this case, you can see that we are going to extend our point-to-point
+example (the link between the nodes n0 and n1 below) by hanging a bus network
+off of the right side. Notice that this is the default network topology
+since you can actually vary the number of nodes created on the LAN. If you
+set nCsma to one, there will be a total of two nodes on the LAN (CSMA
+channel) --- one required node and one "extra" node. By default there are
+three "extra" nodes as seen below:
+
+::
+
+// Default Network Topology
+//
+// 10.1.1.0
+// n0 -------------- n1 n2 n3 n4
+// point-to-point | | | |
+// ================
+// LAN 10.1.2.0
+
+Then the ns-3 namespace is ``used`` and a logging component is defined.
+This is all just as it was in ``first.cc``, so there is nothing new yet.
+
+::
+
+ using namespace ns3;
+
+ NS_LOG_COMPONENT_DEFINE ("SecondScriptExample");
+
+The main program begins with a slightly different twist. We use a verbose
+flag to determine whether or not the ``UdpEchoClientApplication`` and
+``UdpEchoServerApplication`` logging components are enabled. This flag
+defaults to true (the logging components are enabled) but allows us to turn
+off logging during regression testing of this example.
+
+You will see some familiar code that will allow you to change the number
+of devices on the CSMA network via command line argument. We did something
+similar when we allowed the number of packets sent to be changed in the section
+on command line arguments. The last line makes sure you have at least one
+"extra" node.
+
+The code consists of variations of previously covered API so you should be
+entirely comfortable with the following code at this point in the tutorial.
+
+::
+
+ bool verbose = true;
+ uint32_t nCsma = 3;
+
+ CommandLine cmd;
+ cmd.AddValue ("nCsma", "Number of \"extra\" CSMA nodes/devices", nCsma);
+ cmd.AddValue ("verbose", "Tell echo applications to log if true", verbose);
+
+ cmd.Parse (argc,argv);
+
+ if (verbose)
+ {
+ LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_INFO);
+ LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_INFO);
+ }
+
+ nCsma = nCsma == 0 ? 1 : nCsma;
+
+The next step is to create two nodes that we will connect via the
+point-to-point link. The ``NodeContainer`` is used to do this just as was
+done in ``first.cc``.
+
+::
+
+ NodeContainer p2pNodes;
+ p2pNodes.Create (2);
+
+Next, we declare another ``NodeContainer`` to hold the nodes that will be
+part of the bus (CSMA) network. First, we just instantiate the container
+object itself.
+
+::
+
+ NodeContainer csmaNodes;
+ csmaNodes.Add (p2pNodes.Get (1));
+ csmaNodes.Create (nCsma);
+
+The next line of code ``Gets`` the first node (as in having an index of one)
+from the point-to-point node container and adds it to the container of nodes
+that will get CSMA devices. The node in question is going to end up with a
+point-to-point device *and* a CSMA device. We then create a number of
+"extra" nodes that compose the remainder of the CSMA network. Since we
+already have one node in the CSMA network -- the one that will have both a
+point-to-point and CSMA net device, the number of "extra" nodes means the
+number nodes you desire in the CSMA section minus one.
+
+The next bit of code should be quite familiar by now. We instantiate a
+``PointToPointHelper`` and set the associated default ``Attributes`` so
+that we create a five megabit per second transmitter on devices created using
+the helper and a two millisecond delay on channels created by the helper.
+
+::
+
+ PointToPointHelper pointToPoint;
+ pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
+ pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
+
+ NetDeviceContainer p2pDevices;
+ p2pDevices = pointToPoint.Install (p2pNodes);
+
+We then instantiate a ``NetDeviceContainer`` to keep track of the
+point-to-point net devices and we ``Install`` devices on the
+point-to-point nodes.
+
+We mentioned above that you were going to see a helper for CSMA devices and
+channels, and the next lines introduce them. The ``CsmaHelper`` works just
+like a ``PointToPointHelper``, but it creates and connects CSMA devices and
+channels. In the case of a CSMA device and channel pair, notice that the data
+rate is specified by a *channel* ``Attribute`` instead of a device
+``Attribute``. This is because a real CSMA network does not allow one to mix,
+for example, 10Base-T and 100Base-T devices on a given channel. We first set
+the data rate to 100 megabits per second, and then set the speed-of-light delay
+of the channel to 6560 nano-seconds (arbitrarily chosen as 1 nanosecond per foot
+over a 100 meter segment). Notice that you can set an ``Attribute`` using
+its native data type.
+
+::
+
+ CsmaHelper csma;
+ csma.SetChannelAttribute ("DataRate", StringValue ("100Mbps"));
+ csma.SetChannelAttribute ("Delay", TimeValue (NanoSeconds (6560)));
+
+ NetDeviceContainer csmaDevices;
+ csmaDevices = csma.Install (csmaNodes);
+
+Just as we created a ``NetDeviceContainer`` to hold the devices created by
+the ``PointToPointHelper`` we create a ``NetDeviceContainer`` to hold
+the devices created by our ``CsmaHelper``. We call the ``Install``
+method of the ``CsmaHelper`` to install the devices into the nodes of the
+``csmaNodes NodeContainer``.
+
+We now have our nodes, devices and channels created, but we have no protocol
+stacks present. Just as in the ``first.cc`` script, we will use the
+``InternetStackHelper`` to install these stacks.
+
+::
+
+ InternetStackHelper stack;
+ stack.Install (p2pNodes.Get (0));
+ stack.Install (csmaNodes);
+
+Recall that we took one of the nodes from the ``p2pNodes`` container and
+added it to the ``csmaNodes`` container. Thus we only need to install
+the stacks on the remaining ``p2pNodes`` node, and all of the nodes in the
+``csmaNodes`` container to cover all of the nodes in the simulation.
+
+Just as in the ``first.cc`` example script, we are going to use the
+``Ipv4AddressHelper`` to assign IP addresses to our device interfaces.
+First we use the network 10.1.1.0 to create the two addresses needed for our
+two point-to-point devices.
+
+::
+
+ Ipv4AddressHelper address;
+ address.SetBase ("10.1.1.0", "255.255.255.0");
+ Ipv4InterfaceContainer p2pInterfaces;
+ p2pInterfaces = address.Assign (p2pDevices);
+
+Recall that we save the created interfaces in a container to make it easy to
+pull out addressing information later for use in setting up the applications.
+
+We now need to assign IP addresses to our CSMA device interfaces. The
+operation works just as it did for the point-to-point case, except we now
+are performing the operation on a container that has a variable number of
+CSMA devices --- remember we made the number of CSMA devices changeable by
+command line argument. The CSMA devices will be associated with IP addresses
+from network number 10.1.2.0 in this case, as seen below.
+
+::
+
+ address.SetBase ("10.1.2.0", "255.255.255.0");
+ Ipv4InterfaceContainer csmaInterfaces;
+ csmaInterfaces = address.Assign (csmaDevices);
+
+Now we have a topology built, but we need applications. This section is
+going to be fundamentally similar to the applications section of
+``first.cc`` but we are going to instantiate the server on one of the
+nodes that has a CSMA device and the client on the node having only a
+point-to-point device.
+
+First, we set up the echo server. We create a ``UdpEchoServerHelper`` and
+provide a required ``Attribute`` value to the constructor which is the server
+port number. Recall that this port can be changed later using the
+``SetAttribute`` method if desired, but we require it to be provided to
+the constructor.
+
+::
+
+ UdpEchoServerHelper echoServer (9);
+
+ ApplicationContainer serverApps = echoServer.Install (csmaNodes.Get (nCsma));
+ serverApps.Start (Seconds (1.0));
+ serverApps.Stop (Seconds (10.0));
+
+Recall that the ``csmaNodes NodeContainer`` contains one of the
+nodes created for the point-to-point network and ``nCsma`` "extra" nodes.
+What we want to get at is the last of the "extra" nodes. The zeroth entry of
+the ``csmaNodes`` container will be the point-to-point node. The easy
+way to think of this, then, is if we create one "extra" CSMA node, then it
+will be at index one of the ``csmaNodes`` container. By induction,
+if we create ``nCsma`` "extra" nodes the last one will be at index
+``nCsma``. You see this exhibited in the ``Get`` of the first line of
+code.
+
+The client application is set up exactly as we did in the ``first.cc``
+example script. Again, we provide required ``Attributes`` to the
+``UdpEchoClientHelper`` in the constructor (in this case the remote address
+and port). We tell the client to send packets to the server we just installed
+on the last of the "extra" CSMA nodes. We install the client on the
+leftmost point-to-point node seen in the topology illustration.
+
+::
+
+ UdpEchoClientHelper echoClient (csmaInterfaces.GetAddress (nCsma), 9);
+ echoClient.SetAttribute ("MaxPackets", UintegerValue (1));
+ echoClient.SetAttribute ("Interval", TimeValue (Seconds (1.)));
+ echoClient.SetAttribute ("PacketSize", UintegerValue (1024));
+
+ ApplicationContainer clientApps = echoClient.Install (p2pNodes.Get (0));
+ clientApps.Start (Seconds (2.0));
+ clientApps.Stop (Seconds (10.0));
+
+Since we have actually built an internetwork here, we need some form of
+internetwork routing. |ns3| provides what we call global routing to
+help you out. Global routing takes advantage of the fact that the entire
+internetwork is accessible in the simulation and runs through the all of the
+nodes created for the simulation --- it does the hard work of setting up routing
+for you without having to configure routers.
+
+Basically, what happens is that each node behaves as if it were an OSPF router
+that communicates instantly and magically with all other routers behind the
+scenes. Each node generates link advertisements and communicates them
+directly to a global route manager which uses this global information to
+construct the routing tables for each node. Setting up this form of routing
+is a one-liner:
+
+::
+
+ Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
+
+Next we enable pcap tracing. The first line of code to enable pcap tracing
+in the point-to-point helper should be familiar to you by now. The second
+line enables pcap tracing in the CSMA helper and there is an extra parameter
+you haven't encountered yet.
+
+::
+
+ pointToPoint.EnablePcapAll ("second");
+ csma.EnablePcap ("second", csmaDevices.Get (1), true);
+
+The CSMA network is a multi-point-to-point network. This means that there
+can (and are in this case) multiple endpoints on a shared medium. Each of
+these endpoints has a net device associated with it. There are two basic
+alternatives to gathering trace information from such a network. One way
+is to create a trace file for each net device and store only the packets
+that are emitted or consumed by that net device. Another way is to pick
+one of the devices and place it in promiscuous mode. That single device
+then "sniffs" the network for all packets and stores them in a single
+pcap file. This is how ``tcpdump``, for example, works. That final
+parameter tells the CSMA helper whether or not to arrange to capture
+packets in promiscuous mode.
+
+In this example, we are going to select one of the devices on the CSMA
+network and ask it to perform a promiscuous sniff of the network, thereby
+emulating what ``tcpdump`` would do. If you were on a Linux machine
+you might do something like ``tcpdump -i eth0`` to get the trace.
+In this case, we specify the device using ``csmaDevices.Get(1)``,
+which selects the first device in the container. Setting the final
+parameter to true enables promiscuous captures.
+
+The last section of code just runs and cleans up the simulation just like
+the ``first.cc`` example.
+
+::
+
+ Simulator::Run ();
+ Simulator::Destroy ();
+ return 0;
+ }
+
+In order to run this example, copy the ``second.cc`` example script into
+the scratch directory and use waf to build just as you did with
+the ``first.cc`` example. If you are in the top-level directory of the
+repository you just type,
+
+::
+
+ cp examples/tutorial/second.cc scratch/mysecond.cc
+ ./waf
+
+Warning: We use the file ``second.cc`` as one of our regression tests to
+verify that it works exactly as we think it should in order to make your
+tutorial experience a positive one. This means that an executable named
+``second`` already exists in the project. To avoid any confusion
+about what you are executing, please do the renaming to ``mysecond.cc``
+suggested above.
+
+If you are following the tutorial religiously (you are, aren't you) you will
+still have the NS_LOG variable set, so go ahead and clear that variable and
+run the program.
+
+::
+
+ export NS_LOG=
+ ./waf --run scratch/mysecond
+
+Since we have set up the UDP echo applications to log just as we did in
+``first.cc``, you will see similar output when you run the script.
+
+::
+
+ Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
+ Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
+ 'build' finished successfully (0.415s)
+ Sent 1024 bytes to 10.1.2.4
+ Received 1024 bytes from 10.1.1.1
+ Received 1024 bytes from 10.1.2.4
+
+Recall that the first message, "``Sent 1024 bytes to 10.1.2.4``," is the
+UDP echo client sending a packet to the server. In this case, the server
+is on a different network (10.1.2.0). The second message, "``Received 1024
+bytes from 10.1.1.1``," is from the UDP echo server, generated when it receives
+the echo packet. The final message, "``Received 1024 bytes from 10.1.2.4``,"
+is from the echo client, indicating that it has received its echo back from
+the server.
+
+If you now go and look in the top level directory, you will find three trace
+files:
+
+::
+
+ second-0-0.pcap second-1-0.pcap second-2-0.pcap
+
+Let's take a moment to look at the naming of these files. They all have the
+same form, ``<name>-<node>-<device>.pcap``. For example, the first file
+in the listing is ``second-0-0.pcap`` which is the pcap trace from node
+zero, device zero. This is the point-to-point net device on node zero. The
+file ``second-1-0.pcap`` is the pcap trace for device zero on node one,
+also a point-to-point net device; and the file ``second-2-0.pcap`` is the
+pcap trace for device zero on node two.
+
+If you refer back to the topology illustration at the start of the section,
+you will see that node zero is the leftmost node of the point-to-point link
+and node one is the node that has both a point-to-point device and a CSMA
+device. You will see that node two is the first "extra" node on the CSMA
+network and its device zero was selected as the device to capture the
+promiscuous-mode trace.
+
+Now, let's follow the echo packet through the internetwork. First, do a
+tcpdump of the trace file for the leftmost point-to-point node --- node zero.
+
+::
+
+ tcpdump -nn -tt -r second-0-0.pcap
+
+You should see the contents of the pcap file displayed:
+
+::
+
+ reading from file second-0-0.pcap, link-type PPP (PPP)
+ 2.000000 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024
+ 2.007602 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024
+
+The first line of the dump indicates that the link type is PPP (point-to-point)
+which we expect. You then see the echo packet leaving node zero via the
+device associated with IP address 10.1.1.1 headed for IP address
+10.1.2.4 (the rightmost CSMA node). This packet will move over the
+point-to-point link and be received by the point-to-point net device on node
+one. Let's take a look:
+
+::
+
+ tcpdump -nn -tt -r second-1-0.pcap
+
+You should now see the pcap trace output of the other side of the point-to-point
+link:
+
+::
+
+ reading from file second-1-0.pcap, link-type PPP (PPP)
+ 2.003686 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024
+ 2.003915 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024
+
+Here we see that the link type is also PPP as we would expect. You see the
+packet from IP address 10.1.1.1 (that was sent at 2.000000 seconds) headed
+toward IP address 10.1.2.4 appear on this interface. Now, internally to this
+node, the packet will be forwarded to the CSMA interface and we should see it
+pop out on that device headed for its ultimate destination.
+
+Remember that we selected node 2 as the promiscuous sniffer node for the CSMA
+network so let's then look at second-2-0.pcap and see if its there.
+
+::
+
+ tcpdump -nn -tt -r second-2-0.pcap
+
+You should now see the promiscuous dump of node two, device zero:
+
+::
+
+ reading from file second-2-0.pcap, link-type EN10MB (Ethernet)
+ 2.003696 arp who-has 10.1.2.4 (ff:ff:ff:ff:ff:ff) tell 10.1.2.1
+ 2.003707 arp reply 10.1.2.4 is-at 00:00:00:00:00:06
+ 2.003801 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024
+ 2.003811 arp who-has 10.1.2.1 (ff:ff:ff:ff:ff:ff) tell 10.1.2.4
+ 2.003822 arp reply 10.1.2.1 is-at 00:00:00:00:00:03
+ 2.003915 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024
+
+As you can see, the link type is now "Ethernet". Something new has appeared,
+though. The bus network needs ``ARP``, the Address Resolution Protocol.
+Node one knows it needs to send the packet to IP address 10.1.2.4, but it
+doesn't know the MAC address of the corresponding node. It broadcasts on the
+CSMA network (ff:ff:ff:ff:ff:ff) asking for the device that has IP address
+10.1.2.4. In this case, the rightmost node replies saying it is at MAC address
+00:00:00:00:00:06. Note that node two is not directly involved in this
+exchange, but is sniffing the network and reporting all of the traffic it sees.
+
+This exchange is seen in the following lines,
+
+::
+
+ 2.003696 arp who-has 10.1.2.4 (ff:ff:ff:ff:ff:ff) tell 10.1.2.1
+ 2.003707 arp reply 10.1.2.4 is-at 00:00:00:00:00:06
+
+Then node one, device one goes ahead and sends the echo packet to the UDP echo
+server at IP address 10.1.2.4.
+
+::
+
+ 2.003801 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024
+
+The server receives the echo request and turns the packet around trying to send
+it back to the source. The server knows that this address is on another network
+that it reaches via IP address 10.1.2.1. This is because we initialized global
+routing and it has figured all of this out for us. But, the echo server node
+doesn't know the MAC address of the first CSMA node, so it has to ARP for it
+just like the first CSMA node had to do.
+
+::
+
+ 2.003811 arp who-has 10.1.2.1 (ff:ff:ff:ff:ff:ff) tell 10.1.2.4
+ 2.003822 arp reply 10.1.2.1 is-at 00:00:00:00:00:03
+
+The server then sends the echo back to the forwarding node.
+
+::
+
+ 2.003915 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024
+
+Looking back at the rightmost node of the point-to-point link,
+
+::
+
+ tcpdump -nn -tt -r second-1-0.pcap
+
+You can now see the echoed packet coming back onto the point-to-point link as
+the last line of the trace dump.
+
+::
+
+ reading from file second-1-0.pcap, link-type PPP (PPP)
+ 2.003686 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024
+ 2.003915 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024
+
+Lastly, you can look back at the node that originated the echo
+::
+
+ tcpdump -nn -tt -r second-0-0.pcap
+
+and see that the echoed packet arrives back at the source at 2.007602 seconds,
+
+::
+
+ reading from file second-0-0.pcap, link-type PPP (PPP)
+ 2.000000 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024
+ 2.007602 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024
+
+Finally, recall that we added the ability to control the number of CSMA devices
+in the simulation by command line argument. You can change this argument in
+the same way as when we looked at changing the number of packets echoed in the
+``first.cc`` example. Try running the program with the number of "extra"
+devices set to four:
+
+::
+
+ ./waf --run "scratch/mysecond --nCsma=4"
+
+You should now see,
+
+::
+
+ Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
+ Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
+ 'build' finished successfully (0.405s)
+ Sent 1024 bytes to 10.1.2.5
+ Received 1024 bytes from 10.1.1.1
+ Received 1024 bytes from 10.1.2.5
+
+Notice that the echo server has now been relocated to the last of the CSMA
+nodes, which is 10.1.2.5 instead of the default case, 10.1.2.4.
+
+It is possible that you may not be satisfied with a trace file generated by
+a bystander in the CSMA network. You may really want to get a trace from
+a single device and you may not be interested in any other traffic on the
+network. You can do this fairly easily.
+
+Let's take a look at ``scratch/mysecond.cc`` and add that code enabling us
+to be more specific. ``ns-3`` helpers provide methods that take a node
+number and device number as parameters. Go ahead and replace the
+``EnablePcap`` calls with the calls below.
+
+::
+
+ pointToPoint.EnablePcap ("second", p2pNodes.Get (0)->GetId (), 0);
+ csma.EnablePcap ("second", csmaNodes.Get (nCsma)->GetId (), 0, false);
+ csma.EnablePcap ("second", csmaNodes.Get (nCsma-1)->GetId (), 0, false);
+
+We know that we want to create a pcap file with the base name "second" and
+we also know that the device of interest in both cases is going to be zero,
+so those parameters are not really interesting.
+
+In order to get the node number, you have two choices: first, nodes are
+numbered in a monotonically increasing fashion starting from zero in the
+order in which you created them. One way to get a node number is to figure
+this number out "manually" by contemplating the order of node creation.
+If you take a look at the network topology illustration at the beginning of
+the file, we did this for you and you can see that the last CSMA node is
+going to be node number ``nCsma + 1``. This approach can become
+annoyingly difficult in larger simulations.
+
+An alternate way, which we use here, is to realize that the
+``NodeContainers`` contain pointers to |ns3| ``Node`` Objects.
+The ``Node`` Object has a method called ``GetId`` which will return that
+node's ID, which is the node number we seek. Let's go take a look at the
+Doxygen for the ``Node`` and locate that method, which is further down in
+the |ns3| core code than we've seen so far; but sometimes you have to
+search diligently for useful things.
+
+Go to the Doxygen documentation for your release (recall that you can find it
+on the project web site). You can get to the ``Node`` documentation by
+looking through at the "Classes" tab and scrolling down the "Class List"
+until you find ``ns3::Node``. Select ``ns3::Node`` and you will be taken
+to the documentation for the ``Node`` class. If you now scroll down to the
+``GetId`` method and select it, you will be taken to the detailed
+documentation for the method. Using the ``GetId`` method can make
+determining node numbers much easier in complex topologies.
+
+Let's clear the old trace files out of the top-level directory to avoid confusion
+about what is going on,
+
+::
+
+ rm *.pcap
+ rm *.tr
+
+If you build the new script and run the simulation setting ``nCsma`` to 100,
+
+::
+
+ ./waf --run "scratch/mysecond --nCsma=100"
+
+you will see the following output:
+
+::
+
+ Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
+ Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
+ 'build' finished successfully (0.407s)
+ Sent 1024 bytes to 10.1.2.101
+ Received 1024 bytes from 10.1.1.1
+ Received 1024 bytes from 10.1.2.101
+
+Note that the echo server is now located at 10.1.2.101 which corresponds to
+having 100 "extra" CSMA nodes with the echo server on the last one. If you
+list the pcap files in the top level directory you will see,
+
+::
+
+ second-0-0.pcap second-100-0.pcap second-101-0.pcap
+
+The trace file ``second-0-0.pcap`` is the "leftmost" point-to-point device
+which is the echo packet source. The file ``second-101-0.pcap`` corresponds
+to the rightmost CSMA device which is where the echo server resides. You may
+have noticed that the final parameter on the call to enable pcap tracing on the
+echo server node was false. This means that the trace gathered on that node
+was in non-promiscuous mode.
+
+To illustrate the difference between promiscuous and non-promiscuous traces, we
+also requested a non-promiscuous trace for the next-to-last node. Go ahead and
+take a look at the ``tcpdump`` for ``second-100-0.pcap``.
+
+::
+
+ tcpdump -nn -tt -r second-100-0.pcap
+
+You can now see that node 100 is really a bystander in the echo exchange. The
+only packets that it receives are the ARP requests which are broadcast to the
+entire CSMA network.
+
+::
+
+ reading from file second-100-0.pcap, link-type EN10MB (Ethernet)
+ 2.003696 arp who-has 10.1.2.101 (ff:ff:ff:ff:ff:ff) tell 10.1.2.1
+ 2.003811 arp who-has 10.1.2.1 (ff:ff:ff:ff:ff:ff) tell 10.1.2.101
+
+Now take a look at the ``tcpdump`` for ``second-101-0.pcap``.
+
+::
+
+ tcpdump -nn -tt -r second-101-0.pcap
+
+You can now see that node 101 is really the participant in the echo exchange.
+
+::
+
+ reading from file second-101-0.pcap, link-type EN10MB (Ethernet)
+ 2.003696 arp who-has 10.1.2.101 (ff:ff:ff:ff:ff:ff) tell 10.1.2.1
+ 2.003696 arp reply 10.1.2.101 is-at 00:00:00:00:00:67
+ 2.003801 IP 10.1.1.1.49153 > 10.1.2.101.9: UDP, length 1024
+ 2.003801 arp who-has 10.1.2.1 (ff:ff:ff:ff:ff:ff) tell 10.1.2.101
+ 2.003822 arp reply 10.1.2.1 is-at 00:00:00:00:00:03
+ 2.003822 IP 10.1.2.101.9 > 10.1.1.1.49153: UDP, length 1024
+
+Models, Attributes and Reality
+******************************
+
+This is a convenient place to make a small excursion and make an important
+point. It may or may not be obvious to you, but whenever one is using a
+simulation, it is important to understand exactly what is being modeled and
+what is not. It is tempting, for example, to think of the CSMA devices
+and channels used in the previous section as if they were real Ethernet
+devices; and to expect a simulation result to directly reflect what will
+happen in a real Ethernet. This is not the case.
+
+A model is, by definition, an abstraction of reality. It is ultimately the
+responsibility of the simulation script author to determine the so-called
+"range of accuracy" and "domain of applicability" of the simulation as
+a whole, and therefore its constituent parts.
+
+In some cases, like ``Csma``, it can be fairly easy to determine what is
+*not* modeled. By reading the model description (``csma.h``) you
+can find that there is no collision detection in the CSMA model and decide
+on how applicable its use will be in your simulation or what caveats you
+may want to include with your results. In other cases, it can be quite easy
+to configure behaviors that might not agree with any reality you can go out
+and buy. It will prove worthwhile to spend some time investigating a few
+such instances, and how easily you can swerve outside the bounds of reality
+in your simulations.
+
+As you have seen, |ns3| provides ``Attributes`` which a user
+can easily set to change model behavior. Consider two of the ``Attributes``
+of the ``CsmaNetDevice``: ``Mtu`` and ``EncapsulationMode``.
+The ``Mtu`` attribute indicates the Maximum Transmission Unit to the
+device. This is the size of the largest Protocol Data Unit (PDU) that the
+device can send.
+
+The MTU defaults to 1500 bytes in the ``CsmaNetDevice``. This default
+corresponds to a number found in RFC 894, "A Standard for the Transmission
+of IP Datagrams over Ethernet Networks." The number is actually derived
+from the maximum packet size for 10Base5 (full-spec Ethernet) networks --
+1518 bytes. If you subtract the DIX encapsulation overhead for Ethernet
+packets (18 bytes) you will end up with a maximum possible data size (MTU)
+of 1500 bytes. One can also find that the ``MTU`` for IEEE 802.3 networks
+is 1492 bytes. This is because LLC/SNAP encapsulation adds an extra eight
+bytes of overhead to the packet. In both cases, the underlying hardware can
+only send 1518 bytes, but the data size is different.
+
+In order to set the encapsulation mode, the ``CsmaNetDevice`` provides
+an ``Attribute`` called ``EncapsulationMode`` which can take on the
+values ``Dix`` or ``Llc``. These correspond to Ethernet and LLC/SNAP
+framing respectively.
+
+If one leaves the ``Mtu`` at 1500 bytes and changes the encapsulation mode
+to ``Llc``, the result will be a network that encapsulates 1500 byte PDUs
+with LLC/SNAP framing resulting in packets of 1526 bytes, which would be
+illegal in many networks, since they can transmit a maximum of 1518 bytes per
+packet. This would most likely result in a simulation that quite subtly does
+not reflect the reality you might be expecting.
+
+Just to complicate the picture, there exist jumbo frames (1500 < MTU <= 9000 bytes)
+and super-jumbo (MTU > 9000 bytes) frames that are not officially sanctioned
+by IEEE but are available in some high-speed (Gigabit) networks and NICs. One
+could leave the encapsulation mode set to ``Dix``, and set the ``Mtu``
+``Attribute`` on a ``CsmaNetDevice`` to 64000 bytes -- even though an
+associated ``CsmaChannel DataRate`` was set at 10 megabits per second.
+This would essentially model an Ethernet switch made out of vampire-tapped
+1980s-style 10Base5 networks that support super-jumbo datagrams. This is
+certainly not something that was ever made, nor is likely to ever be made,
+but it is quite easy for you to configure.
+
+In the previous example, you used the command line to create a simulation that
+had 100 ``Csma`` nodes. You could have just as easily created a simulation
+with 500 nodes. If you were actually modeling that 10Base5 vampire-tap network,
+the maximum length of a full-spec Ethernet cable is 500 meters, with a minimum
+tap spacing of 2.5 meters. That means there could only be 200 taps on a
+real network. You could have quite easily built an illegal network in that
+way as well. This may or may not result in a meaningful simulation depending
+on what you are trying to model.
+
+Similar situations can occur in many places in |ns3| and in any
+simulator. For example, you may be able to position nodes in such a way that
+they occupy the same space at the same time, or you may be able to configure
+amplifiers or noise levels that violate the basic laws of physics.
+
+|ns3| generally favors flexibility, and many models will allow freely
+setting ``Attributes`` without trying to enforce any arbitrary consistency
+or particular underlying spec.
+
+The thing to take home from this is that |ns3| is going to provide a
+super-flexible base for you to experiment with. It is up to you to understand
+what you are asking the system to do and to make sure that the simulations you
+create have some meaning and some connection with a reality defined by you.
+
+Building a Wireless Network Topology
+************************************
+
+In this section we are going to further expand our knowledge of |ns3|
+network devices and channels to cover an example of a wireless network.
+|ns3| provides a set of 802.11 models that attempt to provide an
+accurate MAC-level implementation of the 802.11 specification and a
+"not-so-slow" PHY-level model of the 802.11a specification.
+
+Just as we have seen both point-to-point and CSMA topology helper objects when
+constructing point-to-point topologies, we will see equivalent ``Wifi``
+topology helpers in this section. The appearance and operation of these
+helpers should look quite familiar to you.
+
+We provide an example script in our ``examples/tutorial`` directory. This script
+builds on the ``second.cc`` script and adds a Wifi network. Go ahead and
+open ``examples/tutorial/third.cc`` in your favorite editor. You will have already
+seen enough |ns3| code to understand most of what is going on in
+this example, but there are a few new things, so we will go over the entire
+script and examine some of the output.
+
+Just as in the ``second.cc`` example (and in all |ns3| examples)
+the file begins with an emacs mode line and some GPL boilerplate.
+
+Take a look at the ASCII art (reproduced below) that shows the default network
+topology constructed in the example. You can see that we are going to
+further extend our example by hanging a wireless network off of the left side.
+Notice that this is a default network topology since you can actually vary the
+number of nodes created on the wired and wireless networks. Just as in the
+``second.cc`` script case, if you change ``nCsma``, it will give you a
+number of "extra" CSMA nodes. Similarly, you can set ``nWifi`` to
+control how many ``STA`` (station) nodes are created in the simulation.
+There will always be one ``AP`` (access point) node on the wireless
+network. By default there are three "extra" CSMA nodes and three wireless
+``STA`` nodes.
+
+The code begins by loading module include files just as was done in the
+``second.cc`` example. There are a couple of new includes corresponding
+to the Wifi module and the mobility module which we will discuss below.
+
+::
+
+#include "ns3/core-module.h"
+#include "ns3/simulator-module.h"
+#include "ns3/node-module.h"
+#include "ns3/helper-module.h"
+#include "ns3/wifi-module.h"
+#include "ns3/mobility-module.h"
+
+The network topology illustration follows:
+
+::
+
+ // Default Network Topology
+ //
+ // Wifi 10.1.3.0
+ // AP
+ // * * * *
+ // | | | | 10.1.1.0
+ // n5 n6 n7 n0 -------------- n1 n2 n3 n4
+ // point-to-point | | | |
+ // ================
+ // LAN 10.1.2.0
+
+You can see that we are adding a new network device to the node on the left
+side of the point-to-point link that becomes the access point for the wireless
+network. A number of wireless STA nodes are created to fill out the new
+10.1.3.0 network as shown on the left side of the illustration.
+
+After the illustration, the ``ns-3`` namespace is ``used`` and a logging
+component is defined. This should all be quite familiar by now.
+
+::
+
+ using namespace ns3;
+
+ NS_LOG_COMPONENT_DEFINE ("ThirdScriptExample");
+
+The main program begins just like ``second.cc`` by adding some command line
+parameters for enabling or disabling logging components and for changing the
+number of devices created.
+
+::
+
+ bool verbose = true;
+ uint32_t nCsma = 3;
+ uint32_t nWifi = 3;
+
+ CommandLine cmd;
+ cmd.AddValue ("nCsma", "Number of \"extra\" CSMA nodes/devices", nCsma);
+ cmd.AddValue ("nWifi", "Number of wifi STA devices", nWifi);
+ cmd.AddValue ("verbose", "Tell echo applications to log if true", verbose);
+
+ cmd.Parse (argc,argv);
+
+ if (verbose)
+ {
+ LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_INFO);
+ LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_INFO);
+ }
+
+Just as in all of the previous examples, the next step is to create two nodes
+that we will connect via the point-to-point link.
+
+::
+
+ NodeContainer p2pNodes;
+ p2pNodes.Create (2);
+
+Next, we see an old friend. We instantiate a ``PointToPointHelper`` and
+set the associated default ``Attributes`` so that we create a five megabit
+per second transmitter on devices created using the helper and a two millisecond
+delay on channels created by the helper. We then ``Intall`` the devices
+on the nodes and the channel between them.
+
+::
+
+ PointToPointHelper pointToPoint;
+ pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
+ pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
+
+ NetDeviceContainer p2pDevices;
+ p2pDevices = pointToPoint.Install (p2pNodes);
+
+Next, we declare another ``NodeContainer`` to hold the nodes that will be
+part of the bus (CSMA) network.
+
+::
+
+ NodeContainer csmaNodes;
+ csmaNodes.Add (p2pNodes.Get (1));
+ csmaNodes.Create (nCsma);
+
+The next line of code ``Gets`` the first node (as in having an index of one)
+from the point-to-point node container and adds it to the container of nodes
+that will get CSMA devices. The node in question is going to end up with a
+point-to-point device and a CSMA device. We then create a number of "extra"
+nodes that compose the remainder of the CSMA network.
+
+We then instantiate a ``CsmaHelper`` and set its ``Attributes`` as we did
+in the previous example. We create a ``NetDeviceContainer`` to keep track of
+the created CSMA net devices and then we ``Install`` CSMA devices on the
+selected nodes.
+
+::
+
+ CsmaHelper csma;
+ csma.SetChannelAttribute ("DataRate", StringValue ("100Mbps"));
+ csma.SetChannelAttribute ("Delay", TimeValue (NanoSeconds (6560)));
+
+ NetDeviceContainer csmaDevices;
+ csmaDevices = csma.Install (csmaNodes);
+
+Next, we are going to create the nodes that will be part of the Wifi network.
+We are going to create a number of "station" nodes as specified by the
+command line argument, and we are going to use the "leftmost" node of the
+point-to-point link as the node for the access point.
+
+::
+
+ NodeContainer wifiStaNodes;
+ wifiStaNodes.Create (nWifi);
+ NodeContainer wifiApNode = p2pNodes.Get (0);
+
+The next bit of code constructs the wifi devices and the interconnection
+channel between these wifi nodes. First, we configure the PHY and channel
+helpers:
+
+::
+
+ YansWifiChannelHelper channel = YansWifiChannelHelper::Default ();
+ YansWifiPhyHelper phy = YansWifiPhyHelper::Default ();
+
+For simplicity, this code uses the default PHY layer configuration and
+channel models which are documented in the API doxygen documentation for
+the ``YansWifiChannelHelper::Default`` and ``YansWifiPhyHelper::Default``
+methods. Once these objects are created, we create a channel object
+and associate it to our PHY layer object manager to make sure
+that all the PHY layer objects created by the ``YansWifiPhyHelper``
+share the same underlying channel, that is, they share the same
+wireless medium and can communication and interfere:
+
+::
+
+ phy.SetChannel (channel.Create ());
+
+Once the PHY helper is configured, we can focus on the MAC layer. Here we choose to
+work with non-Qos MACs so we use a NqosWifiMacHelper object to set MAC parameters.
+
+::
+
+ WifiHelper wifi = WifiHelper::Default ();
+ wifi.SetRemoteStationManager ("ns3::AarfWifiManager");
+
+ NqosWifiMacHelper mac = NqosWifiMacHelper::Default ();
+
+The ``SetRemoteStationManager`` method tells the helper the type of
+rate control algorithm to use. Here, it is asking the helper to use the AARF
+algorithm --- details are, of course, available in Doxygen.
+
+Next, we configure the type of MAC, the SSID of the infrastructure network we
+want to setup and make sure that our stations don't perform active probing:
+
+::
+
+ Ssid ssid = Ssid ("ns-3-ssid");
+ mac.SetType ("ns3::StaWifiMac",
+ "Ssid", SsidValue (ssid),
+ "ActiveProbing", BooleanValue (false));
+
+This code first creates an 802.11 service set identifier (SSID) object
+that will be used to set the value of the "Ssid" ``Attribute`` of
+the MAC layer implementation. The particular kind of MAC layer that
+will be created by the helper is specified by ``Attribute`` as
+being of the "ns3::StaWifiMac" type. The use of
+``NqosWifiMacHelper`` will ensure that the "QosSupported"
+``Attribute`` for created MAC objects is set false. The combination
+of these two configurations means that the MAC instance next created
+will be a non-QoS non-AP station (STA) in an infrastructure BSS (i.e.,
+a BSS with an AP). Finally, the "ActiveProbing" ``Attribute`` is
+set to false. This means that probe requests will not be sent by MACs
+created by this helper.
+
+Once all the station-specific parameters are fully configured, both at the
+MAC and PHY layers, we can invoke our now-familiar ``Install`` method to
+create the wifi devices of these stations:
+
+::
+
+ NetDeviceContainer staDevices;
+ staDevices = wifi.Install (phy, mac, wifiStaNodes);
+
+We have configured Wifi for all of our STA nodes, and now we need to
+configure the AP (access point) node. We begin this process by changing
+the default ``Attributes`` of the ``NqosWifiMacHelper`` to reflect the
+requirements of the AP.
+
+::
+
+ mac.SetType ("ns3::ApWifiMac",
+ "Ssid", SsidValue (ssid),
+ "BeaconGeneration", BooleanValue (true),
+ "BeaconInterval", TimeValue (Seconds (2.5)));
+
+In this case, the ``NqosWifiMacHelper`` is going to create MAC
+layers of the "ns3::ApWifiMac", the latter specifying that a MAC
+instance configured as an AP should be created, with the helper type
+implying that the "QosSupported" ``Attribute`` should be set to
+false - disabling 802.11e/WMM-style QoS support at created APs. We
+set the "BeaconGeneration" ``Attribute`` to true and also set an
+interval between beacons of 2.5 seconds.
+
+The next lines create the single AP which shares the same set of PHY-level
+``Attributes`` (and channel) as the stations:
+
+::
+
+ NetDeviceContainer apDevices;
+ apDevices = wifi.Install (phy, mac, wifiApNode);
+
+Now, we are going to add mobility models. We want the STA nodes to be mobile,
+wandering around inside a bounding box, and we want to make the AP node
+stationary. We use the ``MobilityHelper`` to make this easy for us.
+First, we instantiate a ``MobilityHelper`` object and set some
+``Attributes`` controlling the "position allocator" functionality.
+
+::
+
+ MobilityHelper mobility;
+
+ mobility.SetPositionAllocator ("ns3::GridPositionAllocator",
+ "MinX", DoubleValue (0.0),
+ "MinY", DoubleValue (0.0),
+ "DeltaX", DoubleValue (5.0),
+ "DeltaY", DoubleValue (10.0),
+ "GridWidth", UintegerValue (3),
+ "LayoutType", StringValue ("RowFirst"));
+
+This code tells the mobility helper to use a two-dimensional grid to initially
+place the STA nodes. Feel free to explore the Doxygen for class
+``ns3::GridPositionAllocator`` to see exactly what is being done.
+
+We have arranged our nodes on an initial grid, but now we need to tell them
+how to move. We choose the ``RandomWalk2dMobilityModel`` which has the
+nodes move in a random direction at a random speed around inside a bounding
+box.
+
+::
+
+ mobility.SetMobilityModel ("ns3::RandomWalk2dMobilityModel",
+ "Bounds", RectangleValue (Rectangle (-50, 50, -50, 50)));
+
+We now tell the ``MobilityHelper`` to install the mobility models on the
+STA nodes.
+
+::
+
+ mobility.Install (wifiStaNodes);
+
+We want the access point to remain in a fixed position during the simulation.
+We accomplish this by setting the mobility model for this node to be the
+``ns3::ConstantPositionMobilityModel``:
+
+::
+
+ mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+ mobility.Install (wifiApNode);
+
+We now have our nodes, devices and channels created, and mobility models
+chosen for the Wifi nodes, but we have no protocol stacks present. Just as
+we have done previously many times, we will use the ``InternetStackHelper``
+to install these stacks.
+
+::
+
+ InternetStackHelper stack;
+ stack.Install (csmaNodes);
+ stack.Install (wifiApNode);
+ stack.Install (wifiStaNodes);
+
+Just as in the ``second.cc`` example script, we are going to use the
+``Ipv4AddressHelper`` to assign IP addresses to our device interfaces.
+First we use the network 10.1.1.0 to create the two addresses needed for our
+two point-to-point devices. Then we use network 10.1.2.0 to assign addresses
+to the CSMA network and then we assign addresses from network 10.1.3.0 to
+both the STA devices and the AP on the wireless network.
+
+::
+
+ Ipv4AddressHelper address;
+
+ address.SetBase ("10.1.1.0", "255.255.255.0");
+ Ipv4InterfaceContainer p2pInterfaces;
+ p2pInterfaces = address.Assign (p2pDevices);
+
+ address.SetBase ("10.1.2.0", "255.255.255.0");
+ Ipv4InterfaceContainer csmaInterfaces;
+ csmaInterfaces = address.Assign (csmaDevices);
+
+ address.SetBase ("10.1.3.0", "255.255.255.0");
+ address.Assign (staDevices);
+ address.Assign (apDevices);
+
+We put the echo server on the "rightmost" node in the illustration at the
+start of the file. We have done this before.
+
+::
+
+ UdpEchoServerHelper echoServer (9);
+
+ ApplicationContainer serverApps = echoServer.Install (csmaNodes.Get (nCsma));
+ serverApps.Start (Seconds (1.0));
+ serverApps.Stop (Seconds (10.0));
+
+And we put the echo client on the last STA node we created, pointing it to
+the server on the CSMA network. We have also seen similar operations before.
+
+::
+
+ UdpEchoClientHelper echoClient (csmaInterfaces.GetAddress (nCsma), 9);
+ echoClient.SetAttribute ("MaxPackets", UintegerValue (1));
+ echoClient.SetAttribute ("Interval", TimeValue (Seconds (1.)));
+ echoClient.SetAttribute ("PacketSize", UintegerValue (1024));
+
+ ApplicationContainer clientApps =
+ echoClient.Install (wifiStaNodes.Get (nWifi - 1));
+ clientApps.Start (Seconds (2.0));
+ clientApps.Stop (Seconds (10.0));
+
+Since we have built an internetwork here, we need to enable internetwork routing
+just as we did in the ``second.cc`` example script.
+
+::
+
+ Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
+
+One thing that can surprise some users is the fact that the simulation we just
+created will never "naturally" stop. This is because we asked the wireless
+access point to generate beacons. It will generate beacons forever, and this
+will result in simulator events being scheduled into the future indefinitely,
+so we must tell the simulator to stop even though it may have beacon generation
+events scheduled. The following line of code tells the simulator to stop so that
+we don't simulate beacons forever and enter what is essentially an endless
+loop.
+
+::
+
+ Simulator::Stop (Seconds (10.0));
+
+We create just enough tracing to cover all three networks:
+
+::
+
+ pointToPoint.EnablePcapAll ("third");
+ phy.EnablePcap ("third", apDevices.Get (0));
+ csma.EnablePcap ("third", csmaDevices.Get (0), true);
+
+These three lines of code will start pcap tracing on both of the point-to-point
+nodes that serves as our backbone, will start a promiscuous (monitor) mode
+trace on the Wifi network, and will start a promiscuous trace on the CSMA
+network. This will let us see all of the traffic with a minimum number of
+trace files.
+
+Finally, we actually run the simulation, clean up and then exit the program.
+
+::
+
+ Simulator::Run ();
+ Simulator::Destroy ();
+ return 0;
+ }
+
+In order to run this example, you have to copy the ``third.cc`` example
+script into the scratch directory and use Waf to build just as you did with
+the ``second.cc`` example. If you are in the top-level directory of the
+repository you would type,
+
+::
+
+ cp examples/third.cc scratch/mythird.cc
+ ./waf
+ ./waf --run scratch/mythird
+
+Again, since we have set up the UDP echo applications just as we did in the
+``second.cc`` script, you will see similar output.
+
+::
+
+ Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
+ Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
+ 'build' finished successfully (0.407s)
+ Sent 1024 bytes to 10.1.2.4
+ Received 1024 bytes from 10.1.3.3
+ Received 1024 bytes from 10.1.2.4
+
+Recall that the first message, ``Sent 1024 bytes to 10.1.2.4``," is the
+UDP echo client sending a packet to the server. In this case, the client
+is on the wireless network (10.1.3.0). The second message,
+"``Received 1024 bytes from 10.1.3.3``," is from the UDP echo server,
+generated when it receives the echo packet. The final message,
+"``Received 1024 bytes from 10.1.2.4``," is from the echo client, indicating
+that it has received its echo back from the server.
+
+If you now go and look in the top level directory, you will find four trace
+files from this simulation, two from node zero and two from node one:
+
+::
+
+ third-0-0.pcap third-0-1.pcap third-1-0.pcap third-1-1.pcap
+
+The file "third-0-0.pcap" corresponds to the point-to-point device on node
+zero -- the left side of the "backbone". The file "third-1-0.pcap"
+corresponds to the point-to-point device on node one -- the right side of the
+"backbone". The file "third-0-1.pcap" will be the promiscuous (monitor
+mode) trace from the Wifi network and the file "third-1-1.pcap" will be the
+promiscuous trace from the CSMA network. Can you verify this by inspecting
+the code?
+
+Since the echo client is on the Wifi network, let's start there. Let's take
+a look at the promiscuous (monitor mode) trace we captured on that network.
+
+::
+
+ tcpdump -nn -tt -r third-0-1.pcap
+
+You should see some wifi-looking contents you haven't seen here before:
+
+::
+
+ reading from file third-0-1.pcap, link-type IEEE802_11 (802.11)
+ 0.000025 Beacon () [6.0* 9.0 12.0 18.0 24.0 36.0 48.0 54.0 Mbit] IBSS
+ 0.000263 Assoc Request () [6.0 9.0 12.0 18.0 24.0 36.0 48.0 54.0 Mbit]
+ 0.000279 Acknowledgment RA:00:00:00:00:00:07
+ 0.000357 Assoc Response AID(0) :: Succesful
+ 0.000501 Acknowledgment RA:00:00:00:00:00:0a
+ 0.000748 Assoc Request () [6.0 9.0 12.0 18.0 24.0 36.0 48.0 54.0 Mbit]
+ 0.000764 Acknowledgment RA:00:00:00:00:00:08
+ 0.000842 Assoc Response AID(0) :: Succesful
+ 0.000986 Acknowledgment RA:00:00:00:00:00:0a
+ 0.001242 Assoc Request () [6.0 9.0 12.0 18.0 24.0 36.0 48.0 54.0 Mbit]
+ 0.001258 Acknowledgment RA:00:00:00:00:00:09
+ 0.001336 Assoc Response AID(0) :: Succesful
+ 0.001480 Acknowledgment RA:00:00:00:00:00:0a
+ 2.000112 arp who-has 10.1.3.4 (ff:ff:ff:ff:ff:ff) tell 10.1.3.3
+ 2.000128 Acknowledgment RA:00:00:00:00:00:09
+ 2.000206 arp who-has 10.1.3.4 (ff:ff:ff:ff:ff:ff) tell 10.1.3.3
+ 2.000487 arp reply 10.1.3.4 is-at 00:00:00:00:00:0a
+ 2.000659 Acknowledgment RA:00:00:00:00:00:0a
+ 2.002169 IP 10.1.3.3.49153 > 10.1.2.4.9: UDP, length 1024
+ 2.002185 Acknowledgment RA:00:00:00:00:00:09
+ 2.009771 arp who-has 10.1.3.3 (ff:ff:ff:ff:ff:ff) tell 10.1.3.4
+ 2.010029 arp reply 10.1.3.3 is-at 00:00:00:00:00:09
+ 2.010045 Acknowledgment RA:00:00:00:00:00:09
+ 2.010231 IP 10.1.2.4.9 > 10.1.3.3.49153: UDP, length 1024
+ 2.011767 Acknowledgment RA:00:00:00:00:00:0a
+ 2.500000 Beacon () [6.0* 9.0 12.0 18.0 24.0 36.0 48.0 54.0 Mbit] IBSS
+ 5.000000 Beacon () [6.0* 9.0 12.0 18.0 24.0 36.0 48.0 54.0 Mbit] IBSS
+ 7.500000 Beacon () [6.0* 9.0 12.0 18.0 24.0 36.0 48.0 54.0 Mbit] IBSS
+
+You can see that the link type is now 802.11 as you would expect. You can
+probably understand what is going on and find the IP echo request and response
+packets in this trace. We leave it as an exercise to completely parse the
+trace dump.
+
+Now, look at the pcap file of the right side of the point-to-point link,
+
+::
+
+ tcpdump -nn -tt -r third-0-0.pcap
+
+Again, you should see some familiar looking contents:
+
+::
+
+ reading from file third-0-0.pcap, link-type PPP (PPP)
+ 2.002169 IP 10.1.3.3.49153 > 10.1.2.4.9: UDP, length 1024
+ 2.009771 IP 10.1.2.4.9 > 10.1.3.3.49153: UDP, length 1024
+
+This is the echo packet going from left to right (from Wifi to CSMA) and back
+again across the point-to-point link.
+
+Now, look at the pcap file of the right side of the point-to-point link,
+
+::
+
+ tcpdump -nn -tt -r third-1-0.pcap
+
+Again, you should see some familiar looking contents:
+
+::
+
+ reading from file third-1-0.pcap, link-type PPP (PPP)
+ 2.005855 IP 10.1.3.3.49153 > 10.1.2.4.9: UDP, length 1024
+ 2.006084 IP 10.1.2.4.9 > 10.1.3.3.49153: UDP, length 1024
+
+This is also the echo packet going from left to right (from Wifi to CSMA) and
+back again across the point-to-point link with slightly different timings
+as you might expect.
+
+The echo server is on the CSMA network, let's look at the promiscuous trace
+there:
+
+::
+
+ tcpdump -nn -tt -r third-1-1.pcap
+
+You should see some familiar looking contents:
+
+::
+
+ reading from file third-1-1.pcap, link-type EN10MB (Ethernet)
+ 2.005855 arp who-has 10.1.2.4 (ff:ff:ff:ff:ff:ff) tell 10.1.2.1
+ 2.005877 arp reply 10.1.2.4 is-at 00:00:00:00:00:06
+ 2.005877 IP 10.1.3.3.49153 > 10.1.2.4.9: UDP, length 1024
+ 2.005980 arp who-has 10.1.2.1 (ff:ff:ff:ff:ff:ff) tell 10.1.2.4
+ 2.005980 arp reply 10.1.2.1 is-at 00:00:00:00:00:03
+ 2.006084 IP 10.1.2.4.9 > 10.1.3.3.49153: UDP, length 1024
+
+This should be easily understood. If you've forgotten, go back and look at
+the discussion in ``second.cc``. This is the same sequence.
+
+Now, we spent a lot of time setting up mobility models for the wireless network
+and so it would be a shame to finish up without even showing that the STA
+nodes are actually moving around during the simulation. Let's do this by hooking
+into the ``MobilityModel`` course change trace source. This is just a sneak
+peek into the detailed tracing section which is coming up, but this seems a very
+nice place to get an example in.
+
+As mentioned in the "Tweaking ns-3" section, the |ns3| tracing system
+is divided into trace sources and trace sinks, and we provide functions to
+connect the two. We will use the mobility model predefined course change
+trace source to originate the trace events. We will need to write a trace
+sink to connect to that source that will display some pretty information for
+us. Despite its reputation as being difficult, it's really quite simple.
+Just before the main program of the ``scratch/mythird.cc`` script, add the
+following function:
+
+::
+
+ void
+ CourseChange (std::string context, Ptr<const MobilityModel> model)
+ {
+ Vector position = model->GetPosition ();
+ NS_LOG_UNCOND (context <<
+ " x = " << position.x << ", y = " << position.y);
+ }
+
+This code just pulls the position information from the mobility model and
+unconditionally logs the x and y position of the node. We are
+going to arrange for this function to be called every time the wireless
+node with the echo client changes its position. We do this using the
+``Config::Connect`` function. Add the following lines of code to the
+script just before the ``Simulator::Run`` call.
+
+::
+
+ std::ostringstream oss;
+ oss <<
+ "/NodeList/" << wifiStaNodes.Get (nWifi - 1)->GetId () <<
+ "/$ns3::MobilityModel/CourseChange";
+
+ Config::Connect (oss.str (), MakeCallback (&CourseChange));
+
+What we do here is to create a string containing the tracing namespace path
+of the event to which we want to connect. First, we have to figure out which
+node it is we want using the ``GetId`` method as described earlier. In the
+case of the default number of CSMA and wireless nodes, this turns out to be
+node seven and the tracing namespace path to the mobility model would look
+like,
+
+::
+
+ /NodeList/7/$ns3::MobilityModel/CourseChange
+
+Based on the discussion in the tracing section, you may infer that this trace
+path references the seventh node in the global NodeList. It specifies
+what is called an aggregated object of type ``ns3::MobilityModel``. The
+dollar sign prefix implies that the MobilityModel is aggregated to node seven.
+The last component of the path means that we are hooking into the
+"CourseChange" event of that model.
+
+We make a connection between the trace source in node seven with our trace
+sink by calling ``Config::Connect`` and passing this namespace path. Once
+this is done, every course change event on node seven will be hooked into our
+trace sink, which will in turn print out the new position.
+
+If you now run the simulation, you will see the course changes displayed as
+they happen.
+
+::
+
+ Build finished successfully (00:00:01)
+ /NodeList/7/$ns3::MobilityModel/CourseChange x = 10, y = 0
+ /NodeList/7/$ns3::MobilityModel/CourseChange x = 9.41539, y = -0.811313
+ /NodeList/7/$ns3::MobilityModel/CourseChange x = 8.46199, y = -1.11303
+ /NodeList/7/$ns3::MobilityModel/CourseChange x = 7.52738, y = -1.46869
+ /NodeList/7/$ns3::MobilityModel/CourseChange x = 6.67099, y = -1.98503
+ /NodeList/7/$ns3::MobilityModel/CourseChange x = 5.6835, y = -2.14268
+ /NodeList/7/$ns3::MobilityModel/CourseChange x = 4.70932, y = -1.91689
+ Sent 1024 bytes to 10.1.2.4
+ Received 1024 bytes from 10.1.3.3
+ Received 1024 bytes from 10.1.2.4
+ /NodeList/7/$ns3::MobilityModel/CourseChange x = 5.53175, y = -2.48576
+ /NodeList/7/$ns3::MobilityModel/CourseChange x = 4.58021, y = -2.17821
+ /NodeList/7/$ns3::MobilityModel/CourseChange x = 4.18915, y = -1.25785
+ /NodeList/7/$ns3::MobilityModel/CourseChange x = 4.7572, y = -0.434856
+ /NodeList/7/$ns3::MobilityModel/CourseChange x = 4.62404, y = 0.556238
+ /NodeList/7/$ns3::MobilityModel/CourseChange x = 4.74127, y = 1.54934
+ /NodeList/7/$ns3::MobilityModel/CourseChange x = 5.73934, y = 1.48729
+ /NodeList/7/$ns3::MobilityModel/CourseChange x = 6.18521, y = 0.59219
+ /NodeList/7/$ns3::MobilityModel/CourseChange x = 6.58121, y = 1.51044
+ /NodeList/7/$ns3::MobilityModel/CourseChange x = 7.27897, y = 2.22677
+ /NodeList/7/$ns3::MobilityModel/CourseChange x = 6.42888, y = 1.70014
+ /NodeList/7/$ns3::MobilityModel/CourseChange x = 7.40519, y = 1.91654
+ /NodeList/7/$ns3::MobilityModel/CourseChange x = 6.51981, y = 1.45166
+ /NodeList/7/$ns3::MobilityModel/CourseChange x = 7.34588, y = 2.01523
+ /NodeList/7/$ns3::MobilityModel/CourseChange x = 7.81046, y = 2.90077
+ /NodeList/7/$ns3::MobilityModel/CourseChange x = 6.89186, y = 3.29596
+ /NodeList/7/$ns3::MobilityModel/CourseChange x = 7.46617, y = 2.47732
+ /NodeList/7/$ns3::MobilityModel/CourseChange x = 7.05492, y = 1.56579
+ /NodeList/7/$ns3::MobilityModel/CourseChange x = 8.00393, y = 1.25054
+ /NodeList/7/$ns3::MobilityModel/CourseChange x = 7.00968, y = 1.35768
+ /NodeList/7/$ns3::MobilityModel/CourseChange x = 7.33503, y = 2.30328
+ /NodeList/7/$ns3::MobilityModel/CourseChange x = 7.18682, y = 3.29223
+ /NodeList/7/$ns3::MobilityModel/CourseChange x = 7.96865, y = 2.66873
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/tutorial/source/conceptual-overview.rst Sun Jan 02 22:57:32 2011 -0800
@@ -0,0 +1,840 @@
+.. include:: replace.txt
+
+
+Conceptual Overview
+-------------------
+
+The first thing we need to do before actually starting to look at or write
+|ns3| code is to explain a few core concepts and abstractions in the
+system. Much of this may appear transparently obvious to some, but we
+recommend taking the time to read through this section just to ensure you
+are starting on a firm foundation.
+
+Key Abstractions
+****************
+
+In this section, we'll review some terms that are commonly used in
+networking, but have a specific meaning in |ns3|.
+
+Node
+++++
+In Internet jargon, a computing device that connects to a network is called
+a *host* or sometimes an *end system*. Because |ns3| is a
+*network* simulator, not specifically an *Internet* simulator, we
+intentionally do not use the term host since it is closely associated with
+the Internet and its protocols. Instead, we use a more generic term also
+used by other simulators that originates in Graph Theory --- the *node*.
+
+In |ns3| the basic computing device abstraction is called the
+node. This abstraction is represented in C++ by the class ``Node``. The
+``Node`` class provides methods for managing the representations of
+computing devices in simulations.
+
+You should think of a ``Node`` as a computer to which you will add
+functionality. One adds things like applications, protocol stacks and
+peripheral cards with their associated drivers to enable the computer to do
+useful work. We use the same basic model in |ns3|.
+
+Application
++++++++++++
+Typically, computer software is divided into two broad classes. *System
+Software* organizes various computer resources such as memory, processor
+cycles, disk, network, etc., according to some computing model. System
+software usually does not use those resources to complete tasks that directly
+benefit a user. A user would typically run an *application* that acquires
+and uses the resources controlled by the system software to accomplish some
+goal.
+
+Often, the line of separation between system and application software is made
+at the privilege level change that happens in operating system traps.
+In |ns3| there is no real concept of operating system and especially
+no concept of privilege levels or system calls. We do, however, have the
+idea of an application. Just as software applications run on computers to
+perform tasks in the "real world," |ns3| applications run on
+|ns3| ``Nodes`` to drive simulations in the simulated world.
+
+In |ns3| the basic abstraction for a user program that generates some
+activity to be simulated is the application. This abstraction is represented
+in C++ by the class ``Application``. The ``Application`` class provides
+methods for managing the representations of our version of user-level
+applications in simulations. Developers are expected to specialize the
+``Application`` class in the object-oriented programming sense to create new
+applications. In this tutorial, we will use specializations of class
+``Application`` called ``UdpEchoClientApplication`` and
+``UdpEchoServerApplication``. As you might expect, these applications
+compose a client/server application set used to generate and echo simulated
+network packets
+
+Channel
++++++++
+
+In the real world, one can connect a computer to a network. Often the media
+over which data flows in these networks are called *channels*. When
+you connect your Ethernet cable to the plug in the wall, you are connecting
+your computer to an Ethernet communication channel. In the simulated world
+of |ns3|, one connects a ``Node`` to an object representing a
+communication channel. Here the basic communication subnetwork abstraction
+is called the channel and is represented in C++ by the class ``Channel``.
+
+The ``Channel`` class provides methods for managing communication
+subnetwork objects and connecting nodes to them. ``Channels`` may also be
+specialized by developers in the object oriented programming sense. A
+``Channel`` specialization may model something as simple as a wire. The
+specialized ``Channel`` can also model things as complicated as a large
+Ethernet switch, or three-dimensional space full of obstructions in the case
+of wireless networks.
+
+We will use specialized versions of the ``Channel`` called
+``CsmaChannel``, ``PointToPointChannel`` and ``WifiChannel`` in this
+tutorial. The ``CsmaChannel``, for example, models a version of a
+communication subnetwork that implements a *carrier sense multiple
+access* communication medium. This gives us Ethernet-like functionality.
+
+Net Device
+++++++++++
+It used to be the case that if you wanted to connect a computers to a network,
+you had to buy a specific kind of network cable and a hardware device called
+(in PC terminology) a *peripheral card* that needed to be installed in
+your computer. If the peripheral card implemented some networking function,
+they were called Network Interface Cards, or *NICs*. Today most
+computers come with the network interface hardware built in and users don't
+see these building blocks.
+
+A NIC will not work without a software driver to control the hardware. In
+Unix (or Linux), a piece of peripheral hardware is classified as a
+*device*. Devices are controlled using *device drivers*, and network
+devices (NICs) are controlled using *network device drivers*
+collectively known as *net devices*. In Unix and Linux you refer
+to these net devices by names such as *eth0*.
+
+In |ns3| the *net device* abstraction covers both the software
+driver and the simulated hardware. A net device is "installed" in a
+``Node`` in order to enable the ``Node`` to communicate with other
+``Nodes`` in the simulation via ``Channels``. Just as in a real
+computer, a ``Node`` may be connected to more than one ``Channel`` via
+multiple ``NetDevices``.
+
+The net device abstraction is represented in C++ by the class ``NetDevice``.
+The ``NetDevice`` class provides methods for managing connections to
+``Node`` and ``Channel`` objects; and may be specialized by developers
+in the object-oriented programming sense. We will use the several specialized
+versions of the ``NetDevice`` called ``CsmaNetDevice``,
+``PointToPointNetDevice``, and ``WifiNetDevice`` in this tutorial.
+Just as an Ethernet NIC is designed to work with an Ethernet network, the
+``CsmaNetDevice`` is designed to work with a ``CsmaChannel``; the
+``PointToPointNetDevice`` is designed to work with a
+``PointToPointChannel`` and a ``WifiNetNevice`` is designed to work with
+a ``WifiChannel``.
+
+Topology Helpers
+++++++++++++++++
+In a real network, you will find host computers with added (or built-in)
+NICs. In |ns3| we would say that you will find ``Nodes`` with
+attached ``NetDevices``. In a large simulated network you will need to
+arrange many connections between ``Nodes``, ``NetDevices`` and
+``Channels``.
+
+Since connecting ``NetDevices`` to ``Nodes``, ``NetDevices``
+to ``Channels``, assigning IP addresses, etc., are such common tasks
+in |ns3|, we provide what we call *topology helpers* to make
+this as easy as possible. For example, it may take many distinct
+|ns3| core operations to create a NetDevice, add a MAC address,
+install that net device on a ``Node``, configure the node's protocol stack,
+and then connect the ``NetDevice`` to a ``Channel``. Even more
+operations would be required to connect multiple devices onto multipoint
+channels and then to connect individual networks together into internetworks.
+We provide topology helper objects that combine those many distinct operations
+into an easy to use model for your convenience.
+
+A First ns-3 Script
+*******************
+If you downloaded the system as was suggested above, you will have a release
+of |ns3| in a directory called ``repos`` under your home
+directory. Change into that release directory, and you should find a
+directory structure something like the following:
+
+::
+
+ AUTHORS doc/ README src/ waf.bat*
+ bindings/ examples/ RELEASE_NOTES utils/ wscript
+ build/ LICENSE samples/ VERSION wutils.py
+ CHANGES.html ns3/ scratch/ waf* wutils.pyc
+
+Change into the ``examples/tutorial`` directory. You should see a file named
+``first.cc`` located there. This is a script that will create a simple
+point-to-point link between two nodes and echo a single packet between the
+nodes. Let's take a look at that script line by line, so go ahead and open
+``first.cc`` in your favorite editor.
+
+Boilerplate
++++++++++++
+The first line in the file is an emacs mode line. This tells emacs about the
+formatting conventions (coding style) we use in our source code.
+
+::
+
+ /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+
+This is always a somewhat controversial subject, so we might as well get it
+out of the way immediately. The |ns3| project, like most large
+projects, has adopted a coding style to which all contributed code must
+adhere. If you want to contribute your code to the project, you will
+eventually have to conform to the |ns3| coding standard as described
+in the file ``doc/codingstd.txt`` or shown on the project web page
+`here
+<http://www.nsnam.org/codingstyle.html>`_.
+
+We recommend that you, well, just get used to the look and feel of |ns3|
+code and adopt this standard whenever you are working with our code. All of
+the development team and contributors have done so with various amounts of
+grumbling. The emacs mode line above makes it easier to get the formatting
+correct if you use the emacs editor.
+
+The |ns3| simulator is licensed using the GNU General Public
+License. You will see the appropriate GNU legalese at the head of every file
+in the |ns3| distribution. Often you will see a copyright notice for
+one of the institutions involved in the |ns3| project above the GPL
+text and an author listed below.
+
+::
+
+ /*
+ * 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
+ */
+
+Module Includes
++++++++++++++++
+The code proper starts with a number of include statements.
+
+::
+
+ #include "ns3/core-module.h"
+ #include "ns3/simulator-module.h"
+ #include "ns3/node-module.h"
+ #include "ns3/helper-module.h"
+
+To help our high-level script users deal with the large number of include
+files present in the system, we group includes according to relatively large
+modules. We provide a single include file that will recursively load all of
+the include files used in each module. Rather than having to look up exactly
+what header you need, and possibly have to get a number of dependencies right,
+we give you the ability to load a group of files at a large granularity. This
+is not the most efficient approach but it certainly makes writing scripts much
+easier.
+
+Each of the |ns3| include files is placed in a directory called
+``ns3`` (under the build directory) during the build process to help avoid
+include file name collisions. The ``ns3/core-module.h`` file corresponds
+to the ns-3 module you will find in the directory ``src/core`` in your
+downloaded release distribution. If you list this directory you will find a
+large number of header files. When you do a build, Waf will place public
+header files in an ``ns3`` directory under the appropriate
+``build/debug`` or ``build/optimized`` directory depending on your
+configuration. Waf will also automatically generate a module include file to
+load all of the public header files.
+
+Since you are, of course, following this tutorial religiously, you will
+already have done a
+
+::
+
+ ./waf -d debug configure
+
+in order to configure the project to perform debug builds. You will also have
+done a
+
+::
+
+ ./waf
+
+to build the project. So now if you look in the directory
+``../../build/debug/ns3`` you will find the four module include files shown
+above. You can take a look at the contents of these files and find that they
+do include all of the public include files in their respective modules.
+
+Ns3 Namespace
++++++++++++++
+The next line in the ``first.cc`` script is a namespace declaration.
+
+::
+
+ using namespace ns3;
+
+The |ns3| project is implemented in a C++ namespace called
+``ns3``. This groups all |ns3|-related declarations in a scope
+outside the global namespace, which we hope will help with integration with
+other code. The C++ ``using`` statement introduces the |ns3|
+namespace into the current (global) declarative region. This is a fancy way
+of saying that after this declaration, you will not have to type ``ns3::``
+scope resolution operator before all of the |ns3| code in order to use
+it. If you are unfamiliar with namespaces, please consult almost any C++
+tutorial and compare the ``ns3`` namespace and usage here with instances of
+the ``std`` namespace and the ``using namespace std;`` statements you
+will often find in discussions of ``cout`` and streams.
+
+Logging
++++++++
+The next line of the script is the following,
+
+::
+
+ NS_LOG_COMPONENT_DEFINE ("FirstScriptExample");
+
+We will use this statement as a convenient place to talk about our Doxygen
+documentation system. If you look at the project web site,
+`ns-3 project
+<http://www.nsnam.org>`_, you will find a link to "Doxygen
+(ns-3-dev)" in the navigation bar. If you select this link, you will be
+taken to our documentation page for the current development release. There
+is also a link to "Doxygen (stable)" that will take you to the documentation
+for the latest stable release of |ns3|.
+
+Along the left side, you will find a graphical representation of the structure
+of the documentation. A good place to start is the ``NS-3 Modules``
+"book" in the |ns3| navigation tree. If you expand ``Modules``
+you will see a list of |ns3| module documentation. The concept of
+module here ties directly into the module include files discussed above. It
+turns out that the |ns3| logging subsystem is part of the ``core``
+module, so go ahead and expand that documentation node. Now, expand the
+``Debugging`` book and then select the ``Logging`` page.
+
+You should now be looking at the Doxygen documentation for the Logging module.
+In the list of ``#define``s at the top of the page you will see the entry
+for ``NS_LOG_COMPONENT_DEFINE``. Before jumping in, it would probably be
+good to look for the "Detailed Description" of the logging module to get a
+feel for the overall operation. You can either scroll down or select the
+"More..." link under the collaboration diagram to do this.
+
+Once you have a general idea of what is going on, go ahead and take a look at
+the specific ``NS_LOG_COMPONENT_DEFINE`` documentation. I won't duplicate
+the documentation here, but to summarize, this line declares a logging
+component called ``FirstScriptExample`` that allows you to enable and
+disable console message logging by reference to the name.
+
+Main Function
++++++++++++++
+The next lines of the script you will find are,
+
+::
+
+ int
+ main (int argc, char *argv[])
+ {
+
+This is just the declaration of the main function of your program (script).
+Just as in any C++ program, you need to define a main function that will be
+the first function run. There is nothing at all special here. Your
+|ns3| script is just a C++ program.
+
+The next two lines of the script are used to enable two logging components that
+are built into the Echo Client and Echo Server applications:
+
+::
+
+ LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_INFO);
+ LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_INFO);
+
+If you have read over the Logging component documentation you will have seen
+that there are a number of levels of logging verbosity/detail that you can
+enable on each component. These two lines of code enable debug logging at the
+INFO level for echo clients and servers. This will result in the application
+printing out messages as packets are sent and received during the simulation.
+
+Now we will get directly to the business of creating a topology and running
+a simulation. We use the topology helper objects to make this job as
+easy as possible.
+
+Topology Helpers
+++++++++++++++++
+NodeContainer
+~~~~~~~~~~~~~
+The next two lines of code in our script will actually create the
+|ns3| ``Node`` objects that will represent the computers in the
+simulation.
+
+::
+
+ NodeContainer nodes;
+ nodes.Create (2);
+
+Let's find the documentation for the ``NodeContainer`` class before we
+continue. Another way to get into the documentation for a given class is via
+the ``Classes`` tab in the Doxygen pages. If you still have the Doxygen
+handy, just scroll up to the top of the page and select the ``Classes``
+tab. You should see a new set of tabs appear, one of which is
+``Class List``. Under that tab you will see a list of all of the
+|ns3| classes. Scroll down, looking for ``ns3::NodeContainer``.
+When you find the class, go ahead and select it to go to the documentation for
+the class.
+
+You may recall that one of our key abstractions is the ``Node``. This
+represents a computer to which we are going to add things like protocol stacks,
+applications and peripheral cards. The ``NodeContainer`` topology helper
+provides a convenient way to create, manage and access any ``Node`` objects
+that we create in order to run a simulation. The first line above just
+declares a NodeContainer which we call ``nodes``. The second line calls the
+``Create`` method on the ``nodes`` object and asks the container to
+create two nodes. As described in the Doxygen, the container calls down into
+the |ns3| system proper to create two ``Node`` objects and stores
+pointers to those objects internally.
+
+The nodes as they stand in the script do nothing. The next step in
+constructing a topology is to connect our nodes together into a network.
+The simplest form of network we support is a single point-to-point link
+between two nodes. We'll construct one of those links here.
+
+PointToPointHelper
+~~~~~~~~~~~~~~~~~~
+We are constructing a point to point link, and, in a pattern which will become
+quite familiar to you, we use a topology helper object to do the low-level
+work required to put the link together. Recall that two of our key
+abstractions are the ``NetDevice`` and the ``Channel``. In the real
+world, these terms correspond roughly to peripheral cards and network cables.
+Typically these two things are intimately tied together and one cannot expect
+to interchange, for example, Ethernet devices and wireless channels. Our
+Topology Helpers follow this intimate coupling and therefore you will use a
+single ``PointToPointHelper`` to configure and connect |ns3|
+``PointToPointNetDevice`` and ``PointToPointChannel`` objects in this
+script.
+
+The next three lines in the script are,
+
+::
+
+ PointToPointHelper pointToPoint;
+ pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
+ pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
+
+The first line,
+
+::
+
+ PointToPointHelper pointToPoint;
+
+instantiates a ``PointToPointHelper`` object on the stack. From a
+high-level perspective the next line,
+
+::
+
+ pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
+
+tells the ``PointToPointHelper`` object to use the value "5Mbps"
+(five megabits per second) as the "DataRate" when it creates a
+``PointToPointNetDevice`` object.
+
+From a more detailed perspective, the string "DataRate" corresponds
+to what we call an ``Attribute`` of the ``PointToPointNetDevice``.
+If you look at the Doxygen for class ``ns3::PointToPointNetDevice`` and
+find the documentation for the ``GetTypeId`` method, you will find a list
+of ``Attributes`` defined for the device. Among these is the "DataRate"
+``Attribute``. Most user-visible |ns3| objects have similar lists of
+``Attributes``. We use this mechanism to easily configure simulations without
+recompiling as you will see in a following section.
+
+Similar to the "DataRate" on the ``PointToPointNetDevice`` you will find a
+"Delay" ``Attribute`` associated with the ``PointToPointChannel``. The
+final line,
+
+::
+
+ pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
+
+tells the ``PointToPointHelper`` to use the value "2ms" (two milliseconds)
+as the value of the transmission delay of every point to point channel it
+subsequently creates.
+
+NetDeviceContainer
+~~~~~~~~~~~~~~~~~~
+At this point in the script, we have a ``NodeContainer`` that contains
+two nodes. We have a ``PointToPointHelper`` that is primed and ready to
+make ``PointToPointNetDevices`` and wire ``PointToPointChannel`` objects
+between them. Just as we used the ``NodeContainer`` topology helper object
+to create the ``Nodes`` for our simulation, we will ask the
+``PointToPointHelper`` to do the work involved in creating, configuring and
+installing our devices for us. We will need to have a list of all of the
+NetDevice objects that are created, so we use a NetDeviceContainer to hold
+them just as we used a NodeContainer to hold the nodes we created. The
+following two lines of code,
+
+::
+
+ NetDeviceContainer devices;
+ devices = pointToPoint.Install (nodes);
+
+will finish configuring the devices and channel. The first line declares the
+device container mentioned above and the second does the heavy lifting. The
+``Install`` method of the ``PointToPointHelper`` takes a
+``NodeContainer`` as a parameter. Internally, a ``NetDeviceContainer``
+is created. For each node in the ``NodeContainer`` (there must be exactly
+two for a point-to-point link) a ``PointToPointNetDevice`` is created and
+saved in the device container. A ``PointToPointChannel`` is created and
+the two ``PointToPointNetDevices`` are attached. When objects are created
+by the ``PointToPointHelper``, the ``Attributes`` previously set in the
+helper are used to initialize the corresponding ``Attributes`` in the
+created objects.
+
+After executing the ``pointToPoint.Install (nodes)`` call we will have
+two nodes, each with an installed point-to-point net device and a single
+point-to-point channel between them. Both devices will be configured to
+transmit data at five megabits per second over the channel which has a two
+millisecond transmission delay.
+
+InternetStackHelper
+~~~~~~~~~~~~~~~~~~~
+We now have nodes and devices configured, but we don't have any protocol stacks
+installed on our nodes. The next two lines of code will take care of that.
+
+::
+
+ InternetStackHelper stack;
+ stack.Install (nodes);
+
+The ``InternetStackHelper`` is a topology helper that is to internet stacks
+what the ``PointToPointHelper`` is to point-to-point net devices. The
+``Install`` method takes a ``NodeContainer`` as a parameter. When it is
+executed, it will install an Internet Stack (TCP, UDP, IP, etc.) on each of
+the nodes in the node container.
+
+Ipv4AddressHelper
+~~~~~~~~~~~~~~~~~
+Next we need to associate the devices on our nodes with IP addresses. We
+provide a topology helper to manage the allocation of IP addresses. The only
+user-visible API is to set the base IP address and network mask to use when
+performing the actual address allocation (which is done at a lower level
+inside the helper).
+
+The next two lines of code in our example script, ``first.cc``,
+
+::
+
+ Ipv4AddressHelper address;
+ address.SetBase ("10.1.1.0", "255.255.255.0");
+
+declare an address helper object and tell it that it should begin allocating IP
+addresses from the network 10.1.1.0 using the mask 255.255.255.0 to define
+the allocatable bits. By default the addresses allocated will start at one
+and increase monotonically, so the first address allocated from this base will
+be 10.1.1.1, followed by 10.1.1.2, etc. The low level |ns3| system
+actually remembers all of the IP addresses allocated and will generate a
+fatal error if you accidentally cause the same address to be generated twice
+(which is a very hard to debug error, by the way).
+
+The next line of code,
+
+::
+
+ Ipv4InterfaceContainer interfaces = address.Assign (devices);
+
+performs the actual address assignment. In |ns3| we make the
+association between an IP address and a device using an ``Ipv4Interface``
+object. Just as we sometimes need a list of net devices created by a helper
+for future reference we sometimes need a list of ``Ipv4Interface`` objects.
+The ``Ipv4InterfaceContainer`` provides this functionality.
+
+Now we have a point-to-point network built, with stacks installed and IP
+addresses assigned. What we need at this point are applications to generate
+traffic.
+
+Applications
+++++++++++++
+Another one of the core abstractions of the ns-3 system is the
+``Application``. In this script we use two specializations of the core
+|ns3| class ``Application`` called ``UdpEchoServerApplication``
+and ``UdpEchoClientApplication``. Just as we have in our previous
+explanations, we use helper objects to help configure and manage the
+underlying objects. Here, we use ``UdpEchoServerHelper`` and
+``UdpEchoClientHelper`` objects to make our lives easier.
+
+UdpEchoServerHelper
+~~~~~~~~~~~~~~~~~~~
+The following lines of code in our example script, ``first.cc``, are used
+to set up a UDP echo server application on one of the nodes we have previously
+created.
+
+::
+
+ UdpEchoServerHelper echoServer (9);
+
+ ApplicationContainer serverApps = echoServer.Install (nodes.Get (1));
+ serverApps.Start (Seconds (1.0));
+ serverApps.Stop (Seconds (10.0));
+
+The first line of code in the above snippet declares the
+``UdpEchoServerHelper``. As usual, this isn't the application itself, it
+is an object used to help us create the actual applications. One of our
+conventions is to place *required* ``Attributes`` in the helper constructor.
+In this case, the helper can't do anything useful unless it is provided with
+a port number that the client also knows about. Rather than just picking one
+and hoping it all works out, we require the port number as a parameter to the
+constructor. The constructor, in turn, simply does a ``SetAttribute``
+with the passed value. If you want, you can set the "Port" ``Attribute``
+to another value later using ``SetAttribute``.
+
+Similar to many other helper objects, the ``UdpEchoServerHelper`` object
+has an ``Install`` method. It is the execution of this method that actually
+causes the underlying echo server application to be instantiated and attached
+to a node. Interestingly, the ``Install`` method takes a
+``NodeContainter`` as a parameter just as the other ``Install`` methods
+we have seen. This is actually what is passed to the method even though it
+doesn't look so in this case. There is a C++ *implicit conversion* at
+work here that takes the result of ``nodes.Get (1)`` (which returns a smart
+pointer to a node object --- ``Ptr<Node>``) and uses that in a constructor
+for an unnamed ``NodeContainer`` that is then passed to ``Install``.
+If you are ever at a loss to find a particular method signature in C++ code
+that compiles and runs just fine, look for these kinds of implicit conversions.
+
+We now see that ``echoServer.Install`` is going to install a
+``UdpEchoServerApplication`` on the node found at index number one of the
+``NodeContainer`` we used to manage our nodes. ``Install`` will return
+a container that holds pointers to all of the applications (one in this case
+since we passed a ``NodeContainer`` containing one node) created by the
+helper.
+
+Applications require a time to "start" generating traffic and may take an
+optional time to "stop". We provide both. These times are set using the
+``ApplicationContainer`` methods ``Start`` and ``Stop``. These
+methods take ``Time`` parameters. In this case, we use an *explicit*
+C++ conversion sequence to take the C++ double 1.0 and convert it to an
+|ns3| ``Time`` object using a ``Seconds`` cast. Be aware that
+the conversion rules may be controlled by the model author, and C++ has its
+own rules, so you can't always just assume that parameters will be happily
+converted for you. The two lines,
+
+::
+
+ serverApps.Start (Seconds (1.0));
+ serverApps.Stop (Seconds (10.0));
+
+will cause the echo server application to ``Start`` (enable itself) at one
+second into the simulation and to ``Stop`` (disable itself) at ten seconds
+into the simulation. By virtue of the fact that we have declared a simulation
+event (the application stop event) to be executed at ten seconds, the simulation
+will last *at least* ten seconds.
+
+UdpEchoClientHelper
+~~~~~~~~~~~~~~~~~~~
+
+The echo client application is set up in a method substantially similar to
+that for the server. There is an underlying ``UdpEchoClientApplication``
+that is managed by an ``UdpEchoClientHelper``.
+
+::
+
+ UdpEchoClientHelper echoClient (interfaces.GetAddress (1), 9);
+ echoClient.SetAttribute ("MaxPackets", UintegerValue (1));
+ echoClient.SetAttribute ("Interval", TimeValue (Seconds (1.)));
+ echoClient.SetAttribute ("PacketSize", UintegerValue (1024));
+
+ ApplicationContainer clientApps = echoClient.Install (nodes.Get (0));
+ clientApps.Start (Seconds (2.0));
+ clientApps.Stop (Seconds (10.0));
+
+For the echo client, however, we need to set five different ``Attributes``.
+The first two ``Attributes`` are set during construction of the
+``UdpEchoClientHelper``. We pass parameters that are used (internally to
+the helper) to set the "RemoteAddress" and "RemotePort" ``Attributes``
+in accordance with our convention to make required ``Attributes`` parameters
+in the helper constructors.
+
+Recall that we used an ``Ipv4InterfaceContainer`` to keep track of the IP
+addresses we assigned to our devices. The zeroth interface in the
+``interfaces`` container is going to correspond to the IP address of the
+zeroth node in the ``nodes`` container. The first interface in the
+``interfaces`` container corresponds to the IP address of the first node
+in the ``nodes`` container. So, in the first line of code (from above), we
+are creating the helper and telling it so set the remote address of the client
+to be the IP address assigned to the node on which the server resides. We
+also tell it to arrange to send packets to port nine.
+
+The "MaxPackets" ``Attribute`` tells the client the maximum number of
+packets we allow it to send during the simulation. The "Interval"
+``Attribute`` tells the client how long to wait between packets, and the
+"PacketSize" ``Attribute`` tells the client how large its packet payloads
+should be. With this particular combination of ``Attributes``, we are
+telling the client to send one 1024-byte packet.
+
+Just as in the case of the echo server, we tell the echo client to ``Start``
+and ``Stop``, but here we start the client one second after the server is
+enabled (at two seconds into the simulation).
+
+Simulator
++++++++++
+What we need to do at this point is to actually run the simulation. This is
+done using the global function ``Simulator::Run``.
+
+::
+
+ Simulator::Run ();
+
+When we previously called the methods,
+
+::
+
+ serverApps.Start (Seconds (1.0));
+ serverApps.Stop (Seconds (10.0));
+ ...
+ clientApps.Start (Seconds (2.0));
+ clientApps.Stop (Seconds (10.0));
+
+we actually scheduled events in the simulator at 1.0 seconds, 2.0 seconds and
+two events at 10.0 seconds. When ``Simulator::Run`` is called, the system
+will begin looking through the list of scheduled events and executing them.
+First it will run the event at 1.0 seconds, which will enable the echo server
+application (this event may, in turn, schedule many other events). Then it
+will run the event scheduled for t=2.0 seconds which will start the echo client
+application. Again, this event may schedule many more events. The start event
+implementation in the echo client application will begin the data transfer phase
+of the simulation by sending a packet to the server.
+
+The act of sending the packet to the server will trigger a chain of events
+that will be automatically scheduled behind the scenes and which will perform
+the mechanics of the packet echo according to the various timing parameters
+that we have set in the script.
+
+Eventually, since we only send one packet (recall the ``MaxPackets``
+``Attribute`` was set to one), the chain of events triggered by
+that single client echo request will taper off and the simulation will go
+idle. Once this happens, the remaining events will be the ``Stop`` events
+for the server and the client. When these events are executed, there are
+no further events to process and ``Simulator::Run`` returns. The simulation
+is then complete.
+
+All that remains is to clean up. This is done by calling the global function
+``Simulator::Destroy``. As the helper functions (or low level
+|ns3| code) executed, they arranged it so that hooks were inserted in
+the simulator to destroy all of the objects that were created. You did not
+have to keep track of any of these objects yourself --- all you had to do
+was to call ``Simulator::Destroy`` and exit. The |ns3| system
+took care of the hard part for you. The remaining lines of our first
+|ns3| script, ``first.cc``, do just that:
+
+::
+
+ Simulator::Destroy ();
+ return 0;
+ }
+
+Building Your Script
+++++++++++++++++++++
+We have made it trivial to build your simple scripts. All you have to do is
+to drop your script into the scratch directory and it will automatically be
+built if you run Waf. Let's try it. Copy ``examples/tutorial/first.cc`` into
+the ``scratch`` directory after changing back into the top level directory.
+
+::
+
+ cd ..
+ cp examples/tutorial/first.cc scratch/myfirst.cc
+
+Now build your first example script using waf:
+
+::
+
+ ./waf
+
+You should see messages reporting that your ``myfirst`` example was built
+successfully.
+
+::
+
+ Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
+ [614/708] cxx: scratch/myfirst.cc -> build/debug/scratch/myfirst_3.o
+ [706/708] cxx_link: build/debug/scratch/myfirst_3.o -> build/debug/scratch/myfirst
+ Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
+ 'build' finished successfully (2.357s)
+
+You can now run the example (note that if you build your program in the scratch
+directory you must run it out of the scratch directory):
+
+::
+
+ ./waf --run scratch/myfirst
+
+You should see some output:
+
+::
+
+ Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
+ Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
+ 'build' finished successfully (0.418s)
+ Sent 1024 bytes to 10.1.1.2
+ Received 1024 bytes from 10.1.1.1
+ Received 1024 bytes from 10.1.1.2
+
+Here you see that the build system checks to make sure that the file has been
+build and then runs it. You see the logging component on the echo client
+indicate that it has sent one 1024 byte packet to the Echo Server on
+10.1.1.2. You also see the logging component on the echo server say that
+it has received the 1024 bytes from 10.1.1.1. The echo server silently
+echoes the packet and you see the echo client log that it has received its
+packet back from the server.
+
+Ns-3 Source Code
+****************
+
+Now that you have used some of the |ns3| helpers you may want to
+have a look at some of the source code that implements that functionality.
+The most recent code can be browsed on our web server at the following link:
+http://code.nsnam.org/ns-3-dev. There, you will see the Mercurial
+summary page for our |ns3| development tree.
+
+At the top of the page, you will see a number of links,
+
+::
+
+ summary | shortlog | changelog | graph | tags | files
+
+Go ahead and select the ``files`` link. This is what the top-level of
+most of our *repositories* will look:
+
+::
+
+ drwxr-xr-x [up]
+ drwxr-xr-x bindings python files
+ drwxr-xr-x doc files
+ drwxr-xr-x examples files
+ drwxr-xr-x ns3 files
+ drwxr-xr-x samples files
+ drwxr-xr-x scratch files
+ drwxr-xr-x src files
+ drwxr-xr-x utils files
+ -rw-r--r-- 2009-07-01 12:47 +0200 560 .hgignore file | revisions | annotate
+ -rw-r--r-- 2009-07-01 12:47 +0200 1886 .hgtags file | revisions | annotate
+ -rw-r--r-- 2009-07-01 12:47 +0200 1276 AUTHORS file | revisions | annotate
+ -rw-r--r-- 2009-07-01 12:47 +0200 30961 CHANGES.html file | revisions | annotate
+ -rw-r--r-- 2009-07-01 12:47 +0200 17987 LICENSE file | revisions | annotate
+ -rw-r--r-- 2009-07-01 12:47 +0200 3742 README file | revisions | annotate
+ -rw-r--r-- 2009-07-01 12:47 +0200 16171 RELEASE_NOTES file | revisions | annotate
+ -rw-r--r-- 2009-07-01 12:47 +0200 6 VERSION file | revisions | annotate
+ -rwxr-xr-x 2009-07-01 12:47 +0200 88110 waf file | revisions | annotate
+ -rwxr-xr-x 2009-07-01 12:47 +0200 28 waf.bat file | revisions | annotate
+ -rw-r--r-- 2009-07-01 12:47 +0200 35395 wscript file | revisions | annotate
+ -rw-r--r-- 2009-07-01 12:47 +0200 7673 wutils.py file | revisions | annotate
+
+Our example scripts are in the ``examples`` directory. If you click on ``examples``
+you will see a list of files. One of the files in that directory is ``first.cc``. If
+you click on ``first.cc`` you will find the code you just walked through.
+
+The source code is mainly in the ``src`` directory. You can view source
+code either by clicking on the directory name or by clicking on the ``files``
+link to the right of the directory name. If you click on the ``src``
+directory, you will be taken to the listing of the ``src`` subdirectories. If you
+then click on ``core`` subdirectory, you will find a list of files. The first file
+you will find (as of this writing) is ``abort.h``. If you click on the
+``abort.h`` link, you will be sent to the source file for ``abort.h`` which
+contains useful macros for exiting scripts if abnormal conditions are detected.
+
+The source code for the helpers we have used in this chapter can be found in the
+``src/helper`` directory. Feel free to poke around in the directory tree to
+get a feel for what is there and the style of |ns3| programs.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/tutorial/source/conclusion.rst Sun Jan 02 22:57:32 2011 -0800
@@ -0,0 +1,37 @@
+.. include:: replace.txt
+
+
+Conclusion
+----------
+
+Futures
+*******
+
+This document is a work in process. We hope and expect it to grow over time
+to cover more and more of the nuts and bolts of |ns3|.
+
+We hope to add the following chapters over the next few releases:
+
+* The Callback System
+* The Object System and Memory Management
+* The Routing System
+* Adding a New NetDevice and Channel
+* Adding a New Protocol
+* Working with Real Networks and Hosts
+
+Writing manual and tutorial chapters is not something we all get excited about,
+but it is very important to the project. If you are an expert in one of these
+areas, please consider contributing to |ns3| by providing one of these
+chapters; or any other chapter you may think is important.
+
+Closing
+*******
+
+|ns3| is a large and complicated system. It is impossible to cover all
+of the things you will need to know in one small tutorial.
+
+We have really just scratched the surface of |ns3| in this tutorial,
+but we hope to have covered enough to get you started doing useful networking
+research using our favorite simulator.
+
+-- The |ns3| development team.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/tutorial/source/conf.py Sun Jan 02 22:57:32 2011 -0800
@@ -0,0 +1,216 @@
+# -*- coding: utf-8 -*-
+#
+# ns-3 documentation build configuration file, created by
+# sphinx-quickstart on Tue Dec 14 09:00:39 2010.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys, os
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#sys.path.insert(0, os.path.abspath('.'))
+
+# -- General configuration -----------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['sphinx.ext.pngmath']
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'ns-3'
+copyright = u'2010, ns-3 project'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = 'ns-3.10'
+# The full version, including alpha/beta/rc tags.
+release = 'ns-3.10'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = []
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+
+# -- Options for HTML output ---------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+html_theme = 'default'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further. For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents. If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar. Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it. The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'ns-3doc'
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+# The paper size ('letter' or 'a4').
+#latex_paper_size = 'letter'
+
+# The font size ('10pt', '11pt' or '12pt').
+#latex_font_size = '10pt'
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+ ('index', 'ns-3.tex', u'ns-3 Tutorial',
+ u'ns-3 project', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Additional stuff for the LaTeX preamble.
+#latex_preamble = ''
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output --------------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+ ('index', 'ns-3', u'ns-3 Tutorial',
+ [u'ns-3 project'], 1)
+]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/tutorial/source/figures Sun Jan 02 22:57:32 2011 -0800
@@ -0,0 +1,1 @@
+../figures
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/tutorial/source/getting-started.rst Sun Jan 02 22:57:32 2011 -0800
@@ -0,0 +1,512 @@
+ .. include:: replace.txt
+
+
+Getting Started
+---------------
+
+Downloading ns-3
+****************
+
+The |ns3| system as a whole is a fairly complex system and has a
+number of dependencies on other components. Along with the systems you will
+most likely deal with every day (the GNU toolchain, Mercurial, you programmer
+editor) you will need to ensure that a number of additional libraries are
+present on your system before proceeding. |ns3| provides a wiki
+for your reading pleasure that includes pages with many useful hints and tips.
+One such page is the "Installation" page,
+http://www.nsnam.org/wiki/index.php/Installation.
+
+The "Prerequisites" section of this wiki page explains which packages are
+required to support common |ns3| options, and also provides the
+commands used to install them for common Linux variants. Cygwin users will
+have to use the Cygwin installer (if you are a Cygwin user, you used it to
+install Cygwin).
+
+You may want to take this opportunity to explore the |ns3| wiki
+a bit since there really is a wealth of information there.
+
+From this point forward, we are going to assume that the reader is working in
+Linux or a Linux emulation environment (Linux, Cygwin, etc.) and has the GNU
+toolchain installed and verified along with the prerequisites mentioned
+above. We are also going to assume that you have Mercurial and Waf installed
+and running on the target system as described in the "Getting Started" section
+of the |ns3| web site:
+http://www.nsnam.org/getting_started.html.
+
+The |ns3| code is available in Mercurial repositories on the server
+http://code.nsnam.org. You can also download a tarball release at
+http://www.nsnam.org/releases/, or you can work with repositories
+using Mercurial. We recommend using Mercurial unless there's a good reason
+not to. See the end of this section for instructions on how to get a tarball
+release.
+
+The simplest way to get started using Mercurial repositories is to use the
+``ns-3-allinone`` environment. This is a set of scripts that manages the
+downloading and building of various subsystems of |ns3| for you. We
+recommend that you begin your |ns3| adventures in this environment
+as it can really simplify your life at this point.
+
+Downloading ns-3 Using Mercurial
+++++++++++++++++++++++++++++++++
+One practice is to create a directory called ``repos`` in one's home
+directory under which one can keep local Mercurial repositories.
+*Hint: we will assume you do this later in the tutorial.* If you adopt
+that approach, you can get a copy of ``ns-3-allinone`` by typing the
+following into your Linux shell (assuming you have installed Mercurial):
+
+::
+
+ cd
+ mkdir repos
+ cd repos
+ hg clone http://code.nsnam.org/ns-3-allinone
+
+As the hg (Mercurial) command executes, you should see something like the
+following displayed,
+
+::
+
+ destination directory: ns-3-allinone
+ requesting all changes
+ adding changesets
+ adding manifests
+ adding file changes
+ added 31 changesets with 45 changes to 7 files
+ 7 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+After the clone command completes, you should have a directory called
+``ns-3-allinone`` under your ``~/repos`` directory, the contents of which should
+look something like the following:
+
+::
+
+ build.py* constants.py dist.py* download.py* README util.py
+
+Notice that you really just downloaded some Python scripts. The next step
+will be to use those scripts to download and build the |ns3|
+distribution of your choice.
+
+If you go to the following link: http://code.nsnam.org/,
+you will see a number of repositories. Many are the private repositories of
+the |ns3| development team. The repositories of interest to you will
+be prefixed with "ns-3". Official releases of |ns3| will be
+numbered as ``ns-3.<release>.<hotfix>``. For example, a second hotfix to a
+still hypothetical release nine of |ns3| would be numbered as
+``ns-3.9.2``.
+
+The current development snapshot (unreleased) of |ns3| may be found
+at http://code.nsnam.org/ns-3-dev/. The
+developers attempt to keep these repository in consistent, working states but
+they are in a development area with unreleased code present, so you may want
+to consider staying with an official release if you do not need newly-
+introduced features.
+
+Since the release numbers are going to be changing, I will stick with
+the more constant ns-3-dev here in the tutorial, but you can replace the
+string "ns-3-dev" with your choice of release (e.g., ns-3.10) in the
+text below. You can find the latest version of the
+code either by inspection of the repository list or by going to the
+`"Getting Started"
+<http://www.nsnam.org/getting_started.html>`_
+web page and looking for the latest release identifier.
+
+Go ahead and change into the ``ns-3-allinone`` directory you created when
+you cloned that repository. We are now going to use the ``download.py``
+script to pull down the various pieces of |ns3| you will be using.
+
+Go ahead and type the following into your shell (remember you can substitute
+the name of your chosen release number instead of ``ns-3-dev`` -- like
+``"ns-3.10"`` if you want to work with a
+stable release).
+
+::
+
+ ./download.py -n ns-3-dev
+
+Note that the default for the ``-n`` option is ``ns-3-dev`` and so the
+above is actually redundant. We provide this example to illustrate how to
+specify alternate repositories. In order to download ``ns-3-dev`` you
+can actually use the defaults and simply type,
+
+::
+
+ ./download.py
+
+As the hg (Mercurial) command executes, you should see something like the
+following,
+
+::
+
+ #
+ # Get NS-3
+ #
+
+ Cloning ns-3 branch
+ => hg clone http://code.nsnam.org/ns-3-dev ns-3-dev
+ requesting all changes
+ adding changesets
+ adding manifests
+ adding file changes
+ added 4634 changesets with 16500 changes to 1762 files
+ 870 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+This is output by the download script as it fetches the actual ``ns-3``
+code from the repository.
+
+The download script is smart enough to know that on some platforms various
+pieces of ns-3 are not supported. On your platform you may not see some
+of these pieces come down. However, on most platforms, the process should
+continue with something like,
+
+::
+
+ #
+ # Get PyBindGen
+ #
+
+ Required pybindgen version: 0.10.0.640
+ Trying to fetch pybindgen; this will fail if no network connection is available. Hit Ctrl-C to skip.
+ => bzr checkout -rrevno:640 https://launchpad.net/pybindgen pybindgen
+ Fetch was successful.
+
+This was the download script getting the Python bindings generator for you.
+Note that you will need bazaar (bzr), a version control system, to download
+PyBindGen. Next you should see (modulo platform variations) something along
+the lines of,
+
+::
+
+ #
+ # Get NSC
+ #
+
+ Required NSC version: nsc-0.5.0
+ Retrieving nsc from https://secure.wand.net.nz/mercurial/nsc
+ => hg clone https://secure.wand.net.nz/mercurial/nsc nsc
+ requesting all changes
+ adding changesets
+ adding manifests
+ adding file changes
+ added 273 changesets with 17565 changes to 15175 files
+ 10622 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+This part of the process is the script downloading the Network Simulation
+Cradle for you. Note that NSC is not supported on OSX or Cygwin and works
+best with gcc-3.4 or gcc-4.2 or greater series.
+
+After the download.py script completes, you should have several new directories
+under ``~/repos/ns-3-allinone``:
+
+::
+
+ build.py* constants.pyc download.py* nsc/ README util.pyc
+ constants.py dist.py* ns-3-dev/ pybindgen/ util.py
+
+Go ahead and change into ``ns-3-dev`` under your ``~/repos/ns-3-allinone``
+directory. You should see something like the following there:
+
+::
+
+ AUTHORS examples/ RELEASE_NOTES utils/ wscript
+ bindings/ LICENSE samples/ VERSION wutils.py
+ CHANGES.html ns3/ scratch/ waf*
+ doc/ README src/ waf.bat*
+
+You are now ready to build the |ns3| distribution.
+
+Downloading ns-3 Using a Tarball
+++++++++++++++++++++++++++++++++
+The process for downloading |ns3| via tarball is simpler than the
+Mercurial process since all of the pieces are pre-packaged for you. You just
+have to pick a release, download it and decompress it.
+
+As mentioned above, one practice is to create a directory called ``repos``
+in one's home directory under which one can keep local Mercurial repositories.
+One could also keep a ``tarballs`` directory. *Hint: the tutorial
+will assume you downloaded into a ``repos`` directory, so remember the
+placekeeper.``* If you adopt the ``tarballs`` directory approach, you can
+get a copy of a release by typing the following into your Linux shell
+(substitute the appropriate version numbers, of course):
+
+::
+
+ cd
+ mkdir tarballs
+ cd tarballs
+ wget http://www.nsnam.org/releases/ns-allinone-3.10.tar.bz2
+ tar xjf ns-allinone-3.10.tar.bz2
+
+If you change into the directory ``ns-allinone-3.10`` you should see a
+number of files:
+
+::
+
+ build.py ns-3.10/ pybindgen-0.15.0/ util.py
+ constants.py nsc-0.5.2/ README
+
+You are now ready to build the |ns3| distribution.
+
+Building ns-3
+*************
+
+Building with build.py
+++++++++++++++++++++++
+The first time you build the |ns3| project you should build using the
+``allinone`` environment. This will get the project configured for you
+in the most commonly useful way.
+
+Change into the directory you created in the download section above. If you
+downloaded using Mercurial you should have a directory called
+``ns-3-allinone`` under your ``~/repos`` directory. If you downloaded
+using a tarball you should have a directory called something like
+``ns-allinone-3.10`` under your ``~/tarballs`` directory. Take a deep
+breath and type the following:
+
+::
+
+ ./build.py
+
+You will see lots of typical compiler output messages displayed as the build
+script builds the various pieces you downloaded. Eventually you should see the
+following magic words:
+
+::
+
+ Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
+ 'build' finished successfully (2m30.586s)
+
+Once the project has built you can say goodbye to your old friends, the
+``ns-3-allinone`` scripts. You got what you needed from them and will now
+interact directly with Waf and we do it in the ``ns-3-dev`` directory,
+not in the ``ns-3-allinone`` directory. Go ahead and change into the
+``ns-3-dev`` directory (or the directory for the appropriate release you
+downloaded.
+
+::
+
+ cd ns-3-dev
+
+Building with Waf
++++++++++++++++++
+We use Waf to configure and build the |ns3| project. It's not
+strictly required at this point, but it will be valuable to take a slight
+detour and look at how to make changes to the configuration of the project.
+Probably the most useful configuration change you can make will be to
+build the optimized version of the code. By default you have configured
+your project to build the debug version. Let's tell the project to do
+make an optimized build. To explain to Waf that it should do optimized
+builds you will need to execute the following command,
+
+::
+
+ ./waf -d optimized configure
+
+This runs Waf out of the local directory (which is provided as a convenience
+for you). As the build system checks for various dependencies you should see
+output that looks similar to the following,
+
+::
+
+ Checking for program g++ : ok /usr/bin/g++
+ Checking for program cpp : ok /usr/bin/cpp
+ Checking for program ar : ok /usr/bin/ar
+ Checking for program ranlib : ok /usr/bin/ranlib
+ Checking for g++ : ok
+ Checking for program pkg-config : ok /usr/bin/pkg-config
+ Checking for -Wno-error=deprecated-declarations support : yes
+ Checking for -Wl,--soname=foo support : yes
+ Checking for header stdlib.h : ok
+ Checking for header signal.h : ok
+ Checking for header pthread.h : ok
+ Checking for high precision time implementation : 128-bit integer
+ Checking for header stdint.h : ok
+ Checking for header inttypes.h : ok
+ Checking for header sys/inttypes.h : not found
+ Checking for library rt : ok
+ Checking for header netpacket/packet.h : ok
+ Checking for pkg-config flags for GSL : ok
+ Checking for header linux/if_tun.h : ok
+ Checking for pkg-config flags for GTK_CONFIG_STORE : ok
+ Checking for pkg-config flags for LIBXML2 : ok
+ Checking for library sqlite3 : ok
+ Checking for NSC location : ok ../nsc (guessed)
+ Checking for library dl : ok
+ Checking for NSC supported architecture x86_64 : ok
+ Checking for program python : ok /usr/bin/python
+ Checking for Python version >= 2.3 : ok 2.5.2
+ Checking for library python2.5 : ok
+ Checking for program python2.5-config : ok /usr/bin/python2.5-config
+ Checking for header Python.h : ok
+ Checking for -fvisibility=hidden support : yes
+ Checking for pybindgen location : ok ../pybindgen (guessed)
+ Checking for Python module pybindgen : ok
+ Checking for pybindgen version : ok 0.10.0.640
+ Checking for Python module pygccxml : ok
+ Checking for pygccxml version : ok 0.9.5
+ Checking for program gccxml : ok /usr/local/bin/gccxml
+ Checking for gccxml version : ok 0.9.0
+ Checking for program sudo : ok /usr/bin/sudo
+ Checking for program hg : ok /usr/bin/hg
+ Checking for program valgrind : ok /usr/bin/valgrind
+ ---- Summary of optional NS-3 features:
+ Threading Primitives : enabled
+ Real Time Simulator : enabled
+ Emulated Net Device : enabled
+ GNU Scientific Library (GSL) : enabled
+ Tap Bridge : enabled
+ GtkConfigStore : enabled
+ XmlIo : enabled
+ SQlite stats data output : enabled
+ Network Simulation Cradle : enabled
+ Python Bindings : enabled
+ Python API Scanning Support : enabled
+ Use sudo to set suid bit : not enabled (option --enable-sudo not selected)
+ Build examples and samples : enabled
+ Static build : not enabled (option --enable-static not selected)
+ 'configure' finished successfully (2.870s)
+
+Note the last part of the above output. Some ns-3 options are not enabled by
+default or require support from the underlying system to work properly.
+For instance, to enable XmlTo, the library libxml-2.0 must be found on the
+system. If this library were not found, the corresponding |ns3| feature
+would not be enabled and a message would be displayed. Note further that there is
+a feature to use the program ``sudo`` to set the suid bit of certain programs.
+This is not enabled by default and so this feature is reported as "not enabled."
+
+Now go ahead and switch back to the debug build.
+
+::
+
+ ./waf -d debug configure
+
+The build system is now configured and you can build the debug versions of
+the |ns3| programs by simply typing,
+
+::
+
+ ./waf
+
+Some waf commands are meaningful during the build phase and some commands are valid
+in the configuration phase. For example, if you wanted to use the emulation
+features of |ns3| you might want to enable setting the suid bit using
+sudo as described above. This turns out to be a configuration-time command, and so
+you could reconfigure using the following command
+
+::
+
+ ./waf -d debug --enable-sudo configure
+
+If you do this, waf will have run sudo to change the socket creator programs of the
+emulation code to run as root. There are many other configure- and build-time options
+available in waf. To explore these options, type:
+
+::
+
+ ./waf --help
+
+We'll use some of the testing-related commands in the next section.
+
+Okay, sorry, I made you build the |ns3| part of the system twice,
+but now you know how to change the configuration and build optimized code.
+
+Testing ns-3
+************
+
+You can run the unit tests of the |ns3| distribution by running the
+"./test.py -c core" script,
+
+::
+
+ ./test.py -c core
+
+These tests are run in parallel by waf. You should eventually
+see a report saying that,
+
+::
+
+ 47 of 47 tests passed (47 passed, 0 failed, 0 crashed, 0 valgrind errors)
+
+This is the important message.
+
+You will also see output from the test runner and the output will actually look something like,
+
+::
+
+ Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
+ Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
+ 'build' finished successfully (1.799s)
+ PASS: TestSuite ns3-wifi-interference
+ PASS: TestSuite histogram
+ PASS: TestSuite sample
+ PASS: TestSuite ipv4-address-helper
+ PASS: TestSuite devices-wifi
+ PASS: TestSuite propagation-loss-model
+
+ ...
+
+ PASS: TestSuite attributes
+ PASS: TestSuite config
+ PASS: TestSuite global-value
+ PASS: TestSuite command-line
+ PASS: TestSuite basic-random-number
+ PASS: TestSuite object
+ PASS: TestSuite random-number-generators
+ 47 of 47 tests passed (47 passed, 0 failed, 0 crashed, 0 valgrind errors)
+
+This command is typically run by ``users`` to quickly verify that an
+|ns3| distribution has built correctly.
+
+Running a Script
+****************
+We typically run scripts under the control of Waf. This allows the build
+system to ensure that the shared library paths are set correctly and that
+the libraries are available at run time. To run a program, simply use the
+``--run`` option in Waf. Let's run the |ns3| equivalent of the
+ubiquitous hello world program by typing the following:
+
+::
+
+ ./waf --run hello-simulator
+
+Waf first checks to make sure that the program is built correctly and
+executes a build if required. Waf then executes the program, which
+produces the following output.
+
+::
+
+ Hello Simulator
+
+*Congratulations. You are now an ns-3 user.*
+
+*What do I do if I don't see the output?*
+
+If you don't see ``waf`` messages indicating that the build was
+completed successfully, but do not see the "Hello Simulator" output,
+chances are that you have switched your build mode to "optimized" in
+the "Building with Waf" section, but have missed the change back to
+"debug" mode. All of the console output used in this tutorial uses a
+special |ns3| logging component that is useful for printing
+user messages to the console. Output from this component is
+automatically disabled when you compile optimized code -- it is
+"optimized out." If you don't see the "Hello Simulator" output,
+type the following,
+
+::
+
+ ./waf -d debug configure
+
+to tell ``waf`` to build the debug versions of the |ns3|
+programs. You must still build the actual debug version of the code by
+typing,
+
+::
+
+ ./waf
+
+Now, if you run the ``hello-simulator`` program, you should see the
+expected output.
+
+If you want to run programs under another tool such as gdb or valgrind,
+see this `wiki entry
+<http://www.nsnam.org/wiki/index.php/User_FAQ#How_to_run_NS-3_programs_under_another_tool>`_.
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/tutorial/source/index.rst Sun Jan 02 22:57:32 2011 -0800
@@ -0,0 +1,18 @@
+.. only:: html or latex
+
+ Welcome to ns-3's tutorial!
+ ================================
+
+ Contents:
+
+.. toctree::
+ :maxdepth: 2
+
+ introduction
+ resources
+ getting-started
+ conceptual-overview
+ tweaking
+ building-topologies
+ tracing
+ conclusion
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/tutorial/source/introduction.rst Sun Jan 02 22:57:32 2011 -0800
@@ -0,0 +1,125 @@
+.. include:: replace.txt
+
+Introduction
+------------
+
+The |ns3| simulator is a discrete-event network simulator targeted
+primarily for research and educational use. The
+`ns-3 project
+<http://www.nsnam.org>`_,
+started in 2006, is an open-source project developing |ns3|.
+
+Primary documentation for the |ns3| project is available in four
+forms:
+
+* `ns-3 Doxygen/Manual
+ <http://www.nsnam.org/doxygen/index.html>`_:
+ Documentation of the public APIs of the simulator
+* Tutorial (this document)
+* `Reference Manual
+ <http://www.nsnam.org/docs/manual.html>`_: Reference Manual
+* `ns-3 wiki
+ <http://www.nsnam.org/wiki/index.php>`_
+
+The purpose of this tutorial is to introduce new |ns3| users to the
+system in a structured way. It is sometimes difficult for new users to
+glean essential information from detailed manuals and to convert this
+information into working simulations. In this tutorial, we will build
+several example simulations, introducing and explaining key concepts and
+features as we go.
+
+As the tutorial unfolds, we will introduce the full |ns3| documentation
+and provide pointers to source code for those interested in delving deeper
+into the workings of the system.
+
+A few key points are worth noting at the onset:
+
+* Ns-3 is not an extension of `ns-2
+ <http://www.isi.edu/nsnam/ns>`_;
+ it is a new simulator. The two simulators are both written in C++ but
+ |ns3| is a new simulator that does not support the ns-2 APIs. Some
+ models from ns-2 have already been ported from ns-2 to |ns3|. The
+ project will continue to maintain ns-2 while |ns3| is being built,
+ and will study transition and integration mechanisms.
+* |ns3| is open-source, and the project strives to maintain an
+ open environment for researchers to contribute and share their software.
+
+
+For ns-2 Users
+**************
+
+For those familiar with ns-2, the most visible outward change when moving to
+|ns3| is the choice of scripting language. Ns-2 is
+scripted in OTcl and results of simulations can be visualized using the
+Network Animator nam. It is not possible to run a simulation
+in ns-2 purely from C++ (i.e., as a main() program without any OTcl).
+Moreover, some components of ns-2 are written in C++ and others in OTcl.
+In |ns3|, the simulator is written entirely in C++, with optional
+Python bindings. Simulation scripts can therefore be written in C++
+or in Python. The results of some simulations can be visualized by
+nam, but new animators are under development. Since |ns3|
+generates pcap packet trace files, other utilities can be used to
+analyze traces as well.
+In this tutorial, we will first concentrate on scripting
+directly in C++ and interpreting results via trace files.
+
+But there are similarities as well (both, for example, are based on C++
+objects, and some code from ns-2 has already been ported to |ns3|).
+We will try to highlight differences between ns-2 and |ns3|
+as we proceed in this tutorial.
+
+A question that we often hear is "Should I still use ns-2 or move to
+|ns3|?" The answer is that it depends. |ns3| does not have
+all of the models that ns-2 currently has, but on the other hand, |ns3|
+does have new capabilities (such as handling multiple interfaces on nodes
+correctly, use of IP addressing and more alignment with Internet
+protocols and designs, more detailed 802.11 models, etc.). ns-2
+models can usually be ported to |ns3| (a porting guide is under
+development). There is active development on multiple fronts for
+|ns3|. The |ns3| developers believe (and certain early users
+have proven) that |ns3| is ready for active use, and should be an
+attractive alternative for users looking to start new simulation projects.
+
+Contributing
+************
+
+|ns3| is a research and educational simulator, by and for the
+research community. It will rely on the ongoing contributions of the
+community to develop new models, debug or maintain existing ones, and share
+results. There are a few policies that we hope will encourage people to
+contribute to |ns3| like they have for ns-2:
+
+* Open source licensing based on GNU GPLv2 compatibility;
+* `wiki
+ <http://www.nsnam.org/wiki/index.php>`_;
+* `Contributed Code
+ <http://www.nsnam.org/wiki/index.php/Contributed_Code>`_ page, similar to ns-2's popular Contributed Code
+ `page
+ <http://nsnam.isi.edu/nsnam/index.php/Contributed_Code>`_;
+* ``src/contrib`` directory (we will host your contributed code);
+* Open `bug tracker
+ <http://www.nsnam.org/bugzilla>`_;
+* |ns3| developers will gladly help potential contributors to get
+ started with the simulator (please contact `one of us
+ <http://www.nsnam.org/people.html>`_).
+
+We realize that if you are reading this document, contributing back to
+the project is probably not your foremost concern at this point, but
+we want you to be aware that contributing is in the spirit of the project and
+that even the act of dropping us a note about your early experience
+with |ns3| (e.g. "this tutorial section was not clear..."),
+reports of stale documentation, etc. are much appreciated.
+
+Tutorial Organization
+*********************
+
+The tutorial assumes that new users might initially follow a path such as the
+following:
+
+* Try to download and build a copy;
+* Try to run a few sample programs;
+* Look at simulation output, and try to adjust it.
+
+As a result, we have tried to organize the tutorial along the above
+broad sequences of events.
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/tutorial/source/replace.txt Sun Jan 02 22:57:32 2011 -0800
@@ -0,0 +1,3 @@
+.. |ns3| replace:: *ns-3*
+
+.. |ns2| replace:: *ns-2*
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/tutorial/source/resources.rst Sun Jan 02 22:57:32 2011 -0800
@@ -0,0 +1,144 @@
+.. include:: replace.txt
+
+Resources
+---------
+
+The Web
+*******
+
+There are several important resources of which any |ns3| user must be
+aware. The main web site is located at http://www.nsnam.org and
+provides access to basic information about the |ns3| system. Detailed
+documentation is available through the main web site at
+http://www.nsnam.org/documents.html. You can also find documents
+relating to the system architecture from this page.
+
+There is a Wiki that complements the main |ns3| web site which you will
+find at http://www.nsnam.org/wiki/. You will find user and developer
+FAQs there, as well as troubleshooting guides, third-party contributed code,
+papers, etc.
+
+The source code may be found and browsed at http://code.nsnam.org/.
+There you will find the current development tree in the repository named
+``ns-3-dev``. Past releases and experimental repositories of the core
+developers may also be found there.
+
+Mercurial
+*********
+
+Complex software systems need some way to manage the organization and
+changes to the underlying code and documentation. There are many ways to
+perform this feat, and you may have heard of some of the systems that are
+currently used to do this. The Concurrent Version System (CVS) is probably
+the most well known.
+
+The |ns3| project uses Mercurial as its source code management system.
+Although you do not need to know much about Mercurial in order to complete
+this tutorial, we recommend becoming familiar with Mercurial and using it
+to access the source code. Mercurial has a web site at
+http://www.selenic.com/mercurial/,
+from which you can get binary or source releases of this Software
+Configuration Management (SCM) system. Selenic (the developer of Mercurial)
+also provides a tutorial at
+http://www.selenic.com/mercurial/wiki/index.cgi/Tutorial/,
+and a QuickStart guide at
+http://www.selenic.com/mercurial/wiki/index.cgi/QuickStart/.
+
+You can also find vital information about using Mercurial and |ns3|
+on the main |ns3| web site.
+
+Waf
+***
+
+Once you have source code downloaded to your local system, you will need
+to compile that source to produce usable programs. Just as in the case of
+source code management, there are many tools available to perform this
+function. Probably the most well known of these tools is ``make``. Along
+with being the most well known, ``make`` is probably the most difficult to
+use in a very large and highly configurable system. Because of this, many
+alternatives have been developed. Recently these systems have been developed
+using the Python language.
+
+The build system Waf is used on the |ns3| project. It is one
+of the new generation of Python-based build systems. You will not need to
+understand any Python to build the existing |ns3| system, and will
+only have to understand a tiny and intuitively obvious subset of Python in
+order to extend the system in most cases.
+
+For those interested in the gory details of Waf, the main web site can be
+found at http://code.google.com/p/waf/.
+
+Development Environment
+***********************
+
+As mentioned above, scripting in |ns3| is done in C++ or Python.
+As of ns-3.2, most of the |ns3| API is available in Python, but the
+models are written in C++ in either case. A working
+knowledge of C++ and object-oriented concepts is assumed in this document.
+We will take some time to review some of the more advanced concepts or
+possibly unfamiliar language features, idioms and design patterns as they
+appear. We don't want this tutorial to devolve into a C++ tutorial, though,
+so we do expect a basic command of the language. There are an almost
+unimaginable number of sources of information on C++ available on the web or
+in print.
+
+If you are new to C++, you may want to find a tutorial- or cookbook-based
+book or web site and work through at least the basic features of the language
+before proceeding. For instance, `this tutorial
+<http://www.cplusplus.com/doc/tutorial/>`_.
+
+The |ns3| system uses several components of the GNU "toolchain"
+for development. A
+software toolchain is the set of programming tools available in the given
+environment. For a quick review of what is included in the GNU toolchain see,
+http://en.wikipedia.org/wiki/GNU_toolchain. |ns3| uses gcc,
+GNU binutils, and gdb. However, we do not use the GNU build system tools,
+neither make nor autotools. We use Waf for these functions.
+
+Typically an |ns3| author will work in Linux or a Linux-like
+environment. For those running under Windows, there do exist environments
+which simulate the Linux environment to various degrees. The |ns3|
+project supports development in the Cygwin environment for
+these users. See http://www.cygwin.com/
+for details on downloading (MinGW is presently not officially supported,
+although some of the project maintainers to work with it). Cygwin provides
+many of the popular Linux system commands. It can, however, sometimes be
+problematic due to the way it actually does its emulation, and sometimes
+interactions with other Windows software can cause problems.
+
+If you do use Cygwin or MinGW; and use Logitech products, we will save you
+quite a bit of heartburn right off the bat and encourage you to take a look
+at the `MinGW FAQ
+<http://oldwiki.mingw.org/index.php/FAQ>`_.
+
+Search for "Logitech" and read the FAQ entry, "why does make often
+crash creating a sh.exe.stackdump file when I try to compile my source code."
+Believe it or not, the ``Logitech Process Monitor`` insinuates itself into
+every DLL in the system when it is running. It can cause your Cygwin or
+MinGW DLLs to die in mysterious ways and often prevents debuggers from
+running. Beware of Logitech software when using Cygwin.
+
+Another alternative to Cygwin is to install a virtual machine environment
+such as VMware server and install a Linux virtual machine.
+
+Socket Programming
+******************
+
+We will assume a basic facility with the Berkeley Sockets API in the examples
+used in this tutorial. If you are new to sockets, we recommend reviewing the
+API and some common usage cases. For a good overview of programming TCP/IP
+sockets we recommend `TCP/IP Sockets in C, Donahoo and Calvert
+<http://www.elsevier.com/wps/find/bookdescription.cws_home/717656/description#description>`_.
+
+There is an associated web site that includes source for the examples in the
+book, which you can find at:
+http://cs.baylor.edu/~donahoo/practical/CSockets/.
+
+If you understand the first four chapters of the book (or for those who do
+not have access to a copy of the book, the echo clients and servers shown in
+the website above) you will be in good shape to understand the tutorial.
+There is a similar book on Multicast Sockets,
+`Multicast Sockets, Makofske and Almeroth
+<http://www.elsevier.com/wps/find/bookdescription.cws_home/700736/description#description>`_.
+that covers material you may need to understand if you look at the multicast
+examples in the distribution.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/tutorial/source/tracing.rst Sun Jan 02 22:57:32 2011 -0800
@@ -0,0 +1,3179 @@
+.. include:: replace.txt
+
+
+Tracing
+-------
+
+Background
+**********
+
+As mentioned in the Using the Tracing System section, the whole point of running
+an |ns3| simulation is to generate output for study. You have two basic
+strategies to work with in |ns3|: using generic pre-defined bulk output
+mechanisms and parsing their content to extract interesting information; or
+somehow developing an output mechanism that conveys exactly (and perhaps only)
+the information wanted.
+
+Using pre-defined bulk output mechanisms has the advantage of not requiring any
+changes to |ns3|, 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 |ns3| mechanisms,
+you may get your code added as a contribution.
+
+|ns3| provides another mechanism, called Tracing, that avoids some of the
+problems inherent in the bulk output mechanisms. It has several important
+advantages. First, you can reduce the amount of data you have to manage by only
+tracing the events of interest to you (for large simulations, dumping everything
+to disk for post-processing can create I/O bottlenecks). Second, if you use this
+method, you can control the format of the output directly so you avoid the
+postprocessing step with sed or awk script. If you desire, your output can be
+formatted directly into a form acceptable by gnuplot, for example. You can add
+hooks in the core which can then be accessed by other users, but which will
+produce no information unless explicitly asked to do so. For these reasons, we
+believe that the |ns3| 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 |ns3|.
+
+Blunt Instruments
++++++++++++++++++
+There are many ways to get information out of a program. The most
+straightforward way is to just directly print the information to the standard
+output, as in,
+
+::
+
+ #include <iostream>
+ ...
+ void
+ SomeFunction (void)
+ {
+ uint32_t x = SOME_INTERESTING_VALUE;
+ ...
+ std::cout << "The value of x is " << x << std::endl;
+ ...
+ }
+
+Nobody is going to prevent you from going deep into the core of |ns3| and
+adding print statements. This is insanely easy to do and, after all, you have
+complete control of your own |ns3| branch. This will probably not turn
+out to be very satisfactory in the long term, though.
+
+As the number of print statements increases in your programs, the task of
+dealing with the large number of outputs will become more and more complicated.
+Eventually, you may feel the need to control what information is being printed
+in some way; perhaps by turning on and off certain categories of prints, or
+increasing or decreasing the amount of information you want. If you continue
+down this path you may discover that you have re-implemented the ``NS_LOG``
+mechanism. In order to avoid that, one of the first things you might consider
+is using ``NS_LOG`` itself.
+
+We mentioned above that one way to get information out of |ns3| 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 |ns3| and simply add your interesting information
+to the output stream. Now, this is certainly better than adding your own
+print statements since it follows |ns3| 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
+|ns3| TCP socket (``tcp-socket-base.cc``) you could just add a new
+message down in the implementation. Notice that in TcpSocketBase::ReceivedAck()
+there is no log message for the no ack case. You could simply add one,
+changing the code from:
+
+::
+
+ /** Process the newly received ACK */
+ void
+ TcpSocketBase::ReceivedAck (Ptr<Packet> packet, const TcpHeader& tcpHeader)
+ {
+ NS_LOG_FUNCTION (this << tcpHeader);
+
+ // Received ACK. Compare the ACK number against highest unacked seqno
+ if (0 == (tcpHeader.GetFlags () & TcpHeader::ACK))
+ { // Ignore if no ACK flag
+ }
+ ...
+
+to add a new ``NS_LOG_LOGIC`` in the appropriate statement:
+
+::
+
+ /** Process the newly received ACK */
+ void
+ TcpSocketBase::ReceivedAck (Ptr<Packet> packet, const TcpHeader& tcpHeader)
+ {
+ NS_LOG_FUNCTION (this << tcpHeader);
+
+ // Received ACK. Compare the ACK number against highest unacked seqno
+ if (0 == (tcpHeader.GetFlags () & TcpHeader::ACK))
+ { // Ignore if no ACK flag
+ NS_LOG_LOGIC ("TcpSocketBase " << this << " no ACK flag");
+ }
+ ...
+
+This may seem fairly simple and satisfying at first glance, but something to
+consider is that you will be writing code to add the ``NS_LOG`` statement
+and you will also have to write code (as in grep, sed or awk scripts) to parse
+the log output in order to isolate your information. This is because even
+though you have some control over what is output by the logging system, you
+only have control down to the log component level.
+
+If you are adding code to an existing module, you will also have to live with the
+output that every other developer has found interesting. You may find that in
+order to get the small amount of information you need, you may have to wade
+through huge amounts of extraneous messages that are of no interest to you. You
+may be forced to save huge log files to disk and process them down to a few lines
+whenever you want to do anything.
+
+Since there are no guarantees in |ns3| about the stability of ``NS_LOG``
+output, you may also discover that pieces of log output on which you depend
+disappear or change between releases. If you depend on the structure of the
+output, you may find other messages being added or deleted which may affect your
+parsing code.
+
+For these reasons, we consider prints to ``std::cout`` and NS_LOG messages
+to be quick and dirty ways to get more information out of |ns3|.
+
+It is desirable to have a stable facility using stable APIs that allow one to
+reach into the core system and only get the information required. It is
+desirable to be able to do this without having to change and recompile the
+core system. Even better would be a system that notified the user when an item
+of interest changed or an interesting event happened so the user doesn't have
+to actively poke around in the system looking for things.
+
+The |ns3| 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.
+
+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 interesting 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 |ns3| core.
+
+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.
+
+Callbacks
+~~~~~~~~~
+
+The goal of the Callback system in |ns3| 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,
+
+::
+
+ int (*pfi)(int arg) = 0;
+
+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,
+
+::
+
+ int MyFunction (int arg) {}
+
+If you have this target, you can initialize the variable to point to your
+function:
+
+::
+
+ pfi = MyFunction;
+
+You can then call MyFunction indirectly using the more suggestive form of
+the call,
+
+::
+
+ int result = (*pfi) (1234);
+
+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,
+
+::
+
+ int result = pfi (1234);
+
+This looks like you are calling a function named "pfi," but the compiler is
+smart enough to know to call through the variable ``pfi`` indirectly to
+the function ``MyFunction``.
+
+Conceptually, this is almost exactly how the tracing system will work.
+Basically, a trace source *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 ``operator()`` providing zero or more parameters.
+The ``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
+``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
+|ns3|, feel free to peruse the Callback section of the manual.
+
+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 ``fourth.cc``. Let's walk through it.
+
+::
+
+ /* -*- 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;
+
+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, ``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 |ns3| ``Object`` for the trace source
+to live in. The next code snippet declares and defines a simple Object we can
+work with.
+
+::
+
+ 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;
+ };
+
+The two important lines of code, above, with respect to tracing are the
+``.AddTraceSource`` and the ``TracedValue`` declaration of ``m_myInt``.
+
+The ``.AddTraceSource`` provides the "hooks" used for connecting the trace
+source to the outside world through the config system. The ``TracedValue``
+declaration provides the infrastructure that overloads the operators mentioned
+above and drives the callback process.
+
+::
+
+ void
+ IntTrace (int32_t oldValue, int32_t newValue)
+ {
+ std::cout << "Traced " << oldValue << " to " << newValue << std::endl;
+ }
+
+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 ``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.
+
+::
+
+ int
+ main (int argc, char *argv[])
+ {
+ Ptr<MyObject> myObject = CreateObject<MyObject> ();
+ myObject->TraceConnectWithoutContext ("MyInteger", MakeCallback(&IntTrace));
+
+ myObject->m_myInt = 1234;
+ }
+
+Here we first create the Object in which the trace source lives.
+
+The next step, the ``TraceConnectWithoutContext``, forms the connection
+between the trace source and the trace sink. Notice the ``MakeCallback``
+template function. This function does the magic required to create the
+underlying |ns3| Callback object and associate it with the function
+``IntTrace``. TraceConnect makes the association between your provided
+function and the overloaded ``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 ``pfi()``
+example above to be called by the trace source. The declaration of the
+``TracedValue<int32_t> m_myInt;`` in the Object itself performs the magic
+needed to provide the overloaded operators (++, ---, etc.) that will use the
+``operator()`` to actually invoke the Callback with the desired parameters.
+The ``.AddTraceSource`` performs the magic to connect the Callback to the
+Config system, and ``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,
+
+::
+
+ myObject->m_myInt = 1234;
+
+should be interpreted as an invocation of ``operator=`` on the member
+variable ``m_myInt`` with the integer ``1234`` passed as a parameter.
+
+It turns out that this operator is defined (by ``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 --- ``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,
+
+::
+
+ ./waf --run fourth
+
+you will see the output from the ``IntTrace`` function execute as soon as the
+trace source is hit:
+
+::
+
+ Traced 0 to 1234
+
+When we executed the code, ``myObject->m_myInt = 1234;``, the trace source
+fired and automatically provided the before and after values to the trace sink.
+The function ``IntTrace`` then printed this to the standard output. No
+problem.
+
+Using the Config Subsystem to Connect to Trace Sources
+++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+The ``TraceConnectWithoutContext`` call shown above in the simple example is
+actually very rarely used in the system. More typically, the ``Config``
+subsystem is used to allow selecting a trace source in the system using what is
+called a *config path*. We saw an example of this in the previous section
+where we hooked the "CourseChange" event when we were playing with
+``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.
+
+::
+
+ void
+ CourseChange (std::string context, Ptr<const MobilityModel> model)
+ {
+ Vector position = model->GetPosition ();
+ NS_LOG_UNCOND (context <<
+ " x = " << position.x << ", y = " << position.y);
+ }
+
+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:
+
+::
+
+ std::ostringstream oss;
+ oss <<
+ "/NodeList/" << wifiStaNodes.Get (nWifi - 1)->GetId () <<
+ "/$ns3::MobilityModel/CourseChange";
+
+ Config::Connect (oss.str (), MakeCallback (&CourseChange));
+
+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 ``GetId()`` is "7". In this case, the path
+above turns out to be,
+
+::
+
+ "/NodeList/7/$ns3::MobilityModel/CourseChange"
+
+The last segment of a config path must be an ``Attribute`` of an
+``Object``. In fact, if you had a pointer to the ``Object`` that has the
+"CourseChange" ``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 ``third.cc`` example, the Nodes of
+interest are stored in the ``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:
+
+::
+
+ Ptr<Object> theObject = wifiStaNodes.Get (nWifi - 1);
+ theObject->TraceConnectWithoutContext ("CourseChange", MakeCallback (&CourseChange));
+
+In the ``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,
+
+::
+
+ Ptr<Object> theObject = wifiStaNodes.Get (nWifi - 1);
+ theObject->TraceConnect ("CourseChange", MakeCallback (&CourseChange));
+
+It turns out that the internal code for ``Config::ConnectWithoutContext`` and
+``Config::Connect`` actually do find a Ptr<Object> and call the appropriate
+TraceConnect method at the lowest level.
+
+The ``Config`` functions take a path that represents a chain of ``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 ``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 ``Attribute`` on the last Object it found while walking the path. The
+``Config`` functions then call the appropriate ``TraceConnect`` or
+``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
+``Ptr<Node>`` and so is a subclass of an ``ns3::Object``.
+
+As described in the Object Model section of the |ns3| 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 ``GetObject`` call should be made
+looking for the type that follows. It turns out that the MobilityHelper used in
+``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 ``GetObject``, we have asked the system to do the following:
+
+::
+
+ Ptr<MobilityModel> mobilityModel = node->GetObject<MobilityModel> ()
+
+We are now at the last Object in the path, so we turn our attention to the
+Attributes of that Object. The ``MobilityModel`` class defines an Attribute
+called "CourseChange". You can see this by looking at the source code in
+``src/mobility/mobility-model.cc`` and searching for "CourseChange" in your
+favorite editor. You should find,
+
+::
+
+ .AddTraceSource ("CourseChange",
+ "The value of the position and/or velocity vector changed",
+ MakeTraceSourceAccessor (&MobilityModel::m_courseChangeTrace))
+
+which should look very familiar at this point.
+
+If you look for the corresponding declaration of the underlying traced variable
+in ``mobility-model.h`` you will find
+
+::
+
+ TracedCallback<Ptr<const MobilityModel> > m_courseChangeTrace;
+
+The type declaration ``TracedCallback`` identifies ``m_courseChangeTrace``
+as a special list of Callbacks that can be hooked using the Config functions
+described above.
+
+The ``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 ``NotifyCourseChange()``:
+
+::
+
+ void
+ MobilityModel::NotifyCourseChange (void) const
+ {
+ m_courseChangeTrace(this);
+ }
+
+Derived classes will call into this method whenever they do a course change to
+support tracing. This method invokes ``operator()`` on the underlying
+``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 ``third.cc`` example we looked at, whenever a course change is
+made in one of the ``RandomWalk2dMobilityModel`` instances installed, there
+will be a ``NotifyCourseChange()`` call which calls up into the
+``MobilityModel`` base class. As seen above, this invokes ``operator()``
+on ``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 ``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 ``third.cc``:
+
+::
+
+ /NodeList/7/$ns3::MobilityModel/CourseChange x = 7.27897, y = 2.22677
+
+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 ``Config::Connect``.
+
+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"?
+
+What Trace Sources are Available?
++++++++++++++++++++++++++++++++++
+
+The answer to this question is found in the |ns3| Doxygen. Go to the
+|ns3| web site `"here"
+<http://www.nsnam.org/getting_started.html>`_
+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:
+
+* The list of all trace sources
+* The list of all attributes
+* The list of all global values
+
+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 |ns3| core.
+
+As an example, scroll down to ``ns3::MobilityModel``. You will find
+an entry for
+
+::
+
+ CourseChange: The value of the position and/or velocity vector changed
+
+You should recognize this as the trace source we used in the ``third.cc``
+example. Perusing this list will be helpful.
+
+What String do I use to Connect?
+++++++++++++++++++++++++++++++++
+
+The easiest way to do this is to grep around in the |ns3| 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:
+
+::
+
+ find . -name '*.cc' | xargs grep CourseChange | grep Connect
+
+and you may find your answer along with working code. For example, in this
+case, ``./ns-3-dev/examples/wireless/mixed-wireless.cc`` has something
+just waiting for you to use:
+
+::
+
+ Config::Connect ("/NodeList/*/$ns3::MobilityModel/CourseChange",
+ MakeCallback (&CourseChangeCallback));
+
+If you cannot find any examples in the distribution, you can find this out
+from the |ns3| 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 ``third.cc`` example) an
+``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 |ns3|. Scroll down until you see the
+entry for ``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 ``GetTypeId`` function. You constructed one
+of these in the simple tracing example above:
+
+::
+
+ 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;
+ }
+
+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:
+
+::
+
+ This object is accessible through the following paths with Config::Set and Config::Connect:
+
+ /NodeList/[i]/$ns3::MobilityModel/$ns3::RandomWalk2dMobilityModel
+
+The documentation tells you how to get to the ``RandomWalk2dMobilityModel``
+Object. Compare the string above with the string we actually used in the
+example code:
+
+::
+
+ "/NodeList/7/$ns3::MobilityModel"
+
+The difference is due to the fact that two ``GetObject`` calls are implied
+in the string found in the documentation. The first, for ``$ns3::MobilityModel``
+will query the aggregation for the base class. The second implied
+``GetObject`` call, for ``$ns3::RandomWalk2dMobilityModel``, is used to "cast"
+the base class to the concrete implementation 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 ``GetTypeId`` doxygen. You will find,
+
+::
+
+ 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
+
+This is exactly what you need to know. The trace source of interest is found in
+``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 ``GetObject`` is not required and
+you simply use the path:
+
+::
+
+ /NodeList/[i]/$ns3::MobilityModel
+
+which perfectly matches the example path:
+
+::
+
+ /NodeList/7/$ns3::MobilityModel
+
+What Return Value and Formal Arguments?
++++++++++++++++++++++++++++++++++++++++
+
+The easiest way to do this is to grep around in the |ns3| codebase for someone
+who has already figured it out, You should always try to copy someone else's
+working code. Try something like:
+
+::
+
+ find . -name '*.cc' | xargs grep CourseChange | grep Connect
+
+and you may find your answer along with working code. For example, in this
+case, ``./ns-3-dev/examples/wireless/mixed-wireless.cc`` has something
+just waiting for you to use. You will find
+
+::
+
+ Config::Connect ("/NodeList/*/$ns3::MobilityModel/CourseChange",
+ MakeCallback (&CourseChangeCallback));
+
+as a result of your grep. The ``MakeCallback`` should indicate to you that
+there is a callback function there which you can use. Sure enough, there is:
+
+::
+
+ static void
+ CourseChangeCallback (std::string path, Ptr<const MobilityModel> model)
+ {
+ ...
+ }
+
+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 ``TracedCallback`` can be found
+from the template parameter list in the declaration. Recall that for our
+current example, this is in ``mobility-model.h``, where we have previously
+found:
+
+::
+
+ TracedCallback<Ptr<const MobilityModel> > m_courseChangeTrace;
+
+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 ``Ptr<const MobilityModel>``.
+This tells you that you need a function that returns void and takes a
+a ``Ptr<const MobilityModel>``. For example,
+
+::
+
+ void
+ CourseChangeCallback (Ptr<const MobilityModel> model)
+ {
+ ...
+ }
+
+That's all you need if you want to ``Config::ConnectWithoutContext``. If
+you want a context, you need to ``Config::Connect`` and use a Callback
+function that takes a string context, then the required argument.
+
+::
+
+ void
+ CourseChangeCallback (std::string path, Ptr<const MobilityModel> model)
+ {
+ ...
+ }
+
+If you want to ensure that your ``CourseChangeCallback`` is only visible
+in your local file, you can add the keyword ``static`` and come up with:
+
+::
+
+ static void
+ CourseChangeCallback (std::string path, Ptr<const MobilityModel> model)
+ {
+ ...
+ }
+
+which is exactly what we used in the ``third.cc`` example.
+
+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 |ns3| 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 ``TracedCallback`` and understand it.
+
+The first thing we need to look at is the declaration of the trace source.
+Recall that this is in ``mobility-model.h``, where we have previously
+found:
+
+::
+
+ TracedCallback<Ptr<const MobilityModel> > m_courseChangeTrace;
+
+This declaration is for a template. The template parameter is inside the
+angle-brackets, so we are really interested in finding out what that
+``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
+|ns3| source, so first change into the ``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:
+
+::
+
+ find . -name '*.h' | xargs grep TracedCallback
+
+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.
+
+::
+
+ 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 ...
+
+It turns out that all of this comes from the header file
+``traced-callback.h`` which sounds very promising. You can then take a
+look at ``mobility-model.h`` and see that there is a line which confirms
+this hunch:
+
+::
+
+ #include "ns3/traced-callback.h"
+
+Of course, you could have gone at this from the other direction and started
+by looking at the includes in ``mobility-model.h`` and noticing the
+include of ``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 ``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:
+
+::
+
+ 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.
+
+This should sound very familiar and let you know you are on the right track.
+
+Just after this comment, you will find,
+
+::
+
+ 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
+ {
+ ...
+
+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:
+
+::
+
+ TracedCallback<Ptr<const MobilityModel> > m_courseChangeTrace;
+
+The ``typename T1`` in the templated class declaration corresponds to the
+``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 ``Connect``
+and ``ConnectWithoutContext`` functions. If you scroll down, you will see
+a ``ConnectWithoutContext`` method here:
+
+::
+
+ 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);
+ }
+
+You are now in the belly of the beast. When the template is instantiated for
+the declaration above, the compiler will replace ``T1`` with
+``Ptr<const MobilityModel>``.
+
+::
+
+ void
+ TracedCallback<Ptr<const MobilityModel>::ConnectWithoutContext ... cb
+ {
+ Callback<void, Ptr<const MobilityModel> > cb;
+ cb.Assign (callback);
+ m_callbackList.push_back (cb);
+ }
+
+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 ``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 ``TracedCallback``, you will be
+able to find that the file ``./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:
+
+::
+
+ 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.
+
+We are trying to figure out what the
+
+::
+
+ Callback<void, Ptr<const MobilityModel> > cb;
+
+declaration means. Now we are in a position to understand that the first
+(non-optional) parameter, ``void``, represents the return type of the
+Callback. The second (non-optional) parameter, ``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 ``void`` and takes
+a ``Ptr<const MobilityModel>``. For example,
+
+::
+
+ void
+ CourseChangeCallback (Ptr<const MobilityModel> model)
+ {
+ ...
+ }
+
+That's all you need if you want to ``Config::ConnectWithoutContext``. If
+you want a context, you need to ``Config::Connect`` and use a Callback
+function that takes a string context. This is because the ``Connect``
+function will provide the context for you. You'll need:
+
+::
+
+ void
+ CourseChangeCallback (std::string path, Ptr<const MobilityModel> model)
+ {
+ ...
+ }
+
+If you want to ensure that your ``CourseChangeCallback`` is only visible
+in your local file, you can add the keyword ``static`` and come up with:
+
+::
+
+ static void
+ CourseChangeCallback (std::string path, Ptr<const MobilityModel> model)
+ {
+ ...
+ }
+
+which is exactly what we used in the ``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 |ns3| manual. They are one
+of the most frequently used constructs in the low-level parts of |ns3|.
+It is, in my opinion, a quite elegant thing.
+
+What About TracedValue?
++++++++++++++++++++++++
+
+Earlier in this section, we presented a simple piece of code that used a
+``TracedValue<int32_t>`` to demonstrate the basics of the tracing code.
+We just glossed over the way to find the return type and formal arguments
+for the ``TracedValue``. Rather than go through the whole exercise, we
+will just point you at the correct file, ``src/core/traced-value.h`` and
+to the important piece of code:
+
+::
+
+ template <typename T>
+ class TracedValue
+ {
+ public:
+ ...
+ void Set (const T &v) {
+ if (m_v != v)
+ {
+ m_cb (m_v, v);
+ m_v = v;
+ }
+ }
+ ...
+ private:
+ T m_v;
+ TracedCallback<T,T> m_cb;
+ };
+
+Here you see that the ``TracedValue`` is templated, of course. In the simple
+example case at the start of the section, the typename is int32_t. This means
+that the member variable being traced (``m_v`` in the private section of the
+class) will be an ``int32_t m_v``. The ``Set`` method will take a
+``const int32_t &v`` as a parameter. You should now be able to understand
+that the ``Set`` code will fire the ``m_cb`` callback with two parameters:
+the first being the current value of the ``TracedValue``; and the second
+being the new value being set.
+
+The callback, ``m_cb`` is declared as a ``TracedCallback<T, T>`` which
+will correspond to a ``TracedCallback<int32_t, int32_t>`` when the class is
+instantiated.
+
+Recall that the callback target of a TracedCallback always returns ``void``.
+Further recall that there is a one-to-one correspondence between the template
+parameter list in the declaration and the formal arguments of the callback
+function. Therefore the callback will need to have a function signature that
+looks like:
+
+::
+
+ void
+ MyCallback (int32_t oldValue, int32_t newValue)
+ {
+ ...
+ }
+
+It probably won't surprise you that this is exactly what we provided in that
+simple example we covered so long ago:
+
+::
+
+ void
+ IntTrace (int32_t oldValue, int32_t newValue)
+ {
+ std::cout << "Traced " << oldValue << " to " << newValue << std::endl;
+ }
+
+A Real Example
+**************
+
+Let's do an example taken from one of the best-known books on TCP around.
+"TCP/IP Illustrated, Volume 1: The Protocols," by W. Richard Stevens is a
+classic. I just flipped the book open and ran across a nice plot of both the
+congestion window and sequence numbers versus time on page 366. Stevens calls
+this, "Figure 21.10. Value of cwnd and send sequence number while data is being
+transmitted." Let's just recreate the cwnd part of that plot in |ns3|
+using the tracing system and ``gnuplot``.
+
+Are There Trace Sources Available?
+++++++++++++++++++++++++++++++++++
+
+The first thing to think about is how we want to get the data out. What is it
+that we need to trace? The first thing to do is to consult "The list of all
+trace sources" to see what we have to work with. Recall that this is found
+in the |ns3| Doxygen in the "Core" Module section. If you scroll
+through the list, you will eventually find:
+
+::
+
+ ns3::TcpNewReno
+ CongestionWindow: The TCP connection's congestion window
+
+It turns out that the |ns3| TCP implementation lives (mostly) in the
+file ``src/internet-stack/tcp-socket-base.cc`` while congestion control
+variants are in files such as ``src/internet-stack/tcp-newreno.cc``.
+If you don't know this a priori, you can use the recursive grep trick:
+
+::
+
+ find . -name '*.cc' | xargs grep -i tcp
+
+You will find page after page of instances of tcp pointing you to that file.
+
+If you open ``src/internet-stack/tcp-newreno.cc`` in your favorite
+editor, you will see right up at the top of the file, the following declarations:
+
+::
+
+ TypeId
+ TcpNewReno::GetTypeId ()
+ {
+ static TypeId tid = TypeId("ns3::TcpNewReno")
+ .SetParent<TcpSocketBase> ()
+ .AddConstructor<TcpNewReno> ()
+ .AddTraceSource ("CongestionWindow",
+ "The TCP connection's congestion window",
+ MakeTraceSourceAccessor (&TcpNewReno::m_cWnd))
+ ;
+ return tid;
+ }
+
+This should tell you to look for the declaration of ``m_cWnd`` in the header
+file ``src/internet-stack/tcp-newreno.h``. If you open this file in your
+favorite editor, you will find:
+
+::
+
+ TracedValue<uint32_t> m_cWnd; //Congestion window
+
+You should now understand this code completely. If we have a pointer to the
+``TcpNewReno``, we can ``TraceConnect`` to the "CongestionWindow" trace
+source if we provide an appropriate callback target. This is the same kind of
+trace source that we saw in the simple example at the start of this section,
+except that we are talking about ``uint32_t`` instead of ``int32_t``.
+
+We now know that we need to provide a callback that returns void and takes
+two ``uint32_t`` parameters, the first being the old value and the second
+being the new value:
+
+::
+
+ void
+ CwndTrace (uint32_t oldValue, uint32_t newValue)
+ {
+ ...
+ }
+
+What Script to Use?
++++++++++++++++++++
+
+It's always best to try and find working code laying around that you can
+modify, rather than starting from scratch. So the first order of business now
+is to find some code that already hooks the "CongestionWindow" trace source
+and see if we can modify it. As usual, grep is your friend:
+
+::
+
+ find . -name '*.cc' | xargs grep CongestionWindow
+
+This will point out a couple of promising candidates:
+``examples/tcp/tcp-large-transfer.cc`` and
+``src/test/ns3tcp/ns3tcp-cwnd-test-suite.cc``.
+
+We haven't visited any of the test code yet, so let's take a look there. You
+will typically find that test code is fairly minimal, so this is probably a
+very good bet. Open ``src/test/ns3tcp/ns3tcp-cwnd-test-suite.cc`` in your
+favorite editor and search for "CongestionWindow". You will find,
+
+::
+
+ ns3TcpSocket->TraceConnectWithoutContext ("CongestionWindow",
+ MakeCallback (&Ns3TcpCwndTestCase1::CwndChange, this));
+
+This should look very familiar to you. We mentioned above that if we had a
+pointer to the ``TcpNewReno``, we could ``TraceConnect`` to the
+"CongestionWindow" trace source. That's exactly what we have here; so it
+turns out that this line of code does exactly what we want. Let's go ahead
+and extract the code we need from this function
+(``Ns3TcpCwndTestCase1::DoRun (void)``). If you look at this function,
+you will find that it looks just like an |ns3| script. It turns out that
+is exactly what it is. It is a script run by the test framework, so we can just
+pull it out and wrap it in ``main`` instead of in ``DoRun``. Rather than
+walk through this, step, by step, we have provided the file that results from
+porting this test back to a native |ns3| script --
+``examples/tutorial/fifth.cc``.
+
+A Common Problem and Solution
++++++++++++++++++++++++++++++
+
+The ``fifth.cc`` example demonstrates an extremely important rule that you
+must understand before using any kind of ``Attribute``: you must ensure
+that the target of a ``Config`` command exists before trying to use it.
+This is no different than saying an object must be instantiated before trying
+to call it. Although this may seem obvious when stated this way, it does
+trip up many people trying to use the system for the first time.
+
+Let's return to basics for a moment. There are three basic time periods that
+exist in any |ns3| script. The first time period is sometimes called
+"Configuration Time" or "Setup Time," and is in force during the period
+when the ``main`` function of your script is running, but before
+``Simulator::Run`` is called. The second time period is sometimes called
+"Simulation Time" and is in force during the time period when
+``Simulator::Run`` is actively executing its events. After it completes
+executing the simulation, ``Simulator::Run`` will return control back to
+the ``main`` function. When this happens, the script enters what can be
+called "Teardown Time," which is when the structures and objects created
+during setup and taken apart and released.
+
+Perhaps the most common mistake made in trying to use the tracing system is
+assuming that entities constructed dynamically during simulation time are
+available during configuration time. In particular, an |ns3|
+``Socket`` is a dynamic object often created by ``Applications`` to
+communicate between ``Nodes``. An |ns3| ``Application``
+always has a "Start Time" and a "Stop Time" associated with it. In the
+vast majority of cases, an ``Application`` will not attempt to create
+a dynamic object until its ``StartApplication`` method is called at some
+"Start Time". This is to ensure that the simulation is completely
+configured before the app tries to do anything (what would happen if it tried
+to connect to a node that didn't exist yet during configuration time). The
+answer to this issue is to 1) create a simulator event that is run after the
+dynamic object is created and hook the trace when that event is executed; or
+2) create the dynamic object at configuration time, hook it then, and give
+the object to the system to use during simulation time. We took the second
+approach in the ``fifth.cc`` example. This decision required us to create
+the ``MyApp`` ``Application``, the entire purpose of which is to take
+a ``Socket`` as a parameter.
+
+A fifth.cc Walkthrough
+++++++++++++++++++++++
+
+Now, let's take a look at the example program we constructed by dissecting
+the congestion window test. Open ``examples/tutorial/fifth.cc`` in your
+favorite editor. You should see some familiar looking code:
+
+::
+
+ /* -*- 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, Include., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+ #include <fstream>
+ #include "ns3/core-module.h"
+ #include "ns3/common-module.h"
+ #include "ns3/simulator-module.h"
+ #include "ns3/node-module.h"
+ #include "ns3/helper-module.h"
+
+ using namespace ns3;
+
+ NS_LOG_COMPONENT_DEFINE ("FifthScriptExample");
+
+This has all been covered, so we won't rehash it. The next lines of source are
+the network illustration and a comment addressing the problem described above
+with ``Socket``.
+
+::
+
+ // ===========================================================================
+ //
+ // node 0 node 1
+ // +----------------+ +----------------+
+ // | ns-3 TCP | | ns-3 TCP |
+ // +----------------+ +----------------+
+ // | 10.1.1.1 | | 10.1.1.2 |
+ // +----------------+ +----------------+
+ // | point-to-point | | point-to-point |
+ // +----------------+ +----------------+
+ // | |
+ // +---------------------+
+ // 5 Mbps, 2 ms
+ //
+ //
+ // We want to look at changes in the ns-3 TCP congestion window. We need
+ // to crank up a flow and hook the CongestionWindow attribute on the socket
+ // of the sender. Normally one would use an on-off application to generate a
+ // flow, but this has a couple of problems. First, the socket of the on-off
+ // application is not created until Application Start time, so we wouldn't be
+ // able to hook the socket (now) at configuration time. Second, even if we
+ // could arrange a call after start time, the socket is not public so we
+ // couldn't get at it.
+ //
+ // So, we can cook up a simple version of the on-off application that does what
+ // we want. On the plus side we don't need all of the complexity of the on-off
+ // application. On the minus side, we don't have a helper, so we have to get
+ // a little more involved in the details, but this is trivial.
+ //
+ // So first, we create a socket and do the trace connect on it; then we pass
+ // this socket into the constructor of our simple application which we then
+ // install in the source node.
+ // ===========================================================================
+ //
+
+This should also be self-explanatory.
+
+The next part is the declaration of the ``MyApp`` ``Application`` that
+we put together to allow the ``Socket`` to be created at configuration time.
+
+::
+
+ class MyApp : public Application
+ {
+ public:
+
+ MyApp ();
+ virtual ~MyApp();
+
+ void Setup (Ptr<Socket> socket, Address address, uint32_t packetSize,
+ uint32_t nPackets, DataRate dataRate);
+
+ private:
+ virtual void StartApplication (void);
+ virtual void StopApplication (void);
+
+ void ScheduleTx (void);
+ void SendPacket (void);
+
+ Ptr<Socket> m_socket;
+ Address m_peer;
+ uint32_t m_packetSize;
+ uint32_t m_nPackets;
+ DataRate m_dataRate;
+ EventId m_sendEvent;
+ bool m_running;
+ uint32_t m_packetsSent;
+ };
+
+You can see that this class inherits from the |ns3| ``Application``
+class. Take a look at ``src/node/application.h`` if you are interested in
+what is inherited. The ``MyApp`` class is obligated to override the
+``StartApplication`` and ``StopApplication`` methods. These methods are
+automatically called when ``MyApp`` is required to start and stop sending
+data during the simulation.
+
+How Applications are Started and Stopped (optional)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+It is worthwhile to spend a bit of time explaining how events actually get
+started in the system. This is another fairly deep explanation, and can be
+ignored if you aren't planning on venturing down into the guts of the system.
+It is useful, however, in that the discussion touches on how some very important
+parts of |ns3| work and exposes some important idioms. If you are
+planning on implementing new models, you probably want to understand this
+section.
+
+The most common way to start pumping events is to start an ``Application``.
+This is done as the result of the following (hopefully) familar lines of an
+|ns3| script:
+
+::
+
+ ApplicationContainer apps = ...
+ apps.Start (Seconds (1.0));
+ apps.Stop (Seconds (10.0));
+
+The application container code (see ``src/helper/application-container.h`` if
+you are interested) loops through its contained applications and calls,
+
+::
+
+ app->SetStartTime (startTime);
+
+as a result of the ``apps.Start`` call and
+
+::
+
+ app->SetStopTime (stopTime);
+
+as a result of the ``apps.Stop`` call.
+
+The ultimate result of these calls is that we want to have the simulator
+automatically make calls into our ``Applications`` to tell them when to
+start and stop. In the case of ``MyApp``, it inherits from class
+``Application`` and overrides ``StartApplication``, and
+``StopApplication``. These are the functions that will be called by
+the simulator at the appropriate time. In the case of ``MyApp`` you
+will find that ``MyApp::StartApplication`` does the initial ``Bind``,
+and ``Connect`` on the socket, and then starts data flowing by calling
+``MyApp::SendPacket``. ``MyApp::StopApplication`` stops generating
+packets by cancelling any pending send events and closing the socket.
+
+One of the nice things about |ns3| is that you can completely
+ignore the implementation details of how your ``Application`` is
+"automagically" called by the simulator at the correct time. But since
+we have already ventured deep into |ns3| already, let's go for it.
+
+If you look at ``src/node/application.cc`` you will find that the
+``SetStartTime`` method of an ``Application`` just sets the member
+variable ``m_startTime`` and the ``SetStopTime`` method just sets
+``m_stopTime``. From there, without some hints, the trail will probably
+end.
+
+The key to picking up the trail again is to know that there is a global
+list of all of the nodes in the system. Whenever you create a node in
+a simulation, a pointer to that node is added to the global ``NodeList``.
+
+Take a look at ``src/node/node-list.cc`` and search for
+``NodeList::Add``. The public static implementation calls into a private
+implementation called ``NodeListPriv::Add``. This is a relatively common
+idom in |ns3|. So, take a look at ``NodeListPriv::Add``. There
+you will find,
+
+::
+
+ Simulator::ScheduleWithContext (index, TimeStep (0), &Node::Start, node);
+
+This tells you that whenever a ``Node`` is created in a simulation, as
+a side-effect, a call to that node's ``Start`` method is scheduled for
+you that happens at time zero. Don't read too much into that name, yet.
+It doesn't mean that the node is going to start doing anything, it can be
+interpreted as an informational call into the ``Node`` telling it that
+the simulation has started, not a call for action telling the ``Node``
+to start doing something.
+
+So, ``NodeList::Add`` indirectly schedules a call to ``Node::Start``
+at time zero to advise a new node that the simulation has started. If you
+look in ``src/node/node.h`` you will, however, not find a method called
+``Node::Start``. It turns out that the ``Start`` method is inherited
+from class ``Object``. All objects in the system can be notified when
+the simulation starts, and objects of class ``Node`` are just one kind
+of those objects.
+
+Take a look at ``src/core/object.cc`` next and search for ``Object::Start``.
+This code is not as straightforward as you might have expected since
+|ns3| ``Objects`` support aggregation. The code in
+``Object::Start`` then loops through all of the objects that have been
+aggregated together and calls their ``DoStart`` method. This is another
+idiom that is very common in |ns3|. There is a public API method,
+that stays constant across implementations, that calls a private implementation
+method that is inherited and implemented by subclasses. The names are typically
+something like ``MethodName`` for the public API and ``DoMethodName`` for
+the private API.
+
+This tells us that we should look for a ``Node::DoStart`` method in
+``src/node/node.cc`` for the method that will continue our trail. If you
+locate the code, you will find a method that loops through all of the devices
+in the node and then all of the applications in the node calling
+``device->Start`` and ``application->Start`` respectively.
+
+You may already know that classes ``Device`` and ``Application`` both
+inherit from class ``Object`` and so the next step will be to look at
+what happens when ``Application::DoStart`` is called. Take a look at
+``src/node/application.cc`` and you will find:
+
+::
+
+ void
+ Application::DoStart (void)
+ {
+ m_startEvent = Simulator::Schedule (m_startTime, &Application::StartApplication, this);
+ if (m_stopTime != TimeStep (0))
+ {
+ m_stopEvent = Simulator::Schedule (m_stopTime, &Application::StopApplication, this);
+ }
+ Object::DoStart ();
+ }
+
+Here, we finally come to the end of the trail. If you have kept it all straight,
+when you implement an |ns3| ``Application``, your new application
+inherits from class ``Application``. You override the ``StartApplication``
+and ``StopApplication`` methods and provide mechanisms for starting and
+stopping the flow of data out of your new ``Application``. When a ``Node``
+is created in the simulation, it is added to a global ``NodeList``. The act
+of adding a node to this ``NodeList`` causes a simulator event to be scheduled
+for time zero which calls the ``Node::Start`` method of the newly added
+``Node`` to be called when the simulation starts. Since a ``Node`` inherits
+from ``Object``, this calls the ``Object::Start`` method on the ``Node``
+which, in turn, calls the ``DoStart`` methods on all of the ``Objects``
+aggregated to the ``Node`` (think mobility models). Since the ``Node``
+``Object`` has overridden ``DoStart``, that method is called when the
+simulation starts. The ``Node::DoStart`` method calls the ``Start`` methods
+of all of the ``Applications`` on the node. Since ``Applications`` are
+also ``Objects``, this causes ``Application::DoStart`` to be called. When
+``Application::DoStart`` is called, it schedules events for the
+``StartApplication`` and ``StopApplication`` calls on the ``Application``.
+These calls are designed to start and stop the flow of data from the
+``Application``
+
+This has been another fairly long journey, but it only has to be made once, and
+you now understand another very deep piece of |ns3|.
+
+The MyApp Application
+~~~~~~~~~~~~~~~~~~~~~
+
+The ``MyApp`` ``Application`` needs a constructor and a destructor,
+of course:
+
+::
+
+ MyApp::MyApp ()
+ : m_socket (0),
+ m_peer (),
+ m_packetSize (0),
+ m_nPackets (0),
+ m_dataRate (0),
+ m_sendEvent (),
+ m_running (false),
+ m_packetsSent (0)
+ {
+ }
+
+ MyApp::~MyApp()
+ {
+ m_socket = 0;
+ }
+
+The existence of the next bit of code is the whole reason why we wrote this
+``Application`` in the first place.
+
+::
+
+ void
+ MyApp::Setup (Ptr<Socket> socket, Address address, uint32_t packetSize,
+ uint32_t nPackets, DataRate dataRate)
+ {
+ m_socket = socket;
+ m_peer = address;
+ m_packetSize = packetSize;
+ m_nPackets = nPackets;
+ m_dataRate = dataRate;
+ }
+
+This code should be pretty self-explanatory. We are just initializing member
+variables. The important one from the perspective of tracing is the
+``Ptr<Socket> socket`` which we needed to provide to the application
+during configuration time. Recall that we are going to create the ``Socket``
+as a ``TcpSocket`` (which is implemented by ``TcpNewReno``) and hook
+its "CongestionWindow" trace source before passing it to the ``Setup``
+method.
+
+::
+
+ void
+ MyApp::StartApplication (void)
+ {
+ m_running = true;
+ m_packetsSent = 0;
+ m_socket->Bind ();
+ m_socket->Connect (m_peer);
+ SendPacket ();
+ }
+
+The above code is the overridden implementation ``Application::StartApplication``
+that will be automatically called by the simulator to start our ``Application``
+running at the appropriate time. You can see that it does a ``Socket`` ``Bind``
+operation. If you are familiar with Berkeley Sockets this shouldn't be a surprise.
+It performs the required work on the local side of the connection just as you might
+expect. The following ``Connect`` will do what is required to establish a connection
+with the TCP at ``Address`` m_peer. It should now be clear why we need to defer
+a lot of this to simulation time, since the ``Connect`` is going to need a fully
+functioning network to complete. After the ``Connect``, the ``Application``
+then starts creating simulation events by calling ``SendPacket``.
+
+The next bit of code explains to the ``Application`` how to stop creating
+simulation events.
+
+::
+
+ void
+ MyApp::StopApplication (void)
+ {
+ m_running = false;
+
+ if (m_sendEvent.IsRunning ())
+ {
+ Simulator::Cancel (m_sendEvent);
+ }
+
+ if (m_socket)
+ {
+ m_socket->Close ();
+ }
+ }
+
+Every time a simulation event is scheduled, an ``Event`` is created. If the
+``Event`` is pending execution or executing, its method ``IsRunning`` will
+return ``true``. In this code, if ``IsRunning()`` returns true, we
+``Cancel`` the event which removes it from the simulator event queue. By
+doing this, we break the chain of events that the ``Application`` is using to
+keep sending its ``Packets`` and the ``Application`` goes quiet. After we
+quiet the ``Application`` we ``Close`` the socket which tears down the TCP
+connection.
+
+The socket is actually deleted in the destructor when the ``m_socket = 0`` is
+executed. This removes the last reference to the underlying Ptr<Socket> which
+causes the destructor of that Object to be called.
+
+Recall that ``StartApplication`` called ``SendPacket`` to start the
+chain of events that describes the ``Application`` behavior.
+
+::
+
+ void
+ MyApp::SendPacket (void)
+ {
+ Ptr<Packet> packet = Create<Packet> (m_packetSize);
+ m_socket->Send (packet);
+
+ if (++m_packetsSent < m_nPackets)
+ {
+ ScheduleTx ();
+ }
+ }
+
+Here, you see that ``SendPacket`` does just that. It creates a ``Packet``
+and then does a ``Send`` which, if you know Berkeley Sockets, is probably
+just what you expected to see.
+
+It is the responsibility of the ``Application`` to keep scheduling the
+chain of events, so the next lines call ``ScheduleTx`` to schedule another
+transmit event (a ``SendPacket``) until the ``Application`` decides it
+has sent enough.
+
+::
+
+ void
+ MyApp::ScheduleTx (void)
+ {
+ if (m_running)
+ {
+ Time tNext (Seconds (m_packetSize * 8 / static_cast<double> (m_dataRate.GetBitRate ())));
+ m_sendEvent = Simulator::Schedule (tNext, &MyApp::SendPacket, this);
+ }
+ }
+
+Here, you see that ``ScheduleTx`` does exactly that. If the ``Application``
+is running (if ``StopApplication`` has not been called) it will schedule a
+new event, which calls ``SendPacket`` again. The alert reader will spot
+something that also trips up new users. The data rate of an ``Application`` is
+just that. It has nothing to do with the data rate of an underlying ``Channel``.
+This is the rate at which the ``Application`` produces bits. It does not take
+into account any overhead for the various protocols or channels that it uses to
+transport the data. If you set the data rate of an ``Application`` to the same
+data rate as your underlying ``Channel`` you will eventually get a buffer overflow.
+
+The Trace Sinks
+~~~~~~~~~~~~~~~
+
+The whole point of this exercise is to get trace callbacks from TCP indicating the
+congestion window has been updated. The next piece of code implements the
+corresponding trace sink:
+
+::
+
+ static void
+ CwndChange (uint32_t oldCwnd, uint32_t newCwnd)
+ {
+ NS_LOG_UNCOND (Simulator::Now ().GetSeconds () << "\t" << newCwnd);
+ }
+
+This should be very familiar to you now, so we won't dwell on the details. This
+function just logs the current simulation time and the new value of the
+congestion window every time it is changed. You can probably imagine that you
+could load the resulting output into a graphics program (gnuplot or Excel) and
+immediately see a nice graph of the congestion window behavior over time.
+
+We added a new trace sink to show where packets are dropped. We are going to
+add an error model to this code also, so we wanted to demonstrate this working.
+
+::
+
+ static void
+ RxDrop (Ptr<const Packet> p)
+ {
+ NS_LOG_UNCOND ("RxDrop at " << Simulator::Now ().GetSeconds ());
+ }
+
+This trace sink will be connected to the "PhyRxDrop" trace source of the
+point-to-point NetDevice. This trace source fires when a packet is dropped
+by the physical layer of a ``NetDevice``. If you take a small detour to the
+source (``src/devices/point-to-point/point-to-point-net-device.cc``) you will
+see that this trace source refers to ``PointToPointNetDevice::m_phyRxDropTrace``.
+If you then look in ``src/devices/point-to-point/point-to-point-net-device.h``
+for this member variable, you will find that it is declared as a
+``TracedCallback<Ptr<const Packet> >``. This should tell you that the
+callback target should be a function that returns void and takes a single
+parameter which is a ``Ptr<const Packet>`` -- just what we have above.
+
+The Main Program
+~~~~~~~~~~~~~~~~
+
+The following code should be very familiar to you by now:
+
+::
+
+ int
+ main (int argc, char *argv[])
+ {
+ NodeContainer nodes;
+ nodes.Create (2);
+
+ PointToPointHelper pointToPoint;
+ pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
+ pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
+
+ NetDeviceContainer devices;
+ devices = pointToPoint.Install (nodes);
+
+This creates two nodes with a point-to-point channel between them, just as
+shown in the illustration at the start of the file.
+
+The next few lines of code show something new. If we trace a connection that
+behaves perfectly, we will end up with a monotonically increasing congestion
+window. To see any interesting behavior, we really want to introduce link
+errors which will drop packets, cause duplicate ACKs and trigger the more
+interesting behaviors of the congestion window.
+
+|ns3| provides ``ErrorModel`` objects which can be attached to
+``Channels``. We are using the ``RateErrorModel`` which allows us
+to introduce errors into a ``Channel`` at a given *rate*.
+
+::
+
+ Ptr<RateErrorModel> em = CreateObjectWithAttributes<RateErrorModel> (
+ "RanVar", RandomVariableValue (UniformVariable (0., 1.)),
+ "ErrorRate", DoubleValue (0.00001));
+ devices.Get (1)->SetAttribute ("ReceiveErrorModel", PointerValue (em));
+
+The above code instantiates a ``RateErrorModel`` Object. Rather than
+using the two-step process of instantiating it and then setting Attributes,
+we use the convenience function ``CreateObjectWithAttributes`` which
+allows us to do both at the same time. We set the "RanVar"
+``Attribute`` to a random variable that generates a uniform distribution
+from 0 to 1. We also set the "ErrorRate" ``Attribute``.
+We then set the resulting instantiated ``RateErrorModel`` as the error
+model used by the point-to-point ``NetDevice``. This will give us some
+retransmissions and make our plot a little more interesting.
+
+::
+
+ InternetStackHelper stack;
+ stack.Install (nodes);
+
+ Ipv4AddressHelper address;
+ address.SetBase ("10.1.1.0", "255.255.255.252");
+ Ipv4InterfaceContainer interfaces = address.Assign (devices);
+
+The above code should be familiar. It installs internet stacks on our two
+nodes and creates interfaces and assigns IP addresses for the point-to-point
+devices.
+
+Since we are using TCP, we need something on the destination node to receive
+TCP connections and data. The ``PacketSink`` ``Application`` is commonly
+used in |ns3| for that purpose.
+
+::
+
+ uint16_t sinkPort = 8080;
+ Address sinkAddress (InetSocketAddress(interfaces.GetAddress (1), sinkPort));
+ PacketSinkHelper packetSinkHelper ("ns3::TcpSocketFactory",
+ InetSocketAddress (Ipv4Address::GetAny (), sinkPort));
+ ApplicationContainer sinkApps = packetSinkHelper.Install (nodes.Get (1));
+ sinkApps.Start (Seconds (0.));
+ sinkApps.Stop (Seconds (20.));
+
+This should all be familiar, with the exception of,
+
+::
+
+ PacketSinkHelper packetSinkHelper ("ns3::TcpSocketFactory",
+ InetSocketAddress (Ipv4Address::GetAny (), sinkPort));
+
+This code instantiates a ``PacketSinkHelper`` and tells it to create sockets
+using the class ``ns3::TcpSocketFactory``. This class implements a design
+pattern called "object factory" which is a commonly used mechanism for
+specifying a class used to create objects in an abstract way. Here, instead of
+having to create the objects themselves, you provide the ``PacketSinkHelper``
+a string that specifies a ``TypeId`` string used to create an object which
+can then be used, in turn, to create instances of the Objects created by the
+factory.
+
+The remaining parameter tells the ``Application`` which address and port it
+should ``Bind`` to.
+
+The next two lines of code will create the socket and connect the trace source.
+
+::
+
+ Ptr<Socket> ns3TcpSocket = Socket::CreateSocket (nodes.Get (0),
+ TcpSocketFactory::GetTypeId ());
+ ns3TcpSocket->TraceConnectWithoutContext ("CongestionWindow",
+ MakeCallback (&CwndChange));
+
+The first statement calls the static member function ``Socket::CreateSocket``
+and provides a ``Node`` and an explicit ``TypeId`` for the object factory
+used to create the socket. This is a slightly lower level call than the
+``PacketSinkHelper`` call above, and uses an explicit C++ type instead of
+one referred to by a string. Otherwise, it is conceptually the same thing.
+
+Once the ``TcpSocket`` is created and attached to the ``Node``, we can
+use ``TraceConnectWithoutContext`` to connect the CongestionWindow trace
+source to our trace sink.
+
+Recall that we coded an ``Application`` so we could take that ``Socket``
+we just made (during configuration time) and use it in simulation time. We now
+have to instantiate that ``Application``. We didn't go to any trouble to
+create a helper to manage the ``Application`` so we are going to have to
+create and install it "manually". This is actually quite easy:
+
+::
+
+ Ptr<MyApp> app = CreateObject<MyApp> ();
+ app->Setup (ns3TcpSocket, sinkAddress, 1040, 1000, DataRate ("1Mbps"));
+ nodes.Get (0)->AddApplication (app);
+ app->Start (Seconds (1.));
+ app->Stop (Seconds (20.));
+
+The first line creates an ``Object`` of type ``MyApp`` -- our
+``Application``. The second line tells the ``Application`` what
+``Socket`` to use, what address to connect to, how much data to send
+at each send event, how many send events to generate and the rate at which
+to produce data from those events.
+
+Next, we manually add the ``MyApp Application`` to the source node
+and explicitly call the ``Start`` and ``Stop`` methods on the
+``Application`` to tell it when to start and stop doing its thing.
+
+We need to actually do the connect from the receiver point-to-point ``NetDevice``
+to our callback now.
+
+::
+
+ devices.Get (1)->TraceConnectWithoutContext("PhyRxDrop", MakeCallback (&RxDrop));
+
+It should now be obvious that we are getting a reference to the receiving
+``Node NetDevice`` from its container and connecting the trace source defined
+by the attribute "PhyRxDrop" on that device to the trace sink ``RxDrop``.
+
+Finally, we tell the simulator to override any ``Applications`` and just
+stop processing events at 20 seconds into the simulation.
+
+::
+
+ Simulator::Stop (Seconds(20));
+ Simulator::Run ();
+ Simulator::Destroy ();
+
+ return 0;
+ }
+
+Recall that as soon as ``Simulator::Run`` is called, configuration time
+ends, and simulation time begins. All of the work we orchestrated by
+creating the ``Application`` and teaching it how to connect and send
+data actually happens during this function call.
+
+As soon as ``Simulator::Run`` returns, the simulation is complete and
+we enter the teardown phase. In this case, ``Simulator::Destroy`` takes
+care of the gory details and we just return a success code after it completes.
+
+Running fifth.cc
+++++++++++++++++
+
+Since we have provided the file ``fifth.cc`` for you, if you have built
+your distribution (in debug mode since it uses NS_LOG -- recall that optimized
+builds optimize out NS_LOGs) it will be waiting for you to run.
+
+::
+
+ ./waf --run fifth
+ Waf: Entering directory `/home/craigdo/repos/ns-3-allinone-dev/ns-3-dev/build
+ Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone-dev/ns-3-dev/build'
+ 'build' finished successfully (0.684s)
+ 1.20919 1072
+ 1.21511 1608
+ 1.22103 2144
+ ...
+ 1.2471 8040
+ 1.24895 8576
+ 1.2508 9112
+ RxDrop at 1.25151
+ ...
+
+You can probably see immediately a downside of using prints of any kind in your
+traces. We get those extraneous waf messages printed all over our interesting
+information along with those RxDrop messages. We will remedy that soon, but I'm
+sure you can't wait to see the results of all of this work. Let's redirect that
+output to a file called ``cwnd.dat``:
+
+::
+
+ ./waf --run fifth > cwnd.dat 2>&1
+
+Now edit up "cwnd.dat" in your favorite editor and remove the waf build status
+and drop lines, leaving only the traced data (you could also comment out the
+``TraceConnectWithoutContext("PhyRxDrop", MakeCallback (&RxDrop));`` in the
+script to get rid of the drop prints just as easily.
+
+You can now run gnuplot (if you have it installed) and tell it to generate some
+pretty pictures:
+
+::
+
+ gnuplot> set terminal png size 640,480
+ gnuplot> set output "cwnd.png"
+ gnuplot> plot "cwnd.dat" using 1:2 title 'Congestion Window' with linespoints
+ gnuplot> exit
+
+You should now have a graph of the congestion window versus time sitting in the
+file "cwnd.png" that looks like:
+
+.. figure:: figures/cwnd.png
+
+Using Mid-Level Helpers
++++++++++++++++++++++++
+
+In the previous section, we showed how to hook a trace source and get hopefully
+interesting information out of a simulation. Perhaps you will recall that we
+called logging to the standard output using ``std::cout`` a "Blunt Instrument"
+much earlier in this chapter. We also wrote about how it was a problem having
+to parse the log output in order to isolate interesting information. It may
+have occurred to you that we just spent a lot of time implementing an example
+that exhibits all of the problems we purport to fix with the |ns3| tracing
+system! You would be correct. But, bear with us. We're not done yet.
+
+One of the most important things we want to do is to is to have the ability to
+easily control the amount of output coming out of the simulation; and we also
+want to save those data to a file so we can refer back to it later. We can use
+the mid-level trace helpers provided in |ns3| to do just that and complete
+the picture.
+
+We provide a script that writes the cwnd change and drop events developed in
+the example ``fifth.cc`` to disk in separate files. The cwnd changes are
+stored as a tab-separated ASCII file and the drop events are stored in a pcap
+file. The changes to make this happen are quite small.
+
+A sixth.cc Walkthrough
+~~~~~~~~~~~~~~~~~~~~~~
+
+Let's take a look at the changes required to go from ``fifth.cc`` to
+``sixth.cc``. Open ``examples/tutorial/fifth.cc`` in your favorite
+editor. You can see the first change by searching for CwndChange. You will
+find that we have changed the signatures for the trace sinks and have added
+a single line to each sink that writes the traced information to a stream
+representing a file.
+
+::
+
+ static void
+ CwndChange (Ptr<OutputStreamWrapper> stream, uint32_t oldCwnd, uint32_t newCwnd)
+ {
+ NS_LOG_UNCOND (Simulator::Now ().GetSeconds () << "\t" << newCwnd);
+ *stream->GetStream () << Simulator::Now ().GetSeconds () << "\t" << oldCwnd << "\t" << newCwnd << std::endl;
+ }
+
+ static void
+ RxDrop (Ptr<PcapFileWrapper> file, Ptr<const Packet> p)
+ {
+ NS_LOG_UNCOND ("RxDrop at " << Simulator::Now ().GetSeconds ());
+ file->Write(Simulator::Now(), p);
+ }
+
+We have added a "stream" parameter to the ``CwndChange`` trace sink.
+This is an object that holds (keeps safely alive) a C++ output stream. It
+turns out that this is a very simple object, but one that manages lifetime
+issues for the stream and solves a problem that even experienced C++ users
+run into. It turns out that the copy constructor for ostream is marked
+private. This means that ostreams do not obey value semantics and cannot
+be used in any mechanism that requires the stream to be copied. This includes
+the |ns3| callback system, which as you may recall, requires objects
+that obey value semantics. Further notice that we have added the following
+line in the ``CwndChange`` trace sink implementation:
+
+::
+
+ *stream->GetStream () << Simulator::Now ().GetSeconds () << "\t" << oldCwnd << "\t" << newCwnd << std::endl;
+
+This would be very familiar code if you replaced ``*stream->GetStream ()``
+with ``std::cout``, as in:
+
+::
+
+ std::cout << Simulator::Now ().GetSeconds () << "\t" << oldCwnd << "\t" << newCwnd << std::endl;
+
+This illustrates that the ``Ptr<OutputStreamWrapper>`` is really just
+carrying around a ``std::ofstream`` for you, and you can use it here like
+any other output stream.
+
+A similar situation happens in ``RxDrop`` except that the object being
+passed around (a ``Ptr<PcapFileWrapper>``) represents a pcap file. There
+is a one-liner in the trace sink to write a timestamp and the contents of the
+packet being dropped to the pcap file:
+
+::
+
+ file->Write(Simulator::Now(), p);
+
+Of course, if we have objects representing the two files, we need to create
+them somewhere and also cause them to be passed to the trace sinks. If you
+look in the ``main`` function, you will find new code to do just that:
+
+::
+
+ AsciiTraceHelper asciiTraceHelper;
+ Ptr<OutputStreamWrapper> stream = asciiTraceHelper.CreateFileStream ("sixth.cwnd");
+ ns3TcpSocket->TraceConnectWithoutContext ("CongestionWindow", MakeBoundCallback (&CwndChange, stream));
+
+ ...
+
+ PcapHelper pcapHelper;
+ Ptr<PcapFileWrapper> file = pcapHelper.CreateFile ("sixth.pcap", std::ios::out, PcapHelper::DLT_PPP);
+ devices.Get (1)->TraceConnectWithoutContext("PhyRxDrop", MakeBoundCallback (&RxDrop, file));
+
+In the first section of the code snippet above, we are creating the ASCII
+trace file, creating an object responsible for managing it and using a
+variant of the callback creation function to arrange for the object to be
+passed to the sink. Our ASCII trace helpers provide a rich set of
+functions to make using text (ASCII) files easy. We are just going to
+illustrate the use of the file stream creation function here.
+
+The ``CreateFileStream{}`` function is basically going to instantiate
+a std::ofstream object and create a new file (or truncate an existing file).
+This ofstream is packaged up in an |ns3| object for lifetime management
+and copy constructor issue resolution.
+
+We then take this |ns3| object representing the file and pass it to
+``MakeBoundCallback()``. This function creates a callback just like
+``MakeCallback()``, but it "binds" a new value to the callback. This
+value is added to the callback before it is called.
+
+Essentially, ``MakeBoundCallback(&CwndChange, stream)`` causes the trace
+source to add the additional "stream" parameter to the front of the formal
+parameter list before invoking the callback. This changes the required
+signature of the ``CwndChange`` sink to match the one shown above, which
+includes the "extra" parameter ``Ptr<OutputStreamWrapper> stream``.
+
+In the second section of code in the snippet above, we instantiate a
+``PcapHelper`` to do the same thing for our pcap trace file that we did
+with the ``AsciiTraceHelper``. The line of code,
+
+::
+
+ Ptr<PcapFileWrapper> file = pcapHelper.CreateFile ("sixth.pcap", "w", PcapHelper::DLT_PPP);
+
+creates a pcap file named "sixth.pcap" with file mode "w". This means that
+the new file is to truncated if an existing file with that name is found. The
+final parameter is the "data link type" of the new pcap file. These are
+the same as the pcap library data link types defined in ``bpf.h`` if you are
+familar with pcap. In this case, ``DLT_PPP`` indicates that the pcap file
+is going to contain packets prefixed with point to point headers. This is true
+since the packets are coming from our point-to-point device driver. Other
+common data link types are DLT_EN10MB (10 MB Ethernet) appropriate for csma
+devices and DLT_IEEE802_11 (IEEE 802.11) appropriate for wifi devices. These
+are defined in ``src/helper/trace-helper.h"`` if you are interested in seeing
+the list. The entries in the list match those in ``bpf.h`` but we duplicate
+them to avoid a pcap source dependence.
+
+A |ns3| object representing the pcap file is returned from ``CreateFile``
+and used in a bound callback exactly as it was in the ascii case.
+
+An important detour: It is important to notice that even though both of these
+objects are declared in very similar ways,
+
+::
+
+ Ptr<PcapFileWrapper> file ...
+ Ptr<OutputStreamWrapper> stream ...
+
+The underlying objects are entirely different. For example, the
+Ptr<PcapFileWrapper> is a smart pointer to an |ns3| Object that is a
+fairly heaviweight thing that supports ``Attributes`` and is integrated into
+the config system. The Ptr<OutputStreamWrapper>, on the other hand, is a smart
+pointer to a reference counted object that is a very lightweight thing.
+Remember to always look at the object you are referencing before making any
+assumptions about the "powers" that object may have.
+
+For example, take a look at ``src/common/pcap-file-object.h`` in the
+distribution and notice,
+
+::
+
+ class PcapFileWrapper : public Object
+
+that class ``PcapFileWrapper`` is an |ns3| Object by virtue of
+its inheritance. Then look at ``src/common/output-stream-wrapper.h`` and
+notice,
+
+::
+
+ class OutputStreamWrapper : public SimpleRefCount<OutputStreamWrapper>
+
+that this object is not an |ns3| Object at all, it is "merely" a
+C++ object that happens to support intrusive reference counting.
+
+The point here is that just because you read Ptr<something> it does not necessarily
+mean that "something" is an |ns3| Object on which you can hang |ns3|
+``Attributes``, for example.
+
+Now, back to the example. If you now build and run this example,
+
+::
+
+ ./waf --run sixth
+
+you will see the same messages appear as when you ran "fifth", but two new
+files will appear in the top-level directory of your |ns3| distribution.
+
+::
+
+ sixth.cwnd sixth.pcap
+
+Since "sixth.cwnd" is an ASCII text file, you can view it with ``cat``
+or your favorite file viewer.
+
+::
+
+ 1.20919 536 1072
+ 1.21511 1072 1608
+ ...
+ 9.30922 8893 8925
+ 9.31754 8925 8957
+
+You have a tab separated file with a timestamp, an old congestion window and a
+new congestion window suitable for directly importing into your plot program.
+There are no extraneous prints in the file, no parsing or editing is required.
+
+Since "sixth.pcap" is a pcap file, you can fiew it with ``tcpdump``.
+
+::
+
+ reading from file ../../sixth.pcap, link-type PPP (PPP)
+ 1.251507 IP 10.1.1.1.49153 > 10.1.1.2.8080: . 17689:18225(536) ack 1 win 65535
+ 1.411478 IP 10.1.1.1.49153 > 10.1.1.2.8080: . 33808:34312(504) ack 1 win 65535
+ ...
+ 7.393557 IP 10.1.1.1.49153 > 10.1.1.2.8080: . 781568:782072(504) ack 1 win 65535
+ 8.141483 IP 10.1.1.1.49153 > 10.1.1.2.8080: . 874632:875168(536) ack 1 win 65535
+
+You have a pcap file with the packets that were dropped in the simulation. There
+are no other packets present in the file and there is nothing else present to
+make life difficult.
+
+It's been a long journey, but we are now at a point where we can appreciate the
+|ns3| tracing system. We have pulled important events out of the middle
+of a TCP implementation and a device driver. We stored those events directly in
+files usable with commonly known tools. We did this without modifying any of the
+core code involved, and we did this in only 18 lines of code:
+
+::
+
+ static void
+ CwndChange (Ptr<OutputStreamWrapper> stream, uint32_t oldCwnd, uint32_t newCwnd)
+ {
+ NS_LOG_UNCOND (Simulator::Now ().GetSeconds () << "\t" << newCwnd);
+ *stream->GetStream () << Simulator::Now ().GetSeconds () << "\t" << oldCwnd << "\t" << newCwnd << std::endl;
+ }
+
+ ...
+
+ AsciiTraceHelper asciiTraceHelper;
+ Ptr<OutputStreamWrapper> stream = asciiTraceHelper.CreateFileStream ("sixth.cwnd");
+ ns3TcpSocket->TraceConnectWithoutContext ("CongestionWindow", MakeBoundCallback (&CwndChange, stream));
+
+ ...
+
+ static void
+ RxDrop (Ptr<PcapFileWrapper> file, Ptr<const Packet> p)
+ {
+ NS_LOG_UNCOND ("RxDrop at " << Simulator::Now ().GetSeconds ());
+ file->Write(Simulator::Now(), p);
+ }
+
+ ...
+
+ PcapHelper pcapHelper;
+ Ptr<PcapFileWrapper> file = pcapHelper.CreateFile ("sixth.pcap", "w", PcapHelper::DLT_PPP);
+ devices.Get (1)->TraceConnectWithoutContext("PhyRxDrop", MakeBoundCallback (&RxDrop, file));
+
+Using Trace Helpers
+*******************
+
+The |ns3| trace helpers provide a rich environment for configuring and
+selecting different trace events and writing them to files. In previous
+sections, primarily "Building Topologies," we have seen several varieties
+of the trace helper methods designed for use inside other (device) helpers.
+
+Perhaps you will recall seeing some of these variations:
+
+::
+
+ pointToPoint.EnablePcapAll ("second");
+ pointToPoint.EnablePcap ("second", p2pNodes.Get (0)->GetId (), 0);
+ csma.EnablePcap ("third", csmaDevices.Get (0), true);
+ pointToPoint.EnableAsciiAll (ascii.CreateFileStream ("myfirst.tr"));
+
+What may not be obvious, though, is that there is a consistent model for all of
+the trace-related methods found in the system. We will now take a little time
+and take a look at the "big picture".
+
+There are currently two primary use cases of the tracing helpers in |ns3|:
+Device helpers and protocol helpers. Device helpers look at the problem
+of specifying which traces should be enabled through a node, device pair. For
+example, you may want to specify that pcap tracing should be enabled on a
+particular device on a specific node. This follows from the |ns3| device
+conceptual model, and also the conceptual models of the various device helpers.
+Following naturally from this, the files created follow a
+<prefix>-<node>-<device> naming convention.
+
+Protocol helpers look at the problem of specifying which traces should be
+enabled through a protocol and interface pair. This follows from the |ns3|
+protocol stack conceptual model, and also the conceptual models of internet
+stack helpers. Naturally, the trace files should follow a
+<prefix>-<protocol>-<interface> naming convention.
+
+The trace helpers therefore fall naturally into a two-dimensional taxonomy.
+There are subtleties that prevent all four classes from behaving identically,
+but we do strive to make them all work as similarly as possible; and whenever
+possible there are analogs for all methods in all classes.
+
+::
+
+ | pcap | ascii |
+ -----------------+------+-------|
+ Device Helper | | |
+ -----------------+------+-------|
+ Protocol Helper | | |
+ -----------------+------+-------|
+
+We use an approach called a ``mixin`` to add tracing functionality to our
+helper classes. A ``mixin`` is a class that provides functionality to that
+is inherited by a subclass. Inheriting from a mixin is not considered a form
+of specialization but is really a way to collect functionality.
+
+Let's take a quick look at all four of these cases and their respective
+``mixins``.
+
+Pcap Tracing Device Helpers
++++++++++++++++++++++++++++
+
+The goal of these helpers is to make it easy to add a consistent pcap trace
+facility to an |ns3| device. We want all of the various flavors of
+pcap tracing to work the same across all devices, so the methods of these
+helpers are inherited by device helpers. Take a look at
+``src/helper/trace-helper.h`` if you want to follow the discussion while
+looking at real code.
+
+The class ``PcapHelperForDevice`` is a ``mixin`` provides the high level
+functionality for using pcap tracing in an |ns3| device. Every device
+must implement a single virtual method inherited from this class.
+
+::
+
+ virtual void EnablePcapInternal (std::string prefix, Ptr<NetDevice> nd, bool promiscuous, bool explicitFilename) = 0;
+
+The signature of this method reflects the device-centric view of the situation
+at this level. All of the public methods inherited from class
+2``PcapUserHelperForDevice`` reduce to calling this single device-dependent
+implementation method. For example, the lowest level pcap method,
+
+::
+
+ void EnablePcap (std::string prefix, Ptr<NetDevice> nd, bool promiscuous = false, bool explicitFilename = false);
+
+will call the device implementation of ``EnablePcapInternal`` directly. All
+other public pcap tracing methods build on this implementation to provide
+additional user-level functionality. What this means to the user is that all
+device helpers in the system will have all of the pcap trace methods available;
+and these methods will all work in the same way across devices if the device
+implements ``EnablePcapInternal`` correctly.
+
+Pcap Tracing Device Helper Methods
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ void EnablePcap (std::string prefix, Ptr<NetDevice> nd, bool promiscuous = false, bool explicitFilename = false);
+ void EnablePcap (std::string prefix, std::string ndName, bool promiscuous = false, bool explicitFilename = false);
+ void EnablePcap (std::string prefix, NetDeviceContainer d, bool promiscuous = false);
+ void EnablePcap (std::string prefix, NodeContainer n, bool promiscuous = false);
+ void EnablePcap (std::string prefix, uint32_t nodeid, uint32_t deviceid, bool promiscuous = false);
+ void EnablePcapAll (std::string prefix, bool promiscuous = false);
+
+In each of the methods shown above, there is a default parameter called
+``promiscuous`` that defaults to false. This parameter indicates that the
+trace should not be gathered in promiscuous mode. If you do want your traces
+to include all traffic seen by the device (and if the device supports a
+promiscuous mode) simply add a true parameter to any of the calls above. For example,
+
+::
+
+ Ptr<NetDevice> nd;
+ ...
+ helper.EnablePcap ("prefix", nd, true);
+
+will enable promiscuous mode captures on the ``NetDevice`` specified by ``nd``.
+
+The first two methods also include a default parameter called ``explicitFilename``
+that will be discussed below.
+
+You are encouraged to peruse the Doxygen for class ``PcapHelperForDevice``
+to find the details of these methods; but to summarize ...
+
+You can enable pcap tracing on a particular node/net-device pair by providing a
+``Ptr<NetDevice>`` to an ``EnablePcap`` method. The ``Ptr<Node>`` is
+implicit since the net device must belong to exactly one ``Node``.
+For example,
+
+::
+
+ Ptr<NetDevice> nd;
+ ...
+ helper.EnablePcap ("prefix", nd);
+
+You can enable pcap tracing on a particular node/net-device pair by providing a
+``std::string`` representing an object name service string to an
+``EnablePcap`` method. The ``Ptr<NetDevice>`` is looked up from the name
+string. Again, the ``<Node>`` is implicit since the named net device must
+belong to exactly one ``Node``. For example,
+
+::
+
+ Names::Add ("server" ...);
+ Names::Add ("server/eth0" ...);
+ ...
+ helper.EnablePcap ("prefix", "server/ath0");
+
+You can enable pcap tracing on a collection of node/net-device pairs by
+providing a ``NetDeviceContainer``. For each ``NetDevice`` in the container
+the type is checked. For each device of the proper type (the same type as is
+managed by the device helper), tracing is enabled. Again, the ``<Node>`` is
+implicit since the found net device must belong to exactly one ``Node``.
+For example,
+
+::
+
+ NetDeviceContainer d = ...;
+ ...
+ helper.EnablePcap ("prefix", d);
+
+You can enable pcap tracing on a collection of node/net-device pairs by
+providing a ``NodeContainer``. For each ``Node`` in the ``NodeContainer``
+its attached ``NetDevices`` are iterated. For each ``NetDevice`` attached
+to each node in the container, the type of that device is checked. For each
+device of the proper type (the same type as is managed by the device helper),
+tracing is enabled.
+
+::
+
+ NodeContainer n;
+ ...
+ helper.EnablePcap ("prefix", n);
+
+You can enable pcap tracing on the basis of node ID and device ID as well as
+with explicit ``Ptr``. Each ``Node`` in the system has an integer node ID
+and each device connected to a node has an integer device ID.
+
+::
+
+ helper.EnablePcap ("prefix", 21, 1);
+
+Finally, you can enable pcap tracing for all devices in the system, with the
+same type as that managed by the device helper.
+
+::
+
+ helper.EnablePcapAll ("prefix");
+
+Pcap Tracing Device Helper Filename Selection
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Implicit in the method descriptions above is the construction of a complete
+filename by the implementation method. By convention, pcap traces in the
+|ns3| system are of the form "<prefix>-<node id>-<device id>.pcap"
+
+As previously mentioned, every node in the system will have a system-assigned
+node id; and every device will have an interface index (also called a device id)
+relative to its node. By default, then, a pcap trace file created as a result
+of enabling tracing on the first device of node 21 using the prefix "prefix"
+would be "prefix-21-1.pcap".
+
+You can always use the |ns3| object name service to make this more clear.
+For example, if you use the object name service to assign the name "server"
+to node 21, the resulting pcap trace file name will automatically become,
+"prefix-server-1.pcap" and if you also assign the name "eth0" to the
+device, your pcap file name will automatically pick this up and be called
+"prefix-server-eth0.pcap".
+
+Finally, two of the methods shown above,
+
+::
+
+ void EnablePcap (std::string prefix, Ptr<NetDevice> nd, bool promiscuous = false, bool explicitFilename = false);
+ void EnablePcap (std::string prefix, std::string ndName, bool promiscuous = false, bool explicitFilename = false);
+
+have a default parameter called ``explicitFilename``. When set to true,
+this parameter disables the automatic filename completion mechanism and allows
+you to create an explicit filename. This option is only available in the
+methods which enable pcap tracing on a single device.
+
+For example, in order to arrange for a device helper to create a single
+promiscuous pcap capture file of a specific name ("my-pcap-file.pcap") on a
+given device, one could:
+
+::
+
+ Ptr<NetDevice> nd;
+ ...
+ helper.EnablePcap ("my-pcap-file.pcap", nd, true, true);
+
+The first ``true`` parameter enables promiscuous mode traces and the second
+tells the helper to interpret the ``prefix`` parameter as a complete filename.
+
+Ascii Tracing Device Helpers
+++++++++++++++++++++++++++++
+
+The behavior of the ascii trace helper ``mixin`` is substantially similar to
+the pcap version. Take a look at ``src/helper/trace-helper.h`` if you want to
+follow the discussion while looking at real code.
+
+The class ``AsciiTraceHelperForDevice`` adds the high level functionality for
+using ascii tracing to a device helper class. As in the pcap case, every device
+must implement a single virtual method inherited from the ascii trace ``mixin``.
+
+::
+
+ virtual void EnableAsciiInternal (Ptr<OutputStreamWrapper> stream,
+ std::string prefix,
+ Ptr<NetDevice> nd,
+ bool explicitFilename) = 0;
+
+
+The signature of this method reflects the device-centric view of the situation
+at this level; and also the fact that the helper may be writing to a shared
+output stream. All of the public ascii-trace-related methods inherited from
+class ``AsciiTraceHelperForDevice`` reduce to calling this single device-
+dependent implementation method. For example, the lowest level ascii trace
+methods,
+
+::
+
+ void EnableAscii (std::string prefix, Ptr<NetDevice> nd, bool explicitFilename = false);
+ void EnableAscii (Ptr<OutputStreamWrapper> stream, Ptr<NetDevice> nd);
+
+
+will call the device implementation of ``EnableAsciiInternal`` directly,
+providing either a valid prefix or stream. All other public ascii tracing
+methods will build on these low-level functions to provide additional user-level
+functionality. What this means to the user is that all device helpers in the
+system will have all of the ascii trace methods available; and these methods
+will all work in the same way across devices if the devices implement
+``EnablAsciiInternal`` correctly.
+
+Ascii Tracing Device Helper Methods
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ void EnableAscii (std::string prefix, Ptr<NetDevice> nd, bool explicitFilename = false);
+ void EnableAscii (Ptr<OutputStreamWrapper> stream, Ptr<NetDevice> nd);
+
+ void EnableAscii (std::string prefix, std::string ndName, bool explicitFilename = false);
+ void EnableAscii (Ptr<OutputStreamWrapper> stream, std::string ndName);
+
+ void EnableAscii (std::string prefix, NetDeviceContainer d);
+ void EnableAscii (Ptr<OutputStreamWrapper> stream, NetDeviceContainer d);
+
+ void EnableAscii (std::string prefix, NodeContainer n);
+ void EnableAscii (Ptr<OutputStreamWrapper> stream, NodeContainer n);
+
+ void EnableAsciiAll (std::string prefix);
+ void EnableAsciiAll (Ptr<OutputStreamWrapper> stream);
+
+ void EnableAscii (std::string prefix, uint32_t nodeid, uint32_t deviceid, bool explicitFilename);
+ void EnableAscii (Ptr<OutputStreamWrapper> stream, uint32_t nodeid, uint32_t deviceid);
+
+You are encouraged to peruse the Doxygen for class ``TraceHelperForDevice``
+to find the details of these methods; but to summarize ...
+
+There are twice as many methods available for ascii tracing as there were for
+pcap tracing. This is because, in addition to the pcap-style model where traces
+from each unique node/device pair are written to a unique file, we support a model
+in which trace information for many node/device pairs is written to a common file.
+This means that the <prefix>-<node>-<device> file name generation mechanism is
+replaced by a mechanism to refer to a common file; and the number of API methods
+is doubled to allow all combinations.
+
+Just as in pcap tracing, you can enable ascii tracing on a particular
+node/net-device pair by providing a ``Ptr<NetDevice>`` to an ``EnableAscii``
+method. The ``Ptr<Node>`` is implicit since the net device must belong to
+exactly one ``Node``. For example,
+
+::
+
+ Ptr<NetDevice> nd;
+ ...
+ helper.EnableAscii ("prefix", nd);
+
+The first four methods also include a default parameter called ``explicitFilename``
+that operate similar to equivalent parameters in the pcap case.
+
+In this case, no trace contexts are written to the ascii trace file since they
+would be redundant. The system will pick the file name to be created using
+the same rules as described in the pcap section, except that the file will
+have the suffix ".tr" instead of ".pcap".
+
+If you want to enable ascii tracing on more than one net device and have all
+traces sent to a single file, you can do that as well by using an object to
+refer to a single file. We have already seen this in the "cwnd" example
+above:
+
+::
+
+ Ptr<NetDevice> nd1;
+ Ptr<NetDevice> nd2;
+ ...
+ Ptr<OutputStreamWrapper> stream = asciiTraceHelper.CreateFileStream ("trace-file-name.tr");
+ ...
+ helper.EnableAscii (stream, nd1);
+ helper.EnableAscii (stream, nd2);
+
+
+In this case, trace contexts are written to the ascii trace file since they
+are required to disambiguate traces from the two devices. Note that since the
+user is completely specifying the file name, the string should include the ",tr"
+for consistency.
+
+You can enable ascii tracing on a particular node/net-device pair by providing a
+``std::string`` representing an object name service string to an
+``EnablePcap`` method. The ``Ptr<NetDevice>`` is looked up from the name
+string. Again, the ``<Node>`` is implicit since the named net device must
+belong to exactly one ``Node``. For example,
+
+::
+
+ Names::Add ("client" ...);
+ Names::Add ("client/eth0" ...);
+ Names::Add ("server" ...);
+ Names::Add ("server/eth0" ...);
+ ...
+ helper.EnableAscii ("prefix", "client/eth0");
+ helper.EnableAscii ("prefix", "server/eth0");
+
+This would result in two files named "prefix-client-eth0.tr" and
+"prefix-server-eth0.tr" with traces for each device in the respective trace
+file. Since all of the EnableAscii functions are overloaded to take a stream wrapper,
+you can use that form as well:
+
+::
+
+ Names::Add ("client" ...);
+ Names::Add ("client/eth0" ...);
+ Names::Add ("server" ...);
+ Names::Add ("server/eth0" ...);
+ ...
+ Ptr<OutputStreamWrapper> stream = asciiTraceHelper.CreateFileStream ("trace-file-name.tr");
+ ...
+ helper.EnableAscii (stream, "client/eth0");
+ helper.EnableAscii (stream, "server/eth0");
+
+This would result in a single trace file called "trace-file-name.tr" that
+contains all of the trace events for both devices. The events would be
+disambiguated by trace context strings.
+
+You can enable ascii tracing on a collection of node/net-device pairs by
+providing a ``NetDeviceContainer``. For each ``NetDevice`` in the container
+the type is checked. For each device of the proper type (the same type as is
+managed by the device helper), tracing is enabled. Again, the ``<Node>`` is
+implicit since the found net device must belong to exactly one ``Node``.
+For example,
+
+::
+
+ NetDeviceContainer d = ...;
+ ...
+ helper.EnableAscii ("prefix", d);
+
+This would result in a number of ascii trace files being created, each of which
+follows the <prefix>-<node id>-<device id>.tr convention. Combining all of the
+traces into a single file is accomplished similarly to the examples above:
+
+::
+
+ NetDeviceContainer d = ...;
+ ...
+ Ptr<OutputStreamWrapper> stream = asciiTraceHelper.CreateFileStream ("trace-file-name.tr");
+ ...
+ helper.EnableAscii (stream, d);
+
+You can enable ascii tracing on a collection of node/net-device pairs by
+providing a ``NodeContainer``. For each ``Node`` in the ``NodeContainer``
+its attached ``NetDevices`` are iterated. For each ``NetDevice`` attached
+to each node in the container, the type of that device is checked. For each
+device of the proper type (the same type as is managed by the device helper),
+tracing is enabled.
+
+::
+
+ NodeContainer n;
+ ...
+ helper.EnableAscii ("prefix", n);
+
+This would result in a number of ascii trace files being created, each of which
+follows the <prefix>-<node id>-<device id>.tr convention. Combining all of the
+traces into a single file is accomplished similarly to the examples above:
+
+You can enable pcap tracing on the basis of node ID and device ID as well as
+with explicit ``Ptr``. Each ``Node`` in the system has an integer node ID
+and each device connected to a node has an integer device ID.
+
+::
+
+ helper.EnableAscii ("prefix", 21, 1);
+
+Of course, the traces can be combined into a single file as shown above.
+
+Finally, you can enable pcap tracing for all devices in the system, with the
+same type as that managed by the device helper.
+
+::
+
+ helper.EnableAsciiAll ("prefix");
+
+This would result in a number of ascii trace files being created, one for
+every device in the system of the type managed by the helper. All of these
+files will follow the <prefix>-<node id>-<device id>.tr convention. Combining
+all of the traces into a single file is accomplished similarly to the examples
+above.
+
+Ascii Tracing Device Helper Filename Selection
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Implicit in the prefix-style method descriptions above is the construction of the
+complete filenames by the implementation method. By convention, ascii traces
+in the |ns3| system are of the form "<prefix>-<node id>-<device id>.tr"
+
+As previously mentioned, every node in the system will have a system-assigned
+node id; and every device will have an interface index (also called a device id)
+relative to its node. By default, then, an ascii trace file created as a result
+of enabling tracing on the first device of node 21, using the prefix "prefix",
+would be "prefix-21-1.tr".
+
+You can always use the |ns3| object name service to make this more clear.
+For example, if you use the object name service to assign the name "server"
+to node 21, the resulting ascii trace file name will automatically become,
+"prefix-server-1.tr" and if you also assign the name "eth0" to the
+device, your ascii trace file name will automatically pick this up and be called
+"prefix-server-eth0.tr".
+
+Several of the methods have a default parameter called ``explicitFilename``.
+When set to true, this parameter disables the automatic filename completion
+mechanism and allows you to create an explicit filename. This option is only
+available in the methods which take a prefix and enable tracing on a single device.
+
+Pcap Tracing Protocol Helpers
++++++++++++++++++++++++++++++
+
+The goal of these ``mixins`` is to make it easy to add a consistent pcap trace
+facility to protocols. We want all of the various flavors of pcap tracing to
+work the same across all protocols, so the methods of these helpers are
+inherited by stack helpers. Take a look at ``src/helper/trace-helper.h``
+if you want to follow the discussion while looking at real code.
+
+In this section we will be illustrating the methods as applied to the protocol
+``Ipv4``. To specify traces in similar protocols, just substitute the
+appropriate type. For example, use a ``Ptr<Ipv6>`` instead of a
+``Ptr<Ipv4>`` and call ``EnablePcapIpv6`` instead of ``EnablePcapIpv4``.
+
+The class ``PcapHelperForIpv4`` provides the high level functionality for
+using pcap tracing in the ``Ipv4`` protocol. Each protocol helper enabling these
+methods must implement a single virtual method inherited from this class. There
+will be a separate implementation for ``Ipv6``, for example, but the only
+difference will be in the method names and signatures. Different method names
+are required to disambiguate class ``Ipv4`` from ``Ipv6`` which are both
+derived from class ``Object``, and methods that share the same signature.
+
+::
+
+ virtual void EnablePcapIpv4Internal (std::string prefix,
+ Ptr<Ipv4> ipv4,
+ uint32_t interface,
+ bool explicitFilename) = 0;
+
+The signature of this method reflects the protocol and interface-centric view
+of the situation at this level. All of the public methods inherited from class
+``PcapHelperForIpv4`` reduce to calling this single device-dependent
+implementation method. For example, the lowest level pcap method,
+
+::
+
+ void EnablePcapIpv4 (std::string prefix, Ptr<Ipv4> ipv4, uint32_t interface, bool explicitFilename = false);
+
+
+will call the device implementation of ``EnablePcapIpv4Internal`` directly.
+All other public pcap tracing methods build on this implementation to provide
+additional user-level functionality. What this means to the user is that all
+protocol helpers in the system will have all of the pcap trace methods
+available; and these methods will all work in the same way across
+protocols if the helper implements ``EnablePcapIpv4Internal`` correctly.
+
+Pcap Tracing Protocol Helper Methods
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+These methods are designed to be in one-to-one correspondence with the ``Node``-
+and ``NetDevice``- centric versions of the device versions. Instead of
+``Node`` and ``NetDevice`` pair constraints, we use protocol and interface
+constraints.
+
+Note that just like in the device version, there are six methods:
+
+::
+
+ void EnablePcapIpv4 (std::string prefix, Ptr<Ipv4> ipv4, uint32_t interface, bool explicitFilename = false);
+ void EnablePcapIpv4 (std::string prefix, std::string ipv4Name, uint32_t interface, bool explicitFilename = false);
+ void EnablePcapIpv4 (std::string prefix, Ipv4InterfaceContainer c);
+ void EnablePcapIpv4 (std::string prefix, NodeContainer n);
+ void EnablePcapIpv4 (std::string prefix, uint32_t nodeid, uint32_t interface, bool explicitFilename);
+ void EnablePcapIpv4All (std::string prefix);
+
+You are encouraged to peruse the Doxygen for class ``PcapHelperForIpv4``
+to find the details of these methods; but to summarize ...
+
+You can enable pcap tracing on a particular protocol/interface pair by providing a
+``Ptr<Ipv4>`` and ``interface`` to an ``EnablePcap`` method. For example,
+
+::
+
+ Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
+ ...
+ helper.EnablePcapIpv4 ("prefix", ipv4, 0);
+
+You can enable pcap tracing on a particular node/net-device pair by providing a
+``std::string`` representing an object name service string to an
+``EnablePcap`` method. The ``Ptr<Ipv4>`` is looked up from the name
+string. For example,
+
+::
+
+ Names::Add ("serverIPv4" ...);
+ ...
+ helper.EnablePcapIpv4 ("prefix", "serverIpv4", 1);
+
+You can enable pcap tracing on a collection of protocol/interface pairs by
+providing an ``Ipv4InterfaceContainer``. For each ``Ipv4`` / interface
+pair in the container the protocol type is checked. For each protocol of the
+proper type (the same type as is managed by the device helper), tracing is
+enabled for the corresponding interface. For example,
+
+::
+
+ NodeContainer nodes;
+ ...
+ NetDeviceContainer devices = deviceHelper.Install (nodes);
+ ...
+ Ipv4AddressHelper ipv4;
+ ipv4.SetBase ("10.1.1.0", "255.255.255.0");
+ Ipv4InterfaceContainer interfaces = ipv4.Assign (devices);
+ ...
+ helper.EnablePcapIpv4 ("prefix", interfaces);
+
+You can enable pcap tracing on a collection of protocol/interface pairs by
+providing a ``NodeContainer``. For each ``Node`` in the ``NodeContainer``
+the appropriate protocol is found. For each protocol, its interfaces are
+enumerated and tracing is enabled on the resulting pairs. For example,
+
+::
+
+ NodeContainer n;
+ ...
+ helper.EnablePcapIpv4 ("prefix", n);
+
+You can enable pcap tracing on the basis of node ID and interface as well. In
+this case, the node-id is translated to a ``Ptr<Node>`` and the appropriate
+protocol is looked up in the node. The resulting protocol and interface are
+used to specify the resulting trace source.
+
+::
+
+ helper.EnablePcapIpv4 ("prefix", 21, 1);
+
+Finally, you can enable pcap tracing for all interfaces in the system, with
+associated protocol being the same type as that managed by the device helper.
+
+::
+
+ helper.EnablePcapIpv4All ("prefix");
+
+Pcap Tracing Protocol Helper Filename Selection
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Implicit in all of the method descriptions above is the construction of the
+complete filenames by the implementation method. By convention, pcap traces
+taken for devices in the |ns3| system are of the form
+"<prefix>-<node id>-<device id>.pcap". In the case of protocol traces,
+there is a one-to-one correspondence between protocols and ``Nodes``.
+This is because protocol ``Objects`` are aggregated to ``Node Objects``.
+Since there is no global protocol id in the system, we use the corresponding
+node id in file naming. Therefore there is a possibility for file name
+collisions in automatically chosen trace file names. For this reason, the
+file name convention is changed for protocol traces.
+
+As previously mentioned, every node in the system will have a system-assigned
+node id. Since there is a one-to-one correspondence between protocol instances
+and node instances we use the node id. Each interface has an interface id
+relative to its protocol. We use the convention
+"<prefix>-n<node id>-i<interface id>.pcap" for trace file naming in protocol
+helpers.
+
+Therefore, by default, a pcap trace file created as a result of enabling tracing
+on interface 1 of the Ipv4 protocol of node 21 using the prefix "prefix"
+would be "prefix-n21-i1.pcap".
+
+You can always use the |ns3| object name service to make this more clear.
+For example, if you use the object name service to assign the name "serverIpv4"
+to the Ptr<Ipv4> on node 21, the resulting pcap trace file name will
+automatically become, "prefix-nserverIpv4-i1.pcap".
+
+Several of the methods have a default parameter called ``explicitFilename``.
+When set to true, this parameter disables the automatic filename completion
+mechanism and allows you to create an explicit filename. This option is only
+available in the methods which take a prefix and enable tracing on a single device.
+
+Ascii Tracing Protocol Helpers
+++++++++++++++++++++++++++++++
+
+The behavior of the ascii trace helpers is substantially similar to the pcap
+case. Take a look at ``src/helper/trace-helper.h`` if you want to
+follow the discussion while looking at real code.
+
+In this section we will be illustrating the methods as applied to the protocol
+``Ipv4``. To specify traces in similar protocols, just substitute the
+appropriate type. For example, use a ``Ptr<Ipv6>`` instead of a
+``Ptr<Ipv4>`` and call ``EnableAsciiIpv6`` instead of ``EnableAsciiIpv4``.
+
+The class ``AsciiTraceHelperForIpv4`` adds the high level functionality
+for using ascii tracing to a protocol helper. Each protocol that enables these
+methods must implement a single virtual method inherited from this class.
+
+::
+
+ virtual void EnableAsciiIpv4Internal (Ptr<OutputStreamWrapper> stream,
+ std::string prefix,
+ Ptr<Ipv4> ipv4,
+ uint32_t interface,
+ bool explicitFilename) = 0;
+
+The signature of this method reflects the protocol- and interface-centric view
+of the situation at this level; and also the fact that the helper may be writing
+to a shared output stream. All of the public methods inherited from class
+``PcapAndAsciiTraceHelperForIpv4`` reduce to calling this single device-
+dependent implementation method. For example, the lowest level ascii trace
+methods,
+
+::
+
+ void EnableAsciiIpv4 (std::string prefix, Ptr<Ipv4> ipv4, uint32_t interface, bool explicitFilename = false);
+ void EnableAsciiIpv4 (Ptr<OutputStreamWrapper> stream, Ptr<Ipv4> ipv4, uint32_t interface);
+
+
+will call the device implementation of ``EnableAsciiIpv4Internal`` directly,
+providing either the prefix or the stream. All other public ascii tracing
+methods will build on these low-level functions to provide additional user-level
+functionality. What this means to the user is that all device helpers in the
+system will have all of the ascii trace methods available; and these methods
+will all work in the same way across protocols if the protocols implement
+``EnablAsciiIpv4Internal`` correctly.
+
+Ascii Tracing Protocol Helper Methods
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ void EnableAsciiIpv4 (std::string prefix, Ptr<Ipv4> ipv4, uint32_t interface, bool explicitFilename = false);
+ void EnableAsciiIpv4 (Ptr<OutputStreamWrapper> stream, Ptr<Ipv4> ipv4, uint32_t interface);
+
+ void EnableAsciiIpv4 (std::string prefix, std::string ipv4Name, uint32_t interface, bool explicitFilename = false);
+ void EnableAsciiIpv4 (Ptr<OutputStreamWrapper> stream, std::string ipv4Name, uint32_t interface);
+
+ void EnableAsciiIpv4 (std::string prefix, Ipv4InterfaceContainer c);
+ void EnableAsciiIpv4 (Ptr<OutputStreamWrapper> stream, Ipv4InterfaceContainer c);
+
+ void EnableAsciiIpv4 (std::string prefix, NodeContainer n);
+ void EnableAsciiIpv4 (Ptr<OutputStreamWrapper> stream, NodeContainer n);
+
+ void EnableAsciiIpv4All (std::string prefix);
+ void EnableAsciiIpv4All (Ptr<OutputStreamWrapper> stream);
+
+ void EnableAsciiIpv4 (std::string prefix, uint32_t nodeid, uint32_t deviceid, bool explicitFilename);
+ void EnableAsciiIpv4 (Ptr<OutputStreamWrapper> stream, uint32_t nodeid, uint32_t interface);
+
+You are encouraged to peruse the Doxygen for class ``PcapAndAsciiHelperForIpv4``
+to find the details of these methods; but to summarize ...
+
+There are twice as many methods available for ascii tracing as there were for
+pcap tracing. This is because, in addition to the pcap-style model where traces
+from each unique protocol/interface pair are written to a unique file, we
+support a model in which trace information for many protocol/interface pairs is
+written to a common file. This means that the <prefix>-n<node id>-<interface>
+file name generation mechanism is replaced by a mechanism to refer to a common
+file; and the number of API methods is doubled to allow all combinations.
+
+Just as in pcap tracing, you can enable ascii tracing on a particular
+protocol/interface pair by providing a ``Ptr<Ipv4>`` and an ``interface``
+to an ``EnableAscii`` method.
+For example,
+
+::
+
+ Ptr<Ipv4> ipv4;
+ ...
+ helper.EnableAsciiIpv4 ("prefix", ipv4, 1);
+
+In this case, no trace contexts are written to the ascii trace file since they
+would be redundant. The system will pick the file name to be created using
+the same rules as described in the pcap section, except that the file will
+have the suffix ".tr" instead of ".pcap".
+
+If you want to enable ascii tracing on more than one interface and have all
+traces sent to a single file, you can do that as well by using an object to
+refer to a single file. We have already something similar to this in the
+"cwnd" example above:
+
+::
+
+ Ptr<Ipv4> protocol1 = node1->GetObject<Ipv4> ();
+ Ptr<Ipv4> protocol2 = node2->GetObject<Ipv4> ();
+ ...
+ Ptr<OutputStreamWrapper> stream = asciiTraceHelper.CreateFileStream ("trace-file-name.tr");
+ ...
+ helper.EnableAsciiIpv4 (stream, protocol1, 1);
+ helper.EnableAsciiIpv4 (stream, protocol2, 1);
+
+In this case, trace contexts are written to the ascii trace file since they
+are required to disambiguate traces from the two interfaces. Note that since
+the user is completely specifying the file name, the string should include the
+",tr" for consistency.
+
+You can enable ascii tracing on a particular protocol by providing a
+``std::string`` representing an object name service string to an
+``EnablePcap`` method. The ``Ptr<Ipv4>`` is looked up from the name
+string. The ``<Node>`` in the resulting filenames is implicit since there
+is a one-to-one correspondence between protocol instances and nodes,
+For example,
+
+::
+
+ Names::Add ("node1Ipv4" ...);
+ Names::Add ("node2Ipv4" ...);
+ ...
+ helper.EnableAsciiIpv4 ("prefix", "node1Ipv4", 1);
+ helper.EnableAsciiIpv4 ("prefix", "node2Ipv4", 1);
+
+This would result in two files named "prefix-nnode1Ipv4-i1.tr" and
+"prefix-nnode2Ipv4-i1.tr" with traces for each interface in the respective
+trace file. Since all of the EnableAscii functions are overloaded to take a
+stream wrapper, you can use that form as well:
+
+::
+
+ Names::Add ("node1Ipv4" ...);
+ Names::Add ("node2Ipv4" ...);
+ ...
+ Ptr<OutputStreamWrapper> stream = asciiTraceHelper.CreateFileStream ("trace-file-name.tr");
+ ...
+ helper.EnableAsciiIpv4 (stream, "node1Ipv4", 1);
+ helper.EnableAsciiIpv4 (stream, "node2Ipv4", 1);
+
+This would result in a single trace file called "trace-file-name.tr" that
+contains all of the trace events for both interfaces. The events would be
+disambiguated by trace context strings.
+
+You can enable ascii tracing on a collection of protocol/interface pairs by
+providing an ``Ipv4InterfaceContainer``. For each protocol of the proper
+type (the same type as is managed by the device helper), tracing is enabled
+for the corresponding interface. Again, the ``<Node>`` is implicit since
+there is a one-to-one correspondence between each protocol and its node.
+For example,
+
+::
+
+ NodeContainer nodes;
+ ...
+ NetDeviceContainer devices = deviceHelper.Install (nodes);
+ ...
+ Ipv4AddressHelper ipv4;
+ ipv4.SetBase ("10.1.1.0", "255.255.255.0");
+ Ipv4InterfaceContainer interfaces = ipv4.Assign (devices);
+ ...
+ ...
+ helper.EnableAsciiIpv4 ("prefix", interfaces);
+
+This would result in a number of ascii trace files being created, each of which
+follows the <prefix>-n<node id>-i<interface>.tr convention. Combining all of the
+traces into a single file is accomplished similarly to the examples above:
+
+::
+
+ NodeContainer nodes;
+ ...
+ NetDeviceContainer devices = deviceHelper.Install (nodes);
+ ...
+ Ipv4AddressHelper ipv4;
+ ipv4.SetBase ("10.1.1.0", "255.255.255.0");
+ Ipv4InterfaceContainer interfaces = ipv4.Assign (devices);
+ ...
+ Ptr<OutputStreamWrapper> stream = asciiTraceHelper.CreateFileStream ("trace-file-name.tr");
+ ...
+ helper.EnableAsciiIpv4 (stream, interfaces);
+
+You can enable ascii tracing on a collection of protocol/interface pairs by
+providing a ``NodeContainer``. For each ``Node`` in the ``NodeContainer``
+the appropriate protocol is found. For each protocol, its interfaces are
+enumerated and tracing is enabled on the resulting pairs. For example,
+
+::
+
+ NodeContainer n;
+ ...
+ helper.EnableAsciiIpv4 ("prefix", n);
+
+This would result in a number of ascii trace files being created, each of which
+follows the <prefix>-<node id>-<device id>.tr convention. Combining all of the
+traces into a single file is accomplished similarly to the examples above:
+
+You can enable pcap tracing on the basis of node ID and device ID as well. In
+this case, the node-id is translated to a ``Ptr<Node>`` and the appropriate
+protocol is looked up in the node. The resulting protocol and interface are
+used to specify the resulting trace source.
+
+::
+
+ helper.EnableAsciiIpv4 ("prefix", 21, 1);
+
+Of course, the traces can be combined into a single file as shown above.
+
+Finally, you can enable ascii tracing for all interfaces in the system, with
+associated protocol being the same type as that managed by the device helper.
+
+::
+
+ helper.EnableAsciiIpv4All ("prefix");
+
+This would result in a number of ascii trace files being created, one for
+every interface in the system related to a protocol of the type managed by the
+helper. All of these files will follow the <prefix>-n<node id>-i<interface.tr
+convention. Combining all of the traces into a single file is accomplished
+similarly to the examples above.
+
+Ascii Tracing Protocol Helper Filename Selection
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Implicit in the prefix-style method descriptions above is the construction of the
+complete filenames by the implementation method. By convention, ascii traces
+in the |ns3| system are of the form "<prefix>-<node id>-<device id>.tr"
+
+As previously mentioned, every node in the system will have a system-assigned
+node id. Since there is a one-to-one correspondence between protocols and nodes
+we use to node-id to identify the protocol identity. Every interface on a
+given protocol will have an interface index (also called simply an interface)
+relative to its protocol. By default, then, an ascii trace file created as a result
+of enabling tracing on the first device of node 21, using the prefix "prefix",
+would be "prefix-n21-i1.tr". Use the prefix to disambiguate multiple protocols
+per node.
+
+You can always use the |ns3| object name service to make this more clear.
+For example, if you use the object name service to assign the name "serverIpv4"
+to the protocol on node 21, and also specify interface one, the resulting ascii
+trace file name will automatically become, "prefix-nserverIpv4-1.tr".
+
+Several of the methods have a default parameter called ``explicitFilename``.
+When set to true, this parameter disables the automatic filename completion
+mechanism and allows you to create an explicit filename. This option is only
+available in the methods which take a prefix and enable tracing on a single device.
+
+Summary
+*******
+
+|ns3| includes an extremely rich environment allowing users at several
+levels to customize the kinds of information that can be extracted from
+simulations.
+
+There are high-level helper functions that allow users to simply control the
+collection of pre-defined outputs to a fine granularity. There are mid-level
+helper functions to allow more sophisticated users to customize how information
+is extracted and saved; and there are low-level core functions to allow expert
+users to alter the system to present new and previously unexported information
+in a way that will be immediately accessible to users at higher levels.
+
+This is a very comprehensive system, and we realize that it is a lot to
+digest, especially for new users or those not intimately familiar with C++
+and its idioms. We do consider the tracing system a very important part of
+|ns3| and so recommend becoming as familiar as possible with it. It is
+probably the case that understanding the rest of the |ns3| system will
+be quite simple once you have mastered the tracing system
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/tutorial/source/tweaking.rst Sun Jan 02 22:57:32 2011 -0800
@@ -0,0 +1,996 @@
+.. include:: replace.txt
+
+
+Tweaking
+--------
+
+Using the Logging Module
+************************
+
+We have already taken a brief look at the |ns3| logging module while
+going over the ``first.cc`` script. We will now take a closer look and
+see what kind of use-cases the logging subsystem was designed to cover.
+
+Logging Overview
+++++++++++++++++
+Many large systems support some kind of message logging facility, and
+|ns3| is not an exception. In some cases, only error messages are
+logged to the "operator console" (which is typically ``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.
+
+|ns3| 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, or
+enabled globally; and it provides selectable verbosity levels. The
+|ns3| log module provides a straightforward, relatively easy to use
+way to get useful 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
+simulation output (see the tutorial section Using the Tracing System for
+more details on our tracing system). Logging should be preferred for
+debugging information, warnings, error messages, or any time you want to
+easily get a quick message out of your scripts or models.
+
+There are currently seven levels of log messages of increasing verbosity
+defined in the system.
+
+* NS_LOG_ERROR --- Log error messages;
+* NS_LOG_WARN --- Log warning messages;
+* NS_LOG_DEBUG --- Log relatively rare, ad-hoc debugging messages;
+* NS_LOG_INFO --- Log informational messages about program progress;
+* NS_LOG_FUNCTION --- Log a message describing each function called;
+* NS_LOG_LOGIC -- Log messages describing logical flow within a function;
+* NS_LOG_ALL --- Log everything.
+
+We also provide an unconditional logging level that is always displayed,
+irrespective of logging levels or component selection.
+
+* NS_LOG_UNCOND -- Log the associated message unconditionally.
+
+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 and now would be a good time to peruse the Logging Module
+documentation if you have not done so.
+
+Now that you have read the documentation in great detail, let's use some of
+that knowledge to get some interesting information out of the
+``scratch/myfirst.cc`` example script you have already built.
+
+Enabling Logging
+++++++++++++++++
+Let's use the NS_LOG environment variable to turn on some more logging, but
+first, just to get our bearings, go ahead and run the last script just as you
+did previously,
+
+::
+
+ ./waf --run scratch/myfirst
+
+You should see the now familiar output of the first |ns3| example
+program
+
+::
+
+ Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
+ Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
+ 'build' finished successfully (0.413s)
+ Sent 1024 bytes to 10.1.1.2
+ Received 1024 bytes from 10.1.1.1
+ Received 1024 bytes from 10.1.1.2
+
+It turns out that the "Sent" and "Received" messages you see above are
+actually logging messages from the ``UdpEchoClientApplication`` and
+``UdpEchoServerApplication``. We can 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 you 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 my examples to the "setenv VARIABLE value" syntax
+required by those shells.
+
+Right now, the UDP echo client application is responding to the following line
+of code in ``scratch/myfirst.cc``,
+
+::
+
+ LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_INFO);
+
+This line of code enables the ``LOG_LEVEL_INFO`` level of logging. When
+we pass a logging level flag, we are actually enabling the given level and
+all lower levels. In this case, we have enabled ``NS_LOG_INFO``,
+``NS_LOG_DEBUG``, ``NS_LOG_WARN`` and ``NS_LOG_ERROR``. We can
+increase the logging level and get more information without changing the
+script and recompiling by setting the NS_LOG environment variable like this:
+
+::
+
+ export NS_LOG=UdpEchoClientApplication=level_all
+
+This sets the shell environment variable ``NS_LOG`` to the string,
+
+::
+
+ UdpEchoClientApplication=level_all
+
+The left hand side of the assignment is the name of the logging component we
+want to set, and the right hand side is the flag we want to use. In this case,
+we are going to turn on all of the debugging levels for the application. If
+you run the script with NS_LOG set this way, the |ns3| logging
+system will pick up the change and you should see the following output:
+
+::
+
+ Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build
+ Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
+ 'build' finished successfully (0.404s)
+ UdpEchoClientApplication:UdpEchoClient()
+ UdpEchoClientApplication:SetDataSize(1024)
+ UdpEchoClientApplication:StartApplication()
+ UdpEchoClientApplication:ScheduleTransmit()
+ UdpEchoClientApplication:Send()
+ Sent 1024 bytes to 10.1.1.2
+ Received 1024 bytes from 10.1.1.1
+ UdpEchoClientApplication:HandleRead(0x6241e0, 0x624a20)
+ Received 1024 bytes from 10.1.1.2
+ UdpEchoClientApplication:StopApplication()
+ UdpEchoClientApplication:DoDispose()
+ UdpEchoClientApplication:~UdpEchoClient()
+
+The additional debug information provided by the application is from
+the NS_LOG_FUNCTION level. This shows every time a function in the application
+is called during script execution. Note that there are no requirements in the
+|ns3| system that models must support any particular logging
+functionality. The decision regarding how much information is logged
+is left to the individual model developer. In the case of the echo
+applications, a good deal of log output is available.
+
+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
+``UdpEchoClientApplication`` and the method name where you might have
+expected a C++ scope operator (``::``). 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 some 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 "``Received 1024 bytes from 10.1.1.2``" comes
+from. You can resolve this by OR'ing the ``prefix_func`` level into the
+``NS_LOG`` environment variable. Try doing the following,
+
+::
+
+ export 'NS_LOG=UdpEchoClientApplication=level_all|prefix_func'
+
+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
+name.
+
+::
+
+ Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
+ Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
+ 'build' finished successfully (0.417s)
+ UdpEchoClientApplication:UdpEchoClient()
+ UdpEchoClientApplication:SetDataSize(1024)
+ UdpEchoClientApplication:StartApplication()
+ UdpEchoClientApplication:ScheduleTransmit()
+ UdpEchoClientApplication:Send()
+ UdpEchoClientApplication:Send(): Sent 1024 bytes to 10.1.1.2
+ Received 1024 bytes from 10.1.1.1
+ UdpEchoClientApplication:HandleRead(0x6241e0, 0x624a20)
+ UdpEchoClientApplication:HandleRead(): Received 1024 bytes from 10.1.1.2
+ UdpEchoClientApplication:StopApplication()
+ UdpEchoClientApplication:DoDispose()
+ UdpEchoClientApplication:~UdpEchoClient()
+
+You can now see all of the messages coming from the UDP echo client application
+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.
+
+::
+
+ export 'NS_LOG=UdpEchoClientApplication=level_all|prefix_func:
+ UdpEchoServerApplication=level_all|prefix_func'
+
+Warning: You will need to remove the newline after the ``:`` in the
+example text above which is only there for document formatting purposes.
+
+Now, if you run the script you will see all of the log messages from both the
+echo client and server applications. You may see that this can be very useful
+in debugging problems.
+
+::
+
+ Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
+ Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
+ 'build' finished successfully (0.406s)
+ UdpEchoServerApplication:UdpEchoServer()
+ UdpEchoClientApplication:UdpEchoClient()
+ UdpEchoClientApplication:SetDataSize(1024)
+ UdpEchoServerApplication:StartApplication()
+ UdpEchoClientApplication:StartApplication()
+ UdpEchoClientApplication:ScheduleTransmit()
+ UdpEchoClientApplication:Send()
+ UdpEchoClientApplication:Send(): Sent 1024 bytes to 10.1.1.2
+ UdpEchoServerApplication:HandleRead(): Received 1024 bytes from 10.1.1.1
+ UdpEchoServerApplication:HandleRead(): Echoing packet
+ UdpEchoClientApplication:HandleRead(0x624920, 0x625160)
+ UdpEchoClientApplication:HandleRead(): Received 1024 bytes from 10.1.1.2
+ UdpEchoServerApplication:StopApplication()
+ UdpEchoClientApplication:StopApplication()
+ UdpEchoClientApplication:DoDispose()
+ UdpEchoServerApplication:DoDispose()
+ UdpEchoClientApplication:~UdpEchoClient()
+ UdpEchoServerApplication:~UdpEchoServer()
+
+It is also sometimes useful to be able to see the simulation time at which a
+log message is generated. You can do this by ORing in the prefix_time bit.
+
+::
+
+ export 'NS_LOG=UdpEchoClientApplication=level_all|prefix_func|prefix_time:
+ UdpEchoServerApplication=level_all|prefix_func|prefix_time'
+
+Again, you will have to remove the newline above. If you run the script now,
+you should see the following output:
+
+::
+
+ Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
+ Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
+ 'build' finished successfully (0.418s)
+ 0s UdpEchoServerApplication:UdpEchoServer()
+ 0s UdpEchoClientApplication:UdpEchoClient()
+ 0s UdpEchoClientApplication:SetDataSize(1024)
+ 1s UdpEchoServerApplication:StartApplication()
+ 2s UdpEchoClientApplication:StartApplication()
+ 2s UdpEchoClientApplication:ScheduleTransmit()
+ 2s UdpEchoClientApplication:Send()
+ 2s UdpEchoClientApplication:Send(): Sent 1024 bytes to 10.1.1.2
+ 2.00369s UdpEchoServerApplication:HandleRead(): Received 1024 bytes from 10.1.1.1
+ 2.00369s UdpEchoServerApplication:HandleRead(): Echoing packet
+ 2.00737s UdpEchoClientApplication:HandleRead(0x624290, 0x624ad0)
+ 2.00737s UdpEchoClientApplication:HandleRead(): Received 1024 bytes from 10.1.1.2
+ 10s UdpEchoServerApplication:StopApplication()
+ 10s UdpEchoClientApplication:StopApplication()
+ UdpEchoClientApplication:DoDispose()
+ UdpEchoServerApplication:DoDispose()
+ UdpEchoClientApplication:~UdpEchoClient()
+ UdpEchoServerApplication:~UdpEchoServer()
+
+You can see that the constructor for the UdpEchoServer was called at a
+simulation time of 0 seconds. This is actually happening before the
+simulation starts, but the time is displayed as zero seconds. The same is true
+for the UdpEchoClient constructor message.
+
+Recall that the ``scratch/first.cc`` script started the echo server
+application at one second into the simulation. You can now see that the
+``StartApplication`` method of the server is, in fact, called at one second.
+You can also see that the echo client application is started at a simulation
+time of two seconds as we requested in the script.
+
+You can now follow the progress of the simulation from the
+``ScheduleTransmit`` call in the client that calls ``Send`` to the
+``HandleRead`` callback in the echo server application. Note that the
+elapsed time for the packet to be sent across the point-to-point link is 3.69
+milliseconds. You see the echo server logging a message telling you that it
+has echoed the packet and then, after another channel delay, you see the echo
+client receive the echoed packet in its ``HandleRead`` method.
+
+There is a lot that is happening under the covers in this simulation that you
+are not seeing as well. You can very easily follow the entire process by
+turning on all of the logging components in the system. Try setting the
+``NS_LOG`` variable to the following,
+
+::
+
+ export 'NS_LOG=*=level_all|prefix_func|prefix_time'
+
+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 1265 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,
+
+::
+
+ ./waf --run scratch/myfirst > log.out 2>&1
+
+I personally use this extremely verbose version of logging when I am presented
+with a problem and I 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. I can just edit up the output in my favorite editor
+and search around for things I expect, and see things happening that I don't
+expect. When I have a general idea about what is going wrong, I transition into
+a debugger for a fine-grained examination of the problem. This 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.
+
+Adding Logging to your Code
++++++++++++++++++++++++++++
+You can add new logging to your simulations by making calls to the log
+component via several macros. Let's do so in the ``myfirst.cc`` script we
+have in the ``scratch`` directory.
+
+Recall that we have defined a logging component in that script:
+
+::
+
+ NS_LOG_COMPONENT_DEFINE ("FirstScriptExample");
+
+You now know that you can enable all of the logging for this component by
+setting the ``NS_LOG`` environment variable to the various levels. Let's
+go ahead and add some logging to the script. The macro used to add an
+informational level log message is ``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,
+
+Open ``scratch/myfirst.cc`` in your favorite editor and add the line,
+
+::
+
+ NS_LOG_INFO ("Creating Topology");
+
+right before the lines,
+
+::
+
+ NodeContainer nodes;
+ nodes.Create (2);
+
+Now build the script using waf and clear the ``NS_LOG`` variable to turn
+off the torrent of logging we previously enabled:
+
+::
+
+ ./waf
+ export NS_LOG=
+
+Now, if you run the script,
+
+::
+
+ ./waf --run scratch/myfirst
+
+you will ``not`` see your new message since its associated logging
+component (``FirstScriptExample``) has not been enabled. In order to see your
+message you will have to enable the ``FirstScriptExample`` logging component
+with a level greater than or equal to ``NS_LOG_INFO``. If you just want to
+see this particular level of logging, you can enable it by,
+
+::
+
+ export NS_LOG=FirstScriptExample=info
+
+If you now run the script you will see your new "Creating Topology" log
+message,
+
+::
+
+ Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
+ Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
+ 'build' finished successfully (0.404s)
+ Creating Topology
+ Sent 1024 bytes to 10.1.1.2
+ Received 1024 bytes from 10.1.1.1
+ Received 1024 bytes from 10.1.1.2
+
+Using Command Line Arguments
+****************************
+
+Overriding Default Attributes
++++++++++++++++++++++++++++++
+Another way you can change how |ns3| scripts behave without editing
+and building is via *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
+in the following code,
+
+::
+
+ int
+ main (int argc, char *argv[])
+ {
+ ...
+
+ CommandLine cmd;
+ cmd.Parse (argc, argv);
+
+ ...
+ }
+
+This simple two line snippet is actually very useful by itself. It opens the
+door to the |ns3| global variable and ``Attribute`` systems. Go
+ahead and add that two lines of code to the ``scratch/myfirst.cc`` script at
+the start of ``main``. Go ahead and build the script and run it, but ask
+the script for help in the following way,
+
+::
+
+ ./waf --run "scratch/myfirst --PrintHelp"
+
+This will ask Waf to run the ``scratch/myfirst`` script and pass the command
+line argument ``--PrintHelp`` to the script. The quotes are required to
+sort out which program gets which argument. The command line parser will
+now see the ``--PrintHelp`` argument and respond with,
+
+::
+
+ Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
+ Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
+ 'build' finished successfully (0.413s)
+ TcpL4Protocol:TcpStateMachine()
+ CommandLine:HandleArgument(): Handle arg name=PrintHelp value=
+ --PrintHelp: Print this help message.
+ --PrintGroups: Print the list of groups.
+ --PrintTypeIds: Print all TypeIds.
+ --PrintGroup=[group]: Print all TypeIds of group.
+ --PrintAttributes=[typeid]: Print all attributes of typeid.
+ --PrintGlobals: Print the list of globals.
+
+Let's focus on the ``--PrintAttributes`` option. We have already hinted
+at the |ns3| ``Attribute`` system while walking through the
+``first.cc`` script. We looked at the following lines of code,
+
+::
+
+ PointToPointHelper pointToPoint;
+ pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
+ pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
+
+and mentioned that ``DataRate`` was actually an ``Attribute`` of the
+``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 ``ns3::PointToPointNetDevice``. Let's go ahead and type in,
+
+::
+
+ ./waf --run "scratch/myfirst --PrintAttributes=ns3::PointToPointNetDevice"
+
+The system will print out all of the ``Attributes`` of this kind of net device.
+Among the ``Attributes`` you will see listed is,
+
+::
+
+ --ns3::PointToPointNetDevice::DataRate=[32768bps]:
+ The default data rate for point to point links
+
+This is the default value that will be used when a ``PointToPointNetDevice``
+is created in the system. We overrode this default with the ``Attribute``
+setting in the ``PointToPointHelper`` above. Let's use the default values
+for the point-to-point devices and channels by deleting the
+``SetDeviceAttribute`` call and the ``SetChannelAttribute`` call from
+the ``myfirst.cc`` we have in the scratch directory.
+
+Your script should now just declare the ``PointToPointHelper`` and not do
+any ``set`` operations as in the following example,
+
+::
+
+ ...
+
+ NodeContainer nodes;
+ nodes.Create (2);
+
+ PointToPointHelper pointToPoint;
+
+ NetDeviceContainer devices;
+ devices = pointToPoint.Install (nodes);
+
+ ...
+
+Go ahead and build the new script with Waf (``./waf``) and let's go back
+and enable some logging from the UDP echo server application and turn on the
+time prefix.
+
+::
+
+ export 'NS_LOG=UdpEchoServerApplication=level_all|prefix_time'
+
+If you run the script, you should now see the following output,
+
+::
+
+ Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
+ Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
+ 'build' finished successfully (0.405s)
+ 0s UdpEchoServerApplication:UdpEchoServer()
+ 1s UdpEchoServerApplication:StartApplication()
+ Sent 1024 bytes to 10.1.1.2
+ 2.25732s Received 1024 bytes from 10.1.1.1
+ 2.25732s Echoing packet
+ Received 1024 bytes from 10.1.1.2
+ 10s UdpEchoServerApplication:StopApplication()
+ UdpEchoServerApplication:DoDispose()
+ UdpEchoServerApplication:~UdpEchoServer()
+
+Recall that the last time we looked at the simulation time at which the packet
+was received by the echo server, it was at 2.00369 seconds.
+
+::
+
+ 2.00369s UdpEchoServerApplication:HandleRead(): Received 1024 bytes from 10.1.1.1
+
+Now it is receiving the packet at 2.25732 seconds. This is because we just dropped
+the data rate of the ``PointToPointNetDevice`` down to its default of
+32768 bits per second from five megabits per second.
+
+If we were to provide a new ``DataRate`` using the command line, we could
+speed our simulation up again. We do this in the following way, according to
+the formula implied by the help item:
+
+::
+
+ ./waf --run "scratch/myfirst --ns3::PointToPointNetDevice::DataRate=5Mbps"
+
+This will set the default value of the ``DataRate`` ``Attribute`` back to
+five megabits per second. Are you surprised by the result? It turns out that
+in order to get the original behavior of the script back, we will have to set
+the speed-of-light delay of the channel as well. We can ask the command line
+system to print out the ``Attributes`` of the channel just like we did for
+the net device:
+
+::
+
+ ./waf --run "scratch/myfirst --PrintAttributes=ns3::PointToPointChannel"
+
+We discover the ``Delay`` ``Attribute`` of the channel is set in the following
+way:
+
+::
+
+ --ns3::PointToPointChannel::Delay=[0ns]:
+ Transmission delay through the channel
+
+We can then set both of these default values through the command line system,
+
+::
+
+ ./waf --run "scratch/myfirst
+ --ns3::PointToPointNetDevice::DataRate=5Mbps
+ --ns3::PointToPointChannel::Delay=2ms"
+
+in which case we recover the timing we had when we explicitly set the
+``DataRate`` and ``Delay`` in the script:
+
+::
+
+ Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
+ Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
+ 'build' finished successfully (0.417s)
+ 0s UdpEchoServerApplication:UdpEchoServer()
+ 1s UdpEchoServerApplication:StartApplication()
+ Sent 1024 bytes to 10.1.1.2
+ 2.00369s Received 1024 bytes from 10.1.1.1
+ 2.00369s Echoing packet
+ Received 1024 bytes from 10.1.1.2
+ 10s UdpEchoServerApplication:StopApplication()
+ UdpEchoServerApplication:DoDispose()
+ UdpEchoServerApplication:~UdpEchoServer()
+
+Note that the packet is again received by the server at 2.00369 seconds. We
+could actually set any of the ``Attributes`` used in the script in this way.
+In particular we could set the ``UdpEchoClient Attribute MaxPackets``
+to some other value than one.
+
+How would you go about that? Give it a try. Remember you have to comment
+out the place we override the default ``Attribute`` and explicitly set
+``MaxPackets`` in the script. Then you have to rebuild the script. You
+will also have to find the syntax for actually setting the new default attribute
+value using the command line help facility. Once you have this figured out
+you should be able to control the number of packets echoed from the command
+line. Since we're nice folks, we'll tell you that your command line should
+end up looking something like,
+
+::
+
+ ./waf --run "scratch/myfirst
+ --ns3::PointToPointNetDevice::DataRate=5Mbps
+ --ns3::PointToPointChannel::Delay=2ms
+ --ns3::UdpEchoClient::MaxPackets=2"
+
+Hooking Your Own Values
++++++++++++++++++++++++
+You can also add your own hooks to the command line system. This is done
+quite simply by using the ``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 ``nPackets``
+to the ``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. We do this by adding a call to
+``AddValue``. Go ahead and change the ``scratch/myfirst.cc`` script to
+start with the following code,
+
+::
+
+ int
+ main (int argc, char *argv[])
+ {
+ uint32_t nPackets = 1;
+
+ CommandLine cmd;
+ cmd.AddValue("nPackets", "Number of packets to echo", nPackets);
+ cmd.Parse (argc, argv);
+
+ ...
+
+Scroll down to the point in the script where we set the ``MaxPackets``
+``Attribute`` and change it so that it is set to the variable ``nPackets``
+instead of the constant ``1`` as is shown below.
+
+::
+
+ echoClient.SetAttribute ("MaxPackets", UintegerValue (nPackets));
+
+Now if you run the script and provide the ``--PrintHelp`` argument, you
+should see your new ``User Argument`` listed in the help display.
+
+Try,
+
+::
+
+ ./waf --run "scratch/myfirst --PrintHelp"
+
+::
+
+ Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
+ Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
+ 'build' finished successfully (0.403s)
+ --PrintHelp: Print this help message.
+ --PrintGroups: Print the list of groups.
+ --PrintTypeIds: Print all TypeIds.
+ --PrintGroup=[group]: Print all TypeIds of group.
+ --PrintAttributes=[typeid]: Print all attributes of typeid.
+ --PrintGlobals: Print the list of globals.
+ User Arguments:
+ --nPackets: Number of packets to echo
+
+If you want to specify the number of packets to echo, you can now do so by
+setting the ``--nPackets`` argument in the command line,
+
+::
+
+ ./waf --run "scratch/myfirst --nPackets=2"
+
+You should now see
+
+::
+
+ Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
+ Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
+ 'build' finished successfully (0.404s)
+ 0s UdpEchoServerApplication:UdpEchoServer()
+ 1s UdpEchoServerApplication:StartApplication()
+ Sent 1024 bytes to 10.1.1.2
+ 2.25732s Received 1024 bytes from 10.1.1.1
+ 2.25732s Echoing packet
+ Received 1024 bytes from 10.1.1.2
+ Sent 1024 bytes to 10.1.1.2
+ 3.25732s Received 1024 bytes from 10.1.1.1
+ 3.25732s Echoing packet
+ Received 1024 bytes from 10.1.1.2
+ 10s UdpEchoServerApplication:StopApplication()
+ UdpEchoServerApplication:DoDispose()
+ UdpEchoServerApplication:~UdpEchoServer()
+
+You have now echoed two packets. Pretty easy, isn't it?
+
+You can see that if you are an |ns3| 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.
+
+Using the Tracing System
+************************
+
+The whole point of simulation is to generate output for further study, and
+the |ns3| tracing system is a primary mechanism for this. Since
+|ns3| is a C++ program, standard facilities for generating output
+from C++ programs could be used:
+
+::
+
+ #include <iostream>
+ ...
+ int main ()
+ {
+ ...
+ std::cout << "The value of x is " << x << std::endl;
+ ...
+ }
+
+You could even use the logging module to add a little structure to your
+solution. There are many well-known problems generated by such approaches
+and so we have provided a generic event tracing subsystem to address the
+issues we thought were important.
+
+The basic goals of the |ns3| tracing system are:
+
+* For basic tasks, the tracing system should allow the user to generate
+ standard tracing for popular tracing sources, and to customize which objects
+ generate the tracing;
+* Intermediate users must be able to extend the tracing system to modify
+ the output format generated, or to insert new tracing sources, without
+ modifying the core of the simulator;
+* Advanced users can modify the simulator core to add new tracing sources
+ and sinks.
+
+The |ns3| tracing system is built on the concepts of independent
+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 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
+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
+types of sinks to existing tracing sources, without requiring editing and
+recompilation of the core of the simulator. Thus, in the example above,
+a user could define a new tracing sink in her script and attach it to an
+existing tracing source defined in the simulation core by editing only the
+user script.
+
+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
+extending the tracing namespace and creating new tracing sources.
+
+ASCII Tracing
++++++++++++++
+|ns3| provides helper functionality that wraps the low-level tracing
+system to help you with the details involved in configuring some easily
+understood packet traces. If you enable this functionality, you will see
+output in a ASCII files --- thus the name. For those familiar with
+|ns2| output, this type of trace is analogous to the ``out.tr``
+generated by many scripts.
+
+Let's just jump right in and add some ASCII tracing output to our
+``scratch/myfirst.cc`` script. Right before the call to
+``Simulator::Run ()``, add the following lines of code:
+
+::
+
+ AsciiTraceHelper ascii;
+ pointToPoint.EnableAsciiAll (ascii.CreateFileStream ("myfirst.tr"));
+
+Like in many other |ns3| idioms, this code uses a helper object to
+help create ASCII traces. The second line contains two nested method calls.
+The "inside" method, ``CreateFileStream()`` uses an unnamed object idiom
+to create a file stream object on the stack (without an object name) and pass
+it down to the called method. We'll go into this more in the future, but all
+you have to know at this point is that you are creating an object representing
+a file named "myfirst.tr" and passing it into ``ns-3``. You are telling
+``ns-3`` to deal with the lifetime issues of the created object and also to
+deal with problems caused by a little-known (intentional) limitation of C++
+ofstream objects relating to copy constructors.
+
+The outside call, to ``EnableAsciiAll()``, tells the helper 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.
+
+For those familiar with |ns2|, the traced events are equivalent to
+the popular trace points that log "+", "-", "d", and "r" events.
+
+You can now build the script and run it from the command line:
+
+::
+
+ ./waf --run scratch/myfirst
+
+Just as you have seen many times before, you will see some messages from Waf and then
+"'build' finished successfully" with some number of messages from
+the running program.
+
+When it ran, the program will have created a file named ``myfirst.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
+``--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 ASCII trace file ``myfirst.tr`` in your favorite editor.
+
+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 window considerably.
+
+Each line in the file corresponds to a *trace event*. In this case
+we are tracing events on the *transmit queue* present in every
+point-to-point net device in the simulation. The transmit queue is a queue
+through which every packet destined for a point-to-point 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:
+
+* ``+``: An enqueue operation occurred on the device queue;
+* ``-``: A dequeue operation occurred on the device queue;
+* ``d``: A packet was dropped, typically because the queue was full;
+* ``r``: A packet was received by the net device.
+
+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:
+
+::
+
+ 00 +
+ 01 2
+ 02 /NodeList/0/DeviceList/0/$ns3::PointToPointNetDevice/TxQueue/Enqueue
+ 03 ns3::PppHeader (
+ 04 Point-to-Point Protocol: IP (0x0021))
+ 05 ns3::Ipv4Header (
+ 06 tos 0x0 ttl 64 id 0 protocol 17 offset 0 flags [none]
+ 07 length: 1052 10.1.1.1 > 10.1.1.2)
+ 08 ns3::UdpHeader (
+ 09 length: 1032 49153 > 9)
+ 10 Payload (size=1024)
+
+The first line of this expanded trace event (reference number 00) is the
+operation. We have a ``+`` character, so this corresponds to an
+*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
+``UdpEchoClientApplication`` to start sending packets at two seconds. Here
+we see confirmation that this is, indeed, happening.
+
+The next line of the example trace (reference 02) tell us which trace source
+originated this event (expressed in the tracing namespace). You can think
+of the tracing namespace somewhat like you would a filesystem namespace. The
+root of the namespace is the ``NodeList``. This corresponds to a container
+managed in the |ns3| 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 ``NodeList``. The string
+``/NodeList/0`` therefore refers to the zeroth node in the ``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 ``DeviceList/0`` which is the
+zeroth device installed in the node.
+
+The next string, ``$ns3::PointToPointNetDevice`` tells you what kind of
+device is in the zeroth position of the device list for node zero.
+Recall that the operation ``+`` found at reference 00 meant that an enqueue
+operation happened on the transmit queue of the device. This is reflected in
+the final segments of the "trace path" which are ``TxQueue/Enqueue``.
+
+The remaining lines in the trace should be fairly intuitive. References 03-04
+indicate that the packet is encapsulated 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 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.
+
+The Third line in the trace file shows the packet being received by the net
+device on the node with the echo server. I have reproduced that event below.
+
+::
+
+ 00 r
+ 01 2.25732
+ 02 /NodeList/1/DeviceList/0/$ns3::PointToPointNetDevice/MacRx
+ 03 ns3::Ipv4Header (
+ 04 tos 0x0 ttl 64 id 0 protocol 17 offset 0 flags [none]
+ 05 length: 1052 10.1.1.1 > 10.1.1.2)
+ 06 ns3::UdpHeader (
+ 07 length: 1032 49153 > 9)
+ 08 Payload (size=1024)
+
+Notice that the trace operation is now ``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 ``DataRate`` of the net devices
+and the channel ``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 (``/NodeList/1``) and the packet reception
+trace source (``/MacRx``). 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.
+
+PCAP Tracing
+++++++++++++
+The |ns3| device helpers can also be used to create trace files in the
+``.pcap`` format. The acronym pcap (usually written in lower case) stands
+for packet capture, and is actually an API that includes the
+definition of a ``.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 concentrate on viewing pcap traces with tcpdump.
+
+The code used to enable pcap tracing is a one-liner.
+
+::
+
+ pointToPoint.EnablePcapAll ("myfirst");
+
+Go ahead and insert this line of code after the ASCII tracing code we just
+added to ``scratch/myfirst.cc``. Notice that we only passed the string
+"myfirst," and not "myfirst.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 eventually see files named "myfirst-0-0.pcap"
+and "myfirst-1-0.pcap" which are the pcap traces for node 0-device 0 and
+node 1-device 0, respectively.
+
+Once you have added the line of code to enable pcap tracing, you can run the
+script in the usual way:
+
+::
+
+ ./waf --run scratch/myfirst
+
+If you look at the top level directory of your distribution, you should now
+see three log files: ``myfirst.tr`` is the ASCII trace file we have
+previously examined. ``myfirst-0-0.pcap`` and ``myfirst-1-0.pcap``
+are the new pcap files we just generated.
+
+Reading output with tcpdump
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The easiest thing to do at this point will be to use ``tcpdump`` to look
+at the ``pcap`` files.
+
+::
+
+ tcpdump -nn -tt -r myfirst-0-0.pcap
+ reading from file myfirst-0-0.pcap, link-type PPP (PPP)
+ 2.000000 IP 10.1.1.1.49153 > 10.1.1.2.9: UDP, length 1024
+ 2.514648 IP 10.1.1.2.9 > 10.1.1.1.49153: UDP, length 1024
+
+ tcpdump -nn -tt -r myfirst-1-0.pcap
+ reading from file myfirst-1-0.pcap, link-type PPP (PPP)
+ 2.257324 IP 10.1.1.1.49153 > 10.1.1.2.9: UDP, length 1024
+ 2.257324 IP 10.1.1.2.9 > 10.1.1.1.49153: UDP, length 1024
+
+You can see in the dump of ``myfirst-0-0.pcap`` (the client device) that the
+echo packet is sent at 2 seconds into the simulation. If you look at the
+second dump (``myfirst-1-0.pcap``) you can see that packet being received
+at 2.257324 seconds. You see the packet being echoed back at 2.257324 seconds
+in the second dump, and finally, you see the packet being received back at
+the client in the first dump at 2.514648 seconds.
+
+Reading output with Wireshark
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+If you are unfamiliar with Wireshark, there is a web site available from which
+you can download programs and documentation: http://www.wireshark.org/.
+
+Wireshark is a graphical user interface which can be used for displaying these
+trace files. If you have Wireshark available, you can open each of the trace
+files and display the contents as if you had captured the packets using a
+*packet sniffer*.
--- a/doc/tutorial/tracing.texi Sun Jan 02 22:57:04 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,3174 +0,0 @@
-@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::
-* Overview::
-* A Real Example::
-* Using Mid-Level Trace Helpers::
-@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 mechanisms 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 (for large simulations, dumping everything
-to disk for post-processing can create I/O bottlenecks). Second, if you use this
-method, you can control the format of the output directly so you avoid the
-postprocessing step with sed or awk script. If you desire, your output can be
-formatted directly into a form acceptable by gnuplot, for example. You can add
-hooks in the core which can then be accessed by other users, but which will
-produce no information unless explicitly asked to do so. For these reasons, we
-believe that the @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}
-output, you may also discover that pieces of log output on which you depend
-disappear or change between releases. If you depend on the structure of the
-output, you may find other messages being added or deleted which may affect your
-parsing code.
-
-For these reasons, we consider prints to @code{std::cout} and NS_LOG messages
-to be quick and dirty ways to get more information out of @code{ns-3}.
-
-It is desirable to have a stable facility using stable APIs that allow one to
-reach into the core system and only get the information required. It is
-desirable to be able to do this without having to change and recompile the
-core system. Even better would be a system that notified the user when an item
-of interest changed or an interesting event happened so the user doesn't have
-to actively poke around in the system looking for things.
-
-The @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 interesting 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 implementation 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.
-
-@subsection What About TracedValue?
-
-Earlier in this section, we presented a simple piece of code that used a
-@code{TracedValue<int32_t>} to demonstrate the basics of the tracing code.
-We just glossed over the way to find the return type and formal arguments
-for the @code{TracedValue}. Rather than go through the whole exercise, we
-will just point you at the correct file, @code{src/core/traced-value.h} and
-to the important piece of code:
-
-@verbatim
- template <typename T>
- class TracedValue
- {
- public:
- ...
- void Set (const T &v) {
- if (m_v != v)
- {
- m_cb (m_v, v);
- m_v = v;
- }
- }
- ...
- private:
- T m_v;
- TracedCallback<T,T> m_cb;
- };
-@end verbatim
-
-Here you see that the @code{TracedValue} is templated, of course. In the simple
-example case at the start of the section, the typename is int32_t. This means
-that the member variable being traced (@code{m_v} in the private section of the
-class) will be an @code{int32_t m_v}. The @code{Set} method will take a
-@code{const int32_t &v} as a parameter. You should now be able to understand
-that the @code{Set} code will fire the @code{m_cb} callback with two parameters:
-the first being the current value of the @code{TracedValue}; and the second
-being the new value being set.
-
-The callback, @code{m_cb} is declared as a @code{TracedCallback<T, T>} which
-will correspond to a @code{TracedCallback<int32_t, int32_t>} when the class is
-instantiated.
-
-Recall that the callback target of a TracedCallback always returns @code{void}.
-Further recall that there is a one-to-one correspondence between the template
-parameter list in the declaration and the formal arguments of the callback
-function. Therefore the callback will need to have a function signature that
-looks like:
-
-@verbatim
- void
- MyCallback (int32_t oldValue, int32_t newValue)
- {
- ...
- }
-@end verbatim
-
-It probably won't surprise you that this is exactly what we provided in that
-simple example we covered so long ago:
-
-@verbatim
- void
- IntTrace (int32_t oldValue, int32_t newValue)
- {
- std::cout << "Traced " << oldValue << " to " << newValue << std::endl;
- }
-@end verbatim
-
-@c ============================================================================
-@c A Real Example
-@c ============================================================================
-@node A Real Example
-@section A Real Example
-
-Let's do an example taken from one of the best-known books on TCP around.
-``TCP/IP Illustrated, Volume 1: The Protocols,'' by W. Richard Stevens is a
-classic. I just flipped the book open and ran across a nice plot of both the
-congestion window and sequence numbers versus time on page 366. Stevens calls
-this, ``Figure 21.10. Value of cwnd and send sequence number while data is being
-transmitted.'' Let's just recreate the cwnd part of that plot in @command{ns-3}
-using the tracing system and @code{gnuplot}.
-
-@subsection Are There Trace Sources Available?
-
-The first thing to think about is how we want to get the data out. What is it
-that we need to trace? The first thing to do is to consult ``The list of all
-trace sources'' to see what we have to work with. Recall that this is found
-in the @command{ns-3} Doxygen in the ``Core'' Module section. If you scroll
-through the list, you will eventually find:
-
-@verbatim
- ns3::TcpSocketImpl
- CongestionWindow: The TCP connection's congestion window
-@end verbatim
-
-It turns out that the @command{ns-3} TCP implementation lives (mostly) in the
-file @code{src/internet-stack/tcp-socket-impl.cc}. If you don't know this a
-priori, you can use the recursive grep trick:
-
-@verbatim
- find . -name '*.cc' | xargs grep -i tcp
-@end verbatim
-
-You will find page after page of instances of tcp pointing you to that file.
-
-If you open @code{src/internet-stack/tcp-socket-impl.cc} in your favorite
-editor, you will see right up at the top of the file, the following declarations:
-
-@verbatim
- TypeId
- TcpSocketImpl::GetTypeId ()
- {
- static TypeId tid = TypeId(``ns3::TcpSocketImpl'')
- .SetParent<TcpSocket> ()
- .AddTraceSource (``CongestionWindow'',
- ``The TCP connection's congestion window'',
- MakeTraceSourceAccessor (&TcpSocketImpl::m_cWnd))
- ;
- return tid;
- }
-@end verbatim
-
-This should tell you to look for the declaration of @code{m_cWnd} in the header
-file @code{src/internet-stack/tcp-socket-impl.h}. If you open this file in your
-favorite editor, you will find:
-
-@verbatim
- TracedValue<uint32_t> m_cWnd; //Congestion window
-@end verbatim
-
-You should now understand this code completely. If we have a pointer to the
-@code{TcpSocketImpl}, we can @code{TraceConnect} to the ``CongestionWindow'' trace
-source if we provide an appropriate callback target. This is the same kind of
-trace source that we saw in the simple example at the start of this section,
-except that we are talking about @code{uint32_t} instead of @code{int32_t}.
-
-We now know that we need to provide a callback that returns void and takes
-two @code{uint32_t} parameters, the first being the old value and the second
-being the new value:
-
-@verbatim
- void
- CwndTrace (uint32_t oldValue, uint32_t newValue)
- {
- ...
- }
-@end verbatim
-
-@subsection What Script to Use?
-
-It's always best to try and find working code laying around that you can
-modify, rather than starting from scratch. So the first order of business now
-is to find some code that already hooks the ``CongestionWindow'' trace source
-and see if we can modify it. As usual, grep is your friend:
-
-@verbatim
- find . -name '*.cc' | xargs grep CongestionWindow
-@end verbatim
-
-This will point out a couple of promising candidates:
-@code{examples/tcp/tcp-large-transfer.cc} and
-@code{src/test/ns3tcp/ns3tcp-cwnd-test-suite.cc}.
-
-We haven't visited any of the test code yet, so let's take a look there. You
-will typically find that test code is fairly minimal, so this is probably a
-very good bet. Open @code{src/test/ns3tcp/ns3tcp-cwnd-test-suite.cc} in your
-favorite editor and search for ``CongestionWindow''. You will find,
-
-@verbatim
- ns3TcpSocket->TraceConnectWithoutContext (``CongestionWindow'',
- MakeCallback (&Ns3TcpCwndTestCase1::CwndChange, this));
-@end verbatim
-
-This should look very familiar to you. We mentioned above that if we had a
-pointer to the @code{TcpSocketImpl}, we could @code{TraceConnect} to the
-``CongestionWindow'' trace source. That's exactly what we have here; so it
-turns out that this line of code does exactly what we want. Let's go ahead
-and extract the code we need from this function
-(@code{Ns3TcpCwndTestCase1::DoRun (void)}). If you look at this function,
-you will find that it looks just like an @code{ns-3} script. It turns out that
-is exactly what it is. It is a script run by the test framework, so we can just
-pull it out and wrap it in @code{main} instead of in @code{DoRun}. Rather than
-walk through this, step, by step, we have provided the file that results from
-porting this test back to a native @code{ns-3} script --
-@code{examples/tutorial/fifth.cc}.
-
-@subsection A Common Problem and Solution
-
-The @code{fifth.cc} example demonstrates an extremely important rule that you
-must understand before using any kind of @code{Attribute}: you must ensure
-that the target of a @code{Config} command exists before trying to use it.
-This is no different than saying an object must be instantiated before trying
-to call it. Although this may seem obvious when stated this way, it does
-trip up many people trying to use the system for the first time.
-
-Let's return to basics for a moment. There are three basic time periods that
-exist in any @command{ns-3} script. The first time period is sometimes called
-``Configuration Time'' or ``Setup Time,'' and is in force during the period
-when the @code{main} function of your script is running, but before
-@code{Simulator::Run} is called. The second time period is sometimes called
-``Simulation Time'' and is in force during the time period when
-@code{Simulator::Run} is actively executing its events. After it completes
-executing the simulation, @code{Simulator::Run} will return control back to
-the @code{main} function. When this happens, the script enters what can be
-called ``Teardown Time,'' which is when the structures and objects created
-during setup and taken apart and released.
-
-Perhaps the most common mistake made in trying to use the tracing system is
-assuming that entities constructed dynamically during simulation time are
-available during configuration time. In particular, an @command{ns-3}
-@code{Socket} is a dynamic object often created by @code{Applications} to
-communicate between @code{Nodes}. An @command{ns-3} @code{Application}
-always has a ``Start Time'' and a ``Stop Time'' associated with it. In the
-vast majority of cases, an @code{Application} will not attempt to create
-a dynamic object until its @code{StartApplication} method is called at some
-``Start Time''. This is to ensure that the simulation is completely
-configured before the app tries to do anything (what would happen if it tried
-to connect to a node that didn't exist yet during configuration time). The
-answer to this issue is to 1) create a simulator event that is run after the
-dynamic object is created and hook the trace when that event is executed; or
-2) create the dynamic object at configuration time, hook it then, and give
-the object to the system to use during simulation time. We took the second
-approach in the @code{fifth.cc} example. This decision required us to create
-the @code{MyApp} @code{Application}, the entire purpose of which is to take
-a @code{Socket} as a parameter.
-
-@subsection A fifth.cc Walkthrough
-
-Now, let's take a look at the example program we constructed by dissecting
-the congestion window test. Open @code{examples/tutorial/fifth.cc} in your
-favorite editor. You should see some familiar looking code:
-
-@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, Include., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
- #include <fstream>
- #include "ns3/core-module.h"
- #include "ns3/common-module.h"
- #include "ns3/simulator-module.h"
- #include "ns3/node-module.h"
- #include "ns3/helper-module.h"
-
- using namespace ns3;
-
- NS_LOG_COMPONENT_DEFINE ("FifthScriptExample");
-@end verbatim
-
-This has all been covered, so we won't rehash it. The next lines of source are
-the network illustration and a comment addressing the problem described above
-with @code{Socket}.
-
-@verbatim
- // ===========================================================================
- //
- // node 0 node 1
- // +----------------+ +----------------+
- // | ns-3 TCP | | ns-3 TCP |
- // +----------------+ +----------------+
- // | 10.1.1.1 | | 10.1.1.2 |
- // +----------------+ +----------------+
- // | point-to-point | | point-to-point |
- // +----------------+ +----------------+
- // | |
- // +---------------------+
- // 5 Mbps, 2 ms
- //
- //
- // We want to look at changes in the ns-3 TCP congestion window. We need
- // to crank up a flow and hook the CongestionWindow attribute on the socket
- // of the sender. Normally one would use an on-off application to generate a
- // flow, but this has a couple of problems. First, the socket of the on-off
- // application is not created until Application Start time, so we wouldn't be
- // able to hook the socket (now) at configuration time. Second, even if we
- // could arrange a call after start time, the socket is not public so we
- // couldn't get at it.
- //
- // So, we can cook up a simple version of the on-off application that does what
- // we want. On the plus side we don't need all of the complexity of the on-off
- // application. On the minus side, we don't have a helper, so we have to get
- // a little more involved in the details, but this is trivial.
- //
- // So first, we create a socket and do the trace connect on it; then we pass
- // this socket into the constructor of our simple application which we then
- // install in the source node.
- // ===========================================================================
- //
-@end verbatim
-
-This should also be self-explanatory.
-
-The next part is the declaration of the @code{MyApp} @code{Application} that
-we put together to allow the @code{Socket} to be created at configuration time.
-
-@verbatim
- class MyApp : public Application
- {
- public:
-
- MyApp ();
- virtual ~MyApp();
-
- void Setup (Ptr<Socket> socket, Address address, uint32_t packetSize,
- uint32_t nPackets, DataRate dataRate);
-
- private:
- virtual void StartApplication (void);
- virtual void StopApplication (void);
-
- void ScheduleTx (void);
- void SendPacket (void);
-
- Ptr<Socket> m_socket;
- Address m_peer;
- uint32_t m_packetSize;
- uint32_t m_nPackets;
- DataRate m_dataRate;
- EventId m_sendEvent;
- bool m_running;
- uint32_t m_packetsSent;
- };
-@end verbatim
-
-You can see that this class inherits from the @command{ns-3} @code{Application}
-class. Take a look at @code{src/node/application.h} if you are interested in
-what is inherited. The @code{MyApp} class is obligated to override the
-@code{StartApplication} and @code{StopApplication} methods. These methods are
-automatically called when @code{MyApp} is required to start and stop sending
-data during the simulation.
-
-@subsubsection How Applications are Started and Stopped (optional)
-
-It is worthwhile to spend a bit of time explaining how events actually get
-started in the system. This is another fairly deep explanation, and can be
-ignored if you aren't planning on venturing down into the guts of the system.
-It is useful, however, in that the discussion touches on how some very important
-parts of @code{ns-3} work and exposes some important idioms. If you are
-planning on implementing new models, you probably want to understand this
-section.
-
-The most common way to start pumping events is to start an @code{Application}.
-This is done as the result of the following (hopefully) familar lines of an
-@command{ns-3} script:
-
-@verbatim
- ApplicationContainer apps = ...
- apps.Start (Seconds (1.0));
- apps.Stop (Seconds (10.0));
-@end verbatim
-
-The application container code (see @code{src/helper/application-container.h} if
-you are interested) loops through its contained applications and calls,
-
-@verbatim
- app->SetStartTime (startTime);
-@end verbatim
-
-as a result of the @code{apps.Start} call and
-
-@verbatim
- app->SetStopTime (stopTime);
-@end verbatim
-
-as a result of the @code{apps.Stop} call.
-
-The ultimate result of these calls is that we want to have the simulator
-automatically make calls into our @code{Applications} to tell them when to
-start and stop. In the case of @code{MyApp}, it inherits from class
-@code{Application} and overrides @code{StartApplication}, and
-@code{StopApplication}. These are the functions that will be called by
-the simulator at the appropriate time. In the case of @code{MyApp} you
-will find that @code{MyApp::StartApplication} does the initial @code{Bind},
-and @code{Connect} on the socket, and then starts data flowing by calling
-@code{MyApp::SendPacket}. @code{MyApp::StopApplication} stops generating
-packets by cancelling any pending send events and closing the socket.
-
-One of the nice things about @command{ns-3} is that you can completely
-ignore the implementation details of how your @code{Application} is
-``automagically'' called by the simulator at the correct time. But since
-we have already ventured deep into @command{ns-3} already, let's go for it.
-
-If you look at @code{src/node/application.cc} you will find that the
-@code{SetStartTime} method of an @code{Application} just sets the member
-variable @code{m_startTime} and the @code{SetStopTime} method just sets
-@code{m_stopTime}. From there, without some hints, the trail will probably
-end.
-
-The key to picking up the trail again is to know that there is a global
-list of all of the nodes in the system. Whenever you create a node in
-a simulation, a pointer to that node is added to the global @code{NodeList}.
-
-Take a look at @code{src/node/node-list.cc} and search for
-@code{NodeList::Add}. The public static implementation calls into a private
-implementation called @code{NodeListPriv::Add}. This is a relatively common
-idom in @command{ns-3}. So, take a look at @code{NodeListPriv::Add}. There
-you will find,
-
-@verbatim
- Simulator::ScheduleWithContext (index, TimeStep (0), &Node::Start, node);
-@end verbatim
-
-This tells you that whenever a @code{Node} is created in a simulation, as
-a side-effect, a call to that node's @code{Start} method is scheduled for
-you that happens at time zero. Don't read too much into that name, yet.
-It doesn't mean that the node is going to start doing anything, it can be
-interpreted as an informational call into the @code{Node} telling it that
-the simulation has started, not a call for action telling the @code{Node}
-to start doing something.
-
-So, @code{NodeList::Add} indirectly schedules a call to @code{Node::Start}
-at time zero to advise a new node that the simulation has started. If you
-look in @code{src/node/node.h} you will, however, not find a method called
-@code{Node::Start}. It turns out that the @code{Start} method is inherited
-from class @code{Object}. All objects in the system can be notified when
-the simulation starts, and objects of class @code{Node} are just one kind
-of those objects.
-
-Take a look at @code{src/core/object.cc} next and search for @code{Object::Start}.
-This code is not as straightforward as you might have expected since
-@command{ns-3} @code{Objects} support aggregation. The code in
-@code{Object::Start} then loops through all of the objects that have been
-aggregated together and calls their @code{DoStart} method. This is another
-idiom that is very common in @command{ns-3}. There is a public API method,
-that stays constant across implementations, that calls a private implementation
-method that is inherited and implemented by subclasses. The names are typically
-something like @code{MethodName} for the public API and @code{DoMethodName} for
-the private API.
-
-This tells us that we should look for a @code{Node::DoStart} method in
-@code{src/node/node.cc} for the method that will continue our trail. If you
-locate the code, you will find a method that loops through all of the devices
-in the node and then all of the applications in the node calling
-@code{device->Start} and @code{application->Start} respectively.
-
-You may already know that classes @code{Device} and @code{Application} both
-inherit from class @code{Object} and so the next step will be to look at
-what happens when @code{Application::DoStart} is called. Take a look at
-@code{src/node/application.cc} and you will find:
-
-@verbatim
- void
- Application::DoStart (void)
- {
- m_startEvent = Simulator::Schedule (m_startTime, &Application::StartApplication, this);
- if (m_stopTime != TimeStep (0))
- {
- m_stopEvent = Simulator::Schedule (m_stopTime, &Application::StopApplication, this);
- }
- Object::DoStart ();
- }
-@end verbatim
-
-Here, we finally come to the end of the trail. If you have kept it all straight,
-when you implement an @command{ns-3} @code{Application}, your new application
-inherits from class @code{Application}. You override the @code{StartApplication}
-and @code{StopApplication} methods and provide mechanisms for starting and
-stopping the flow of data out of your new @code{Application}. When a @code{Node}
-is created in the simulation, it is added to a global @code{NodeList}. The act
-of adding a node to this @code{NodeList} causes a simulator event to be scheduled
-for time zero which calls the @code{Node::Start} method of the newly added
-@code{Node} to be called when the simulation starts. Since a @code{Node} inherits
-from @code{Object}, this calls the @code{Object::Start} method on the @code{Node}
-which, in turn, calls the @code{DoStart} methods on all of the @code{Objects}
-aggregated to the @code{Node} (think mobility models). Since the @code{Node}
-@code{Object} has overridden @code{DoStart}, that method is called when the
-simulation starts. The @code{Node::DoStart} method calls the @code{Start} methods
-of all of the @code{Applications} on the node. Since @code{Applications} are
-also @code{Objects}, this causes @code{Application::DoStart} to be called. When
-@code{Application::DoStart} is called, it schedules events for the
-@code{StartApplication} and @code{StopApplication} calls on the @code{Application}.
-These calls are designed to start and stop the flow of data from the
-@code{Application}
-
-This has been another fairly long journey, but it only has to be made once, and
-you now understand another very deep piece of @command{ns-3}.
-
-@subsubsection The MyApp Application
-
-The @code{MyApp} @code{Application} needs a constructor and a destructor,
-of course:
-
-@verbatim
- MyApp::MyApp ()
- : m_socket (0),
- m_peer (),
- m_packetSize (0),
- m_nPackets (0),
- m_dataRate (0),
- m_sendEvent (),
- m_running (false),
- m_packetsSent (0)
- {
- }
-
- MyApp::~MyApp()
- {
- m_socket = 0;
- }
-@end verbatim
-
-The existence of the next bit of code is the whole reason why we wrote this
-@code{Application} in the first place.
-
-@verbatim
-void
-MyApp::Setup (Ptr<Socket> socket, Address address, uint32_t packetSize,
- uint32_t nPackets, DataRate dataRate)
-{
- m_socket = socket;
- m_peer = address;
- m_packetSize = packetSize;
- m_nPackets = nPackets;
- m_dataRate = dataRate;
-}
-@end verbatim
-
-This code should be pretty self-explanatory. We are just initializing member
-variables. The important one from the perspective of tracing is the
-@code{Ptr<Socket> socket} which we needed to provide to the application
-during configuration time. Recall that we are going to create the @code{Socket}
-as a @code{TcpSocket} (which is implemented by @code{TcpSocketImpl}) and hook
-its ``CongestionWindow'' trace source before passing it to the @code{Setup}
-method.
-
-@verbatim
- void
- MyApp::StartApplication (void)
- {
- m_running = true;
- m_packetsSent = 0;
- m_socket->Bind ();
- m_socket->Connect (m_peer);
- SendPacket ();
- }
-@end verbatim
-
-The above code is the overridden implementation @code{Application::StartApplication}
-that will be automatically called by the simulator to start our @code{Application}
-running at the appropriate time. You can see that it does a @code{Socket} @code{Bind}
-operation. If you are familiar with Berkeley Sockets this shouldn't be a surprise.
-It performs the required work on the local side of the connection just as you might
-expect. The following @code{Connect} will do what is required to establish a connection
-with the TCP at @code{Address} m_peer. It should now be clear why we need to defer
-a lot of this to simulation time, since the @code{Connect} is going to need a fully
-functioning network to complete. After the @code{Connect}, the @code{Application}
-then starts creating simulation events by calling @code{SendPacket}.
-
-The next bit of code explains to the @code{Application} how to stop creating
-simulation events.
-
-@verbatim
- void
- MyApp::StopApplication (void)
- {
- m_running = false;
-
- if (m_sendEvent.IsRunning ())
- {
- Simulator::Cancel (m_sendEvent);
- }
-
- if (m_socket)
- {
- m_socket->Close ();
- }
- }
-@end verbatim
-
-Every time a simulation event is scheduled, an @code{Event} is created. If the
-@code{Event} is pending execution or executing, its method @code{IsRunning} will
-return @code{true}. In this code, if @code{IsRunning()} returns true, we
-@code{Cancel} the event which removes it from the simulator event queue. By
-doing this, we break the chain of events that the @code{Application} is using to
-keep sending its @code{Packets} and the @code{Application} goes quiet. After we
-quiet the @code{Application} we @code{Close} the socket which tears down the TCP
-connection.
-
-The socket is actually deleted in the destructor when the @code{m_socket = 0} is
-executed. This removes the last reference to the underlying Ptr<Socket> which
-causes the destructor of that Object to be called.
-
-Recall that @code{StartApplication} called @code{SendPacket} to start the
-chain of events that describes the @code{Application} behavior.
-
-@verbatim
- void
- MyApp::SendPacket (void)
- {
- Ptr<Packet> packet = Create<Packet> (m_packetSize);
- m_socket->Send (packet);
-
- if (++m_packetsSent < m_nPackets)
- {
- ScheduleTx ();
- }
- }
-@end verbatim
-
-Here, you see that @code{SendPacket} does just that. It creates a @code{Packet}
-and then does a @code{Send} which, if you know Berkeley Sockets, is probably
-just what you expected to see.
-
-It is the responsibility of the @code{Application} to keep scheduling the
-chain of events, so the next lines call @code{ScheduleTx} to schedule another
-transmit event (a @code{SendPacket}) until the @code{Application} decides it
-has sent enough.
-
-@verbatim
- void
- MyApp::ScheduleTx (void)
- {
- if (m_running)
- {
- Time tNext (Seconds (m_packetSize * 8 / static_cast<double> (m_dataRate.GetBitRate ())));
- m_sendEvent = Simulator::Schedule (tNext, &MyApp::SendPacket, this);
- }
- }
-@end verbatim
-
-Here, you see that @code{ScheduleTx} does exactly that. If the @code{Application}
-is running (if @code{StopApplication} has not been called) it will schedule a
-new event, which calls @code{SendPacket} again. The alert reader will spot
-something that also trips up new users. The data rate of an @code{Application} is
-just that. It has nothing to do with the data rate of an underlying @code{Channel}.
-This is the rate at which the @code{Application} produces bits. It does not take
-into account any overhead for the various protocols or channels that it uses to
-transport the data. If you set the data rate of an @code{Application} to the same
-data rate as your underlying @code{Channel} you will eventually get a buffer overflow.
-
-@subsubsection The Trace Sinks
-
-The whole point of this exercise is to get trace callbacks from TCP indicating the
-congestion window has been updated. The next piece of code implements the
-corresponding trace sink:
-
-@verbatim
- static void
- CwndChange (uint32_t oldCwnd, uint32_t newCwnd)
- {
- NS_LOG_UNCOND (Simulator::Now ().GetSeconds () << ``\t'' << newCwnd);
- }
-@end verbatim
-
-This should be very familiar to you now, so we won't dwell on the details. This
-function just logs the current simulation time and the new value of the
-congestion window every time it is changed. You can probably imagine that you
-could load the resulting output into a graphics program (gnuplot or Excel) and
-immediately see a nice graph of the congestion window behavior over time.
-
-We added a new trace sink to show where packets are dropped. We are going to
-add an error model to this code also, so we wanted to demonstrate this working.
-
-@verbatim
- static void
- RxDrop (Ptr<const Packet> p)
- {
- NS_LOG_UNCOND ("RxDrop at " << Simulator::Now ().GetSeconds ());
- }
-@end verbatim
-
-This trace sink will be connected to the ``PhyRxDrop'' trace source of the
-point-to-point NetDevice. This trace source fires when a packet is dropped
-by the physical layer of a @code{NetDevice}. If you take a small detour to the
-source (@code{src/devices/point-to-point/point-to-point-net-device.cc}) you will
-see that this trace source refers to @code{PointToPointNetDevice::m_phyRxDropTrace}.
-If you then look in @code{src/devices/point-to-point/point-to-point-net-device.h}
-for this member variable, you will find that it is declared as a
-@code{TracedCallback<Ptr<const Packet> >}. This should tell you that the
-callback target should be a function that returns void and takes a single
-parameter which is a @code{Ptr<const Packet>} -- just what we have above.
-
-@subsubsection The Main Program
-
-The following code should be very familiar to you by now:
-
-@verbatim
- int
- main (int argc, char *argv[])
- {
- NodeContainer nodes;
- nodes.Create (2);
-
- PointToPointHelper pointToPoint;
- pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
- pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
-
- NetDeviceContainer devices;
- devices = pointToPoint.Install (nodes);
-@end verbatim
-
-This creates two nodes with a point-to-point channel between them, just as
-shown in the illustration at the start of the file.
-
-The next few lines of code show something new. If we trace a connection that
-behaves perfectly, we will end up with a monotonically increasing congestion
-window. To see any interesting behavior, we really want to introduce link
-errors which will drop packets, cause duplicate ACKs and trigger the more
-interesting behaviors of the congestion window.
-
-@command{ns-3} provides @code{ErrorModel} objects which can be attached to
-@code{Channels}. We are using the @code{RateErrorModel} which allows us
-to introduce errors into a @code{Channel} at a given @emph{rate}.
-
-@verbatim
- Ptr<RateErrorModel> em = CreateObjectWithAttributes<RateErrorModel> (
- "RanVar", RandomVariableValue (UniformVariable (0., 1.)),
- "ErrorRate", DoubleValue (0.00001));
- devices.Get (1)->SetAttribute ("ReceiveErrorModel", PointerValue (em));
-@end verbatim
-
-The above code instantiates a @code{RateErrorModel} Object. Rather than
-using the two-step process of instantiating it and then setting Attributes,
-we use the convenience function @code{CreateObjectWithAttributes} which
-allows us to do both at the same time. We set the ``RanVar''
-@code{Attribute} to a random variable that generates a uniform distribution
-from 0 to 1. We also set the ``ErrorRate'' @code{Attribute}.
-We then set the resulting instantiated @code{RateErrorModel} as the error
-model used by the point-to-point @code{NetDevice}. This will give us some
-retransmissions and make our plot a little more interesting.
-
-@verbatim
- InternetStackHelper stack;
- stack.Install (nodes);
-
- Ipv4AddressHelper address;
- address.SetBase (``10.1.1.0'', ``255.255.255.252'');
- Ipv4InterfaceContainer interfaces = address.Assign (devices);
-@end verbatim
-
-The above code should be familiar. It installs internet stacks on our two
-nodes and creates interfaces and assigns IP addresses for the point-to-point
-devices.
-
-Since we are using TCP, we need something on the destination node to receive
-TCP connections and data. The @code{PacketSink} @code{Application} is commonly
-used in @command{ns-3} for that purpose.
-
-@verbatim
- uint16_t sinkPort = 8080;
- Address sinkAddress (InetSocketAddress(interfaces.GetAddress (1), sinkPort));
- PacketSinkHelper packetSinkHelper ("ns3::TcpSocketFactory",
- InetSocketAddress (Ipv4Address::GetAny (), sinkPort));
- ApplicationContainer sinkApps = packetSinkHelper.Install (nodes.Get (1));
- sinkApps.Start (Seconds (0.));
- sinkApps.Stop (Seconds (20.));
-@end verbatim
-
-This should all be familiar, with the exception of,
-
-@verbatim
- PacketSinkHelper packetSinkHelper ("ns3::TcpSocketFactory",
- InetSocketAddress (Ipv4Address::GetAny (), sinkPort));
-@end verbatim
-
-This code instantiates a @code{PacketSinkHelper} and tells it to create sockets
-using the class @code{ns3::TcpSocketFactory}. This class implements a design
-pattern called ``object factory'' which is a commonly used mechanism for
-specifying a class used to create objects in an abstract way. Here, instead of
-having to create the objects themselves, you provide the @code{ PacketSinkHelper}
-a string that specifies a @code{TypeId} string used to create an object which
-can then be used, in turn, to create instances of the Objects created by the
-factory.
-
-The remaining parameter tells the @code{Application} which address and port it
-should @code{Bind} to.
-
-The next two lines of code will create the socket and connect the trace source.
-
-@verbatim
- Ptr<Socket> ns3TcpSocket = Socket::CreateSocket (nodes.Get (0),
- TcpSocketFactory::GetTypeId ());
- ns3TcpSocket->TraceConnectWithoutContext (``CongestionWindow'',
- MakeCallback (&CwndChange));
-@end verbatim
-
-The first statement calls the static member function @code{Socket::CreateSocket}
-and provides a @code{Node} and an explicit @code{TypeId} for the object factory
-used to create the socket. This is a slightly lower level call than the
-@code{PacketSinkHelper} call above, and uses an explicit C++ type instead of
-one referred to by a string. Otherwise, it is conceptually the same thing.
-
-Once the @code{TcpSocket} is created and attached to the @code{Node}, we can
-use @code{TraceConnectWithoutContext} to connect the CongestionWindow trace
-source to our trace sink.
-
-Recall that we coded an @code{Application} so we could take that @code{Socket}
-we just made (during configuration time) and use it in simulation time. We now
-have to instantiate that @code{Application}. We didn't go to any trouble to
-create a helper to manage the @code{Application} so we are going to have to
-create and install it ``manually''. This is actually quite easy:
-
-@verbatim
- Ptr<MyApp> app = CreateObject<MyApp> ();
- app->Setup (ns3TcpSocket, sinkAddress, 1040, 1000, DataRate ("1Mbps"));
- nodes.Get (0)->AddApplication (app);
- app->Start (Seconds (1.));
- app->Stop (Seconds (20.));
-@end verbatim
-
-The first line creates an @code{Object} of type @code{MyApp} -- our
-@code{Application}. The second line tells the @code{Application} what
-@code{Socket} to use, what address to connect to, how much data to send
-at each send event, how many send events to generate and the rate at which
-to produce data from those events.
-
-Next, we manually add the @code{MyApp Application} to the source node
-and explicitly call the @code{Start} and @code{Stop} methods on the
-@code{Application} to tell it when to start and stop doing its thing.
-
-We need to actually do the connect from the receiver point-to-point @code{NetDevice}
-to our callback now.
-
-@verbatim
- devices.Get (1)->TraceConnectWithoutContext("PhyRxDrop", MakeCallback (&RxDrop));
-@end verbatim
-
-It should now be obvious that we are getting a reference to the receiving
-@code{Node NetDevice} from its container and connecting the trace source defined
-by the attribute ``PhyRxDrop'' on that device to the trace sink @code{RxDrop}.
-
-Finally, we tell the simulator to override any @code{Applications} and just
-stop processing events at 20 seconds into the simulation.
-
-@verbatim
- Simulator::Stop (Seconds(20));
- Simulator::Run ();
- Simulator::Destroy ();
-
- return 0;
- }
-@end verbatim
-
-Recall that as soon as @code{Simulator::Run} is called, configuration time
-ends, and simulation time begins. All of the work we orchestrated by
-creating the @code{Application} and teaching it how to connect and send
-data actually happens during this function call.
-
-As soon as @code{Simulator::Run} returns, the simulation is complete and
-we enter the teardown phase. In this case, @code{Simulator::Destroy} takes
-care of the gory details and we just return a success code after it completes.
-
-@subsection Running fifth.cc
-
-Since we have provided the file @code{fifth.cc} for you, if you have built
-your distribution (in debug mode since it uses NS_LOG -- recall that optimized
-builds optimize out NS_LOGs) it will be waiting for you to run.
-
-@verbatim
- ./waf --run fifth
- Waf: Entering directory `/home/craigdo/repos/ns-3-allinone-dev/ns-3-dev/build
- Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone-dev/ns-3-dev/build'
- 'build' finished successfully (0.684s)
- 1.20919 1072
- 1.21511 1608
- 1.22103 2144
- ...
- 1.2471 8040
- 1.24895 8576
- 1.2508 9112
- RxDrop at 1.25151
- ...
-@end verbatim
-
-You can probably see immediately a downside of using prints of any kind in your
-traces. We get those extraneous waf messages printed all over our interesting
-information along with those RxDrop messages. We will remedy that soon, but I'm
-sure you can't wait to see the results of all of this work. Let's redirect that
-output to a file called @code{cwnd.dat}:
-
-@verbatim
- ./waf --run fifth > cwnd.dat 2>&1
-@end verbatim
-
-Now edit up ``cwnd.dat'' in your favorite editor and remove the waf build status
-and drop lines, leaving only the traced data (you could also comment out the
-@code{TraceConnectWithoutContext("PhyRxDrop", MakeCallback (&RxDrop));} in the
-script to get rid of the drop prints just as easily.
-
-You can now run gnuplot (if you have it installed) and tell it to generate some
-pretty pictures:
-
-@verbatim
- gnuplot> set terminal png size 640,480
- gnuplot> set output "cwnd.png"
- gnuplot> plot "cwnd.dat" using 1:2 title 'Congestion Window' with linespoints
- gnuplot> exit
-@end verbatim
-
-You should now have a graph of the congestion window versus time sitting in the
-file ``cwnd.png'' in all of its glory, that looks like:
-
-@sp 1
-@center @image{figures/cwnd,,,,png}
-
-@subsection Using Mid-Level Helpers
-
-In the previous section, we showed how to hook a trace source and get hopefully
-interesting information out of a simulation. Perhaps you will recall that we
-called logging to the standard output using @code{std::cout} a ``Blunt Instrument''
-much earlier in this chapter. We also wrote about how it was a problem having
-to parse the log output in order to isolate interesting information. It may
-have occurred to you that we just spent a lot of time implementing an example
-that exhibits all of the problems we purport to fix with the @code{ns-3} tracing
-system! You would be correct. But, bear with us. We're not done yet.
-
-One of the most important things we want to do is to is to have the ability to
-easily control the amount of output coming out of the simulation; and we also
-want to save those data to a file so we can refer back to it later. We can use
-the mid-level trace helpers provided in @code{ns-3} to do just that and complete
-the picture.
-
-We provide a script that writes the cwnd change and drop events developed in
-the example @code{fifth.cc } to disk in separate files. The cwnd changes are
-stored as a tab-separated ASCII file and the drop events are stored in a pcap
-file. The changes to make this happen are quite small.
-
-@subsubsection A sixth.cc Walkthrough
-
-Let's take a look at the changes required to go from @code{fifth.cc} to
-@code{sixth.cc}. Open @code{examples/tutorial/fifth.cc} in your favorite
-editor. You can see the first change by searching for CwndChange. You will
-find that we have changed the signatures for the trace sinks and have added
-a single line to each sink that writes the traced information to a stream
-representing a file.
-
-@verbatim
- static void
- CwndChange (Ptr<OutputStreamWrapper> stream, uint32_t oldCwnd, uint32_t newCwnd)
- {
- NS_LOG_UNCOND (Simulator::Now ().GetSeconds () << "\t" << newCwnd);
- *stream->GetStream () << Simulator::Now ().GetSeconds () << "\t" << oldCwnd << "\t" << newCwnd << std::endl;
- }
-
- static void
- RxDrop (Ptr<PcapFileWrapper> file, Ptr<const Packet> p)
- {
- NS_LOG_UNCOND ("RxDrop at " << Simulator::Now ().GetSeconds ());
- file->Write(Simulator::Now(), p);
- }
-@end verbatim
-
-We have added a ``stream'' parameter to the @code{CwndChange} trace sink.
-This is an object that holds (keeps safely alive) a C++ output stream. It
-turns out that this is a very simple object, but one that manages lifetime
-issues for the stream and solves a problem that even experienced C++ users
-run into. It turns out that the copy constructor for ostream is marked
-private. This means that ostreams do not obey value semantics and cannot
-be used in any mechanism that requires the stream to be copied. This includes
-the @command{ns-3} callback system, which as you may recall, requires objects
-that obey value semantics. Further notice that we have added the following
-line in the @code{CwndChange} trace sink implementation:
-
-@verbatim
- *stream->GetStream () << Simulator::Now ().GetSeconds () << "\t" << oldCwnd << "\t" << newCwnd << std::endl;
-@end verbatim
-
-This would be very familiar code if you replaced @code{*stream->GetStream ()}
-with @code{std::cout}, as in:
-
-@verbatim
- std::cout << Simulator::Now ().GetSeconds () << "\t" << oldCwnd << "\t" << newCwnd << std::endl;
-@end verbatim
-
-This illustrates that the @code{Ptr<OutputStreamWrapper>} is really just
-carrying around a @code{std::ofstream} for you, and you can use it here like
-any other output stream.
-
-A similar situation happens in @code{RxDrop} except that the object being
-passed around (a @code{Ptr<PcapFileWrapper>}) represents a pcap file. There
-is a one-liner in the trace sink to write a timestamp and the contents of the
-packet being dropped to the pcap file:
-
-@verbatim
- file->Write(Simulator::Now(), p);
-@end verbatim
-
-Of course, if we have objects representing the two files, we need to create
-them somewhere and also cause them to be passed to the trace sinks. If you
-look in the @code{main} function, you will find new code to do just that:
-
-@verbatim
- AsciiTraceHelper asciiTraceHelper;
- Ptr<OutputStreamWrapper> stream = asciiTraceHelper.CreateFileStream ("sixth.cwnd");
- ns3TcpSocket->TraceConnectWithoutContext ("CongestionWindow", MakeBoundCallback (&CwndChange, stream));
-
- ...
-
- PcapHelper pcapHelper;
- Ptr<PcapFileWrapper> file = pcapHelper.CreateFile ("sixth.pcap", std::ios::out, PcapHelper::DLT_PPP);
- devices.Get (1)->TraceConnectWithoutContext("PhyRxDrop", MakeBoundCallback (&RxDrop, file));
-@end verbatim
-
-In the first section of the code snippet above, we are creating the ASCII
-trace file, creating an object responsible for managing it and using a
-variant of the callback creation function to arrange for the object to be
-passed to the sink. Our ASCII trace helpers provide a rich set of
-functions to make using text (ASCII) files easy. We are just going to
-illustrate the use of the file stream creation function here.
-
-The @code{CreateFileStream{}} function is basically going to instantiate
-a std::ofstream object and create a new file (or truncate an existing file).
-This ofstream is packaged up in an @code{ns-3} object for lifetime management
-and copy constructor issue resolution.
-
-We then take this @code{ns-3} object representing the file and pass it to
-@code{MakeBoundCallback()}. This function creates a callback just like
-@code{MakeCallback()}, but it ``binds'' a new value to the callback. This
-value is added to the callback before it is called.
-
-Essentially, @code{MakeBoundCallback(&CwndChange, stream)} causes the trace
-source to add the additional ``stream'' parameter to the front of the formal
-parameter list before invoking the callback. This changes the required
-signature of the @code{CwndChange} sink to match the one shown above, which
-includes the ``extra'' parameter @code{Ptr<OutputStreamWrapper> stream}.
-
-In the second section of code in the snippet above, we instantiate a
-@code{PcapHelper} to do the same thing for our pcap trace file that we did
-with the @code{AsciiTraceHelper}. The line of code,
-
-@verbatim
- Ptr<PcapFileWrapper> file = pcapHelper.CreateFile ("sixth.pcap", "w", PcapHelper::DLT_PPP);
-@end verbatim
-
-creates a pcap file named ``sixth.pcap'' with file mode ``w''. This means that
-the new file is to truncated if an existing file with that name is found. The
-final parameter is the ``data link type'' of the new pcap file. These are
-the same as the pcap library data link types defined in @code{bpf.h} if you are
-familar with pcap. In this case, @code{DLT_PPP} indicates that the pcap file
-is going to contain packets prefixed with point to point headers. This is true
-since the packets are coming from our point-to-point device driver. Other
-common data link types are DLT_EN10MB (10 MB Ethernet) appropriate for csma
-devices and DLT_IEEE802_11 (IEEE 802.11) appropriate for wifi devices. These
-are defined in @code{src/helper/trace-helper.h"} if you are interested in seeing
-the list. The entries in the list match those in @code{bpf.h} but we duplicate
-them to avoid a pcap source dependence.
-
-A @code{ns-3} object representing the pcap file is returned from @code{CreateFile}
-and used in a bound callback exactly as it was in the ascii case.
-
-An important detour: It is important to notice that even though both of these
-objects are declared in very similar ways,
-
-@verbatim
- Ptr<PcapFileWrapper> file ...
- Ptr<OutputStreamWrapper> stream ...
-@end verbatim
-
-The underlying objects are entirely different. For example, the
-Ptr<PcapFileWrapper> is a smart pointer to an @command{ns-3} Object that is a
-fairly heaviweight thing that supports @code{Attributes} and is integrated into
-the config system. The Ptr<OutputStreamWrapper>, on the other hand, is a smart
-pointer to a reference counted object that is a very lightweight thing.
-Remember to always look at the object you are referencing before making any
-assumptions about the ``powers'' that object may have.
-
-For example, take a look at @code{src/common/pcap-file-object.h} in the
-distribution and notice,
-
-@verbatim
- class PcapFileWrapper : public Object
-@end verbatim
-
-that class @code{PcapFileWrapper} is an @command{ns-3} Object by virtue of
-its inheritance. Then look at @code{src/common/output-stream-wrapper.h} and
-notice,
-
-@verbatim
- class OutputStreamWrapper : public SimpleRefCount<OutputStreamWrapper>
-@end verbatim
-
-that this object is not an @command{ns-3} Object at all, it is ``merely'' a
-C++ object that happens to support intrusive reference counting.
-
-The point here is that just because you read Ptr<something> it does not necessarily
-mean that ``something'' is an @command{ns-3} Object on which you can hang @command{ns-3}
-@code{Attributes}, for example.
-
-Now, back to the example. If you now build and run this example,
-
-@verbatim
- ./waf --run sixth
-@end verbatim
-
-you will see the same messages appear as when you ran ``fifth'', but two new
-files will appear in the top-level directory of your @code{ns-3} distribution.
-
-@verbatim
- sixth.cwnd sixth.pcap
-@end verbatim
-
-Since ``sixth.cwnd'' is an ASCII text file, you can view it with @code{cat}
-or your favorite file viewer.
-
-@verbatim
- 1.20919 536 1072
- 1.21511 1072 1608
- ...
- 9.30922 8893 8925
- 9.31754 8925 8957
-@end verbatim
-
-You have a tab separated file with a timestamp, an old congestion window and a
-new congestion window suitable for directly importing into your plot program.
-There are no extraneous prints in the file, no parsing or editing is required.
-
-Since ``sixth.pcap'' is a pcap file, you can fiew it with @code{tcpdump}.
-
-@verbatim
- reading from file ../../sixth.pcap, link-type PPP (PPP)
- 1.251507 IP 10.1.1.1.49153 > 10.1.1.2.8080: . 17689:18225(536) ack 1 win 65535
- 1.411478 IP 10.1.1.1.49153 > 10.1.1.2.8080: . 33808:34312(504) ack 1 win 65535
- ...
- 7.393557 IP 10.1.1.1.49153 > 10.1.1.2.8080: . 781568:782072(504) ack 1 win 65535
- 8.141483 IP 10.1.1.1.49153 > 10.1.1.2.8080: . 874632:875168(536) ack 1 win 65535
-@end verbatim
-
-You have a pcap file with the packets that were dropped in the simulation. There
-are no other packets present in the file and there is nothing else present to
-make life difficult.
-
-It's been a long journey, but we are now at a point where we can appreciate the
-@code{ns-3} tracing system. We have pulled important events out of the middle
-of a TCP implementation and a device driver. We stored those events directly in
-files usable with commonly known tools. We did this without modifying any of the
-core code involved, and we did this in only 18 lines of code:
-
-@verbatim
- static void
- CwndChange (Ptr<OutputStreamWrapper> stream, uint32_t oldCwnd, uint32_t newCwnd)
- {
- NS_LOG_UNCOND (Simulator::Now ().GetSeconds () << "\t" << newCwnd);
- *stream->GetStream () << Simulator::Now ().GetSeconds () << "\t" << oldCwnd << "\t" << newCwnd << std::endl;
- }
-
- ...
-
- AsciiTraceHelper asciiTraceHelper;
- Ptr<OutputStreamWrapper> stream = asciiTraceHelper.CreateFileStream ("sixth.cwnd");
- ns3TcpSocket->TraceConnectWithoutContext ("CongestionWindow", MakeBoundCallback (&CwndChange, stream));
-
- ...
-
- static void
- RxDrop (Ptr<PcapFileWrapper> file, Ptr<const Packet> p)
- {
- NS_LOG_UNCOND ("RxDrop at " << Simulator::Now ().GetSeconds ());
- file->Write(Simulator::Now(), p);
- }
-
- ...
-
- PcapHelper pcapHelper;
- Ptr<PcapFileWrapper> file = pcapHelper.CreateFile ("sixth.pcap", "w", PcapHelper::DLT_PPP);
- devices.Get (1)->TraceConnectWithoutContext("PhyRxDrop", MakeBoundCallback (&RxDrop, file));
-@end verbatim
-
-@c ============================================================================
-@c Using Trace Helpers
-@c ============================================================================
-@node Using Trace Helpers
-@section Using Trace Helpers
-
-The @code{ns-3} trace helpers provide a rich environment for configuring and
-selecting different trace events and writing them to files. In previous
-sections, primarily ``Building Topologies,'' we have seen several varieties
-of the trace helper methods designed for use inside other (device) helpers.
-
-Perhaps you will recall seeing some of these variations:
-
-@verbatim
- pointToPoint.EnablePcapAll ("second");
- pointToPoint.EnablePcap ("second", p2pNodes.Get (0)->GetId (), 0);
- csma.EnablePcap ("third", csmaDevices.Get (0), true);
- pointToPoint.EnableAsciiAll (ascii.CreateFileStream ("myfirst.tr"));
-@end verbatim
-
-What may not be obvious, though, is that there is a consistent model for all of
-the trace-related methods found in the system. We will now take a little time
-and take a look at the ``big picture''.
-
-There are currently two primary use cases of the tracing helpers in @code{ns-3}:
-Device helpers and protocol helpers. Device helpers look at the problem
-of specifying which traces should be enabled through a node, device pair. For
-example, you may want to specify that pcap tracing should be enabled on a
-particular device on a specific node. This follows from the @code{ns-3} device
-conceptual model, and also the conceptual models of the various device helpers.
-Following naturally from this, the files created follow a
-<prefix>-<node>-<device> naming convention.
-
-Protocol helpers look at the problem of specifying which traces should be
-enabled through a protocol and interface pair. This follows from the @code{ns-3}
-protocol stack conceptual model, and also the conceptual models of internet
-stack helpers. Naturally, the trace files should follow a
-<prefix>-<protocol>-<interface> naming convention.
-
-The trace helpers therefore fall naturally into a two-dimensional taxonomy.
-There are subtleties that prevent all four classes from behaving identically,
-but we do strive to make them all work as similarly as possible; and whenever
-possible there are analogs for all methods in all classes.
-
-@verbatim
- | pcap | ascii |
- -----------------+------+-------|
- Device Helper | | |
- -----------------+------+-------|
- Protocol Helper | | |
- -----------------+------+-------|
-@end verbatim
-
-We use an approach called a @code{mixin} to add tracing functionality to our
-helper classes. A @code{mixin} is a class that provides functionality to that
-is inherited by a subclass. Inheriting from a mixin is not considered a form
-of specialization but is really a way to collect functionality.
-
-Let's take a quick look at all four of these cases and their respective
-@code{mixins}.
-
-@subsection Pcap Tracing Device Helpers
-
-The goal of these helpers is to make it easy to add a consistent pcap trace
-facility to an @code{ns-3} device. We want all of the various flavors of
-pcap tracing to work the same across all devices, so the methods of these
-helpers are inherited by device helpers. Take a look at
-@code{src/helper/trace-helper.h} if you want to follow the discussion while
-looking at real code.
-
-The class @code{PcapHelperForDevice} is a @code{mixin} provides the high level
-functionality for using pcap tracing in an @code{ns-3} device. Every device
-must implement a single virtual method inherited from this class.
-
-@verbatim
- virtual void EnablePcapInternal (std::string prefix, Ptr<NetDevice> nd, bool promiscuous, bool explicitFilename) = 0;
-@end verbatim
-
-The signature of this method reflects the device-centric view of the situation
-at this level. All of the public methods inherited from class
-2@code{PcapUserHelperForDevice} reduce to calling this single device-dependent
-implementation method. For example, the lowest level pcap method,
-
-@verbatim
- void EnablePcap (std::string prefix, Ptr<NetDevice> nd, bool promiscuous = false, bool explicitFilename = false);
-@end verbatim
-
-will call the device implementation of @code{EnablePcapInternal} directly. All
-other public pcap tracing methods build on this implementation to provide
-additional user-level functionality. What this means to the user is that all
-device helpers in the system will have all of the pcap trace methods available;
-and these methods will all work in the same way across devices if the device
-implements @code{EnablePcapInternal} correctly.
-
-@subsubsection Pcap Tracing Device Helper Methods
-
-@verbatim
- void EnablePcap (std::string prefix, Ptr<NetDevice> nd, bool promiscuous = false, bool explicitFilename = false);
- void EnablePcap (std::string prefix, std::string ndName, bool promiscuous = false, bool explicitFilename = false);
- void EnablePcap (std::string prefix, NetDeviceContainer d, bool promiscuous = false);
- void EnablePcap (std::string prefix, NodeContainer n, bool promiscuous = false);
- void EnablePcap (std::string prefix, uint32_t nodeid, uint32_t deviceid, bool promiscuous = false);
- void EnablePcapAll (std::string prefix, bool promiscuous = false);
-@end verbatim
-
-In each of the methods shown above, there is a default parameter called
-@code{promiscuous} that defaults to false. This parameter indicates that the
-trace should not be gathered in promiscuous mode. If you do want your traces
-to include all traffic seen by the device (and if the device supports a
-promiscuous mode) simply add a true parameter to any of the calls above. For example,
-
-@verbatim
- Ptr<NetDevice> nd;
- ...
- helper.EnablePcap ("prefix", nd, true);
-@end verbatim
-
-will enable promiscuous mode captures on the @code{NetDevice} specified by @code{nd}.
-
-The first two methods also include a default parameter called @code{explicitFilename}
-that will be discussed below.
-
-You are encouraged to peruse the Doxygen for class @code{PcapHelperForDevice}
-to find the details of these methods; but to summarize ...
-
-You can enable pcap tracing on a particular node/net-device pair by providing a
-@code{Ptr<NetDevice>} to an @code{EnablePcap} method. The @code{Ptr<Node>} is
-implicit since the net device must belong to exactly one @code{Node}.
-For example,
-
-@verbatim
- Ptr<NetDevice> nd;
- ...
- helper.EnablePcap ("prefix", nd);
-@end verbatim
-
-You can enable pcap tracing on a particular node/net-device pair by providing a
-@code{std::string} representing an object name service string to an
-@code{EnablePcap} method. The @code{Ptr<NetDevice>} is looked up from the name
-string. Again, the @code<Node> is implicit since the named net device must
-belong to exactly one @code{Node}. For example,
-
-@verbatim
- Names::Add ("server" ...);
- Names::Add ("server/eth0" ...);
- ...
- helper.EnablePcap ("prefix", "server/ath0");
-@end verbatim
-
-You can enable pcap tracing on a collection of node/net-device pairs by
-providing a @code{NetDeviceContainer}. For each @code{NetDevice} in the container
-the type is checked. For each device of the proper type (the same type as is
-managed by the device helper), tracing is enabled. Again, the @code<Node> is
-implicit since the found net device must belong to exactly one @code{Node}.
-For example,
-
-@verbatim
- NetDeviceContainer d = ...;
- ...
- helper.EnablePcap ("prefix", d);
-@end verbatim
-
-You can enable pcap tracing on a collection of node/net-device pairs by
-providing a @code{NodeContainer}. For each @code{Node} in the @code{NodeContainer}
-its attached @code{NetDevices} are iterated. For each @code{NetDevice} attached
-to each node in the container, the type of that device is checked. For each
-device of the proper type (the same type as is managed by the device helper),
-tracing is enabled.
-
-@verbatim
- NodeContainer n;
- ...
- helper.EnablePcap ("prefix", n);
-@end verbatim
-
-You can enable pcap tracing on the basis of node ID and device ID as well as
-with explicit @code{Ptr}. Each @code{Node} in the system has an integer node ID
-and each device connected to a node has an integer device ID.
-
-@verbatim
- helper.EnablePcap ("prefix", 21, 1);
-@end verbatim
-
-Finally, you can enable pcap tracing for all devices in the system, with the
-same type as that managed by the device helper.
-
-@verbatim
- helper.EnablePcapAll ("prefix");
-@end verbatim
-
-@subsubsection Pcap Tracing Device Helper Filename Selection
-
-Implicit in the method descriptions above is the construction of a complete
-filename by the implementation method. By convention, pcap traces in the
-@code{ns-3} system are of the form ``<prefix>-<node id>-<device id>.pcap''
-
-As previously mentioned, every node in the system will have a system-assigned
-node id; and every device will have an interface index (also called a device id)
-relative to its node. By default, then, a pcap trace file created as a result
-of enabling tracing on the first device of node 21 using the prefix ``prefix''
-would be ``prefix-21-1.pcap''.
-
-You can always use the @code{ns-3} object name service to make this more clear.
-For example, if you use the object name service to assign the name ``server''
-to node 21, the resulting pcap trace file name will automatically become,
-``prefix-server-1.pcap'' and if you also assign the name ``eth0'' to the
-device, your pcap file name will automatically pick this up and be called
-``prefix-server-eth0.pcap''.
-
-Finally, two of the methods shown above,
-
-@verbatim
- void EnablePcap (std::string prefix, Ptr<NetDevice> nd, bool promiscuous = false, bool explicitFilename = false);
- void EnablePcap (std::string prefix, std::string ndName, bool promiscuous = false, bool explicitFilename = false);
-@end verbatim
-
-have a default parameter called @code{explicitFilename}. When set to true,
-this parameter disables the automatic filename completion mechanism and allows
-you to create an explicit filename. This option is only available in the
-methods which enable pcap tracing on a single device.
-
-For example, in order to arrange for a device helper to create a single
-promiscuous pcap capture file of a specific name (``my-pcap-file.pcap'') on a
-given device, one could:
-
-@verbatim
- Ptr<NetDevice> nd;
- ...
- helper.EnablePcap ("my-pcap-file.pcap", nd, true, true);
-@end verbatim
-
-The first @code{true} parameter enables promiscuous mode traces and the second
-tells the helper to interpret the @code{prefix} parameter as a complete filename.
-
-@subsection Ascii Tracing Device Helpers
-
-The behavior of the ascii trace helper @code{mixin} is substantially similar to
-the pcap version. Take a look at @code{src/helper/trace-helper.h} if you want to
-follow the discussion while looking at real code.
-
-The class @code{AsciiTraceHelperForDevice} adds the high level functionality for
-using ascii tracing to a device helper class. As in the pcap case, every device
-must implement a single virtual method inherited from the ascii trace @code{mixin}.
-
-@verbatim
- virtual void EnableAsciiInternal (Ptr<OutputStreamWrapper> stream,
- std::string prefix,
- Ptr<NetDevice> nd,
- bool explicitFilename) = 0;
-
-@end verbatim
-
-The signature of this method reflects the device-centric view of the situation
-at this level; and also the fact that the helper may be writing to a shared
-output stream. All of the public ascii-trace-related methods inherited from
-class @code{AsciiTraceHelperForDevice} reduce to calling this single device-
-dependent implementation method. For example, the lowest level ascii trace
-methods,
-
-@verbatim
- void EnableAscii (std::string prefix, Ptr<NetDevice> nd, bool explicitFilename = false);
- void EnableAscii (Ptr<OutputStreamWrapper> stream, Ptr<NetDevice> nd);
-@verbatim
-
-will call the device implementation of @code{EnableAsciiInternal} directly,
-providing either a valid prefix or stream. All other public ascii tracing
-methods will build on these low-level functions to provide additional user-level
-functionality. What this means to the user is that all device helpers in the
-system will have all of the ascii trace methods available; and these methods
-will all work in the same way across devices if the devices implement
-@code{EnablAsciiInternal} correctly.
-
-@subsubsection Ascii Tracing Device Helper Methods
-
-@verbatim
- void EnableAscii (std::string prefix, Ptr<NetDevice> nd, bool explicitFilename = false);
- void EnableAscii (Ptr<OutputStreamWrapper> stream, Ptr<NetDevice> nd);
-
- void EnableAscii (std::string prefix, std::string ndName, bool explicitFilename = false);
- void EnableAscii (Ptr<OutputStreamWrapper> stream, std::string ndName);
-
- void EnableAscii (std::string prefix, NetDeviceContainer d);
- void EnableAscii (Ptr<OutputStreamWrapper> stream, NetDeviceContainer d);
-
- void EnableAscii (std::string prefix, NodeContainer n);
- void EnableAscii (Ptr<OutputStreamWrapper> stream, NodeContainer n);
-
- void EnableAsciiAll (std::string prefix);
- void EnableAsciiAll (Ptr<OutputStreamWrapper> stream);
-
- void EnableAscii (std::string prefix, uint32_t nodeid, uint32_t deviceid, bool explicitFilename);
- void EnableAscii (Ptr<OutputStreamWrapper> stream, uint32_t nodeid, uint32_t deviceid);
-@end verbatim
-
-You are encouraged to peruse the Doxygen for class @code{TraceHelperForDevice}
-to find the details of these methods; but to summarize ...
-
-There are twice as many methods available for ascii tracing as there were for
-pcap tracing. This is because, in addition to the pcap-style model where traces
-from each unique node/device pair are written to a unique file, we support a model
-in which trace information for many node/device pairs is written to a common file.
-This means that the <prefix>-<node>-<device> file name generation mechanism is
-replaced by a mechanism to refer to a common file; and the number of API methods
-is doubled to allow all combinations.
-
-Just as in pcap tracing, you can enable ascii tracing on a particular
-node/net-device pair by providing a @code{Ptr<NetDevice>} to an @code{EnableAscii}
-method. The @code{Ptr<Node>} is implicit since the net device must belong to
-exactly one @code{Node}. For example,
-
-@verbatim
- Ptr<NetDevice> nd;
- ...
- helper.EnableAscii ("prefix", nd);
-@end verbatim
-
-The first four methods also include a default parameter called @code{explicitFilename}
-that operate similar to equivalent parameters in the pcap case.
-
-In this case, no trace contexts are written to the ascii trace file since they
-would be redundant. The system will pick the file name to be created using
-the same rules as described in the pcap section, except that the file will
-have the suffix ``.tr'' instead of ``.pcap''.
-
-If you want to enable ascii tracing on more than one net device and have all
-traces sent to a single file, you can do that as well by using an object to
-refer to a single file. We have already seen this in the ``cwnd'' example
-above:
-
-@verbatim
- Ptr<NetDevice> nd1;
- Ptr<NetDevice> nd2;
- ...
- Ptr<OutputStreamWrapper> stream = asciiTraceHelper.CreateFileStream ("trace-file-name.tr");
- ...
- helper.EnableAscii (stream, nd1);
- helper.EnableAscii (stream, nd2);
-@verbatim
-
-In this case, trace contexts are written to the ascii trace file since they
-are required to disambiguate traces from the two devices. Note that since the
-user is completely specifying the file name, the string should include the ``,tr''
-for consistency.
-
-You can enable ascii tracing on a particular node/net-device pair by providing a
-@code{std::string} representing an object name service string to an
-@code{EnablePcap} method. The @code{Ptr<NetDevice>} is looked up from the name
-string. Again, the @code<Node> is implicit since the named net device must
-belong to exactly one @code{Node}. For example,
-
-@verbatim
- Names::Add ("client" ...);
- Names::Add ("client/eth0" ...);
- Names::Add ("server" ...);
- Names::Add ("server/eth0" ...);
- ...
- helper.EnableAscii ("prefix", "client/eth0");
- helper.EnableAscii ("prefix", "server/eth0");
-@end verbatim
-
-This would result in two files named ``prefix-client-eth0.tr'' and
-``prefix-server-eth0.tr'' with traces for each device in the respective trace
-file. Since all of the EnableAscii functions are overloaded to take a stream wrapper,
-you can use that form as well:
-
-@verbatim
- Names::Add ("client" ...);
- Names::Add ("client/eth0" ...);
- Names::Add ("server" ...);
- Names::Add ("server/eth0" ...);
- ...
- Ptr<OutputStreamWrapper> stream = asciiTraceHelper.CreateFileStream ("trace-file-name.tr");
- ...
- helper.EnableAscii (stream, "client/eth0");
- helper.EnableAscii (stream, "server/eth0");
-@end verbatim
-
-This would result in a single trace file called ``trace-file-name.tr'' that
-contains all of the trace events for both devices. The events would be
-disambiguated by trace context strings.
-
-You can enable ascii tracing on a collection of node/net-device pairs by
-providing a @code{NetDeviceContainer}. For each @code{NetDevice} in the container
-the type is checked. For each device of the proper type (the same type as is
-managed by the device helper), tracing is enabled. Again, the @code<Node> is
-implicit since the found net device must belong to exactly one @code{Node}.
-For example,
-
-@verbatim
- NetDeviceContainer d = ...;
- ...
- helper.EnableAscii ("prefix", d);
-@end verbatim
-
-This would result in a number of ascii trace files being created, each of which
-follows the <prefix>-<node id>-<device id>.tr convention. Combining all of the
-traces into a single file is accomplished similarly to the examples above:
-
-@verbatim
- NetDeviceContainer d = ...;
- ...
- Ptr<OutputStreamWrapper> stream = asciiTraceHelper.CreateFileStream ("trace-file-name.tr");
- ...
- helper.EnableAscii (stream, d);
-@end verbatim
-
-You can enable ascii tracing on a collection of node/net-device pairs by
-providing a @code{NodeContainer}. For each @code{Node} in the @code{NodeContainer}
-its attached @code{NetDevices} are iterated. For each @code{NetDevice} attached
-to each node in the container, the type of that device is checked. For each
-device of the proper type (the same type as is managed by the device helper),
-tracing is enabled.
-
-@verbatim
- NodeContainer n;
- ...
- helper.EnableAscii ("prefix", n);
-@end verbatim
-
-This would result in a number of ascii trace files being created, each of which
-follows the <prefix>-<node id>-<device id>.tr convention. Combining all of the
-traces into a single file is accomplished similarly to the examples above:
-
-You can enable pcap tracing on the basis of node ID and device ID as well as
-with explicit @code{Ptr}. Each @code{Node} in the system has an integer node ID
-and each device connected to a node has an integer device ID.
-
-@verbatim
- helper.EnableAscii ("prefix", 21, 1);
-@end verbatim
-
-Of course, the traces can be combined into a single file as shown above.
-
-Finally, you can enable pcap tracing for all devices in the system, with the
-same type as that managed by the device helper.
-
-@verbatim
- helper.EnableAsciiAll ("prefix");
-@end verbatim
-
-This would result in a number of ascii trace files being created, one for
-every device in the system of the type managed by the helper. All of these
-files will follow the <prefix>-<node id>-<device id>.tr convention. Combining
-all of the traces into a single file is accomplished similarly to the examples
-above.
-
-@subsubsection Ascii Tracing Device Helper Filename Selection
-
-Implicit in the prefix-style method descriptions above is the construction of the
-complete filenames by the implementation method. By convention, ascii traces
-in the @code{ns-3} system are of the form ``<prefix>-<node id>-<device id>.tr''
-
-As previously mentioned, every node in the system will have a system-assigned
-node id; and every device will have an interface index (also called a device id)
-relative to its node. By default, then, an ascii trace file created as a result
-of enabling tracing on the first device of node 21, using the prefix ``prefix'',
-would be ``prefix-21-1.tr''.
-
-You can always use the @code{ns-3} object name service to make this more clear.
-For example, if you use the object name service to assign the name ``server''
-to node 21, the resulting ascii trace file name will automatically become,
-``prefix-server-1.tr'' and if you also assign the name ``eth0'' to the
-device, your ascii trace file name will automatically pick this up and be called
-``prefix-server-eth0.tr''.
-
-Several of the methods have a default parameter called @code{explicitFilename}.
-When set to true, this parameter disables the automatic filename completion
-mechanism and allows you to create an explicit filename. This option is only
-available in the methods which take a prefix and enable tracing on a single device.
-
-@subsection Pcap Tracing Protocol Helpers
-
-The goal of these @code{mixins} is to make it easy to add a consistent pcap trace
-facility to protocols. We want all of the various flavors of pcap tracing to
-work the same across all protocols, so the methods of these helpers are
-inherited by stack helpers. Take a look at @code{src/helper/trace-helper.h}
-if you want to follow the discussion while looking at real code.
-
-In this section we will be illustrating the methods as applied to the protocol
-@code{Ipv4}. To specify traces in similar protocols, just substitute the
-appropriate type. For example, use a @code{Ptr<Ipv6>} instead of a
-@code{Ptr<Ipv4>} and call @code{EnablePcapIpv6} instead of @code{EnablePcapIpv4}.
-
-The class @code{PcapHelperForIpv4} provides the high level functionality for
-using pcap tracing in the @code{Ipv4} protocol. Each protocol helper enabling these
-methods must implement a single virtual method inherited from this class. There
-will be a separate implementation for @code{Ipv6}, for example, but the only
-difference will be in the method names and signatures. Different method names
-are required to disambiguate class @code{Ipv4} from @code{Ipv6} which are both
-derived from class @code{Object}, and methods that share the same signature.
-
-@verbatim
- virtual void EnablePcapIpv4Internal (std::string prefix,
- Ptr<Ipv4> ipv4,
- uint32_t interface,
- bool explicitFilename) = 0;
-@end verbatim
-
-The signature of this method reflects the protocol and interface-centric view
-of the situation at this level. All of the public methods inherited from class
-@code{PcapHelperForIpv4} reduce to calling this single device-dependent
-implementation method. For example, the lowest level pcap method,
-
-@verbatim
- void EnablePcapIpv4 (std::string prefix, Ptr<Ipv4> ipv4, uint32_t interface, bool explicitFilename = false);
-@verbatim
-
-will call the device implementation of @code{EnablePcapIpv4Internal} directly.
-All other public pcap tracing methods build on this implementation to provide
-additional user-level functionality. What this means to the user is that all
-protocol helpers in the system will have all of the pcap trace methods
-available; and these methods will all work in the same way across
-protocols if the helper implements @code{EnablePcapIpv4Internal} correctly.
-
-@subsubsection Pcap Tracing Protocol Helper Methods
-
-These methods are designed to be in one-to-one correspondence with the @code{Node}-
-and @code{NetDevice}- centric versions of the device versions. Instead of
-@code{Node} and @code{NetDevice} pair constraints, we use protocol and interface
-constraints.
-
-Note that just like in the device version, there are six methods:
-
-@verbatim
- void EnablePcapIpv4 (std::string prefix, Ptr<Ipv4> ipv4, uint32_t interface, bool explicitFilename = false);
- void EnablePcapIpv4 (std::string prefix, std::string ipv4Name, uint32_t interface, bool explicitFilename = false);
- void EnablePcapIpv4 (std::string prefix, Ipv4InterfaceContainer c);
- void EnablePcapIpv4 (std::string prefix, NodeContainer n);
- void EnablePcapIpv4 (std::string prefix, uint32_t nodeid, uint32_t interface, bool explicitFilename);
- void EnablePcapIpv4All (std::string prefix);
-@end verbatim
-
-You are encouraged to peruse the Doxygen for class @code{PcapHelperForIpv4}
-to find the details of these methods; but to summarize ...
-
-You can enable pcap tracing on a particular protocol/interface pair by providing a
-@code{Ptr<Ipv4>} and @code{interface} to an @code{EnablePcap} method. For example,
-
-@verbatim
- Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
- ...
- helper.EnablePcapIpv4 ("prefix", ipv4, 0);
-@end verbatim
-
-You can enable pcap tracing on a particular node/net-device pair by providing a
-@code{std::string} representing an object name service string to an
-@code{EnablePcap} method. The @code{Ptr<Ipv4>} is looked up from the name
-string. For example,
-
-@verbatim
- Names::Add ("serverIPv4" ...);
- ...
- helper.EnablePcapIpv4 ("prefix", "serverIpv4", 1);
-@end verbatim
-
-You can enable pcap tracing on a collection of protocol/interface pairs by
-providing an @code{Ipv4InterfaceContainer}. For each @code{Ipv4} / interface
-pair in the container the protocol type is checked. For each protocol of the
-proper type (the same type as is managed by the device helper), tracing is
-enabled for the corresponding interface. For example,
-
-@verbatim
- NodeContainer nodes;
- ...
- NetDeviceContainer devices = deviceHelper.Install (nodes);
- ...
- Ipv4AddressHelper ipv4;
- ipv4.SetBase ("10.1.1.0", "255.255.255.0");
- Ipv4InterfaceContainer interfaces = ipv4.Assign (devices);
- ...
- helper.EnablePcapIpv4 ("prefix", interfaces);
-@end verbatim
-
-You can enable pcap tracing on a collection of protocol/interface pairs by
-providing a @code{NodeContainer}. For each @code{Node} in the @code{NodeContainer}
-the appropriate protocol is found. For each protocol, its interfaces are
-enumerated and tracing is enabled on the resulting pairs. For example,
-
-@verbatim
- NodeContainer n;
- ...
- helper.EnablePcapIpv4 ("prefix", n);
-@end verbatim
-
-You can enable pcap tracing on the basis of node ID and interface as well. In
-this case, the node-id is translated to a @code{Ptr<Node>} and the appropriate
-protocol is looked up in the node. The resulting protocol and interface are
-used to specify the resulting trace source.
-
-@verbatim
- helper.EnablePcapIpv4 ("prefix", 21, 1);
-@end verbatim
-
-Finally, you can enable pcap tracing for all interfaces in the system, with
-associated protocol being the same type as that managed by the device helper.
-
-@verbatim
- helper.EnablePcapIpv4All ("prefix");
-@end verbatim
-
-@subsubsection Pcap Tracing Protocol Helper Filename Selection
-
-Implicit in all of the method descriptions above is the construction of the
-complete filenames by the implementation method. By convention, pcap traces
-taken for devices in the @code{ns-3} system are of the form
-``<prefix>-<node id>-<device id>.pcap''. In the case of protocol traces,
-there is a one-to-one correspondence between protocols and @code{Nodes}.
-This is because protocol @code{Objects} are aggregated to @code{Node Objects}.
-Since there is no global protocol id in the system, we use the corresponding
-node id in file naming. Therefore there is a possibility for file name
-collisions in automatically chosen trace file names. For this reason, the
-file name convention is changed for protocol traces.
-
-As previously mentioned, every node in the system will have a system-assigned
-node id. Since there is a one-to-one correspondence between protocol instances
-and node instances we use the node id. Each interface has an interface id
-relative to its protocol. We use the convention
-"<prefix>-n<node id>-i<interface id>.pcap" for trace file naming in protocol
-helpers.
-
-Therefore, by default, a pcap trace file created as a result of enabling tracing
-on interface 1 of the Ipv4 protocol of node 21 using the prefix ``prefix''
-would be ``prefix-n21-i1.pcap''.
-
-You can always use the @code{ns-3} object name service to make this more clear.
-For example, if you use the object name service to assign the name ``serverIpv4''
-to the Ptr<Ipv4> on node 21, the resulting pcap trace file name will
-automatically become, ``prefix-nserverIpv4-i1.pcap''.
-
-Several of the methods have a default parameter called @code{explicitFilename}.
-When set to true, this parameter disables the automatic filename completion
-mechanism and allows you to create an explicit filename. This option is only
-available in the methods which take a prefix and enable tracing on a single device.
-
-@subsection Ascii Tracing Protocol Helpers
-
-The behavior of the ascii trace helpers is substantially similar to the pcap
-case. Take a look at @code{src/helper/trace-helper.h} if you want to
-follow the discussion while looking at real code.
-
-In this section we will be illustrating the methods as applied to the protocol
-@code{Ipv4}. To specify traces in similar protocols, just substitute the
-appropriate type. For example, use a @code{Ptr<Ipv6>} instead of a
-@code{Ptr<Ipv4>} and call @code{EnableAsciiIpv6} instead of @code{EnableAsciiIpv4}.
-
-The class @code{AsciiTraceHelperForIpv4} adds the high level functionality
-for using ascii tracing to a protocol helper. Each protocol that enables these
-methods must implement a single virtual method inherited from this class.
-
-@verbatim
- virtual void EnableAsciiIpv4Internal (Ptr<OutputStreamWrapper> stream,
- std::string prefix,
- Ptr<Ipv4> ipv4,
- uint32_t interface,
- bool explicitFilename) = 0;
-@end verbatim
-
-The signature of this method reflects the protocol- and interface-centric view
-of the situation at this level; and also the fact that the helper may be writing
-to a shared output stream. All of the public methods inherited from class
-@code{PcapAndAsciiTraceHelperForIpv4} reduce to calling this single device-
-dependent implementation method. For example, the lowest level ascii trace
-methods,
-
-@verbatim
- void EnableAsciiIpv4 (std::string prefix, Ptr<Ipv4> ipv4, uint32_t interface, bool explicitFilename = false);
- void EnableAsciiIpv4 (Ptr<OutputStreamWrapper> stream, Ptr<Ipv4> ipv4, uint32_t interface);
-@verbatim
-
-will call the device implementation of @code{EnableAsciiIpv4Internal} directly,
-providing either the prefix or the stream. All other public ascii tracing
-methods will build on these low-level functions to provide additional user-level
-functionality. What this means to the user is that all device helpers in the
-system will have all of the ascii trace methods available; and these methods
-will all work in the same way across protocols if the protocols implement
-@code{EnablAsciiIpv4Internal} correctly.
-
-@subsubsection Ascii Tracing Protocol Helper Methods
-
-@verbatim
- void EnableAsciiIpv4 (std::string prefix, Ptr<Ipv4> ipv4, uint32_t interface, bool explicitFilename = false);
- void EnableAsciiIpv4 (Ptr<OutputStreamWrapper> stream, Ptr<Ipv4> ipv4, uint32_t interface);
-
- void EnableAsciiIpv4 (std::string prefix, std::string ipv4Name, uint32_t interface, bool explicitFilename = false);
- void EnableAsciiIpv4 (Ptr<OutputStreamWrapper> stream, std::string ipv4Name, uint32_t interface);
-
- void EnableAsciiIpv4 (std::string prefix, Ipv4InterfaceContainer c);
- void EnableAsciiIpv4 (Ptr<OutputStreamWrapper> stream, Ipv4InterfaceContainer c);
-
- void EnableAsciiIpv4 (std::string prefix, NodeContainer n);
- void EnableAsciiIpv4 (Ptr<OutputStreamWrapper> stream, NodeContainer n);
-
- void EnableAsciiIpv4All (std::string prefix);
- void EnableAsciiIpv4All (Ptr<OutputStreamWrapper> stream);
-
- void EnableAsciiIpv4 (std::string prefix, uint32_t nodeid, uint32_t deviceid, bool explicitFilename);
- void EnableAsciiIpv4 (Ptr<OutputStreamWrapper> stream, uint32_t nodeid, uint32_t interface);
-@end verbatim
-
-You are encouraged to peruse the Doxygen for class @code{PcapAndAsciiHelperForIpv4}
-to find the details of these methods; but to summarize ...
-
-There are twice as many methods available for ascii tracing as there were for
-pcap tracing. This is because, in addition to the pcap-style model where traces
-from each unique protocol/interface pair are written to a unique file, we
-support a model in which trace information for many protocol/interface pairs is
-written to a common file. This means that the <prefix>-n<node id>-<interface>
-file name generation mechanism is replaced by a mechanism to refer to a common
-file; and the number of API methods is doubled to allow all combinations.
-
-Just as in pcap tracing, you can enable ascii tracing on a particular
-protocol/interface pair by providing a @code{Ptr<Ipv4>} and an @code{interface}
-to an @code{EnableAscii} method.
-For example,
-
-@verbatim
- Ptr<Ipv4> ipv4;
- ...
- helper.EnableAsciiIpv4 ("prefix", ipv4, 1);
-@end verbatim
-
-In this case, no trace contexts are written to the ascii trace file since they
-would be redundant. The system will pick the file name to be created using
-the same rules as described in the pcap section, except that the file will
-have the suffix ``.tr'' instead of ``.pcap''.
-
-If you want to enable ascii tracing on more than one interface and have all
-traces sent to a single file, you can do that as well by using an object to
-refer to a single file. We have already something similar to this in the
-``cwnd'' example above:
-
-@verbatim
- Ptr<Ipv4> protocol1 = node1->GetObject<Ipv4> ();
- Ptr<Ipv4> protocol2 = node2->GetObject<Ipv4> ();
- ...
- Ptr<OutputStreamWrapper> stream = asciiTraceHelper.CreateFileStream ("trace-file-name.tr");
- ...
- helper.EnableAsciiIpv4 (stream, protocol1, 1);
- helper.EnableAsciiIpv4 (stream, protocol2, 1);
-@verbatim
-
-In this case, trace contexts are written to the ascii trace file since they
-are required to disambiguate traces from the two interfaces. Note that since
-the user is completely specifying the file name, the string should include the
-``,tr'' for consistency.
-
-You can enable ascii tracing on a particular protocol by providing a
-@code{std::string} representing an object name service string to an
-@code{EnablePcap} method. The @code{Ptr<Ipv4>} is looked up from the name
-string. The @code<Node> in the resulting filenames is implicit since there
-is a one-to-one correspondence between protocol instances and nodes,
-For example,
-
-@verbatim
- Names::Add ("node1Ipv4" ...);
- Names::Add ("node2Ipv4" ...);
- ...
- helper.EnableAsciiIpv4 ("prefix", "node1Ipv4", 1);
- helper.EnableAsciiIpv4 ("prefix", "node2Ipv4", 1);
-@end verbatim
-
-This would result in two files named ``prefix-nnode1Ipv4-i1.tr'' and
-``prefix-nnode2Ipv4-i1.tr'' with traces for each interface in the respective
-trace file. Since all of the EnableAscii functions are overloaded to take a
-stream wrapper, you can use that form as well:
-
-@verbatim
- Names::Add ("node1Ipv4" ...);
- Names::Add ("node2Ipv4" ...);
- ...
- Ptr<OutputStreamWrapper> stream = asciiTraceHelper.CreateFileStream ("trace-file-name.tr");
- ...
- helper.EnableAsciiIpv4 (stream, "node1Ipv4", 1);
- helper.EnableAsciiIpv4 (stream, "node2Ipv4", 1);
-@end verbatim
-
-This would result in a single trace file called ``trace-file-name.tr'' that
-contains all of the trace events for both interfaces. The events would be
-disambiguated by trace context strings.
-
-You can enable ascii tracing on a collection of protocol/interface pairs by
-providing an @code{Ipv4InterfaceContainer}. For each protocol of the proper
-type (the same type as is managed by the device helper), tracing is enabled
-for the corresponding interface. Again, the @code<Node> is implicit since
-there is a one-to-one correspondence between each protocol and its node.
-For example,
-
-@verbatim
- NodeContainer nodes;
- ...
- NetDeviceContainer devices = deviceHelper.Install (nodes);
- ...
- Ipv4AddressHelper ipv4;
- ipv4.SetBase ("10.1.1.0", "255.255.255.0");
- Ipv4InterfaceContainer interfaces = ipv4.Assign (devices);
- ...
- ...
- helper.EnableAsciiIpv4 ("prefix", interfaces);
-@end verbatim
-
-This would result in a number of ascii trace files being created, each of which
-follows the <prefix>-n<node id>-i<interface>.tr convention. Combining all of the
-traces into a single file is accomplished similarly to the examples above:
-
-@verbatim
- NodeContainer nodes;
- ...
- NetDeviceContainer devices = deviceHelper.Install (nodes);
- ...
- Ipv4AddressHelper ipv4;
- ipv4.SetBase ("10.1.1.0", "255.255.255.0");
- Ipv4InterfaceContainer interfaces = ipv4.Assign (devices);
- ...
- Ptr<OutputStreamWrapper> stream = asciiTraceHelper.CreateFileStream ("trace-file-name.tr");
- ...
- helper.EnableAsciiIpv4 (stream, interfaces);
-@end verbatim
-
-You can enable ascii tracing on a collection of protocol/interface pairs by
-providing a @code{NodeContainer}. For each @code{Node} in the @code{NodeContainer}
-the appropriate protocol is found. For each protocol, its interfaces are
-enumerated and tracing is enabled on the resulting pairs. For example,
-
-@verbatim
- NodeContainer n;
- ...
- helper.EnableAsciiIpv4 ("prefix", n);
-@end verbatim
-
-This would result in a number of ascii trace files being created, each of which
-follows the <prefix>-<node id>-<device id>.tr convention. Combining all of the
-traces into a single file is accomplished similarly to the examples above:
-
-You can enable pcap tracing on the basis of node ID and device ID as well. In
-this case, the node-id is translated to a @code{Ptr<Node>} and the appropriate
-protocol is looked up in the node. The resulting protocol and interface are
-used to specify the resulting trace source.
-
-@verbatim
- helper.EnableAsciiIpv4 ("prefix", 21, 1);
-@end verbatim
-
-Of course, the traces can be combined into a single file as shown above.
-
-Finally, you can enable ascii tracing for all interfaces in the system, with
-associated protocol being the same type as that managed by the device helper.
-
-@verbatim
- helper.EnableAsciiIpv4All ("prefix");
-@end verbatim
-
-This would result in a number of ascii trace files being created, one for
-every interface in the system related to a protocol of the type managed by the
-helper. All of these files will follow the <prefix>-n<node id>-i<interface.tr
-convention. Combining all of the traces into a single file is accomplished
-similarly to the examples above.
-
-@subsubsection Ascii Tracing Protocol Helper Filename Selection
-
-Implicit in the prefix-style method descriptions above is the construction of the
-complete filenames by the implementation method. By convention, ascii traces
-in the @code{ns-3} system are of the form ``<prefix>-<node id>-<device id>.tr''
-
-As previously mentioned, every node in the system will have a system-assigned
-node id. Since there is a one-to-one correspondence between protocols and nodes
-we use to node-id to identify the protocol identity. Every interface on a
-given protocol will have an interface index (also called simply an interface)
-relative to its protocol. By default, then, an ascii trace file created as a result
-of enabling tracing on the first device of node 21, using the prefix ``prefix'',
-would be ``prefix-n21-i1.tr''. Use the prefix to disambiguate multiple protocols
-per node.
-
-You can always use the @code{ns-3} object name service to make this more clear.
-For example, if you use the object name service to assign the name ``serverIpv4''
-to the protocol on node 21, and also specify interface one, the resulting ascii
-trace file name will automatically become, ``prefix-nserverIpv4-1.tr''.
-
-Several of the methods have a default parameter called @code{explicitFilename}.
-When set to true, this parameter disables the automatic filename completion
-mechanism and allows you to create an explicit filename. This option is only
-available in the methods which take a prefix and enable tracing on a single device.
-
-@c ============================================================================
-@c Summary
-@c ============================================================================
-@node Summary
-@section Summary
-
-@code{ns-3} includes an extremely rich environment allowing users at several
-levels to customize the kinds of information that can be extracted from
-simulations.
-
-There are high-level helper functions that allow users to simply control the
-collection of pre-defined outputs to a fine granularity. There are mid-level
-helper functions to allow more sophisticated users to customize how information
-is extracted and saved; and there are low-level core functions to allow expert
-users to alter the system to present new and previously unexported information
-in a way that will be immediately accessible to users at higher levels.
-
-This is a very comprehensive system, and we realize that it is a lot to
-digest, especially for new users or those not intimately familiar with C++
-and its idioms. We do consider the tracing system a very important part of
-@code{ns-3} and so recommend becoming as familiar as possible with it. It is
-probably the case that understanding the rest of the @code{ns-3} system will
-be quite simple once you have mastered the tracing system
--- a/doc/tutorial/tutorial.css Sun Jan 02 22:57:04 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,156 +0,0 @@
-body {
- font-family: "Trebuchet MS", "Bitstream Vera Sans", verdana, lucida, arial, helvetica, sans-serif;
- background: white;
- color: black;
- font-size: 11pt;
-}
-
-h1, h2, h3, h4, h5, h6 {
-# color: #990000;
- color: #009999;
-}
-
-pre {
- font-size: 10pt;
- background: #e0e0e0;
- color: black;
-}
-
-a:link, a:visited {
- font-weight: normal;
- text-decoration: none;
- color: #0047b9;
-}
-
-a:hover {
- font-weight: normal;
- text-decoration: underline;
- color: #0047b9;
-}
-
-img {
- border: 0px;
-}
-
-#main th {
- font-size: 12pt;
- background: #b0b0b0;
-}
-
-.odd {
- font-size: 12pt;
- background: white;
-}
-
-.even {
- font-size: 12pt;
- background: #e0e0e0;
-}
-
-.answer {
- font-size: large;
- font-weight: bold;
-}
-
-.answer p {
- font-size: 12pt;
- font-weight: normal;
-}
-
-.answer ul {
- font-size: 12pt;
- font-weight: normal;
-}
-
-#container {
- position: absolute;
- width: 100%;
- height: 100%;
- top: 0px;
-}
-
-#feedback {
- color: #b0b0b0;
- font-size: 9pt;
- font-style: italic;
-}
-
-#header {
- position: absolute;
- margin: 0px;
- top: 10px;
- height:96px;
- left: 175px;
- right: 10em;
- bottom: auto;
- background: white;
- clear: both;
-}
-
-#middle {
- position: absolute;
- left: 0;
- height: auto;
- width: 100%;
-}
-
-#main {
- position: absolute;
- top: 50px;
- left: 175px;
- right: 100px;
- background: white;
- padding: 0em 0em 0em 0em;
-}
-
-#navbar {
- position: absolute;
- top: 75px;
- left: 0em;
- width: 146px;
- padding: 0px;
- margin: 0px;
- font-size: 10pt;
-}
-
-#navbar a:link, #navbar a:visited {
- font-weight: normal;
- text-decoration: none;
- color: #0047b9;
-}
-
-#navbar a:hover {
- font-weight: normal;
- text-decoration: underline;
- color: #0047b9;
-}
-
-#navbar dl {
- width: 146px;
- padding: 0;
- margin: 0 0 10px 0px;
- background: #99ffff url(images/box_bottom2.gif) no-repeat bottom left;
-}
-
-#navbar dt {
- padding: 6px 10px;
- font-size: 100%;
- font-weight: bold;
- background: #009999;
- margin: 0px;
- border-bottom: 1px solid #fff;
- color: white;
- background: #009999 url(images/box_top2.gif) no-repeat top left;
-}
-
-#navbar dd {
- font-size: 100%;
- margin: 0 0 0 0px;
- padding: 6px 10px;
- color: #0047b9;
-}
-
-dd#selected {
- background: #99ffff url(images/arrow.gif) no-repeat;
- background-position: 4px 10px;
-}
--- a/doc/tutorial/tutorial.texi Sun Jan 02 22:57:04 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,106 +0,0 @@
-\input texinfo @c -*-texinfo-*-
-@c %**start of header
-@setfilename ns-3.info
-@settitle ns-3 tutorial
-@c @setchapternewpage odd
-@c %**end of header
-
-@ifinfo
-Primary documentation for the @command{ns-3} project is available in
-four forms:
-@itemize @bullet
-@item @uref{http://www.nsnam.org/doxygen/index.html,,ns-3 Doxygen/Manual}: Documentation of the public APIs of the simulator
-@item Tutorial (this document)
-@item @uref{http://www.nsnam.org/docs/manual.html,,Reference Manual}: Reference Manual
-@item @uref{http://www.nsnam.org/wiki/index.php,, ns-3 wiki}
-@end itemize
-
-This document is written in GNU Texinfo and is to be maintained in revision
-control on the @command{ns-3} code server. Both PDF and HTML versions should
-be available on the server. Changes to the document should be discussed on
-the ns-developers@@isi.edu mailing list.
-@end ifinfo
-
-@copying
-
-This is an @command{ns-3} tutorial.
-Primary documentation for the @command{ns-3} project is available in
-four forms:
-@itemize @bullet
-@item @uref{http://www.nsnam.org/doxygen/index.html,,ns-3 Doxygen/Manual}: Documentation of the public APIs of the simulator
-@item Tutorial (this document)
-@item @uref{http://www.nsnam.org/docs/manual.html,,Reference Manual}: Reference Manual
-@item @uref{http://www.nsnam.org/wiki/index.php,, ns-3 wiki}
-@end itemize
-
-This document is written in GNU Texinfo and is to be maintained in revision
-control on the @command{ns-3} code server. Both PDF and HTML versions should
-be available on the server. Changes to the document should be discussed on
-the ns-developers@@isi.edu mailing list.
-
-This software is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This software 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, see @uref{http://www.gnu.org/licenses/}.
-@end copying
-
-@titlepage
-@title ns-3 Tutorial
-@author ns-3 project
-@author feedback: ns-developers@@isi.edu
-@today{}
-
-@c @page
-@vskip 0pt plus 1filll
-@insertcopying
-@end titlepage
-
-@c So the toc is printed at the start.
-@ifnottex
-@anchor{Full Table of Contents}
-@end ifnottex
-@contents
-
-@ifnottex
-@node Top, Introduction, Full Table of Contents
-@top ns-3 Tutorial (html version)
-
-For a pdf version of this tutorial,
-see @uref{http://www.nsnam.org/docs/tutorial.pdf}.
-
-@insertcopying
-@end ifnottex
-
-@menu
-* Introduction::
-* Resources::
-* Getting Started::
-* Conceptual Overview::
-* Tweaking ns-3::
-* Building Topologies::
-* The Tracing System::
-* Closing Remarks::
-* Index::
-@end menu
-
-@include introduction.texi
-@include getting-started.texi
-@include conceptual-overview.texi
-@include tweaking.texi
-@include building-topologies.texi
-@include tracing.texi
-@include conclusion.texi
-
-@node Index
-@unnumbered Index
-@printindex cp
-
-@bye
--- a/doc/tutorial/tweaking.texi Sun Jan 02 22:57:04 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1046 +0,0 @@
-
-@c ========================================================================
-@c Begin document body here
-@c ========================================================================
-
-@c ========================================================================
-@c PART: Tweaking ns-3
-@c ========================================================================
-@c The below chapters are under the major heading "Tweaking ns-3"
-@c This is similar to the Latex \part command
-@c
-@c ========================================================================
-@c Tweaking ns-3
-@c ========================================================================
-@node Tweaking ns-3
-@chapter Tweaking ns-3
-
-@menu
-* Using the Logging Module::
-* Using Command Line Arguments::
-* Using the Tracing System::
-@end menu
-
-@c ========================================================================
-@c Using the Logging Module
-@c ========================================================================
-@node Using the Logging Module
-@section Using the Logging Module
-
-@cindex logging
-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
-@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.
-
-@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, or
-enabled globally; and it provides selectable verbosity levels. The
-@command{ns-3} log module provides a straightforward, relatively easy to use
-way to get useful 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
-simulation output (see the tutorial section Using the Tracing System for
-more details on our tracing system). Logging should be preferred for
-debugging information, warnings, error messages, or any time you want to
-easily get a quick message out of your scripts or models.
-
-There are currently seven levels of log messages of increasing verbosity
-defined in the system.
-
-@itemize @bullet
-@item NS_LOG_ERROR --- Log error messages;
-@item NS_LOG_WARN --- Log warning messages;
-@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 within a function;
-@item NS_LOG_ALL --- Log everything.
-@end itemize
-
-We also provide an unconditional logging level that is always displayed,
-irrespective of logging levels or component selection.
-
-@itemize @bullet
-@item NS_LOG_UNCOND -- Log the associated message unconditionally.
-@end itemize
-
-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 and now would be a good time to peruse the Logging Module
-documentation if you have not done so.
-
-Now that you have read the documentation in great detail, let's use some of
-that knowledge to get some interesting information out of the
-@code{scratch/myfirst.cc} example script you have already built.
-
-@node Enabling Logging
-@subsection Enabling Logging
-@cindex NS_LOG
-Let's use the NS_LOG environment variable to turn on some more logging, but
-first, just to get our bearings, go ahead and run the last script just as you
-did previously,
-
-@verbatim
- ./waf --run scratch/myfirst
-@end verbatim
-
-You should see the now familiar output of the first @command{ns-3} example
-program
-
-@verbatim
- Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
- Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
- 'build' finished successfully (0.413s)
- Sent 1024 bytes to 10.1.1.2
- Received 1024 bytes from 10.1.1.1
- Received 1024 bytes from 10.1.1.2
-@end verbatim
-
-It turns out that the ``Sent'' and ``Received'' messages you see above are
-actually logging messages from the @code{UdpEchoClientApplication} and
-@code{UdpEchoServerApplication}. We can 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 you 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 my examples to the ``setenv VARIABLE value'' syntax
-required by those shells.
-
-Right now, the UDP echo client application is responding to the following line
-of code in @code{scratch/myfirst.cc},
-
-@verbatim
- LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_INFO);
-@end verbatim
-
-This line of code enables the @code{LOG_LEVEL_INFO} level of logging. When
-we pass a logging level flag, we are actually enabling the given level and
-all lower levels. In this case, we have enabled @code{NS_LOG_INFO},
-@code{NS_LOG_DEBUG}, @code{NS_LOG_WARN} and @code{NS_LOG_ERROR}. We can
-increase the logging level and get more information without changing the
-script and recompiling by setting the NS_LOG environment variable like this:
-
-@verbatim
- export NS_LOG=UdpEchoClientApplication=level_all
-@end verbatim
-
-This sets the shell environment variable @code{NS_LOG} to the string,
-
-@verbatim
- UdpEchoClientApplication=level_all
-@end verbatim
-
-The left hand side of the assignment is the name of the logging component we
-want to set, and the right hand side is the flag we want to use. In this case,
-we are going to turn on all of the debugging levels for the application. If
-you run the script with NS_LOG set this way, the @command{ns-3} logging
-system will pick up the change and you should see the following output:
-
-@verbatim
- Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build
- Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
- 'build' finished successfully (0.404s)
- UdpEchoClientApplication:UdpEchoClient()
- UdpEchoClientApplication:SetDataSize(1024)
- UdpEchoClientApplication:StartApplication()
- UdpEchoClientApplication:ScheduleTransmit()
- UdpEchoClientApplication:Send()
- Sent 1024 bytes to 10.1.1.2
- Received 1024 bytes from 10.1.1.1
- UdpEchoClientApplication:HandleRead(0x6241e0, 0x624a20)
- Received 1024 bytes from 10.1.1.2
- UdpEchoClientApplication:StopApplication()
- UdpEchoClientApplication:DoDispose()
- UdpEchoClientApplication:~UdpEchoClient()
-@end verbatim
-
-The additional debug information provided by the application is from
-the NS_LOG_FUNCTION level. This shows every time a function in the application
-is called during script execution. Note that there are no requirements in the
-@command{ns-3} system that models must support any particular logging
-functionality. The decision regarding how much information is logged
-is left to the individual model developer. In the case of the echo
-applications, a good deal of log output is available.
-
-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 some 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.2}'' comes
-from. You can resolve this by OR'ing the @code{prefix_func} level into the
-@code{NS_LOG} environment variable. Try doing the following,
-
-@verbatim
- export 'NS_LOG=UdpEchoClientApplication=level_all|prefix_func'
-@end verbatim
-
-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
-name.
-
-@verbatim
- Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
- Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
- 'build' finished successfully (0.417s)
- UdpEchoClientApplication:UdpEchoClient()
- UdpEchoClientApplication:SetDataSize(1024)
- UdpEchoClientApplication:StartApplication()
- UdpEchoClientApplication:ScheduleTransmit()
- UdpEchoClientApplication:Send()
- UdpEchoClientApplication:Send(): Sent 1024 bytes to 10.1.1.2
- Received 1024 bytes from 10.1.1.1
- UdpEchoClientApplication:HandleRead(0x6241e0, 0x624a20)
- UdpEchoClientApplication:HandleRead(): Received 1024 bytes from 10.1.1.2
- UdpEchoClientApplication:StopApplication()
- UdpEchoClientApplication:DoDispose()
- UdpEchoClientApplication:~UdpEchoClient()
-@end verbatim
-
-You can now see all of the messages coming from the UDP echo client application
-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:
- UdpEchoServerApplication=level_all|prefix_func'
-@end verbatim
-
-Warning: You will need to remove the newline after the @code{:} in the
-example text above which is only there for document formatting purposes.
-
-Now, if you run the script you will see all of the log messages from both the
-echo client and server applications. You may see that this can be very useful
-in debugging problems.
-
-@verbatim
- Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
- Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
- 'build' finished successfully (0.406s)
- UdpEchoServerApplication:UdpEchoServer()
- UdpEchoClientApplication:UdpEchoClient()
- UdpEchoClientApplication:SetDataSize(1024)
- UdpEchoServerApplication:StartApplication()
- UdpEchoClientApplication:StartApplication()
- UdpEchoClientApplication:ScheduleTransmit()
- UdpEchoClientApplication:Send()
- UdpEchoClientApplication:Send(): Sent 1024 bytes to 10.1.1.2
- UdpEchoServerApplication:HandleRead(): Received 1024 bytes from 10.1.1.1
- UdpEchoServerApplication:HandleRead(): Echoing packet
- UdpEchoClientApplication:HandleRead(0x624920, 0x625160)
- UdpEchoClientApplication:HandleRead(): Received 1024 bytes from 10.1.1.2
- UdpEchoServerApplication:StopApplication()
- UdpEchoClientApplication:StopApplication()
- UdpEchoClientApplication:DoDispose()
- UdpEchoServerApplication:DoDispose()
- UdpEchoClientApplication:~UdpEchoClient()
- UdpEchoServerApplication:~UdpEchoServer()
-@end verbatim
-
-It is also sometimes useful to be able to see the simulation time at which a
-log message is generated. You can do this by ORing in the prefix_time bit.
-
-@verbatim
- export 'NS_LOG=UdpEchoClientApplication=level_all|prefix_func|prefix_time:
- UdpEchoServerApplication=level_all|prefix_func|prefix_time'
-@end verbatim
-
-Again, you will have to remove the newline above. If you run the script now,
-you should see the following output:
-
-@verbatim
- Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
- Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
- 'build' finished successfully (0.418s)
- 0s UdpEchoServerApplication:UdpEchoServer()
- 0s UdpEchoClientApplication:UdpEchoClient()
- 0s UdpEchoClientApplication:SetDataSize(1024)
- 1s UdpEchoServerApplication:StartApplication()
- 2s UdpEchoClientApplication:StartApplication()
- 2s UdpEchoClientApplication:ScheduleTransmit()
- 2s UdpEchoClientApplication:Send()
- 2s UdpEchoClientApplication:Send(): Sent 1024 bytes to 10.1.1.2
- 2.00369s UdpEchoServerApplication:HandleRead(): Received 1024 bytes from 10.1.1.1
- 2.00369s UdpEchoServerApplication:HandleRead(): Echoing packet
- 2.00737s UdpEchoClientApplication:HandleRead(0x624290, 0x624ad0)
- 2.00737s UdpEchoClientApplication:HandleRead(): Received 1024 bytes from 10.1.1.2
- 10s UdpEchoServerApplication:StopApplication()
- 10s UdpEchoClientApplication:StopApplication()
- UdpEchoClientApplication:DoDispose()
- UdpEchoServerApplication:DoDispose()
- UdpEchoClientApplication:~UdpEchoClient()
- UdpEchoServerApplication:~UdpEchoServer()
-@end verbatim
-
-You can see that the constructor for the UdpEchoServer was called at a
-simulation time of 0 seconds. This is actually happening before the
-simulation starts, but the time is displayed as zero seconds. The same is true
-for the UdpEchoClient constructor message.
-
-Recall that the @code{scratch/first.cc} script started the echo server
-application at one second into the simulation. You can now see that the
-@code{StartApplication} method of the server is, in fact, called at one second.
-You can also see that the echo client application is started at a simulation
-time of two seconds as we requested in the script.
-
-You can now follow the progress of the simulation from the
-@code{ScheduleTransmit} call in the client that calls @code{Send} to the
-@code{HandleRead} callback in the echo server application. Note that the
-elapsed time for the packet to be sent across the point-to-point link is 3.69
-milliseconds. You see the echo server logging a message telling you that it
-has echoed the packet and then, after another channel delay, you see the echo
-client receive the echoed packet in its @code{HandleRead} method.
-
-There is a lot that is happening under the covers in this simulation that you
-are not seeing as well. You can very easily follow the entire process by
-turning on all of the logging components in the system. Try setting the
-@code{NS_LOG} variable to the following,
-
-@verbatim
- export 'NS_LOG=*=level_all|prefix_func|prefix_time'
-@end verbatim
-
-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 1265 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
- ./waf --run scratch/myfirst > log.out 2>&1
-@end verbatim
-
-I personally use this extremely verbose version of logging when I am presented
-with a problem and I 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. I can just edit up the output in my favorite editor
-and search around for things I expect, and see things happening that I don't
-expect. When I have a general idea about what is going wrong, I transition into
-a debugger for a fine-grained examination of the problem. This 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
-@cindex NS_LOG
-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{myfirst.cc} script we
-have in the @code{scratch} directory.
-
-Recall that we have defined a logging component in that script:
-
-@verbatim
- NS_LOG_COMPONENT_DEFINE ("FirstScriptExample");
-@end verbatim
-
-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
-go ahead and 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,
-
-Open @code{scratch/myfirst.cc} in your favorite editor and add the line,
-
-@verbatim
- NS_LOG_INFO ("Creating Topology");
-@end verbatim
-
-right before the lines,
-
-@verbatim
- NodeContainer nodes;
- nodes.Create (2);
-@end verbatim
-
-Now build the script using waf and clear the @code{NS_LOG} variable to turn
-off the torrent of logging we previously enabled:
-
-@verbatim
- ./waf
- export NS_LOG=
-@end verbatim
-
-Now, if you run the script,
-
-@verbatim
- ./waf --run scratch/myfirst
-@end verbatim
-
-you will @emph{not} see your new message since its 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
- export NS_LOG=FirstScriptExample=info
-@end verbatim
-
-If you now run the script you will see your new ``Creating Topology'' log
-message,
-
-@verbatim
- Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
- Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
- 'build' finished successfully (0.404s)
- Creating Topology
- Sent 1024 bytes to 10.1.1.2
- Received 1024 bytes from 10.1.1.1
- Received 1024 bytes from 10.1.1.2
-@end verbatim
-
-@c ========================================================================
-@c Using Command Line Arguments
-@c ========================================================================
-@node Using Command Line Arguments
-@section Using Command Line Arguments
-
-@subsection Overriding Default Attributes
-@cindex command line 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
-in the following code,
-
-@verbatim
- int
- main (int argc, char *argv[])
- {
- ...
-
- CommandLine cmd;
- cmd.Parse (argc, argv);
-
- ...
- }
-@end verbatim
-
-This simple two line snippet is actually very useful by itself. It opens the
-door to the @command{ns-3} global variable and @code{Attribute} systems. Go
-ahead and add that two lines of code to the @code{scratch/myfirst.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
- ./waf --run "scratch/myfirst --PrintHelp"
-@end verbatim
-
-This will ask Waf to run the @code{scratch/myfirst} 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
- Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
- Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
- 'build' finished successfully (0.413s)
- TcpL4Protocol:TcpStateMachine()
- CommandLine:HandleArgument(): Handle arg name=PrintHelp value=
- --PrintHelp: Print this help message.
- --PrintGroups: Print the list of groups.
- --PrintTypeIds: Print all TypeIds.
- --PrintGroup=[group]: Print all TypeIds of group.
- --PrintAttributes=[typeid]: Print all attributes of typeid.
- --PrintGlobals: Print the list of globals.
-@end verbatim
-
-Let's focus on the @code{--PrintAttributes} option. We have already hinted
-at the @command{ns-3} @code{Attribute} system while walking through the
-@code{first.cc} script. We looked at the following lines of code,
-
-@verbatim
- PointToPointHelper pointToPoint;
- pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
- pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
-@end verbatim
-
-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 @code{Attributes} of the PointToPointNetDevice. The help
-listing says that we should provide a @code{TypeId}. This corresponds to the
-class name of the class to which the @code{Attributes} belong. In this case it
-will be @code{ns3::PointToPointNetDevice}. Let's go ahead and type in,
-
-@verbatim
- ./waf --run "scratch/myfirst --PrintAttributes=ns3::PointToPointNetDevice"
-@end verbatim
-
-The system will print out all of the @code{Attributes} of this kind of net device.
-Among the @code{Attributes} you will see listed is,
-
-@verbatim
- --ns3::PointToPointNetDevice::DataRate=[32768bps]:
- The default data rate for point to point links
-@end verbatim
-
-This is the default value that will be used when a @code{PointToPointNetDevice}
-is created in the system. We overrode this default with the @code{Attribute}
-setting in the @code{PointToPointHelper} above. Let's use the default values
-for the point-to-point devices and channels by deleting the
-@code{SetDeviceAttribute} call and the @code{SetChannelAttribute} call from
-the @code{myfirst.cc} we have in the scratch directory.
-
-Your script should now just declare the @code{PointToPointHelper} and not do
-any @code{set} operations as in the following example,
-
-@verbatim
- ...
-
- NodeContainer nodes;
- nodes.Create (2);
-
- PointToPointHelper pointToPoint;
-
- NetDeviceContainer devices;
- devices = pointToPoint.Install (nodes);
-
- ...
-@end verbatim
-
-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'
-@end verbatim
-
-If you run the script, you should now see the following output,
-
-@verbatim
- Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
- Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
- 'build' finished successfully (0.405s)
- 0s UdpEchoServerApplication:UdpEchoServer()
- 1s UdpEchoServerApplication:StartApplication()
- Sent 1024 bytes to 10.1.1.2
- 2.25732s Received 1024 bytes from 10.1.1.1
- 2.25732s Echoing packet
- Received 1024 bytes from 10.1.1.2
- 10s UdpEchoServerApplication:StopApplication()
- UdpEchoServerApplication:DoDispose()
- UdpEchoServerApplication:~UdpEchoServer()
-@end verbatim
-
-Recall that the last time we looked at the simulation time at which the packet
-was received by the echo server, it was at 2.00369 seconds.
-
-@verbatim
- 2.00369s UdpEchoServerApplication:HandleRead(): Received 1024 bytes from 10.1.1.1
-@end verbatim
-
-Now it is receiving the packet at 2.25732 seconds. This is because we just dropped
-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. We do this in the following way, according to
-the formula implied by the help item:
-
-@verbatim
- ./waf --run "scratch/myfirst --ns3::PointToPointNetDevice::DataRate=5Mbps"
-@end verbatim
-
-This will set the default value of the @code{DataRate} @code{Attribute} back to
-five megabits per second. Are you surprised by the result? It turns out that
-in order to get the original behavior of the script back, we will have to set
-the speed-of-light delay of the channel as well. We can ask the command line
-system to print out the @code{Attributes} of the channel just like we did for
-the net device:
-
-@verbatim
- ./waf --run "scratch/myfirst --PrintAttributes=ns3::PointToPointChannel"
-@end verbatim
-
-We discover the @code{Delay} @code{Attribute} of the channel is set in the following
-way:
-
-@verbatim
- --ns3::PointToPointChannel::Delay=[0ns]:
- Transmission delay through the channel
-@end verbatim
-
-We can then set both of these default values through the command line system,
-
-@verbatim
- ./waf --run "scratch/myfirst
- --ns3::PointToPointNetDevice::DataRate=5Mbps
- --ns3::PointToPointChannel::Delay=2ms"
-@end verbatim
-
-in which case we recover the timing we had when we explicitly set the
-@code{DataRate} and @code{Delay} in the script:
-
-@verbatim
- Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
- Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
- 'build' finished successfully (0.417s)
- 0s UdpEchoServerApplication:UdpEchoServer()
- 1s UdpEchoServerApplication:StartApplication()
- Sent 1024 bytes to 10.1.1.2
- 2.00369s Received 1024 bytes from 10.1.1.1
- 2.00369s Echoing packet
- Received 1024 bytes from 10.1.1.2
- 10s UdpEchoServerApplication:StopApplication()
- UdpEchoServerApplication:DoDispose()
- UdpEchoServerApplication:~UdpEchoServer()
-@end verbatim
-
-Note that the packet is again received by the server at 2.00369 seconds. We
-could actually set any of the @code{Attributes} used in the script in this way.
-In particular we could set the @code{UdpEchoClient Attribute MaxPackets}
-to some other value than one.
-
-How would you go about that? Give it a try. Remember you have to comment
-out the place we override the default @code{Attribute} and explicitly set
-@code{MaxPackets} in the script. Then you have to rebuild the script. You
-will also have to find the syntax for actually setting the new default attribute
-value using the command line help facility. Once you have this figured out
-you should be able to control the number of packets echoed from the command
-line. Since we're nice folks, we'll tell you that your command line should
-end up looking something like,
-
-@verbatim
- ./waf --run "scratch/myfirst
- --ns3::PointToPointNetDevice::DataRate=5Mbps
- --ns3::PointToPointChannel::Delay=2ms
- --ns3::UdpEchoClient::MaxPackets=2"
-@end verbatim
-
-@subsection Hooking Your Own Values
-You can also add your own hooks to the command line system. This is done
-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 @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. We do this by adding a call to
-@code{AddValue}. Go ahead and change the @code{scratch/myfirst.cc} script to
-start with the following code,
-
-@verbatim
- int
- main (int argc, char *argv[])
- {
- uint32_t nPackets = 1;
-
- CommandLine cmd;
- cmd.AddValue("nPackets", "Number of packets to echo", nPackets);
- cmd.Parse (argc, argv);
-
- ...
-@end verbatim
-
-Scroll down to the point in the script where we set the @code{MaxPackets}
-@code{Attribute} and change it so that it is set to the variable @code{nPackets}
-instead of the constant @code{1} as is shown below.
-
-@verbatim
- echoClient.SetAttribute ("MaxPackets", UintegerValue (nPackets));
-@end verbatim
-
-Now if you run the script and provide the @code{--PrintHelp} argument, you
-should see your new @code{User Argument} listed in the help display.
-
-Try,
-
-@verbatim
- ./waf --run "scratch/myfirst --PrintHelp"
-@end verbatim
-
-@verbatim
- Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
- Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
- 'build' finished successfully (0.403s)
- --PrintHelp: Print this help message.
- --PrintGroups: Print the list of groups.
- --PrintTypeIds: Print all TypeIds.
- --PrintGroup=[group]: Print all TypeIds of group.
- --PrintAttributes=[typeid]: Print all attributes of typeid.
- --PrintGlobals: Print the list of globals.
- User Arguments:
- --nPackets: Number of packets to echo
-@end verbatim
-
-If you want to specify the number of packets to echo, you can now do so by
-setting the @code{--nPackets} argument in the command line,
-
-@verbatim
- ./waf --run "scratch/myfirst --nPackets=2"
-@end verbatim
-
-You should now see
-
-@verbatim
- Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
- Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
- 'build' finished successfully (0.404s)
- 0s UdpEchoServerApplication:UdpEchoServer()
- 1s UdpEchoServerApplication:StartApplication()
- Sent 1024 bytes to 10.1.1.2
- 2.25732s Received 1024 bytes from 10.1.1.1
- 2.25732s Echoing packet
- Received 1024 bytes from 10.1.1.2
- Sent 1024 bytes to 10.1.1.2
- 3.25732s Received 1024 bytes from 10.1.1.1
- 3.25732s Echoing packet
- Received 1024 bytes from 10.1.1.2
- 10s UdpEchoServerApplication:StopApplication()
- UdpEchoServerApplication:DoDispose()
- UdpEchoServerApplication:~UdpEchoServer()
-@end verbatim
-
-You have now echoed two packets. Pretty easy, isn't it?
-
-You can see that if you are an @command{ns-3} user, you can use the command
-line argument system to control global values and @code{Attributes}. If you are
-a model author, you can add new @code{Attributes} to your @code{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
-@c ========================================================================
-@node Using the Tracing System
-@section Using the Tracing System
-
-The whole point of simulation is to generate output for further study, and
-the @command{ns-3} tracing system is a primary mechanism for this. Since
-@command{ns-3} is a C++ program, standard facilities for generating output
-from C++ programs could be used:
-
-@verbatim
- #include <iostream>
- ...
- int main ()
- {
- ...
- std::cout << "The value of x is " << x << std::endl;
- ...
- }
-@end verbatim
-
-You could even use the logging module to add a little structure to your
-solution. There are many well-known problems generated by such approaches
-and so we have provided a generic event tracing subsystem to address the
-issues we thought were important.
-
-The basic goals of the @command{ns-3} tracing system are:
-
-@itemize @bullet
-@item For basic tasks, the tracing system should allow the user to generate
-standard tracing for popular tracing sources, and to customize which objects
-generate the tracing;
-@item Intermediate users must be able to extend the tracing system to modify
-the output format generated, or to insert new tracing sources, without
-modifying the core of the simulator;
-@item Advanced users can modify the simulator core to add new tracing sources
-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
-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.
-
-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
-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
-types of sinks to existing tracing sources, without requiring editing and
-recompilation of the core of the simulator. Thus, in the example above,
-a user could define a new tracing sink in her script and attach it to an
-existing tracing source defined in the simulation core by editing only the
-user script.
-
-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
-extending the tracing namespace and creating new tracing sources.
-
-@cindex tracing
-@cindex ASCII tracing
-@subsection ASCII Tracing
-@command{Ns-3} provides helper functionality that wraps the low-level tracing
-system to help you with the details involved in configuring some easily
-understood packet traces. If you enable this functionality, you will see
-output in a ASCII files --- 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
-@code{scratch/myfirst.cc} script. Right before the call to
-@code{Simulator::Run ()}, add the following lines of code:
-
-@verbatim
- AsciiTraceHelper ascii;
- pointToPoint.EnableAsciiAll (ascii.CreateFileStream ("myfirst.tr"));
-@end verbatim
-
-Like in many other @command{ns-3} idioms, this code uses a helper object to
-help create ASCII traces. The second line contains two nested method calls.
-The ``inside'' method, @code{CreateFileStream()} uses an unnamed object idiom
-to create a file stream object on the stack (without an object name) and pass
-it down to the called method. We'll go into this more in the future, but all
-you have to know at this point is that you are creating an object representing
-a file named ``myfirst.tr'' and passing it into @code{ns-3}. You are telling
-@code{ns-3} to deal with the lifetime issues of the created object and also to
-deal with problems caused by a little-known (intentional) limitation of C++
-ofstream objects relating to copy constructors.
-
-The outside call, to @code{EnableAsciiAll()}, tells the helper 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.
-
-For those familiar with @command{ns-2}, the traced events are equivalent to
-the popular trace points that log "+", "-", "d", and "r" events.
-
-You can now build the script and run it from the command line:
-
-@verbatim
- ./waf --run scratch/myfirst
-@end verbatim
-
-@cindex myfirst.tr
-Just as you have seen many times before, you will see some messages from Waf and then
-``'build' finished successfully'' with some number of messages from
-the running program.
-
-When it ran, the program will have created a file named @code{myfirst.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 ASCII trace file @code{myfirst.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 window considerably.
-
-Each line in the file corresponds to a @emph{trace event}. In this case
-we are tracing events on the @emph{transmit queue} present in every
-point-to-point net device in the simulation. The transmit queue is a queue
-through which every packet destined for a point-to-point 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
-@cindex ascii trace drop operation
-@cindex ascii trace receive operation
-@itemize @bullet
-@item @code{+}: An enqueue operation occurred on the device queue;
-@item @code{-}: A dequeue operation occurred on the device queue;
-@item @code{d}: A packet was dropped, typically because the queue was full;
-@item @code{r}: A packet was received by the net device.
-@end itemize
-
-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 +
- 01 2
- 02 /NodeList/0/DeviceList/0/$ns3::PointToPointNetDevice/TxQueue/Enqueue
- 03 ns3::PppHeader (
- 04 Point-to-Point Protocol: IP (0x0021))
- 05 ns3::Ipv4Header (
- 06 tos 0x0 ttl 64 id 0 protocol 17 offset 0 flags [none]
- 07 length: 1052 10.1.1.1 > 10.1.1.2)
- 08 ns3::UdpHeader (
- 09 length: 1032 49153 > 9)
- 10 Payload (size=1024)
-@end verbatim
-
-@cindex trace event
-@cindex simulation time
-The first line of this expanded trace event (reference number 00) is the
-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 trace (reference 02) tell us which trace source
-originated this event (expressed in the tracing namespace). You can think
-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 is in the zeroth position of the device list for node zero.
-Recall that the operation @code{+} found at reference 00 meant that 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 encapsulated 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 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.
-
-The Third line in the trace file shows the packet being received by the net
-device on the node with the echo server. I have reproduced that event below.
-
-@verbatim
- 00 r
- 01 2.25732
- 02 /NodeList/1/DeviceList/0/$ns3::PointToPointNetDevice/MacRx
- 03 ns3::Ipv4Header (
- 04 tos 0x0 ttl 64 id 0 protocol 17 offset 0 flags [none]
- 05 length: 1052 10.1.1.1 > 10.1.1.2)
- 06 ns3::UdpHeader (
- 07 length: 1032 49153 > 9)
- 08 Payload (size=1024)
-@end verbatim
-
-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
-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
-trace source (@code{/MacRx}). 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 Tracing
-@cindex pcap
-@cindex Wireshark
-The @command{ns-3} device helpers can also 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 concentrate on viewing pcap traces with tcpdump.
-
-@cindex pcap tracing
-The code used to enable pcap tracing is a one-liner.
-
-@verbatim
- pointToPoint.EnablePcapAll ("myfirst");
-@end verbatim
-
-Go ahead and insert this line of code after the ASCII tracing code we just
-added to @code{scratch/myfirst.cc}. Notice that we only passed the string
-``myfirst,'' and not ``myfirst.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 eventually see files named ``myfirst-0-0.pcap''
-and ``myfirst-1-0.pcap'' which are the pcap traces for node 0-device 0 and
-node 1-device 0, respectively.
-
-Once you have added the line of code to enable pcap tracing, you can run the
-script in the usual way:
-
-@verbatim
- ./waf --run scratch/myfirst
-@end verbatim
-
-If you look at the top level directory of your distribution, you should now
-see three log files: @code{myfirst.tr} is the ASCII trace file we have
-previously examined. @code{myfirst-0-0.pcap} and @code{myfirst-1-0.pcap}
-are the new pcap files we just generated.
-
-@subsubsection Reading output with tcpdump
-@cindex tcpdump
-The easiest thing to do at this point will be to use @code{tcpdump} to look
-at the @code{pcap} files.
-
-@verbatim
- tcpdump -nn -tt -r myfirst-0-0.pcap
- reading from file myfirst-0-0.pcap, link-type PPP (PPP)
- 2.000000 IP 10.1.1.1.49153 > 10.1.1.2.9: UDP, length 1024
- 2.514648 IP 10.1.1.2.9 > 10.1.1.1.49153: UDP, length 1024
-
- tcpdump -nn -tt -r myfirst-1-0.pcap
- reading from file myfirst-1-0.pcap, link-type PPP (PPP)
- 2.257324 IP 10.1.1.1.49153 > 10.1.1.2.9: UDP, length 1024
- 2.257324 IP 10.1.1.2.9 > 10.1.1.1.49153: UDP, length 1024
-@end verbatim
-
-You can see in the dump of @code{myfirst-0-0.pcap} (the client device) that the
-echo packet is sent at 2 seconds into the simulation. If you look at the
-second dump (@code{myfirst-1-0.pcap}) you can see that packet being received
-at 2.257324 seconds. You see the packet being echoed back at 2.257324 seconds
-in the second dump, and finally, you see the packet being received back at
-the client in the first dump at 2.514648 seconds.
-
-@subsubsection Reading output with Wireshark
-@cindex Wireshark
-If you are unfamiliar with Wireshark, there is a web site available from which
-you can download programs and documentation: @uref{http://www.wireshark.org/}.
-
-Wireshark is a graphical user interface which can be used for displaying these
-trace files. If you have Wireshark available, you can open each of the trace
-files and display the contents as if you had captured the packets using a
-@emph{packet sniffer}.