A Discrete-Event Network Simulator
API
wifi-aggregation.cc
Go to the documentation of this file.
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/uinteger.h"
24 #include "ns3/boolean.h"
25 #include "ns3/string.h"
26 #include "ns3/log.h"
27 #include "ns3/yans-wifi-helper.h"
28 #include "ns3/ssid.h"
29 #include "ns3/mobility-helper.h"
30 #include "ns3/internet-stack-helper.h"
31 #include "ns3/ipv4-address-helper.h"
32 #include "ns3/udp-client-server-helper.h"
33 #include "ns3/packet-sink-helper.h"
34 #include "ns3/yans-wifi-channel.h"
35 #include "ns3/wifi-net-device.h"
36 #include "ns3/wifi-mac.h"
37 
38 // This is an example that illustrates how 802.11n aggregation is configured.
39 // It defines 4 independent Wi-Fi networks (working on different channels).
40 // Each network contains one access point and one station. Each station
41 // continuously transmits data packets to its respective AP.
42 //
43 // Network topology (numbers in parentheses are channel numbers):
44 //
45 // Network A (36) Network B (40) Network C (44) Network D (48)
46 // * * * * * * * *
47 // | | | | | | | |
48 // AP A STA A AP B STA B AP C STA C AP D STA D
49 //
50 // The aggregation parameters are configured differently on the 4 stations:
51 // - station A uses default aggregation parameter values (A-MSDU disabled, A-MPDU enabled with maximum size of 65 kB);
52 // - station B doesn't use aggregation (both A-MPDU and A-MSDU are disabled);
53 // - station C enables A-MSDU (with maximum size of 8 kB) but disables A-MPDU;
54 // - station D uses two-level aggregation (A-MPDU with maximum size of 32 kB and A-MSDU with maximum size of 4 kB).
55 //
56 //Packets in this simulation belong to BestEffort Access Class (AC_BE).
57 //
58 // The user can select the distance between the stations and the APs and can enable/disable the RTS/CTS mechanism.
59 // Example: ./waf --run "wifi-aggregation --distance=10 --enableRts=0 --simulationTime=20"
60 //
61 // The output prints the throughput measured for the 4 cases/networks described above. When default aggregation parameters are enabled, the
62 // maximum A-MPDU size is 65 kB and the throughput is maximal. When aggregation is disabled, the throughput is about the half of the physical
63 // bitrate. When only A-MSDU is enabled, the throughput is increased but is not maximal, since the maximum A-MSDU size is limited to 7935 bytes
64 // (whereas the maximum A-MPDU size is limited to 65535 bytes). When A-MSDU and A-MPDU are both enabled (= two-level aggregation),
65 // the throughput is slightly smaller than the first scenario since we set a smaller maximum A-MPDU size.
66 //
67 // When the distance is increased, the frame error rate gets higher, and the output shows how it affects the throughput for the 4 networks.
68 // Even through A-MSDU has less overheads than A-MPDU, A-MSDU is less robust against transmission errors than A-MPDU. When the distance is
69 // augmented, the throughput for the third scenario is more affected than the throughput obtained in other networks.
70 
71 using namespace ns3;
72 
73 NS_LOG_COMPONENT_DEFINE ("SimpleMpduAggregation");
74 
75 int main (int argc, char *argv[])
76 {
77  uint32_t payloadSize = 1472; //bytes
78  double simulationTime = 10; //seconds
79  double distance = 5; //meters
80  bool enableRts = 0;
81  bool enablePcap = 0;
82  bool verifyResults = 0; //used for regression
83 
84  CommandLine cmd (__FILE__);
85  cmd.AddValue ("payloadSize", "Payload size in bytes", payloadSize);
86  cmd.AddValue ("enableRts", "Enable or disable RTS/CTS", enableRts);
87  cmd.AddValue ("simulationTime", "Simulation time in seconds", simulationTime);
88  cmd.AddValue ("distance", "Distance in meters between the station and the access point", distance);
89  cmd.AddValue ("enablePcap", "Enable/disable pcap file generation", enablePcap);
90  cmd.AddValue ("verifyResults", "Enable/disable results verification at the end of the simulation", verifyResults);
91  cmd.Parse (argc, argv);
92 
93  Config::SetDefault ("ns3::WifiRemoteStationManager::RtsCtsThreshold", enableRts ? StringValue ("0") : StringValue ("999999"));
94 
96  wifiStaNodes.Create (4);
97  NodeContainer wifiApNodes;
98  wifiApNodes.Create (4);
99 
102  phy.SetPcapDataLinkType (WifiPhyHelper::DLT_IEEE802_11_RADIO);
103  phy.SetChannel (channel.Create ());
104 
106  wifi.SetStandard (WIFI_STANDARD_80211n_5GHZ);
107  wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager", "DataMode", StringValue ("HtMcs7"), "ControlMode", StringValue ("HtMcs0"));
109 
110  NetDeviceContainer staDeviceA, staDeviceB, staDeviceC, staDeviceD, apDeviceA, apDeviceB, apDeviceC, apDeviceD;
111  Ssid ssid;
112 
113  // Network A
114  ssid = Ssid ("network-A");
115  phy.Set ("ChannelNumber", UintegerValue (36));
116  mac.SetType ("ns3::StaWifiMac",
117  "Ssid", SsidValue (ssid));
118  staDeviceA = wifi.Install (phy, mac, wifiStaNodes.Get (0));
119 
120  mac.SetType ("ns3::ApWifiMac",
121  "Ssid", SsidValue (ssid),
122  "EnableBeaconJitter", BooleanValue (false));
123  apDeviceA = wifi.Install (phy, mac, wifiApNodes.Get (0));
124 
125  // Network B
126  ssid = Ssid ("network-B");
127  phy.Set ("ChannelNumber", UintegerValue (40));
128  mac.SetType ("ns3::StaWifiMac",
129  "Ssid", SsidValue (ssid));
130 
131  staDeviceB = wifi.Install (phy, mac, wifiStaNodes.Get (1));
132 
133  // Disable A-MPDU
134  Ptr<NetDevice> dev = wifiStaNodes.Get (1)->GetDevice (0);
135  Ptr<WifiNetDevice> wifi_dev = DynamicCast<WifiNetDevice> (dev);
136  wifi_dev->GetMac ()->SetAttribute ("BE_MaxAmpduSize", UintegerValue (0));
137 
138  mac.SetType ("ns3::ApWifiMac",
139  "Ssid", SsidValue (ssid),
140  "EnableBeaconJitter", BooleanValue (false));
141  apDeviceB = wifi.Install (phy, mac, wifiApNodes.Get (1));
142 
143  // Disable A-MPDU
144  dev = wifiApNodes.Get (1)->GetDevice (0);
145  wifi_dev = DynamicCast<WifiNetDevice> (dev);
146  wifi_dev->GetMac ()->SetAttribute ("BE_MaxAmpduSize", UintegerValue (0));
147 
148  // Network C
149  ssid = Ssid ("network-C");
150  phy.Set ("ChannelNumber", UintegerValue (44));
151  mac.SetType ("ns3::StaWifiMac",
152  "Ssid", SsidValue (ssid));
153 
154  staDeviceC = wifi.Install (phy, mac, wifiStaNodes.Get (2));
155 
156  // Disable A-MPDU and enable A-MSDU with the highest maximum size allowed by the standard (7935 bytes)
157  dev = wifiStaNodes.Get (2)->GetDevice (0);
158  wifi_dev = DynamicCast<WifiNetDevice> (dev);
159  wifi_dev->GetMac ()->SetAttribute ("BE_MaxAmpduSize", UintegerValue (0));
160  wifi_dev->GetMac ()->SetAttribute ("BE_MaxAmsduSize", UintegerValue (7935));
161 
162  mac.SetType ("ns3::ApWifiMac",
163  "Ssid", SsidValue (ssid),
164  "EnableBeaconJitter", BooleanValue (false));
165  apDeviceC = wifi.Install (phy, mac, wifiApNodes.Get (2));
166 
167  // Disable A-MPDU and enable A-MSDU with the highest maximum size allowed by the standard (7935 bytes)
168  dev = wifiApNodes.Get (2)->GetDevice (0);
169  wifi_dev = DynamicCast<WifiNetDevice> (dev);
170  wifi_dev->GetMac ()->SetAttribute ("BE_MaxAmpduSize", UintegerValue (0));
171  wifi_dev->GetMac ()->SetAttribute ("BE_MaxAmsduSize", UintegerValue (7935));
172 
173  // Network D
174  ssid = Ssid ("network-D");
175  phy.Set ("ChannelNumber", UintegerValue (48));
176  mac.SetType ("ns3::StaWifiMac",
177  "Ssid", SsidValue (ssid));
178 
179  staDeviceD = wifi.Install (phy, mac, wifiStaNodes.Get (3));
180 
181  // Enable A-MPDU with a smaller size than the default one and
182  // enable A-MSDU with the smallest maximum size allowed by the standard (3839 bytes)
183  dev = wifiStaNodes.Get (3)->GetDevice (0);
184  wifi_dev = DynamicCast<WifiNetDevice> (dev);
185  wifi_dev->GetMac ()->SetAttribute ("BE_MaxAmpduSize", UintegerValue (32768));
186  wifi_dev->GetMac ()->SetAttribute ("BE_MaxAmsduSize", UintegerValue (3839));
187 
188  mac.SetType ("ns3::ApWifiMac",
189  "Ssid", SsidValue (ssid),
190  "EnableBeaconJitter", BooleanValue (false));
191  apDeviceD = wifi.Install (phy, mac, wifiApNodes.Get (3));
192 
193  // Enable A-MPDU with a smaller size than the default one and
194  // enable A-MSDU with the smallest maximum size allowed by the standard (3839 bytes)
195  dev = wifiApNodes.Get (3)->GetDevice (0);
196  wifi_dev = DynamicCast<WifiNetDevice> (dev);
197  wifi_dev->GetMac ()->SetAttribute ("BE_MaxAmpduSize", UintegerValue (32768));
198  wifi_dev->GetMac ()->SetAttribute ("BE_MaxAmsduSize", UintegerValue (3839));
199 
200  // Setting mobility model
202  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
203  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
204 
205  // Set position for APs
206  positionAlloc->Add (Vector (0.0, 0.0, 0.0));
207  positionAlloc->Add (Vector (10.0, 0.0, 0.0));
208  positionAlloc->Add (Vector (20.0, 0.0, 0.0));
209  positionAlloc->Add (Vector (30.0, 0.0, 0.0));
210  // Set position for STAs
211  positionAlloc->Add (Vector (distance, 0.0, 0.0));
212  positionAlloc->Add (Vector (10 + distance, 0.0, 0.0));
213  positionAlloc->Add (Vector (20 + distance, 0.0, 0.0));
214  positionAlloc->Add (Vector (30 + distance, 0.0, 0.0));
215 
216  mobility.SetPositionAllocator (positionAlloc);
217  mobility.Install (wifiApNodes);
218  mobility.Install (wifiStaNodes);
219 
220  // Internet stack
222  stack.Install (wifiApNodes);
223  stack.Install (wifiStaNodes);
224 
226  address.SetBase ("192.168.1.0", "255.255.255.0");
227  Ipv4InterfaceContainer StaInterfaceA;
228  StaInterfaceA = address.Assign (staDeviceA);
229  Ipv4InterfaceContainer ApInterfaceA;
230  ApInterfaceA = address.Assign (apDeviceA);
231 
232  address.SetBase ("192.168.2.0", "255.255.255.0");
233  Ipv4InterfaceContainer StaInterfaceB;
234  StaInterfaceB = address.Assign (staDeviceB);
235  Ipv4InterfaceContainer ApInterfaceB;
236  ApInterfaceB = address.Assign (apDeviceB);
237 
238  address.SetBase ("192.168.3.0", "255.255.255.0");
239  Ipv4InterfaceContainer StaInterfaceC;
240  StaInterfaceC = address.Assign (staDeviceC);
241  Ipv4InterfaceContainer ApInterfaceC;
242  ApInterfaceC = address.Assign (apDeviceC);
243 
244  address.SetBase ("192.168.4.0", "255.255.255.0");
245  Ipv4InterfaceContainer StaInterfaceD;
246  StaInterfaceD = address.Assign (staDeviceD);
247  Ipv4InterfaceContainer ApInterfaceD;
248  ApInterfaceD = address.Assign (apDeviceD);
249 
250  // Setting applications
251  uint16_t port = 9;
252  UdpServerHelper serverA (port);
253  ApplicationContainer serverAppA = serverA.Install (wifiStaNodes.Get (0));
254  serverAppA.Start (Seconds (0.0));
255  serverAppA.Stop (Seconds (simulationTime + 1));
256 
257  UdpClientHelper clientA (StaInterfaceA.GetAddress (0), port);
258  clientA.SetAttribute ("MaxPackets", UintegerValue (4294967295u));
259  clientA.SetAttribute ("Interval", TimeValue (Time ("0.0001"))); //packets/s
260  clientA.SetAttribute ("PacketSize", UintegerValue (payloadSize));
261 
262  ApplicationContainer clientAppA = clientA.Install (wifiApNodes.Get (0));
263  clientAppA.Start (Seconds (1.0));
264  clientAppA.Stop (Seconds (simulationTime + 1));
265 
266  UdpServerHelper serverB (port);
267  ApplicationContainer serverAppB = serverB.Install (wifiStaNodes.Get (1));
268  serverAppB.Start (Seconds (0.0));
269  serverAppB.Stop (Seconds (simulationTime + 1));
270 
271  UdpClientHelper clientB (StaInterfaceB.GetAddress (0), port);
272  clientB.SetAttribute ("MaxPackets", UintegerValue (4294967295u));
273  clientB.SetAttribute ("Interval", TimeValue (Time ("0.0001"))); //packets/s
274  clientB.SetAttribute ("PacketSize", UintegerValue (payloadSize));
275 
276  ApplicationContainer clientAppB = clientB.Install (wifiApNodes.Get (1));
277  clientAppB.Start (Seconds (1.0));
278  clientAppB.Stop (Seconds (simulationTime + 1));
279 
280  UdpServerHelper serverC (port);
281  ApplicationContainer serverAppC = serverC.Install (wifiStaNodes.Get (2));
282  serverAppC.Start (Seconds (0.0));
283  serverAppC.Stop (Seconds (simulationTime + 1));
284 
285  UdpClientHelper clientC (StaInterfaceC.GetAddress (0), port);
286  clientC.SetAttribute ("MaxPackets", UintegerValue (4294967295u));
287  clientC.SetAttribute ("Interval", TimeValue (Time ("0.0001"))); //packets/s
288  clientC.SetAttribute ("PacketSize", UintegerValue (payloadSize));
289 
290  ApplicationContainer clientAppC = clientC.Install (wifiApNodes.Get (2));
291  clientAppC.Start (Seconds (1.0));
292  clientAppC.Stop (Seconds (simulationTime + 1));
293 
294  UdpServerHelper serverD (port);
295  ApplicationContainer serverAppD = serverD.Install (wifiStaNodes.Get (3));
296  serverAppD.Start (Seconds (0.0));
297  serverAppD.Stop (Seconds (simulationTime + 1));
298 
299  UdpClientHelper clientD (StaInterfaceD.GetAddress (0), port);
300  clientD.SetAttribute ("MaxPackets", UintegerValue (4294967295u));
301  clientD.SetAttribute ("Interval", TimeValue (Time ("0.0001"))); //packets/s
302  clientD.SetAttribute ("PacketSize", UintegerValue (payloadSize));
303 
304  ApplicationContainer clientAppD = clientD.Install (wifiApNodes.Get (3));
305  clientAppD.Start (Seconds (1.0));
306  clientAppD.Stop (Seconds (simulationTime + 1));
307 
308  if (enablePcap)
309  {
310  phy.EnablePcap ("AP_A", apDeviceA.Get (0));
311  phy.EnablePcap ("STA_A", staDeviceA.Get (0));
312  phy.EnablePcap ("AP_B", apDeviceB.Get (0));
313  phy.EnablePcap ("STA_B", staDeviceB.Get (0));
314  phy.EnablePcap ("AP_C", apDeviceC.Get (0));
315  phy.EnablePcap ("STA_C", staDeviceC.Get (0));
316  phy.EnablePcap ("AP_D", apDeviceD.Get (0));
317  phy.EnablePcap ("STA_D", staDeviceD.Get (0));
318  }
319 
320  Simulator::Stop (Seconds (simulationTime + 1));
321  Simulator::Run ();
322 
323  // Show results
324  uint64_t totalPacketsThroughA = DynamicCast<UdpServer> (serverAppA.Get (0))->GetReceived ();
325  uint64_t totalPacketsThroughB = DynamicCast<UdpServer> (serverAppB.Get (0))->GetReceived ();
326  uint64_t totalPacketsThroughC = DynamicCast<UdpServer> (serverAppC.Get (0))->GetReceived ();
327  uint64_t totalPacketsThroughD = DynamicCast<UdpServer> (serverAppD.Get (0))->GetReceived ();
328 
330 
331  double throughput = totalPacketsThroughA * payloadSize * 8 / (simulationTime * 1000000.0);
332  std::cout << "Throughput with default configuration (A-MPDU aggregation enabled, 65kB): " << throughput << " Mbit/s" << '\n';
333  if (verifyResults && (throughput < 58.5 || throughput > 59.5))
334  {
335  NS_LOG_ERROR ("Obtained throughput " << throughput << " is not in the expected boundaries!");
336  exit (1);
337  }
338 
339  throughput = totalPacketsThroughB * payloadSize * 8 / (simulationTime * 1000000.0);
340  std::cout << "Throughput with aggregation disabled: " << throughput << " Mbit/s" << '\n';
341  if (verifyResults && (throughput < 30 || throughput > 31))
342  {
343  NS_LOG_ERROR ("Obtained throughput " << throughput << " is not in the expected boundaries!");
344  exit (1);
345  }
346 
347  throughput = totalPacketsThroughC * payloadSize * 8 / (simulationTime * 1000000.0);
348  std::cout << "Throughput with A-MPDU disabled and A-MSDU enabled (8kB): " << throughput << " Mbit/s" << '\n';
349  if (verifyResults && (throughput < 51 || throughput > 52))
350  {
351  NS_LOG_ERROR ("Obtained throughput " << throughput << " is not in the expected boundaries!");
352  exit (1);
353  }
354 
355  throughput = totalPacketsThroughD * payloadSize * 8 / (simulationTime * 1000000.0);
356  std::cout << "Throughput with A-MPDU enabled (32kB) and A-MSDU enabled (4kB): " << throughput << " Mbit/s" << '\n';
357  if (verifyResults && (throughput < 58 || throughput > 59))
358  {
359  NS_LOG_ERROR ("Obtained throughput " << throughput << " is not in the expected boundaries!");
360  exit (1);
361  }
362 
363  return 0;
364 }
holds a vector of ns3::Application pointers.
Ptr< NetDevice > Get(uint32_t i) const
Get the Ptr<NetDevice> stored in this container at a given index.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:73
AttributeValue implementation for Boolean.
Definition: boolean.h:36
holds a vector of std::pair of Ptr<Ipv4> and interface index.
Hold variables of type string.
Definition: string.h:41
Make it easy to create and manage PHY objects for the YANS model.
static YansWifiChannelHelper Default(void)
Create a channel helper in a default working state.
Ptr< NetDevice > GetDevice(uint32_t index) const
Retrieve the index-th NetDevice associated to this node.
Definition: node.cc:144
bool enablePcap
static void Run(void)
Run the simulation.
Definition: simulator.cc:172
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
aggregate IP/TCP/UDP functionality to existing Nodes.
cmd
Definition: second.py:35
helps to create WifiNetDevice objects
Definition: wifi-helper.h:326
stack
Definition: first.py:41
uint16_t port
Definition: dsdv-manet.cc:45
channel
Definition: third.py:92
mobility
Definition: third.py:108
phy
Definition: third.py:93
Create a client application which sends UDP packets carrying a 32bit sequence number and a 64 bit tim...
AttributeValue implementation for Time.
Definition: nstime.h:1353
Ipv4Address GetAddress(uint32_t i, uint32_t j=0) const
Hold an unsigned integer type.
Definition: uinteger.h:44
ssid
Definition: third.py:100
holds a vector of ns3::NetDevice pointers
mac
Definition: third.py:99
Create a server application which waits for input UDP packets and uses the information carried into t...
void Start(Time start)
Arrange for all of the Applications in this container to Start() at the Time given as a parameter...
Parse command-line arguments.
Definition: command-line.h:227
static void Destroy(void)
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:136
void SetAttribute(std::string name, const AttributeValue &value)
Record an attribute to be set in each Application after it is is created.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
keep track of a set of node pointers.
address
Definition: first.py:44
manage and create wifi channel objects for the YANS model.
create MAC layers for a ns3::WifiNetDevice.
The IEEE 802.11 SSID Information Element.
Definition: ssid.h:35
wifi
Definition: third.py:96
Helper class used to assign positions and mobility models to nodes.
void Stop(Time stop)
Arrange for all of the Applications in this container to Stop() at the Time given as a parameter...
Ptr< WifiMac > GetMac(void) const
static void Stop(void)
Tell the Simulator the calling event should be the last one executed.
Definition: simulator.cc:180
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1289
AttributeValue implementation for Ssid.
Definition: ssid.h:105
void SetDefault(std::string name, const AttributeValue &value)
Definition: config.cc:849
void Add(Vector v)
Add a position to the list of positions.
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
A helper class to make life easier while doing simple IPv4 address assignment in scripts.
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition: log.h:257
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
wifiStaNodes
Definition: third.py:88
Include Radiotap link layer information.
Definition: wifi-helper.h:180
Ptr< Application > Get(uint32_t i) const
Get the Ptr<Application> stored in this container at a given index.