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 
36 // This is an example that illustrates how 802.11n aggregation is configured.
37 // It defines 4 independent Wi-Fi networks (working on different channels).
38 // Each network contains one access point and one station. Each station
39 // continuously transmits data packets to its respective AP.
40 //
41 // Network topology (numbers in parentheses are channel numbers):
42 //
43 // Network A (36) Network B (40) Network C (44) Network D (48)
44 // * * * * * * * *
45 // | | | | | | | |
46 // AP A STA A AP B STA B AP C STA C AP D STA D
47 //
48 // The aggregation parameters are configured differently on the 4 stations:
49 // - station A uses default aggregation parameter values (A-MSDU disabled, A-MPDU enabled with maximum size of 65 kB);
50 // - station B doesn't use aggregation (both A-MPDU and A-MSDU are disabled);
51 // - station C enables A-MSDU (with maximum size of 8 kB) but disables A-MPDU;
52 // - station D uses two-level aggregation (A-MPDU with maximum size of 32 kB and A-MSDU with maximum size of 4 kB).
53 //
54 // Packets in this simulation aren't marked with a QosTag so they
55 // are considered belonging to BestEffort Access Class (AC_BE).
56 //
57 // The user can select the distance between the stations and the APs and can enable/disable the RTS/CTS mechanism.
58 // Example: ./waf --run "wifi-aggregation --distance=10 --enableRts=0 --simulationTime=20"
59 //
60 // The output prints the throughput measured for the 4 cases/networks described above. When default aggregation parameters are enabled, the
61 // maximum A-MPDU size is 65 kB and the throughput is maximal. When aggregation is disabled, the throughput is about the half of the
62 // physical bitrate as in legacy wifi networks. When only A-MSDU is enabled, the throughput is increased but is not maximal, since the maximum
63 // 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
64 // (= two-level aggregation), the throughput is slightly smaller than the first scenario since we set a smaller maximum A-MPDU size.
65 //
66 // When the distance is increased, the frame error rate gets higher, and the output shows how it affects the throughput for the 4 networks.
67 // 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
68 // augmented, the throughput for the third scenario is more affected than the throughput obtained in other networks.
69 
70 using namespace ns3;
71 
72 NS_LOG_COMPONENT_DEFINE ("SimpleMpduAggregation");
73 
74 int main (int argc, char *argv[])
75 {
76  uint32_t payloadSize = 1472; //bytes
77  double simulationTime = 10; //seconds
78  double distance = 5; //meters
79  bool enableRts = 0;
80  bool enablePcap = 0;
81  bool verifyResults = 0; //used for regression
82 
84  cmd.AddValue ("payloadSize", "Payload size in bytes", payloadSize);
85  cmd.AddValue ("enableRts", "Enable or disable RTS/CTS", enableRts);
86  cmd.AddValue ("simulationTime", "Simulation time in seconds", simulationTime);
87  cmd.AddValue ("distance", "Distance in meters between the station and the access point", distance);
88  cmd.AddValue ("enablePcap", "Enable/disable pcap file generation", enablePcap);
89  cmd.AddValue ("verifyResults", "Enable/disable results verification at the end of the simulation", verifyResults);
90  cmd.Parse (argc, argv);
91 
92  Config::SetDefault ("ns3::WifiRemoteStationManager::RtsCtsThreshold", enableRts ? StringValue ("0") : StringValue ("999999"));
93 
95  wifiStaNodes.Create (4);
96  NodeContainer wifiApNodes;
97  wifiApNodes.Create (4);
98 
101  phy.SetPcapDataLinkType (WifiPhyHelper::DLT_IEEE802_11_RADIO);
102  phy.SetChannel (channel.Create ());
103 
105  wifi.SetStandard (WIFI_PHY_STANDARD_80211n_5GHZ);
106  wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager", "DataMode", StringValue ("HtMcs7"), "ControlMode", StringValue ("HtMcs0"));
108 
109  NetDeviceContainer staDeviceA, staDeviceB, staDeviceC, staDeviceD, apDeviceA, apDeviceB, apDeviceC, apDeviceD;
110  Ssid ssid;
111 
112  //Network A
113  ssid = Ssid ("network-A");
114  phy.Set ("ChannelNumber", UintegerValue (36));
115  mac.SetType ("ns3::StaWifiMac",
116  "Ssid", SsidValue (ssid));
117  staDeviceA = wifi.Install (phy, mac, wifiStaNodes.Get (0));
118 
119  mac.SetType ("ns3::ApWifiMac",
120  "Ssid", SsidValue (ssid),
121  "EnableBeaconJitter", BooleanValue (false));
122  apDeviceA = wifi.Install (phy, mac, wifiApNodes.Get (0));
123 
124  //Network B
125  ssid = Ssid ("network-B");
126  phy.Set ("ChannelNumber", UintegerValue (40));
127  mac.SetType ("ns3::StaWifiMac",
128  "Ssid", SsidValue (ssid),
129  "BE_MaxAmpduSize", UintegerValue (0)); //Disable A-MPDU
130 
131  staDeviceB = wifi.Install (phy, mac, wifiStaNodes.Get (1));
132 
133  mac.SetType ("ns3::ApWifiMac",
134  "Ssid", SsidValue (ssid),
135  "EnableBeaconJitter", BooleanValue (false));
136  apDeviceB = wifi.Install (phy, mac, wifiApNodes.Get (1));
137 
138  //Network C
139  ssid = Ssid ("network-C");
140  phy.Set ("ChannelNumber", UintegerValue (44));
141  mac.SetType ("ns3::StaWifiMac",
142  "Ssid", SsidValue (ssid),
143  "BE_MaxAmpduSize", UintegerValue (0), //Disable A-MPDU
144  "BE_MaxAmsduSize", UintegerValue (7935)); //Enable A-MSDU with the highest maximum size allowed by the standard (7935 bytes)
145 
146  staDeviceC = wifi.Install (phy, mac, wifiStaNodes.Get (2));
147 
148  mac.SetType ("ns3::ApWifiMac",
149  "Ssid", SsidValue (ssid),
150  "EnableBeaconJitter", BooleanValue (false));
151  apDeviceC = wifi.Install (phy, mac, wifiApNodes.Get (2));
152 
153  //Network D
154  ssid = Ssid ("network-D");
155  phy.Set ("ChannelNumber", UintegerValue (48));
156  mac.SetType ("ns3::StaWifiMac",
157  "Ssid", SsidValue (ssid),
158  "BE_MaxAmpduSize", UintegerValue (32768), //Enable A-MPDU with a smaller size than the default one
159  "BE_MaxAmsduSize", UintegerValue (3839)); //Enable A-MSDU with the smallest maximum size allowed by the standard (3839 bytes)
160 
161  staDeviceD = wifi.Install (phy, mac, wifiStaNodes.Get (3));
162 
163  mac.SetType ("ns3::ApWifiMac",
164  "Ssid", SsidValue (ssid),
165  "EnableBeaconJitter", BooleanValue (false));
166  apDeviceD = wifi.Install (phy, mac, wifiApNodes.Get (3));
167 
168  /* Setting mobility model */
170  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
171  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
172 
173  //Set position for APs
174  positionAlloc->Add (Vector (0.0, 0.0, 0.0));
175  positionAlloc->Add (Vector (10.0, 0.0, 0.0));
176  positionAlloc->Add (Vector (20.0, 0.0, 0.0));
177  positionAlloc->Add (Vector (30.0, 0.0, 0.0));
178  //Set position for STAs
179  positionAlloc->Add (Vector (distance, 0.0, 0.0));
180  positionAlloc->Add (Vector (10 + distance, 0.0, 0.0));
181  positionAlloc->Add (Vector (20 + distance, 0.0, 0.0));
182  positionAlloc->Add (Vector (30 + distance, 0.0, 0.0));
183 
184  mobility.SetPositionAllocator (positionAlloc);
185  mobility.Install (wifiApNodes);
186  mobility.Install (wifiStaNodes);
187 
188  /* Internet stack */
190  stack.Install (wifiApNodes);
191  stack.Install (wifiStaNodes);
192 
194  address.SetBase ("192.168.1.0", "255.255.255.0");
195  Ipv4InterfaceContainer StaInterfaceA;
196  StaInterfaceA = address.Assign (staDeviceA);
197  Ipv4InterfaceContainer ApInterfaceA;
198  ApInterfaceA = address.Assign (apDeviceA);
199 
200  address.SetBase ("192.168.2.0", "255.255.255.0");
201  Ipv4InterfaceContainer StaInterfaceB;
202  StaInterfaceB = address.Assign (staDeviceB);
203  Ipv4InterfaceContainer ApInterfaceB;
204  ApInterfaceB = address.Assign (apDeviceB);
205 
206  address.SetBase ("192.168.3.0", "255.255.255.0");
207  Ipv4InterfaceContainer StaInterfaceC;
208  StaInterfaceC = address.Assign (staDeviceC);
209  Ipv4InterfaceContainer ApInterfaceC;
210  ApInterfaceC = address.Assign (apDeviceC);
211 
212  address.SetBase ("192.168.4.0", "255.255.255.0");
213  Ipv4InterfaceContainer StaInterfaceD;
214  StaInterfaceD = address.Assign (staDeviceD);
215  Ipv4InterfaceContainer ApInterfaceD;
216  ApInterfaceD = address.Assign (apDeviceD);
217 
218  /* Setting applications */
219  uint16_t port = 9;
220  UdpServerHelper serverA (port);
221  ApplicationContainer serverAppA = serverA.Install (wifiStaNodes.Get (0));
222  serverAppA.Start (Seconds (0.0));
223  serverAppA.Stop (Seconds (simulationTime + 1));
224 
225  UdpClientHelper clientA (StaInterfaceA.GetAddress (0), port);
226  clientA.SetAttribute ("MaxPackets", UintegerValue (4294967295u));
227  clientA.SetAttribute ("Interval", TimeValue (Time ("0.00002"))); //packets/s
228  clientA.SetAttribute ("PacketSize", UintegerValue (payloadSize));
229 
230  ApplicationContainer clientAppA = clientA.Install (wifiApNodes.Get (0));
231  clientAppA.Start (Seconds (1.0));
232  clientAppA.Stop (Seconds (simulationTime + 1));
233 
234  UdpServerHelper serverB (port);
235  ApplicationContainer serverAppB = serverB.Install (wifiStaNodes.Get (1));
236  serverAppB.Start (Seconds (0.0));
237  serverAppB.Stop (Seconds (simulationTime + 1));
238 
239  UdpClientHelper clientB (StaInterfaceB.GetAddress (0), port);
240  clientB.SetAttribute ("MaxPackets", UintegerValue (4294967295u));
241  clientB.SetAttribute ("Interval", TimeValue (Time ("0.00002"))); //packets/s
242  clientB.SetAttribute ("PacketSize", UintegerValue (payloadSize));
243 
244  ApplicationContainer clientAppB = clientB.Install (wifiApNodes.Get (1));
245  clientAppB.Start (Seconds (1.0));
246  clientAppB.Stop (Seconds (simulationTime + 1));
247 
248  UdpServerHelper serverC (port);
249  ApplicationContainer serverAppC = serverC.Install (wifiStaNodes.Get (2));
250  serverAppC.Start (Seconds (0.0));
251  serverAppC.Stop (Seconds (simulationTime + 1));
252 
253  UdpClientHelper clientC (StaInterfaceC.GetAddress (0), port);
254  clientC.SetAttribute ("MaxPackets", UintegerValue (4294967295u));
255  clientC.SetAttribute ("Interval", TimeValue (Time ("0.00002"))); //packets/s
256  clientC.SetAttribute ("PacketSize", UintegerValue (payloadSize));
257 
258  ApplicationContainer clientAppC = clientC.Install (wifiApNodes.Get (2));
259  clientAppC.Start (Seconds (1.0));
260  clientAppC.Stop (Seconds (simulationTime + 1));
261 
262  UdpServerHelper serverD (port);
263  ApplicationContainer serverAppD = serverD.Install (wifiStaNodes.Get (3));
264  serverAppD.Start (Seconds (0.0));
265  serverAppD.Stop (Seconds (simulationTime + 1));
266 
267  UdpClientHelper clientD (StaInterfaceD.GetAddress (0), port);
268  clientD.SetAttribute ("MaxPackets", UintegerValue (4294967295u));
269  clientD.SetAttribute ("Interval", TimeValue (Time ("0.00002"))); //packets/s
270  clientD.SetAttribute ("PacketSize", UintegerValue (payloadSize));
271 
272  ApplicationContainer clientAppD = clientD.Install (wifiApNodes.Get (3));
273  clientAppD.Start (Seconds (1.0));
274  clientAppD.Stop (Seconds (simulationTime + 1));
275 
276  if (enablePcap)
277  {
278  phy.EnablePcap ("AP_A", apDeviceA.Get (0));
279  phy.EnablePcap ("STA_A", staDeviceA.Get (0));
280  phy.EnablePcap ("AP_B", apDeviceB.Get (0));
281  phy.EnablePcap ("STA_B", staDeviceB.Get (0));
282  phy.EnablePcap ("AP_C", apDeviceC.Get (0));
283  phy.EnablePcap ("STA_C", staDeviceC.Get (0));
284  phy.EnablePcap ("AP_D", apDeviceD.Get (0));
285  phy.EnablePcap ("STA_D", staDeviceD.Get (0));
286  }
287 
288  Simulator::Stop (Seconds (simulationTime + 1));
289  Simulator::Run ();
290 
291  /* Show results */
292  uint64_t totalPacketsThroughA = DynamicCast<UdpServer> (serverAppA.Get (0))->GetReceived ();
293  uint64_t totalPacketsThroughB = DynamicCast<UdpServer> (serverAppB.Get (0))->GetReceived ();
294  uint64_t totalPacketsThroughC = DynamicCast<UdpServer> (serverAppC.Get (0))->GetReceived ();
295  uint64_t totalPacketsThroughD = DynamicCast<UdpServer> (serverAppD.Get (0))->GetReceived ();
296 
298 
299  double throughput = totalPacketsThroughA * payloadSize * 8 / (simulationTime * 1000000.0);
300  std::cout << "Throughput with default configuration (A-MPDU aggregation enabled, 65kB): " << throughput << " Mbit/s" << '\n';
301  if (verifyResults && (throughput < 59 || throughput > 60))
302  {
303  NS_LOG_ERROR ("Obtained throughput " << throughput << " is not in the expected boundaries!");
304  exit (1);
305  }
306 
307  throughput = totalPacketsThroughB * payloadSize * 8 / (simulationTime * 1000000.0);
308  std::cout << "Throughput with aggregation disabled: " << throughput << " Mbit/s" << '\n';
309  if (verifyResults && (throughput < 30 || throughput > 30.5))
310  {
311  NS_LOG_ERROR ("Obtained throughput " << throughput << " is not in the expected boundaries!");
312  exit (1);
313  }
314 
315  throughput = totalPacketsThroughC * payloadSize * 8 / (simulationTime * 1000000.0);
316  std::cout << "Throughput with A-MPDU disabled and A-MSDU enabled (8kB): " << throughput << " Mbit/s" << '\n';
317  if (verifyResults && (throughput < 51 || throughput > 52))
318  {
319  NS_LOG_ERROR ("Obtained throughput " << throughput << " is not in the expected boundaries!");
320  exit (1);
321  }
322 
323  throughput = totalPacketsThroughD * payloadSize * 8 / (simulationTime * 1000000.0);
324  std::cout << "Throughput with A-MPDU enabled (32kB) and A-MSDU enabled (4kB): " << throughput << " Mbit/s" << '\n';
325  if (verifyResults && (throughput < 58 || throughput > 59))
326  {
327  NS_LOG_ERROR ("Obtained throughput " << throughput << " is not in the expected boundaries!");
328  exit (1);
329  }
330 
331  return 0;
332 }
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.
bool enablePcap
static void Run(void)
Run the simulation.
Definition: simulator.cc:226
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
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:230
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:1076
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:190
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...
static void Stop(void)
Tell the Simulator the calling event should be the last one executed.
Definition: simulator.cc:234
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1014
AttributeValue implementation for Ssid.
Definition: ssid.h:110
void SetDefault(std::string name, const AttributeValue &value)
Definition: config.cc:782
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:254
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:111
Ptr< Application > Get(uint32_t i) const
Get the Ptr<Application> stored in this container at a given index.