Skip to content

ieee80211: repair Basic Block Ack agreement lifecycle - #1343

Open
mgonzalezlopezudc wants to merge 4 commits into
inet-framework:masterfrom
mgonzalezlopezudc:work/compressed-blockack-s3b
Open

mgonzalezlopezudc wants to merge 4 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 completes 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. Peer reset clears this state.

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. The frame-sequence handler owns 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"]
    E --> A["Association reset"]
    A --> AD["Clear both roles and old peer work<br/>Discard old receive buffers"]
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. Association reset instead discards old buffered units. With Block Ack enabled, reset also discards old-peer queued and in-progress QoS DATA, including unsent Normal Ack DATA without an agreement.

Management supplies the old peer identity before association replacement, even when the new capabilities equal the old capabilities. HCF detaches both roles before deletion callbacks. Another peer retains its agreements, DATA, and lifetime records. The MIB retains its boolean notification and coherent committed state.

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 extracts B<br/>with ordinary pull effects"]
    A -.-> W["Keep queued DATA<br/>and its original lifetime"]
    C -.-> W
Loading

An optional queue contract permits extraction past deferred DATA. Each queue layer applies its ordinary ownership transfer, residence metadata, events, and accounting once. An eligible advertised head needs no optional capability. If a required bypass lacks support, the service refuses it before ownership or sequence state changes.

Physical completion does not authorize retired work

Logical retirement cannot delete a context that the radio still uses. An accepted exchange retains its physical completion context and records physical statistics. Its later callbacks cannot submit retired work after CTS. The frame-sequence handler destroys the context before deferred frame copies.

sequenceDiagram
    participant H as HCF
    participant T as Radio and transmitter
    participant M as Management
    H->>T: Submit RTS for DATA A
    T-->>H: Accept transmission
    M->>H: Reset old peer
    H->>H: Retire DATA A and detach agreements
    Note over H,T: Keep the accepted exchange context
    T-->>H: CTS arrives for the accepted exchange
    H->>H: Refuse retired DATA A after CTS
    H->>H: Complete physical accounting and release context
Loading

Commits and integration surface

The comparison starts at master commit 675655fc3559231c56b12d651384cb8695255abc and ends at 0c234006883d25a5d47458bdf68abfc29d85f96d. These four commits form the exact S3b prefix of #1363. Corrective collision and fragment retirement changes reside in their lifecycle owner.

  1. 435fc0866d adds selected extraction with ordinary queue effects; it prepares the lifecycle consumer.
  2. 2c6b1df761 connects Action delivery, setup, retirement, reset, and deferred DATA selection.
  3. 832dc3672c gives the frame-sequence handler ownership of interruption outcomes.
  4. 0c23400688 records S3b completion and its verification scope.

The lifecycle conversion changes its contracts, handlers, and HCF together. Its first retirement path needs Action invalidation and safe exchange completion. A partial caller conversion would leave unsafe frame references or eligible obsolete Actions.

The integration surface includes agreement handlers, recipient services, management reset, frame-sequence interruption, and optional queue selection. 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 replaces markFirstDataTransmitted() and the former cyclic-sequence overload.

Custom QoS data services must supply Ieee80211DataSequenceTag before fragmentation. The agreement exposes its highest transmitted allocation index through getHighestTransmittedDataIndex(), which replaces getHighestTransmittedSequence().

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 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.

The completed S3b summary explains component ownership. The execution record separates final verification from earlier results. Completion records the branch state; it does not assert a merge into master.

Verification and limits

Fresh debug and release builds pass at 0c234006883d25a5d47458bdf68abfc29d85f96d with all 12 available CPUs. The debug campaign covers every changed test fixture in the master comparison. All selected fixtures report their expected successful result.

Check Result
Debug and release compilation Both PASS.
Module fixtures 14 PASS.
Functional fingerprint cases 7 PASS, with unchanged expectations.
Series and description gates All five PASS.
Source seals and scoped MAC architecture PASS.
Global architecture, naming, and interface gates The same inherited findings remain. These gates retain exit code 1.

The global comparison checks the finding text. Counts of unchanged interfaces and examined declarations can differ between stages. These counts do not introduce new findings.

Executed commands and selectors

The build commands run from this PR's checkout root:

make MODE=debug -j12
make MODE=release -j12
opp_repl --load /home/user/omnetpp-6.4.0aipre2/.venv/lib/python3.14/site-packages/opp_repl/opp/inet.opp -p inet

The opp_repl adapter selects this checkout's inet_project. It calls the checked-out test functions with these exact arguments. It rejects empty selections and unexpected results.

run_module_tests(simulation_project=inet_project, mode="debug", filter=r"(?:Ieee80211BlockAckActionDelivery_1\.test|Ieee80211BlockAckActionDispatch_1\.test|Ieee80211BlockAckActionDisposal_1\.test|Ieee80211BlockAckAdmission_1\.test|Ieee80211BlockAckAssociationReset_1\.test|Ieee80211BlockAckDataSelection_1\.test|Ieee80211BlockAckDeferral_1\.test|Ieee80211BlockAckDeferredCollision_1\.test|Ieee80211BlockAckFragmentRetirement_1\.test|Ieee80211BlockAckLifecycle_1\.test|Ieee80211BlockAckNegotiation_1\.test|Ieee80211BlockAckResponseWait_1\.test|Ieee80211BlockAckRetiredData_1\.test|PacketSelectiveExtraction_1\.test)$", concurrent=False)

The fingerprint command runs from tests/fingerprint:

./fingerprinttest -d -F tyf -t 3 -m 'showcases/wireless/blockack/|showcases/wireless/fragmentation/.*-c HCFfragblockack |showcases/wireless/txop/|examples/adhoc/qos/.*-c MacQos -r 1|examples/wireless/qos/.*-c MacQosWithBlockAck ' showcases.csv examples.csv

The mechanical checks use the pinned master base 675655fc3559231c56b12d651384cb8695255abc. They cover the complete series and description, source seals, scoped MAC architecture, and the three global gates. This campaign changes no recorded expectation.

Seven previously approved functional fingerprint rows remain with the lifecycle change in 2c6b1df761. Numbered DATA resolves before setup, and setup waits for a later successor instead of an empty request. The collision and fragment repairs introduce no further baseline change. This synchronization changes no baseline value.

All four commits retain their scoped debug results from the #1363 reconstruction. The final tree exactly equals the former PR head, 39fd321b0d3c0f4d93ae5cfd16c72c8a7df74907. Fresh checks below cover the synchronized head.

Release behavioral tests, graphical tyf fingerprints, sanitizers, and other platforms remain unverified. This synchronization supplies no new independent correctness audit. Local test results do not establish CI results.

@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 from 992fcfb to 39fd321 Compare October 17, 2026 13:40
Before this commit, consumers can inspect queued packets but cannot extract a later eligible packet with ordinary pull effects. Collection removal represents disposal. Deferred Block Ack DATA needs selection past an ineligible head without loss of queue observations.

After this commit, the optional collection contract provides a pure predicate query and atomic selected extraction. PacketQueue, CompoundPacketQueueBase, and PriorityScheduler preserve configured service order. Each layer applies its ordinary pull effects once. For example, extraction behind a deferred head retains ownership, residence metadata, and queue events.

An unsupported provider reports UnsupportedPacketSelection before extraction. Other queue and predicate errors retain their types. Direct tests cover storage, ownership, metadata, events, scheduler order, and unsupported providers. Ordinary head service remains unchanged.

Plan: plan/pending/ieee80211-compressed-blockack-replacement.md
Change: src.queueing | behavior.add | test whatsnew | ieee80211-compressed-blockack-replacement
Before this commit, Action dispatch can reuse deleted headers and repeat agreement effects. Setup can accept an uncorrelated response. Teardown can retain obsolete work or unsent fragments of transmitted DATA. DATA extraction can advance sequence state before setup resolves.

After this commit, HCF dispatches complete accepted Actions once. Handlers correlate peer, TID, and dialog token before acceptance. The response determines agreement parameters. Directional retirement detaches the agreement before cleanup. Association replacement clears both roles before notification. Accepted physical exchanges finish safely but cannot submit retired protected frames after CTS.

Setup defers new DATA extraction until the procedure resolves. Already numbered DATA resolves before ADDBA. A later successor can start setup after an empty interval without an empty request. The response timeout starts after the request ACK. Uncertain setup requires DELBA before surviving unsent DATA can resume.

The QoS data service assigns a monotonic allocation index before fragmentation. All fragments retain that index in a tag. The agreement retains its highest transmitted index after ACK removal. Teardown uses that index to discard incomplete DATA. Older retransmissions cannot move the boundary backward. Wire sequence numbers remain unchanged.

For example, sequence 0 transmits before sequences 1 through 2047 expire. Fragment 0 of sequence 2048 next transmits. Teardown discards its unsent siblings despite the exact half-range gap. Later intact DATA and unrelated peer DATA remain eligible. Deferred deletion protects references during accepted physical exchanges.

An internal collision that discards first DATA also triggers retirement. HCF queues DELBA before the unsent successor can resume. Contention uses current eligibility, so deferred work cannot charge another category an internal collision. HCF schedules the earliest absolute deadline across both agreement roles.

These lifecycle contracts change together because retirement requires safe Action invalidation and accepted-exchange completion at first use. The shared queue capability precedes this commit. Direct fixtures cover Action correlation, timeout, collision, fragment retirement, sequence gaps, and association reset. The migration guide explains custom-module contracts.

Seven approved Basic fingerprint rows describe the changed setup boundaries. Numbered DATA resolves before setup, while infrastructure MacQosWithBlockAck waits for later DATA instead of empty-successor setup. Graphical expectations remain unchanged. Basic remains the default. Compressed exchanges, final-transfer arbitration, and MAC stop/start remain outside this commit.

Plan: plan/pending/ieee80211-compressed-blockack-replacement.md
Change: src.ieee80211 | behavior.change.fix | test whatsnew migration fingerprint | ieee80211-compressed-blockack-replacement
Before this commit, HCF chooses completion or failure when an accepted Action interrupts a response wait. The frame-sequence handler owns the relevant exchange state, so receive dispatch duplicates that decision.

After this commit, HCF requests interruption without an outcome argument. The frame-sequence handler checks whether recipient processing retires the outgoing frame. A retired frame completes without failure feedback. Other exchanges retain the ordinary failure path. HCF cancels the receive timer at sequence completion.

For example, a correlated Action can retire outgoing management work during a response wait. The handler completes that retired exchange without failure feedback. Existing fixtures also cover refusals, unrelated Actions, and immediate ACK behavior. Custom handlers must implement the no-argument interruption operation. The migration guide explains this contract. Built-in packet behavior and event order remain unchanged.

Plan: plan/pending/ieee80211-compressed-blockack-replacement.md
Change: src.ieee80211 | refactor | test migration | ieee80211-compressed-blockack-replacement
Before this commit, the branch lacks committed S3b completion records. Reviewers need component responsibilities, scope limits, and verification results in one record.

After this commit, plan/done/ contains the summary and execution record. The summary explains agreement setup, retirement, peer reset, and safe physical completion. The execution record explains allocation indices and separates results by original source revision. Those historical revision identifiers remain unchanged.

The records describe debug and release compilation, focused module fixtures, and functional fingerprint checks for the original implementation and later retirement repair. This documentation commit changes no protocol behavior or recorded expectation. S4 and production Compressed exchanges remain outside the completed stage.

Plan: plan/done/ieee80211-compressed-blockack-s3b-summary.md
Change: plan | behavior.add | -
@mgonzalezlopezudc
mgonzalezlopezudc force-pushed the work/compressed-blockack-s3b branch from 39fd321 to 0c23400 Compare October 17, 2026 21:29

This branch has not been deployed

No deployments
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.

1 participant