1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3 * Copyright (c) 2016 Sébastien Deronne
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Sébastien Deronne <sebastien.deronne@gmail.com>
19 */
20
21 #include "ns3/command-line.h"
22 #include "ns3/config.h"
23 #include "ns3/string.h"
24 #include "ns3/pointer.h"
25 #include "ns3/log.h"
26 #include "ns3/yans-wifi-helper.h"
27 #include "ns3/ssid.h"
28 #include "ns3/mobility-helper.h"
29 #include "ns3/internet-stack-helper.h"
30 #include "ns3/ipv4-address-helper.h"
31 #include "ns3/udp-client-server-helper.h"
32 #include "ns3/on-off-helper.h"
33 #include "ns3/yans-wifi-channel.h"
34 #include "ns3/wifi-net-device.h"
35 #include "ns3/qos-txop.h"
36 #include "ns3/wifi-mac.h"
37 #include "ns3/packet-sink-helper.h"
38 #include "ns3/packet-sink.h"
39 #include "ns3/ht-configuration.h"
40
41 // This example shows how to configure mixed networks (i.e. mixed b/g and HT/non-HT) and how are performance in several scenarios.
42 //
43 // The example compares first g only and mixed b/g cases with various configurations depending on the following parameters:
44 // - protection mode that is configured on the AP;
45 // - whether short PPDU format is supported by the 802.11b station;
46 // - whether short slot time is supported by both the 802.11g station and the AP.
47 //
48 // The example then compares HT only and mixed HT/non-HT cases.
49 //
50 // The output results show that the presence of an 802.11b station strongly affects 802.11g performance.
51 // Protection mechanisms ensure that the NAV value of 802.11b stations is set correctly in case of 802.11g transmissions.
52 // In practice, those protection mechanism add a lot of overhead, resulting in reduced performance. CTS-To-Self introduces
53 // less overhead than Rts-Cts, but is not heard by hidden stations (and is thus generally only recommended as a protection
54 // mechanism for access points). Since short slot time is disabled once an 802.11b station enters the network, benefits from
55 // short slot time are only observed in a g only configuration.
56 //
57 // The user can also select the payload size and can choose either an UDP or a TCP connection.
58 // Example: ./waf --run "wifi-mixed-network --isUdp=1"
59
60 using namespace ns3;
61
62 NS_LOG_COMPONENT_DEFINE ("MixedNetwork");
63
64 struct Parameters
65 {
66 std::string testName;
67 bool enableErpProtection;
68 std::string erpProtectionMode;
69 bool enableShortSlotTime;
70 bool enableShortPhyPreamble;
71 WifiStandard apType;
72 uint32_t nWifiB;
73 bool bHasTraffic;
74 uint32_t nWifiG;
75 bool gHasTraffic;
76 uint32_t nWifiN;
77 bool nHasTraffic;
78 bool isUdp;
79 uint32_t payloadSize;
80 double simulationTime;
81 };
82
83 class Experiment
84 {
85 public:
86 Experiment ();
87 double Run (Parameters params);
88 };
89
Experiment()90 Experiment::Experiment ()
91 {
92 }
93
94 double
Run(Parameters params)95 Experiment::Run (Parameters params)
96 {
97 std::string apTypeString;
98 if (params.apType == WIFI_STANDARD_80211g)
99 {
100 apTypeString = "WIFI_STANDARD_80211g";
101 }
102 else if (params.apType == WIFI_STANDARD_80211n_2_4GHZ)
103 {
104 apTypeString = "WIFI_STANDARD_80211n_2_4GHZ";
105 }
106
107 std::cout << "Run: " << params.testName
108 << "\n\t enableErpProtection=" << params.enableErpProtection
109 << "\n\t erpProtectionMode=" << params.erpProtectionMode
110 << "\n\t enableShortSlotTime=" << params.enableShortSlotTime
111 << "\n\t enableShortPhyPreamble=" << params.enableShortPhyPreamble
112 << "\n\t apType=" << apTypeString
113 << "\n\t nWifiB=" << params.nWifiB
114 << "\n\t bHasTraffic=" << params.bHasTraffic
115 << "\n\t nWifiG=" << params.nWifiG
116 << "\n\t gHasTraffic=" << params.gHasTraffic
117 << "\n\t nWifiN=" << params.nWifiN
118 << "\n\t nHasTraffic=" << params.nHasTraffic
119 << std::endl;
120
121 Config::SetDefault ("ns3::WifiRemoteStationManager::ErpProtectionMode", StringValue (params.erpProtectionMode));
122
123 double throughput = 0;
124 uint32_t nWifiB = params.nWifiB;
125 uint32_t nWifiG = params.nWifiG;
126 uint32_t nWifiN = params.nWifiN;
127 double simulationTime = params.simulationTime;
128 uint32_t payloadSize = params.payloadSize;
129
130 NodeContainer wifiBStaNodes;
131 wifiBStaNodes.Create (nWifiB);
132 NodeContainer wifiGStaNodes;
133 wifiGStaNodes.Create (nWifiG);
134 NodeContainer wifiNStaNodes;
135 wifiNStaNodes.Create (nWifiN);
136 NodeContainer wifiApNode;
137 wifiApNode.Create (1);
138
139 YansWifiChannelHelper channel = YansWifiChannelHelper::Default ();
140 channel.AddPropagationLoss ("ns3::RangePropagationLossModel");
141
142 YansWifiPhyHelper phy;
143 phy.SetChannel (channel.Create ());
144
145 WifiHelper wifi;
146 wifi.SetRemoteStationManager ("ns3::IdealWifiManager");
147
148 // 802.11b STA
149 wifi.SetStandard (WIFI_STANDARD_80211b);
150
151 WifiMacHelper mac;
152 Ssid ssid = Ssid ("ns-3-ssid");
153
154 mac.SetType ("ns3::StaWifiMac",
155 "Ssid", SsidValue (ssid),
156 "ShortSlotTimeSupported", BooleanValue (params.enableShortSlotTime));
157
158 // Configure the PHY preamble type: long or short
159 phy.Set ("ShortPlcpPreambleSupported", BooleanValue (params.enableShortPhyPreamble));
160
161 NetDeviceContainer bStaDevice;
162 bStaDevice = wifi.Install (phy, mac, wifiBStaNodes);
163
164 // 802.11b/g STA
165 wifi.SetStandard (WIFI_STANDARD_80211g);
166 NetDeviceContainer gStaDevice;
167 gStaDevice = wifi.Install (phy, mac, wifiGStaNodes);
168
169 // 802.11b/g/n STA
170 wifi.SetStandard (WIFI_STANDARD_80211n_2_4GHZ);
171 NetDeviceContainer nStaDevice;
172 mac.SetType ("ns3::StaWifiMac",
173 "Ssid", SsidValue (ssid),
174 "BE_BlockAckThreshold", UintegerValue (2),
175 "ShortSlotTimeSupported", BooleanValue (params.enableShortSlotTime));
176 nStaDevice = wifi.Install (phy, mac, wifiNStaNodes);
177
178 // AP
179 NetDeviceContainer apDevice;
180 wifi.SetStandard (params.apType);
181 mac.SetType ("ns3::ApWifiMac",
182 "Ssid", SsidValue (ssid),
183 "EnableBeaconJitter", BooleanValue (false),
184 "BE_BlockAckThreshold", UintegerValue (2),
185 "EnableNonErpProtection", BooleanValue (params.enableErpProtection),
186 "ShortSlotTimeSupported", BooleanValue (params.enableShortSlotTime));
187 apDevice = wifi.Install (phy, mac, wifiApNode);
188
189 // Set TXOP limit
190 if (params.apType == WIFI_STANDARD_80211n_2_4GHZ)
191 {
192 Ptr<NetDevice> dev = wifiApNode.Get (0)->GetDevice (0);
193 Ptr<WifiNetDevice> wifi_dev = DynamicCast<WifiNetDevice> (dev);
194 Ptr<WifiMac> wifi_mac = wifi_dev->GetMac ();
195 PointerValue ptr;
196 wifi_mac->GetAttribute ("BE_Txop", ptr);
197 Ptr<QosTxop> edca = ptr.Get<QosTxop> ();
198 edca->SetTxopLimit (MicroSeconds (3008));
199 }
200 if (nWifiN > 0)
201 {
202 Ptr<NetDevice> dev = wifiNStaNodes.Get (0)->GetDevice (0);
203 Ptr<WifiNetDevice> wifi_dev = DynamicCast<WifiNetDevice> (dev);
204 Ptr<WifiMac> wifi_mac = wifi_dev->GetMac ();
205 PointerValue ptr;
206 wifi_mac->GetAttribute ("BE_Txop", ptr);
207 Ptr<QosTxop> edca = ptr.Get<QosTxop> ();
208 edca->SetTxopLimit (MicroSeconds (3008));
209 }
210
211 Config::Set ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/BE_MaxAmpduSize", UintegerValue (0)); //Disable A-MPDU
212
213 // Define mobility model
214 MobilityHelper mobility;
215 Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
216
217 positionAlloc->Add (Vector (0.0, 0.0, 0.0));
218 for (uint32_t i = 0; i < nWifiB; i++)
219 {
220 positionAlloc->Add (Vector (5.0, 0.0, 0.0));
221 }
222 for (uint32_t i = 0; i < nWifiG; i++)
223 {
224 positionAlloc->Add (Vector (0.0, 5.0, 0.0));
225 }
226 for (uint32_t i = 0; i < nWifiN; i++)
227 {
228 positionAlloc->Add (Vector (0.0, 0.0, 5.0));
229 }
230
231 mobility.SetPositionAllocator (positionAlloc);
232 mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
233 mobility.Install (wifiApNode);
234 mobility.Install (wifiBStaNodes);
235 mobility.Install (wifiGStaNodes);
236 mobility.Install (wifiNStaNodes);
237
238 // Internet stack
239 InternetStackHelper stack;
240 stack.Install (wifiApNode);
241 stack.Install (wifiBStaNodes);
242 stack.Install (wifiGStaNodes);
243 stack.Install (wifiNStaNodes);
244
245 Ipv4AddressHelper address;
246 address.SetBase ("192.168.1.0", "255.255.255.0");
247 Ipv4InterfaceContainer bStaInterface;
248 bStaInterface = address.Assign (bStaDevice);
249 Ipv4InterfaceContainer gStaInterface;
250 gStaInterface = address.Assign (gStaDevice);
251 Ipv4InterfaceContainer nStaInterface;
252 nStaInterface = address.Assign (nStaDevice);
253 Ipv4InterfaceContainer ApInterface;
254 ApInterface = address.Assign (apDevice);
255
256 // Setting applications
257 if (params.isUdp)
258 {
259 uint16_t port = 9;
260 UdpServerHelper server (port);
261 ApplicationContainer serverApp = server.Install (wifiApNode);
262 serverApp.Start (Seconds (0.0));
263 serverApp.Stop (Seconds (simulationTime + 1));
264
265 UdpClientHelper client (ApInterface.GetAddress (0), port);
266 client.SetAttribute ("MaxPackets", UintegerValue (4294967295u));
267 client.SetAttribute ("Interval", TimeValue (Time ("0.0002"))); //packets/s
268 client.SetAttribute ("PacketSize", UintegerValue (payloadSize));
269
270 ApplicationContainer clientApps;
271 if (params.bHasTraffic)
272 {
273 clientApps.Add (client.Install (wifiBStaNodes));
274 }
275 if (params.gHasTraffic)
276 {
277 clientApps.Add (client.Install (wifiGStaNodes));
278 }
279 if (params.nHasTraffic)
280 {
281 clientApps.Add (client.Install (wifiNStaNodes));
282 }
283 clientApps.Start (Seconds (1.0));
284 clientApps.Stop (Seconds (simulationTime + 1));
285
286 Simulator::Stop (Seconds (simulationTime + 1));
287 Simulator::Run ();
288
289 uint64_t totalPacketsThrough = DynamicCast<UdpServer> (serverApp.Get (0))->GetReceived ();
290 throughput = totalPacketsThrough * payloadSize * 8 / (simulationTime * 1000000.0);
291 }
292 else
293 {
294 uint16_t port = 50000;
295 Address localAddress (InetSocketAddress (Ipv4Address::GetAny (), port));
296 PacketSinkHelper packetSinkHelper ("ns3::TcpSocketFactory", localAddress);
297
298 ApplicationContainer serverApp = packetSinkHelper.Install (wifiApNode.Get (0));
299 serverApp.Start (Seconds (0.0));
300 serverApp.Stop (Seconds (simulationTime + 1));
301
302 OnOffHelper onoff ("ns3::TcpSocketFactory", Ipv4Address::GetAny ());
303 onoff.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
304 onoff.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
305 onoff.SetAttribute ("PacketSize", UintegerValue (payloadSize));
306 onoff.SetAttribute ("DataRate", DataRateValue (150000000)); //bit/s
307
308 AddressValue remoteAddress (InetSocketAddress (ApInterface.GetAddress (0), port));
309 onoff.SetAttribute ("Remote", remoteAddress);
310
311 ApplicationContainer clientApps;
312 if (params.bHasTraffic)
313 {
314 clientApps.Add (onoff.Install (wifiBStaNodes));
315 }
316 if (params.gHasTraffic)
317 {
318 clientApps.Add (onoff.Install (wifiGStaNodes));
319 }
320 if (params.nHasTraffic)
321 {
322 clientApps.Add (onoff.Install (wifiNStaNodes));
323 }
324 clientApps.Start (Seconds (1.0));
325 clientApps.Stop (Seconds (simulationTime + 1));
326
327 Simulator::Stop (Seconds (simulationTime + 1));
328 Simulator::Run ();
329
330 uint64_t totalPacketsThrough = DynamicCast<PacketSink> (serverApp.Get (0))->GetTotalRx ();
331 throughput += totalPacketsThrough * 8 / (simulationTime * 1000000.0);
332 }
333 Simulator::Destroy ();
334 return throughput;
335 }
336
main(int argc,char * argv[])337 int main (int argc, char *argv[])
338 {
339 Parameters params;
340 params.testName = "";
341 params.enableErpProtection = false;
342 params.erpProtectionMode = "Cts-To-Self";
343 params.enableShortSlotTime = false;
344 params.enableShortPhyPreamble = false;
345 params.apType = WIFI_STANDARD_80211g;
346 params.nWifiB = 0;
347 params.bHasTraffic = false;
348 params.nWifiG = 1;
349 params.gHasTraffic = true;
350 params.nWifiN = 0;
351 params.nHasTraffic = false;
352 params.isUdp = true;
353 params.payloadSize = 1472; //bytes
354 params.simulationTime = 10; //seconds
355
356 bool verifyResults = 0; //used for regression
357
358 CommandLine cmd (__FILE__);
359 cmd.AddValue ("payloadSize", "Payload size in bytes", params.payloadSize);
360 cmd.AddValue ("simulationTime", "Simulation time in seconds", params.simulationTime);
361 cmd.AddValue ("isUdp", "UDP if set to 1, TCP otherwise", params.isUdp);
362 cmd.AddValue ("verifyResults", "Enable/disable results verification at the end of the simulation", verifyResults);
363 cmd.Parse (argc, argv);
364
365 Experiment experiment;
366 double throughput = 0;
367
368 params.testName = "g only with all g features disabled";
369 throughput = experiment.Run (params);
370 if (verifyResults && (throughput < 22.5 || throughput > 23.5))
371 {
372 NS_LOG_ERROR ("Obtained throughput " << throughput << " is not in the expected boundaries!");
373 exit (1);
374 }
375 std::cout << "Throughput: " << throughput << " Mbit/s \n" << std::endl;
376
377 params.testName = "g only with short slot time enabled";
378 params.enableErpProtection = false;
379 params.enableShortSlotTime = true;
380 params.enableShortPhyPreamble = false;
381 params.nWifiB = 0;
382 throughput = experiment.Run (params);
383 if (verifyResults && (throughput < 29 || throughput > 30))
384 {
385 NS_LOG_ERROR ("Obtained throughput " << throughput << " is not in the expected boundaries!");
386 exit (1);
387 }
388 std::cout << "Throughput: " << throughput << " Mbit/s \n" << std::endl;
389
390 params.testName = "Mixed b/g with all g features disabled";
391 params.enableErpProtection = false;
392 params.enableShortSlotTime = false;
393 params.enableShortPhyPreamble = false;
394 params.nWifiB = 1;
395 throughput = experiment.Run (params);
396 if (verifyResults && (throughput < 22.5 || throughput > 23.5))
397 {
398 NS_LOG_ERROR ("Obtained throughput " << throughput << " is not in the expected boundaries!");
399 exit (1);
400 }
401 std::cout << "Throughput: " << throughput << " Mbit/s \n" << std::endl;
402
403 params.testName = "Mixed b/g with short plcp preamble enabled";
404 params.enableErpProtection = false;
405 params.enableShortSlotTime = false;
406 params.enableShortPhyPreamble = true;
407 params.nWifiB = 1;
408 throughput = experiment.Run (params);
409 if (verifyResults && (throughput < 22.5 || throughput > 23.5))
410 {
411 NS_LOG_ERROR ("Obtained throughput " << throughput << " is not in the expected boundaries!");
412 exit (1);
413 }
414 std::cout << "Throughput: " << throughput << " Mbit/s \n" << std::endl;
415
416 params.testName = "Mixed b/g with short slot time enabled using RTS-CTS protection";
417 params.enableErpProtection = true;
418 params.erpProtectionMode = "Rts-Cts";
419 params.enableShortSlotTime = false;
420 params.enableShortPhyPreamble = false;
421 params.nWifiB = 1;
422 throughput = experiment.Run (params);
423 if (verifyResults && (throughput < 19 || throughput > 20))
424 {
425 NS_LOG_ERROR ("Obtained throughput " << throughput << " is not in the expected boundaries!");
426 exit (1);
427 }
428 std::cout << "Throughput: " << throughput << " Mbit/s \n" << std::endl;
429
430 params.testName = "Mixed b/g with short plcp preamble enabled using RTS-CTS protection";
431 params.enableErpProtection = true;
432 params.enableShortSlotTime = false;
433 params.enableShortPhyPreamble = true;
434 params.nWifiB = 1;
435 throughput = experiment.Run (params);
436 if (verifyResults && (throughput < 19 || throughput > 20))
437 {
438 NS_LOG_ERROR ("Obtained throughput " << throughput << " is not in the expected boundaries!");
439 exit (1);
440 }
441 std::cout << "Throughput: " << throughput << " Mbit/s \n" << std::endl;
442
443 params.testName = "Mixed b/g with short slot time enabled using CTS-TO-SELF protection";
444 params.enableErpProtection = true;
445 params.erpProtectionMode = "Cts-To-Self";
446 params.enableShortSlotTime = false;
447 params.enableShortPhyPreamble = false;
448 params.nWifiB = 1;
449 throughput = experiment.Run (params);
450 if (verifyResults && (throughput < 20.5 || throughput > 21.5))
451 {
452 NS_LOG_ERROR ("Obtained throughput " << throughput << " is not in the expected boundaries!");
453 exit (1);
454 }
455 std::cout << "Throughput: " << throughput << " Mbit/s \n" << std::endl;
456
457 params.testName = "Mixed b/g with short plcp preamble enabled using CTS-TO-SELF protection";
458 params.enableErpProtection = true;
459 params.enableShortSlotTime = false;
460 params.enableShortPhyPreamble = true;
461 params.nWifiB = 1;
462 throughput = experiment.Run (params);
463 if (verifyResults && (throughput < 20.5 || throughput > 21.5))
464 {
465 NS_LOG_ERROR ("Obtained throughput " << throughput << " is not in the expected boundaries!");
466 exit (1);
467 }
468 std::cout << "Throughput: " << throughput << " Mbit/s \n" << std::endl;
469
470 params.testName = "HT only";
471 params.enableErpProtection = false;
472 params.enableShortSlotTime = false;
473 params.enableShortPhyPreamble = false;
474 params.apType = WIFI_STANDARD_80211n_2_4GHZ;
475 params.nWifiB = 0;
476 params.bHasTraffic = false;
477 params.nWifiG = 0;
478 params.gHasTraffic = false;
479 params.nWifiN = 1;
480 params.nHasTraffic = true;
481 throughput = experiment.Run (params);
482 if (verifyResults && (throughput < 44 || throughput > 45))
483 {
484 NS_LOG_ERROR ("Obtained throughput " << throughput << " is not in the expected boundaries!");
485 exit (1);
486 }
487 std::cout << "Throughput: " << throughput << " Mbit/s \n" << std::endl;
488
489 params.testName = "Mixed HT/non-HT";
490 params.enableErpProtection = false;
491 params.enableShortSlotTime = false;
492 params.enableShortPhyPreamble = false;
493 params.apType = WIFI_STANDARD_80211n_2_4GHZ;
494 params.nWifiB = 0;
495 params.bHasTraffic = false;
496 params.nWifiG = 1;
497 params.gHasTraffic = false;
498 params.nWifiN = 1;
499 params.nHasTraffic = true;
500 throughput = experiment.Run (params);
501 if (verifyResults && (throughput < 44 || throughput > 45))
502 {
503 NS_LOG_ERROR ("Obtained throughput " << throughput << " is not in the expected boundaries!");
504 exit (1);
505 }
506 std::cout << "Throughput: " << throughput << " Mbit/s \n" << std::endl;
507
508 return 0;
509 }
510