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