--- a/src/wifi/model/ap-wifi-mac.cc Tue Oct 24 22:58:32 2017 +0200 +++ a/src/wifi/model/ap-wifi-mac.cc Tue Jan 23 22:56:00 2018 +0100 @@ -719,11 +719,11 @@ } void -ApWifiMac::SendAssocResp (Mac48Address to, bool success) +ApWifiMac::SendAssocResp (Mac48Address to, bool success, bool isReassoc) { NS_LOG_FUNCTION (this << to << success); WifiMacHeader hdr; - hdr.SetType (WIFI_MAC_MGT_ASSOCIATION_RESPONSE); + hdr.SetType (isReassoc ? WIFI_MAC_MGT_REASSOCIATION_RESPONSE : WIFI_MAC_MGT_ASSOCIATION_RESPONSE); hdr.SetAddr1 (to); hdr.SetAddr2 (GetAddress ()); hdr.SetAddr3 (GetAddress ()); @@ -736,8 +736,25 @@ if (success) { code.SetSuccess (); - uint16_t aid = GetNextAssociationId (); - m_staList.insert (std::make_pair (aid, to)); + uint16_t aid; + bool found = false; + if (isReassoc) + { + for (std::map::const_iterator i = m_staList.begin (); i != m_staList.end (); ++i) + { + if (i->second == to) + { + aid = i->first; + found = true; + break; + } + } + } + if (!found) + { + aid = GetNextAssociationId (); + m_staList.insert (std::make_pair (aid, to)); + } assoc.SetAssociationId (aid); } else @@ -858,7 +875,7 @@ NS_LOG_FUNCTION (this); RegularWifiMac::TxOk (hdr); - if (hdr.IsAssocResp () + if ((hdr.IsAssocResp () || hdr.IsReassocResp ()) && m_stationManager->IsWaitAssocTxOk (hdr.GetAddr1 ())) { NS_LOG_DEBUG ("associated with sta=" << hdr.GetAddr1 ()); @@ -872,7 +889,7 @@ NS_LOG_FUNCTION (this); RegularWifiMac::TxFailed (hdr); - if (hdr.IsAssocResp () + if ((hdr.IsAssocResp () || hdr.IsReassocResp ()) && m_stationManager->IsWaitAssocTxOk (hdr.GetAddr1 ())) { NS_LOG_DEBUG ("assoc failed with sta=" << hdr.GetAddr1 ()); @@ -1077,7 +1094,7 @@ //One of the Basic Rate set mode is not //supported by the station. So, we return an assoc //response with an error status. - SendAssocResp (hdr->GetAddr2 (), false); + SendAssocResp (hdr->GetAddr2 (), false, false); } else { @@ -1136,13 +1153,197 @@ if (!isHtStation) { m_nonHtStations.push_back (hdr->GetAddr2 ()); + m_nonHtStations.unique (); } if (!isErpStation && isDsssStation) { m_nonErpStations.push_back (hdr->GetAddr2 ()); + m_nonErpStations.unique (); } // send assoc response with success status. - SendAssocResp (hdr->GetAddr2 (), true); + SendAssocResp (hdr->GetAddr2 (), true, false); + } + return; + } + else if (hdr->IsReassocReq ()) + { + //first, verify that the the station's supported + //rate set is compatible with our Basic Rate set + MgtReassocRequestHeader reassocReq; + packet->RemoveHeader (reassocReq); + CapabilityInformation capabilities = reassocReq.GetCapabilities (); + m_stationManager->AddSupportedPlcpPreamble (from, capabilities.IsShortPreamble ()); + SupportedRates rates = reassocReq.GetSupportedRates (); + bool problem = false; + bool isHtStation = false; + bool isOfdmStation = false; + bool isErpStation = false; + bool isDsssStation = false; + for (uint8_t i = 0; i < m_stationManager->GetNBasicModes (); i++) + { + WifiMode mode = m_stationManager->GetBasicMode (i); + if (!rates.IsSupportedRate (mode.GetDataRate (m_phy->GetChannelWidth ()))) + { + if ((mode.GetModulationClass () == WIFI_MOD_CLASS_DSSS) || (mode.GetModulationClass () == WIFI_MOD_CLASS_HR_DSSS)) + { + isDsssStation = false; + } + else if (mode.GetModulationClass () == WIFI_MOD_CLASS_ERP_OFDM) + { + isErpStation = false; + } + else if (mode.GetModulationClass () == WIFI_MOD_CLASS_OFDM) + { + isOfdmStation = false; + } + if (isDsssStation == false && isErpStation == false && isOfdmStation == false) + { + problem = true; + break; + } + } + else + { + if ((mode.GetModulationClass () == WIFI_MOD_CLASS_DSSS) || (mode.GetModulationClass () == WIFI_MOD_CLASS_HR_DSSS)) + { + isDsssStation = true; + } + else if (mode.GetModulationClass () == WIFI_MOD_CLASS_ERP_OFDM) + { + isErpStation = true; + } + else if (mode.GetModulationClass () == WIFI_MOD_CLASS_OFDM) + { + isOfdmStation = true; + } + } + } + m_stationManager->AddSupportedErpSlotTime (from, capabilities.IsShortSlotTime () && isErpStation); + if (m_htSupported) + { + //check whether the HT STA supports all MCSs in Basic MCS Set + HtCapabilities htcapabilities = reassocReq.GetHtCapabilities (); + if (htcapabilities.IsSupportedMcs (0)) + { + isHtStation = true; + for (uint8_t i = 0; i < m_stationManager->GetNBasicMcs (); i++) + { + WifiMode mcs = m_stationManager->GetBasicMcs (i); + if (!htcapabilities.IsSupportedMcs (mcs.GetMcsValue ())) + { + problem = true; + break; + } + } + } + } + if (m_vhtSupported) + { + //check whether the VHT STA supports all MCSs in Basic MCS Set + VhtCapabilities vhtcapabilities = reassocReq.GetVhtCapabilities (); + if (vhtcapabilities.GetVhtCapabilitiesInfo () != 0) + { + for (uint8_t i = 0; i < m_stationManager->GetNBasicMcs (); i++) + { + WifiMode mcs = m_stationManager->GetBasicMcs (i); + if (!vhtcapabilities.IsSupportedTxMcs (mcs.GetMcsValue ())) + { + problem = true; + break; + } + } + } + } + if (m_heSupported) + { + //check whether the HE STA supports all MCSs in Basic MCS Set + HeCapabilities hecapabilities = reassocReq.GetHeCapabilities (); + if (hecapabilities.GetSupportedMcsAndNss () != 0) + { + for (uint8_t i = 0; i < m_stationManager->GetNBasicMcs (); i++) + { + WifiMode mcs = m_stationManager->GetBasicMcs (i); + if (!hecapabilities.IsSupportedTxMcs (mcs.GetMcsValue ())) + { + problem = true; + break; + } + } + } + } + if (problem) + { + //One of the Basic Rate set mode is not + //supported by the station. So, we return an reassoc + //response with an error status. + SendAssocResp (hdr->GetAddr2 (), false, true); + } + else + { + //station supports all rates in Basic Rate Set. + //record all its supported modes in its associated WifiRemoteStation + for (uint8_t j = 0; j < m_phy->GetNModes (); j++) + { + WifiMode mode = m_phy->GetMode (j); + if (rates.IsSupportedRate (mode.GetDataRate (m_phy->GetChannelWidth ()))) + { + m_stationManager->AddSupportedMode (from, mode); + } + } + if (m_htSupported) + { + HtCapabilities htCapabilities = reassocReq.GetHtCapabilities (); + if (htCapabilities.IsSupportedMcs (0)) + { + m_stationManager->AddStationHtCapabilities (from, htCapabilities); + } + } + if (m_vhtSupported) + { + VhtCapabilities vhtCapabilities = reassocReq.GetVhtCapabilities (); + //we will always fill in RxHighestSupportedLgiDataRate field at TX, so this can be used to check whether it supports VHT + if (vhtCapabilities.GetRxHighestSupportedLgiDataRate () > 0) + { + m_stationManager->AddStationVhtCapabilities (from, vhtCapabilities); + for (uint8_t i = 0; i < m_phy->GetNMcs (); i++) + { + WifiMode mcs = m_phy->GetMcs (i); + if (mcs.GetModulationClass () == WIFI_MOD_CLASS_VHT && vhtCapabilities.IsSupportedTxMcs (mcs.GetMcsValue ())) + { + m_stationManager->AddSupportedMcs (hdr->GetAddr2 (), mcs); + //here should add a control to add basic MCS when it is implemented + } + } + } + } + if (m_heSupported) + { + HeCapabilities heCapabilities = reassocReq.GetHeCapabilities (); + //todo: once we support non constant rate managers, we should add checks here whether HE is supported by the peer + m_stationManager->AddStationHeCapabilities (from, heCapabilities); + for (uint8_t i = 0; i < m_phy->GetNMcs (); i++) + { + WifiMode mcs = m_phy->GetMcs (i); + if (mcs.GetModulationClass () == WIFI_MOD_CLASS_HE && heCapabilities.IsSupportedTxMcs (mcs.GetMcsValue ())) + { + m_stationManager->AddSupportedMcs (hdr->GetAddr2 (), mcs); + //here should add a control to add basic MCS when it is implemented + } + } + } + m_stationManager->RecordWaitAssocTxOk (from); + if (!isHtStation) + { + m_nonHtStations.push_back (hdr->GetAddr2 ()); + m_nonHtStations.unique (); + } + if (!isErpStation && isDsssStation) + { + m_nonErpStations.push_back (hdr->GetAddr2 ()); + m_nonErpStations.unique (); + } + // send reassoc response with success status. + SendAssocResp (hdr->GetAddr2 (), true, true); } return; } --- a/src/wifi/model/ap-wifi-mac.h Tue Oct 24 22:58:32 2017 +0200 +++ a/src/wifi/model/ap-wifi-mac.h Tue Jan 23 22:56:00 2018 +0100 @@ -199,13 +199,15 @@ */ void SendProbeResp (Mac48Address to); /** - * Forward an association response packet to the DCF. The standard is not clear on the correct - * queue for management frames if QoS is supported. We always use the DCF. + * Forward an association or a reassociation response packet to the DCF. + * The standard is not clear on the correct queue for management frames if QoS is supported. + * We always use the DCF. * * \param to the address of the STA we are sending an association response to * \param success indicates whether the association was successful or not + * \param isReassoc indicates whether it is a reassociation response */ - void SendAssocResp (Mac48Address to, bool success); + void SendAssocResp (Mac48Address to, bool success, bool isReassoc); /** * Forward a beacon packet to the beacon special DCF. */ --- a/src/wifi/model/mgt-headers.cc Tue Oct 24 22:58:32 2017 +0200 +++ a/src/wifi/model/mgt-headers.cc Tue Jan 23 22:56:00 2018 +0100 @@ -686,7 +686,203 @@ /*********************************************************** - * Assoc Response + * Ressoc Request + ***********************************************************/ + +NS_OBJECT_ENSURE_REGISTERED (MgtReassocRequestHeader); + +MgtReassocRequestHeader::MgtReassocRequestHeader () + : m_currentApAddr (Mac48Address ()) +{ +} + +MgtReassocRequestHeader::~MgtReassocRequestHeader () +{ +} + +void +MgtReassocRequestHeader::SetSsid (Ssid ssid) +{ + m_ssid = ssid; +} + +void +MgtReassocRequestHeader::SetSupportedRates (SupportedRates rates) +{ + m_rates = rates; +} + +void +MgtReassocRequestHeader::SetListenInterval (uint16_t interval) +{ + m_listenInterval = interval; +} + +void +MgtReassocRequestHeader::SetCapabilities (CapabilityInformation capabilities) +{ + m_capability = capabilities; +} + +CapabilityInformation +MgtReassocRequestHeader::GetCapabilities (void) const +{ + return m_capability; +} + +void +MgtReassocRequestHeader::SetExtendedCapabilities (ExtendedCapabilities extendedcapabilities) +{ + m_extendedCapability = extendedcapabilities; +} + +ExtendedCapabilities +MgtReassocRequestHeader::GetExtendedCapabilities (void) const +{ + return m_extendedCapability; +} + +void +MgtReassocRequestHeader::SetHtCapabilities (HtCapabilities htcapabilities) +{ + m_htCapability = htcapabilities; +} + +HtCapabilities +MgtReassocRequestHeader::GetHtCapabilities (void) const +{ + return m_htCapability; +} + +void +MgtReassocRequestHeader::SetVhtCapabilities (VhtCapabilities vhtcapabilities) +{ + m_vhtCapability = vhtcapabilities; +} + +VhtCapabilities +MgtReassocRequestHeader::GetVhtCapabilities (void) const +{ + return m_vhtCapability; +} + +void +MgtReassocRequestHeader::SetHeCapabilities (HeCapabilities hecapabilities) +{ + m_heCapability = hecapabilities; +} + +HeCapabilities +MgtReassocRequestHeader::GetHeCapabilities (void) const +{ + return m_heCapability; +} + +Ssid +MgtReassocRequestHeader::GetSsid (void) const +{ + return m_ssid; +} + +SupportedRates +MgtReassocRequestHeader::GetSupportedRates (void) const +{ + return m_rates; +} + +uint16_t +MgtReassocRequestHeader::GetListenInterval (void) const +{ + return m_listenInterval; +} + +void +MgtReassocRequestHeader::SetCurrentApAddress (Mac48Address currentApAddr) +{ + m_currentApAddr = currentApAddr; +} + +TypeId +MgtReassocRequestHeader::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::MgtReassocRequestHeader") + .SetParent
() + .SetGroupName ("Wifi") + .AddConstructor () + ; + return tid; +} + +TypeId +MgtReassocRequestHeader::GetInstanceTypeId (void) const +{ + return GetTypeId (); +} + +uint32_t +MgtReassocRequestHeader::GetSerializedSize (void) const +{ + uint32_t size = 0; + size += m_capability.GetSerializedSize (); + size += 2; //listen interval + size += 6; //current AP address + size += m_ssid.GetSerializedSize (); + size += m_rates.GetSerializedSize (); + size += m_rates.extended.GetSerializedSize (); + size += m_extendedCapability.GetSerializedSize (); + size += m_htCapability.GetSerializedSize (); + size += m_vhtCapability.GetSerializedSize (); + size += m_heCapability.GetSerializedSize (); + return size; +} + +void +MgtReassocRequestHeader::Print (std::ostream &os) const +{ + os << "current AP address=" << m_currentApAddr << ", " + << "ssid=" << m_ssid << ", " + << "rates=" << m_rates << ", " + << "HT Capabilities=" << m_htCapability << " , " + << "VHT Capabilities=" << m_vhtCapability << " , " + << "HE Capabilities=" << m_heCapability; +} + +void +MgtReassocRequestHeader::Serialize (Buffer::Iterator start) const +{ + Buffer::Iterator i = start; + i = m_capability.Serialize (i); + i.WriteHtolsbU16 (m_listenInterval); + WriteTo (i, m_currentApAddr); + i = m_ssid.Serialize (i); + i = m_rates.Serialize (i); + i = m_rates.extended.Serialize (i); + i = m_extendedCapability.Serialize (i); + i = m_htCapability.Serialize (i); + i = m_vhtCapability.Serialize (i); + i = m_heCapability.Serialize (i); +} + +uint32_t +MgtReassocRequestHeader::Deserialize (Buffer::Iterator start) +{ + Buffer::Iterator i = start; + i = m_capability.Deserialize (i); + m_listenInterval = i.ReadLsbtohU16 (); + ReadFrom (i, m_currentApAddr); + i = m_ssid.Deserialize (i); + i = m_rates.Deserialize (i); + i = m_rates.extended.DeserializeIfPresent (i); + i = m_extendedCapability.DeserializeIfPresent (i); + i = m_htCapability.DeserializeIfPresent (i); + i = m_vhtCapability.DeserializeIfPresent (i); + i = m_heCapability.DeserializeIfPresent (i); + return i.GetDistanceFrom (start); +} + + +/*********************************************************** + * Assoc/Reassoc Response ***********************************************************/ NS_OBJECT_ENSURE_REGISTERED (MgtAssocResponseHeader); --- a/src/wifi/model/mgt-headers.h Tue Oct 24 22:58:32 2017 +0200 +++ a/src/wifi/model/mgt-headers.h Tue Jan 23 22:56:00 2018 +0100 @@ -37,6 +37,7 @@ #include "edca-parameter-set.h" #include "he-capabilities.h" #include "he-operation.h" +#include "ns3/address-utils.h" namespace ns3 { @@ -173,7 +174,145 @@ /** * \ingroup wifi - * Implement the header for management frames of type association response. + * Implement the header for management frames of type reassociation request. + */ +class MgtReassocRequestHeader : public Header +{ +public: + MgtReassocRequestHeader (); + ~MgtReassocRequestHeader (); + + /** + * Set the Service Set Identifier (SSID). + * + * \param ssid SSID + */ + void SetSsid (Ssid ssid); + /** + * Set the supported rates. + * + * \param rates the supported rates + */ + void SetSupportedRates (SupportedRates rates); + /** + * Set the listen interval. + * + * \param interval the listen interval + */ + void SetListenInterval (uint16_t interval); + /** + * Set the Capability information. + * + * \param capabilities Capability information + */ + void SetCapabilities (CapabilityInformation capabilities); + /** + * Set the Extended Capabilities. + * + * \param extendedcapabilities the Extended Capabilities + */ + void SetExtendedCapabilities (ExtendedCapabilities extendedcapabilities); + /** + * Set the HT capabilities. + * + * \param htcapabilities HT capabilities + */ + void SetHtCapabilities (HtCapabilities htcapabilities); + /** + * Set the VHT capabilities. + * + * \param vhtcapabilities VHT capabilities + */ + void SetVhtCapabilities (VhtCapabilities vhtcapabilities); + /** + * Set the HE capabilities. + * + * \param hecapabilities HE capabilities + */ + void SetHeCapabilities (HeCapabilities hecapabilities); + /** + * Return the Capability information. + * + * \return Capability information + */ + CapabilityInformation GetCapabilities (void) const; + /** + * Return the extended capabilities. + * + * \return the extended capabilities + */ + ExtendedCapabilities GetExtendedCapabilities (void) const; + /** + * Return the HT capabilities. + * + * \return HT capabilities + */ + HtCapabilities GetHtCapabilities (void) const; + /** + * Return the VHT capabilities. + * + * \return VHT capabilities + */ + VhtCapabilities GetVhtCapabilities (void) const; + /** + * Return the HE capabilities. + * + * \return HE capabilities + */ + HeCapabilities GetHeCapabilities (void) const; + /** + * Return the Service Set Identifier (SSID). + * + * \return SSID + */ + Ssid GetSsid (void) const; + /** + * Return the supported rates. + * + * \return the supported rates + */ + SupportedRates GetSupportedRates (void) const; + /** + * Return the listen interval. + * + * \return the listen interval + */ + uint16_t GetListenInterval (void) const; + /** + * Set the address of the current access point. + * + * \param currentApAddr address of the current access point + */ + void SetCurrentApAddress (Mac48Address currentApAddr); + + /** + * Register this type. + * \return The TypeId. + */ + static TypeId GetTypeId (void); + TypeId GetInstanceTypeId (void) const; + void Print (std::ostream &os) const; + uint32_t GetSerializedSize (void) const; + void Serialize (Buffer::Iterator start) const; + uint32_t Deserialize (Buffer::Iterator start); + + +private: + Mac48Address m_currentApAddr; //!< Address of the current access point + Ssid m_ssid; //!< Service Set ID (SSID) + SupportedRates m_rates; //!< List of supported rates + CapabilityInformation m_capability; //!< Capability information + ExtendedCapabilities m_extendedCapability; //!< Extended capabilities + HtCapabilities m_htCapability; //!< HT capabilities + VhtCapabilities m_vhtCapability; //!< VHT capabilities + HeCapabilities m_heCapability; //!< HE capabilities + uint16_t m_listenInterval; //!< listen interval +}; + + +/** + * \ingroup wifi + * Implement the header for management frames of type association and reassociation response. */ class MgtAssocResponseHeader : public Header { --- a/src/wifi/model/regular-wifi-mac.h Tue Oct 24 22:58:32 2017 +0200 +++ a/src/wifi/model/regular-wifi-mac.h Tue Jan 23 22:56:00 2018 +0100 @@ -216,7 +216,7 @@ /** * \param phy the physical layer attached to this MAC. */ - void SetWifiPhy (const Ptr phy); + virtual void SetWifiPhy (const Ptr phy); /** * \return the physical layer attached to this MAC. */ --- a/src/wifi/model/sta-wifi-mac.cc Tue Oct 24 22:58:32 2017 +0200 +++ a/src/wifi/model/sta-wifi-mac.cc Tue Jan 23 22:56:00 2018 +0100 @@ -120,12 +120,20 @@ m_activeProbing = enable; } -bool StaWifiMac::GetActiveProbing (void) const +bool +StaWifiMac::GetActiveProbing (void) const { return m_activeProbing; } void +StaWifiMac::SetWifiPhy (const Ptr phy) +{ + RegularWifiMac::SetWifiPhy (phy); + m_phy->SetCapabilitiesChangedCallback (MakeCallback (&StaWifiMac::PhyCapabilitiesChanged, this)); +} + +void StaWifiMac::SendProbeRequest (void) { NS_LOG_FUNCTION (this); @@ -171,11 +179,11 @@ } void -StaWifiMac::SendAssociationRequest (void) +StaWifiMac::SendAssociationRequest (bool isReassoc) { - NS_LOG_FUNCTION (this << GetBssid ()); + NS_LOG_FUNCTION (this << GetBssid () << isReassoc); WifiMacHeader hdr; - hdr.SetType (WIFI_MAC_MGT_ASSOCIATION_REQUEST); + hdr.SetType (isReassoc ? WIFI_MAC_MGT_REASSOCIATION_REQUEST : WIFI_MAC_MGT_ASSOCIATION_REQUEST); hdr.SetAddr1 (GetBssid ()); hdr.SetAddr2 (GetAddress ()); hdr.SetAddr3 (GetBssid ()); @@ -183,24 +191,49 @@ hdr.SetDsNotTo (); hdr.SetNoOrder (); Ptr packet = Create (); - MgtAssocRequestHeader assoc; - assoc.SetSsid (GetSsid ()); - assoc.SetSupportedRates (GetSupportedRates ()); - assoc.SetCapabilities (GetCapabilities ()); - if (m_htSupported || m_vhtSupported || m_heSupported) + if (!isReassoc) { - assoc.SetExtendedCapabilities (GetExtendedCapabilities ()); - assoc.SetHtCapabilities (GetHtCapabilities ()); + MgtAssocRequestHeader assoc; + assoc.SetSsid (GetSsid ()); + assoc.SetSupportedRates (GetSupportedRates ()); + assoc.SetCapabilities (GetCapabilities ()); + if (m_htSupported || m_vhtSupported || m_heSupported) + { + assoc.SetExtendedCapabilities (GetExtendedCapabilities ()); + assoc.SetHtCapabilities (GetHtCapabilities ()); + } + if (m_vhtSupported || m_heSupported) + { + assoc.SetVhtCapabilities (GetVhtCapabilities ()); + } + if (m_heSupported) + { + assoc.SetHeCapabilities (GetHeCapabilities ()); + } + packet->AddHeader (assoc); } - if (m_vhtSupported || m_heSupported) + else { - assoc.SetVhtCapabilities (GetVhtCapabilities ()); + MgtReassocRequestHeader reassoc; + reassoc.SetCurrentApAddress (GetBssid ()); + reassoc.SetSsid (GetSsid ()); + reassoc.SetSupportedRates (GetSupportedRates ()); + reassoc.SetCapabilities (GetCapabilities ()); + if (m_htSupported || m_vhtSupported || m_heSupported) + { + reassoc.SetExtendedCapabilities (GetExtendedCapabilities ()); + reassoc.SetHtCapabilities (GetHtCapabilities ()); + } + if (m_vhtSupported || m_heSupported) + { + reassoc.SetVhtCapabilities (GetVhtCapabilities ()); + } + if (m_heSupported) + { + reassoc.SetHeCapabilities (GetHeCapabilities ()); + } + packet->AddHeader (reassoc); } - if (m_heSupported) - { - assoc.SetHeCapabilities (GetHeCapabilities ()); - } - packet->AddHeader (assoc); //The standard is not clear on the correct queue for management //frames if we are a QoS AP. The approach taken here is to always @@ -265,7 +298,7 @@ { NS_LOG_FUNCTION (this); SetState (WAIT_ASSOC_RESP); - SendAssociationRequest (); + SendAssociationRequest (false); } void @@ -447,7 +480,8 @@ return; } else if (hdr->IsProbeReq () - || hdr->IsAssocReq ()) + || hdr->IsAssocReq () + || hdr->IsReassocReq ()) { //This is a frame aimed at an AP, so we can safely ignore it. NotifyRxDrop (packet); @@ -608,7 +642,7 @@ if (goodBeacon && m_state == BEACON_MISSED) { SetState (WAIT_ASSOC_RESP); - SendAssociationRequest (); + SendAssociationRequest (false); } return; } @@ -692,11 +726,11 @@ m_probeRequestEvent.Cancel (); } SetState (WAIT_ASSOC_RESP); - SendAssociationRequest (); + SendAssociationRequest (false); } return; } - else if (hdr->IsAssocResp ()) + else if (hdr->IsAssocResp () || hdr->IsReassocResp ()) { if (m_state == WAIT_ASSOC_RESP) { @@ -938,4 +972,15 @@ edca->SetTxopLimit (txopLimit); } +void +StaWifiMac::PhyCapabilitiesChanged (void) +{ + NS_LOG_FUNCTION (this); + if (IsAssociated ()) + { + SetState (WAIT_ASSOC_RESP); + SendAssociationRequest (true); + } +} + } //namespace ns3 --- a/src/wifi/model/sta-wifi-mac.h Tue Oct 24 22:58:32 2017 +0200 +++ a/src/wifi/model/sta-wifi-mac.h Tue Jan 23 22:56:00 2018 +0100 @@ -58,6 +58,11 @@ */ void Enqueue (Ptr packet, Mac48Address to); + /** + * \param phy the physical layer attached to this MAC. + */ + void SetWifiPhy (const Ptr phy); + private: /** @@ -93,10 +98,14 @@ */ void SendProbeRequest (void); /** - * Forward an association request packet to the DCF. The standard is not clear on the correct - * queue for management frames if QoS is supported. We always use the DCF. + * Forward an association or reassociation request packet to the DCF. + * The standard is not clear on the correct queue for management frames if QoS is supported. + * We always use the DCF. + * + * \param isReassoc flag whether it is a reassociation request + * */ - void SendAssociationRequest (void); + void SendAssociationRequest (bool isReassoc); /** * Try to ensure that we are associated with an AP by taking an appropriate action * depending on the current association status. @@ -164,6 +173,11 @@ */ CapabilityInformation GetCapabilities (void) const; + /** + * Indicate that PHY capabilities have changed. + */ + void PhyCapabilitiesChanged (void); + MacState m_state; ///< MAC state Time m_probeRequestTimeout; ///< probe request timeout Time m_assocRequestTimeout; ///< assoc request timeout --- a/src/wifi/model/wifi-phy.cc Tue Oct 24 22:58:32 2017 +0200 +++ a/src/wifi/model/wifi-phy.cc Tue Jan 23 22:56:00 2018 +0100 @@ -435,6 +435,12 @@ } void +WifiPhy::SetCapabilitiesChangedCallback (Callback callback) +{ + m_capabilitiesChangedCallback = callback; +} + +void WifiPhy::InitializeFrequencyChannelNumber (void) { NS_LOG_FUNCTION (this); @@ -1267,9 +1273,15 @@ void WifiPhy::SetChannelWidth (uint8_t channelwidth) { + NS_LOG_FUNCTION (this << static_cast(channelwidth)); NS_ASSERT_MSG (channelwidth == 5 || channelwidth == 10 || channelwidth == 20 || channelwidth == 22 || channelwidth == 40 || channelwidth == 80 || channelwidth == 160, "wrong channel width value"); + bool changed = (m_channelWidth == channelwidth); m_channelWidth = channelwidth; AddSupportedChannelWidth (channelwidth); + if (changed && !m_capabilitiesChangedCallback.IsNull ()) + { + m_capabilitiesChangedCallback (); + } } uint8_t @@ -1296,8 +1308,13 @@ WifiPhy::SetMaxSupportedTxSpatialStreams (uint8_t streams) { NS_ASSERT (streams <= GetNumberOfAntennas ()); + bool changed = (m_txSpatialStreams == streams); m_txSpatialStreams = streams; ConfigureHtDeviceMcsSet (); + if (changed && !m_capabilitiesChangedCallback.IsNull ()) + { + m_capabilitiesChangedCallback (); + } } uint8_t @@ -1310,7 +1327,12 @@ WifiPhy::SetMaxSupportedRxSpatialStreams (uint8_t streams) { NS_ASSERT (streams <= GetNumberOfAntennas ()); + bool changed = (m_rxSpatialStreams == streams); m_rxSpatialStreams = streams; + if (changed && !m_capabilitiesChangedCallback.IsNull ()) + { + m_capabilitiesChangedCallback (); + } } uint8_t --- a/src/wifi/model/wifi-phy.h Tue Oct 24 22:58:32 2017 +0200 +++ a/src/wifi/model/wifi-phy.h Tue Jan 23 22:56:00 2018 +0100 @@ -258,6 +258,11 @@ void UnregisterListener (WifiPhyListener *listener); /** + * \param callback the callback to invoke when PHY capabilities have changed. + */ + void SetCapabilitiesChangedCallback (Callback callback); + + /** * Starting receiving the plcp of a packet (i.e. the first bit of the preamble has arrived). * * \param packet the arriving packet @@ -1987,6 +1992,8 @@ Ptr m_currentEvent; //!< Hold the current event Ptr m_frameCaptureModel; //!< Frame capture model Ptr m_wifiRadioEnergyModel; //!< Wifi radio energy model + + Callback m_capabilitiesChangedCallback; //!< Callback when PHY capabilities changed }; /**