wifi: Add initial manager classes for GCR

Only GCR-UR is supported at this stage by these managers
This commit is contained in:
Sébastien Deronne
2023-06-10 15:47:41 +02:00
parent 0c26cfdef1
commit da9a8a92e6
6 changed files with 449 additions and 0 deletions

View File

@@ -50,6 +50,7 @@ set(source_files
model/frame-capture-model.cc
model/frame-exchange-manager.cc
model/gcr-group-address.cc
model/gcr-manager.cc
model/he/constant-obss-pd-algorithm.cc
model/he/he-6ghz-band-capabilities.cc
model/he/he-capabilities.cc
@@ -135,6 +136,7 @@ set(source_files
model/wifi-bandwidth-filter.cc
model/wifi-default-ack-manager.cc
model/wifi-default-assoc-manager.cc
model/wifi-default-gcr-manager.cc
model/wifi-default-protection-manager.cc
model/wifi-information-element.cc
model/wifi-mac-header.cc
@@ -216,6 +218,7 @@ set(header_files
model/frame-capture-model.h
model/frame-exchange-manager.h
model/gcr-group-address.h
model/gcr-manager.h
model/he/constant-obss-pd-algorithm.h
model/he/he-6ghz-band-capabilities.h
model/he/he-capabilities.h
@@ -301,6 +304,7 @@ set(header_files
model/wifi-bandwidth-filter.h
model/wifi-default-ack-manager.h
model/wifi-default-assoc-manager.h
model/wifi-default-gcr-manager.h
model/wifi-default-protection-manager.h
model/wifi-information-element.h
model/wifi-mac-header.h

View File

@@ -1197,6 +1197,7 @@ WifiHelper::EnableLogComponents(LogLevel logLevel)
LogComponentEnable("ErpOfdmPhy", logLevel);
LogComponentEnable("ErpOfdmPpdu", logLevel);
LogComponentEnable("FrameExchangeManager", logLevel);
LogComponentEnable("GcrManager", logLevel);
LogComponentEnable("HeConfiguration", logLevel);
LogComponentEnable("HeFrameExchangeManager", logLevel);
LogComponentEnable("HePhy", logLevel);
@@ -1244,6 +1245,7 @@ WifiHelper::EnableLogComponents(LogLevel logLevel)
LogComponentEnable("WifiAssocManager", logLevel);
LogComponentEnable("WifiDefaultAckManager", logLevel);
LogComponentEnable("WifiDefaultAssocManager", logLevel);
LogComponentEnable("WifiDefaultGcrManager", logLevel);
LogComponentEnable("WifiDefaultProtectionManager", logLevel);
LogComponentEnable("WifiMac", logLevel);
LogComponentEnable("WifiMacQueue", logLevel);

View File

@@ -0,0 +1,197 @@
/*
* Copyright (c) 2023 DERONNE SOFTWARE ENGINEERING
*
* SPDX-License-Identifier: GPL-2.0-only
*
* Author: Sébastien Deronne <sebastien.deronne@gmail.com>
*/
#include "gcr-manager.h"
#include "ap-wifi-mac.h"
#include "wifi-mpdu.h"
#include "ns3/enum.h"
#include "ns3/log.h"
#include "ns3/uinteger.h"
#include <algorithm>
namespace ns3
{
NS_LOG_COMPONENT_DEFINE("GcrManager");
NS_OBJECT_ENSURE_REGISTERED(GcrManager);
TypeId
GcrManager::GetTypeId()
{
static TypeId tid =
TypeId("ns3::GcrManager")
.SetParent<Object>()
.SetGroupName("Wifi")
.AddAttribute("RetransmissionPolicy",
"The retransmission policy to use for group addresses.",
TypeId::ATTR_GET |
TypeId::ATTR_CONSTRUCT, // prevent setting after construction
EnumValue(GroupAddressRetransmissionPolicy::NO_ACK_NO_RETRY),
MakeEnumAccessor<GroupAddressRetransmissionPolicy>(
&GcrManager::m_retransmissionPolicy),
MakeEnumChecker(GroupAddressRetransmissionPolicy::NO_ACK_NO_RETRY,
"NO_RETRY",
GroupAddressRetransmissionPolicy::GCR_UNSOLICITED_RETRY,
"GCR_UR"))
.AddAttribute("UnsolicitedRetryLimit",
"The maximum number of transmission attempts of a frame delivered using "
"the GCR unsolicited retry retransmission policy.",
UintegerValue(7),
MakeUintegerAccessor(&GcrManager::m_gcrUnsolicitedRetryLimit),
MakeUintegerChecker<uint8_t>());
return tid;
}
GcrManager::GcrManager()
: m_unsolicitedRetryCounter{0}
{
NS_LOG_FUNCTION(this);
}
GcrManager::~GcrManager()
{
NS_LOG_FUNCTION(this);
}
void
GcrManager::DoDispose()
{
NS_LOG_FUNCTION(this);
m_apMac = nullptr;
Object::DoDispose();
}
void
GcrManager::SetWifiMac(Ptr<ApWifiMac> mac)
{
NS_LOG_FUNCTION(this << mac);
NS_ASSERT(mac);
m_apMac = mac;
NS_ABORT_MSG_IF(m_apMac->GetTypeOfStation() != AP || !m_apMac->GetQosSupported(),
"GcrManager can only be installed on QoS APs");
}
GroupAddressRetransmissionPolicy
GcrManager::GetRetransmissionPolicy() const
{
return m_retransmissionPolicy;
}
GroupAddressRetransmissionPolicy
GcrManager::GetRetransmissionPolicyFor(const WifiMacHeader& header) const
{
NS_ASSERT_MSG(header.IsQosData() && IsGroupcast(header.GetAddr1()),
"GCR service is only for QoS groupcast data frames");
// 11.21.16.3.4 GCR operation:
// A STA providing GCR service may switch between the DMS,
// GCR block ack, or GCR unsolicited retry retransmission policies
// This is a retry, use configured retransmission policy
if (header.IsRetry())
{
return m_retransmissionPolicy;
}
// This is not a retry but all STAs are GCR-capable, use configured retransmission policy
if (m_nonGcrStas.empty())
{
return m_retransmissionPolicy;
}
// not a retry and GCR-incapable STA(s) present, transmit using No-Ack/No-Retry
return GroupAddressRetransmissionPolicy::NO_ACK_NO_RETRY;
}
bool
GcrManager::KeepGroupcastQueued(Ptr<WifiMpdu> mpdu)
{
NS_LOG_FUNCTION(this << *mpdu);
NS_ASSERT_MSG(mpdu->GetHeader().IsQosData() && IsGroupcast(mpdu->GetHeader().GetAddr1()),
"GCR service is only for QoS groupcast data frames");
NS_ASSERT_MSG(m_retransmissionPolicy != GroupAddressRetransmissionPolicy::NO_ACK_NO_RETRY,
"GCR service is not enabled");
NS_ASSERT_MSG(!m_staMembers.empty(), "GCR service should not be used");
if (!m_mpdu || !mpdu->GetHeader().IsRetry())
{
m_unsolicitedRetryCounter = 0;
m_mpdu = mpdu;
NS_LOG_DEBUG("First groupcast transmission using No-Ack/No-Retry");
}
else
{
m_unsolicitedRetryCounter++;
NS_LOG_DEBUG("GCR solicited retry counter increased to " << +m_unsolicitedRetryCounter);
}
if (m_unsolicitedRetryCounter == m_gcrUnsolicitedRetryLimit)
{
NS_LOG_DEBUG("Last groupcast transmission retry done");
m_mpdu = nullptr;
m_unsolicitedRetryCounter = 0;
return false;
}
return true;
}
void
GcrManager::NotifyStaAssociated(const Mac48Address& staAddress, bool gcrCapable)
{
if (m_retransmissionPolicy == GroupAddressRetransmissionPolicy::NO_ACK_NO_RETRY)
{
// GCR is not used and we do not support run-time change of the retransmission policy
return;
}
NS_LOG_FUNCTION(this << staAddress << gcrCapable);
if (gcrCapable)
{
NS_ASSERT(m_staMembers.count(staAddress) == 0);
m_staMembers.insert(staAddress);
}
else
{
NS_ASSERT(m_nonGcrStas.count(staAddress) == 0);
m_nonGcrStas.insert(staAddress);
}
}
void
GcrManager::NotifyStaDeassociated(const Mac48Address& staAddress)
{
if (m_retransmissionPolicy == GroupAddressRetransmissionPolicy::NO_ACK_NO_RETRY)
{
// GCR is not used and we do not support run-time change of the retransmission policy
return;
}
NS_LOG_FUNCTION(this << staAddress);
m_nonGcrStas.erase(staAddress);
m_staMembers.erase(staAddress);
}
const GcrManager::GcrMembers&
GcrManager::GetMemberStasForGroupAddress(const Mac48Address& /* groupAddress */) const
{
// TODO: we currently assume all STAs belong to all group addresses
// as long as group membership action frame is not implemented
return m_staMembers;
}
void
GcrManager::NotifyGroupMembershipChanged(const Mac48Address& staAddress,
const std::set<Mac48Address>& groupAddressList)
{
NS_LOG_FUNCTION(this << staAddress << groupAddressList.size());
// TODO: group membership is not implemented yet, current implementation assumes GCR STAs are
// members of all groups
}
} // namespace ns3

View File

@@ -0,0 +1,144 @@
/*
* Copyright (c) 2023 DERONNE SOFTWARE ENGINEERING
*
* SPDX-License-Identifier: GPL-2.0-only
*
* Author: Sébastien Deronne <sebastien.deronne@gmail.com>
*/
#ifndef GCR_MANAGER_H
#define GCR_MANAGER_H
#include "qos-utils.h"
#include "ns3/mac48-address.h"
#include "ns3/object.h"
#include <set>
#include <unordered_set>
namespace ns3
{
class ApWifiMac;
class WifiMpdu;
/**
* @brief The possible values for group address retransmission policy
*/
enum class GroupAddressRetransmissionPolicy : uint8_t
{
NO_ACK_NO_RETRY = 0,
GCR_UNSOLICITED_RETRY
};
/**
* @ingroup wifi
*
* GcrManager is a base class defining the API to handle 802.11aa GCR.
*/
class GcrManager : public Object
{
public:
/**
* @brief Get the type ID.
* @return the object TypeId
*/
static TypeId GetTypeId();
GcrManager();
~GcrManager() override;
/**
* Set the wifi MAC. Note that it must be the MAC of a QoS AP.
*
* @param mac the wifi MAC
*/
void SetWifiMac(Ptr<ApWifiMac> mac);
/**
* Get the configured retransmission policy.
*
* @return the configured retransmission policy
*/
GroupAddressRetransmissionPolicy GetRetransmissionPolicy() const;
/**
* Get the retransmission policy to use to transmit a given group addressed packet.
*
* @param header the header of the groupcast frame
* @return the retransmission policy to use
*/
GroupAddressRetransmissionPolicy GetRetransmissionPolicyFor(const WifiMacHeader& header) const;
/**
* This function indicates whether a groupcast MPDU should be kept for next retransmission.
*
* @param mpdu the groupcast MPDU
* @return whether a groupcast MPDU should be kept for next retransmission
*/
bool KeepGroupcastQueued(Ptr<WifiMpdu> mpdu);
/**
* This function notifies a STA is associated.
*
* @param staAddress the MAC address of the STA
* @param isGcrCapable whether GCR is supported by the STA
*/
void NotifyStaAssociated(const Mac48Address& staAddress, bool isGcrCapable);
/**
* This function deletes a STA as a member of any group addresses.
*
* @param staAddress the MAC address of the STA
*/
void NotifyStaDeassociated(const Mac48Address& staAddress);
/**
* This function adds a STA as a member of zero or more group addresses.
*
* @param staAddress the MAC address of the STA
* @param groupAddressList zero or more MAC addresses to indicate the set of group addressed MAC
* addresses for which the STA receives frames
*/
void NotifyGroupMembershipChanged(const Mac48Address& staAddress,
const std::set<Mac48Address>& groupAddressList);
/// MAC addresses of member STAs of a GCR group
using GcrMembers = std::unordered_set<Mac48Address, WifiAddressHash>;
/**
* Get the list of MAC addresses of member STAs for a given group address.
* @param groupAddress the group address
* @return list of MAC addresses of member STAs for the group address
*/
const GcrMembers& GetMemberStasForGroupAddress(const Mac48Address& groupAddress) const;
/**
* Get the MAC address of the individually addressed recipient to use for a groupcast frame for
* a given group address.
* @param groupAddress the group address
* @return the MAC address of the individually addressed recipient to use.
*/
virtual Mac48Address GetIndividuallyAddressedRecipient(
const Mac48Address& groupAddress) const = 0;
protected:
void DoDispose() override;
/// List of associated STAs that are not GCR capable
using NonGcrStas = GcrMembers;
Ptr<ApWifiMac> m_apMac; //!< the MAC of the AP
GroupAddressRetransmissionPolicy m_retransmissionPolicy; //!< retransmission policy
uint8_t m_gcrUnsolicitedRetryLimit; //!< GCR Unsolicited Retry Limit
uint8_t m_unsolicitedRetryCounter; //!< the unsolicited retry counter
Ptr<WifiMpdu> m_mpdu; //!< current MPDU being retransmitted
NonGcrStas m_nonGcrStas; //!< the list of non-GCR capable STAs
GcrMembers m_staMembers; //!< the list of STA members (assume currently each member is part of
//!< all group)
};
} // namespace ns3
#endif /* GCR_MANAGER_H */

View File

@@ -0,0 +1,57 @@
/*
* Copyright (c) 2023 DERONNE SOFTWARE ENGINEERING
*
* SPDX-License-Identifier: GPL-2.0-only
*
* Author: Sébastien Deronne <sebastien.deronne@gmail.com>
*/
#include "wifi-default-gcr-manager.h"
#include "ap-wifi-mac.h"
#include "ns3/log.h"
namespace ns3
{
NS_LOG_COMPONENT_DEFINE("WifiDefaultGcrManager");
NS_OBJECT_ENSURE_REGISTERED(WifiDefaultGcrManager);
TypeId
WifiDefaultGcrManager::GetTypeId()
{
static TypeId tid = TypeId("ns3::WifiDefaultGcrManager")
.SetParent<GcrManager>()
.SetGroupName("Wifi")
.AddConstructor<WifiDefaultGcrManager>();
return tid;
}
WifiDefaultGcrManager::WifiDefaultGcrManager()
{
NS_LOG_FUNCTION(this);
}
WifiDefaultGcrManager::~WifiDefaultGcrManager()
{
NS_LOG_FUNCTION_NOARGS();
}
Mac48Address
WifiDefaultGcrManager::GetIndividuallyAddressedRecipient(
const Mac48Address& /* groupAddress */) const
{
/*
* 802.11-2020: 10.23.2.12.2 Unsolicited retry procedure:
* When using a protection mechanism that requires a response from another STA,
* the AP should select a STA that is a member of the GCR group.
* For now, we assume all associated GCR-capable STAs are part of the GCR group,
* hence we pick the first STA from the list held by the AP.
*/
NS_ASSERT(!m_staMembers.empty());
return *m_staMembers.cbegin();
}
} // namespace ns3

View File

@@ -0,0 +1,45 @@
/*
* Copyright (c) 2023 DERONNE SOFTWARE ENGINEERING
*
* SPDX-License-Identifier: GPL-2.0-only
*
* Author: Sébastien Deronne <sebastien.deronne@gmail.com>
*/
#ifndef WIFI_DEFAULT_GCR_MANAGER_H
#define WIFI_DEFAULT_GCR_MANAGER_H
#include "gcr-manager.h"
namespace ns3
{
/**
* @ingroup wifi
*
* WifiDefaultGcrManager is the default implementation for groupcast with retries GCR, as defined in
* 802.11aa. Since the standard does not describe how to map GCR-capable STAs to a given GCR group,
* the default implementation assumes all GCR-capable STAs are part of all GCR groups. Also, it is
* left left open to implementation which individual address to use to use while protecting a GCR
* transmission. The default implementation decides to pick the address of the first associated
* GCR-capable STA.
*/
class WifiDefaultGcrManager : public GcrManager
{
public:
/**
* @brief Get the type ID.
* @return the object TypeId
*/
static TypeId GetTypeId();
WifiDefaultGcrManager();
~WifiDefaultGcrManager() override;
Mac48Address GetIndividuallyAddressedRecipient(
const Mac48Address& groupcastAddress) const override;
};
} // namespace ns3
#endif /* WIFI_DEFAULT_GCR_MANAGER_H */