A Discrete-Event Network Simulator
API
mixed-wired-wireless.py
Go to the documentation of this file.
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 
54 from ns import ns
55 
56 # #
57 # # This function will be used below as a trace sink
58 # #
59 # static void
60 # CourseChangeCallback(std.string path, Ptr<const MobilityModel> model)
61 # {
62 # Vector position = model.GetPosition();
63 # std.cout << "CourseChange " << path << " x=" << position.x << ", y=" << position.y << ", z=" << position.z << std.endl;
64 # }
65 
66 def main(argv):
67  #
68  # First, we initialize a few local variables that control some
69  # simulation parameters.
70  #
71  from ctypes import c_int, c_double
72  backboneNodes = c_int(10)
73  infraNodes = c_int(2)
74  lanNodes = c_int(2)
75  stopTime = c_double(20)
76  cmd = ns.CommandLine(__file__)
77 
78  #
79  # Simulation defaults are typically set next, before command line
80  # arguments are parsed.
81  #
82  ns.core.Config.SetDefault("ns3::OnOffApplication::PacketSize", ns.core.StringValue("1472"))
83  ns.core.Config.SetDefault("ns3::OnOffApplication::DataRate", ns.core.StringValue("100kb/s"))
84 
85  #
86  # For convenience, we add the local variables to the command line argument
87  # system so that they can be overridden with flags such as
88  # "--backboneNodes=20"
89  #
90 
91  cmd.AddValue("backboneNodes", "number of backbone nodes", backboneNodes)
92  cmd.AddValue("infraNodes", "number of leaf nodes", infraNodes)
93  cmd.AddValue("lanNodes", "number of LAN nodes", lanNodes)
94  cmd.AddValue("stopTime", "simulation stop time(seconds)", stopTime)
95 
96  #
97  # The system global variables and the local values added to the argument
98  # system can be overridden by command line arguments by using this call.
99  #
100  cmd.Parse(argv)
101 
102  if (stopTime.value < 10):
103  print ("Use a simulation stop time >= 10 seconds")
104  exit(1)
105  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # /
106  # #
107  # Construct the backbone #
108  # #
109  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # /
110 
111  #
112  # Create a container to manage the nodes of the adhoc(backbone) network.
113  # Later we'll create the rest of the nodes we'll need.
114  #
115  backbone = ns.network.NodeContainer()
116  backbone.Create(backboneNodes.value)
117  #
118  # Create the backbone wifi net devices and install them into the nodes in
119  # our container
120  #
121  wifi = ns.wifi.WifiHelper()
122  mac = ns.wifi.WifiMacHelper()
123  mac.SetType("ns3::AdhocWifiMac")
124  wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager",
125  "DataMode", ns.core.StringValue("OfdmRate54Mbps"))
126  wifiPhy = ns.wifi.YansWifiPhyHelper()
127  wifiPhy.SetPcapDataLinkType(wifiPhy.DLT_IEEE802_11_RADIO)
128  wifiChannel = ns.wifi.YansWifiChannelHelper.Default()
129  wifiPhy.SetChannel(wifiChannel.Create())
130  backboneDevices = wifi.Install(wifiPhy, mac, backbone)
131  #
132  # Add the IPv4 protocol stack to the nodes in our container
133  #
134  print ("Enabling OLSR routing on all backbone nodes")
135  internet = ns.internet.InternetStackHelper()
136  olsr = ns.olsr.OlsrHelper()
137  internet.SetRoutingHelper(olsr); # has effect on the next Install ()
138  internet.Install(backbone);
139  # re-initialize for non-olsr routing.
140  # internet.Reset()
141  #
142  # Assign IPv4 addresses to the device drivers(actually to the associated
143  # IPv4 interfaces) we just created.
144  #
145  ipAddrs = ns.internet.Ipv4AddressHelper()
146  ipAddrs.SetBase(ns.network.Ipv4Address("192.168.0.0"), ns.network.Ipv4Mask("255.255.255.0"))
147  ipAddrs.Assign(backboneDevices)
148 
149  #
150  # The ad-hoc network nodes need a mobility model so we aggregate one to
151  # each of the nodes we just finished building.
152  #
153  mobility = ns.mobility.MobilityHelper()
154  mobility.SetPositionAllocator("ns3::GridPositionAllocator",
155  "MinX", ns.core.DoubleValue(20.0),
156  "MinY", ns.core.DoubleValue(20.0),
157  "DeltaX", ns.core.DoubleValue(20.0),
158  "DeltaY", ns.core.DoubleValue(20.0),
159  "GridWidth", ns.core.UintegerValue(5),
160  "LayoutType", ns.core.StringValue("RowFirst"))
161  mobility.SetMobilityModel("ns3::RandomDirection2dMobilityModel",
162  "Bounds", ns.mobility.RectangleValue(ns.mobility.Rectangle(-500, 500, -500, 500)),
163  "Speed", ns.core.StringValue ("ns3::ConstantRandomVariable[Constant=2]"),
164  "Pause", ns.core.StringValue ("ns3::ConstantRandomVariable[Constant=0.2]"))
165  mobility.Install(backbone)
166 
167  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # /
168  # #
169  # Construct the LANs #
170  # #
171  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # /
172 
173  # Reset the address base-- all of the CSMA networks will be in
174  # the "172.16 address space
175  ipAddrs.SetBase(ns.network.Ipv4Address("172.16.0.0"), ns.network.Ipv4Mask("255.255.255.0"))
176 
177  for i in range(backboneNodes.value):
178  print ("Configuring local area network for backbone node ", i)
179  #
180  # Create a container to manage the nodes of the LAN. We need
181  # two containers here; one with all of the new nodes, and one
182  # with all of the nodes including new and existing nodes
183  #
184  newLanNodes = ns.network.NodeContainer()
185  newLanNodes.Create(lanNodes.value - 1)
186  # Now, create the container with all nodes on this link
187  lan = ns.network.NodeContainer(ns.network.NodeContainer(backbone.Get(i)), newLanNodes)
188  #
189  # Create the CSMA net devices and install them into the nodes in our
190  # collection.
191  #
192  csma = ns.csma.CsmaHelper()
193  csma.SetChannelAttribute("DataRate", ns.network.DataRateValue(ns.network.DataRate(5000000)))
194  csma.SetChannelAttribute("Delay", ns.core.TimeValue(ns.core.MilliSeconds(2)))
195  lanDevices = csma.Install(lan)
196  #
197  # Add the IPv4 protocol stack to the new LAN nodes
198  #
199  internet.Install(newLanNodes)
200  #
201  # Assign IPv4 addresses to the device drivers(actually to the
202  # associated IPv4 interfaces) we just created.
203  #
204  ipAddrs.Assign(lanDevices)
205  #
206  # Assign a new network prefix for the next LAN, according to the
207  # network mask initialized above
208  #
209  ipAddrs.NewNetwork()
210  #
211  # The new LAN nodes need a mobility model so we aggregate one
212  # to each of the nodes we just finished building.
213  #
214  mobilityLan = ns.mobility.MobilityHelper()
215  positionAlloc = ns.mobility.ListPositionAllocator()
216  for j in range(newLanNodes.GetN()):
217  positionAlloc.Add(ns.core.Vector(0.0, (j*10 + 10), 0.0))
218 
219  mobilityLan.SetPositionAllocator(positionAlloc)
220  mobilityLan.PushReferenceMobilityModel(backbone.Get(i))
221  mobilityLan.SetMobilityModel("ns3::ConstantPositionMobilityModel")
222  mobilityLan.Install(newLanNodes);
223 
224  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # /
225  # #
226  # Construct the mobile networks #
227  # #
228  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # /
229 
230  # Reset the address base-- all of the 802.11 networks will be in
231  # the "10.0" address space
232  ipAddrs.SetBase(ns.network.Ipv4Address("10.0.0.0"), ns.network.Ipv4Mask("255.255.255.0"))
233  tempRef = [] # list of references to be held to prevent garbage collection
234  for i in range(backboneNodes.value):
235  print ("Configuring wireless network for backbone node ", i)
236  #
237  # Create a container to manage the nodes of the LAN. We need
238  # two containers here; one with all of the new nodes, and one
239  # with all of the nodes including new and existing nodes
240  #
241  stas = ns.network.NodeContainer()
242  stas.Create(infraNodes.value - 1)
243  # Now, create the container with all nodes on this link
244  infra = ns.network.NodeContainer(ns.network.NodeContainer(backbone.Get(i)), stas)
245  #
246  # Create another ad hoc network and devices
247  #
248  ssid = ns.wifi.Ssid('wifi-infra' + str(i))
249  wifiInfra = ns.wifi.WifiHelper()
250  wifiPhy.SetChannel(wifiChannel.Create())
251  macInfra = ns.wifi.WifiMacHelper();
252  macInfra.SetType("ns3::StaWifiMac",
253  "Ssid", ns.wifi.SsidValue(ssid))
254 
255  # setup stas
256  staDevices = wifiInfra.Install(wifiPhy, macInfra, stas)
257  # setup ap.
258  macInfra.SetType("ns3::ApWifiMac",
259  "Ssid", ns.wifi.SsidValue(ssid))
260  apDevices = wifiInfra.Install(wifiPhy, macInfra, backbone.Get(i))
261  # Collect all of these new devices
262  infraDevices = ns.network.NetDeviceContainer(apDevices, staDevices)
263 
264  # Add the IPv4 protocol stack to the nodes in our container
265  #
266  internet.Install(stas)
267  #
268  # Assign IPv4 addresses to the device drivers(actually to the associated
269  # IPv4 interfaces) we just created.
270  #
271  ipAddrs.Assign(infraDevices)
272  #
273  # Assign a new network prefix for each mobile network, according to
274  # the network mask initialized above
275  #
276  ipAddrs.NewNetwork()
277 
278  # This call returns an instance that needs to be stored in the outer scope
279  # not to be garbage collected when overwritten in the next iteration
280  subnetAlloc = ns.mobility.ListPositionAllocator()
281 
282  # Appending the object to a list is enough to prevent the garbage collection
283  tempRef.append(subnetAlloc)
284 
285  #
286  # The new wireless nodes need a mobility model so we aggregate one
287  # to each of the nodes we just finished building.
288  #
289  for j in range(infra.GetN()):
290  subnetAlloc.Add(ns.core.Vector(0.0, j, 0.0))
291 
292  mobility.PushReferenceMobilityModel(backbone.Get(i))
293  mobility.SetPositionAllocator(subnetAlloc)
294  mobility.SetMobilityModel("ns3::RandomDirection2dMobilityModel",
295  "Bounds", ns.mobility.RectangleValue(ns.mobility.Rectangle(-10, 10, -10, 10)),
296  "Speed", ns.core.StringValue ("ns3::ConstantRandomVariable[Constant=3]"),
297  "Pause", ns.core.StringValue ("ns3::ConstantRandomVariable[Constant=0.4]"))
298  mobility.Install(stas)
299 
300  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # /
301  # #
302  # Application configuration #
303  # #
304  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # /
305 
306  # Create the OnOff application to send UDP datagrams of size
307  # 210 bytes at a rate of 448 Kb/s, between two nodes
308  print ("Create Applications.")
309  port = 9 # Discard port(RFC 863)
310 
311  appSource = ns.network.NodeList.GetNode(backboneNodes.value)
312  lastNodeIndex = backboneNodes.value + backboneNodes.value*(lanNodes.value - 1) + backboneNodes.value*(infraNodes.value - 1) - 1
313  appSink = ns.network.NodeList.GetNode(lastNodeIndex)
314 
315  ns.cppyy.cppdef("""
316  Ipv4Address getIpv4AddressFromNode(Ptr<Node> node){
317  return node->GetObject<Ipv4>()->GetAddress(1,0).GetLocal();
318  }
319  """)
320  # Let's fetch the IP address of the last node, which is on Ipv4Interface 1
321  remoteAddr = ns.cppyy.gbl.getIpv4AddressFromNode(appSink)
322  socketAddr = ns.network.InetSocketAddress(remoteAddr, port)
323  onoff = ns.applications.OnOffHelper("ns3::UdpSocketFactory", socketAddr.ConvertTo())
324  apps = onoff.Install(ns.network.NodeContainer(appSource))
325  apps.Start(ns.core.Seconds(3))
326  apps.Stop(ns.core.Seconds(stopTime.value - 1))
327 
328  # Create a packet sink to receive these packets
329  sink = ns.applications.PacketSinkHelper("ns3::UdpSocketFactory",
330  ns.network.InetSocketAddress(ns.network.InetSocketAddress(ns.network.Ipv4Address.GetAny(), port)).ConvertTo())
331  sinkContainer = ns.network.NodeContainer(appSink)
332  apps = sink.Install(sinkContainer)
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.value))
372  ns.core.Simulator.Run()
373  ns.core.Simulator.Destroy()
374 
375 if __name__ == '__main__':
376  import sys
377  main(sys.argv)
378 
379