wifi: (fixes #2399) Improve scanning procedure of StaWifiMac

This commit is contained in:
Muhammad Iqbal CR
2018-06-07 12:48:30 -07:00
parent 3006b584c4
commit b9ed68da5f
4 changed files with 423 additions and 86 deletions

View File

@@ -485,25 +485,27 @@ Infrastructure association
Association in infrastructure (IBSS) mode is a high-level MAC function.
Either active probing or passive scanning is used (default is passive scan).
At the start of the simulation, Wi-Fi network devices configured as
STA will listen for beacons on the same SSID and will attempt to associate
with the AP that generates the first received beacon that is considered
to be good. If active probing is enabled, STA will regularly send probe
request until it receive probe response and will similarly attempt to
associate with the AP that generates the first received probe response.
STA will attempt to scan the channel. Depends on whether passive or active
scanning is selected, STA will attempt to gather beacons, or send a probe
request and gather probe responses until the respective timeout occurs. The
end result will be a list of candidate AP to associate to. STA will then try
to associate to the best AP (i.e., best SNR).
If association is rejected by the AP for some reason, the STA will
move to a 'REFUSED' state and the simulation user will need to force a
reassociation retry in some way, perhaps by changing configuration
(i.e. the STA will not persistently try to associate upon a refusal).
If association is rejected by the AP for some reason, the STA will try to
associate to the next best AP until the candidate list is exhausted which
then sends STA to 'REFUSED' state. If this occurs, the simulation user will
need to force reassociation retry in some way, perhaps by changing
configuration (i.e. the STA will not persistently try to associate upon a
refusal).
When associated, if the configuration is changed by the simulation user,
the STA will try to reassociate with the existing AP.
If a number of missed beacons exceeds a threshold, the STA will notify
the rest of the device that the link is down (association is lost). If
configured for passive scanning, the STA will try to associate again with
the first good beacon heard. If in active probing, the STA will initiate
a new probe request.
If the number of missed beacons exceeds the threshold, the STA will notify
the rest of the device that the link is down (association is lost) and
restart the scanning process. Note that this can also happen when an
association request fails without explicit refusal (i.e., the AP fails to
respond to association request).
Roaming
#######

View File

@@ -27,6 +27,7 @@
#include "wifi-phy.h"
#include "mac-low.h"
#include "mgt-headers.h"
#include "snr-tag.h"
namespace ns3 {
@@ -41,10 +42,14 @@ StaWifiMac::GetTypeId (void)
.SetParent<InfrastructureWifiMac> ()
.SetGroupName ("Wifi")
.AddConstructor<StaWifiMac> ()
.AddAttribute ("ProbeRequestTimeout", "The interval between two consecutive probe request attempts.",
.AddAttribute ("ProbeRequestTimeout", "The duration to actively probe the channel.",
TimeValue (Seconds (0.05)),
MakeTimeAccessor (&StaWifiMac::m_probeRequestTimeout),
MakeTimeChecker ())
.AddAttribute ("WaitBeaconTimeout", "The duration to dwell on a channel while passively scanning for beacon",
TimeValue (MilliSeconds (120)),
MakeTimeAccessor (&StaWifiMac::m_waitBeaconTimeout),
MakeTimeChecker ())
.AddAttribute ("AssocRequestTimeout", "The interval between two consecutive association request attempts.",
TimeValue (Seconds (0.5)),
MakeTimeAccessor (&StaWifiMac::m_assocRequestTimeout),
@@ -75,7 +80,8 @@ StaWifiMac::GetTypeId (void)
}
StaWifiMac::StaWifiMac ()
: m_state (BEACON_MISSED),
: m_state (UNASSOCIATED),
m_waitBeaconEvent (),
m_probeRequestEvent (),
m_assocRequestEvent (),
m_beaconWatchdogEnd (Seconds (0))
@@ -87,6 +93,13 @@ StaWifiMac::StaWifiMac ()
SetTypeOfStation (STA);
}
void
StaWifiMac::DoInitialize (void)
{
NS_LOG_FUNCTION (this);
StartScanning ();
}
StaWifiMac::~StaWifiMac ()
{
NS_LOG_FUNCTION (this);
@@ -96,15 +109,12 @@ void
StaWifiMac::SetActiveProbing (bool enable)
{
NS_LOG_FUNCTION (this << enable);
if (enable)
{
Simulator::ScheduleNow (&StaWifiMac::TryToEnsureAssociated, this);
}
else
{
m_probeRequestEvent.Cancel ();
}
m_activeProbing = enable;
if (m_state == WAIT_PROBE_RESP || m_state == WAIT_BEACON)
{
NS_LOG_DEBUG ("STA is still scanning, reset scanning process");
StartScanning ();
}
}
bool
@@ -165,13 +175,6 @@ StaWifiMac::SendProbeRequest (void)
//use the non-QoS for these regardless of whether we have a QoS
//association or not.
m_txop->Queue (packet, hdr);
if (m_probeRequestEvent.IsRunning ())
{
m_probeRequestEvent.Cancel ();
}
m_probeRequestEvent = Simulator::Schedule (m_probeRequestTimeout,
&StaWifiMac::ProbeRequestTimeout, this);
}
void
@@ -271,17 +274,18 @@ StaWifiMac::TryToEnsureAssociated (void)
or until we get a probe response
*/
break;
case BEACON_MISSED:
case WAIT_BEACON:
/* we have initiated passive scanning, continue to wait
and gather beacons
*/
break;
case UNASSOCIATED:
/* we were associated but we missed a bunch of beacons
* so we should assume we are not associated anymore.
* We try to initiate a probe request now.
* We try to initiate a scan now.
*/
m_linkDown ();
if (GetActiveProbing ())
{
SetState (WAIT_PROBE_RESP);
SendProbeRequest ();
}
StartScanning ();
break;
case WAIT_ASSOC_RESP:
/* we have sent an association request so we do not need to
@@ -299,6 +303,69 @@ StaWifiMac::TryToEnsureAssociated (void)
}
}
void
StaWifiMac::StartScanning (void)
{
NS_LOG_FUNCTION (this);
m_candidateAps.clear ();
if (m_probeRequestEvent.IsRunning ())
{
m_probeRequestEvent.Cancel ();
}
if (m_waitBeaconEvent.IsRunning ())
{
m_waitBeaconEvent.Cancel ();
}
if (GetActiveProbing ())
{
SetState (WAIT_PROBE_RESP);
SendProbeRequest ();
m_probeRequestEvent = Simulator::Schedule (m_probeRequestTimeout,
&StaWifiMac::ScanningTimeout,
this);
}
else
{
SetState (WAIT_BEACON);
m_waitBeaconEvent = Simulator::Schedule (m_waitBeaconTimeout,
&StaWifiMac::ScanningTimeout,
this);
}
}
void
StaWifiMac::ScanningTimeout (void)
{
NS_LOG_FUNCTION (this);
if (!m_candidateAps.empty ())
{
ApInfo bestAp = m_candidateAps.front();
m_candidateAps.erase(m_candidateAps.begin ());
NS_LOG_DEBUG ("Attempting to associate with BSSID " << bestAp.m_bssid);
Time beaconInterval;
if (bestAp.m_activeProbing)
{
UpdateApInfoFromProbeResp (bestAp.m_probeResp, bestAp.m_apAddr, bestAp.m_bssid);
beaconInterval = MicroSeconds (bestAp.m_probeResp.GetBeaconIntervalUs ());
}
else
{
UpdateApInfoFromBeacon (bestAp.m_beacon, bestAp.m_apAddr, bestAp.m_bssid);
beaconInterval = MicroSeconds (bestAp.m_beacon.GetBeaconIntervalUs ());
}
Time delay = beaconInterval * m_maxMissedBeacons;
RestartBeaconWatchdog (delay);
SetState (WAIT_ASSOC_RESP);
SendAssociationRequest (false);
}
else
{
NS_LOG_DEBUG ("Exhausted list of candidate AP; restart scanning");
StartScanning ();
}
}
void
StaWifiMac::AssocRequestTimeout (void)
{
@@ -307,14 +374,6 @@ StaWifiMac::AssocRequestTimeout (void)
SendAssociationRequest (false);
}
void
StaWifiMac::ProbeRequestTimeout (void)
{
NS_LOG_FUNCTION (this);
SetState (WAIT_PROBE_RESP);
SendProbeRequest ();
}
void
StaWifiMac::MissedBeacons (void)
{
@@ -330,7 +389,7 @@ StaWifiMac::MissedBeacons (void)
return;
}
NS_LOG_DEBUG ("beacon missed");
SetState (BEACON_MISSED);
SetState (UNASSOCIATED);
TryToEnsureAssociated ();
}
@@ -545,17 +604,25 @@ StaWifiMac::Receive (Ptr<Packet> packet, const WifiMacHeader *hdr)
NS_LOG_LOGIC ("Beacon is not for us");
goodBeacon = false;
}
if (goodBeacon)
if (goodBeacon && m_state == ASSOCIATED)
{
Time delay = MicroSeconds (beacon.GetBeaconIntervalUs () * m_maxMissedBeacons);
RestartBeaconWatchdog (delay);
UpdateApInfoFromBeacon (beacon, hdr->GetAddr2 (), hdr->GetAddr3 ());
}
if (goodBeacon && m_state == BEACON_MISSED)
if (goodBeacon && m_state == WAIT_BEACON)
{
SetState (WAIT_ASSOC_RESP);
NS_LOG_DEBUG ("Good beacon received: send association request");
SendAssociationRequest (false);
NS_LOG_DEBUG ("Beacon received while scanning from " << hdr->GetAddr2 ());
SnrTag snrTag;
bool removed = packet->RemovePacketTag (snrTag);
NS_ASSERT (removed);
ApInfo apInfo;
apInfo.m_apAddr = hdr->GetAddr2 ();
apInfo.m_bssid = hdr->GetAddr3 ();
apInfo.m_activeProbing = false;
apInfo.m_snr = snrTag.Get ();
apInfo.m_beacon = beacon;
UpdateCandidateApList (apInfo);
}
return;
}
@@ -563,7 +630,7 @@ StaWifiMac::Receive (Ptr<Packet> packet, const WifiMacHeader *hdr)
{
if (m_state == WAIT_PROBE_RESP)
{
NS_LOG_DEBUG ("Probe response received");
NS_LOG_DEBUG ("Probe response received while scanning from " << hdr->GetAddr2 ());
MgtProbeResponseHeader probeResp;
packet->RemoveHeader (probeResp);
if (!probeResp.GetSsid ().IsEqual (GetSsid ()))
@@ -571,15 +638,16 @@ StaWifiMac::Receive (Ptr<Packet> packet, const WifiMacHeader *hdr)
NS_LOG_DEBUG ("Probe response is not for our SSID");
return;
}
UpdateApInfoFromProbeResp (probeResp, hdr->GetAddr2 (), hdr->GetAddr3 ());
Time delay = MicroSeconds (probeResp.GetBeaconIntervalUs () * m_maxMissedBeacons);
RestartBeaconWatchdog (delay);
if (m_probeRequestEvent.IsRunning ())
{
m_probeRequestEvent.Cancel ();
}
SetState (WAIT_ASSOC_RESP);
SendAssociationRequest (false);
SnrTag snrTag;
bool removed = packet->RemovePacketTag (snrTag);
NS_ASSERT (removed);
ApInfo apInfo;
apInfo.m_apAddr = hdr->GetAddr2 ();
apInfo.m_bssid = hdr->GetAddr3 ();
apInfo.m_activeProbing = true;
apInfo.m_snr = snrTag.Get ();
apInfo.m_probeResp = probeResp;
UpdateCandidateApList (apInfo);
}
return;
}
@@ -613,7 +681,14 @@ StaWifiMac::Receive (Ptr<Packet> packet, const WifiMacHeader *hdr)
else
{
NS_LOG_DEBUG ("association refused");
SetState (REFUSED);
if (m_candidateAps.empty ())
{
SetState (REFUSED);
}
else
{
ScanningTimeout ();
}
}
}
return;
@@ -625,6 +700,32 @@ StaWifiMac::Receive (Ptr<Packet> packet, const WifiMacHeader *hdr)
RegularWifiMac::Receive (packet, hdr);
}
void
StaWifiMac::UpdateCandidateApList (ApInfo newApInfo)
{
NS_LOG_FUNCTION (this << newApInfo.m_bssid << newApInfo.m_apAddr << newApInfo.m_snr << newApInfo.m_activeProbing << newApInfo.m_beacon << newApInfo.m_probeResp);
// Remove duplicate ApInfo entry
for (std::vector<ApInfo>::iterator i = m_candidateAps.begin(); i != m_candidateAps.end(); ++i)
{
if (newApInfo.m_bssid == (*i).m_bssid)
{
m_candidateAps.erase(i);
break;
}
}
// Insert before the entry with lower SNR
for (std::vector<ApInfo>::iterator i = m_candidateAps.begin(); i != m_candidateAps.end(); ++i)
{
if (newApInfo.m_snr > (*i).m_snr)
{
m_candidateAps.insert (i, newApInfo);
return;
}
}
// If new ApInfo is the lowest, insert at back
m_candidateAps.push_back(newApInfo);
}
void
StaWifiMac::UpdateApInfoFromBeacon (MgtBeaconHeader beacon, Mac48Address apAddr, Mac48Address bssid)
{

View File

@@ -24,16 +24,29 @@
#define STA_WIFI_MAC_H
#include "infrastructure-wifi-mac.h"
#include "mgt-headers.h"
namespace ns3 {
class MgtAddBaRequestHeader;
class MgtBeaconHeader;
class MgtProbeResponseHeader;
class MgtAssocResponseHeader;
class SupportedRates;
class CapabilityInformation;
/**
* \ingroup wifi
*
* Struct to hold information regarding observed AP through
* active/passive scanning
*/
struct ApInfo
{
Mac48Address m_bssid;
Mac48Address m_apAddr;
double m_snr;
bool m_activeProbing;
MgtBeaconHeader m_beacon;
MgtProbeResponseHeader m_probeResp;
};
/**
* \ingroup wifi
*
@@ -41,30 +54,50 @@ class CapabilityInformation;
* machine is as follows:
*
\verbatim
--------- -------------- -----------
| Start | | Associated | <-------- ------> | Refused |
--------- -------------- | / -----------
| | | /
\ v v /
\ ----------------- -----------------------------
\-> | Beacon Missed | <--> | Wait Association Response |
----------------- -----------------------------
\ ^ ^ |
\ | | |
\ ----------------------- -
\-> | Wait Probe Response |
-----------------------
--------- -------------- -----------
| Start | | Associated | <------------------------- ----> | Refused |
--------- -------------- | / -----------
| | /------------------------------\ | /
\ v v | v /
\ ---------------- --------------- -----------------------------
\-> | Unassociated | --> | Wait Beacon | --> | Wait Association Response |
---------------- --------------- -----------------------------
\ ^ ^ | ^ ^ |
\ | | | | | |
\ v - / -
\ ----------------------- /
\-> | Wait Probe Response | --------/
-----------------------
^ |
| |
-
\endverbatim
*
* Notes:
* 1. The state 'Start' is not included in #MacState and only used
* for illustration purpose.
* 2. The transition from Wait Association Response to Beacon Missed
* 2. The Unassociated state is a transient state before STA starts the
* scanning procedure which moves it into either Wait Beacon or Wait
* Probe Response, based on whether passive or active scanning is
* selected.
* 3. In Wait Beacon and Wait Probe Response, STA is gathering beacon or
* probe response packets from APs, resulted in a list of candidate AP.
* After the respective timeout, it then tries to associate to the best
* AP (i.e., best SNR). STA will switch between the two states and
* restart the scanning procedure if SetActiveProbing() called.
* 4. In the case when AP responded to STA's association request with a
* refusal, STA will try to associate to the next best AP until the list
* of candidate AP is exhausted which sends STA to Refused state.
* - Note that this behavior is not currently tested since ns-3 does not
* implement association refusal at present.
* 5. The transition from Wait Association Response to Unassociated
* occurs if an association request fails without explicit
* refusal (i.e., the AP fails to respond).
* 3. The transition from Associated to Wait Association Response
* 6. The transition from Associated to Wait Association Response
* occurs when STA's PHY capabilities changed. In this state, STA
* tries to reassociate with the previously associated AP.
* 7. The transition from Associated to Unassociated occurs if the number
* of missed beacons exceeds the threshold.
*/
class StaWifiMac : public InfrastructureWifiMac
{
@@ -108,9 +141,10 @@ private:
enum MacState
{
ASSOCIATED,
WAIT_BEACON,
WAIT_PROBE_RESP,
WAIT_ASSOC_RESP,
BEACON_MISSED,
UNASSOCIATED,
REFUSED
};
@@ -159,6 +193,13 @@ private:
* \param apAddr mac address of the AP
*/
void UpdateApInfoFromAssocResp (MgtAssocResponseHeader assocResp, Mac48Address apAddr);
/**
* Update list of candidate AP to associate. The list should contain ApInfo sorted from
* best to worst SNR, with no duplicate.
*
* \param newApInfo the new ApInfo to be inserted
*/
void UpdateCandidateApList (ApInfo newApInfo);
/**
* Forward a probe request packet to the DCF. The standard is not clear on the correct
@@ -189,10 +230,16 @@ private:
*/
void AssocRequestTimeout (void);
/**
* This method is called after the probe request timeout occurred. We switch the state to
* WAIT_PROBE_RESP and re-send a probe request.
* Start the scanning process which trigger active or passive scanning based on the
* active probing flag.
*/
void ProbeRequestTimeout (void);
void StartScanning (void);
/**
* This method is called after wait beacon timeout or wait probe request timeout has
* occured. This will trigger association process from beacons or probe responses
* gathered while scanning.
*/
void ScanningTimeout (void);
/**
* Return whether we are associated with an AP.
*
@@ -250,15 +297,24 @@ private:
*/
void PhyCapabilitiesChanged (void);
void DoInitialize (void);
MacState m_state; ///< MAC state
Time m_waitBeaconTimeout; ///< wait beacon timeout
Time m_probeRequestTimeout; ///< probe request timeout
Time m_assocRequestTimeout; ///< assoc request timeout
EventId m_waitBeaconEvent; ///< wait beacon event
EventId m_probeRequestEvent; ///< probe request event
EventId m_assocRequestEvent; ///< assoc request event
EventId m_beaconWatchdog; ///< beacon watchdog
Time m_beaconWatchdogEnd; ///< beacon watchdog end
uint32_t m_maxMissedBeacons; ///< maximum missed beacons
bool m_activeProbing; ///< active probing
std::vector<ApInfo> m_candidateAps; ///< list of candidate APs to associate
// Note: std::multiset<ApInfo> might be a candidate container to implement
// this sorted list, but we are using a std::vector because we want to sort
// based on SNR but find duplicates based on BSSID, and in practice this
// candidate vector should not be too large.
TracedCallback<Mac48Address> m_assocLogger; ///< assoc logger
TracedCallback<Mac48Address> m_deAssocLogger; ///< deassoc logger

View File

@@ -26,6 +26,7 @@
#include "ns3/mobility-helper.h"
#include "ns3/wifi-net-device.h"
#include "ns3/adhoc-wifi-mac.h"
#include "ns3/ap-wifi-mac.h"
#include "ns3/propagation-loss-model.h"
#include "ns3/yans-error-rate-model.h"
#include "ns3/constant-position-mobility-model.h"
@@ -1512,6 +1513,182 @@ Bug2831TestCase::DoRun (void)
NS_TEST_ASSERT_MSG_EQ (m_countOperationalChannelWidth40, 20, "Incorrect operational channel width after channel change");
}
//-----------------------------------------------------------------------------
/**
* Make sure that Wifi STA is correctly associating to the best AP (i.e.,
* nearest from STA). We consider 3 AP and 1 STA. This test case consisted of
* three sub tests:
* - The best AP sends its beacon later than the other APs. STA is expected
* to associate to the best AP.
* - The STA is using active scanning instead of passive, the rest of the
* APs works normally. STA is expected to associate to the best AP
* - The nearest AP is turned off after sending beacon and while STA is
* still scanning. STA is expected to associate to the second best AP.
*
* See \bugid{2399}
* \todo Add explicit association refusal test if ns-3 implemented it.
*/
class StaWifiMacScanningTestCase : public TestCase
{
public:
StaWifiMacScanningTestCase ();
virtual ~StaWifiMacScanningTestCase ();
virtual void DoRun (void);
private:
/**
* Callback function on STA assoc event
* \param context context string
* \param bssid the associated AP's bssid
*/
void AssocCallback (std::string context, Mac48Address bssid);
/**
* Turn beacon generation on the AP node
* \param apNode the AP node
*/
void TurnBeaconGenerationOn (Ptr<Node> apNode);
/**
* Turn the AP node off
* \param apNode the AP node
*/
void TurnApOff (Ptr<Node> apNode);
/**
* Setup test
* \param nearestApBeaconGeneration set BeaconGeneration attribute of the nearest AP
* \param staActiveProbe set ActiveProbing attribute of the STA
* \return node container containing all nodes
*/
NodeContainer Setup (bool nearestApBeaconGeneration, bool staActiveProbe);
Mac48Address m_associatedApBssid; ///< Associated AP's bssid
};
StaWifiMacScanningTestCase::StaWifiMacScanningTestCase ()
: TestCase ("Test case for StaWifiMac scanning capability")
{
}
StaWifiMacScanningTestCase::~StaWifiMacScanningTestCase ()
{
}
void
StaWifiMacScanningTestCase::AssocCallback (std::string context, Mac48Address bssid)
{
m_associatedApBssid = bssid;
}
void
StaWifiMacScanningTestCase::TurnBeaconGenerationOn (Ptr<Node> apNode)
{
Ptr<WifiNetDevice> netDevice = DynamicCast<WifiNetDevice> (apNode->GetDevice (0));
Ptr<ApWifiMac> mac = DynamicCast<ApWifiMac> (netDevice->GetMac ());
mac->SetAttribute ("BeaconGeneration", BooleanValue (true));
}
void
StaWifiMacScanningTestCase::TurnApOff (Ptr<Node> apNode)
{
Ptr<WifiNetDevice> netDevice = DynamicCast<WifiNetDevice> (apNode->GetDevice (0));
Ptr<WifiPhy> phy = netDevice->GetPhy ();
phy->SetOffMode();
}
NodeContainer
StaWifiMacScanningTestCase::Setup (bool nearestApBeaconGeneration, bool staActiveProbe)
{
NodeContainer apNodes;
apNodes.Create (2);
Ptr<Node> apNodeNearest = CreateObject<Node> ();
Ptr<Node> staNode = CreateObject<Node> ();
YansWifiPhyHelper phy = YansWifiPhyHelper::Default ();
YansWifiChannelHelper channel = YansWifiChannelHelper::Default ();
phy.SetChannel (channel.Create ());
WifiHelper wifi;
wifi.SetStandard (WIFI_PHY_STANDARD_80211n_2_4GHZ);
wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager");
WifiMacHelper mac;
NetDeviceContainer apDevice, apDeviceNearest;
mac.SetType ("ns3::ApWifiMac",
"BeaconGeneration", BooleanValue (true));
apDevice = wifi.Install (phy, mac, apNodes);
mac.SetType ("ns3::ApWifiMac",
"BeaconGeneration", BooleanValue (nearestApBeaconGeneration));
apDeviceNearest = wifi.Install (phy, mac, apNodeNearest);
NetDeviceContainer staDevice;
mac.SetType ("ns3::StaWifiMac",
"ActiveProbing", BooleanValue (staActiveProbe));
staDevice = wifi.Install (phy, mac, staNode);
MobilityHelper mobility;
Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
positionAlloc->Add (Vector (0.0, 0.0, 0.0)); // Furthest AP
positionAlloc->Add (Vector (10.0, 0.0, 0.0)); // Second nearest AP
positionAlloc->Add (Vector (5.0, 5.0, 0.0)); // Nearest AP
positionAlloc->Add (Vector (6.0, 5.0, 0.0)); // STA
mobility.SetPositionAllocator (positionAlloc);
mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
mobility.Install (apNodes);
mobility.Install (apNodeNearest);
mobility.Install (staNode);
Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/$ns3::StaWifiMac/Assoc", MakeCallback (&StaWifiMacScanningTestCase::AssocCallback, this));
NodeContainer allNodes = NodeContainer (apNodes, apNodeNearest, staNode);
return allNodes;
}
void
StaWifiMacScanningTestCase::DoRun (void)
{
{
NodeContainer nodes = Setup (false, false);
Ptr<Node> nearestAp = nodes.Get (2);
Mac48Address nearestApAddr = DynamicCast<WifiNetDevice> (nearestAp->GetDevice (0))->GetMac ()->GetAddress ();
Simulator::Schedule (Seconds (0.05), &StaWifiMacScanningTestCase::TurnBeaconGenerationOn, this, nearestAp);
Simulator::Stop (Seconds (0.2));
Simulator::Run ();
Simulator::Destroy ();
NS_TEST_ASSERT_MSG_EQ (m_associatedApBssid, nearestApAddr, "STA is associated to the wrong AP");
}
m_associatedApBssid = Mac48Address ();
{
NodeContainer nodes = Setup (true, true);
Ptr<Node> nearestAp = nodes.Get (2);
Mac48Address nearestApAddr = DynamicCast<WifiNetDevice> (nearestAp->GetDevice (0))->GetMac ()->GetAddress ();
Simulator::Stop (Seconds (0.2));
Simulator::Run ();
Simulator::Destroy ();
NS_TEST_ASSERT_MSG_EQ (m_associatedApBssid, nearestApAddr, "STA is associated to the wrong AP");
}
m_associatedApBssid = Mac48Address ();
{
NodeContainer nodes = Setup (true, false);
Ptr<Node> nearestAp = nodes.Get (2);
Mac48Address secondNearestApAddr = DynamicCast<WifiNetDevice> (nodes.Get (1)->GetDevice (0))->GetMac ()->GetAddress ();
Simulator::Schedule (Seconds (0.1), &StaWifiMacScanningTestCase::TurnApOff, this, nearestAp);
Simulator::Stop (Seconds (1.5));
Simulator::Run ();
Simulator::Destroy ();
NS_TEST_ASSERT_MSG_EQ (m_associatedApBssid, secondNearestApAddr, "STA is associated to the wrong AP");
}
}
/**
* \ingroup wifi-test
* \ingroup tests
@@ -1536,6 +1713,7 @@ WifiTestSuite::WifiTestSuite ()
AddTestCase (new Bug2222TestCase, TestCase::QUICK); //Bug 2222
AddTestCase (new Bug2483TestCase, TestCase::QUICK); //Bug 2483
AddTestCase (new Bug2831TestCase, TestCase::QUICK); //Bug 2831
AddTestCase (new StaWifiMacScanningTestCase, TestCase::QUICK); //Bug 2399
}
static WifiTestSuite g_wifiTestSuite; ///< the test suite