6754
|
1 |
.. include:: replace.txt
|
|
2 |
|
|
3 |
|
|
4 |
Building Topologies
|
|
5 |
-------------------
|
|
6 |
|
|
7 |
Building a Bus Network Topology
|
|
8 |
*******************************
|
|
9 |
|
|
10 |
In this section we are going to expand our mastery of |ns3| network
|
|
11 |
devices and channels to cover an example of a bus network. |ns3|
|
|
12 |
provides a net device and channel we call CSMA (Carrier Sense Multiple Access).
|
|
13 |
|
|
14 |
The |ns3| CSMA device models a simple network in the spirit of
|
|
15 |
Ethernet. A real Ethernet uses CSMA/CD (Carrier Sense Multiple Access with
|
|
16 |
Collision Detection) scheme with exponentially increasing backoff to contend
|
|
17 |
for the shared transmission medium. The |ns3| CSMA device and
|
|
18 |
channel models only a subset of this.
|
|
19 |
|
|
20 |
Just as we have seen point-to-point topology helper objects when constructing
|
|
21 |
point-to-point topologies, we will see equivalent CSMA topology helpers in
|
|
22 |
this section. The appearance and operation of these helpers should look
|
|
23 |
quite familiar to you.
|
|
24 |
|
|
25 |
We provide an example script in our examples/tutorial} directory. This script
|
|
26 |
builds on the ``first.cc`` script and adds a CSMA network to the
|
|
27 |
point-to-point simulation we've already considered. Go ahead and open
|
|
28 |
``examples/tutorial/second.cc`` in your favorite editor. You will have already seen
|
|
29 |
enough |ns3| code to understand most of what is going on in this
|
|
30 |
example, but we will go over the entire script and examine some of the output.
|
|
31 |
|
|
32 |
Just as in the ``first.cc`` example (and in all ns-3 examples) the file
|
|
33 |
begins with an emacs mode line and some GPL boilerplate.
|
|
34 |
|
|
35 |
The actual code begins by loading module include files just as was done in the
|
|
36 |
``first.cc`` example.
|
|
37 |
|
|
38 |
::
|
|
39 |
|
|
40 |
#include "ns3/core-module.h"
|
|
41 |
#include "ns3/simulator-module.h"
|
|
42 |
#include "ns3/node-module.h"
|
|
43 |
#include "ns3/helper-module.h"
|
|
44 |
|
|
45 |
One thing that can be surprisingly useful is a small bit of ASCII art that
|
|
46 |
shows a cartoon of the network topology constructed in the example. You will
|
|
47 |
find a similar "drawing" in most of our examples.
|
|
48 |
|
|
49 |
In this case, you can see that we are going to extend our point-to-point
|
|
50 |
example (the link between the nodes n0 and n1 below) by hanging a bus network
|
|
51 |
off of the right side. Notice that this is the default network topology
|
|
52 |
since you can actually vary the number of nodes created on the LAN. If you
|
|
53 |
set nCsma to one, there will be a total of two nodes on the LAN (CSMA
|
|
54 |
channel) --- one required node and one "extra" node. By default there are
|
|
55 |
three "extra" nodes as seen below:
|
|
56 |
|
|
57 |
::
|
|
58 |
|
|
59 |
// Default Network Topology
|
|
60 |
//
|
|
61 |
// 10.1.1.0
|
|
62 |
// n0 -------------- n1 n2 n3 n4
|
|
63 |
// point-to-point | | | |
|
|
64 |
// ================
|
|
65 |
// LAN 10.1.2.0
|
|
66 |
|
|
67 |
Then the ns-3 namespace is ``used`` and a logging component is defined.
|
|
68 |
This is all just as it was in ``first.cc``, so there is nothing new yet.
|
|
69 |
|
|
70 |
::
|
|
71 |
|
|
72 |
using namespace ns3;
|
|
73 |
|
|
74 |
NS_LOG_COMPONENT_DEFINE ("SecondScriptExample");
|
|
75 |
|
|
76 |
The main program begins with a slightly different twist. We use a verbose
|
|
77 |
flag to determine whether or not the ``UdpEchoClientApplication`` and
|
|
78 |
``UdpEchoServerApplication`` logging components are enabled. This flag
|
|
79 |
defaults to true (the logging components are enabled) but allows us to turn
|
|
80 |
off logging during regression testing of this example.
|
|
81 |
|
|
82 |
You will see some familiar code that will allow you to change the number
|
|
83 |
of devices on the CSMA network via command line argument. We did something
|
|
84 |
similar when we allowed the number of packets sent to be changed in the section
|
|
85 |
on command line arguments. The last line makes sure you have at least one
|
|
86 |
"extra" node.
|
|
87 |
|
|
88 |
The code consists of variations of previously covered API so you should be
|
|
89 |
entirely comfortable with the following code at this point in the tutorial.
|
|
90 |
|
|
91 |
::
|
|
92 |
|
|
93 |
bool verbose = true;
|
|
94 |
uint32_t nCsma = 3;
|
|
95 |
|
|
96 |
CommandLine cmd;
|
|
97 |
cmd.AddValue ("nCsma", "Number of \"extra\" CSMA nodes/devices", nCsma);
|
|
98 |
cmd.AddValue ("verbose", "Tell echo applications to log if true", verbose);
|
|
99 |
|
|
100 |
cmd.Parse (argc,argv);
|
|
101 |
|
|
102 |
if (verbose)
|
|
103 |
{
|
|
104 |
LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_INFO);
|
|
105 |
LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_INFO);
|
|
106 |
}
|
|
107 |
|
|
108 |
nCsma = nCsma == 0 ? 1 : nCsma;
|
|
109 |
|
|
110 |
The next step is to create two nodes that we will connect via the
|
|
111 |
point-to-point link. The ``NodeContainer`` is used to do this just as was
|
|
112 |
done in ``first.cc``.
|
|
113 |
|
|
114 |
::
|
|
115 |
|
|
116 |
NodeContainer p2pNodes;
|
|
117 |
p2pNodes.Create (2);
|
|
118 |
|
|
119 |
Next, we declare another ``NodeContainer`` to hold the nodes that will be
|
|
120 |
part of the bus (CSMA) network. First, we just instantiate the container
|
|
121 |
object itself.
|
|
122 |
|
|
123 |
::
|
|
124 |
|
|
125 |
NodeContainer csmaNodes;
|
|
126 |
csmaNodes.Add (p2pNodes.Get (1));
|
|
127 |
csmaNodes.Create (nCsma);
|
|
128 |
|
|
129 |
The next line of code ``Gets`` the first node (as in having an index of one)
|
|
130 |
from the point-to-point node container and adds it to the container of nodes
|
|
131 |
that will get CSMA devices. The node in question is going to end up with a
|
|
132 |
point-to-point device *and* a CSMA device. We then create a number of
|
|
133 |
"extra" nodes that compose the remainder of the CSMA network. Since we
|
|
134 |
already have one node in the CSMA network -- the one that will have both a
|
|
135 |
point-to-point and CSMA net device, the number of "extra" nodes means the
|
|
136 |
number nodes you desire in the CSMA section minus one.
|
|
137 |
|
|
138 |
The next bit of code should be quite familiar by now. We instantiate a
|
|
139 |
``PointToPointHelper`` and set the associated default ``Attributes`` so
|
|
140 |
that we create a five megabit per second transmitter on devices created using
|
|
141 |
the helper and a two millisecond delay on channels created by the helper.
|
|
142 |
|
|
143 |
::
|
|
144 |
|
|
145 |
PointToPointHelper pointToPoint;
|
|
146 |
pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
|
|
147 |
pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
|
|
148 |
|
|
149 |
NetDeviceContainer p2pDevices;
|
|
150 |
p2pDevices = pointToPoint.Install (p2pNodes);
|
|
151 |
|
|
152 |
We then instantiate a ``NetDeviceContainer`` to keep track of the
|
|
153 |
point-to-point net devices and we ``Install`` devices on the
|
|
154 |
point-to-point nodes.
|
|
155 |
|
|
156 |
We mentioned above that you were going to see a helper for CSMA devices and
|
|
157 |
channels, and the next lines introduce them. The ``CsmaHelper`` works just
|
|
158 |
like a ``PointToPointHelper``, but it creates and connects CSMA devices and
|
|
159 |
channels. In the case of a CSMA device and channel pair, notice that the data
|
|
160 |
rate is specified by a *channel* ``Attribute`` instead of a device
|
|
161 |
``Attribute``. This is because a real CSMA network does not allow one to mix,
|
|
162 |
for example, 10Base-T and 100Base-T devices on a given channel. We first set
|
|
163 |
the data rate to 100 megabits per second, and then set the speed-of-light delay
|
|
164 |
of the channel to 6560 nano-seconds (arbitrarily chosen as 1 nanosecond per foot
|
|
165 |
over a 100 meter segment). Notice that you can set an ``Attribute`` using
|
|
166 |
its native data type.
|
|
167 |
|
|
168 |
::
|
|
169 |
|
|
170 |
CsmaHelper csma;
|
|
171 |
csma.SetChannelAttribute ("DataRate", StringValue ("100Mbps"));
|
|
172 |
csma.SetChannelAttribute ("Delay", TimeValue (NanoSeconds (6560)));
|
|
173 |
|
|
174 |
NetDeviceContainer csmaDevices;
|
|
175 |
csmaDevices = csma.Install (csmaNodes);
|
|
176 |
|
|
177 |
Just as we created a ``NetDeviceContainer`` to hold the devices created by
|
|
178 |
the ``PointToPointHelper`` we create a ``NetDeviceContainer`` to hold
|
|
179 |
the devices created by our ``CsmaHelper``. We call the ``Install``
|
|
180 |
method of the ``CsmaHelper`` to install the devices into the nodes of the
|
|
181 |
``csmaNodes NodeContainer``.
|
|
182 |
|
|
183 |
We now have our nodes, devices and channels created, but we have no protocol
|
|
184 |
stacks present. Just as in the ``first.cc`` script, we will use the
|
|
185 |
``InternetStackHelper`` to install these stacks.
|
|
186 |
|
|
187 |
::
|
|
188 |
|
|
189 |
InternetStackHelper stack;
|
|
190 |
stack.Install (p2pNodes.Get (0));
|
|
191 |
stack.Install (csmaNodes);
|
|
192 |
|
|
193 |
Recall that we took one of the nodes from the ``p2pNodes`` container and
|
|
194 |
added it to the ``csmaNodes`` container. Thus we only need to install
|
|
195 |
the stacks on the remaining ``p2pNodes`` node, and all of the nodes in the
|
|
196 |
``csmaNodes`` container to cover all of the nodes in the simulation.
|
|
197 |
|
|
198 |
Just as in the ``first.cc`` example script, we are going to use the
|
|
199 |
``Ipv4AddressHelper`` to assign IP addresses to our device interfaces.
|
|
200 |
First we use the network 10.1.1.0 to create the two addresses needed for our
|
|
201 |
two point-to-point devices.
|
|
202 |
|
|
203 |
::
|
|
204 |
|
|
205 |
Ipv4AddressHelper address;
|
|
206 |
address.SetBase ("10.1.1.0", "255.255.255.0");
|
|
207 |
Ipv4InterfaceContainer p2pInterfaces;
|
|
208 |
p2pInterfaces = address.Assign (p2pDevices);
|
|
209 |
|
|
210 |
Recall that we save the created interfaces in a container to make it easy to
|
|
211 |
pull out addressing information later for use in setting up the applications.
|
|
212 |
|
|
213 |
We now need to assign IP addresses to our CSMA device interfaces. The
|
|
214 |
operation works just as it did for the point-to-point case, except we now
|
|
215 |
are performing the operation on a container that has a variable number of
|
|
216 |
CSMA devices --- remember we made the number of CSMA devices changeable by
|
|
217 |
command line argument. The CSMA devices will be associated with IP addresses
|
|
218 |
from network number 10.1.2.0 in this case, as seen below.
|
|
219 |
|
|
220 |
::
|
|
221 |
|
|
222 |
address.SetBase ("10.1.2.0", "255.255.255.0");
|
|
223 |
Ipv4InterfaceContainer csmaInterfaces;
|
|
224 |
csmaInterfaces = address.Assign (csmaDevices);
|
|
225 |
|
|
226 |
Now we have a topology built, but we need applications. This section is
|
|
227 |
going to be fundamentally similar to the applications section of
|
|
228 |
``first.cc`` but we are going to instantiate the server on one of the
|
|
229 |
nodes that has a CSMA device and the client on the node having only a
|
|
230 |
point-to-point device.
|
|
231 |
|
|
232 |
First, we set up the echo server. We create a ``UdpEchoServerHelper`` and
|
|
233 |
provide a required ``Attribute`` value to the constructor which is the server
|
|
234 |
port number. Recall that this port can be changed later using the
|
|
235 |
``SetAttribute`` method if desired, but we require it to be provided to
|
|
236 |
the constructor.
|
|
237 |
|
|
238 |
::
|
|
239 |
|
|
240 |
UdpEchoServerHelper echoServer (9);
|
|
241 |
|
|
242 |
ApplicationContainer serverApps = echoServer.Install (csmaNodes.Get (nCsma));
|
|
243 |
serverApps.Start (Seconds (1.0));
|
|
244 |
serverApps.Stop (Seconds (10.0));
|
|
245 |
|
|
246 |
Recall that the ``csmaNodes NodeContainer`` contains one of the
|
|
247 |
nodes created for the point-to-point network and ``nCsma`` "extra" nodes.
|
|
248 |
What we want to get at is the last of the "extra" nodes. The zeroth entry of
|
|
249 |
the ``csmaNodes`` container will be the point-to-point node. The easy
|
|
250 |
way to think of this, then, is if we create one "extra" CSMA node, then it
|
|
251 |
will be at index one of the ``csmaNodes`` container. By induction,
|
|
252 |
if we create ``nCsma`` "extra" nodes the last one will be at index
|
|
253 |
``nCsma``. You see this exhibited in the ``Get`` of the first line of
|
|
254 |
code.
|
|
255 |
|
|
256 |
The client application is set up exactly as we did in the ``first.cc``
|
|
257 |
example script. Again, we provide required ``Attributes`` to the
|
|
258 |
``UdpEchoClientHelper`` in the constructor (in this case the remote address
|
|
259 |
and port). We tell the client to send packets to the server we just installed
|
|
260 |
on the last of the "extra" CSMA nodes. We install the client on the
|
|
261 |
leftmost point-to-point node seen in the topology illustration.
|
|
262 |
|
|
263 |
::
|
|
264 |
|
|
265 |
UdpEchoClientHelper echoClient (csmaInterfaces.GetAddress (nCsma), 9);
|
|
266 |
echoClient.SetAttribute ("MaxPackets", UintegerValue (1));
|
|
267 |
echoClient.SetAttribute ("Interval", TimeValue (Seconds (1.)));
|
|
268 |
echoClient.SetAttribute ("PacketSize", UintegerValue (1024));
|
|
269 |
|
|
270 |
ApplicationContainer clientApps = echoClient.Install (p2pNodes.Get (0));
|
|
271 |
clientApps.Start (Seconds (2.0));
|
|
272 |
clientApps.Stop (Seconds (10.0));
|
|
273 |
|
|
274 |
Since we have actually built an internetwork here, we need some form of
|
|
275 |
internetwork routing. |ns3| provides what we call global routing to
|
|
276 |
help you out. Global routing takes advantage of the fact that the entire
|
|
277 |
internetwork is accessible in the simulation and runs through the all of the
|
|
278 |
nodes created for the simulation --- it does the hard work of setting up routing
|
|
279 |
for you without having to configure routers.
|
|
280 |
|
|
281 |
Basically, what happens is that each node behaves as if it were an OSPF router
|
|
282 |
that communicates instantly and magically with all other routers behind the
|
|
283 |
scenes. Each node generates link advertisements and communicates them
|
|
284 |
directly to a global route manager which uses this global information to
|
|
285 |
construct the routing tables for each node. Setting up this form of routing
|
|
286 |
is a one-liner:
|
|
287 |
|
|
288 |
::
|
|
289 |
|
|
290 |
Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
|
|
291 |
|
|
292 |
Next we enable pcap tracing. The first line of code to enable pcap tracing
|
|
293 |
in the point-to-point helper should be familiar to you by now. The second
|
|
294 |
line enables pcap tracing in the CSMA helper and there is an extra parameter
|
|
295 |
you haven't encountered yet.
|
|
296 |
|
|
297 |
::
|
|
298 |
|
|
299 |
pointToPoint.EnablePcapAll ("second");
|
|
300 |
csma.EnablePcap ("second", csmaDevices.Get (1), true);
|
|
301 |
|
|
302 |
The CSMA network is a multi-point-to-point network. This means that there
|
|
303 |
can (and are in this case) multiple endpoints on a shared medium. Each of
|
|
304 |
these endpoints has a net device associated with it. There are two basic
|
|
305 |
alternatives to gathering trace information from such a network. One way
|
|
306 |
is to create a trace file for each net device and store only the packets
|
|
307 |
that are emitted or consumed by that net device. Another way is to pick
|
|
308 |
one of the devices and place it in promiscuous mode. That single device
|
|
309 |
then "sniffs" the network for all packets and stores them in a single
|
|
310 |
pcap file. This is how ``tcpdump``, for example, works. That final
|
|
311 |
parameter tells the CSMA helper whether or not to arrange to capture
|
|
312 |
packets in promiscuous mode.
|
|
313 |
|
|
314 |
In this example, we are going to select one of the devices on the CSMA
|
|
315 |
network and ask it to perform a promiscuous sniff of the network, thereby
|
|
316 |
emulating what ``tcpdump`` would do. If you were on a Linux machine
|
|
317 |
you might do something like ``tcpdump -i eth0`` to get the trace.
|
|
318 |
In this case, we specify the device using ``csmaDevices.Get(1)``,
|
|
319 |
which selects the first device in the container. Setting the final
|
|
320 |
parameter to true enables promiscuous captures.
|
|
321 |
|
|
322 |
The last section of code just runs and cleans up the simulation just like
|
|
323 |
the ``first.cc`` example.
|
|
324 |
|
|
325 |
::
|
|
326 |
|
|
327 |
Simulator::Run ();
|
|
328 |
Simulator::Destroy ();
|
|
329 |
return 0;
|
|
330 |
}
|
|
331 |
|
|
332 |
In order to run this example, copy the ``second.cc`` example script into
|
|
333 |
the scratch directory and use waf to build just as you did with
|
|
334 |
the ``first.cc`` example. If you are in the top-level directory of the
|
|
335 |
repository you just type,
|
|
336 |
|
|
337 |
::
|
|
338 |
|
|
339 |
cp examples/tutorial/second.cc scratch/mysecond.cc
|
|
340 |
./waf
|
|
341 |
|
|
342 |
Warning: We use the file ``second.cc`` as one of our regression tests to
|
|
343 |
verify that it works exactly as we think it should in order to make your
|
|
344 |
tutorial experience a positive one. This means that an executable named
|
|
345 |
``second`` already exists in the project. To avoid any confusion
|
|
346 |
about what you are executing, please do the renaming to ``mysecond.cc``
|
|
347 |
suggested above.
|
|
348 |
|
|
349 |
If you are following the tutorial religiously (you are, aren't you) you will
|
|
350 |
still have the NS_LOG variable set, so go ahead and clear that variable and
|
|
351 |
run the program.
|
|
352 |
|
|
353 |
::
|
|
354 |
|
|
355 |
export NS_LOG=
|
|
356 |
./waf --run scratch/mysecond
|
|
357 |
|
|
358 |
Since we have set up the UDP echo applications to log just as we did in
|
|
359 |
``first.cc``, you will see similar output when you run the script.
|
|
360 |
|
|
361 |
::
|
|
362 |
|
|
363 |
Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
|
|
364 |
Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
|
|
365 |
'build' finished successfully (0.415s)
|
|
366 |
Sent 1024 bytes to 10.1.2.4
|
|
367 |
Received 1024 bytes from 10.1.1.1
|
|
368 |
Received 1024 bytes from 10.1.2.4
|
|
369 |
|
|
370 |
Recall that the first message, "``Sent 1024 bytes to 10.1.2.4``," is the
|
|
371 |
UDP echo client sending a packet to the server. In this case, the server
|
|
372 |
is on a different network (10.1.2.0). The second message, "``Received 1024
|
|
373 |
bytes from 10.1.1.1``," is from the UDP echo server, generated when it receives
|
|
374 |
the echo packet. The final message, "``Received 1024 bytes from 10.1.2.4``,"
|
|
375 |
is from the echo client, indicating that it has received its echo back from
|
|
376 |
the server.
|
|
377 |
|
|
378 |
If you now go and look in the top level directory, you will find three trace
|
|
379 |
files:
|
|
380 |
|
|
381 |
::
|
|
382 |
|
|
383 |
second-0-0.pcap second-1-0.pcap second-2-0.pcap
|
|
384 |
|
|
385 |
Let's take a moment to look at the naming of these files. They all have the
|
|
386 |
same form, ``<name>-<node>-<device>.pcap``. For example, the first file
|
|
387 |
in the listing is ``second-0-0.pcap`` which is the pcap trace from node
|
|
388 |
zero, device zero. This is the point-to-point net device on node zero. The
|
|
389 |
file ``second-1-0.pcap`` is the pcap trace for device zero on node one,
|
|
390 |
also a point-to-point net device; and the file ``second-2-0.pcap`` is the
|
|
391 |
pcap trace for device zero on node two.
|
|
392 |
|
|
393 |
If you refer back to the topology illustration at the start of the section,
|
|
394 |
you will see that node zero is the leftmost node of the point-to-point link
|
|
395 |
and node one is the node that has both a point-to-point device and a CSMA
|
|
396 |
device. You will see that node two is the first "extra" node on the CSMA
|
|
397 |
network and its device zero was selected as the device to capture the
|
|
398 |
promiscuous-mode trace.
|
|
399 |
|
|
400 |
Now, let's follow the echo packet through the internetwork. First, do a
|
|
401 |
tcpdump of the trace file for the leftmost point-to-point node --- node zero.
|
|
402 |
|
|
403 |
::
|
|
404 |
|
|
405 |
tcpdump -nn -tt -r second-0-0.pcap
|
|
406 |
|
|
407 |
You should see the contents of the pcap file displayed:
|
|
408 |
|
|
409 |
::
|
|
410 |
|
|
411 |
reading from file second-0-0.pcap, link-type PPP (PPP)
|
|
412 |
2.000000 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024
|
|
413 |
2.007602 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024
|
|
414 |
|
|
415 |
The first line of the dump indicates that the link type is PPP (point-to-point)
|
|
416 |
which we expect. You then see the echo packet leaving node zero via the
|
|
417 |
device associated with IP address 10.1.1.1 headed for IP address
|
|
418 |
10.1.2.4 (the rightmost CSMA node). This packet will move over the
|
|
419 |
point-to-point link and be received by the point-to-point net device on node
|
|
420 |
one. Let's take a look:
|
|
421 |
|
|
422 |
::
|
|
423 |
|
|
424 |
tcpdump -nn -tt -r second-1-0.pcap
|
|
425 |
|
|
426 |
You should now see the pcap trace output of the other side of the point-to-point
|
|
427 |
link:
|
|
428 |
|
|
429 |
::
|
|
430 |
|
|
431 |
reading from file second-1-0.pcap, link-type PPP (PPP)
|
|
432 |
2.003686 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024
|
|
433 |
2.003915 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024
|
|
434 |
|
|
435 |
Here we see that the link type is also PPP as we would expect. You see the
|
|
436 |
packet from IP address 10.1.1.1 (that was sent at 2.000000 seconds) headed
|
|
437 |
toward IP address 10.1.2.4 appear on this interface. Now, internally to this
|
|
438 |
node, the packet will be forwarded to the CSMA interface and we should see it
|
|
439 |
pop out on that device headed for its ultimate destination.
|
|
440 |
|
|
441 |
Remember that we selected node 2 as the promiscuous sniffer node for the CSMA
|
|
442 |
network so let's then look at second-2-0.pcap and see if its there.
|
|
443 |
|
|
444 |
::
|
|
445 |
|
|
446 |
tcpdump -nn -tt -r second-2-0.pcap
|
|
447 |
|
|
448 |
You should now see the promiscuous dump of node two, device zero:
|
|
449 |
|
|
450 |
::
|
|
451 |
|
|
452 |
reading from file second-2-0.pcap, link-type EN10MB (Ethernet)
|
|
453 |
2.003696 arp who-has 10.1.2.4 (ff:ff:ff:ff:ff:ff) tell 10.1.2.1
|
|
454 |
2.003707 arp reply 10.1.2.4 is-at 00:00:00:00:00:06
|
|
455 |
2.003801 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024
|
|
456 |
2.003811 arp who-has 10.1.2.1 (ff:ff:ff:ff:ff:ff) tell 10.1.2.4
|
|
457 |
2.003822 arp reply 10.1.2.1 is-at 00:00:00:00:00:03
|
|
458 |
2.003915 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024
|
|
459 |
|
|
460 |
As you can see, the link type is now "Ethernet". Something new has appeared,
|
|
461 |
though. The bus network needs ``ARP``, the Address Resolution Protocol.
|
|
462 |
Node one knows it needs to send the packet to IP address 10.1.2.4, but it
|
|
463 |
doesn't know the MAC address of the corresponding node. It broadcasts on the
|
|
464 |
CSMA network (ff:ff:ff:ff:ff:ff) asking for the device that has IP address
|
|
465 |
10.1.2.4. In this case, the rightmost node replies saying it is at MAC address
|
|
466 |
00:00:00:00:00:06. Note that node two is not directly involved in this
|
|
467 |
exchange, but is sniffing the network and reporting all of the traffic it sees.
|
|
468 |
|
|
469 |
This exchange is seen in the following lines,
|
|
470 |
|
|
471 |
::
|
|
472 |
|
|
473 |
2.003696 arp who-has 10.1.2.4 (ff:ff:ff:ff:ff:ff) tell 10.1.2.1
|
|
474 |
2.003707 arp reply 10.1.2.4 is-at 00:00:00:00:00:06
|
|
475 |
|
|
476 |
Then node one, device one goes ahead and sends the echo packet to the UDP echo
|
|
477 |
server at IP address 10.1.2.4.
|
|
478 |
|
|
479 |
::
|
|
480 |
|
|
481 |
2.003801 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024
|
|
482 |
|
|
483 |
The server receives the echo request and turns the packet around trying to send
|
|
484 |
it back to the source. The server knows that this address is on another network
|
|
485 |
that it reaches via IP address 10.1.2.1. This is because we initialized global
|
|
486 |
routing and it has figured all of this out for us. But, the echo server node
|
|
487 |
doesn't know the MAC address of the first CSMA node, so it has to ARP for it
|
|
488 |
just like the first CSMA node had to do.
|
|
489 |
|
|
490 |
::
|
|
491 |
|
|
492 |
2.003811 arp who-has 10.1.2.1 (ff:ff:ff:ff:ff:ff) tell 10.1.2.4
|
|
493 |
2.003822 arp reply 10.1.2.1 is-at 00:00:00:00:00:03
|
|
494 |
|
|
495 |
The server then sends the echo back to the forwarding node.
|
|
496 |
|
|
497 |
::
|
|
498 |
|
|
499 |
2.003915 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024
|
|
500 |
|
|
501 |
Looking back at the rightmost node of the point-to-point link,
|
|
502 |
|
|
503 |
::
|
|
504 |
|
|
505 |
tcpdump -nn -tt -r second-1-0.pcap
|
|
506 |
|
|
507 |
You can now see the echoed packet coming back onto the point-to-point link as
|
|
508 |
the last line of the trace dump.
|
|
509 |
|
|
510 |
::
|
|
511 |
|
|
512 |
reading from file second-1-0.pcap, link-type PPP (PPP)
|
|
513 |
2.003686 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024
|
|
514 |
2.003915 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024
|
|
515 |
|
|
516 |
Lastly, you can look back at the node that originated the echo
|
|
517 |
::
|
|
518 |
|
|
519 |
tcpdump -nn -tt -r second-0-0.pcap
|
|
520 |
|
|
521 |
and see that the echoed packet arrives back at the source at 2.007602 seconds,
|
|
522 |
|
|
523 |
::
|
|
524 |
|
|
525 |
reading from file second-0-0.pcap, link-type PPP (PPP)
|
|
526 |
2.000000 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024
|
|
527 |
2.007602 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024
|
|
528 |
|
|
529 |
Finally, recall that we added the ability to control the number of CSMA devices
|
|
530 |
in the simulation by command line argument. You can change this argument in
|
|
531 |
the same way as when we looked at changing the number of packets echoed in the
|
|
532 |
``first.cc`` example. Try running the program with the number of "extra"
|
|
533 |
devices set to four:
|
|
534 |
|
|
535 |
::
|
|
536 |
|
|
537 |
./waf --run "scratch/mysecond --nCsma=4"
|
|
538 |
|
|
539 |
You should now see,
|
|
540 |
|
|
541 |
::
|
|
542 |
|
|
543 |
Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
|
|
544 |
Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
|
|
545 |
'build' finished successfully (0.405s)
|
|
546 |
Sent 1024 bytes to 10.1.2.5
|
|
547 |
Received 1024 bytes from 10.1.1.1
|
|
548 |
Received 1024 bytes from 10.1.2.5
|
|
549 |
|
|
550 |
Notice that the echo server has now been relocated to the last of the CSMA
|
|
551 |
nodes, which is 10.1.2.5 instead of the default case, 10.1.2.4.
|
|
552 |
|
|
553 |
It is possible that you may not be satisfied with a trace file generated by
|
|
554 |
a bystander in the CSMA network. You may really want to get a trace from
|
|
555 |
a single device and you may not be interested in any other traffic on the
|
|
556 |
network. You can do this fairly easily.
|
|
557 |
|
|
558 |
Let's take a look at ``scratch/mysecond.cc`` and add that code enabling us
|
|
559 |
to be more specific. ``ns-3`` helpers provide methods that take a node
|
|
560 |
number and device number as parameters. Go ahead and replace the
|
|
561 |
``EnablePcap`` calls with the calls below.
|
|
562 |
|
|
563 |
::
|
|
564 |
|
|
565 |
pointToPoint.EnablePcap ("second", p2pNodes.Get (0)->GetId (), 0);
|
|
566 |
csma.EnablePcap ("second", csmaNodes.Get (nCsma)->GetId (), 0, false);
|
|
567 |
csma.EnablePcap ("second", csmaNodes.Get (nCsma-1)->GetId (), 0, false);
|
|
568 |
|
|
569 |
We know that we want to create a pcap file with the base name "second" and
|
|
570 |
we also know that the device of interest in both cases is going to be zero,
|
|
571 |
so those parameters are not really interesting.
|
|
572 |
|
|
573 |
In order to get the node number, you have two choices: first, nodes are
|
|
574 |
numbered in a monotonically increasing fashion starting from zero in the
|
|
575 |
order in which you created them. One way to get a node number is to figure
|
|
576 |
this number out "manually" by contemplating the order of node creation.
|
|
577 |
If you take a look at the network topology illustration at the beginning of
|
|
578 |
the file, we did this for you and you can see that the last CSMA node is
|
|
579 |
going to be node number ``nCsma + 1``. This approach can become
|
|
580 |
annoyingly difficult in larger simulations.
|
|
581 |
|
|
582 |
An alternate way, which we use here, is to realize that the
|
|
583 |
``NodeContainers`` contain pointers to |ns3| ``Node`` Objects.
|
|
584 |
The ``Node`` Object has a method called ``GetId`` which will return that
|
|
585 |
node's ID, which is the node number we seek. Let's go take a look at the
|
|
586 |
Doxygen for the ``Node`` and locate that method, which is further down in
|
|
587 |
the |ns3| core code than we've seen so far; but sometimes you have to
|
|
588 |
search diligently for useful things.
|
|
589 |
|
|
590 |
Go to the Doxygen documentation for your release (recall that you can find it
|
|
591 |
on the project web site). You can get to the ``Node`` documentation by
|
|
592 |
looking through at the "Classes" tab and scrolling down the "Class List"
|
|
593 |
until you find ``ns3::Node``. Select ``ns3::Node`` and you will be taken
|
|
594 |
to the documentation for the ``Node`` class. If you now scroll down to the
|
|
595 |
``GetId`` method and select it, you will be taken to the detailed
|
|
596 |
documentation for the method. Using the ``GetId`` method can make
|
|
597 |
determining node numbers much easier in complex topologies.
|
|
598 |
|
|
599 |
Let's clear the old trace files out of the top-level directory to avoid confusion
|
|
600 |
about what is going on,
|
|
601 |
|
|
602 |
::
|
|
603 |
|
|
604 |
rm *.pcap
|
|
605 |
rm *.tr
|
|
606 |
|
|
607 |
If you build the new script and run the simulation setting ``nCsma`` to 100,
|
|
608 |
|
|
609 |
::
|
|
610 |
|
|
611 |
./waf --run "scratch/mysecond --nCsma=100"
|
|
612 |
|
|
613 |
you will see the following output:
|
|
614 |
|
|
615 |
::
|
|
616 |
|
|
617 |
Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
|
|
618 |
Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
|
|
619 |
'build' finished successfully (0.407s)
|
|
620 |
Sent 1024 bytes to 10.1.2.101
|
|
621 |
Received 1024 bytes from 10.1.1.1
|
|
622 |
Received 1024 bytes from 10.1.2.101
|
|
623 |
|
|
624 |
Note that the echo server is now located at 10.1.2.101 which corresponds to
|
|
625 |
having 100 "extra" CSMA nodes with the echo server on the last one. If you
|
|
626 |
list the pcap files in the top level directory you will see,
|
|
627 |
|
|
628 |
::
|
|
629 |
|
|
630 |
second-0-0.pcap second-100-0.pcap second-101-0.pcap
|
|
631 |
|
|
632 |
The trace file ``second-0-0.pcap`` is the "leftmost" point-to-point device
|
|
633 |
which is the echo packet source. The file ``second-101-0.pcap`` corresponds
|
|
634 |
to the rightmost CSMA device which is where the echo server resides. You may
|
|
635 |
have noticed that the final parameter on the call to enable pcap tracing on the
|
|
636 |
echo server node was false. This means that the trace gathered on that node
|
|
637 |
was in non-promiscuous mode.
|
|
638 |
|
|
639 |
To illustrate the difference between promiscuous and non-promiscuous traces, we
|
|
640 |
also requested a non-promiscuous trace for the next-to-last node. Go ahead and
|
|
641 |
take a look at the ``tcpdump`` for ``second-100-0.pcap``.
|
|
642 |
|
|
643 |
::
|
|
644 |
|
|
645 |
tcpdump -nn -tt -r second-100-0.pcap
|
|
646 |
|
|
647 |
You can now see that node 100 is really a bystander in the echo exchange. The
|
|
648 |
only packets that it receives are the ARP requests which are broadcast to the
|
|
649 |
entire CSMA network.
|
|
650 |
|
|
651 |
::
|
|
652 |
|
|
653 |
reading from file second-100-0.pcap, link-type EN10MB (Ethernet)
|
|
654 |
2.003696 arp who-has 10.1.2.101 (ff:ff:ff:ff:ff:ff) tell 10.1.2.1
|
|
655 |
2.003811 arp who-has 10.1.2.1 (ff:ff:ff:ff:ff:ff) tell 10.1.2.101
|
|
656 |
|
|
657 |
Now take a look at the ``tcpdump`` for ``second-101-0.pcap``.
|
|
658 |
|
|
659 |
::
|
|
660 |
|
|
661 |
tcpdump -nn -tt -r second-101-0.pcap
|
|
662 |
|
|
663 |
You can now see that node 101 is really the participant in the echo exchange.
|
|
664 |
|
|
665 |
::
|
|
666 |
|
|
667 |
reading from file second-101-0.pcap, link-type EN10MB (Ethernet)
|
|
668 |
2.003696 arp who-has 10.1.2.101 (ff:ff:ff:ff:ff:ff) tell 10.1.2.1
|
|
669 |
2.003696 arp reply 10.1.2.101 is-at 00:00:00:00:00:67
|
|
670 |
2.003801 IP 10.1.1.1.49153 > 10.1.2.101.9: UDP, length 1024
|
|
671 |
2.003801 arp who-has 10.1.2.1 (ff:ff:ff:ff:ff:ff) tell 10.1.2.101
|
|
672 |
2.003822 arp reply 10.1.2.1 is-at 00:00:00:00:00:03
|
|
673 |
2.003822 IP 10.1.2.101.9 > 10.1.1.1.49153: UDP, length 1024
|
|
674 |
|
|
675 |
Models, Attributes and Reality
|
|
676 |
******************************
|
|
677 |
|
|
678 |
This is a convenient place to make a small excursion and make an important
|
|
679 |
point. It may or may not be obvious to you, but whenever one is using a
|
|
680 |
simulation, it is important to understand exactly what is being modeled and
|
|
681 |
what is not. It is tempting, for example, to think of the CSMA devices
|
|
682 |
and channels used in the previous section as if they were real Ethernet
|
|
683 |
devices; and to expect a simulation result to directly reflect what will
|
|
684 |
happen in a real Ethernet. This is not the case.
|
|
685 |
|
|
686 |
A model is, by definition, an abstraction of reality. It is ultimately the
|
|
687 |
responsibility of the simulation script author to determine the so-called
|
|
688 |
"range of accuracy" and "domain of applicability" of the simulation as
|
|
689 |
a whole, and therefore its constituent parts.
|
|
690 |
|
|
691 |
In some cases, like ``Csma``, it can be fairly easy to determine what is
|
|
692 |
*not* modeled. By reading the model description (``csma.h``) you
|
|
693 |
can find that there is no collision detection in the CSMA model and decide
|
|
694 |
on how applicable its use will be in your simulation or what caveats you
|
|
695 |
may want to include with your results. In other cases, it can be quite easy
|
|
696 |
to configure behaviors that might not agree with any reality you can go out
|
|
697 |
and buy. It will prove worthwhile to spend some time investigating a few
|
|
698 |
such instances, and how easily you can swerve outside the bounds of reality
|
|
699 |
in your simulations.
|
|
700 |
|
|
701 |
As you have seen, |ns3| provides ``Attributes`` which a user
|
|
702 |
can easily set to change model behavior. Consider two of the ``Attributes``
|
|
703 |
of the ``CsmaNetDevice``: ``Mtu`` and ``EncapsulationMode``.
|
|
704 |
The ``Mtu`` attribute indicates the Maximum Transmission Unit to the
|
|
705 |
device. This is the size of the largest Protocol Data Unit (PDU) that the
|
|
706 |
device can send.
|
|
707 |
|
|
708 |
The MTU defaults to 1500 bytes in the ``CsmaNetDevice``. This default
|
|
709 |
corresponds to a number found in RFC 894, "A Standard for the Transmission
|
|
710 |
of IP Datagrams over Ethernet Networks." The number is actually derived
|
|
711 |
from the maximum packet size for 10Base5 (full-spec Ethernet) networks --
|
|
712 |
1518 bytes. If you subtract the DIX encapsulation overhead for Ethernet
|
|
713 |
packets (18 bytes) you will end up with a maximum possible data size (MTU)
|
|
714 |
of 1500 bytes. One can also find that the ``MTU`` for IEEE 802.3 networks
|
|
715 |
is 1492 bytes. This is because LLC/SNAP encapsulation adds an extra eight
|
|
716 |
bytes of overhead to the packet. In both cases, the underlying hardware can
|
|
717 |
only send 1518 bytes, but the data size is different.
|
|
718 |
|
|
719 |
In order to set the encapsulation mode, the ``CsmaNetDevice`` provides
|
|
720 |
an ``Attribute`` called ``EncapsulationMode`` which can take on the
|
|
721 |
values ``Dix`` or ``Llc``. These correspond to Ethernet and LLC/SNAP
|
|
722 |
framing respectively.
|
|
723 |
|
|
724 |
If one leaves the ``Mtu`` at 1500 bytes and changes the encapsulation mode
|
|
725 |
to ``Llc``, the result will be a network that encapsulates 1500 byte PDUs
|
|
726 |
with LLC/SNAP framing resulting in packets of 1526 bytes, which would be
|
|
727 |
illegal in many networks, since they can transmit a maximum of 1518 bytes per
|
|
728 |
packet. This would most likely result in a simulation that quite subtly does
|
|
729 |
not reflect the reality you might be expecting.
|
|
730 |
|
|
731 |
Just to complicate the picture, there exist jumbo frames (1500 < MTU <= 9000 bytes)
|
|
732 |
and super-jumbo (MTU > 9000 bytes) frames that are not officially sanctioned
|
|
733 |
by IEEE but are available in some high-speed (Gigabit) networks and NICs. One
|
|
734 |
could leave the encapsulation mode set to ``Dix``, and set the ``Mtu``
|
|
735 |
``Attribute`` on a ``CsmaNetDevice`` to 64000 bytes -- even though an
|
|
736 |
associated ``CsmaChannel DataRate`` was set at 10 megabits per second.
|
|
737 |
This would essentially model an Ethernet switch made out of vampire-tapped
|
|
738 |
1980s-style 10Base5 networks that support super-jumbo datagrams. This is
|
|
739 |
certainly not something that was ever made, nor is likely to ever be made,
|
|
740 |
but it is quite easy for you to configure.
|
|
741 |
|
|
742 |
In the previous example, you used the command line to create a simulation that
|
|
743 |
had 100 ``Csma`` nodes. You could have just as easily created a simulation
|
|
744 |
with 500 nodes. If you were actually modeling that 10Base5 vampire-tap network,
|
|
745 |
the maximum length of a full-spec Ethernet cable is 500 meters, with a minimum
|
|
746 |
tap spacing of 2.5 meters. That means there could only be 200 taps on a
|
|
747 |
real network. You could have quite easily built an illegal network in that
|
|
748 |
way as well. This may or may not result in a meaningful simulation depending
|
|
749 |
on what you are trying to model.
|
|
750 |
|
|
751 |
Similar situations can occur in many places in |ns3| and in any
|
|
752 |
simulator. For example, you may be able to position nodes in such a way that
|
|
753 |
they occupy the same space at the same time, or you may be able to configure
|
|
754 |
amplifiers or noise levels that violate the basic laws of physics.
|
|
755 |
|
|
756 |
|ns3| generally favors flexibility, and many models will allow freely
|
|
757 |
setting ``Attributes`` without trying to enforce any arbitrary consistency
|
|
758 |
or particular underlying spec.
|
|
759 |
|
|
760 |
The thing to take home from this is that |ns3| is going to provide a
|
|
761 |
super-flexible base for you to experiment with. It is up to you to understand
|
|
762 |
what you are asking the system to do and to make sure that the simulations you
|
|
763 |
create have some meaning and some connection with a reality defined by you.
|
|
764 |
|
|
765 |
Building a Wireless Network Topology
|
|
766 |
************************************
|
|
767 |
|
|
768 |
In this section we are going to further expand our knowledge of |ns3|
|
|
769 |
network devices and channels to cover an example of a wireless network.
|
|
770 |
|ns3| provides a set of 802.11 models that attempt to provide an
|
|
771 |
accurate MAC-level implementation of the 802.11 specification and a
|
|
772 |
"not-so-slow" PHY-level model of the 802.11a specification.
|
|
773 |
|
|
774 |
Just as we have seen both point-to-point and CSMA topology helper objects when
|
|
775 |
constructing point-to-point topologies, we will see equivalent ``Wifi``
|
|
776 |
topology helpers in this section. The appearance and operation of these
|
|
777 |
helpers should look quite familiar to you.
|
|
778 |
|
|
779 |
We provide an example script in our ``examples/tutorial`` directory. This script
|
|
780 |
builds on the ``second.cc`` script and adds a Wifi network. Go ahead and
|
|
781 |
open ``examples/tutorial/third.cc`` in your favorite editor. You will have already
|
|
782 |
seen enough |ns3| code to understand most of what is going on in
|
|
783 |
this example, but there are a few new things, so we will go over the entire
|
|
784 |
script and examine some of the output.
|
|
785 |
|
|
786 |
Just as in the ``second.cc`` example (and in all |ns3| examples)
|
|
787 |
the file begins with an emacs mode line and some GPL boilerplate.
|
|
788 |
|
|
789 |
Take a look at the ASCII art (reproduced below) that shows the default network
|
|
790 |
topology constructed in the example. You can see that we are going to
|
|
791 |
further extend our example by hanging a wireless network off of the left side.
|
|
792 |
Notice that this is a default network topology since you can actually vary the
|
|
793 |
number of nodes created on the wired and wireless networks. Just as in the
|
|
794 |
``second.cc`` script case, if you change ``nCsma``, it will give you a
|
|
795 |
number of "extra" CSMA nodes. Similarly, you can set ``nWifi`` to
|
|
796 |
control how many ``STA`` (station) nodes are created in the simulation.
|
|
797 |
There will always be one ``AP`` (access point) node on the wireless
|
|
798 |
network. By default there are three "extra" CSMA nodes and three wireless
|
|
799 |
``STA`` nodes.
|
|
800 |
|
|
801 |
The code begins by loading module include files just as was done in the
|
|
802 |
``second.cc`` example. There are a couple of new includes corresponding
|
|
803 |
to the Wifi module and the mobility module which we will discuss below.
|
|
804 |
|
|
805 |
::
|
|
806 |
|
|
807 |
#include "ns3/core-module.h"
|
|
808 |
#include "ns3/simulator-module.h"
|
|
809 |
#include "ns3/node-module.h"
|
|
810 |
#include "ns3/helper-module.h"
|
|
811 |
#include "ns3/wifi-module.h"
|
|
812 |
#include "ns3/mobility-module.h"
|
|
813 |
|
|
814 |
The network topology illustration follows:
|
|
815 |
|
|
816 |
::
|
|
817 |
|
|
818 |
// Default Network Topology
|
|
819 |
//
|
|
820 |
// Wifi 10.1.3.0
|
|
821 |
// AP
|
|
822 |
// * * * *
|
|
823 |
// | | | | 10.1.1.0
|
|
824 |
// n5 n6 n7 n0 -------------- n1 n2 n3 n4
|
|
825 |
// point-to-point | | | |
|
|
826 |
// ================
|
|
827 |
// LAN 10.1.2.0
|
|
828 |
|
|
829 |
You can see that we are adding a new network device to the node on the left
|
|
830 |
side of the point-to-point link that becomes the access point for the wireless
|
|
831 |
network. A number of wireless STA nodes are created to fill out the new
|
|
832 |
10.1.3.0 network as shown on the left side of the illustration.
|
|
833 |
|
|
834 |
After the illustration, the ``ns-3`` namespace is ``used`` and a logging
|
|
835 |
component is defined. This should all be quite familiar by now.
|
|
836 |
|
|
837 |
::
|
|
838 |
|
|
839 |
using namespace ns3;
|
|
840 |
|
|
841 |
NS_LOG_COMPONENT_DEFINE ("ThirdScriptExample");
|
|
842 |
|
|
843 |
The main program begins just like ``second.cc`` by adding some command line
|
|
844 |
parameters for enabling or disabling logging components and for changing the
|
|
845 |
number of devices created.
|
|
846 |
|
|
847 |
::
|
|
848 |
|
|
849 |
bool verbose = true;
|
|
850 |
uint32_t nCsma = 3;
|
|
851 |
uint32_t nWifi = 3;
|
|
852 |
|
|
853 |
CommandLine cmd;
|
|
854 |
cmd.AddValue ("nCsma", "Number of \"extra\" CSMA nodes/devices", nCsma);
|
|
855 |
cmd.AddValue ("nWifi", "Number of wifi STA devices", nWifi);
|
|
856 |
cmd.AddValue ("verbose", "Tell echo applications to log if true", verbose);
|
|
857 |
|
|
858 |
cmd.Parse (argc,argv);
|
|
859 |
|
|
860 |
if (verbose)
|
|
861 |
{
|
|
862 |
LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_INFO);
|
|
863 |
LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_INFO);
|
|
864 |
}
|
|
865 |
|
|
866 |
Just as in all of the previous examples, the next step is to create two nodes
|
|
867 |
that we will connect via the point-to-point link.
|
|
868 |
|
|
869 |
::
|
|
870 |
|
|
871 |
NodeContainer p2pNodes;
|
|
872 |
p2pNodes.Create (2);
|
|
873 |
|
|
874 |
Next, we see an old friend. We instantiate a ``PointToPointHelper`` and
|
|
875 |
set the associated default ``Attributes`` so that we create a five megabit
|
|
876 |
per second transmitter on devices created using the helper and a two millisecond
|
|
877 |
delay on channels created by the helper. We then ``Intall`` the devices
|
|
878 |
on the nodes and the channel between them.
|
|
879 |
|
|
880 |
::
|
|
881 |
|
|
882 |
PointToPointHelper pointToPoint;
|
|
883 |
pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
|
|
884 |
pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
|
|
885 |
|
|
886 |
NetDeviceContainer p2pDevices;
|
|
887 |
p2pDevices = pointToPoint.Install (p2pNodes);
|
|
888 |
|
|
889 |
Next, we declare another ``NodeContainer`` to hold the nodes that will be
|
|
890 |
part of the bus (CSMA) network.
|
|
891 |
|
|
892 |
::
|
|
893 |
|
|
894 |
NodeContainer csmaNodes;
|
|
895 |
csmaNodes.Add (p2pNodes.Get (1));
|
|
896 |
csmaNodes.Create (nCsma);
|
|
897 |
|
|
898 |
The next line of code ``Gets`` the first node (as in having an index of one)
|
|
899 |
from the point-to-point node container and adds it to the container of nodes
|
|
900 |
that will get CSMA devices. The node in question is going to end up with a
|
|
901 |
point-to-point device and a CSMA device. We then create a number of "extra"
|
|
902 |
nodes that compose the remainder of the CSMA network.
|
|
903 |
|
|
904 |
We then instantiate a ``CsmaHelper`` and set its ``Attributes`` as we did
|
|
905 |
in the previous example. We create a ``NetDeviceContainer`` to keep track of
|
|
906 |
the created CSMA net devices and then we ``Install`` CSMA devices on the
|
|
907 |
selected nodes.
|
|
908 |
|
|
909 |
::
|
|
910 |
|
|
911 |
CsmaHelper csma;
|
|
912 |
csma.SetChannelAttribute ("DataRate", StringValue ("100Mbps"));
|
|
913 |
csma.SetChannelAttribute ("Delay", TimeValue (NanoSeconds (6560)));
|
|
914 |
|
|
915 |
NetDeviceContainer csmaDevices;
|
|
916 |
csmaDevices = csma.Install (csmaNodes);
|
|
917 |
|
|
918 |
Next, we are going to create the nodes that will be part of the Wifi network.
|
|
919 |
We are going to create a number of "station" nodes as specified by the
|
|
920 |
command line argument, and we are going to use the "leftmost" node of the
|
|
921 |
point-to-point link as the node for the access point.
|
|
922 |
|
|
923 |
::
|
|
924 |
|
|
925 |
NodeContainer wifiStaNodes;
|
|
926 |
wifiStaNodes.Create (nWifi);
|
|
927 |
NodeContainer wifiApNode = p2pNodes.Get (0);
|
|
928 |
|
|
929 |
The next bit of code constructs the wifi devices and the interconnection
|
|
930 |
channel between these wifi nodes. First, we configure the PHY and channel
|
|
931 |
helpers:
|
|
932 |
|
|
933 |
::
|
|
934 |
|
|
935 |
YansWifiChannelHelper channel = YansWifiChannelHelper::Default ();
|
|
936 |
YansWifiPhyHelper phy = YansWifiPhyHelper::Default ();
|
|
937 |
|
|
938 |
For simplicity, this code uses the default PHY layer configuration and
|
|
939 |
channel models which are documented in the API doxygen documentation for
|
|
940 |
the ``YansWifiChannelHelper::Default`` and ``YansWifiPhyHelper::Default``
|
|
941 |
methods. Once these objects are created, we create a channel object
|
|
942 |
and associate it to our PHY layer object manager to make sure
|
|
943 |
that all the PHY layer objects created by the ``YansWifiPhyHelper``
|
|
944 |
share the same underlying channel, that is, they share the same
|
|
945 |
wireless medium and can communication and interfere:
|
|
946 |
|
|
947 |
::
|
|
948 |
|
|
949 |
phy.SetChannel (channel.Create ());
|
|
950 |
|
|
951 |
Once the PHY helper is configured, we can focus on the MAC layer. Here we choose to
|
|
952 |
work with non-Qos MACs so we use a NqosWifiMacHelper object to set MAC parameters.
|
|
953 |
|
|
954 |
::
|
|
955 |
|
|
956 |
WifiHelper wifi = WifiHelper::Default ();
|
|
957 |
wifi.SetRemoteStationManager ("ns3::AarfWifiManager");
|
|
958 |
|
|
959 |
NqosWifiMacHelper mac = NqosWifiMacHelper::Default ();
|
|
960 |
|
|
961 |
The ``SetRemoteStationManager`` method tells the helper the type of
|
|
962 |
rate control algorithm to use. Here, it is asking the helper to use the AARF
|
|
963 |
algorithm --- details are, of course, available in Doxygen.
|
|
964 |
|
|
965 |
Next, we configure the type of MAC, the SSID of the infrastructure network we
|
|
966 |
want to setup and make sure that our stations don't perform active probing:
|
|
967 |
|
|
968 |
::
|
|
969 |
|
|
970 |
Ssid ssid = Ssid ("ns-3-ssid");
|
|
971 |
mac.SetType ("ns3::StaWifiMac",
|
|
972 |
"Ssid", SsidValue (ssid),
|
|
973 |
"ActiveProbing", BooleanValue (false));
|
|
974 |
|
|
975 |
This code first creates an 802.11 service set identifier (SSID) object
|
|
976 |
that will be used to set the value of the "Ssid" ``Attribute`` of
|
|
977 |
the MAC layer implementation. The particular kind of MAC layer that
|
|
978 |
will be created by the helper is specified by ``Attribute`` as
|
|
979 |
being of the "ns3::StaWifiMac" type. The use of
|
|
980 |
``NqosWifiMacHelper`` will ensure that the "QosSupported"
|
|
981 |
``Attribute`` for created MAC objects is set false. The combination
|
|
982 |
of these two configurations means that the MAC instance next created
|
|
983 |
will be a non-QoS non-AP station (STA) in an infrastructure BSS (i.e.,
|
|
984 |
a BSS with an AP). Finally, the "ActiveProbing" ``Attribute`` is
|
|
985 |
set to false. This means that probe requests will not be sent by MACs
|
|
986 |
created by this helper.
|
|
987 |
|
|
988 |
Once all the station-specific parameters are fully configured, both at the
|
|
989 |
MAC and PHY layers, we can invoke our now-familiar ``Install`` method to
|
|
990 |
create the wifi devices of these stations:
|
|
991 |
|
|
992 |
::
|
|
993 |
|
|
994 |
NetDeviceContainer staDevices;
|
|
995 |
staDevices = wifi.Install (phy, mac, wifiStaNodes);
|
|
996 |
|
|
997 |
We have configured Wifi for all of our STA nodes, and now we need to
|
|
998 |
configure the AP (access point) node. We begin this process by changing
|
|
999 |
the default ``Attributes`` of the ``NqosWifiMacHelper`` to reflect the
|
|
1000 |
requirements of the AP.
|
|
1001 |
|
|
1002 |
::
|
|
1003 |
|
|
1004 |
mac.SetType ("ns3::ApWifiMac",
|
|
1005 |
"Ssid", SsidValue (ssid),
|
|
1006 |
"BeaconGeneration", BooleanValue (true),
|
|
1007 |
"BeaconInterval", TimeValue (Seconds (2.5)));
|
|
1008 |
|
|
1009 |
In this case, the ``NqosWifiMacHelper`` is going to create MAC
|
|
1010 |
layers of the "ns3::ApWifiMac", the latter specifying that a MAC
|
|
1011 |
instance configured as an AP should be created, with the helper type
|
|
1012 |
implying that the "QosSupported" ``Attribute`` should be set to
|
|
1013 |
false - disabling 802.11e/WMM-style QoS support at created APs. We
|
|
1014 |
set the "BeaconGeneration" ``Attribute`` to true and also set an
|
|
1015 |
interval between beacons of 2.5 seconds.
|
|
1016 |
|
|
1017 |
The next lines create the single AP which shares the same set of PHY-level
|
|
1018 |
``Attributes`` (and channel) as the stations:
|
|
1019 |
|
|
1020 |
::
|
|
1021 |
|
|
1022 |
NetDeviceContainer apDevices;
|
|
1023 |
apDevices = wifi.Install (phy, mac, wifiApNode);
|
|
1024 |
|
|
1025 |
Now, we are going to add mobility models. We want the STA nodes to be mobile,
|
|
1026 |
wandering around inside a bounding box, and we want to make the AP node
|
|
1027 |
stationary. We use the ``MobilityHelper`` to make this easy for us.
|
|
1028 |
First, we instantiate a ``MobilityHelper`` object and set some
|
|
1029 |
``Attributes`` controlling the "position allocator" functionality.
|
|
1030 |
|
|
1031 |
::
|
|
1032 |
|
|
1033 |
MobilityHelper mobility;
|
|
1034 |
|
|
1035 |
mobility.SetPositionAllocator ("ns3::GridPositionAllocator",
|
|
1036 |
"MinX", DoubleValue (0.0),
|
|
1037 |
"MinY", DoubleValue (0.0),
|
|
1038 |
"DeltaX", DoubleValue (5.0),
|
|
1039 |
"DeltaY", DoubleValue (10.0),
|
|
1040 |
"GridWidth", UintegerValue (3),
|
|
1041 |
"LayoutType", StringValue ("RowFirst"));
|
|
1042 |
|
|
1043 |
This code tells the mobility helper to use a two-dimensional grid to initially
|
|
1044 |
place the STA nodes. Feel free to explore the Doxygen for class
|
|
1045 |
``ns3::GridPositionAllocator`` to see exactly what is being done.
|
|
1046 |
|
|
1047 |
We have arranged our nodes on an initial grid, but now we need to tell them
|
|
1048 |
how to move. We choose the ``RandomWalk2dMobilityModel`` which has the
|
|
1049 |
nodes move in a random direction at a random speed around inside a bounding
|
|
1050 |
box.
|
|
1051 |
|
|
1052 |
::
|
|
1053 |
|
|
1054 |
mobility.SetMobilityModel ("ns3::RandomWalk2dMobilityModel",
|
|
1055 |
"Bounds", RectangleValue (Rectangle (-50, 50, -50, 50)));
|
|
1056 |
|
|
1057 |
We now tell the ``MobilityHelper`` to install the mobility models on the
|
|
1058 |
STA nodes.
|
|
1059 |
|
|
1060 |
::
|
|
1061 |
|
|
1062 |
mobility.Install (wifiStaNodes);
|
|
1063 |
|
|
1064 |
We want the access point to remain in a fixed position during the simulation.
|
|
1065 |
We accomplish this by setting the mobility model for this node to be the
|
|
1066 |
``ns3::ConstantPositionMobilityModel``:
|
|
1067 |
|
|
1068 |
::
|
|
1069 |
|
|
1070 |
mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
|
|
1071 |
mobility.Install (wifiApNode);
|
|
1072 |
|
|
1073 |
We now have our nodes, devices and channels created, and mobility models
|
|
1074 |
chosen for the Wifi nodes, but we have no protocol stacks present. Just as
|
|
1075 |
we have done previously many times, we will use the ``InternetStackHelper``
|
|
1076 |
to install these stacks.
|
|
1077 |
|
|
1078 |
::
|
|
1079 |
|
|
1080 |
InternetStackHelper stack;
|
|
1081 |
stack.Install (csmaNodes);
|
|
1082 |
stack.Install (wifiApNode);
|
|
1083 |
stack.Install (wifiStaNodes);
|
|
1084 |
|
|
1085 |
Just as in the ``second.cc`` example script, we are going to use the
|
|
1086 |
``Ipv4AddressHelper`` to assign IP addresses to our device interfaces.
|
|
1087 |
First we use the network 10.1.1.0 to create the two addresses needed for our
|
|
1088 |
two point-to-point devices. Then we use network 10.1.2.0 to assign addresses
|
|
1089 |
to the CSMA network and then we assign addresses from network 10.1.3.0 to
|
|
1090 |
both the STA devices and the AP on the wireless network.
|
|
1091 |
|
|
1092 |
::
|
|
1093 |
|
|
1094 |
Ipv4AddressHelper address;
|
|
1095 |
|
|
1096 |
address.SetBase ("10.1.1.0", "255.255.255.0");
|
|
1097 |
Ipv4InterfaceContainer p2pInterfaces;
|
|
1098 |
p2pInterfaces = address.Assign (p2pDevices);
|
|
1099 |
|
|
1100 |
address.SetBase ("10.1.2.0", "255.255.255.0");
|
|
1101 |
Ipv4InterfaceContainer csmaInterfaces;
|
|
1102 |
csmaInterfaces = address.Assign (csmaDevices);
|
|
1103 |
|
|
1104 |
address.SetBase ("10.1.3.0", "255.255.255.0");
|
|
1105 |
address.Assign (staDevices);
|
|
1106 |
address.Assign (apDevices);
|
|
1107 |
|
|
1108 |
We put the echo server on the "rightmost" node in the illustration at the
|
|
1109 |
start of the file. We have done this before.
|
|
1110 |
|
|
1111 |
::
|
|
1112 |
|
|
1113 |
UdpEchoServerHelper echoServer (9);
|
|
1114 |
|
|
1115 |
ApplicationContainer serverApps = echoServer.Install (csmaNodes.Get (nCsma));
|
|
1116 |
serverApps.Start (Seconds (1.0));
|
|
1117 |
serverApps.Stop (Seconds (10.0));
|
|
1118 |
|
|
1119 |
And we put the echo client on the last STA node we created, pointing it to
|
|
1120 |
the server on the CSMA network. We have also seen similar operations before.
|
|
1121 |
|
|
1122 |
::
|
|
1123 |
|
|
1124 |
UdpEchoClientHelper echoClient (csmaInterfaces.GetAddress (nCsma), 9);
|
|
1125 |
echoClient.SetAttribute ("MaxPackets", UintegerValue (1));
|
|
1126 |
echoClient.SetAttribute ("Interval", TimeValue (Seconds (1.)));
|
|
1127 |
echoClient.SetAttribute ("PacketSize", UintegerValue (1024));
|
|
1128 |
|
|
1129 |
ApplicationContainer clientApps =
|
|
1130 |
echoClient.Install (wifiStaNodes.Get (nWifi - 1));
|
|
1131 |
clientApps.Start (Seconds (2.0));
|
|
1132 |
clientApps.Stop (Seconds (10.0));
|
|
1133 |
|
|
1134 |
Since we have built an internetwork here, we need to enable internetwork routing
|
|
1135 |
just as we did in the ``second.cc`` example script.
|
|
1136 |
|
|
1137 |
::
|
|
1138 |
|
|
1139 |
Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
|
|
1140 |
|
|
1141 |
One thing that can surprise some users is the fact that the simulation we just
|
|
1142 |
created will never "naturally" stop. This is because we asked the wireless
|
|
1143 |
access point to generate beacons. It will generate beacons forever, and this
|
|
1144 |
will result in simulator events being scheduled into the future indefinitely,
|
|
1145 |
so we must tell the simulator to stop even though it may have beacon generation
|
|
1146 |
events scheduled. The following line of code tells the simulator to stop so that
|
|
1147 |
we don't simulate beacons forever and enter what is essentially an endless
|
|
1148 |
loop.
|
|
1149 |
|
|
1150 |
::
|
|
1151 |
|
|
1152 |
Simulator::Stop (Seconds (10.0));
|
|
1153 |
|
|
1154 |
We create just enough tracing to cover all three networks:
|
|
1155 |
|
|
1156 |
::
|
|
1157 |
|
|
1158 |
pointToPoint.EnablePcapAll ("third");
|
|
1159 |
phy.EnablePcap ("third", apDevices.Get (0));
|
|
1160 |
csma.EnablePcap ("third", csmaDevices.Get (0), true);
|
|
1161 |
|
|
1162 |
These three lines of code will start pcap tracing on both of the point-to-point
|
|
1163 |
nodes that serves as our backbone, will start a promiscuous (monitor) mode
|
|
1164 |
trace on the Wifi network, and will start a promiscuous trace on the CSMA
|
|
1165 |
network. This will let us see all of the traffic with a minimum number of
|
|
1166 |
trace files.
|
|
1167 |
|
|
1168 |
Finally, we actually run the simulation, clean up and then exit the program.
|
|
1169 |
|
|
1170 |
::
|
|
1171 |
|
|
1172 |
Simulator::Run ();
|
|
1173 |
Simulator::Destroy ();
|
|
1174 |
return 0;
|
|
1175 |
}
|
|
1176 |
|
|
1177 |
In order to run this example, you have to copy the ``third.cc`` example
|
|
1178 |
script into the scratch directory and use Waf to build just as you did with
|
|
1179 |
the ``second.cc`` example. If you are in the top-level directory of the
|
|
1180 |
repository you would type,
|
|
1181 |
|
|
1182 |
::
|
|
1183 |
|
|
1184 |
cp examples/third.cc scratch/mythird.cc
|
|
1185 |
./waf
|
|
1186 |
./waf --run scratch/mythird
|
|
1187 |
|
|
1188 |
Again, since we have set up the UDP echo applications just as we did in the
|
|
1189 |
``second.cc`` script, you will see similar output.
|
|
1190 |
|
|
1191 |
::
|
|
1192 |
|
|
1193 |
Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
|
|
1194 |
Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
|
|
1195 |
'build' finished successfully (0.407s)
|
|
1196 |
Sent 1024 bytes to 10.1.2.4
|
|
1197 |
Received 1024 bytes from 10.1.3.3
|
|
1198 |
Received 1024 bytes from 10.1.2.4
|
|
1199 |
|
|
1200 |
Recall that the first message, ``Sent 1024 bytes to 10.1.2.4``," is the
|
|
1201 |
UDP echo client sending a packet to the server. In this case, the client
|
|
1202 |
is on the wireless network (10.1.3.0). The second message,
|
|
1203 |
"``Received 1024 bytes from 10.1.3.3``," is from the UDP echo server,
|
|
1204 |
generated when it receives the echo packet. The final message,
|
|
1205 |
"``Received 1024 bytes from 10.1.2.4``," is from the echo client, indicating
|
|
1206 |
that it has received its echo back from the server.
|
|
1207 |
|
|
1208 |
If you now go and look in the top level directory, you will find four trace
|
|
1209 |
files from this simulation, two from node zero and two from node one:
|
|
1210 |
|
|
1211 |
::
|
|
1212 |
|
|
1213 |
third-0-0.pcap third-0-1.pcap third-1-0.pcap third-1-1.pcap
|
|
1214 |
|
|
1215 |
The file "third-0-0.pcap" corresponds to the point-to-point device on node
|
|
1216 |
zero -- the left side of the "backbone". The file "third-1-0.pcap"
|
|
1217 |
corresponds to the point-to-point device on node one -- the right side of the
|
|
1218 |
"backbone". The file "third-0-1.pcap" will be the promiscuous (monitor
|
|
1219 |
mode) trace from the Wifi network and the file "third-1-1.pcap" will be the
|
|
1220 |
promiscuous trace from the CSMA network. Can you verify this by inspecting
|
|
1221 |
the code?
|
|
1222 |
|
|
1223 |
Since the echo client is on the Wifi network, let's start there. Let's take
|
|
1224 |
a look at the promiscuous (monitor mode) trace we captured on that network.
|
|
1225 |
|
|
1226 |
::
|
|
1227 |
|
|
1228 |
tcpdump -nn -tt -r third-0-1.pcap
|
|
1229 |
|
|
1230 |
You should see some wifi-looking contents you haven't seen here before:
|
|
1231 |
|
|
1232 |
::
|
|
1233 |
|
|
1234 |
reading from file third-0-1.pcap, link-type IEEE802_11 (802.11)
|
|
1235 |
0.000025 Beacon () [6.0* 9.0 12.0 18.0 24.0 36.0 48.0 54.0 Mbit] IBSS
|
|
1236 |
0.000263 Assoc Request () [6.0 9.0 12.0 18.0 24.0 36.0 48.0 54.0 Mbit]
|
|
1237 |
0.000279 Acknowledgment RA:00:00:00:00:00:07
|
|
1238 |
0.000357 Assoc Response AID(0) :: Succesful
|
|
1239 |
0.000501 Acknowledgment RA:00:00:00:00:00:0a
|
|
1240 |
0.000748 Assoc Request () [6.0 9.0 12.0 18.0 24.0 36.0 48.0 54.0 Mbit]
|
|
1241 |
0.000764 Acknowledgment RA:00:00:00:00:00:08
|
|
1242 |
0.000842 Assoc Response AID(0) :: Succesful
|
|
1243 |
0.000986 Acknowledgment RA:00:00:00:00:00:0a
|
|
1244 |
0.001242 Assoc Request () [6.0 9.0 12.0 18.0 24.0 36.0 48.0 54.0 Mbit]
|
|
1245 |
0.001258 Acknowledgment RA:00:00:00:00:00:09
|
|
1246 |
0.001336 Assoc Response AID(0) :: Succesful
|
|
1247 |
0.001480 Acknowledgment RA:00:00:00:00:00:0a
|
|
1248 |
2.000112 arp who-has 10.1.3.4 (ff:ff:ff:ff:ff:ff) tell 10.1.3.3
|
|
1249 |
2.000128 Acknowledgment RA:00:00:00:00:00:09
|
|
1250 |
2.000206 arp who-has 10.1.3.4 (ff:ff:ff:ff:ff:ff) tell 10.1.3.3
|
|
1251 |
2.000487 arp reply 10.1.3.4 is-at 00:00:00:00:00:0a
|
|
1252 |
2.000659 Acknowledgment RA:00:00:00:00:00:0a
|
|
1253 |
2.002169 IP 10.1.3.3.49153 > 10.1.2.4.9: UDP, length 1024
|
|
1254 |
2.002185 Acknowledgment RA:00:00:00:00:00:09
|
|
1255 |
2.009771 arp who-has 10.1.3.3 (ff:ff:ff:ff:ff:ff) tell 10.1.3.4
|
|
1256 |
2.010029 arp reply 10.1.3.3 is-at 00:00:00:00:00:09
|
|
1257 |
2.010045 Acknowledgment RA:00:00:00:00:00:09
|
|
1258 |
2.010231 IP 10.1.2.4.9 > 10.1.3.3.49153: UDP, length 1024
|
|
1259 |
2.011767 Acknowledgment RA:00:00:00:00:00:0a
|
|
1260 |
2.500000 Beacon () [6.0* 9.0 12.0 18.0 24.0 36.0 48.0 54.0 Mbit] IBSS
|
|
1261 |
5.000000 Beacon () [6.0* 9.0 12.0 18.0 24.0 36.0 48.0 54.0 Mbit] IBSS
|
|
1262 |
7.500000 Beacon () [6.0* 9.0 12.0 18.0 24.0 36.0 48.0 54.0 Mbit] IBSS
|
|
1263 |
|
|
1264 |
You can see that the link type is now 802.11 as you would expect. You can
|
|
1265 |
probably understand what is going on and find the IP echo request and response
|
|
1266 |
packets in this trace. We leave it as an exercise to completely parse the
|
|
1267 |
trace dump.
|
|
1268 |
|
|
1269 |
Now, look at the pcap file of the right side of the point-to-point link,
|
|
1270 |
|
|
1271 |
::
|
|
1272 |
|
|
1273 |
tcpdump -nn -tt -r third-0-0.pcap
|
|
1274 |
|
|
1275 |
Again, you should see some familiar looking contents:
|
|
1276 |
|
|
1277 |
::
|
|
1278 |
|
|
1279 |
reading from file third-0-0.pcap, link-type PPP (PPP)
|
|
1280 |
2.002169 IP 10.1.3.3.49153 > 10.1.2.4.9: UDP, length 1024
|
|
1281 |
2.009771 IP 10.1.2.4.9 > 10.1.3.3.49153: UDP, length 1024
|
|
1282 |
|
|
1283 |
This is the echo packet going from left to right (from Wifi to CSMA) and back
|
|
1284 |
again across the point-to-point link.
|
|
1285 |
|
|
1286 |
Now, look at the pcap file of the right side of the point-to-point link,
|
|
1287 |
|
|
1288 |
::
|
|
1289 |
|
|
1290 |
tcpdump -nn -tt -r third-1-0.pcap
|
|
1291 |
|
|
1292 |
Again, you should see some familiar looking contents:
|
|
1293 |
|
|
1294 |
::
|
|
1295 |
|
|
1296 |
reading from file third-1-0.pcap, link-type PPP (PPP)
|
|
1297 |
2.005855 IP 10.1.3.3.49153 > 10.1.2.4.9: UDP, length 1024
|
|
1298 |
2.006084 IP 10.1.2.4.9 > 10.1.3.3.49153: UDP, length 1024
|
|
1299 |
|
|
1300 |
This is also the echo packet going from left to right (from Wifi to CSMA) and
|
|
1301 |
back again across the point-to-point link with slightly different timings
|
|
1302 |
as you might expect.
|
|
1303 |
|
|
1304 |
The echo server is on the CSMA network, let's look at the promiscuous trace
|
|
1305 |
there:
|
|
1306 |
|
|
1307 |
::
|
|
1308 |
|
|
1309 |
tcpdump -nn -tt -r third-1-1.pcap
|
|
1310 |
|
|
1311 |
You should see some familiar looking contents:
|
|
1312 |
|
|
1313 |
::
|
|
1314 |
|
|
1315 |
reading from file third-1-1.pcap, link-type EN10MB (Ethernet)
|
|
1316 |
2.005855 arp who-has 10.1.2.4 (ff:ff:ff:ff:ff:ff) tell 10.1.2.1
|
|
1317 |
2.005877 arp reply 10.1.2.4 is-at 00:00:00:00:00:06
|
|
1318 |
2.005877 IP 10.1.3.3.49153 > 10.1.2.4.9: UDP, length 1024
|
|
1319 |
2.005980 arp who-has 10.1.2.1 (ff:ff:ff:ff:ff:ff) tell 10.1.2.4
|
|
1320 |
2.005980 arp reply 10.1.2.1 is-at 00:00:00:00:00:03
|
|
1321 |
2.006084 IP 10.1.2.4.9 > 10.1.3.3.49153: UDP, length 1024
|
|
1322 |
|
|
1323 |
This should be easily understood. If you've forgotten, go back and look at
|
|
1324 |
the discussion in ``second.cc``. This is the same sequence.
|
|
1325 |
|
|
1326 |
Now, we spent a lot of time setting up mobility models for the wireless network
|
|
1327 |
and so it would be a shame to finish up without even showing that the STA
|
|
1328 |
nodes are actually moving around during the simulation. Let's do this by hooking
|
|
1329 |
into the ``MobilityModel`` course change trace source. This is just a sneak
|
|
1330 |
peek into the detailed tracing section which is coming up, but this seems a very
|
|
1331 |
nice place to get an example in.
|
|
1332 |
|
|
1333 |
As mentioned in the "Tweaking ns-3" section, the |ns3| tracing system
|
|
1334 |
is divided into trace sources and trace sinks, and we provide functions to
|
|
1335 |
connect the two. We will use the mobility model predefined course change
|
|
1336 |
trace source to originate the trace events. We will need to write a trace
|
|
1337 |
sink to connect to that source that will display some pretty information for
|
|
1338 |
us. Despite its reputation as being difficult, it's really quite simple.
|
|
1339 |
Just before the main program of the ``scratch/mythird.cc`` script, add the
|
|
1340 |
following function:
|
|
1341 |
|
|
1342 |
::
|
|
1343 |
|
|
1344 |
void
|
|
1345 |
CourseChange (std::string context, Ptr<const MobilityModel> model)
|
|
1346 |
{
|
|
1347 |
Vector position = model->GetPosition ();
|
|
1348 |
NS_LOG_UNCOND (context <<
|
|
1349 |
" x = " << position.x << ", y = " << position.y);
|
|
1350 |
}
|
|
1351 |
|
|
1352 |
This code just pulls the position information from the mobility model and
|
|
1353 |
unconditionally logs the x and y position of the node. We are
|
|
1354 |
going to arrange for this function to be called every time the wireless
|
|
1355 |
node with the echo client changes its position. We do this using the
|
|
1356 |
``Config::Connect`` function. Add the following lines of code to the
|
|
1357 |
script just before the ``Simulator::Run`` call.
|
|
1358 |
|
|
1359 |
::
|
|
1360 |
|
|
1361 |
std::ostringstream oss;
|
|
1362 |
oss <<
|
|
1363 |
"/NodeList/" << wifiStaNodes.Get (nWifi - 1)->GetId () <<
|
|
1364 |
"/$ns3::MobilityModel/CourseChange";
|
|
1365 |
|
|
1366 |
Config::Connect (oss.str (), MakeCallback (&CourseChange));
|
|
1367 |
|
|
1368 |
What we do here is to create a string containing the tracing namespace path
|
|
1369 |
of the event to which we want to connect. First, we have to figure out which
|
|
1370 |
node it is we want using the ``GetId`` method as described earlier. In the
|
|
1371 |
case of the default number of CSMA and wireless nodes, this turns out to be
|
|
1372 |
node seven and the tracing namespace path to the mobility model would look
|
|
1373 |
like,
|
|
1374 |
|
|
1375 |
::
|
|
1376 |
|
|
1377 |
/NodeList/7/$ns3::MobilityModel/CourseChange
|
|
1378 |
|
|
1379 |
Based on the discussion in the tracing section, you may infer that this trace
|
|
1380 |
path references the seventh node in the global NodeList. It specifies
|
|
1381 |
what is called an aggregated object of type ``ns3::MobilityModel``. The
|
|
1382 |
dollar sign prefix implies that the MobilityModel is aggregated to node seven.
|
|
1383 |
The last component of the path means that we are hooking into the
|
|
1384 |
"CourseChange" event of that model.
|
|
1385 |
|
|
1386 |
We make a connection between the trace source in node seven with our trace
|
|
1387 |
sink by calling ``Config::Connect`` and passing this namespace path. Once
|
|
1388 |
this is done, every course change event on node seven will be hooked into our
|
|
1389 |
trace sink, which will in turn print out the new position.
|
|
1390 |
|
|
1391 |
If you now run the simulation, you will see the course changes displayed as
|
|
1392 |
they happen.
|
|
1393 |
|
|
1394 |
::
|
|
1395 |
|
|
1396 |
Build finished successfully (00:00:01)
|
|
1397 |
/NodeList/7/$ns3::MobilityModel/CourseChange x = 10, y = 0
|
|
1398 |
/NodeList/7/$ns3::MobilityModel/CourseChange x = 9.41539, y = -0.811313
|
|
1399 |
/NodeList/7/$ns3::MobilityModel/CourseChange x = 8.46199, y = -1.11303
|
|
1400 |
/NodeList/7/$ns3::MobilityModel/CourseChange x = 7.52738, y = -1.46869
|
|
1401 |
/NodeList/7/$ns3::MobilityModel/CourseChange x = 6.67099, y = -1.98503
|
|
1402 |
/NodeList/7/$ns3::MobilityModel/CourseChange x = 5.6835, y = -2.14268
|
|
1403 |
/NodeList/7/$ns3::MobilityModel/CourseChange x = 4.70932, y = -1.91689
|
|
1404 |
Sent 1024 bytes to 10.1.2.4
|
|
1405 |
Received 1024 bytes from 10.1.3.3
|
|
1406 |
Received 1024 bytes from 10.1.2.4
|
|
1407 |
/NodeList/7/$ns3::MobilityModel/CourseChange x = 5.53175, y = -2.48576
|
|
1408 |
/NodeList/7/$ns3::MobilityModel/CourseChange x = 4.58021, y = -2.17821
|
|
1409 |
/NodeList/7/$ns3::MobilityModel/CourseChange x = 4.18915, y = -1.25785
|
|
1410 |
/NodeList/7/$ns3::MobilityModel/CourseChange x = 4.7572, y = -0.434856
|
|
1411 |
/NodeList/7/$ns3::MobilityModel/CourseChange x = 4.62404, y = 0.556238
|
|
1412 |
/NodeList/7/$ns3::MobilityModel/CourseChange x = 4.74127, y = 1.54934
|
|
1413 |
/NodeList/7/$ns3::MobilityModel/CourseChange x = 5.73934, y = 1.48729
|
|
1414 |
/NodeList/7/$ns3::MobilityModel/CourseChange x = 6.18521, y = 0.59219
|
|
1415 |
/NodeList/7/$ns3::MobilityModel/CourseChange x = 6.58121, y = 1.51044
|
|
1416 |
/NodeList/7/$ns3::MobilityModel/CourseChange x = 7.27897, y = 2.22677
|
|
1417 |
/NodeList/7/$ns3::MobilityModel/CourseChange x = 6.42888, y = 1.70014
|
|
1418 |
/NodeList/7/$ns3::MobilityModel/CourseChange x = 7.40519, y = 1.91654
|
|
1419 |
/NodeList/7/$ns3::MobilityModel/CourseChange x = 6.51981, y = 1.45166
|
|
1420 |
/NodeList/7/$ns3::MobilityModel/CourseChange x = 7.34588, y = 2.01523
|
|
1421 |
/NodeList/7/$ns3::MobilityModel/CourseChange x = 7.81046, y = 2.90077
|
|
1422 |
/NodeList/7/$ns3::MobilityModel/CourseChange x = 6.89186, y = 3.29596
|
|
1423 |
/NodeList/7/$ns3::MobilityModel/CourseChange x = 7.46617, y = 2.47732
|
|
1424 |
/NodeList/7/$ns3::MobilityModel/CourseChange x = 7.05492, y = 1.56579
|
|
1425 |
/NodeList/7/$ns3::MobilityModel/CourseChange x = 8.00393, y = 1.25054
|
|
1426 |
/NodeList/7/$ns3::MobilityModel/CourseChange x = 7.00968, y = 1.35768
|
|
1427 |
/NodeList/7/$ns3::MobilityModel/CourseChange x = 7.33503, y = 2.30328
|
|
1428 |
/NodeList/7/$ns3::MobilityModel/CourseChange x = 7.18682, y = 3.29223
|
|
1429 |
/NodeList/7/$ns3::MobilityModel/CourseChange x = 7.96865, y = 2.66873
|