wifi: (fixes #1072) Enable using Txop attributes to set DCF/EDCA access parameters
This commit is contained in:
@@ -43,6 +43,7 @@ been tested on Linux. The latest known version to work with ns-3 is cppyy==3.1.2
|
||||
- (bindings, core) - Introduced a helper class to manage static initialization of Time as a workaround for Cppyy3 static initialization problems.
|
||||
- (bindings, lte, wifi) - Relocated statically initialized variables from header files to source files for Cppyy3 compatibility.
|
||||
- (tests) - Enhanced error handling in test.py to avoid attempts to open non-existent XML files following early test termination by sanitizers.
|
||||
- (wifi) #1072 - Support configuration of custom EDCA parameters via Txop attributes before device installation
|
||||
|
||||
Release 3.41
|
||||
------------
|
||||
|
||||
@@ -87,8 +87,11 @@ Txop::GetTypeId()
|
||||
"Use MinCws attribute instead of MinCw")
|
||||
.AddAttribute(
|
||||
"MinCws",
|
||||
"The minimum values of the contention window for all the links",
|
||||
TypeId::ATTR_GET | TypeId::ATTR_SET, // do not set at construction time
|
||||
"The minimum values of the contention window for all the links (sorted in "
|
||||
"increasing order of link ID). An empty vector is ignored and the default value "
|
||||
"as per Table 9-155 of the IEEE 802.11-2020 standard will be used. Note that, if "
|
||||
"this is a non-AP STA, these values could be overridden by values advertised by "
|
||||
"the AP through EDCA Parameter Set elements.",
|
||||
AttributeContainerValue<UintegerValue>(),
|
||||
MakeAttributeContainerAccessor<UintegerValue>(&Txop::SetMinCws, &Txop::GetMinCws),
|
||||
MakeAttributeContainerChecker<UintegerValue>(MakeUintegerChecker<uint32_t>()))
|
||||
@@ -104,8 +107,11 @@ Txop::GetTypeId()
|
||||
"Use MaxCws attribute instead of MaxCw")
|
||||
.AddAttribute(
|
||||
"MaxCws",
|
||||
"The maximum values of the contention window for all the links",
|
||||
TypeId::ATTR_GET | TypeId::ATTR_SET, // do not set at construction time
|
||||
"The maximum values of the contention window for all the links (sorted in "
|
||||
"increasing order of link ID). An empty vector is ignored and the default value "
|
||||
"as per Table 9-155 of the IEEE 802.11-2020 standard will be used. Note that, if "
|
||||
"this is a non-AP STA, these values could be overridden by values advertised by "
|
||||
"the AP through EDCA Parameter Set elements.",
|
||||
AttributeContainerValue<UintegerValue>(),
|
||||
MakeAttributeContainerAccessor<UintegerValue>(&Txop::SetMaxCws, &Txop::GetMaxCws),
|
||||
MakeAttributeContainerChecker<UintegerValue>(MakeUintegerChecker<uint32_t>()))
|
||||
@@ -122,8 +128,11 @@ Txop::GetTypeId()
|
||||
"Use Aifsns attribute instead of Aifsn")
|
||||
.AddAttribute(
|
||||
"Aifsns",
|
||||
"The values of AIFSN for all the links",
|
||||
TypeId::ATTR_GET | TypeId::ATTR_SET, // do not set at construction time
|
||||
"The values of AIFSN for all the links (sorted in increasing order "
|
||||
"of link ID). An empty vector is ignored and the default value as per "
|
||||
"Table 9-155 of the IEEE 802.11-2020 standard will be used. Note that, if "
|
||||
"this is a non-AP STA, these values could be overridden by values advertised by "
|
||||
"the AP through EDCA Parameter Set elements.",
|
||||
AttributeContainerValue<UintegerValue>(),
|
||||
MakeAttributeContainerAccessor<UintegerValue>(&Txop::SetAifsns, &Txop::GetAifsns),
|
||||
MakeAttributeContainerChecker<UintegerValue>(MakeUintegerChecker<uint8_t>()))
|
||||
@@ -137,13 +146,17 @@ Txop::GetTypeId()
|
||||
MakeTimeChecker(),
|
||||
TypeId::OBSOLETE,
|
||||
"Use TxopLimits attribute instead of TxopLimit")
|
||||
.AddAttribute("TxopLimits",
|
||||
"The values of TXOP limit for all the links",
|
||||
TypeId::ATTR_GET | TypeId::ATTR_SET, // do not set at construction time
|
||||
AttributeContainerValue<TimeValue>(),
|
||||
MakeAttributeContainerAccessor<TimeValue>(&Txop::SetTxopLimits,
|
||||
&Txop::GetTxopLimits),
|
||||
MakeAttributeContainerChecker<TimeValue>(MakeTimeChecker()))
|
||||
.AddAttribute(
|
||||
"TxopLimits",
|
||||
"The values of TXOP limit for all the links (sorted in increasing order "
|
||||
"of link ID). An empty vector is ignored and the default value as per "
|
||||
"Table 9-155 of the IEEE 802.11-2020 standard will be used. Note that, if "
|
||||
"this is a non-AP STA, these values could be overridden by values advertised by "
|
||||
"the AP through EDCA Parameter Set elements.",
|
||||
AttributeContainerValue<TimeValue>(),
|
||||
MakeAttributeContainerAccessor<TimeValue>(&Txop::SetTxopLimits,
|
||||
&Txop::GetTxopLimits),
|
||||
MakeAttributeContainerChecker<TimeValue>(MakeTimeChecker()))
|
||||
.AddAttribute("Queue",
|
||||
"The WifiMacQueue object",
|
||||
PointerValue(),
|
||||
@@ -270,9 +283,20 @@ Txop::SetMinCw(uint32_t minCw)
|
||||
}
|
||||
|
||||
void
|
||||
Txop::SetMinCws(std::vector<uint32_t> minCws)
|
||||
Txop::SetMinCws(const std::vector<uint32_t>& minCws)
|
||||
{
|
||||
NS_ABORT_IF(minCws.size() != m_links.size());
|
||||
if (minCws.empty())
|
||||
{
|
||||
// an empty vector is passed to use the default values specified by the standard
|
||||
return;
|
||||
}
|
||||
|
||||
NS_ABORT_MSG_IF(!m_links.empty() && minCws.size() != m_links.size(),
|
||||
"The size of the given vector (" << minCws.size()
|
||||
<< ") does not match the number of links ("
|
||||
<< m_links.size() << ")");
|
||||
m_userAccessParams.cwMins = minCws;
|
||||
|
||||
std::size_t i = 0;
|
||||
for (const auto& [id, link] : m_links)
|
||||
{
|
||||
@@ -284,6 +308,8 @@ void
|
||||
Txop::SetMinCw(uint32_t minCw, uint8_t linkId)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << minCw << linkId);
|
||||
NS_ASSERT_MSG(!m_links.empty(),
|
||||
"This function can only be called after that links have been created");
|
||||
auto& link = GetLink(linkId);
|
||||
bool changed = (link.cwMin != minCw);
|
||||
link.cwMin = minCw;
|
||||
@@ -300,9 +326,20 @@ Txop::SetMaxCw(uint32_t maxCw)
|
||||
}
|
||||
|
||||
void
|
||||
Txop::SetMaxCws(std::vector<uint32_t> maxCws)
|
||||
Txop::SetMaxCws(const std::vector<uint32_t>& maxCws)
|
||||
{
|
||||
NS_ABORT_IF(maxCws.size() != m_links.size());
|
||||
if (maxCws.empty())
|
||||
{
|
||||
// an empty vector is passed to use the default values specified by the standard
|
||||
return;
|
||||
}
|
||||
|
||||
NS_ABORT_MSG_IF(!m_links.empty() && maxCws.size() != m_links.size(),
|
||||
"The size of the given vector (" << maxCws.size()
|
||||
<< ") does not match the number of links ("
|
||||
<< m_links.size() << ")");
|
||||
m_userAccessParams.cwMaxs = maxCws;
|
||||
|
||||
std::size_t i = 0;
|
||||
for (const auto& [id, link] : m_links)
|
||||
{
|
||||
@@ -314,6 +351,8 @@ void
|
||||
Txop::SetMaxCw(uint32_t maxCw, uint8_t linkId)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << maxCw << linkId);
|
||||
NS_ASSERT_MSG(!m_links.empty(),
|
||||
"This function can only be called after that links have been created");
|
||||
auto& link = GetLink(linkId);
|
||||
bool changed = (link.cwMax != maxCw);
|
||||
link.cwMax = maxCw;
|
||||
@@ -398,9 +437,20 @@ Txop::SetAifsn(uint8_t aifsn)
|
||||
}
|
||||
|
||||
void
|
||||
Txop::SetAifsns(std::vector<uint8_t> aifsns)
|
||||
Txop::SetAifsns(const std::vector<uint8_t>& aifsns)
|
||||
{
|
||||
NS_ABORT_IF(aifsns.size() != m_links.size());
|
||||
if (aifsns.empty())
|
||||
{
|
||||
// an empty vector is passed to use the default values specified by the standard
|
||||
return;
|
||||
}
|
||||
|
||||
NS_ABORT_MSG_IF(!m_links.empty() && aifsns.size() != m_links.size(),
|
||||
"The size of the given vector (" << aifsns.size()
|
||||
<< ") does not match the number of links ("
|
||||
<< m_links.size() << ")");
|
||||
m_userAccessParams.aifsns = aifsns;
|
||||
|
||||
std::size_t i = 0;
|
||||
for (const auto& [id, link] : m_links)
|
||||
{
|
||||
@@ -412,6 +462,8 @@ void
|
||||
Txop::SetAifsn(uint8_t aifsn, uint8_t linkId)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << aifsn << linkId);
|
||||
NS_ASSERT_MSG(!m_links.empty(),
|
||||
"This function can only be called after that links have been created");
|
||||
GetLink(linkId).aifsn = aifsn;
|
||||
}
|
||||
|
||||
@@ -424,10 +476,18 @@ Txop::SetTxopLimit(Time txopLimit)
|
||||
void
|
||||
Txop::SetTxopLimits(const std::vector<Time>& txopLimits)
|
||||
{
|
||||
NS_ABORT_MSG_IF(txopLimits.size() != m_links.size(),
|
||||
if (txopLimits.empty())
|
||||
{
|
||||
// an empty vector is passed to use the default values specified by the standard
|
||||
return;
|
||||
}
|
||||
|
||||
NS_ABORT_MSG_IF(!m_links.empty() && txopLimits.size() != m_links.size(),
|
||||
"The size of the given vector (" << txopLimits.size()
|
||||
<< ") does not match the number of links ("
|
||||
<< m_links.size() << ")");
|
||||
m_userAccessParams.txopLimits = txopLimits;
|
||||
|
||||
std::size_t i = 0;
|
||||
for (const auto& [id, link] : m_links)
|
||||
{
|
||||
@@ -439,11 +499,20 @@ void
|
||||
Txop::SetTxopLimit(Time txopLimit, uint8_t linkId)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << txopLimit << linkId);
|
||||
NS_ASSERT_MSG(txopLimit.IsPositive(), "TXOP limit cannot be negative");
|
||||
NS_ASSERT_MSG((txopLimit.GetMicroSeconds() % 32 == 0),
|
||||
"The TXOP limit must be expressed in multiple of 32 microseconds!");
|
||||
NS_ASSERT_MSG(!m_links.empty(),
|
||||
"This function can only be called after that links have been created");
|
||||
GetLink(linkId).txopLimit = txopLimit;
|
||||
}
|
||||
|
||||
const Txop::UserDefinedAccessParams&
|
||||
Txop::GetUserAccessParams() const
|
||||
{
|
||||
return m_userAccessParams;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
Txop::GetMinCw() const
|
||||
{
|
||||
|
||||
@@ -146,14 +146,16 @@ class Txop : public Object
|
||||
void SetMinCw(uint32_t minCw);
|
||||
/**
|
||||
* Set the minimum contention window size for each link.
|
||||
* Note that the size of <i>minCws</i> must match the number
|
||||
* Note that an empty <i>minCws</i> is ignored, otherwise its size must match the number
|
||||
* of links.
|
||||
*
|
||||
* \param minCws the minimum contention window size values.
|
||||
* \param minCws the minimum contention window size for each link (links are sorted in
|
||||
* increasing order of link ID).
|
||||
*/
|
||||
void SetMinCws(std::vector<uint32_t> minCws);
|
||||
void SetMinCws(const std::vector<uint32_t>& minCws);
|
||||
/**
|
||||
* Set the minimum contention window size for the given link.
|
||||
* Set the minimum contention window size for the given link. Note that this function can
|
||||
* only be called after that links have been created.
|
||||
*
|
||||
* \param minCw the minimum contention window size.
|
||||
* \param linkId the ID of the given link
|
||||
@@ -168,14 +170,16 @@ class Txop : public Object
|
||||
void SetMaxCw(uint32_t maxCw);
|
||||
/**
|
||||
* Set the maximum contention window size for each link.
|
||||
* Note that the size of <i>maxCws</i> must match the number
|
||||
* Note that an empty <i>maxCws</i> is ignored, otherwise its size must match the number
|
||||
* of links.
|
||||
*
|
||||
* \param maxCws the maximum contention window size values.
|
||||
* \param maxCws the maximum contention window size for each link (links are sorted in
|
||||
* increasing order of link ID).
|
||||
*/
|
||||
void SetMaxCws(std::vector<uint32_t> maxCws);
|
||||
void SetMaxCws(const std::vector<uint32_t>& maxCws);
|
||||
/**
|
||||
* Set the maximum contention window size for the given link.
|
||||
* Set the maximum contention window size for the given link. Note that this function can
|
||||
* only be called after that links have been created.
|
||||
*
|
||||
* \param maxCw the maximum contention window size.
|
||||
* \param linkId the ID of the given link
|
||||
@@ -190,14 +194,16 @@ class Txop : public Object
|
||||
void SetAifsn(uint8_t aifsn);
|
||||
/**
|
||||
* Set the number of slots that make up an AIFS for each link.
|
||||
* Note that the size of <i>aifsns</i> must match the number
|
||||
* Note that an empty <i>aifsns</i> is ignored, otherwise its size must match the number
|
||||
* of links.
|
||||
*
|
||||
* \param aifsns the number of slots that make up an AIFS for each link.
|
||||
* \param aifsns the number of slots that make up an AIFS for each link (links are sorted in
|
||||
* increasing order of link ID).
|
||||
*/
|
||||
void SetAifsns(std::vector<uint8_t> aifsns);
|
||||
void SetAifsns(const std::vector<uint8_t>& aifsns);
|
||||
/**
|
||||
* Set the number of slots that make up an AIFS for the given link.
|
||||
* Set the number of slots that make up an AIFS for the given link. Note that this function
|
||||
* can only be called after that links have been created.
|
||||
*
|
||||
* \param aifsn the number of slots that make up an AIFS.
|
||||
* \param linkId the ID of the given link
|
||||
@@ -212,17 +218,18 @@ class Txop : public Object
|
||||
void SetTxopLimit(Time txopLimit);
|
||||
/**
|
||||
* Set the TXOP limit for each link.
|
||||
* Note that the size of <i>txopLimits</i> must match the number
|
||||
* Note that an empty <i>txopLimits</i> is ignored, otherwise its size must match the number
|
||||
* of links.
|
||||
*
|
||||
* \param txopLimits the TXOP limit for each link.
|
||||
* \param txopLimits the TXOP limit for each link (links are sorted in increasing order of
|
||||
* link ID).
|
||||
*/
|
||||
void SetTxopLimits(const std::vector<Time>& txopLimits);
|
||||
/**
|
||||
* Set the TXOP limit for the given link.
|
||||
* Set the TXOP limit for the given link. Note that this function can only be called after
|
||||
* that links have been created.
|
||||
*
|
||||
* \param txopLimit the TXOP limit.
|
||||
* Value zero corresponds to default Txop.
|
||||
* \param txopLimit the TXOP limit (must not be negative)
|
||||
* \param linkId the ID of the given link
|
||||
*/
|
||||
void SetTxopLimit(Time txopLimit, uint8_t linkId);
|
||||
@@ -447,6 +454,25 @@ class Txop : public Object
|
||||
*/
|
||||
void SwapLinks(std::map<uint8_t, uint8_t> links);
|
||||
|
||||
/**
|
||||
* DCF/EDCA access parameters for all the links provided by users via this class' attributes
|
||||
* or the corresponding setter methods. For each access parameter, values are sorted in
|
||||
* increasing order of link ID. If user provides access parameters, they are used by WifiMac
|
||||
* instead of the default values specified by Table 9-155 of 802.11-2020.
|
||||
*/
|
||||
struct UserDefinedAccessParams
|
||||
{
|
||||
std::vector<uint32_t> cwMins; //!< the minimum contention window values for all the links
|
||||
std::vector<uint32_t> cwMaxs; //!< the maximum contention window values for all the links
|
||||
std::vector<uint8_t> aifsns; //!< the AIFSN values for all the links
|
||||
std::vector<Time> txopLimits; //!< TXOP limit values for all the links
|
||||
};
|
||||
|
||||
/**
|
||||
* \return a const reference to user-provided access parameters
|
||||
*/
|
||||
const UserDefinedAccessParams& GetUserAccessParams() const;
|
||||
|
||||
protected:
|
||||
///< ChannelAccessManager associated class
|
||||
friend class ChannelAccessManager;
|
||||
@@ -581,6 +607,8 @@ class Txop : public Object
|
||||
|
||||
std::map<uint8_t, std::unique_ptr<LinkEntity>>
|
||||
m_links; //!< ID-indexed map of LinkEntity objects
|
||||
|
||||
UserDefinedAccessParams m_userAccessParams; //!< user-defined DCF/EDCA access parameters
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
@@ -824,23 +824,33 @@ WifiMac::ConfigureDcf(Ptr<Txop> dcf,
|
||||
break;
|
||||
}
|
||||
|
||||
std::vector<uint32_t> cwValues(m_links.size());
|
||||
std::vector<uint8_t> aifsnValues(m_links.size());
|
||||
std::vector<Time> txopLimitValues(m_links.size());
|
||||
const auto& userDefinedParams = dcf->GetUserAccessParams();
|
||||
|
||||
std::fill(cwValues.begin(), cwValues.end(), cwMinValue);
|
||||
dcf->SetMinCws(cwValues);
|
||||
std::fill(cwValues.begin(), cwValues.end(), cwMaxValue);
|
||||
dcf->SetMaxCws(cwValues);
|
||||
std::fill(aifsnValues.begin(), aifsnValues.end(), aifsnValue);
|
||||
dcf->SetAifsns(aifsnValues);
|
||||
std::transform(isDsss.begin(),
|
||||
isDsss.end(),
|
||||
txopLimitValues.begin(),
|
||||
[&txopLimitDsss, &txopLimitNoDsss](bool dsss) {
|
||||
return (dsss ? txopLimitDsss : txopLimitNoDsss);
|
||||
});
|
||||
dcf->SetTxopLimits(txopLimitValues);
|
||||
dcf->SetMinCws(!userDefinedParams.cwMins.empty()
|
||||
? userDefinedParams.cwMins
|
||||
: std::vector<uint32_t>(m_links.size(), cwMinValue));
|
||||
dcf->SetMaxCws(!userDefinedParams.cwMaxs.empty()
|
||||
? userDefinedParams.cwMaxs
|
||||
: std::vector<uint32_t>(m_links.size(), cwMaxValue));
|
||||
dcf->SetAifsns(!userDefinedParams.aifsns.empty()
|
||||
? userDefinedParams.aifsns
|
||||
: std::vector<uint8_t>(m_links.size(), aifsnValue));
|
||||
|
||||
if (!userDefinedParams.txopLimits.empty())
|
||||
{
|
||||
dcf->SetTxopLimits(userDefinedParams.txopLimits);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<Time> txopLimitValues(m_links.size());
|
||||
std::transform(isDsss.begin(),
|
||||
isDsss.end(),
|
||||
txopLimitValues.begin(),
|
||||
[&txopLimitDsss, &txopLimitNoDsss](bool dsss) {
|
||||
return (dsss ? txopLimitDsss : txopLimitNoDsss);
|
||||
});
|
||||
dcf->SetTxopLimits(txopLimitValues);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
Reference in New Issue
Block a user