swap in new tutorial

This commit is contained in:
Craig Dowell
2008-06-28 19:46:55 -07:00
parent f58dda2fcb
commit 5cf2aa1ebf
24 changed files with 2660 additions and 21 deletions

View File

@@ -0,0 +1,300 @@
@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 Star Topology
@end menu
@c ========================================================================
@c Building a Star Topology
@c ========================================================================
@node Building a Star Topology
@section Building a Star Topology
@cindex topology
@cindex topology|star
In this section we are going to use the point-to-point topology primitive we
have explored in quite some detail to construct a star network. In the star,
there is a central node that is connected to other nodes in a ``hub and spoke''
fashion, with each ``spoke'' being a point-to-point link.
We provide an example of a star topology simulation script on our
@code{examples} directory. Go ahead and open @code{examples/star.cc} in your
favorite editor. You will have already seen enough ns-3 code to understand
this example, but we will go over the script briefly and examine some of the
output.
There is an amazingly beautiful bit of ASCII art at the beginning of the file
that shows the topology used in the script. Most ns-3 example programs
provide this, which can be surprisingly useful in understanding the code.
@verbatim
// Network topology
//
// n3 n2
// | /
// | /
// n4 --- n0 --- n1
// / |
// / |
// n5 n6
@end verbatim
There are seven nodes in this simulation, nodes zero through six. Node zero is
the hub of this star network. We are going to discover that there will be a
flow of echo packets between node four and node one, between node three and
node six, and node five and node two.
The script starts by creating seven nodes in a @code{NodeContainer} and
installs internet protocol stacks on all seven.
@verbatim
int
main (int argc, char *argv[])
{
NodeContainer nodes;
nodes.Create (7);
InternetStackHelper stack;
stack.Install (nodes);
...
@end verbatim
It then creates six more @code{NodeContainer}s representing the nodes at each
end of the six spokes. In all cases, the first node in the spoke is node zero.
@verbatim
NodeContainer nodes0and1 = NodeContainer (nodes.Get (0), nodes.Get (1));
NodeContainer nodes0and2 = NodeContainer (nodes.Get (0), nodes.Get (2));
NodeContainer nodes0and3 = NodeContainer (nodes.Get (0), nodes.Get (3));
NodeContainer nodes0and4 = NodeContainer (nodes.Get (0), nodes.Get (4));
NodeContainer nodes0and5 = NodeContainer (nodes.Get (0), nodes.Get (5));
NodeContainer nodes0and6 = NodeContainer (nodes.Get (0), nodes.Get (6));
@end verbatim
These node containers will be used during the creation of the point-to-point
links by the @code{PointToPointHelper}. The next bit of code instantiates
a helper and sets the default values for the device @code{DataRate} and the
channel @code{Delay} attributes as we have previously seen.
@verbatim
PointToPointHelper pointToPoint;
pointToPoint.SetDeviceParameter ("DataRate", StringValue ("5Mbps"));
pointToPoint.SetChannelParameter ("Delay", StringValue ("2ms"));
@end verbatim
The next step is to install the net devices on the nodes referenced by the
six node containers and connect them via channels. We used one instance
of the @code{pointToPoint.Install} method to construct our single
point-to-point link in the @code{first.cc} script. This code just does that
six times between different combinations of nodes.
@verbatim
NetDeviceContainer devicesOnNodes0and1 = pointToPoint.Install (nodes0and1);
NetDeviceContainer devicesOnNodes0and2 = pointToPoint.Install (nodes0and2);
NetDeviceContainer devicesOnNodes0and3 = pointToPoint.Install (nodes0and3);
NetDeviceContainer devicesOnNodes0and4 = pointToPoint.Install (nodes0and4);
NetDeviceContainer devicesOnNodes0and5 = pointToPoint.Install (nodes0and5);
NetDeviceContainer devicesOnNodes0and6 = pointToPoint.Install (nodes0and6);
@end verbatim
Note that this does mean that node zero will have six net devices after this
code executes. Recall that we need to keep containers holding the net devices
we created in order to do IP address assignment. This is the next step in the
script.
Just as in @code{first.cc} we use the Ipv4AddressHelper to make it easy to
deal with addressing. We need to create different networks for each stub, so
we have to call the @code{SetBase} method and provide a different network
number before assigning addresses to the devices on each network. We make it
easy to remember what is what by setting the least significant bits of the
network number to the unique node on the spoke. For example, the spoke between
nodes zero and one is network 10.1.1; and the spoke between nodes zero and
two is 10.1.2, etc. Note that the network mask is set to 255.255.255.252 in
all cases.
@verbatim
Ipv4AddressHelper ipv4;
ipv4.SetBase ("10.1.1.0", "255.255.255.252");
Ipv4InterfaceContainer interfacesOnNodes0and1 =
ipv4.Assign (devicesOnNodes0and1);
ipv4.SetBase ("10.1.2.0", "255.255.255.252");
Ipv4InterfaceContainer interfacesOnNodes0and2 =
ipv4.Assign (devicesOnNodes0and2);
ipv4.SetBase ("10.1.3.0", "255.255.255.252");
Ipv4InterfaceContainer interfacesOnNodes0and3 =
ipv4.Assign (devicesOnNodes0and3);
ipv4.SetBase ("10.1.4.0", "255.255.255.252");
Ipv4InterfaceContainer interfacesOnNodes0and4 =
ipv4.Assign (devicesOnNodes0and4);
ipv4.SetBase ("10.1.5.0", "255.255.255.252");
Ipv4InterfaceContainer interfacesOnNodes0and5 =
ipv4.Assign (devicesOnNodes0and5);
ipv4.SetBase ("10.1.6.0", "255.255.255.252");
Ipv4InterfaceContainer interfacesOnNodes0and6 =
ipv4.Assign (devicesOnNodes0and6);
@end verbatim
When the above code has executed, we will have the topology complete and then
need to move on to applications. The code to do this should be familiar to
you, but we have rearranged it slightly.
We use an ApplicationContainer to hold the results of the helper operations,
and use the UdpEchoServerHelper and UdpEchoClient server to configure the
apps just as we did in the @code{first.cc} script.
@verbatim
uint16_t port = 9;
ApplicationContainer apps;
UdpEchoServerHelper server;
server.SetPort (port);
UdpEchoClientHelper client;
client.SetAppAttribute ("MaxPackets", UintegerValue (10));
client.SetAppAttribute ("Interval", StringValue ("10ms"));
client.SetAppAttribute ("PacketSize", UintegerValue (137));
@end verbatim
The next section of code is repeated three times, once for each data flow.
We'll skim over the first instance quickly. The other two differ only in
the nodes selected and the starting times of the flows.
Just as we did in the @code{first.cc} script, we use the
@code{UdpEchoServerHelper} to install the echo server on a node (in this case,
node number one -- the rightmost spoke in the topology). We tell the server
application to start at a simulation time of one second. We use the
@code{UdpEchoClientHelper} to install the echo client on a node (in this case,
node number four -- the leftmost spoke in the topology). We tell the client
to start sending data at a simulation time of two seconds.
@verbatim
//
// Echo from node 4 to node 1 starting at 2 sec
//
apps = server.Install (nodes.Get (1));
apps.Start (Seconds (1.0));
client.SetRemote (interfacesOnNodes0and1.GetAddress (1), port);
apps = client.Install (nodes.Get (4));
apps.Start (Seconds (2.0));
@end verbatim
The next sections do the same thing, but for nodes three and six with a flow
starting at 2.1 seconds, and for nodes five and two with flow starting at 2.2
seconds.
The only piece of code you may not have seen before follows. Since we have
built an internetwork, we need some form of internetwork routing. Ns-3
provides what we call a global route manager to set up the routing tables on
nodes. This route manager has a global function that runs though the nodes
of the simulation and does the hard work of setting up routing for you.
Basically, what happens is that each node behaves as if it were an OSPF router
that communicates instantly and magically with all other routers. Each node
generates link advertisements to the global route manager, which uses this
information to construct the routing tables for each node.
@verbatim
GlobalRouteManager::PopulateRoutingTables ();
@end verbatim
The remainder of the script should be very familiar to you. We just enable
ASCII and pcap tracing and run the simulation:
@verbatim
std::ofstream ascii;
ascii.open (``star.tr'');
PointToPointHelper::EnableAsciiAll (ascii);
PointToPointHelper::EnablePcapAll (``star'');
Simulator::Run ();
Simulator::Destroy ();
}
@end verbatim
In order to run this example, you use waf. All of our example programs are
built by default, so all you have to do is run it. Now, you did not build
this script by copying it into the scratch directory, so you don't have to
add the scratch directory to the run command. You just do the following,
@verbatim
./waf --run star
@end verbatim
There is no output from this script by default. It will just go off and
silently do its thing. All you will see are waf messages:
@verbatim
~/repos/ns-3-tutorial > ./waf --run star
Entering directory `/home/craigdo/repos/ns-3-tutorial/build'
Compilation finished successfully
~/repos/ns-3-tutorial >
@end verbatim
If you now go and look in the top level directory, you will find a number of
trace files:
@verbatim
~/repos/ns-3-tutorial > ls *.pcap *.tr
star-0-0.pcap star-0-3.pcap star-1-0.pcap star-4-0.pcap star.tr
star-0-1.pcap star-0-4.pcap star-2-0.pcap star-5-0.pcap
star-0-2.pcap star-0-5.pcap star-3-0.pcap star-6-0.pcap
~/repos/ns-3-tutorial >
@end verbatim
If you have gone through the tracing section of this tutorial, you know how to
interpret all of these files. For your reading pleasure, we reproduce a
tcpdump from the net device on node four:
@verbatim
[ns-regression] ~/repos/ns-3-tutorial > tcpdump -r star-4-0.pcap -nn -tt
reading from file star-4-0.pcap, link-type PPP (PPP)
2.000000 IP 10.1.4.2.49153 > 10.1.1.2.9: UDP, length 137
2.009068 IP 10.1.1.2.9 > 10.1.4.2.49153: UDP, length 137
2.010000 IP 10.1.4.2.49153 > 10.1.1.2.9: UDP, length 137
2.019068 IP 10.1.1.2.9 > 10.1.4.2.49153: UDP, length 137
2.020000 IP 10.1.4.2.49153 > 10.1.1.2.9: UDP, length 137
2.029068 IP 10.1.1.2.9 > 10.1.4.2.49153: UDP, length 137
2.030000 IP 10.1.4.2.49153 > 10.1.1.2.9: UDP, length 137
2.039068 IP 10.1.1.2.9 > 10.1.4.2.49153: UDP, length 137
2.040000 IP 10.1.4.2.49153 > 10.1.1.2.9: UDP, length 137
2.049068 IP 10.1.1.2.9 > 10.1.4.2.49153: UDP, length 137
2.050000 IP 10.1.4.2.49153 > 10.1.1.2.9: UDP, length 137
2.059068 IP 10.1.1.2.9 > 10.1.4.2.49153: UDP, length 137
2.060000 IP 10.1.4.2.49153 > 10.1.1.2.9: UDP, length 137
2.069068 IP 10.1.1.2.9 > 10.1.4.2.49153: UDP, length 137
2.070000 IP 10.1.4.2.49153 > 10.1.1.2.9: UDP, length 137
2.079068 IP 10.1.1.2.9 > 10.1.4.2.49153: UDP, length 137
2.080000 IP 10.1.4.2.49153 > 10.1.1.2.9: UDP, length 137
2.089068 IP 10.1.1.2.9 > 10.1.4.2.49153: UDP, length 137
2.090000 IP 10.1.4.2.49153 > 10.1.1.2.9: UDP, length 137
2.099068 IP 10.1.1.2.9 > 10.1.4.2.49153: UDP, length 137
[ns-regression] ~/repos/ns-3-tutorial >
@end verbatim
You are encouraged to think through the pcap traces and map them back to the
script. Also, take a look at the @code{star.tr} ASCII trace file (which is
quite large) to make sure you understand what it is telling you.

View File

@@ -0,0 +1,809 @@
@c ========================================================================
@c Begin document body here
@c ========================================================================
@c ========================================================================
@c PART: Conceptual Overview
@c ========================================================================
@c The below chapters are under the major heading "Getting Started"
@c This is similar to the Latex \part command
@c ========================================================================
@c Some Conceptual Overview
@c ========================================================================
@node Conceptual Overveiw
@chapter Conceptual Overview
@menu
* Key Abstractions::
@end menu
The first thing we need to do before actually starting to look at or write
ns-3 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.
@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 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 netowrks 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
@cindex helper
@cindex topology
@cindex helper|topology
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 @code{NetDevice}s to @code{Node}s, @code{NetDevice}s
to @code{Channel}s, assigning IP addresses, etc., are such common tasks
in ns-3 we provide what we call @emph{topology helpers} to make this as easy
as possible. For example, will take several distinct ns-3 core operations
to create a NetDevice, add a MAC address, connect the net device to a
@code{Node}, configure the protocol stack, and then connect the
@code{NetDevice} to a @code{Channel}. More higher level operations would be
required to connect multiple devices onto multipoint channels and then to
connect networks together into internetworks. We use topology helper objects
to compose those distinct operations into an easy to use model.
@c ========================================================================
@c A First ns-3 script
@c ========================================================================
@node A First ns-3 Script
@chapter A First ns-3 script
@cindex first script
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 release directory, and you should find a directory structure
something like the following:
@verbatim
AUTHORS examples/ README samples/ tutorial/ waf*
build/ LICENSE regression/ scratch/ utils/ waf.bat*
doc/ ns3/ RELEASE_NOTES src/ VERSION wscript
@end verbatim
@cindex first.cc
Change into the examples 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 the script line by line.
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 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 ns-3 coding style as described in INSERT LINK TO CODING STYLE PAGE ON WEB.
The emacs mode line above makes it easier to get the formatting correct if you
use the emacs editor.
The ns-3 simulator is licentsed using the GNU General Public License. You
will see the appropriate GNU legalese at the head of every file in the ns-3
distribution.
@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
@section Module Includes
The code proper starts with a number of include statements. To help our high
level 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, in turn, includes 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 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 ns-3 files
is placed in a directory called @code{ns3} to help with include file name
collisions.
@verbatim
#include "ns3/core-module.h"
#include "ns3/simulator-module.h"
#include "ns3/node-module.h"
#include "ns3/helper-module.h"
@end verbatim
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 following
this tutorial perfectly, you will have done a
@verbatim
./waf -d debug configure
@end verbatim
to configure the project to perform debug builds. You will also have done a,
@verbatim
./waf
@end verbatim
to build the project. So if you look in the directory @code{build/debug/ns-3}
you will find the four module includes shown above.
@section Ns3 Namespace
The next line in the @code{first.cc} script is a namespace statement:
@verbatim
using namespace ns3;
@end verbatim
The ns-3 project is implemented in a C++ namespace called @code{ns3}. This
groups all 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 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::} before all of the ns-3 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 the std namespace and
a @code{using namespace std;} statement.
@section 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 ``Other
Documentation'' in the navigation bar. If you select this link, you will be
taken to our documentation page. You will find links to our development
@code{ns-3-dev} documentation as well as that for our latest release. If you
select the @code{HTML} link you will be taken to the Doxygen documentation for
that version.
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.'' If you expand @code{Modules} you will see a list of ns-3 module
documentation. The concept of module here ties directly into the module
include files discussed above. It turns out that the ns-3 logging subsystem
is part of the @code{core} module, so go ahead and expand that node. Now,
open 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 you will see @code{NS_LOG_COMPONENT_DEFINE}.
It would probably be good to look for the ``Detailed Description'' of the
logging module now to get a feel for the overall operation and then 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.
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. 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 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 see that
there are a number of levels of detail that you 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
a message as packets are sent and received.
Now we will get directly to the business of creating a topology and running
a simulation. We will use the topology helper objects to make this job as
easy as possible.
@section Topology Helpers
@subsection NodeContainer
The next two lines of code in our script will actually create the ns-3 objects
that will represent the computers in the simulation.
@verbatim
NodeContainer nodes;
nodes.Create (2);
@end verbatim
Let's find the documentation for the first object before we continue. Another
way to get into the documentation system is via the @code{Classes} tab in the
HTML 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 ns-3 classes. Scroll down, looking for
@code{ns3::NodeContainer}. When you find the class, go ahead and select it to
go to the Doxygen.
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 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 ns-3 system to create two @code{Node} objects and stores the pointers
internally.
The nodes as they stand at this point 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 is a single point-to-point link between two nodes
so we'll construct one here.
@subsection 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, this corresponds roughly to peripheral cards and network cables.
Typically these two things are intimately tied together and one cannot expect
to interchange Ethernet devices and wireless channels, for example. Our
Topology Helpers follow this intimate coupling and therefore you will use a
single @code{PointToPointHelper} to configure and connect ns-3
@code{PointToPointNetDevice} and @code{PointToPointChannel} objects in this
script.
The next three lines in the @code{first.cc} script are
@verbatim
PointToPointHelper pointToPoint;
pointToPoint.SetDeviceParameter ("DataRate", StringValue ("5Mbps"));
pointToPoint.SetChannelParameter ("Delay", StringValue ("2ms"));
@end verbatim
The first line
@verbatim
PointToPointHelper pointToPoint;
@end verbatim
creates a @code{PointToPointHelper} object on the stack.
From a high-level perspective the next line,
@verbatim
pointToPoint.SetDeviceParameter ("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''
attribute. Most user-visible ns-3 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 @code{PointToPointNetDevice} we find a
``Delay'' attribute associated with the @code{PointToPointChannel}. THe
final line,
@verbatim
pointToPoint.SetChannelParameter ("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
creates.
@subsection 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{PoiintToPointChannel} objects
between them. Just as we used the @code{NodeContainer} topology helper object
to create the @code{Node}s 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 attributes previously set in the helper
are used to initialize the corresponding attributes in the created objects.
After executing the the @code{pointToPoint.Install (nodes)} call we will have
two nodes, each with an installed point-to-point net device and a
point-to-point channel between them. Both devices will send data at five
megabits per second over the channel which has a two millisecond transmission
delay.
@subsection InternetStackHelper
We have nodes and devices configured, but we don't have any protocol stacks
installed on our nodes. The next two lines of code 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.
@subsection 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 in the
code).
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.
The next line of code,
@verbatim
Ipv4InterfaceContainer interfaces = address.Assign (devices);
@end verbatim
performs the actual address assignment. In 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 made with IP addresses assigned. What
we need at this point are applications to generate traffic.
@section 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
ns-3 class @code{Application} called @code{UdpEchoServerApplication} and
@code{UdpEchoClientApplication}. Just as in the previous instances of ns-3
objects, 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.
@subsection 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 and connected using a point-to-point link.
@verbatim
UdpEchoServerHelper echoServer;
echoServer.SetPort (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 to help us create the actual applications. The second line
that has the @code{SetPort} call, is used to tell the helper to assign the
value nine to the ``Port'' attribute when creating
@code{UdpEchoServerApplication} objects.
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. It will be worth a slight digression
to undersand what is going on here.
@subsubsection Implicit Conversions
This is an example of a C++ @code{implicit conversion} at work. Many
programmers use 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}.
C++ will try to determine a sequence of type conversions to use in order to
convert an argument in a function call to the type of a corresponding paramter
in a method declaration. The method call in this case is,
@verbatim
ApplicationContainer serverApps = echoServer.Install (nodes.Get (1));
@end verbatim
If you look at the declaration of the Install method in the source (or the
Doxygen) you will see,
@verbatim
ApplicationContainer
UdpEchoServerHelper::Install (NodeContainer c)
{
...
}
@end verbatim
Now, the @code{Get} method of the @code{NodeContainer} returns a smart pointer
to a node object:
@verbatim
Ptr<Node>
NodeContainer::Get (uint32_t i) const
{
...
}
@end verbatim
C++ notices that it needs to convert a type @code{Ptr<Node>} into a type
@code{NodeContainer}. It turns out that @code{NodeContainer} has a
constructor that takes a @code{Ptr<Node>} as a parameter.
@verbatim
NodeContainer::NodeContainer (Ptr<Node> node)
{
...
}
@end verbatim
The C++ compiler implicitly provides the @code{Ptr<Node>} returned from the
@code{NodeContainer::Get} to the above constructor for @code{NodeContainer} to
make a new @code{NodeContainer} to pass to the @code{Install} method of the
@code{UdpEchoServerHelper} object.
Taking advantage of these implicit conversion sequences can allow you to
avoid doing a lot of typing. The result is also fairly intuitive if you
don't pay close attention to the called method signatures. If you are
one of those folks that pays close attention, it does have the downside of
sometimes being surprising when you, for example, look for the method
in @code{UdpEchoServerHelper} named @code{Install} that takes a parameter
@code{Ptr<Node>} and cannot find it.
@subsection UdpEchoServerHelper Continued
Returning to the example script, we are looking at the following code snippet.
@verbatim
UdpEchoServerHelper echoServer;
echoServer.SetPort (9);
ApplicationContainer serverApps = echoServer.Install (nodes.Get (1));
serverApps.Start (Seconds (1.0));
serverApps.Stop (Seconds (10.0));
@end verbatim
We now see that @code{echoServer.Install} is going to install an
@code{UdpEchoServerApplication} on the node found at index number one of the
@code{NodeContainer} we use to manage our nodes. @code{Install} will return
a container that has all of the applications (one in this case since we passed
a @code{NodeContainer} containing one node) made by the helper.
Applications require a time to ``start'' generating traffic and a time to
``stop.'' These times are set using @code{ApplicationContainer} methods
@code{Start} and @code{Stop}. These methods take @code{Time} parameters.
In this case, we use an explicit conversion sequence to take a c++ double
1.0 and convert it to a @code{Time} object using a @code{Seconds ()} cast.
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 implicilty declared
a simulation event at ten seconds, the simulation will last at least ten
seconds.
@subsection UdpEchoClientHelper
The echo client application is set up in a method similar to the server.
There is an underlying @code{UdpEchoClientApplication} that is managed by an
@code{UdpEchoClientHelper}.
@verbatim
UdpEchoClientHelper echoClient;
echoClient.SetRemote (interfaces.GetAddress (1), 9);
echoClient.SetAppAttribute ("MaxPackets", UintegerValue (1));
echoClient.SetAppAttribute ("Interval", TimeValue (Seconds (1.)));
echoClient.SetAppAttribute ("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, we need to set four different attributes. The first
attribute is set using the @code{SetRemote} method. Here we refer back to
the @code{Ipv4InterfaceContainer} we created to keep track of the IP addresses
we assigned to our devices.
@verbatim
Ipv4InterfaceContainer interfaces = address.Assign (devices);
@end verbatim
In this case, the zeroth interface in the @code{interfaces} container
cooresponds to the IP address of the zeroth node in the @code{nodes} container.
The first interface in the @code{interfaces} container cooresponds to the IP
address of the first node in the @code{nodes} container. So, in the following
line of code, we are setting the remote address of the client to be the IP
address assigned to the node on which the server resides. We tell it to send
to port nine.
@verbatim
echoClient.SetRemote (interfaces.GetAddress (1), 9);
@end verbatim
The ``MaxPackets'' attribute tells the client the maximum number of packets
it can send. The ``Interval'' attribute tells the cleint how long to wait
between packets and the ``PacketSize'' attribute tells the client how large
its packets should be. In this case 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 @code{Simulator} singleton which is accessed via the global
function @code{Simulator::Run}
@verbatim
Simulator::Run ();
@end verbatim
When we 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
10.0 seconds. When @code{Simulator::Run} is called, it 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. Then
it will run the event scheduled for t=2.0 seconds which will start the echo
client application. The start event implementation in the echo cleint 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
which will be automatically scheduled and which will perform the packet echo
according to the various timing parameters that we have set in the script.
Eventually, since we only sent one packet, the chain of events triggered by
the single client echo request will taper off and the simulation will go
idle. Once this happens, the remaining events are 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 complete.
All that remains is to clean up after ourselves. This is done by calling the
global function @code{Simulator::Destroy}. As the helper functions (or low
level ns-3 code) executed they arranged it so that hooks were inserted in the
simulator to destruct all of the objects that were created. You do not have
to keep track of all of these objects yourself --- all you have to do is to
call @code{Simulator::Destroy} and exit. The remaining lines of our first
ns-3 script, @code{first.cc}, do just that
@verbatim
Simulator::Destroy ();
return 0;
}
@end verbatim
@section 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. Let's try it. Copy @code{examples/first.cc} into @code{scratch}:
@verbatim
~/repos/ns-3-tutorial > cp examples/first.cc scratch
@end verbatim
and then build it using waf,
@verbatim
~/repos/ns-3-tutorial > ./waf
Entering directory `/home/craigdo/repos/ns-3-tutorial/build'
[432/477] cxx: scratch/first.cc -> build/debug/scratch/first_2.o
[433/477] cxx: scratch/simple.cc -> build/debug/scratch/simple_3.o
[475/477] cxx_link: build/debug/scratch/first_2.o -> build/debug/scratch/first
Compilation finished successfully
~/repos/ns-3-tutorial >
@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 direcory):
@verbatim
~/repos/ns-3-tutorial > ./waf --run scratch/first
Entering directory `/home/craigdo/repos/ns-3-tutorial/build'
Compilation finished successfully
Sent 1024 bytes to 10.1.1.2
Received 1024 bytes from 10.1.1.1
Received 1024 bytes from 10.1.1.2
~/repos/ns-3-tutorial >
@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
note 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 receive the 1024 bytes
from 10.1.1.1. The echo server silently echoes the packet and you see the
echo client note that it has received its packet back from the server.

View File

@@ -0,0 +1,275 @@
@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 and Compiling ns-3::
@end menu
@c ========================================================================
@c Downloading and Compiling ns-3
@c ========================================================================
@node Downloading and Compiling ns-3
@section Downloading and Compiling ns-3
@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/}. Official
releases of ns-3 will be numbered as @code{ns-3.<release>} with any requred
hotfixes added as minor release numbers. For example, a second hotfix to a
hypothetical release nine of ns-3 would be numbered @code{ns-3.9.2}.
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 staying with an official
release.
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.1) 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'' 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.nanam.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 3276 changesets with 12301 changes to 1353 files
594 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 LICENSE regression/ scratch/ utils/ waf.bat*
doc/ ns3/ RELEASE_NOTES src/ VERSION wscript
examples/ README samples/ tutorial/ waf*
@end verbatim
You are now ready to build the ns-3 distribution.
@section Building and Testing
@cindex Waf!build
@cindex Waf!configure
@cindex Waf!debug
@cindex Waf!compile
@cindex Waf!check
@cindex Waf!regression
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 compiler version : ok Version 4.1.2
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 -O2 -DNDEBUG : ok
Checking for flags -g -DDEBUG : ok
Checking for flags -g3 -O0 -DDEBUG : ok
Checking for flags -Wall : 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
Checking for package gtk+-2.0 >= 2.12 : not found
Checking for package goocanvas gthread-2.0 : not found
Checking for program diff : ok /usr/bin/diff
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
@cindex tests|unit
You can run the unit tests of the ns-3 distribution by running the ``check''
command,
@verbatim
./waf check
@end verbatim
You should see a report from each unit test that executes indicating that the
test has passed.
@verbatim
~/repos/ns-3-dev > ./waf check
Entering directory `/home/craigdo/repos/ns-3-dev/build'
Compilation finished successfully
PASS AddressHelper
PASS Wifi
PASS DcfManager
...
PASS Object
PASS Ptr
PASS Callback
~/repos/ns-3-dev >
@end verbatim
@cindex tests|regression
This command is typically run by @code{users} to quickly verify that an ns-3
distribution has built correctly.
You can also run @code{regression tests} to ensure that your distribution and
tool chain have produced binaries that generate trace files which are
compatible with reference trace files stored in a central location. To run the
regression tests you run Waf with the regression flag.
@verbatim
./waf --regression
@end verbatim
Waf will verify that the current files in the ns-3 distribution are built and
will then look for trace files in the aforementioned centralized location. If
your tool chain includes Mercurial, the regression tests will be downloaded
from a repository at @code{code.nsnam.org}. If you do not have Mercurial
installed, the reference traces will be downloaded from a tarball located in
the @code{releases} section of @code{www.nsnam.org}. The particular name of
the reference trace location is built from the ns-3 version located in the
VERSION file, so don't change that string.
Once the reference traces are downloaded to your local machine, Waf will run
a number of tests that generate trace files. The content of these trace
files are compared with the reference traces just downloaded. If they are
identical, the regression tests report a PASS status. If the regression tests
pass, you should see something like,
@verbatim
~/repos/ns-3-dev > ./waf --regression
Entering directory `/home/craigdo/repos/ns-3-dev/build'
Compilation finished successfully
========== Running Regression Tests ==========
Synchronizing reference traces using Mercurial.
http://code.nsnam.org/ns-3-dev-ref-traces
Done.
PASS test-csma-broadcast
PASS test-csma-multicast
PASS test-csma-one-subnet
PASS test-csma-packet-socket
PASS test-simple-error-model
PASS test-simple-global-routing
PASS test-simple-point-to-point-olsr
PASS test-tcp-large-transfer
PASS test-udp-echo
~/repos/ns-3-dev >
@end verbatim
If a regression tests fails you will see a FAIL indication along with a
pointer to the offending trace file and its associated reference trace file
along with a suggestion on how to run diff in order to see what has gone awry.
@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.}

View File

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -0,0 +1,156 @@
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;
}

View File

@@ -0,0 +1,105 @@
\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

View File

@@ -66,7 +66,7 @@ along with this program. If not, see @uref{http://www.gnu.org/licenses/}.
@contents
@ifnottex
@node Top, Overview, Full Table of Contents
@node Top, Introduction, Full Table of Contents
@top ns-3 Tutorial (html version)
For a pdf version of this tutorial,
@@ -76,29 +76,18 @@ see @uref{http://www.nsnam.org/docs/tutorial.pdf}.
@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::
* Introduction::
* Geting Started::
* Conceptual Overview::
* Tweaking Ns-3::
* Building Topologies::
@end menu
@include introduction.texi
@include log.texi
@include attributes.texi
@include statistics.texi
@include helpers.texi
@include getting-started.texi
@include conceptual-overview.texi
@include tweaking.texi
@include building-topologies.texi
@printindex cp

978
doc/tutorial/tweaking.texi Normal file
View File

@@ -0,0 +1,978 @@
@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 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.
@section Logging Overview
Many large systems support some kind of message logging facility, and ns-3
is not an exception. In some cases, only error messages are logged to the
``operator console'' (which is typically @code{stderr} in Unix-based systems).
In other systems, warning messages may be output as well as more detailed
informational messages. In some cases, logging facilities are used to output
debug messages which can quickly turn the output into a blur.
Ns-3 takes the view that all of these verbosity levels are useful and se
provides a selectable, multi-level approach to message logging. Logging can
be disabled completely, enabled on a component-by-component basis, enabled
globally and has selectable verbosity levels. The ns-3 log module provides
a straightforward, relatively easy to use way to get some kinds of information
out of your simulation.
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 in 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
NS_LOG_UNCOND -- Log the associated message unconditionally.
@end itemize
Each level can be requested singly or cumulatively; and can be set using a
shell environment variable (NS_LOG) or by logging system function call. As
was seen earlier in the tutorial, the logging system has Doxygen documentation
so now would be a good time to peruse the Logging Module documentation.
Now that you have read the documentation in great detail, we can get some
interesting information out of the @code{first.cc} example script you dropped
in the scratch directory after the script walkthrough.
@section Enabling Logging Using the NS_LOG Environment Variable
@cindex NS_LOG
First, let's use the NS_LOG environment variable to turn on some more logging
in the @code{first.cc} script you have already built. Go ahead and run the
script just as you did previously,
@verbatim
~/repos/ns-3-tutorial > ./waf --run scratch/first
Entering directory `/home/craigdo/repos/ns-3-tutorial/build'
Compilation finished successfully
Sent 1024 bytes to 10.1.1.2
Received 1024 bytes from 10.1.1.1
Received 1024 bytes from 10.1.1.2
~/repos/ns-3-tutorial >
@end verbatim
The ``Sent'' and ``Received'' messages 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 are using an sh-like shell that uses the``VARIABLE=value''
syntax. If you are using a csh-like shell, then you will have to convert to
``setenv VARIABLE value'' syntax.
Let's ask the UDP echo client application to print a little more information.
Right now, it is responding to the following line of code in @code{first.cc},
@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
~/repos/ns-3-tutorial > export NS_LOG=UdpEchoClientApplication=level_all
@end verbatim
This sets the 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 you should see the following
output:
@verbatim
~/repos/ns-3-tutorial > ./waf --run scratch/first
Entering directory `/home/craigdo/repos/ns-3-tutorial/build'
Compilation finished successfully
UdpEchoClientApplication:UdpEchoClient()
UdpEchoClientApplication:StartApplication()
UdpEchoClientApplication:ScheduleTransmit()
UdpEchoClientApplication:Send()
Sent 1024 bytes to 10.1.1.2
Received 1024 bytes from 10.1.1.1
UdpEchoClientApplication:HandleRead(0x62c640, 0x62cd70)
Received 1024 bytes from 10.1.1.2
UdpEchoClientApplication:StopApplication()
UdpEchoClientApplication:DoDispose()
UdpEchoClientApplication:~UdpEchoClient()
~/repos/ns-3-tutorial >
@end verbatim
The only additional debug information provided by the application is from
the NS_LOG_FUNCTION level. You can now see a log of the function calls that
were made to the application. If you look closely you will notice a single
colon between the string @code{UdpEchoClientApplication} and the method name
where you might have expected a C++ scope operator (@code{::}). This is
intentional. The name is not actually a class name, it is a logging component
name. When there is a one-to-one correspondence between a source file and a
class, this will generally be the class name but you should understand that
it is not actually a class name, and there is a single colon to separate the
logging component name from the function name that is printed.
It turns out that in come cases, it can be hard to determine which method
actually generates a log message. If you look in the text above, you may
wonder where the string ``@code{Received 1024 bytes from 10.1.1.1}'' comes
from. You can resolve this by ORing 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 single quotes are required since the vertical bar is 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
~/repos/ns-3-tutorial > ./waf --run scratch/first
Entering directory `/home/craigdo/repos/ns-3-tutorial/build'
Compilation finished successfully
UdpEchoClientApplication:UdpEchoClient()
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(0x62c710, 0x62ce40)
UdpEchoClientApplication:HandleRead(): Received 1024 bytes from 10.1.1.2
UdpEchoClientApplication:StopApplication()
UdpEchoClientApplication:DoDispose()
UdpEchoClientApplication:~UdpEchoClient()
~/repos/ns-3-tutorial >
@end verbatim
You can now see all of the messages coming from the UDP echo client application
are identified as such. The remaining message must be coming from the UDP
echo server application. We can enable that component by entering a colon
separated list of components in the NS_LOG environment variable.
@verbatim
export 'NS_LOG=UdpEchoClientApplication=level_all|prefix_func:
UdpEchoServerApplication=level_all|prefix_func'
@end verbatim
Note that you will need to remove the newline after the @code{:} in the
example text above.
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
~/repos/ns-3-tutorial > ./waf --run scratch/first
Entering directory `/home/craigdo/repos/ns-3-tutorial/build'
Compilation finished successfully
UdpEchoServerApplication:UdpEchoServer()
UdpEchoClientApplication:UdpEchoClient()
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(0x62c760, 0x62ce90)
UdpEchoClientApplication:HandleRead(): Received 1024 bytes from 10.1.1.2
UdpEchoServerApplication:StopApplication()
UdpEchoClientApplication:StopApplication()
UdpEchoClientApplication:DoDispose()
UdpEchoServerApplication:DoDispose()
UdpEchoClientApplication:~UdpEchoClient()
UdpEchoServerApplication:~UdpEchoServer()
~/repos/ns-3-tutorial >
@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
If you run the script now, you should see the following output:
@verbatim
~/repos/ns-3-tutorial > ./waf --run scratch/first
Entering directory `/home/craigdo/repos/ns-3-tutorial/build'
Compilation finished successfully
0ns UdpEchoServerApplication:UdpEchoServer()
0ns UdpEchoClientApplication:UdpEchoClient()
1000000000ns UdpEchoServerApplication:StartApplication()
2000000000ns UdpEchoClientApplication:StartApplication()
2000000000ns UdpEchoClientApplication:ScheduleTransmit()
2000000000ns UdpEchoClientApplication:Send()
2000000000ns UdpEchoClientApplication:Send(): Sent 1024 bytes to 10.1.1.2
2003686400ns UdpEchoServerApplication:HandleRead(): Received 1024 bytes
from 10.1.1.1
2003686400ns UdpEchoServerApplication:HandleRead(): Echoing packet
2007372800ns UdpEchoClientApplication:HandleRead(0x62c8c0, 0x62d020)
2007372800ns UdpEchoClientApplication:HandleRead(): Received 1024 bytes
from 10.1.1.2
10000000000ns UdpEchoServerApplication:StopApplication()
10000000000ns UdpEchoClientApplication:StopApplication()
UdpEchoClientApplication:DoDispose()
UdpEchoServerApplication:DoDispose()
UdpEchoClientApplication:~UdpEchoClient()
UdpEchoServerApplication:~UdpEchoServer()
~/repos/ns-3-tutorial >
@end verbatim
You can see that the constructor for the UdpEchoServer was called at a
simulation time of 0 nanoseconds. This is actually happening before the
simulation starts. The same for the UdpEchoClient constructor.
Recall that the @code{first.cc} script started the echo server application at
one second into the simulation. You can now see that the
@code{StartApplication} of the server is, in fact, called at one second (or
one billion nanoseconds). 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 as the packet is sent across the point-to-point link is 3.6864
milliseconds. You see the echo server logging a message telling you that it
has echoed the packet and then, after a delay, you see the echo client receive
the echoed packet.
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 is the logging component wildcard. This will turn on all of the
logging in all of the components in the system. I won't reproduce the output
here (as of this writing it produces 772 lines of output for the single packet
echo) but you can redirect this information into a file and look through it
with your favorite editor if you like,
@verbatim
~/repos/ns-3-tutorial > ./waf --run scratch/first >& log.out
@end verbatim
I personally use this quite a bit 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. When I have a general idea about what is going wrong, I
transition into a debugger for fine-grained examination of the problem. This
output can be especially useful when your script does something completely
unexpected.
@section 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{first.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
add some logging. The macro to add an informational level log message is
@code{NS_LOG_INFO}. Add one just before we start creating the nodes that
tells you that the script is ``Creating Topology.'' This is done as in this
code snippet,
@verbatim
NS_LOG_INFO ("Creating Topology");
@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
~/repos/ns-3-tutorial > export NS_LOG=
@end verbatim
Now, if you run the script, you will not see your new message since its
associated logging component has not been enabled. In order to see your
message you will have to enable the @code{FirstScriptExample} logging
component with a level greater than or equal to @code{NS_LOG_INFO}. If
you just want to see this particular level of logging, you can enable that
by,
@verbatim
~/repos/ns-3-tutorial > export NS_LOG=FirstScriptExample=info
@end verbatim
If you now run the script you will see your new logging message,
@verbatim
~/repos/ns-3-tutorial > ./waf --run scratch/first
Entering directory `/home/craigdo/repos/ns-3-tutorial/build'
Compilation finished successfully
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
~/repos/ns-3-tutorial >
@end verbatim
As previously described, this does not also enable the lower levels of logging
but selects out the single infomational level.
As we outlined in the Logging Overview, there are currently seven levels of
logging verbosity you can use and you can also prefix your various log messages
with component name and simulation time.
@c ========================================================================
@c Using Command Line Arguments
@c ========================================================================
@node Using Command Line Arguments
@section Using Command Line Arguments
@section Overriding Default Attributes
@cindex arguments|command line
Another way you can change the way that ns-3 scripts behave without editing
and building scripts is via @emph{command line arguments.} We provide a
mechanism to parse command line arguments and automatically set local and
global variables based on those arguments.
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 ns-3 global variable and attribute systems. Go ahead and add that
two lines of code to the @code{first.cc} script at the start of @code{main}.
Go ahead and build the script and run it, but ask the script for help in the
following way,
@verbatim
~/repos/ns-3-tutorial > ./waf --run "scratch/first --PrintHelp"
@end verbatim
This will ask way to run the @code{scratch/first} script and pass the command
line argument @code{--PrintHelp} to the script. The command line parser will
now see the @code{PrintHelp} argument and respond with,
@verbatim
~/repos/ns-3-tutorial > ./waf --run ``scratch/first --PrintHelp''
Entering directory `/home/craigdo/repos/ns-3-tutorial/build'
Compilation finished successfully
--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.
~/repos/ns-3-tutorial >
@end verbatim
Let's focus on the @code{--PrintAttributes} option. We have already hinted
at the attribute system while walking through the @code{first.cc} script. We
looked at the following lines of code,
@verbatim
PointToPointHelper pointToPoint;
pointToPoint.SetDeviceParameter ("DataRate", StringValue ("5Mbps"));
pointToPoint.SetChannelParameter ("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 attributes of the PointToPointNetDevice. The help
listing says that we should provide a typeid. This corresponds to the class
name of the class to which the attributes belong. In this case it will be
@code{ns3::PointToPointNetDevice}. Let's go ahead and type in,
@verbatim
./waf --run "scratch/first --PrintAttributes=ns3::PointToPointNetDevice"
@end verbatim
The system will print out all of the attributes of this kind of net device.
Among the attributes you will see listed is,
@verbatim
--ns3::PointToPointNetDevice::DataRate=[32768bps]:
The default data rate fo r point to point links
@end verbatim
This is the default value that will be used when a PointToPointNetDevice is
created in the system. We overrode this default with the parameter setting
in the PointToPointHelper above. Let's use the default values for the
PointToPoint devices and channels by deleting the SetDeviceParameter call and
the SetChannelParameter call from the @code{first.cc} we have in the scratch
directory.
Your script should now just declare the PointToPointHelper and not do any
sets 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. Now 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
~/repos/ns-3-tutorial > ./waf --run scratch/first
Entering directory `/home/craigdo/repos/ns-3-tutorial/build'
Compilation finished successfully
0ns UdpEchoServerApplication:UdpEchoServer()
1000000000ns UdpEchoServerApplication:StartApplication()
Sent 1024 bytes to 10.1.1.2
2257324218ns Received 1024 bytes from 10.1.1.1
2257324218ns Echoing packet
Received 1024 bytes from 10.1.1.2
10000000000ns UdpEchoServerApplication:StopApplication()
UdpEchoServerApplication:DoDispose()
UdpEchoServerApplication:~UdpEchoServer()
~/repos/ns-3-tutorial >
@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.0036864 seconds. Now it is
receiving the packet at about 2.257 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,
@verbatim
./waf --run "scratch/first --ns3::PointToPointNetDevice::DataRate=5Mbps"
@end verbatim
This will set the default value of the @code{DataRate} attribute back to
five megabits per second. To get the old behavior back, we will have to set
the speed-of-light delay of the channel. We can ask the command line system
to print out the @code{Attributes} of the channel just like we did the net
device:
@verbatim
./waf --run "scratch/first --PrintAttributes=ns3::PointToPointChannel"
@end verbatim
and we discover the @code{Delay} attribute.
@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/first
--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
Compilation finished successfully
0ns UdpEchoServerApplication:UdpEchoServer()
1000000000ns UdpEchoServerApplication:StartApplication()
Sent 1024 bytes to 10.1.1.2
2003686400ns Received 1024 bytes from 10.1.1.1
2003686400ns Echoing packet
Received 1024 bytes from 10.1.1.2
10000000000ns UdpEchoServerApplication:StopApplication()
UdpEchoServerApplication:DoDispose()
UdpEchoServerApplication:~UdpEchoServer()
@end verbatim
Note that the packet is received by the server at 2.0036864 seconds. We
could actually set any of the attributes used in the script in this way. In
particular we could set the @code{UdpEchoClient} attribute @code{MaxPackets}
to some other value than one.
How would you go about that? Give it a try. Remember you have to comment
out the place we override the default attribute in the script. Then you
have to rebuild the script using the default. You will also have to find the
syntax for actually setting the new default atribute 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/first
--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 main function. We'll initialize it to one to match our previous
default behavior. To allow the command line parser to change this value, we
need to hook the value into the parser. Do this by adding a call to
@code{AddValue}. Go ahead and change the @code{scratch/first.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}
attribute and change it so that it is set to the variable @code{nPackets}
instead of the constant @code{1} as below.
@verbatim
echoClient.SetAppAttribute ("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.
@verbatim
~/repos/ns-3-tutorial > ./waf --run "scratch/first --PrintHelp"
Entering directory `/home/craigdo/repos/ns-3-tutorial/build'
Compilation finished successfully
--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
~/repos/ns-3-tutorial >
@end verbatim
If you want to specify the number of packets to echo, you can now do so by
setting the @code{nPackets} argument,
@verbatim
~/repos/ns-3-tutorial > ./waf --run "scratch/first --nPackets=2"
Entering directory `/home/craigdo/repos/ns-3-tutorial/build'
Compilation finished successfully
Sent 1024 bytes to 10.1.1.2
Received 1024 bytes from 10.1.1.1
Received 1024 bytes from 10.1.1.2
Sent 1024 bytes to 10.1.1.2
Received 1024 bytes from 10.1.1.1
Received 1024 bytes from 10.1.1.2
~/repos/ns-3-tutorial >
@end verbatim
If you are an ns-3 user, you can use the command line argument system to
control global values and attributes. If you are a model author, you can
add new attributes to your Objects and they will automatically be available
for setting by your users through the command line system. If you are a
script author, you can add new variables to your scripts and hook them into
the command line system quite painlessly.
@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 apply:
@verbatim
#include <iostream>
...
int main ()
{
...
std::cout << "The value of x is " << x << std::endl;
...
}
@end verbatim
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 for interested trace sinks.
Trace sources are not useful by themselves, they must be ``connected'' to
other pieces of code that actually do something useful with the information
provided by the sink. Trace sinks are consumers of the events and data
provided by the trace sources. For example, one could create a trace sink t
hat would (when connected to the trace source of the previous example) print
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 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 editing only the
user script.
What remains to be defined is a way for users to find these hooks (tracing
sources) and attach sinks to them. A tracing namespace is defined for
this purpose.
In this tutorial, we will walk through some pre-defined sources and sinks and
show how they may be customized with little user effort. See the ns-3 manual
or how-to sections for information on advanced tracing configuration including
extending the tracing namespace and creating new tracing sources.
@cindex tracing
@cindex tracing|ASCII
@subsection ASCII Tracing
Ns-3 provides an ASCII trace helper that is a wrapper around low-level
tracing system. This helper lets you configure some useful and easily
understood packet traces easily. The output of a trace of a simulation run
is an ASCII file --- thus the name. For those familiar with @command{ns-2}
output, this type of trace is analogous to the @command{out.tr} generated
by many scripts.
@cindex tracing|packets
Let's just jump right in and add some ASCII tracing output to our
@code{first.cc} script. The first thing you need to do is to add the
following code to the script just before the call to @code{Simulator::Run ()}.
@verbatim
std::ofstream ascii;
ascii.open ("first.tr");
PointToPointHelper::EnableAsciiAll (ascii);
@end verbatim
The first two lines are just vanilla C++ code to open a stream that will be
written to a file named ``first.tr.'' See your favorite C++ tutorial if you
are unfamiliar with this code. The last line of code in the snippet above
tells ns-3 that you want to enable ASCII tracing on all point-to-point devices
in your simulation; and you want the (provided) trace sinks to write out
information about packet movement in ASCII format to the stream provided.
For those familiar with @command{ns-2}, the traced events are equivalent
to the popular trace points that log "+", "-", "d", and "r" events.
Since we have used a @code{std::ofstream} object, we also need to include the
appropriate header. Add the following line to the script (I typically add it
above the ns-3 includes):
@verbatim
#include <fstream>
@end verbatim
You can now build the script and run it from the command line:
@verbatim
./waf --run scratch/first
@end verbatim
@cindex first.tr
Just as you have seen previously, you may see some messages from Waf and then
the ``Compilation finished successfully'' message. The following messages are
from the running program. When it ran, the program will have created a file
named @code{first.tr}. Because of the way that Waf works, the file is not
created in the local directory, it is created at the top-level directory of
the repository by default. If you want to control where the traces are saved
you can use the @code{--cwd} option of Waf to specify this. We have not done
so, thus we need to change into the top level directory of our repo and take a
look at the file @code{first.tr} in your favorite editor.
@subsubsection Parsing Ascii Traces
@cindex parsing ascii traces
There's a lot of information there in a pretty dense form, but the first thing
to notice is that there are a number of distinct lines in this file. It may
be difficult to see this clearly unless you widen your windows considerably.
Each line in the file corresponds to a @emph{trace event}. In this case
we are tracing events on the @emph{device queue} present in every net device
on every node in the simulation. The device queue is a queue through which
every packet destined for a channel must pass --- it is the device
@emph{transmit} queue. Note that each line in the trace file begins with a
lone character (has a space after it). This character will have the following
meaning:
@cindex ascii trace|enqueue
@cindex ascii trace|dequeue
@cindex ascii trace|drop
@cindex ascii trace|receive
@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. 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 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
queue operation. We have a @code{+} character, so this corresponds to an
@emph{enqueue} operation. The second line (reference 01) is the simulation
time expressed in seconds. You may recall that we asked the
@code{UdpEchoClient} to start sending packets at two seconds. Here we again
see confirmation that this is, indeed, happening.
@cindex node number
@cindex net device number
@cindex smart pointer
The next line of the example listing (reference 02) tell us the trace source
that originated this even expressed in the tracing namespace. You can think
of the tracing womewhat like you would a filesystem namespace. The root of
the namespace is the @code{NodeList}. This corresponds to a container in the
ns-3 code that contains all of the nodes that were created in the system.
Just as a filesystem has may have directories under the root, we have node
numbers in the @code{NodeList}. The string @code{/NodeList/0} therefore
refers to the zeroth node in the @code{NodeList} which we can think of as
``node 0.'' In each node there is a list of devices that have been installed.
This list appears next. You can see that this trace event comes from
@code{DeviceList/0} which is the zeroth device installed in the node.
The next string, @code{$ns3::PointToPointNetDevice} tells you what kind of
device it is that is in the zeroth position of the device list for node zero.
This should by now be completely expected. Recall that the operation @code{+}
found at reference 00 means an enqueue operation on the transmit queue of the
device. This is reflected in the final segments of the ``trace path'' which
are @code{TxQueue/Enqueue}.
The remaining lines in the trace should be fairly intuitive. References 03-04
indicate that the packet is encapulated in the point-to-point protocol.
References 05-07 show that the packet has an IP version four header and has
originated from IP address 10.1.1.1 and is destined for 10.1.1.2. References
08-09 show that this is a UDP packet from and finally reference 10 shows that
the payload is the expected 1024 bytes.
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/Rx
03 ns3::PppHeader (
04 Point-to-Point Protocol: IP (0x0021))
05 ns3::Ipv4Header (
06 tos 0x0 ttl 64 id 0 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
Notice that the trace operation is now @code{r} and the simulation time has
increased to 2.25732 seconds. If you have been following the tutorial steps
closely this means that you have left the @code{DataRate} of the net devices
set to their default value of 32768 bps with a channel @code{Delay} of two
milliseconds. This time should be familiar as you have seen it before in a
previous section.
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{/Rx}). It should be quite easy for you to follow the
progress of the packet through the topology by looking at the rest of the
traces in the file.
@subsection PCAP Trace Helper
@cindex pcap
@cindex Wireshark
The @command{ns-3} @emph{pcap trace helper} 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.
We encourage users to exploit the many tools available for analyzing pcap
traces. In this tutorial, we show how tcpdump and Wireshark can be used.
@cindex tracing|pcap
The code used to enable pcap tracing is a one-liner.
@verbatim
PointToPointHelper::EnablePcapAll ("first");
@end verbatim
Go ahead and insert this line of code after the ASCII tracing code we just
added to @code{scratch/first.cc}. Notice that we only gave the pcap trace
helper call the string, ``first,'' and not ``first.pcap'' or something
similar. This is because the parameter is a prefix, not a complete file name.
The pcap trace helper will actually create a trace file for every device in
the simulation that generates a traced event. The file names will be built
using the prefix, the node number, the device number and a ``.pcap'' suffix.
In our example script, we will see a files named ``first-0-0.pcap'' and
``first.1-0.pcap'' which are the pcap traces for node 0, device 0 and node 1,
device 1, respectively.
You can now run the script as you have been:
@verbatim
./waf --run scratch/first
@end verbatim
If you look at the top level directory of your distribution, you should now
see three log files: @code{first.tr} is the ASCII trace file we have
previously examined. @code{first-0-0.pcap} and @code{first-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. Output from dumping both files is shown below:
@verbatim
~/repos/ns-3-tutorial > /usr/sbin/tcpdump -r first-0-0.pcap -nn -tt
reading from file first-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
~/repos/ns-3-tutorial > /usr/sbin/tcpdump -r first-1-0.pcap -nn -tt
reading from file first-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
~/repos/ns-3-tutorial >
@end verbatim
You can see in the dump of ``first-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 (of ``first-1-0.pcap'') you can see that packet being received
at 2.257324 seconds. You see the packet being echoed 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 unfamilar 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}.

View File

@@ -0,0 +1,27 @@
/* -*- 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/core-module.h"
NS_LOG_COMPONENT_DEFINE ("HelloSimulator");
using namespace ns3;
int
main (int argc, char *argv[])
{
NS_LOG_UNCOND ("Hello Simulator");
}