swap in new tutorial
This commit is contained in:
300
doc/tutorial/building-topologies.texi
Normal file
300
doc/tutorial/building-topologies.texi
Normal 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.
|
||||
809
doc/tutorial/conceptual-overview.texi
Normal file
809
doc/tutorial/conceptual-overview.texi
Normal 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.
|
||||
275
doc/tutorial/getting-started.texi
Normal file
275
doc/tutorial/getting-started.texi
Normal 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.}
|
||||
|
Before Width: | Height: | Size: 6.0 KiB After Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
156
doc/tutorial/in-process/tutorial.css
Normal file
156
doc/tutorial/in-process/tutorial.css
Normal 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;
|
||||
}
|
||||
105
doc/tutorial/in-process/tutorial.texi
Normal file
105
doc/tutorial/in-process/tutorial.texi
Normal 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
|
||||
@@ -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
978
doc/tutorial/tweaking.texi
Normal 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}.
|
||||
27
examples/hello-simulator.cc
Normal file
27
examples/hello-simulator.cc
Normal 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");
|
||||
}
|
||||
Reference in New Issue
Block a user