wifi: Add initial manager classes for GCR
Only GCR-UR is supported at this stage by these managers
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
197
src/wifi/model/gcr-manager.cc
Normal file
197
src/wifi/model/gcr-manager.cc
Normal 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
|
||||
144
src/wifi/model/gcr-manager.h
Normal file
144
src/wifi/model/gcr-manager.h
Normal 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 */
|
||||
57
src/wifi/model/wifi-default-gcr-manager.cc
Normal file
57
src/wifi/model/wifi-default-gcr-manager.cc
Normal 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
|
||||
45
src/wifi/model/wifi-default-gcr-manager.h
Normal file
45
src/wifi/model/wifi-default-gcr-manager.h
Normal 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 */
|
||||
Reference in New Issue
Block a user