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 aren't marked with a QosTag so they
57 // are considered belonging to BestEffort Access Class (AC_BE).
58 //
59 // The user can select the distance between the stations and the APs and can enable/disable the RTS/CTS mechanism.
60 // Example: ./waf --run "wifi-aggregation --distance=10 --enableRts=0 --simulationTime=20"
61 //
62 // The output prints the throughput measured for the 4 cases/networks described above. When default aggregation parameters are enabled, the
63 // maximum A-MPDU size is 65 kB and the throughput is maximal. When aggregation is disabled, the throughput is about the half of the
64 // physical bitrate as in legacy wifi networks. When only A-MSDU is enabled, the throughput is increased but is not maximal, since the maximum
65 // A-MSDU size is limited to 7935 bytes (whereas the maximum A-MPDU size is limited to 65535 bytes). When A-MSDU and A-MPDU are both enabled
66 // (= two-level aggregation), the throughput is slightly smaller than the first scenario since we set a smaller maximum A-MPDU size.
67 //
68 // When the distance is increased, the frame error rate gets higher, and the output shows how it affects the throughput for the 4 networks.
69 // 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
70 // augmented, the throughput for the third scenario is more affected than the throughput obtained in other networks.
71 
72 using namespace ns3;
73 
74 NS_LOG_COMPONENT_DEFINE ("SimpleMpduAggregation");
75 
76 int main (int argc, char *argv[])
77 {
78  uint32_t payloadSize = 1472; //bytes
79  double simulationTime = 10; //seconds
80  double distance = 5; //meters
81  bool enableRts = 0;
82  bool enablePcap = 0;
83  bool verifyResults = 0; //used for regression
84 
86  cmd.AddValue ("payloadSize", "Payload size in bytes", payloadSize);
87  cmd.AddValue ("enableRts", "Enable or disable RTS/CTS", enableRts);
88  cmd.AddValue ("simulationTime", "Simulation time in seconds", simulationTime);
89  cmd.AddValue ("distance", "Distance in meters between the station and the access point", distance);
90  cmd.AddValue ("enablePcap", "Enable/disable pcap file generation", enablePcap);
91  cmd.AddValue ("verifyResults", "Enable/disable results verification at the end of the simulation", verifyResults);
92  cmd.Parse (argc, argv);
93 
94  Config::SetDefault ("ns3::WifiRemoteStationManager::RtsCtsThreshold", enableRts ? StringValue ("0") : StringValue ("999999"));
95 
97  wifiStaNodes.Create (4);
98  NodeContainer wifiApNodes;
99  wifiApNodes.Create (4);
100 
103  phy.SetPcapDataLinkType (WifiPhyHelper::DLT_IEEE802_11_RADIO);
104  phy.SetChannel (channel.Create ());
105 
107  wifi.SetStandard (WIFI_PHY_STANDARD_80211n_5GHZ);
108  wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager", "DataMode", StringValue ("HtMcs7"), "ControlMode", StringValue ("HtMcs0"));
110 
111  NetDeviceContainer staDeviceA, staDeviceB, staDeviceC, staDeviceD, apDeviceA, apDeviceB, apDeviceC, apDeviceD;
112  Ssid ssid;
113 
114  // Network A
115  ssid = Ssid ("network-A");
116  phy.Set ("ChannelNumber", UintegerValue (36));
117  mac.SetType ("ns3::StaWifiMac",
118  "Ssid", SsidValue (ssid));
119  staDeviceA = wifi.Install (phy, mac, wifiStaNodes.Get (0));
120 
121  mac.SetType ("ns3::ApWifiMac",
122  "Ssid", SsidValue (ssid),
123  "EnableBeaconJitter", BooleanValue (false));
124  apDeviceA = wifi.Install (phy, mac, wifiApNodes.Get (0));
125 
126  // Network B
127  ssid = Ssid ("network-B");
128  phy.Set ("ChannelNumber", UintegerValue (40));
129  mac.SetType ("ns3::StaWifiMac",
130  "Ssid", SsidValue (ssid));
131 
132  staDeviceB = wifi.Install (phy, mac, wifiStaNodes.Get (1));
133 
134  // Disable A-MPDU
135  Ptr<NetDevice> dev = wifiStaNodes.Get (1)->GetDevice (0);
136  Ptr<WifiNetDevice> wifi_dev = DynamicCast<WifiNetDevice> (dev);
137  wifi_dev->GetMac ()->SetAttribute ("BE_MaxAmpduSize", UintegerValue (0));
138 
139  mac.SetType ("ns3::ApWifiMac",
140  "Ssid", SsidValue (ssid),
141  "EnableBeaconJitter", BooleanValue (false));
142  apDeviceB = wifi.Install (phy, mac, wifiApNodes.Get (1));
143 
144  // Disable A-MPDU
145  dev = wifiApNodes.Get (1)->GetDevice (0);
146  wifi_dev = DynamicCast<WifiNetDevice> (dev);
147  wifi_dev->GetMac ()->SetAttribute ("BE_MaxAmpduSize", UintegerValue (0));
148 
149  // Network C
150  ssid = Ssid ("network-C");
151  phy.Set ("ChannelNumber", UintegerValue (44));
152  mac.SetType ("ns3::StaWifiMac",
153  "Ssid", SsidValue (ssid));
154 
155  staDeviceC = wifi.Install (phy, mac, wifiStaNodes.Get (2));
156 
157  // Disable A-MPDU and enable A-MSDU with the highest maximum size allowed by the standard (7935 bytes)
158  dev = wifiStaNodes.Get (2)->GetDevice (0);
159  wifi_dev = DynamicCast<WifiNetDevice> (dev);
160  wifi_dev->GetMac ()->SetAttribute ("BE_MaxAmpduSize", UintegerValue (0));
161  wifi_dev->GetMac ()->SetAttribute ("BE_MaxAmsduSize", UintegerValue (7935));
162 
163  mac.SetType ("ns3::ApWifiMac",
164  "Ssid", SsidValue (ssid),
165  "EnableBeaconJitter", BooleanValue (false));
166  apDeviceC = wifi.Install (phy, mac, wifiApNodes.Get (2));
167 
168  // Disable A-MPDU and enable A-MSDU with the highest maximum size allowed by the standard (7935 bytes)
169  dev = wifiApNodes.Get (2)->GetDevice (0);
170  wifi_dev = DynamicCast<WifiNetDevice> (dev);
171  wifi_dev->GetMac ()->SetAttribute ("BE_MaxAmpduSize", UintegerValue (0));
172  wifi_dev->GetMac ()->SetAttribute ("BE_MaxAmsduSize", UintegerValue (7935));
173 
174  // Network D
175  ssid = Ssid ("network-D");
176  phy.Set ("ChannelNumber", UintegerValue (48));
177  mac.SetType ("ns3::StaWifiMac",
178  "Ssid", SsidValue (ssid));
179 
180  staDeviceD = wifi.Install (phy, mac, wifiStaNodes.Get (3));
181 
182  // Enable A-MPDU with a smaller size than the default one and
183  // enable A-MSDU with the smallest maximum size allowed by the standard (3839 bytes)
184  dev = wifiStaNodes.Get (3)->GetDevice (0);
185  wifi_dev = DynamicCast<WifiNetDevice> (dev);
186  wifi_dev->GetMac ()->SetAttribute ("BE_MaxAmpduSize", UintegerValue (32768));
187  wifi_dev->GetMac ()->SetAttribute ("BE_MaxAmsduSize", UintegerValue (3839));
188 
189  mac.SetType ("ns3::ApWifiMac",
190  "Ssid", SsidValue (ssid),
191  "EnableBeaconJitter", BooleanValue (false));
192  apDeviceD = wifi.Install (phy, mac, wifiApNodes.Get (3));
193 
194  // Enable A-MPDU with a smaller size than the default one and
195  // enable A-MSDU with the smallest maximum size allowed by the standard (3839 bytes)
196  dev = wifiApNodes.Get (3)->GetDevice (0);
197  wifi_dev = DynamicCast<WifiNetDevice> (dev);
198  wifi_dev->GetMac ()->SetAttribute ("BE_MaxAmpduSize", UintegerValue (32768));
199  wifi_dev->GetMac ()->SetAttribute ("BE_MaxAmsduSize", UintegerValue (3839));
200 
201  // Setting mobility model
203  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
204  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
205 
206  // Set position for APs
207  positionAlloc->Add (Vector (0.0, 0.0, 0.0));
208  positionAlloc->Add (Vector (10.0, 0.0, 0.0));
209  positionAlloc->Add (Vector (20.0, 0.0, 0.0));
210  positionAlloc->Add (Vector (30.0, 0.0, 0.0));
211  // Set position for STAs
212  positionAlloc->Add (Vector (distance, 0.0, 0.0));
213  positionAlloc->Add (Vector (10 + distance, 0.0, 0.0));
214  positionAlloc->Add (Vector (20 + distance, 0.0, 0.0));
215  positionAlloc->Add (Vector (30 + distance, 0.0, 0.0));
216 
217  mobility.SetPositionAllocator (positionAlloc);
218  mobility.Install (wifiApNodes);
219  mobility.Install (wifiStaNodes);
220 
221  // Internet stack
223  stack.Install (wifiApNodes);
224  stack.Install (wifiStaNodes);
225 
227  address.SetBase ("192.168.1.0", "255.255.255.0");
228  Ipv4InterfaceContainer StaInterfaceA;
229  StaInterfaceA = address.Assign (staDeviceA);
230  Ipv4InterfaceContainer ApInterfaceA;
231  ApInterfaceA = address.Assign (apDeviceA);
232 
233  address.SetBase ("192.168.2.0", "255.255.255.0");
234  Ipv4InterfaceContainer StaInterfaceB;
235  StaInterfaceB = address.Assign (staDeviceB);
236  Ipv4InterfaceContainer ApInterfaceB;
237  ApInterfaceB = address.Assign (apDeviceB);
238 
239  address.SetBase ("192.168.3.0", "255.255.255.0");
240  Ipv4InterfaceContainer StaInterfaceC;
241  StaInterfaceC = address.Assign (staDeviceC);
242  Ipv4InterfaceContainer ApInterfaceC;
243  ApInterfaceC = address.Assign (apDeviceC);
244 
245  address.SetBase ("192.168.4.0", "255.255.255.0");
246  Ipv4InterfaceContainer StaInterfaceD;
247  StaInterfaceD = address.Assign (staDeviceD);
248  Ipv4InterfaceContainer ApInterfaceD;
249  ApInterfaceD = address.Assign (apDeviceD);
250 
251  // Setting applications
252  uint16_t port = 9;
253  UdpServerHelper serverA (port);
254  ApplicationContainer serverAppA = serverA.Install (wifiStaNodes.Get (0));
255  serverAppA.Start (Seconds (0.0));
256  serverAppA.Stop (Seconds (simulationTime + 1));
257 
258  UdpClientHelper clientA (StaInterfaceA.GetAddress (0), port);
259  clientA.SetAttribute ("MaxPackets", UintegerValue (4294967295u));
260  clientA.SetAttribute ("Interval", TimeValue (Time ("0.0001"))); //packets/s
261  clientA.SetAttribute ("PacketSize", UintegerValue (payloadSize));
262 
263  ApplicationContainer clientAppA = clientA.Install (wifiApNodes.Get (0));
264  clientAppA.Start (Seconds (1.0));
265  clientAppA.Stop (Seconds (simulationTime + 1));
266 
267  UdpServerHelper serverB (port);
268  ApplicationContainer serverAppB = serverB.Install (wifiStaNodes.Get (1));
269  serverAppB.Start (Seconds (0.0));
270  serverAppB.Stop (Seconds (simulationTime + 1));
271 
272  UdpClientHelper clientB (StaInterfaceB.GetAddress (0), port);
273  clientB.SetAttribute ("MaxPackets", UintegerValue (4294967295u));
274  clientB.SetAttribute ("Interval", TimeValue (Time ("0.0001"))); //packets/s
275  clientB.SetAttribute ("PacketSize", UintegerValue (payloadSize));
276 
277  ApplicationContainer clientAppB = clientB.Install (wifiApNodes.Get (1));
278  clientAppB.Start (Seconds (1.0));
279  clientAppB.Stop (Seconds (simulationTime + 1));
280 
281  UdpServerHelper serverC (port);
282  ApplicationContainer serverAppC = serverC.Install (wifiStaNodes.Get (2));
283  serverAppC.Start (Seconds (0.0));
284  serverAppC.Stop (Seconds (simulationTime + 1));
285 
286  UdpClientHelper clientC (StaInterfaceC.GetAddress (0), port);
287  clientC.SetAttribute ("MaxPackets", UintegerValue (4294967295u));
288  clientC.SetAttribute ("Interval", TimeValue (Time ("0.0001"))); //packets/s
289  clientC.SetAttribute ("PacketSize", UintegerValue (payloadSize));
290 
291  ApplicationContainer clientAppC = clientC.Install (wifiApNodes.Get (2));
292  clientAppC.Start (Seconds (1.0));
293  clientAppC.Stop (Seconds (simulationTime + 1));
294 
295  UdpServerHelper serverD (port);
296  ApplicationContainer serverAppD = serverD.Install (wifiStaNodes.Get (3));
297  serverAppD.Start (Seconds (0.0));
298  serverAppD.Stop (Seconds (simulationTime + 1));
299 
300  UdpClientHelper clientD (StaInterfaceD.GetAddress (0), port);
301  clientD.SetAttribute ("MaxPackets", UintegerValue (4294967295u));
302  clientD.SetAttribute ("Interval", TimeValue (Time ("0.0001"))); //packets/s
303  clientD.SetAttribute ("PacketSize", UintegerValue (payloadSize));
304 
305  ApplicationContainer clientAppD = clientD.Install (wifiApNodes.Get (3));
306  clientAppD.Start (Seconds (1.0));
307  clientAppD.Stop (Seconds (simulationTime + 1));
308 
309  if (enablePcap)
310  {
311  phy.EnablePcap ("AP_A", apDeviceA.Get (0));
312  phy.EnablePcap ("STA_A", staDeviceA.Get (0));
313  phy.EnablePcap ("AP_B", apDeviceB.Get (0));
314  phy.EnablePcap ("STA_B", staDeviceB.Get (0));
315  phy.EnablePcap ("AP_C", apDeviceC.Get (0));
316  phy.EnablePcap ("STA_C", staDeviceC.Get (0));
317  phy.EnablePcap ("AP_D", apDeviceD.Get (0));
318  phy.EnablePcap ("STA_D", staDeviceD.Get (0));
319  }
320 
321  Simulator::Stop (Seconds (simulationTime + 1));
322  Simulator::Run ();
323 
324  // Show results
325  uint64_t totalPacketsThroughA = DynamicCast<UdpServer> (serverAppA.Get (0))->GetReceived ();
326  uint64_t totalPacketsThroughB = DynamicCast<UdpServer> (serverAppB.Get (0))->GetReceived ();
327  uint64_t totalPacketsThroughC = DynamicCast<UdpServer> (serverAppC.Get (0))->GetReceived ();
328  uint64_t totalPacketsThroughD = DynamicCast<UdpServer> (serverAppD.Get (0))->GetReceived ();
329 
331 
332  double throughput = totalPacketsThroughA * payloadSize * 8 / (simulationTime * 1000000.0);
333  std::cout << "Throughput with default configuration (A-MPDU aggregation enabled, 65kB): " << throughput << " Mbit/s" << '\n';
334  if (verifyResults && (throughput < 58.5 || throughput > 59.5))
335  {
336  NS_LOG_ERROR ("Obtained throughput " << throughput << " is not in the expected boundaries!");
337  exit (1);
338  }
339 
340  throughput = totalPacketsThroughB * payloadSize * 8 / (simulationTime * 1000000.0);
341  std::cout << "Throughput with aggregation disabled: " << throughput << " Mbit/s" << '\n';
342  if (verifyResults && (throughput < 30 || throughput > 31))
343  {
344  NS_LOG_ERROR ("Obtained throughput " << throughput << " is not in the expected boundaries!");
345  exit (1);
346  }
347 
348  throughput = totalPacketsThroughC * payloadSize * 8 / (simulationTime * 1000000.0);
349  std::cout << "Throughput with A-MPDU disabled and A-MSDU enabled (8kB): " << throughput << " Mbit/s" << '\n';
350  if (verifyResults && (throughput < 51 || throughput > 52))
351  {
352  NS_LOG_ERROR ("Obtained throughput " << throughput << " is not in the expected boundaries!");
353  exit (1);
354  }
355 
356  throughput = totalPacketsThroughD * payloadSize * 8 / (simulationTime * 1000000.0);
357  std::cout << "Throughput with A-MPDU enabled (32kB) and A-MSDU enabled (4kB): " << throughput << " Mbit/s" << '\n';
358  if (verifyResults && (throughput < 58 || throughput > 59))
359  {
360  NS_LOG_ERROR ("Obtained throughput " << throughput << " is not in the expected boundaries!");
361  exit (1);
362  }
363 
364  return 0;
365 }
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:102
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:73
AttributeValue implementation for Boolean.
Definition: boolean.h:36
HT PHY for the 5 GHz band (clause 20)
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:142
bool enablePcap
static void Run(void)
Run the simulation.
Definition: simulator.cc:170
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:204
aggregate IP/TCP/UDP functionality to existing Nodes.
cmd
Definition: second.py:35
static YansWifiPhyHelper Default(void)
Create a phy helper in a default working state.
helps to create WifiNetDevice objects
Definition: wifi-helper.h:299
stack
Definition: first.py:34
uint16_t port
Definition: dsdv-manet.cc:45
channel
Definition: third.py:85
mobility
Definition: third.py:101
phy
Definition: third.py:86
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:1124
Ipv4Address GetAddress(uint32_t i, uint32_t j=0) const
Hold an unsigned integer type.
Definition: uinteger.h:44
ssid
Definition: third.py:93
holds a vector of ns3::NetDevice pointers
mac
Definition: third.py:92
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:213
static void Destroy(void)
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:134
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:37
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:89
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:178
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1062
AttributeValue implementation for Ssid.
Definition: ssid.h:110
void SetDefault(std::string name, const AttributeValue &value)
Definition: config.cc:810
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:256
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
wifiStaNodes
Definition: third.py:81
Include Radiotap link layer information.
Definition: wifi-helper.h:178
Ptr< Application > Get(uint32_t i) const
Get the Ptr<Application> stored in this container at a given index.