diff options
Diffstat (limited to 'emu-radio/ns3-patch/wifi/model/wifi-remote-station-manager.cc')
-rw-r--r-- | emu-radio/ns3-patch/wifi/model/wifi-remote-station-manager.cc | 1751 |
1 files changed, 1751 insertions, 0 deletions
diff --git a/emu-radio/ns3-patch/wifi/model/wifi-remote-station-manager.cc b/emu-radio/ns3-patch/wifi/model/wifi-remote-station-manager.cc new file mode 100644 index 00000000..d1b6f016 --- /dev/null +++ b/emu-radio/ns3-patch/wifi/model/wifi-remote-station-manager.cc @@ -0,0 +1,1751 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2005,2006,2007 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 <mathieu.lacage@sophia.inria.fr> + */ + +#include <iostream> +#include "wifi-remote-station-manager.h" +#include "ns3/simulator.h" +#include "ns3/assert.h" +#include "ns3/log.h" +#include "ns3/tag.h" +#include "ns3/boolean.h" +#include "ns3/double.h" +#include "ns3/uinteger.h" +#include "ns3/wifi-phy.h" +#include "ns3/wifi-mac.h" +#include "ns3/trace-source-accessor.h" +#include "wifi-mac-header.h" +#include "wifi-mac-trailer.h" + +/*************************************************************** + * Packet Mode Tagger + ***************************************************************/ + +namespace ns3 { + +NS_LOG_COMPONENT_DEFINE ("WifiRemoteStationManager"); + +class HighLatencyDataTxVectorTag : public Tag +{ +public: + HighLatencyDataTxVectorTag (); + HighLatencyDataTxVectorTag (WifiTxVector dataTxVector); + /** + * \returns the transmission mode to use to send this packet + */ + WifiTxVector GetDataTxVector (void) const; + + static TypeId GetTypeId (void); + virtual TypeId GetInstanceTypeId (void) const; + virtual uint32_t GetSerializedSize (void) const; + virtual void Serialize (TagBuffer i) const; + virtual void Deserialize (TagBuffer i); + virtual void Print (std::ostream &os) const; +private: + WifiTxVector m_dataTxVector; +}; + +HighLatencyDataTxVectorTag::HighLatencyDataTxVectorTag () +{ +} + +HighLatencyDataTxVectorTag::HighLatencyDataTxVectorTag (WifiTxVector dataTxVector) + : m_dataTxVector (dataTxVector) +{ +} + +WifiTxVector +HighLatencyDataTxVectorTag::GetDataTxVector (void) const +{ + return m_dataTxVector; +} + +TypeId +HighLatencyDataTxVectorTag::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::HighLatencyDataTxVectorTag") + .SetParent<Tag> () + .SetGroupName ("Wifi") + .AddConstructor<HighLatencyDataTxVectorTag> () + ; + return tid; +} + +TypeId +HighLatencyDataTxVectorTag::GetInstanceTypeId (void) const +{ + return GetTypeId (); +} + +uint32_t +HighLatencyDataTxVectorTag::GetSerializedSize (void) const +{ + return sizeof (WifiTxVector); +} + +void +HighLatencyDataTxVectorTag::Serialize (TagBuffer i) const +{ + i.Write ((uint8_t *)&m_dataTxVector, sizeof (WifiTxVector)); +} + +void +HighLatencyDataTxVectorTag::Deserialize (TagBuffer i) +{ + i.Read ((uint8_t *)&m_dataTxVector, sizeof (WifiTxVector)); +} + +void +HighLatencyDataTxVectorTag::Print (std::ostream &os) const +{ + os << "Data=" << m_dataTxVector; +} + +class HighLatencyRtsTxVectorTag : public Tag +{ +public: + HighLatencyRtsTxVectorTag (); + HighLatencyRtsTxVectorTag (WifiTxVector rtsTxVector); + /** + * \returns the transmission mode to use to send the RTS prior to the + * transmission of the data packet itself. + */ + WifiTxVector GetRtsTxVector (void) const; + + static TypeId GetTypeId (void); + virtual TypeId GetInstanceTypeId (void) const; + virtual uint32_t GetSerializedSize (void) const; + virtual void Serialize (TagBuffer i) const; + virtual void Deserialize (TagBuffer i); + virtual void Print (std::ostream &os) const; +private: + WifiTxVector m_rtsTxVector; +}; + +HighLatencyRtsTxVectorTag::HighLatencyRtsTxVectorTag () +{ +} + +HighLatencyRtsTxVectorTag::HighLatencyRtsTxVectorTag (WifiTxVector rtsTxVector) + : m_rtsTxVector (rtsTxVector) +{ +} + +WifiTxVector +HighLatencyRtsTxVectorTag::GetRtsTxVector (void) const +{ + return m_rtsTxVector; +} + +TypeId +HighLatencyRtsTxVectorTag::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::HighLatencyRtsTxVectorTag") + .SetParent<Tag> () + .SetGroupName ("Wifi") + .AddConstructor<HighLatencyRtsTxVectorTag> () + ; + return tid; +} + +TypeId +HighLatencyRtsTxVectorTag::GetInstanceTypeId (void) const +{ + return GetTypeId (); +} + +uint32_t +HighLatencyRtsTxVectorTag::GetSerializedSize (void) const +{ + return sizeof (WifiTxVector); +} + +void +HighLatencyRtsTxVectorTag::Serialize (TagBuffer i) const +{ + i.Write ((uint8_t *)&m_rtsTxVector, sizeof (WifiTxVector)); +} + +void +HighLatencyRtsTxVectorTag::Deserialize (TagBuffer i) +{ + i.Read ((uint8_t *)&m_rtsTxVector, sizeof (WifiTxVector)); +} + +void +HighLatencyRtsTxVectorTag::Print (std::ostream &os) const +{ + os << "Rts=" << m_rtsTxVector; +} + +class HighLatencyCtsToSelfTxVectorTag : public Tag +{ +public: + HighLatencyCtsToSelfTxVectorTag (); + HighLatencyCtsToSelfTxVectorTag (WifiTxVector ctsToSelfTxVector); + /** + * \returns the transmission mode to use for the CTS-to-self. + */ + WifiTxVector GetCtsToSelfTxVector (void) const; + + static TypeId GetTypeId (void); + virtual TypeId GetInstanceTypeId (void) const; + virtual uint32_t GetSerializedSize (void) const; + virtual void Serialize (TagBuffer i) const; + virtual void Deserialize (TagBuffer i); + virtual void Print (std::ostream &os) const; +private: + WifiTxVector m_ctsToSelfTxVector; +}; + +HighLatencyCtsToSelfTxVectorTag::HighLatencyCtsToSelfTxVectorTag () +{ +} + +HighLatencyCtsToSelfTxVectorTag::HighLatencyCtsToSelfTxVectorTag (WifiTxVector ctsToSelfTxVector) + : m_ctsToSelfTxVector (ctsToSelfTxVector) +{ +} + +WifiTxVector +HighLatencyCtsToSelfTxVectorTag::GetCtsToSelfTxVector (void) const +{ + return m_ctsToSelfTxVector; +} + +TypeId +HighLatencyCtsToSelfTxVectorTag::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::HighLatencyCtsToSelfTxVectorTag") + .SetParent<Tag> () + .SetGroupName ("Wifi") + .AddConstructor<HighLatencyCtsToSelfTxVectorTag> () + ; + return tid; +} + +TypeId +HighLatencyCtsToSelfTxVectorTag::GetInstanceTypeId (void) const +{ + return GetTypeId (); +} + +uint32_t +HighLatencyCtsToSelfTxVectorTag::GetSerializedSize (void) const +{ + return sizeof (WifiTxVector); +} + +void +HighLatencyCtsToSelfTxVectorTag::Serialize (TagBuffer i) const +{ + i.Write ((uint8_t *)&m_ctsToSelfTxVector, sizeof (WifiTxVector)); +} + +void +HighLatencyCtsToSelfTxVectorTag::Deserialize (TagBuffer i) +{ + i.Read ((uint8_t *)&m_ctsToSelfTxVector, sizeof (WifiTxVector)); +} + +void +HighLatencyCtsToSelfTxVectorTag::Print (std::ostream &os) const +{ + os << "Cts To Self=" << m_ctsToSelfTxVector; +} + +} //namespace ns3 + +namespace ns3 { + +NS_OBJECT_ENSURE_REGISTERED (WifiRemoteStationManager); + +TypeId +WifiRemoteStationManager::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::WifiRemoteStationManager") + .SetParent<Object> () + .SetGroupName ("Wifi") + .AddAttribute ("IsLowLatency", "If true, we attempt to modelize a so-called low-latency device: a device" + " where decisions about tx parameters can be made on a per-packet basis and feedback about the" + " transmission of each packet is obtained before sending the next. Otherwise, we modelize a " + " high-latency device, that is a device where we cannot update our decision about tx parameters" + " after every packet transmission.", + BooleanValue (true), //this value is ignored because there is no setter + MakeBooleanAccessor (&WifiRemoteStationManager::IsLowLatency), + MakeBooleanChecker ()) + .AddAttribute ("MaxSsrc", "The maximum number of retransmission attempts for an RTS. This value" + " will not have any effect on some rate control algorithms.", + UintegerValue (7), + MakeUintegerAccessor (&WifiRemoteStationManager::m_maxSsrc), + MakeUintegerChecker<uint32_t> ()) + .AddAttribute ("MaxSlrc", "The maximum number of retransmission attempts for a DATA packet. This value" + " will not have any effect on some rate control algorithms.", + UintegerValue (7), + MakeUintegerAccessor (&WifiRemoteStationManager::m_maxSlrc), + MakeUintegerChecker<uint32_t> ()) + .AddAttribute ("RtsCtsThreshold", "If the size of the data packet + LLC header + MAC header + FCS trailer is bigger than " + "this value, we use an RTS/CTS handshake before sending the data, as per IEEE Std. 802.11-2012, Section 9.3.5. " + "This value will not have any effect on some rate control algorithms.", + UintegerValue (2346), + MakeUintegerAccessor (&WifiRemoteStationManager::m_rtsCtsThreshold), + MakeUintegerChecker<uint32_t> ()) + .AddAttribute ("FragmentationThreshold", "If the size of the data packet + LLC header + MAC header + FCS trailer is bigger" + "than this value, we fragment it such that the size of the fragments are equal or smaller " + "than this value, as per IEEE Std. 802.11-2012, Section 9.5. " + "This value will not have any effect on some rate control algorithms.", + UintegerValue (2346), + MakeUintegerAccessor (&WifiRemoteStationManager::DoSetFragmentationThreshold, + &WifiRemoteStationManager::DoGetFragmentationThreshold), + MakeUintegerChecker<uint32_t> ()) + .AddAttribute ("NonUnicastMode", "Wifi mode used for non-unicast transmissions.", + WifiModeValue (), + MakeWifiModeAccessor (&WifiRemoteStationManager::m_nonUnicastMode), + MakeWifiModeChecker ()) + .AddAttribute ("DefaultTxPowerLevel", "Default power level to be used for transmissions. " + "This is the power level that is used by all those WifiManagers that do not" + "implement TX power control.", + UintegerValue (0), + MakeUintegerAccessor (&WifiRemoteStationManager::m_defaultTxPowerLevel), + MakeUintegerChecker<uint8_t> ()) + .AddTraceSource ("MacTxRtsFailed", + "The transmission of a RTS by the MAC layer has failed", + MakeTraceSourceAccessor (&WifiRemoteStationManager::m_macTxRtsFailed), + "ns3::Mac48Address::TracedCallback") + .AddTraceSource ("MacTxDataFailed", + "The transmission of a data packet by the MAC layer has failed", + MakeTraceSourceAccessor (&WifiRemoteStationManager::m_macTxDataFailed), + "ns3::Mac48Address::TracedCallback") + .AddTraceSource ("MacTxFinalRtsFailed", + "The transmission of a RTS has exceeded the maximum number of attempts", + MakeTraceSourceAccessor (&WifiRemoteStationManager::m_macTxFinalRtsFailed), + "ns3::Mac48Address::TracedCallback") + .AddTraceSource ("MacTxFinalDataFailed", + "The transmission of a data packet has exceeded the maximum number of attempts", + MakeTraceSourceAccessor (&WifiRemoteStationManager::m_macTxFinalDataFailed), + "ns3::Mac48Address::TracedCallback") + ; + return tid; +} + +WifiRemoteStationManager::WifiRemoteStationManager () + : m_htSupported (false), + m_vhtSupported (false) +{ +} + +WifiRemoteStationManager::~WifiRemoteStationManager () +{ +} + +void +WifiRemoteStationManager::DoDispose (void) +{ + for (StationStates::const_iterator i = m_states.begin (); i != m_states.end (); i++) + { + delete (*i); + } + m_states.clear (); + for (Stations::const_iterator i = m_stations.begin (); i != m_stations.end (); i++) + { + delete (*i); + } + m_stations.clear (); +} + +void +WifiRemoteStationManager::SetupPhy (Ptr<WifiPhy> phy) +{ + //We need to track our PHY because it is the object that knows the + //full set of transmit rates that are supported. We need to know + //this in order to find the relevant mandatory rates when chosing a + //transmit rate for automatic control responses like + //acknowledgements. + m_wifiPhy = phy; + m_defaultTxMode = phy->GetMode (0); + if (HasHtSupported () || HasVhtSupported ()) + { + m_defaultTxMcs = phy->GetMcs (0); + } + Reset (); +} + +void +WifiRemoteStationManager::SetupMac (Ptr<WifiMac> mac) +{ + //We need to track our MAC because it is the object that knows the + //full set of interframe spaces. + m_wifiMac = mac; + Reset (); +} + +void +WifiRemoteStationManager::SetHtSupported (bool enable) +{ + m_htSupported = enable; +} + +void +WifiRemoteStationManager::SetMaxSsrc (uint32_t maxSsrc) +{ + m_maxSsrc = maxSsrc; +} + +void +WifiRemoteStationManager::SetMaxSlrc (uint32_t maxSlrc) +{ + m_maxSlrc = maxSlrc; +} + +void +WifiRemoteStationManager::SetRtsCtsThreshold (uint32_t threshold) +{ + m_rtsCtsThreshold = threshold; +} + +void +WifiRemoteStationManager::SetFragmentationThreshold (uint32_t threshold) +{ + DoSetFragmentationThreshold (threshold); +} + +bool +WifiRemoteStationManager::HasHtSupported (void) const +{ + return m_htSupported; +} + +void +WifiRemoteStationManager::SetVhtSupported (bool enable) +{ + m_vhtSupported = enable; +} + +bool +WifiRemoteStationManager::HasVhtSupported (void) const +{ + return m_vhtSupported; +} + +uint32_t +WifiRemoteStationManager::GetMaxSsrc (void) const +{ + return m_maxSsrc; +} + +uint32_t +WifiRemoteStationManager::GetMaxSlrc (void) const +{ + return m_maxSlrc; +} + +uint32_t +WifiRemoteStationManager::GetRtsCtsThreshold (void) const +{ + return m_rtsCtsThreshold; +} + +uint32_t +WifiRemoteStationManager::GetFragmentationThreshold (void) const +{ + return DoGetFragmentationThreshold (); +} + +void +WifiRemoteStationManager::Reset (Mac48Address address) +{ + NS_LOG_FUNCTION (this << address); + NS_ASSERT (!address.IsGroup ()); + WifiRemoteStationState *state = LookupState (address); + state->m_operationalRateSet.clear (); + state->m_operationalMcsSet.clear (); + AddSupportedMode (address, GetDefaultMode ()); + AddSupportedMcs (address, GetDefaultMcs ()); +} + +void +WifiRemoteStationManager::AddSupportedMode (Mac48Address address, WifiMode mode) +{ + NS_LOG_FUNCTION (this << address << mode); + NS_ASSERT (!address.IsGroup ()); + WifiRemoteStationState *state = LookupState (address); + for (WifiModeListIterator i = state->m_operationalRateSet.begin (); i != state->m_operationalRateSet.end (); i++) + { + if ((*i) == mode) + { + //already in. + return; + } + } + state->m_operationalRateSet.push_back (mode); +} + +void +WifiRemoteStationManager::AddAllSupportedModes (Mac48Address address) +{ + NS_ASSERT (!address.IsGroup ()); + WifiRemoteStationState *state = LookupState (address); + state->m_operationalRateSet.clear (); + for (uint32_t i = 0; i < m_wifiPhy->GetNModes (); i++) + { + state->m_operationalRateSet.push_back (m_wifiPhy->GetMode (i)); + } +} + +void +WifiRemoteStationManager::AddSupportedMcs (Mac48Address address, WifiMode mcs) +{ + NS_LOG_FUNCTION (this << address << mcs); + NS_ASSERT (!address.IsGroup ()); + WifiRemoteStationState *state = LookupState (address); + for (WifiModeListIterator i = state->m_operationalMcsSet.begin (); i != state->m_operationalMcsSet.end (); i++) + { + if ((*i) == mcs) + { + //already in. + return; + } + } + state->m_operationalMcsSet.push_back (mcs); +} + +bool +WifiRemoteStationManager::IsBrandNew (Mac48Address address) const +{ + if (address.IsGroup ()) + { + return false; + } + return LookupState (address)->m_state == WifiRemoteStationState::BRAND_NEW; +} + +std::vector<Mac48Address> +WifiRemoteStationManager::GetRemoteAddresses() const +{ + std::vector<Mac48Address> remoteAddresses; + + + if( m_wifiMac->GetBssid() == m_wifiMac->GetAddress() )// as an AP + { + for (StationStates::const_iterator i = m_states.begin (); i != m_states.end (); i++) + { + if ((*i)->m_state == WifiRemoteStationState::GOT_ASSOC_TX_OK)// the station is associated + { + NS_LOG_DEBUG ("WifiRemoteStationManager::LookupState returning existing state"); + remoteAddresses.push_back((*i)->m_address); + } + } + return remoteAddresses; + + } + else + { + remoteAddresses.push_back(m_wifiMac->GetBssid()); + return remoteAddresses; + } +} + +bool +WifiRemoteStationManager::IsAssociated (Mac48Address address) const +{ + if (address.IsGroup ()) + { + return true; + } + return LookupState (address)->m_state == WifiRemoteStationState::GOT_ASSOC_TX_OK; +} + +bool +WifiRemoteStationManager::IsWaitAssocTxOk (Mac48Address address) const +{ + if (address.IsGroup ()) + { + return false; + } + return LookupState (address)->m_state == WifiRemoteStationState::WAIT_ASSOC_TX_OK; +} + +void +WifiRemoteStationManager::RecordWaitAssocTxOk (Mac48Address address) +{ + NS_ASSERT (!address.IsGroup ()); + LookupState (address)->m_state = WifiRemoteStationState::WAIT_ASSOC_TX_OK; + //added by zeng: to avoid bugs in association process + LookupState (address)->m_assocRespTxRetryCount=0; + //end +} +//added by zeng++++++++++++++ +void +WifiRemoteStationManager::ReportGotAssocTxFailed (Mac48Address address) +{ + NS_ASSERT (!address.IsGroup ()); + NS_LOG_DEBUG("association response not acked,retry="<<LookupState (address)->m_assocRespTxRetryCount); + LookupState (address)->m_assocRespTxRetryCount++; +} + +bool +WifiRemoteStationManager::NeedAssocRespRetransmission(Mac48Address address) +{ + return LookupState (address)->m_assocRespTxRetryCount < 3; +} +//end++++++++++++++++++ +void +WifiRemoteStationManager::RecordGotAssocTxOk (Mac48Address address) +{ + NS_ASSERT (!address.IsGroup ()); + LookupState (address)->m_state = WifiRemoteStationState::GOT_ASSOC_TX_OK; + //added by zeng: to avoid bugs in association process + LookupState (address)->m_assocRespTxRetryCount=0; + //end +} + +void +WifiRemoteStationManager::RecordGotAssocTxFailed (Mac48Address address) +{ + NS_ASSERT (!address.IsGroup ()); + LookupState (address)->m_state = WifiRemoteStationState::DISASSOC; + //added by zeng: to avoid bugs in association process + LookupState (address)->m_assocRespTxRetryCount=0; + //end +} + +void +WifiRemoteStationManager::RecordDisassociated (Mac48Address address) +{ + NS_ASSERT (!address.IsGroup ()); + LookupState (address)->m_state = WifiRemoteStationState::DISASSOC; +} + +void +WifiRemoteStationManager::PrepareForQueue (Mac48Address address, const WifiMacHeader *header, + Ptr<const Packet> packet, uint32_t fullPacketSize) +{ + NS_LOG_FUNCTION (this << address << *header << packet << fullPacketSize); + if (IsLowLatency () || address.IsGroup ()) + { + return; + } + WifiRemoteStation *station = Lookup (address, header); + WifiTxVector rts = DoGetRtsTxVector (station); + WifiTxVector data = DoGetDataTxVector (station, fullPacketSize); + WifiTxVector ctstoself = DoGetCtsToSelfTxVector (); + HighLatencyDataTxVectorTag datatag; + HighLatencyRtsTxVectorTag rtstag; + HighLatencyCtsToSelfTxVectorTag ctstoselftag; + //first, make sure that the tag is not here anymore. + ConstCast<Packet> (packet)->RemovePacketTag (datatag); + ConstCast<Packet> (packet)->RemovePacketTag (rtstag); + ConstCast<Packet> (packet)->RemovePacketTag (ctstoselftag); + datatag = HighLatencyDataTxVectorTag (data); + rtstag = HighLatencyRtsTxVectorTag (rts); + ctstoselftag = HighLatencyCtsToSelfTxVectorTag (ctstoself); + //and then, add it back + packet->AddPacketTag (datatag); + packet->AddPacketTag (rtstag); + packet->AddPacketTag (ctstoselftag); +} + +WifiTxVector +WifiRemoteStationManager::GetDataTxVector (Mac48Address address, const WifiMacHeader *header, + Ptr<const Packet> packet, uint32_t fullPacketSize) +{ + NS_LOG_FUNCTION (this << address << *header << packet << fullPacketSize); + if (address.IsGroup ()) + { + WifiTxVector v; + v.SetMode (GetNonUnicastMode ()); + v.SetTxPowerLevel (m_defaultTxPowerLevel); + v.SetChannelWidth (m_wifiPhy->GetChannelWidth ()); + v.SetShortGuardInterval (m_wifiPhy->GetGuardInterval ()); + v.SetNss (1); + v.SetNess (0); + v.SetStbc (false); + return v; + } + if (!IsLowLatency ()) + { + HighLatencyDataTxVectorTag datatag; + bool found; + found = ConstCast<Packet> (packet)->PeekPacketTag (datatag); + NS_ASSERT (found); + //cast found to void, to suppress 'found' set but not used + //compiler warning + (void) found; + return datatag.GetDataTxVector (); + } + return DoGetDataTxVector (Lookup (address, header), fullPacketSize); +} + +WifiTxVector +WifiRemoteStationManager::GetCtsToSelfTxVector (const WifiMacHeader *header, + Ptr<const Packet> packet) +{ + NS_LOG_FUNCTION (this << *header << packet); + if (!IsLowLatency ()) + { + HighLatencyCtsToSelfTxVectorTag ctstoselftag; + bool found; + found = ConstCast<Packet> (packet)->PeekPacketTag (ctstoselftag); + NS_ASSERT (found); + //cast found to void, to suppress 'found' set but not used + //compiler warning + (void) found; + return ctstoselftag.GetCtsToSelfTxVector (); + } + return DoGetCtsToSelfTxVector (); +} + +WifiTxVector +WifiRemoteStationManager::DoGetCtsToSelfTxVector (void) +{ + return WifiTxVector (GetDefaultMode (), + GetDefaultTxPowerLevel (), + 0, + m_wifiPhy->GetChannelWidth (), + m_wifiPhy->GetGuardInterval (), + GetNumberOfTransmitAntennas (), + GetNumberOfTransmitAntennas (), + false, + false); +} + +WifiTxVector +WifiRemoteStationManager::GetRtsTxVector (Mac48Address address, const WifiMacHeader *header, + Ptr<const Packet> packet) +{ + NS_LOG_FUNCTION (this << address << *header << packet); + NS_ASSERT (!address.IsGroup ()); + if (!IsLowLatency ()) + { + HighLatencyRtsTxVectorTag rtstag; + bool found; + found = ConstCast<Packet> (packet)->PeekPacketTag (rtstag); + NS_ASSERT (found); + //cast found to void, to suppress 'found' set but not used + //compiler warning + (void) found; + return rtstag.GetRtsTxVector (); + } + return DoGetRtsTxVector (Lookup (address, header)); +} + +void +WifiRemoteStationManager::ReportRtsFailed (Mac48Address address, const WifiMacHeader *header) +{ + NS_LOG_FUNCTION (this << address << *header); + NS_ASSERT (!address.IsGroup ()); + WifiRemoteStation *station = Lookup (address, header); + station->m_ssrc++; + m_macTxRtsFailed (address); + DoReportRtsFailed (station); +} + +void +WifiRemoteStationManager::ReportDataFailed (Mac48Address address, const WifiMacHeader *header) +{ + NS_LOG_FUNCTION (this << address << *header); + NS_ASSERT (!address.IsGroup ()); + WifiRemoteStation *station = Lookup (address, header); + station->m_slrc++; + m_macTxDataFailed (address); + DoReportDataFailed (station); +} + +void +WifiRemoteStationManager::ReportRtsOk (Mac48Address address, const WifiMacHeader *header, + double ctsSnr, WifiMode ctsMode, double rtsSnr) +{ + NS_LOG_FUNCTION (this << address << *header << ctsSnr << ctsMode << rtsSnr); + NS_ASSERT (!address.IsGroup ()); + WifiRemoteStation *station = Lookup (address, header); + station->m_state->m_info.NotifyTxSuccess (station->m_ssrc); + station->m_ssrc = 0; + DoReportRtsOk (station, ctsSnr, ctsMode, rtsSnr); +} + +void +WifiRemoteStationManager::ReportDataOk (Mac48Address address, const WifiMacHeader *header, + double ackSnr, WifiMode ackMode, double dataSnr) +{ + NS_LOG_FUNCTION (this << address << *header << ackSnr << ackMode << dataSnr); + NS_ASSERT (!address.IsGroup ()); + WifiRemoteStation *station = Lookup (address, header); + station->m_state->m_info.NotifyTxSuccess (station->m_slrc); + station->m_slrc = 0; + DoReportDataOk (station, ackSnr, ackMode, dataSnr); +} + +void +WifiRemoteStationManager::ReportFinalRtsFailed (Mac48Address address, const WifiMacHeader *header) +{ + NS_LOG_FUNCTION (this << address << *header); + NS_ASSERT (!address.IsGroup ()); + WifiRemoteStation *station = Lookup (address, header); + station->m_state->m_info.NotifyTxFailed (); + station->m_ssrc = 0; + m_macTxFinalRtsFailed (address); + DoReportFinalRtsFailed (station); +} + +void +WifiRemoteStationManager::ReportFinalDataFailed (Mac48Address address, const WifiMacHeader *header) +{ + NS_LOG_FUNCTION (this << address << *header); + NS_ASSERT (!address.IsGroup ()); + WifiRemoteStation *station = Lookup (address, header); + station->m_state->m_info.NotifyTxFailed (); + station->m_slrc = 0; + m_macTxFinalDataFailed (address); + DoReportFinalDataFailed (station); +} + +void +WifiRemoteStationManager::ReportRxOk (Mac48Address address, const WifiMacHeader *header, + double rxSnr, WifiMode txMode) +{ + NS_LOG_FUNCTION (this << address << *header << rxSnr << txMode); + if (address.IsGroup ()) + { + return; + } + WifiRemoteStation *station = Lookup (address, header); + DoReportRxOk (station, rxSnr, txMode); +} + +bool +WifiRemoteStationManager::NeedRts (Mac48Address address, const WifiMacHeader *header, + Ptr<const Packet> packet) +{ + NS_LOG_FUNCTION (this << address << *header << packet); + if (address.IsGroup ()) + { + return false; + } + bool normally = (packet->GetSize () + header->GetSize () + WIFI_MAC_FCS_LENGTH) > GetRtsCtsThreshold (); + return DoNeedRts (Lookup (address, header), packet, normally); +} + +bool +WifiRemoteStationManager::NeedCtsToSelf (WifiTxVector txVector) +{ + NS_LOG_FUNCTION (this << txVector); + WifiMode mode = txVector.GetMode (); + //search for the BSS Basic Rate set, if the used mode is in the basic set then there is no need for Cts To Self + for (WifiModeListIterator i = m_bssBasicRateSet.begin (); i != m_bssBasicRateSet.end (); i++) + { + if (mode == *i) + { + NS_LOG_DEBUG ("WifiRemoteStationManager::NeedCtsToSelf returning false"); + return false; + } + } + if (HasHtSupported ()) + { + //search for the BSS Basic MCS set, if the used mode is in the basic set then there is no need for Cts To Self + for (WifiModeListIterator i = m_bssBasicMcsSet.begin (); i != m_bssBasicMcsSet.end (); i++) + { + if (mode == *i) + { + NS_LOG_DEBUG ("WifiRemoteStationManager::NeedCtsToSelf returning false"); + return false; + } + } + } + NS_LOG_DEBUG ("WifiRemoteStationManager::NeedCtsToSelf returning true"); + return true; +} + +bool +WifiRemoteStationManager::NeedRtsRetransmission (Mac48Address address, const WifiMacHeader *header, + Ptr<const Packet> packet) +{ + NS_LOG_FUNCTION (this << address << packet << *header); + NS_ASSERT (!address.IsGroup ()); + WifiRemoteStation *station = Lookup (address, header); + bool normally = station->m_ssrc < GetMaxSsrc (); + NS_LOG_DEBUG ("WifiRemoteStationManager::NeedDataRetransmission count: " << station->m_ssrc << " result: " << std::boolalpha << normally); + return DoNeedRtsRetransmission (station, packet, normally); +} + +bool +WifiRemoteStationManager::NeedDataRetransmission (Mac48Address address, const WifiMacHeader *header, + Ptr<const Packet> packet) +{ + NS_LOG_FUNCTION (this << address << packet << *header); + NS_ASSERT (!address.IsGroup ()); + WifiRemoteStation *station = Lookup (address, header); + bool normally = station->m_slrc < GetMaxSlrc (); + NS_LOG_DEBUG ("WifiRemoteStationManager::NeedDataRetransmission count: " << station->m_slrc << " result: " << std::boolalpha << normally); + return DoNeedDataRetransmission (station, packet, normally); +} + +bool +WifiRemoteStationManager::NeedFragmentation (Mac48Address address, const WifiMacHeader *header, + Ptr<const Packet> packet) +{ + NS_LOG_FUNCTION (this << address << packet << *header); + if (address.IsGroup ()) + { + return false; + } + WifiRemoteStation *station = Lookup (address, header); + bool normally = (packet->GetSize () + header->GetSize () + WIFI_MAC_FCS_LENGTH) > GetFragmentationThreshold (); + NS_LOG_DEBUG ("WifiRemoteStationManager::NeedFragmentation result: " << std::boolalpha << normally); + return DoNeedFragmentation (station, packet, normally); +} + +void +WifiRemoteStationManager::DoSetFragmentationThreshold (uint32_t threshold) +{ + NS_LOG_FUNCTION (this << threshold); + if (threshold < 256) + { + /* + * ASN.1 encoding of the MAC and PHY MIB (256 ... 8000) + */ + NS_LOG_WARN ("Fragmentation threshold should be larger than 256. Setting to 256."); + m_nextFragmentationThreshold = 256; + } + else + { + /* + * The length of each fragment shall be an even number of octets, except for the last fragment if an MSDU or + * MMPDU, which may be either an even or an odd number of octets. + */ + if (threshold % 2 != 0) + { + NS_LOG_WARN ("Fragmentation threshold should be an even number. Setting to " << threshold - 1); + m_nextFragmentationThreshold = threshold - 1; + } + else + { + m_nextFragmentationThreshold = threshold; + } + } +} + +void +WifiRemoteStationManager::UpdateFragmentationThreshold (void) +{ + m_fragmentationThreshold = m_nextFragmentationThreshold; +} + +uint32_t +WifiRemoteStationManager::DoGetFragmentationThreshold (void) const +{ + return m_fragmentationThreshold; +} + +uint32_t +WifiRemoteStationManager::GetNFragments (const WifiMacHeader *header, Ptr<const Packet> packet) +{ + NS_LOG_FUNCTION (this << *header << packet); + //The number of bytes a fragment can support is (Threshold - WIFI_HEADER_SIZE - WIFI_FCS). + uint32_t nFragments = (packet->GetSize () / (GetFragmentationThreshold () - header->GetSize () - WIFI_MAC_FCS_LENGTH)); + + //If the size of the last fragment is not 0. + if ((packet->GetSize () % (GetFragmentationThreshold () - header->GetSize () - WIFI_MAC_FCS_LENGTH)) > 0) + { + nFragments++; + } + NS_LOG_DEBUG ("WifiRemoteStationManager::GetNFragments returning " << nFragments); + return nFragments; +} + +uint32_t +WifiRemoteStationManager::GetFragmentSize (Mac48Address address, const WifiMacHeader *header, + Ptr<const Packet> packet, uint32_t fragmentNumber) +{ + NS_LOG_FUNCTION (this << address << *header << packet << fragmentNumber); + NS_ASSERT (!address.IsGroup ()); + uint32_t nFragment = GetNFragments (header, packet); + if (fragmentNumber >= nFragment) + { + NS_LOG_DEBUG ("WifiRemoteStationManager::GetFragmentSize returning 0"); + return 0; + } + //Last fragment + if (fragmentNumber == nFragment - 1) + { + uint32_t lastFragmentSize = packet->GetSize () - (fragmentNumber * (GetFragmentationThreshold () - header->GetSize () - WIFI_MAC_FCS_LENGTH)); + NS_LOG_DEBUG ("WifiRemoteStationManager::GetFragmentSize returning " << lastFragmentSize); + return lastFragmentSize; + } + //All fragments but the last, the number of bytes is (Threshold - WIFI_HEADER_SIZE - WIFI_FCS). + else + { + uint32_t fragmentSize = GetFragmentationThreshold () - header->GetSize () - WIFI_MAC_FCS_LENGTH; + NS_LOG_DEBUG ("WifiRemoteStationManager::GetFragmentSize returning " << fragmentSize); + return fragmentSize; + } +} + +uint32_t +WifiRemoteStationManager::GetFragmentOffset (Mac48Address address, const WifiMacHeader *header, + Ptr<const Packet> packet, uint32_t fragmentNumber) +{ + NS_LOG_FUNCTION (this << address << *header << packet << fragmentNumber); + NS_ASSERT (!address.IsGroup ()); + NS_ASSERT (fragmentNumber < GetNFragments (header, packet)); + uint32_t fragmentOffset = fragmentNumber * (GetFragmentationThreshold () - header->GetSize () - WIFI_MAC_FCS_LENGTH); + NS_LOG_DEBUG ("WifiRemoteStationManager::GetFragmentOffset returning " << fragmentOffset); + return fragmentOffset; +} + +bool +WifiRemoteStationManager::IsLastFragment (Mac48Address address, const WifiMacHeader *header, + Ptr<const Packet> packet, uint32_t fragmentNumber) +{ + NS_LOG_FUNCTION (this << address << *header << packet << fragmentNumber); + NS_ASSERT (!address.IsGroup ()); + bool isLast = fragmentNumber == (GetNFragments (header, packet) - 1); + NS_LOG_DEBUG ("WifiRemoteStationManager::IsLastFragment returning " << std::boolalpha << isLast); + return isLast; +} + +WifiMode +WifiRemoteStationManager::GetControlAnswerMode (Mac48Address address, WifiMode reqMode) +{ + /** + * The standard has relatively unambiguous rules for selecting a + * control response rate (the below is quoted from IEEE 802.11-2012, + * Section 9.7): + * + * To allow the transmitting STA to calculate the contents of the + * Duration/ID field, a STA responding to a received frame shall + * transmit its Control Response frame (either CTS or ACK), other + * than the BlockAck control frame, at the highest rate in the + * BSSBasicRateSet parameter that is less than or equal to the + * rate of the immediately previous frame in the frame exchange + * sequence (as defined in Annex G) and that is of the same + * modulation class (see Section 9.7.8) as the received frame... + */ + NS_LOG_FUNCTION (this << address << reqMode); + WifiMode mode = GetDefaultMode (); + bool found = false; + //First, search the BSS Basic Rate set + for (WifiModeListIterator i = m_bssBasicRateSet.begin (); i != m_bssBasicRateSet.end (); i++) + { + if ((!found || i->GetPhyRate (m_wifiPhy->GetChannelWidth (), 0, 1) > mode.GetPhyRate (m_wifiPhy->GetChannelWidth (), 0, 1)) + && (i->GetPhyRate (m_wifiPhy->GetChannelWidth (), 0, 1) <= reqMode.GetPhyRate (m_wifiPhy->GetChannelWidth (), 0, 1)) + && (i->GetConstellationSize (1) <= reqMode.GetConstellationSize (1)) + && ((i->GetModulationClass () == reqMode.GetModulationClass ()) + || (reqMode.GetModulationClass () == WIFI_MOD_CLASS_HT) + || (reqMode.GetModulationClass () == WIFI_MOD_CLASS_VHT))) + + { + mode = *i; + //We've found a potentially-suitable transmit rate, but we + //need to continue and consider all the basic rates before + //we can be sure we've got the right one. + found = true; + } + } + if (HasHtSupported () || HasVhtSupported ()) + { + if (!found) + { + mode = GetDefaultMcs (); + for (WifiModeListIterator i = m_bssBasicMcsSet.begin (); i != m_bssBasicMcsSet.end (); i++) + { + if ((!found || i->GetPhyRate (m_wifiPhy->GetChannelWidth (), 0, 1) > mode.GetPhyRate (m_wifiPhy->GetChannelWidth (), 0, 1)) + && i->GetPhyRate (m_wifiPhy->GetChannelWidth (), 0, 1) <= reqMode.GetPhyRate (m_wifiPhy->GetChannelWidth (), 0, 1)) + //&& thismode.GetModulationClass () == reqMode.GetModulationClass ()) //TODO: check standard + { + mode = *i; + //We've found a potentially-suitable transmit rate, but we + //need to continue and consider all the basic rates before + //we can be sure we've got the right one. + found = true; + } + } + } + } + //If we found a suitable rate in the BSSBasicRateSet, then we are + //done and can return that mode. + if (found) + { + NS_LOG_DEBUG ("WifiRemoteStationManager::GetControlAnswerMode returning " << mode); + return mode; + } + + /** + * If no suitable basic rate was found, we search the mandatory + * rates. The standard (IEEE 802.11-2007, Section 9.6) says: + * + * ...If no rate contained in the BSSBasicRateSet parameter meets + * these conditions, then the control frame sent in response to a + * received frame shall be transmitted at the highest mandatory + * rate of the PHY that is less than or equal to the rate of the + * received frame, and that is of the same modulation class as the + * received frame. In addition, the Control Response frame shall + * be sent using the same PHY options as the received frame, + * unless they conflict with the requirement to use the + * BSSBasicRateSet parameter. + * + * \todo Note that we're ignoring the last sentence for now, because + * there is not yet any manipulation here of PHY options. + */ + for (uint32_t idx = 0; idx < m_wifiPhy->GetNModes (); idx++) + { + WifiMode thismode = m_wifiPhy->GetMode (idx); + + /* If the rate: + * + * - is a mandatory rate for the PHY, and + * - is equal to or faster than our current best choice, and + * - is less than or equal to the rate of the received frame, and + * - is of the same modulation class as the received frame + * + * ...then it's our best choice so far. + */ + if (thismode.IsMandatory () + && (!found || thismode.GetPhyRate (m_wifiPhy->GetChannelWidth (), 0, 1) > mode.GetPhyRate (m_wifiPhy->GetChannelWidth (), 0, 1)) + && (thismode.GetPhyRate (m_wifiPhy->GetChannelWidth (), 0, 1) <= reqMode.GetPhyRate (m_wifiPhy->GetChannelWidth (), 0, 1)) + && (thismode.GetConstellationSize (1) <= reqMode.GetConstellationSize (1)) + && ((thismode.GetModulationClass () == reqMode.GetModulationClass ()) + || (reqMode.GetModulationClass () == WIFI_MOD_CLASS_HT) + || (reqMode.GetModulationClass () == WIFI_MOD_CLASS_HT))) + + { + mode = thismode; + //As above; we've found a potentially-suitable transmit + //rate, but we need to continue and consider all the + //mandatory rates before we can be sure we've got the right one. + found = true; + } + } + if (HasHtSupported () || HasVhtSupported ()) + { + for (uint32_t idx = 0; idx < m_wifiPhy->GetNMcs (); idx++) + { + WifiMode thismode = m_wifiPhy->GetMcs (idx); + if (thismode.IsMandatory () + && (!found || thismode.GetPhyRate (m_wifiPhy->GetChannelWidth (), 0, 1) > mode.GetPhyRate (m_wifiPhy->GetChannelWidth (), 0, 1)) + && thismode.GetPhyRate (m_wifiPhy->GetChannelWidth (), 0, 1) <= reqMode.GetPhyRate (m_wifiPhy->GetChannelWidth (), 0, 1)) + //&& thismode.GetModulationClass () == reqMode.GetModulationClass ()) //TODO: check standard + { + mode = thismode; + //As above; we've found a potentially-suitable transmit + //rate, but we need to continue and consider all the + //mandatory rates before we can be sure we've got the right one. + found = true; + } + + } + } + + /** + * If we still haven't found a suitable rate for the response then + * someone has messed up the simulation config. This probably means + * that the WifiPhyStandard is not set correctly, or that a rate that + * is not supported by the PHY has been explicitly requested in a + * WifiRemoteStationManager (or descendant) configuration. + * + * Either way, it is serious - we can either disobey the standard or + * fail, and I have chosen to do the latter... + */ + if (!found) + { + NS_FATAL_ERROR ("Can't find response rate for " << reqMode); + } + + NS_LOG_DEBUG ("WifiRemoteStationManager::GetControlAnswerMode returning " << mode); + return mode; +} + +WifiTxVector +WifiRemoteStationManager::GetCtsTxVector (Mac48Address address, WifiMode rtsMode) +{ + NS_ASSERT (!address.IsGroup ()); + WifiTxVector v; + v.SetMode (GetControlAnswerMode (address, rtsMode)); + v.SetTxPowerLevel (DoGetCtsTxPowerLevel (address, v.GetMode ())); + v.SetChannelWidth (DoGetCtsTxChannelWidth (address, v.GetMode ())); + v.SetShortGuardInterval (DoGetCtsTxGuardInterval (address, v.GetMode ())); + v.SetNss (DoGetCtsTxNss (address, v.GetMode ())); + v.SetNess (DoGetCtsTxNess (address, v.GetMode ())); + v.SetStbc (DoGetCtsTxStbc (address, v.GetMode ())); + return v; +} + +WifiTxVector +WifiRemoteStationManager::GetAckTxVector (Mac48Address address, WifiMode dataMode) +{ + NS_ASSERT (!address.IsGroup ()); + WifiTxVector v; + v.SetMode (GetControlAnswerMode (address, dataMode)); + v.SetTxPowerLevel (DoGetAckTxPowerLevel (address, v.GetMode ())); + v.SetChannelWidth (DoGetAckTxChannelWidth (address, v.GetMode ())); + v.SetShortGuardInterval (DoGetAckTxGuardInterval (address, v.GetMode ())); + v.SetNss (DoGetAckTxNss (address, v.GetMode ())); + v.SetNess (DoGetAckTxNess (address, v.GetMode ())); + v.SetStbc (DoGetAckTxStbc (address, v.GetMode ())); + return v; +} + +WifiTxVector +WifiRemoteStationManager::GetBlockAckTxVector (Mac48Address address, WifiMode blockAckReqMode) +{ + NS_ASSERT (!address.IsGroup ()); + WifiTxVector v; + v.SetMode (GetControlAnswerMode (address, blockAckReqMode)); + v.SetTxPowerLevel (DoGetBlockAckTxPowerLevel (address, v.GetMode ())); + v.SetChannelWidth (DoGetBlockAckTxChannelWidth (address, v.GetMode ())); + v.SetShortGuardInterval (DoGetBlockAckTxGuardInterval (address, v.GetMode ())); + v.SetNss (DoGetBlockAckTxNss (address, v.GetMode ())); + v.SetNess (DoGetBlockAckTxNess (address, v.GetMode ())); + v.SetStbc (DoGetBlockAckTxStbc (address, v.GetMode ())); + return v; +} + +uint8_t +WifiRemoteStationManager::DoGetCtsTxPowerLevel (Mac48Address address, WifiMode ctsMode) +{ + return m_defaultTxPowerLevel; +} + +uint32_t +WifiRemoteStationManager::DoGetCtsTxChannelWidth (Mac48Address address, WifiMode ctsMode) +{ + return m_wifiPhy->GetChannelWidth (); +} + +bool +WifiRemoteStationManager::DoGetCtsTxGuardInterval (Mac48Address address, WifiMode ctsMode) +{ + return m_wifiPhy->GetGuardInterval (); +} + +uint8_t +WifiRemoteStationManager::DoGetCtsTxNss (Mac48Address address, WifiMode ctsMode) +{ + return 1; +} + +uint8_t +WifiRemoteStationManager::DoGetCtsTxNess (Mac48Address address, WifiMode ctsMode) +{ + return 0; +} + +bool +WifiRemoteStationManager::DoGetCtsTxStbc (Mac48Address address, WifiMode ctsMode) +{ + return m_wifiPhy->GetStbc (); +} + +uint8_t +WifiRemoteStationManager::DoGetAckTxPowerLevel (Mac48Address address, WifiMode ackMode) +{ + return m_defaultTxPowerLevel; +} + +uint32_t +WifiRemoteStationManager::DoGetAckTxChannelWidth (Mac48Address address, WifiMode ctsMode) +{ + return m_wifiPhy->GetChannelWidth (); +} + +bool +WifiRemoteStationManager::DoGetAckTxGuardInterval (Mac48Address address, WifiMode ackMode) +{ + return m_wifiPhy->GetGuardInterval (); +} + +uint8_t +WifiRemoteStationManager::DoGetAckTxNss (Mac48Address address, WifiMode ackMode) +{ + return 1; +} + +uint8_t +WifiRemoteStationManager::DoGetAckTxNess (Mac48Address address, WifiMode ackMode) +{ + return 0; +} + +bool +WifiRemoteStationManager::DoGetAckTxStbc (Mac48Address address, WifiMode ackMode) +{ + return m_wifiPhy->GetStbc (); +} + +uint8_t +WifiRemoteStationManager::DoGetBlockAckTxPowerLevel (Mac48Address address, WifiMode blockAckMode) +{ + return m_defaultTxPowerLevel; +} + +uint32_t +WifiRemoteStationManager::DoGetBlockAckTxChannelWidth (Mac48Address address, WifiMode ctsMode) +{ + return m_wifiPhy->GetChannelWidth (); +} + +bool +WifiRemoteStationManager::DoGetBlockAckTxGuardInterval (Mac48Address address, WifiMode blockAckMode) +{ + return m_wifiPhy->GetGuardInterval (); +} + +uint8_t +WifiRemoteStationManager::DoGetBlockAckTxNss (Mac48Address address, WifiMode blockAckMode) +{ + return 1; +} + +uint8_t +WifiRemoteStationManager::DoGetBlockAckTxNess (Mac48Address address, WifiMode blockAckMode) +{ + return 0; +} + +bool +WifiRemoteStationManager::DoGetBlockAckTxStbc (Mac48Address address, WifiMode blockAckMode) +{ + return m_wifiPhy->GetStbc (); +} + +uint8_t +WifiRemoteStationManager::GetDefaultTxPowerLevel (void) const +{ + return m_defaultTxPowerLevel; +} + +WifiRemoteStationInfo +WifiRemoteStationManager::GetInfo (Mac48Address address) +{ + WifiRemoteStationState *state = LookupState (address); + return state->m_info; +} + +WifiRemoteStationState * +WifiRemoteStationManager::LookupState (Mac48Address address) const +{ + NS_LOG_FUNCTION (this << address); + for (StationStates::const_iterator i = m_states.begin (); i != m_states.end (); i++) + { + if ((*i)->m_address == address) + { + NS_LOG_DEBUG ("WifiRemoteStationManager::LookupState returning existing state"); + return (*i); + } + } + WifiRemoteStationState *state = new WifiRemoteStationState (); + state->m_state = WifiRemoteStationState::BRAND_NEW; + state->m_address = address; + state->m_operationalRateSet.push_back (GetDefaultMode ()); + state->m_operationalMcsSet.push_back (GetDefaultMcs ()); + state->m_channelWidth = m_wifiPhy->GetChannelWidth (); + state->m_shortGuardInterval = m_wifiPhy->GetGuardInterval (); + state->m_greenfield = m_wifiPhy->GetGreenfield (); + state->m_rx = 1; + state->m_tx = 1; + state->m_ness = 0; + state->m_aggregation = false; + state->m_stbc = false; + //added by zeng: + state->m_assocRespTxRetryCount=0; + //end + const_cast<WifiRemoteStationManager *> (this)->m_states.push_back (state); + NS_LOG_DEBUG ("WifiRemoteStationManager::LookupState returning new state"); + return state; +} + +WifiRemoteStation * +WifiRemoteStationManager::Lookup (Mac48Address address, const WifiMacHeader *header) const +{ + uint8_t tid; + if (header->IsQosData ()) + { + tid = header->GetQosTid (); + } + else + { + tid = 0; + } + return Lookup (address, tid); +} + +WifiRemoteStation * +WifiRemoteStationManager::Lookup (Mac48Address address, uint8_t tid) const +{ + NS_LOG_FUNCTION (this << address << (uint16_t)tid); + for (Stations::const_iterator i = m_stations.begin (); i != m_stations.end (); i++) + { + if ((*i)->m_tid == tid + && (*i)->m_state->m_address == address) + { + return (*i); + } + } + WifiRemoteStationState *state = LookupState (address); + + WifiRemoteStation *station = DoCreateStation (); + station->m_state = state; + station->m_tid = tid; + station->m_ssrc = 0; + station->m_slrc = 0; + const_cast<WifiRemoteStationManager *> (this)->m_stations.push_back (station); + return station; +} + +void +WifiRemoteStationManager::AddStationHtCapabilities (Mac48Address from, HtCapabilities htCapabilities) +{ + //Used by all stations to record HT capabilities of remote stations + NS_LOG_FUNCTION (this << from << htCapabilities); + WifiRemoteStationState *state; + state = LookupState (from); + state->m_shortGuardInterval = htCapabilities.GetShortGuardInterval20 (); + if (htCapabilities.GetSupportedChannelWidth () == 1) + { + state->m_channelWidth = 40; + } + else + { + state->m_channelWidth = 20; + } + state->m_greenfield = htCapabilities.GetGreenfield (); +} + +void +WifiRemoteStationManager::AddStationVhtCapabilities (Mac48Address from, VhtCapabilities vhtCapabilities) +{ + //Used by all stations to record VHT capabilities of remote stations + NS_LOG_FUNCTION (this << from << vhtCapabilities); + WifiRemoteStationState *state; + state = LookupState (from); + if (vhtCapabilities.GetSupportedChannelWidthSet () == 1) + { + state->m_channelWidth = 160; + } + else + { + state->m_channelWidth = 80; + } + //This is a workaround to enable users to force a 20 or 40 MHz channel for a VHT-compliant device, + //since IEEE 802.11ac standard says that 20, 40 and 80 MHz channels are mandatory. + if (m_wifiPhy->GetChannelWidth () < state->m_channelWidth) + { + state->m_channelWidth = m_wifiPhy->GetChannelWidth (); + } +} + +bool +WifiRemoteStationManager::GetGreenfieldSupported (Mac48Address address) const +{ + return LookupState (address)->m_greenfield; +} + +WifiMode +WifiRemoteStationManager::GetDefaultMode (void) const +{ + return m_defaultTxMode; +} + +WifiMode +WifiRemoteStationManager::GetDefaultMcs (void) const +{ + return m_defaultTxMcs; +} + +void +WifiRemoteStationManager::Reset (void) +{ + NS_LOG_FUNCTION (this); + for (Stations::const_iterator i = m_stations.begin (); i != m_stations.end (); i++) + { + delete (*i); + } + m_stations.clear (); + m_bssBasicRateSet.clear (); + m_bssBasicRateSet.push_back (m_defaultTxMode); + m_bssBasicMcsSet.clear (); + m_bssBasicMcsSet.push_back (m_defaultTxMcs); + NS_ASSERT (m_defaultTxMode.IsMandatory ()); +} + +void +WifiRemoteStationManager::RemoveStation (Mac48Address sta) +{ + NS_LOG_FUNCTION (sta); + for (Stations::iterator i = m_stations.begin (); i != m_stations.end (); i++) + { + if((*i)->m_state->m_address == sta ) + { + delete (*i); + m_stations.erase(i); + break; + } + } +} + +void +WifiRemoteStationManager::AddBasicMode (WifiMode mode) +{ + NS_LOG_FUNCTION (this << mode); + if (mode.GetModulationClass () == WIFI_MOD_CLASS_HT || mode.GetModulationClass () == WIFI_MOD_CLASS_VHT) + { + NS_FATAL_ERROR ("It is not allowed to add a (V)HT rate in the BSSBasicRateSet!"); + } + for (uint32_t i = 0; i < GetNBasicModes (); i++) + { + if (GetBasicMode (i) == mode) + { + return; + } + } + m_bssBasicRateSet.push_back (mode); +} + +uint32_t +WifiRemoteStationManager::GetNBasicModes (void) const +{ + return m_bssBasicRateSet.size (); +} + +WifiMode +WifiRemoteStationManager::GetBasicMode (uint32_t i) const +{ + NS_ASSERT (i < m_bssBasicRateSet.size ()); + return m_bssBasicRateSet[i]; +} + +void +WifiRemoteStationManager::AddBasicMcs (WifiMode mcs) +{ + NS_LOG_FUNCTION (this << (uint32_t)mcs.GetMcsValue ()); + for (uint32_t i = 0; i < GetNBasicMcs (); i++) + { + if (GetBasicMcs (i) == mcs) + { + return; + } + } + m_bssBasicMcsSet.push_back (mcs); +} + +uint32_t +WifiRemoteStationManager::GetNBasicMcs (void) const +{ + return m_bssBasicMcsSet.size (); +} + +WifiMode +WifiRemoteStationManager::GetBasicMcs (uint32_t i) const +{ + NS_ASSERT (i < m_bssBasicMcsSet.size ()); + return m_bssBasicMcsSet[i]; +} + +WifiMode +WifiRemoteStationManager::GetNonUnicastMode (void) const +{ + if (m_nonUnicastMode == WifiMode ()) + { + return GetBasicMode (0); + } + else + { + return m_nonUnicastMode; + } +} + +bool +WifiRemoteStationManager::DoNeedRts (WifiRemoteStation *station, + Ptr<const Packet> packet, bool normally) +{ + return normally; +} + +bool +WifiRemoteStationManager::DoNeedRtsRetransmission (WifiRemoteStation *station, + Ptr<const Packet> packet, bool normally) +{ + return normally; +} + +bool +WifiRemoteStationManager::DoNeedDataRetransmission (WifiRemoteStation *station, + Ptr<const Packet> packet, bool normally) +{ + return normally; +} + +bool +WifiRemoteStationManager::DoNeedFragmentation (WifiRemoteStation *station, + Ptr<const Packet> packet, bool normally) +{ + return normally; +} + +WifiMode +WifiRemoteStationManager::GetSupported (const WifiRemoteStation *station, uint32_t i) const +{ + NS_ASSERT (i < GetNSupported (station)); + return station->m_state->m_operationalRateSet[i]; +} + +WifiMode +WifiRemoteStationManager::GetMcsSupported (const WifiRemoteStation *station, uint32_t i) const +{ + NS_ASSERT (i < GetNMcsSupported (station)); + return station->m_state->m_operationalMcsSet[i]; +} + +uint32_t +WifiRemoteStationManager::GetChannelWidth (const WifiRemoteStation *station) const +{ + return station->m_state->m_channelWidth; +} + +bool +WifiRemoteStationManager::GetShortGuardInterval (const WifiRemoteStation *station) const +{ + return station->m_state->m_shortGuardInterval; +} + +bool +WifiRemoteStationManager::GetGreenfield (const WifiRemoteStation *station) const +{ + return station->m_state->m_greenfield; +} + +bool +WifiRemoteStationManager::GetAggregation (const WifiRemoteStation *station) const +{ + return station->m_state->m_aggregation; +} + +bool +WifiRemoteStationManager::GetStbc (const WifiRemoteStation *station) const +{ + return station->m_state->m_stbc; +} + +uint32_t +WifiRemoteStationManager::GetNumberOfReceiveAntennas (const WifiRemoteStation *station) const +{ + return station->m_state->m_rx; +} + +uint32_t +WifiRemoteStationManager::GetNumberOfTransmitAntennas (const WifiRemoteStation *station) const +{ + return station->m_state->m_tx; +} + +uint32_t +WifiRemoteStationManager::GetNess (const WifiRemoteStation *station) const +{ + return station->m_state->m_ness; +} + +uint32_t +WifiRemoteStationManager::GetShortRetryCount (const WifiRemoteStation *station) const +{ + return station->m_ssrc; +} + +Ptr<WifiPhy> +WifiRemoteStationManager::GetPhy (void) const +{ + return m_wifiPhy; +} + +Ptr<WifiMac> +WifiRemoteStationManager::GetMac (void) const +{ + return m_wifiMac; +} + +uint32_t +WifiRemoteStationManager::GetLongRetryCount (const WifiRemoteStation *station) const +{ + return station->m_slrc; +} + +uint32_t +WifiRemoteStationManager::GetNSupported (const WifiRemoteStation *station) const +{ + return station->m_state->m_operationalRateSet.size (); +} + +uint32_t +WifiRemoteStationManager::GetNMcsSupported (const WifiRemoteStation *station) const +{ + return station->m_state->m_operationalMcsSet.size (); +} + +void +WifiRemoteStationManager::SetDefaultTxPowerLevel (uint8_t txPower) +{ + m_defaultTxPowerLevel = txPower; +} + +uint32_t +WifiRemoteStationManager::GetNumberOfTransmitAntennas (void) +{ + return m_wifiPhy->GetNumberOfTransmitAntennas (); +} + +WifiRemoteStationInfo::WifiRemoteStationInfo () + : m_memoryTime (Seconds (1.0)), + m_lastUpdate (Seconds (0.0)), + m_failAvg (0.0) +{ +} + +double +WifiRemoteStationInfo::CalculateAveragingCoefficient () +{ + double retval = std::exp ((double)(m_lastUpdate.GetMicroSeconds () - Simulator::Now ().GetMicroSeconds ()) + / (double)m_memoryTime.GetMicroSeconds ()); + m_lastUpdate = Simulator::Now (); + return retval; +} + +void +WifiRemoteStationInfo::NotifyTxSuccess (uint32_t retryCounter) +{ + double coefficient = CalculateAveragingCoefficient (); + m_failAvg = (double)retryCounter / (1 + (double)retryCounter) * (1.0 - coefficient) + coefficient * m_failAvg; +} + +void +WifiRemoteStationInfo::NotifyTxFailed () +{ + double coefficient = CalculateAveragingCoefficient (); + m_failAvg = (1.0 - coefficient) + coefficient * m_failAvg; +} + +double +WifiRemoteStationInfo::GetFrameErrorRate () const +{ + return m_failAvg; +} + +WifiRemoteStation::~WifiRemoteStation () +{ + NS_LOG_FUNCTION (this); +} + +} //namespace ns3 |