A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
wifi-spatial-reuse.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2019 University of Washington
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Sébastien Deronne <sebastien.deronne@gmail.com>
7 */
8
9//
10// This example program can be used to experiment with spatial
11// reuse mechanisms of 802.11ax.
12//
13// The geometry is as follows:
14//
15// STA1 STA2
16// | |
17// d1 | |d2
18// | d3 |
19// AP1 -----------AP2
20//
21// STA1 and AP1 are in one BSS (with color set to 1), while STA2 and AP2 are in
22// another BSS (with color set to 2). The distances are configurable (d1 through d3).
23//
24// STA1 is continuously transmitting data to AP1, while STA2 is continuously sending data to AP2.
25// Each STA has configurable traffic loads (inter packet interval and packet size).
26// It is also possible to configure TX power per node as well as their CCA-ED thresholds.
27// OBSS_PD spatial reuse feature can be enabled (default) or disabled, and the OBSS_PD
28// threshold can be set as well (default: -72 dBm).
29// A simple Friis path loss model is used and a constant PHY rate is considered.
30//
31// In general, the program can be configured at run-time by passing command-line arguments.
32// The following command will display all of the available run-time help options:
33// ./ns3 run "wifi-spatial-reuse --help"
34//
35// According to the Wi-Fi models of ns-3.36 release, throughput with
36// OBSS PD enabled (--enableObssPd=True) was roughly 6.5 Mbps, and with
37// it disabled (--enableObssPd=False) was roughly 3.5 Mbps.
38//
39// This difference between those results is because OBSS_PD spatial
40// reuse enables to ignore transmissions from another BSS when the
41// received power is below the configured threshold, and therefore
42// either defer during ongoing transmission or transmit at the same
43// time.
44//
45// Note that, by default, this script configures a network using a
46// channel width of 20 MHz. Changing this value alone (through
47// the --channelWidth argument) without properly adjusting other
48// parameters will void the effect of spatial reuse: since energy is
49// measured over the 20 MHz primary channel regardless of the channel
50// width, doubling the transmission bandwidth creates a 3 dB drop in
51// the measured energy level (i.e., a halving of the measured
52// energy). Because of this, when using the channelWidth argument
53// users should also adjust the CCA-ED Thresholds (via --ccaEdTrSta1,
54// --ccaEdTrSta2, --ccaEdTrAp1, and --ccaEdTrAp2), the Minimum RSSI
55// for preamble detection (via --minimumRssi), and the OBSS PD
56// Threshold (via --obssPdThreshold) appropriately. For instance,
57// this can be accomplished for a channel width of 40 MHz by lowering
58// all these values by 3 dB compared to their defaults.
59//
60// In addition, consider that adapting the adjustments shown above
61// for an 80 MHz channel width (using a 6 dB threshold adjustment instead
62// of 3 dB) will not produce any changes when enableObssPd is enabled
63// or disabled. The cause for this is the insufficient amount of
64// traffic that is generated by default in the example: increasing
65// the channel width shortens the frame durations, and lowers the
66// collision probability. Collisions between BSSs are a necessary
67// condition to see the improvements brought by spatial reuse, and
68// thus increasing the amount of generated traffic by setting the
69// interval argument to a lower value is necessary to see the
70// benefits of spatial reuse in this scenario. This can, for
71// instance, be accomplished by setting --interval=100us.
72//
73// Spatial reuse reset events are traced in two text files:
74// - wifi-spatial-reuse-resets-bss-1.txt (for STA 1)
75// - wifi-spatial-reuse-resets-bss-2.txt (for STA 2)
76
77#include "ns3/abort.h"
78#include "ns3/ap-wifi-mac.h"
79#include "ns3/application-container.h"
80#include "ns3/command-line.h"
81#include "ns3/config.h"
82#include "ns3/double.h"
83#include "ns3/he-configuration.h"
84#include "ns3/he-phy.h"
85#include "ns3/mobility-helper.h"
86#include "ns3/multi-model-spectrum-channel.h"
87#include "ns3/obss-pd-algorithm.h"
88#include "ns3/packet-socket-client.h"
89#include "ns3/packet-socket-helper.h"
90#include "ns3/packet-socket-server.h"
91#include "ns3/spectrum-wifi-helper.h"
92#include "ns3/ssid.h"
93#include "ns3/string.h"
94#include "ns3/wifi-net-device.h"
95
96using namespace ns3;
97
98std::vector<uint32_t> bytesReceived(4);
99std::ofstream g_resetFile1;
100std::ofstream g_resetFile2;
101
103ContextToNodeId(std::string context)
104{
105 std::string sub = context.substr(10);
106 uint32_t pos = sub.find("/Device");
107 return std::stoi(sub.substr(0, pos));
108}
109
110void
111SocketRx(std::string context, Ptr<const Packet> p, const Address& addr)
112{
113 uint32_t nodeId = ContextToNodeId(context);
114 bytesReceived[nodeId] += p->GetSize();
115}
116
117void
118ResetTrace(std::string context,
119 uint8_t bssColor,
120 double rssiDbm,
121 bool powerRestricted,
122 double txPowerMaxDbmSiso,
123 double txPowerMaxDbmMimo)
124{
125 if (context == "1")
126 {
127 g_resetFile1 << Simulator::Now().GetSeconds() << " bssColor: " << +bssColor
128 << " rssiDbm: " << rssiDbm << " powerRestricted: " << powerRestricted
129 << " txPowerMaxDbmSiso: " << txPowerMaxDbmSiso
130 << " txPowerMaxDbmMimo: " << txPowerMaxDbmMimo << std::endl;
131 }
132 else if (context == "2")
133 {
134 g_resetFile2 << Simulator::Now().GetSeconds() << " bssColor: " << +bssColor
135 << " rssiDbm: " << rssiDbm << " powerRestricted: " << powerRestricted
136 << " txPowerMaxDbmSiso: " << txPowerMaxDbmSiso
137 << " txPowerMaxDbmMimo: " << txPowerMaxDbmMimo << std::endl;
138 }
139 else
140 {
141 NS_FATAL_ERROR("Unknown context " << context);
142 }
143}
144
145int
146main(int argc, char* argv[])
147{
148 Time duration{"10s"};
149 meter_u d1{30.0};
150 meter_u d2{30.0};
151 meter_u d3{150.0};
152 dBm_u powSta1{10.0};
153 dBm_u powSta2{10.0};
154 dBm_u powAp1{21.0};
155 dBm_u powAp2{21.0};
156 dBm_u ccaEdTrSta1{-62};
157 dBm_u ccaEdTrSta2{-62};
158 dBm_u ccaEdTrAp1{-62};
159 dBm_u ccaEdTrAp2{-62};
160 dBm_u minimumRssi{-82};
161 int channelWidth{20}; // MHz
162 uint32_t payloadSize{1500}; // bytes
163 uint32_t mcs{0}; // MCS value
164 Time interval{"1ms"};
165 bool enableObssPd{true};
166 dBm_u obssPdThreshold{-72.0};
167
168 CommandLine cmd(__FILE__);
169 cmd.AddValue("duration", "Duration of simulation", duration);
170 cmd.AddValue("interval", "Inter packet interval", interval);
171 cmd.AddValue("enableObssPd", "Enable/disable OBSS_PD", enableObssPd);
172 cmd.AddValue("d1", "Distance between STA1 and AP1 (m)", d1);
173 cmd.AddValue("d2", "Distance between STA2 and AP2 (m)", d2);
174 cmd.AddValue("d3", "Distance between AP1 and AP2 (m)", d3);
175 cmd.AddValue("powSta1", "Power of STA1 (dBm)", powSta1);
176 cmd.AddValue("powSta2", "Power of STA2 (dBm)", powSta2);
177 cmd.AddValue("powAp1", "Power of AP1 (dBm)", powAp1);
178 cmd.AddValue("powAp2", "Power of AP2 (dBm)", powAp2);
179 cmd.AddValue("ccaEdTrSta1", "CCA-ED Threshold of STA1 (dBm)", ccaEdTrSta1);
180 cmd.AddValue("ccaEdTrSta2", "CCA-ED Threshold of STA2 (dBm)", ccaEdTrSta2);
181 cmd.AddValue("ccaEdTrAp1", "CCA-ED Threshold of AP1 (dBm)", ccaEdTrAp1);
182 cmd.AddValue("ccaEdTrAp2", "CCA-ED Threshold of AP2 (dBm)", ccaEdTrAp2);
183 cmd.AddValue("minimumRssi",
184 "Minimum RSSI for the ThresholdPreambleDetectionModel",
185 minimumRssi);
186 cmd.AddValue("channelWidth", "Bandwidth of the channel in MHz [20, 40, or 80]", channelWidth);
187 cmd.AddValue("obssPdThreshold", "Threshold for the OBSS PD Algorithm", obssPdThreshold);
188 cmd.AddValue("mcs", "The constant MCS value to transmit HE PPDUs", mcs);
189 cmd.Parse(argc, argv);
190
191 g_resetFile1.open("wifi-spatial-reuse-resets-bss-1.txt", std::ofstream::out);
192 g_resetFile2.open("wifi-spatial-reuse-resets-bss-2.txt", std::ofstream::out);
193
195 wifiStaNodes.Create(2);
196
197 NodeContainer wifiApNodes;
198 wifiApNodes.Create(2);
199
200 SpectrumWifiPhyHelper spectrumPhy;
203 spectrumChannel->AddPropagationLossModel(lossModel);
206 spectrumChannel->SetPropagationDelayModel(delayModel);
207
208 spectrumPhy.SetChannel(spectrumChannel);
209 spectrumPhy.SetErrorRateModel("ns3::YansErrorRateModel");
210 switch (channelWidth)
211 {
212 case 20:
213 spectrumPhy.Set("ChannelSettings", StringValue("{36, 20, BAND_5GHZ, 0}"));
214 break;
215 case 40:
216 spectrumPhy.Set("ChannelSettings", StringValue("{62, 40, BAND_5GHZ, 0}"));
217 break;
218 case 80:
219 spectrumPhy.Set("ChannelSettings", StringValue("{171, 80, BAND_5GHZ, 0}"));
220 break;
221 default:
222 NS_ABORT_MSG("Unrecognized channel width: " << channelWidth);
223 break;
224 }
225 spectrumPhy.SetPreambleDetectionModel("ns3::ThresholdPreambleDetectionModel",
226 "MinimumRssi",
227 DoubleValue(minimumRssi));
228
230 wifi.SetStandard(WIFI_STANDARD_80211ax);
231 if (enableObssPd)
232 {
233 wifi.SetObssPdAlgorithm("ns3::ConstantObssPdAlgorithm",
234 "ObssPdLevel",
235 DoubleValue(obssPdThreshold));
236 }
237
239 std::ostringstream oss;
240 oss << "HeMcs" << mcs;
241 wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager",
242 "DataMode",
243 StringValue(oss.str()),
244 "ControlMode",
245 StringValue(oss.str()));
246
247 spectrumPhy.Set("TxPowerStart", DoubleValue(powSta1));
248 spectrumPhy.Set("TxPowerEnd", DoubleValue(powSta1));
249 spectrumPhy.Set("CcaEdThreshold", DoubleValue(ccaEdTrSta1));
250 spectrumPhy.Set("RxSensitivity", DoubleValue(-92.0));
251
252 Ssid ssidA = Ssid("A");
253 mac.SetType("ns3::StaWifiMac", "Ssid", SsidValue(ssidA));
254 NetDeviceContainer staDeviceA = wifi.Install(spectrumPhy, mac, wifiStaNodes.Get(0));
255
256 spectrumPhy.Set("TxPowerStart", DoubleValue(powAp1));
257 spectrumPhy.Set("TxPowerEnd", DoubleValue(powAp1));
258 spectrumPhy.Set("CcaEdThreshold", DoubleValue(ccaEdTrAp1));
259 spectrumPhy.Set("RxSensitivity", DoubleValue(-92.0));
260
261 mac.SetType("ns3::ApWifiMac", "Ssid", SsidValue(ssidA));
262 NetDeviceContainer apDeviceA = wifi.Install(spectrumPhy, mac, wifiApNodes.Get(0));
263
264 Ptr<WifiNetDevice> apDevice = apDeviceA.Get(0)->GetObject<WifiNetDevice>();
265 Ptr<ApWifiMac> apWifiMac = apDevice->GetMac()->GetObject<ApWifiMac>();
266 if (enableObssPd)
267 {
268 apDevice->GetHeConfiguration()->SetAttribute("BssColor", UintegerValue(1));
269 }
270
271 spectrumPhy.Set("TxPowerStart", DoubleValue(powSta2));
272 spectrumPhy.Set("TxPowerEnd", DoubleValue(powSta2));
273 spectrumPhy.Set("CcaEdThreshold", DoubleValue(ccaEdTrSta2));
274 spectrumPhy.Set("RxSensitivity", DoubleValue(-92.0));
275
276 Ssid ssidB = Ssid("B");
277 mac.SetType("ns3::StaWifiMac", "Ssid", SsidValue(ssidB));
278 NetDeviceContainer staDeviceB = wifi.Install(spectrumPhy, mac, wifiStaNodes.Get(1));
279
280 spectrumPhy.Set("TxPowerStart", DoubleValue(powAp2));
281 spectrumPhy.Set("TxPowerEnd", DoubleValue(powAp2));
282 spectrumPhy.Set("CcaEdThreshold", DoubleValue(ccaEdTrAp2));
283 spectrumPhy.Set("RxSensitivity", DoubleValue(-92.0));
284
285 mac.SetType("ns3::ApWifiMac", "Ssid", SsidValue(ssidB));
286 NetDeviceContainer apDeviceB = wifi.Install(spectrumPhy, mac, wifiApNodes.Get(1));
287
288 Ptr<WifiNetDevice> ap2Device = apDeviceB.Get(0)->GetObject<WifiNetDevice>();
289 apWifiMac = ap2Device->GetMac()->GetObject<ApWifiMac>();
290 if (enableObssPd)
291 {
292 ap2Device->GetHeConfiguration()->SetAttribute("BssColor", UintegerValue(2));
293 }
294
297 positionAlloc->Add(Vector(0.0, 0.0, 0.0)); // AP1
298 positionAlloc->Add(Vector(d3, 0.0, 0.0)); // AP2
299 positionAlloc->Add(Vector(0.0, d1, 0.0)); // STA1
300 positionAlloc->Add(Vector(d3, d2, 0.0)); // STA2
301 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
302 mobility.SetPositionAllocator(positionAlloc);
303 mobility.Install(wifiApNodes);
304 mobility.Install(wifiStaNodes);
305
306 PacketSocketHelper packetSocket;
307 packetSocket.Install(wifiApNodes);
308 packetSocket.Install(wifiStaNodes);
310
311 // BSS 1
312 {
313 PacketSocketAddress socketAddr;
314 socketAddr.SetSingleDevice(staDeviceA.Get(0)->GetIfIndex());
315 socketAddr.SetPhysicalAddress(apDeviceA.Get(0)->GetAddress());
316 socketAddr.SetProtocol(1);
318 client->SetRemote(socketAddr);
319 wifiStaNodes.Get(0)->AddApplication(client);
320 client->SetAttribute("PacketSize", UintegerValue(payloadSize));
321 client->SetAttribute("MaxPackets", UintegerValue(0));
322 client->SetAttribute("Interval", TimeValue(interval));
324 server->SetLocal(socketAddr);
325 wifiApNodes.Get(0)->AddApplication(server);
326 }
327
328 // BSS 2
329 {
330 PacketSocketAddress socketAddr;
331 socketAddr.SetSingleDevice(staDeviceB.Get(0)->GetIfIndex());
332 socketAddr.SetPhysicalAddress(apDeviceB.Get(0)->GetAddress());
333 socketAddr.SetProtocol(1);
335 client->SetRemote(socketAddr);
336 wifiStaNodes.Get(1)->AddApplication(client);
337 client->SetAttribute("PacketSize", UintegerValue(payloadSize));
338 client->SetAttribute("MaxPackets", UintegerValue(0));
339 client->SetAttribute("Interval", TimeValue(interval));
341 server->SetLocal(socketAddr);
342 wifiApNodes.Get(1)->AddApplication(server);
343 }
344
345 Config::Connect("/NodeList/*/ApplicationList/*/$ns3::PacketSocketServer/Rx",
347
348 // Obtain pointers to the ObssPdAlgorithm objects and hook trace sinks
349 // to the Reset trace source on each STA. Note that this trace connection
350 // cannot be done through the Config path system, so pointers are used.
351 auto deviceA = staDeviceA.Get(0)->GetObject<WifiNetDevice>();
352 auto hePhyA = DynamicCast<HePhy>(deviceA->GetPhy()->GetPhyEntity(WIFI_MOD_CLASS_HE));
353 // Pass in the context string "1" to allow the trace to distinguish objects
354 hePhyA->GetObssPdAlgorithm()->TraceConnect("Reset", "1", MakeCallback(&ResetTrace));
355 auto deviceB = staDeviceB.Get(0)->GetObject<WifiNetDevice>();
356 auto hePhyB = DynamicCast<HePhy>(deviceB->GetPhy()->GetPhyEntity(WIFI_MOD_CLASS_HE));
357 // Pass in the context string "2" to allow the trace to distinguish objects
358 hePhyB->GetObssPdAlgorithm()->TraceConnect("Reset", "2", MakeCallback(&ResetTrace));
359
360 Simulator::Stop(duration);
362
364
365 for (uint32_t i = 0; i < 2; i++)
366 {
367 const auto throughput = bytesReceived[2 + i] * 8.0 / duration.GetMicroSeconds();
368 std::cout << "Throughput for BSS " << i + 1 << ": " << throughput << " Mbit/s" << std::endl;
369 }
370
371 g_resetFile1.close();
372 g_resetFile2.close();
373
374 return 0;
375}
a polymophic address class
Definition address.h:90
Wi-Fi AP state machine.
Definition ap-wifi-mac.h:63
holds a vector of ns3::Application pointers.
Parse command-line arguments.
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition double.h:31
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:153
bool TraceConnect(std::string name, std::string context, const CallbackBase &cb)
Connect a TraceSource to a Callback with a context.
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.
Smart pointer class similar to boost::intrusive_ptr.
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition simulator.cc:131
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:197
static void Run()
Run the simulation.
Definition simulator.cc:167
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Definition simulator.cc:175
Make it easy to create and manage PHY objects for the spectrum model.
void SetChannel(const Ptr< SpectrumChannel > channel)
The IEEE 802.11 SSID Information Element.
Definition ssid.h:25
Hold variables of type string.
Definition string.h:45
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition nstime.h:392
Hold an unsigned integer type.
Definition uinteger.h:34
helps to create WifiNetDevice objects
create MAC layers for a ns3::WifiNetDevice.
Hold together all Wifi-related objects.
void Set(std::string name, const AttributeValue &v)
void SetErrorRateModel(std::string type, Args &&... args)
Helper function used to set the error rate model.
void SetPreambleDetectionModel(std::string type, Args &&... args)
Helper function used to set the preamble detection model.
void Connect(std::string path, const CallbackBase &cb)
Definition config.cc:967
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition abort.h:38
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
@ WIFI_STANDARD_80211ax
@ WIFI_MOD_CLASS_HE
HE (Clause 27)
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:684
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:580
mac
Definition third.py:81
wifi
Definition third.py:84
mobility
Definition third.py:92
wifiStaNodes
Definition third.py:73
uint32_t bytesReceived
Counter of the received bytes.
std::ofstream throughput
uint32_t ContextToNodeId(std::string context)
std::ofstream g_resetFile2
void ResetTrace(std::string context, uint8_t bssColor, double rssiDbm, bool powerRestricted, double txPowerMaxDbmSiso, double txPowerMaxDbmMimo)
std::ofstream g_resetFile1
void SocketRx(std::string context, Ptr< const Packet > p, const Address &addr)