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