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