A Discrete-Event Network Simulator
API
wifi-spatial-reuse.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2019 University of Washington
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author: Sébastien Deronne <sebastien.deronne@gmail.com>
18  */
19 
20 //
21 // This example program can be used to experiment with spatial
22 // reuse mechanisms of 802.11ax.
23 //
24 // The geometry is as follows:
25 //
26 // STA1 STA1
27 // | |
28 // d1 | |d2
29 // | d3 |
30 // AP1 -----------AP2
31 //
32 // STA1 and AP1 are in one BSS (with color set to 1), while STA2 and AP2 are in
33 // another BSS (with color set to 2). The distances are configurable (d1 through d3).
34 //
35 // STA1 is continuously transmitting data to AP1, while STA2 is continuously sending data to AP2.
36 // Each STA has configurable traffic loads (inter packet interval and packet size).
37 // It is also possible to configure TX power per node as well as their CCA-ED tresholds.
38 // OBSS_PD spatial reuse feature can be enabled (default) or disabled, and the OBSS_PD
39 // threshold can be set as well (default: -72 dBm).
40 // A simple Friis path loss model is used and a constant PHY rate is considered.
41 //
42 // In general, the program can be configured at run-time by passing command-line arguments.
43 // The following command will display all of the available run-time help options:
44 // ./ns3 run "wifi-spatial-reuse --help"
45 //
46 // According to the Wi-Fi models of ns-3.36 release, throughput with
47 // OBSS PD enabled (--enableObssPd=True) was roughly 6.5 Mbps, and with
48 // it disabled (--enableObssPd=False) was roughly 3.5 Mbps.
49 //
50 // This difference between those results is because OBSS_PD spatial
51 // reuse enables to ignore transmissions from another BSS when the
52 // received power is below the configured threshold, and therefore
53 // either defer during ongoing transmission or transmit at the same
54 // time.
55 //
56 // Note that, by default, this script configures a network using a
57 // channel bandwidth of 20 MHz. Changing this value alone (through
58 // the --channelWidth argument) without properly adjusting other
59 // parameters will void the effect of spatial reuse: since energy is
60 // measured over the 20 MHz primary channel regardless of the channel
61 // width, doubling the transmission bandwidth creates a 3 dB drop in
62 // the measured energy level (i.e., a halving of the measured
63 // energy). Because of this, when using the channelWidth argument
64 // users should also adjust the CCA-ED Thresholds (via --ccaEdTrSta1,
65 // --ccaEdTrSta2, --ccaEdTrAp1, and --ccaEdTrAp2), the Minimum RSSI
66 // for preamble detection (via --minimumRssi), and the OBSS PD
67 // Threshold (via --obssPdThreshold) appropriately. For instance,
68 // this can be accomplished for a channel width of 40 MHz by lowering
69 // all these values by 3 dB compared to their defaults.
70 //
71 // In addition, consider that adapting the adjustments shown above
72 // for an 80 MHz bandwidth (using a 6 dB threshold adjustment instead
73 // of 3 dB) will not produce any changes when enableObssPd is enabled
74 // or disabled. The cause for this is the insufficient amount of
75 // traffic that is generated by default in the example: increasing
76 // the bandwidth shortens the frame durations, and lowers the
77 // collision probability. Collisions between BSSs are a necessary
78 // condition to see the improvements brought by spatial reuse, and
79 // thus increasing the amount of generated traffic by setting the
80 // interval argument to a lower value is necessary to see the
81 // benefits of spatial reuse in this scenario. This can, for
82 // instance, be accomplished by setting --interval=0.0001.
83 //
84 
85 #include "ns3/abort.h"
86 #include "ns3/ap-wifi-mac.h"
87 #include "ns3/application-container.h"
88 #include "ns3/command-line.h"
89 #include "ns3/config.h"
90 #include "ns3/double.h"
91 #include "ns3/he-configuration.h"
92 #include "ns3/mobility-helper.h"
93 #include "ns3/multi-model-spectrum-channel.h"
94 #include "ns3/packet-socket-client.h"
95 #include "ns3/packet-socket-helper.h"
96 #include "ns3/packet-socket-server.h"
97 #include "ns3/spectrum-wifi-helper.h"
98 #include "ns3/ssid.h"
99 #include "ns3/string.h"
100 #include "ns3/wifi-net-device.h"
101 
102 using namespace ns3;
103 
104 std::vector<uint32_t> bytesReceived(4);
105 
106 uint32_t
107 ContextToNodeId(std::string context)
108 {
109  std::string sub = context.substr(10);
110  uint32_t pos = sub.find("/Device");
111  return std::stoi(sub.substr(0, pos));
112 }
113 
114 void
115 SocketRx(std::string context, Ptr<const Packet> p, const Address& addr)
116 {
117  uint32_t nodeId = ContextToNodeId(context);
118  bytesReceived[nodeId] += p->GetSize();
119 }
120 
121 int
122 main(int argc, char* argv[])
123 {
124  double duration = 10.0; // seconds
125  double d1 = 30.0; // meters
126  double d2 = 30.0; // meters
127  double d3 = 150.0; // meters
128  double powSta1 = 10.0; // dBm
129  double powSta2 = 10.0; // dBm
130  double powAp1 = 21.0; // dBm
131  double powAp2 = 21.0; // dBm
132  double ccaEdTrSta1 = -62; // dBm
133  double ccaEdTrSta2 = -62; // dBm
134  double ccaEdTrAp1 = -62; // dBm
135  double ccaEdTrAp2 = -62; // dBm
136  double minimumRssi = -82; // dBm
137  int channelBandwidth = 20; // MHz
138  uint32_t payloadSize = 1500; // bytes
139  uint32_t mcs = 0; // MCS value
140  double interval = 0.001; // seconds
141  bool enableObssPd = true;
142  double obssPdThreshold = -72.0; // dBm
143 
144  CommandLine cmd(__FILE__);
145  cmd.AddValue("duration", "Duration of simulation (s)", duration);
146  cmd.AddValue("interval", "Inter packet interval (s)", interval);
147  cmd.AddValue("enableObssPd", "Enable/disable OBSS_PD", enableObssPd);
148  cmd.AddValue("d1", "Distance between STA1 and AP1 (m)", d1);
149  cmd.AddValue("d2", "Distance between STA2 and AP2 (m)", d2);
150  cmd.AddValue("d3", "Distance between AP1 and AP2 (m)", d3);
151  cmd.AddValue("powSta1", "Power of STA1 (dBm)", powSta1);
152  cmd.AddValue("powSta2", "Power of STA2 (dBm)", powSta2);
153  cmd.AddValue("powAp1", "Power of AP1 (dBm)", powAp1);
154  cmd.AddValue("powAp2", "Power of AP2 (dBm)", powAp2);
155  cmd.AddValue("ccaEdTrSta1", "CCA-ED Threshold of STA1 (dBm)", ccaEdTrSta1);
156  cmd.AddValue("ccaEdTrSta2", "CCA-ED Threshold of STA2 (dBm)", ccaEdTrSta2);
157  cmd.AddValue("ccaEdTrAp1", "CCA-ED Threshold of AP1 (dBm)", ccaEdTrAp1);
158  cmd.AddValue("ccaEdTrAp2", "CCA-ED Threshold of AP2 (dBm)", ccaEdTrAp2);
159  cmd.AddValue("minimumRssi",
160  "Minimum RSSI for the ThresholdPreambleDetectionModel",
161  minimumRssi);
162  cmd.AddValue("channelBandwidth",
163  "Bandwidth of the channel in MHz [20, 40, or 80]",
164  channelBandwidth);
165  cmd.AddValue("obssPdThreshold", "Threshold for the OBSS PD Algorithm", obssPdThreshold);
166  cmd.AddValue("mcs", "The constant MCS value to transmit HE PPDUs", mcs);
167  cmd.Parse(argc, argv);
168 
170  wifiStaNodes.Create(2);
171 
172  NodeContainer wifiApNodes;
173  wifiApNodes.Create(2);
174 
175  SpectrumWifiPhyHelper spectrumPhy;
176  Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
177  Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
178  spectrumChannel->AddPropagationLossModel(lossModel);
180  CreateObject<ConstantSpeedPropagationDelayModel>();
181  spectrumChannel->SetPropagationDelayModel(delayModel);
182 
183  spectrumPhy.SetChannel(spectrumChannel);
184  spectrumPhy.SetErrorRateModel("ns3::YansErrorRateModel");
185  switch (channelBandwidth)
186  {
187  case 20:
188  spectrumPhy.Set("ChannelSettings", StringValue("{36, 20, BAND_5GHZ, 0}"));
189  break;
190  case 40:
191  spectrumPhy.Set("ChannelSettings", StringValue("{62, 40, BAND_5GHZ, 0}"));
192  break;
193  case 80:
194  spectrumPhy.Set("ChannelSettings", StringValue("{171, 80, BAND_5GHZ, 0}"));
195  break;
196  default:
197  NS_ABORT_MSG("Unrecognized channel bandwidth: " << channelBandwidth);
198  break;
199  }
200  spectrumPhy.SetPreambleDetectionModel("ns3::ThresholdPreambleDetectionModel",
201  "MinimumRssi",
202  DoubleValue(minimumRssi));
203 
205  wifi.SetStandard(WIFI_STANDARD_80211ax);
206  if (enableObssPd)
207  {
208  wifi.SetObssPdAlgorithm("ns3::ConstantObssPdAlgorithm",
209  "ObssPdLevel",
210  DoubleValue(obssPdThreshold));
211  }
212 
214  std::ostringstream oss;
215  oss << "HeMcs" << mcs;
216  wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager",
217  "DataMode",
218  StringValue(oss.str()),
219  "ControlMode",
220  StringValue(oss.str()));
221 
222  spectrumPhy.Set("TxPowerStart", DoubleValue(powSta1));
223  spectrumPhy.Set("TxPowerEnd", DoubleValue(powSta1));
224  spectrumPhy.Set("CcaEdThreshold", DoubleValue(ccaEdTrSta1));
225  spectrumPhy.Set("RxSensitivity", DoubleValue(-92.0));
226 
227  Ssid ssidA = Ssid("A");
228  mac.SetType("ns3::StaWifiMac", "Ssid", SsidValue(ssidA));
229  NetDeviceContainer staDeviceA = wifi.Install(spectrumPhy, mac, wifiStaNodes.Get(0));
230 
231  spectrumPhy.Set("TxPowerStart", DoubleValue(powAp1));
232  spectrumPhy.Set("TxPowerEnd", DoubleValue(powAp1));
233  spectrumPhy.Set("CcaEdThreshold", DoubleValue(ccaEdTrAp1));
234  spectrumPhy.Set("RxSensitivity", DoubleValue(-92.0));
235 
236  mac.SetType("ns3::ApWifiMac", "Ssid", SsidValue(ssidA));
237  NetDeviceContainer apDeviceA = wifi.Install(spectrumPhy, mac, wifiApNodes.Get(0));
238 
239  Ptr<WifiNetDevice> apDevice = apDeviceA.Get(0)->GetObject<WifiNetDevice>();
240  Ptr<ApWifiMac> apWifiMac = apDevice->GetMac()->GetObject<ApWifiMac>();
241  if (enableObssPd)
242  {
243  apDevice->GetHeConfiguration()->SetAttribute("BssColor", UintegerValue(1));
244  }
245 
246  spectrumPhy.Set("TxPowerStart", DoubleValue(powSta2));
247  spectrumPhy.Set("TxPowerEnd", DoubleValue(powSta2));
248  spectrumPhy.Set("CcaEdThreshold", DoubleValue(ccaEdTrSta2));
249  spectrumPhy.Set("RxSensitivity", DoubleValue(-92.0));
250 
251  Ssid ssidB = Ssid("B");
252  mac.SetType("ns3::StaWifiMac", "Ssid", SsidValue(ssidB));
253  NetDeviceContainer staDeviceB = wifi.Install(spectrumPhy, mac, wifiStaNodes.Get(1));
254 
255  spectrumPhy.Set("TxPowerStart", DoubleValue(powAp2));
256  spectrumPhy.Set("TxPowerEnd", DoubleValue(powAp2));
257  spectrumPhy.Set("CcaEdThreshold", DoubleValue(ccaEdTrAp2));
258  spectrumPhy.Set("RxSensitivity", DoubleValue(-92.0));
259 
260  mac.SetType("ns3::ApWifiMac", "Ssid", SsidValue(ssidB));
261  NetDeviceContainer apDeviceB = wifi.Install(spectrumPhy, mac, wifiApNodes.Get(1));
262 
263  Ptr<WifiNetDevice> ap2Device = apDeviceB.Get(0)->GetObject<WifiNetDevice>();
264  apWifiMac = ap2Device->GetMac()->GetObject<ApWifiMac>();
265  if (enableObssPd)
266  {
267  ap2Device->GetHeConfiguration()->SetAttribute("BssColor", UintegerValue(2));
268  }
269 
271  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
272  positionAlloc->Add(Vector(0.0, 0.0, 0.0)); // AP1
273  positionAlloc->Add(Vector(d3, 0.0, 0.0)); // AP2
274  positionAlloc->Add(Vector(0.0, d1, 0.0)); // STA1
275  positionAlloc->Add(Vector(d3, d2, 0.0)); // STA2
276  mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
277  mobility.SetPositionAllocator(positionAlloc);
278  mobility.Install(wifiApNodes);
279  mobility.Install(wifiStaNodes);
280 
281  PacketSocketHelper packetSocket;
282  packetSocket.Install(wifiApNodes);
283  packetSocket.Install(wifiStaNodes);
285 
286  // BSS 1
287  {
288  PacketSocketAddress socketAddr;
289  socketAddr.SetSingleDevice(staDeviceA.Get(0)->GetIfIndex());
290  socketAddr.SetPhysicalAddress(apDeviceA.Get(0)->GetAddress());
291  socketAddr.SetProtocol(1);
292  Ptr<PacketSocketClient> client = CreateObject<PacketSocketClient>();
293  client->SetRemote(socketAddr);
294  wifiStaNodes.Get(0)->AddApplication(client);
295  client->SetAttribute("PacketSize", UintegerValue(payloadSize));
296  client->SetAttribute("MaxPackets", UintegerValue(0));
297  client->SetAttribute("Interval", TimeValue(Seconds(interval)));
298  Ptr<PacketSocketServer> server = CreateObject<PacketSocketServer>();
299  server->SetLocal(socketAddr);
300  wifiApNodes.Get(0)->AddApplication(server);
301  }
302 
303  // BSS 2
304  {
305  PacketSocketAddress socketAddr;
306  socketAddr.SetSingleDevice(staDeviceB.Get(0)->GetIfIndex());
307  socketAddr.SetPhysicalAddress(apDeviceB.Get(0)->GetAddress());
308  socketAddr.SetProtocol(1);
309  Ptr<PacketSocketClient> client = CreateObject<PacketSocketClient>();
310  client->SetRemote(socketAddr);
311  wifiStaNodes.Get(1)->AddApplication(client);
312  client->SetAttribute("PacketSize", UintegerValue(payloadSize));
313  client->SetAttribute("MaxPackets", UintegerValue(0));
314  client->SetAttribute("Interval", TimeValue(Seconds(interval)));
315  Ptr<PacketSocketServer> server = CreateObject<PacketSocketServer>();
316  server->SetLocal(socketAddr);
317  wifiApNodes.Get(1)->AddApplication(server);
318  }
319 
320  Config::Connect("/NodeList/*/ApplicationList/*/$ns3::PacketSocketServer/Rx",
322 
323  Simulator::Stop(Seconds(duration));
324  Simulator::Run();
325 
327 
328  for (uint32_t i = 0; i < 2; i++)
329  {
330  double throughput = static_cast<double>(bytesReceived[2 + i]) * 8 / 1000 / 1000 / duration;
331  std::cout << "Throughput for BSS " << i + 1 << ": " << throughput << " Mbit/s" << std::endl;
332  }
333 
334  return 0;
335 }
a polymophic address class
Definition: address.h:100
Wi-Fi AP state machine.
Definition: ap-wifi-mac.h:64
holds a vector of ns3::Application pointers.
Parse command-line arguments.
Definition: command-line.h:232
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition: double.h:42
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.
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
uint32_t AddApplication(Ptr< Application > application)
Associate an Application to this Node.
Definition: node.cc:169
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition: object.h:471
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:863
an address for a packet socket
void SetProtocol(uint16_t protocol)
Set the protocol.
void SetPhysicalAddress(const Address address)
Set the destination address.
void SetSingleDevice(uint32_t device)
Set the address to match only a specified NetDevice.
Give ns3::PacketSocket powers to ns3::Node.
void Install(Ptr< Node > node) const
Aggregate an instance of a ns3::PacketSocketFactory onto the provided node.
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:140
static void Run()
Run the simulation.
Definition: simulator.cc:176
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Definition: simulator.cc:184
Make it easy to create and manage PHY objects for the spectrum model.
void SetChannel(Ptr< SpectrumChannel > channel)
The IEEE 802.11 SSID Information Element.
Definition: ssid.h:36
AttributeValue implementation for Ssid.
Hold variables of type string.
Definition: string.h:56
AttributeValue implementation for Time.
Definition: nstime.h:1423
Hold an unsigned integer type.
Definition: uinteger.h:45
helps to create WifiNetDevice objects
Definition: wifi-helper.h:325
create MAC layers for a ns3::WifiNetDevice.
Hold together all Wifi-related objects.
Ptr< WifiMac > GetMac() const
Ptr< HeConfiguration > GetHeConfiguration() const
void Set(std::string name, const AttributeValue &v)
Definition: wifi-helper.cc:163
void SetErrorRateModel(std::string type, Args &&... args)
Helper function used to set the error rate model.
Definition: wifi-helper.h:551
void SetPreambleDetectionModel(std::string type, Args &&... args)
Helper function used to set the preamble detection model.
Definition: wifi-helper.h:587
void Connect(std::string path, const CallbackBase &cb)
Definition: config.cc:975
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:49
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1336
@ WIFI_STANDARD_80211ax
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:707
cmd
Definition: second.py:33
mac
Definition: third.py:85
wifi
Definition: third.py:88
mobility
Definition: third.py:96
wifiStaNodes
Definition: third.py:77
uint32_t ContextToNodeId(std::string context)
std::vector< uint32_t > bytesReceived(4)
void SocketRx(std::string context, Ptr< const Packet > p, const Address &addr)