Files
unison/examples/wireless/wifi-spatial-reuse.cc
Davide Magrin df05ad1210 wifi: Set wifi-spatial-reuse.cc to use 20 MHz BW
This commit adapts the example to use the new way of specifying channel,
bandwidth and band via the ChannelSettings attribute, solving a
regression that caused it to use an 80 MHz bandwidth instead of the 20
MHz it was originally calibrated with.

In addition, it also expands the script description to reflect the
discussions in !873 and #566.
2022-03-21 13:57:12 -07:00

332 lines
14 KiB
C++

/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2019 University of Washington
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Sébastien Deronne <sebastien.deronne@gmail.com>
*/
//
// This example program can be used to experiment with spatial
// reuse mechanisms of 802.11ax.
//
// The geometry is as follows:
//
// STA1 STA1
// | |
// d1 | |d2
// | d3 |
// AP1 -----------AP2
//
// STA1 and AP1 are in one BSS (with color set to 1), while STA2 and AP2 are in
// another BSS (with color set to 2). The distances are configurable (d1 through d3).
//
// STA1 is continously transmitting data to AP1, while STA2 is continuously sending data to AP2.
// Each STA has configurable traffic loads (inter packet interval and packet size).
// It is also possible to configure TX power per node as well as their CCA-ED tresholds.
// OBSS_PD spatial reuse feature can be enabled (default) or disabled, and the OBSS_PD
// threshold can be set as well (default: -72 dBm).
// A simple Friis path loss model is used and a constant PHY rate is considered.
//
// In general, the program can be configured at run-time by passing command-line arguments.
// The following command will display all of the available run-time help options:
// ./ns3 run "wifi-spatial-reuse --help"
//
// According to the Wi-Fi models of ns-3.36 release, throughput with
// OBSS PD enabled (--enableObssPd=True) was roughly 6.5 Mbps, and with
// it disabled (--enableObssPd=False) was roughly 3.5 Mbps.
//
// This difference between those results is because OBSS_PD spatial
// reuse enables to ignore transmissions from another BSS when the
// received power is below the configured threshold, and therefore
// either defer during ongoing transmission or transmit at the same
// time.
//
// Note that, by default, this script configures a network using a
// channel bandwidth of 20 MHz. Changing this value alone (through
// the --channelWidth argument) without properly adjusting other
// parameters will void the effect of spatial reuse: since energy is
// measured over the 20 MHz primary channel regardless of the channel
// width, doubling the transmission bandwidth creates a 3 dB drop in
// the measured energy level (i.e., a halving of the measured
// energy). Because of this, when using the channelWidth argument
// users should also adjust the CCA-ED Thresholds (via --ccaEdTrSta1,
// --ccaEdTrSta2, --ccaEdTrAp1, and --ccaEdTrAp2), the Minimum RSSI
// for preamble detection (via --minimumRssi), and the OBSS PD
// Threshold (via --obssPdThreshold) appropriately. For instance,
// this can be accomplished for a channel width of 40 MHz by lowering
// all these values by 3 dB compared to their defaults.
//
// In addition, consider that adapting the adjustments shown above
// for an 80 MHz bandwidth (using a 6 dB threshold adjustment instead
// of 3 dB) will not produce any changes when enableObssPd is enabled
// or disabled. The cause for this is the insufficient amount of
// traffic that is generated by default in the example: increasing
// the bandwidth shortens the frame durations, and lowers the
// collision probability. Collisions between BSSs are a necessary
// condition to see the improvements brought by spatial reuse, and
// thus increasing the amount of generated traffic by setting the
// interval argument to a lower value is necessary to see the
// benefits of spatial reuse in this scenario. This can, for
// instance, be accomplished by setting --interval=0.0001.
//
#include "ns3/abort.h"
#include "ns3/command-line.h"
#include "ns3/config.h"
#include "ns3/string.h"
#include "ns3/double.h"
#include "ns3/spectrum-wifi-helper.h"
#include "ns3/ssid.h"
#include "ns3/mobility-helper.h"
#include "ns3/application-container.h"
#include "ns3/multi-model-spectrum-channel.h"
#include "ns3/wifi-net-device.h"
#include "ns3/ap-wifi-mac.h"
#include "ns3/he-configuration.h"
#include "ns3/packet-socket-helper.h"
#include "ns3/packet-socket-client.h"
#include "ns3/packet-socket-server.h"
using namespace ns3;
std::vector<uint32_t> bytesReceived (4);
uint32_t
ContextToNodeId (std::string context)
{
std::string sub = context.substr (10);
uint32_t pos = sub.find ("/Device");
return atoi (sub.substr (0, pos).c_str ());
}
void
SocketRx (std::string context, Ptr<const Packet> p, const Address &addr)
{
uint32_t nodeId = ContextToNodeId (context);
bytesReceived[nodeId] += p->GetSize ();
}
int
main (int argc, char *argv[])
{
double duration = 10.0; // seconds
double d1 = 30.0; // meters
double d2 = 30.0; // meters
double d3 = 150.0; // meters
double powSta1 = 10.0; // dBm
double powSta2 = 10.0; // dBm
double powAp1 = 21.0; // dBm
double powAp2 = 21.0; // dBm
double ccaEdTrSta1 = -62; // dBm
double ccaEdTrSta2 = -62; // dBm
double ccaEdTrAp1 = -62; // dBm
double ccaEdTrAp2 = -62; // dBm
double minimumRssi = -82; // dBm
int channelBandwidth = 20; // MHz
uint32_t payloadSize = 1500; // bytes
uint32_t mcs = 0; // MCS value
double interval = 0.001; // seconds
bool enableObssPd = true;
double obssPdThreshold = -72.0; // dBm
CommandLine cmd (__FILE__);
cmd.AddValue ("duration", "Duration of simulation (s)", duration);
cmd.AddValue ("interval", "Inter packet interval (s)", interval);
cmd.AddValue ("enableObssPd", "Enable/disable OBSS_PD", enableObssPd);
cmd.AddValue ("d1", "Distance between STA1 and AP1 (m)", d1);
cmd.AddValue ("d2", "Distance between STA2 and AP2 (m)", d2);
cmd.AddValue ("d3", "Distance between AP1 and AP2 (m)", d3);
cmd.AddValue ("powSta1", "Power of STA1 (dBm)", powSta1);
cmd.AddValue ("powSta2", "Power of STA2 (dBm)", powSta2);
cmd.AddValue ("powAp1", "Power of AP1 (dBm)", powAp1);
cmd.AddValue ("powAp2", "Power of AP2 (dBm)", powAp2);
cmd.AddValue ("ccaEdTrSta1", "CCA-ED Threshold of STA1 (dBm)", ccaEdTrSta1);
cmd.AddValue ("ccaEdTrSta2", "CCA-ED Threshold of STA2 (dBm)", ccaEdTrSta2);
cmd.AddValue ("ccaEdTrAp1", "CCA-ED Threshold of AP1 (dBm)", ccaEdTrAp1);
cmd.AddValue ("ccaEdTrAp2", "CCA-ED Threshold of AP2 (dBm)", ccaEdTrAp2);
cmd.AddValue ("minimumRssi", "Minimum RSSI for the ThresholdPreambleDetectionModel", minimumRssi);
cmd.AddValue ("channelBandwidth", "Bandwidth of the channel in MHz [20, 40, or 80]", channelBandwidth);
cmd.AddValue ("obssPdThreshold", "Threshold for the OBSS PD Algorithm", obssPdThreshold);
cmd.AddValue ("mcs", "The constant MCS value to transmit HE PPDUs", mcs);
cmd.Parse (argc, argv);
NodeContainer wifiStaNodes;
wifiStaNodes.Create (2);
NodeContainer wifiApNodes;
wifiApNodes.Create (2);
SpectrumWifiPhyHelper spectrumPhy;
Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel> ();
Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel> ();
spectrumChannel->AddPropagationLossModel (lossModel);
Ptr<ConstantSpeedPropagationDelayModel> delayModel = CreateObject<ConstantSpeedPropagationDelayModel> ();
spectrumChannel->SetPropagationDelayModel (delayModel);
spectrumPhy.SetChannel (spectrumChannel);
spectrumPhy.SetErrorRateModel ("ns3::YansErrorRateModel");
switch (channelBandwidth)
{
case 20:
spectrumPhy.Set ("ChannelSettings", StringValue ("{36, 20, BAND_5GHZ, 0}"));
break;
case 40:
spectrumPhy.Set ("ChannelSettings", StringValue ("{62, 40, BAND_5GHZ, 0}"));
break;
case 80:
spectrumPhy.Set ("ChannelSettings", StringValue ("{171, 80, BAND_5GHZ, 0}"));
break;
default:
NS_ABORT_MSG ("Unrecognized channel bandwidth: " << channelBandwidth);
break;
}
spectrumPhy.SetPreambleDetectionModel ("ns3::ThresholdPreambleDetectionModel",
"MinimumRssi", DoubleValue (minimumRssi));
WifiHelper wifi;
wifi.SetStandard (WIFI_STANDARD_80211ax);
if (enableObssPd)
{
wifi.SetObssPdAlgorithm ("ns3::ConstantObssPdAlgorithm",
"ObssPdLevel", DoubleValue (obssPdThreshold));
}
WifiMacHelper mac;
std::ostringstream oss;
oss << "HeMcs" << mcs;
wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager",
"DataMode", StringValue (oss.str ()),
"ControlMode", StringValue (oss.str ()));
spectrumPhy.Set ("TxPowerStart", DoubleValue (powSta1));
spectrumPhy.Set ("TxPowerEnd", DoubleValue (powSta1));
spectrumPhy.Set ("CcaEdThreshold", DoubleValue (ccaEdTrSta1));
spectrumPhy.Set ("RxSensitivity", DoubleValue (-92.0));
Ssid ssidA = Ssid ("A");
mac.SetType ("ns3::StaWifiMac",
"Ssid", SsidValue (ssidA));
NetDeviceContainer staDeviceA = wifi.Install (spectrumPhy, mac, wifiStaNodes.Get (0));
spectrumPhy.Set ("TxPowerStart", DoubleValue (powAp1));
spectrumPhy.Set ("TxPowerEnd", DoubleValue (powAp1));
spectrumPhy.Set ("CcaEdThreshold", DoubleValue (ccaEdTrAp1));
spectrumPhy.Set ("RxSensitivity", DoubleValue (-92.0));
mac.SetType ("ns3::ApWifiMac",
"Ssid", SsidValue (ssidA));
NetDeviceContainer apDeviceA = wifi.Install (spectrumPhy, mac, wifiApNodes.Get (0));
Ptr<WifiNetDevice> apDevice = apDeviceA.Get (0)->GetObject<WifiNetDevice> ();
Ptr<ApWifiMac> apWifiMac = apDevice->GetMac ()->GetObject<ApWifiMac> ();
if (enableObssPd)
{
apDevice->GetHeConfiguration ()->SetAttribute ("BssColor", UintegerValue (1));
}
spectrumPhy.Set ("TxPowerStart", DoubleValue (powSta2));
spectrumPhy.Set ("TxPowerEnd", DoubleValue (powSta2));
spectrumPhy.Set ("CcaEdThreshold", DoubleValue (ccaEdTrSta2));
spectrumPhy.Set ("RxSensitivity", DoubleValue (-92.0));
Ssid ssidB = Ssid ("B");
mac.SetType ("ns3::StaWifiMac",
"Ssid", SsidValue (ssidB));
NetDeviceContainer staDeviceB = wifi.Install (spectrumPhy, mac, wifiStaNodes.Get (1));
spectrumPhy.Set ("TxPowerStart", DoubleValue (powAp2));
spectrumPhy.Set ("TxPowerEnd", DoubleValue (powAp2));
spectrumPhy.Set ("CcaEdThreshold", DoubleValue (ccaEdTrAp2));
spectrumPhy.Set ("RxSensitivity", DoubleValue (-92.0));
mac.SetType ("ns3::ApWifiMac",
"Ssid", SsidValue (ssidB));
NetDeviceContainer apDeviceB = wifi.Install (spectrumPhy, mac, wifiApNodes.Get (1));
Ptr<WifiNetDevice> ap2Device = apDeviceB.Get (0)->GetObject<WifiNetDevice> ();
apWifiMac = ap2Device->GetMac ()->GetObject<ApWifiMac> ();
if (enableObssPd)
{
ap2Device->GetHeConfiguration ()->SetAttribute ("BssColor", UintegerValue (2));
}
MobilityHelper mobility;
Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
positionAlloc->Add (Vector (0.0, 0.0, 0.0)); // AP1
positionAlloc->Add (Vector (d3, 0.0, 0.0)); // AP2
positionAlloc->Add (Vector (0.0, d1, 0.0)); // STA1
positionAlloc->Add (Vector (d3, d2, 0.0)); // STA2
mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
mobility.SetPositionAllocator (positionAlloc);
mobility.Install (wifiApNodes);
mobility.Install (wifiStaNodes);
PacketSocketHelper packetSocket;
packetSocket.Install (wifiApNodes);
packetSocket.Install (wifiStaNodes);
ApplicationContainer apps;
TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
//BSS 1
{
PacketSocketAddress socketAddr;
socketAddr.SetSingleDevice (staDeviceA.Get (0)->GetIfIndex ());
socketAddr.SetPhysicalAddress (apDeviceA.Get (0)->GetAddress ());
socketAddr.SetProtocol (1);
Ptr<PacketSocketClient> client = CreateObject<PacketSocketClient> ();
client->SetRemote (socketAddr);
wifiStaNodes.Get (0)->AddApplication (client);
client->SetAttribute ("PacketSize", UintegerValue (payloadSize));
client->SetAttribute ("MaxPackets", UintegerValue (0));
client->SetAttribute ("Interval", TimeValue (Seconds (interval)));
Ptr<PacketSocketServer> server = CreateObject<PacketSocketServer> ();
server->SetLocal (socketAddr);
wifiApNodes.Get (0)->AddApplication (server);
}
// BSS 2
{
PacketSocketAddress socketAddr;
socketAddr.SetSingleDevice (staDeviceB.Get (0)->GetIfIndex ());
socketAddr.SetPhysicalAddress (apDeviceB.Get (0)->GetAddress ());
socketAddr.SetProtocol (1);
Ptr<PacketSocketClient> client = CreateObject<PacketSocketClient> ();
client->SetRemote (socketAddr);
wifiStaNodes.Get (1)->AddApplication (client);
client->SetAttribute ("PacketSize", UintegerValue (payloadSize));
client->SetAttribute ("MaxPackets", UintegerValue (0));
client->SetAttribute ("Interval", TimeValue (Seconds (interval)));
Ptr<PacketSocketServer> server = CreateObject<PacketSocketServer> ();
server->SetLocal (socketAddr);
wifiApNodes.Get (1)->AddApplication (server);
}
Config::Connect ("/NodeList/*/ApplicationList/*/$ns3::PacketSocketServer/Rx", MakeCallback (&SocketRx));
Simulator::Stop (Seconds (duration));
Simulator::Run ();
Simulator::Destroy ();
for (uint32_t i = 0; i < 2; i++)
{
double throughput = static_cast<double> (bytesReceived[2 + i]) * 8 / 1000 / 1000 / duration;
std::cout << "Throughput for BSS " << i + 1 << ": " << throughput << " Mbit/s" << std::endl;
}
return 0;
}