wifi: Enable configuration of 80+80MHz operating channel

This commit is contained in:
Sébastien Deronne
2023-05-17 12:16:07 +02:00
parent 7a265bb5b6
commit d0400f34d8
7 changed files with 106 additions and 76 deletions

View File

@@ -17,6 +17,7 @@
* Author: Sebastien Deronne <sebastien.deronne@gmail.com>
*/
#include "ns3/attribute-container.h"
#include "ns3/boolean.h"
#include "ns3/command-line.h"
#include "ns3/config.h"
@@ -150,7 +151,10 @@ main(int argc, char* argv[])
WifiMacHelper mac;
WifiHelper wifi;
Ssid ssid = Ssid("ns3");
TupleValue<UintegerValue, UintegerValue, EnumValue<WifiPhyBand>, UintegerValue> channelValue;
AttributeContainerValue<
TupleValue<UintegerValue, UintegerValue, EnumValue<WifiPhyBand>, UintegerValue>,
';'>
channelValue;
const auto& [staStandard, staBand] = ConvertStringToStandardAndBand(staVersion);
wifi.SetStandard(staStandard);
@@ -160,7 +164,7 @@ main(int argc, char* argv[])
// Workaround needed as long as we do not fully support channel bonding
uint16_t width = (staVersion == "80211ac" ? 20 : 0);
channelValue.Set(WifiPhy::ChannelTuple{0, width, staBand, 0});
channelValue.Set(WifiPhy::ChannelSegments{{0, width, staBand, 0}});
phy.Set("ChannelSettings", channelValue);
NetDeviceContainer staDevice;
@@ -174,7 +178,7 @@ main(int argc, char* argv[])
// Workaround needed as long as we do not fully support channel bonding
width = (apVersion == "80211ac" ? 20 : 0);
channelValue.Set(WifiPhy::ChannelTuple{0, width, apBand, 0});
channelValue.Set(WifiPhy::ChannelSegments{{0, width, apBand, 0}});
phy.Set("ChannelSettings", channelValue);
NetDeviceContainer apDevice;

View File

@@ -18,6 +18,7 @@
* Sebastien Deronne <sebastien.deronne@gmail.com>
*/
#include "ns3/attribute-container.h"
#include "ns3/boolean.h"
#include "ns3/command-line.h"
#include "ns3/config.h"
@@ -176,10 +177,12 @@ main(int argc, char* argv[])
wifi.ConfigHtOptions("ShortGuardIntervalSupported", BooleanValue(sgi));
Ssid ssid = Ssid("ns3-80211n");
TupleValue<UintegerValue, UintegerValue, EnumValue<WifiPhyBand>, UintegerValue>
AttributeContainerValue<
TupleValue<UintegerValue, UintegerValue, EnumValue<WifiPhyBand>, UintegerValue>,
';'>
channelValue;
WifiPhyBand band = (frequency == 5.0 ? WIFI_PHY_BAND_5GHZ : WIFI_PHY_BAND_2_4GHZ);
channelValue.Set(WifiPhy::ChannelTuple{0, channelWidth, band, 0});
channelValue.Set(WifiPhy::ChannelSegments{{0, channelWidth, band, 0}});
mac.SetType("ns3::StaWifiMac", "Ssid", SsidValue(ssid));
phy.Set("ChannelSettings", channelValue);

View File

@@ -46,6 +46,7 @@
// --broadcast instead of unicast (default is unicast)
// --rtsThreshold (by default, value of 99999 disables it)
#include "ns3/attribute-container.h"
#include "ns3/boolean.h"
#include "ns3/command-line.h"
#include "ns3/config.h"
@@ -639,41 +640,38 @@ main(int argc, char* argv[])
NetDeviceContainer serverDevice;
NetDeviceContainer clientDevice;
TupleValue<UintegerValue, UintegerValue, EnumValue<WifiPhyBand>, UintegerValue> channelValue;
AttributeContainerValue<
TupleValue<UintegerValue, UintegerValue, EnumValue<WifiPhyBand>, UintegerValue>,
';'>
channelValue;
WifiMacHelper wifiMac;
if (infrastructure)
{
Ssid ssid = Ssid("ns-3-ssid");
wifiMac.SetType("ns3::StaWifiMac", "Ssid", SsidValue(ssid));
channelValue.Set(WifiPhy::ChannelTuple{0,
serverSelectedStandard.m_width,
serverSelectedStandard.m_band,
0});
channelValue.Set(WifiPhy::ChannelSegments{
{0, serverSelectedStandard.m_width, serverSelectedStandard.m_band, 0}});
wifiPhy.Set("ChannelSettings", channelValue);
serverDevice = wifi.Install(wifiPhy, wifiMac, serverNode);
wifiMac.SetType("ns3::ApWifiMac", "Ssid", SsidValue(ssid));
channelValue.Set(WifiPhy::ChannelTuple{0,
clientSelectedStandard.m_width,
clientSelectedStandard.m_band,
0});
channelValue.Set(WifiPhy::ChannelSegments{
{0, clientSelectedStandard.m_width, clientSelectedStandard.m_band, 0}});
wifiPhy.Set("ChannelSettings", channelValue);
clientDevice = wifi.Install(wifiPhy, wifiMac, clientNode);
}
else
{
wifiMac.SetType("ns3::AdhocWifiMac");
channelValue.Set(WifiPhy::ChannelTuple{0,
serverSelectedStandard.m_width,
serverSelectedStandard.m_band,
0});
channelValue.Set(WifiPhy::ChannelSegments{
{0, serverSelectedStandard.m_width, serverSelectedStandard.m_band, 0}});
wifiPhy.Set("ChannelSettings", channelValue);
serverDevice = wifi.Install(wifiPhy, wifiMac, serverNode);
channelValue.Set(WifiPhy::ChannelTuple{0,
clientSelectedStandard.m_width,
clientSelectedStandard.m_band,
0});
channelValue.Set(WifiPhy::ChannelSegments{
{0, clientSelectedStandard.m_width, clientSelectedStandard.m_band, 0}});
wifiPhy.Set("ChannelSettings", channelValue);
clientDevice = wifi.Install(wifiPhy, wifiMac, clientNode);
}

View File

@@ -30,6 +30,7 @@
#include "wifi-radio-energy-model.h"
#include "wifi-utils.h"
#include "ns3/attribute-container.h"
#include "ns3/channel.h"
#include "ns3/dsss-phy.h"
#include "ns3/eht-phy.h" //also includes OFDM, HT, VHT and HE
@@ -80,9 +81,11 @@ WifiPhy::GetTypeId()
MakePointerChecker<Channel>())
.AddAttribute(
"ChannelSettings",
"Tuple {channel number, channel width (MHz), PHY band, primary20 index} "
"describing the settings of the operating channel. The primary20 index is "
"the index of the primary 20 MHz channel within the operating channel "
"A vector of tuple {channel number, channel width (MHz), PHY band, primary20 "
"index} "
"describing the settings of the operating channel for each segment. "
"The primary20 index (only the value set for the first segment is used) "
"is the index of the primary 20 MHz channel within the operating channel "
"(0 indicates the 20 MHz subchannel with the lowest center frequency) and "
"is only valid if the width of the operating channel is a multiple of 20 MHz. "
"If the standard for this object has not been set yet, the value of this "
@@ -91,19 +94,19 @@ WifiPhy::GetTypeId()
"band for the configured standard is used. If the channel width and the "
"channel number are both 0, the default channel width for the configured "
"standard and band are used. If the channel number is 0, the default "
"channel number for the configured standard, band and channel width is used."
"channel number for the configured standard, band and channel width is used. "
"Note that the channel width can be left unspecified (0) if the channel "
"number uniquely identify a frequency channel for the given standard and band.",
StringValue("{0, 0, BAND_UNSPECIFIED, 0}"),
MakeTupleAccessor<UintegerValue,
UintegerValue,
EnumValue<WifiPhyBand>,
UintegerValue>((void(WifiPhy::*)(const ChannelTuple&)) &
WifiPhy::SetOperatingChannel),
MakeTupleChecker<UintegerValue,
UintegerValue,
EnumValue<WifiPhyBand>,
UintegerValue>(
MakeAttributeContainerAccessor<
TupleValue<UintegerValue, UintegerValue, EnumValue<WifiPhyBand>, UintegerValue>,
';'>((void(WifiPhy::*)(const ChannelSegments&)) & WifiPhy::SetOperatingChannel),
MakeAttributeContainerChecker<
TupleValue<UintegerValue, UintegerValue, EnumValue<WifiPhyBand>, UintegerValue>,
';'>(MakeTupleChecker<UintegerValue,
UintegerValue,
EnumValue<WifiPhyBand>,
UintegerValue>(
MakeUintegerChecker<uint8_t>(0, 233),
MakeUintegerChecker<ChannelWidthMhz>(0, 160),
MakeEnumChecker(WifiPhyBand::WIFI_PHY_BAND_2_4GHZ,
@@ -114,7 +117,7 @@ WifiPhy::GetTypeId()
"BAND_6GHZ",
WifiPhyBand::WIFI_PHY_BAND_UNSPECIFIED,
"BAND_UNSPECIFIED"),
MakeUintegerChecker<uint8_t>(0, 7)))
MakeUintegerChecker<uint8_t>(0, 7))))
.AddAttribute("Frequency",
"The center frequency (MHz) of the current operating channel.",
TypeId::ATTR_GET,
@@ -1128,14 +1131,22 @@ WifiPhy::SetOperatingChannel(const WifiPhyOperatingChannel& channel)
}
void
WifiPhy::SetOperatingChannel(const ChannelTuple& channelTuple)
WifiPhy::SetOperatingChannel(const ChannelTuple& tuple)
{
// the generic operator<< for tuples does not give a pretty result
NS_LOG_FUNCTION(this << +std::get<0>(channelTuple) << std::get<1>(channelTuple)
<< static_cast<WifiPhyBand>(std::get<2>(channelTuple))
<< +std::get<3>(channelTuple));
SetOperatingChannel(ChannelSegments{tuple});
}
m_channelSettings = channelTuple;
void
WifiPhy::SetOperatingChannel(const ChannelSegments& channelSegments)
{
NS_ASSERT_MSG(channelSegments.size() == 1,
"Non-contiguous operating channel is not supported yet");
NS_LOG_FUNCTION(this << +std::get<0>(channelSegments.front())
<< std::get<1>(channelSegments.front())
<< static_cast<WifiPhyBand>(std::get<2>(channelSegments.front()))
<< +std::get<3>(channelSegments.front()));
m_channelSettings = channelSegments;
if (m_standard == WIFI_STANDARD_UNSPECIFIED)
{
@@ -1154,8 +1165,8 @@ WifiPhy::SetOperatingChannel(const ChannelTuple& channelTuple)
if (delay.value().IsStrictlyPositive())
{
// switching channel has been postponed
void (WifiPhy::*fp)(const ChannelTuple&) = &WifiPhy::SetOperatingChannel;
Simulator::Schedule(delay.value(), fp, this, channelTuple);
void (WifiPhy::*fp)(const ChannelSegments&) = &WifiPhy::SetOperatingChannel;
Simulator::Schedule(delay.value(), fp, this, channelSegments);
return;
}
}
@@ -1213,7 +1224,7 @@ WifiPhy::DoChannelSwitch()
// Update unspecified parameters with default values
{
auto& [number, width, band, primary20] = m_channelSettings;
auto& [number, width, band, primary20] = m_channelSettings.front();
if (band == WIFI_PHY_BAND_UNSPECIFIED)
{
band = GetDefaultPhyBand(m_standard);
@@ -1234,15 +1245,16 @@ WifiPhy::DoChannelSwitch()
// We need to call SetStandard if this is the first time we set a channel or we
// are changing PHY band. Checking if the new PHY band is different than the
// previous one covers both cases because initially the PHY band is unspecified
bool changingPhyBand = (static_cast<WifiPhyBand>(std::get<2>(m_channelSettings)) != m_band);
bool changingPhyBand =
(static_cast<WifiPhyBand>(std::get<2>(m_channelSettings.front())) != m_band);
NS_ABORT_MSG_IF(IsInitialized() && m_fixedPhyBand && changingPhyBand,
"Trying to change PHY band while prohibited.");
m_band = static_cast<WifiPhyBand>(std::get<2>(m_channelSettings));
m_band = static_cast<WifiPhyBand>(std::get<2>(m_channelSettings.front()));
// check that the channel width is supported
ChannelWidthMhz chWidth = std::get<1>(m_channelSettings);
const auto chWidth = std::get<1>(m_channelSettings.front());
if (m_device)
{
@@ -1264,8 +1276,8 @@ WifiPhy::DoChannelSwitch()
}
NS_LOG_DEBUG("switching channel");
m_operatingChannel.Set(std::get<0>(m_channelSettings), 0, chWidth, m_standard, m_band);
m_operatingChannel.SetPrimary20Index(std::get<3>(m_channelSettings));
m_operatingChannel.Set(std::get<0>(m_channelSettings.front()), 0, chWidth, m_standard, m_band);
m_operatingChannel.SetPrimary20Index(std::get<3>(m_channelSettings.front()));
if (changingPhyBand)
{

View File

@@ -919,26 +919,15 @@ class WifiPhy : public Object
*/
Ptr<MobilityModel> GetMobility() const;
using ChannelTuple =
std::tuple<uint8_t /* channel number */,
ChannelWidthMhz /* channel width */,
WifiPhyBand /* WifiPhyBand */,
uint8_t /* primary20 index*/>; //!< Tuple identifying an operating channel
using ChannelTuple = std::tuple<uint8_t /* channel number */,
ChannelWidthMhz /* channel width */,
WifiPhyBand /* WifiPhyBand */,
uint8_t /* primary20 index*/>; //!< Tuple identifying a segment
//!< of an operating channel
using ChannelSegments =
std::vector<ChannelTuple>; //!< segments identifying an operating channel
/**
* If the standard for this object has not been set yet, store the given channel
* settings. Otherwise, check if a channel switch can be performed now. If not,
* schedule another call to this method when channel switch can be performed.
* Otherwise, set the operating channel based on the given channel settings and
* call ConfigureStandard if the PHY band has changed.
*
* Note that, in case a Spectrum PHY is used, a spectrum channel covering the
* operating channel bandwidth must have been already added when actually setting
* the operating channel.
*
* \param channelTuple the given channel settings
*/
void SetOperatingChannel(const ChannelTuple& channelTuple);
/**
* If the standard for this object has not been set yet, store the channel settings
* corresponding to the given operating channel. Otherwise, check if a channel switch
@@ -953,6 +942,23 @@ class WifiPhy : public Object
* \param channel the given operating channel
*/
void SetOperatingChannel(const WifiPhyOperatingChannel& channel);
/**
* This overloaded function is used to pass a list of segments
* from which the operating channel can be deduced.
*
* \param channelSegments the segments identifying the operating channel
*/
void SetOperatingChannel(const ChannelSegments& channelSegments);
/**
* This overloaded function is used when the operating channel
* consists of a single segment, identified by a tuple.
*
* \param tuple the segment identifying the operating channel
*/
void SetOperatingChannel(const ChannelTuple& tuple);
/**
* Configure whether it is prohibited to change PHY band after initialization.
*
@@ -1564,7 +1570,7 @@ class WifiPhy : public Object
WifiStandard m_standard; //!< WifiStandard
WifiModulationClass m_maxModClassSupported; //!< max modulation class supported
WifiPhyBand m_band; //!< WifiPhyBand
ChannelTuple m_channelSettings; //!< Store operating channel settings until initialization
ChannelSegments m_channelSettings; //!< Store operating channel settings until initialization
WifiPhyOperatingChannel m_operatingChannel; //!< Operating channel
bool m_fixedPhyBand; //!< True to prohibit changing PHY band after initialization

View File

@@ -186,9 +186,12 @@ WifiFilsFrameTest::SetupDevice(Ptr<YansWifiChannel>& channel, bool isAp)
MobilityHelper mobility;
node.Create(1);
phy.SetChannel(channel);
TupleValue<UintegerValue, UintegerValue, EnumValue<WifiPhyBand>, UintegerValue> channelValue;
channelValue.Set(
WifiPhy::ChannelTuple{INVALID_CHAN_NUM, m_params.bw, DEFAULT_BAND, DEFAULT_PRIMARY_INDEX});
AttributeContainerValue<
TupleValue<UintegerValue, UintegerValue, EnumValue<WifiPhyBand>, UintegerValue>,
';'>
channelValue;
channelValue.Set(WifiPhy::ChannelSegments{
{INVALID_CHAN_NUM, m_params.bw, DEFAULT_BAND, DEFAULT_PRIMARY_INDEX}});
phy.Set("ChannelSettings", channelValue);
phy.Set("Antennas", UintegerValue(m_params.nss));
phy.Set("MaxSupportedTxSpatialStreams", UintegerValue(m_params.nss));

View File

@@ -18,6 +18,7 @@
*/
#include "ns3/ap-wifi-mac.h"
#include "ns3/attribute-container.h"
#include "ns3/boolean.h"
#include "ns3/config.h"
#include "ns3/ctrl-headers.h"
@@ -397,13 +398,16 @@ WifiPrimaryChannelsTest::DoSetup()
"WaitBeaconTimeout",
TimeValue(MicroSeconds(102400))); // same as BeaconInterval
TupleValue<UintegerValue, UintegerValue, EnumValue<WifiPhyBand>, UintegerValue> channelValue;
AttributeContainerValue<
TupleValue<UintegerValue, UintegerValue, EnumValue<WifiPhyBand>, UintegerValue>,
';'>
channelValue;
// Each BSS uses a distinct primary20 channel
for (uint8_t bss = 0; bss < m_nBss; bss++)
{
channelValue.Set(
WifiPhy::ChannelTuple{channelNum, m_channelWidth, WIFI_PHY_BAND_5GHZ, bss});
WifiPhy::ChannelSegments{{channelNum, m_channelWidth, WIFI_PHY_BAND_5GHZ, bss}});
phy.Set("ChannelSettings", channelValue);
m_staDevices.push_back(wifi.Install(phy, mac, wifiStaNodes[bss]));
@@ -412,7 +416,7 @@ WifiPrimaryChannelsTest::DoSetup()
for (uint8_t bss = 0; bss < m_nBss; bss++)
{
channelValue.Set(
WifiPhy::ChannelTuple{channelNum, m_channelWidth, WIFI_PHY_BAND_5GHZ, bss});
WifiPhy::ChannelSegments{{channelNum, m_channelWidth, WIFI_PHY_BAND_5GHZ, bss}});
phy.Set("ChannelSettings", channelValue);
mac.SetType("ns3::ApWifiMac",