wifi: (fixes #1072) Enable using Txop attributes to set DCF/EDCA access parameters

This commit is contained in:
Stefano Avallone
2024-03-27 16:10:06 +01:00
parent eb0b861236
commit dd49dbfac8
4 changed files with 161 additions and 53 deletions

View File

@@ -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
------------

View File

@@ -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
{

View File

@@ -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

View File

@@ -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