A Discrete-Event Network Simulator
QKDNetSim v2.0 (NS-3 v3.41) @ (+)
API
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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 try:
55  from ns import ns
56 except ModuleNotFoundError:
57  raise SystemExit(
58  "Error: ns3 Python module not found;"
59  " Python bindings may not be enabled"
60  " or your PYTHONPATH might not be properly configured"
61  )
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 
73 
74 def main(argv):
75  #
76  # First, we initialize a few local variables that control some
77  # simulation parameters.
78  #
79  from ctypes import c_double, c_int
80 
81  backboneNodes = c_int(10)
82  infraNodes = c_int(2)
83  lanNodes = c_int(2)
84  stopTime = c_double(20)
85  cmd = ns.CommandLine(__file__)
86 
87  #
88  # Simulation defaults are typically set next, before command line
89  # arguments are parsed.
90  #
91  ns.core.Config.SetDefault("ns3::OnOffApplication::PacketSize", ns.core.StringValue("1472"))
92  ns.core.Config.SetDefault("ns3::OnOffApplication::DataRate", ns.core.StringValue("100kb/s"))
93 
94  #
95  # For convenience, we add the local variables to the command line argument
96  # system so that they can be overridden with flags such as
97  # "--backboneNodes=20"
98  #
99 
100  cmd.AddValue("backboneNodes", "number of backbone nodes", backboneNodes)
101  cmd.AddValue("infraNodes", "number of leaf nodes", infraNodes)
102  cmd.AddValue("lanNodes", "number of LAN nodes", lanNodes)
103  cmd.AddValue["double"]("stopTime", "simulation stop time(seconds)", stopTime)
104 
105  #
106  # The system global variables and the local values added to the argument
107  # system can be overridden by command line arguments by using this call.
108  #
109  cmd.Parse(argv)
110 
111  if stopTime.value < 10:
112  print("Use a simulation stop time >= 10 seconds")
113  exit(1)
114  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # /
115  # #
116  # Construct the backbone #
117  # #
118  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # /
119 
120  #
121  # Create a container to manage the nodes of the adhoc(backbone) network.
122  # Later we'll create the rest of the nodes we'll need.
123  #
124  backbone = ns.network.NodeContainer()
125  backbone.Create(backboneNodes.value)
126  #
127  # Create the backbone wifi net devices and install them into the nodes in
128  # our container
129  #
130  wifi = ns.wifi.WifiHelper()
131  mac = ns.wifi.WifiMacHelper()
132  mac.SetType("ns3::AdhocWifiMac")
133  wifi.SetRemoteStationManager(
134  "ns3::ConstantRateWifiManager", "DataMode", ns.core.StringValue("OfdmRate54Mbps")
135  )
136  wifiPhy = ns.wifi.YansWifiPhyHelper()
137  wifiPhy.SetPcapDataLinkType(wifiPhy.DLT_IEEE802_11_RADIO)
138  wifiChannel = ns.wifi.YansWifiChannelHelper.Default()
139  wifiPhy.SetChannel(wifiChannel.Create())
140  backboneDevices = wifi.Install(wifiPhy, mac, backbone)
141  #
142  # Add the IPv4 protocol stack to the nodes in our container
143  #
144  print("Enabling OLSR routing on all backbone nodes")
145  internet = ns.internet.InternetStackHelper()
146  olsr = ns.olsr.OlsrHelper()
147  internet.SetRoutingHelper(olsr)
148  # has effect on the next Install ()
149  internet.Install(backbone)
150  # re-initialize for non-olsr routing.
151  # internet.Reset()
152  #
153  # Assign IPv4 addresses to the device drivers(actually to the associated
154  # IPv4 interfaces) we just created.
155  #
156  ipAddrs = ns.internet.Ipv4AddressHelper()
157  ipAddrs.SetBase(ns.network.Ipv4Address("192.168.0.0"), ns.network.Ipv4Mask("255.255.255.0"))
158  ipAddrs.Assign(backboneDevices)
159 
160  #
161  # The ad-hoc network nodes need a mobility model so we aggregate one to
162  # each of the nodes we just finished building.
163  #
164  mobility = ns.mobility.MobilityHelper()
165  mobility.SetPositionAllocator(
166  "ns3::GridPositionAllocator",
167  "MinX",
168  ns.core.DoubleValue(20.0),
169  "MinY",
170  ns.core.DoubleValue(20.0),
171  "DeltaX",
172  ns.core.DoubleValue(20.0),
173  "DeltaY",
174  ns.core.DoubleValue(20.0),
175  "GridWidth",
176  ns.core.UintegerValue(5),
177  "LayoutType",
178  ns.core.StringValue("RowFirst"),
179  )
180  mobility.SetMobilityModel(
181  "ns3::RandomDirection2dMobilityModel",
182  "Bounds",
183  ns.mobility.RectangleValue(ns.mobility.Rectangle(-500, 500, -500, 500)),
184  "Speed",
185  ns.core.StringValue("ns3::ConstantRandomVariable[Constant=2]"),
186  "Pause",
187  ns.core.StringValue("ns3::ConstantRandomVariable[Constant=0.2]"),
188  )
189  mobility.Install(backbone)
190 
191  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # /
192  # #
193  # Construct the LANs #
194  # #
195  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # /
196 
197  # Reset the address base-- all of the CSMA networks will be in
198  # the "172.16 address space
199  ipAddrs.SetBase(ns.network.Ipv4Address("172.16.0.0"), ns.network.Ipv4Mask("255.255.255.0"))
200 
201  for i in range(backboneNodes.value):
202  print("Configuring local area network for backbone node ", i)
203  #
204  # Create a container to manage the nodes of the LAN. We need
205  # two containers here; one with all of the new nodes, and one
206  # with all of the nodes including new and existing nodes
207  #
208  newLanNodes = ns.network.NodeContainer()
209  newLanNodes.Create(lanNodes.value - 1)
210  # Now, create the container with all nodes on this link
211  lan = ns.network.NodeContainer(ns.network.NodeContainer(backbone.Get(i)), newLanNodes)
212  #
213  # Create the CSMA net devices and install them into the nodes in our
214  # collection.
215  #
216  csma = ns.csma.CsmaHelper()
217  csma.SetChannelAttribute("DataRate", ns.network.DataRateValue(ns.network.DataRate(5000000)))
218  csma.SetChannelAttribute("Delay", ns.core.TimeValue(ns.core.MilliSeconds(2)))
219  lanDevices = csma.Install(lan)
220  #
221  # Add the IPv4 protocol stack to the new LAN nodes
222  #
223  internet.Install(newLanNodes)
224  #
225  # Assign IPv4 addresses to the device drivers(actually to the
226  # associated IPv4 interfaces) we just created.
227  #
228  ipAddrs.Assign(lanDevices)
229  #
230  # Assign a new network prefix for the next LAN, according to the
231  # network mask initialized above
232  #
233  ipAddrs.NewNetwork()
234  #
235  # The new LAN nodes need a mobility model so we aggregate one
236  # to each of the nodes we just finished building.
237  #
238  mobilityLan = ns.mobility.MobilityHelper()
239  positionAlloc = ns.mobility.ListPositionAllocator()
240  for j in range(newLanNodes.GetN()):
241  positionAlloc.Add(ns.core.Vector(0.0, (j * 10 + 10), 0.0))
242 
243  mobilityLan.SetPositionAllocator(positionAlloc)
244  mobilityLan.PushReferenceMobilityModel(backbone.Get(i))
245  mobilityLan.SetMobilityModel("ns3::ConstantPositionMobilityModel")
246  mobilityLan.Install(newLanNodes)
247 
248  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # /
249  # #
250  # Construct the mobile networks #
251  # #
252  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # /
253 
254  # Reset the address base-- all of the 802.11 networks will be in
255  # the "10.0" address space
256  ipAddrs.SetBase(ns.network.Ipv4Address("10.0.0.0"), ns.network.Ipv4Mask("255.255.255.0"))
257  tempRef = [] # list of references to be held to prevent garbage collection
258  for i in range(backboneNodes.value):
259  print("Configuring wireless network for backbone node ", i)
260  #
261  # Create a container to manage the nodes of the LAN. We need
262  # two containers here; one with all of the new nodes, and one
263  # with all of the nodes including new and existing nodes
264  #
265  stas = ns.network.NodeContainer()
266  stas.Create(infraNodes.value - 1)
267  # Now, create the container with all nodes on this link
268  infra = ns.network.NodeContainer(ns.network.NodeContainer(backbone.Get(i)), stas)
269  #
270  # Create another ad hoc network and devices
271  #
272  ssid = ns.wifi.Ssid("wifi-infra" + str(i))
273  wifiInfra = ns.wifi.WifiHelper()
274  wifiPhy.SetChannel(wifiChannel.Create())
275  macInfra = ns.wifi.WifiMacHelper()
276  macInfra.SetType("ns3::StaWifiMac", "Ssid", ns.wifi.SsidValue(ssid))
277 
278  # setup stas
279  staDevices = wifiInfra.Install(wifiPhy, macInfra, stas)
280  # setup ap.
281  macInfra.SetType("ns3::ApWifiMac", "Ssid", ns.wifi.SsidValue(ssid))
282  apDevices = wifiInfra.Install(wifiPhy, macInfra, backbone.Get(i))
283  # Collect all of these new devices
284  infraDevices = ns.network.NetDeviceContainer(apDevices, staDevices)
285 
286  # Add the IPv4 protocol stack to the nodes in our container
287  #
288  internet.Install(stas)
289  #
290  # Assign IPv4 addresses to the device drivers(actually to the associated
291  # IPv4 interfaces) we just created.
292  #
293  ipAddrs.Assign(infraDevices)
294  #
295  # Assign a new network prefix for each mobile network, according to
296  # the network mask initialized above
297  #
298  ipAddrs.NewNetwork()
299 
300  # This call returns an instance that needs to be stored in the outer scope
301  # not to be garbage collected when overwritten in the next iteration
302  subnetAlloc = ns.mobility.ListPositionAllocator()
303 
304  # Appending the object to a list is enough to prevent the garbage collection
305  tempRef.append(subnetAlloc)
306 
307  #
308  # The new wireless nodes need a mobility model so we aggregate one
309  # to each of the nodes we just finished building.
310  #
311  for j in range(infra.GetN()):
312  subnetAlloc.Add(ns.core.Vector(0.0, j, 0.0))
313 
314  mobility.PushReferenceMobilityModel(backbone.Get(i))
315  mobility.SetPositionAllocator(subnetAlloc)
316  mobility.SetMobilityModel(
317  "ns3::RandomDirection2dMobilityModel",
318  "Bounds",
319  ns.mobility.RectangleValue(ns.mobility.Rectangle(-10, 10, -10, 10)),
320  "Speed",
321  ns.core.StringValue("ns3::ConstantRandomVariable[Constant=3]"),
322  "Pause",
323  ns.core.StringValue("ns3::ConstantRandomVariable[Constant=0.4]"),
324  )
325  mobility.Install(stas)
326 
327  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # /
328  # #
329  # Application configuration #
330  # #
331  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # /
332 
333  # Create the OnOff application to send UDP datagrams of size
334  # 210 bytes at a rate of 448 Kb/s, between two nodes
335  print("Create Applications.")
336  port = 9 # Discard port(RFC 863)
337 
338  appSource = ns.network.NodeList.GetNode(backboneNodes.value)
339  lastNodeIndex = (
340  backboneNodes.value
341  + backboneNodes.value * (lanNodes.value - 1)
342  + backboneNodes.value * (infraNodes.value - 1)
343  - 1
344  )
345  appSink = ns.network.NodeList.GetNode(lastNodeIndex)
346 
347  ns.cppyy.cppdef(
348  """
349  Ipv4Address getIpv4AddressFromNode(Ptr<Node> node){
350  return node->GetObject<Ipv4>()->GetAddress(1,0).GetLocal();
351  }
352  """
353  )
354  # Let's fetch the IP address of the last node, which is on Ipv4Interface 1
355  remoteAddr = ns.cppyy.gbl.getIpv4AddressFromNode(appSink)
356  socketAddr = ns.network.InetSocketAddress(remoteAddr, port)
357  onoff = ns.applications.OnOffHelper("ns3::UdpSocketFactory", socketAddr.ConvertTo())
358  apps = onoff.Install(ns.network.NodeContainer(appSource))
359  apps.Start(ns.core.Seconds(3))
360  apps.Stop(ns.core.Seconds(stopTime.value - 1))
361 
362  # Create a packet sink to receive these packets
363  sink = ns.applications.PacketSinkHelper(
364  "ns3::UdpSocketFactory",
365  ns.network.InetSocketAddress(
366  ns.network.InetSocketAddress(ns.network.Ipv4Address.GetAny(), port)
367  ).ConvertTo(),
368  )
369  sinkContainer = ns.network.NodeContainer(appSink)
370  apps = sink.Install(sinkContainer)
371  apps.Start(ns.core.Seconds(3))
372 
373  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # /
374  # #
375  # Tracing configuration #
376  # #
377  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # /
378 
379  print("Configure Tracing.")
380  csma = ns.csma.CsmaHelper()
381  #
382  # Let's set up some ns-2-like ascii traces, using another helper class
383  #
384  ascii = ns.network.AsciiTraceHelper()
385  stream = ascii.CreateFileStream("mixed-wireless.tr")
386  wifiPhy.EnableAsciiAll(stream)
387  csma.EnableAsciiAll(stream)
388  internet.EnableAsciiIpv4All(stream)
389 
390  # Csma captures in non-promiscuous mode
391  csma.EnablePcapAll("mixed-wireless", False)
392  # Let's do a pcap trace on the backbone devices
393  wifiPhy.EnablePcap("mixed-wireless", backboneDevices)
394  wifiPhy.EnablePcap("mixed-wireless", appSink.GetId(), 0)
395 
396  # #ifdef ENABLE_FOR_TRACING_EXAMPLE
397  # Config.Connect("/NodeList/*/$MobilityModel/CourseChange",
398  # MakeCallback(&CourseChangeCallback))
399  # #endif
400 
401  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
402  # #
403  # Run simulation #
404  # #
405  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
406 
407  print("Run Simulation.")
408  ns.core.Simulator.Stop(ns.core.Seconds(stopTime.value))
409  ns.core.Simulator.Run()
410  ns.core.Simulator.Destroy()
411 
412 
413 if __name__ == "__main__":
414  import sys
415 
416  main(sys.argv)