Skip to content

Commit 3086d2e

Browse files
Fix 802.11 management reassociation lifecycle handling
Restore the simplified station association bootstrap whenever its lifecycle starts so AP membership, BSS identity, association state, and bilateral negotiated HT peer state are recreated after shutdown or crash recovery. Report reassociation outcomes through Ieee80211Prim_ReassociateConfirm, populate the AP address on association confirms, return a refused reassociation confirm before initial association, and preserve the reassociation primitive on timeout. Scan complete frame sequences for acknowledged association responses instead of assuming the response and ACK are the final two steps. Also advertise only initialized mandatory supported-rate entries. Extend the simplified-station module test with a deterministic stop/start cycle that verifies restored association and HT peer state. Validated with the release build, focused HT serializer and AP transaction unit tests, and the simplified-station lifecycle module test.
1 parent a8b2362 commit 3086d2e

7 files changed

Lines changed: 100 additions & 29 deletions

File tree

src/inet/linklayer/ieee80211/mgmt/Ieee80211MgmtAp.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -145,9 +145,9 @@ void Ieee80211MgmtAp::receiveSignal(cComponent *source, simsignal_t signalID, cO
145145

146146
if (signalID == IFrameSequenceHandler::frameSequenceFinishedSignal) {
147147
auto context = check_and_cast<FrameSequenceContext *>(obj);
148-
if (context->getNumSteps() >= 2) {
149-
auto transmitStep = dynamic_cast<ITransmitStep *>(context->getStepBeforeLast());
150-
auto receiveStep = dynamic_cast<IReceiveStep *>(context->getLastStep());
148+
for (int stepIndex = 0; stepIndex + 1 < context->getNumSteps(); stepIndex++) {
149+
auto transmitStep = dynamic_cast<ITransmitStep *>(context->getStep(stepIndex));
150+
auto receiveStep = dynamic_cast<IReceiveStep *>(context->getStep(stepIndex + 1));
151151
if (transmitStep && receiveStep) {
152152
const Packet *responseFrame = getAssociationResponseFrame(transmitStep);
153153
auto responseHeader = dynamicPtrCast<const Ieee80211MgmtHeader>(responseFrame->peekAtFront<Ieee80211MacHeader>());

src/inet/linklayer/ieee80211/mgmt/Ieee80211MgmtBase.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,11 @@ void Ieee80211MgmtBase::receiveSignal(cComponent *source, simsignal_t signalID,
4747
if (signalID == modesetChangedSignal) {
4848
modeSet = check_and_cast<physicallayer::Ieee80211ModeSet *>(obj);
4949
mib->updateLocalHtCapabilities(modeSet);
50-
supportedRates.numRates = std::min(8, modeSet->getNumModes());
5150
int rateIndex = 0;
52-
for (int i = 0; i < supportedRates.numRates; i++)
51+
for (int i = 0; i < modeSet->getNumModes() && rateIndex < 8; i++)
5352
if (modeSet->isMandatory(i))
5453
supportedRates.rate[rateIndex++] = modeSet->getMode(i)->getDataMode()->getNetBitrate().get<Mbps>();
54+
supportedRates.numRates = rateIndex;
5555
}
5656
}
5757

src/inet/linklayer/ieee80211/mgmt/Ieee80211MgmtSta.cc

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,11 @@ void Ieee80211MgmtSta::handleTimer(cMessage *msg)
125125
EV << "Association timed out, AP address = " << ap->address << "\n";
126126

127127
// send back failure report to agent
128-
sendAssociationConfirm(ap, PRC_TIMEOUT);
128+
if (reassociationInProgress)
129+
sendReassociationConfirm(ap, PRC_TIMEOUT);
130+
else
131+
sendAssociationConfirm(ap, PRC_TIMEOUT);
132+
reassociationInProgress = false;
129133
}
130134
else if (msg->getKind() == MK_SCAN_MAXCHANNELTIME) {
131135
// go to next channel during scanning
@@ -273,6 +277,7 @@ void Ieee80211MgmtSta::startAssociation(ApInfo *ap, simtime_t timeout)
273277
addHtCapabilities(body);
274278
body->setChunkLength(B(2 + 2 + (2 + strlen(body->getSSID())) + (2 + body->getSupportedRates().numRates)) + getHtMgmtElementsLength(body));
275279
sendManagementFrame("Assoc", body, ST_ASSOCIATIONREQUEST, ap->address);
280+
reassociationInProgress = false;
276281

277282
// schedule timeout
278283
ASSERT(assocTimeoutMsg == nullptr);
@@ -295,6 +300,7 @@ void Ieee80211MgmtSta::startReassociation(ApInfo *ap, simtime_t timeout)
295300
addHtCapabilities(body);
296301
body->setChunkLength(B(2 + 2 + 6 + (2 + strlen(body->getSSID())) + (2 + body->getSupportedRates().numRates)) + getHtMgmtElementsLength(body));
297302
sendManagementFrame("Reassoc", body, ST_REASSOCIATIONREQUEST, ap->address);
303+
reassociationInProgress = true;
298304
assocTimeoutMsg = new cMessage("assocTimeout", MK_ASSOC_TIMEOUT);
299305
assocTimeoutMsg->setContextPointer(ap);
300306
scheduleAfter(timeout, assocTimeoutMsg);
@@ -468,6 +474,12 @@ void Ieee80211MgmtSta::processAssociateCommand(Ieee80211Prim_AssociateRequest *c
468474
void Ieee80211MgmtSta::processReassociateCommand(Ieee80211Prim_ReassociateRequest *ctrl)
469475
{
470476
const MacAddress& address = ctrl->getAddress();
477+
if (!mib->bssStationData.isAssociated) {
478+
auto confirm = new Ieee80211Prim_ReassociateConfirm();
479+
confirm->setAddress(address);
480+
sendConfirm(confirm, PRC_REFUSED);
481+
return;
482+
}
471483
ApInfo *ap = lookupAP(address);
472484
if (!ap)
473485
throw cRuntimeError("processReassociateCommand: AP not known: address = %s", address.str().c_str());
@@ -513,7 +525,16 @@ void Ieee80211MgmtSta::sendAuthenticationConfirm(ApInfo *ap, Ieee80211PrimResult
513525

514526
void Ieee80211MgmtSta::sendAssociationConfirm(ApInfo *ap, Ieee80211PrimResultCode resultCode)
515527
{
516-
sendConfirm(new Ieee80211Prim_AssociateConfirm(), resultCode);
528+
auto confirm = new Ieee80211Prim_AssociateConfirm();
529+
confirm->setAddress(ap->address);
530+
sendConfirm(confirm, resultCode);
531+
}
532+
533+
void Ieee80211MgmtSta::sendReassociationConfirm(ApInfo *ap, Ieee80211PrimResultCode resultCode)
534+
{
535+
auto confirm = new Ieee80211Prim_ReassociateConfirm();
536+
confirm->setAddress(ap->address);
537+
sendConfirm(confirm, resultCode);
517538
}
518539

519540
void Ieee80211MgmtSta::sendConfirm(Ieee80211PrimConfirm *confirm, Ieee80211PrimResultCode resultCode)
@@ -634,10 +655,10 @@ void Ieee80211MgmtSta::handleAssociationRequestFrame(Packet *packet, const Ptr<c
634655

635656
void Ieee80211MgmtSta::handleAssociationResponseFrame(Packet *packet, const Ptr<const Ieee80211MgmtHeader>& header)
636657
{
637-
processAssociationResponse(packet, header);
658+
processAssociationResponse(packet, header, false);
638659
}
639660

640-
void Ieee80211MgmtSta::processAssociationResponse(Packet *packet, const Ptr<const Ieee80211MgmtHeader>& header)
661+
void Ieee80211MgmtSta::processAssociationResponse(Packet *packet, const Ptr<const Ieee80211MgmtHeader>& header, bool reassociation)
641662
{
642663
EV << "Received Association or Reassociation Response frame\n";
643664

@@ -677,6 +698,7 @@ void Ieee80211MgmtSta::processAssociationResponse(Packet *packet, const Ptr<cons
677698

678699
cancelAndDelete(assocTimeoutMsg);
679700
assocTimeoutMsg = nullptr;
701+
reassociationInProgress = false;
680702

681703
if (statusCode != SC_SUCCESSFUL) {
682704
EV << "Association failed with AP address=" << ap->address << "\n";
@@ -712,7 +734,10 @@ void Ieee80211MgmtSta::processAssociationResponse(Packet *packet, const Ptr<cons
712734
}
713735

714736
// report back to agent
715-
sendAssociationConfirm(ap, statusCodeToPrimResultCode(statusCode));
737+
if (reassociation)
738+
sendReassociationConfirm(ap, statusCodeToPrimResultCode(statusCode));
739+
else
740+
sendAssociationConfirm(ap, statusCodeToPrimResultCode(statusCode));
716741
}
717742

718743
void Ieee80211MgmtSta::handleReassociationRequestFrame(Packet *packet, const Ptr<const Ieee80211MgmtHeader>& header)
@@ -722,7 +747,7 @@ void Ieee80211MgmtSta::handleReassociationRequestFrame(Packet *packet, const Ptr
722747

723748
void Ieee80211MgmtSta::handleReassociationResponseFrame(Packet *packet, const Ptr<const Ieee80211MgmtHeader>& header)
724749
{
725-
processAssociationResponse(packet, header);
750+
processAssociationResponse(packet, header, true);
726751
}
727752

728753
void Ieee80211MgmtSta::handleDisassociationFrame(Packet *packet, const Ptr<const Ieee80211MgmtHeader>& header)

src/inet/linklayer/ieee80211/mgmt/Ieee80211MgmtSta.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ class INET_API Ieee80211MgmtSta : public Ieee80211MgmtBase
9696

9797
// associated Access Point
9898
cMessage *assocTimeoutMsg; // if non-nullptr: association is in progress
99+
bool reassociationInProgress = false;
99100
AssociatedApInfo assocAP;
100101

101102
public:
@@ -133,7 +134,7 @@ class INET_API Ieee80211MgmtSta : public Ieee80211MgmtBase
133134
virtual void storeAPInfo(Packet *packet, const Ptr<const Ieee80211MgmtHeader>& header, const Ptr<const Ieee80211BeaconFrame>& body);
134135

135136
/** Processes Association and Reassociation Responses without using cached Beacon capabilities. */
136-
virtual void processAssociationResponse(Packet *packet, const Ptr<const Ieee80211MgmtHeader>& header);
137+
virtual void processAssociationResponse(Packet *packet, const Ptr<const Ieee80211MgmtHeader>& header, bool reassociation);
137138

138139
/** Switches to the next channel to scan; returns true if done (there wasn't any more channel to scan). */
139140
virtual bool scanNextChannel();
@@ -152,6 +153,7 @@ class INET_API Ieee80211MgmtSta : public Ieee80211MgmtBase
152153

153154
/** Sends back result of association to the agent */
154155
virtual void sendAssociationConfirm(ApInfo *ap, Ieee80211PrimResultCode resultCode);
156+
virtual void sendReassociationConfirm(ApInfo *ap, Ieee80211PrimResultCode resultCode);
155157

156158
/** Utility function: Cancel the existing association */
157159
virtual void disassociate();

src/inet/linklayer/ieee80211/mgmt/Ieee80211MgmtStaSimplified.cc

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,21 +37,32 @@ void Ieee80211MgmtStaSimplified::initialize(int stage)
3737
mib->bssStationData.isAssociated = true;
3838
}
3939
else if (stage == INITSTAGE_LINK_LAYER) {
40-
L3AddressResolver addressResolver;
41-
auto accessPointAddress = addressResolver.resolve(par("accessPointAddress"), L3AddressResolver::ADDR_MAC).toMac();
42-
mib->bssData.bssid = accessPointAddress;
43-
auto apMib = findAccessPointMib(accessPointAddress);
44-
apMib->bssAccessPointData.stations[mib->address] = Ieee80211Mib::ASSOCIATED;
45-
mib->bssData.ssid = apMib->bssData.ssid;
40+
configureAssociation();
4641
}
47-
else if (stage == INITSTAGE_LAST) {
48-
auto apMib = findAccessPointMib(mib->bssData.bssid);
49-
// Simplified management is an explicit no-air abstraction: install the state that the
50-
// Association Request/Response exchange would have committed in detailed management.
51-
if (mib->isHtOperationSupported() && apMib->isHtOperationSupported()) {
52-
mib->setPeerHtCapabilities(apMib->address, apMib->localHtCapabilities, apMib->htOperation);
53-
apMib->setPeerHtCapabilities(mib->address, mib->localHtCapabilities, apMib->htOperation);
54-
}
42+
else if (stage == INITSTAGE_LAST)
43+
configureAssociation();
44+
}
45+
46+
void Ieee80211MgmtStaSimplified::start()
47+
{
48+
Ieee80211MgmtBase::start();
49+
configureAssociation();
50+
}
51+
52+
void Ieee80211MgmtStaSimplified::configureAssociation()
53+
{
54+
L3AddressResolver addressResolver;
55+
auto accessPointAddress = addressResolver.resolve(par("accessPointAddress"), L3AddressResolver::ADDR_MAC).toMac();
56+
mib->bssData.bssid = accessPointAddress;
57+
auto apMib = findAccessPointMib(accessPointAddress);
58+
apMib->bssAccessPointData.stations[mib->address] = Ieee80211Mib::ASSOCIATED;
59+
mib->bssData.ssid = apMib->bssData.ssid;
60+
mib->bssStationData.isAssociated = true;
61+
// Simplified management is an explicit no-air abstraction: install the state that the
62+
// Association Request/Response exchange would have committed in detailed management.
63+
if (mib->isHtOperationSupported() && apMib->isHtOperationSupported()) {
64+
mib->setPeerHtCapabilities(apMib->address, apMib->localHtCapabilities, apMib->htOperation);
65+
apMib->setPeerHtCapabilities(mib->address, mib->localHtCapabilities, apMib->htOperation);
5566
}
5667
}
5768

src/inet/linklayer/ieee80211/mgmt/Ieee80211MgmtStaSimplified.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ class INET_API Ieee80211MgmtStaSimplified : public Ieee80211MgmtBase
2525
protected:
2626
virtual int numInitStages() const override { return NUM_INIT_STAGES; }
2727
virtual void initialize(int) override;
28+
virtual void start() override;
29+
virtual void configureAssociation();
2830

2931
/** Implements abstract Ieee80211MgmtBase method */
3032
virtual void handleTimer(cMessage *msg) override;
@@ -52,4 +54,3 @@ class INET_API Ieee80211MgmtStaSimplified : public Ieee80211MgmtBase
5254
} // namespace inet
5355

5456
#endif
55-

tests/module/Ieee80211MgmtStaSimplifiedInitialization_1.test

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,25 @@ class TestInitializationObserver : public cSimpleModule
4747
ASSERT(apMib->findPeerHtState(staMib->address) != nullptr);
4848
ASSERT(staMib->findPeerHtState(apMib->address) != nullptr);
4949
std::cout << "Simplified STA HT peer state installed at last initialization stage.\n";
50+
scheduleAt(SimTime(3, SIMTIME_US), new cMessage("checkRestart"));
5051
}
5152
}
5253
}
5354

54-
virtual void handleMessage(cMessage *message) override { throw cRuntimeError("Unexpected message"); }
55+
virtual void handleMessage(cMessage *message) override
56+
{
57+
auto apInterface = check_and_cast<NetworkInterface *>(getModuleByPath("^.ap.wlan[0]"));
58+
auto staInterface = check_and_cast<NetworkInterface *>(getModuleByPath("^.sta.wlan[0]"));
59+
auto apMib = check_and_cast<ieee80211::Ieee80211Mib *>(apInterface->getSubmodule("mib"));
60+
auto staMib = check_and_cast<ieee80211::Ieee80211Mib *>(staInterface->getSubmodule("mib"));
61+
ASSERT(staMib->bssStationData.isAssociated);
62+
ASSERT(staMib->bssData.ssid == apMib->bssData.ssid);
63+
ASSERT(apMib->bssAccessPointData.stations.at(staMib->address) == ieee80211::Ieee80211Mib::ASSOCIATED);
64+
ASSERT(apMib->findPeerHtState(staMib->address) != nullptr);
65+
ASSERT(staMib->findPeerHtState(apMib->address) != nullptr);
66+
std::cout << "Simplified STA association and HT peer state restored after restart.\n";
67+
delete message;
68+
}
5569
};
5670

5771
Define_Module(TestInitializationObserver);
@@ -61,6 +75,7 @@ Define_Module(TestInitializationObserver);
6175
%file: test.ned
6276

6377
import inet.common.SimpleModule;
78+
import inet.common.scenario.ScenarioManager;
6479
import inet.networklayer.configurator.ipv4.Ipv4NetworkConfigurator;
6580
import inet.node.inet.WirelessHost;
6681
import inet.node.wireless.AccessPoint;
@@ -83,6 +98,7 @@ network Ieee80211MgmtStaSimplifiedInitializationTestNetwork
8398
submodules:
8499
radioMedium: Ieee80211ScalarRadioMedium;
85100
configurator: TestIpv4NetworkConfigurator;
101+
scenarioManager: ScenarioManager;
86102
ap: AccessPoint {
87103
parameters:
88104
wlan[*].mgmt.typename = "Ieee80211MgmtApSimplified";
@@ -101,7 +117,7 @@ network Ieee80211MgmtStaSimplifiedInitializationTestNetwork
101117
[General]
102118
network = Ieee80211MgmtStaSimplifiedInitializationTestNetwork
103119
ned-path = .;../../../../src;../../lib
104-
sim-time-limit = 1us
120+
sim-time-limit = 4us
105121
cmdenv-express-mode = true
106122
record-vector-results = false
107123
record-scalar-results = false
@@ -111,6 +127,8 @@ record-scalar-results = false
111127
*.ap.wlan[0].mgmt.ssid = "review-ssid"
112128
*.sta.wlan[0].mgmt.accessPointAddress = "02:00:00:00:00:01"
113129
**.wlan[0].opMode = "n(mixed-2.4Ghz)"
130+
**.hasStatus = true
131+
**.scenarioManager.script = xmldoc("scenario.xml")
114132
**.wlan[0].bitrate = 65Mbps
115133
**.wlan[0].radio.bandName = "2.4 GHz"
116134
**.wlan[0].radio.centerFrequency = 2.4GHz
@@ -122,8 +140,22 @@ record-scalar-results = false
122140
**.mobility.constraintAreaMaxY = 100m
123141
**.mobility.constraintAreaMaxZ = 0m
124142

143+
%file: scenario.xml
144+
145+
<scenario>
146+
<at t="1us">
147+
<shutdown module="sta"/>
148+
</at>
149+
<at t="2us">
150+
<startup module="sta"/>
151+
</at>
152+
</scenario>
153+
125154
%contains: stdout
126155
Simplified STA wireless identity available during network configuration.
127156

128157
%contains: stdout
129158
Simplified STA HT peer state installed at last initialization stage.
159+
160+
%contains: stdout
161+
Simplified STA association and HT peer state restored after restart.

0 commit comments

Comments
 (0)