wifi: AP processes Power Management flag in received frames
This commit is contained in:
committed by
Stefano Avallone
parent
e345ad196b
commit
8aeac2ff67
@@ -1498,6 +1498,56 @@ ApWifiMac::TxFailed(WifiMacDropReason timeoutReason, Ptr<const WifiMpdu> mpdu)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ApWifiMac::ProcessPowerManagementFlag(Ptr<const WifiMpdu> mpdu, uint8_t linkId)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << *mpdu << linkId);
|
||||
|
||||
Mac48Address staAddr = mpdu->GetHeader().GetAddr2();
|
||||
bool staInPsMode = GetWifiRemoteStationManager(linkId)->IsInPsMode(staAddr);
|
||||
|
||||
if (!staInPsMode && mpdu->GetHeader().IsPowerManagement())
|
||||
{
|
||||
// the sending STA is switching to Power Save mode
|
||||
StaSwitchingToPsMode(staAddr, linkId);
|
||||
}
|
||||
else if (staInPsMode && !mpdu->GetHeader().IsPowerManagement())
|
||||
{
|
||||
// the sending STA is switching back to Active mode
|
||||
StaSwitchingToActiveModeOrDeassociated(staAddr, linkId);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ApWifiMac::StaSwitchingToPsMode(const Mac48Address& staAddr, uint8_t linkId)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << staAddr << linkId);
|
||||
|
||||
GetWifiRemoteStationManager(linkId)->SetPsMode(staAddr, true);
|
||||
|
||||
// Block frames addressed to the STA in PS mode
|
||||
NS_LOG_DEBUG("Block destination " << staAddr << " on link " << +linkId);
|
||||
auto staMldAddr = GetWifiRemoteStationManager(linkId)->GetMldAddress(staAddr).value_or(staAddr);
|
||||
BlockUnicastTxOnLinks(WifiQueueBlockedReason::POWER_SAVE_MODE, staMldAddr, {linkId});
|
||||
}
|
||||
|
||||
void
|
||||
ApWifiMac::StaSwitchingToActiveModeOrDeassociated(const Mac48Address& staAddr, uint8_t linkId)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << staAddr << linkId);
|
||||
|
||||
GetWifiRemoteStationManager(linkId)->SetPsMode(staAddr, false);
|
||||
|
||||
if (GetWifiRemoteStationManager(linkId)->IsAssociated(staAddr))
|
||||
{
|
||||
// the station is still associated, unblock its frames
|
||||
NS_LOG_DEBUG("Unblock destination " << staAddr << " on link " << +linkId);
|
||||
auto staMldAddr =
|
||||
GetWifiRemoteStationManager(linkId)->GetMldAddress(staAddr).value_or(staAddr);
|
||||
UnblockUnicastTxOnLinks(WifiQueueBlockedReason::POWER_SAVE_MODE, staMldAddr, {linkId});
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<uint8_t>
|
||||
ApWifiMac::IsAssociated(const Mac48Address& address) const
|
||||
{
|
||||
@@ -1546,6 +1596,10 @@ ApWifiMac::Receive(Ptr<const WifiMpdu> mpdu, uint8_t linkId)
|
||||
(apLinkId = IsAssociated(mpdu->GetHeader().GetAddr2())) &&
|
||||
mpdu->GetHeader().GetAddr1() == GetFrameExchangeManager(*apLinkId)->GetAddress())
|
||||
{
|
||||
// this MPDU is being acknowledged by the AP, so we can process
|
||||
// the Power Management flag
|
||||
ProcessPowerManagementFlag(mpdu, *apLinkId);
|
||||
|
||||
Mac48Address to = hdr->GetAddr3();
|
||||
// Address3 can be our MLD address (e.g., this is an MPDU containing a single MSDU
|
||||
// addressed to us) or a BSSID (e.g., this is an MPDU containing an A-MSDU)
|
||||
@@ -1611,6 +1665,13 @@ ApWifiMac::Receive(Ptr<const WifiMpdu> mpdu, uint8_t linkId)
|
||||
}
|
||||
else if (hdr->IsMgt())
|
||||
{
|
||||
if (hdr->GetAddr1() == GetFrameExchangeManager(linkId)->GetAddress() &&
|
||||
GetWifiRemoteStationManager(linkId)->IsAssociated(from))
|
||||
{
|
||||
// this MPDU is being acknowledged by the AP, so we can process
|
||||
// the Power Management flag
|
||||
ProcessPowerManagementFlag(mpdu, linkId);
|
||||
}
|
||||
if (hdr->IsProbeReq() && (hdr->GetAddr1().IsGroup() ||
|
||||
hdr->GetAddr1() == GetFrameExchangeManager(linkId)->GetAddress()))
|
||||
{
|
||||
@@ -1685,6 +1746,7 @@ ApWifiMac::Receive(Ptr<const WifiMpdu> mpdu, uint8_t linkId)
|
||||
}
|
||||
UpdateShortSlotTimeEnabled(linkId);
|
||||
UpdateShortPreambleEnabled(linkId);
|
||||
StaSwitchingToActiveModeOrDeassociated(from, linkId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -357,6 +357,31 @@ class ApWifiMac : public WifiMac
|
||||
*/
|
||||
void SendOneBeacon(uint8_t linkId);
|
||||
|
||||
/**
|
||||
* Process the Power Management bit in the Frame Control field of an MPDU
|
||||
* successfully received on the given link.
|
||||
*
|
||||
* \param mpdu the successfully received MPDU
|
||||
* \param linkId the ID of the given link
|
||||
*/
|
||||
void ProcessPowerManagementFlag(Ptr<const WifiMpdu> mpdu, uint8_t linkId);
|
||||
/**
|
||||
* Perform the necessary actions when a given station switches from active mode
|
||||
* to powersave mode.
|
||||
*
|
||||
* \param staAddr the MAC address of the given station
|
||||
* \param linkId the ID of the link on which the given station is operating
|
||||
*/
|
||||
void StaSwitchingToPsMode(const Mac48Address& staAddr, uint8_t linkId);
|
||||
/**
|
||||
* Perform the necessary actions when a given station deassociates or switches
|
||||
* from powersave mode to active mode.
|
||||
*
|
||||
* \param staAddr the MAC address of the given station
|
||||
* \param linkId the ID of the link on which the given station is operating
|
||||
*/
|
||||
void StaSwitchingToActiveModeOrDeassociated(const Mac48Address& staAddr, uint8_t linkId);
|
||||
|
||||
/**
|
||||
* Return the Capability information of the current AP for the given link.
|
||||
*
|
||||
|
||||
@@ -42,6 +42,7 @@ class WifiMac;
|
||||
enum class WifiQueueBlockedReason : uint8_t
|
||||
{
|
||||
WAITING_ADDBA_RESP = 0,
|
||||
POWER_SAVE_MODE,
|
||||
REASONS_COUNT
|
||||
};
|
||||
|
||||
@@ -59,6 +60,8 @@ operator<<(std::ostream& os, WifiQueueBlockedReason reason)
|
||||
{
|
||||
case WifiQueueBlockedReason::WAITING_ADDBA_RESP:
|
||||
return (os << "WAITING_ADDBA_RESP");
|
||||
case WifiQueueBlockedReason::POWER_SAVE_MODE:
|
||||
return (os << "POWER_SAVE_MODE");
|
||||
case WifiQueueBlockedReason::REASONS_COUNT:
|
||||
return (os << "REASONS_COUNT");
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user