Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions WHATSNEW
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,13 @@ Notable backward incompatible changes are the following:
These changes are backward incompatible for C++ code that directly references
the old combined ICMP error indication or tag types.

7. 802.11n control-response rate selection

Ordinary ACK and Basic BlockAck responses in the n(mixed-2.4Ghz) profile now
use the mandatory non-HT fallback because BSSBasicRateSet is not modelled.
This can change airtime, timeout trajectories, throughput, and fingerprints
in existing simulations. An HT RTS continues to receive an HT-mixed CTS.

Notable backward compatible changes are the following:

1. IPv6 network configurator
Expand Down
37 changes: 37 additions & 0 deletions examples/wireless/lan80211/omnetpp-ht-greenfield.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
[General]
network = Lan80211
abstract = true
cmdenv-express-mode = true

**.constraintAreaMinX = 0m
**.constraintAreaMinY = 0m
**.constraintAreaMinZ = 0m
**.constraintAreaMaxX = 600m
**.constraintAreaMaxY = 400m
**.constraintAreaMaxZ = 0m

**.arp.typename = "GlobalArp"
**.opMode = "n(greenfield-2.4Ghz)"
**.wlan[*].bitrate = 13Mbps

*.ap.wlan[*].address = "10:00:00:00:00:00"
*.host[*].**.mgmt.accessPointAddress = "10:00:00:00:00:00"

*.ap.mobility.typename = "StationaryMobility"
*.ap.mobility.initialX = 250m
*.ap.mobility.initialY = 200m
*.host[*].mobility.typename = "StationaryMobility"
*.host[*].mobility.initialY = 200m
*.host[0].mobility.initialX = 260m
*.host[1].mobility.initialX = 270m

[Config HtGreenfield]
description = "HT Greenfield mode exchanging ping traffic through an access point"
sim-time-limit = 2s
*.numHosts = 2
*.host[0].numApps = 0
*.host[1].numApps = 1
*.host[1].app[0].typename = "PingApp"
*.host[1].app[0].destAddr = "host[0]"
*.host[1].app[0].sendInterval = 100ms
*.host[1].app[0].printPing = true
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ module ExtUpperIeee80211Interface extends ExtInterface like IWirelessInterface
{
parameters:
string energySourceModule = default("");
string opMode @enum("a","b","g(erp)","g(mixed)","n(mixed-2.4Ghz)","p","ac") = default("g(mixed)");
string opMode @enum("a","b","g(erp)","g(mixed)","n(mixed-2.4Ghz)","n(greenfield-2.4Ghz)","p","ac") = default("g(mixed)");
double bitrate @unit(bps) = default(-1bps);
**.opMode = this.opMode;
**.bitrate = this.bitrate;
Expand Down Expand Up @@ -92,4 +92,3 @@ module ExtUpperIeee80211Interface extends ExtInterface like IWirelessInterface

classifier.in <-- { @display("m=n"); } <-- tap.lowerLayerOut;
}

3 changes: 1 addition & 2 deletions src/inet/linklayer/ieee80211/Ieee80211Interface.ned
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ module Ieee80211Interface extends NetworkInterface like IWirelessInterface
parameters:
string interfaceTableModule;
string energySourceModule = default("");
string opMode @enum("a","b","g(erp)","g(mixed)","n(mixed-2.4Ghz)","p","ac") = default("g(mixed)");
string opMode @enum("a","b","g(erp)","g(mixed)","n(mixed-2.4Ghz)","n(greenfield-2.4Ghz)","p","ac") = default("g(mixed)");
string address @mutable = default("auto"); // MAC address as hex string (12 hex digits), or
// "auto". "auto" values will be replaced by
// a generated MAC address in init stage 0.
Expand Down Expand Up @@ -129,4 +129,3 @@ module Ieee80211Interface extends NetworkInterface like IWirelessInterface

classifier.in <-- { @display("m=n"); } <-- upperLayerIn;
}

3 changes: 1 addition & 2 deletions src/inet/linklayer/ieee80211/mac/Ieee80211Mac.ned
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ module Ieee80211Mac extends MacProtocolBase like IIeee80211Mac
{
parameters:
string mibModule;
string modeSet @enum("a","b","g(erp)","g(mixed)","n(mixed-2.4Ghz)","p","ac") = default("g(mixed)");
string modeSet @enum("a","b","g(erp)","g(mixed)","n(mixed-2.4Ghz)","n(greenfield-2.4Ghz)","p","ac") = default("g(mixed)");
string fcsMode @enum("declared","computed") = default("declared");
string initialRadioMode @enum("off","sleep","receiver","transmitter","transceiver") = default("receiver");

Expand Down Expand Up @@ -130,4 +130,3 @@ module Ieee80211Mac extends MacProtocolBase like IIeee80211Mac
@display("p=250,200");
}
}

112 changes: 68 additions & 44 deletions src/inet/linklayer/ieee80211/mac/rateselection/QosRateSelection.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,30 +16,65 @@ namespace ieee80211 {

using namespace inet::physicallayer;

static const IIeee80211Mode *resolveConfiguredResponseCtsFrameMode(const Ieee80211ModeSet *modeSet, double bitrate, const char *modulePath)
{
if (bitrate == -1)
return nullptr;
try {
return modeSet->getMode(bps(bitrate));
}
catch (const cRuntimeError& error) {
throw cRuntimeError("%s has invalid responseCtsFrameBitrate=%g bps for operation mode '%s'; "
"the configured CTS rate must resolve to a selectable mode (HT RTS responses require an HT mode): %s",
modulePath, bitrate, modeSet->getName(), error.getFormattedMessage().c_str());
}
}

Define_Module(QosRateSelection);

void QosRateSelection::initialize(int stage)
{
ModeSetListener::initialize(stage);
if (stage == INITSTAGE_LINK_LAYER) {
dataOrMgmtRateControl = dynamic_cast<IRateControl *>(findModuleByPath(par("rateControlModule")));
double multicastFrameBitrate = par("multicastFrameBitrate");
multicastFrameMode = (multicastFrameBitrate == -1) ? nullptr : modeSet->getMode(bps(multicastFrameBitrate));
double dataFrameBitrate = par("dataFrameBitrate");
dataFrameMode = (dataFrameBitrate == -1) ? nullptr : modeSet->getMode(bps(dataFrameBitrate), Hz(par("dataFrameBandwidth")), par("dataFrameNumSpatialStreams"));
double mgmtFrameBitrate = par("mgmtFrameBitrate");
mgmtFrameMode = (mgmtFrameBitrate == -1) ? nullptr : modeSet->getMode(bps(mgmtFrameBitrate));
double controlFrameBitrate = par("controlFrameBitrate");
controlFrameMode = (controlFrameBitrate == -1) ? nullptr : modeSet->getMode(bps(controlFrameBitrate));
double responseAckFrameBitrate = par("responseAckFrameBitrate");
responseAckFrameMode = (responseAckFrameBitrate == -1) ? nullptr : modeSet->getMode(bps(responseAckFrameBitrate));
double responseBlockAckFrameBitrate = par("responseBlockAckFrameBitrate");
responseBlockAckFrameMode = (responseBlockAckFrameBitrate == -1) ? nullptr : modeSet->getMode(bps(responseBlockAckFrameBitrate));
double responseCtsFrameBitrate = par("responseCtsFrameBitrate");
responseCtsFrameMode = (responseCtsFrameBitrate == -1) ? nullptr : modeSet->getMode(bps(responseCtsFrameBitrate));
if (modeSet == nullptr)
throw cRuntimeError("QosRateSelection module %s has no mode set at link-layer initialization", getFullPath().c_str());
resolveConfiguredModes(modeSet);
}
}

void QosRateSelection::resolveConfiguredModes(const Ieee80211ModeSet *newModeSet)
{
if (newModeSet == nullptr)
return;
double multicastFrameBitrate = par("multicastFrameBitrate");
auto newMulticastFrameMode = multicastFrameBitrate == -1 ? nullptr : newModeSet->getMode(bps(multicastFrameBitrate));
double dataFrameBitrate = par("dataFrameBitrate");
auto newDataFrameMode = dataFrameBitrate == -1 ? nullptr : newModeSet->getMode(bps(dataFrameBitrate), Hz(par("dataFrameBandwidth")), par("dataFrameNumSpatialStreams"));
double mgmtFrameBitrate = par("mgmtFrameBitrate");
auto newMgmtFrameMode = mgmtFrameBitrate == -1 ? nullptr : newModeSet->getMode(bps(mgmtFrameBitrate));
double controlFrameBitrate = par("controlFrameBitrate");
auto newControlFrameMode = controlFrameBitrate == -1 ? nullptr : newModeSet->getMode(bps(controlFrameBitrate));
double responseAckFrameBitrate = par("responseAckFrameBitrate");
auto newResponseAckFrameMode = responseAckFrameBitrate == -1 ? nullptr : newModeSet->getMode(bps(responseAckFrameBitrate));
double responseBlockAckFrameBitrate = par("responseBlockAckFrameBitrate");
auto newResponseBlockAckFrameMode = responseBlockAckFrameBitrate == -1 ? nullptr : newModeSet->getMode(bps(responseBlockAckFrameBitrate));
double responseCtsFrameBitrate = par("responseCtsFrameBitrate");
auto newResponseCtsFrameMode = resolveConfiguredResponseCtsFrameMode(newModeSet, responseCtsFrameBitrate, getFullPath().c_str());
auto newFastestMandatoryMode = newModeSet->getFastestMandatoryMode();

modeSet = newModeSet;
multicastFrameMode = newMulticastFrameMode;
dataFrameMode = newDataFrameMode;
mgmtFrameMode = newMgmtFrameMode;
controlFrameMode = newControlFrameMode;
responseAckFrameMode = newResponseAckFrameMode;
responseBlockAckFrameMode = newResponseBlockAckFrameMode;
responseCtsFrameMode = newResponseCtsFrameMode;
fastestMandatoryMode = newFastestMandatoryMode;
lastTransmittedFrameMode.clear();
}

const IIeee80211Mode *QosRateSelection::getMode(Packet *packet, const Ptr<const Ieee80211MacHeader>& header)
{
const auto& modeReqTag = packet->findTag<Ieee80211ModeReq>();
Expand Down Expand Up @@ -71,36 +106,22 @@ bool QosRateSelection::isControlResponseFrame(const Ptr<const Ieee80211MacHeader
//
const IIeee80211Mode *QosRateSelection::computeResponseAckFrameMode(Packet *packet, const Ptr<const Ieee80211DataOrMgmtHeader>& dataOrMgmtHeader)
{
// TODO BSSBasicRateSet, alternate rate
if (responseAckFrameMode)
return modeSet->getNonHtControlResponseMode(responseAckFrameMode, false);
auto mode = getMode(packet, dataOrMgmtHeader);
ASSERT(modeSet->containsMode(mode));
if (!responseAckFrameMode) {
if (modeSet->getIsMandatory(mode))
return mode;
else if (auto slowerMode = modeSet->getSlowerMandatoryMode(mode))
return slowerMode;
else
throw cRuntimeError("Mandatory mode not found");
}
else
return responseAckFrameMode;
ASSERT(modeSet->supportsMode(mode));
// IEEE 802.11-2024 10.6.6.1/10.6.6.5.2: this bounded model uses a
// mandatory non-HT rate for ordinary ACK responses; BSSBasicRateSet is not modelled.
return modeSet->getMandatoryControlResponseMode(mode);
}

const IIeee80211Mode *QosRateSelection::computeResponseCtsFrameMode(Packet *packet, const Ptr<const Ieee80211RtsFrame>& rtsFrame)
{
// TODO BSSBasicRateSet, alternate rate
auto mode = getMode(packet, rtsFrame);
ASSERT(modeSet->containsMode(mode));
if (!responseCtsFrameMode) {
if (modeSet->getIsMandatory(mode))
return mode;
else if (auto slowerMode = modeSet->getSlowerMandatoryMode(mode))
return slowerMode;
else
throw cRuntimeError("Mandatory mode not found");
}
else
return responseCtsFrameMode;
ASSERT(modeSet->supportsMode(mode));
// The eliciting mode is required even when a CTS rate is configured because
// the response format and CandidateMCSSet depend on the received PPDU.
return modeSet->getControlResponseMode(mode, responseCtsFrameMode);
}

//
Expand All @@ -111,10 +132,15 @@ const IIeee80211Mode *QosRateSelection::computeResponseCtsFrameMode(Packet *pack
//
const IIeee80211Mode *QosRateSelection::computeResponseBlockAckFrameMode(Packet *packet, const Ptr<const Ieee80211BlockAckReq>& blockAckReq)
{
if (dynamicPtrCast<const Ieee80211BasicBlockAckReq>(blockAckReq))
return responseBlockAckFrameMode ? responseBlockAckFrameMode : getMode(packet, blockAckReq);
else
if (!dynamicPtrCast<const Ieee80211BasicBlockAckReq>(blockAckReq))
throw cRuntimeError("Unknown BlockAckReq frame type");
if (responseBlockAckFrameMode)
return modeSet->getNonHtControlResponseMode(responseBlockAckFrameMode, false);
auto mode = getMode(packet, blockAckReq);
ASSERT(modeSet->supportsMode(mode));
// IEEE 802.11-2024 10.6.6.5.2 permits non-HT Basic BlockAck responses;
// this model has no BSSBasicRateSet/HT Control context to select another PPDU.
return modeSet->getNonHtControlResponseMode(mode, false);
}

const IIeee80211Mode *QosRateSelection::computeDataOrMgmtFrameMode(const Ptr<const Ieee80211DataOrMgmtHeader>& dataOrMgmtHeader)
Expand Down Expand Up @@ -235,8 +261,7 @@ void QosRateSelection::receiveSignal(cComponent *source, simsignal_t signalID, c
Enter_Method("%s", cComponent::getSignalName(signalID));

if (signalID == modesetChangedSignal) {
modeSet = check_and_cast<Ieee80211ModeSet *>(obj);
fastestMandatoryMode = modeSet->getFastestMandatoryMode();
resolveConfiguredModes(check_and_cast<Ieee80211ModeSet *>(obj));
}
}

Expand All @@ -248,4 +273,3 @@ void QosRateSelection::frameTransmitted(Packet *packet, const Ptr<const Ieee8021

} /* namespace ieee80211 */
} /* namespace inet */

Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class INET_API QosRateSelection : public IQosRateSelection, public ModeSetListen
virtual int numInitStages() const override { return NUM_INIT_STAGES; }
virtual void initialize(int stage) override;
virtual void receiveSignal(cComponent *source, simsignal_t signalID, cObject *obj, cObject *details) override;
void resolveConfiguredModes(const physicallayer::Ieee80211ModeSet *newModeSet);

virtual const physicallayer::IIeee80211Mode *getMode(Packet *packet, const Ptr<const Ieee80211MacHeader>& header);
virtual const physicallayer::IIeee80211Mode *computeControlFrameMode(const Ptr<const Ieee80211MacHeader>& header, TxopProcedure *txopProcedure);
Expand All @@ -78,4 +79,3 @@ class INET_API QosRateSelection : public IQosRateSelection, public ModeSetListen
} /* namespace inet */

#endif

Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,18 @@ simple QosRateSelection extends SimpleModule

double multicastFrameBitrate @unit(bps) = default(-1bps);

// -1 selects the standard-derived automatic response. In a 2.4 GHz HT profile,
// a configured HT bitrate is an upper bound mapped to the highest mandatory
// non-HT rate at or below it; it does not select an exact HT ACK PPDU.
double responseAckFrameBitrate @unit(bps) = default(-1bps);
// -1 selects the standard-derived automatic response. In a 2.4 GHz HT profile,
// a configured HT bitrate is an upper bound mapped to the highest mandatory
// non-HT rate at or below it; it does not select an exact HT BlockAck PPDU.
double responseBlockAckFrameBitrate @unit(bps) = default(-1bps);
// -1 selects the standard-derived automatic response. A configured value must resolve to a
// selectable mode; for an HT RTS it must be HT and is translated to the corresponding HT-mixed
// CTS while preserving MCS, bandwidth, NSS, and GI. An explicitly configured HT value is a
// deliberate override and may bypass IEEE 802.11-2024 10.6.6.5.3/10.6.6.5.7 response constraints.
double responseCtsFrameBitrate @unit(bps) = default(-1bps);

double dataFrameBitrate @unit(bps) = default(-1bps); // Fastest
Expand All @@ -38,4 +48,3 @@ simple QosRateSelection extends SimpleModule
double controlFrameBitrate @unit(bps) = default(-1bps);
@display("i=block/cogwheel");
}

Loading
Loading