diff --git a/src/devices/wifi/mac-high-nqsta.cc b/src/devices/wifi/mac-high-nqsta.cc new file mode 100644 index 000000000..5720786e0 --- /dev/null +++ b/src/devices/wifi/mac-high-nqsta.cc @@ -0,0 +1,380 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2005,2006 INRIA + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Mathieu Lacage + */ + +#include "ns3/packet.h" +#include "ns3/simulator.h" +#include "ns3/watchdog.h" +#include "ns3/assert.h" + +#include "mac-high-nqsta.h" +#include "wifi-mac-header.h" +#include "wifi-net-device.h" +#include "mgt-headers.h" +#include "wifi-phy.h" +#include "dca-txop.h" + +#define noNQSTA_DEBUG 1 + +#ifdef NQSTA_DEBUG +#include +# define TRACE(x) \ + std::cout << "NQSTA now=" << Simulator::Now () << " " << x << std::endl; +#else +# define TRACE(x) +#endif + +/* + * The state machine for this NQSTA is: + -------------- ----------- + | Associated | <-------------------- -------> | Refused | + -------------- \ / ----------- + \ \ / + \ ----------------- ----------------------------- + \-> | Beacon Missed | --> | Wait Association Response | + ----------------- ----------------------------- + \ ^ + \ | + \ ----------------------- + \-> | Wait Probe Response | + ----------------------- + */ + + +namespace ns3 { + +MacHighNqsta::MacHighNqsta () + : m_state (BEACON_MISSED), + m_probeRequestTimeout (Seconds (0.5)), + m_assocRequestTimeout (Seconds (0.5)), + m_probeRequestEvent (), + m_assocRequestEvent (), + m_beaconWatchdog (new Watchdog ()) +{ + m_beaconWatchdog->SetFunction (&MacHighNqsta::MissedBeacons, this); + // this is the default value for the number of beacons missed + // before attempting to reassociate. + m_maxMissedBeacons = 10; +} + +MacHighNqsta::~MacHighNqsta () +{} + +void +MacHighNqsta::SetSupportedRates (SupportedRates rates) +{ + m_rates = rates; +} +void +MacHighNqsta::SetDcaTxop (DcaTxop *dca) +{ + m_dca = dca; +} +void +MacHighNqsta::SetInterface (WifiNetDevice *interface) +{ + m_interface = interface; +} +void +MacHighNqsta::SetForwardCallback (ForwardCallback callback) +{ + m_forward = callback; +} +void +MacHighNqsta::SetAssociatedCallback (AssociatedCallback callback) +{ + m_associatedCallback = callback; +} +void +MacHighNqsta::SetDisAssociatedCallback (DisAssociatedCallback callback) +{ + m_disAssociatedCallback = callback; +} +void +MacHighNqsta::SetMaxMissedBeacons (uint32_t missed) +{ + m_maxMissedBeacons = missed; +} +void +MacHighNqsta::SetProbeRequestTimeout (Time timeout) +{ + m_probeRequestTimeout = timeout; +} +void +MacHighNqsta::SetAssocRequestTimeout (Time timeout) +{ + m_assocRequestTimeout = timeout; +} + +Mac48Address +MacHighNqsta::GetBssid (void) const +{ + return m_bssid; +} +void +MacHighNqsta::SetBssid (Mac48Address bssid) +{ + m_bssid = bssid; + +} +void +MacHighNqsta::StartActiveAssociation (void) +{ + TryToEnsureAssociated (); +} + +Mac48Address +MacHighNqsta::GetBroadcastBssid (void) +{ + return Mac48Address::GetBroadcast (); +} +SupportedRates +MacHighNqsta::GetSupportedRates (void) +{ + return m_rates; +} + +void +MacHighNqsta::SendProbeRequest (void) +{ + TRACE ("send probe request"); + WifiMacHeader hdr; + hdr.SetProbeReq (); + hdr.SetAddr1 (GetBroadcastBssid ()); + hdr.SetAddr2 (m_interface->GetSelfAddress ()); + hdr.SetAddr3 (GetBroadcastBssid ()); + hdr.SetDsNotFrom (); + hdr.SetDsNotTo (); + Packet packet; + MgtProbeRequestHeader probe; + probe.SetSsid (m_interface->GetSsid ()); + SupportedRates rates = GetSupportedRates (); + probe.SetSupportedRates (rates); + packet.AddHeader (probe); + + m_dca->Queue (packet, hdr); + + m_probeRequestEvent = Simulator::Schedule (m_probeRequestTimeout, + &MacHighNqsta::ProbeRequestTimeout, this); +} + +void +MacHighNqsta::SendAssociationRequest () +{ + TRACE ("send assoc request"); + WifiMacHeader hdr; + hdr.SetAssocReq (); + hdr.SetAddr1 (GetBssid ()); + hdr.SetAddr2 (m_interface->GetSelfAddress ()); + hdr.SetAddr3 (GetBssid ()); + hdr.SetDsNotFrom (); + hdr.SetDsNotTo (); + Packet packet; + MgtAssocRequestHeader assoc; + assoc.SetSsid (m_interface->GetSsid ()); + SupportedRates rates = GetSupportedRates (); + assoc.SetSupportedRates (rates); + packet.AddHeader (assoc); + + m_dca->Queue (packet, hdr); + + m_assocRequestEvent = Simulator::Schedule (m_assocRequestTimeout, + &MacHighNqsta::AssocRequestTimeout, this); +} +void +MacHighNqsta::TryToEnsureAssociated (void) +{ + switch (m_state) { + case ASSOCIATED: + return; + break; + case WAIT_PROBE_RESP: + /* we have sent a probe request earlier so we + do not need to re-send a probe request immediately. + We just need to wait until probe-request-timeout + or until we get a probe response + */ + break; + case BEACON_MISSED: + /* 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. + */ + m_disAssociatedCallback (); + m_state = WAIT_PROBE_RESP; + SendProbeRequest (); + break; + case WAIT_ASSOC_RESP: + /* we have sent an assoc request so we do not need to + re-send an assoc request right now. We just need to + wait until either assoc-request-timeout or until + we get an assoc response. + */ + break; + case REFUSED: + /* we have sent an assoc request and received a negative + assoc resp. We wait until someone restarts an + association with a given ssid. + */ + break; + } +} + +void +MacHighNqsta::AssocRequestTimeout (void) +{ + TRACE ("assoc request timeout"); + m_state = WAIT_ASSOC_RESP; + SendAssociationRequest (); +} +void +MacHighNqsta::ProbeRequestTimeout (void) +{ + TRACE ("probe request timeout"); + m_state = WAIT_PROBE_RESP; + SendProbeRequest (); +} +void +MacHighNqsta::MissedBeacons (void) +{ + m_state = BEACON_MISSED; +} +bool +MacHighNqsta::IsAssociated (void) +{ + return (m_state == ASSOCIATED)?true:false; +} + +void +MacHighNqsta::Queue (Packet packet, Mac48Address to) +{ + if (!IsAssociated ()) + { + TryToEnsureAssociated (); + return; + } + //TRACE ("enqueue size="< + */ +#ifndef MAC_HIGH_NQSTA_H +#define MAC_HIGH_NQSTA_H + +#include + +#include "ns3/mac48-address.h" +#include "ns3/callback.h" +#include "ns3/event-id.h" +#include "ns3/packet.h" +#include "ns3/nstime.h" + +#include "supported-rates.h" + +namespace ns3 { + +class WifiMacHeader; +class WifiNetDevice; +class DcaTxop; +class Watchdog; + +class MacHighNqsta { +public: + typedef Callback ForwardCallback; + typedef Callback AssociatedCallback; + typedef Callback DisAssociatedCallback; + + MacHighNqsta (); + ~MacHighNqsta (); + + void SetDcaTxop (DcaTxop *dca); + void SetInterface (WifiNetDevice *interface); + void SetForwardCallback (ForwardCallback callback); + void SetAssociatedCallback (AssociatedCallback callback); + void SetDisAssociatedCallback (DisAssociatedCallback callback); + void SetSupportedRates (SupportedRates rates); + + void SetMaxMissedBeacons (uint32_t missed); + void SetProbeRequestTimeout (Time timeout); + void SetAssocRequestTimeout (Time timeout); + + Mac48Address GetBssid (void) const; + + void StartActiveAssociation (void); + + void Queue (Packet packet, Mac48Address to); + + void Receive (Packet packet, WifiMacHeader const *hdr); +private: + void SetBssid (Mac48Address bssid); + Mac48Address GetBroadcastBssid (void); + void SendProbeRequest (void); + void SendAssociationRequest (); + void TryToEnsureAssociated (void); + void AssocRequestTimeout (void); + void ProbeRequestTimeout (void); + bool IsAssociated (void); + SupportedRates GetSupportedRates (void); + void MissedBeacons (void); + enum { + ASSOCIATED, + WAIT_PROBE_RESP, + WAIT_ASSOC_RESP, + BEACON_MISSED, + REFUSED + } m_state; + Time m_probeRequestTimeout; + Time m_assocRequestTimeout; + EventId m_probeRequestEvent; + EventId m_assocRequestEvent; + WifiNetDevice *m_interface; + ForwardCallback m_forward; + AssociatedCallback m_associatedCallback; + DisAssociatedCallback m_disAssociatedCallback; + SupportedRates m_rates; + DcaTxop *m_dca; + Watchdog *m_beaconWatchdog; + Mac48Address m_bssid; + uint32_t m_maxMissedBeacons; +}; + +} // namespace ns3 + + +#endif /* MAC_HIGH_NQSTA_H */ diff --git a/src/devices/wifi/wscript b/src/devices/wifi/wscript index 138e9f2b1..4cb380b2c 100644 --- a/src/devices/wifi/wscript +++ b/src/devices/wifi/wscript @@ -29,6 +29,7 @@ def build(bld): 'status-code.cc', 'mgt-headers.cc', 'mac-high-nqap.cc', + 'mac-high-nqsta.cc', ] headers = bld.create_obj('ns3header') headers.source = [