wifi: Add Txop support for link swapping

This commit is contained in:
Stefano Avallone
2023-05-18 19:57:08 +02:00
committed by Stefano Avallone
parent 44e62a838b
commit 0901e95ce4
4 changed files with 88 additions and 42 deletions

View File

@@ -640,9 +640,9 @@ QosTxop::GotAddBaResponse(const MgtAddBaResponseHeader& respHdr, Mac48Address re
m_baManager->NotifyOriginatorAgreementRejected(recipient, tid);
}
for (uint8_t linkId = 0; linkId < GetNLinks(); linkId++)
for (const auto& [id, link] : GetLinks())
{
StartAccessIfNeeded(linkId);
StartAccessIfNeeded(id);
}
}
@@ -662,9 +662,9 @@ QosTxop::NotifyOriginatorAgreementNoReply(const Mac48Address& recipient, uint8_t
m_baManager->NotifyOriginatorAgreementNoReply(recipient, tid);
// the recipient has been "unblocked" and transmissions can resume using normal
// acknowledgment, hence start access (if needed) on all the links
for (uint8_t linkId = 0; linkId < GetNLinks(); linkId++)
for (const auto& [id, link] : GetLinks())
{
StartAccessIfNeeded(linkId);
StartAccessIfNeeded(id);
}
}

View File

@@ -169,15 +169,33 @@ Txop::CreateLinkEntity() const
Txop::LinkEntity&
Txop::GetLink(uint8_t linkId) const
{
NS_ASSERT(linkId < m_links.size());
NS_ASSERT(m_links.at(linkId)); // check that the pointer owns an object
return *m_links.at(linkId);
auto it = m_links.find(linkId);
NS_ASSERT(it != m_links.cend());
NS_ASSERT(it->second); // check that the pointer owns an object
return *it->second;
}
uint8_t
Txop::GetNLinks() const
const std::map<uint8_t, std::unique_ptr<Txop::LinkEntity>>&
Txop::GetLinks() const
{
return m_links.size();
return m_links;
}
void
Txop::SwapLinks(std::map<uint8_t, uint8_t> links)
{
NS_LOG_FUNCTION(this);
decltype(m_links) tmp;
tmp.swap(m_links); // move all links to temporary map
for (const auto& [from, to] : links)
{
auto nh = tmp.extract(from);
nh.key() = to;
m_links.insert(std::move(nh));
}
// move links remaining in tmp to m_links
m_links.merge(tmp);
}
void
@@ -192,12 +210,9 @@ Txop::SetWifiMac(const Ptr<WifiMac> mac)
{
NS_LOG_FUNCTION(this << mac);
m_mac = mac;
m_links.resize(m_mac->GetNLinks());
uint8_t linkId = 0;
for (auto& link : m_links)
for (const auto linkId : m_mac->GetLinkIds())
{
link = CreateLinkEntity();
link->id = linkId++;
m_links.emplace(linkId, CreateLinkEntity());
}
}
@@ -229,9 +244,10 @@ void
Txop::SetMinCws(std::vector<uint32_t> minCws)
{
NS_ABORT_IF(minCws.size() != m_links.size());
for (std::size_t linkId = 0; linkId < minCws.size(); linkId++)
std::size_t i = 0;
for (const auto& [id, link] : m_links)
{
SetMinCw(minCws[linkId], linkId);
SetMinCw(minCws[i++], id);
}
}
@@ -258,9 +274,10 @@ void
Txop::SetMaxCws(std::vector<uint32_t> maxCws)
{
NS_ABORT_IF(maxCws.size() != m_links.size());
for (std::size_t linkId = 0; linkId < maxCws.size(); linkId++)
std::size_t i = 0;
for (const auto& [id, link] : m_links)
{
SetMaxCw(maxCws[linkId], linkId);
SetMaxCw(maxCws[i++], id);
}
}
@@ -355,9 +372,10 @@ void
Txop::SetAifsns(std::vector<uint8_t> aifsns)
{
NS_ABORT_IF(aifsns.size() != m_links.size());
for (std::size_t linkId = 0; linkId < aifsns.size(); linkId++)
std::size_t i = 0;
for (const auto& [id, link] : m_links)
{
SetAifsn(aifsns[linkId], linkId);
SetAifsn(aifsns[i++], id);
}
}
@@ -381,9 +399,10 @@ Txop::SetTxopLimits(const std::vector<Time>& txopLimits)
"The size of the given vector (" << txopLimits.size()
<< ") does not match the number of links ("
<< m_links.size() << ")");
for (std::size_t linkId = 0; linkId < txopLimits.size(); linkId++)
std::size_t i = 0;
for (const auto& [id, link] : m_links)
{
SetTxopLimit(txopLimits[linkId], linkId);
SetTxopLimit(txopLimits[i++], id);
}
}
@@ -406,9 +425,10 @@ std::vector<uint32_t>
Txop::GetMinCws() const
{
std::vector<uint32_t> ret;
for (std::size_t linkId = 0; linkId < m_links.size(); linkId++)
ret.reserve(m_links.size());
for (const auto& [id, link] : m_links)
{
ret.push_back(GetMinCw(linkId));
ret.push_back(link->cwMin);
}
return ret;
}
@@ -429,9 +449,10 @@ std::vector<uint32_t>
Txop::GetMaxCws() const
{
std::vector<uint32_t> ret;
for (std::size_t linkId = 0; linkId < m_links.size(); linkId++)
ret.reserve(m_links.size());
for (const auto& [id, link] : m_links)
{
ret.push_back(GetMaxCw(linkId));
ret.push_back(link->cwMax);
}
return ret;
}
@@ -452,9 +473,10 @@ std::vector<uint8_t>
Txop::GetAifsns() const
{
std::vector<uint8_t> ret;
for (std::size_t linkId = 0; linkId < m_links.size(); linkId++)
ret.reserve(m_links.size());
for (const auto& [id, link] : m_links)
{
ret.push_back(GetAifsn(linkId));
ret.push_back(link->aifsn);
}
return ret;
}
@@ -475,9 +497,10 @@ std::vector<Time>
Txop::GetTxopLimits() const
{
std::vector<Time> ret;
for (std::size_t linkId = 0; linkId < m_links.size(); linkId++)
ret.reserve(m_links.size());
for (const auto& [id, link] : m_links)
{
ret.push_back(GetTxopLimit(linkId));
ret.push_back(link->txopLimit);
}
return ret;
}
@@ -548,10 +571,10 @@ void
Txop::DoInitialize()
{
NS_LOG_FUNCTION(this);
for (std::size_t linkId = 0; linkId < m_links.size(); linkId++)
for (const auto& [id, link] : m_links)
{
ResetCw(linkId);
GenerateBackoff(linkId);
ResetCw(id);
GenerateBackoff(id);
}
}
@@ -630,9 +653,9 @@ void
Txop::NotifyOn()
{
NS_LOG_FUNCTION(this);
for (std::size_t linkId = 0; linkId < m_links.size(); linkId++)
for (const auto& [id, link] : m_links)
{
StartAccessIfNeeded(linkId);
StartAccessIfNeeded(id);
}
}

View File

@@ -26,6 +26,7 @@
#include "ns3/object.h"
#include "ns3/traced-value.h"
#include <map>
#include <memory>
#include <vector>
@@ -408,6 +409,16 @@ class Txop : public Object
*/
virtual bool HasFramesToTransmit(uint8_t linkId);
/**
* Swap the links based on the information included in the given map. This method
* is normally called by the WifiMac of a non-AP MLD upon completing ML setup to have
* its link IDs match AP MLD's link IDs.
*
* \param links a set of pairs (from, to) each mapping a current link ID to the
* link ID it has to become (i.e., link 'from' becomes link 'to')
*/
void SwapLinks(std::map<uint8_t, uint8_t> links);
protected:
///< ChannelAccessManager associated class
friend class ChannelAccessManager;
@@ -483,7 +494,6 @@ class Txop : public Object
/// Destructor (a virtual method is needed to make this struct polymorphic)
virtual ~LinkEntity() = default;
uint8_t id{0}; //!< Link ID (starting at 0)
uint32_t backoffSlots{0}; //!< the number of backoff slots
Time backoffStart{0}; /**< the backoffStart variable is used to keep
track of the time at which a backoff was
@@ -504,12 +514,11 @@ class Txop : public Object
* \return a reference to the link associated with the given ID
*/
LinkEntity& GetLink(uint8_t linkId) const;
/**
* Get the number of links.
*
* \return the number of links
* \return a const reference to the map of link entities
*/
uint8_t GetNLinks() const;
const std::map<uint8_t, std::unique_ptr<LinkEntity>>& GetLinks() const;
DroppedMpdu m_droppedMpduCallback; //!< the dropped MPDU callback
Ptr<WifiMacQueue> m_queue; //!< the wifi MAC queue
@@ -533,7 +542,8 @@ class Txop : public Object
*/
virtual std::unique_ptr<LinkEntity> CreateLinkEntity() const;
std::vector<std::unique_ptr<LinkEntity>> m_links; //!< vector of LinkEntity objects
std::map<uint8_t, std::unique_ptr<LinkEntity>>
m_links; //!< ID-indexed map of LinkEntity objects
};
} // namespace ns3

View File

@@ -996,6 +996,8 @@ WifiMac::SwapLinks(std::map<uint8_t, uint8_t> links)
{
NS_LOG_FUNCTION(this);
std::map<uint8_t, uint8_t> actualPairs;
while (!links.empty())
{
auto from = links.cbegin()->first;
@@ -1018,6 +1020,7 @@ WifiMac::SwapLinks(std::map<uint8_t, uint8_t> links)
auto [it, inserted] =
m_links.emplace(to, nullptr); // insert an element with key to if not present
m_links[to].swap(linkToMove); // to is the link to move now
actualPairs.emplace(from, to);
UpdateLinkId(to);
links.erase(from);
if (!linkToMove)
@@ -1034,6 +1037,7 @@ WifiMac::SwapLinks(std::map<uint8_t, uint8_t> links)
{
// no new position specified for 'to', use the current empty cell
m_links[empty].swap(linkToMove);
actualPairs.emplace(to, empty);
break;
}
@@ -1047,6 +1051,15 @@ WifiMac::SwapLinks(std::map<uint8_t, uint8_t> links)
{
m_linkIds.insert(id);
}
if (m_txop)
{
m_txop->SwapLinks(actualPairs);
}
for (auto& [ac, edca] : m_edca)
{
edca->SwapLinks(actualPairs);
}
}
void