wifi: Enable configuration of 80+80MHz operating channel
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user