Run utils/trim-trailing-whitespace.py on codebase
This commit is contained in:
@@ -20,12 +20,12 @@ def dump_pickles(out, dirname, filename, path):
|
||||
out.write(' <page url="%s">\n' % path)
|
||||
out.write(' <fragment>%s.frag</fragment>\n' % data['current_page_name'])
|
||||
if data['prev'] is not None:
|
||||
out.write(' <prev url="%s">%s</prev>\n' %
|
||||
(os.path.normpath(os.path.join(path, data['prev']['link'])),
|
||||
out.write(' <prev url="%s">%s</prev>\n' %
|
||||
(os.path.normpath(os.path.join(path, data['prev']['link'])),
|
||||
data['prev']['title']))
|
||||
if data['next'] is not None:
|
||||
out.write(' <next url="%s">%s</next>\n' %
|
||||
(os.path.normpath(os.path.join(path, data['next']['link'])),
|
||||
out.write(' <next url="%s">%s</next>\n' %
|
||||
(os.path.normpath(os.path.join(path, data['next']['link'])),
|
||||
data['next']['title']))
|
||||
out.write(' </page>\n')
|
||||
f.close()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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):
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user