TXOP loss from RTS, CTS and Block Ack¶
Method on 2026-10-20¶
On the anonymized test data in testdata/sessions/, with tshark 4.6.8 and the radiotap TSF (radiotap.mactime) as the clock. RTS, CTS and Block Ack go at legacy rates, so the sensor captures them whatever MCS the data uses.
- Per RTS from the client to the AP: a CTS to the client within 200 µs, and a Block Ack from the AP to the client within the RTS's duration plus 60 µs. Without the CTS the RTS went unanswered; with the CTS and without the BA the data, or its BA, was lost whole.
- Per RTS from the AP to the client: a Block Ack from the client within the same span. Without it, the next frame of the AP to the client or of the client within 2 ms: an RTS again is an RTS the client left unanswered.
Until 2026-10-20 the client's CTS to the AP was outside the focus filter: a CTS has no transmitter address, and its receiver is the AP. In the downlink of the sessions below an unanswered RTS and data lost whole therefore look alike, apart from the RTS that comes again. Since then the filter takes it, and the downlink splits like the uplink (below).
Results¶
| Session | Channel | Client | RTS client → AP: unanswered / CTS without BA | RTS AP → client: with BA / again within 2 ms | AP's RTS per client BA | BA success down / up |
|---|---|---|---|---|---|---|
u7-phone-same-channel |
5 GHz ch 48/80 | phone | 377: 0.3 % / 0.3 % | 17 RTS | – | 99.7 % / 100 % |
testlab-baseline |
5 GHz ch 48/80 | A9000 | none sent | 1,255: 80.2 % / 17.4 % | 6.5 % | 100 % / 100 % |
testlab-co-channel |
5 GHz ch 48/80, a second AP on it | A9000 | 975: 17.5 % / 3.1 % | 4,064: 62.2 % / 2.7 % | 7.4 % | near 100 % |
testlab-intermittent-loss |
2.4 GHz ch 6/20 | MacBook | 31,453: 22.1 % / 18.3 % | 5,195: 47.2 % / 37.8 % | 26.6 % | 98.4 % / 98.7 % |
The A9000 client sent RTS only in the two minutes of co-channel before the phone's download, none during it; the U7 started a few percent of its TXOPs on 5 GHz with RTS, the Mac on 2.4 GHz nearly all of them.
The microwave oven¶
testlab-intermittent-loss in steps of 4 s, the client's RTS:
| Seconds | RTS per 4 s | Unanswered | CTS without BA | The AP's RTS to the client |
|---|---|---|---|---|
| 136–160 | 580–750 | 19–22 % | 10–21 % | 90–190 per 4 s |
| 164–176 | 226–286 | 26–34 % | 25–33 % | none from 168 to 176 |
| 176–200 | 760–880 | 23–26 % | 18–28 % | about 100 per 4 s |
In the oven's window BA success read 81.5 % down, most of it given up by the AP's BARs, and 94.6 % up.
With the iPhone on the AP45's ch 6, 2 m from the oven and the AP45 in the office (testlab-intermittent-loss-psk-iphone, 2026-11-04), BA success read 99.0 % down and 100.0 % up in the oven's window: the retries delivered what the oven took. The oven showed in everything else. The AP's frames sent again rose from 11 to about 40 %, the client's from 18 to about 34 %, and the TXOPs with RTS that failed went from 49 to 55 % down and from 20 to 38 % up. In the recording before it (testlab-intermittent-loss-psk-iphone-moved) the AP's frames sent again read about 46 % and the client's 30 % in the oven's window, at about 97 % BA success down.
The data fell far less than the sensor decoded: the sensor stood near the oven too and captured 55 % of the downlink at the worst. Against the session's median, in the worst window of each recording:
| Recording | New MPDUs by the AP's sequence numbers | Delivered by the Block Acks | Decoded by the sensor | Downlink captured |
|---|---|---|---|---|
testlab-intermittent-loss-psk-iphone |
0.78 | 0.80 | 0.43 | 54.6 % |
testlab-intermittent-loss-psk-iphone-moved |
0.93 | 0.93 | 0.68 | 71.1 % |
testlab-intermittent-loss |
0.60 | 0.46 | 0.50 | 93.5 % |
What the sensor misses does not touch the sequence numbers. The download held to 2 Mbit/s kept most of its rate: the retries delivered it, at a higher cost in airtime.
Against the client's own level¶
The shares sent again in the windows that decide, on all 58 recordings on 2026-11-04, in points above the level of each direction:
| Window | Sent again AP / client | Jump AP / client | Right after wakes |
|---|---|---|---|
…-psk-iphone 17:49:09, the oven |
31.6 % (Mist) / 33.6 % | 12.9 / 14.8 | 21.5 % |
…-psk-iphone 17:49:04, the oven |
30.3 % (Mist) / 28.8 % | 11.6 / 9.9 | 17.6 % |
…-psk-iphone-moved 17:31:12, the oven |
32.9 % (Mist) / 28.8 % | 13.5 / 9.6 | 26.2 % |
…-psk-iphone-moved 17:31:07, the oven |
32.9 % (Mist) / 26.4 % | 13.5 / 7.2 | 23.6 % |
…-psk-iphone-moved 17:34:17, 139 wakes |
8.7 % / 19.2 % | −1.6 / −0.1 | 39.0 % |
ap45-phone-reconnect 21:07:03 |
33.3 % / 15.0 % | 14.7 / 12.2 | 100 % |
testlab-client-leaves-sae-mac 18:13:59, its first |
24.3 % / 22.0 % | 17.4 / 13.6 | 94.3 % |
A jump alone does not tell the oven: the reconnect's is larger than the oven's in the second recording. What does:
- Both directions in one window. Of the 2,632 windows outside the ovens with a measure, the AP jumped 7.5 points in 136, in 24 recordings, the client in 28, in 11 recordings, and both in 4.
- Not mostly right after wakes. Those 4 were, the ovens were not. Of the 48 windows that are lost both ways today and not after wakes, the largest jump in both directions is 3.2 points, against 9.6 in the oven. 7.5 points stands on that gap, nearer the oven's side, as a missed oven stays a note and a false finding names a side.
BA success low with the other way at its usual level is the window of the 139 wakes alone, 5.0 points under the phone's 94.6 %, where the first oven lay 12.5 to 18.4 under its 99.9 %, with the client's frames jumping beside it: the same 7.5 points tell a dip from a loss one way, which no recording holds yet.
The data falling separates nothing: decoded, the downlink stood at 0.8 of the median or less in 184 of 805 windows outside the ovens, in 26 recordings, and by the Block Acks in 150, in 24; the window of the 139 wakes fell further by the Block Acks than the oven in the same recording. Other levels gave the same verdicts at 7.5 points: the median of every window, of the windows before it, and the lower quartile. The level is per BSS, as it differs there: the AP sent 1.2 % again on one BSS and 17.3 % on the other in u7-phone-search-copies, and the client 0 and 13.6 % in u7-phone-search-again. The retry bit is no measure of the AP's frames under 90 % captured: outside any oven it read up to 34.5 points over its level (u7-phone-search-again).
One MPDU¶
At 75.5 s, before the oven: the Mac sent MPDU 3262 about ten times in 36 ms, each after an RTS, with the retry bit, its rate falling from 43 to 7.2 Mbps. Two BAs from the AP in between started at 3263 and 3265, past it; the BA at 36 ms acknowledged it. BA success counts it once, as delivered.
What it shows¶
- With the client sending RTS, the TXOP outcome is a sensitive measure: 0.3 % lost on a clean 5 GHz channel, about 40 % on the home 2.4 GHz channel where BA success reads 98.4 and 98.7 %, and about 60 % with the oven. BA success sees the oven only through the AP's BARs.
- It runs only while a transmitter uses RTS, and that changes per device and over time. Without RTS the measure is untested.
- A transmitter that sends an RTS mostly before a retransmission gives the failed share of its retransmissions, not of its TXOPs: 70 % of the U7's TXOPs with RTS to the phone failed while BA success read 99.5 % (below).
- An unanswered RTS is no loss by itself: the receiver may have its NAV set by another BSS (contention at the receiver), be dozing or be off-channel. The A9000 client seemed to leave 17 % of the AP's RTS unanswered on a clean channel where every MPDU was delivered, before its CTS was in the capture; with it, 1 of 710 went unanswered and 10.8 % had a CTS and no Block Ack (below). A CTS without a BA is the closer loss measure: in the uplink from the start, in the downlink since the focus filter takes the client's CTS and ACK to the AP (below).
- In a few samples of co-channel the U7's data frame after an RTS it repeated within 2 ms carried the retry bit: an unanswered RTS may set it. The AP45 does: it sent 12 to 20 MPDUs with the retry bit that had not been on the air before per RTS the MacBook left unanswered (mist-events.md). The retry share of co-channel (22 % up) then counts contention as well as loss; the A9000 there set it on frames the sensor had not seen on the air before in three of five retries (below).
In the engine¶
TxopTracker counts the same on the same sessions (golden files): the Mac's uplink in testlab-intermittent-loss 31,453 RTS, 22.1 % unanswered and 18.3 % with a CTS and no answer, 40.4 % failed; co-channel's uplink 17.5 % and 3.1 %; the baseline's downlink 17.5 % unanswered. In the downlink it settles a TXOP on the first frame of the AP to the client or of the client after the RTS's duration, so a few percent more go to no Block Ack than above (36.1 % unanswered in testlab-intermittent-loss).
The downlink with the client's CTS¶
On the Mist AP45 with the phone on 5 GHz ch 52/20, on 2026-10-21 (power-save.md), as TxopTracker counts them:
| Session | The AP's RTS to the phone | Unanswered | CTS, then no Block Ack | The phone's RTS: unanswered / CTS without answer | BA success down / up |
|---|---|---|---|---|---|
| A download, outside the repo | 111,369 | 0.4 % | 1.9 % | 57,513: 5.9 % / 1.2 % | 99.2 % / 99.7 % |
testlab-power-save-video |
4,429 | 0.6 % | 13.7 % | 4,206: 1.3 % / 1.0 % | 98.0 % / 100 % |
testlab-power-save-second-client, the phone |
2,361 | 0.5 % | 10.1 % | 2,425: 1.2 % / 1.2 % | 98.4 % / 100 % |
testlab-power-save-second-client, the Mac |
5,294 | 0.9 % | 8.6 % | 4,574: 2.2 % / 1.8 % | 98.8 % / 99.5 % |
The download's row replayed at dfc1efb on 2026-11-03: its TXOPs as before, its BA success 99.2 % / 99.7 % against 98.9 % / 99.5 % with the rule before, which counted the frames of a Block Ack for an older window again.
The AP45 sent an RTS before 86 to 90 % of its frames to the phone, and the phone answered nearly every one. In the video's bursts one in seven of the AP's TXOPs was lost whole after the phone's CTS, the phone awake, and one in ten for both the phone and the Mac when both dozed between bursts; BA success counts none of them.
What is still to check is in the plan (docs/status.md).
The A9000 on the U7, 2026-10-23¶
The client's CTS and ACK in the capture, AP A at home, as TxopTracker counts them (outside the repo, testlab-baseline.md, eht-capture.md, sensor-link.md):
| Session | The AP's RTS: unanswered / CTS, then no Block Ack | The client's RTS: unanswered / CTS without answer |
|---|---|---|
| 5 GHz ch 48/80, UDP 2 Mbit/s both ways | 710: 0.1 % / 10.8 % | none |
| The same, TCP uplink at 94 Mbit/s | 5,697: 4.6 % / 5.8 % | 40,450: 0.5 % / 2.9 % |
| 6 GHz ch 37/160, TCP downlink at 1.29 Gbit/s, sensor on USB 3 | 6,251: 0.1 % / 0.8 % | 5,775: 8.6 % / 3.2 % |
The phone on the U7, 2026-10-25¶
The recording of 2026-10-25 15:17, 712 s, outside the repo (roam-u7.md): the phone with a video 1 m from the sensor, on AP A's 5 GHz (ch 48/80) until it roamed to AP B (ch 100/80) at 15:19:15. TxopTracker counts 174 RTS of the APs to the phone, 61 % of them failed, while BA success towards the phone read 99.5 % and 2.0 % of the phone's own 5,344 RTS failed:
| The AP's RTS to the phone | RTS | Delivered | Unanswered | CTS, then no Block Ack |
|---|---|---|---|---|
AP A, on capA |
144 | 43 | 8 | 93 |
AP B, on capB until 15:21 and on capA after its lock at 15:22:36 |
30 | 25 | 0 | 5 |
The counts are what the air shows. Each CTS came 60 µs after AP A's RTS at the phone's signal (−44 dBm, chains −46 and −47; the phone's own RTS −44 with −46 and −48, AP A's frames −45 with −46 and −52), AP A's A-MPDU followed, and no Block Ack or ACK of the phone came before AP A's next frame; in its next TXOP AP A sent the same MPDUs again with the retry bit, so it had no Block Ack either. At 15:18:14.7, for one: AP A sent MPDUs 3469 and 3470 at HE MCS 10 2 SS twice without an RTS and drew no Block Ack; then six RTS in 4.2 ms, each answered by the phone's CTS, each followed by the same MPDUs again and new ones, at MCS 10, 10, 9, 9, 9 and 8. Only the sixth drew the phone's Block Ack, with three of the MPDUs still missing. BA success counts every one of them as delivered: each A-MPDU was lost whole and delivered on a retry.
The share is high because AP A sends an RTS before a retransmission and seldom before a first transmission. Of the 122 RTS after which an MPDU of AP A was captured, 117 were followed by one with the retry bit, and AP A's 144 RTS stand against 2,440 Block Acks of the phone to it. They came in 42 runs less than 5 ms apart, up to eight in a row, 35 of the runs ending in a delivered TXOP. The failed share of AP A's TXOPs with RTS is that of its retransmissions; the phone's own RTS, before nearly every TXOP (5,344 against 5,356 Block Acks of the APs), are the unselected sample. Why the phone left those A-MPDUs unanswered is open: they failed at every rate AP A tried, from HE MCS 10 2 SS at 80 MHz (1,080.9 Mbit/s) down to 275 Mbit/s, beamformed or not alike (70 and 68 %), 72 of the 101 failed TXOPs in the minute from 15:18.
capB on AP B's 5500 also decoded about a hundred of AP A's frames from 260 MHz away, at −82 dBm (a9000.md). None of them counted: the engine puts an RTS or Block Ack on the link of the AP it names and counts it from the radio on that AP's primary channel, here capA (one radio per link, LinkMetrics). capB's 15 TXOPs are all AP B's, until 15:20:59, and capA's 15 of AP B came after its lock on AP B: none counted twice. The CTS and ACK to an AP have no transmitter address; they took the link of the frequency they were heard on, and capB counted six copies of the phone's CTS to AP A on its own link, where no TXOP of AP A was open, so no count changed. Since 2026-10-25 they take the link of the AP in their RA, and a radio listening outside that AP's channel, as capB here, counts none of a link's frames (LinkMetrics, a9000.md).
The phone on the AP45, 2026-11-01¶
The app's recording of 2026-11-01 23:40, 248 s, outside the repo (~/linkside-captures/2026-11-01-2340-…): the phone on eduroam on the AP45's 5 GHz ch 112 at 20 MHz, next to the sensor, the AP at −41 dBm there. The AP45 sent an A-MPDU to the phone twice at HE MCS 10, 2 streams, the phone answering each RTS with a CTS and sending no Block Ack, and a third time at MCS 8, which the phone acknowledged: the AP's rate after a pause too high for the phone, then lower. Over the session:
| Towards the phone | Count |
|---|---|
| BA success | 98.6 % (27,547 MPDUs delivered, 392 lost) |
| The AP's data frames with the retry bit | 6,334 of 34,061 (18.6 %), 99.3 % of the downlink captured |
| The AP's TXOPs that start with an RTS | 10,400 |
| CTS, then no Block Ack | 1,086 (10.4 %) |
| Unanswered | 382 (3.7 %) |
Delivery was good; the airtime it cost was not, and it grows with the load. The Overview grades the first and shows the second beside it (the verdict); the note of frames sent again in the window of 23:41:51 to 23:42:11 named 37.1 %.
The client's retry bit, 2026-10-29¶
Since 2026-10-29 the loss rules count the client's frames sent again by the retry bit, as they count the AP's (rules): BA success counts an A-MPDU lost whole and delivered on a retry as delivered, both ways. Per data frame of the client with the retry bit (Null and QoS Null left out), whether capA captured the same TID and sequence number from it within 2 s before, in the recordings and windows where uplink-loss or two-way-loss found the client's frames sent again (tshark on capA.pcap):
| Recording, window | The client's data frames | Retry bit | On the air before | Not seen before |
|---|---|---|---|---|
testlab-intermittent-loss, the Mac on 2.4 GHz, the session outside the oven's window |
31,849 | 24.6 % | 24.6 % | 0 |
| The same, the oven's window | 4,248 | 49.9 % | 48.5 % | 1.4 % |
| The same, the window of the note outside the oven | 3,264 | 23.5 % | 23.4 % | 0.1 % |
testlab-co-channel, the A9000 beside the busy co-channel AP |
3,278 | 23.3 % | 8.8 % | 14.5 % |
u7-phone-search-again, the phone |
185 | 23.2 % | 23.2 % | 0 |
ap45-phone-reconnect, the phone up to its own disconnect |
280 | 15.0 % | 10.7 % | 4.3 % |
- The Mac set the retry bit only on frames that had been on the air: the 22.1 % of its RTS the AP left unanswered (above) left no trace in it. Its frames sent again are its losses, a quarter of them on the home 2.4 GHz channel without the oven and half with it, while its BA success read 99.9 and 94.6 %.
- The A9000 beside a busy co-channel AP set it on frames the sensor had not seen before in three of five retries: after an RTS left unanswered, or frames the sensor missed. For such a client the uplink's retry bit counts contention as well as loss, as the AP45's does towards the client (mist-events.md).
- The phone reached 15 to 23 % in windows of a few hundred frames, in sessions without a problem: with nothing to compare, the client's frames sent again are a note, as the AP's are towards the client.