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