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