diff --git a/src/mesh/model/mesh-wifi-interface-mac.cc b/src/mesh/model/mesh-wifi-interface-mac.cc index 0dd2cc6c1..366518581 100644 --- a/src/mesh/model/mesh-wifi-interface-mac.cc +++ b/src/mesh/model/mesh-wifi-interface-mac.cc @@ -205,7 +205,7 @@ MeshWifiInterfaceMac::SwitchFrequencyChannel (uint16_t new_id) */ GetWifiPhy ()->SetOperatingChannel (WifiPhy::ChannelTuple {new_id, 0, GetWifiPhy ()->GetPhyBand (), 0}); // Don't know NAV on new channel - m_channelAccessManager->NotifyNavResetNow (Seconds (0)); + GetLink (SINGLE_LINK_OP_ID).channelAccessManager->NotifyNavResetNow (Seconds (0)); } //----------------------------------------------------------------------------- // Forward frame down diff --git a/src/wave/model/default-channel-scheduler.cc b/src/wave/model/default-channel-scheduler.cc index 5ba0540e9..c1e27656a 100644 --- a/src/wave/model/default-channel-scheduler.cc +++ b/src/wave/model/default-channel-scheduler.cc @@ -369,7 +369,7 @@ DefaultChannelScheduler::SwitchToNextChannel (uint32_t curChannelNumber, uint32_ // first make current MAC entity in sleep mode. curMacEntity->Suspend (); // second unattached current MAC entity from single PHY device - curMacEntity->ResetWifiPhy (); + curMacEntity->ResetWifiPhys (); // third switch PHY device from current channel to next channel; m_phy->SetOperatingChannel (WifiPhy::ChannelTuple {nextChannelNumber, 0, WIFI_PHY_BAND_5GHZ, 0}); // four attach next MAC entity to single PHY device diff --git a/src/wave/model/ocb-wifi-mac.cc b/src/wave/model/ocb-wifi-mac.cc index 02af5ae22..fc58bd99e 100644 --- a/src/wave/model/ocb-wifi-mac.cc +++ b/src/wave/model/ocb-wifi-mac.cc @@ -379,23 +379,24 @@ OcbWifiMac::ConfigureEdca (uint32_t cwmin, uint32_t cwmax, uint32_t aifsn, enum break; } - dcf->SetChannelAccessManager (m_channelAccessManager); + dcf->SetChannelAccessManager (GetLink (SINGLE_LINK_OP_ID).channelAccessManager); } void OcbWifiMac::SetWifiPhy (Ptr phy) { NS_LOG_FUNCTION (this << phy); - WifiMac::SetWifiPhy (phy); + WifiMac::SetWifiPhys ({phy}); NS_ABORT_MSG_IF (!phy->GetOperatingChannel ().IsSet (), "PHY operating channel must have been set"); - if (m_channelAccessManager != nullptr) + auto& link = GetLink (SINGLE_LINK_OP_ID); + if (link.channelAccessManager != nullptr) { - m_channelAccessManager->SetupPhyListener (phy); + link.channelAccessManager->SetupPhyListener (phy); } - if (m_feManager != nullptr) + if (link.feManager != nullptr) { - m_feManager->SetWifiPhy (phy); + link.feManager->SetWifiPhy (phy); } } @@ -405,8 +406,15 @@ OcbWifiMac::ConfigureStandard (enum WifiStandard standard) NS_LOG_FUNCTION (this << standard); NS_ASSERT (standard == WIFI_STANDARD_80211p); + if (GetNLinks () == 0) + { + WifiMac::SetWifiPhys ({nullptr}); // for the purpose of adding a link + } + + auto& link = GetLink (SINGLE_LINK_OP_ID); + // Setup ChannelAccessManager - m_channelAccessManager = CreateObject (); + link.channelAccessManager = CreateObject (); uint32_t cwmin = 15; uint32_t cwmax = 1023; @@ -429,17 +437,18 @@ OcbWifiMac::ConfigureStandard (enum WifiStandard standard) } // Setup FrameExchangeManager - m_feManager = CreateObject (); - m_feManager->SetWifiMac (this); - m_feManager->SetMacTxMiddle (m_txMiddle); - m_feManager->SetMacRxMiddle (m_rxMiddle); - m_feManager->SetAddress (GetAddress ()); - m_channelAccessManager->SetupFrameExchangeManager (m_feManager); + auto feManager = CreateObject (); + feManager->SetWifiMac (this); + feManager->SetMacTxMiddle (m_txMiddle); + feManager->SetMacRxMiddle (m_rxMiddle); + feManager->SetAddress (GetAddress ()); + link.channelAccessManager->SetupFrameExchangeManager (feManager); if (auto phy = GetWifiPhy (); phy != nullptr) { - m_feManager->SetWifiPhy (phy); - m_channelAccessManager->SetupPhyListener (phy); + feManager->SetWifiPhy (phy); + link.channelAccessManager->SetupPhyListener (phy); } + link.feManager = feManager; } @@ -447,8 +456,8 @@ void OcbWifiMac::Suspend (void) { NS_LOG_FUNCTION (this); - m_channelAccessManager->NotifySleepNow (); - m_feManager->NotifySleepNow (); + GetLink (SINGLE_LINK_OP_ID).channelAccessManager->NotifySleepNow (); + GetLink (SINGLE_LINK_OP_ID).feManager->NotifySleepNow (); } void @@ -456,14 +465,14 @@ OcbWifiMac::Resume (void) { NS_LOG_FUNCTION (this); // wake-up operation is not required in m_low object - m_channelAccessManager->NotifyWakeupNow (); + GetLink (SINGLE_LINK_OP_ID).channelAccessManager->NotifyWakeupNow (); } void OcbWifiMac::MakeVirtualBusy (Time duration) { NS_LOG_FUNCTION (this << duration); - m_channelAccessManager->NotifyCcaBusyStartNow (duration, WIFI_CHANLIST_PRIMARY, {}); + GetLink (SINGLE_LINK_OP_ID).channelAccessManager->NotifyCcaBusyStartNow (duration, WIFI_CHANLIST_PRIMARY, {}); } void @@ -481,8 +490,8 @@ OcbWifiMac::Reset (void) { NS_LOG_FUNCTION (this); // The switching event is used to notify MAC entity reset its operation. - m_channelAccessManager->NotifySwitchingStartNow (Time (0)); - m_feManager->NotifySwitchingStartNow (Time (0)); + GetLink (SINGLE_LINK_OP_ID).channelAccessManager->NotifySwitchingStartNow (Time (0)); + GetLink (SINGLE_LINK_OP_ID).feManager->NotifySwitchingStartNow (Time (0)); } void @@ -490,7 +499,7 @@ OcbWifiMac::EnableForWave (Ptr device) { NS_LOG_FUNCTION (this << device); // To extend current OcbWifiMac for WAVE 1609.4, we shall use WaveFrameExchangeManager - StaticCast (m_feManager)->SetWaveNetDevice (device); + StaticCast (GetLink (SINGLE_LINK_OP_ID).feManager)->SetWaveNetDevice (device); } void diff --git a/src/wave/model/ocb-wifi-mac.h b/src/wave/model/ocb-wifi-mac.h index 16047befb..0ab5b1b65 100644 --- a/src/wave/model/ocb-wifi-mac.h +++ b/src/wave/model/ocb-wifi-mac.h @@ -174,10 +174,15 @@ public: * Reset current MAC entity and flush its internal queues. */ void Reset (void); + /** + * Set the PHY. + * + * \param phy the PHY object + */ + void SetWifiPhy (Ptr phy); // Inherited from base class virtual void ConfigureStandard (enum WifiStandard standard); - virtual void SetWifiPhy (Ptr phy); protected: virtual void DoDispose (void); private: diff --git a/src/wifi/model/ap-wifi-mac.cc b/src/wifi/model/ap-wifi-mac.cc index 28770a4d3..b4a7f31d5 100644 --- a/src/wifi/model/ap-wifi-mac.cc +++ b/src/wifi/model/ap-wifi-mac.cc @@ -148,7 +148,7 @@ ApWifiMac::ConfigureStandard (WifiStandard standard) { NS_LOG_FUNCTION (this << standard); WifiMac::ConfigureStandard (standard); - m_beaconTxop->SetChannelAccessManager (m_channelAccessManager); + m_beaconTxop->SetChannelAccessManager (GetLink (SINGLE_LINK_OP_ID).channelAccessManager); } Ptr diff --git a/src/wifi/model/frame-exchange-manager.cc b/src/wifi/model/frame-exchange-manager.cc index ddefed479..c54cc3524 100644 --- a/src/wifi/model/frame-exchange-manager.cc +++ b/src/wifi/model/frame-exchange-manager.cc @@ -167,10 +167,14 @@ FrameExchangeManager::SetWifiPhy (Ptr phy) void FrameExchangeManager::ResetPhy (void) { - m_phy->TraceDisconnectWithoutContext ("PhyRxPayloadBegin", - MakeCallback (&FrameExchangeManager::RxStartIndication, this)); - m_phy->SetReceiveOkCallback (MakeNullCallback, RxSignalInfo, WifiTxVector, std::vector> ()); - m_phy = 0; + NS_LOG_FUNCTION (this); + if (m_phy != nullptr) + { + m_phy->TraceDisconnectWithoutContext ("PhyRxPayloadBegin", + MakeCallback (&FrameExchangeManager::RxStartIndication, this)); + m_phy->SetReceiveOkCallback (MakeNullCallback, RxSignalInfo, WifiTxVector, std::vector> ()); + m_phy = nullptr; + } } void diff --git a/src/wifi/model/sta-wifi-mac.cc b/src/wifi/model/sta-wifi-mac.cc index 1213bda44..42245eaa6 100644 --- a/src/wifi/model/sta-wifi-mac.cc +++ b/src/wifi/model/sta-wifi-mac.cc @@ -140,11 +140,14 @@ StaWifiMac::GetActiveProbing (void) const } void -StaWifiMac::SetWifiPhy (const Ptr phy) +StaWifiMac::SetWifiPhys (const std::vector>& phys) { - NS_LOG_FUNCTION (this << phy); - WifiMac::SetWifiPhy (phy); - GetWifiPhy ()->SetCapabilitiesChangedCallback (MakeCallback (&StaWifiMac::PhyCapabilitiesChanged, this)); + NS_LOG_FUNCTION (this); + WifiMac::SetWifiPhys (phys); + for (auto& phy : phys) + { + phy->SetCapabilitiesChangedCallback (MakeCallback (&StaWifiMac::PhyCapabilitiesChanged, this)); + } } void diff --git a/src/wifi/model/sta-wifi-mac.h b/src/wifi/model/sta-wifi-mac.h index bb4fdf965..cc9e7d57c 100644 --- a/src/wifi/model/sta-wifi-mac.h +++ b/src/wifi/model/sta-wifi-mac.h @@ -133,9 +133,9 @@ public: bool CanForwardPacketsTo (Mac48Address to) const override; /** - * \param phy the physical layer attached to this MAC. + * \param phys the physical layers attached to this MAC. */ - void SetWifiPhy (const Ptr phy) override; + void SetWifiPhys (const std::vector>& phys) override; /** * Return whether we are associated with an AP. diff --git a/src/wifi/model/wifi-mac.cc b/src/wifi/model/wifi-mac.cc index 15fc57163..0ad693b6f 100644 --- a/src/wifi/model/wifi-mac.cc +++ b/src/wifi/model/wifi-mac.cc @@ -342,12 +342,7 @@ WifiMac::DoDispose () m_rxMiddle = 0; m_txMiddle = 0; - - if (m_channelAccessManager != nullptr) - { - m_channelAccessManager->Dispose (); - } - m_channelAccessManager = 0; + m_links.clear (); if (m_txop != nullptr) { @@ -361,18 +356,23 @@ WifiMac::DoDispose () it->second = 0; } - if (m_feManager != 0) - { - m_feManager->Dispose (); - } - m_feManager = 0; - m_stationManager = 0; - m_phy = 0; - m_device = 0; } +WifiMac::LinkEntity::~LinkEntity () +{ + // WifiMac owns pointers to ChannelAccessManager and FrameExchangeManager + if (channelAccessManager != nullptr) + { + channelAccessManager->Dispose (); + } + if (feManager != nullptr) + { + feManager->Dispose (); + } +} + void WifiMac::SetTypeOfStation (TypeOfStation type) { @@ -429,9 +429,9 @@ WifiMac::SetBssid (Mac48Address bssid) { NS_LOG_FUNCTION (this << bssid); m_bssid = bssid; - if (m_feManager) + for (auto& link : m_links) { - m_feManager->SetBssid (bssid); + link->feManager->SetBssid (bssid); } } @@ -444,8 +444,10 @@ WifiMac::GetBssid (void) const void WifiMac::SetPromisc (void) { - NS_ASSERT (m_feManager != 0); - m_feManager->SetPromisc (); + for (auto& link : m_links) + { + link->feManager->SetPromisc (); + } } Ptr @@ -518,7 +520,7 @@ WifiMac::NotifyChannelSwitching (void) // SetupPhy not only resets the remote station manager, but also sets the // default TX mode and MCS, which is required when switching to a channel // in a different band - m_stationManager->SetupPhy (m_phy); + m_stationManager->SetupPhy (GetLink (SINGLE_LINK_OP_ID).phy); } void @@ -656,39 +658,54 @@ WifiMac::ConfigureStandard (WifiStandard standard) { NS_LOG_FUNCTION (this << standard); NS_ABORT_IF (standard >= WIFI_STANDARD_80211n && !m_qosSupported); - NS_ABORT_MSG_IF (m_phy == nullptr || !m_phy->GetOperatingChannel ().IsSet (), - "PHY must have been set and an operating channel must have been set"); + NS_ABORT_MSG_IF (m_links.empty (), "No PHY configured yet"); - m_channelAccessManager = CreateObject (); - m_channelAccessManager->SetupPhyListener (m_phy); + for (auto& link : m_links) + { + NS_ABORT_MSG_IF (link->phy == nullptr || !link->phy->GetOperatingChannel ().IsSet (), + "[LinkID " << link->id << "] PHY must have been set and an operating channel must have been set"); + + // do not create a ChannelAccessManager and a FrameExchangeManager if they + // already exist (this function may be called after ResetWifiPhys) + if (link->channelAccessManager == nullptr) + { + link->channelAccessManager = CreateObject (); + } + link->channelAccessManager->SetupPhyListener (link->phy); + + if (link->feManager == nullptr) + { + link->feManager = SetupFrameExchangeManager (standard); + } + link->feManager->SetWifiPhy (link->phy); + link->feManager->SetWifiMac (this); + link->channelAccessManager->SetupFrameExchangeManager (link->feManager); + } ConfigurePhyDependentParameters (); - SetupFrameExchangeManager (standard); - m_feManager->SetWifiPhy (m_phy); - m_channelAccessManager->SetupFrameExchangeManager (m_feManager); - if (m_txop != nullptr) { - m_txop->SetChannelAccessManager (m_channelAccessManager); + m_txop->SetChannelAccessManager (m_links[SINGLE_LINK_OP_ID]->channelAccessManager); } for (auto it = m_edca.begin (); it!= m_edca.end (); ++it) { - it->second->SetChannelAccessManager (m_channelAccessManager); + it->second->SetChannelAccessManager (m_links[SINGLE_LINK_OP_ID]->channelAccessManager); } } void WifiMac::ConfigurePhyDependentParameters (void) { - WifiPhyBand band = m_phy->GetPhyBand (); + auto& link = GetLink (SINGLE_LINK_OP_ID); + NS_ASSERT (link.phy != nullptr); + WifiPhyBand band = link.phy->GetPhyBand (); NS_LOG_FUNCTION (this << band); uint32_t cwmin = 0; uint32_t cwmax = 0; - NS_ASSERT (m_phy != 0); - WifiStandard standard = m_phy->GetStandard (); + WifiStandard standard = link.phy->GetStandard (); if (standard == WIFI_STANDARD_80211b) { @@ -710,60 +727,61 @@ WifiMac::ConfigurePhyDependentParameters (void) ConfigureContentionWindow (cwmin, cwmax); } -void +Ptr WifiMac::SetupFrameExchangeManager (WifiStandard standard) { NS_LOG_FUNCTION (this << standard); NS_ABORT_MSG_IF (standard == WIFI_STANDARD_UNSPECIFIED, "Wifi standard not set"); + Ptr feManager; if (standard >= WIFI_STANDARD_80211ax) { - m_feManager = CreateObject (); + feManager = CreateObject (); } else if (standard >= WIFI_STANDARD_80211ac) { - m_feManager = CreateObject (); + feManager = CreateObject (); } else if (standard >= WIFI_STANDARD_80211n) { - m_feManager = CreateObject (); + feManager = CreateObject (); } else if (m_qosSupported) { - m_feManager = CreateObject (); + feManager = CreateObject (); } else { - m_feManager = CreateObject (); + feManager = CreateObject (); } - m_feManager->SetWifiMac (this); - m_feManager->SetMacTxMiddle (m_txMiddle); - m_feManager->SetMacRxMiddle (m_rxMiddle); - m_feManager->SetAddress (GetAddress ()); - m_feManager->SetBssid (GetBssid ()); - m_feManager->GetWifiTxTimer ().SetMpduResponseTimeoutCallback (MakeCallback (&MpduResponseTimeoutTracedCallback::operator(), - &m_mpduResponseTimeoutCallback)); - m_feManager->GetWifiTxTimer ().SetPsduResponseTimeoutCallback (MakeCallback (&PsduResponseTimeoutTracedCallback::operator(), - &m_psduResponseTimeoutCallback)); - m_feManager->GetWifiTxTimer ().SetPsduMapResponseTimeoutCallback (MakeCallback (&PsduMapResponseTimeoutTracedCallback::operator(), - &m_psduMapResponseTimeoutCallback)); - m_feManager->SetDroppedMpduCallback (MakeCallback (&DroppedMpduTracedCallback::operator(), - &m_droppedMpduCallback)); - m_feManager->SetAckedMpduCallback (MakeCallback (&MpduTracedCallback::operator(), - &m_ackedMpduCallback)); + feManager->SetMacTxMiddle (m_txMiddle); + feManager->SetMacRxMiddle (m_rxMiddle); + feManager->SetAddress (GetAddress ()); + feManager->SetBssid (GetBssid ()); + feManager->GetWifiTxTimer ().SetMpduResponseTimeoutCallback (MakeCallback (&MpduResponseTimeoutTracedCallback::operator(), + &m_mpduResponseTimeoutCallback)); + feManager->GetWifiTxTimer ().SetPsduResponseTimeoutCallback (MakeCallback (&PsduResponseTimeoutTracedCallback::operator(), + &m_psduResponseTimeoutCallback)); + feManager->GetWifiTxTimer ().SetPsduMapResponseTimeoutCallback (MakeCallback (&PsduMapResponseTimeoutTracedCallback::operator(), + &m_psduMapResponseTimeoutCallback)); + feManager->SetDroppedMpduCallback (MakeCallback (&DroppedMpduTracedCallback::operator(), + &m_droppedMpduCallback)); + feManager->SetAckedMpduCallback (MakeCallback (&MpduTracedCallback::operator(), + &m_ackedMpduCallback)); + return feManager; } Ptr -WifiMac::GetFrameExchangeManager (void) const +WifiMac::GetFrameExchangeManager (uint8_t linkId) const { - return m_feManager; + return GetLink (linkId).feManager; } Ptr -WifiMac::GetChannelAccessManager (void) const +WifiMac::GetChannelAccessManager (uint8_t linkId) const { - return m_channelAccessManager; + return GetLink (linkId).channelAccessManager; } void @@ -779,28 +797,74 @@ WifiMac::GetWifiRemoteStationManager () const return m_stationManager; } -void -WifiMac::SetWifiPhy (const Ptr phy) +std::unique_ptr +WifiMac::CreateLinkEntity (void) const { - NS_LOG_FUNCTION (this << phy); - m_phy = phy; + return std::make_unique (); +} + +WifiMac::LinkEntity& +WifiMac::GetLink (uint8_t linkId) const +{ + NS_ASSERT (linkId < m_links.size ()); + NS_ASSERT (m_links.at (linkId)); // check that the pointer owns an object + return *m_links.at (linkId); +} + +uint8_t +WifiMac::GetNLinks (void) const +{ + return m_links.size (); +} + +void +WifiMac::SetWifiPhys (const std::vector>& phys) +{ + NS_LOG_FUNCTION (this); + ResetWifiPhys (); + + NS_ABORT_MSG_UNLESS (m_links.size () == 0 || m_links.size () == phys.size (), + "If links have been already created, the number of provided " + "PHY objects (" << phys.size () << ") must match the number " + "of links (" << m_links.size () << ")"); + + for (std::size_t i = 0; i < phys.size (); i++) + { + // the link may already exist in case we are setting new PHY objects + // (ResetWifiPhys just nullified the PHY(s) but left the links) + if (i == m_links.size ()) + { + m_links.push_back (CreateLinkEntity ()); + m_links.back ()->id = i; + } + NS_ABORT_IF (i != m_links[i]->id); + m_links[i]->phy = phys[i]; + } } Ptr -WifiMac::GetWifiPhy (void) const +WifiMac::GetWifiPhy (uint8_t linkId) const { - NS_LOG_FUNCTION (this); - return m_phy; + NS_LOG_FUNCTION (this << +linkId); + return GetLink (linkId).phy; } void -WifiMac::ResetWifiPhy (void) +WifiMac::ResetWifiPhys (void) { NS_LOG_FUNCTION (this); - NS_ASSERT (m_feManager != 0); - m_feManager->ResetPhy (); - m_channelAccessManager->RemovePhyListener (m_phy); - m_phy = 0; + for (auto& link : m_links) + { + if (link->feManager != nullptr) + { + link->feManager->ResetPhy (); + } + if (link->channelAccessManager != nullptr) + { + link->channelAccessManager->RemovePhyListener (link->phy); + } + link->phy = nullptr; + } } void @@ -941,6 +1005,7 @@ WifiMac::Receive (Ptr mpdu) Ptr packet = mpdu->GetPacket ()->Copy (); Mac48Address to = hdr->GetAddr1 (); Mac48Address from = hdr->GetAddr2 (); + auto& link = GetLink (SINGLE_LINK_OP_ID); //We don't know how to deal with any frame that is not addressed to //us (and odds are there is nothing sensible we could do anyway), @@ -976,8 +1041,8 @@ WifiMac::Receive (Ptr mpdu) //We've received an ADDBA Request. Our policy here is //to automatically accept it, so we get the ADDBA //Response on it's way immediately. - NS_ASSERT (m_feManager != 0); - Ptr htFem = DynamicCast (m_feManager); + NS_ASSERT (link.feManager != nullptr); + auto htFem = DynamicCast (link.feManager); if (htFem != 0) { htFem->SendAddBaResponse (&reqHdr, from); @@ -997,7 +1062,7 @@ WifiMac::Receive (Ptr mpdu) //and act by locally establishing the agreement on //the appropriate queue. GetQosTxop (respHdr.GetTid ())->GotAddBaResponse (&respHdr, from); - auto htFem = DynamicCast (m_feManager); + auto htFem = DynamicCast (link.feManager); if (htFem != 0) { GetQosTxop (respHdr.GetTid ())->GetBaManager ()->SetBlockAckInactivityCallback (MakeCallback (&HtFrameExchangeManager::SendDelbaFrame, htFem)); @@ -1016,8 +1081,8 @@ WifiMac::Receive (Ptr mpdu) //this means that an ingoing established //agreement exists in HtFrameExchangeManager and we need to //destroy it. - NS_ASSERT (m_feManager != 0); - Ptr htFem = DynamicCast (m_feManager); + NS_ASSERT (link.feManager != nullptr); + auto htFem = DynamicCast (link.feManager); if (htFem != 0) { htFem->DestroyBlockAckAgreement (from, delBaHdr.GetTid ()); @@ -1352,19 +1417,20 @@ WifiMac::GetHeCapabilities (void) const HeCapabilities capabilities; if (GetHeSupported ()) { + Ptr phy = GetLink (SINGLE_LINK_OP_ID).phy; Ptr htConfiguration = GetHtConfiguration (); Ptr heConfiguration = GetHeConfiguration (); capabilities.SetHeSupported (1); uint8_t channelWidthSet = 0; - if ((m_phy->GetChannelWidth () >= 40) && (m_phy->GetPhyBand () == WIFI_PHY_BAND_2_4GHZ)) + if ((phy->GetChannelWidth () >= 40) && (phy->GetPhyBand () == WIFI_PHY_BAND_2_4GHZ)) { channelWidthSet |= 0x01; } - if ((m_phy->GetChannelWidth () >= 80) && ((m_phy->GetPhyBand () == WIFI_PHY_BAND_5GHZ) || (m_phy->GetPhyBand () == WIFI_PHY_BAND_6GHZ))) + if ((phy->GetChannelWidth () >= 80) && ((phy->GetPhyBand () == WIFI_PHY_BAND_5GHZ) || (phy->GetPhyBand () == WIFI_PHY_BAND_6GHZ))) { channelWidthSet |= 0x02; } - if ((m_phy->GetChannelWidth () >= 160) && ((m_phy->GetPhyBand () == WIFI_PHY_BAND_5GHZ) || (m_phy->GetPhyBand () == WIFI_PHY_BAND_6GHZ))) + if ((phy->GetChannelWidth () >= 160) && ((phy->GetPhyBand () == WIFI_PHY_BAND_5GHZ) || (phy->GetPhyBand () == WIFI_PHY_BAND_6GHZ))) { channelWidthSet |= 0x04; } @@ -1386,7 +1452,7 @@ WifiMac::GetHeCapabilities (void) const capabilities.SetMaxAmpduLength (std::min (std::max (maxAmpduLength, 1048575u), 8388607u)); uint8_t maxMcs = 0; - for (const auto & mcs : m_phy->GetMcsList (WIFI_MOD_CLASS_HE)) + for (const auto & mcs : phy->GetMcsList (WIFI_MOD_CLASS_HE)) { if (mcs.GetMcsValue () > maxMcs) { @@ -1394,7 +1460,7 @@ WifiMac::GetHeCapabilities (void) const } } capabilities.SetHighestMcsSupported (maxMcs); - capabilities.SetHighestNssSupported (m_phy->GetMaxSupportedTxSpatialStreams ()); + capabilities.SetHighestNssSupported (phy->GetMaxSupportedTxSpatialStreams ()); } return capabilities; } diff --git a/src/wifi/model/wifi-mac.h b/src/wifi/model/wifi-mac.h index 2ee2b70ce..06c209fb3 100644 --- a/src/wifi/model/wifi-mac.h +++ b/src/wifi/model/wifi-mac.h @@ -27,6 +27,8 @@ #include "wifi-remote-station-manager.h" #include "qos-utils.h" #include "ssid.h" +#include +#include namespace ns3 { @@ -112,17 +114,27 @@ public: Ptr GetDevice (void) const; /** - * Get the Frame Exchange Manager + * Get the Frame Exchange Manager associated with the given link * + * \param linkId the ID of the given link * \return the Frame Exchange Manager */ - Ptr GetFrameExchangeManager (void) const; + Ptr GetFrameExchangeManager (uint8_t linkId = SINGLE_LINK_OP_ID) const; + /** - * Get the Channel Access Manager + * Get the Channel Access Manager associated with the given link * + * \param linkId the ID of the given link * \return the Channel Access Manager */ - Ptr GetChannelAccessManager (void) const; + Ptr GetChannelAccessManager (uint8_t linkId = SINGLE_LINK_OP_ID) const; + + /** + * Get the number of links (can be greater than 1 for 11be devices only). + * + * \return the number of links used by this MAC + */ + uint8_t GetNLinks (void) const; /** * Accessor for the Txop object @@ -249,17 +261,18 @@ public: virtual bool SupportsSendFrom (void) const; /** - * \param phy the physical layer attached to this MAC. + * \param phys the physical layers attached to this MAC. */ - virtual void SetWifiPhy (Ptr phy); + virtual void SetWifiPhys (const std::vector>& phys); /** + * \param linkId the index (starting at 0) of the PHY object to retrieve * \return the physical layer attached to this MAC */ - Ptr GetWifiPhy (void) const; + Ptr GetWifiPhy (uint8_t linkId = SINGLE_LINK_OP_ID) const; /** - * Remove currently attached WifiPhy device from this MAC. + * Remove currently attached WifiPhy objects from this MAC. */ - void ResetWifiPhy (void); + void ResetWifiPhys (void); /** * \param stationManager the station manager attached to this MAC. @@ -544,11 +557,35 @@ protected: */ virtual void DeaggregateAmsduAndForward (Ptr mpdu); + /** + * Structure holding information specific to a single link. Here, the meaning of + * "link" is that of the 11be amendment which introduced multi-link devices. For + * previous amendments, only one link can be created. Therefore, "link" has not + * to be confused with the general concept of link for a NetDevice (used by the + * m_linkUp and m_linkDown callbacks). + */ + struct LinkEntity + { + /// Destructor (a virtual method is needed to make this struct polymorphic) + virtual ~LinkEntity (); + + uint8_t id; //!< Link ID (starting at 0) + Ptr phy; //!< Wifi PHY object + Ptr channelAccessManager; //!< channel access manager object + Ptr feManager; //!< Frame Exchange Manager object + }; + + /** + * Get a reference to the link associated with the given ID. + * + * \param linkId the given link ID + * \return a reference to the link associated with the given ID + */ + LinkEntity& GetLink (uint8_t linkId) const; + Ptr m_rxMiddle; //!< RX middle (defragmentation etc.) Ptr m_txMiddle; //!< TX middle (aggregation etc.) - Ptr m_channelAccessManager; //!< channel access manager - Ptr m_feManager; //!< Frame Exchange Manager - Ptr m_txop; //!< TXOP used for transmission of frames to non-QoS peers. + Ptr m_txop; //!< TXOP used for transmission of frames to non-QoS peers. Callback m_linkUp; //!< Callback when a link is up Callback m_linkDown; //!< Callback when a link is down @@ -584,8 +621,16 @@ private: * of the standard. * * \param standard the supported version of the standard + * \return the created Frame Exchange Manager */ - void SetupFrameExchangeManager (WifiStandard standard); + Ptr SetupFrameExchangeManager (WifiStandard standard); + + /** + * Create a LinkEntity object. + * + * \return a unique pointer to the created LinkEntity object + */ + virtual std::unique_ptr CreateLinkEntity (void) const; /** * Enable or disable ERP support for the device. @@ -681,8 +726,8 @@ private: TypeOfStation m_typeOfStation; //!< the type of station Ptr m_device; //!< Pointer to the device - Ptr m_phy; //!< Wifi PHY Ptr m_stationManager; //!< Remote station manager (rate control, RTS/CTS/fragmentation thresholds etc.) + std::vector> m_links; //!< vector of Link objects Mac48Address m_address; //!< MAC address of this station Ssid m_ssid; //!< Service Set ID (SSID) diff --git a/src/wifi/model/wifi-net-device.cc b/src/wifi/model/wifi-net-device.cc index 11676c3d8..0c54fc8c0 100644 --- a/src/wifi/model/wifi-net-device.cc +++ b/src/wifi/model/wifi-net-device.cc @@ -195,7 +195,7 @@ WifiNetDevice::CompleteConfig (void) return; } m_mac->SetWifiRemoteStationManager (m_stationManager); - m_mac->SetWifiPhy (m_phys[SINGLE_LINK_OP_ID]); + m_mac->SetWifiPhys (m_phys); m_mac->SetForwardUpCallback (MakeCallback (&WifiNetDevice::ForwardUp, this)); m_mac->SetLinkUpCallback (MakeCallback (&WifiNetDevice::LinkUp, this)); m_mac->SetLinkDownCallback (MakeCallback (&WifiNetDevice::LinkDown, this)); diff --git a/src/wifi/test/wifi-aggregation-test.cc b/src/wifi/test/wifi-aggregation-test.cc index e924a89c3..b40f18693 100644 --- a/src/wifi/test/wifi-aggregation-test.cc +++ b/src/wifi/test/wifi-aggregation-test.cc @@ -126,7 +126,7 @@ AmpduAggregationTest::DoRun (void) m_mac->SetDevice (m_device); m_mac->SetWifiRemoteStationManager (m_manager); m_mac->SetAddress (Mac48Address ("00:00:00:00:00:01")); - m_mac->SetWifiPhy (m_phy); + m_mac->SetWifiPhys ({m_phy}); m_mac->ConfigureStandard (WIFI_STANDARD_80211n); Ptr fem = m_mac->GetFrameExchangeManager (); Ptr protectionManager = CreateObject (); @@ -377,7 +377,7 @@ TwoLevelAggregationTest::DoRun (void) m_mac->SetDevice (m_device); m_mac->SetWifiRemoteStationManager (m_manager); m_mac->SetAddress (Mac48Address ("00:00:00:00:00:01")); - m_mac->SetWifiPhy (m_phy); + m_mac->SetWifiPhys ({m_phy}); m_mac->ConfigureStandard (WIFI_STANDARD_80211n); Ptr fem = m_mac->GetFrameExchangeManager (); Ptr protectionManager = CreateObject (); @@ -613,7 +613,7 @@ HeAggregationTest::DoRunSubTest (uint16_t bufferSize) m_mac->SetDevice (m_device); m_mac->SetWifiRemoteStationManager (m_manager); m_mac->SetAddress (Mac48Address ("00:00:00:00:00:01")); - m_mac->SetWifiPhy (m_phy); + m_mac->SetWifiPhys ({m_phy}); m_mac->ConfigureStandard (WIFI_STANDARD_80211ax); Ptr fem = m_mac->GetFrameExchangeManager (); Ptr protectionManager = CreateObject ();