diff --git a/src/devices/wifi/dca-txop.cc b/src/devices/wifi/dca-txop.cc --- a/src/devices/wifi/dca-txop.cc +++ b/src/devices/wifi/dca-txop.cc @@ -276,14 +276,14 @@ DcaTxop::NeedRtsRetransmission (void) { WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ()); - return station->NeedRtsRetransmission (m_currentPacket); + return station->NeedRtsRetransmission (&m_currentHdr); } bool DcaTxop::NeedDataRetransmission (void) { WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ()); - return station->NeedDataRetransmission (m_currentPacket); + return station->NeedDataRetransmission (&m_currentHdr); } bool DcaTxop::NeedFragmentation (void) diff --git a/src/devices/wifi/edca-txop-n.cc b/src/devices/wifi/edca-txop-n.cc --- a/src/devices/wifi/edca-txop-n.cc +++ b/src/devices/wifi/edca-txop-n.cc @@ -410,7 +410,15 @@ { MY_DEBUG ("Cts Fail"); WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ()); - station->ReportFinalRtsFailed (); + if (m_currentHdr.IsQosData ()) + { + uint8_t tid = m_currentHdr.GetQosTid (); + station->ReportFinalRtsFailed (QosUtilsMapTidToAc (tid)); + } + else + { + station->ReportFinalRtsFailed (); + } if (!m_txFailedCallback.IsNull ()) { m_txFailedCallback (m_currentHdr); @@ -473,7 +481,15 @@ { MY_DEBUG ("Ack Fail"); WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ()); - station->ReportFinalDataFailed (); + if (m_currentHdr.IsQosData ()) + { + uint8_t tid = m_currentHdr.GetQosTid (); + station->ReportFinalDataFailed (QosUtilsMapTidToAc (tid)); + } + else + { + station->ReportFinalDataFailed (); + } if (!m_txFailedCallback.IsNull ()) { m_txFailedCallback (m_currentHdr); @@ -533,14 +549,14 @@ EdcaTxopN::NeedRtsRetransmission (void) { WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ()); - return station->NeedRtsRetransmission (m_currentPacket); + return station->NeedRtsRetransmission (&m_currentHdr); } bool EdcaTxopN::NeedDataRetransmission (void) { WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ()); - return station->NeedDataRetransmission (m_currentPacket); + return station->NeedDataRetransmission (&m_currentHdr); } void diff --git a/src/devices/wifi/mac-low.cc b/src/devices/wifi/mac-low.cc --- a/src/devices/wifi/mac-low.cc +++ b/src/devices/wifi/mac-low.cc @@ -540,8 +540,15 @@ packet->RemovePacketTag (tag); WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ()); station->ReportRxOk (rxSnr, txMode); - station->ReportRtsOk (rxSnr, txMode, tag.Get ()); - + if (m_currentHdr.IsQosData ()) + { + uint8_t tid = m_currentHdr.GetQosTid (); + station->ReportRtsOk (rxSnr, txMode, tag.Get (), QosUtilsMapTidToAc (tid)); + } + else + { + station->ReportRtsOk (rxSnr, txMode, tag.Get ()); + } m_ctsTimeoutEvent.Cancel (); NotifyCtsTimeoutResetNow (); m_listener->GotCts (rxSnr, txMode); @@ -564,7 +571,15 @@ packet->RemovePacketTag (tag); WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ()); station->ReportRxOk (rxSnr, txMode); - station->ReportDataOk (rxSnr, txMode, tag.Get ()); + if (m_currentHdr.IsQosData ()) + { + uint8_t tid = m_currentHdr.GetQosTid (); + station->ReportDataOk (rxSnr, txMode, tag.Get (), QosUtilsMapTidToAc (tid)); + } + else + { + station->ReportDataOk (rxSnr, txMode, tag.Get ()); + } bool gotAck = false; if (m_txParams.MustWaitNormalAck () && m_normalAckTimeoutEvent.IsRunning ()) @@ -879,7 +894,15 @@ // we should restart a new cts timeout now until the expected // end of rx if there was a rx start before now. WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ()); - station->ReportRtsFailed (); + if (m_currentHdr.IsQosData ()) + { + uint8_t tid = m_currentHdr.GetQosTid (); + station->ReportRtsFailed (QosUtilsMapTidToAc (tid)); + } + else + { + station->ReportRtsFailed (); + } m_currentPacket = 0; MacLowTransmissionListener *listener = m_listener; m_listener = 0; @@ -894,7 +917,15 @@ // we should restart a new ack timeout now until the expected // end of rx if there was a rx start before now. WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ()); - station->ReportDataFailed (); + if (m_currentHdr.IsQosData ()) + { + uint8_t tid = m_currentHdr.GetQosTid (); + station->ReportDataFailed (QosUtilsMapTidToAc (tid)); + } + else + { + station->ReportDataFailed (); + } MacLowTransmissionListener *listener = m_listener; m_listener = 0; listener->MissedAck (); @@ -904,7 +935,15 @@ { NS_LOG_FUNCTION (this); WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ()); - station->ReportDataFailed (); + if (m_currentHdr.IsQosData ()) + { + uint8_t tid = m_currentHdr.GetQosTid (); + station->ReportDataFailed (QosUtilsMapTidToAc (tid)); + } + else + { + station->ReportDataFailed (); + } MacLowTransmissionListener *listener = m_listener; m_listener = 0; if (m_phy->IsStateIdle ()) @@ -922,7 +961,15 @@ { NS_LOG_FUNCTION (this); WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ()); - station->ReportDataFailed (); + if (m_currentHdr.IsQosData ()) + { + uint8_t tid = m_currentHdr.GetQosTid (); + station->ReportDataFailed (QosUtilsMapTidToAc (tid)); + } + else + { + station->ReportDataFailed (); + } MacLowTransmissionListener *listener = m_listener; m_listener = 0; if (m_phy->IsStateIdle ()) diff --git a/src/devices/wifi/wifi-remote-station-manager.cc b/src/devices/wifi/wifi-remote-station-manager.cc --- a/src/devices/wifi/wifi-remote-station-manager.cc +++ b/src/devices/wifi/wifi-remote-station-manager.cc @@ -476,7 +476,17 @@ m_slrc (0), m_avgSlrcCoefficient(0.9), m_avgSlrc (0) -{} +{ + m_qosSsrc.insert (std::make_pair (AC_VO, 0)); + m_qosSsrc.insert (std::make_pair (AC_VI, 0)); + m_qosSsrc.insert (std::make_pair (AC_BE, 0)); + m_qosSsrc.insert (std::make_pair (AC_BK, 0)); + + m_qosSlrc.insert (std::make_pair (AC_VO, 0)); + m_qosSlrc.insert (std::make_pair (AC_VI, 0)); + m_qosSlrc.insert (std::make_pair (AC_BE, 0)); + m_qosSlrc.insert (std::make_pair (AC_BK, 0)); +} WifiRemoteStation::~WifiRemoteStation () {} @@ -675,15 +685,31 @@ } } bool -WifiRemoteStation::NeedRtsRetransmission (Ptr packet) +WifiRemoteStation::NeedRtsRetransmission (const WifiMacHeader *hdr) { - return (m_ssrc < GetManager ()->GetMaxSsrc ()); + if (hdr->IsQosData ()) + { + AccessClass ac = QosUtilsMapTidToAc (hdr->GetQosTid ()); + return (m_qosSsrc.find (ac)->second < GetManager ()->GetMaxSsrc ()); + } + else + { + return (m_ssrc < GetManager ()->GetMaxSsrc ()); + } } bool -WifiRemoteStation::NeedDataRetransmission (Ptr packet) +WifiRemoteStation::NeedDataRetransmission (const WifiMacHeader *hdr) { - return (m_slrc < GetManager ()->GetMaxSlrc ()); + if (hdr->IsQosData ()) + { + AccessClass ac = QosUtilsMapTidToAc (hdr->GetQosTid ()); + return (m_qosSlrc.find (ac)->second < GetManager ()->GetMaxSlrc ()); + } + else + { + return (m_slrc < GetManager ()->GetMaxSlrc ()); + } } bool @@ -745,55 +771,128 @@ } void -WifiRemoteStation::ReportRtsFailed (void) +WifiRemoteStation::ReportRtsFailed (enum AccessClass ac) { - m_ssrc++; + if (ac == AC_UNDEF) + { + NS_LOG_INFO ("Access class not supported"); + NS_ASSERT (false); + } + else if (ac == AC_BE_NQOS) + { + m_ssrc++; + } + else + { + m_qosSsrc.find (ac)->second++; + } GetManager ()->NotifyTxRtsFailed (m_address); DoReportRtsFailed (); } void -WifiRemoteStation::ReportDataFailed (void) +WifiRemoteStation::ReportDataFailed (enum AccessClass ac) { - m_slrc++; + if (ac == AC_UNDEF) + { + NS_LOG_INFO ("Access class not supported"); + NS_ASSERT (false); + } + else if (ac == AC_BE_NQOS) + { + m_slrc++; + } + else + { + m_qosSlrc.find (ac)->second++; + } GetManager ()->NotifyTxDataFailed (m_address); DoReportDataFailed (); } void -WifiRemoteStation::ReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr) +WifiRemoteStation::ReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr, enum AccessClass ac) { - m_ssrc = 0; + if (ac == AC_UNDEF) + { + NS_LOG_INFO ("Access class not supported"); + NS_ASSERT (false); + } + else if (ac == AC_BE_NQOS) + { + m_ssrc = 0; + } + else + { + m_qosSsrc.find (ac)->second = 0; + } DoReportRtsOk (ctsSnr, ctsMode, rtsSnr); } void -WifiRemoteStation::ReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr) +WifiRemoteStation::ReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr, enum AccessClass ac) { m_avgSlrc = m_avgSlrc * m_avgSlrcCoefficient + (double) m_slrc * (1 - m_avgSlrcCoefficient); - m_slrc = 0; + if (ac == AC_UNDEF) + { + NS_LOG_INFO ("Access class not supported"); + NS_ASSERT (false); + } + else if (ac == AC_BE_NQOS) + { + m_slrc = 0; + } + else + { + m_qosSlrc.find (ac)->second = 0; + } DoReportDataOk (ackSnr, ackMode, dataSnr); } void -WifiRemoteStation::ReportFinalRtsFailed (void) +WifiRemoteStation::ReportFinalRtsFailed (enum AccessClass ac) { - m_ssrc = 0; + if (ac == AC_UNDEF) + { + NS_LOG_INFO ("Access class not supported"); + NS_ASSERT (false); + } + else if (ac == AC_BE_NQOS) + { + m_ssrc = 0; + } + else + { + m_qosSsrc.find (ac)->second = 0; + } GetManager ()->NotifyTxFinalRtsFailed (m_address); DoReportFinalRtsFailed (); } void -WifiRemoteStation::ReportFinalDataFailed (void) +WifiRemoteStation::ReportFinalDataFailed (enum AccessClass ac) { - m_slrc = 0; + if (ac == AC_UNDEF) + { + NS_LOG_INFO ("Access class not supported"); + NS_ASSERT (false); + } + else if (ac == AC_BE_NQOS) + { + m_slrc = 0; + } + else + { + m_qosSlrc.find (ac)->second = 0; + } GetManager ()->NotifyTxFinalDataFailed (m_address); DoReportFinalDataFailed (); } void -WifiRemoteStation::ReportRxOk (double rxSnr, WifiMode txMode) +WifiRemoteStation::ReportRxOk (double rxSnr, WifiMode txMode, enum AccessClass ac) { + //How should we use 'ac' parameter here? DoReportRxOk (rxSnr, txMode); } } // namespace ns3 diff --git a/src/devices/wifi/wifi-remote-station-manager.h b/src/devices/wifi/wifi-remote-station-manager.h --- a/src/devices/wifi/wifi-remote-station-manager.h +++ b/src/devices/wifi/wifi-remote-station-manager.h @@ -1,6 +1,7 @@ /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ /* * Copyright (c) 2005,2006,2007 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 @@ -16,17 +17,21 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Author: Mathieu Lacage + * Author: Mirko Banchi */ #ifndef WIFI_REMOTE_STATION_MANAGER_H #define WIFI_REMOTE_STATION_MANAGER_H #include #include +#include #include "ns3/mac48-address.h" #include "ns3/packet.h" #include "ns3/object.h" #include "ns3/traced-value.h" +#include "ns3/wifi-mac-header.h" #include "wifi-mode.h" +#include "qos-utils.h" namespace ns3 { @@ -224,35 +229,47 @@ */ WifiMode GetRtsMode (Ptr packet); /** + * \param ac Represents access class of the packet for which a rts was transmitted. + * * Should be invoked whenever the RtsTimeout associated to a transmission * attempt expires. */ - void ReportRtsFailed (void); + void ReportRtsFailed (enum AccessClass ac = AC_BE_NQOS); /** + * \param ac Access class which failed data belongs. + * * Should be invoked whenever the AckTimeout associated to a transmission * attempt expires. */ - void ReportDataFailed (void); + void ReportDataFailed (enum AccessClass ac = AC_BE_NQOS); /** + * \param ac Represents access class of the packet for which the rts was transmitted. + * * Should be invoked whenever we receive the Cts associated to an RTS * we just sent. */ - void ReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr); + void ReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr, enum AccessClass ac = AC_BE_NQOS); /** + * \param ac Access class which correct received data belongs. + * * Should be invoked whenever we receive the Ack associated to a data packet * we just sent. */ - void ReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr); + void ReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr, enum AccessClass ac = AC_BE_NQOS); /** + * \param ac Represents access class of the packet for which a rts was transmitted. + * * Should be invoked after calling ReportRtsFailed if * NeedRtsRetransmission returns false */ - void ReportFinalRtsFailed (void); + void ReportFinalRtsFailed (enum AccessClass ac = AC_BE_NQOS); /** + * \param ac Access class which failed data belongs. + * * Should be invoked after calling ReportDataFailed if * NeedDataRetransmission returns false */ - void ReportFinalDataFailed (void); + void ReportFinalDataFailed (enum AccessClass ac = AC_BE_NQOS); /** * \param rxSnr the snr of the packet received @@ -260,7 +277,7 @@ * * Should be invoked whenever a packet is successfully received. */ - void ReportRxOk (double rxSnr, WifiMode txMode); + void ReportRxOk (double rxSnr, WifiMode txMode, enum AccessClass ac = AC_BE_NQOS); /** * \param packet the packet to send @@ -269,17 +286,17 @@ */ virtual bool NeedRts (Ptr packet); /** - * \param packet the packet to send + * \param hdr the header of the packet to send * \returns true if we want to restart a failed RTS/CTS * handshake, false otherwise. */ - virtual bool NeedRtsRetransmission (Ptr packet); + virtual bool NeedRtsRetransmission (const WifiMacHeader *hdr); /** - * \param packet the packet to send + * \param hdr the header of the packet to send * \returns true if we want to resend a packet * after a failed transmission attempt, false otherwise. */ - virtual bool NeedDataRetransmission (Ptr packet); + virtual bool NeedDataRetransmission (const WifiMacHeader *hdr); /** * \param packet the packet to send @@ -361,6 +378,8 @@ SupportedModes m_modes; TracedValue m_ssrc; TracedValue m_slrc; + std::map > m_qosSsrc; + std::map > m_qosSlrc; double m_avgSlrcCoefficient; double m_avgSlrc; Mac48Address m_address;