Run utils/trim-trailing-whitespace.py on codebase

This commit is contained in:
Tom Henderson
2022-06-05 21:01:11 -07:00
parent 7c47d8af08
commit b6a5ee8151
1385 changed files with 16008 additions and 16008 deletions

View File

@@ -9,26 +9,26 @@ Building Topologies
Building a Bus Network Topology
*******************************
In this section we are going to expand our mastery of |ns3| network
In this section we are going to expand our mastery of |ns3| network
devices and channels to cover an example of a bus network. |ns3|
provides a net device and channel we call CSMA (Carrier Sense Multiple Access).
The |ns3| CSMA device models a simple network in the spirit of
Ethernet. A real Ethernet uses CSMA/CD (Carrier Sense Multiple Access with
Collision Detection) scheme with exponentially increasing backoff to contend
for the shared transmission medium. The |ns3| CSMA device and
The |ns3| CSMA device models a simple network in the spirit of
Ethernet. A real Ethernet uses CSMA/CD (Carrier Sense Multiple Access with
Collision Detection) scheme with exponentially increasing backoff to contend
for the shared transmission medium. The |ns3| CSMA device and
channel models only a subset of this.
Just as we have seen point-to-point topology helper objects when constructing
point-to-point topologies, we will see equivalent CSMA topology helpers in
this section. The appearance and operation of these helpers should look
this section. The appearance and operation of these helpers should look
quite familiar to you.
We provide an example script in our ``examples/tutorial`` directory. This script
builds on the ``first.cc`` script and adds a CSMA network to the
point-to-point simulation we've already considered. Go ahead and open
builds on the ``first.cc`` script and adds a CSMA network to the
point-to-point simulation we've already considered. Go ahead and open
``examples/tutorial/second.cc`` in your favorite editor. You will have already seen
enough |ns3| code to understand most of what is going on in this
enough |ns3| code to understand most of what is going on in this
example, but we will go over the entire script and examine some of the output.
Just as in the ``first.cc`` example (and in all ns-3 examples) the file
@@ -53,9 +53,9 @@ find a similar "drawing" in most of our examples.
In this case, you can see that we are going to extend our point-to-point
example (the link between the nodes n0 and n1 below) by hanging a bus network
off of the right side. Notice that this is the default network topology
off of the right side. Notice that this is the default network topology
since you can actually vary the number of nodes created on the LAN. If you
set nCsma to one, there will be a total of two nodes on the LAN (CSMA
set nCsma to one, there will be a total of two nodes on the LAN (CSMA
channel) --- one required node and one "extra" node. By default there are
three "extra" nodes as seen below:
@@ -73,9 +73,9 @@ Then the ns-3 namespace is ``used`` and a logging component is defined.
This is all just as it was in ``first.cc``, so there is nothing new yet.
::
using namespace ns3;
NS_LOG_COMPONENT_DEFINE ("SecondScriptExample");
The main program begins with a slightly different twist. We use a verbose
@@ -112,7 +112,7 @@ entirely comfortable with the following code at this point in the tutorial.
nCsma = nCsma == 0 ? 1 : nCsma;
The next step is to create two nodes that we will connect via the
The next step is to create two nodes that we will connect via the
point-to-point link. The ``NodeContainer`` is used to do this just as was
done in ``first.cc``.
@@ -123,7 +123,7 @@ done in ``first.cc``.
Next, we declare another ``NodeContainer`` to hold the nodes that will be
part of the bus (CSMA) network. First, we just instantiate the container
object itself.
object itself.
::
@@ -133,9 +133,9 @@ object itself.
The next line of code ``Gets`` the first node (as in having an index of one)
from the point-to-point node container and adds it to the container of nodes
that will get CSMA devices. The node in question is going to end up with a
point-to-point device *and* a CSMA device. We then create a number of
"extra" nodes that compose the remainder of the CSMA network. Since we
that will get CSMA devices. The node in question is going to end up with a
point-to-point device *and* a CSMA device. We then create a number of
"extra" nodes that compose the remainder of the CSMA network. Since we
already have one node in the CSMA network -- the one that will have both a
point-to-point and CSMA net device, the number of "extra" nodes means the
number nodes you desire in the CSMA section minus one.
@@ -154,20 +154,20 @@ the helper and a two millisecond delay on channels created by the helper.
NetDeviceContainer p2pDevices;
p2pDevices = pointToPoint.Install (p2pNodes);
We then instantiate a ``NetDeviceContainer`` to keep track of the
point-to-point net devices and we ``Install`` devices on the
We then instantiate a ``NetDeviceContainer`` to keep track of the
point-to-point net devices and we ``Install`` devices on the
point-to-point nodes.
We mentioned above that you were going to see a helper for CSMA devices and
channels, and the next lines introduce them. The ``CsmaHelper`` works just
like a ``PointToPointHelper``, but it creates and connects CSMA devices and
channels. In the case of a CSMA device and channel pair, notice that the data
rate is specified by a *channel* ``Attribute`` instead of a device
rate is specified by a *channel* ``Attribute`` instead of a device
``Attribute``. This is because a real CSMA network does not allow one to mix,
for example, 10Base-T and 100Base-T devices on a given channel. We first set
for example, 10Base-T and 100Base-T devices on a given channel. We first set
the data rate to 100 megabits per second, and then set the speed-of-light delay
of the channel to 6560 nano-seconds (arbitrarily chosen as 1 nanosecond per foot
over a 2000 meter segment). Notice that you can set an ``Attribute`` using
over a 2000 meter segment). Notice that you can set an ``Attribute`` using
its native data type.
::
@@ -180,8 +180,8 @@ its native data type.
csmaDevices = csma.Install (csmaNodes);
Just as we created a ``NetDeviceContainer`` to hold the devices created by
the ``PointToPointHelper`` we create a ``NetDeviceContainer`` to hold
the devices created by our ``CsmaHelper``. We call the ``Install``
the ``PointToPointHelper`` we create a ``NetDeviceContainer`` to hold
the devices created by our ``CsmaHelper``. We call the ``Install``
method of the ``CsmaHelper`` to install the devices into the nodes of the
``csmaNodes NodeContainer``.
@@ -196,11 +196,11 @@ stacks present. Just as in the ``first.cc`` script, we will use the
stack.Install (csmaNodes);
Recall that we took one of the nodes from the ``p2pNodes`` container and
added it to the ``csmaNodes`` container. Thus we only need to install
added it to the ``csmaNodes`` container. Thus we only need to install
the stacks on the remaining ``p2pNodes`` node, and all of the nodes in the
``csmaNodes`` container to cover all of the nodes in the simulation.
Just as in the ``first.cc`` example script, we are going to use the
Just as in the ``first.cc`` example script, we are going to use the
``Ipv4AddressHelper`` to assign IP addresses to our device interfaces.
First we use the network 10.1.1.0 to create the two addresses needed for our
two point-to-point devices.
@@ -215,11 +215,11 @@ two point-to-point devices.
Recall that we save the created interfaces in a container to make it easy to
pull out addressing information later for use in setting up the applications.
We now need to assign IP addresses to our CSMA device interfaces. The
We now need to assign IP addresses to our CSMA device interfaces. The
operation works just as it did for the point-to-point case, except we now
are performing the operation on a container that has a variable number of
CSMA devices --- remember we made the number of CSMA devices changeable by
command line argument. The CSMA devices will be associated with IP addresses
are performing the operation on a container that has a variable number of
CSMA devices --- remember we made the number of CSMA devices changeable by
command line argument. The CSMA devices will be associated with IP addresses
from network number 10.1.2.0 in this case, as seen below.
::
@@ -229,14 +229,14 @@ from network number 10.1.2.0 in this case, as seen below.
csmaInterfaces = address.Assign (csmaDevices);
Now we have a topology built, but we need applications. This section is
going to be fundamentally similar to the applications section of
``first.cc`` but we are going to instantiate the server on one of the
nodes that has a CSMA device and the client on the node having only a
going to be fundamentally similar to the applications section of
``first.cc`` but we are going to instantiate the server on one of the
nodes that has a CSMA device and the client on the node having only a
point-to-point device.
First, we set up the echo server. We create a ``UdpEchoServerHelper`` and
provide a required ``Attribute`` value to the constructor which is the server
port number. Recall that this port can be changed later using the
port number. Recall that this port can be changed later using the
``SetAttribute`` method if desired, but we require it to be provided to
the constructor.
@@ -248,21 +248,21 @@ the constructor.
serverApps.Start (Seconds (1.0));
serverApps.Stop (Seconds (10.0));
Recall that the ``csmaNodes NodeContainer`` contains one of the
nodes created for the point-to-point network and ``nCsma`` "extra" nodes.
Recall that the ``csmaNodes NodeContainer`` contains one of the
nodes created for the point-to-point network and ``nCsma`` "extra" nodes.
What we want to get at is the last of the "extra" nodes. The zeroth entry of
the ``csmaNodes`` container will be the point-to-point node. The easy
way to think of this, then, is if we create one "extra" CSMA node, then it
will be at index one of the ``csmaNodes`` container. By induction,
if we create ``nCsma`` "extra" nodes the last one will be at index
``nCsma``. You see this exhibited in the ``Get`` of the first line of
if we create ``nCsma`` "extra" nodes the last one will be at index
``nCsma``. You see this exhibited in the ``Get`` of the first line of
code.
The client application is set up exactly as we did in the ``first.cc``
example script. Again, we provide required ``Attributes`` to the
example script. Again, we provide required ``Attributes`` to the
``UdpEchoClientHelper`` in the constructor (in this case the remote address
and port). We tell the client to send packets to the server we just installed
on the last of the "extra" CSMA nodes. We install the client on the
on the last of the "extra" CSMA nodes. We install the client on the
leftmost point-to-point node seen in the topology illustration.
::
@@ -276,17 +276,17 @@ leftmost point-to-point node seen in the topology illustration.
clientApps.Start (Seconds (2.0));
clientApps.Stop (Seconds (10.0));
Since we have actually built an internetwork here, we need some form of
Since we have actually built an internetwork here, we need some form of
internetwork routing. |ns3| provides what we call global routing to
help you out. Global routing takes advantage of the fact that the entire
help you out. Global routing takes advantage of the fact that the entire
internetwork is accessible in the simulation and runs through the all of the
nodes created for the simulation --- it does the hard work of setting up routing
nodes created for the simulation --- it does the hard work of setting up routing
for you without having to configure routers.
Basically, what happens is that each node behaves as if it were an OSPF router
that communicates instantly and magically with all other routers behind the
scenes. Each node generates link advertisements and communicates them
directly to a global route manager which uses this global information to
scenes. Each node generates link advertisements and communicates them
directly to a global route manager which uses this global information to
construct the routing tables for each node. Setting up this form of routing
is a one-liner:
@@ -294,7 +294,7 @@ is a one-liner:
Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
Next we enable pcap tracing. The first line of code to enable pcap tracing
Next we enable pcap tracing. The first line of code to enable pcap tracing
in the point-to-point helper should be familiar to you by now. The second
line enables pcap tracing in the CSMA helper and there is an extra parameter
you haven't encountered yet.
@@ -304,23 +304,23 @@ you haven't encountered yet.
pointToPoint.EnablePcapAll ("second");
csma.EnablePcap ("second", csmaDevices.Get (1), true);
The CSMA network is a multi-point-to-point network. This means that there
can (and are in this case) multiple endpoints on a shared medium. Each of
The CSMA network is a multi-point-to-point network. This means that there
can (and are in this case) multiple endpoints on a shared medium. Each of
these endpoints has a net device associated with it. There are two basic
alternatives to gathering trace information from such a network. One way
alternatives to gathering trace information from such a network. One way
is to create a trace file for each net device and store only the packets
that are emitted or consumed by that net device. Another way is to pick
that are emitted or consumed by that net device. Another way is to pick
one of the devices and place it in promiscuous mode. That single device
then "sniffs" the network for all packets and stores them in a single
pcap file. This is how ``tcpdump``, for example, works. That final
parameter tells the CSMA helper whether or not to arrange to capture
packets in promiscuous mode.
pcap file. This is how ``tcpdump``, for example, works. That final
parameter tells the CSMA helper whether or not to arrange to capture
packets in promiscuous mode.
In this example, we are going to select one of the devices on the CSMA
network and ask it to perform a promiscuous sniff of the network, thereby
emulating what ``tcpdump`` would do. If you were on a Linux machine
you might do something like ``tcpdump -i eth0`` to get the trace.
In this case, we specify the device using ``csmaDevices.Get(1)``,
you might do something like ``tcpdump -i eth0`` to get the trace.
In this case, we specify the device using ``csmaDevices.Get(1)``,
which selects the first device in the container. Setting the final
parameter to true enables promiscuous captures.
@@ -334,7 +334,7 @@ the ``first.cc`` example.
return 0;
}
In order to run this example, copy the ``second.cc`` example script into
In order to run this example, copy the ``second.cc`` example script into
the scratch directory and use ns3 to build just as you did with
the ``first.cc`` example. If you are in the top-level directory of the
repository you just type,
@@ -346,7 +346,7 @@ repository you just type,
Warning: We use the file ``second.cc`` as one of our regression tests to
verify that it works exactly as we think it should in order to make your
tutorial experience a positive one. This means that an executable named
tutorial experience a positive one. This means that an executable named
``second`` already exists in the project. To avoid any confusion
about what you are executing, please do the renaming to ``mysecond.cc``
suggested above.
@@ -360,7 +360,7 @@ run the program.
$ export NS_LOG=
$ ./ns3 run scratch/mysecond
Since we have set up the UDP echo applications to log just as we did in
Since we have set up the UDP echo applications to log just as we did in
``first.cc``, you will see similar output when you run the script.
.. sourcecode:: text
@@ -372,37 +372,37 @@ Since we have set up the UDP echo applications to log just as we did in
Received 1024 bytes from 10.1.1.1
Received 1024 bytes from 10.1.2.4
Recall that the first message, "``Sent 1024 bytes to 10.1.2.4``," is the
Recall that the first message, "``Sent 1024 bytes to 10.1.2.4``," is the
UDP echo client sending a packet to the server. In this case, the server
is on a different network (10.1.2.0). The second message, "``Received 1024
is on a different network (10.1.2.0). The second message, "``Received 1024
bytes from 10.1.1.1``," is from the UDP echo server, generated when it receives
the echo packet. The final message, "``Received 1024 bytes from 10.1.2.4``,"
is from the echo client, indicating that it has received its echo back from
the server.
If you now go and look in the top level directory, you will find three trace
If you now go and look in the top level directory, you will find three trace
files:
.. sourcecode:: text
second-0-0.pcap second-1-0.pcap second-2-0.pcap
Let's take a moment to look at the naming of these files. They all have the
Let's take a moment to look at the naming of these files. They all have the
same form, ``<name>-<node>-<device>.pcap``. For example, the first file
in the listing is ``second-0-0.pcap`` which is the pcap trace from node
zero, device zero. This is the point-to-point net device on node zero. The
in the listing is ``second-0-0.pcap`` which is the pcap trace from node
zero, device zero. This is the point-to-point net device on node zero. The
file ``second-1-0.pcap`` is the pcap trace for device zero on node one,
also a point-to-point net device; and the file ``second-2-0.pcap`` is the
pcap trace for device zero on node two.
If you refer back to the topology illustration at the start of the section,
If you refer back to the topology illustration at the start of the section,
you will see that node zero is the leftmost node of the point-to-point link
and node one is the node that has both a point-to-point device and a CSMA
and node one is the node that has both a point-to-point device and a CSMA
device. You will see that node two is the first "extra" node on the CSMA
network and its device zero was selected as the device to capture the
network and its device zero was selected as the device to capture the
promiscuous-mode trace.
Now, let's follow the echo packet through the internetwork. First, do a
Now, let's follow the echo packet through the internetwork. First, do a
tcpdump of the trace file for the leftmost point-to-point node --- node zero.
.. sourcecode:: bash
@@ -418,10 +418,10 @@ You should see the contents of the pcap file displayed:
2.017607 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024
The first line of the dump indicates that the link type is PPP (point-to-point)
which we expect. You then see the echo packet leaving node zero via the
which we expect. You then see the echo packet leaving node zero via the
device associated with IP address 10.1.1.1 headed for IP address
10.1.2.4 (the rightmost CSMA node). This packet will move over the
point-to-point link and be received by the point-to-point net device on node
10.1.2.4 (the rightmost CSMA node). This packet will move over the
point-to-point link and be received by the point-to-point net device on node
one. Let's take a look:
.. sourcecode:: bash
@@ -438,10 +438,10 @@ link:
2.013921 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024
Here we see that the link type is also PPP as we would expect. You see the
packet from IP address 10.1.1.1 (that was sent at 2.000000 seconds) headed
toward IP address 10.1.2.4 appear on this interface. Now, internally to this
node, the packet will be forwarded to the CSMA interface and we should see it
pop out on that device headed for its ultimate destination.
packet from IP address 10.1.1.1 (that was sent at 2.000000 seconds) headed
toward IP address 10.1.2.4 appear on this interface. Now, internally to this
node, the packet will be forwarded to the CSMA interface and we should see it
pop out on that device headed for its ultimate destination.
Remember that we selected node 2 as the promiscuous sniffer node for the CSMA
network so let's then look at second-2-0.pcap and see if its there.
@@ -468,7 +468,7 @@ Node one knows it needs to send the packet to IP address 10.1.2.4, but it
doesn't know the MAC address of the corresponding node. It broadcasts on the
CSMA network (ff:ff:ff:ff:ff:ff) asking for the device that has IP address
10.1.2.4. In this case, the rightmost node replies saying it is at MAC address
00:00:00:00:00:06. Note that node two is not directly involved in this
00:00:00:00:00:06. Note that node two is not directly involved in this
exchange, but is sniffing the network and reporting all of the traffic it sees.
This exchange is seen in the following lines,
@@ -479,7 +479,7 @@ This exchange is seen in the following lines,
2.007710 ARP, Reply 10.1.2.4 is-at 00:00:00:00:00:06, length 50
Then node one, device one goes ahead and sends the echo packet to the UDP echo
server at IP address 10.1.2.4.
server at IP address 10.1.2.4.
.. sourcecode:: text
@@ -535,7 +535,7 @@ and see that the echoed packet arrives back at the source at 2.017607 seconds,
Finally, recall that we added the ability to control the number of CSMA devices
in the simulation by command line argument. You can change this argument in
the same way as when we looked at changing the number of packets echoed in the
``first.cc`` example. Try running the program with the number of "extra"
``first.cc`` example. Try running the program with the number of "extra"
devices set to four:
.. sourcecode:: bash
@@ -559,12 +559,12 @@ nodes, which is 10.1.2.5 instead of the default case, 10.1.2.4.
It is possible that you may not be satisfied with a trace file generated by
a bystander in the CSMA network. You may really want to get a trace from
a single device and you may not be interested in any other traffic on the
a single device and you may not be interested in any other traffic on the
network. You can do this fairly easily.
Let's take a look at ``scratch/mysecond.cc`` and add that code enabling us
to be more specific. ``ns-3`` helpers provide methods that take a node
number and device number as parameters. Go ahead and replace the
number and device number as parameters. Go ahead and replace the
``EnablePcap`` calls with the calls below.
::
@@ -577,30 +577,30 @@ We know that we want to create a pcap file with the base name "second" and
we also know that the device of interest in both cases is going to be zero,
so those parameters are not really interesting.
In order to get the node number, you have two choices: first, nodes are
numbered in a monotonically increasing fashion starting from zero in the
order in which you created them. One way to get a node number is to figure
this number out "manually" by contemplating the order of node creation.
If you take a look at the network topology illustration at the beginning of
the file, we did this for you and you can see that the last CSMA node is
going to be node number ``nCsma + 1``. This approach can become
annoyingly difficult in larger simulations.
In order to get the node number, you have two choices: first, nodes are
numbered in a monotonically increasing fashion starting from zero in the
order in which you created them. One way to get a node number is to figure
this number out "manually" by contemplating the order of node creation.
If you take a look at the network topology illustration at the beginning of
the file, we did this for you and you can see that the last CSMA node is
going to be node number ``nCsma + 1``. This approach can become
annoyingly difficult in larger simulations.
An alternate way, which we use here, is to realize that the
``NodeContainers`` contain pointers to |ns3| ``Node`` Objects.
The ``Node`` Object has a method called ``GetId`` which will return that
node's ID, which is the node number we seek. Let's go take a look at the
Doxygen for the ``Node`` and locate that method, which is further down in
node's ID, which is the node number we seek. Let's go take a look at the
Doxygen for the ``Node`` and locate that method, which is further down in
the |ns3| core code than we've seen so far; but sometimes you have to
search diligently for useful things.
Go to the Doxygen documentation for your release (recall that you can find it
on the project web site). You can get to the ``Node`` documentation by
looking through at the "Classes" tab and scrolling down the "Class List"
looking through at the "Classes" tab and scrolling down the "Class List"
until you find ``ns3::Node``. Select ``ns3::Node`` and you will be taken
to the documentation for the ``Node`` class. If you now scroll down to the
``GetId`` method and select it, you will be taken to the detailed
documentation for the method. Using the ``GetId`` method can make
``GetId`` method and select it, you will be taken to the detailed
documentation for the method. Using the ``GetId`` method can make
determining node numbers much easier in complex topologies.
Let's clear the old trace files out of the top-level directory to avoid confusion
@@ -639,8 +639,8 @@ list the pcap files in the top level directory you will see,
The trace file ``second-0-0.pcap`` is the "leftmost" point-to-point device
which is the echo packet source. The file ``second-101-0.pcap`` corresponds
to the rightmost CSMA device which is where the echo server resides. You may
have noticed that the final parameter on the call to enable pcap tracing on the
to the rightmost CSMA device which is where the echo server resides. You may
have noticed that the final parameter on the call to enable pcap tracing on the
echo server node was false. This means that the trace gathered on that node
was in non-promiscuous mode.
@@ -684,22 +684,22 @@ Models, Attributes and Reality
******************************
This is a convenient place to make a small excursion and make an important
point. It may or may not be obvious to you, but whenever one is using a
point. It may or may not be obvious to you, but whenever one is using a
simulation, it is important to understand exactly what is being modeled and
what is not. It is tempting, for example, to think of the CSMA devices
and channels used in the previous section as if they were real Ethernet
devices; and to expect a simulation result to directly reflect what will
happen in a real Ethernet. This is not the case.
what is not. It is tempting, for example, to think of the CSMA devices
and channels used in the previous section as if they were real Ethernet
devices; and to expect a simulation result to directly reflect what will
happen in a real Ethernet. This is not the case.
A model is, by definition, an abstraction of reality. It is ultimately the
A model is, by definition, an abstraction of reality. It is ultimately the
responsibility of the simulation script author to determine the so-called
"range of accuracy" and "domain of applicability" of the simulation as
a whole, and therefore its constituent parts.
In some cases, like ``Csma``, it can be fairly easy to determine what is
*not* modeled. By reading the model description (``csma.h``) you
In some cases, like ``Csma``, it can be fairly easy to determine what is
*not* modeled. By reading the model description (``csma.h``) you
can find that there is no collision detection in the CSMA model and decide
on how applicable its use will be in your simulation or what caveats you
on how applicable its use will be in your simulation or what caveats you
may want to include with your results. In other cases, it can be quite easy
to configure behaviors that might not agree with any reality you can go out
and buy. It will prove worthwhile to spend some time investigating a few
@@ -708,30 +708,30 @@ in your simulations.
As you have seen, |ns3| provides ``Attributes`` which a user
can easily set to change model behavior. Consider two of the ``Attributes``
of the ``CsmaNetDevice``: ``Mtu`` and ``EncapsulationMode``.
The ``Mtu`` attribute indicates the Maximum Transmission Unit to the
of the ``CsmaNetDevice``: ``Mtu`` and ``EncapsulationMode``.
The ``Mtu`` attribute indicates the Maximum Transmission Unit to the
device. This is the size of the largest Protocol Data Unit (PDU) that the
device can send.
device can send.
The MTU defaults to 1500 bytes in the ``CsmaNetDevice``. This default
corresponds to a number found in RFC 894, "A Standard for the Transmission
of IP Datagrams over Ethernet Networks." The number is actually derived
from the maximum packet size for 10Base5 (full-spec Ethernet) networks --
1518 bytes. If you subtract the DIX encapsulation overhead for Ethernet
packets (18 bytes) you will end up with a maximum possible data size (MTU)
of IP Datagrams over Ethernet Networks." The number is actually derived
from the maximum packet size for 10Base5 (full-spec Ethernet) networks --
1518 bytes. If you subtract the DIX encapsulation overhead for Ethernet
packets (18 bytes) you will end up with a maximum possible data size (MTU)
of 1500 bytes. One can also find that the ``MTU`` for IEEE 802.3 networks
is 1492 bytes. This is because LLC/SNAP encapsulation adds an extra eight
is 1492 bytes. This is because LLC/SNAP encapsulation adds an extra eight
bytes of overhead to the packet. In both cases, the underlying hardware can
only send 1518 bytes, but the data size is different.
In order to set the encapsulation mode, the ``CsmaNetDevice`` provides
an ``Attribute`` called ``EncapsulationMode`` which can take on the
an ``Attribute`` called ``EncapsulationMode`` which can take on the
values ``Dix`` or ``Llc``. These correspond to Ethernet and LLC/SNAP
framing respectively.
If one leaves the ``Mtu`` at 1500 bytes and changes the encapsulation mode
to ``Llc``, the result will be a network that encapsulates 1500 byte PDUs
with LLC/SNAP framing resulting in packets of 1526 bytes, which would be
with LLC/SNAP framing resulting in packets of 1526 bytes, which would be
illegal in many networks, since they can transmit a maximum of 1518 bytes per
packet. This would most likely result in a simulation that quite subtly does
not reflect the reality you might be expecting.
@@ -740,8 +740,8 @@ Just to complicate the picture, there exist jumbo frames (1500 < MTU <= 9000 byt
and super-jumbo (MTU > 9000 bytes) frames that are not officially sanctioned
by IEEE but are available in some high-speed (Gigabit) networks and NICs. One
could leave the encapsulation mode set to ``Dix``, and set the ``Mtu``
``Attribute`` on a ``CsmaNetDevice`` to 64000 bytes -- even though an
associated ``CsmaChannel DataRate`` was set at 10 megabits per second.
``Attribute`` on a ``CsmaNetDevice`` to 64000 bytes -- even though an
associated ``CsmaChannel DataRate`` was set at 10 megabits per second.
This would essentially model an Ethernet switch made out of vampire-tapped
1980s-style 10Base5 networks that support super-jumbo datagrams. This is
certainly not something that was ever made, nor is likely to ever be made,
@@ -750,8 +750,8 @@ but it is quite easy for you to configure.
In the previous example, you used the command line to create a simulation that
had 100 ``Csma`` nodes. You could have just as easily created a simulation
with 500 nodes. If you were actually modeling that 10Base5 vampire-tap network,
the maximum length of a full-spec Ethernet cable is 500 meters, with a minimum
tap spacing of 2.5 meters. That means there could only be 200 taps on a
the maximum length of a full-spec Ethernet cable is 500 meters, with a minimum
tap spacing of 2.5 meters. That means there could only be 200 taps on a
real network. You could have quite easily built an illegal network in that
way as well. This may or may not result in a meaningful simulation depending
on what you are trying to model.
@@ -774,36 +774,36 @@ Building a Wireless Network Topology
************************************
In this section we are going to further expand our knowledge of |ns3|
network devices and channels to cover an example of a wireless network.
|ns3| provides a set of 802.11 models that attempt to provide an
accurate MAC-level implementation of the 802.11 specification and a
network devices and channels to cover an example of a wireless network.
|ns3| provides a set of 802.11 models that attempt to provide an
accurate MAC-level implementation of the 802.11 specification and a
"not-so-slow" PHY-level model of the 802.11a specification.
Just as we have seen both point-to-point and CSMA topology helper objects when
constructing point-to-point topologies, we will see equivalent ``Wifi``
topology helpers in this section. The appearance and operation of these
topology helpers in this section. The appearance and operation of these
helpers should look quite familiar to you.
We provide an example script in our ``examples/tutorial`` directory. This script
builds on the ``second.cc`` script and adds a Wi-Fi network. Go ahead and
open ``examples/tutorial/third.cc`` in your favorite editor. You will have already
seen enough |ns3| code to understand most of what is going on in
this example, but there are a few new things, so we will go over the entire
seen enough |ns3| code to understand most of what is going on in
this example, but there are a few new things, so we will go over the entire
script and examine some of the output.
Just as in the ``second.cc`` example (and in all |ns3| examples)
the file begins with an emacs mode line and some GPL boilerplate.
Take a look at the ASCII art (reproduced below) that shows the default network
topology constructed in the example. You can see that we are going to
topology constructed in the example. You can see that we are going to
further extend our example by hanging a wireless network off of the left side.
Notice that this is a default network topology since you can actually vary the
number of nodes created on the wired and wireless networks. Just as in the
``second.cc`` script case, if you change ``nCsma``, it will give you a
number of "extra" CSMA nodes. Similarly, you can set ``nWifi`` to
number of nodes created on the wired and wireless networks. Just as in the
``second.cc`` script case, if you change ``nCsma``, it will give you a
number of "extra" CSMA nodes. Similarly, you can set ``nWifi`` to
control how many ``STA`` (station) nodes are created in the simulation.
There will always be one ``AP`` (access point) node on the wireless
network. By default there are three "extra" CSMA nodes and three wireless
There will always be one ``AP`` (access point) node on the wireless
network. By default there are three "extra" CSMA nodes and three wireless
``STA`` nodes.
The code begins by loading module include files just as was done in the
@@ -836,9 +836,9 @@ The network topology illustration follows:
// ================
// LAN 10.1.2.0
You can see that we are adding a new network device to the node on the left
You can see that we are adding a new network device to the node on the left
side of the point-to-point link that becomes the access point for the wireless
network. A number of wireless STA nodes are created to fill out the new
network. A number of wireless STA nodes are created to fill out the new
10.1.3.0 network as shown on the left side of the illustration.
After the illustration, the ``ns-3`` namespace is ``used`` and a logging
@@ -847,11 +847,11 @@ component is defined. This should all be quite familiar by now.
::
using namespace ns3;
NS_LOG_COMPONENT_DEFINE ("ThirdScriptExample");
The main program begins just like ``second.cc`` by adding some command line
parameters for enabling or disabling logging components and for changing the
parameters for enabling or disabling logging components and for changing the
number of devices created.
::
@@ -874,16 +874,16 @@ number of devices created.
}
Just as in all of the previous examples, the next step is to create two nodes
that we will connect via the point-to-point link.
that we will connect via the point-to-point link.
::
NodeContainer p2pNodes;
p2pNodes.Create (2);
Next, we see an old friend. We instantiate a ``PointToPointHelper`` and
set the associated default ``Attributes`` so that we create a five megabit
per second transmitter on devices created using the helper and a two millisecond
Next, we see an old friend. We instantiate a ``PointToPointHelper`` and
set the associated default ``Attributes`` so that we create a five megabit
per second transmitter on devices created using the helper and a two millisecond
delay on channels created by the helper. We then ``Install`` the devices
on the nodes and the channel between them.
@@ -907,13 +907,13 @@ part of the bus (CSMA) network.
The next line of code ``Gets`` the first node (as in having an index of one)
from the point-to-point node container and adds it to the container of nodes
that will get CSMA devices. The node in question is going to end up with a
that will get CSMA devices. The node in question is going to end up with a
point-to-point device and a CSMA device. We then create a number of "extra"
nodes that compose the remainder of the CSMA network.
We then instantiate a ``CsmaHelper`` and set its ``Attributes`` as we did
in the previous example. We create a ``NetDeviceContainer`` to keep track of
the created CSMA net devices and then we ``Install`` CSMA devices on the
the created CSMA net devices and then we ``Install`` CSMA devices on the
selected nodes.
::
@@ -926,8 +926,8 @@ selected nodes.
csmaDevices = csma.Install (csmaNodes);
Next, we are going to create the nodes that will be part of the Wi-Fi network.
We are going to create a number of "station" nodes as specified by the
command line argument, and we are going to use the "leftmost" node of the
We are going to create a number of "station" nodes as specified by the
command line argument, and we are going to use the "leftmost" node of the
point-to-point link as the node for the access point.
::
@@ -962,7 +962,7 @@ Once the PHY helper is configured, we can focus on the MAC layer. The
WifiMacHelper object is used to set MAC parameters.
The second statement below creates an 802.11 service set identifier (SSID)
object that will be used to set the value of the "Ssid" ``Attribute`` of
the MAC layer implementation.
the MAC layer implementation.
::
@@ -978,7 +978,7 @@ a compatible rate control algorithm (IdealWifiManager).
WifiHelper wifi;
We are now ready to install Wi-Fi models on the nodes, using these four
We are now ready to install Wi-Fi models on the nodes, using these four
helper objects (YansWifiChannelHelper, YansWifiPhyHelper, WifiMacHelper,
WifiHelper) and the Ssid object created above. These helpers have
encapsulated a lot of default configuration,
@@ -1005,7 +1005,7 @@ set to false. This means that probe requests will not be sent by MACs
created by this helper, and stations will listen for AP beacons.
Once all the station-specific parameters are fully configured, both at the
MAC and PHY layers, we can invoke our now-familiar ``Install`` method to
MAC and PHY layers, we can invoke our now-familiar ``Install`` method to
create the Wi-Fi devices of these stations:
::
@@ -1013,9 +1013,9 @@ create the Wi-Fi devices of these stations:
NetDeviceContainer staDevices;
staDevices = wifi.Install (phy, mac, wifiStaNodes);
We have configured Wi-Fi for all of our STA nodes, and now we need to
We have configured Wi-Fi for all of our STA nodes, and now we need to
configure the AP (access point) node. We begin this process by changing
the default ``Attributes`` of the ``WifiMacHelper`` to reflect the
the default ``Attributes`` of the ``WifiMacHelper`` to reflect the
requirements of the AP.
::
@@ -1036,9 +1036,9 @@ The next lines create the single AP which shares the same set of PHY-level
apDevices = wifi.Install (phy, mac, wifiApNode);
Now, we are going to add mobility models. We want the STA nodes to be mobile,
wandering around inside a bounding box, and we want to make the AP node
wandering around inside a bounding box, and we want to make the AP node
stationary. We use the ``MobilityHelper`` to make this easy for us.
First, we instantiate a ``MobilityHelper`` object and set some
First, we instantiate a ``MobilityHelper`` object and set some
``Attributes`` controlling the "position allocator" functionality.
::
@@ -1054,12 +1054,12 @@ First, we instantiate a ``MobilityHelper`` object and set some
"LayoutType", StringValue ("RowFirst"));
This code tells the mobility helper to use a two-dimensional grid to initially
place the STA nodes. Feel free to explore the Doxygen for class
place the STA nodes. Feel free to explore the Doxygen for class
``ns3::GridPositionAllocator`` to see exactly what is being done.
We have arranged our nodes on an initial grid, but now we need to tell them
how to move. We choose the ``RandomWalk2dMobilityModel`` which has the
nodes move in a random direction at a random speed around inside a bounding
how to move. We choose the ``RandomWalk2dMobilityModel`` which has the
nodes move in a random direction at a random speed around inside a bounding
box.
::
@@ -1067,7 +1067,7 @@ box.
mobility.SetMobilityModel ("ns3::RandomWalk2dMobilityModel",
"Bounds", RectangleValue (Rectangle (-50, 50, -50, 50)));
We now tell the ``MobilityHelper`` to install the mobility models on the
We now tell the ``MobilityHelper`` to install the mobility models on the
STA nodes.
::
@@ -1075,7 +1075,7 @@ STA nodes.
mobility.Install (wifiStaNodes);
We want the access point to remain in a fixed position during the simulation.
We accomplish this by setting the mobility model for this node to be the
We accomplish this by setting the mobility model for this node to be the
``ns3::ConstantPositionMobilityModel``:
::
@@ -1083,8 +1083,8 @@ We accomplish this by setting the mobility model for this node to be the
mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
mobility.Install (wifiApNode);
We now have our nodes, devices and channels created, and mobility models
chosen for the Wi-Fi nodes, but we have no protocol stacks present. Just as
We now have our nodes, devices and channels created, and mobility models
chosen for the Wi-Fi nodes, but we have no protocol stacks present. Just as
we have done previously many times, we will use the ``InternetStackHelper``
to install these stacks.
@@ -1095,7 +1095,7 @@ to install these stacks.
stack.Install (wifiApNode);
stack.Install (wifiStaNodes);
Just as in the ``second.cc`` example script, we are going to use the
Just as in the ``second.cc`` example script, we are going to use the
``Ipv4AddressHelper`` to assign IP addresses to our device interfaces.
First we use the network 10.1.1.0 to create the two addresses needed for our
two point-to-point devices. Then we use network 10.1.2.0 to assign addresses
@@ -1156,7 +1156,7 @@ created will never "naturally" stop. This is because we asked the wireless
access point to generate beacons. It will generate beacons forever, and this
will result in simulator events being scheduled into the future indefinitely,
so we must tell the simulator to stop even though it may have beacon generation
events scheduled. The following line of code tells the simulator to stop so that
events scheduled. The following line of code tells the simulator to stop so that
we don't simulate beacons forever and enter what is essentially an endless
loop.
@@ -1173,9 +1173,9 @@ We create just enough tracing to cover all three networks:
csma.EnablePcap ("third", csmaDevices.Get (0), true);
These three lines of code will start pcap tracing on both of the point-to-point
nodes that serves as our backbone, will start a promiscuous (monitor) mode
trace on the Wi-Fi network, and will start a promiscuous trace on the CSMA
network. This will let us see all of the traffic with a minimum number of
nodes that serves as our backbone, will start a promiscuous (monitor) mode
trace on the Wi-Fi network, and will start a promiscuous trace on the CSMA
network. This will let us see all of the traffic with a minimum number of
trace files.
Finally, we actually run the simulation, clean up and then exit the program.
@@ -1197,7 +1197,7 @@ repository you would type,
$ cp examples/tutorial/third.cc scratch/mythird.cc
$ ./ns3 run scratch/mythird
Again, since we have set up the UDP echo applications just as we did in the
Again, since we have set up the UDP echo applications just as we did in the
``second.cc`` script, you will see similar output.
.. sourcecode:: text
@@ -1210,15 +1210,15 @@ Again, since we have set up the UDP echo applications just as we did in the
At time 2.01796s server sent 1024 bytes to 10.1.3.3 port 49153
At time 2.03364s client received 1024 bytes from 10.1.2.4 port 9
Recall that the first message, ``Sent 1024 bytes to 10.1.2.4``," is the
Recall that the first message, ``Sent 1024 bytes to 10.1.2.4``," is the
UDP echo client sending a packet to the server. In this case, the client
is on the wireless network (10.1.3.0). The second message,
"``Received 1024 bytes from 10.1.3.3``," is from the UDP echo server,
generated when it receives the echo packet. The final message,
is on the wireless network (10.1.3.0). The second message,
"``Received 1024 bytes from 10.1.3.3``," is from the UDP echo server,
generated when it receives the echo packet. The final message,
"``Received 1024 bytes from 10.1.2.4``," is from the echo client, indicating
that it has received its echo back from the server.
If you now go and look in the top level directory, you will find four trace
If you now go and look in the top level directory, you will find four trace
files from this simulation, two from node zero and two from node one:
.. sourcecode:: text
@@ -1226,7 +1226,7 @@ files from this simulation, two from node zero and two from node one:
third-0-0.pcap third-0-1.pcap third-1-0.pcap third-1-1.pcap
The file "third-0-0.pcap" corresponds to the point-to-point device on node
zero -- the left side of the "backbone". The file "third-1-0.pcap"
zero -- the left side of the "backbone". The file "third-1-0.pcap"
corresponds to the point-to-point device on node one -- the right side of the
"backbone". The file "third-0-1.pcap" will be the promiscuous (monitor
mode) trace from the Wi-Fi network and the file "third-1-1.pcap" will be the
@@ -1247,24 +1247,24 @@ You should see some wifi-looking contents you haven't seen here before:
reading from file third-0-1.pcap, link-type IEEE802_11 (802.11)
0.000025 Beacon (ns-3-ssid) [6.0* 9.0 12.0 18.0 24.0 36.0 48.0 54.0 Mbit] IBSS
0.000308 Assoc Request (ns-3-ssid) [6.0 9.0 12.0 18.0 24.0 36.0 48.0 54.0 Mbit]
0.000324 Acknowledgment RA:00:00:00:00:00:08
0.000324 Acknowledgment RA:00:00:00:00:00:08
0.000402 Assoc Response AID(0) :: Successful
0.000546 Acknowledgment RA:00:00:00:00:00:0a
0.000546 Acknowledgment RA:00:00:00:00:00:0a
0.000721 Assoc Request (ns-3-ssid) [6.0 9.0 12.0 18.0 24.0 36.0 48.0 54.0 Mbit]
0.000737 Acknowledgment RA:00:00:00:00:00:07
0.000737 Acknowledgment RA:00:00:00:00:00:07
0.000824 Assoc Response AID(0) :: Successful
0.000968 Acknowledgment RA:00:00:00:00:00:0a
0.000968 Acknowledgment RA:00:00:00:00:00:0a
0.001134 Assoc Request (ns-3-ssid) [6.0 9.0 12.0 18.0 24.0 36.0 48.0 54.0 Mbit]
0.001150 Acknowledgment RA:00:00:00:00:00:09
0.001150 Acknowledgment RA:00:00:00:00:00:09
0.001273 Assoc Response AID(0) :: Successful
0.001417 Acknowledgment RA:00:00:00:00:00:0a
0.001417 Acknowledgment RA:00:00:00:00:00:0a
0.102400 Beacon (ns-3-ssid) [6.0* 9.0 12.0 18.0 24.0 36.0 48.0 54.0 Mbit] IBSS
0.204800 Beacon (ns-3-ssid) [6.0* 9.0 12.0 18.0 24.0 36.0 48.0 54.0 Mbit] IBSS
0.307200 Beacon (ns-3-ssid) [6.0* 9.0 12.0 18.0 24.0 36.0 48.0 54.0 Mbit] IBSS
You can see that the link type is now 802.11 as you would expect. You can
You can see that the link type is now 802.11 as you would expect. You can
probably understand what is going on and find the IP echo request and response
packets in this trace. We leave it as an exercise to completely parse the
packets in this trace. We leave it as an exercise to completely parse the
trace dump.
Now, look at the pcap file of the left side of the point-to-point link,
@@ -1298,11 +1298,11 @@ Again, you should see some familiar looking contents:
2.011837 IP 10.1.3.3.49153 > 10.1.2.4.9: UDP, length 1024
2.023072 IP 10.1.2.4.9 > 10.1.3.3.49153: UDP, length 1024
This is also the echo packet going from left to right (from Wi-Fi to CSMA) and
This is also the echo packet going from left to right (from Wi-Fi to CSMA) and
back again across the point-to-point link with slightly different timings
as you might expect.
The echo server is on the CSMA network, let's look at the promiscuous trace
The echo server is on the CSMA network, let's look at the promiscuous trace
there:
.. sourcecode:: bash
@@ -1331,14 +1331,14 @@ into the ``MobilityModel`` course change trace source. This is just a sneak
peek into the detailed tracing section which is coming up, but this seems a very
nice place to get an example in.
As mentioned in the "Tweaking ns-3" section, the |ns3| tracing system
is divided into trace sources and trace sinks, and we provide functions to
connect the two. We will use the mobility model predefined course change
trace source to originate the trace events. We will need to write a trace
sink to connect to that source that will display some pretty information for
As mentioned in the "Tweaking ns-3" section, the |ns3| tracing system
is divided into trace sources and trace sinks, and we provide functions to
connect the two. We will use the mobility model predefined course change
trace source to originate the trace events. We will need to write a trace
sink to connect to that source that will display some pretty information for
us. Despite its reputation as being difficult, it's really quite simple.
Just before the main program of the ``scratch/mythird.cc`` script (i.e.,
just after the ``NS_LOG_COMPONENT_DEFINE`` statement), add the
just after the ``NS_LOG_COMPONENT_DEFINE`` statement), add the
following function:
::
@@ -1347,14 +1347,14 @@ following function:
CourseChange (std::string context, Ptr<const MobilityModel> model)
{
Vector position = model->GetPosition ();
NS_LOG_UNCOND (context <<
NS_LOG_UNCOND (context <<
" x = " << position.x << ", y = " << position.y);
}
This code just pulls the position information from the mobility model and
This code just pulls the position information from the mobility model and
unconditionally logs the x and y position of the node. We are
going to arrange for this function to be called every time the wireless
node with the echo client changes its position. We do this using the
node with the echo client changes its position. We do this using the
``Config::Connect`` function. Add the following lines of code to the
script just before the ``Simulator::Run`` call.
@@ -1368,9 +1368,9 @@ script just before the ``Simulator::Run`` call.
Config::Connect (oss.str (), MakeCallback (&CourseChange));
What we do here is to create a string containing the tracing namespace path
of the event to which we want to connect. First, we have to figure out which
of the event to which we want to connect. First, we have to figure out which
node it is we want using the ``GetId`` method as described earlier. In the
case of the default number of CSMA and wireless nodes, this turns out to be
case of the default number of CSMA and wireless nodes, this turns out to be
node seven and the tracing namespace path to the mobility model would look
like,
@@ -1378,19 +1378,19 @@ like,
/NodeList/7/$ns3::MobilityModel/CourseChange
Based on the discussion in the tracing section, you may infer that this trace
Based on the discussion in the tracing section, you may infer that this trace
path references the seventh node in the global NodeList. It specifies
what is called an aggregated object of type ``ns3::MobilityModel``. The
what is called an aggregated object of type ``ns3::MobilityModel``. The
dollar sign prefix implies that the MobilityModel is aggregated to node seven.
The last component of the path means that we are hooking into the
"CourseChange" event of that model.
The last component of the path means that we are hooking into the
"CourseChange" event of that model.
We make a connection between the trace source in node seven with our trace
sink by calling ``Config::Connect`` and passing this namespace path. Once
this is done, every course change event on node seven will be hooked into our
We make a connection between the trace source in node seven with our trace
sink by calling ``Config::Connect`` and passing this namespace path. Once
this is done, every course change event on node seven will be hooked into our
trace sink, which will in turn print out the new position.
If you now run the simulation, you will see the course changes displayed as
If you now run the simulation, you will see the course changes displayed as
they happen.
.. sourcecode:: text
@@ -1439,7 +1439,7 @@ The selection of queueing disciplines in |ns3| can have a large impact
on performance, and it is important for users to understand what is installed
by default and how to change the defaults and observe the performance.
Architecturally, |ns3| separates the device layer from the IP layers
Architecturally, |ns3| separates the device layer from the IP layers
or traffic control layers of an Internet host. Since recent releases
of |ns3|, outgoing packets traverse two queueing layers before reaching
the channel object. The first queueing layer encountered is what is

View File

@@ -21,18 +21,18 @@ networking, but have a specific meaning in |ns3|.
Node
++++
In Internet jargon, a computing device that connects to a network is called
a *host* or sometimes an *end system*. Because |ns3| is a
*network* simulator, not specifically an *Internet* simulator, we
a *host* or sometimes an *end system*. Because |ns3| is a
*network* simulator, not specifically an *Internet* simulator, we
intentionally do not use the term host since it is closely associated with
the Internet and its protocols. Instead, we use a more generic term also
used by other simulators that originates in Graph Theory --- the *node*.
In |ns3| the basic computing device abstraction is called the
node. This abstraction is represented in C++ by the class ``Node``. The
``Node`` class provides methods for managing the representations of
In |ns3| the basic computing device abstraction is called the
node. This abstraction is represented in C++ by the class ``Node``. The
``Node`` class provides methods for managing the representations of
computing devices in simulations.
You should think of a ``Node`` as a computer to which you will add
You should think of a ``Node`` as a computer to which you will add
functionality. One adds things like applications, protocol stacks and
peripheral cards with their associated drivers to enable the computer to do
useful work. We use the same basic model in |ns3|.
@@ -45,7 +45,7 @@ cycles, disk, network, etc., according to some computing model. System
software usually does not use those resources to complete tasks that directly
benefit a user. A user would typically run an *application* that acquires
and uses the resources controlled by the system software to accomplish some
goal.
goal.
Often, the line of separation between system and application software is made
at the privilege level change that happens in operating system traps.
@@ -56,41 +56,41 @@ perform tasks in the "real world," |ns3| applications run on
|ns3| ``Nodes`` to drive simulations in the simulated world.
In |ns3| the basic abstraction for a user program that generates some
activity to be simulated is the application. This abstraction is represented
in C++ by the class ``Application``. The ``Application`` class provides
methods for managing the representations of our version of user-level
activity to be simulated is the application. This abstraction is represented
in C++ by the class ``Application``. The ``Application`` class provides
methods for managing the representations of our version of user-level
applications in simulations. Developers are expected to specialize the
``Application`` class in the object-oriented programming sense to create new
applications. In this tutorial, we will use specializations of class
``Application`` called ``UdpEchoClientApplication`` and
``UdpEchoServerApplication``. As you might expect, these applications
compose a client/server application set used to generate and echo simulated
network packets
applications. In this tutorial, we will use specializations of class
``Application`` called ``UdpEchoClientApplication`` and
``UdpEchoServerApplication``. As you might expect, these applications
compose a client/server application set used to generate and echo simulated
network packets
Channel
+++++++
In the real world, one can connect a computer to a network. Often the media
over which data flows in these networks are called *channels*. When
you connect your Ethernet cable to the plug in the wall, you are connecting
you connect your Ethernet cable to the plug in the wall, you are connecting
your computer to an Ethernet communication channel. In the simulated world
of |ns3|, one connects a ``Node`` to an object representing a
communication channel. Here the basic communication subnetwork abstraction
is called the channel and is represented in C++ by the class ``Channel``.
communication channel. Here the basic communication subnetwork abstraction
is called the channel and is represented in C++ by the class ``Channel``.
The ``Channel`` class provides methods for managing communication
The ``Channel`` class provides methods for managing communication
subnetwork objects and connecting nodes to them. ``Channels`` may also be
specialized by developers in the object oriented programming sense. A
``Channel`` specialization may model something as simple as a wire. The
specialized ``Channel`` can also model things as complicated as a large
Ethernet switch, or three-dimensional space full of obstructions in the case
specialized by developers in the object oriented programming sense. A
``Channel`` specialization may model something as simple as a wire. The
specialized ``Channel`` can also model things as complicated as a large
Ethernet switch, or three-dimensional space full of obstructions in the case
of wireless networks.
We will use specialized versions of the ``Channel`` called
``CsmaChannel``, ``PointToPointChannel`` and ``WifiChannel`` in this
tutorial. The ``CsmaChannel``, for example, models a version of a
communication subnetwork that implements a *carrier sense multiple
access* communication medium. This gives us Ethernet-like functionality.
tutorial. The ``CsmaChannel``, for example, models a version of a
communication subnetwork that implements a *carrier sense multiple
access* communication medium. This gives us Ethernet-like functionality.
Net Device
++++++++++
@@ -98,52 +98,52 @@ It used to be the case that if you wanted to connect a computer to a network,
you had to buy a specific kind of network cable and a hardware device called
(in PC terminology) a *peripheral card* that needed to be installed in
your computer. If the peripheral card implemented some networking function,
they were called Network Interface Cards, or *NICs*. Today most
computers come with the network interface hardware built in and users don't
they were called Network Interface Cards, or *NICs*. Today most
computers come with the network interface hardware built in and users don't
see these building blocks.
A NIC will not work without a software driver to control the hardware. In
Unix (or Linux), a piece of peripheral hardware is classified as a
A NIC will not work without a software driver to control the hardware. In
Unix (or Linux), a piece of peripheral hardware is classified as a
*device*. Devices are controlled using *device drivers*, and network
devices (NICs) are controlled using *network device drivers*
collectively known as *net devices*. In Unix and Linux you refer
to these net devices by names such as *eth0*.
In |ns3| the *net device* abstraction covers both the software
driver and the simulated hardware. A net device is "installed" in a
``Node`` in order to enable the ``Node`` to communicate with other
In |ns3| the *net device* abstraction covers both the software
driver and the simulated hardware. A net device is "installed" in a
``Node`` in order to enable the ``Node`` to communicate with other
``Nodes`` in the simulation via ``Channels``. Just as in a real
computer, a ``Node`` may be connected to more than one ``Channel`` via
multiple ``NetDevices``.
The net device abstraction is represented in C++ by the class ``NetDevice``.
The ``NetDevice`` class provides methods for managing connections to
The ``NetDevice`` class provides methods for managing connections to
``Node`` and ``Channel`` objects; and may be specialized by developers
in the object-oriented programming sense. We will use the several specialized
versions of the ``NetDevice`` called ``CsmaNetDevice``,
``PointToPointNetDevice``, and ``WifiNetDevice`` in this tutorial.
Just as an Ethernet NIC is designed to work with an Ethernet network, the
``CsmaNetDevice`` is designed to work with a ``CsmaChannel``; the
``PointToPointNetDevice`` is designed to work with a
``PointToPointNetDevice`` is designed to work with a
``PointToPointChannel`` and a ``WifiNetNevice`` is designed to work with
a ``WifiChannel``.
Topology Helpers
++++++++++++++++
In a real network, you will find host computers with added (or built-in)
NICs. In |ns3| we would say that you will find ``Nodes`` with
attached ``NetDevices``. In a large simulated network you will need to
arrange many connections between ``Nodes``, ``NetDevices`` and
NICs. In |ns3| we would say that you will find ``Nodes`` with
attached ``NetDevices``. In a large simulated network you will need to
arrange many connections between ``Nodes``, ``NetDevices`` and
``Channels``.
Since connecting ``NetDevices`` to ``Nodes``, ``NetDevices``
to ``Channels``, assigning IP addresses, etc., are such common tasks
in |ns3|, we provide what we call *topology helpers* to make
this as easy as possible. For example, it may take many distinct
|ns3| core operations to create a NetDevice, add a MAC address,
in |ns3|, we provide what we call *topology helpers* to make
this as easy as possible. For example, it may take many distinct
|ns3| core operations to create a NetDevice, add a MAC address,
install that net device on a ``Node``, configure the node's protocol stack,
and then connect the ``NetDevice`` to a ``Channel``. Even more
operations would be required to connect multiple devices onto multipoint
operations would be required to connect multiple devices onto multipoint
channels and then to connect individual networks together into internetworks.
We provide topology helper objects that combine those many distinct operations
into an easy to use model for your convenience.
@@ -151,8 +151,8 @@ into an easy to use model for your convenience.
A First ns-3 Script
*******************
If you downloaded the system as was suggested above, you will have a release
of |ns3| in a directory called ``repos`` under your home
directory. Change into that release directory, and you should find a
of |ns3| in a directory called ``repos`` under your home
directory. Change into that release directory, and you should find a
directory structure something like the following:
.. sourcecode:: bash
@@ -160,10 +160,10 @@ directory structure something like the following:
AUTHORS doc RELEASE_NOTES.md utils
bindings examples scratch utils.py
CHANGES.html LICENSE src VERSION
contrib Makefile test.py
contrib Makefile test.py
CONTRIBUTING.md README.md testpy.supp
Change into the ``examples/tutorial`` directory. You should see a file named
Change into the ``examples/tutorial`` directory. You should see a file named
``first.cc`` located there. This is a script that will create a simple
point-to-point link between two nodes and echo a single packet between the
nodes. Let's take a look at that script line by line, so go ahead and open
@@ -172,29 +172,29 @@ nodes. Let's take a look at that script line by line, so go ahead and open
Boilerplate
+++++++++++
The first line in the file is an emacs mode line. This tells emacs about the
formatting conventions (coding style) we use in our source code.
formatting conventions (coding style) we use in our source code.
::
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
This is always a somewhat controversial subject, so we might as well get it
out of the way immediately. The |ns3| project, like most large
projects, has adopted a coding style to which all contributed code must
adhere. If you want to contribute your code to the project, you will
eventually have to conform to the |ns3| coding standard as described
out of the way immediately. The |ns3| project, like most large
projects, has adopted a coding style to which all contributed code must
adhere. If you want to contribute your code to the project, you will
eventually have to conform to the |ns3| coding standard as described
in the file ``doc/codingstd.txt`` or shown on the project web page
`here
<http://www.nsnam.org/developers/contributing-code/coding-style/>`_.
We recommend that you, well, just get used to the look and feel of |ns3|
code and adopt this standard whenever you are working with our code. All of
the development team and contributors have done so with various amounts of
grumbling. The emacs mode line above makes it easier to get the formatting
code and adopt this standard whenever you are working with our code. All of
the development team and contributors have done so with various amounts of
grumbling. The emacs mode line above makes it easier to get the formatting
correct if you use the emacs editor.
The |ns3| simulator is licensed using the GNU General Public
License. You will see the appropriate GNU legalese at the head of every file
The |ns3| simulator is licensed using the GNU General Public
License. You will see the appropriate GNU legalese at the head of every file
in the |ns3| distribution. Often you will see a copyright notice for
one of the institutions involved in the |ns3| project above the GPL
text and an author listed below.
@@ -218,7 +218,7 @@ text and an author listed below.
Module Includes
+++++++++++++++
The code proper starts with a number of include statements.
The code proper starts with a number of include statements.
::
@@ -228,41 +228,41 @@ The code proper starts with a number of include statements.
#include "ns3/point-to-point-module.h"
#include "ns3/applications-module.h"
To help our high-level script users deal with the large number of include
files present in the system, we group includes according to relatively large
modules. We provide a single include file that will recursively load all of
To help our high-level script users deal with the large number of include
files present in the system, we group includes according to relatively large
modules. We provide a single include file that will recursively load all of
the include files used in each module. Rather than having to look up exactly
what header you need, and possibly have to get a number of dependencies right,
we give you the ability to load a group of files at a large granularity. This
is not the most efficient approach but it certainly makes writing scripts much
easier.
Each of the |ns3| include files is placed in a directory called
Each of the |ns3| include files is placed in a directory called
``ns3`` (under the build directory) during the build process to help avoid
include file name collisions. The ``ns3/core-module.h`` file corresponds
to the ns-3 module you will find in the directory ``src/core`` in your
include file name collisions. The ``ns3/core-module.h`` file corresponds
to the ns-3 module you will find in the directory ``src/core`` in your
downloaded release distribution. If you list this directory you will find a
large number of header files. When you do a build, ns3 will place public
header files in an ``ns3`` directory under the appropriate
``build/debug`` or ``build/optimized`` directory depending on your
header files in an ``ns3`` directory under the appropriate
``build/debug`` or ``build/optimized`` directory depending on your
configuration. CMake will also automatically generate a module include file to
load all of the public header files.
Since you are, of course, following this tutorial religiously, you will
Since you are, of course, following this tutorial religiously, you will
already have done a
.. sourcecode:: bash
$ ./ns3 configure -d debug --enable-examples --enable-tests
in order to configure the project to perform debug builds that include
in order to configure the project to perform debug builds that include
examples and tests. You will also have done a
.. sourcecode:: bash
$ ./ns3 build
to build the project. So now if you look in the directory
to build the project. So now if you look in the directory
``../../build/include/ns3`` you will find the four module include files shown
above. You can take a look at the contents of these files and find that they
do include all of the public include files in their respective modules.
@@ -275,16 +275,16 @@ The next line in the ``first.cc`` script is a namespace declaration.
using namespace ns3;
The |ns3| project is implemented in a C++ namespace called
The |ns3| project is implemented in a C++ namespace called
``ns3``. This groups all |ns3|-related declarations in a scope
outside the global namespace, which we hope will help with integration with
outside the global namespace, which we hope will help with integration with
other code. The C++ ``using`` statement introduces the |ns3|
namespace into the current (global) declarative region. This is a fancy way
of saying that after this declaration, you will not have to type ``ns3::``
scope resolution operator before all of the |ns3| code in order to use
it. If you are unfamiliar with namespaces, please consult almost any C++
it. If you are unfamiliar with namespaces, please consult almost any C++
tutorial and compare the ``ns3`` namespace and usage here with instances of
the ``std`` namespace and the ``using namespace std;`` statements you
the ``std`` namespace and the ``using namespace std;`` statements you
will often find in discussions of ``cout`` and streams.
Logging
@@ -296,10 +296,10 @@ The next line of the script is the following,
NS_LOG_COMPONENT_DEFINE ("FirstScriptExample");
We will use this statement as a convenient place to talk about our Doxygen
documentation system. If you look at the project web site,
documentation system. If you look at the project web site,
`ns-3 project
<http://www.nsnam.org>`_, you will find a link to "Documentation" in the navigation bar. If you select this link, you will be
taken to our documentation page. There
taken to our documentation page. There
is a link to "Latest Release" that will take you to the documentation
for the latest stable release of |ns3|.
If you select the "API Documentation" link, you will be
@@ -307,25 +307,25 @@ taken to the |ns3| API documentation page.
Along the left side, you will find a graphical representation of the structure
of the documentation. A good place to start is the ``NS-3 Modules``
"book" in the |ns3| navigation tree. If you expand ``Modules``
you will see a list of |ns3| module documentation. The concept of
"book" in the |ns3| navigation tree. If you expand ``Modules``
you will see a list of |ns3| module documentation. The concept of
module here ties directly into the module include files discussed above. The |ns3| logging subsystem is discussed in the :ref:`UsingLogging` section, so
we'll get to it later in this tutorial, but you can find out about the above
statement by looking at the ``Core`` module, then expanding the
statement by looking at the ``Core`` module, then expanding the
``Debugging tools`` book, and then selecting the ``Logging`` page. Click
on ``Logging``.
You should now be looking at the Doxygen documentation for the Logging module.
In the list of ``Macros``'s at the top of the page you will see the entry
for ``NS_LOG_COMPONENT_DEFINE``. Before jumping in, it would probably be
good to look for the "Detailed Description" of the logging module to get a
for ``NS_LOG_COMPONENT_DEFINE``. Before jumping in, it would probably be
good to look for the "Detailed Description" of the logging module to get a
feel for the overall operation. You can either scroll down or select the
"More..." link under the collaboration diagram to do this.
Once you have a general idea of what is going on, go ahead and take a look at
the specific ``NS_LOG_COMPONENT_DEFINE`` documentation. I won't duplicate
the documentation here, but to summarize, this line declares a logging
component called ``FirstScriptExample`` that allows you to enable and
the documentation here, but to summarize, this line declares a logging
component called ``FirstScriptExample`` that allows you to enable and
disable console message logging by reference to the name.
Main Function
@@ -339,8 +339,8 @@ The next lines of the script you will find are,
{
This is just the declaration of the main function of your program (script).
Just as in any C++ program, you need to define a main function that will be
the first function run. There is nothing at all special here. Your
Just as in any C++ program, you need to define a main function that will be
the first function run. There is nothing at all special here. Your
|ns3| script is just a C++ program.
The next line sets the time resolution to one nanosecond, which happens
@@ -367,12 +367,12 @@ are built into the Echo Client and Echo Server applications:
LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_INFO);
If you have read over the Logging component documentation you will have seen
that there are a number of levels of logging verbosity/detail that you can
that there are a number of levels of logging verbosity/detail that you can
enable on each component. These two lines of code enable debug logging at the
INFO level for echo clients and servers. This will result in the application
printing out messages as packets are sent and received during the simulation.
Now we will get directly to the business of creating a topology and running
Now we will get directly to the business of creating a topology and running
a simulation. We use the topology helper objects to make this job as
easy as possible.
@@ -380,9 +380,9 @@ Topology Helpers
++++++++++++++++
NodeContainer
~~~~~~~~~~~~~
The next two lines of code in our script will actually create the
|ns3| ``Node`` objects that will represent the computers in the
simulation.
The next two lines of code in our script will actually create the
|ns3| ``Node`` objects that will represent the computers in the
simulation.
::
@@ -390,11 +390,11 @@ simulation.
nodes.Create (2);
Let's find the documentation for the ``NodeContainer`` class before we
continue. Another way to get into the documentation for a given class is via
the ``Classes`` tab in the Doxygen pages. If you still have the Doxygen
handy, just scroll up to the top of the page and select the ``Classes``
tab. You should see a new set of tabs appear, one of which is
``Class List``. Under that tab you will see a list of all of the
continue. Another way to get into the documentation for a given class is via
the ``Classes`` tab in the Doxygen pages. If you still have the Doxygen
handy, just scroll up to the top of the page and select the ``Classes``
tab. You should see a new set of tabs appear, one of which is
``Class List``. Under that tab you will see a list of all of the
|ns3| classes. Scroll down, looking for ``ns3::NodeContainer``.
When you find the class, go ahead and select it to go to the documentation for
the class.
@@ -403,30 +403,30 @@ You may recall that one of our key abstractions is the ``Node``. This
represents a computer to which we are going to add things like protocol stacks,
applications and peripheral cards. The ``NodeContainer`` topology helper
provides a convenient way to create, manage and access any ``Node`` objects
that we create in order to run a simulation. The first line above just
that we create in order to run a simulation. The first line above just
declares a NodeContainer which we call ``nodes``. The second line calls the
``Create`` method on the ``nodes`` object and asks the container to
``Create`` method on the ``nodes`` object and asks the container to
create two nodes. As described in the Doxygen, the container calls down into
the |ns3| system proper to create two ``Node`` objects and stores
pointers to those objects internally.
The nodes as they stand in the script do nothing. The next step in
The nodes as they stand in the script do nothing. The next step in
constructing a topology is to connect our nodes together into a network.
The simplest form of network we support is a single point-to-point link
The simplest form of network we support is a single point-to-point link
between two nodes. We'll construct one of those links here.
PointToPointHelper
~~~~~~~~~~~~~~~~~~
We are constructing a point to point link, and, in a pattern which will become
quite familiar to you, we use a topology helper object to do the low-level
work required to put the link together. Recall that two of our key
work required to put the link together. Recall that two of our key
abstractions are the ``NetDevice`` and the ``Channel``. In the real
world, these terms correspond roughly to peripheral cards and network cables.
world, these terms correspond roughly to peripheral cards and network cables.
Typically these two things are intimately tied together and one cannot expect
to interchange, for example, Ethernet devices and wireless channels. Our
to interchange, for example, Ethernet devices and wireless channels. Our
Topology Helpers follow this intimate coupling and therefore you will use a
single ``PointToPointHelper`` to configure and connect |ns3|
``PointToPointNetDevice`` and ``PointToPointChannel`` objects in this
``PointToPointNetDevice`` and ``PointToPointChannel`` objects in this
script.
The next three lines in the script are,
@@ -443,7 +443,7 @@ The first line,
PointToPointHelper pointToPoint;
instantiates a ``PointToPointHelper`` object on the stack. From a
instantiates a ``PointToPointHelper`` object on the stack. From a
high-level perspective the next line,
::
@@ -451,20 +451,20 @@ high-level perspective the next line,
pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
tells the ``PointToPointHelper`` object to use the value "5Mbps"
(five megabits per second) as the "DataRate" when it creates a
(five megabits per second) as the "DataRate" when it creates a
``PointToPointNetDevice`` object.
From a more detailed perspective, the string "DataRate" corresponds
to what we call an ``Attribute`` of the ``PointToPointNetDevice``.
If you look at the Doxygen for class ``ns3::PointToPointNetDevice`` and
If you look at the Doxygen for class ``ns3::PointToPointNetDevice`` and
find the documentation for the ``GetTypeId`` method, you will find a list
of ``Attributes`` defined for the device. Among these is the "DataRate"
``Attribute``. Most user-visible |ns3| objects have similar lists of
``Attribute``. Most user-visible |ns3| objects have similar lists of
``Attributes``. We use this mechanism to easily configure simulations without
recompiling as you will see in a following section.
Similar to the "DataRate" on the ``PointToPointNetDevice`` you will find a
"Delay" ``Attribute`` associated with the ``PointToPointChannel``. The
"Delay" ``Attribute`` associated with the ``PointToPointChannel``. The
final line,
::
@@ -472,20 +472,20 @@ final line,
pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
tells the ``PointToPointHelper`` to use the value "2ms" (two milliseconds)
as the value of the propagation delay of every point to point channel it
as the value of the propagation delay of every point to point channel it
subsequently creates.
NetDeviceContainer
~~~~~~~~~~~~~~~~~~
At this point in the script, we have a ``NodeContainer`` that contains
two nodes. We have a ``PointToPointHelper`` that is primed and ready to
two nodes. We have a ``PointToPointHelper`` that is primed and ready to
make ``PointToPointNetDevices`` and wire ``PointToPointChannel`` objects
between them. Just as we used the ``NodeContainer`` topology helper object
to create the ``Nodes`` for our simulation, we will ask the
to create the ``Nodes`` for our simulation, we will ask the
``PointToPointHelper`` to do the work involved in creating, configuring and
installing our devices for us. We will need to have a list of all of the
NetDevice objects that are created, so we use a NetDeviceContainer to hold
them just as we used a NodeContainer to hold the nodes we created. The
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,
::
@@ -493,22 +493,22 @@ following two lines of code,
NetDeviceContainer devices;
devices = pointToPoint.Install (nodes);
will finish configuring the devices and channel. The first line declares the
device container mentioned above and the second does the heavy lifting. The
``Install`` method of the ``PointToPointHelper`` takes a
``NodeContainer`` as a parameter. Internally, a ``NetDeviceContainer``
is created. For each node in the ``NodeContainer`` (there must be exactly
two for a point-to-point link) a ``PointToPointNetDevice`` is created and
saved in the device container. A ``PointToPointChannel`` is created and
will finish configuring the devices and channel. The first line declares the
device container mentioned above and the second does the heavy lifting. The
``Install`` method of the ``PointToPointHelper`` takes a
``NodeContainer`` as a parameter. Internally, a ``NetDeviceContainer``
is created. For each node in the ``NodeContainer`` (there must be exactly
two for a point-to-point link) a ``PointToPointNetDevice`` is created and
saved in the device container. A ``PointToPointChannel`` is created and
the two ``PointToPointNetDevices`` are attached. When objects are created
by the ``PointToPointHelper``, the ``Attributes`` previously set in the
helper are used to initialize the corresponding ``Attributes`` in the
by the ``PointToPointHelper``, the ``Attributes`` previously set in the
helper are used to initialize the corresponding ``Attributes`` in the
created objects.
After executing the ``pointToPoint.Install (nodes)`` call we will have
two nodes, each with an installed point-to-point net device and a single
point-to-point channel between them. Both devices will be configured to
transmit data at five megabits per second over the channel which has a two
point-to-point channel between them. Both devices will be configured to
transmit data at five megabits per second over the channel which has a two
millisecond transmission delay.
InternetStackHelper
@@ -529,10 +529,10 @@ the nodes in the node container.
Ipv4AddressHelper
~~~~~~~~~~~~~~~~~
Next we need to associate the devices on our nodes with IP addresses. We
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
performing the actual address allocation (which is done at a lower level
inside the helper).
The next two lines of code in our example script, ``first.cc``,
@@ -543,12 +543,12 @@ The next two lines of code in our example script, ``first.cc``,
address.SetBase ("10.1.1.0", "255.255.255.0");
declare an address helper object and tell it that it should begin allocating IP
addresses from the network 10.1.1.0 using the mask 255.255.255.0 to define
addresses from the network 10.1.1.0 using the mask 255.255.255.0 to define
the allocatable bits. By default the addresses allocated will start at one
and increase monotonically, so the first address allocated from this base will
be 10.1.1.1, followed by 10.1.1.2, etc. The low level |ns3| system
actually remembers all of the IP addresses allocated and will generate a
fatal error if you accidentally cause the same address to be generated twice
fatal error if you accidentally cause the same address to be generated twice
(which is a very hard to debug error, by the way).
The next line of code,
@@ -559,21 +559,21 @@ The next line of code,
performs the actual address assignment. In |ns3| we make the
association between an IP address and a device using an ``Ipv4Interface``
object. Just as we sometimes need a list of net devices created by a helper
object. Just as we sometimes need a list of net devices created by a helper
for future reference we sometimes need a list of ``Ipv4Interface`` objects.
The ``Ipv4InterfaceContainer`` provides this functionality.
Now we have a point-to-point network built, with stacks installed and IP
Now we have a point-to-point network built, with stacks installed and IP
addresses assigned. What we need at this point are applications to generate
traffic.
Applications
++++++++++++
Another one of the core abstractions of the ns-3 system is the
Another one of the core abstractions of the ns-3 system is the
``Application``. In this script we use two specializations of the core
|ns3| class ``Application`` called ``UdpEchoServerApplication``
and ``UdpEchoClientApplication``. Just as we have in our previous
explanations, we use helper objects to help configure and manage the
and ``UdpEchoClientApplication``. Just as we have in our previous
explanations, we use helper objects to help configure and manage the
underlying objects. Here, we use ``UdpEchoServerHelper`` and
``UdpEchoClientHelper`` objects to make our lives easier.
@@ -591,45 +591,45 @@ created.
serverApps.Start (Seconds (1.0));
serverApps.Stop (Seconds (10.0));
The first line of code in the above snippet declares the
The first line of code in the above snippet declares the
``UdpEchoServerHelper``. As usual, this isn't the application itself, it
is an object used to help us create the actual applications. One of our
is an object used to help us create the actual applications. One of our
conventions is to place *required* ``Attributes`` in the helper constructor.
In this case, the helper can't do anything useful unless it is provided with
a port number that the client also knows about. Rather than just picking one
and hoping it all works out, we require the port number as a parameter to the
a port number that the client also knows about. Rather than just picking one
and hoping it all works out, we require the port number as a parameter to the
constructor. The constructor, in turn, simply does a ``SetAttribute``
with the passed value. If you want, you can set the "Port" ``Attribute``
to another value later using ``SetAttribute``.
Similar to many other helper objects, the ``UdpEchoServerHelper`` object
Similar to many other helper objects, the ``UdpEchoServerHelper`` object
has an ``Install`` method. It is the execution of this method that actually
causes the underlying echo server application to be instantiated and attached
to a node. Interestingly, the ``Install`` method takes a
``NodeContainter`` as a parameter just as the other ``Install`` methods
we have seen. This is actually what is passed to the method even though it
we have seen. This is actually what is passed to the method even though it
doesn't look so in this case. There is a C++ *implicit conversion* at
work here that takes the result of ``nodes.Get (1)`` (which returns a smart
pointer to a node object --- ``Ptr<Node>``) and uses that in a constructor
for an unnamed ``NodeContainer`` that is then passed to ``Install``.
If you are ever at a loss to find a particular method signature in C++ code
that compiles and runs just fine, look for these kinds of implicit conversions.
that compiles and runs just fine, look for these kinds of implicit conversions.
We now see that ``echoServer.Install`` is going to install a
``UdpEchoServerApplication`` on the node found at index number one of the
``NodeContainer`` we used to manage our nodes. ``Install`` will return
a container that holds pointers to all of the applications (one in this case
since we passed a ``NodeContainer`` containing one node) created by the
a container that holds pointers to all of the applications (one in this case
since we passed a ``NodeContainer`` containing one node) created by the
helper.
Applications require a time to "start" generating traffic and may take an
optional time to "stop". We provide both. These times are set using the
``ApplicationContainer`` methods ``Start`` and ``Stop``. These
``ApplicationContainer`` methods ``Start`` and ``Stop``. These
methods take ``Time`` parameters. In this case, we use an *explicit*
C++ conversion sequence to take the C++ double 1.0 and convert it to an
C++ conversion sequence to take the C++ double 1.0 and convert it to an
|ns3| ``Time`` object using a ``Seconds`` cast. Be aware that
the conversion rules may be controlled by the model author, and C++ has its
own rules, so you can't always just assume that parameters will be happily
own rules, so you can't always just assume that parameters will be happily
converted for you. The two lines,
::
@@ -662,27 +662,27 @@ that is managed by an ``UdpEchoClientHelper``.
clientApps.Stop (Seconds (10.0));
For the echo client, however, we need to set five different ``Attributes``.
The first two ``Attributes`` are set during construction of the
The first two ``Attributes`` are set during construction of the
``UdpEchoClientHelper``. We pass parameters that are used (internally to
the helper) to set the "RemoteAddress" and "RemotePort" ``Attributes``
in accordance with our convention to make required ``Attributes`` parameters
in the helper constructors.
in the helper constructors.
Recall that we used an ``Ipv4InterfaceContainer`` to keep track of the IP
addresses we assigned to our devices. The zeroth interface in the
``interfaces`` container is going to correspond to the IP address of the
zeroth node in the ``nodes`` container. The first interface in the
``interfaces`` container corresponds to the IP address of the first node
Recall that we used an ``Ipv4InterfaceContainer`` to keep track of the IP
addresses we assigned to our devices. The zeroth interface in the
``interfaces`` container is going to correspond to the IP address of the
zeroth node in the ``nodes`` container. The first interface in the
``interfaces`` container corresponds to the IP address of the first node
in the ``nodes`` container. So, in the first line of code (from above), we
are creating the helper and telling it so set the remote address of the client
to be the IP address assigned to the node on which the server resides. We
to be the IP address assigned to the node on which the server resides. We
also tell it to arrange to send packets to port nine.
The "MaxPackets" ``Attribute`` tells the client the maximum number of
packets we allow it to send during the simulation. The "Interval"
The "MaxPackets" ``Attribute`` tells the client the maximum number of
packets we allow it to send during the simulation. The "Interval"
``Attribute`` tells the client how long to wait between packets, and the
"PacketSize" ``Attribute`` tells the client how large its packet payloads
should be. With this particular combination of ``Attributes``, we are
should be. With this particular combination of ``Attributes``, we are
telling the client to send one 1024-byte packet.
Just as in the case of the echo server, we tell the echo client to ``Start``
@@ -691,7 +691,7 @@ enabled (at two seconds into the simulation).
Simulator
+++++++++
What we need to do at this point is to actually run the simulation. This is
What we need to do at this point is to actually run the simulation. This is
done using the global function ``Simulator::Run``.
::
@@ -709,35 +709,35 @@ When we previously called the methods,
clientApps.Stop (Seconds (10.0));
we actually scheduled events in the simulator at 1.0 seconds, 2.0 seconds and
two events at 10.0 seconds. When ``Simulator::Run`` is called, the system
will begin looking through the list of scheduled events and executing them.
First it will run the event at 1.0 seconds, which will enable the echo server
application (this event may, in turn, schedule many other events). Then it
two events at 10.0 seconds. When ``Simulator::Run`` is called, the system
will begin looking through the list of scheduled events and executing them.
First it will run the event at 1.0 seconds, which will enable the echo server
application (this event may, in turn, schedule many other events). Then it
will run the event scheduled for t=2.0 seconds which will start the echo client
application. Again, this event may schedule many more events. The start event
implementation in the echo client application will begin the data transfer phase
of the simulation by sending a packet to the server.
The act of sending the packet to the server will trigger a chain of events
that will be automatically scheduled behind the scenes and which will perform
the mechanics of the packet echo according to the various timing parameters
that will be automatically scheduled behind the scenes and which will perform
the mechanics of the packet echo according to the various timing parameters
that we have set in the script.
Eventually, since we only send one packet (recall the ``MaxPackets``
``Attribute`` was set to one), the chain of events triggered by
that single client echo request will taper off and the simulation will go
Eventually, since we only send one packet (recall the ``MaxPackets``
``Attribute`` was set to one), the chain of events triggered by
that single client echo request will taper off and the simulation will go
idle. Once this happens, the remaining events will be the ``Stop`` events
for the server and the client. When these events are executed, there are
no further events to process and ``Simulator::Run`` returns. The simulation
is then complete.
All that remains is to clean up. This is done by calling the global function
``Simulator::Destroy``. As the helper functions (or low level
All that remains is to clean up. This is done by calling the global function
``Simulator::Destroy``. As the helper functions (or low level
|ns3| code) executed, they arranged it so that hooks were inserted in
the simulator to destroy all of the objects that were created. You did not
have to keep track of any of these objects yourself --- all you had to do
the simulator to destroy all of the objects that were created. You did not
have to keep track of any of these objects yourself --- all you had to do
was to call ``Simulator::Destroy`` and exit. The |ns3| system
took care of the hard part for you. The remaining lines of our first
took care of the hard part for you. The remaining lines of our first
|ns3| script, ``first.cc``, do just that:
::
@@ -755,21 +755,21 @@ events in the temporal order of simulation time. Events may cause future
events to be scheduled (for example, a timer may reschedule itself to
expire at the next interval).
The initial events are usually triggered by each object, e.g., IPv6 will
schedule Router Advertisements, Neighbor Solicitations, etc.,
The initial events are usually triggered by each object, e.g., IPv6 will
schedule Router Advertisements, Neighbor Solicitations, etc.,
an Application schedule the first packet sending event, etc.
When an event is processed, it may generate zero, one or more events.
As a simulation executes, events are consumed, but more events may (or may
not) be generated.
The simulation will stop automatically when no further events are in the
event queue, or when a special Stop event is found. The Stop event is
created through the
The simulation will stop automatically when no further events are in the
event queue, or when a special Stop event is found. The Stop event is
created through the
``Simulator::Stop (stopTime);`` function.
There is a typical case where ``Simulator::Stop`` is absolutely necessary
There is a typical case where ``Simulator::Stop`` is absolutely necessary
to stop the simulation: when there is a self-sustaining event.
Self-sustaining (or recurring) events are events that always reschedule
Self-sustaining (or recurring) events are events that always reschedule
themselves. As a consequence, they always keep the event queue non-empty.
There are many protocols and modules containing recurring events, e.g.:
@@ -778,17 +778,17 @@ There are many protocols and modules containing recurring events, e.g.:
* RIPng - periodic broadcast of routing tables update
* etc.
In these cases, ``Simulator::Stop`` is necessary to gracefully stop the
simulation. In addition, when |ns3| is in emulation mode, the
``RealtimeSimulator`` is used to keep the simulation clock aligned with
the machine clock, and ``Simulator::Stop`` is necessary to stop the
process.
In these cases, ``Simulator::Stop`` is necessary to gracefully stop the
simulation. In addition, when |ns3| is in emulation mode, the
``RealtimeSimulator`` is used to keep the simulation clock aligned with
the machine clock, and ``Simulator::Stop`` is necessary to stop the
process.
Many of the simulation programs in the tutorial do not explicitly call
``Simulator::Stop``, since the event queue will automatically run out
of events. However, these programs will also accept a call to
of events. However, these programs will also accept a call to
``Simulator::Stop``. For example, the following additional statement
in the first example program will schedule an explicit stop at 11 seconds:
in the first example program will schedule an explicit stop at 11 seconds:
::
@@ -799,20 +799,20 @@ in the first example program will schedule an explicit stop at 11 seconds:
}
The above will not actually change the behavior of this program, since
this particular simulation naturally ends after 10 seconds. But if you
were to change the stop time in the above statement from 11 seconds to 1
second, you would notice that the simulation stops before any output is
printed to the screen (since the output occurs around time 2 seconds of
this particular simulation naturally ends after 10 seconds. But if you
were to change the stop time in the above statement from 11 seconds to 1
second, you would notice that the simulation stops before any output is
printed to the screen (since the output occurs around time 2 seconds of
simulation time).
It is important to call ``Simulator::Stop`` *before* calling
It is important to call ``Simulator::Stop`` *before* calling
``Simulator::Run``; otherwise, ``Simulator::Run`` may never return control
to the main program to execute the stop!
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
We have made it trivial to build your simple scripts. All you have to do is
to drop your script into the scratch directory and it will automatically be
built if you run ns3. Let's try it. Copy ``examples/tutorial/first.cc`` into
the ``scratch`` directory after changing back into the top level directory.
@@ -857,17 +857,17 @@ You should see some output:
Received 1024 bytes from 10.1.1.2
Here you see that the build system checks to make sure that the file has been
build and then runs it. You see the logging component on the echo client
indicate that it has sent one 1024 byte packet to the Echo Server on
build and then runs it. You see the logging component on the echo client
indicate that it has sent one 1024 byte packet to the Echo Server on
10.1.1.2. You also see the logging component on the echo server say that
it has received the 1024 bytes from 10.1.1.1. The echo server silently
echoes the packet and you see the echo client log that it has received its
it has received the 1024 bytes from 10.1.1.1. The echo server silently
echoes the packet and you see the echo client log that it has received its
packet back from the server.
Ns-3 Source Code
****************
Now that you have used some of the |ns3| helpers you may want to
Now that you have used some of the |ns3| helpers you may want to
have a look at some of the source code that implements that functionality.
The most recent code can be browsed on our web server at the following link:
https://gitlab.com/nsnam/ns-3-dev.git. There, you will see the Git/GitLab
@@ -877,7 +877,7 @@ At the top of the page, you will see a number of links,
.. sourcecode:: text
summary | shortlog | changelog | graph | tags | files
summary | shortlog | changelog | graph | tags | files
Go ahead and select the ``files`` link. This is what the top-level of
most of our *repositories* will look:
@@ -922,12 +922,12 @@ you click on ``first.cc`` you will find the code you just walked through.
The source code is mainly in the ``src`` directory. You can view source
code either by clicking on the directory name or by clicking on the ``files``
link to the right of the directory name. If you click on the ``src``
directory, you will be taken to the listing of the ``src`` subdirectories. If you
directory, you will be taken to the listing of the ``src`` subdirectories. If you
then click on ``core`` subdirectory, you will find a list of files. The first file
you will find (as of this writing) is ``abort.h``. If you click on the
``abort.h`` link, you will be sent to the source file for ``abort.h`` which
you will find (as of this writing) is ``abort.h``. If you click on the
``abort.h`` link, you will be sent to the source file for ``abort.h`` which
contains useful macros for exiting scripts if abnormal conditions are detected.
The source code for the helpers we have used in this chapter can be found in the
The source code for the helpers we have used in this chapter can be found in the
``src/applications/helper`` directory. Feel free to poke around in the directory tree to
get a feel for what is there and the style of |ns3| programs.

View File

@@ -7,8 +7,8 @@ Conclusion
Futures
*******
This document is intended as a living document. We hope and expect it to
grow over time to cover more and more of the nuts and bolts of |ns3|.
This document is intended as a living document. We hope and expect it to
grow over time to cover more and more of the nuts and bolts of |ns3|.
Writing manual and tutorial chapters is not something we all get excited about,
but it is very important to the project. If you are an expert in one of these
@@ -18,7 +18,7 @@ chapters; or any other chapter you may think is important.
Closing
*******
|ns3| is a large and complicated system. It is impossible to cover all
|ns3| is a large and complicated system. It is impossible to cover all
of the things you will need to know in one small tutorial. Readers
who want to learn more are encouraged to read the following additional
documentation:

View File

@@ -22,7 +22,7 @@
# To change default code-block format in Latex to footnotesize (8pt)
# Tip from https://stackoverflow.com/questions/9899283/how-do-you-change-the-code-example-font-size-in-latex-pdf-output-with-sphinx/9955928
# Note: sizes are \footnotesize (8pt), \small (9pt), and \normalsize (10pt).
# Note: sizes are \footnotesize (8pt), \small (9pt), and \normalsize (10pt).
#from sphinx.highlighting import PygmentsBridge
#from pygments.formatters.latex import LatexFormatter
@@ -271,7 +271,7 @@ latex_elements = {
# (double backquotes) to either \footnotesize (8pt) or \small (9pt)
#
# See above to change the font size of verbatim code blocks
#
#
# 'preamble': '',
'preamble': u'''\\usepackage{amssymb}
\\definecolor{VerbatimBorderColor}{rgb}{1,1,1}

View File

@@ -13,10 +13,10 @@ tutorial section is also a work-in-progress.
Motivation
**********
One of the main points of running simulations is to generate output data,
One of the main points of running simulations is to generate output data,
either for research purposes or simply to learn about the system.
In the previous chapter, we introduced the tracing subsystem and
the example ``sixth.cc``. from which PCAP or ASCII trace files are
the example ``sixth.cc``. from which PCAP or ASCII trace files are
generated. These traces are valuable for data analysis using a
variety of external tools, and for many users, such output data is
a preferred means of gathering data (for analysis by external tools).
@@ -30,7 +30,7 @@ including the following:
trace files is prohibitive or cumbersome, and
* the need for *online* data reduction or computation, during the course
of the simulation. A good example of this is to define a termination
condition for the simulation, to tell it when to stop when it has
condition for the simulation, to tell it when to stop when it has
received enough data to form a narrow-enough confidence interval around
the estimate of some parameter.
@@ -38,7 +38,7 @@ The |ns3| data collection framework is designed to provide these
additional capabilities beyond trace-based output. We recommend
that the reader interested in this topic consult the |ns3| Manual
for a more detailed treatment of this framework; here, we summarize
with an example program some of the developing capabilities.
with an example program some of the developing capabilities.
Example Code
************
@@ -47,14 +47,14 @@ The tutorial example ``examples/tutorial/seventh.cc`` resembles the
``sixth.cc`` example we previously reviewed, except for a few changes.
First, it has been enabled for IPv6 support with a command-line option:
::
::
CommandLine cmd;
cmd.AddValue ("useIpv6", "Use Ipv6", useV6);
cmd.Parse (argc, argv);
If the user specifies ``useIpv6``, option, the program will be run
using IPv6 instead of IPv4. The ``help`` option, available on all |ns3|
using IPv6 instead of IPv4. The ``help`` option, available on all |ns3|
programs that support the CommandLine object as shown above, can
be invoked as follows (please note the use of double quotes):
@@ -67,10 +67,10 @@ which produces:
::
ns3-dev-seventh-debug [Program Arguments] [General Arguments]
Program Arguments:
--useIpv6: Use Ipv6 [false]
General Arguments:
--PrintGlobals: Print the list of globals.
--PrintGroups: Print the list of groups.
@@ -79,7 +79,7 @@ which produces:
--PrintAttributes=[typeid]: Print all attributes of typeid.
--PrintHelp: Print this help message.
This default (use of IPv4, since useIpv6 is false) can be changed by
This default (use of IPv4, since useIpv6 is false) can be changed by
toggling the boolean value as follows:
::
@@ -93,11 +93,11 @@ and have a look at the pcap generated, such as with ``tcpdump``:
tcpdump -r seventh.pcap -nn -tt
This has been a short digression into IPv6 support and the command line,
which was also introduced earlier in this tutorial. For a dedicated
example of command line usage, please see
which was also introduced earlier in this tutorial. For a dedicated
example of command line usage, please see
``src/core/examples/command-line-example.cc``.
Now back to data collection. In the ``examples/tutorial/`` directory,
Now back to data collection. In the ``examples/tutorial/`` directory,
type the following command: ``diff -u sixth.cc seventh.cc``, and examine
some of the new lines of this diff:
@@ -120,7 +120,7 @@ some of the new lines of this diff:
...
+ // Use GnuplotHelper to plot the packet byte count over time
+ GnuplotHelper plotHelper;
+
+
+ // Configure the plot. The first argument is the file name prefix
+ // for the output files generated. The second, third, and fourth
+ // arguments are, respectively, the plot title, x-axis, and y-axis labels
@@ -128,7 +128,7 @@ some of the new lines of this diff:
+ "Packet Byte Count vs. Time",
+ "Time (Seconds)",
+ "Packet Byte Count");
+
+
+ // Specify the probe type, trace source path (in configuration namespace), and
+ // probe output trace source ("OutputBytes") to plot. The fourth argument
+ // specifies the name of the data series label on the plot. The last
@@ -138,27 +138,27 @@ some of the new lines of this diff:
+ "OutputBytes",
+ "Packet Byte Count",
+ GnuplotAggregator::KEY_BELOW);
+
+
+ // Use FileHelper to write out the packet byte count over time
+ FileHelper fileHelper;
+
+
+ // Configure the file to be written, and the formatting of output data.
+ fileHelper.ConfigureFile ("seventh-packet-byte-count",
+ FileAggregator::FORMATTED);
+
+
+ // Set the labels for this formatted output file.
+ fileHelper.Set2dFormat ("Time (Seconds) = %.3e\tPacket Byte Count = %.0f");
+
+
+ // Specify the probe type, probe path (in configuration namespace), and
+ // probe output trace source ("OutputBytes") to write.
+ fileHelper.WriteProbe (probeType,
+ tracePath,
+ "OutputBytes");
+
+
Simulator::Stop (Seconds (20));
Simulator::Run ();
Simulator::Destroy ();
The careful reader will have noticed, when testing the IPv6 command
line attribute above, that ``seventh.cc`` had created a number of new output files:
@@ -185,20 +185,20 @@ GnuplotHelper
The GnuplotHelper is an |ns3| helper object aimed at the production of
``gnuplot`` plots with as few statements as possible, for common cases.
It hooks |ns3| trace sources with data types supported by the
data collection system. Not all |ns3| trace sources data types are
supported, but many of the common trace types are, including TracedValues
It hooks |ns3| trace sources with data types supported by the
data collection system. Not all |ns3| trace sources data types are
supported, but many of the common trace types are, including TracedValues
with plain old data (POD) types.
Let's look at the output produced by this helper:
::
seventh-packet-byte-count.dat
seventh-packet-byte-count.plt
seventh-packet-byte-count.sh
The first is a gnuplot data file with a series of space-delimited
The first is a gnuplot data file with a series of space-delimited
timestamps and packet byte counts. We'll cover how this particular
data output was configured below, but let's continue with the output
files. The file ``seventh-packet-byte-count.plt`` is a gnuplot plot file,
@@ -209,16 +209,16 @@ syntax can see that this will produce a formatted output PNG file named
to produce the desired PNG (which can be viewed in an image editor); that
is, the command:
::
::
sh seventh-packet-byte-count.sh
will yield ``seventh-packet-byte-count.png``. Why wasn't this PNG
produced in the first place? The answer is that by providing the
produced in the first place? The answer is that by providing the
plt file, the user can hand-configure the result if desired, before
producing the PNG.
The PNG image title states that this plot is a plot of
The PNG image title states that this plot is a plot of
"Packet Byte Count vs. Time", and that it is plotting the probed data
corresponding to the trace source path:
@@ -226,7 +226,7 @@ corresponding to the trace source path:
/NodeList/*/$ns3::Ipv6L3Protocol/Tx
Note the wild-card in the trace path. In summary, what this plot is
Note the wild-card in the trace path. In summary, what this plot is
capturing is the plot of packet bytes observed at the transmit trace
source of the Ipv6L3Protocol object; largely 596-byte TCP segments
in one direction, and 60-byte TCP acks in the other (two node
@@ -236,7 +236,7 @@ How was this configured? A few statements need to be provided. First,
the GnuplotHelper object must be declared and configured:
::
+ // Use GnuplotHelper to plot the packet byte count over time
+ GnuplotHelper plotHelper;
+
@@ -254,7 +254,7 @@ is the first argument, the plot title is the second, the x-axis label
the third, and the y-axis label the fourth argument.
The next step is to configure the data, and here is where the trace
source is hooked. First, note above in the program we declared a few
source is hooked. First, note above in the program we declared a few
variables for later use:
::
@@ -267,7 +267,7 @@ variables for later use:
We use them here:
::
+ // Specify the probe type, trace source path (in configuration namespace), and
+ // probe output trace source ("OutputBytes") to plot. The fourth argument
+ // specifies the name of the data series label on the plot. The last
@@ -315,7 +315,7 @@ The Ipv6PacketProbe exports, itself, some trace sources that extract
the data out of the probed Packet object:
::
TypeId
Ipv6PacketProbe::GetTypeId ()
{
@@ -332,14 +332,14 @@ the data out of the probed Packet object:
;
return tid;
}
The third argument of our PlotProbe statement specifies that we are
interested in the number of bytes in this packet; specifically, the
"OutputBytes" trace source of Ipv6PacketProbe.
Finally, the last two arguments of the statement provide the plot
legend for this data series ("Packet Byte Count"), and an optional
gnuplot formatting statement (GnuplotAggregator::KEY_BELOW) that we want
gnuplot formatting statement (GnuplotAggregator::KEY_BELOW) that we want
the plot key to be inserted below the plot. Other options include
NO_KEY, KEY_INSIDE, and KEY_ABOVE.
@@ -381,7 +381,7 @@ The following TraceSource types are supported by Probes as of this writing:
| Ptr<const Packet>, const Address& | ApplicationPacketProbe | OutputBytes | applications/model/application-packet-probe.h |
+------------------------------------------+------------------------+---------------+----------------------------------------------------+
As can be seen, only a few trace sources are supported, and they are all
As can be seen, only a few trace sources are supported, and they are all
oriented towards outputting the Packet size (in bytes). However,
most of the fundamental data types available as TracedValues can be
supported with these helpers.
@@ -394,7 +394,7 @@ example. The example program provides formatted output of the
same timestamped data, such as follows:
::
Time (Seconds) = 9.312e+00 Packet Byte Count = 596
Time (Seconds) = 9.312e+00 Packet Byte Count = 564
@@ -405,7 +405,7 @@ be seen in the filenames. Let's look at the code piece-by-piece:
+ // Use FileHelper to write out the packet byte count over time
+ FileHelper fileHelper;
+
+
+ // Configure the file to be written, and the formatting of output data.
+ fileHelper.ConfigureFile ("seventh-packet-byte-count",
+ FileAggregator::FORMATTED);
@@ -414,11 +414,11 @@ The file helper file prefix is the first argument, and a format specifier
is next.
Some other options for formatting include SPACE_SEPARATED, COMMA_SEPARATED,
and TAB_SEPARATED. Users are able to change the formatting (if
FORMATTED is specified) with a format string such as follows:
FORMATTED is specified) with a format string such as follows:
::
+
+
+ // Set the labels for this formatted output file.
+ fileHelper.Set2dFormat ("Time (Seconds) = %.3e\tPacket Byte Count = %.0f");
@@ -428,17 +428,17 @@ trace source "OutputBytes" is hooked:
::
+
+
+ // Specify the probe type, trace source path (in configuration namespace), and
+ // probe output trace source ("OutputBytes") to write.
+ fileHelper.WriteProbe (probeType,
+ tracePath,
+ "OutputBytes");
+
+
The wildcard fields in this trace source specifier match two trace sources.
Unlike the GnuplotHelper example, in which two data series were overlaid
on the same plot, here, two separate files are written to disk.
on the same plot, here, two separate files are written to disk.
Summary
*******
@@ -447,5 +447,5 @@ Data collection support is new as of ns-3.18, and basic support for
providing time series output has been added. The basic pattern described
above may be replicated within the scope of support of the existing
probes and trace sources. More capabilities including statistics
processing will be added in future releases.
processing will be added in future releases.

View File

@@ -16,17 +16,17 @@ Overview
|ns3| is built as a system of software libraries that work together.
User programs can be written that links with (or imports from) these
libraries. User programs are written in either the C++ or Python
libraries. User programs are written in either the C++ or Python
programming languages.
|ns3| is distributed as source code, meaning that the target system
needs to have a software development environment to build the libraries
first, then build the user program. |ns3| could in principle be
first, then build the user program. |ns3| could in principle be
distributed as pre-built libraries for selected systems, and in the
future it may be distributed that way, but at present, many users
actually do their work by editing |ns3| itself, so having the source
code around to rebuild the libraries is useful. If someone would like
to undertake the job of making pre-built libraries and packages for
code around to rebuild the libraries is useful. If someone would like
to undertake the job of making pre-built libraries and packages for
operating systems, please contact the ns-developers mailing list.
In the following, we'll look at three ways of downloading and building
@@ -49,11 +49,11 @@ a non-privileged user account is recommended.
Prerequisites
*************
The entire set of available |ns3| libraries has a number of dependencies
The entire set of available |ns3| libraries has a number of dependencies
on third-party libraries, but most of |ns3| can be built and used with
support for a few common (often installed by default) components: a
C++ compiler, an installation of Python, a source code editor (such as vim,
emacs, or Eclipse) and, if using the development repositories, an
emacs, or Eclipse) and, if using the development repositories, an
installation of Git source code control system. Most beginning users
need not concern themselves if their configuration reports some missing
optional features of |ns3|, but for those wishing a full installation,
@@ -62,13 +62,13 @@ and tips. One such page is the "Installation" page, with install instructions
for various systems, available at
https://www.nsnam.org/wiki/Installation.
The "Prerequisites" section of this wiki page explains which packages are
required to support common |ns3| options, and also provides the
The "Prerequisites" section of this wiki page explains which packages are
required to support common |ns3| options, and also provides the
commands used to install them for common Linux or macOS variants.
You may want to take this opportunity to explore the |ns3| wiki
a bit, or the main web site at https://www.nsnam.org, since there is a
wealth of information there.
You may want to take this opportunity to explore the |ns3| wiki
a bit, or the main web site at https://www.nsnam.org, since there is a
wealth of information there.
As of the most recent |ns3| release (ns-3.36), the following tools
are needed to get started with |ns3|:
@@ -104,7 +104,7 @@ of the parent directories contains a space in the directory name:
Downloading a release of ns-3 as a source archive
+++++++++++++++++++++++++++++++++++++++++++++++++
This option is for the new user who wishes to download and experiment with
This option is for the new user who wishes to download and experiment with
the most recently released and packaged version of |ns3|.
|ns3| publishes its releases as compressed source archives, sometimes
referred to as a tarball.
@@ -114,9 +114,9 @@ The process for downloading |ns3| via tarball is simple; you just
have to pick a release, download it and uncompress it.
Let's assume that you, as a user, wish to build |ns3| in a local
directory called ``workspace``.
If you adopt the ``workspace`` directory approach, you can
get a copy of a release by typing the following into your Linux shell
directory called ``workspace``.
If you adopt the ``workspace`` directory approach, you can
get a copy of a release by typing the following into your Linux shell
(substitute the appropriate version numbers, of course)
.. sourcecode:: console
@@ -130,8 +130,8 @@ get a copy of a release by typing the following into your Linux shell
Notice the use above of the ``wget`` utility, which is a command-line
tool to fetch objects from the web; if you do not have this installed,
you can use a browser for this step.
Following these steps, if you change into the directory
Following these steps, if you change into the directory
``ns-allinone-3.36``, you should see a number of files and directories
.. sourcecode:: text
@@ -152,7 +152,7 @@ at https://gitlab.com/nsnam/. The group name ``nsnam`` organizes the
various repositories used by the open source project.
The simplest way to get started using Git repositories is to fork or clone
the ``ns-3-allinone`` environment. This is a set of scripts that manages the
the ``ns-3-allinone`` environment. This is a set of scripts that manages the
downloading and building of the most commonly used subsystems of |ns3|
for you. If you are new to Git, the terminology of ``fork`` and ``clone``
may be foreign to you; if so, we recommend that you simply ``clone``
@@ -193,7 +193,7 @@ release number:
After this step, the additional repositories of |ns3|, bake, pybindgen,
and netanim will be downloaded to the ``ns-3-allinone`` directory.
Downloading ns-3 Using Bake
+++++++++++++++++++++++++++
@@ -205,7 +205,7 @@ ns-3-allinone is called ``bake``.
Bake is a tool for coordinated software building from multiple repositories,
developed for the |ns3| project. Bake can be used to fetch development
versions of the |ns3| software, and to download and build extensions to the
versions of the |ns3| software, and to download and build extensions to the
base |ns3| distribution, such as the Direct Code Execution environment,
Network Simulation Cradle, ability to create new Python bindings, and
various |ns3| "apps". If you envision that your |ns3| installation may
@@ -218,10 +218,10 @@ will allow one to download any software that was current at the
time of the release. That is, for example, the version of Bake that
is distributed with the ``ns-3.30`` release can be used to fetch components
for that |ns3| release or earlier, but can't be used to fetch components
for later releases (unless the ``bakeconf.xml`` package description file
for later releases (unless the ``bakeconf.xml`` package description file
is updated).
You can also get the most recent copy of ``bake`` by typing the
You can also get the most recent copy of ``bake`` by typing the
following into your Linux shell (assuming you have installed Git)::
$ cd
@@ -229,7 +229,7 @@ following into your Linux shell (assuming you have installed Git)::
$ cd workspace
$ git clone https://gitlab.com/nsnam/bake.git
As the git command executes, you should see something like the
As the git command executes, you should see something like the
following displayed:
.. sourcecode:: console
@@ -242,7 +242,7 @@ following displayed:
Receiving objects: 100% (2086/2086), 2.68 MiB | 3.82 MiB/s, done.
Resolving deltas: 100% (1404/1404), done.
After the clone command completes, you should have a directory called
After the clone command completes, you should have a directory called
``bake``, the contents of which should look something like the following:
.. sourcecode:: console
@@ -266,21 +266,21 @@ There are a few configuration targets available:
4. ``ns-3-allinone``: similar to the released version of the allinone
module, but for development code.
The current development snapshot (unreleased) of |ns3| may be found
at https://gitlab.com/nsnam/ns-3-dev.git. The
The current development snapshot (unreleased) of |ns3| may be found
at https://gitlab.com/nsnam/ns-3-dev.git. The
developers attempt to keep these repositories in consistent, working states but
they are in a development area with unreleased code present, so you may want
they are in a development area with unreleased code present, so you may want
to consider staying with an official release if you do not need newly-
introduced features.
You can find the latest version of the
code either by inspection of the repository list or by going to the
code either by inspection of the repository list or by going to the
`"ns-3 Releases"
<https://www.nsnam.org/releases>`_
web page and clicking on the latest release link. We'll proceed in
this tutorial example with ``ns-3.36``.
We are now going to use the bake tool to pull down the various pieces of
We are now going to use the bake tool to pull down the various pieces of
|ns3| you will be using. First, we'll say a word about running bake.
Bake works by downloading source packages into a source directory,
@@ -290,9 +290,9 @@ outside of the directory it was downloaded into, it is advisable
to put bake into your path, such as follows (Linux bash shell example).
First, change into the 'bake' directory, and then set the following
environment variables:
.. sourcecode:: console
$ export BAKE_HOME=`pwd`
$ export PATH=$PATH:$BAKE_HOME:$BAKE_HOME/build/bin
$ export PYTHONPATH=$PYTHONPATH:$BAKE_HOME:$BAKE_HOME/build/lib
@@ -333,8 +333,8 @@ You should see something like the following:
In particular, download tools such as Git and Mercurial
are our principal concerns at this point, since they allow us to fetch
the code. Please install missing tools at this stage, in the usual
way for your system (if you are able to), or contact your system
administrator as needed to install these tools. You can also
way for your system (if you are able to), or contact your system
administrator as needed to install these tools. You can also
Next, try to download the software:
@@ -393,15 +393,15 @@ described above; not from downloading via git or bake.
When working from a released tarball, a convenience script available as
part of ``ns-3-allinone`` can orchestrate a simple build of components.
This program is called ``build.py``. This
This program is called ``build.py``. This
program will get the project configured for you
in the most commonly useful way. However, please note that more advanced
configuration and work with |ns3| will typically involve using the
native |ns3| build system, CMake, to be introduced later in this tutorial.
If you downloaded
using a tarball you should have a directory called something like
``ns-allinone-3.36`` under your ``~/workspace`` directory.
using a tarball you should have a directory called something like
``ns-allinone-3.36`` under your ``~/workspace`` directory.
Type the following:
.. sourcecode:: console
@@ -424,7 +424,7 @@ Building with bake
++++++++++++++++++
If you used bake above to fetch source code from project repositories, you
may continue to use it to build |ns3|. Type:
may continue to use it to build |ns3|. Type:
.. sourcecode:: console
@@ -440,12 +440,12 @@ and you should see something like:
There may be failures to build all components, but the build will proceed
anyway if the component is optional. For example, a recent portability issue
has been that castxml may not build via the bake build tool on all
has been that castxml may not build via the bake build tool on all
platforms; in this case, the line will show something like::
>> Building castxml - Problem
> Problem: Optional dependency, module "castxml" failed
This may reduce the functionality of the final build.
This may reduce the functionality of the final build.
However, bake will continue since "castxml" is not an essential dependency.
For more information call bake with -v or -vvv, for full verbose mode.
@@ -475,18 +475,18 @@ CMake needs to be installed before building |ns3|.
So, to proceed, please change your working directory to
the |ns3| directory that you have initially built.
It's not
It's not
strictly required at this point, but it will be valuable to take a slight
detour and look at how to make changes to the configuration of the project.
Probably the most useful configuration change you can make will be to
Probably the most useful configuration change you can make will be to
build the optimized version of the code. The project will be configured
by default using the ``default`` build profile, which is an optimized
build with debug information (CMAKE_BUILD_TYPE=relwithdebinfo) version.
build with debug information (CMAKE_BUILD_TYPE=relwithdebinfo) version.
Let's tell the project to make an optimized build.
To maintain a similar interface for command-line users, we include a
wrapper script for CMake, |ns3|. To tell |ns3| that it should do optimized
builds that include the examples and tests, you will need to execute the
builds that include the examples and tests, you will need to execute the
following commands:
.. sourcecode:: console
@@ -495,11 +495,11 @@ following commands:
$ ./ns3 configure --build-profile=optimized --enable-examples --enable-tests
This runs CMake out of the local directory (which is provided as a convenience
for you). The first command to clean out the previous build is not
for you). The first command to clean out the previous build is not
typically strictly necessary but is good practice (but see `Build Profiles`_,
below); it will remove the
previously built libraries and object files found in directory ``build/``.
When the project is reconfigured and the build system checks for various
previously built libraries and object files found in directory ``build/``.
When the project is reconfigured and the build system checks for various
dependencies, you should see
output that looks similar to the following:
@@ -651,8 +651,8 @@ output that looks similar to the following:
Tap Bridge : ON
Tap FdNetDevice : ON
Tests : ON
Modules configured to be built:
antenna aodv applications
bridge buildings config-store
@@ -667,13 +667,13 @@ output that looks similar to the following:
tap-bridge test topology-read
traffic-control uan virtual-net-device
wave wifi wimax
Modules that cannot be built:
brite click mpi
openflow visualizer
-- Configuring done
-- Generating done
-- Build files have been written to: /mnt/dev/tools/source/ns-3-dev/cmake-cache
@@ -686,8 +686,8 @@ Note the last part of the above output. Some |ns3| options are not enabled by
default or require support from the underlying system to work properly (``OFF (not requested)``).
Other options might depend on third-party libraries, which if not found will be disabled
(``OFF(missing dependency)``).
If this library were not found, the corresponding |ns3| feature
would not be enabled and a message would be displayed. Note further that there is
If this library were not found, the corresponding |ns3| feature
would not be enabled and a message would be displayed. Note further that there is
a feature to use the program ``sudo`` to set the suid bit of certain programs.
This is not enabled by default and so this feature is reported as "not enabled."
Finally, to reprint this summary of which optional features are enabled, use
@@ -700,7 +700,7 @@ Now go ahead and switch back to the debug build that includes the examples and t
$ ./ns3 clean
$ ./ns3 configure --build-profile=debug --enable-examples --enable-tests
The build system is now configured and you can build the debug versions of
The build system is now configured and you can build the debug versions of
the |ns3| programs by simply typing:
.. sourcecode:: console
@@ -737,7 +737,7 @@ options through to ns3, so instead of the above, the following will work:
.. sourcecode:: console
$ ./build.py -- --disable-python
$ ./build.py -- --disable-python
as it generates the underlying command ``./ns3 configure --disable-python``.
@@ -762,7 +762,7 @@ on Fedora 28, when Gtk2+ is installed, will result in an error such as::
void (*__gtk_reserved1);
In releases starting with ns-3.28.1, an option is available in CMake to work
around these issues. The option disables the inclusion of the '-Werror'
around these issues. The option disables the inclusion of the '-Werror'
flag to g++ and clang++. The option is '--disable-werror' and must be
used at configure time; e.g.:
@@ -774,9 +774,9 @@ Configure vs. Build
===================
Some CMake commands are only meaningful during the configure phase and some commands are valid
in the build phase. For example, if you wanted to use the emulation
in the build phase. For example, if you wanted to use the emulation
features of |ns3|, you might want to enable setting the suid bit using
sudo as described above. This turns out to be a configuration-time command, and so
sudo as described above. This turns out to be a configuration-time command, and so
you could reconfigure using the following command that also includes the examples and tests.
.. sourcecode:: console
@@ -829,10 +829,10 @@ The build profile controls the use of logging, assertions, and compiler optimiza
| Flags | | | | ``-march=native`` |
| | | | | ``-mtune=native`` |
+----------+---------------------------------+-----------------------------+-------------------------------+---------------------------------+
As you can see, logging and assertions are only configured
by default in debug builds, although they can be selectively enabled
in other build profiles by using the ``--enable-logs`` and
in other build profiles by using the ``--enable-logs`` and
``--enable-asserts`` flags during CMake configuration time.
Recommended practice is to develop your scenario in debug mode, then
conduct repetitive runs (for statistics or changing parameters) in
@@ -932,7 +932,7 @@ into ``/usr/local/bin``, libraries into ``/usr/local/lib``, and headers
into ``/usr/local/include``. Superuser privileges are typically needed
to install to the default prefix, so the typical command would be
``sudo ./ns3 install``. When running programs with ns3, ns3 will
first prefer to use shared libraries in the build directory, then
first prefer to use shared libraries in the build directory, then
will look for libraries in the library path configured in the local
environment. So when installing libraries to the system, it is good
practice to check that the intended libraries are being used.
@@ -950,7 +950,7 @@ the project if ns3 will be used to install things at a different prefix.
In summary, it is not necessary to call ``./ns3 install`` to use |ns3|.
Most users will not need this command since ns3 will pick up the
current libraries from the ``build`` directory, but some users may find
current libraries from the ``build`` directory, but some users may find
it useful if their use case involves working with programs outside
of the |ns3| directory.
@@ -968,8 +968,8 @@ remember where you are, and invoke ns3 like this:
but that gets tedious, and error prone, and there are better solutions.
One common way when using a text-based editor such as emacs or vim is to
open two terminal sessions and use one to build |ns3| and one to
One common way when using a text-based editor such as emacs or vim is to
open two terminal sessions and use one to build |ns3| and one to
edit source code.
If you only have the tarball, an environment variable can help:
@@ -1255,7 +1255,7 @@ source files to/from the CMakeLists.txt files, adding a new module or dependenci
Testing ns-3
************
You can run the unit tests of the |ns3| distribution by running the
You can run the unit tests of the |ns3| distribution by running the
``./test.py`` script:
.. sourcecode:: console
@@ -1314,7 +1314,7 @@ executing each test, which will actually look something like:
739 of 742 tests passed (739 passed, 3 skipped, 0 failed, 0 crashed, 0 valgrind errors)
This command is typically run by users to quickly verify that an
This command is typically run by users to quickly verify that an
|ns3| distribution has built correctly. (Note the order of the ``PASS: ...``
lines can vary, which is okay. What's important is that the summary line at
the end report that all tests passed; none failed or crashed.)
@@ -1348,13 +1348,13 @@ Congratulations! You are now an ns-3 user!
**What do I do if I don't see the output?**
If you see ns3 messages indicating that the build was
completed successfully, but do not see the "Hello Simulator" output,
chances are that you have switched your build mode to ``optimized`` in
completed successfully, but do not see the "Hello Simulator" output,
chances are that you have switched your build mode to ``optimized`` in
the `Building with the ns3 CMake wrapper`_ section, but have missed the change back to
``debug`` mode. All of the console output used in this tutorial uses a
special |ns3| logging component that is useful for printing
user messages to the console. Output from this component is
automatically disabled when you compile optimized code -- it is
``debug`` mode. All of the console output used in this tutorial uses a
special |ns3| logging component that is useful for printing
user messages to the console. Output from this component is
automatically disabled when you compile optimized code -- it is
"optimized out." If you don't see the "Hello Simulator" output,
type the following:
@@ -1363,14 +1363,14 @@ type the following:
$ ./ns3 configure --build-profile=debug --enable-examples --enable-tests
to tell ns3 to build the debug versions of the |ns3|
programs that includes the examples and tests. You must still build
programs that includes the examples and tests. You must still build
the actual debug version of the code by typing
.. sourcecode:: console
$ ./ns3
Now, if you run the ``hello-simulator`` program, you should see the
Now, if you run the ``hello-simulator`` program, you should see the
expected output.
Program Arguments
@@ -1387,7 +1387,7 @@ for ``<args>``. The ``--command-template`` argument to ns3 is
basically a recipe for constructing the actual command line ns3 should use
to execute the program. ns3 checks that the build is complete,
sets the shared library paths, then invokes the executable
using the provided command line template,
using the provided command line template,
inserting the program name for the ``%s`` placeholder.
If you find the above to be syntactically complicated, a simpler variant
@@ -1466,7 +1466,7 @@ Running without Building
As of the ns-3.30 release, a new ns3 option was introduced to allow the
running of programs while skipping the build step. This can reduce the time
to run programs when, for example, running the same program repeatedly
through a shell script, or when demonstrating program execution.
through a shell script, or when demonstrating program execution.
The option ``--no-build`` modifies the ``run`` option,
skipping the build steps of the program and required ns-3 libraries.
@@ -1478,8 +1478,8 @@ Build version
+++++++++++++
As of the ns-3.32 release, a new ns3 configure option ``--enable-build-version``
was introduced which inspects the local ns3 git repository during builds and adds
version metadata to the core module.
was introduced which inspects the local ns3 git repository during builds and adds
version metadata to the core module.
This configuration option has the following prerequisites:
@@ -1493,9 +1493,9 @@ or
If these prerequisites are not met, the configuration will fail.
When these prerequisites are met and ns-3 is configured with the
When these prerequisites are met and ns-3 is configured with the
``--enable-build-version`` option, the ns3 command ``--check-version`` can be
used to query the local git repository and display the current version metadata.
used to query the local git repository and display the current version metadata.
.. sourcecode:: console
@@ -1513,10 +1513,10 @@ an error message indicating that the option is disabled will be displayed instea
.. sourcecode:: text
Build version support is not enabled, reconfigure with --enable-build-version flag
Build version support is not enabled, reconfigure with --enable-build-version flag
The build information is generated by examining the current state of the git
repository. The output of ``--check-version`` will change whenever the state
The build information is generated by examining the current state of the git
repository. The output of ``--check-version`` will change whenever the state
of the active branch changes.
The output of ``--check-version`` has the following format:
@@ -1525,39 +1525,39 @@ The output of ``--check-version`` has the following format:
<version_tag>[+closest_tag][+distance_from_tag]@<commit_hash>[-tree_state]-<profile>
version_tag
version_tag
version_tag contains the version of the ns-3 code. The version tag is
defined as a git tag with the format ns-3*. If multiple git tags match the
format, the tag on the active branch which is closest to the current commit
is chosen.
is chosen.
closest_tag
closest_tag is similar to version_tag except it is the first tag found,
regardless of format. The closest tag is not included in the output when
closest_tag and version_tag have the same value.
closest_tag and version_tag have the same value.
distance_from_tag
distance_from_tag contains the number of commits between the current commit
and closest_tag. distance_from_tag is not included in the output when the
distance_from_tag contains the number of commits between the current commit
and closest_tag. distance_from_tag is not included in the output when the
value is 0 (i.e. when closest_tag points to the current commit)
commit_hash
commit_hash is the hash of the commit at the tip of the active branch. The
value is 'g' followed by the first 7 characters of the commit hash. The 'g'
prefix is used to indicate that this is a git hash.
prefix is used to indicate that this is a git hash.
tree_state
tree_state indicates the state of the working tree. When the working tree
has uncommitted changes this field has the value 'dirty'. The tree state is
not included in the version output when the working tree is clean (e.g. when
there are no uncommitted changes).
has uncommitted changes this field has the value 'dirty'. The tree state is
not included in the version output when the working tree is clean (e.g. when
there are no uncommitted changes).
profile
The build profile specified in the ``--build-profile`` option passed to
The build profile specified in the ``--build-profile`` option passed to
``ns3 configure``
A new class, named Version, has been added to the core module. The Version class
contains functions to retrieve individual fields of the build version as well
A new class, named Version, has been added to the core module. The Version class
contains functions to retrieve individual fields of the build version as well
as functions to print the full build version like ``--check-version``.
The ``build-version-example`` application provides an example of how to use
the Version class to retrieve the various build version fields. See the
@@ -1572,7 +1572,7 @@ the core module when the ``--enable-build-version`` option is configured.
build-version-example:
Program Version (according to CommandLine): ns-3.33+249@g80e0dd0-dirty-debug
Version fields:
LongVersion: ns-3.33+249@g80e0dd0-dirty-debug
ShortVersion: ns-3.33+*
@@ -1581,14 +1581,14 @@ the core module when the ``--enable-build-version`` option is configured.
Major: 3
Minor: 33
Patch: 0
ReleaseCandidate:
ReleaseCandidate:
ClosestAncestorTag: ns-3.33
TagDistance: 249
CommitHash: g80e0dd0
BuildProfile: debug
WorkingTree: dirty
The CommandLine class has also been updated to support the ``--version``
The CommandLine class has also been updated to support the ``--version``
option which will print the full build version and exit.
.. sourcecode:: text

View File

@@ -5,20 +5,20 @@
Introduction
------------
The |ns3| simulator is a discrete-event network simulator targeted
primarily for research and educational use. The
The |ns3| simulator is a discrete-event network simulator targeted
primarily for research and educational use. The
`ns-3 project
<http://www.nsnam.org>`_,
<http://www.nsnam.org>`_,
started in 2006, is an open-source project developing |ns3|.
The purpose of this tutorial is to introduce new |ns3| users to the
The purpose of this tutorial is to introduce new |ns3| users to the
system in a structured way. It is sometimes difficult for new users to
glean essential information from detailed manuals and to convert this
information into working simulations. In this tutorial, we will build
information into working simulations. In this tutorial, we will build
several example simulations, introducing and explaining key concepts and
features as we go.
As the tutorial unfolds, we will introduce the full |ns3| documentation
As the tutorial unfolds, we will introduce the full |ns3| documentation
and provide pointers to source code for those interested in delving deeper
into the workings of the system.
@@ -27,11 +27,11 @@ diving right in without too much documentation.
A few key points are worth noting at the onset:
* |ns3| is open-source, and the project strives to maintain an
open environment for researchers to contribute and share their software.
* |ns3| is open-source, and the project strives to maintain an
open environment for researchers to contribute and share their software.
* |ns3| is not a backwards-compatible extension of `ns-2
<http://www.isi.edu/nsnam/ns>`_;
it is a new simulator. The two simulators are both written in C++ but
<http://www.isi.edu/nsnam/ns>`_;
it is a new simulator. The two simulators are both written in C++ but
|ns3| is a new simulator that does not support the |ns2| APIs.
@@ -45,7 +45,7 @@ simulation engine for users to conduct simulation experiments. Some of the
reasons to use |ns3| include to perform studies that are more difficult
or not possible to perform with real systems, to study system behavior in
a highly controlled, reproducible environment, and to learn about how
networks work. Users will note that the available model set in |ns3|
networks work. Users will note that the available model set in |ns3|
focuses on modeling how Internet protocols and networks work, but
|ns3| is not limited to Internet systems; several users are using
|ns3| to model non-Internet-based systems.
@@ -55,28 +55,28 @@ a few distinguishing features of |ns3| in contrast to other tools.
* |ns3| is designed as a set of libraries that can be combined together
and also with other external software libraries. While some simulation
platforms provide users with a single, integrated graphical user
interface environment in which all tasks are carried out, |ns3| is
platforms provide users with a single, integrated graphical user
interface environment in which all tasks are carried out, |ns3| is
more modular in this regard. Several external animators and
data analysis and visualization tools can be used with |ns3|. However,
users should expect to work at the command line and with C++ and/or
Python software development tools.
Python software development tools.
* |ns3| is primarily used on Linux or macOS systems, although support exists
for BSD systems and also for Windows frameworks that can build Linux code,
such as Windows Subsystem for Linux, or Cygwin. Native Windows
Visual Studio is not presently supported although a developer is working
such as Windows Subsystem for Linux, or Cygwin. Native Windows
Visual Studio is not presently supported although a developer is working
on future support. Windows users may also use a Linux virtual machine.
* |ns3| is not an officially supported software product of any company.
Support for |ns3| is done on a best-effort basis on the
Support for |ns3| is done on a best-effort basis on the
ns-3-users forum (ns-3-users@googlegroups.com).
For ns-2 Users
**************
For those familiar with |ns2| (a popular tool that preceded |ns3|),
the most visible outward change when moving to
|ns3| is the choice of scripting language. Programs in |ns2| are
scripted in OTcl and results of simulations can be visualized using the
For those familiar with |ns2| (a popular tool that preceded |ns3|),
the most visible outward change when moving to
|ns3| is the choice of scripting language. Programs in |ns2| are
scripted in OTcl and results of simulations can be visualized using the
Network Animator nam. It is not possible to run a simulation
in |ns2| purely from C++ (i.e., as a main() program without any OTcl).
Moreover, some components of |ns2| are written in C++ and others in OTcl.
@@ -86,10 +86,10 @@ or in Python. New animators and visualizers are available and under
current development. Since |ns3|
generates pcap packet trace files, other utilities can be used to
analyze traces as well.
In this tutorial, we will first concentrate on scripting
directly in C++ and interpreting results via trace files.
In this tutorial, we will first concentrate on scripting
directly in C++ and interpreting results via trace files.
But there are similarities as well (both, for example, are based on C++
But there are similarities as well (both, for example, are based on C++
objects, and some code from |ns2| has already been ported to |ns3|).
We will try to highlight differences between |ns2| and |ns3|
as we proceed in this tutorial.
@@ -101,7 +101,7 @@ of |ns2|, or based on a specific simulation model that is only available
in |ns2|), a user will be more productive with |ns3| for the following
reasons:
* |ns3| is actively maintained with an active, responsive users mailing
* |ns3| is actively maintained with an active, responsive users mailing
list, while |ns2| is only lightly maintained and has not seen
significant development in its main code tree for over a decade.
* |ns3| provides features not available in |ns2|, such as a implementation
@@ -115,16 +115,16 @@ reasons:
If in doubt, a good guideline would be to look at both simulators (as
well as other simulators), and in particular the models available
for your research, but keep in mind that your experience may be better
in using the tool that is being actively developed and
in using the tool that is being actively developed and
maintained (|ns3|).
Contributing
************
|ns3| is a research and educational simulator, by and for the
research community. It will rely on the ongoing contributions of the
community to develop new models, debug or maintain existing ones, and share
results. There are a few policies that we hope will encourage people to
|ns3| is a research and educational simulator, by and for the
research community. It will rely on the ongoing contributions of the
community to develop new models, debug or maintain existing ones, and share
results. There are a few policies that we hope will encourage people to
contribute to |ns3| like they have for |ns2|:
* Open source licensing based on GNU GPLv2 compatibility
@@ -133,16 +133,16 @@ contribute to |ns3| like they have for |ns2|:
* `Contributed Code
<https://www.nsnam.org/wiki/Contributed_Code>`_ page, similar to |ns2|'s popular Contributed Code
`page
<http://nsnam.isi.edu/nsnam/index.php/Contributed_Code>`_
<http://nsnam.isi.edu/nsnam/index.php/Contributed_Code>`_
* Use of GitLab.com including issue tracker
<https://www.gitlab.com/nsnam>`_
We realize that if you are reading this document, contributing back to
We realize that if you are reading this document, contributing back to
the project is probably not your foremost concern at this point, but
we want you to be aware that contributing is in the spirit of the project and
that even the act of dropping us a note about your early experience
with |ns3| (e.g. "this tutorial section was not clear..."),
reports of stale documentation or comments in the code, etc. are much
that even the act of dropping us a note about your early experience
with |ns3| (e.g. "this tutorial section was not clear..."),
reports of stale documentation or comments in the code, etc. are much
appreciated. The preferred way to submit patches is either to fork
our project on GitLab.com and generate a Merge Request, or to open
an issue on our issue tracker and append a patch.

View File

@@ -17,10 +17,10 @@ Brief Summary
It is written directly in C++, not in a high-level modeling language;
simulation events are simply C++ function calls, organized by a scheduler.
An |ns3| user will obtain the |ns3| source code (see below),
compile it into shared (or static) libraries, and link the libraries to
An |ns3| user will obtain the |ns3| source code (see below),
compile it into shared (or static) libraries, and link the libraries to
`main()` programs that he or she authors. The `main()` program is where
the specific simulation scenario configuration is performed and where the
the specific simulation scenario configuration is performed and where the
simulator is run and stopped. Several example programs are provided, which
can be modified or copied to create new simulation scenarios. Users also
often edit the |ns3| library code (and rebuild the libraries) to change
@@ -38,9 +38,9 @@ a build-system (e.g. make, ninja, Xcode).
We focus in this chapter only on getting |ns3| up and running on a system
supported by a recent C++ compiler and Python runtime support.
For Linux, use either g++ or clang++ compilers. For macOS, use clang++
For Linux, use either g++ or clang++ compilers. For macOS, use clang++
(available in Xcode or Xcode Command Line Tools). For Windows, we recommend
to either use a Linux virtual machine, or the Windows Subsystem for Linux.
to either use a Linux virtual machine, or the Windows Subsystem for Linux.
Downloading ns-3
****************
@@ -127,7 +127,7 @@ Once complete, you can run the unit tests to check your build:
All tests should either PASS or be SKIPped. At this point, you have a
working |ns3| simulator. From here, you can start to
run programs (look in the examples directory). To run the first tutorial
program, whose source code is located at `examples/tutorial/first.cc`,
program, whose source code is located at `examples/tutorial/first.cc`,
use ns3 to run it (by doing so, the |ns3| shared libraries are found
automatically):

View File

@@ -7,18 +7,18 @@ The Web
*******
There are several important resources of which any |ns3| user must be
aware. The main web site is located at https://www.nsnam.org and
provides access to basic information about the |ns3| system. Detailed
aware. The main web site is located at https://www.nsnam.org and
provides access to basic information about the |ns3| system. Detailed
documentation is available through the main web site at
https://www.nsnam.org/documentation/. You can also find documents
https://www.nsnam.org/documentation/. You can also find documents
relating to the system architecture from this page.
There is a Wiki that complements the main |ns3| web site which you will
find at https://www.nsnam.org/wiki/. You will find user and developer
FAQs there, as well as troubleshooting guides, third-party contributed code,
papers, etc.
find at https://www.nsnam.org/wiki/. You will find user and developer
FAQs there, as well as troubleshooting guides, third-party contributed code,
papers, etc.
The source code may be found and browsed at GitLab.com:
The source code may be found and browsed at GitLab.com:
https://gitlab.com/nsnam/.
There you will find the current development tree in the repository named
``ns-3-dev``. Past releases and experimental repositories of the core
@@ -28,22 +28,22 @@ http://code.nsnam.org.
Git
***
Complex software systems need some way to manage the organization and
Complex software systems need some way to manage the organization and
changes to the underlying code and documentation. There are many ways to
perform this feat, and you may have heard of some of the systems that are
currently used to do this. Until recently, the |ns3| project used Mercurial
as its source code management system, but in December 2018, switch to
using Git. Although you do not need to know much about Git in order to
complete this tutorial, we recommend becoming familiar with Git and using it
complete this tutorial, we recommend becoming familiar with Git and using it
to access the source code. GitLab.com provides resources to get started
at: https://docs.gitlab.com/ee/gitlab-basics/.
CMake
*****
Once you have source code downloaded to your local system, you will need
Once you have source code downloaded to your local system, you will need
to compile that source to produce usable programs. Just as in the case of
source code management, there are many tools available to perform this
source code management, there are many tools available to perform this
function. Probably the most well known of these tools is ``make``. Along
with being the most well known, ``make`` is probably the most difficult to
use in a very large and highly configurable system. Because of this, many
@@ -59,11 +59,11 @@ Development Environment
***********************
As mentioned above, scripting in |ns3| is done in C++ or Python.
Most of the |ns3| API is available in Python, but the
models are written in C++ in either case. A working
Most of the |ns3| API is available in Python, but the
models are written in C++ in either case. A working
knowledge of C++ and object-oriented concepts is assumed in this document.
We will take some time to review some of the more advanced concepts or
possibly unfamiliar language features, idioms and design patterns as they
We will take some time to review some of the more advanced concepts or
possibly unfamiliar language features, idioms and design patterns as they
appear. We don't want this tutorial to devolve into a C++ tutorial, though,
so we do expect a basic command of the language. There are a wide
number of sources of information on C++ available on the web or
@@ -74,12 +74,12 @@ book or web site and work through at least the basic features of the language
before proceeding. For instance, `this tutorial
<http://www.cplusplus.com/doc/tutorial/>`_.
On Linux, the |ns3| system uses several components of the GNU "toolchain"
for development. A
software toolchain is the set of programming tools available in the given
On Linux, the |ns3| system uses several components of the GNU "toolchain"
for development. A
software toolchain is the set of programming tools available in the given
environment. For a quick review of what is included in the GNU toolchain see,
http://en.wikipedia.org/wiki/GNU_toolchain. |ns3| uses gcc,
GNU binutils, and gdb. However, we do not use the GNU build system tools,
http://en.wikipedia.org/wiki/GNU_toolchain. |ns3| uses gcc,
GNU binutils, and gdb. However, we do not use the GNU build system tools,
neither make directly. We use CMake for these functions.
On macOS, the toolchain used is Xcode. |ns3| users on a Mac are strongly
@@ -87,11 +87,11 @@ encouraged to install Xcode and the command-line tools packages from the
Apple App Store, and to look at the |ns3| installation wiki for more
information (https://www.nsnam.org/wiki/Installation).
Typically an |ns3| author will work in Linux or a Unix-like environment.
For those running under Windows, there do exist environments
which simulate the Linux environment to various degrees. The |ns3|
project has in the past (but not presently) supported development in the Cygwin environment for
these users. See http://www.cygwin.com/
Typically an |ns3| author will work in Linux or a Unix-like environment.
For those running under Windows, there do exist environments
which simulate the Linux environment to various degrees. The |ns3|
project has in the past (but not presently) supported development in the Cygwin environment for
these users. See http://www.cygwin.com/
for details on downloading, and visit the |ns3| wiki for more information
about Cygwin and |ns3|. MinGW is presently not officially supported.
Another alternative to Cygwin is to install a virtual machine environment
@@ -111,10 +111,10 @@ book, which you can find at:
http://cs.baylor.edu/~donahoo/practical/CSockets/.
If you understand the first four chapters of the book (or for those who do
not have access to a copy of the book, the echo clients and servers shown in
not have access to a copy of the book, the echo clients and servers shown in
the website above) you will be in good shape to understand the tutorial.
There is a similar book on Multicast Sockets,
`Multicast Sockets, Makofske and Almeroth
<https://www.elsevier.com/books/multicast-sockets/makofske/978-1-55860-846-7>`_.
that covers material you may need to understand if you look at the multicast
that covers material you may need to understand if you look at the multicast
examples in the distribution.

View File

@@ -4,7 +4,7 @@
:format: html latex
.. Mimic doxygen formatting for parameter names
.. raw:: html
<style>.param {font-weight:bold; color:#602020;}</style>
@@ -77,7 +77,7 @@ standard output, as in::
...
std::cout << "The value of x is " << x << std::endl;
...
}
}
Nobody is going to prevent you from going deep into the core of |ns3|
and adding print statements. This is insanely easy to do and, after
@@ -107,7 +107,7 @@ other people as a patch to the existing core.
Let's pick a random example. If you wanted to add more logging to the
|ns3| TCP socket (``tcp-socket-base.cc``) you could just add a new
message down in the implementation. Notice that in
``TcpSocketBase::ProcessEstablished ()`` there is no log message for the
``TcpSocketBase::ProcessEstablished ()`` there is no log message for the
reception of a SYN+ACK in ESTABLISHED state.
You could simply add one, changing the code. Here is the original::
@@ -158,7 +158,7 @@ files to disk and process them down to a few lines whenever you want
to do anything.
Since there are no guarantees in |ns3| about the stability of
``NS_LOG`` output, you may also discover that pieces of log output
``NS_LOG`` output, you may also discover that pieces of log output
which you depend on disappear or change between releases. If you depend
on the structure of the output, you may find other messages being
added or deleted which may affect your parsing code.
@@ -328,14 +328,14 @@ the tutorial directory as ``fourth.cc``. Let's walk through it::
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "ns3/object.h"
#include "ns3/uinteger.h"
#include "ns3/traced-value.h"
#include "ns3/trace-source-accessor.h"
#include <iostream>
using namespace ns3;
Most of this code should be quite familiar to you. As mentioned
@@ -376,7 +376,7 @@ simple Object we can work with.
;
return tid;
}
MyObject () {}
TracedValue<int32_t> m_myInt;
};
@@ -431,7 +431,7 @@ code to connect the source to the sink, which happens in ``main``::
{
Ptr<MyObject> myObject = CreateObject<MyObject> ();
myObject->TraceConnectWithoutContext ("MyInteger", MakeCallback(&IntTrace));
myObject->m_myInt = 1234;
}
@@ -522,7 +522,7 @@ more clear to you what this function is doing::
CourseChange (std::string context, Ptr<const MobilityModel> model)
{
Vector position = model->GetPosition ();
NS_LOG_UNCOND (context <<
NS_LOG_UNCOND (context <<
" x = " << position.x << ", y = " << position.y);
}
@@ -628,7 +628,7 @@ for "CourseChange" in your favorite editor. You should find
MakeTraceSourceAccessor (&MobilityModel::m_courseChangeTrace),
"ns3::MobilityModel::CourseChangeCallback")
which should look very familiar at this point.
which should look very familiar at this point.
If you look for the corresponding declaration of the underlying traced
variable in ``mobility-model.h`` you will find
@@ -740,7 +740,7 @@ an entry for
::
CourseChange: The value of the position and/or velocity vector changed
CourseChange: The value of the position and/or velocity vector changed
You should recognize this as the trace source we used in the
``third.cc`` example. Perusing this list will be helpful.
@@ -772,7 +772,7 @@ in the "All TraceSources" list and you want to figure out how to
connect to it. You know that you are using (again, from the
``third.cc`` example) an ``ns3::RandomWalk2dMobilityModel``. So
either click on the class name in the "All TraceSources" list, or find
``ns3::RandomWalk2dMobilityModel`` in the "Class List". Either way
``ns3::RandomWalk2dMobilityModel`` in the "Class List". Either way
you should now be looking at the "ns3::RandomWalk2dMobilityModel Class
Reference" page.
@@ -808,7 +808,7 @@ Look further down in the "Detailed Description" section for the list
of trace sources. You will find
No TraceSources are defined for this type.
**TraceSources defined in parent class ``ns3::MobilityModel``**
* **CourseChange**: The value of the position and/or velocity vector
@@ -843,11 +843,11 @@ and you may find your answer along with working code. For example, in
this case, ``src/mobility/examples/main-random-topology.cc`` has
something just waiting for you to use::
Config::Connect ("/NodeList/*/$ns3::MobilityModel/CourseChange",
Config::Connect ("/NodeList/*/$ns3::MobilityModel/CourseChange",
MakeCallback (&CourseChange));
We'll return to this example in a moment.
We'll return to this example in a moment.
Callback Signatures
+++++++++++++++++++
@@ -871,7 +871,7 @@ The callback signature is given as a link to the relevant ``typedef``,
where we find
``typedef void (* CourseChangeCallback)(std::string context, Ptr<const MobilityModel> * model);``
**TracedCallback** signature for course change notifications.
If the callback is connected using ``ConnectWithoutContext`` omit the
@@ -1040,11 +1040,11 @@ Just after this comment, you will find
::
template<typename T1 = empty, typename T2 = empty,
template<typename T1 = empty, typename T2 = empty,
typename T3 = empty, typename T4 = empty,
typename T5 = empty, typename T6 = empty,
typename T7 = empty, typename T8 = empty>
class TracedCallback
class TracedCallback
{
...
@@ -1063,11 +1063,11 @@ tracing system is in the ``Connect`` and ``ConnectWithoutContext``
functions. If you scroll down, you will see a
``ConnectWithoutContext`` method here::
template<typename T1, typename T2,
template<typename T1, typename T2,
typename T3, typename T4,
typename T5, typename T6,
typename T7, typename T8>
void
void
TracedCallback<T1,T2,T3,T4,T5,T6,T7,T8>::ConnectWithoutContext ...
{
Callback<void,T1,T2,T3,T4,T5,T6,T7,T8> cb;
@@ -1081,7 +1081,7 @@ instantiated for the declaration above, the compiler will replace
::
void
void
TracedCallback<Ptr<const MobilityModel>::ConnectWithoutContext ... cb
{
Callback<void, Ptr<const MobilityModel> > cb;
@@ -1304,8 +1304,8 @@ usual, ``grep`` is your friend:
$ find . -name '*.cc' | xargs grep CongestionWindow
This will point out a couple of promising candidates:
``examples/tcp/tcp-large-transfer.cc`` and
This will point out a couple of promising candidates:
``examples/tcp/tcp-large-transfer.cc`` and
``src/test/ns3tcp/ns3tcp-cwnd-test-suite.cc``.
We haven't visited any of the test code yet, so let's take a look
@@ -1316,7 +1316,7 @@ and search for "CongestionWindow". You will find,
::
ns3TcpSocket->TraceConnectWithoutContext ("CongestionWindow",
ns3TcpSocket->TraceConnectWithoutContext ("CongestionWindow",
MakeCallback (&Ns3TcpCwndTestCase1::CwndChange, this));
This should look very familiar to you. We mentioned above that if we
@@ -1405,16 +1405,16 @@ see some familiar looking code::
* along with this program; if not, write to the Free Software
* Foundation, Include., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <fstream>
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/internet-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/applications-module.h"
using namespace ns3;
NS_LOG_COMPONENT_DEFINE ("FifthScriptExample");
This has all been covered, so we won't rehash it. The next lines of
@@ -1469,20 +1469,20 @@ time.
class MyApp : public Application
{
public:
MyApp ();
virtual ~MyApp();
void Setup (Ptr<Socket> socket, Address address, uint32_t packetSize,
void Setup (Ptr<Socket> socket, Address address, uint32_t packetSize,
uint32_t nPackets, DataRate dataRate);
private:
virtual void StartApplication (void);
virtual void StopApplication (void);
void ScheduleTx (void);
void SendPacket (void);
Ptr<Socket> m_socket;
Address m_peer;
uint32_t m_packetSize;
@@ -1669,7 +1669,7 @@ course::
m_packetsSent (0)
{
}
MyApp::~MyApp()
{
m_socket = 0;
@@ -1681,7 +1681,7 @@ this ``Application`` in the first place.
::
void
MyApp::Setup (Ptr<Socket> socket, Address address, uint32_t packetSize,
MyApp::Setup (Ptr<Socket> socket, Address address, uint32_t packetSize,
uint32_t nPackets, DataRate dataRate)
{
m_socket = socket;
@@ -1690,7 +1690,7 @@ this ``Application`` in the first place.
m_nPackets = nPackets;
m_dataRate = dataRate;
}
This code should be pretty self-explanatory. We are just initializing
member variables. The important one from the perspective of tracing
is the ``Ptr<Socket> socket`` which we needed to provide to the
@@ -1734,12 +1734,12 @@ creating simulation events.
MyApp::StopApplication (void)
{
m_running = false;
if (m_sendEvent.IsRunning ())
{
Simulator::Cancel (m_sendEvent);
}
if (m_socket)
{
m_socket->Close ();
@@ -1769,7 +1769,7 @@ chain of events that describes the ``Application`` behavior.
{
Ptr<Packet> packet = Create<Packet> (m_packetSize);
m_socket->Send (packet);
if (++m_packetsSent < m_nPackets)
{
ScheduleTx ();
@@ -1865,11 +1865,11 @@ The following code should be very familiar to you by now::
{
NodeContainer nodes;
nodes.Create (2);
PointToPointHelper pointToPoint;
pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
NetDeviceContainer devices;
devices = pointToPoint.Install (nodes);
@@ -1886,7 +1886,7 @@ congestion window.
|ns3| provides ``ErrorModel`` objects which can be attached to
``Channels``. We are using the ``RateErrorModel`` which allows us to
introduce errors
into a ``Channel`` at a given *rate*.
into a ``Channel`` at a given *rate*.
::
@@ -1921,7 +1921,7 @@ is commonly used in |ns3| for that purpose.
uint16_t sinkPort = 8080;
Address sinkAddress (InetSocketAddress(interfaces.GetAddress (1), sinkPort));
PacketSinkHelper packetSinkHelper ("ns3::TcpSocketFactory",
PacketSinkHelper packetSinkHelper ("ns3::TcpSocketFactory",
InetSocketAddress (Ipv4Address::GetAny (), sinkPort));
ApplicationContainer sinkApps = packetSinkHelper.Install (nodes.Get (1));
sinkApps.Start (Seconds (0.));
@@ -1931,7 +1931,7 @@ This should all be familiar, with the exception of,
::
PacketSinkHelper packetSinkHelper ("ns3::TcpSocketFactory",
PacketSinkHelper packetSinkHelper ("ns3::TcpSocketFactory",
InetSocketAddress (Ipv4Address::GetAny (), sinkPort));
This code instantiates a ``PacketSinkHelper`` and tells it to create
@@ -1952,9 +1952,9 @@ trace source.
::
Ptr<Socket> ns3TcpSocket = Socket::CreateSocket (nodes.Get (0),
Ptr<Socket> ns3TcpSocket = Socket::CreateSocket (nodes.Get (0),
TcpSocketFactory::GetTypeId ());
ns3TcpSocket->TraceConnectWithoutContext ("CongestionWindow",
ns3TcpSocket->TraceConnectWithoutContext ("CongestionWindow",
MakeCallback (&CwndChange));
The first statement calls the static member function
@@ -2127,7 +2127,7 @@ information to a stream representing a file.
NS_LOG_UNCOND (Simulator::Now ().GetSeconds () << "\t" << newCwnd);
*stream->GetStream () << Simulator::Now ().GetSeconds () << "\t" << oldCwnd << "\t" << newCwnd << std::endl;
}
static void
RxDrop (Ptr<PcapFileWrapper> file, Ptr<const Packet> p)
{
@@ -2350,7 +2350,7 @@ and we did this in only 18 lines of code::
}
...
PcapHelper pcapHelper;
Ptr<PcapFileWrapper> file = pcapHelper.CreateFile ("sixth.pcap", "w", PcapHelper::DLT_PPP);
devices.Get (1)->TraceConnectWithoutContext("PhyRxDrop", MakeBoundCallback (&RxDrop, file));
@@ -2364,7 +2364,7 @@ previous sections, primarily :ref:`BuildingTopologies`, we have seen
several varieties of the trace helper methods designed for use inside
other (device) helpers.
Perhaps you will recall seeing some of these variations:
Perhaps you will recall seeing some of these variations:
::
@@ -2619,8 +2619,8 @@ inherited from the ASCII trace ``mixin``.
::
virtual void EnableAsciiInternal (Ptr<OutputStreamWrapper> stream,
std::string prefix,
virtual void EnableAsciiInternal (Ptr<OutputStreamWrapper> stream,
std::string prefix,
Ptr<NetDevice> nd,
bool explicitFilename) = 0;
@@ -2778,7 +2778,7 @@ but to summarize ...
This would result in a number of ASCII trace files being created,
each of which follows the ``<prefix>-<node id>-<device id>.tr``
convention.
Combining all of the traces into a single file is accomplished
similarly to the examples above::
@@ -2889,8 +2889,8 @@ class ``Object``, and methods that share the same signature.
::
virtual void EnablePcapIpv4Internal (std::string prefix,
Ptr<Ipv4> ipv4,
virtual void EnablePcapIpv4Internal (std::string prefix,
Ptr<Ipv4> ipv4,
uint32_t interface,
bool explicitFilename) = 0;
@@ -2967,7 +2967,7 @@ summarize ...
NodeContainer nodes;
...
NetDeviceContainer devices = deviceHelper.Install (nodes);
...
...
Ipv4AddressHelper ipv4;
ipv4.SetBase ("10.1.1.0", "255.255.255.0");
Ipv4InterfaceContainer interfaces = ipv4.Assign (devices);
@@ -3061,9 +3061,9 @@ method inherited from this class.
::
virtual void EnableAsciiIpv4Internal (Ptr<OutputStreamWrapper> stream,
std::string prefix,
Ptr<Ipv4> ipv4,
virtual void EnableAsciiIpv4Internal (Ptr<OutputStreamWrapper> stream,
std::string prefix,
Ptr<Ipv4> ipv4,
uint32_t interface,
bool explicitFilename) = 0;
@@ -3204,7 +3204,7 @@ but to summarize ...
NodeContainer nodes;
...
NetDeviceContainer devices = deviceHelper.Install (nodes);
...
...
Ipv4AddressHelper ipv4;
ipv4.SetBase ("10.1.1.0", "255.255.255.0");
Ipv4InterfaceContainer interfaces = ipv4.Assign (devices);
@@ -3220,7 +3220,7 @@ but to summarize ...
NodeContainer nodes;
...
NetDeviceContainer devices = deviceHelper.Install (nodes);
...
...
Ipv4AddressHelper ipv4;
ipv4.SetBase ("10.1.1.0", "255.255.255.0");
Ipv4InterfaceContainer interfaces = ipv4.Assign (devices);

View File

@@ -11,34 +11,34 @@ Using the Logging Module
************************
We have already taken a brief look at the |ns3| logging module while
going over the ``first.cc`` script. We will now take a closer look and
going over the ``first.cc`` script. We will now take a closer look and
see what kind of use-cases the logging subsystem was designed to cover.
Logging Overview
++++++++++++++++
Many large systems support some kind of message logging facility, and
|ns3| is not an exception. In some cases, only error messages are
Many large systems support some kind of message logging facility, and
|ns3| is not an exception. In some cases, only error messages are
logged to the "operator console" (which is typically ``stderr`` in Unix-
based systems). In other systems, warning messages may be output as well as
more detailed informational messages. In some cases, logging facilities are
based systems). In other systems, warning messages may be output as well as
more detailed informational messages. In some cases, logging facilities are
used to output debug messages which can quickly turn the output into a blur.
|ns3| takes the view that all of these verbosity levels are useful
|ns3| takes the view that all of these verbosity levels are useful
and we provide a selectable, multi-level approach to message logging. Logging
can be disabled completely, enabled on a component-by-component basis, or
enabled globally; and it provides selectable verbosity levels. The
enabled globally; and it provides selectable verbosity levels. The
|ns3| log module provides a straightforward, relatively easy to use
way to get useful information out of your simulation.
You should understand that we do provide a general purpose mechanism ---
tracing --- to get data out of your models which should be preferred for
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
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.
defined in the system.
* LOG_ERROR --- Log error messages (associated macro: NS_LOG_ERROR);
* LOG_WARN --- Log warning messages (associated macro: NS_LOG_WARN);
@@ -59,7 +59,7 @@ consequence of this, LOG_ERROR and LOG_LEVEL_ERROR and also LOG_ALL
and LOG_LEVEL_ALL are functionally equivalent.) For example,
enabling LOG_INFO will only enable messages provided by NS_LOG_INFO macro,
while enabling LOG_LEVEL_INFO will also enable messages provided by
NS_LOG_DEBUG, NS_LOG_WARN and NS_LOG_ERROR macros.
NS_LOG_DEBUG, NS_LOG_WARN and NS_LOG_ERROR macros.
We also provide an unconditional logging macro that is always displayed,
irrespective of logging levels or component selection.
@@ -67,20 +67,20 @@ irrespective of logging levels or component selection.
* NS_LOG_UNCOND -- Log the associated message unconditionally (no associated
log level).
Each level can be requested singly or cumulatively; and logging can be set
up using a shell environment variable (NS_LOG) or by logging system function
call. As was seen earlier in the tutorial, the logging system has Doxygen
documentation and now would be a good time to peruse the Logging Module
Each level can be requested singly or cumulatively; and logging can be set
up using a shell environment variable (NS_LOG) or by logging system function
call. As was seen earlier in the tutorial, the logging system has Doxygen
documentation and now would be a good time to peruse the Logging Module
documentation if you have not done so.
Now that you have read the documentation in great detail, let's use some of
that knowledge to get some interesting information out of the
that knowledge to get some interesting information out of the
``scratch/myfirst.cc`` example script you have already built.
Enabling Logging
++++++++++++++++
Let's use the NS_LOG environment variable to turn on some more logging, but
first, just to get our bearings, go ahead and run the last script just as you
first, just to get our bearings, go ahead and run the last script just as you
did previously,
.. sourcecode:: bash
@@ -100,14 +100,14 @@ program
Received 1024 bytes from 10.1.1.2
It turns out that the "Sent" and "Received" messages you see above are
actually logging messages from the ``UdpEchoClientApplication`` and
``UdpEchoServerApplication``. We can ask the client application, for
example, to print more information by setting its logging level via the
NS_LOG environment variable.
actually logging messages from the ``UdpEchoClientApplication`` and
``UdpEchoServerApplication``. We can ask the client application, for
example, to print more information by setting its logging level via the
NS_LOG environment variable.
I am going to assume from here on that you are using an sh-like shell that uses
the"VARIABLE=value" syntax. If you are using a csh-like shell, then you
will have to convert my examples to the "setenv VARIABLE value" syntax
I am going to assume from here on that you are using an sh-like shell that uses
the"VARIABLE=value" syntax. If you are using a csh-like shell, then you
will have to convert my examples to the "setenv VARIABLE value" syntax
required by those shells.
Right now, the UDP echo client application is responding to the following line
@@ -117,7 +117,7 @@ of code in ``scratch/myfirst.cc``,
LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_INFO);
This line of code enables the ``LOG_LEVEL_INFO`` level of logging. When
This line of code enables the ``LOG_LEVEL_INFO`` level of logging. When
we pass a logging level flag, we are actually enabling the given level and
all lower levels. In this case, we have enabled ``NS_LOG_INFO``,
``NS_LOG_DEBUG``, ``NS_LOG_WARN`` and ``NS_LOG_ERROR``. We can
@@ -137,7 +137,7 @@ This sets the shell environment variable ``NS_LOG`` to the string,
The left hand side of the assignment is the name of the logging component we
want to set, and the right hand side is the flag we want to use. In this case,
we are going to turn on all of the debugging levels for the application. If
you run the script with NS_LOG set this way, the |ns3| logging
you run the script with NS_LOG set this way, the |ns3| logging
system will pick up the change and you should see the following output:
.. sourcecode:: bash
@@ -169,15 +169,15 @@ is left to the individual model developer. In the case of the echo
applications, a good deal of log output is available.
You can now see a log of the function calls that were made to the application.
If you look closely you will notice a single colon between the string
``UdpEchoClientApplication`` and the method name where you might have
expected a C++ scope operator (``::``). This is intentional.
If you look closely you will notice a single colon between the string
``UdpEchoClientApplication`` and the method name where you might have
expected a C++ scope operator (``::``). This is intentional.
The name is not actually a class name, it is a logging component name. When
there is a one-to-one correspondence between a source file and a class, this
will generally be the class name but you should understand that it is not
The name is not actually a class name, it is a logging component name. When
there is a one-to-one correspondence between a source file and a class, this
will generally be the class name but you should understand that it is not
actually a class name, and there is a single colon there instead of a double
colon to remind you in a relatively subtle way to conceptually separate the
colon to remind you in a relatively subtle way to conceptually separate the
logging component name from the class name.
It turns out that in some cases, it can be hard to determine which method
@@ -193,7 +193,7 @@ from. You can resolve this by OR'ing the ``prefix_func`` level into the
Note that the quotes are required since the vertical bar we use to indicate an
OR operation is also a Unix pipe connector.
Now, if you run the script you will see that the logging system makes sure
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.
@@ -217,8 +217,8 @@ name.
You can now see all of the messages coming from the UDP echo client application
are identified as such. The message "Received 1024 bytes from 10.1.1.2" is
now clearly identified as coming from the echo client application. The
remaining message must be coming from the UDP echo server application. We
now clearly identified as coming from the echo client application. The
remaining message must be coming from the UDP echo server application. We
can enable that component by entering a colon separated list of components in
the NS_LOG environment variable.
@@ -293,20 +293,20 @@ you should see the following output:
UdpEchoClientApplication:~UdpEchoClient()
UdpEchoServerApplication:~UdpEchoServer()
You can see that the constructor for the UdpEchoServer was called at a
simulation time of 0 seconds. This is actually happening before the
You can see that the constructor for the UdpEchoServer was called at a
simulation time of 0 seconds. This is actually happening before the
simulation starts, but the time is displayed as zero seconds. The same is true
for the UdpEchoClient constructor message.
Recall that the ``scratch/first.cc`` script started the echo server
application at one second into the simulation. You can now see that the
Recall that the ``scratch/first.cc`` script started the echo server
application at one second into the simulation. You can now see that the
``StartApplication`` method of the server is, in fact, called at one second.
You can also see that the echo client application is started at a simulation
You can also see that the echo client application is started at a simulation
time of two seconds as we requested in the script.
You can now follow the progress of the simulation from the
``ScheduleTransmit`` call in the client that calls ``Send`` to the
``HandleRead`` callback in the echo server application. Note that the
You can now follow the progress of the simulation from the
``ScheduleTransmit`` call in the client that calls ``Send`` to the
``HandleRead`` callback in the echo server application. Note that the
elapsed time for the packet to be sent across the point-to-point link is 3.69
milliseconds. You see the echo server logging a message telling you that it
has echoed the packet and then, after another channel delay, you see the echo
@@ -314,37 +314,37 @@ client receive the echoed packet in its ``HandleRead`` method.
There is a lot that is happening under the covers in this simulation that you
are not seeing as well. You can very easily follow the entire process by
turning on all of the logging components in the system. Try setting the
turning on all of the logging components in the system. Try setting the
``NS_LOG`` variable to the following,
.. sourcecode:: bash
$ export 'NS_LOG=*=level_all|prefix_func|prefix_time'
The asterisk above is the logging component wildcard. This will turn on all
of the logging in all of the components used in the simulation. I won't
The asterisk above is the logging component wildcard. This will turn on all
of the logging in all of the components used in the simulation. I won't
reproduce the output here (as of this writing it produces 1265 lines of output
for the single packet echo) but you can redirect this information into a file
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,
.. sourcecode:: bash
$ ./ns3 run scratch/myfirst > log.out 2>&1
I personally use this extremely verbose version of logging when I am presented
with a problem and I have no idea where things are going wrong. I can follow the
progress of the code quite easily without having to set breakpoints and step
I personally use this extremely verbose version of logging when I am presented
with a problem and I have no idea where things are going wrong. I can follow the
progress of the code quite easily without having to set breakpoints and step
through code in a debugger. I can just edit up the output in my favorite editor
and search around for things I expect, and see things happening that I don't
and search around for things I expect, and see things happening that I don't
expect. When I have a general idea about what is going wrong, I transition into
a debugger for a fine-grained examination of the problem. This kind of output
a debugger for a fine-grained examination of the problem. This kind of output
can be especially useful when your script does something completely unexpected.
If you are stepping using a debugger you may miss an unexpected excursion
If you are stepping using a debugger you may miss an unexpected excursion
completely. Logging the excursion makes it quickly visible.
Adding Logging to your Code
+++++++++++++++++++++++++++
You can add new logging to your simulations by making calls to the log
You can add new logging to your simulations by making calls to the log
component via several macros. Let's do so in the ``myfirst.cc`` script we
have in the ``scratch`` directory.
@@ -356,9 +356,9 @@ Recall that we have defined a logging component in that script:
You now know that you can enable all of the logging for this component by
setting the ``NS_LOG`` environment variable to the various levels. Let's
go ahead and add some logging to the script. The macro used to add an
informational level log message is ``NS_LOG_INFO``. Go ahead and add one
(just before we start creating the nodes) that tells you that the script is
go ahead and add some logging to the script. The macro used to add an
informational level log message is ``NS_LOG_INFO``. Go ahead and add one
(just before we start creating the nodes) that tells you that the script is
"Creating Topology." This is done as in this code snippet,
Open ``scratch/myfirst.cc`` in your favorite editor and add the line,
@@ -382,16 +382,16 @@ off the torrent of logging we previously enabled:
$ ./ns3
$ export NS_LOG=
Now, if you run the script,
Now, if you run the script,
.. sourcecode:: bash
$ ./ns3 run scratch/myfirst
you will ``not`` see your new message since its associated logging
you will ``not`` see your new message since its associated logging
component (``FirstScriptExample``) has not been enabled. In order to see your
message you will have to enable the ``FirstScriptExample`` logging component
with a level greater than or equal to ``NS_LOG_INFO``. If you just want to
with a level greater than or equal to ``NS_LOG_INFO``. If you just want to
see this particular level of logging, you can enable it by,
.. sourcecode:: bash
@@ -419,7 +419,7 @@ Using Command Line Arguments
Overriding Default Attributes
+++++++++++++++++++++++++++++
Another way you can change how |ns3| scripts behave without editing
and building is via *command line arguments.* We provide a mechanism to
and building is via *command line arguments.* We provide a mechanism to
parse command line arguments and automatically set local and global variables
based on those arguments.
@@ -432,7 +432,7 @@ in the following code,
int
main (int argc, char *argv[])
{
...
...
CommandLine cmd;
cmd.Parse (argc, argv);
@@ -441,9 +441,9 @@ in the following code,
}
This simple two line snippet is actually very useful by itself. It opens the
door to the |ns3| global variable and ``Attribute`` systems. Go
door to the |ns3| global variable and ``Attribute`` systems. Go
ahead and add that two lines of code to the ``scratch/myfirst.cc`` script at
the start of ``main``. Go ahead and build the script and run it, but ask
the start of ``main``. Go ahead and build the script and run it, but ask
the script for help in the following way,
.. sourcecode:: bash
@@ -451,7 +451,7 @@ the script for help in the following way,
$ ./ns3 run "scratch/myfirst --PrintHelp"
This will ask ns3 to run the ``scratch/myfirst`` script and pass the command
line argument ``--PrintHelp`` to the script. The quotes are required to
line argument ``--PrintHelp`` to the script. The quotes are required to
sort out which program gets which argument. The command line parser will
now see the ``--PrintHelp`` argument and respond with,
@@ -470,7 +470,7 @@ now see the ``--PrintHelp`` argument and respond with,
--PrintGlobals: Print the list of globals.
Let's focus on the ``--PrintAttributes`` option. We have already hinted
at the |ns3| ``Attribute`` system while walking through the
at the |ns3| ``Attribute`` system while walking through the
``first.cc`` script. We looked at the following lines of code,
::
@@ -479,7 +479,7 @@ at the |ns3| ``Attribute`` system while walking through the
pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
and mentioned that ``DataRate`` was actually an ``Attribute`` of the
and mentioned that ``DataRate`` was actually an ``Attribute`` of the
``PointToPointNetDevice``. Let's use the command line argument parser
to take a look at the ``Attributes`` of the PointToPointNetDevice. The help
listing says that we should provide a ``TypeId``. This corresponds to the
@@ -500,12 +500,12 @@ Among the ``Attributes`` you will see listed is,
This is the default value that will be used when a ``PointToPointNetDevice``
is created in the system. We overrode this default with the ``Attribute``
setting in the ``PointToPointHelper`` above. Let's use the default values
for the point-to-point devices and channels by deleting the
``SetDeviceAttribute`` call and the ``SetChannelAttribute`` call from
setting in the ``PointToPointHelper`` above. Let's use the default values
for the point-to-point devices and channels by deleting the
``SetDeviceAttribute`` call and the ``SetChannelAttribute`` call from
the ``myfirst.cc`` we have in the scratch directory.
Your script should now just declare the ``PointToPointHelper`` and not do
Your script should now just declare the ``PointToPointHelper`` and not do
any ``set`` operations as in the following example,
::
@@ -523,7 +523,7 @@ any ``set`` operations as in the following example,
...
Go ahead and build the new script with ns3 (``./ns3``) and let's go back
and enable some logging from the UDP echo server application and turn on the
and enable some logging from the UDP echo server application and turn on the
time prefix.
.. sourcecode:: bash
@@ -555,10 +555,10 @@ was received by the echo server, it was at 2.00369 seconds.
2.00369s UdpEchoServerApplication:HandleRead(): Received 1024 bytes from 10.1.1.1
Now it is receiving the packet at 2.25732 seconds. This is because we just dropped
the data rate of the ``PointToPointNetDevice`` down to its default of
the data rate of the ``PointToPointNetDevice`` down to its default of
32768 bits per second from five megabits per second.
If we were to provide a new ``DataRate`` using the command line, we could
If we were to provide a new ``DataRate`` using the command line, we could
speed our simulation up again. We do this in the following way, according to
the formula implied by the help item:
@@ -566,10 +566,10 @@ the formula implied by the help item:
$ ./ns3 run "scratch/myfirst --ns3::PointToPointNetDevice::DataRate=5Mbps"
This will set the default value of the ``DataRate`` ``Attribute`` back to
This will set the default value of the ``DataRate`` ``Attribute`` back to
five megabits per second. Are you surprised by the result? It turns out that
in order to get the original behavior of the script back, we will have to set
the speed-of-light delay of the channel as well. We can ask the command line
in order to get the original behavior of the script back, we will have to set
the speed-of-light delay of the channel as well. We can ask the command line
system to print out the ``Attributes`` of the channel just like we did for
the net device:
@@ -611,25 +611,25 @@ in which case we recover the timing we had when we explicitly set the
UdpEchoServerApplication:DoDispose()
UdpEchoServerApplication:~UdpEchoServer()
Note that the packet is again received by the server at 2.00369 seconds. We
Note that the packet is again received by the server at 2.00369 seconds. We
could actually set any of the ``Attributes`` used in the script in this way.
In particular we could set the ``UdpEchoClient Attribute MaxPackets``
In particular we could set the ``UdpEchoClient Attribute MaxPackets``
to some other value than one.
How would you go about that? Give it a try. Remember you have to comment
out the place we override the default ``Attribute`` and explicitly set
``MaxPackets`` in the script. Then you have to rebuild the script. You
How would you go about that? Give it a try. Remember you have to comment
out the place we override the default ``Attribute`` and explicitly set
``MaxPackets`` in the script. Then you have to rebuild the script. You
will also have to find the syntax for actually setting the new default attribute
value using the command line help facility. Once you have this figured out
you should be able to control the number of packets echoed from the command
line. Since we're nice folks, we'll tell you that your command line should
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,
.. sourcecode:: bash
$ ./ns3 run "scratch/myfirst
--ns3::PointToPointNetDevice::DataRate=5Mbps
--ns3::PointToPointChannel::Delay=2ms
--ns3::PointToPointNetDevice::DataRate=5Mbps
--ns3::PointToPointChannel::Delay=2ms
--ns3::UdpEchoClient::MaxPackets=2"
A natural question to arise at this point is how to learn about the existence
@@ -651,8 +651,8 @@ a feature for this. If we ask for command line help we should see:
If you select the "PrintGroups" argument, you should see a list of all
registered TypeId groups. The group names are aligned with the module names
in the source directory (although with a leading capital letter). Printing
out all of the information at once would be too much, so a further filter
in the source directory (although with a leading capital letter). Printing
out all of the information at once would be too much, so a further filter
is available to print information on a per-group basis. So, focusing
again on the point-to-point module:
@@ -677,11 +677,11 @@ Hooking Your Own Values
You can also add your own hooks to the command line system. This is done
quite simply by using the ``AddValue`` method to the command line parser.
Let's use this facility to specify the number of packets to echo in a
Let's use this facility to specify the number of packets to echo in a
completely different way. Let's add a local variable called ``nPackets``
to the ``main`` function. We'll initialize it to one to match our previous
to the ``main`` function. We'll initialize it to one to match our previous
default behavior. To allow the command line parser to change this value, we
need to hook the value into the parser. We do this by adding a call to
need to hook the value into the parser. We do this by adding a call to
``AddValue``. Go ahead and change the ``scratch/myfirst.cc`` script to
start with the following code,
@@ -706,7 +706,7 @@ instead of the constant ``1`` as is shown below.
echoClient.SetAttribute ("MaxPackets", UintegerValue (nPackets));
Now if you run the script and provide the ``--PrintHelp`` argument, you
Now if you run the script and provide the ``--PrintHelp`` argument, you
should see your new ``User Argument`` listed in the help display.
Try,
@@ -759,11 +759,11 @@ You should now see
You have now echoed two packets. Pretty easy, isn't it?
You can see that if you are an |ns3| user, you can use the command
You can see that if you are an |ns3| user, you can use the command
line argument system to control global values and ``Attributes``. If you are
a model author, you can add new ``Attributes`` to your ``Objects`` and
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
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.
.. _UsingTracingSystem:
@@ -771,10 +771,10 @@ your scripts and hook them into the command line system quite painlessly.
Using the Tracing System
************************
The whole point of simulation is to generate output for further study, and
the |ns3| tracing system is a primary mechanism for this. Since
|ns3| is a C++ program, standard facilities for generating output
from C++ programs could be used:
The whole point of simulation is to generate output for further study, and
the |ns3| tracing system is a primary mechanism for this. Since
|ns3| is a C++ program, standard facilities for generating output
from C++ programs could be used:
::
@@ -785,43 +785,43 @@ from C++ programs could be used:
...
std::cout << "The value of x is " << x << std::endl;
...
}
}
You could even use the logging module to add a little structure to your
You could even use the logging module to add a little structure to your
solution. There are many well-known problems generated by such approaches
and so we have provided a generic event tracing subsystem to address the
and so we have provided a generic event tracing subsystem to address the
issues we thought were important.
The basic goals of the |ns3| tracing system are:
* For basic tasks, the tracing system should allow the user to generate
* For basic tasks, the tracing system should allow the user to generate
standard tracing for popular tracing sources, and to customize which objects
generate the tracing;
* Intermediate users must be able to extend the tracing system to modify
the output format generated, or to insert new tracing sources, without
the output format generated, or to insert new tracing sources, without
modifying the core of the simulator;
* Advanced users can modify the simulator core to add new tracing sources
and sinks.
The |ns3| tracing system is built on the concepts of independent
The |ns3| tracing system is built on the concepts of independent
tracing sources and tracing sinks, and a uniform mechanism for connecting
sources to sinks. Trace sources are entities that can signal events that
happen in a simulation and provide access to interesting underlying data.
happen in a simulation and provide access to interesting underlying data.
For example, a trace source could indicate when a packet is received by a net
device and provide access to the packet contents for interested trace sinks.
Trace sources are not useful by themselves, they must be "connected" to
other pieces of code that actually do something useful with the information
other pieces of code that actually do something useful with the information
provided by the sink. Trace sinks are consumers of the events and data
provided by the trace sources. For example, one could create a trace sink
that would (when connected to the trace source of the previous example) print
provided by the trace sources. For example, one could create a trace sink
that would (when connected to the trace source of the previous example) print
out interesting parts of the received packet.
The rationale for this explicit division is to allow users to attach new
types of sinks to existing tracing sources, without requiring editing and
recompilation of the core of the simulator. Thus, in the example above,
a user could define a new tracing sink in her script and attach it to an
existing tracing source defined in the simulation core by editing only the
types of sinks to existing tracing sources, without requiring editing and
recompilation of the core of the simulator. Thus, in the example above,
a user could define a new tracing sink in her script and attach it to an
existing tracing source defined in the simulation core by editing only the
user script.
In this tutorial, we will walk through some pre-defined sources and sinks and
@@ -832,14 +832,14 @@ extending the tracing namespace and creating new tracing sources.
ASCII Tracing
+++++++++++++
|ns3| provides helper functionality that wraps the low-level tracing
system to help you with the details involved in configuring some easily
system to help you with the details involved in configuring some easily
understood packet traces. If you enable this functionality, you will see
output in a ASCII files --- thus the name. For those familiar with
output in a ASCII files --- thus the name. For those familiar with
|ns2| output, this type of trace is analogous to the ``out.tr``
generated by many scripts.
Let's just jump right in and add some ASCII tracing output to our
``scratch/myfirst.cc`` script. Right before the call to
Let's just jump right in and add some ASCII tracing output to our
``scratch/myfirst.cc`` script. Right before the call to
``Simulator::Run ()``, add the following lines of code:
::
@@ -847,23 +847,23 @@ Let's just jump right in and add some ASCII tracing output to our
AsciiTraceHelper ascii;
pointToPoint.EnableAsciiAll (ascii.CreateFileStream ("myfirst.tr"));
Like in many other |ns3| idioms, this code uses a helper object to
help create ASCII traces. The second line contains two nested method calls.
Like in many other |ns3| idioms, this code uses a helper object to
help create ASCII traces. The second line contains two nested method calls.
The "inside" method, ``CreateFileStream()`` uses an unnamed object idiom
to create a file stream object on the stack (without an object name) and pass
it down to the called method. We'll go into this more in the future, but all
you have to know at this point is that you are creating an object representing
a file named "myfirst.tr" and passing it into ``ns-3``. You are telling
``ns-3`` to deal with the lifetime issues of the created object and also to
deal with problems caused by a little-known (intentional) limitation of C++
a file named "myfirst.tr" and passing it into ``ns-3``. You are telling
``ns-3`` to deal with the lifetime issues of the created object and also to
deal with problems caused by a little-known (intentional) limitation of C++
ofstream objects relating to copy constructors.
The outside call, to ``EnableAsciiAll()``, tells the helper that you
want to enable ASCII tracing on all point-to-point devices in your simulation;
and you want the (provided) trace sinks to write out information about packet
The outside call, to ``EnableAsciiAll()``, tells the helper that you
want to enable ASCII tracing on all point-to-point devices in your simulation;
and you want the (provided) trace sinks to write out information about packet
movement in ASCII format.
For those familiar with |ns2|, the traced events are equivalent to
For those familiar with |ns2|, the traced events are equivalent to
the popular trace points that log "+", "-", "d", and "r" events.
You can now build the script and run it from the command line:
@@ -873,15 +873,15 @@ You can now build the script and run it from the command line:
$ ./ns3 run scratch/myfirst
Just as you have seen many times before, you will see some messages from ns3 and then
"'build' finished successfully" with some number of messages from
the running program.
"'build' finished successfully" with some number of messages from
the running program.
When it ran, the program will have created a file named ``myfirst.tr``.
When it ran, the program will have created a file named ``myfirst.tr``.
Because of the way that ns3 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
directory, it is created at the top-level directory of the repository by
default. If you want to control where the traces are saved you can use the
``--cwd`` option of ns3 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
need to change into the top level directory of our repo and take a look at
the ASCII trace file ``myfirst.tr`` in your favorite editor.
Parsing Ascii Traces
@@ -891,10 +891,10 @@ to notice is that there are a number of distinct lines in this file. It may
be difficult to see this clearly unless you widen your window considerably.
Each line in the file corresponds to a *trace event*. In this case
we are tracing events on the *transmit queue* present in every
point-to-point net device in the simulation. The transmit queue is a queue
we are tracing events on the *transmit queue* present in every
point-to-point net device in the simulation. The transmit queue is a queue
through which every packet destined for a point-to-point channel must pass.
Note that each line in the trace file begins with a lone character (has a
Note that each line in the trace file begins with a lone character (has a
space after it). This character will have the following meaning:
* ``+``: An enqueue operation occurred on the device queue;
@@ -902,60 +902,60 @@ space after it). This character will have the following meaning:
* ``d``: A packet was dropped, typically because the queue was full;
* ``r``: A packet was received by the net device.
Let's take a more detailed view of the first line in the trace file. I'll
Let's take a more detailed view of the first line in the trace file. I'll
break it down into sections (indented for clarity) with a reference
number on the left side:
.. sourcecode:: text
:linenos:
+
2
/NodeList/0/DeviceList/0/$ns3::PointToPointNetDevice/TxQueue/Enqueue
+
2
/NodeList/0/DeviceList/0/$ns3::PointToPointNetDevice/TxQueue/Enqueue
ns3::PppHeader (
Point-to-Point Protocol: IP (0x0021))
Point-to-Point Protocol: IP (0x0021))
ns3::Ipv4Header (
tos 0x0 ttl 64 id 0 protocol 17 offset 0 flags [none]
tos 0x0 ttl 64 id 0 protocol 17 offset 0 flags [none]
length: 1052 10.1.1.1 > 10.1.1.2)
ns3::UdpHeader (
length: 1032 49153 > 9)
length: 1032 49153 > 9)
Payload (size=1024)
The first section of this expanded trace event (reference number 0) is the
The first section of this expanded trace event (reference number 0) is the
operation. We have a ``+`` character, so this corresponds to an
*enqueue* operation on the transmit queue. The second section (reference 1)
is the simulation time expressed in seconds. You may recall that we asked the
is the simulation time expressed in seconds. You may recall that we asked the
``UdpEchoClientApplication`` to start sending packets at two seconds. Here
we see confirmation that this is, indeed, happening.
The next section of the example trace (reference 2) tell us which trace source
originated this event (expressed in the tracing namespace). You can think
of the tracing namespace somewhat like you would a filesystem namespace. The
of the tracing namespace somewhat like you would a filesystem namespace. The
root of the namespace is the ``NodeList``. This corresponds to a container
managed in the |ns3| core code that contains all of the nodes that are
created in a script. Just as a filesystem may have directories under the
root, we may have node numbers in the ``NodeList``. The string
created in a script. Just as a filesystem may have directories under the
root, we may have node numbers in the ``NodeList``. The string
``/NodeList/0`` therefore refers to the zeroth node in the ``NodeList``
which we typically think of as "node 0". In each node there is a list of
which we typically think of as "node 0". In each node there is a list of
devices that have been installed. This list appears next in the namespace.
You can see that this trace event comes from ``DeviceList/0`` which is the
zeroth device installed in the node.
You can see that this trace event comes from ``DeviceList/0`` which is the
zeroth device installed in the node.
The next string, ``$ns3::PointToPointNetDevice`` tells you what kind of
The next string, ``$ns3::PointToPointNetDevice`` tells you what kind of
device is in the zeroth position of the device list for node zero.
Recall that the operation ``+`` found at reference 00 meant that an enqueue
operation happened on the transmit queue of the device. This is reflected in
Recall that the operation ``+`` found at reference 00 meant that an enqueue
operation happened on the transmit queue of the device. This is reflected in
the final segments of the "trace path" which are ``TxQueue/Enqueue``.
The remaining sections in the trace should be fairly intuitive. References 3-4
indicate that the packet is encapsulated in the point-to-point protocol.
indicate that the packet is encapsulated in the point-to-point protocol.
References 5-7 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
8-9 show that this packet has a UDP header and, finally, reference 10 shows
that the payload is the expected 1024 bytes.
The next line in the trace file shows the same packet being dequeued from the
transmit queue on the same node.
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.
@@ -963,55 +963,55 @@ device on the node with the echo server. I have reproduced that event below.
.. sourcecode:: text
:linenos:
r
2.25732
/NodeList/1/DeviceList/0/$ns3::PointToPointNetDevice/MacRx
r
2.25732
/NodeList/1/DeviceList/0/$ns3::PointToPointNetDevice/MacRx
ns3::Ipv4Header (
tos 0x0 ttl 64 id 0 protocol 17 offset 0 flags [none]
length: 1052 10.1.1.1 > 10.1.1.2)
ns3::UdpHeader (
length: 1032 49153 > 9)
length: 1032 49153 > 9)
Payload (size=1024)
Notice that the trace operation is now ``r`` and the simulation time has
increased to 2.25732 seconds. If you have been following the tutorial steps
closely this means that you have left the ``DataRate`` of the net devices
and the channel ``Delay`` set to their default values. This time should
and the channel ``Delay`` set to their default values. This time should
be familiar as you have seen it before in a previous section.
The trace source namespace entry (reference 02) has changed to reflect that
this event is coming from node 1 (``/NodeList/1``) and the packet reception
trace source (``/MacRx``). It should be quite easy for you to follow the
progress of the packet through the topology by looking at the rest of the
trace source (``/MacRx``). It should be quite easy for you to follow the
progress of the packet through the topology by looking at the rest of the
traces in the file.
PCAP Tracing
++++++++++++
The |ns3| device helpers can also be used to create trace files in the
``.pcap`` format. The acronym pcap (usually written in lower case) stands
for packet capture, and is actually an API that includes the
for packet capture, and is actually an API that includes the
definition of a ``.pcap`` file format. The most popular program that can
read and display this format is Wireshark (formerly called Ethereal).
However, there are many traffic trace analyzers that use this packet format.
We encourage users to exploit the many tools available for analyzing pcap
traces. In this tutorial, we concentrate on viewing pcap traces with tcpdump.
The code used to enable pcap tracing is a one-liner.
The code used to enable pcap tracing is a one-liner.
::
pointToPoint.EnablePcapAll ("myfirst");
Go ahead and insert this line of code after the ASCII tracing code we just
Go ahead and insert this line of code after the ASCII tracing code we just
added to ``scratch/myfirst.cc``. Notice that we only passed the string
"myfirst," and not "myfirst.pcap" or something similar. This is because the
parameter is a prefix, not a complete file name. The helper will actually
create a trace file for every point-to-point device in the simulation. The
"myfirst," and not "myfirst.pcap" or something similar. This is because the
parameter is a prefix, not a complete file name. The helper will actually
create a trace file for every point-to-point device in the simulation. The
file names will be built using the prefix, the node number, the device number
and a ".pcap" suffix.
In our example script, we will eventually see files named "myfirst-0-0.pcap"
and "myfirst-1-0.pcap" which are the pcap traces for node 0-device 0 and
In our example script, we will eventually see files named "myfirst-0-0.pcap"
and "myfirst-1-0.pcap" which are the pcap traces for node 0-device 0 and
node 1-device 0, respectively.
Once you have added the line of code to enable pcap tracing, you can run the
@@ -1022,14 +1022,14 @@ script in the usual way:
$ ./ns3 run scratch/myfirst
If you look at the top level directory of your distribution, you should now
see three log files: ``myfirst.tr`` is the ASCII trace file we have
see three log files: ``myfirst.tr`` is the ASCII trace file we have
previously examined. ``myfirst-0-0.pcap`` and ``myfirst-1-0.pcap``
are the new pcap files we just generated.
are the new pcap files we just generated.
Reading output with tcpdump
~~~~~~~~~~~~~~~~~~~~~~~~~~~
The easiest thing to do at this point will be to use ``tcpdump`` to look
at the ``pcap`` files.
at the ``pcap`` files.
.. sourcecode:: bash
@@ -1043,11 +1043,11 @@ at the ``pcap`` files.
2.257324 IP 10.1.1.1.49153 > 10.1.1.2.9: UDP, length 1024
2.257324 IP 10.1.1.2.9 > 10.1.1.1.49153: UDP, length 1024
You can see in the dump of ``myfirst-0-0.pcap`` (the client device) that the
You can see in the dump of ``myfirst-0-0.pcap`` (the client device) that the
echo packet is sent at 2 seconds into the simulation. If you look at the
second dump (``myfirst-1-0.pcap``) you can see that packet being received
at 2.257324 seconds. You see the packet being echoed back at 2.257324 seconds
in the second dump, and finally, you see the packet being received back at
in the second dump, and finally, you see the packet being received back at
the client in the first dump at 2.514648 seconds.
Reading output with Wireshark