A Discrete-Event Network Simulator
API
wifi-pcf.cc
Go to the documentation of this file.
1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2017
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: Sebastien Deronne <sebastien.deronne@gmail.com>
19  */
20 
21 #include "ns3/log.h"
22 #include "ns3/config.h"
23 #include "ns3/command-line.h"
24 #include "ns3/uinteger.h"
25 #include "ns3/boolean.h"
26 #include "ns3/string.h"
27 #include "ns3/yans-wifi-helper.h"
28 #include "ns3/mobility-helper.h"
29 #include "ns3/internet-stack-helper.h"
30 #include "ns3/ipv4-address-helper.h"
31 #include "ns3/packet-sink-helper.h"
32 #include "ns3/on-off-helper.h"
33 #include "ns3/packet-sink.h"
34 #include "ns3/ssid.h"
35 #include "ns3/wifi-mac-header.h"
36 
37 /* This is a simple example in order to show the frames exchanged in 802.11 PCF.
38  * The output prints the overal throughput as well as the number of different PCF frames that have been transmitted.
39  *
40  * It is possible to tune some parameters using the command line:
41  * - number of connected stations
42  * - enable/disable PCF
43  * - enable PCAP output file generation in order to vizualise frame exchange.
44  * - configure UDP data traffic:
45  * -> enable/disable data generation: --withData=<0|1>
46  * -> select traffic direction: --trafficDirection=<upstream|downstream>
47  *
48  * For example, one can observe the benefit of PCF over DCF when the number of stations increased:
49  * ./waf --run "wifi-pcf enablePcf=0 --nWifi=10" => DCF only
50  * ./waf --run "wifi-pcf enablePcf=1 --nWifi=10" => alternance of PCF and DCF
51  *
52  * One can also change the value of cfpMaxDuration: a shorter valer means the granted time for PCF is shorter, and so it's benefit is reduced.
53  * ./waf --run "wifi-pcf enablePcf=1 --nWifi=10 --cfpMaxDuration=10240"
54  *
55  * One can also see the different types of piggybacked frames depending on the traffic direction and whether PCF is enabled or not:
56  * ./waf --run "wifi-pcf enablePcf=0 --nWifi=1" => only CF_POLL and DATA_NULL frames should be seen
57  * ./waf --run "wifi-pcf enablePcf=1 --nWifi=1 --trafficDirection=upstream" => no DATA_NULL frames should be seen
58  * ./waf --run "wifi-pcf enablePcf=1 --nWifi=1 --trafficDirection=downstream" => no CF_END_ACK frames should be seen
59  */
60 
61 using namespace ns3;
62 
63 NS_LOG_COMPONENT_DEFINE ("WifiPcf");
64 
65 uint64_t m_countBeacon;
66 uint64_t m_countCfPoll;
70 uint64_t m_countCfEnd;
71 uint64_t m_countCfEndAck;
72 uint64_t m_countDataNull;
73 uint64_t m_countData;
74 
75 void TxCallback (std::string context, Ptr<const Packet> p, double txPowerW)
76 {
77  WifiMacHeader hdr;
78  p->PeekHeader (hdr);
79  if (hdr.IsBeacon ())
80  {
81  m_countBeacon++;
82  }
83  else if (hdr.IsCfPoll ())
84  {
85  if (hdr.IsCfAck () && hdr.HasData ())
86  {
88  }
89  else if (!hdr.IsCfAck () && hdr.HasData ())
90  {
92  }
93  else if (hdr.IsCfAck () && !hdr.HasData ())
94  {
96  }
97  else
98  {
99  m_countCfPoll++;
100  }
101  }
102  else if (hdr.IsCfEnd ())
103  {
104  if (hdr.IsCfAck ())
105  {
106  m_countCfEndAck++;
107  }
108  else
109  {
110  m_countCfEnd++;
111  }
112  }
113  else if (hdr.IsData ())
114  {
115  if (!hdr.HasData ())
116  {
117  m_countDataNull++;
118  }
119  else
120  {
121  m_countData++;
122  }
123  }
124 }
125 
126 int main (int argc, char *argv[])
127 {
128  uint32_t nWifi = 1;
129  bool enablePcap = false;
130  bool enablePcf = true;
131  bool withData = true;
132  std::string trafficDirection = "upstream";
133  uint64_t cfpMaxDurationUs = 65536; //microseconds
134  double simulationTime = 10; //seconds
135 
136  CommandLine cmd (__FILE__);
137  cmd.AddValue ("nWifi", "Number of wifi STA devices", nWifi);
138  cmd.AddValue ("enablePcf", "Enable/disable PCF mode", enablePcf);
139  cmd.AddValue ("withData", "Enable/disable UDP data packets generation", withData);
140  cmd.AddValue ("trafficDirection", "Data traffic direction (if withData is set to 1): upstream (all STAs -> AP) or downstream (AP -> all STAs)", trafficDirection);
141  cmd.AddValue ("cfpMaxDuration", "CFP max duration in microseconds", cfpMaxDurationUs);
142  cmd.AddValue ("simulationTime", "Simulation time in seconds", simulationTime);
143  cmd.AddValue ("enablePcap", "Enable/disable PCAP output", enablePcap);
144  cmd.Parse (argc, argv);
145 
146  m_countBeacon = 0;
147  m_countCfEnd = 0;
148  m_countCfEndAck = 0;
149  m_countCfPoll = 0;
150  m_countCfPollAck = 0;
151  m_countCfPollData = 0;
153  m_countDataNull = 0;
154  m_countData = 0;
155  m_countDataNull = 0;
156  m_countData = 0;
157 
159  wifiStaNodes.Create (nWifi);
160 
162  wifiApNode.Create (1);
163 
166  phy.SetPcapDataLinkType (YansWifiPhyHelper::DLT_IEEE802_11_RADIO);
167  phy.SetChannel (channel.Create ());
168 
171 
172  Ssid ssid = Ssid ("wifi-pcf");
173  wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager", "DataMode", StringValue ("OfdmRate54Mbps"), "ControlMode", StringValue ("OfdmRate24Mbps"));
174 
176  mac.SetType ("ns3::StaWifiMac",
177  "Ssid", SsidValue (ssid),
178  "ActiveProbing", BooleanValue (false),
179  "PcfSupported", BooleanValue (enablePcf));
180  staDevices = wifi.Install (phy, mac, wifiStaNodes);
181 
182  mac.SetType ("ns3::ApWifiMac",
183  "Ssid", SsidValue (ssid),
184  "BeaconGeneration", BooleanValue (true),
185  "PcfSupported", BooleanValue (enablePcf),
186  "CfpMaxDuration", TimeValue (MicroSeconds (cfpMaxDurationUs)));
187 
188  NetDeviceContainer apDevice;
189  apDevice = wifi.Install (phy, mac, wifiApNode);
190 
192 
193  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
194 
195  for (uint32_t i = 0; i < nWifi; i++)
196  {
197  positionAlloc->Add (Vector (1.0, 0.0, 0.0));
198  }
199  positionAlloc->Add (Vector (0.0, 0.0, 0.0));
200  mobility.SetPositionAllocator (positionAlloc);
201 
202  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
203 
204  mobility.Install (wifiApNode);
205  mobility.Install (wifiStaNodes);
206 
208  stack.Install (wifiApNode);
209  stack.Install (wifiStaNodes);
210 
212 
213  address.SetBase ("10.1.1.0", "255.255.255.0");
214  Ipv4InterfaceContainer StaInterface;
215  StaInterface = address.Assign (staDevices);
216  Ipv4InterfaceContainer ApInterface;
217  ApInterface = address.Assign (apDevice);
218 
219  ApplicationContainer sourceApplications, sinkApplications;
220  if (withData)
221  {
222  uint32_t portNumber = 9;
223  for (uint32_t index = 0; index < nWifi; ++index)
224  {
225  auto ipv4 = (trafficDirection == "upstream") ? wifiApNode.Get (0)->GetObject<Ipv4> () : wifiStaNodes.Get (index)->GetObject<Ipv4> ();
226  const auto address = ipv4->GetAddress (1, 0).GetLocal ();
227  InetSocketAddress sinkSocket (address, portNumber++);
228  OnOffHelper onOffHelper ("ns3::UdpSocketFactory", sinkSocket);
229  onOffHelper.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
230  onOffHelper.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
231  onOffHelper.SetAttribute ("DataRate", DataRateValue (50000000 / nWifi));
232  onOffHelper.SetAttribute ("PacketSize", UintegerValue (1472)); //bytes
233  PacketSinkHelper packetSinkHelper ("ns3::UdpSocketFactory", sinkSocket);
234  if (trafficDirection == "upstream")
235  {
236  sourceApplications.Add (onOffHelper.Install (wifiStaNodes.Get (index)));
237  sinkApplications.Add (packetSinkHelper.Install (wifiApNode.Get (0)));
238  }
239  else if (trafficDirection == "downstream")
240  {
241  sinkApplications.Add (packetSinkHelper.Install (wifiStaNodes.Get (index)));
242  sourceApplications.Add (onOffHelper.Install (wifiApNode.Get (0)));
243  }
244  else
245  {
246  NS_ASSERT_MSG (false, "Invalid trafficDirection!");
247  }
248  }
249  sinkApplications.Start (Seconds (0.0));
250  sinkApplications.Stop (Seconds (simulationTime + 1));
251  sourceApplications.Start (Seconds (1.0));
252  sourceApplications.Stop (Seconds (simulationTime + 1));
253  }
254 
255  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyTxBegin", MakeCallback (&TxCallback));
256 
257  if (enablePcap)
258  {
259  phy.EnablePcap ("wifi_pcf", apDevice.Get (0));
260  }
261 
262  Simulator::Stop (Seconds (simulationTime + 1));
263  Simulator::Run ();
264 
265  double throughput = 0;
266  for (uint32_t index = 0; index < sinkApplications.GetN (); ++index)
267  {
268  uint64_t totalPacketsThrough = DynamicCast<PacketSink> (sinkApplications.Get (index))->GetTotalRx ();
269  throughput += ((totalPacketsThrough * 8) / (simulationTime * 1000000.0)); //Mbit/s
270  }
271 
272  std::cout << "Throughput: " << throughput << " Mbit/s" << std::endl;
273 
274  std::cout << "# tx beacons: " << m_countBeacon << std::endl;
275  std::cout << "# tx CF-END: " << m_countCfEnd << std::endl;
276  std::cout << "# tx CF-END-ACK: " << m_countCfEndAck << std::endl;
277  std::cout << "# tx CF-POLL: " << m_countCfPoll << std::endl;
278  std::cout << "# tx CF-POLL-ACK: " << m_countCfPollAck << std::endl;
279  std::cout << "# tx CF-POLL-DATA: " << m_countCfPollData << std::endl;
280  std::cout << "# tx CF-POLL-DATA-ACK: " << m_countCfPollDataAck << std::endl;
281  std::cout << "# tx DATA-NULL: " << m_countDataNull << std::endl;
282  std::cout << "# tx DATA: " << m_countData << std::endl;
283 
285  return 0;
286 }
holds a vector of ns3::Application pointers.
Ptr< Application > Get(uint32_t i) const
Get the Ptr<Application> stored in this container at a given index.
void Start(Time start)
Arrange for all of the Applications in this container to Start() at the Time given as a parameter.
void Add(ApplicationContainer other)
Append the contents of another ApplicationContainer to the end of this container.
void Stop(Time stop)
Arrange for all of the Applications in this container to Stop() at the Time given as a parameter.
uint32_t GetN(void) const
Get the number of Ptr<Application> stored in this container.
AttributeValue implementation for Boolean.
Definition: boolean.h:37
Parse command-line arguments.
Definition: command-line.h:229
AttributeValue implementation for DataRate.
Definition: data-rate.h:298
an Inet address class
aggregate IP/TCP/UDP functionality to existing Nodes.
A helper class to make life easier while doing simple IPv4 address assignment in scripts.
Access to the IPv4 forwarding table, interfaces, and configuration.
Definition: ipv4.h:77
holds a vector of std::pair of Ptr<Ipv4> and interface index.
Helper class used to assign positions and mobility models to nodes.
holds a vector of ns3::NetDevice pointers
Ptr< NetDevice > Get(uint32_t i) const
Get the Ptr<NetDevice> stored in this container at a given index.
keep track of a set of node pointers.
A helper to make it easier to instantiate an ns3::OnOffApplication on a set of nodes.
Definition: on-off-helper.h:43
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition: packet.cc:290
A helper to make it easier to instantiate an ns3::PacketSinkApplication on a set of nodes.
static void Stop(void)
Tell the Simulator the calling event should be the last one executed.
Definition: simulator.cc:180
static void Destroy(void)
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:136
static void Run(void)
Run the simulation.
Definition: simulator.cc:172
The IEEE 802.11 SSID Information Element.
Definition: ssid.h:36
AttributeValue implementation for Ssid.
Definition: ssid.h:105
Hold variables of type string.
Definition: string.h:41
AttributeValue implementation for Time.
Definition: nstime.h:1308
Hold an unsigned integer type.
Definition: uinteger.h:44
helps to create WifiNetDevice objects
Definition: wifi-helper.h:274
Implements the IEEE 802.11 MAC header.
bool HasData(void) const
Return true if the header type is DATA and is not DATA_NULL.
bool IsCfEnd(void) const
Return true if the header is a CF-End header.
bool IsCfPoll(void) const
Return true if the Type/Subtype is one of the possible CF-Poll headers.
bool IsData(void) const
Return true if the Type is DATA.
bool IsCfAck(void) const
Return true if the header is a CF-Ack header.
bool IsBeacon(void) const
Return true if the header is a Beacon header.
create MAC layers for a ns3::WifiNetDevice.
@ DLT_IEEE802_11_RADIO
Include Radiotap link layer information.
Definition: wifi-helper.h:126
manage and create wifi channel objects for the YANS model.
static YansWifiChannelHelper Default(void)
Create a channel helper in a default working state.
Make it easy to create and manage PHY objects for the YANS model.
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:88
void Connect(std::string path, const CallbackBase &cb)
Definition: config.cc:920
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1260
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1244
address
Definition: first.py:44
stack
Definition: first.py:41
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Ts... > MakeCallback(R(T::*memPtr)(Ts...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:1648
cmd
Definition: second.py:35
staDevices
Definition: third.py:103
ssid
Definition: third.py:100
channel
Definition: third.py:92
nWifi
Definition: third.py:43
mac
Definition: third.py:99
wifi
Definition: third.py:96
wifiApNode
Definition: third.py:90
mobility
Definition: third.py:108
wifiStaNodes
Definition: third.py:88
phy
Definition: third.py:93
bool enablePcap
uint64_t m_countData
Definition: wifi-pcf.cc:73
void TxCallback(std::string context, Ptr< const Packet > p, double txPowerW)
Definition: wifi-pcf.cc:75
uint64_t m_countCfPollAck
Definition: wifi-pcf.cc:67
uint64_t m_countDataNull
Definition: wifi-pcf.cc:72
uint64_t m_countCfEnd
Definition: wifi-pcf.cc:70
uint64_t m_countBeacon
Definition: wifi-pcf.cc:63
uint64_t m_countCfPoll
Definition: wifi-pcf.cc:66
uint64_t m_countCfPollDataAck
Definition: wifi-pcf.cc:69
uint64_t m_countCfEndAck
Definition: wifi-pcf.cc:71
uint64_t m_countCfPollData
Definition: wifi-pcf.cc:68