wifi: Add new WifiMac::Enqueue methods to avoid code duplication

At this stage, these methods are not yet used.
This commit is contained in:
Stefano Avallone
2024-05-03 17:25:07 +02:00
committed by Stefano Avallone
parent 12d8a340bf
commit 35d4921402
11 changed files with 302 additions and 11 deletions

View File

@@ -222,6 +222,51 @@ MeshWifiInterfaceMac::SwitchFrequencyChannel(uint16_t new_id)
//-----------------------------------------------------------------------------
// Forward frame down
//-----------------------------------------------------------------------------
void
MeshWifiInterfaceMac::Enqueue(Ptr<WifiMpdu> mpdu, Mac48Address to, Mac48Address from)
{
NS_LOG_FUNCTION(this << *mpdu << to << from);
auto& hdr = mpdu->GetHeader();
auto packet = mpdu->GetPacket()->Copy();
hdr.SetAddr2(GetAddress());
hdr.SetAddr3(to);
hdr.SetAddr4(from);
hdr.SetDsFrom();
hdr.SetDsTo();
// Address 1 is unknown here. Routing plugin is responsible to correctly set it.
hdr.SetAddr1(Mac48Address());
// Filter packet through all installed plugins
for (auto i = m_plugins.end() - 1; i != m_plugins.begin() - 1; i--)
{
bool drop = !((*i)->UpdateOutcomingFrame(packet, hdr, from, to));
if (drop)
{
return; // plugin drops frame
}
}
// Assert that address1 is set. Assert will fail e.g. if there is no installed routing plugin.
NS_ASSERT(hdr.GetAddr1() != Mac48Address());
// Queue frame
if (GetWifiRemoteStationManager()->IsBrandNew(hdr.GetAddr1()))
{
// in adhoc mode, we assume that every destination
// supports all the rates we support.
for (const auto& mode : GetWifiPhy()->GetModeList())
{
GetWifiRemoteStationManager()->AddSupportedMode(hdr.GetAddr1(), mode);
}
GetWifiRemoteStationManager()->RecordDisassociated(hdr.GetAddr1());
}
m_stats.sentFrames++;
m_stats.sentBytes += packet->GetSize();
auto tid = hdr.GetQosTid();
NS_ASSERT(GetQosTxop(tid) != nullptr);
GetQosTxop(tid)->Queue(Create<WifiMpdu>(packet, hdr));
}
void
MeshWifiInterfaceMac::ForwardDown(Ptr<Packet> packet, Mac48Address from, Mac48Address to)
{

View File

@@ -264,6 +264,7 @@ class MeshWifiInterfaceMac : public WifiMac
typedef std::vector<Ptr<MeshWifiInterfaceMacPlugin>> PluginList; ///< PluginList typedef
void DoInitialize() override;
void Enqueue(Ptr<WifiMpdu> mpdu, Mac48Address to, Mac48Address from) override;
/// \name Mesh timing intervals
///@{

View File

@@ -71,6 +71,62 @@ AdhocWifiMac::CanForwardPacketsTo(Mac48Address to) const
return true;
}
void
AdhocWifiMac::Enqueue(Ptr<WifiMpdu> mpdu, Mac48Address to, Mac48Address from)
{
NS_LOG_FUNCTION(this << *mpdu << to << from);
if (GetWifiRemoteStationManager()->IsBrandNew(to))
{
// In ad hoc mode, we assume that every destination supports all the rates we support.
if (GetHtSupported(SINGLE_LINK_OP_ID))
{
GetWifiRemoteStationManager()->AddAllSupportedMcs(to);
GetWifiRemoteStationManager()->AddStationHtCapabilities(
to,
GetHtCapabilities(SINGLE_LINK_OP_ID));
}
if (GetVhtSupported(SINGLE_LINK_OP_ID))
{
GetWifiRemoteStationManager()->AddStationVhtCapabilities(
to,
GetVhtCapabilities(SINGLE_LINK_OP_ID));
}
if (GetHeSupported())
{
GetWifiRemoteStationManager()->AddStationHeCapabilities(
to,
GetHeCapabilities(SINGLE_LINK_OP_ID));
if (Is6GhzBand(SINGLE_LINK_OP_ID))
{
GetWifiRemoteStationManager()->AddStationHe6GhzCapabilities(
to,
GetHe6GhzBandCapabilities(SINGLE_LINK_OP_ID));
}
}
if (GetEhtSupported())
{
GetWifiRemoteStationManager()->AddStationEhtCapabilities(
to,
GetEhtCapabilities(SINGLE_LINK_OP_ID));
}
GetWifiRemoteStationManager()->AddAllSupportedModes(to);
GetWifiRemoteStationManager()->RecordDisassociated(to);
}
auto& hdr = mpdu->GetHeader();
hdr.SetAddr1(to);
hdr.SetAddr2(GetAddress());
hdr.SetAddr3(GetBssid(SINGLE_LINK_OP_ID));
hdr.SetDsNotFrom();
hdr.SetDsNotTo();
auto txop = hdr.IsQosData() ? StaticCast<Txop>(GetQosTxop(hdr.GetQosTid())) : GetTxop();
NS_ASSERT(txop);
txop->Queue(mpdu);
}
void
AdhocWifiMac::Enqueue(Ptr<Packet> packet, Mac48Address to)
{

View File

@@ -51,6 +51,7 @@ class AdhocWifiMac : public WifiMac
private:
void Receive(Ptr<const WifiMpdu> mpdu, uint8_t linkId) override;
void DoCompleteConfig() override;
void Enqueue(Ptr<WifiMpdu> mpdu, Mac48Address to, Mac48Address from) override;
};
} // namespace ns3

View File

@@ -525,6 +525,55 @@ ApWifiMac::Enqueue(Ptr<Packet> packet, Mac48Address to)
Enqueue(packet, to, GetAddress());
}
void
ApWifiMac::Enqueue(Ptr<WifiMpdu> mpdu, Mac48Address to, Mac48Address from)
{
NS_LOG_FUNCTION(this << *mpdu << to << from);
std::list<Mac48Address> addr2Set;
if (to.IsGroup())
{
// broadcast frames are transmitted on all the links
for (uint8_t linkId = 0; linkId < GetNLinks(); linkId++)
{
addr2Set.push_back(GetFrameExchangeManager(linkId)->GetAddress());
}
}
else
{
// the Transmitter Address (TA) is the MLD address only for non-broadcast data frames
// exchanged between two MLDs
addr2Set = {GetAddress()};
auto linkId = IsAssociated(to);
NS_ASSERT_MSG(linkId, "Station " << to << "is not associated, cannot send it a frame");
if (GetNLinks() == 1 || !GetWifiRemoteStationManager(*linkId)->GetMldAddress(to))
{
addr2Set = {GetFrameExchangeManager(*linkId)->GetAddress()};
}
}
for (auto addr2 = addr2Set.cbegin(); addr2 != addr2Set.cend(); ++addr2)
{
auto& hdr = mpdu->GetHeader();
hdr.SetAddr1(to);
hdr.SetAddr2(*addr2);
hdr.SetAddr3(from);
hdr.SetDsFrom();
hdr.SetDsNotTo();
auto txop = hdr.IsQosData() ? StaticCast<Txop>(GetQosTxop(hdr.GetQosTid())) : GetTxop();
NS_ASSERT(txop);
txop->Queue(mpdu);
// create another MPDU if needed
if (std::next(addr2) != addr2Set.cend())
{
mpdu = Create<WifiMpdu>(mpdu->GetPacket()->Copy(), hdr);
}
}
}
bool
ApWifiMac::SupportsSendFrom() const
{

View File

@@ -266,6 +266,7 @@ class ApWifiMac : public WifiMac
Mac48Address DoGetLocalAddress(const Mac48Address& remoteAddr) const override;
void Receive(Ptr<const WifiMpdu> mpdu, uint8_t linkId) override;
void DoCompleteConfig() override;
void Enqueue(Ptr<WifiMpdu> mpdu, Mac48Address to, Mac48Address from) override;
/**
* Check whether the supported rate set included in the received (Re)Association

View File

@@ -972,6 +972,38 @@ StaWifiMac::CanForwardPacketsTo(Mac48Address to) const
return IsAssociated();
}
void
StaWifiMac::NotifyDropPacketToEnqueue(Ptr<Packet> packet, Mac48Address to)
{
NS_LOG_FUNCTION(this << packet << to);
TryToEnsureAssociated();
}
void
StaWifiMac::Enqueue(Ptr<WifiMpdu> mpdu, Mac48Address to, Mac48Address from)
{
NS_LOG_FUNCTION(this << *mpdu << to << from);
auto& hdr = mpdu->GetHeader();
// the Receiver Address (RA) and the Transmitter Address (TA) are the MLD addresses only for
// non-broadcast data frames exchanged between two MLDs
auto linkIds = GetSetupLinkIds();
NS_ASSERT(!linkIds.empty());
uint8_t linkId = *linkIds.begin();
const auto apMldAddr = GetWifiRemoteStationManager(linkId)->GetMldAddress(GetBssid(linkId));
hdr.SetAddr1(apMldAddr.value_or(GetBssid(linkId)));
hdr.SetAddr2(apMldAddr ? GetAddress() : GetFrameExchangeManager(linkId)->GetAddress());
hdr.SetAddr3(to);
hdr.SetDsNotFrom();
hdr.SetDsTo();
auto txop = hdr.IsQosData() ? StaticCast<Txop>(GetQosTxop(hdr.GetQosTid())) : GetTxop();
NS_ASSERT(txop);
txop->Queue(mpdu);
}
void
StaWifiMac::Enqueue(Ptr<Packet> packet, Mac48Address to)
{

View File

@@ -410,6 +410,8 @@ class StaWifiMac : public WifiMac
void Receive(Ptr<const WifiMpdu> mpdu, uint8_t linkId) override;
std::unique_ptr<LinkEntity> CreateLinkEntity() const override;
Mac48Address DoGetLocalAddress(const Mac48Address& remoteAddr) const override;
void Enqueue(Ptr<WifiMpdu> mpdu, Mac48Address to, Mac48Address from) override;
void NotifyDropPacketToEnqueue(Ptr<Packet> packet, Mac48Address to) override;
/**
* Process the Beacon frame received on the given link.

View File

@@ -37,6 +37,7 @@
#include "ns3/packet.h"
#include "ns3/pointer.h"
#include "ns3/shuffle.h"
#include "ns3/socket.h"
#include "ns3/string.h"
#include "ns3/vht-configuration.h"
@@ -1617,15 +1618,80 @@ WifiMac::UnblockUnicastTxOnLinks(WifiQueueBlockedReason reason,
}
}
void
WifiMac::Enqueue(Ptr<Packet> packet, Mac48Address to)
{
NS_LOG_FUNCTION(this << packet << to);
// We're sending this packet with a from address that is our own. We
// get that address from the lower MAC and make use of the
// from-spoofing Enqueue() method to avoid duplicated code.
Enqueue(packet, to, GetAddress());
}
void
WifiMac::Enqueue(Ptr<Packet> packet, Mac48Address to, Mac48Address from)
{
// We expect WifiMac subclasses which do support forwarding (e.g.,
// AP) to override this method. Therefore, we throw a fatal error if
// someone tries to invoke this method on a class which has not done
// this.
NS_FATAL_ERROR("This MAC entity (" << this << ", " << GetAddress()
<< ") does not support Enqueue() with from address");
NS_LOG_FUNCTION(this << packet << to << from);
// If we are not a QoS AP then we definitely want to use AC_BE to
// transmit the packet. A TID of zero will map to AC_BE (through \c
// QosUtilsMapTidToAc()), so we use that as our default here.
uint8_t tid = 0;
SocketPriorityTag qos;
if (packet->RemovePacketTag(qos) && qos.GetPriority() < 8)
{
tid = qos.GetPriority();
}
Enqueue(packet, to, from, tid);
}
void
WifiMac::Enqueue(Ptr<Packet> packet, Mac48Address to, Mac48Address from, uint8_t tid)
{
NS_LOG_FUNCTION(this << packet << to << from << tid);
NS_ABORT_MSG_IF(!SupportsSendFrom() && from != GetAddress(),
"This Mac does not support forwarding frames");
if (!CanForwardPacketsTo(to))
{
NotifyTxDrop(packet);
NotifyDropPacketToEnqueue(packet, to);
return;
}
WifiMacHeader hdr;
// For now, an AP that supports QoS does not support non-QoS
// associations, and vice versa. In future the AP model should
// support simultaneously associated QoS and non-QoS STAs, at which
// point there will need to be per-association QoS state maintained
// by the association state machine, and consulted here.
if (GetQosSupported())
{
hdr.SetType(WIFI_MAC_QOSDATA);
hdr.SetQosAckPolicy(WifiMacHeader::NORMAL_ACK);
hdr.SetQosNoEosp();
hdr.SetQosNoAmsdu();
hdr.SetQosTid(tid);
hdr.SetNoOrder(); // explicitly set to 0 for the time being since HT control field is not
// yet implemented (set it to 1 when implemented)
}
else
{
hdr.SetType(WIFI_MAC_DATA);
}
// create an MPDU and pass it to subclasses to finalize MAC header
Enqueue(Create<WifiMpdu>(packet, hdr), to, from);
}
void
WifiMac::NotifyDropPacketToEnqueue(Ptr<Packet> packet, Mac48Address to)
{
NS_LOG_FUNCTION(this << packet << to);
}
void

View File

@@ -370,27 +370,43 @@ class WifiMac : public Object
* \return whether packets can be forwarded to the given destination
*/
virtual bool CanForwardPacketsTo(Mac48Address to) const = 0;
/**
* \param packet the packet to send.
* \param to the address to which the packet should be sent.
*
* The packet should be enqueued in a TX queue, and should be
* dequeued as soon as the DCF/EDCA function determines that
* access is granted to this MAC.
*/
virtual void Enqueue(Ptr<Packet> packet, Mac48Address to);
/**
* \param packet the packet to send.
* \param to the address to which the packet should be sent.
* \param from the address from which the packet should be sent.
*
* The packet should be enqueued in a TX queue, and should be
* dequeued as soon as the DCF function determines that
* access it granted to this MAC. The extra parameter "from" allows
* dequeued as soon as the DCF/EDCA function determines that
* access is granted to this MAC. The extra parameter "from" allows
* this device to operate in a bridged mode, forwarding received
* frames without altering the source address.
*/
virtual void Enqueue(Ptr<Packet> packet, Mac48Address to, Mac48Address from);
/**
* \param packet the packet to send.
* \param to the address to which the packet should be sent.
* \param from the address from which the packet should be sent.
* \param tid the TID to use to send this packet
*
* The packet should be enqueued in a TX queue, and should be
* dequeued as soon as the DCF function determines that
* access it granted to this MAC.
* dequeued as soon as the DCF/EDCA function determines that
* access is granted to this MAC. The extra parameter "tid" allows
* to specify the TID to use in case QoS is supported.
*/
virtual void Enqueue(Ptr<Packet> packet, Mac48Address to) = 0;
void Enqueue(Ptr<Packet> packet, Mac48Address to, Mac48Address from, uint8_t tid);
/**
* \return if this MAC supports sending from arbitrary address.
*
@@ -1114,6 +1130,24 @@ class WifiMac : public Object
*/
void SetBkBlockAckInactivityTimeout(uint16_t timeout);
/**
* \param mpdu the MPDU to send.
* \param to the address to which the packet should be sent.
* \param from the address from which the packet should be sent.
*
* Subclasses need to implement this method to finalize the MAC header of the MPDU
* (MAC addresses and ToDS/FromDS flags) and enqueue the MPDU in a TX queue.
*/
virtual void Enqueue(Ptr<WifiMpdu> mpdu, Mac48Address to, Mac48Address from) = 0;
/**
* Allow subclasses to take actions when a packet to enqueue has been dropped.
*
* \param packet the dropped packet
* \param to the address to which the packet should have been sent
*/
virtual void NotifyDropPacketToEnqueue(Ptr<Packet> packet, Mac48Address to);
/**
* This Boolean is set \c true iff this WifiMac is to model
* 802.11e/WMM style Quality of Service. It is exposed through the

View File

@@ -221,6 +221,10 @@ class MldSwapLinksTest : public TestCase
void DoCompleteConfig() override
{
}
void Enqueue(Ptr<WifiMpdu> mpdu, Mac48Address to, Mac48Address from) override
{
}
};
public: