wifi: (fixes #2831) trigger reassociation if PHY capabilities changed

This commit is contained in:
Sébastien Deronne
2018-02-23 23:11:17 +01:00
parent e136b8eb0a
commit 3acf9f511a
13 changed files with 883 additions and 73 deletions

View File

@@ -51,6 +51,7 @@ Bugs fixed
- Bug 2824 - ICMP opcode fr fragment timeout drop is wrong - Bug 2824 - ICMP opcode fr fragment timeout drop is wrong
- Bug 2828 - OLSR simple P2P example produces wrong results - Bug 2828 - OLSR simple P2P example produces wrong results
- Bug 2827 - wifi: Active scanning not working with 802.11n/ac/ax - Bug 2827 - wifi: Active scanning not working with 802.11n/ac/ax
- Bug 2831 - wifi: runtime channel width switch has no effect
- Bug 2836 - wifi: Missing VHT information in radiotap header when A-MPDU is used - Bug 2836 - wifi: Missing VHT information in radiotap header when A-MPDU is used
- Bug 2838 - wifi: ht-wifi-network crashes with RTS/CTS enabled and frequency set to 2.4GHz - Bug 2838 - wifi: ht-wifi-network crashes with RTS/CTS enabled and frequency set to 2.4GHz
- Bug 2843 - spectrum, wifi: Incorrect channel width and center frequency provided for non-HT PPDUs when building SpectralDensity - Bug 2843 - spectrum, wifi: Incorrect channel width and center frequency provided for non-HT PPDUs when building SpectralDensity

View File

@@ -719,11 +719,11 @@ ApWifiMac::SendProbeResp (Mac48Address to)
} }
void void
ApWifiMac::SendAssocResp (Mac48Address to, bool success) ApWifiMac::SendAssocResp (Mac48Address to, bool success, bool isReassoc)
{ {
NS_LOG_FUNCTION (this << to << success); NS_LOG_FUNCTION (this << to << success << isReassoc);
WifiMacHeader hdr; 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.SetAddr1 (to);
hdr.SetAddr2 (GetAddress ()); hdr.SetAddr2 (GetAddress ());
hdr.SetAddr3 (GetAddress ()); hdr.SetAddr3 (GetAddress ());
@@ -736,8 +736,25 @@ ApWifiMac::SendAssocResp (Mac48Address to, bool success)
if (success) if (success)
{ {
code.SetSuccess (); code.SetSuccess ();
uint16_t aid = GetNextAssociationId (); uint16_t aid;
m_staList.insert (std::make_pair (aid, to)); bool found = false;
if (isReassoc)
{
for (std::map<uint16_t, Mac48Address>::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); assoc.SetAssociationId (aid);
} }
else else
@@ -857,8 +874,7 @@ ApWifiMac::TxOk (const WifiMacHeader &hdr)
{ {
NS_LOG_FUNCTION (this); NS_LOG_FUNCTION (this);
RegularWifiMac::TxOk (hdr); RegularWifiMac::TxOk (hdr);
if ((hdr.IsAssocResp () || hdr.IsReassocResp ())
if (hdr.IsAssocResp ()
&& m_stationManager->IsWaitAssocTxOk (hdr.GetAddr1 ())) && m_stationManager->IsWaitAssocTxOk (hdr.GetAddr1 ()))
{ {
NS_LOG_DEBUG ("associated with sta=" << hdr.GetAddr1 ()); NS_LOG_DEBUG ("associated with sta=" << hdr.GetAddr1 ());
@@ -872,10 +888,10 @@ ApWifiMac::TxFailed (const WifiMacHeader &hdr)
NS_LOG_FUNCTION (this); NS_LOG_FUNCTION (this);
RegularWifiMac::TxFailed (hdr); RegularWifiMac::TxFailed (hdr);
if (hdr.IsAssocResp () if ((hdr.IsAssocResp () || hdr.IsReassocResp ())
&& m_stationManager->IsWaitAssocTxOk (hdr.GetAddr1 ())) && m_stationManager->IsWaitAssocTxOk (hdr.GetAddr1 ()))
{ {
NS_LOG_DEBUG ("assoc failed with sta=" << hdr.GetAddr1 ()); NS_LOG_DEBUG ("association failed with sta=" << hdr.GetAddr1 ());
m_stationManager->RecordGotAssocTxFailed (hdr.GetAddr1 ()); m_stationManager->RecordGotAssocTxFailed (hdr.GetAddr1 ());
} }
} }
@@ -884,9 +900,7 @@ void
ApWifiMac::Receive (Ptr<Packet> packet, const WifiMacHeader *hdr) ApWifiMac::Receive (Ptr<Packet> packet, const WifiMacHeader *hdr)
{ {
NS_LOG_FUNCTION (this << packet << hdr); NS_LOG_FUNCTION (this << packet << hdr);
Mac48Address from = hdr->GetAddr2 (); Mac48Address from = hdr->GetAddr2 ();
if (hdr->IsData ()) if (hdr->IsData ())
{ {
Mac48Address bssid = hdr->GetAddr1 (); Mac48Address bssid = hdr->GetAddr1 ();
@@ -961,6 +975,7 @@ ApWifiMac::Receive (Ptr<Packet> packet, const WifiMacHeader *hdr)
if (hdr->IsProbeReq ()) if (hdr->IsProbeReq ())
{ {
NS_ASSERT (hdr->GetAddr1 ().IsBroadcast ()); NS_ASSERT (hdr->GetAddr1 ().IsBroadcast ());
NS_LOG_DEBUG ("Probe request received from " << from << ": send probe response");
SendProbeResp (from); SendProbeResp (from);
return; return;
} }
@@ -968,6 +983,7 @@ ApWifiMac::Receive (Ptr<Packet> packet, const WifiMacHeader *hdr)
{ {
if (hdr->IsAssocReq ()) if (hdr->IsAssocReq ())
{ {
NS_LOG_DEBUG ("Association request received from " << from);
//first, verify that the the station's supported //first, verify that the the station's supported
//rate set is compatible with our Basic Rate set //rate set is compatible with our Basic Rate set
MgtAssocRequestHeader assocReq; MgtAssocRequestHeader assocReq;
@@ -1074,14 +1090,12 @@ ApWifiMac::Receive (Ptr<Packet> packet, const WifiMacHeader *hdr)
} }
if (problem) if (problem)
{ {
//One of the Basic Rate set mode is not NS_LOG_DEBUG ("One of the Basic Rate set mode is not supported by the station: send association response with an error status");
//supported by the station. So, we return an assoc SendAssocResp (hdr->GetAddr2 (), false, false);
//response with an error status.
SendAssocResp (hdr->GetAddr2 (), false);
} }
else else
{ {
//station supports all rates in Basic Rate Set. NS_LOG_DEBUG ("The Basic Rate set modes are supported by the station");
//record all its supported modes in its associated WifiRemoteStation //record all its supported modes in its associated WifiRemoteStation
for (uint8_t j = 0; j < m_phy->GetNModes (); j++) for (uint8_t j = 0; j < m_phy->GetNModes (); j++)
{ {
@@ -1136,18 +1150,202 @@ ApWifiMac::Receive (Ptr<Packet> packet, const WifiMacHeader *hdr)
if (!isHtStation) if (!isHtStation)
{ {
m_nonHtStations.push_back (hdr->GetAddr2 ()); m_nonHtStations.push_back (hdr->GetAddr2 ());
m_nonHtStations.unique ();
} }
if (!isErpStation && isDsssStation) if (!isErpStation && isDsssStation)
{ {
m_nonErpStations.push_back (hdr->GetAddr2 ()); m_nonErpStations.push_back (hdr->GetAddr2 ());
m_nonErpStations.unique ();
} }
// send assoc response with success status. NS_LOG_DEBUG ("Send association response with success status");
SendAssocResp (hdr->GetAddr2 (), true); SendAssocResp (hdr->GetAddr2 (), true, false);
}
return;
}
else if (hdr->IsReassocReq ())
{
NS_LOG_DEBUG ("Reassociation request received from " << from);
//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)
{
NS_LOG_DEBUG ("One of the Basic Rate set mode is not supported by the station: send reassociation response with an error status");
SendAssocResp (hdr->GetAddr2 (), false, true);
}
else
{
NS_LOG_DEBUG ("The Basic Rate set modes are supported by the station");
//update 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 ();
}
NS_LOG_DEBUG ("Send reassociation response with success status");
SendAssocResp (hdr->GetAddr2 (), true, true);
} }
return; return;
} }
else if (hdr->IsDisassociation ()) else if (hdr->IsDisassociation ())
{ {
NS_LOG_DEBUG ("Disassociation received from " << from);
m_stationManager->RecordDisassociated (from); m_stationManager->RecordDisassociated (from);
for (std::map<uint16_t, Mac48Address>::const_iterator j = m_staList.begin (); j != m_staList.end (); j++) for (std::map<uint16_t, Mac48Address>::const_iterator j = m_staList.begin (); j != m_staList.end (); j++)
{ {

View File

@@ -199,13 +199,15 @@ private:
*/ */
void SendProbeResp (Mac48Address to); void SendProbeResp (Mac48Address to);
/** /**
* Forward an association response packet to the DCF. The standard is not clear on the correct * Forward an association or a reassociation response packet to the DCF.
* queue for management frames if QoS is supported. We always use 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 to the address of the STA we are sending an association response to
* \param success indicates whether the association was successful or not * \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. * Forward a beacon packet to the beacon special DCF.
*/ */
@@ -300,7 +302,7 @@ private:
EventId m_beaconEvent; //!< Event to generate one beacon EventId m_beaconEvent; //!< Event to generate one beacon
Ptr<UniformRandomVariable> m_beaconJitter; //!< UniformRandomVariable used to randomize the time of the first beacon Ptr<UniformRandomVariable> m_beaconJitter; //!< UniformRandomVariable used to randomize the time of the first beacon
bool m_enableBeaconJitter; //!< Flag whether the first beacon should be generated at random time bool m_enableBeaconJitter; //!< Flag whether the first beacon should be generated at random time
std::map<uint16_t, Mac48Address> m_staList;//!< Map of all stations currently associated to the AP with their association ID std::map<uint16_t, Mac48Address> m_staList; //!< Map of all stations currently associated to the AP with their association ID
std::list<Mac48Address> m_nonErpStations; //!< List of all non-ERP stations currently associated to the AP std::list<Mac48Address> m_nonErpStations; //!< List of all non-ERP stations currently associated to the AP
std::list<Mac48Address> m_nonHtStations; //!< List of all non-HT stations currently associated to the AP std::list<Mac48Address> m_nonHtStations; //!< List of all non-HT stations currently associated to the AP
bool m_enableNonErpProtection; //!< Flag whether protection mechanism is used or not when non-ERP STAs are present within the BSS bool m_enableNonErpProtection; //!< Flag whether protection mechanism is used or not when non-ERP STAs are present within the BSS

View File

@@ -686,7 +686,203 @@ MgtAssocRequestHeader::Deserialize (Buffer::Iterator start)
/*********************************************************** /***********************************************************
* 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<Header> ()
.SetGroupName ("Wifi")
.AddConstructor<MgtReassocRequestHeader> ()
;
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); NS_OBJECT_ENSURE_REGISTERED (MgtAssocResponseHeader);

View File

@@ -37,6 +37,7 @@
#include "edca-parameter-set.h" #include "edca-parameter-set.h"
#include "he-capabilities.h" #include "he-capabilities.h"
#include "he-operation.h" #include "he-operation.h"
#include "ns3/address-utils.h"
namespace ns3 { namespace ns3 {
@@ -173,7 +174,145 @@ private:
/** /**
* \ingroup wifi * \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 class MgtAssocResponseHeader : public Header
{ {

View File

@@ -1006,7 +1006,7 @@ RegularWifiMac::Receive (Ptr<Packet> packet, const WifiMacHeader *hdr)
void void
RegularWifiMac::DeaggregateAmsduAndForward (Ptr<Packet> aggregatedPacket, const WifiMacHeader *hdr) RegularWifiMac::DeaggregateAmsduAndForward (Ptr<Packet> aggregatedPacket, const WifiMacHeader *hdr)
{ {
NS_LOG_FUNCTION(this << aggregatedPacket << hdr); NS_LOG_FUNCTION (this << aggregatedPacket << hdr);
MsduAggregator::DeaggregatedMsdus packets = MsduAggregator::Deaggregate (aggregatedPacket); MsduAggregator::DeaggregatedMsdus packets = MsduAggregator::Deaggregate (aggregatedPacket);
for (MsduAggregator::DeaggregatedMsdusCI i = packets.begin (); for (MsduAggregator::DeaggregatedMsdusCI i = packets.begin ();
i != packets.end (); ++i) i != packets.end (); ++i)

View File

@@ -216,7 +216,7 @@ public:
/** /**
* \param phy the physical layer attached to this MAC. * \param phy the physical layer attached to this MAC.
*/ */
void SetWifiPhy (const Ptr<WifiPhy> phy); virtual void SetWifiPhy (const Ptr<WifiPhy> phy);
/** /**
* \return the physical layer attached to this MAC. * \return the physical layer attached to this MAC.
*/ */

View File

@@ -58,7 +58,7 @@ StaWifiMac::GetTypeId (void)
TimeValue (Seconds (0.05)), TimeValue (Seconds (0.05)),
MakeTimeAccessor (&StaWifiMac::m_probeRequestTimeout), MakeTimeAccessor (&StaWifiMac::m_probeRequestTimeout),
MakeTimeChecker ()) MakeTimeChecker ())
.AddAttribute ("AssocRequestTimeout", "The interval between two consecutive assoc request attempts.", .AddAttribute ("AssocRequestTimeout", "The interval between two consecutive association request attempts.",
TimeValue (Seconds (0.5)), TimeValue (Seconds (0.5)),
MakeTimeAccessor (&StaWifiMac::m_assocRequestTimeout), MakeTimeAccessor (&StaWifiMac::m_assocRequestTimeout),
MakeTimeChecker ()) MakeTimeChecker ())
@@ -120,11 +120,20 @@ StaWifiMac::SetActiveProbing (bool enable)
m_activeProbing = enable; m_activeProbing = enable;
} }
bool StaWifiMac::GetActiveProbing (void) const bool
StaWifiMac::GetActiveProbing (void) const
{ {
return m_activeProbing; return m_activeProbing;
} }
void
StaWifiMac::SetWifiPhy (const Ptr<WifiPhy> phy)
{
NS_LOG_FUNCTION (this << phy);
RegularWifiMac::SetWifiPhy (phy);
m_phy->SetCapabilitiesChangedCallback (MakeCallback (&StaWifiMac::PhyCapabilitiesChanged, this));
}
void void
StaWifiMac::SendProbeRequest (void) StaWifiMac::SendProbeRequest (void)
{ {
@@ -171,11 +180,11 @@ StaWifiMac::SendProbeRequest (void)
} }
void void
StaWifiMac::SendAssociationRequest (void) StaWifiMac::SendAssociationRequest (bool isReassoc)
{ {
NS_LOG_FUNCTION (this << GetBssid ()); NS_LOG_FUNCTION (this << GetBssid () << isReassoc);
WifiMacHeader hdr; 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.SetAddr1 (GetBssid ());
hdr.SetAddr2 (GetAddress ()); hdr.SetAddr2 (GetAddress ());
hdr.SetAddr3 (GetBssid ()); hdr.SetAddr3 (GetBssid ());
@@ -183,24 +192,49 @@ StaWifiMac::SendAssociationRequest (void)
hdr.SetDsNotTo (); hdr.SetDsNotTo ();
hdr.SetNoOrder (); hdr.SetNoOrder ();
Ptr<Packet> packet = Create<Packet> (); Ptr<Packet> packet = Create<Packet> ();
MgtAssocRequestHeader assoc; if (!isReassoc)
assoc.SetSsid (GetSsid ());
assoc.SetSupportedRates (GetSupportedRates ());
assoc.SetCapabilities (GetCapabilities ());
if (m_htSupported || m_vhtSupported || m_heSupported)
{ {
assoc.SetExtendedCapabilities (GetExtendedCapabilities ()); MgtAssocRequestHeader assoc;
assoc.SetHtCapabilities (GetHtCapabilities ()); 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 //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 //frames if we are a QoS AP. The approach taken here is to always
@@ -245,15 +279,15 @@ StaWifiMac::TryToEnsureAssociated (void)
} }
break; break;
case WAIT_ASSOC_RESP: case WAIT_ASSOC_RESP:
/* we have sent an assoc request so we do not need to /* we have sent an association request so we do not need to
re-send an assoc request right now. We just need to re-send an association request right now. We just need to
wait until either assoc-request-timeout or until wait until either assoc-request-timeout or until
we get an assoc response. we get an association response.
*/ */
break; break;
case REFUSED: case REFUSED:
/* we have sent an assoc request and received a negative /* we have sent an association request and received a negative
assoc resp. We wait until someone restarts an association response. We wait until someone restarts an
association with a given ssid. association with a given ssid.
*/ */
break; break;
@@ -265,7 +299,7 @@ StaWifiMac::AssocRequestTimeout (void)
{ {
NS_LOG_FUNCTION (this); NS_LOG_FUNCTION (this);
SetState (WAIT_ASSOC_RESP); SetState (WAIT_ASSOC_RESP);
SendAssociationRequest (); SendAssociationRequest (false);
} }
void void
@@ -447,7 +481,8 @@ StaWifiMac::Receive (Ptr<Packet> packet, const WifiMacHeader *hdr)
return; return;
} }
else if (hdr->IsProbeReq () else if (hdr->IsProbeReq ()
|| hdr->IsAssocReq ()) || hdr->IsAssocReq ()
|| hdr->IsReassocReq ())
{ {
//This is a frame aimed at an AP, so we can safely ignore it. //This is a frame aimed at an AP, so we can safely ignore it.
NotifyRxDrop (packet); NotifyRxDrop (packet);
@@ -455,6 +490,7 @@ StaWifiMac::Receive (Ptr<Packet> packet, const WifiMacHeader *hdr)
} }
else if (hdr->IsBeacon ()) else if (hdr->IsBeacon ())
{ {
NS_LOG_DEBUG ("Beacon received");
MgtBeaconHeader beacon; MgtBeaconHeader beacon;
packet->RemoveHeader (beacon); packet->RemoveHeader (beacon);
CapabilityInformation capabilities = beacon.GetCapabilities (); CapabilityInformation capabilities = beacon.GetCapabilities ();
@@ -608,7 +644,8 @@ StaWifiMac::Receive (Ptr<Packet> packet, const WifiMacHeader *hdr)
if (goodBeacon && m_state == BEACON_MISSED) if (goodBeacon && m_state == BEACON_MISSED)
{ {
SetState (WAIT_ASSOC_RESP); SetState (WAIT_ASSOC_RESP);
SendAssociationRequest (); NS_LOG_DEBUG ("Good beacon received: send association request");
SendAssociationRequest (false);
} }
return; return;
} }
@@ -616,12 +653,13 @@ StaWifiMac::Receive (Ptr<Packet> packet, const WifiMacHeader *hdr)
{ {
if (m_state == WAIT_PROBE_RESP) if (m_state == WAIT_PROBE_RESP)
{ {
NS_LOG_DEBUG ("Probe response received");
MgtProbeResponseHeader probeResp; MgtProbeResponseHeader probeResp;
packet->RemoveHeader (probeResp); packet->RemoveHeader (probeResp);
CapabilityInformation capabilities = probeResp.GetCapabilities (); CapabilityInformation capabilities = probeResp.GetCapabilities ();
if (!probeResp.GetSsid ().IsEqual (GetSsid ())) if (!probeResp.GetSsid ().IsEqual (GetSsid ()))
{ {
//not a probe resp for our ssid. NS_LOG_DEBUG ("Probe response is not for our SSID");
return; return;
} }
SupportedRates rates = probeResp.GetSupportedRates (); SupportedRates rates = probeResp.GetSupportedRates ();
@@ -630,6 +668,7 @@ StaWifiMac::Receive (Ptr<Packet> packet, const WifiMacHeader *hdr)
uint8_t selector = m_phy->GetBssMembershipSelector (i); uint8_t selector = m_phy->GetBssMembershipSelector (i);
if (!rates.IsBssMembershipSelectorRate (selector)) if (!rates.IsBssMembershipSelectorRate (selector))
{ {
NS_LOG_DEBUG ("Supported rates do not fit with the BSS membership selector");
return; return;
} }
} }
@@ -692,11 +731,11 @@ StaWifiMac::Receive (Ptr<Packet> packet, const WifiMacHeader *hdr)
m_probeRequestEvent.Cancel (); m_probeRequestEvent.Cancel ();
} }
SetState (WAIT_ASSOC_RESP); SetState (WAIT_ASSOC_RESP);
SendAssociationRequest (); SendAssociationRequest (false);
} }
return; return;
} }
else if (hdr->IsAssocResp ()) else if (hdr->IsAssocResp () || hdr->IsReassocResp ())
{ {
if (m_state == WAIT_ASSOC_RESP) if (m_state == WAIT_ASSOC_RESP)
{ {
@@ -709,7 +748,14 @@ StaWifiMac::Receive (Ptr<Packet> packet, const WifiMacHeader *hdr)
if (assocResp.GetStatusCode ().IsSuccess ()) if (assocResp.GetStatusCode ().IsSuccess ())
{ {
SetState (ASSOCIATED); SetState (ASSOCIATED);
NS_LOG_DEBUG ("assoc completed"); if (hdr->IsReassocResp ())
{
NS_LOG_DEBUG ("reassociation done");
}
else
{
NS_LOG_DEBUG ("association completed");
}
CapabilityInformation capabilities = assocResp.GetCapabilities (); CapabilityInformation capabilities = assocResp.GetCapabilities ();
SupportedRates rates = assocResp.GetSupportedRates (); SupportedRates rates = assocResp.GetSupportedRates ();
bool isShortPreambleEnabled = capabilities.IsShortPreamble (); bool isShortPreambleEnabled = capabilities.IsShortPreamble ();
@@ -869,7 +915,7 @@ StaWifiMac::Receive (Ptr<Packet> packet, const WifiMacHeader *hdr)
} }
else else
{ {
NS_LOG_DEBUG ("assoc refused"); NS_LOG_DEBUG ("association refused");
SetState (REFUSED); SetState (REFUSED);
} }
} }
@@ -938,4 +984,16 @@ StaWifiMac::SetEdcaParameters (AcIndex ac, uint32_t cwMin, uint32_t cwMax, uint8
edca->SetTxopLimit (txopLimit); edca->SetTxopLimit (txopLimit);
} }
void
StaWifiMac::PhyCapabilitiesChanged (void)
{
NS_LOG_FUNCTION (this);
if (IsAssociated ())
{
NS_LOG_DEBUG ("PHY capabilities changed: send reassociation request");
SetState (WAIT_ASSOC_RESP);
SendAssociationRequest (true);
}
}
} //namespace ns3 } //namespace ns3

View File

@@ -58,6 +58,11 @@ public:
*/ */
void Enqueue (Ptr<const Packet> packet, Mac48Address to); void Enqueue (Ptr<const Packet> packet, Mac48Address to);
/**
* \param phy the physical layer attached to this MAC.
*/
void SetWifiPhy (const Ptr<WifiPhy> phy);
private: private:
/** /**
@@ -93,10 +98,14 @@ private:
*/ */
void SendProbeRequest (void); void SendProbeRequest (void);
/** /**
* Forward an association request packet to the DCF. The standard is not clear on the correct * Forward an association or reassociation request packet to the DCF.
* queue for management frames if QoS is supported. We always use 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 * Try to ensure that we are associated with an AP by taking an appropriate action
* depending on the current association status. * depending on the current association status.
@@ -164,6 +173,11 @@ private:
*/ */
CapabilityInformation GetCapabilities (void) const; CapabilityInformation GetCapabilities (void) const;
/**
* Indicate that PHY capabilities have changed.
*/
void PhyCapabilitiesChanged (void);
MacState m_state; ///< MAC state MacState m_state; ///< MAC state
Time m_probeRequestTimeout; ///< probe request timeout Time m_probeRequestTimeout; ///< probe request timeout
Time m_assocRequestTimeout; ///< assoc request timeout Time m_assocRequestTimeout; ///< assoc request timeout

View File

@@ -98,6 +98,7 @@ WifiNetDevice::DoDispose (void)
void void
WifiNetDevice::DoInitialize (void) WifiNetDevice::DoInitialize (void)
{ {
NS_LOG_FUNCTION_NOARGS ();
m_phy->Initialize (); m_phy->Initialize ();
m_mac->Initialize (); m_mac->Initialize ();
m_stationManager->Initialize (); m_stationManager->Initialize ();
@@ -140,7 +141,7 @@ WifiNetDevice::NotifyNewAggregate (void)
// register the select queue callback // register the select queue callback
m_queueInterface->SetSelectQueueCallback (MakeCallback (&WifiNetDevice::SelectQueue, this)); m_queueInterface->SetSelectQueueCallback (MakeCallback (&WifiNetDevice::SelectQueue, this));
m_queueInterface->SetLateTxQueuesCreation (true); m_queueInterface->SetLateTxQueuesCreation (true);
FlowControlConfig (); FlowControlConfig ();
} }
} }
NetDevice::NotifyNewAggregate (); NetDevice::NotifyNewAggregate ();

View File

@@ -434,6 +434,12 @@ WifiPhy::UnregisterListener (WifiPhyListener *listener)
m_state->UnregisterListener (listener); m_state->UnregisterListener (listener);
} }
void
WifiPhy::SetCapabilitiesChangedCallback (Callback<void> callback)
{
m_capabilitiesChangedCallback = callback;
}
void void
WifiPhy::InitializeFrequencyChannelNumber (void) WifiPhy::InitializeFrequencyChannelNumber (void)
{ {
@@ -537,7 +543,7 @@ WifiPhy::GetTxPowerEnd (void) const
void void
WifiPhy::SetNTxPower (uint8_t n) WifiPhy::SetNTxPower (uint8_t n)
{ {
NS_LOG_FUNCTION (this << static_cast<uint16_t>(n)); NS_LOG_FUNCTION (this << static_cast<uint16_t> (n));
m_nTxPower = n; m_nTxPower = n;
} }
@@ -707,7 +713,7 @@ WifiPhy::GetFrameCaptureModel (void) const
{ {
return m_frameCaptureModel; return m_frameCaptureModel;
} }
void void
WifiPhy::SetWifiRadioEnergyModel (const Ptr<WifiRadioEnergyModel> wifiRadioEnergyModel) WifiPhy::SetWifiRadioEnergyModel (const Ptr<WifiRadioEnergyModel> wifiRadioEnergyModel)
{ {
@@ -1267,9 +1273,15 @@ WifiPhy::GetFrequency (void) const
void void
WifiPhy::SetChannelWidth (uint8_t channelwidth) WifiPhy::SetChannelWidth (uint8_t channelwidth)
{ {
NS_LOG_FUNCTION (this << static_cast<uint16_t> (channelwidth));
NS_ASSERT_MSG (channelwidth == 5 || channelwidth == 10 || channelwidth == 20 || channelwidth == 22 || channelwidth == 40 || channelwidth == 80 || channelwidth == 160, "wrong channel width value"); 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; m_channelWidth = channelwidth;
AddSupportedChannelWidth (channelwidth); AddSupportedChannelWidth (channelwidth);
if (changed && !m_capabilitiesChangedCallback.IsNull ())
{
m_capabilitiesChangedCallback ();
}
} }
uint8_t uint8_t
@@ -1296,8 +1308,13 @@ void
WifiPhy::SetMaxSupportedTxSpatialStreams (uint8_t streams) WifiPhy::SetMaxSupportedTxSpatialStreams (uint8_t streams)
{ {
NS_ASSERT (streams <= GetNumberOfAntennas ()); NS_ASSERT (streams <= GetNumberOfAntennas ());
bool changed = (m_txSpatialStreams == streams);
m_txSpatialStreams = streams; m_txSpatialStreams = streams;
ConfigureHtDeviceMcsSet (); ConfigureHtDeviceMcsSet ();
if (changed && !m_capabilitiesChangedCallback.IsNull ())
{
m_capabilitiesChangedCallback ();
}
} }
uint8_t uint8_t
@@ -1310,7 +1327,12 @@ void
WifiPhy::SetMaxSupportedRxSpatialStreams (uint8_t streams) WifiPhy::SetMaxSupportedRxSpatialStreams (uint8_t streams)
{ {
NS_ASSERT (streams <= GetNumberOfAntennas ()); NS_ASSERT (streams <= GetNumberOfAntennas ());
bool changed = (m_rxSpatialStreams == streams);
m_rxSpatialStreams = streams; m_rxSpatialStreams = streams;
if (changed && !m_capabilitiesChangedCallback.IsNull ())
{
m_capabilitiesChangedCallback ();
}
} }
uint8_t uint8_t
@@ -2398,10 +2420,10 @@ WifiPhy::StartReceivePreambleAndHeader (Ptr<Packet> packet, double rxPowerW, Tim
if (tag.GetFrameComplete () == 0) if (tag.GetFrameComplete () == 0)
{ {
NS_LOG_DEBUG ("drop packet because of incomplete frame"); NS_LOG_DEBUG ("drop packet because of incomplete frame");
NotifyRxDrop (packet); NotifyRxDrop (packet);
m_plcpSuccess = false; m_plcpSuccess = false;
return; return;
} }
WifiTxVector txVector = tag.GetWifiTxVector (); WifiTxVector txVector = tag.GetWifiTxVector ();

View File

@@ -53,7 +53,7 @@ class FrameCaptureModel;
* WifiRadioEnergyModel class * WifiRadioEnergyModel class
*/ */
class WifiRadioEnergyModel; class WifiRadioEnergyModel;
/** /**
* This enumeration defines the type of an MPDU. * This enumeration defines the type of an MPDU.
*/ */
@@ -257,6 +257,11 @@ public:
*/ */
void UnregisterListener (WifiPhyListener *listener); void UnregisterListener (WifiPhyListener *listener);
/**
* \param callback the callback to invoke when PHY capabilities have changed.
*/
void SetCapabilitiesChangedCallback (Callback<void> callback);
/** /**
* Starting receiving the plcp of a packet (i.e. the first bit of the preamble has arrived). * Starting receiving the plcp of a packet (i.e. the first bit of the preamble has arrived).
* *
@@ -353,7 +358,7 @@ public:
/** /**
* \return true if the current state of the PHY layer is WifiPhy::OFF, false otherwise. * \return true if the current state of the PHY layer is WifiPhy::OFF, false otherwise.
*/ */
bool IsStateOff (void) const ; bool IsStateOff (void) const;
/** /**
* \return the amount of time since the current state has started. * \return the amount of time since the current state has started.
@@ -1798,7 +1803,7 @@ private:
* \return the FrequencyWidthPair found * \return the FrequencyWidthPair found
*/ */
FrequencyWidthPair GetFrequencyWidthForChannelNumberStandard (uint8_t channelNumber, WifiPhyStandard standard) const; FrequencyWidthPair GetFrequencyWidthForChannelNumberStandard (uint8_t channelNumber, WifiPhyStandard standard) const;
/** /**
* Due to newly arrived signal, the current reception cannot be continued and has to be aborted * Due to newly arrived signal, the current reception cannot be continued and has to be aborted
* *
@@ -1809,7 +1814,7 @@ private:
* Eventually switch to CCA busy * Eventually switch to CCA busy
*/ */
void MaybeCcaBusyDuration (void); void MaybeCcaBusyDuration (void);
/** /**
* Starting receiving the packet after having detected the medium is idle or after a reception switch. * Starting receiving the packet after having detected the medium is idle or after a reception switch.
* *
@@ -1987,6 +1992,8 @@ private:
Ptr<InterferenceHelper::Event> m_currentEvent; //!< Hold the current event Ptr<InterferenceHelper::Event> m_currentEvent; //!< Hold the current event
Ptr<FrameCaptureModel> m_frameCaptureModel; //!< Frame capture model Ptr<FrameCaptureModel> m_frameCaptureModel; //!< Frame capture model
Ptr<WifiRadioEnergyModel> m_wifiRadioEnergyModel; //!< Wifi radio energy model Ptr<WifiRadioEnergyModel> m_wifiRadioEnergyModel; //!< Wifi radio energy model
Callback<void> m_capabilitiesChangedCallback; //!< Callback when PHY capabilities changed
}; };
/** /**

View File

@@ -1283,7 +1283,7 @@ Bug2483TestCase::DoRun (void)
spectrumChannel->AddPropagationLossModel (lossModel); spectrumChannel->AddPropagationLossModel (lossModel);
Ptr<ConstantSpeedPropagationDelayModel> delayModel Ptr<ConstantSpeedPropagationDelayModel> delayModel
= CreateObject<ConstantSpeedPropagationDelayModel> (); = CreateObject<ConstantSpeedPropagationDelayModel> ();
spectrumChannel->SetPropagationDelayModel (delayModel); spectrumChannel->SetPropagationDelayModel (delayModel);
spectrumPhy.SetChannel (spectrumChannel); spectrumPhy.SetChannel (spectrumChannel);
@@ -1343,6 +1343,177 @@ Bug2483TestCase::DoRun (void)
NS_TEST_ASSERT_MSG_EQ (std::get<3> (m_distinctTuples[1]), WifiModulationClass::WIFI_MOD_CLASS_VHT, "Second tuple should be VHT_OFDM"); NS_TEST_ASSERT_MSG_EQ (std::get<3> (m_distinctTuples[1]), WifiModulationClass::WIFI_MOD_CLASS_VHT, "Second tuple should be VHT_OFDM");
} }
//-----------------------------------------------------------------------------
/**
* Make sure that the channel width and the channel number can be changed at runtime.
*
* The scenario considers an access point and a station using a 20 MHz channel width.
* After 1s, we change the channel width and the channel number to use a 40 MHz channel.
* The tests checks the operational channel width sent in Beacon frames
* and verify that a reassociation procedure is executed.
*
* See \bugid{2831}
*/
class Bug2831TestCase : public TestCase
{
public:
Bug2831TestCase ();
virtual ~Bug2831TestCase ();
virtual void DoRun (void);
private:
/**
* Function called to change the supported channel width at runtime
*/
void ChangeSupportedChannelWidth (void);
/**
* Callback triggered when a packet is received by the PHYs
* \param context the context
* \param p the received packet
*/
void RxCallback (std::string context, Ptr<const Packet> p);
Ptr<YansWifiPhy> m_apPhy; ///< AP PHY
Ptr<YansWifiPhy> m_staPhy; ///< STA PHY
uint8_t m_reassocReqCount; ///< count number of reassociation requests
uint8_t m_reassocRespCount; ///< count number of reassociation responses
uint8_t m_countOperationalChannelWidth20; ///< count number of beacon frames announcing a 20 MHz operating channel width
uint8_t m_countOperationalChannelWidth40; ///< count number of beacon frames announcing a 40 MHz operating channel width
};
Bug2831TestCase::Bug2831TestCase ()
: TestCase ("Test case for Bug 2831"),
m_reassocReqCount (0),
m_reassocRespCount (0),
m_countOperationalChannelWidth20 (0),
m_countOperationalChannelWidth40 (0)
{
}
Bug2831TestCase::~Bug2831TestCase ()
{
}
void
Bug2831TestCase::ChangeSupportedChannelWidth ()
{
m_apPhy->SetChannelNumber (38);
m_apPhy->SetChannelWidth (40);
m_staPhy->SetChannelNumber (38);
m_staPhy->SetChannelWidth (40);
}
void
Bug2831TestCase::RxCallback (std::string context, Ptr<const Packet> p)
{
Ptr<Packet> packet = p->Copy ();
WifiMacHeader hdr;
packet->RemoveHeader (hdr);
if (hdr.IsReassocReq ())
{
m_reassocReqCount++;
}
else if (hdr.IsReassocResp ())
{
m_reassocRespCount++;
}
else if (hdr.IsBeacon ())
{
MgtBeaconHeader beacon;
packet->RemoveHeader (beacon);
HtOperation htOperation = beacon.GetHtOperation ();
if (htOperation.GetStaChannelWidth () > 0)
{
m_countOperationalChannelWidth40++;
}
else
{
m_countOperationalChannelWidth20++;
}
}
}
void
Bug2831TestCase::DoRun (void)
{
Ptr<YansWifiChannel> channel = CreateObject<YansWifiChannel> ();
ObjectFactory propDelay;
propDelay.SetTypeId ("ns3::ConstantSpeedPropagationDelayModel");
Ptr<PropagationDelayModel> propagationDelay = propDelay.Create<PropagationDelayModel> ();
Ptr<PropagationLossModel> propagationLoss = CreateObject<RandomPropagationLossModel> ();
channel->SetPropagationDelayModel (propagationDelay);
channel->SetPropagationLossModel (propagationLoss);
Ptr<Node> apNode = CreateObject<Node> ();
Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice> ();
ObjectFactory mac;
mac.SetTypeId ("ns3::ApWifiMac");
Ptr<WifiMac> apMac = mac.Create<WifiMac> ();
apMac->ConfigureStandard (WIFI_PHY_STANDARD_80211n_5GHZ);
Ptr<Node> staNode = CreateObject<Node> ();
Ptr<WifiNetDevice> staDev = CreateObject<WifiNetDevice> ();
mac.SetTypeId ("ns3::StaWifiMac");
Ptr<WifiMac> staMac = mac.Create<WifiMac> ();
staMac->ConfigureStandard (WIFI_PHY_STANDARD_80211n_5GHZ);
Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel> ();
apMobility->SetPosition (Vector (0.0, 0.0, 0.0));
apNode->AggregateObject (apMobility);
Ptr<ErrorRateModel> error = CreateObject<YansErrorRateModel> ();
m_apPhy = CreateObject<YansWifiPhy> ();
m_apPhy->SetErrorRateModel (error);
m_apPhy->SetChannel (channel);
m_apPhy->SetMobility (apMobility);
m_apPhy->SetDevice (apDev);
m_apPhy->ConfigureStandard (WIFI_PHY_STANDARD_80211n_5GHZ);
m_apPhy->SetChannelNumber (36);
m_apPhy->SetChannelWidth (20);
Ptr<ConstantPositionMobilityModel> staMobility = CreateObject<ConstantPositionMobilityModel> ();
staMobility->SetPosition (Vector (1.0, 0.0, 0.0));
staNode->AggregateObject (staMobility);
m_staPhy = CreateObject<YansWifiPhy> ();
m_staPhy->SetErrorRateModel (error);
m_staPhy->SetChannel (channel);
m_staPhy->SetMobility (staMobility);
m_staPhy->SetDevice (apDev);
m_staPhy->ConfigureStandard (WIFI_PHY_STANDARD_80211n_5GHZ);
m_staPhy->SetChannelNumber (36);
m_staPhy->SetChannelWidth (20);
apMac->SetAddress (Mac48Address::Allocate ());
apDev->SetMac (apMac);
apDev->SetPhy (m_apPhy);
ObjectFactory manager;
manager.SetTypeId ("ns3::ConstantRateWifiManager");
apDev->SetRemoteStationManager (manager.Create<WifiRemoteStationManager> ());
apNode->AddDevice (apDev);
staMac->SetAddress (Mac48Address::Allocate ());
staDev->SetMac (staMac);
staDev->SetPhy (m_staPhy);
staDev->SetRemoteStationManager (manager.Create<WifiRemoteStationManager> ());
staNode->AddDevice (staDev);
Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyRxBegin", MakeCallback (&Bug2831TestCase::RxCallback, this));
Simulator::Schedule (Seconds (1.0), &Bug2831TestCase::ChangeSupportedChannelWidth, this);
Simulator::Stop (Seconds (3.0));
Simulator::Run ();
Simulator::Destroy ();
NS_TEST_ASSERT_MSG_EQ (m_reassocReqCount, 1, "Reassociation request not received");
NS_TEST_ASSERT_MSG_EQ (m_reassocRespCount, 1, "Reassociation response not received");
NS_TEST_ASSERT_MSG_EQ (m_countOperationalChannelWidth20, 10, "Incorrect operational channel width before channel change");
NS_TEST_ASSERT_MSG_EQ (m_countOperationalChannelWidth40, 20, "Incorrect operational channel width after channel change");
}
/** /**
* \ingroup wifi-test * \ingroup wifi-test
* \ingroup tests * \ingroup tests
@@ -1366,6 +1537,7 @@ WifiTestSuite::WifiTestSuite ()
AddTestCase (new SetChannelFrequencyTest, TestCase::QUICK); AddTestCase (new SetChannelFrequencyTest, TestCase::QUICK);
AddTestCase (new Bug2222TestCase, TestCase::QUICK); //Bug 2222 AddTestCase (new Bug2222TestCase, TestCase::QUICK); //Bug 2222
AddTestCase (new Bug2483TestCase, TestCase::QUICK); //Bug 2483 AddTestCase (new Bug2483TestCase, TestCase::QUICK); //Bug 2483
AddTestCase (new Bug2831TestCase, TestCase::QUICK); //Bug 2831
} }
static WifiTestSuite g_wifiTestSuite; ///< the test suite static WifiTestSuite g_wifiTestSuite; ///< the test suite