diff --git a/src/wifi/CMakeLists.txt b/src/wifi/CMakeLists.txt index ef17fdc1d..7915ff46c 100644 --- a/src/wifi/CMakeLists.txt +++ b/src/wifi/CMakeLists.txt @@ -27,6 +27,7 @@ set(source_files model/channel-access-manager.cc model/ctrl-headers.cc model/edca-parameter-set.cc + model/eht/advanced-emlsr-manager.cc model/eht/default-emlsr-manager.cc model/eht/eht-capabilities.cc model/eht/eht-configuration.cc @@ -186,6 +187,7 @@ set(header_files model/channel-access-manager.h model/ctrl-headers.h model/edca-parameter-set.h + model/eht/advanced-emlsr-manager.h model/eht/default-emlsr-manager.h model/eht/eht-capabilities.h model/eht/eht-configuration.h diff --git a/src/wifi/helper/wifi-helper.cc b/src/wifi/helper/wifi-helper.cc index 9db6317fc..1f098672f 100644 --- a/src/wifi/helper/wifi-helper.cc +++ b/src/wifi/helper/wifi-helper.cc @@ -885,6 +885,7 @@ WifiHelper::EnableLogComponents(LogLevel logLevel) LogComponentEnable("AarfWifiManager", logLevel); LogComponentEnable("AarfcdWifiManager", logLevel); LogComponentEnable("AdhocWifiMac", logLevel); + LogComponentEnable("AdvancedEmlsrManager", logLevel); LogComponentEnable("AmrrWifiManager", logLevel); LogComponentEnable("ApWifiMac", logLevel); LogComponentEnable("AparfWifiManager", logLevel); diff --git a/src/wifi/model/eht/advanced-emlsr-manager.cc b/src/wifi/model/eht/advanced-emlsr-manager.cc new file mode 100644 index 000000000..4fc550e74 --- /dev/null +++ b/src/wifi/model/eht/advanced-emlsr-manager.cc @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2024 Universita' di Napoli Federico II + * + * 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: Stefano Avallone + */ + +#include "advanced-emlsr-manager.h" + +#include "eht-frame-exchange-manager.h" + +#include "ns3/boolean.h" +#include "ns3/log.h" +#include "ns3/wifi-net-device.h" +#include "ns3/wifi-phy.h" + +namespace ns3 +{ + +NS_LOG_COMPONENT_DEFINE("AdvancedEmlsrManager"); + +NS_OBJECT_ENSURE_REGISTERED(AdvancedEmlsrManager); + +TypeId +AdvancedEmlsrManager::GetTypeId() +{ + static TypeId tid = + TypeId("ns3::AdvancedEmlsrManager") + .SetParent() + .SetGroupName("Wifi") + .AddConstructor() + .AddAttribute("UseNotifiedMacHdr", + "Whether to use the information about the MAC header of the MPDU " + "being received, if notified by the PHY.", + BooleanValue(true), + MakeBooleanAccessor(&AdvancedEmlsrManager::m_useNotifiedMacHdr), + MakeBooleanChecker()) + .AddAttribute("AllowUlTxopInRx", + "Whether a (main or aux) PHY is allowed to start an UL TXOP if " + "another PHY is receiving a PPDU (possibly starting a DL TXOP). " + "If this attribute is true, the PPDU may be dropped.", + BooleanValue(false), + MakeBooleanAccessor(&AdvancedEmlsrManager::m_allowUlTxopInRx), + MakeBooleanChecker()); + return tid; +} + +AdvancedEmlsrManager::AdvancedEmlsrManager() +{ + NS_LOG_FUNCTION(this); +} + +AdvancedEmlsrManager::~AdvancedEmlsrManager() +{ + NS_LOG_FUNCTION_NOARGS(); +} + +Time +AdvancedEmlsrManager::GetDelayUntilAccessRequest(uint8_t linkId) +{ + NS_LOG_FUNCTION(this << linkId); + + // prevent or allow an UL TXOP depending on whether another PHY is receiving a PPDU + for (const auto id : GetStaMac()->GetLinkIds()) + { + if (id != linkId && GetStaMac()->IsEmlsrLink(id)) + { + auto phy = GetStaMac()->GetWifiPhy(id); + + if (auto macHdr = GetEhtFem(id)->GetReceivedMacHdr(); macHdr && m_useNotifiedMacHdr) + { + NS_ASSERT(phy && + phy->GetState()->GetLastTime({WifiPhyState::RX}) == Simulator::Now()); + // we are receiving the MAC payload of a PSDU; if the PSDU being received on + // another link is an ICF, give up the TXOP and restart channel access at the + // end of PSDU reception. Note that we cannot be sure that the PSDU being received + // is an ICF addressed to us until we receive the entire PSDU + if (const auto& hdr = macHdr->get(); + hdr.IsTrigger() && + (hdr.GetAddr1().IsBroadcast() || hdr.GetAddr1() == GetEhtFem(id)->GetAddress())) + { + return phy->GetDelayUntilIdle(); + } + continue; + } + + if (phy && phy->IsReceivingPhyHeader()) + { + // we don't know yet the type of the frame being received; prevent or allow + // the UL TXOP based on user configuration + if (!m_allowUlTxopInRx) + { + // retry channel access after the end of the current PHY header field + return phy->GetDelayUntilIdle(); + } + continue; + } + + if (phy && phy->IsStateRx()) + { + // we don't know yet the type of the frame being received; prevent or allow + // the UL TXOP based on user configuration + if (!m_allowUlTxopInRx) + { + if (!m_useNotifiedMacHdr) + { + // restart channel access at the end of PSDU reception + return phy->GetDelayUntilIdle(); + } + + // retry channel access after the expected end of the MAC header reception + auto macHdrSize = WifiMacHeader(WIFI_MAC_QOSDATA).GetSerializedSize() + + 4 /* A-MPDU subframe header length */; + auto ongoingRxInfo = GetEhtFem(id)->GetOngoingRxInfo(); + // if a PHY is in RX state, it should have info about received MAC header. + // The exception is represented by this situation: + // - an aux PHY is disconnected from the MAC stack because the main PHY is + // operating on its link + // - the main PHY notifies the MAC header info to the FEM and then leaves the + // link (e.g., because it recognizes that the MPDU is not addressed to the + // EMLSR client). Disconnecting the main PHY from the MAC stack causes the + // MAC header info to be discarded by the FEM + // - the aux PHY is re-connected to the MAC stack and is still in RX state + // when the main PHY gets channel access on another link (and we get here) + if (!ongoingRxInfo.has_value()) + { + NS_ASSERT_MSG(phy != GetStaMac()->GetDevice()->GetPhy(GetMainPhyId()), + "Main PHY should have MAC header info when in RX state"); + // we are in the situation described above; if the MPDU being received + // by the aux PHY is not addressed to the EMLSR client, we can ignore it + continue; + } + const auto& txVector = ongoingRxInfo->get().txVector; + if (txVector.IsMu()) + { + // this is not an ICF, ignore it + continue; + } + auto macHdrDuration = DataRate(txVector.GetMode().GetDataRate(txVector)) + .CalculateBytesTxTime(macHdrSize); + const auto timeSinceRxStart = + Simulator::Now() - phy->GetState()->GetLastTime({WifiPhyState::CCA_BUSY}); + return Max(macHdrDuration - timeSinceRxStart, Time{0}); + } + continue; + } + } + } + + return Time{0}; +} + +} // namespace ns3 diff --git a/src/wifi/model/eht/advanced-emlsr-manager.h b/src/wifi/model/eht/advanced-emlsr-manager.h new file mode 100644 index 000000000..7c229519d --- /dev/null +++ b/src/wifi/model/eht/advanced-emlsr-manager.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2024 Universita' di Napoli Federico II + * + * 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: Stefano Avallone + */ + +#ifndef ADVANCED_EMLSR_MANAGER_H +#define ADVANCED_EMLSR_MANAGER_H + +#include "default-emlsr-manager.h" + +namespace ns3 +{ + +/** + * \ingroup wifi + * + * AdvancedEmlsrManager is an advanced EMLSR manager. + */ +class AdvancedEmlsrManager : public DefaultEmlsrManager +{ + public: + /** + * \brief Get the type ID. + * \return the object TypeId + */ + static TypeId GetTypeId(); + + AdvancedEmlsrManager(); + ~AdvancedEmlsrManager() override; + + Time GetDelayUntilAccessRequest(uint8_t linkId) override; + + private: + bool m_useNotifiedMacHdr; //!< whether to use the information about the MAC header of + //!< the MPDU being received (if notified by the PHY) + bool m_allowUlTxopInRx; //!< whether a (main or aux) PHY is allowed to start an UL + //!< TXOP if another PHY is receiving a PPDU +}; + +} // namespace ns3 + +#endif /* ADVANCED_EMLSR_MANAGER_H */