diff --git a/src/wifi/model/frame-exchange-manager.cc b/src/wifi/model/frame-exchange-manager.cc index bcf781f9a..714fe1d2e 100644 --- a/src/wifi/model/frame-exchange-manager.cc +++ b/src/wifi/model/frame-exchange-manager.cc @@ -52,7 +52,8 @@ FrameExchangeManager::GetTypeId() } FrameExchangeManager::FrameExchangeManager() - : m_navEnd(Seconds(0)), + : m_navEnd(0), + m_txNav(0), m_linkId(0), m_allowedWidth(0), m_promisc(false), @@ -573,6 +574,14 @@ FrameExchangeManager::ForwardMpduDown(Ptr mpdu, WifiTxVector& txVector auto psdu = Create(mpdu, false); FinalizeMacHeader(psdu); m_allowedWidth = std::min(m_allowedWidth, txVector.GetChannelWidth()); + auto txDuration = WifiPhy::CalculateTxDuration(psdu, txVector, m_phy->GetPhyBand()); + // The TXNAV timer is a single timer, shared by the EDCAFs within a STA, that is initialized + // with the duration from the Duration/ID field in the frame most recently successfully + // transmitted by the TXOP holder, except for PS-Poll frames. (Sec.10.23.2.2 IEEE 802.11-2020) + if (!mpdu->GetHeader().IsPsPoll()) + { + m_txNav = Max(m_txNav, Simulator::Now() + txDuration + mpdu->GetHeader().GetDuration()); + } m_phy->Send(psdu, txVector); } @@ -968,6 +977,8 @@ FrameExchangeManager::TransmissionFailed() // A non-QoS station always releases the channel upon a transmission failure NotifyChannelReleased(m_dcf); m_dcf = nullptr; + // reset TXNAV because transmission failed + m_txNav = Simulator::Now(); } void diff --git a/src/wifi/model/frame-exchange-manager.h b/src/wifi/model/frame-exchange-manager.h index 28b31eb10..950a0b2a7 100644 --- a/src/wifi/model/frame-exchange-manager.h +++ b/src/wifi/model/frame-exchange-manager.h @@ -512,6 +512,7 @@ class FrameExchangeManager : public Object Mac48Address m_self; //!< the MAC address of this device Mac48Address m_bssid; //!< BSSID address (Mac48Address) Time m_navEnd; //!< NAV expiration time + Time m_txNav; //!< the TXNAV timer std::set m_sentRtsTo; //!< the STA(s) which we sent an RTS to (waiting for CTS) std::set m_sentFrameTo; //!< the STA(s) to which we sent a frame requesting a response diff --git a/src/wifi/model/he/he-frame-exchange-manager.cc b/src/wifi/model/he/he-frame-exchange-manager.cc index d2960ebf1..73d598694 100644 --- a/src/wifi/model/he/he-frame-exchange-manager.cc +++ b/src/wifi/model/he/he-frame-exchange-manager.cc @@ -998,6 +998,12 @@ HeFrameExchangeManager::ForwardPsduMapDown(WifiConstPsduMap psduMap, WifiTxVecto txVector.SetAggregation(true); } + auto txDuration = WifiPhy::CalculateTxDuration(psduMap, txVector, m_phy->GetPhyBand()); + // The TXNAV timer is a single timer, shared by the EDCAFs within a STA, that is initialized + // with the duration from the Duration/ID field in the frame most recently successfully + // transmitted by the TXOP holder, except for PS-Poll frames. (Sec.10.23.2.2 IEEE 802.11-2020) + m_txNav = Max(m_txNav, Simulator::Now() + txDuration + psduMap.cbegin()->second->GetDuration()); + m_phy->Send(psduMap, txVector); } diff --git a/src/wifi/model/ht/ht-frame-exchange-manager.cc b/src/wifi/model/ht/ht-frame-exchange-manager.cc index 5851f205e..5dacad633 100644 --- a/src/wifi/model/ht/ht-frame-exchange-manager.cc +++ b/src/wifi/model/ht/ht-frame-exchange-manager.cc @@ -1148,6 +1148,15 @@ HtFrameExchangeManager::ForwardPsduDown(Ptr psdu, WifiTxVector& txVector.SetAggregation(true); } + auto txDuration = WifiPhy::CalculateTxDuration(psdu, txVector, m_phy->GetPhyBand()); + // The TXNAV timer is a single timer, shared by the EDCAFs within a STA, that is initialized + // with the duration from the Duration/ID field in the frame most recently successfully + // transmitted by the TXOP holder, except for PS-Poll frames. (Sec.10.23.2.2 IEEE 802.11-2020) + if (!psdu->GetHeader(0).IsPsPoll()) + { + m_txNav = Max(m_txNav, Simulator::Now() + txDuration + psdu->GetDuration()); + } + m_phy->Send(psdu, txVector); } diff --git a/src/wifi/model/qos-frame-exchange-manager.cc b/src/wifi/model/qos-frame-exchange-manager.cc index b931da361..163c07e37 100644 --- a/src/wifi/model/qos-frame-exchange-manager.cc +++ b/src/wifi/model/qos-frame-exchange-manager.cc @@ -657,6 +657,8 @@ QosFrameExchangeManager::TransmissionFailed() } m_initialFrame = false; m_sentFrameTo.clear(); + // reset TXNAV because transmission failed + m_txNav = Simulator::Now(); } void