Skip to content

ieee80211: repair Basic Block Ack agreement lifecycle - #1343

Merged
levy merged 7 commits into
inet-framework:masterfrom
mgonzalezlopezudc:work/compressed-blockack-s3b
Oct 21, 2026
Merged

levy merged 7 commits into
inet-framework:masterfrom
mgonzalezlopezudc:work/compressed-blockack-s3b

Conversation

@mgonzalezlopezudc

@mgonzalezlopezudc mgonzalezlopezudc commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Block Ack setup and teardown can leave the two stations with different agreement state. The parent dispatches duplicate Actions, accepts unchecked setup responses, and treats absolute inactivity deadlines as relative delays. Setup can also consume sequence numbers before the agreement exists. These defects can repeat agreement changes, retain obsolete work, or let DATA use the wrong agreement.

This PR supplies the setup and teardown part of S3b, the agreement lifecycle stage. HCF, the hybrid coordination function, coordinates accepted Actions, agreement owners, DATA eligibility, and safe cleanup. The recipient data service checks duplicates before HCF dispatches an Action. Agreement handlers validate setup and retire obsolete work before resource release. Setup and recovery defer DATA for the affected peer and traffic identifier (TID), while other eligible traffic can continue.

Basic remains the default and retains legacy ad hoc and non-HT compatibility. HCF still rejects Compressed selection during initialization. This PR supplies lifecycle behavior that later Compressed exchanges will need. The main integration risks affect custom module contracts, queue accounting, and exchanges that the radio accepts before retirement. The migration guide explains the required changes.

Setup preserves the first sequence number

ADDBA establishes an agreement through a request and response. An ACK for the request confirms reception; only a matched successful response activates the originator agreement. The response must match the peer, TID, and dialog token. The handlers also validate status, immediate policy, profile, and supported parameters.

HCF first resolves DATA that already has sequence numbers. It defers further extraction for the same peer and TID before it creates ADDBA. The data service supplies the next sequence number without consumption. After acceptance, the first extracted DATA therefore receives the request number.

sequenceDiagram
    participant Q as Originator DATA queue
    participant O as Originator HCF
    participant R as Recipient
    O->>O: Resolve already numbered DATA
    O->>Q: Defer new extraction for this peer and TID
    Q-->>O: Next unassigned sequence number N
    O->>R: ADDBA Request with N, TID, and token
    R-->>O: Immediate ACK
    Note over O: Start response timer, default 100 ms
    R->>R: Validate request and create accepted agreement
    R->>O: ADDBA Response with accepted parameters
    O->>O: Match identity and validate response
    O-->>R: Immediate ACK
    O->>Q: Permit eligible extraction
    Q-->>O: First DATA receives sequence number N
    O->>R: DATA under the accepted agreement
Loading

The recipient response supplies the buffer size and inactivity timeout for both agreement owners. The built-in Basic recipient selects the smaller of 64 and its configured maximum. Request size zero supplies no size guidance. Both negotiated A-MSDU flags must permit aggregation. These rules give both owners the same accepted parameters.

One DATA frame without a successor causes no empty setup request. After an eligible Normal Ack transmission, the handler can wait for a later successor without an Action or timer. HCF starts setup before it extracts that successor.

Retries apply each accepted Action once

A valid MAC retry still receives its immediate ACK. The recipient data service returns only complete, nonduplicate Actions for agreement dispatch. The dialog token identifies setup; it does not replace MAC duplicate checks.

flowchart TD
    RX["Addressed ADDBA or DELBA"] --> C["Recipient service checks<br/>complete-frame state and duplicates"]
    C -->|Duplicate| D["Retain immediate ACK behavior<br/>No agreement dispatch"]
    C -->|Accepted complete Action| H["HCF dispatches once<br/>to the agreement owner"]
    H --> W{"Does the Action resolve<br/>the active procedure?"}
    W -->|Yes| S["Apply the result before exchange cleanup<br/>Suppress obsolete failure feedback"]
    W -->|No| F["Keep ordinary failure feedback<br/>for the interrupted exchange"]
Loading

For example, the request ACK can be lost before a successful ADDBA Response arrives during the request's final ACK wait. The originator accepts that response before obsolete request failure can cause teardown or DATA disposal. HCF selects the interruption outcome after recipient processing. An unrelated Action retains the interrupted exchange's ordinary failure result. The diagram shows decisions, not ACK timing.

Uncertain setup requires teardown before DATA resumes

DELBA ends an agreement. After any possible request transmission, response loss does not prove that the recipient lacks an agreement. The response timeout therefore starts DELBA recovery. DATA lifetime continues to limit deferred DATA throughout setup and recovery.

flowchart TD
    P["Setup pending<br/>DATA deferred"] -->|Matched success| A["Active agreement<br/>Release eligible DATA"]
    P -->|Initial rejection or cancellation<br/>before an accepted request attempt| N["No agreement<br/>Normal Ack DATA can resume"]
    P -->|Attempted request fails<br/>or response deadline expires| T["DELBA pending<br/>DATA remains deferred"]
    T -->|DELBA receives ACK| N
    T -->|Originator DELBA fails<br/>or suffers queue disposal| R["Discard current deferred batch<br/>Retain recovery state"]
    R -->|New DATA arrives| T
Loading

This INET profile treats the DELBA ACK as teardown confirmation. Failed originator DELBA discards the current deferred batch. Later DATA starts one fresh recovery exchange; no periodic retry timer runs. Failed recipient-role DELBA clears its procedure without disposal of opposite-direction DATA. Valid Block Ack-policy DATA or BAR without an agreement triggers recipient-role DELBA. That DATA receives no upper delivery, and that BAR creates no receive state.

HCF schedules the earliest absolute inactivity deadline across both agreement roles. A zero negotiated inactivity value disables expiration. The response timer starts after the request ACK, with a positive, finite configurable default of 100 ms. These timers have different purposes and remain separate.

Teardown preserves the correct DATA boundary

Directional teardown removes only the selected local role. The originator discards transmitted, unacknowledged DATA for that agreement. It also discards unsent fragments through the highest transmitted allocation index. The QoS data service assigns this local index before fragmentation; all fragments retain it in Ieee80211DataSequenceTag. The agreement retains the highest transmitted index after ACK processing removes an earlier fragment. Older retransmissions cannot move this boundary backward, and wire sequence numbers remain unchanged.

The fragment regression supplies a concrete example. DATA with sequence 0 transmits. The fixture allocates intervening DATA through the production data service and deletes that DATA without transmission. Fragment 0 of sequence 2048 then transmits. Allocation indices advance the boundary correctly despite the sequence gap; teardown removes unsent siblings and preserves later intact DATA.

This case tests an allocation gap; it does not test lifetime expiry of the intervening DATA. The fixture also checks sequence wraparound and teardown after fragment 0 receives its Normal Ack. These cases retain unrelated-peer DATA.

flowchart TD
    E["Agreement retirement"] --> O["Ordinary originator teardown"]
    O --> OD["Discard transmitted, unacknowledged DATA<br/>and unsent fragments through the transmitted boundary"]
    O --> OK["Preserve later intact DATA<br/>and the opposite agreement role"]
    E --> R["Ordinary recipient teardown"]
    R --> RD["Deliver complete buffered units in cyclic order<br/>Discard incomplete units"]
Loading

The recipient delivers complete buffered units across gaps before resource release. For example, complete units 101 and 102 reach the upper process despite absent unit 100. This release across a gap is INET policy.

First-DATA disposal needs a separate guard. If an internal collision discards the negotiated first DATA before transmission, HCF retires the agreement and queues DELBA. The successor remains deferred. Lifetime expiry and RTS failure use the same retirement mechanism.

Deferral preserves access for eligible traffic

A nonempty queue does not prove that its DATA can contend. HCF uses a pure eligibility query for contention and extraction. Deferred work cannot charge valid traffic in another access category an internal collision.

flowchart LR
    subgraph Q["Configured queue service order"]
        A["Peer A, TID 2<br/>Setup pending: deferred"]
        B["Peer B, TID 5<br/>Eligible"]
        C["Peer A, TID 2<br/>Deferred"]
        A --- B --- C
    end
    B --> X["Queue owner pulls B through a filter<br/>with ordinary pull effects"]
    A -.-> W["Keep queued DATA<br/>and its original lifetime"]
    C -.-> W
Loading

HCF uses the existing filtered canPullPacket() query to find unexpired DATA for a peer and TID. The data service uses an eligibility filter to select DATA past a deferred head. It supplies an identity filter to pullPacket() to transfer that selected frame. Each queue layer applies its ordinary pull effects once, including ownership, residence metadata, events, and statistics. An eligible advertised head retains ordinary dequeue. Queue and filter errors propagate without collection removal.

Custom pending queues must support filtered queries. A bypass also requires filtered pulls. For example, deferred DATA for peer A can precede eligible DATA for peer B. The filtered pull transfers B; A retains its queue position, sequence state, and lifetime. This PR adds no extractPacket() method or optional selection interface. CPacketFilterFunction accepts captured values so callers can express these acceptance conditions through the existing queue contract.

Commits and integration surface

The series starts at master commit 89d600a341976f646435ed341c3f980746c7d6be and ends at 80cfe33c0a73c8449bbe3aa4fd60a513d4d69fa4. The seven commits place prerequisites before their users. Each protocol test enters with its implementation fix, guide, and comparison record.

  1. 54d538def3 permits captured values in packet filters and tests ordinary pull effects.
  2. 61881413bf adds the shared protocol comparison procedure before its first test user.
  3. a69d6c9528 dispatches complete accepted Actions once and adds the duplicate test with its guide and comparison.
  4. c17821f17d validates negotiation and adds the dialog-token test with its guide and comparison.
  5. 2bc3054c9f prepares selective DATA extraction.
  6. acdef17618 tracks allocation order across fragments.
  7. 80cfe33c0a repairs lifecycle boundaries and adds BAR and inactivity tests, each with a guide and comparison.

The extraction and allocation commits prepare the lifecycle core. Negotiation records both A-MSDU flags before the core activates their combined permission.

Absolute deadline activation and expiry retirement form one change. At expiry, HCF detaches the agreement before it recalculates the timer. The expired deadline cannot schedule another immediate expiry event. For example, an agreement starts at 1 ms with a 4 ms timeout. HCF retires it once at 5 ms, and time can advance.

The lifecycle core exceeds 400 changed source lines because its active paths share Action invalidation, reference lifetime, and recovery eligibility. Its first retirement path must preserve all three conditions. For example, retirement during CTS wait must prevent protected DATA transmission. The accepted exchange retains its context until safe completion. Earlier commits supply the independent mechanisms before this integration.

The integration surface includes agreement handlers, recipient services, frame-sequence interruption, and filtered queue operations. The migration guide describes each changed contract. In particular, custom frame-sequence handlers implement interruptFrameSequence(). Agreement callbacks implement scheduleInactivityTimer() without an argument. Originator code calls recordTransmittedData(allocationIndex) to preserve the teardown boundary after ACK processing. This PR adds the operation and its local allocation metadata.

Custom QoS data services must supply Ieee80211DataSequenceTag before fragmentation. The new getHighestTransmittedDataIndex() query exposes the agreement's highest transmitted allocation index.

The new eligibility callback in OriginatorQosMacDataService::setEligibility() accepts const Packet *. Custom callers must use this signature. The shared queue change extends only the callable wrapper. PacketQueue, PriorityScheduler, and CompoundPacketQueueBase retain their implementations from master.

The configuration adds addbaFailureTimeout to the originator agreement policy. The PR adds Ieee80211DataSequenceTag.msg for local metadata; it changes no wire format, serializer, or feature descriptor. Changed source paths are unsealed. No new architecture or naming exception forms part of this PR.

The scope excludes explicit association reset, frame-sequence ownership of interruption outcomes, Compressed exchanges, final-transfer arbitration, MAC stop/start recovery, delayed policy, Multi-TID, and A-MPDU support. Basic remains historical INET compatibility. Its reserved type value does not establish current-standard support. S4 and later Compressed stages are outside this PR.

Protocol test documentation and evidence

Each protocol test has exactly two Markdown documents: one guide and one comparison record. Both enter with the test's implementation fix. The lifecycle commit adds two tests and therefore four Markdown files. The shared reproduction procedure and suite index use separate documentation commits.

Protocol test Guide Comparison record
Duplicate ADDBA Request Guide Before and after
Dialog token Guide Before and after
BAR without an agreement Guide Before and after
Inactivity deadline Guide Before and after

Each guide explains the scenario, diagrams, assertions, compliance justification, and profile limits, with the relevant standards references. Each comparison record reports observations before and after its fix. The shared procedure explains reproduction and corpus diagnostics.

Each before revision is the selected fix's first parent. Each after revision is the fix itself. Identical fixture inputs and successful assertions apply to both sides. The BAR and inactivity records use the same lifecycle fix and parent, but each reports only its own fixture.

Test Fix Parent Before and after
Duplicate request a69d6c9528 61881413bf FAIL: two dispatches before; PASS: one dispatch and two completed request ACKs after
Dialog token c17821f17d a69d6c9528 Two token checks fail before and pass after; the token control passes on both
Orphan BAR 80cfe33c0a acdef17618 Required DELBA is absent before and present after; the established-agreement control passes on both
Inactivity 80cfe33c0a acdef17618 Agreement remains at its deadline before and expires correctly after; the zero-timeout control passes on both

The comparison records report results at each fix and its parent. Their recorded results do not constitute a fresh test run at this PR head.

The wrong-token mutation remains artificial robustness evidence. Basic Block Ack remains historical INET compatibility, with a reserved current-standard BAR type. Direct stimuli bypass ordinary channel access. The 20 ms timeout is not an integer number of time units. The guides retain these limits; the tests do not establish complete standards conformance.

Verification and limits

The PR head is 80cfe33c0a73c8449bbe3aa4fd60a513d4d69fa4. The lifecycle commit now includes a human-readable explanation with eight diagrams. Its production source, tests, and baseline values remain unchanged. Document links and diagram syntax pass validation. No build or behavioral test ran for this documentation update. Earlier final-head results at 46978ae133 do not establish results for this head.

The four comparison records above retain their commands, recorded results, and scope limits. The shared procedure supplies reproduction instructions.

Seven functional fingerprint updates remain with the lifecycle commit that causes them. This branch update changes no baseline values. Release behavioral tests, graphical fingerprints, statistical comparisons, sanitizers, and feature-off builds remain unverified for this head. This update includes no independent correctness audit.

The association reset, interruption ownership, completion records, and suite index now reside on work/compressed-blockack-s3b-followup. That branch preserves the four commits from bf7f36fdc2 through 35282c579d above this PR head.

@mgonzalezlopezudc
mgonzalezlopezudc force-pushed the work/compressed-blockack-s3b branch from f6497bc to 3002141 Compare October 15, 2026 15:41
@mgonzalezlopezudc
mgonzalezlopezudc marked this pull request as ready for review October 15, 2026 15:41
@mgonzalezlopezudc
mgonzalezlopezudc force-pushed the work/compressed-blockack-s3b branch 2 times, most recently from 6b7c109 to 667ae51 Compare October 15, 2026 16:15
mgonzalezlopezudc added a commit to mgonzalezlopezudc/inet that referenced this pull request Oct 15, 2026
Before this commit, the S3b summary and execution record remain local files under plan/pending/. Their status describes an earlier unpublished candidate, although PR inet-framework#1343 contains the completed implementation.

After this commit, plan/done/ contains both records with the final source revision, results, scope limits, and corrected links. The execution record preserves its earlier evidence as a separate snapshot. The summary explains collision and fragment retirement, peer reset, and safe physical completion.

The final source revision is 8ba7c9e. Its recorded verification includes debug and release compilation, 26 selected debug module fixtures, and 19 functional fingerprint cases. This documentation change repeats no simulation test and changes no protocol behavior or recorded expectation. S4 and production Compressed exchanges remain outside the completed stage.

Local links resolve against published files or the two completed records. All nine document diagrams pass Mermaid syntax checks.

Plan: plan/done/ieee80211-compressed-blockack-s3b-summary.md
Change: plan | behavior.add | -
@mgonzalezlopezudc
mgonzalezlopezudc force-pushed the work/compressed-blockack-s3b branch 3 times, most recently from f6f12c5 to 992fcfb Compare October 15, 2026 19:22
@mgonzalezlopezudc
mgonzalezlopezudc force-pushed the work/compressed-blockack-s3b branch 2 times, most recently from 39fd321 to 0c23400 Compare October 17, 2026 21:29
levy added a commit that referenced this pull request Oct 19, 2026
Before this commit, no plan described how a pull consumer can take a packet behind a head that it cannot accept now. Pull request #1343 needs this for an 802.11 frame behind a frame that waits for ADDBA, and its first commit adds ISelectivePacketCollection, an optional second path beside the pull path with an exception and fallbacks, for priority scheduling only.

After this commit, plan/pending/queueing-filtered-pull-and-dequeue.md proposes the pull counterpart of canPushPacket(): the active sink gives its acceptance condition to the passive source as an IPacketFilterFunction, and the source pulls as if it held only the accepted packets, with the normal effects of every layer. The interfaces get declarations only, every Base throws "Invalid operation", and PassivePacketSource, EmptyPacketSource, PacketQueue, PriorityScheduler, WrrScheduler and CompoundPacketQueueBase opt in. IPacketQueue gets dequeuePacket(filter). The plan gives five steps with their tests, the rejected options, and three decisions for the owner.

Plan: plan/pending/queueing-filtered-pull-and-dequeue.md
Change: plan | behavior.add | - | queueing-filtered-pull
levy added a commit that referenced this pull request Oct 19, 2026
Before this commit, the plan of the acceptance filter left three decisions to the owner: the method names, a gate-less query on IPacketQueue, and the test category. It also left the use in the 802.11 MAC to pull request #1343.

After this commit, the plan records the decisions of the owner: overloads of canPullPacket(), pullPacket() and dequeuePacket(); no new query on IPacketQueue; module tests; and the recommendation that the MAC uses the filtered dequeue only to skip a blocked head. The approval of the implementation is still pending.

Plan: plan/pending/queueing-filtered-pull-and-dequeue.md
Change: plan | behavior.change | - | queueing-filtered-pull
levy added a commit that referenced this pull request Oct 19, 2026
Before this commit, the plan of the acceptance filter said that the work was ready for review on the branch topic/queueing-filtered-pull.

After this commit, it says that the work landed on master on 2026-10-19 with the approval of the owner, as a fast-forward of master ee4afb4 to 538ce90, and that the use in the IEEE 802.11 MAC belongs to pull request #1343.

Plan: plan/pending/queueing-filtered-pull-and-dequeue.md
Change: plan | behavior.change | - | queueing-filtered-pull
@mgonzalezlopezudc
mgonzalezlopezudc force-pushed the work/compressed-blockack-s3b branch 9 times, most recently from bebf604 to d0e4ca3 Compare October 20, 2026 16:00
Before this commit, CPacketFilterFunction accepts only function pointers. A consumer cannot use this wrapper for an acceptance condition with captured values. The filtered canPullPacket() and pullPacket() operations already exist.

After this commit, the wrapper stores a std::function that accepts const Packet *. Consumers can capture a selected packet or peer-specific eligibility state. Existing function pointers remain valid. For example, a filter can accept one queued packet behind a deferred head. The source retains its configured service order and applies ordinary pull effects.

The six fixture cases use existing filtered operations through simple and compound queues. Assertions cover query purity, ownership, residence metadata, pull events, reversed priority, and refusal without mutation. This commit adds no queue operation or interface.

Plan: plan/pending/ieee80211-compressed-blockack-replacement.md
Change: src.queueing | behavior.add | test whatsnew | ieee80211-compressed-blockack-replacement
@mgonzalezlopezudc
mgonzalezlopezudc force-pushed the work/compressed-blockack-s3b branch 2 times, most recently from c92e6a6 to 3ac4269 Compare October 20, 2026 16:48
Before this commit, the series lacks a shared procedure for protocol comparisons between a fix and its parent. Reviewers need identical fixture inputs and separate builds for the two revisions.

After this commit, the procedure explains revision selection, fixture copies, build mode, controls, and evidence reuse. Later commits use it for their per-test comparison records. The standards section preserves corpus diagnostics shared by the test guides. This commit changes no production source, fixture, or baseline.

Change: doc | behavior.add | -
Before this commit, the recipient service deletes accepted Actions before HCF dispatches their headers. HCF also dispatches duplicate Actions that the service rejects.

After this commit, the service returns complete accepted Actions after duplicate checks and reassembly. HCF dispatches each returned Action once before it deletes the frame. For example, an original request and its MAC retry cause two ACKs but one agreement dispatch. Two management fragments produce one complete Action.

Keep the existing recipient reorder cleanup until the later directional retirement commit supplies its replacement. This prerequisite changes reception ownership without activation of the new setup state machine.

The protocol fixture supplies request ACK loss and delays the response until the request retry. It requires one dispatch and two completed ACK transmissions. The observer records packet tree IDs for request ACKs and excludes unrelated DATA ACKs. Its guide and parent-to-commit comparison record explain the scenario, assertions, results, and compliance limits.

Plan: plan/pending/ieee80211-blockack-agreement-lifecycle.md
Change: src.ieee80211 | behavior.change.fix | test whatsnew migration | ieee80211-compressed-blockack-replacement
Before this commit, agreement policies accept responses without complete request correlation. The recipient can copy advisory request parameters into its agreement instead of its response parameters.

After this commit, the originator validates the peer, TID, nonzero dialog token, status, policy, buffer size, and timeout. Request creation supplies a per-peer token. The recipient echoes that token and installs its selected buffer size and timeout. For example, a request for eight entries can receive 64 entries, and the recipient stores 64.

The typed policy contract retains Basic admission without HT capability state. Isolated policy tests require local and peer HT eligibility for Compressed admission. Production HCF retains Compressed initialization rejection. The agreement stores both A-MSDU flags for the later lifecycle consumer.

The existing request path retains token assignment until the setup state machine replaces that path. No response timeout or recovery state machine becomes active here.

The protocol fixture checks response token echo, wrong-token rejection, and a matching-token control. The controlled peer uses production Tx and Rx. Its guide and parent-to-commit comparison record explain the assertions and identify the wrong-token mutation as artificial robustness evidence.

Plan: plan/pending/ieee80211-blockack-agreement-lifecycle.md
Change: src.ieee80211 | behavior.change.fix | test whatsnew migration | ieee80211-compressed-blockack-replacement
Before this commit, the QoS data service removes the next queued packet without an eligibility condition. That path cannot preserve deferred DATA when another peer has eligible work behind it.

After this commit, the service queries the first eligible packet in configured service order. It retains ordinary dequeue for the advertised next packet. Otherwise, an identity filter selects the packet through a normal filtered pull. Queue accounting, lifetime records, and ownership follow the queue's pull contract. A refused filtered pull propagates its error without source removal.

For example, a compound queue can contain deferred multicast DATA before eligible unicast DATA. The service extracts the unicast packet while the multicast sources retain their sequence numbers and deadlines. The service checks all A-MSDU candidates before removal and calls the aggregation policy once.

HCF gains the queued-DATA query for later setup coordination. This commit supplies the optional callbacks; the lifecycle commit activates deferral.

Plan: plan/pending/ieee80211-blockack-agreement-lifecycle.md
Change: src.ieee80211 | behavior.add | test whatsnew migration | ieee80211-compressed-blockack-replacement
Before this commit, agreement state has no durable allocation order after ACK processing removes DATA. Cyclic sequence numbers alone cannot order transmissions across an exact half-range gap.

After this commit, the QoS data service assigns an allocation index before fragmentation. Every fragment retains that index. The originator agreement records the highest transmitted index when Tx accepts DATA. An older retransmission cannot move the index backward. Wire sequence numbers remain unchanged.

For example, allocations 0 and 2048 can transmit before a retransmission of allocation 1. The retained index remains 2048. The later retirement commit uses this boundary to discard unsent fragments of a partially transmitted unit.

Custom QoS data services must supply the tag. Custom originator code must record the index when Tx accepts DATA. This commit adds metadata without activation of the retirement consumer.

Plan: plan/pending/ieee80211-blockack-agreement-lifecycle.md
Change: src.ieee80211 | behavior.add | test migration | ieee80211-compressed-blockack-replacement
@mgonzalezlopezudc
mgonzalezlopezudc force-pushed the work/compressed-blockack-s3b branch 3 times, most recently from 63bd715 to b16ef7c Compare October 21, 2026 10:11
Before this commit, HCF treats absolute inactivity deadlines as relative delays. DATA extraction can advance sequence state before setup resolves. Action disposal lacks one procedure outcome. Teardown can retain obsolete Actions or unsent fragments of transmitted DATA.

After this commit, HCF coordinates setup intent, request identity, response deadlines, teardown, and recovery with the agreement handlers. Already numbered DATA resolves before ADDBA. New DATA for that peer and TID waits until setup or recovery resolves. Another peer remains eligible. The response timeout starts after the request ACK.

HCF schedules the earliest absolute inactivity deadline across both agreement roles. At expiry, HCF detaches the agreement before timer recalculation. For example, an agreement created at 1 ms with a 4 ms timeout expires once at 5 ms. Time can advance after retirement.

Directional retirement detaches the agreement before cleanup and deletion notification. The recipient releases complete units in cyclic order and discards incomplete units. The originator discards transmitted DATA and unsent fragments through the highest transmitted allocation index. For example, transmission at allocations 0 and 2048 cannot leave unsent siblings of allocation 2048 after teardown. Later intact DATA remains eligible.

Owned Actions produce one terminal outcome. Invalidation prevents obsolete callbacks from changing a later agreement. Accepted exchanges retain their references until safe completion. An exchange in CTS wait cannot submit retired protected DATA after CTS. Uncertain setup requires DELBA before surviving unsent DATA resumes. Failed DELBA discards its batch; later DATA can start recovery again.

This commit also activates the earlier extraction callbacks and negotiated A-MSDU permission. EDCA excludes deferred work from collision decisions. Internal-collision disposal, lifetime expiry, and RTS failure retire first DATA through the same mechanism. Valid Block Ack DATA or BAR without an agreement causes recipient-role recovery without receive-state allocation.

The source exceeds 400 changed lines because these active paths share Action invalidation, reference lifetime, and recovery eligibility. Their first use must preserve all three conditions. Separate preparation commits already supply reception, negotiation, selected extraction, and allocation metadata. Absolute deadline activation stays with retirement because expiry must remove the expired deadline before timer recalculation. Association reset follows in its own commit.

The fingerprint rows change because numbered DATA resolves before ADDBA and setup waits for a successor. The affected cases are ad hoc MacQos run 1, infrastructure MacQosWithBlockAck, the three Block Ack showcases, HCFfragblockack, and TXOP General. These setup boundaries change transmitted frames and event order. Graphical expectations remain unchanged.

The protocol fixtures check orphan-BAR DELBA and recipient expiration at the absolute deadline. Controls check an established agreement and disabled expiration. Their guides and parent-to-commit comparison records explain the production paths, recorded parent and fix results, and compatibility limits.

Plan: plan/pending/ieee80211-blockack-agreement-lifecycle.md
Change: src.ieee80211 | behavior.change.fix | test whatsnew migration fingerprint | ieee80211-compressed-blockack-replacement
@mgonzalezlopezudc
mgonzalezlopezudc force-pushed the work/compressed-blockack-s3b branch from b16ef7c to 80cfe33 Compare October 21, 2026 10:13
@levy
levy merged commit dcae92d into inet-framework:master Oct 21, 2026
18 of 19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants