A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
mixed-wired-wireless.py
Go to the documentation of this file.
1# /*
2# * SPDX-License-Identifier: GPL-2.0-only
3# */
4
5#
6# This ns-3 example demonstrates the use of helper functions to ease
7# the construction of simulation scenarios.
8#
9# The simulation topology consists of a mixed wired and wireless
10# scenario in which a hierarchical mobility model is used.
11#
12# The simulation layout consists of N backbone routers interconnected
13# by an ad hoc wifi network.
14# Each backbone router also has a local 802.11 network and is connected
15# to a local LAN. An additional set of(K-1) nodes are connected to
16# this backbone. Finally, a local LAN is connected to each router
17# on the backbone, with L-1 additional hosts.
18#
19# The nodes are populated with TCP/IP stacks, and OLSR unicast routing
20# on the backbone. An example UDP transfer is shown. The simulator
21# be configured to output tcpdumps or traces from different nodes.
22#
23#
24# +--------------------------------------------------------+
25# | |
26# | 802.11 ad hoc, ns-2 mobility |
27# | |
28# +--------------------------------------------------------+
29# | o o o(N backbone routers) |
30# +--------+ +--------+
31# wired LAN | mobile | wired LAN | mobile |
32# -----------| router | -----------| router |
33# --------- ---------
34# | |
35# +----------------+ +----------------+
36# | 802.11 | | 802.11 |
37# | net | | net |
38# | K-1 hosts | | K-1 hosts |
39# +----------------+ +----------------+
40#
41
42try:
43 from ns import ns
44except ModuleNotFoundError:
45 raise SystemExit(
46 "Error: ns3 Python module not found;"
47 " Python bindings may not be enabled"
48 " or your PYTHONPATH might not be properly configured"
49 )
50
51# #
52# # This function will be used below as a trace sink
53# #
54# static void
55# CourseChangeCallback(std.string path, Ptr<const MobilityModel> model)
56# {
57# Vector position = model.GetPosition();
58# std.cout << "CourseChange " << path << " x=" << position.x << ", y=" << position.y << ", z=" << position.z << std.endl;
59# }
60
61
62def main(argv):
63 #
64 # First, we initialize a few local variables that control some
65 # simulation parameters.
66 #
67 from ctypes import c_double, c_int
68
69 backboneNodes = c_int(10)
70 infraNodes = c_int(2)
71 lanNodes = c_int(2)
72 stopTime = c_double(20)
73 cmd = ns.CommandLine(__file__)
74
75 #
76 # Simulation defaults are typically set next, before command line
77 # arguments are parsed.
78 #
79 ns.Config.SetDefault("ns3::OnOffApplication::PacketSize", ns.StringValue("1472"))
80 ns.Config.SetDefault("ns3::OnOffApplication::DataRate", ns.StringValue("100kb/s"))
81
82 #
83 # For convenience, we add the local variables to the command line argument
84 # system so that they can be overridden with flags such as
85 # "--backboneNodes=20"
86 #
87
88 cmd.AddValue("backboneNodes", "number of backbone nodes", backboneNodes)
89 cmd.AddValue("infraNodes", "number of leaf nodes", infraNodes)
90 cmd.AddValue("lanNodes", "number of LAN nodes", lanNodes)
91 cmd.AddValue["double"]("stopTime", "simulation stop time(seconds)", stopTime)
92
93 #
94 # The system global variables and the local values added to the argument
95 # system can be overridden by command line arguments by using this call.
96 #
97 cmd.Parse(argv)
98
99 if stopTime.value < 10:
100 print("Use a simulation stop time >= 10 seconds")
101 exit(1)
102 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # /
103 # #
104 # Construct the backbone #
105 # #
106 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # /
107
108 #
109 # Create a container to manage the nodes of the adhoc(backbone) network.
110 # Later we'll create the rest of the nodes we'll need.
111 #
112 backbone = ns.NodeContainer()
113 backbone.Create(backboneNodes.value)
114 #
115 # Create the backbone wifi net devices and install them into the nodes in
116 # our container
117 #
118 wifi = ns.WifiHelper()
119 mac = ns.WifiMacHelper()
120 mac.SetType("ns3::AdhocWifiMac")
121 wifi.SetRemoteStationManager(
122 "ns3::ConstantRateWifiManager", "DataMode", ns.StringValue("OfdmRate54Mbps")
123 )
124 wifiPhy = ns.YansWifiPhyHelper()
125 wifiPhy.SetPcapDataLinkType(wifiPhy.DLT_IEEE802_11_RADIO)
126 wifiChannel = ns.YansWifiChannelHelper.Default()
127 wifiPhy.SetChannel(wifiChannel.Create())
128 backboneDevices = wifi.Install(wifiPhy, mac, backbone)
129 #
130 # Add the IPv4 protocol stack to the nodes in our container
131 #
132 print("Enabling OLSR routing on all backbone nodes")
133 internet = ns.InternetStackHelper()
134 olsr = ns.OlsrHelper()
135 internet.SetRoutingHelper(olsr)
136 # has effect on the next Install ()
137 internet.Install(backbone)
138 # re-initialize for non-olsr routing.
139 # internet.Reset()
140 #
141 # Assign IPv4 addresses to the device drivers(actually to the associated
142 # IPv4 interfaces) we just created.
143 #
144 ipAddrs = ns.Ipv4AddressHelper()
145 ipAddrs.SetBase(ns.Ipv4Address("192.168.0.0"), ns.Ipv4Mask("255.255.255.0"))
146 ipAddrs.Assign(backboneDevices)
147
148 #
149 # The ad-hoc network nodes need a mobility model so we aggregate one to
150 # each of the nodes we just finished building.
151 #
152 mobility = ns.MobilityHelper()
153 mobility.SetPositionAllocator(
154 "ns3::GridPositionAllocator",
155 "MinX",
156 ns.DoubleValue(20.0),
157 "MinY",
158 ns.DoubleValue(20.0),
159 "DeltaX",
160 ns.DoubleValue(20.0),
161 "DeltaY",
162 ns.DoubleValue(20.0),
163 "GridWidth",
164 ns.UintegerValue(5),
165 "LayoutType",
166 ns.StringValue("RowFirst"),
167 )
168 mobility.SetMobilityModel(
169 "ns3::RandomDirection2dMobilityModel",
170 "Bounds",
171 ns.RectangleValue(ns.Rectangle(-500, 500, -500, 500)),
172 "Speed",
173 ns.StringValue("ns3::ConstantRandomVariable[Constant=2]"),
174 "Pause",
175 ns.StringValue("ns3::ConstantRandomVariable[Constant=0.2]"),
176 )
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.Ipv4Address("172.16.0.0"), ns.Ipv4Mask("255.255.255.0"))
188
189 for i in range(backboneNodes.value):
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.NodeContainer()
197 newLanNodes.Create(lanNodes.value - 1)
198 # Now, create the container with all nodes on this link
199 lan = ns.NodeContainer(ns.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.CsmaHelper()
205 csma.SetChannelAttribute("DataRate", ns.DataRateValue(ns.DataRate(5000000)))
206 csma.SetChannelAttribute("Delay", ns.TimeValue(ns.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.MobilityHelper()
227 positionAlloc = ns.ListPositionAllocator()
228 for j in range(newLanNodes.GetN()):
229 positionAlloc.Add(ns.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.Ipv4Address("10.0.0.0"), ns.Ipv4Mask("255.255.255.0"))
245 tempRef = [] # list of references to be held to prevent garbage collection
246 for i in range(backboneNodes.value):
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.NodeContainer()
254 stas.Create(infraNodes.value - 1)
255 # Now, create the container with all nodes on this link
256 infra = ns.NodeContainer(ns.NodeContainer(backbone.Get(i)), stas)
257 #
258 # Create another ad hoc network and devices
259 #
260 ssid = ns.Ssid("wifi-infra" + str(i))
261 wifiInfra = ns.WifiHelper()
262 wifiPhy.SetChannel(wifiChannel.Create())
263 macInfra = ns.WifiMacHelper()
264 macInfra.SetType("ns3::StaWifiMac", "Ssid", ns.SsidValue(ssid))
265
266 # setup stas
267 staDevices = wifiInfra.Install(wifiPhy, macInfra, stas)
268 # setup ap.
269 macInfra.SetType("ns3::ApWifiMac", "Ssid", ns.SsidValue(ssid))
270 apDevices = wifiInfra.Install(wifiPhy, macInfra, backbone.Get(i))
271 # Collect all of these new devices
272 infraDevices = ns.NetDeviceContainer(apDevices, staDevices)
273
274 # Add the IPv4 protocol stack to the nodes in our container
275 #
276 internet.Install(stas)
277 #
278 # Assign IPv4 addresses to the device drivers(actually to the associated
279 # IPv4 interfaces) we just created.
280 #
281 ipAddrs.Assign(infraDevices)
282 #
283 # Assign a new network prefix for each mobile network, according to
284 # the network mask initialized above
285 #
286 ipAddrs.NewNetwork()
287
288 # This call returns an instance that needs to be stored in the outer scope
289 # not to be garbage collected when overwritten in the next iteration
290 subnetAlloc = ns.ListPositionAllocator()
291
292 # Appending the object to a list is enough to prevent the garbage collection
293 tempRef.append(subnetAlloc)
294
295 #
296 # The new wireless nodes need a mobility model so we aggregate one
297 # to each of the nodes we just finished building.
298 #
299 for j in range(infra.GetN()):
300 subnetAlloc.Add(ns.Vector(0.0, j, 0.0))
301
302 mobility.PushReferenceMobilityModel(backbone.Get(i))
303 mobility.SetPositionAllocator(subnetAlloc)
304 mobility.SetMobilityModel(
305 "ns3::RandomDirection2dMobilityModel",
306 "Bounds",
307 ns.RectangleValue(ns.Rectangle(-10, 10, -10, 10)),
308 "Speed",
309 ns.StringValue("ns3::ConstantRandomVariable[Constant=3]"),
310 "Pause",
311 ns.StringValue("ns3::ConstantRandomVariable[Constant=0.4]"),
312 )
313 mobility.Install(stas)
314
315 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # /
316 # #
317 # Application configuration #
318 # #
319 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # /
320
321 # Create the OnOff application to send UDP datagrams of size
322 # 210 bytes at a rate of 448 Kb/s, between two nodes
323 print("Create Applications.")
324 port = 9 # Discard port(RFC 863)
325
326 appSource = ns.NodeList.GetNode(backboneNodes.value)
327 lastNodeIndex = (
328 backboneNodes.value
329 + backboneNodes.value * (lanNodes.value - 1)
330 + backboneNodes.value * (infraNodes.value - 1)
331 - 1
332 )
333 appSink = ns.NodeList.GetNode(lastNodeIndex)
334
335 ns.cppyy.cppdef(
336 """
337 Ipv4Address getIpv4AddressFromNode(Ptr<Node> node){
338 return node->GetObject<Ipv4>()->GetAddress(1,0).GetLocal();
339 }
340 """
341 )
342 # Let's fetch the IP address of the last node, which is on Ipv4Interface 1
343 remoteAddr = ns.cppyy.gbl.getIpv4AddressFromNode(appSink)
344 socketAddr = ns.InetSocketAddress(remoteAddr, port)
345 onoff = ns.OnOffHelper("ns3::UdpSocketFactory", socketAddr.ConvertTo())
346 apps = onoff.Install(ns.NodeContainer(appSource))
347 apps.Start(ns.Seconds(3))
348 apps.Stop(ns.Seconds(stopTime.value - 1))
349
350 # Create a packet sink to receive these packets
351 sink = ns.PacketSinkHelper(
352 "ns3::UdpSocketFactory",
353 ns.InetSocketAddress(ns.InetSocketAddress(ns.Ipv4Address.GetAny(), port)).ConvertTo(),
354 )
355 sinkContainer = ns.NodeContainer(appSink)
356 apps = sink.Install(sinkContainer)
357 apps.Start(ns.Seconds(3))
358
359 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # /
360 # #
361 # Tracing configuration #
362 # #
363 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # /
364
365 print("Configure Tracing.")
366 csma = ns.CsmaHelper()
367 #
368 # Let's set up some ns-2-like ascii traces, using another helper class
369 #
370 ascii = ns.AsciiTraceHelper()
371 stream = ascii.CreateFileStream("mixed-wireless.tr")
372 wifiPhy.EnableAsciiAll(stream)
373 csma.EnableAsciiAll(stream)
374 internet.EnableAsciiIpv4All(stream)
375
376 # Csma captures in non-promiscuous mode
377 csma.EnablePcapAll("mixed-wireless", False)
378 # Let's do a pcap trace on the backbone devices
379 wifiPhy.EnablePcap("mixed-wireless", backboneDevices)
380 wifiPhy.EnablePcap("mixed-wireless", appSink.GetId(), 0)
381
382 # #ifdef ENABLE_FOR_TRACING_EXAMPLE
383 # Config.Connect("/NodeList/*/$MobilityModel/CourseChange",
384 # MakeCallback(&CourseChangeCallback))
385 # #endif
386
387 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
388 # #
389 # Run simulation #
390 # #
391 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
392
393 print("Run Simulation.")
394 ns.Simulator.Stop(ns.Seconds(stopTime.value))
395 ns.Simulator.Run()
396 ns.Simulator.Destroy()
397
398
399if __name__ == "__main__":
400 import sys
401
402 main(sys.argv)