diff --git a/src/wifi/model/sta-wifi-mac.cc b/src/wifi/model/sta-wifi-mac.cc index 7ed522640..748d2185e 100644 --- a/src/wifi/model/sta-wifi-mac.cc +++ b/src/wifi/model/sta-wifi-mac.cc @@ -602,7 +602,7 @@ StaWifiMac::Receive (Ptr 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 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 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 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 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 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 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 (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 diff --git a/src/wifi/model/sta-wifi-mac.h b/src/wifi/model/sta-wifi-mac.h index 38e90b998..fa0010777 100644 --- a/src/wifi/model/sta-wifi-mac.h +++ b/src/wifi/model/sta-wifi-mac.h @@ -257,6 +257,30 @@ private: void Receive (Ptr 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 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 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 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