wifi: Add a WifiChannelConfig struct to replace ChannelTuple
This commit is contained in:
@@ -189,7 +189,7 @@ MeshWifiInterfaceMac::SwitchFrequencyChannel(uint16_t new_id)
|
||||
* Now we use dirty channel switch -- just change frequency
|
||||
*/
|
||||
GetWifiPhy()->SetOperatingChannel(
|
||||
WifiPhy::ChannelTuple{new_id, 0, GetWifiPhy()->GetPhyBand(), 0});
|
||||
WifiPhy::ChannelTuple{static_cast<uint8_t>(new_id), 0, GetWifiPhy()->GetPhyBand(), 0});
|
||||
// Don't know NAV on new channel
|
||||
GetLink(SINGLE_LINK_OP_ID).channelAccessManager->NotifyNavResetNow(Seconds(0));
|
||||
}
|
||||
|
||||
@@ -172,6 +172,7 @@ set(source_files
|
||||
model/wifi-tx-parameters.cc
|
||||
model/wifi-tx-timer.cc
|
||||
model/wifi-tx-vector.cc
|
||||
model/wifi-types.cc
|
||||
model/wifi-utils.cc
|
||||
model/yans-error-rate-model.cc
|
||||
model/yans-wifi-channel.cc
|
||||
|
||||
@@ -1012,7 +1012,7 @@ WifiPhy::ConfigureStandard(WifiStandard standard)
|
||||
if (!m_operatingChannel.IsSet())
|
||||
{
|
||||
NS_LOG_DEBUG("Setting the operating channel first");
|
||||
SetOperatingChannel(m_channelSettings);
|
||||
SetOperatingChannel(m_channelCfg);
|
||||
// return because we are called back by SetOperatingChannel
|
||||
return;
|
||||
}
|
||||
@@ -1124,36 +1124,39 @@ void
|
||||
WifiPhy::SetOperatingChannel(const WifiPhyOperatingChannel& channel)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << channel);
|
||||
ChannelSegments segments{};
|
||||
WifiChannelConfig cfg;
|
||||
for (std::size_t segmentId = 0; segmentId < channel.GetNSegments(); ++segmentId)
|
||||
{
|
||||
segments.emplace_back(channel.GetNumber(segmentId),
|
||||
channel.GetWidth(segmentId),
|
||||
channel.GetPhyBand(),
|
||||
channel.GetPrimaryChannelIndex(MHz_u{20}));
|
||||
cfg.segments.emplace_back(channel.GetNumber(segmentId),
|
||||
channel.GetWidth(segmentId),
|
||||
channel.GetPhyBand(),
|
||||
channel.GetPrimaryChannelIndex(MHz_u{20}));
|
||||
}
|
||||
SetOperatingChannel(segments);
|
||||
}
|
||||
|
||||
void
|
||||
WifiPhy::SetOperatingChannel(const ChannelTuple& tuple)
|
||||
{
|
||||
SetOperatingChannel(ChannelSegments{tuple});
|
||||
SetOperatingChannel(cfg);
|
||||
}
|
||||
|
||||
void
|
||||
WifiPhy::SetOperatingChannel(const ChannelSegments& channelSegments)
|
||||
{
|
||||
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()));
|
||||
SetOperatingChannel(WifiChannelConfig(channelSegments));
|
||||
}
|
||||
|
||||
m_channelSettings = channelSegments;
|
||||
void
|
||||
WifiPhy::SetOperatingChannel(const WifiChannelConfig& channelCfg)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << +channelCfg.front().number << channelCfg.front().width
|
||||
<< channelCfg.front().band << +channelCfg.front().p20Index);
|
||||
|
||||
if (IsInitialized() && m_operatingChannel.IsSet() && (m_channelCfg == channelCfg))
|
||||
{
|
||||
NS_LOG_DEBUG("Already operating on requested channel");
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_standard == WIFI_STANDARD_UNSPECIFIED)
|
||||
{
|
||||
NS_LOG_DEBUG("Channel information will be applied when a standard is configured");
|
||||
m_channelCfg = channelCfg;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1168,12 +1171,13 @@ WifiPhy::SetOperatingChannel(const ChannelSegments& channelSegments)
|
||||
if (delay.value().IsStrictlyPositive())
|
||||
{
|
||||
// switching channel has been postponed
|
||||
void (WifiPhy::*fp)(const ChannelSegments&) = &WifiPhy::SetOperatingChannel;
|
||||
Simulator::Schedule(delay.value(), fp, this, channelSegments);
|
||||
Simulator::Schedule(delay.value(), [=, this] { SetOperatingChannel(channelCfg); });
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
m_channelCfg = channelCfg;
|
||||
|
||||
// channel can be switched now.
|
||||
DoChannelSwitch();
|
||||
}
|
||||
@@ -1229,7 +1233,7 @@ WifiPhy::DoChannelSwitch()
|
||||
|
||||
// Update unspecified parameters with default values
|
||||
std::optional<uint8_t> prevChannelNumber{};
|
||||
for (auto& [number, width, band, primary20] : m_channelSettings)
|
||||
for (auto& [number, width, band, primary20] : m_channelCfg.segments)
|
||||
{
|
||||
if (band == WIFI_PHY_BAND_UNSPECIFIED)
|
||||
{
|
||||
@@ -1253,27 +1257,23 @@ 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.front())) != m_band);
|
||||
const auto changingPhyBand = (m_channelCfg.front().band != 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.front()));
|
||||
m_band = m_channelCfg.front().band;
|
||||
|
||||
NS_LOG_DEBUG("switching channel");
|
||||
std::vector<FrequencyChannelInfo> segments{};
|
||||
std::transform(m_channelSettings.cbegin(),
|
||||
m_channelSettings.cend(),
|
||||
std::transform(m_channelCfg.segments.cbegin(),
|
||||
m_channelCfg.segments.cend(),
|
||||
std::back_inserter(segments),
|
||||
[this](const auto& channelTuple) {
|
||||
return FrequencyChannelInfo{std::get<0>(channelTuple),
|
||||
MHz_u{0},
|
||||
std::get<1>(channelTuple),
|
||||
m_band};
|
||||
[this](const auto& segment) {
|
||||
return FrequencyChannelInfo{segment.number, MHz_u{0}, segment.width, m_band};
|
||||
});
|
||||
m_operatingChannel.Set(segments, m_standard);
|
||||
m_operatingChannel.SetPrimary20Index(std::get<3>(m_channelSettings.front()));
|
||||
m_operatingChannel.SetPrimary20Index(m_channelCfg.front().p20Index);
|
||||
|
||||
// check that the channel width is supported
|
||||
if (const auto chWidth = GetChannelWidth();
|
||||
|
||||
@@ -941,14 +941,11 @@ class WIFI_EXPORT WifiPhy : public Object
|
||||
*/
|
||||
Ptr<MobilityModel> GetMobility() const;
|
||||
|
||||
using ChannelTuple = std::tuple<uint8_t /* channel number */,
|
||||
MHz_u /* channel width */,
|
||||
WifiPhyBand /* WifiPhyBand */,
|
||||
uint8_t /* primary20 index*/>; //!< Tuple identifying a segment
|
||||
//!< of an operating channel
|
||||
/// kept for backward compatibility, can be deprecated when using strong types
|
||||
using ChannelTuple = WifiChannelConfig::SegmentWithoutUnits;
|
||||
|
||||
using ChannelSegments =
|
||||
std::vector<ChannelTuple>; //!< segments identifying an operating channel
|
||||
/// segments identifying an operating channel
|
||||
using ChannelSegments = std::list<WifiChannelConfig::TupleWithoutUnits>;
|
||||
|
||||
/**
|
||||
* If the standard for this object has not been set yet, store the channel settings
|
||||
@@ -974,12 +971,12 @@ class WIFI_EXPORT WifiPhy : public Object
|
||||
void SetOperatingChannel(const ChannelSegments& channelSegments);
|
||||
|
||||
/**
|
||||
* This overloaded function is used when the operating channel
|
||||
* consists of a single segment, identified by a tuple.
|
||||
* This overloaded function is used to pass a WifiChannelConfig object from which
|
||||
* the operating channel can be deduced.
|
||||
*
|
||||
* @param tuple the segment identifying the operating channel
|
||||
* @param channelCfg the channel config object
|
||||
*/
|
||||
void SetOperatingChannel(const ChannelTuple& tuple);
|
||||
void SetOperatingChannel(const WifiChannelConfig& channelCfg);
|
||||
|
||||
/**
|
||||
* Configure whether it is prohibited to change PHY band after initialization.
|
||||
@@ -1613,7 +1610,7 @@ class WIFI_EXPORT WifiPhy : public Object
|
||||
WifiStandard m_standard; //!< WifiStandard
|
||||
WifiModulationClass m_maxModClassSupported; //!< max modulation class supported
|
||||
WifiPhyBand m_band; //!< WifiPhyBand
|
||||
ChannelSegments m_channelSettings; //!< Store operating channel settings until initialization
|
||||
WifiChannelConfig m_channelCfg; //!< Store operating channel config until initialization
|
||||
WifiPhyOperatingChannel m_operatingChannel; //!< Operating channel
|
||||
bool m_fixedPhyBand; //!< True to prohibit changing PHY band after initialization
|
||||
|
||||
|
||||
21
src/wifi/model/wifi-types.cc
Normal file
21
src/wifi/model/wifi-types.cc
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Universita' degli Studi di Napoli Federico II
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-only
|
||||
*
|
||||
* Author: Stefano Avallone <stavallo@unina.it>
|
||||
*/
|
||||
|
||||
#include "wifi-types.h"
|
||||
|
||||
namespace ns3
|
||||
{
|
||||
|
||||
WifiChannelConfig::WifiChannelConfig(const std::list<TupleWithoutUnits>& tuples)
|
||||
{
|
||||
std::for_each(tuples.cbegin(), tuples.cend(), [this](auto&& t) {
|
||||
segments.emplace_back(std::make_from_tuple<SegmentWithoutUnits>(t));
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
@@ -9,13 +9,17 @@
|
||||
#ifndef WIFI_TYPES_H
|
||||
#define WIFI_TYPES_H
|
||||
|
||||
#include "wifi-phy-band.h"
|
||||
#include "wifi-units.h"
|
||||
|
||||
#include "ns3/fatal-error.h"
|
||||
|
||||
#include <compare>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <ostream>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
namespace ns3
|
||||
{
|
||||
@@ -92,6 +96,127 @@ enum class FrequencyChannelType : uint8_t
|
||||
CH_80211P
|
||||
};
|
||||
|
||||
/**
|
||||
* Struct defining the configuration of a wifi channel, which can be made of one or multiple
|
||||
* channel segments.
|
||||
*/
|
||||
struct WifiChannelConfig
|
||||
{
|
||||
/// a channel segment, as a struct without units for channel width (to be deprecated when using
|
||||
/// strong types)
|
||||
struct SegmentWithoutUnits
|
||||
{
|
||||
uint8_t number{}; ///< channel number
|
||||
double width{}; ///< channel width in MHz
|
||||
WifiPhyBand band{WIFI_PHY_BAND_UNSPECIFIED}; ///< PHY band
|
||||
uint8_t p20Index{}; ///< primary20 index
|
||||
};
|
||||
|
||||
/// a channel segment, as a struct with units for channel width
|
||||
struct Segment
|
||||
{
|
||||
uint8_t number{}; ///< channel number
|
||||
MHz_u width{}; ///< channel width
|
||||
WifiPhyBand band{WIFI_PHY_BAND_UNSPECIFIED}; ///< PHY band
|
||||
uint8_t p20Index{}; ///< primary20 index
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param n the channel number
|
||||
* @param w the channel width
|
||||
* @param b the PHY band
|
||||
* @param i the primary20 index
|
||||
*/
|
||||
Segment(uint8_t n, MHz_u w, WifiPhyBand b, uint8_t i)
|
||||
: number(n),
|
||||
width(w),
|
||||
band(b),
|
||||
p20Index(i)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Converting constructor (to be deprecated when using strong types)
|
||||
*
|
||||
* @param s a channel segment as a struct without units for channel width
|
||||
*/
|
||||
Segment(const SegmentWithoutUnits& s)
|
||||
: number(s.number),
|
||||
width(MHz_u{s.width}),
|
||||
band(s.band),
|
||||
p20Index(s.p20Index)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Three-way comparison operator
|
||||
*
|
||||
* @param rhs right hand side
|
||||
* @return deduced comparison type
|
||||
*/
|
||||
auto operator<=>(const Segment& rhs) const = default;
|
||||
};
|
||||
|
||||
std::vector<Segment> segments; ///< channel config
|
||||
|
||||
WifiChannelConfig() = default;
|
||||
|
||||
/**
|
||||
* Construct a channel config from a channel segment
|
||||
*
|
||||
* @param segment the channel segment
|
||||
*/
|
||||
WifiChannelConfig(const Segment& segment)
|
||||
: segments(std::vector<Segment>{segment})
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a channel config from a segment without units for channel width
|
||||
*
|
||||
* @param s the segment without units for channel width
|
||||
*/
|
||||
WifiChannelConfig(const SegmentWithoutUnits& s)
|
||||
: WifiChannelConfig(Segment(s))
|
||||
{
|
||||
}
|
||||
|
||||
/// a channel segment, as a tuple without units for channel width (to be deprecated when using
|
||||
/// strong types)
|
||||
using TupleWithoutUnits = std::tuple<uint64_t /* channel number */,
|
||||
uint64_t /* channel width in MHz */,
|
||||
WifiPhyBand /* PHY band */,
|
||||
uint64_t /* primary20 index*/>;
|
||||
|
||||
/**
|
||||
* Construct a channel config from a list of tuples without units for channel width
|
||||
*
|
||||
* @param tuples the list of tuples without units for channel width
|
||||
*/
|
||||
WifiChannelConfig(const std::list<TupleWithoutUnits>& tuples);
|
||||
|
||||
/// @return a const reference to the first channel segment
|
||||
const Segment& front() const
|
||||
{
|
||||
return segments.front();
|
||||
}
|
||||
|
||||
/// @return a reference to the first channel segment
|
||||
Segment& front()
|
||||
{
|
||||
return segments.front();
|
||||
}
|
||||
|
||||
/**
|
||||
* Three-way comparison operator
|
||||
*
|
||||
* @param rhs right hand side
|
||||
* @return deduced comparison type
|
||||
*/
|
||||
auto operator<=>(const WifiChannelConfig& rhs) const = default;
|
||||
};
|
||||
|
||||
/**
|
||||
* The different Resource Unit (RU) types.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user