work through second tutorial example
This commit is contained in:
@@ -16,285 +16,437 @@
|
||||
@chapter Building Topologies
|
||||
|
||||
@menu
|
||||
* Building a Star Topology
|
||||
* Building a Bus Network Topology
|
||||
@end menu
|
||||
|
||||
@c ========================================================================
|
||||
@c Building a Star Topology
|
||||
@c Building a Bus Network Topology
|
||||
@c ========================================================================
|
||||
@node Building a Star Topology
|
||||
@section Building a Star Topology
|
||||
@node Building a Bus Network Topology
|
||||
@section Building a Bus Network Topology
|
||||
|
||||
@cindex topology
|
||||
@cindex topology|star
|
||||
In this section we are going to use the point-to-point topology primitive we
|
||||
have explored in quite some detail to construct a star network. In the star,
|
||||
there is a central node that is connected to other nodes in a ``hub and spoke''
|
||||
fashion, with each ``spoke'' being a point-to-point link.
|
||||
In this section we are going to expand our mastery of ns-3 network devices and
|
||||
channels to cover an example of a bus network. Ns-3 provides a net device and
|
||||
channel we call CSMA (Carrier Sense Multiple Access).
|
||||
|
||||
We provide an example of a star topology simulation script on our
|
||||
@code{examples} directory. Go ahead and open @code{examples/star.cc} in your
|
||||
favorite editor. You will have already seen enough ns-3 code to understand
|
||||
this example, but we will go over the script briefly and examine some of the
|
||||
output.
|
||||
The ns-3 CSMA device models a simple network in the spirit of Ethernet. A real
|
||||
Ethernet uses CSMA/CD (Carrier Sense Multiple Access with Collision Detection)
|
||||
scheme with exponentially increasing backoff to contend for the shared
|
||||
transmission medium. The ns-3 CSMA device and channel models only a
|
||||
subset of this.
|
||||
|
||||
There is an amazingly beautiful bit of ASCII art at the beginning of the file
|
||||
that shows the topology used in the script. Most ns-3 example programs
|
||||
provide this, which can be surprisingly useful in understanding the code.
|
||||
Just as we have seen point-to-point topology helper objects when constructing
|
||||
point-to-point topologies, we will see equivalent CSMA topology helpers in
|
||||
this section. The appearance and operation of these helpers should look
|
||||
quite familiar to you.
|
||||
|
||||
We provide an example script in our @code{examples} directory. This script
|
||||
builds on the @code{first.cc} script and adds a CSMA network to the
|
||||
point-to-point simulation we've already considered. Go ahead and open
|
||||
@code{examples/second.cc} in your favorite editor. You will have already seen
|
||||
enough ns-3 code to understand most of what is going on in this example, but
|
||||
we will go over the entire script and examine some of the output.
|
||||
|
||||
Just as in the @code{first.cc} example (and in all ns-3 examples) the file
|
||||
begins with an emacs mode line and some GPL boilerplate.
|
||||
|
||||
One thing that can be surprisingly useful is a small bit of ASCII art that
|
||||
shows a cartoon of the network topology constructed in the example. You will
|
||||
find a similar ``drawing'' in most of our examples.
|
||||
|
||||
In this case, you can see that we are going to extend our point-to-point
|
||||
example (the link between the nodes n0 and n1 below) by hanging a bus network
|
||||
off of the right side. Notice that this is the default network topology
|
||||
since you can actually vary the number of nodes created on the LAN. If you
|
||||
set nCsma to one, there will be a total of two nodes on the LAN (CSMA
|
||||
channel) --- one required node and one ``extra'' node. By default there are
|
||||
thee ``extra'' nodes as seen below:
|
||||
|
||||
@verbatim
|
||||
// Network topology
|
||||
//
|
||||
// n3 n2
|
||||
// | /
|
||||
// | /
|
||||
// n4 --- n0 --- n1
|
||||
// / |
|
||||
// / |
|
||||
// n5 n6
|
||||
// Default Network Topology
|
||||
//
|
||||
// 10.1.1.0
|
||||
// n0 -------------- n1 n2 n3 n4
|
||||
// point-to-point | | | |
|
||||
// ================
|
||||
// LAN 10.1.2.0
|
||||
@end verbatim
|
||||
|
||||
There are seven nodes in this simulation, nodes zero through six. Node zero is
|
||||
the hub of this star network. We are going to discover that there will be a
|
||||
flow of echo packets between node four and node one, between node three and
|
||||
node six, and node five and node two.
|
||||
|
||||
The script starts by creating seven nodes in a @code{NodeContainer} and
|
||||
installs internet protocol stacks on all seven.
|
||||
The actual code begins by loading module include files just as was done in the
|
||||
@code{first.cc} example. Then the ns-3 namespace is @code{used} and a logging
|
||||
component is defined. This is all just as it was in @code{first.cc}, so there
|
||||
is nothing new yet.
|
||||
|
||||
@verbatim
|
||||
int
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/simulator-module.h"
|
||||
#include "ns3/node-module.h"
|
||||
#include "ns3/helper-module.h"
|
||||
#include "ns3/global-routing-module.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("SecondScriptExample");
|
||||
@end verbatim
|
||||
|
||||
The main program begins by enabling the @code{UdpEchoClientApplication} and
|
||||
@code{UdpEchoServerApplication} logging components at @code{INFO} level so
|
||||
we can see some output when we run the example. This should be entirely
|
||||
familiar to you so far.
|
||||
|
||||
@verbatim
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
NodeContainer nodes;
|
||||
nodes.Create (7);
|
||||
|
||||
InternetStackHelper stack;
|
||||
stack.Install (nodes);
|
||||
|
||||
...
|
||||
LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_INFO);
|
||||
LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_INFO);
|
||||
@end verbatim
|
||||
|
||||
It then creates six more @code{NodeContainer}s representing the nodes at each
|
||||
end of the six spokes. In all cases, the first node in the spoke is node zero.
|
||||
Next, you will see some familiar code that will allow you to change the number
|
||||
of devices on the CSMA network via command line argument. We did something
|
||||
similar when we allowed the number of packets sent to be changed in the section
|
||||
on command line arguments.
|
||||
|
||||
@verbatim
|
||||
NodeContainer nodes0and1 = NodeContainer (nodes.Get (0), nodes.Get (1));
|
||||
NodeContainer nodes0and2 = NodeContainer (nodes.Get (0), nodes.Get (2));
|
||||
NodeContainer nodes0and3 = NodeContainer (nodes.Get (0), nodes.Get (3));
|
||||
NodeContainer nodes0and4 = NodeContainer (nodes.Get (0), nodes.Get (4));
|
||||
NodeContainer nodes0and5 = NodeContainer (nodes.Get (0), nodes.Get (5));
|
||||
NodeContainer nodes0and6 = NodeContainer (nodes.Get (0), nodes.Get (6));
|
||||
uint32_t nCsma = 3;
|
||||
CommandLine cmd;
|
||||
cmd.AddValue ("nCsma", "Number of \"extra\" CSMA nodes/devices", nCsma);
|
||||
cmd.Parse (argc,argv);
|
||||
@end verbatim
|
||||
|
||||
These node containers will be used during the creation of the point-to-point
|
||||
links by the @code{PointToPointHelper}. The next bit of code instantiates
|
||||
a helper and sets the default values for the device @code{DataRate} and the
|
||||
channel @code{Delay} attributes as we have previously seen.
|
||||
The next step is to create two nodes that we will connect via the
|
||||
point-to-point link. The @code{NodeContainer} is used to do this just as was
|
||||
done in @code{first.cc}.
|
||||
|
||||
@verbatim
|
||||
NodeContainer p2pNodes;
|
||||
p2pNodes.Create (2);
|
||||
@end verbatim
|
||||
|
||||
Next, we delare another @code{NodeContainer} to hold the nodes that will be
|
||||
part of the bus (CSMA) network. First we just instantiate the container
|
||||
object itself.
|
||||
|
||||
@verbatim
|
||||
NodeContainer csmaNodes;
|
||||
csmaNodes.Add (p2pNodes.Get (1));
|
||||
csmaNodes.Create (nCsma);
|
||||
@end verbatim
|
||||
|
||||
The next line of code @code{Get}s 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.
|
||||
|
||||
The next bit of code should be quite familiar by now. We instantiate a
|
||||
@code{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.
|
||||
|
||||
@verbatim
|
||||
PointToPointHelper pointToPoint;
|
||||
pointToPoint.SetDeviceParameter ("DataRate", StringValue ("5Mbps"));
|
||||
pointToPoint.SetChannelParameter ("Delay", StringValue ("2ms"));
|
||||
|
||||
NetDeviceContainer p2pDevices;
|
||||
p2pDevices = pointToPoint.Install (p2pNodes);
|
||||
@end verbatim
|
||||
|
||||
The next step is to install the net devices on the nodes referenced by the
|
||||
six node containers and connect them via channels. We used one instance
|
||||
of the @code{pointToPoint.Install} method to construct our single
|
||||
point-to-point link in the @code{first.cc} script. This code just does that
|
||||
six times between different combinations of nodes.
|
||||
We then instantiate a @code{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 @code{CsmaHelper} works just
|
||||
like a @code{PointToPointHelper}, but it creates and connects CSMA devices and
|
||||
channels.
|
||||
|
||||
@verbatim
|
||||
NetDeviceContainer devicesOnNodes0and1 = pointToPoint.Install (nodes0and1);
|
||||
NetDeviceContainer devicesOnNodes0and2 = pointToPoint.Install (nodes0and2);
|
||||
NetDeviceContainer devicesOnNodes0and3 = pointToPoint.Install (nodes0and3);
|
||||
NetDeviceContainer devicesOnNodes0and4 = pointToPoint.Install (nodes0and4);
|
||||
NetDeviceContainer devicesOnNodes0and5 = pointToPoint.Install (nodes0and5);
|
||||
NetDeviceContainer devicesOnNodes0and6 = pointToPoint.Install (nodes0and6);
|
||||
CsmaHelper csma;
|
||||
|
||||
NetDeviceContainer csmaDevices;
|
||||
csmaDevices = csma.Install (csmaNodes);
|
||||
@end verbatim
|
||||
|
||||
Note that this does mean that node zero will have six net devices after this
|
||||
code executes. Recall that we need to keep containers holding the net devices
|
||||
we created in order to do IP address assignment. This is the next step in the
|
||||
script.
|
||||
Just as we created a @code{NetDeviceContainer} to hold the devices created by
|
||||
the @code{PointToPointHelper} we create a @code{NetDeviceContainer} to hold
|
||||
the devices created by our @code{CsmaHelper}. We call the @code{Install}
|
||||
method of the @code{CsmaHelper} to install the devices into the nodes of the
|
||||
@code{csmaNodes NodeContainer}.
|
||||
|
||||
Just as in @code{first.cc} we use the Ipv4AddressHelper to make it easy to
|
||||
deal with addressing. We need to create different networks for each stub, so
|
||||
we have to call the @code{SetBase} method and provide a different network
|
||||
number before assigning addresses to the devices on each network. We make it
|
||||
easy to remember what is what by setting the least significant bits of the
|
||||
network number to the unique node on the spoke. For example, the spoke between
|
||||
nodes zero and one is network 10.1.1; and the spoke between nodes zero and
|
||||
two is 10.1.2, etc. Note that the network mask is set to 255.255.255.252 in
|
||||
all cases.
|
||||
We now have our nodes, devices and channels created, but we have no protocol
|
||||
stacks present. Just as in the @code{first.cc} script, we will use the
|
||||
@code{InternetStackHelper} to install these stacks.
|
||||
|
||||
@verbatim
|
||||
Ipv4AddressHelper ipv4;
|
||||
|
||||
ipv4.SetBase ("10.1.1.0", "255.255.255.252");
|
||||
Ipv4InterfaceContainer interfacesOnNodes0and1 =
|
||||
ipv4.Assign (devicesOnNodes0and1);
|
||||
|
||||
ipv4.SetBase ("10.1.2.0", "255.255.255.252");
|
||||
Ipv4InterfaceContainer interfacesOnNodes0and2 =
|
||||
ipv4.Assign (devicesOnNodes0and2);
|
||||
|
||||
ipv4.SetBase ("10.1.3.0", "255.255.255.252");
|
||||
Ipv4InterfaceContainer interfacesOnNodes0and3 =
|
||||
ipv4.Assign (devicesOnNodes0and3);
|
||||
|
||||
ipv4.SetBase ("10.1.4.0", "255.255.255.252");
|
||||
Ipv4InterfaceContainer interfacesOnNodes0and4 =
|
||||
ipv4.Assign (devicesOnNodes0and4);
|
||||
|
||||
ipv4.SetBase ("10.1.5.0", "255.255.255.252");
|
||||
Ipv4InterfaceContainer interfacesOnNodes0and5 =
|
||||
ipv4.Assign (devicesOnNodes0and5);
|
||||
|
||||
ipv4.SetBase ("10.1.6.0", "255.255.255.252");
|
||||
Ipv4InterfaceContainer interfacesOnNodes0and6 =
|
||||
ipv4.Assign (devicesOnNodes0and6);
|
||||
InternetStackHelper stack;
|
||||
stack.Install (p2pNodes.Get (0));
|
||||
stack.Install (csmaNodes);
|
||||
@end verbatim
|
||||
|
||||
When the above code has executed, we will have the topology complete and then
|
||||
need to move on to applications. The code to do this should be familiar to
|
||||
you, but we have rearranged it slightly.
|
||||
Recall that we took one of the nodes from the @code{p2pNodes} container and
|
||||
added it to the @code{csmaNodes} container. Thus we only need to install
|
||||
the stacks on the remaining @code{p2pNodes} node, and all of the nodes in the
|
||||
@code{csmaNodes} container.
|
||||
|
||||
We use an ApplicationContainer to hold the results of the helper operations,
|
||||
and use the UdpEchoServerHelper and UdpEchoClient server to configure the
|
||||
apps just as we did in the @code{first.cc} script.
|
||||
Just as in the @code{first.cc} example script, we are going to use the
|
||||
@code{Ipv4AddressHelper} to assign IP addresses to our device interfaces.
|
||||
First we use the network 10.1.1.0 to create the two addresses needed for our
|
||||
two point-to-point devices.
|
||||
|
||||
@verbatim
|
||||
uint16_t port = 9;
|
||||
|
||||
ApplicationContainer apps;
|
||||
|
||||
UdpEchoServerHelper server;
|
||||
server.SetPort (port);
|
||||
|
||||
UdpEchoClientHelper client;
|
||||
client.SetAppAttribute ("MaxPackets", UintegerValue (10));
|
||||
client.SetAppAttribute ("Interval", StringValue ("10ms"));
|
||||
client.SetAppAttribute ("PacketSize", UintegerValue (137));
|
||||
Ipv4AddressHelper address;
|
||||
address.SetBase ("10.1.1.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer p2pInterfaces;
|
||||
p2pInterfaces = address.Assign (p2pDevices);
|
||||
@end verbatim
|
||||
|
||||
The next section of code is repeated three times, once for each data flow.
|
||||
We'll skim over the first instance quickly. The other two differ only in
|
||||
the nodes selected and the starting times of the flows.
|
||||
Recall that we save the created interfaces in a container to make it easy to
|
||||
pull out addressing information later.
|
||||
|
||||
Just as we did in the @code{first.cc} script, we use the
|
||||
@code{UdpEchoServerHelper} to install the echo server on a node (in this case,
|
||||
node number one -- the rightmost spoke in the topology). We tell the server
|
||||
application to start at a simulation time of one second. We use the
|
||||
@code{UdpEchoClientHelper} to install the echo client on a node (in this case,
|
||||
node number four -- the leftmost spoke in the topology). We tell the client
|
||||
to start sending data at a simulation time of two seconds.
|
||||
We then 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 that number changeable by command line
|
||||
argument. So the CSMA devices will be associated with IP addresses from
|
||||
network number 10.1.2.0 in this case.
|
||||
|
||||
@verbatim
|
||||
//
|
||||
// Echo from node 4 to node 1 starting at 2 sec
|
||||
//
|
||||
apps = server.Install (nodes.Get (1));
|
||||
apps.Start (Seconds (1.0));
|
||||
|
||||
client.SetRemote (interfacesOnNodes0and1.GetAddress (1), port);
|
||||
apps = client.Install (nodes.Get (4));
|
||||
apps.Start (Seconds (2.0));
|
||||
address.SetBase ("10.1.2.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer csmaInterfaces;
|
||||
csmaInterfaces = address.Assign (csmaDevices);
|
||||
@end verbatim
|
||||
|
||||
The next sections do the same thing, but for nodes three and six with a flow
|
||||
starting at 2.1 seconds, and for nodes five and two with flow starting at 2.2
|
||||
seconds.
|
||||
Now, we have a topology built, but we need applications. This section is
|
||||
going to be fundamentally similar to the applications section of
|
||||
@code{first.cc} but we are going to instantiate the server on one of the
|
||||
nodes that has a CSMA node and the client on the node having only a
|
||||
point-to-point device.
|
||||
|
||||
The only piece of code you may not have seen before follows. Since we have
|
||||
built an internetwork, we need some form of internetwork routing. Ns-3
|
||||
provides what we call a global route manager to set up the routing tables on
|
||||
nodes. This route manager has a global function that runs though the nodes
|
||||
of the simulation and does the hard work of setting up routing for you.
|
||||
You should completely understand the code for setting up the server since we
|
||||
have seen this before.
|
||||
|
||||
@verbatim
|
||||
ApplicationContainer serverApps = echoServer.Install (csmaNodes.Get (nCsma));
|
||||
serverApps.Start (Seconds (1.0));
|
||||
serverApps.Stop (Seconds (10.0));
|
||||
@end verbatim
|
||||
|
||||
Recall that the @code{csmaNodes NodeContainer} contains one of the
|
||||
nodes created for the point-to-point network and @code{nCsma} extra nodes.
|
||||
What we want to get is the last of the ``extra'' nodes. The zeroth entry of
|
||||
the @code{csmaNodes} container will the 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 be at index one of the @code{csmaNodes} container and, by induction,
|
||||
if we create @code{nCsma} ``extra'' nodes the last one will be at index
|
||||
@code{nCsma}. You see this exhibited in the first line of code.
|
||||
|
||||
The client application is set up exactly as we did in the @code{first.cc}
|
||||
example script. We point the client to the server we set up on the last of
|
||||
the ``extra'' CSMA nodes and install the client onto the point-to-point node
|
||||
that is not associated with any CSMA device.
|
||||
|
||||
@verbatim
|
||||
UdpEchoClientHelper echoClient;
|
||||
echoClient.SetRemote (csmaInterfaces.GetAddress (nCsma), 9);
|
||||
echoClient.SetAppAttribute ("MaxPackets", UintegerValue (1));
|
||||
echoClient.SetAppAttribute ("Interval", TimeValue (Seconds (1.)));
|
||||
echoClient.SetAppAttribute ("PacketSize", UintegerValue (1024));
|
||||
|
||||
ApplicationContainer clientApps = echoClient.Install (p2pNodes.Get (0));
|
||||
clientApps.Start (Seconds (2.0));
|
||||
clientApps.Stop (Seconds (10.0));
|
||||
@end verbatim
|
||||
|
||||
Since we have actually built an internetwork here, we need some form of
|
||||
internetwork routing. Ns-3 provides what we call a global route manager to
|
||||
set up the routing tables on nodes. This route manager has a global function
|
||||
that runs though the nodes created for the simulation and does the hard work
|
||||
of setting up routing for you.
|
||||
|
||||
Basically, what happens is that each node behaves as if it were an OSPF router
|
||||
that communicates instantly and magically with all other routers. Each node
|
||||
generates link advertisements to the global route manager, which uses this
|
||||
information to construct the routing tables for each node.
|
||||
generates link advertisements and communicates them directly to a global route
|
||||
manager, which uses this global information to construct the routing tables
|
||||
for each node. Setting up this form of routing is a one-liner:
|
||||
|
||||
@verbatim
|
||||
GlobalRouteManager::PopulateRoutingTables ();
|
||||
@end verbatim
|
||||
|
||||
The remainder of the script should be very familiar to you. We just enable
|
||||
ASCII and pcap tracing and run the simulation:
|
||||
pcap tracing, run the simulation and exit the script. Notice that enabling
|
||||
pcap tracing using the CSMA helper is done in the same way as for the pcap
|
||||
tracing with the point-to-point helper.
|
||||
|
||||
@verbatim
|
||||
std::ofstream ascii;
|
||||
ascii.open (``star.tr'');
|
||||
PointToPointHelper::EnableAsciiAll (ascii);
|
||||
PointToPointHelper::EnablePcapAll (``star'');
|
||||
PointToPointHelper::EnablePcapAll ("second");
|
||||
CsmaHelper::EnablePcapAll ("second");
|
||||
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
return 0;
|
||||
}
|
||||
@end verbatim
|
||||
|
||||
In order to run this example, you use waf. All of our example programs are
|
||||
built by default, so all you have to do is run it. Now, you did not build
|
||||
this script by copying it into the scratch directory, so you don't have to
|
||||
add the scratch directory to the run command. You just do the following,
|
||||
In order to run this example, you have to copy the @code{second.cc} example
|
||||
script into the scratch directory and use waf to build just as you did with
|
||||
the @code{first.cc} example. If you are in the top-level directory of the
|
||||
repository you would type,
|
||||
|
||||
@verbatim
|
||||
./waf --run star
|
||||
cp examples/second.cc scratch/
|
||||
./waf
|
||||
./waf --run scratch/second
|
||||
@end verbatim
|
||||
|
||||
There is no output from this script by default. It will just go off and
|
||||
silently do its thing. All you will see are waf messages:
|
||||
Since we have set up the UDP echo applications just as we did in the
|
||||
@code{first.cc} script, you will see similar output.
|
||||
|
||||
@verbatim
|
||||
~/repos/ns-3-tutorial > ./waf --run star
|
||||
Entering directory `/home/craigdo/repos/ns-3-tutorial/build'
|
||||
~/repos/ns-3-dev > ./waf --run scratch/second
|
||||
Entering directory `/home/craigdo/repos/ns-3-dev/build'
|
||||
Compilation finished successfully
|
||||
~/repos/ns-3-tutorial >
|
||||
Sent 1024 bytes to 10.1.2.4
|
||||
Received 1024 bytes from 10.1.1.1
|
||||
Received 1024 bytes from 10.1.2.4
|
||||
~/repos/ns-3-dev >
|
||||
@end verbatim
|
||||
|
||||
Recall that the first message, @code{Sent 1024 bytes to 10.1.2.4} is the
|
||||
UDP echo client sending a packet to the server. In this case, the server
|
||||
is on a different network (10.1.2.0). The second message, @code{Received 1024
|
||||
bytes from 10.1.1.1}, is from the UDP echo server, generated when it receives
|
||||
the echo packet. The final message, @code{Received 1024 bytes from 10.1.2.4}
|
||||
is from the echo client, indicating that it has received its echo back from
|
||||
the server.
|
||||
|
||||
If you now go and look in the top level directory, you will find a number of
|
||||
trace files:
|
||||
|
||||
@verbatim
|
||||
~/repos/ns-3-tutorial > ls *.pcap *.tr
|
||||
star-0-0.pcap star-0-3.pcap star-1-0.pcap star-4-0.pcap star.tr
|
||||
star-0-1.pcap star-0-4.pcap star-2-0.pcap star-5-0.pcap
|
||||
star-0-2.pcap star-0-5.pcap star-3-0.pcap star-6-0.pcap
|
||||
~/repos/ns-3-tutorial >
|
||||
~/repos/ns-3-dev > ls *.pcap
|
||||
second-0-0.pcap second-1-1.pcap second-3-0.pcap
|
||||
second-1-0.pcap second-2-0.pcap second-4-0.pcap
|
||||
~/repos/ns-3-dev >
|
||||
@end verbatim
|
||||
|
||||
If you have gone through the tracing section of this tutorial, you know how to
|
||||
interpret all of these files. For your reading pleasure, we reproduce a
|
||||
tcpdump from the net device on node four:
|
||||
Let's take a moment to look at the naming of these files. They all have the
|
||||
same form --- @code{<name>-<node>-<device>.pcap}. For example, the first file
|
||||
in the listing is @code{second-0-0.pcap} which is the pcap trace from node
|
||||
zero, device zero. There are no other devices on node zero so this is the
|
||||
only trace from that node.
|
||||
|
||||
Now look at @code{second-1-0.pcap} and @code{second-1-1.pcap}. The former is
|
||||
the pcap trace for device zero on node one and the latter is the trace file
|
||||
for device one on node one. If you refer back to the topology cartoon at
|
||||
the start of the section, you will see that node one is the node that has
|
||||
both a point-to-point device and a CSMA device, so we should expect two pcap
|
||||
traces for that node.
|
||||
|
||||
Now, let's follow the echo packet through the internetwork. First, do a
|
||||
tcpdump of the trace file for the leftmost point-to-point node --- node zero.
|
||||
|
||||
@verbatim
|
||||
[ns-regression] ~/repos/ns-3-tutorial > tcpdump -r star-4-0.pcap -nn -tt
|
||||
reading from file star-4-0.pcap, link-type PPP (PPP)
|
||||
2.000000 IP 10.1.4.2.49153 > 10.1.1.2.9: UDP, length 137
|
||||
2.009068 IP 10.1.1.2.9 > 10.1.4.2.49153: UDP, length 137
|
||||
2.010000 IP 10.1.4.2.49153 > 10.1.1.2.9: UDP, length 137
|
||||
2.019068 IP 10.1.1.2.9 > 10.1.4.2.49153: UDP, length 137
|
||||
2.020000 IP 10.1.4.2.49153 > 10.1.1.2.9: UDP, length 137
|
||||
2.029068 IP 10.1.1.2.9 > 10.1.4.2.49153: UDP, length 137
|
||||
2.030000 IP 10.1.4.2.49153 > 10.1.1.2.9: UDP, length 137
|
||||
2.039068 IP 10.1.1.2.9 > 10.1.4.2.49153: UDP, length 137
|
||||
2.040000 IP 10.1.4.2.49153 > 10.1.1.2.9: UDP, length 137
|
||||
2.049068 IP 10.1.1.2.9 > 10.1.4.2.49153: UDP, length 137
|
||||
2.050000 IP 10.1.4.2.49153 > 10.1.1.2.9: UDP, length 137
|
||||
2.059068 IP 10.1.1.2.9 > 10.1.4.2.49153: UDP, length 137
|
||||
2.060000 IP 10.1.4.2.49153 > 10.1.1.2.9: UDP, length 137
|
||||
2.069068 IP 10.1.1.2.9 > 10.1.4.2.49153: UDP, length 137
|
||||
2.070000 IP 10.1.4.2.49153 > 10.1.1.2.9: UDP, length 137
|
||||
2.079068 IP 10.1.1.2.9 > 10.1.4.2.49153: UDP, length 137
|
||||
2.080000 IP 10.1.4.2.49153 > 10.1.1.2.9: UDP, length 137
|
||||
2.089068 IP 10.1.1.2.9 > 10.1.4.2.49153: UDP, length 137
|
||||
2.090000 IP 10.1.4.2.49153 > 10.1.1.2.9: UDP, length 137
|
||||
2.099068 IP 10.1.1.2.9 > 10.1.4.2.49153: UDP, length 137
|
||||
[ns-regression] ~/repos/ns-3-tutorial >
|
||||
~/repos/ns-3-dev > tcpdump -r second-0-0.pcap -nn -tt
|
||||
reading from file second-0-0.pcap, link-type PPP (PPP)
|
||||
2.000000 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024
|
||||
2.007382 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024
|
||||
~/repos/ns-3-dev >
|
||||
@end verbatim
|
||||
|
||||
You are encouraged to think through the pcap traces and map them back to the
|
||||
script. Also, take a look at the @code{star.tr} ASCII trace file (which is
|
||||
quite large) to make sure you understand what it is telling you.
|
||||
The first line of the dump indicates that the link type is PPP (point-to-point)
|
||||
which we should expect. You then see the echo packet leaving node zero on
|
||||
via the device associated with IP address 10.1.1.1 headed for IP address
|
||||
10.1.2.4 (the rightmost CSMA node).
|
||||
|
||||
This packet will move over the point-to-point link and be received by the
|
||||
point-to-point net device on node one. Let's take a look:
|
||||
|
||||
@verbatim
|
||||
~/repos/ns-3-dev > tcpdump -r second-1-0.pcap -nn -tt
|
||||
reading from file second-1-0.pcap, link-type PPP (PPP)
|
||||
2.003686 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024
|
||||
2.003695 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024
|
||||
~/repos/ns-3-dev >
|
||||
@end verbatim
|
||||
|
||||
Here we see that the link type is also PPP as we would expect. You see the
|
||||
packet from IP address 10.1.1.1 headed toward 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 the other device headed for its
|
||||
ultimate destination. Let's then look at second-1-1.pcap and see if its there.
|
||||
|
||||
@verbatim
|
||||
~/repos/ns-3-dev > tcpdump -r second-1-1.pcap -nn -tt
|
||||
reading from file second-1-1.pcap, link-type EN10MB (Ethernet)
|
||||
2.003686 arp who-has 10.1.2.4 (ff:ff:ff:ff:ff:ff) tell 10.1.2.1
|
||||
2.003687 arp reply 10.1.2.4 is-at 00:00:00:00:00:06
|
||||
2.003687 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024
|
||||
2.003691 arp who-has 10.1.2.1 (ff:ff:ff:ff:ff:ff) tell 10.1.2.4
|
||||
2.003691 arp reply 10.1.2.1 is-at 00:00:00:00:00:03
|
||||
2.003695 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024
|
||||
~/repos/ns-3-dev >
|
||||
@end verbatim
|
||||
|
||||
As you can see, the link type is now ``Ethernet.'' Something new has appeared,
|
||||
though. The bus network needs @code{ARP}, the Address Resolution Protocol.
|
||||
The node 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. This exchange is seen in the following lines,
|
||||
|
||||
@verbatim
|
||||
2.003686 arp who-has 10.1.2.4 (ff:ff:ff:ff:ff:ff) tell 10.1.2.1
|
||||
2.003687 arp reply 10.1.2.4 is-at 00:00:00:00:00:06
|
||||
@end verbatim
|
||||
|
||||
Then node one, device one goes ahead and sends the echo packet to the UDP echo
|
||||
server at IP address 10.1.2.4. We can now look at the pcap trace for the
|
||||
echo server,
|
||||
|
||||
@verbatim
|
||||
~/repos/ns-3-dev > tcpdump -r second-4-0.pcap -nn -tt
|
||||
reading from file second-4-0.pcap, link-type EN10MB (Ethernet)
|
||||
2.003686 arp who-has 10.1.2.4 (ff:ff:ff:ff:ff:ff) tell 10.1.2.1
|
||||
2.003686 arp reply 10.1.2.4 is-at 00:00:00:00:00:06
|
||||
2.003690 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024
|
||||
2.003690 arp who-has 10.1.2.1 (ff:ff:ff:ff:ff:ff) tell 10.1.2.4
|
||||
2.003692 arp reply 10.1.2.1 is-at 00:00:00:00:00:03
|
||||
2.003692 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024
|
||||
~/repos/ns-3-dev >
|
||||
@end verbatim
|
||||
|
||||
Again, you see that the link type is ``Ethernet.'' The first two entries are
|
||||
the ARP exchange we just explained. The third packet is the echo packet
|
||||
being delivered to its final destination.
|
||||
|
||||
The echo server turns the packet around and needs to send it back to the echo
|
||||
cleint on 10.1.1.1 but it knows that this address is on another network that
|
||||
it reaches via IP address 10.1.2.1. This is because we initialized the global
|
||||
routing and it has figured all of this out for us. But, the echo server node
|
||||
doesn't know the MAC address of the first CSMA node, so it has to ARP for it
|
||||
just like the first CSMA node had to do. We leave it as an exercise for you
|
||||
to find the entries corresponding to the packet returning back on its way to
|
||||
the client (we have already dumped the traces and you can find them in those
|
||||
tcpdumps above.
|
||||
|
||||
Finally, let's take a look at one of the CSMA nodes that wasn't involved in
|
||||
the packet exchange:
|
||||
|
||||
@verbatim
|
||||
~/repos/ns-3-dev > tcpdump -r second-2-0.pcap -nn -tt
|
||||
reading from file second-2-0.pcap, link-type EN10MB (Ethernet)
|
||||
2.003686 arp who-has 10.1.2.4 (ff:ff:ff:ff:ff:ff) tell 10.1.2.1
|
||||
2.003691 arp who-has 10.1.2.1 (ff:ff:ff:ff:ff:ff) tell 10.1.2.4
|
||||
~/repos/ns-3-dev >
|
||||
@end verbatim
|
||||
|
||||
You can see that the CSMA channel is a broadcast medium and so all of the
|
||||
devices see the ARP requests involved in the packet exchange. The remaining
|
||||
pcap trace will be identical to this one.
|
||||
|
||||
|
||||
@@ -20,6 +20,15 @@
|
||||
#include "ns3/helper-module.h"
|
||||
#include "ns3/global-routing-module.h"
|
||||
|
||||
// Default Network Topology
|
||||
//
|
||||
// 10.1.1.0
|
||||
// n0 -------------- n1 n2 n3 n4
|
||||
// point-to-point | | | |
|
||||
// ================
|
||||
// LAN 10.1.2.0
|
||||
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("SecondScriptExample");
|
||||
@@ -30,9 +39,9 @@ main (int argc, char *argv[])
|
||||
LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_INFO);
|
||||
LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_INFO);
|
||||
|
||||
uint32_t nCsma = 10;
|
||||
uint32_t nCsma = 3;
|
||||
CommandLine cmd;
|
||||
cmd.AddValue ("nCsma", "number of csma devices", nCsma);
|
||||
cmd.AddValue ("nCsma", "Number of \"extra\" CSMA nodes/devices", nCsma);
|
||||
cmd.Parse (argc,argv);
|
||||
|
||||
NodeContainer p2pNodes;
|
||||
@@ -70,12 +79,12 @@ main (int argc, char *argv[])
|
||||
UdpEchoServerHelper echoServer;
|
||||
echoServer.SetPort (9);
|
||||
|
||||
ApplicationContainer serverApps = echoServer.Install (csmaNodes.Get (5));
|
||||
ApplicationContainer serverApps = echoServer.Install (csmaNodes.Get (nCsma));
|
||||
serverApps.Start (Seconds (1.0));
|
||||
serverApps.Stop (Seconds (10.0));
|
||||
|
||||
UdpEchoClientHelper echoClient;
|
||||
echoClient.SetRemote (csmaInterfaces.GetAddress (5), 9);
|
||||
echoClient.SetRemote (csmaInterfaces.GetAddress (nCsma), 9);
|
||||
echoClient.SetAppAttribute ("MaxPackets", UintegerValue (1));
|
||||
echoClient.SetAppAttribute ("Interval", TimeValue (Seconds (1.)));
|
||||
echoClient.SetAppAttribute ("PacketSize", UintegerValue (1024));
|
||||
@@ -86,6 +95,9 @@ main (int argc, char *argv[])
|
||||
|
||||
GlobalRouteManager::PopulateRoutingTables ();
|
||||
|
||||
PointToPointHelper::EnablePcapAll ("second");
|
||||
CsmaHelper::EnablePcapAll ("second");
|
||||
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
return 0;
|
||||
|
||||
@@ -4,12 +4,6 @@ def build(bld):
|
||||
obj = bld.create_ns3_program('hello-simulator')
|
||||
obj.source = 'hello-simulator.cc'
|
||||
|
||||
obj = bld.create_ns3_program('second')
|
||||
obj.source = 'second.cc'
|
||||
|
||||
obj = bld.create_ns3_program('third')
|
||||
obj.source = 'third.cc'
|
||||
|
||||
obj = bld.create_ns3_program('mixed-wireless',
|
||||
['core', 'simulator', 'mobility', 'wifi', 'point-to-point', 'internet-stack'])
|
||||
obj.source = 'mixed-wireless.cc'
|
||||
|
||||
Reference in New Issue
Block a user