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 continously 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
102using namespace ns3;
103
104std::vector<uint32_t> bytesReceived(4);
105
107ContextToNodeId(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
114void
115SocketRx(std::string context, Ptr<const Packet> p, const Address& addr)
116{
117 uint32_t nodeId = ContextToNodeId(context);
118 bytesReceived[nodeId] += p->GetSize();
119}
120
121int
122main(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
326 Simulator::Destroy();
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:92
Wi-Fi AP state machine.
Definition: ap-wifi-mac.h:63
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
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.
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:42
AttributeValue implementation for Time.
Definition: nstime.h:1425
Hold an unsigned integer type.
Definition: uinteger.h:45
Vector3D Vector
Vector alias typedef for compatibility with mobility models.
Definition: vector.h:324
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:536
void SetPreambleDetectionModel(std::string type, Args &&... args)
Helper function used to set the preamble detection model.
Definition: wifi-helper.h:572
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:1338
@ 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:691
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)