@@ -64,14 +64,31 @@ class TestIeee80211MgmtAp : public Ieee80211MgmtAp
6464 return aid;
6565 }
6666
67- void finishSuccessfulReassociation (const MacAddress& address)
67+ short startPendingAssociatedReassociation (const MacAddress& address)
6868 {
69+ Enter_Method("startPendingAssociatedReassociation");
70+ auto& sta = staList[address];
71+ sta.address = address;
72+ clearPendingAssociation(&sta);
73+ short aid = mib->allocateAssociationId(address);
74+ mib->bssAccessPointData.stations[address] = Ieee80211Mib::ASSOCIATED;
75+ ASSERT(mib->reserveAssociationId(address) == aid);
76+ sta.pendingAssociationSuccessful = true;
77+ sta.pendingAssociationTransactionId = createAssociationTransactionId();
78+ startAssociationResponseTimeout(&sta);
79+ return aid;
80+ }
81+
82+ void finishSuccessfulReassociation(const MacAddress& address, uint64_t transactionId = 0)
83+ {
84+ if (transactionId == 0)
85+ transactionId = staList.at(address).pendingAssociationTransactionId;
6986 auto response = new Packet("ReassocResp-OK");
7087 auto responseHeader = makeShared<Ieee80211MgmtHeader>();
7188 responseHeader->setType(ST_REASSOCIATIONRESPONSE);
7289 responseHeader->setReceiverAddress(address);
7390 response->insertAtBack(responseHeader);
74- response->addTag<Ieee80211MgmtTransactionTag>()->setTransactionId(staList.at(address).pendingAssociationTransactionId );
91+ response->addTag<Ieee80211MgmtTransactionTag>()->setTransactionId(transactionId );
7592
7693 FrameSequenceContext context(MacAddress::UNSPECIFIED_ADDRESS, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
7794 auto transmitStep = new TransmitStep(response, SIMTIME_ZERO);
@@ -86,12 +103,32 @@ class TestIeee80211MgmtAp : public Ieee80211MgmtAp
86103 delete response;
87104 }
88105
106+ void deauthenticate(const MacAddress& address)
107+ {
108+ Enter_Method("deauthenticate");
109+ auto packet = new Packet("Deauth");
110+ auto header = makeShared<Ieee80211MgmtHeader>();
111+ header->setTransmitterAddress(address);
112+ handleDeauthenticationFrame(packet, header);
113+ }
114+
115+ void disassociate(const MacAddress& address)
116+ {
117+ Enter_Method("disassociate");
118+ auto packet = new Packet("Disassoc");
119+ auto header = makeShared<Ieee80211MgmtHeader>();
120+ header->setTransmitterAddress(address);
121+ handleDisassociationFrame(packet, header);
122+ }
123+
89124 bool hasPendingAssociation(const MacAddress& address) const
90125 {
91126 auto it = staList.find(address);
92127 return it != staList.end() && it->second.pendingAssociationTransactionId != 0;
93128 }
94129
130+ uint64_t getPendingAssociationTransactionId(const MacAddress& address) const { return staList.at(address).pendingAssociationTransactionId; }
131+
95132 short reserveAssociationId(const MacAddress& address) { return mib->reserveAssociationId(address); }
96133 void cancelAssociationIdReservation(const MacAddress& address) { mib->cancelAssociationIdReservation(address); }
97134 bool hasCommittedAssociationId(const MacAddress& address) const { return mib->bssAccessPointData.associationIds.find(address) != mib->bssAccessPointData.associationIds.end(); }
@@ -109,8 +146,10 @@ class Ieee80211MgmtApTimeoutTest : public cSimpleModule, public cListener
109146 protected:
110147 TestIeee80211MgmtAp *mgmt = nullptr;
111148 MacAddress expectedAssociatedAddress;
149+ MacAddress expectedDisassociatedAddress;
112150 short expectedAssociationId = 0;
113151 int associationNotifications = 0;
152+ int disassociationNotifications = 0;
114153
115154 public:
116155 Ieee80211MgmtApTimeoutTest() : cSimpleModule(65536) {}
@@ -120,17 +159,25 @@ class Ieee80211MgmtApTimeoutTest : public cSimpleModule, public cListener
120159 {
121160 mgmt = check_and_cast<TestIeee80211MgmtAp *>(getModuleByPath("^.ap.wlan[0].mgmt"));
122161 mgmt->subscribe(l2ApAssociatedSignal, this);
162+ mgmt->subscribe(l2ApDisassociatedSignal, this);
123163 }
124164
125165 virtual void receiveSignal(cComponent *source, simsignal_t signalID, cObject *value, cObject *details) override
126166 {
127167 ASSERT(source == mgmt);
128- ASSERT(signalID == l2ApAssociatedSignal);
129168 const auto& notification = check_and_cast<Ieee80211MgmtAp::NotificationInfoSta *>(value);
130- ASSERT(notification->getStaAddress() == expectedAssociatedAddress);
131- ASSERT(mgmt->getStationStatus(expectedAssociatedAddress) == Ieee80211Mib::ASSOCIATED);
132- ASSERT(mgmt->getCommittedAssociationId(expectedAssociatedAddress) == expectedAssociationId);
133- associationNotifications++;
169+ if (signalID == l2ApAssociatedSignal) {
170+ ASSERT(notification->getStaAddress() == expectedAssociatedAddress);
171+ ASSERT(mgmt->getStationStatus(expectedAssociatedAddress) == Ieee80211Mib::ASSOCIATED);
172+ ASSERT(mgmt->getCommittedAssociationId(expectedAssociatedAddress) == expectedAssociationId);
173+ associationNotifications++;
174+ }
175+ else {
176+ ASSERT(signalID == l2ApDisassociatedSignal);
177+ ASSERT(notification->getStaAddress() == expectedDisassociatedAddress);
178+ ASSERT(!mgmt->hasPendingAssociation(expectedDisassociatedAddress));
179+ disassociationNotifications++;
180+ }
134181 }
135182
136183 virtual void activity() override
@@ -181,6 +228,30 @@ class Ieee80211MgmtApTimeoutTest : public cSimpleModule, public cListener
181228 ASSERT(associationNotifications == 1);
182229 ASSERT(!mgmt->hasPendingAssociation(expectedAssociatedAddress));
183230
231+ MacAddress deauthenticated("02:00:00:00:00:07");
232+ mgmt->startPendingAssociatedReassociation(deauthenticated);
233+ uint64_t staleDeauthenticationTransaction = mgmt->getPendingAssociationTransactionId(deauthenticated);
234+ expectedDisassociatedAddress = deauthenticated;
235+ mgmt->deauthenticate(deauthenticated);
236+ ASSERT(disassociationNotifications == 1);
237+ ASSERT(!mgmt->hasPendingAssociation(deauthenticated));
238+ ASSERT(!mgmt->hasCommittedAssociationId(deauthenticated));
239+ ASSERT(mgmt->getStationStatus(deauthenticated) == Ieee80211Mib::NOT_AUTHENTICATED);
240+ mgmt->finishSuccessfulReassociation(deauthenticated, staleDeauthenticationTransaction);
241+ ASSERT(!mgmt->hasCommittedAssociationId(deauthenticated));
242+
243+ MacAddress disassociated("02:00:00:00:00:08");
244+ mgmt->startPendingAssociatedReassociation(disassociated);
245+ uint64_t staleDisassociationTransaction = mgmt->getPendingAssociationTransactionId(disassociated);
246+ expectedDisassociatedAddress = disassociated;
247+ mgmt->disassociate(disassociated);
248+ ASSERT(disassociationNotifications == 2);
249+ ASSERT(!mgmt->hasPendingAssociation(disassociated));
250+ ASSERT(!mgmt->hasCommittedAssociationId(disassociated));
251+ ASSERT(mgmt->getStationStatus(disassociated) == Ieee80211Mib::AUTHENTICATED);
252+ mgmt->finishSuccessfulReassociation(disassociated, staleDisassociationTransaction);
253+ ASSERT(!mgmt->hasCommittedAssociationId(disassociated));
254+
184255 std::cout << "AP association response timeout lifecycle verified.\n";
185256 std::cout << "AP reassociation notification commit ordering verified.\n";
186257 }
0 commit comments