@@ -14,11 +14,19 @@ namespace ieee80211 {
1414
1515void OriginatorBlockAckAgreementHandler::createAgreement (const Ptr<const Ieee80211AddbaRequest>& addbaRequest)
1616{
17- OriginatorBlockAckAgreement *blockAckAgreement = new OriginatorBlockAckAgreement (addbaRequest->getReceiverAddress (), addbaRequest->getTid (), addbaRequest->getStartingSequenceNumber (), addbaRequest->getBufferSize (), addbaRequest->getAMsduSupported (), addbaRequest->getBlockAckPolicy () == 0 );
17+ ASSERT (addbaRequest->getDialogToken () != 0 );
18+ OriginatorBlockAckAgreement *blockAckAgreement = new OriginatorBlockAckAgreement (addbaRequest->getReceiverAddress (), addbaRequest->getTid (), addbaRequest->getStartingSequenceNumber (), addbaRequest->getBufferSize (), addbaRequest->getAMsduSupported (), addbaRequest->getBlockAckPolicy () == 0 , addbaRequest->getDialogToken ());
1819 auto agreementId = std::make_pair (addbaRequest->getReceiverAddress (), addbaRequest->getTid ());
1920 blockAckAgreements[agreementId] = blockAckAgreement;
2021}
2122
23+ uint8_t OriginatorBlockAckAgreementHandler::allocateDialogToken ()
24+ {
25+ auto dialogToken = nextDialogToken;
26+ nextDialogToken = nextDialogToken == 255 ? 1 : nextDialogToken + 1 ;
27+ return dialogToken;
28+ }
29+
2230simtime_t OriginatorBlockAckAgreementHandler::computeEarliestExpirationTime ()
2331{
2432 simtime_t earliestTime = SIMTIME_MAX ;
@@ -33,6 +41,35 @@ simtime_t OriginatorBlockAckAgreementHandler::computeEarliestExpirationTime()
3341 return earliestTime;
3442}
3543
44+ simtime_t OriginatorBlockAckAgreementHandler::computeEarliestAddbaResponseDeadline () const
45+ {
46+ simtime_t earliestDeadline = SIMTIME_MAX ;
47+ for (const auto & entry : blockAckAgreements) {
48+ auto agreement = entry.second ;
49+ if (agreement->isPending () && agreement->getIsAddbaRequestSent ()) {
50+ ASSERT (agreement->getAddbaResponseDeadline () >= 0 );
51+ earliestDeadline = std::min (earliestDeadline, agreement->getAddbaResponseDeadline ());
52+ }
53+ }
54+ return earliestDeadline;
55+ }
56+
57+ void OriginatorBlockAckAgreementHandler::addbaResponseTimeoutExpired (IBlockAckAgreementHandlerCallback *callback)
58+ {
59+ auto now = simTime ();
60+ for (auto it = blockAckAgreements.begin (); it != blockAckAgreements.end ();) {
61+ auto agreement = it->second ;
62+ if (agreement->isPending () && agreement->getIsAddbaRequestSent () && agreement->getAddbaResponseDeadline () <= now) {
63+ EV_INFO << " ADDBA Response timeout for receiver=" << agreement->getReceiverAddr () << " tid=" << (int )agreement->getTid () << endl;
64+ it = blockAckAgreements.erase (it);
65+ delete agreement;
66+ }
67+ else
68+ it++;
69+ }
70+ scheduleAddbaResponseTimer (callback);
71+ }
72+
3673void OriginatorBlockAckAgreementHandler::blockAckAgreementExpired (IProcedureCallback *procedureCallback, IBlockAckAgreementHandlerCallback *agreementHandlerCallback)
3774{
3875 // When a timeout of BlockAckTimeout is detected, the STA shall send a DELBA frame to the
@@ -57,6 +94,9 @@ const Ptr<Ieee80211AddbaRequest> OriginatorBlockAckAgreementHandler::buildAddbaR
5794{
5895 auto addbaRequest = makeShared<Ieee80211AddbaRequest>();
5996 addbaRequest->setReceiverAddress (receiverAddr);
97+ // IEEE Std 802.11-2024, 9.6.4.2: a solicited ADDBA Request uses a nonzero
98+ // Dialog Token, and the corresponding response copies that token.
99+ addbaRequest->setDialogToken (allocateDialogToken ());
60100 addbaRequest->setTid (tid);
61101 addbaRequest->setAMsduSupported (blockAckAgreementPolicy->isMsduSupported ());
62102 addbaRequest->setBlockAckTimeoutValue (blockAckAgreementPolicy->getBlockAckTimeoutValue ());
@@ -92,13 +132,24 @@ void OriginatorBlockAckAgreementHandler::scheduleInactivityTimer(IBlockAckAgreem
92132 callback->scheduleInactivityTimer (earliestExpirationTime);
93133}
94134
135+ void OriginatorBlockAckAgreementHandler::scheduleAddbaResponseTimer (IBlockAckAgreementHandlerCallback *callback)
136+ {
137+ callback->scheduleAddbaResponseTimer (computeEarliestAddbaResponseDeadline ());
138+ }
139+
95140OriginatorBlockAckAgreement *OriginatorBlockAckAgreementHandler::getAgreement (MacAddress receiverAddr, Tid tid)
96141{
97142 auto agreementId = std::make_pair (receiverAddr, tid);
98143 auto it = blockAckAgreements.find (agreementId);
99144 return it != blockAckAgreements.end () ? it->second : nullptr ;
100145}
101146
147+ bool OriginatorBlockAckAgreementHandler::isAddbaResponsePending (MacAddress receiverAddr, Tid tid) const
148+ {
149+ auto it = blockAckAgreements.find (std::make_pair (receiverAddr, tid));
150+ return it != blockAckAgreements.end () && it->second ->isPending ();
151+ }
152+
102153const Ptr<Ieee80211Delba> OriginatorBlockAckAgreementHandler::buildDelba (MacAddress receiverAddr, Tid tid, int reasonCode)
103154{
104155 auto delba = makeShared<Ieee80211Delba>();
@@ -132,15 +183,23 @@ void OriginatorBlockAckAgreementHandler::processTransmittedDataFrame(Packet *pac
132183 }
133184}
134185
135- void OriginatorBlockAckAgreementHandler::processReceivedAddbaResp (const Ptr<const Ieee80211AddbaResponse>& addbaResp, IOriginatorBlockAckAgreementPolicy *blockAckAgreementPolicy, IBlockAckAgreementHandlerCallback *callback)
186+ OriginatorBlockAckAgreement * OriginatorBlockAckAgreementHandler::processReceivedAddbaResp (const Ptr<const Ieee80211AddbaResponse>& addbaResp, IOriginatorBlockAckAgreementPolicy *blockAckAgreementPolicy, IBlockAckAgreementHandlerCallback *callback)
136187{
137188 auto agreement = getAgreement (addbaResp->getTransmitterAddress (), addbaResp->getTid ());
138- if (blockAckAgreementPolicy->isAddbaReqAccepted (addbaResp, agreement)) {
189+ // IEEE Std 802.11-2024, 11.5.2.2: only a successful response matching the
190+ // outstanding peer, TID, and Dialog Token establishes the agreement.
191+ if (agreement == nullptr || !agreement->isPending () || !agreement->getIsAddbaRequestSent () || agreement->getDialogToken () != addbaResp->getDialogToken ())
192+ return nullptr ;
193+ if (addbaResp->getStatusCode () == 0 && blockAckAgreementPolicy->isAddbaReqAccepted (addbaResp, agreement)) {
139194 updateAgreement (agreement, addbaResp);
140195 scheduleInactivityTimer (callback);
196+ scheduleAddbaResponseTimer (callback);
197+ return agreement;
141198 }
142199 else {
143- // TODO send a new one?
200+ terminateAgreement (addbaResp->getTransmitterAddress (), addbaResp->getTid ());
201+ scheduleAddbaResponseTimer (callback);
202+ return nullptr ;
144203 }
145204}
146205
@@ -152,13 +211,21 @@ void OriginatorBlockAckAgreementHandler::updateAgreement(OriginatorBlockAckAgree
152211 agreement->calculateExpirationTime ();
153212}
154213
155- void OriginatorBlockAckAgreementHandler::processTransmittedAddbaReq (const Ptr<const Ieee80211AddbaRequest>& addbaReq)
214+ void OriginatorBlockAckAgreementHandler::processTransmittedAddbaReq (const Ptr<const Ieee80211AddbaRequest>& addbaReq, IOriginatorBlockAckAgreementPolicy *blockAckAgreementPolicy, IBlockAckAgreementHandlerCallback *callback )
156215{
157216 auto agreement = getAgreement (addbaReq->getReceiverAddress (), addbaReq->getTid ());
158- if (agreement)
217+ if (agreement && agreement->isPending () && agreement->getDialogToken () == addbaReq->getDialogToken ()) {
218+ if (agreement->getAddbaResponseDeadline () < 0 ) {
219+ auto addbaFailureTimeout = blockAckAgreementPolicy->computeAddbaFailureTimeout ();
220+ if (addbaFailureTimeout <= 0 )
221+ throw cRuntimeError (" ADDBA failure timeout must be greater than zero" );
222+ agreement->setAddbaResponseDeadline (simTime () + addbaFailureTimeout);
223+ }
159224 agreement->setIsAddbaRequestSent (true );
225+ scheduleAddbaResponseTimer (callback);
226+ }
160227 else
161- throw cRuntimeError ( " Block Ack Agreement should have already been added " ) ;
228+ EV_WARN << " Ignoring stale transmitted ADDBA Request for receiver= " << addbaReq-> getReceiverAddress () << " tid= " << ( int )addbaReq-> getTid () << " dialogToken= " << ( int )addbaReq-> getDialogToken () << endl ;
162229}
163230
164231void OriginatorBlockAckAgreementHandler::processTransmittedDelba (const Ptr<const Ieee80211Delba>& delba)
@@ -180,4 +247,3 @@ OriginatorBlockAckAgreementHandler::~OriginatorBlockAckAgreementHandler()
180247
181248} // namespace ieee80211
182249} // namespace inet
183-
0 commit comments