/* -*- 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 * Mirko Banchi */ #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 () .SetGroupName ("Wifi") .AddConstructor () .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 ()) .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 (); 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 stationManager) { NS_LOG_FUNCTION (this << stationManager); m_beaconDca->SetWifiRemoteStationManager (stationManager); RegularWifiMac::SetWifiRemoteStationManager (stationManager); } void ApWifiMac::SetLinkUpCallback (Callback 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 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 packet, Mac48Address from, Mac48Address to, uint8_t tid) { NS_LOG_FUNCTION (this << packet << from << to << static_cast (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 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 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 = Create (); 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 = Create (); 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 = Create (); 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="<RecordGotAssocTxFailed (hdr.GetAddr1 ()); } } } void ApWifiMac::Receive (Ptr 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 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 edcaQueue=m_edca[ac]->GetEdcaQueue (); Ptr 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 "< 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 "<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 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