77
88#include " inet/linklayer/ieee80211/mac/rateselection/QosRateSelection.h"
99
10+ #include " inet/physicallayer/wireless/ieee80211/mode/Ieee80211HtMode.h"
11+
1012#include " inet/common/ModuleAccess.h"
1113#include " inet/common/Simsignals.h"
1214#include " inet/physicallayer/wireless/ieee80211/packetlevel/Ieee80211Tag_m.h"
@@ -16,6 +18,24 @@ namespace ieee80211 {
1618
1719using namespace inet ::physicallayer;
1820
21+ static const IIeee80211Mode *getConfiguredControlResponseMode (const Ieee80211ModeSet *modeSet, const IIeee80211Mode *mode)
22+ {
23+ // Explicit legacy/VHT overrides retain their requested mode; HT rates need the
24+ // bounded non-HT control-response conversion for ACK/BlockAck.
25+ return dynamic_cast <const Ieee80211HtMode *>(mode) != nullptr ? modeSet->getNonHtControlResponseMode (mode) : mode;
26+ }
27+
28+ static const IIeee80211Mode *getDynamicControlResponseMode (const Ieee80211ModeSet *modeSet, const IIeee80211Mode *mode)
29+ {
30+ if (dynamic_cast <const Ieee80211HtMode *>(mode) != nullptr || !modeSet->containsMode (mode))
31+ return modeSet->getNonHtControlResponseMode (mode);
32+ if (modeSet->getIsMandatory (mode))
33+ return mode;
34+ if (auto slowerMode = modeSet->getSlowerMandatoryMode (mode))
35+ return slowerMode;
36+ return modeSet->getNonHtControlResponseMode (mode);
37+ }
38+
1939Define_Module (QosRateSelection);
2040
2141void QosRateSelection::initialize (int stage)
@@ -31,15 +51,22 @@ void QosRateSelection::initialize(int stage)
3151 mgmtFrameMode = (mgmtFrameBitrate == -1 ) ? nullptr : modeSet->getMode (bps (mgmtFrameBitrate));
3252 double controlFrameBitrate = par (" controlFrameBitrate" );
3353 controlFrameMode = (controlFrameBitrate == -1 ) ? nullptr : modeSet->getMode (bps (controlFrameBitrate));
34- double responseAckFrameBitrate = par (" responseAckFrameBitrate" );
35- responseAckFrameMode = (responseAckFrameBitrate == -1 ) ? nullptr : modeSet->getMode (bps (responseAckFrameBitrate));
36- double responseBlockAckFrameBitrate = par (" responseBlockAckFrameBitrate" );
37- responseBlockAckFrameMode = (responseBlockAckFrameBitrate == -1 ) ? nullptr : modeSet->getMode (bps (responseBlockAckFrameBitrate));
38- double responseCtsFrameBitrate = par (" responseCtsFrameBitrate" );
39- responseCtsFrameMode = (responseCtsFrameBitrate == -1 ) ? nullptr : modeSet->getMode (bps (responseCtsFrameBitrate));
54+ resolveConfiguredResponseModes ();
4055 }
4156}
4257
58+ void QosRateSelection::resolveConfiguredResponseModes ()
59+ {
60+ if (modeSet == nullptr )
61+ return ;
62+ double responseAckFrameBitrate = par (" responseAckFrameBitrate" );
63+ responseAckFrameMode = responseAckFrameBitrate == -1 ? nullptr : modeSet->getMode (bps (responseAckFrameBitrate));
64+ double responseBlockAckFrameBitrate = par (" responseBlockAckFrameBitrate" );
65+ responseBlockAckFrameMode = responseBlockAckFrameBitrate == -1 ? nullptr : modeSet->getMode (bps (responseBlockAckFrameBitrate));
66+ double responseCtsFrameBitrate = par (" responseCtsFrameBitrate" );
67+ responseCtsFrameMode = responseCtsFrameBitrate == -1 ? nullptr : modeSet->getMode (bps (responseCtsFrameBitrate));
68+ }
69+
4370const IIeee80211Mode *QosRateSelection::getMode (Packet *packet, const Ptr<const Ieee80211MacHeader>& header)
4471{
4572 const auto & modeReqTag = packet->findTag <Ieee80211ModeReq>();
@@ -71,40 +98,25 @@ bool QosRateSelection::isControlResponseFrame(const Ptr<const Ieee80211MacHeader
7198//
7299const IIeee80211Mode *QosRateSelection::computeResponseAckFrameMode (Packet *packet, const Ptr<const Ieee80211DataOrMgmtHeader>& dataOrMgmtHeader)
73100{
74- // TODO BSSBasicRateSet, alternate rate
101+ if (responseAckFrameMode)
102+ return getConfiguredControlResponseMode (modeSet, responseAckFrameMode);
75103 auto mode = getMode (packet, dataOrMgmtHeader);
76- ASSERT (modeSet->containsMode (mode));
77- if (!responseAckFrameMode) {
78- auto responseModeSet = modeSet->getControlResponseModeSet (mode);
79- auto responseMode = responseModeSet->getMode (mode);
80- if (responseModeSet->getIsMandatory (responseMode))
81- return responseMode;
82- else if (auto slowerMode = responseModeSet->getSlowerMandatoryMode (responseMode))
83- return slowerMode;
84- else
85- throw cRuntimeError (" Mandatory mode not found" );
86- }
87- else
88- return modeSet->getControlResponseMode (responseAckFrameMode);
104+ ASSERT (modeSet->supportsMode (mode));
105+ // IEEE 802.11-2024 10.6.6.1/10.6.6.5.2: this bounded model uses a
106+ // mandatory non-HT rate for ordinary ACK responses; BSSBasicRateSet is not modelled.
107+ return getDynamicControlResponseMode (modeSet, mode);
89108}
90109
91110const IIeee80211Mode *QosRateSelection::computeResponseCtsFrameMode (Packet *packet, const Ptr<const Ieee80211RtsFrame>& rtsFrame)
92111{
93- // TODO BSSBasicRateSet, alternate rate
94112 auto mode = getMode (packet, rtsFrame);
95- ASSERT (modeSet->containsMode (mode));
96- if (!responseCtsFrameMode) {
97- auto responseModeSet = modeSet->getControlResponseModeSet (mode);
98- auto responseMode = responseModeSet->getMode (mode);
99- if (responseModeSet->getIsMandatory (responseMode))
100- return responseMode;
101- else if (auto slowerMode = responseModeSet->getSlowerMandatoryMode (responseMode))
102- return slowerMode;
103- else
104- throw cRuntimeError (" Mandatory mode not found" );
113+ ASSERT (modeSet->supportsMode (mode));
114+ auto responseMode = responseCtsFrameMode ? responseCtsFrameMode : mode;
115+ if (dynamic_cast <const Ieee80211HtMode *>(mode) != nullptr ) {
116+ // IEEE 802.11-2024 10.6.6.1 and 10.6.6.5.7 require an HT response to HT RTS; HT-GF is never a response.
117+ return responseCtsFrameMode && dynamic_cast <const Ieee80211HtMode *>(responseMode) == nullptr ? responseMode : modeSet->getControlResponseMode (responseMode);
105118 }
106- else
107- return modeSet->getControlResponseMode (responseCtsFrameMode);
119+ return responseCtsFrameMode ? getConfiguredControlResponseMode (modeSet, responseMode) : getDynamicControlResponseMode (modeSet, responseMode);
108120}
109121
110122//
@@ -115,14 +127,17 @@ const IIeee80211Mode *QosRateSelection::computeResponseCtsFrameMode(Packet *pack
115127//
116128const IIeee80211Mode *QosRateSelection::computeResponseBlockAckFrameMode (Packet *packet, const Ptr<const Ieee80211BlockAckReq>& blockAckReq)
117129{
118- if (dynamicPtrCast<const Ieee80211BasicBlockAckReq>(blockAckReq)) {
119- if (responseBlockAckFrameMode)
120- return modeSet->getControlResponseMode (responseBlockAckFrameMode);
121- else
122- return modeSet->getControlResponseMode (getMode (packet, blockAckReq));
123- }
124- else
130+ if (!dynamicPtrCast<const Ieee80211BasicBlockAckReq>(blockAckReq))
125131 throw cRuntimeError (" Unknown BlockAckReq frame type" );
132+ if (responseBlockAckFrameMode)
133+ return getConfiguredControlResponseMode (modeSet, responseBlockAckFrameMode);
134+ auto mode = getMode (packet, blockAckReq);
135+ ASSERT (modeSet->supportsMode (mode));
136+ // IEEE 802.11-2024 10.6.6.5.2 permits non-HT Basic BlockAck responses;
137+ // this model has no BSSBasicRateSet/HT Control context to select another PPDU.
138+ if (dynamic_cast <const Ieee80211HtMode *>(mode) != nullptr )
139+ return modeSet->getNonHtControlResponseMode (mode);
140+ return mode;
126141}
127142
128143const IIeee80211Mode *QosRateSelection::computeDataOrMgmtFrameMode (const Ptr<const Ieee80211DataOrMgmtHeader>& dataOrMgmtHeader)
@@ -245,6 +260,7 @@ void QosRateSelection::receiveSignal(cComponent *source, simsignal_t signalID, c
245260 if (signalID == modesetChangedSignal) {
246261 modeSet = check_and_cast<Ieee80211ModeSet *>(obj);
247262 fastestMandatoryMode = modeSet->getFastestMandatoryMode ();
263+ resolveConfiguredResponseModes ();
248264 }
249265}
250266
0 commit comments