wifi: Refactor StaWifiMac::Receive()

This commit is contained in:
Stefano Avallone
2022-06-20 13:10:41 +02:00
parent 825ab44017
commit b348edb951
2 changed files with 162 additions and 111 deletions

View File

@@ -602,7 +602,7 @@ StaWifiMac::Receive (Ptr<WifiMacQueueItem> mpdu, uint8_t linkId)
NS_LOG_LOGIC ("packet sent by us.");
return;
}
else if (hdr->GetAddr1 () != GetAddress ()
if (hdr->GetAddr1 () != GetAddress ()
&& !hdr->GetAddr1 ().IsGroup ())
{
NS_LOG_LOGIC ("packet is not for us");
@@ -648,130 +648,157 @@ StaWifiMac::Receive (Ptr<WifiMacQueueItem> mpdu, uint8_t linkId)
}
return;
}
else if (hdr->IsProbeReq ()
|| hdr->IsAssocReq ()
|| hdr->IsReassocReq ())
switch (hdr->GetType ())
{
case WIFI_MAC_MGT_PROBE_REQUEST:
case WIFI_MAC_MGT_ASSOCIATION_REQUEST:
case WIFI_MAC_MGT_REASSOCIATION_REQUEST:
//This is a frame aimed at an AP, so we can safely ignore it.
NotifyRxDrop (packet);
return;
}
else if (hdr->IsBeacon ())
{
NS_LOG_DEBUG ("Beacon received");
MgtBeaconHeader beacon;
Ptr<Packet> copy = packet->Copy ();
copy->RemoveHeader (beacon);
const CapabilityInformation& capabilities = beacon.GetCapabilities ();
NS_ASSERT (capabilities.IsEss ());
bool goodBeacon;
if (IsWaitAssocResp () || IsAssociated ())
{
// we have to process this Beacon only if sent by the AP we are associated
// with or from which we are waiting an Association Response frame
goodBeacon = (hdr->GetAddr3 () == GetBssid (linkId));
}
else
{
// we retain this Beacon as candidate AP if the supported rates fit the
// configured BSS membership selector
goodBeacon = CheckSupportedRates (beacon, linkId);
}
break;
if (!goodBeacon)
{
NS_LOG_LOGIC ("Beacon is not for us");
return;
}
if (m_state == ASSOCIATED)
{
m_beaconArrival (Simulator::Now ());
Time delay = MicroSeconds (beacon.GetBeaconIntervalUs () * m_maxMissedBeacons);
RestartBeaconWatchdog (delay);
UpdateApInfo (beacon, hdr->GetAddr2 (), hdr->GetAddr3 (), linkId);
}
else
{
NS_LOG_DEBUG ("Beacon received from " << hdr->GetAddr2 ());
SnrTag snrTag;
bool removed = copy->RemovePacketTag (snrTag);
NS_ASSERT (removed);
ApInfo apInfo;
apInfo.m_apAddr = hdr->GetAddr2 ();
apInfo.m_bssid = hdr->GetAddr3 ();
apInfo.m_snr = snrTag.Get ();
apInfo.m_frame = std::move (beacon);
apInfo.m_linkId = linkId;
apInfo.m_channel = {GetCurrentChannel (linkId)};
m_assocManager->NotifyApInfo (std::move (apInfo));
}
case WIFI_MAC_MGT_BEACON:
ReceiveBeacon (mpdu, linkId);
break;
case WIFI_MAC_MGT_PROBE_RESPONSE:
ReceiveProbeResp (mpdu, linkId);
break;
case WIFI_MAC_MGT_ASSOCIATION_RESPONSE:
case WIFI_MAC_MGT_REASSOCIATION_RESPONSE:
ReceiveAssocResp (mpdu, linkId);
break;
default:
//Invoke the receive handler of our parent class to deal with any
//other frames. Specifically, this will handle Block Ack-related
//Management Action frames.
WifiMac::Receive (mpdu, linkId);
}
}
void
StaWifiMac::ReceiveBeacon (Ptr<WifiMacQueueItem> mpdu, uint8_t linkId)
{
NS_LOG_FUNCTION (this << *mpdu << +linkId);
const WifiMacHeader& hdr = mpdu->GetHeader ();
NS_ASSERT (hdr.IsBeacon ());
NS_LOG_DEBUG ("Beacon received");
MgtBeaconHeader beacon;
mpdu->GetPacket ()->PeekHeader (beacon);
const CapabilityInformation& capabilities = beacon.GetCapabilities ();
NS_ASSERT (capabilities.IsEss ());
bool goodBeacon;
if (IsWaitAssocResp () || IsAssociated ())
{
// we have to process this Beacon only if sent by the AP we are associated
// with or from which we are waiting an Association Response frame
goodBeacon = (hdr.GetAddr3 () == GetBssid (linkId));
}
else
{
// we retain this Beacon as candidate AP if the supported rates fit the
// configured BSS membership selector
goodBeacon = CheckSupportedRates (beacon, linkId);
}
if (!goodBeacon)
{
NS_LOG_LOGIC ("Beacon is not for us");
return;
}
else if (hdr->IsProbeResp ())
if (m_state == ASSOCIATED)
{
NS_LOG_DEBUG ("Probe response received from " << hdr->GetAddr2 ());
MgtProbeResponseHeader probeResp;
Ptr<Packet> copy = packet->Copy ();
copy->RemoveHeader (probeResp);
if (!CheckSupportedRates (probeResp, linkId))
{
return;
}
m_beaconArrival (Simulator::Now ());
Time delay = MicroSeconds (beacon.GetBeaconIntervalUs () * m_maxMissedBeacons);
RestartBeaconWatchdog (delay);
UpdateApInfo (beacon, hdr.GetAddr2 (), hdr.GetAddr3 (), linkId);
}
else
{
NS_LOG_DEBUG ("Beacon received from " << hdr.GetAddr2 ());
SnrTag snrTag;
bool removed = copy->RemovePacketTag (snrTag);
NS_ASSERT (removed);
ApInfo apInfo;
apInfo.m_apAddr = hdr->GetAddr2 ();
apInfo.m_bssid = hdr->GetAddr3 ();
apInfo.m_snr = snrTag.Get ();
apInfo.m_frame = std::move (probeResp);
apInfo.m_linkId = linkId;
apInfo.m_channel = {GetCurrentChannel (linkId)};
m_assocManager->NotifyApInfo (std::move (apInfo));
bool found = mpdu->GetPacket ()->PeekPacketTag (snrTag);
NS_ASSERT (found);
m_assocManager->NotifyApInfo (ApInfo {.m_bssid = hdr.GetAddr3 (),
.m_apAddr = hdr.GetAddr2 (),
.m_snr = snrTag.Get (),
.m_frame = std::move (beacon),
.m_channel = {GetCurrentChannel (linkId)},
.m_linkId = linkId});
}
}
void
StaWifiMac::ReceiveProbeResp (Ptr<WifiMacQueueItem> mpdu, uint8_t linkId)
{
NS_LOG_FUNCTION (this << *mpdu << +linkId);
const WifiMacHeader& hdr = mpdu->GetHeader ();
NS_ASSERT (hdr.IsProbeResp ());
NS_LOG_DEBUG ("Probe response received from " << hdr.GetAddr2 ());
MgtProbeResponseHeader probeResp;
mpdu->GetPacket ()->PeekHeader (probeResp);
if (!CheckSupportedRates (probeResp, linkId))
{
return;
}
else if (hdr->IsAssocResp () || hdr->IsReassocResp ())
SnrTag snrTag;
bool found = mpdu->GetPacket ()->PeekPacketTag (snrTag);
NS_ASSERT (found);
m_assocManager->NotifyApInfo (ApInfo {.m_bssid = hdr.GetAddr3 (),
.m_apAddr = hdr.GetAddr2 (),
.m_snr = snrTag.Get (),
.m_frame = std::move (probeResp),
.m_channel = {GetCurrentChannel (linkId)},
.m_linkId = linkId});
}
void
StaWifiMac::ReceiveAssocResp (Ptr<WifiMacQueueItem> mpdu, uint8_t linkId)
{
NS_LOG_FUNCTION (this << *mpdu << +linkId);
const WifiMacHeader& hdr = mpdu->GetHeader ();
NS_ASSERT (hdr.IsAssocResp () || hdr.IsReassocResp ());
if (m_state != WAIT_ASSOC_RESP)
{
if (m_state == WAIT_ASSOC_RESP)
{
MgtAssocResponseHeader assocResp;
packet->PeekHeader (assocResp);
if (m_assocRequestEvent.IsRunning ())
{
m_assocRequestEvent.Cancel ();
}
if (assocResp.GetStatusCode ().IsSuccess ())
{
SetState (ASSOCIATED);
m_aid = assocResp.GetAssociationId ();
if (hdr->IsReassocResp ())
{
NS_LOG_DEBUG ("reassociation done");
}
else
{
NS_LOG_DEBUG ("association completed");
}
UpdateApInfo (assocResp, hdr->GetAddr2 (), hdr->GetAddr3 (), linkId);
if (!m_linkUp.IsNull ())
{
m_linkUp ();
}
}
else
{
NS_LOG_DEBUG ("association refused");
SetState (REFUSED);
StartScanning ();
}
}
return;
}
//Invoke the receive handler of our parent class to deal with any
//other frames. Specifically, this will handle Block Ack-related
//Management Action frames.
WifiMac::Receive (Create<WifiMacQueueItem> (packet, *hdr), linkId);
MgtAssocResponseHeader assocResp;
mpdu->GetPacket ()->PeekHeader (assocResp);
if (m_assocRequestEvent.IsRunning ())
{
m_assocRequestEvent.Cancel ();
}
if (assocResp.GetStatusCode ().IsSuccess ())
{
SetState (ASSOCIATED);
m_aid = assocResp.GetAssociationId ();
if (hdr.IsReassocResp ())
{
NS_LOG_DEBUG ("reassociation done");
}
else
{
NS_LOG_DEBUG ("association completed");
}
UpdateApInfo (assocResp, hdr.GetAddr2 (), hdr.GetAddr3 (), linkId);
if (!m_linkUp.IsNull ())
{
m_linkUp ();
}
}
else
{
NS_LOG_DEBUG ("association refused");
SetState (REFUSED);
StartScanning ();
}
}
bool

View File

@@ -257,6 +257,30 @@ private:
void Receive (Ptr<WifiMacQueueItem> mpdu, uint8_t linkId) override;
/**
* Process the Beacon frame received on the given link.
*
* \param mpdu the MPDU containing the Beacon frame
* \param linkId the ID of the given link
*/
void ReceiveBeacon (Ptr<WifiMacQueueItem> mpdu, uint8_t linkId);
/**
* Process the Probe Response frame received on the given link.
*
* \param mpdu the MPDU containing the Probe Response frame
* \param linkId the ID of the given link
*/
void ReceiveProbeResp (Ptr<WifiMacQueueItem> mpdu, uint8_t linkId);
/**
* Process the (Re)Association Response frame received on the given link.
*
* \param mpdu the MPDU containing the (Re)Association Response frame
* \param linkId the ID of the given link
*/
void ReceiveAssocResp (Ptr<WifiMacQueueItem> mpdu, uint8_t linkId);
/**
* Update associated AP's information from the given management frame (Beacon,
* Probe Response or Association Response). If STA is not associated, this