diff options
Diffstat (limited to 'emu-radio/ns3-patch/wifi/model/ap-wifi-mac.cc')
-rw-r--r-- | emu-radio/ns3-patch/wifi/model/ap-wifi-mac.cc | 876 |
1 files changed, 876 insertions, 0 deletions
diff --git a/emu-radio/ns3-patch/wifi/model/ap-wifi-mac.cc b/emu-radio/ns3-patch/wifi/model/ap-wifi-mac.cc new file mode 100644 index 00000000..696d972c --- /dev/null +++ b/emu-radio/ns3-patch/wifi/model/ap-wifi-mac.cc @@ -0,0 +1,876 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2006, 2009 INRIA + * Copyright (c) 2009 MIRKO BANCHI + * + * 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 + * + * Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr> + * Mirko Banchi <mk.banchi@gmail.com> + */ + +#include "ap-wifi-mac.h" +#include "ns3/assert.h" +#include "ns3/log.h" +#include "ns3/simulator.h" +#include "ns3/string.h" +#include "ns3/pointer.h" +#include "ns3/boolean.h" +#include "qos-tag.h" +#include "wifi-phy.h" +#include "dcf-manager.h" +#include "mac-rx-middle.h" +#include "mac-tx-middle.h" +#include "mgt-headers.h" +#include "mac-low.h" +#include "amsdu-subframe-header.h" +#include "msdu-aggregator.h" + +//added: for removing packets to old station +#include "wifi-mac-queue.h" + +namespace ns3 { + +NS_LOG_COMPONENT_DEFINE ("ApWifiMac"); + +NS_OBJECT_ENSURE_REGISTERED (ApWifiMac); + +TypeId +ApWifiMac::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::ApWifiMac") + .SetParent<RegularWifiMac> () + .SetGroupName ("Wifi") + .AddConstructor<ApWifiMac> () + .AddAttribute ("BeaconInterval", "Delay between two beacons", + TimeValue (MicroSeconds (102400)), + MakeTimeAccessor (&ApWifiMac::GetBeaconInterval, + &ApWifiMac::SetBeaconInterval), + MakeTimeChecker ()) + .AddAttribute ("BeaconJitter", "A uniform random variable to cause the initial beacon starting time (after simulation time 0) " + "to be distributed between 0 and the BeaconInterval.", + StringValue ("ns3::UniformRandomVariable"), + MakePointerAccessor (&ApWifiMac::m_beaconJitter), + MakePointerChecker<UniformRandomVariable> ()) + .AddAttribute ("EnableBeaconJitter", "If beacons are enabled, whether to jitter the initial send event.", + BooleanValue (false), + MakeBooleanAccessor (&ApWifiMac::m_enableBeaconJitter), + MakeBooleanChecker ()) + .AddAttribute ("BeaconGeneration", "Whether or not beacons are generated.", + BooleanValue (true), + MakeBooleanAccessor (&ApWifiMac::SetBeaconGeneration, + &ApWifiMac::GetBeaconGeneration), + MakeBooleanChecker ()) + ; + return tid; +} + +ApWifiMac::ApWifiMac () +{ + NS_LOG_FUNCTION (this); + m_beaconDca = CreateObject<DcaTxop> (); + m_beaconDca->SetAifsn (1); + m_beaconDca->SetMinCw (0); + m_beaconDca->SetMaxCw (0); + m_beaconDca->SetLow (m_low); + m_beaconDca->SetManager (m_dcfManager); + m_beaconDca->SetTxMiddle (m_txMiddle); + + //Let the lower layers know that we are acting as an AP. + SetTypeOfStation (AP); + + m_enableBeaconGeneration = false; +} + +ApWifiMac::~ApWifiMac () +{ + NS_LOG_FUNCTION (this); +} + +void +ApWifiMac::DoDispose () +{ + NS_LOG_FUNCTION (this); + m_beaconDca = 0; + m_enableBeaconGeneration = false; + m_beaconEvent.Cancel (); + RegularWifiMac::DoDispose (); +} + +void +ApWifiMac::SetAddress (Mac48Address address) +{ + NS_LOG_FUNCTION (this << address); + //As an AP, our MAC address is also the BSSID. Hence we are + //overriding this function and setting both in our parent class. + RegularWifiMac::SetAddress (address); + RegularWifiMac::SetBssid (address); +} + +void +ApWifiMac::SetBeaconGeneration (bool enable) +{ + NS_LOG_FUNCTION (this << enable); + if (!enable) + { + m_beaconEvent.Cancel (); + } + else if (enable && !m_enableBeaconGeneration) + { + m_beaconEvent = Simulator::ScheduleNow (&ApWifiMac::SendOneBeacon, this); + } + m_enableBeaconGeneration = enable; +} + +bool +ApWifiMac::GetBeaconGeneration (void) const +{ + NS_LOG_FUNCTION (this); + return m_enableBeaconGeneration; +} + +Time +ApWifiMac::GetBeaconInterval (void) const +{ + NS_LOG_FUNCTION (this); + return m_beaconInterval; +} + +void +ApWifiMac::SetWifiRemoteStationManager (Ptr<WifiRemoteStationManager> stationManager) +{ + NS_LOG_FUNCTION (this << stationManager); + m_beaconDca->SetWifiRemoteStationManager (stationManager); + RegularWifiMac::SetWifiRemoteStationManager (stationManager); +} + +void +ApWifiMac::SetLinkUpCallback (Callback<void> linkUp) +{ + NS_LOG_FUNCTION (this << &linkUp); + RegularWifiMac::SetLinkUpCallback (linkUp); + + //The approach taken here is that, from the point of view of an AP, + //the link is always up, so we immediately invoke the callback if + //one is set + linkUp (); +} + +void +ApWifiMac::SetBeaconInterval (Time interval) +{ + NS_LOG_FUNCTION (this << interval); + if ((interval.GetMicroSeconds () % 1024) != 0) + { + NS_LOG_WARN ("beacon interval should be multiple of 1024us (802.11 time unit), see IEEE Std. 802.11-2012"); + } + m_beaconInterval = interval; +} + +void +ApWifiMac::StartBeaconing (void) +{ + NS_LOG_FUNCTION (this); + SendOneBeacon (); +} + +int64_t +ApWifiMac::AssignStreams (int64_t stream) +{ + NS_LOG_FUNCTION (this << stream); + m_beaconJitter->SetStream (stream); + return 1; +} + +void +ApWifiMac::ForwardDown (Ptr<const Packet> packet, Mac48Address from, + Mac48Address to) +{ + NS_LOG_FUNCTION (this << packet << from << to); + //If we are not a QoS AP then we definitely want to use AC_BE to + //transmit the packet. A TID of zero will map to AC_BE (through \c + //QosUtilsMapTidToAc()), so we use that as our default here. + uint8_t tid = 0; + + //If we are a QoS AP then we attempt to get a TID for this packet + if (m_qosSupported) + { + tid = QosUtilsGetTidForPacket (packet); + //Any value greater than 7 is invalid and likely indicates that + //the packet had no QoS tag, so we revert to zero, which'll + //mean that AC_BE is used. + if (tid > 7) + { + tid = 0; + } + } + + ForwardDown (packet, from, to, tid); +} + +void +ApWifiMac::ForwardDown (Ptr<const Packet> packet, Mac48Address from, + Mac48Address to, uint8_t tid) +{ + NS_LOG_FUNCTION (this << packet << from << to << static_cast<uint32_t> (tid)); + WifiMacHeader hdr; + + //For now, an AP that supports QoS does not support non-QoS + //associations, and vice versa. In future the AP model should + //support simultaneously associated QoS and non-QoS STAs, at which + //point there will need to be per-association QoS state maintained + //by the association state machine, and consulted here. + if (m_qosSupported) + { + hdr.SetType (WIFI_MAC_QOSDATA); + hdr.SetQosAckPolicy (WifiMacHeader::NORMAL_ACK); + hdr.SetQosNoEosp (); + hdr.SetQosNoAmsdu (); + //Transmission of multiple frames in the same TXOP is not + //supported for now + hdr.SetQosTxopLimit (0); + //Fill in the QoS control field in the MAC header + hdr.SetQosTid (tid); + } + else + { + hdr.SetTypeData (); + } + + if (m_htSupported || m_vhtSupported) + { + hdr.SetNoOrder (); + } + hdr.SetAddr1 (to); + hdr.SetAddr2 (GetAddress ()); + hdr.SetAddr3 (from); + hdr.SetDsFrom (); + hdr.SetDsNotTo (); + + if (m_qosSupported) + { + //Sanity check that the TID is valid + NS_ASSERT (tid < 8); + m_edca[QosUtilsMapTidToAc (tid)]->Queue (packet, hdr); + } + else + { + m_dca->Queue (packet, hdr); + } +} + +void +ApWifiMac::Enqueue (Ptr<const Packet> packet, Mac48Address to, Mac48Address from) +{ + NS_LOG_FUNCTION (this << packet << to << from); + if (to.IsBroadcast () || m_stationManager->IsAssociated (to)) + { + ForwardDown (packet, from, to); + } +} + +void +ApWifiMac::Enqueue (Ptr<const Packet> packet, Mac48Address to) +{ + NS_LOG_FUNCTION (this << packet << to); + //We're sending this packet with a from address that is our own. We + //get that address from the lower MAC and make use of the + //from-spoofing Enqueue() method to avoid duplicated code. + Enqueue (packet, to, m_low->GetAddress ()); +} + +bool +ApWifiMac::SupportsSendFrom (void) const +{ + NS_LOG_FUNCTION (this); + return true; +} + +SupportedRates +ApWifiMac::GetSupportedRates (void) const +{ + NS_LOG_FUNCTION (this); + SupportedRates rates; + //If it is an HT-AP then add the BSSMembershipSelectorSet + //which only includes 127 for HT now. The standard says that the BSSMembershipSelectorSet + //must have its MSB set to 1 (must be treated as a Basic Rate) + //Also the standard mentioned that at leat 1 element should be included in the SupportedRates the rest can be in the ExtendedSupportedRates + if (m_htSupported || m_vhtSupported) + { + for (uint32_t i = 0; i < m_phy->GetNBssMembershipSelectors (); i++) + { + rates.SetBasicRate (m_phy->GetBssMembershipSelector (i)); + } + } + //Send the set of supported rates and make sure that we indicate + //the Basic Rate set in this set of supported rates. + for (uint32_t i = 0; i < m_phy->GetNModes (); i++) + { + WifiMode mode = m_phy->GetMode (i); + rates.AddSupportedRate (mode.GetDataRate (m_phy->GetChannelWidth (), false, 1)); + //Add rates that are part of the BSSBasicRateSet (manufacturer dependent!) + //here we choose to add the mandatory rates to the BSSBasicRateSet, + //exept for 802.11b where we assume that only the non HR-DSSS rates are part of the BSSBasicRateSet + if (mode.IsMandatory () && (mode.GetModulationClass () != WIFI_MOD_CLASS_HR_DSSS)) + { + m_stationManager->AddBasicMode (mode); + } + } + //set the basic rates + for (uint32_t j = 0; j < m_stationManager->GetNBasicModes (); j++) + { + WifiMode mode = m_stationManager->GetBasicMode (j); + rates.SetBasicRate (mode.GetDataRate (m_phy->GetChannelWidth (), false, 1)); + } + + return rates; +} + +HtCapabilities +ApWifiMac::GetHtCapabilities (void) const +{ + HtCapabilities capabilities; + capabilities.SetHtSupported (1); + if (m_htSupported) + { + capabilities.SetLdpc (m_phy->GetLdpc ()); + capabilities.SetSupportedChannelWidth (m_phy->GetChannelWidth () == 40); + capabilities.SetShortGuardInterval20 (m_phy->GetGuardInterval ()); + capabilities.SetShortGuardInterval40 (m_phy->GetChannelWidth () == 40 && m_phy->GetGuardInterval ()); + capabilities.SetGreenfield (m_phy->GetGreenfield ()); + capabilities.SetMaxAmsduLength (1); //hardcoded for now (TBD) + capabilities.SetLSigProtectionSupport (!m_phy->GetGreenfield ()); + capabilities.SetMaxAmpduLength (3); //hardcoded for now (TBD) + uint64_t maxSupportedRate = 0; //in bit/s + for (uint8_t i = 0; i < m_phy->GetNMcs (); i++) + { + WifiMode mcs = m_phy->GetMcs (i); + capabilities.SetRxMcsBitmask (mcs.GetMcsValue ()); + if (mcs.GetDataRate (m_phy->GetGuardInterval (), m_phy->GetGuardInterval (), 1) > maxSupportedRate) + { + maxSupportedRate = mcs.GetDataRate (m_phy->GetGuardInterval (), m_phy->GetGuardInterval (), 1); + } + } + capabilities.SetRxHighestSupportedDataRate (maxSupportedRate / 1e6); //in Mbit/s + capabilities.SetTxMcsSetDefined (m_phy->GetNMcs () > 0); + capabilities.SetTxMaxNSpatialStreams (m_phy->GetNumberOfTransmitAntennas ()); + } + return capabilities; +} + +VhtCapabilities +ApWifiMac::GetVhtCapabilities (void) const +{ + VhtCapabilities capabilities; + capabilities.SetVhtSupported (1); + if (m_vhtSupported) + { + if (m_phy->GetChannelWidth () == 160) + { + capabilities.SetSupportedChannelWidthSet (1); + } + else + { + capabilities.SetSupportedChannelWidthSet (0); + } + capabilities.SetMaxMpduLength (2); //hardcoded for now (TBD) + capabilities.SetRxLdpc (m_phy->GetLdpc ()); + capabilities.SetShortGuardIntervalFor80Mhz ((m_phy->GetChannelWidth () == 80) && m_phy->GetGuardInterval ()); + capabilities.SetShortGuardIntervalFor160Mhz ((m_phy->GetChannelWidth () == 160) && m_phy->GetGuardInterval ()); + capabilities.SetMaxAmpduLengthExponent (7); //hardcoded for now (TBD) + uint8_t maxMcs = 0; + for (uint8_t i = 0; i < m_phy->GetNMcs (); i++) + { + WifiMode mcs = m_phy->GetMcs (i); + if (mcs.GetMcsValue () > maxMcs) + { + maxMcs = mcs.GetMcsValue (); + } + } + capabilities.SetRxMcsMap (maxMcs, 1); //Only 1 SS is currently supported + capabilities.SetTxMcsMap (maxMcs, 1); //Only 1 SS is currently supported + } + return capabilities; +} + +void +ApWifiMac::SendProbeResp (Mac48Address to) +{ + NS_LOG_FUNCTION (this << to); + WifiMacHeader hdr; + hdr.SetProbeResp (); + hdr.SetAddr1 (to); + hdr.SetAddr2 (GetAddress ()); + hdr.SetAddr3 (GetAddress ()); + hdr.SetDsNotFrom (); + hdr.SetDsNotTo (); + Ptr<Packet> packet = Create<Packet> (); + MgtProbeResponseHeader probe; + probe.SetSsid (GetSsid ()); + probe.SetSupportedRates (GetSupportedRates ()); + probe.SetBeaconIntervalUs (m_beaconInterval.GetMicroSeconds ()); + if (m_htSupported || m_vhtSupported) + { + probe.SetHtCapabilities (GetHtCapabilities ()); + hdr.SetNoOrder (); + } + if (m_vhtSupported) + { + probe.SetVhtCapabilities (GetVhtCapabilities ()); + } + packet->AddHeader (probe); + + //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 + //use the DCF for these regardless of whether we have a QoS + //association or not. + m_dca->Queue (packet, hdr); +} + +void +ApWifiMac::SendAssocResp (Mac48Address to, bool success) +{ + NS_LOG_FUNCTION (this << to << success); + WifiMacHeader hdr; + hdr.SetAssocResp (); + hdr.SetAddr1 (to); + hdr.SetAddr2 (GetAddress ()); + hdr.SetAddr3 (GetAddress ()); + hdr.SetDsNotFrom (); + hdr.SetDsNotTo (); + Ptr<Packet> packet = Create<Packet> (); + MgtAssocResponseHeader assoc; + StatusCode code; + if (success) + { + code.SetSuccess (); + } + else + { + code.SetFailure (); + } + assoc.SetSupportedRates (GetSupportedRates ()); + assoc.SetStatusCode (code); + + if (m_htSupported || m_vhtSupported) + { + assoc.SetHtCapabilities (GetHtCapabilities ()); + hdr.SetNoOrder (); + } + if (m_vhtSupported) + { + assoc.SetVhtCapabilities (GetVhtCapabilities ()); + } + 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 + //use the DCF for these regardless of whether we have a QoS + //association or not. + m_dca->Queue (packet, hdr); +} + +void +ApWifiMac::SendOneBeacon (void) +{ + NS_LOG_FUNCTION (this); + WifiMacHeader hdr; + hdr.SetBeacon (); + hdr.SetAddr1 (Mac48Address::GetBroadcast ()); + hdr.SetAddr2 (GetAddress ()); + hdr.SetAddr3 (GetAddress ()); + hdr.SetDsNotFrom (); + hdr.SetDsNotTo (); + Ptr<Packet> packet = Create<Packet> (); + MgtBeaconHeader beacon; + beacon.SetSsid (GetSsid ()); + beacon.SetSupportedRates (GetSupportedRates ()); + beacon.SetBeaconIntervalUs (m_beaconInterval.GetMicroSeconds ()); + if (m_htSupported || m_vhtSupported) + { + beacon.SetHtCapabilities (GetHtCapabilities ()); + hdr.SetNoOrder (); + } + if (m_vhtSupported) + { + beacon.SetVhtCapabilities (GetVhtCapabilities ()); + } + packet->AddHeader (beacon); + + //The beacon has it's own special queue, so we load it in there + m_beaconDca->Queue (packet, hdr); + m_beaconEvent = Simulator::Schedule (m_beaconInterval, &ApWifiMac::SendOneBeacon, this); +} + +void +ApWifiMac::TxOk (const WifiMacHeader &hdr) +{ + NS_LOG_FUNCTION (this); + RegularWifiMac::TxOk (hdr); + + if (hdr.IsAssocResp () + && m_stationManager->IsWaitAssocTxOk (hdr.GetAddr1 ())) + { + NS_LOG_DEBUG ("associated with sta=" << hdr.GetAddr1 ()); + m_stationManager->RecordGotAssocTxOk (hdr.GetAddr1 ()); + } +} + +void +ApWifiMac::TxFailed (const WifiMacHeader &hdr) +{ + NS_LOG_FUNCTION (this); + RegularWifiMac::TxFailed (hdr); + + //modified by zeng: to avoid bugs in associaton process, transmit multiple times association response message until it is acked + if (hdr.IsAssocResp () + && m_stationManager->IsWaitAssocTxOk (hdr.GetAddr1 ())) + { + m_stationManager->ReportGotAssocTxFailed(hdr.GetAddr1 ()); + + if(m_stationManager->NeedAssocRespRetransmission(hdr.GetAddr1 ())) + { + SendAssocResp(hdr.GetAddr1 (),true);//here it is hardcoded to true for the moment + } + else + { + NS_LOG_DEBUG ("assoc failed with sta=" << hdr.GetAddr1 ()); + std::cout<<"assoc failed with sta="<<hdr.GetAddr1 ()<<"\n"; + m_stationManager->RecordGotAssocTxFailed (hdr.GetAddr1 ()); + } + + } +} + +void +ApWifiMac::Receive (Ptr<Packet> packet, const WifiMacHeader *hdr) +{ + NS_LOG_FUNCTION (this << packet << hdr); + + Mac48Address from = hdr->GetAddr2 (); + + if (hdr->IsData ()) + { + Mac48Address bssid = hdr->GetAddr1 (); + if (!hdr->IsFromDs () + && hdr->IsToDs () + && bssid == GetAddress () + && m_stationManager->IsAssociated (from)) + { + Mac48Address to = hdr->GetAddr3 (); + if (to == GetAddress ()) + { + NS_LOG_DEBUG ("frame for me from=" << from); + if (hdr->IsQosData ()) + { + if (hdr->IsQosAmsdu ()) + { + NS_LOG_DEBUG ("Received A-MSDU from=" << from << ", size=" << packet->GetSize ()); + DeaggregateAmsduAndForward (packet, hdr); + packet = 0; + } + else + { + ForwardUp (packet, from, bssid); + } + } + else + { + ForwardUp (packet, from, bssid); + } + } + else if (to.IsGroup () + || m_stationManager->IsAssociated (to)) + { + NS_LOG_DEBUG ("forwarding frame from=" << from << ", to=" << to); + Ptr<Packet> copy = packet->Copy (); + + //If the frame we are forwarding is of type QoS Data, + //then we need to preserve the UP in the QoS control + //header... + if (hdr->IsQosData ()) + { + ForwardDown (packet, from, to, hdr->GetQosTid ()); + } + else + { + ForwardDown (packet, from, to); + } + ForwardUp (copy, from, to); + } + else + { + ForwardUp (packet, from, to); + } + } + else if (hdr->IsFromDs () + && hdr->IsToDs ()) + { + //this is an AP-to-AP frame + //we ignore for now. + NotifyRxDrop (packet); + } + else + { + //we can ignore these frames since + //they are not targeted at the AP + NotifyRxDrop (packet); + } + return; + } + else if (hdr->IsMgt ()) + { + if (hdr->IsProbeReq ()) + { + NS_ASSERT (hdr->GetAddr1 ().IsBroadcast ()); + SendProbeResp (from); + return; + } + else if (hdr->GetAddr1 () == GetAddress ()) + { + if (hdr->IsAssocReq ()) + { + //first, verify that the the station's supported + //rate set is compatible with our Basic Rate set + MgtAssocRequestHeader assocReq; + packet->RemoveHeader (assocReq); + SupportedRates rates = assocReq.GetSupportedRates (); + bool problem = false; + for (uint32_t i = 0; i < m_stationManager->GetNBasicModes (); i++) + { + WifiMode mode = m_stationManager->GetBasicMode (i); + if (!rates.IsSupportedRate (mode.GetDataRate (m_phy->GetChannelWidth (), false, 1))) + { + problem = true; + break; + } + } + if (m_htSupported) + { + //check that the STA supports all MCSs in Basic MCS Set + HtCapabilities htcapabilities = assocReq.GetHtCapabilities (); + for (uint32_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 that the STA supports all MCSs in Basic MCS Set + VhtCapabilities vhtcapabilities = assocReq.GetVhtCapabilities (); + for (uint32_t i = 0; i < m_stationManager->GetNBasicMcs (); i++) + { + WifiMode mcs = m_stationManager->GetBasicMcs (i); + if (!vhtcapabilities.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 assoc + //response with an error status. + SendAssocResp (hdr->GetAddr2 (), false); + } + else + { + //station supports all rates in Basic Rate Set. + + //added+++++++++++++++ + //before moving on to accept assoication, we need to clean up the old states related to this station + //m_stationManager->RemoveStation(from); + //++++++++++++++++++++++++ +#ifdef WITH_MORE_FIX_TO_BA_IN_AP + //added: since it is a reassociation, destroy all the existing agreements immediately if exists + for(uint8_t tid=0; tid<=7;tid++) + { + + MgtDelBaHeader delbaHdr; + + delbaHdr.SetTid (tid); + + AcIndex ac = QosUtilsMapTidToAc (tid); + + //destroy aggreement with station in baMananger: + m_edca[ac]->GotDelBaFrame(&delbaHdr, hdr->GetAddr2 ()); + + //also destroy aggreement with station at mac low immediately: + m_low->DestroyBlockAckAgreement (hdr->GetAddr2 (), tid); + } +#endif + + //record all its supported modes in its associated WifiRemoteStation + for (uint32_t j = 0; j < m_phy->GetNModes (); j++) + { + WifiMode mode = m_phy->GetMode (j); + if (rates.IsSupportedRate (mode.GetDataRate (m_phy->GetChannelWidth (), false, 1))) + { + m_stationManager->AddSupportedMode (from, mode); + } + } + if (m_htSupported) + { + HtCapabilities htcapabilities = assocReq.GetHtCapabilities (); + m_stationManager->AddStationHtCapabilities (from,htcapabilities); + for (uint32_t j = 0; j < m_phy->GetNMcs (); j++) + { + WifiMode mcs = m_phy->GetMcs (j); + if (mcs.GetModulationClass () == WIFI_MOD_CLASS_HT && htcapabilities.IsSupportedMcs (mcs.GetMcsValue ())) + { + m_stationManager->AddSupportedMcs (from, mcs); + } + } + } + if (m_vhtSupported) + { + VhtCapabilities vhtCapabilities = assocReq.GetVhtCapabilities (); + m_stationManager->AddStationVhtCapabilities (from, vhtCapabilities); + for (uint32_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 + } + } + } + m_stationManager->RecordWaitAssocTxOk (from); + // send assoc response with success status. + SendAssocResp (hdr->GetAddr2 (), true); + } + return; + } + else if (hdr->IsDisassociation ()) + { + //deestroy aggreements and clean up packets to the station: + //destroy all block ack agreement with old AP (by pretending to receive a delba frame from AP). + //clean up packets for the old AP in the meanwhile + for(uint8_t tid=0; tid<=7;tid++) + { + MgtDelBaHeader delbaHdr; + delbaHdr.SetTid (tid); + AcIndex ac = QosUtilsMapTidToAc (tid); + m_edca[ac]->GotDelBaFrame(&delbaHdr, from); +// //also destroy aggreement at mac low immediately: + m_low->DestroyBlockAckAgreement (from, tid); + + WifiMacHeader dequeuedHdr; + + //for edca: + Ptr<WifiMacQueue > edcaQueue=m_edca[ac]->GetEdcaQueue (); + + Ptr<const Packet> dequeuedPacket = edcaQueue->DequeueByTidAndAddress (&dequeuedHdr, tid, + WifiMacHeader::ADDR1, + from); + // int count=0; + while (dequeuedPacket != 0) + { + // count++; + dequeuedPacket = edcaQueue->DequeueByTidAndAddress (&dequeuedHdr, tid, + WifiMacHeader::ADDR1, + from); + } + + // if(count!=0) + // std::cout<<"No. of packets for old AP is "<<count<<"\n"; + + // count=0; + //for dca + Ptr<WifiMacQueue > dcaQueue=m_dca->GetQueue (); + dequeuedPacket = dcaQueue->DequeueByTidAndAddress (&dequeuedHdr, tid, + WifiMacHeader::ADDR1, + from); + + while (dequeuedPacket != 0) + { +// count++; + dequeuedPacket = dcaQueue->DequeueByTidAndAddress (&dequeuedHdr, tid, + WifiMacHeader::ADDR1, + from); + } +// if(count!=0) +// std::cout<<"No. of packets in dca for old AP is "<<count<<"\n"; + + } + m_stationManager->RecordDisassociated (from); + return; + } + } + } + + //Invoke the receive handler of our parent class to deal with any + //other frames. Specifically, this will handle Block Ack-related + //Management Action frames. + RegularWifiMac::Receive (packet, hdr); +} + +void +ApWifiMac::DeaggregateAmsduAndForward (Ptr<Packet> aggregatedPacket, + const WifiMacHeader *hdr) +{ + NS_LOG_FUNCTION (this << aggregatedPacket << hdr); + MsduAggregator::DeaggregatedMsdus packets = + MsduAggregator::Deaggregate (aggregatedPacket); + + for (MsduAggregator::DeaggregatedMsdusCI i = packets.begin (); + i != packets.end (); ++i) + { + if ((*i).second.GetDestinationAddr () == GetAddress ()) + { + ForwardUp ((*i).first, (*i).second.GetSourceAddr (), + (*i).second.GetDestinationAddr ()); + } + else + { + Mac48Address from = (*i).second.GetSourceAddr (); + Mac48Address to = (*i).second.GetDestinationAddr (); + NS_LOG_DEBUG ("forwarding QoS frame from=" << from << ", to=" << to); + ForwardDown ((*i).first, from, to, hdr->GetQosTid ()); + } + } +} + +void +ApWifiMac::DoInitialize (void) +{ + NS_LOG_FUNCTION (this); + m_beaconDca->Initialize (); + m_beaconEvent.Cancel (); + if (m_enableBeaconGeneration) + { + if (m_enableBeaconJitter) + { + int64_t jitter = m_beaconJitter->GetValue (0, m_beaconInterval.GetMicroSeconds ()); + NS_LOG_DEBUG ("Scheduling initial beacon for access point " << GetAddress () << " at time " << jitter << " microseconds"); + m_beaconEvent = Simulator::Schedule (MicroSeconds (jitter), &ApWifiMac::SendOneBeacon, this); + } + else + { + NS_LOG_DEBUG ("Scheduling initial beacon for access point " << GetAddress () << " at time 0"); + m_beaconEvent = Simulator::ScheduleNow (&ApWifiMac::SendOneBeacon, this); + } + } + RegularWifiMac::DoInitialize (); +} + +} //namespace ns3 |