1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 as
5 * published by the Free Software Foundation;
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 *
16 */
17
18 //
19 // This ns-3 example demonstrates the use of helper functions to ease
20 // the construction of simulation scenarios.
21 //
22 // The simulation topology consists of a mixed wired and wireless
23 // scenario in which a hierarchical mobility model is used.
24 //
25 // The simulation layout consists of N backbone routers interconnected
26 // by an ad hoc wifi network.
27 // Each backbone router also has a local 802.11 network and is connected
28 // to a local LAN. An additional set of (K-1) nodes are connected to
29 // this backbone. Finally, a local LAN is connected to each router
30 // on the backbone, with L-1 additional hosts.
31 //
32 // The nodes are populated with TCP/IP stacks, and OLSR unicast routing
33 // on the backbone. An example UDP transfer is shown. The simulator
34 // be configured to output tcpdumps or traces from different nodes.
35 //
36 //
37 // +--------------------------------------------------------+
38 // | |
39 // | 802.11 ad hoc, ns-2 mobility |
40 // | |
41 // +--------------------------------------------------------+
42 // | o o o (N backbone routers) |
43 // +--------+ +--------+
44 // wired LAN | mobile | wired LAN | mobile |
45 // -----------| router | -----------| router |
46 // --------- ---------
47 // | |
48 // +----------------+ +----------------+
49 // | 802.11 | | 802.11 |
50 // | infra net | | infra net |
51 // | K-1 hosts | | K-1 hosts |
52 // +----------------+ +----------------+
53 //
54 // We'll send data from the first wired LAN node on the first wired LAN
55 // to the last wireless STA on the last infrastructure net, thereby
56 // causing packets to traverse CSMA to adhoc to infrastructure links
57 //
58 // Note that certain mobility patterns may cause packet forwarding
59 // to fail (if nodes become disconnected)
60
61 #include "ns3/command-line.h"
62 #include "ns3/string.h"
63 #include "ns3/yans-wifi-helper.h"
64 #include "ns3/ssid.h"
65 #include "ns3/mobility-helper.h"
66 #include "ns3/internet-stack-helper.h"
67 #include "ns3/ipv4-address-helper.h"
68 #include "ns3/on-off-helper.h"
69 #include "ns3/yans-wifi-channel.h"
70 #include "ns3/qos-txop.h"
71 #include "ns3/packet-sink-helper.h"
72 #include "ns3/olsr-helper.h"
73 #include "ns3/csma-helper.h"
74 #include "ns3/animation-interface.h"
75
76 using namespace ns3;
77
78 //
79 // Define logging keyword for this file
80 //
81 NS_LOG_COMPONENT_DEFINE ("MixedWireless");
82
83 //
84 // This function will be used below as a trace sink, if the command-line
85 // argument or default value "useCourseChangeCallback" is set to true
86 //
87 static void
CourseChangeCallback(std::string path,Ptr<const MobilityModel> model)88 CourseChangeCallback (std::string path, Ptr<const MobilityModel> model)
89 {
90 Vector position = model->GetPosition ();
91 std::cout << "CourseChange " << path << " x=" << position.x << ", y=" << position.y << ", z=" << position.z << std::endl;
92 }
93
94 int
main(int argc,char * argv[])95 main (int argc, char *argv[])
96 {
97 //
98 // First, we declare and initialize a few local variables that control some
99 // simulation parameters.
100 //
101 uint32_t backboneNodes = 10;
102 uint32_t infraNodes = 2;
103 uint32_t lanNodes = 2;
104 uint32_t stopTime = 20;
105 bool useCourseChangeCallback = false;
106
107 //
108 // Simulation defaults are typically set next, before command line
109 // arguments are parsed.
110 //
111 Config::SetDefault ("ns3::OnOffApplication::PacketSize", StringValue ("1472"));
112 Config::SetDefault ("ns3::OnOffApplication::DataRate", StringValue ("100kb/s"));
113
114 //
115 // For convenience, we add the local variables to the command line argument
116 // system so that they can be overridden with flags such as
117 // "--backboneNodes=20"
118 //
119 CommandLine cmd (__FILE__);
120 cmd.AddValue ("backboneNodes", "number of backbone nodes", backboneNodes);
121 cmd.AddValue ("infraNodes", "number of leaf nodes", infraNodes);
122 cmd.AddValue ("lanNodes", "number of LAN nodes", lanNodes);
123 cmd.AddValue ("stopTime", "simulation stop time (seconds)", stopTime);
124 cmd.AddValue ("useCourseChangeCallback", "whether to enable course change tracing", useCourseChangeCallback);
125
126 //
127 // The system global variables and the local values added to the argument
128 // system can be overridden by command line arguments by using this call.
129 //
130 cmd.Parse (argc, argv);
131
132 if (stopTime < 10)
133 {
134 std::cout << "Use a simulation stop time >= 10 seconds" << std::endl;
135 exit (1);
136 }
137 ///////////////////////////////////////////////////////////////////////////
138 // //
139 // Construct the backbone //
140 // //
141 ///////////////////////////////////////////////////////////////////////////
142
143 //
144 // Create a container to manage the nodes of the adhoc (backbone) network.
145 // Later we'll create the rest of the nodes we'll need.
146 //
147 NodeContainer backbone;
148 backbone.Create (backboneNodes);
149 //
150 // Create the backbone wifi net devices and install them into the nodes in
151 // our container
152 //
153 WifiHelper wifi;
154 WifiMacHelper mac;
155 mac.SetType ("ns3::AdhocWifiMac");
156 wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager",
157 "DataMode", StringValue ("OfdmRate54Mbps"));
158 YansWifiPhyHelper wifiPhy;
159 wifiPhy.SetPcapDataLinkType (WifiPhyHelper::DLT_IEEE802_11_RADIO);
160 YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default ();
161 wifiPhy.SetChannel (wifiChannel.Create ());
162 NetDeviceContainer backboneDevices = wifi.Install (wifiPhy, mac, backbone);
163
164 // We enable OLSR (which will be consulted at a higher priority than
165 // the global routing) on the backbone ad hoc nodes
166 NS_LOG_INFO ("Enabling OLSR routing on all backbone nodes");
167 OlsrHelper olsr;
168 //
169 // Add the IPv4 protocol stack to the nodes in our container
170 //
171 InternetStackHelper internet;
172 internet.SetRoutingHelper (olsr); // has effect on the next Install ()
173 internet.Install (backbone);
174
175 //
176 // Assign IPv4 addresses to the device drivers (actually to the associated
177 // IPv4 interfaces) we just created.
178 //
179 Ipv4AddressHelper ipAddrs;
180 ipAddrs.SetBase ("192.168.0.0", "255.255.255.0");
181 ipAddrs.Assign (backboneDevices);
182
183 //
184 // The ad-hoc network nodes need a mobility model so we aggregate one to
185 // each of the nodes we just finished building.
186 //
187 MobilityHelper mobility;
188 mobility.SetPositionAllocator ("ns3::GridPositionAllocator",
189 "MinX", DoubleValue (20.0),
190 "MinY", DoubleValue (20.0),
191 "DeltaX", DoubleValue (20.0),
192 "DeltaY", DoubleValue (20.0),
193 "GridWidth", UintegerValue (5),
194 "LayoutType", StringValue ("RowFirst"));
195 mobility.SetMobilityModel ("ns3::RandomDirection2dMobilityModel",
196 "Bounds", RectangleValue (Rectangle (-500, 500, -500, 500)),
197 "Speed", StringValue ("ns3::ConstantRandomVariable[Constant=2]"),
198 "Pause", StringValue ("ns3::ConstantRandomVariable[Constant=0.2]"));
199 mobility.Install (backbone);
200
201 ///////////////////////////////////////////////////////////////////////////
202 // //
203 // Construct the LANs //
204 // //
205 ///////////////////////////////////////////////////////////////////////////
206
207 // Reset the address base-- all of the CSMA networks will be in
208 // the "172.16 address space
209 ipAddrs.SetBase ("172.16.0.0", "255.255.255.0");
210
211
212 for (uint32_t i = 0; i < backboneNodes; ++i)
213 {
214 NS_LOG_INFO ("Configuring local area network for backbone node " << i);
215 //
216 // Create a container to manage the nodes of the LAN. We need
217 // two containers here; one with all of the new nodes, and one
218 // with all of the nodes including new and existing nodes
219 //
220 NodeContainer newLanNodes;
221 newLanNodes.Create (lanNodes - 1);
222 // Now, create the container with all nodes on this link
223 NodeContainer lan (backbone.Get (i), newLanNodes);
224 //
225 // Create the CSMA net devices and install them into the nodes in our
226 // collection.
227 //
228 CsmaHelper csma;
229 csma.SetChannelAttribute ("DataRate",
230 DataRateValue (DataRate (5000000)));
231 csma.SetChannelAttribute ("Delay", TimeValue (MilliSeconds (2)));
232 NetDeviceContainer lanDevices = csma.Install (lan);
233 //
234 // Add the IPv4 protocol stack to the new LAN nodes
235 //
236 internet.Install (newLanNodes);
237 //
238 // Assign IPv4 addresses to the device drivers (actually to the
239 // associated IPv4 interfaces) we just created.
240 //
241 ipAddrs.Assign (lanDevices);
242 //
243 // Assign a new network prefix for the next LAN, according to the
244 // network mask initialized above
245 //
246 ipAddrs.NewNetwork ();
247 //
248 // The new LAN nodes need a mobility model so we aggregate one
249 // to each of the nodes we just finished building.
250 //
251 MobilityHelper mobilityLan;
252 Ptr<ListPositionAllocator> subnetAlloc =
253 CreateObject<ListPositionAllocator> ();
254 for (uint32_t j = 0; j < newLanNodes.GetN (); ++j)
255 {
256 subnetAlloc->Add (Vector (0.0, j * 10 + 10, 0.0));
257 }
258 mobilityLan.PushReferenceMobilityModel (backbone.Get (i));
259 mobilityLan.SetPositionAllocator (subnetAlloc);
260 mobilityLan.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
261 mobilityLan.Install (newLanNodes);
262 }
263
264 ///////////////////////////////////////////////////////////////////////////
265 // //
266 // Construct the mobile networks //
267 // //
268 ///////////////////////////////////////////////////////////////////////////
269
270 // Reset the address base-- all of the 802.11 networks will be in
271 // the "10.0" address space
272 ipAddrs.SetBase ("10.0.0.0", "255.255.255.0");
273
274 for (uint32_t i = 0; i < backboneNodes; ++i)
275 {
276 NS_LOG_INFO ("Configuring wireless network for backbone node " << i);
277 //
278 // Create a container to manage the nodes of the LAN. We need
279 // two containers here; one with all of the new nodes, and one
280 // with all of the nodes including new and existing nodes
281 //
282 NodeContainer stas;
283 stas.Create (infraNodes - 1);
284 // Now, create the container with all nodes on this link
285 NodeContainer infra (backbone.Get (i), stas);
286 //
287 // Create an infrastructure network
288 //
289 WifiHelper wifiInfra;
290 WifiMacHelper macInfra;
291 wifiPhy.SetChannel (wifiChannel.Create ());
292 // Create unique ssids for these networks
293 std::string ssidString ("wifi-infra");
294 std::stringstream ss;
295 ss << i;
296 ssidString += ss.str ();
297 Ssid ssid = Ssid (ssidString);
298 wifiInfra.SetRemoteStationManager ("ns3::ArfWifiManager");
299 // setup stas
300 macInfra.SetType ("ns3::StaWifiMac",
301 "Ssid", SsidValue (ssid));
302 NetDeviceContainer staDevices = wifiInfra.Install (wifiPhy, macInfra, stas);
303 // setup ap.
304 macInfra.SetType ("ns3::ApWifiMac",
305 "Ssid", SsidValue (ssid));
306 NetDeviceContainer apDevices = wifiInfra.Install (wifiPhy, macInfra, backbone.Get (i));
307 // Collect all of these new devices
308 NetDeviceContainer infraDevices (apDevices, staDevices);
309
310 // Add the IPv4 protocol stack to the nodes in our container
311 //
312 internet.Install (stas);
313 //
314 // Assign IPv4 addresses to the device drivers (actually to the associated
315 // IPv4 interfaces) we just created.
316 //
317 ipAddrs.Assign (infraDevices);
318 //
319 // Assign a new network prefix for each mobile network, according to
320 // the network mask initialized above
321 //
322 ipAddrs.NewNetwork ();
323 //
324 // The new wireless nodes need a mobility model so we aggregate one
325 // to each of the nodes we just finished building.
326 //
327 Ptr<ListPositionAllocator> subnetAlloc =
328 CreateObject<ListPositionAllocator> ();
329 for (uint32_t j = 0; j < infra.GetN (); ++j)
330 {
331 subnetAlloc->Add (Vector (0.0, j, 0.0));
332 }
333 mobility.PushReferenceMobilityModel (backbone.Get (i));
334 mobility.SetPositionAllocator (subnetAlloc);
335 mobility.SetMobilityModel ("ns3::RandomDirection2dMobilityModel",
336 "Bounds", RectangleValue (Rectangle (-10, 10, -10, 10)),
337 "Speed", StringValue ("ns3::ConstantRandomVariable[Constant=3]"),
338 "Pause", StringValue ("ns3::ConstantRandomVariable[Constant=0.4]"));
339 mobility.Install (stas);
340 }
341
342 ///////////////////////////////////////////////////////////////////////////
343 // //
344 // Application configuration //
345 // //
346 ///////////////////////////////////////////////////////////////////////////
347
348 // Create the OnOff application to send UDP datagrams of size
349 // 210 bytes at a rate of 10 Kb/s, between two nodes
350 // We'll send data from the first wired LAN node on the first wired LAN
351 // to the last wireless STA on the last infrastructure net, thereby
352 // causing packets to traverse CSMA to adhoc to infrastructure links
353
354 NS_LOG_INFO ("Create Applications.");
355 uint16_t port = 9; // Discard port (RFC 863)
356
357 // Let's make sure that the user does not define too few nodes
358 // to make this example work. We need lanNodes > 1 and infraNodes > 1
359 NS_ASSERT (lanNodes > 1 && infraNodes > 1);
360 // We want the source to be the first node created outside of the backbone
361 // Conveniently, the variable "backboneNodes" holds this node index value
362 Ptr<Node> appSource = NodeList::GetNode (backboneNodes);
363 // We want the sink to be the last node created in the topology.
364 uint32_t lastNodeIndex = backboneNodes + backboneNodes * (lanNodes - 1) + backboneNodes * (infraNodes - 1) - 1;
365 Ptr<Node> appSink = NodeList::GetNode (lastNodeIndex);
366 // Let's fetch the IP address of the last node, which is on Ipv4Interface 1
367 Ipv4Address remoteAddr = appSink->GetObject<Ipv4> ()->GetAddress (1, 0).GetLocal ();
368
369 OnOffHelper onoff ("ns3::UdpSocketFactory",
370 Address (InetSocketAddress (remoteAddr, port)));
371
372 ApplicationContainer apps = onoff.Install (appSource);
373 apps.Start (Seconds (3));
374 apps.Stop (Seconds (stopTime - 1));
375
376 // Create a packet sink to receive these packets
377 PacketSinkHelper sink ("ns3::UdpSocketFactory",
378 InetSocketAddress (Ipv4Address::GetAny (), port));
379 apps = sink.Install (appSink);
380 apps.Start (Seconds (3));
381
382 ///////////////////////////////////////////////////////////////////////////
383 // //
384 // Tracing configuration //
385 // //
386 ///////////////////////////////////////////////////////////////////////////
387
388 NS_LOG_INFO ("Configure Tracing.");
389 CsmaHelper csma;
390
391 //
392 // Let's set up some ns-2-like ascii traces, using another helper class
393 //
394 AsciiTraceHelper ascii;
395 Ptr<OutputStreamWrapper> stream = ascii.CreateFileStream ("mixed-wireless.tr");
396 wifiPhy.EnableAsciiAll (stream);
397 csma.EnableAsciiAll (stream);
398 internet.EnableAsciiIpv4All (stream);
399
400 // Csma captures in non-promiscuous mode
401 csma.EnablePcapAll ("mixed-wireless", false);
402 // pcap captures on the backbone wifi devices
403 wifiPhy.EnablePcap ("mixed-wireless", backboneDevices, false);
404 // pcap trace on the application data sink
405 wifiPhy.EnablePcap ("mixed-wireless", appSink->GetId (), 0);
406
407 if (useCourseChangeCallback == true)
408 {
409 Config::Connect ("/NodeList/*/$ns3::MobilityModel/CourseChange", MakeCallback (&CourseChangeCallback));
410 }
411
412 AnimationInterface anim ("mixed-wireless.xml");
413
414 ///////////////////////////////////////////////////////////////////////////
415 // //
416 // Run simulation //
417 // //
418 ///////////////////////////////////////////////////////////////////////////
419
420 NS_LOG_INFO ("Run Simulation.");
421 Simulator::Stop (Seconds (stopTime));
422 Simulator::Run ();
423 Simulator::Destroy ();
424 }
425