Mist events and stats of one client¶
Setup on 2026-10-21¶
The AP45 at home in the work org, firmware 0.14.30137, broadcasting eduroam on 5 GHz ch 52/20 (key_mgmt WPA3-EAP-FT/CCMP); its other radios on 2.4 GHz ch 6/20 and 6 GHz ch 21/80, all three chosen by Mist. Its beacons carry the BSS Load element on all three radios, so congestion and wifi-fine have the AP's channel load on a Mist AP. The phone (an iPhone with a private address on eduroam) the only client, at −50 to −54 dBm at the AP. An org token with the Helpdesk role. linkside-cli mist events --raw yes and mist stats polled the client every 5.4 s (median) for 8 minutes, 83 polls. No sensor capture.
The fields of an event¶
type_code is Mist's number of the event type, not a reason or status code. The 802.11 reason is in reason_code, the status in status_code; both are 0 in the other events. An 802.1X failure also carries authorization_reason_code and authorization_reason_msg.
| Event | type_code |
|---|---|
CLIENT_IP_ASSIGNED |
8 |
CLIENT_DEAUTHENTICATION |
10 |
CLIENT_DNS_OK |
15 |
CLIENT_GW_ARP_OK |
23 |
CLIENT_AUTH_ASSOCIATION |
49 |
MARVIS_EVENT_CLIENT_AUTH_FAILURE |
50 |
CLIENT_DEAUTHENTICATED |
58 |
Every event carries the client's rssi at the AP, key_mgmt, proto, num_streams, random_mac, the AP, the BSSID, the band and the channel, and from the login on time_since_assoc in milliseconds. The events of the login also carry the client's IP address, the subnet, the gateway and the DHCP and DNS servers.
The login¶
Two logins, the first at 12:53 and the reconnect at 13:01, each in four events:
| Event | After the association | Latency |
|---|---|---|
CLIENT_AUTH_ASSOCIATION, auth_type eap, status 0 |
443 and 295 ms | |
CLIENT_IP_ASSIGNED |
2,525 ms both | dhcp_latency 2.02 and 2.17 s |
CLIENT_GW_ARP_OK |
4,157 and 4,156 ms | arp_latency 4 ms |
CLIENT_DNS_OK |
4,448 and 4,563 ms | dns_latency 62 and 100 ms |
A latency can read a literal 0 where a measured one reads 0.006578862, which the app takes as no latency (MistView.IPService). Of the 63 CLIENT_IP_ASSIGNED kept up to 2026-11-04, each recording counted once, two have dhcp_latency 0: each a second event of its association, 1.7 and 2.1 s after one of 6 ms, 2.0 and 2.5 s after the association, one of them the iPhone's. Of the 77 CLIENT_GW_ARP_OK seven have arp_latency 0, six of them 1.7 to 2.9 s after the association, none after an earlier ARP event; the others read 1 to 12 ms, nearly all 4 to 8, and none 2. What they stand for the capture does not show, the payload being encrypted. A known difference, left as it is (2026-11-04): the DHCP event keeps its line "Address from DHCP" with its green mark in the Timeline and Latest, so a join can show two, the second without a time.
There is no event of its own for 802.1X or EAP: the login is CLIENT_AUTH_ASSOCIATION, with auth_server 127.0.0.1, the AP's own proxy to the RADIUS servers.
Wi-Fi off on the client¶
The phone's Wi-Fi turned off in Settings at 13:00:06, 6.4 minutes after its login. Three events within 57 ms:
| After the first | Event | type_code |
reason_code |
|---|---|---|---|
| 0 ms | MARVIS_EVENT_CLIENT_AUTH_FAILURE |
50 | 23, "IEEE 802.1X authentication failed"; authorization_reason_code 23 |
| 19 ms | CLIENT_DEAUTHENTICATION |
10 | 23 |
| 57 ms | CLIENT_DEAUTHENTICATED |
58 | 6, "Class 2 frame received from nonauthenticated STA" |
A client that left on its own came out of Mist as an 802.1X failure and a deauthentication with reason 23, and a reason 6 after it. Which frames went over the air, and from whom, the events do not say. When Wi-Fi came back on, the phone joined the home SSID first and eduroam 73 s after it left; that reconnect gave the same four events as the first login.
Wi-Fi off over the air¶
The same Wi-Fi off once more at 13:22:42, with the sensor on the AP's channel (testlab-client-leaves-eduroam), Mist logging the same three events:
| Time | Frame | Likely |
|---|---|---|
| .386 | a protected data frame from the phone, TID 0, 24 Mbit/s, 16 bytes of payload | an EAPOL-Logoff, by its size, its rate and the AP's answer |
| .393 to .404 | 42 BARs from the AP, the SSN from 322 to 454, each answered by an empty Block Ack | the AP drops its queue for the phone |
| about .395 | a protected data frame from the AP, TID 5, 24 Mbit/s, 17 bytes of payload | an EAP-Request/Identity: the authenticator after a logoff |
| .405 | deauthentication from the AP in the clear, reason 23 | the keys already gone, so no PMF |
| .406 | a protected action frame from the phone, 4 bytes of body | an SA Query: PMF checking an unprotected deauthentication |
| .441 | the phone's protected disassociation | the phone leaving |
Mist's timestamps follow the air by 8 to 22 ms: the auth failure at .413, its deauthentication at .427. The deauthentication with reason 6 at .464 comes 23 ms after the phone's disassociation, the AP's answer to a frame from a station it had deauthenticated, and is not in the capture. The data frames are encrypted; what they carry is inferred.
A Reconnect from the portal¶
At 16:50:53 Reconnect on the phone's page in the Mist portal, the phone on eduroam with a video playing and the screen on, the sensor on the AP's channel (testlab-ap-kick-eduroam):
| Time | Over the air | Mist |
|---|---|---|
| .789 | a deauthentication from the AP, protected (PMF): the reason is encrypted | CLIENT_DEAUTHENTICATION, type 10, reason 2, at .802 |
| .857 | probe requests from the phone | |
| .908 to 54.166 | authentication, association, a full EAP-TLS and the 4-way: connected again after 377 ms | CLIENT_AUTH_ASSOCIATION at 54.187 |
No auth failure, no CLIENT_DEAUTHENTICATED, no BAR flush and no SA Query: the AP still had the keys. After the reconnect Mist logged DNS and ARP but no CLIENT_IP_ASSIGNED. The deauthentication appeared in the API between 17 and 48 s after its timestamp, later than the events of the Wi-Fi off; the poll at 16:51:11, 18 s after the reconnect, returned no stats.
On testwlan-psk, without PMF, the same Reconnect is reason 2 in the clear: twice each with the iPhone and the MacBook, the AP's deauthentication with reason 2 and the client's authentication or reassociation 115 to 120 ms later, Mist's CLIENT_DEAUTHENTICATION with reason 2, then CLIENT_AUTH_REASSOCIATION (2026-11-03, testlab-ap-kick-psk-iphone, testlab-ap-kick-psk-mac). On a connection with PMF a frame in the clear is something else, the AP having dropped its keys first, so that use goes with the connection, not with the frame alone.
Between the two disconnects: CLIENT_DEAUTHENTICATION (type 10) is the deauthentication the AP sends, with its reason, protected or in the clear. CLIENT_DEAUTHENTICATED (type 58) came only when the client left by itself, 23 ms after its own disassociation, with reason 6 from an AP that no longer had its keys: Mist's view of the client leaving, from one sample. MARVIS_EVENT_CLIENT_AUTH_FAILURE came only with the logoff.
A reconnect on the phone¶
On 2026-10-27 at 21:06:47 a disconnect and connect on the phone itself, the phone on eduroam (FT-802.1X, PMF) on the AP45's 5 GHz ch 128/20, the sensor on the AP's channel, a live session in the app:
| Time | Frame | Likely |
|---|---|---|
| .433 | a data frame from the phone, TID 0, protected, 16 bytes of payload: the only one of that size in the session | an EAPOL-Logoff, by its size |
| .448 | deauthentication from the AP in the clear, reason 36 ("requested from peer STA as the STA is leaving the BSS") | the keys already gone, so no PMF |
| .449 | a protected action frame from the phone | an SA Query, as after the Wi-Fi off |
| .496 | the phone's protected disassociation | the phone leaving |
| 50.496 to 50.776 | authentication, association, EAP-TLS and the 4-way | connected again after 3 s |
Mist logged the deauthentication with reason 36. No BAR flush and no EAP-Request/Identity this time, against the Wi-Fi off's reason 23: the same logoff, another reason from the same AP. The logoff before the AP's deauthentication makes the disconnect the client's (HintFacts.Disconnect.Order), and with the join 3 s later it is the reconnect the user made. Which action on the phone gave this 36 was not noted; on 2026-10-30 its Wi-Fi off and on in Control Center gave 36 again, in the same order of frames (ap45-phone-video-reconnect), where its Wi-Fi off in Settings gave 23; on 2026-11-02 Control Center gave 36 once more and Settings the phone's own disassociation first (below), and the Mac's Disconnect in its Wi-Fi menu 36 as well (below).
A reconnect with the keys kept¶
On 2026-10-24 at 00:45:33 the reconnect a live session asked for (2026-10-24-0043-iPhone in ~/linkside-captures, not in the test data), the phone on eduroam (FT-802.1X, PMF) on the AP45's 5 GHz ch 52/20, the sensor on the AP's channel; Mac time, the Pi's clock 21.29 s behind:
| Time | Frame | Likely |
|---|---|---|
| .168 | a data frame from the phone, TID 0, protected, 24 Mbit/s, 16 bytes of payload | an EAPOL-Logoff, by its size |
| .172 | a protected data frame from the AP, TID 5, 24 Mbit/s, 17 bytes of payload | an EAP-Request/Identity, as after the Wi-Fi off |
| .186 | deauthentication from the AP, protected (PMF) | the keys still in place |
| .254 | probe requests from the phone | |
| 41.355 | authentication, association, EAP-TLS and the 4-way | connected again after 8.2 s |
Mist logged the deauthentication with reason 23 at .205 and two auth failures (MARVIS_EVENT_CLIENT_AUTH_FAILURE_11R) with reason 23. The same logoff as before the Wi-Fi off and the reconnect of 2026-10-27, this time with the keys kept: the AP's deauthentication came protected, and no SA Query or disassociation of the phone followed. A protected deauthentication from a Mist AP is therefore no sign by itself that the AP began; the logoff before it is, 18 ms before it here, 20 ms before the Wi-Fi off and 15 ms before the reconnect of 2026-10-27 by the engine's clock.
The encrypted frame with 16 bytes of payload came at ten disconnects in the recordings of the test data and ~/linkside-captures up to 2026-10-29, all from the iPhone on eduroam, and nowhere else from a client: the smallest encrypted data frame of the recordings, sent as the iPhone sends its EAPOL frames, TID 0 at 24 Mbit/s. Within 4 to 31 ms the AP's deauthentication followed (reason 23 or 36, in the clear or protected) or the iPhone's own disassociation, and in five the AP's EAP-Request/Identity 4 to 10 ms after it, as an 802.1X authenticator answers a logoff. A frame from the mt7925 has no FCS (eht-capture.md), so the payload is LLC/SNAP (8 bytes), the size of an EAPOL header (4) and 4 more. An EAPOL-Logoff has no body, and Apple's open-source supplicant sends it without one (eap8021x, EAPOLSocketSourceTransmit), 12 bytes; the iPhone's other EAPOL frames measure to their header and body exactly, so the 4 bytes are no VLAN tag or padding of all its frames. The phone's own capture shows the frame as an EAPOL-Logoff of 4 bytes, the 4 more added below where iOS and macOS capture, and the Mac's logoff has 16 bytes of payload in the air as well (below). The engine takes the frame as the client's EAPOL-Logoff by when it comes and how the AP answers it (encryptedLogoff); an EAPOL-Start would draw the same answer, but a client with its keys has no login to start.
Disconnect in Control Center and Wi-Fi off in Settings¶
On 2026-11-02 the phone on eduroam (FT-802.1X, PMF) on the AP45's 5 GHz ch 112/20, the sensor on the AP's channel, a live session in the app (in ~/linkside-captures, not in the test data); Mac time, the Pi's clock 11.53 s behind. First the Wi-Fi icon in Control Center tapped, which leaves the network with Wi-Fi on, and tapped again; then Wi-Fi off in Settings, and on again:
| Time | Frame | Likely | Mist |
|---|---|---|---|
| 01:39:05.122 | a data frame from the phone, TID 0, protected, 16 bytes of payload | an EAPOL-Logoff, by its size | |
| .136 | deauthentication from the AP in the clear, reason 36 | the keys already gone | CLIENT_DEAUTHENTICATION, reason 36, at .148; MARVIS_EVENT_CLIENT_AUTH_FAILURE, reason 36, text codes 771 and 23, at .150 |
| .137 | a protected action frame from the phone | an SA Query | |
| .182 | the phone's protected disassociation | the phone leaving | |
| 23.952 to 24.240 | authentication, association, EAP-TLS and the 4-way | connected again after 18.8 s, the icon tapped again | |
| 01:39:49.434 | a data frame from the phone, TID 0, protected, 16 bytes of payload | an EAPOL-Logoff, by its size | |
| .440 | the phone's protected disassociation, 6 ms after it | the phone leaving | CLIENT_DEASSOCIATION, type 6, reason 8 ("leaving the BSS"), at .455 |
| 01:41:06.046 to .360 | authentication, association, EAP-TLS and the 4-way | connected again after 76.6 s, Wi-Fi on again |
The disconnect in Control Center gave what the phone's disconnect of 2026-10-27 and its Control Center of 2026-10-30 gave: the AP's reason 36 in the clear after the logoff, an SA Query, the phone's disassociation; Mist added an auth failure with reason 36. The Wi-Fi off in Settings gave another order than on 2026-10-21: no answer of the AP before the phone disassociated, 6 ms after its logoff, no SA Query, no auth failure and no CLIENT_DEAUTHENTICATED, and Mist's reason 8 for the phone's disassociation, which PMF encrypted over the air; the evening gave that order twice more (below). The engine reads both as the client leaving (client-disconnect), the first by the logoff before the AP's 36, the second by Mist's reason 8; back in 18.8 s the first is the reconnect, gone 76.6 s, longer than rejoinWindow (60 s), the second counts as the client leaving.
Wi-Fi off, Forget This Network and a Mac on eduroam¶
On 2026-11-02 from 22:33 the phone (iOS 26.6.2) on eduroam (FT-802.1X, CCMP, PMF, EAP-TLS) on the AP45's 5 GHz ch 132/20, the sensor on the AP's channel, a live session in the app (in ~/linkside-captures, not in the test data); Mac time, the Pi's clock 704,127 s behind (clock.md). The phone on the Mac's USB cable, its own traffic captured on the Mac through rvictl (rvi0) with Apple's tcpdump -P: PKTAP, with the Ethernet frames of the phone's en0; Wireshark's dumpcap offers only Raw IP on rvi0, which leaves out every frame that is not IP, EAPOL among them. Then the Mac (macOS 27.0.1) on the same BSS with EAP-TLS, a session of its own, its EAPOL frames captured on its en0 with dumpcap:
| Action | The logoff in the air | Then, from the logoff | Mist | Back |
|---|---|---|---|---|
| The phone: Wi-Fi off in Settings, on again a few seconds later | 22:35:27.006 | the phone's protected disassociation at 10 ms; no frame of the AP between, no SA Query | CLIENT_DEASSOCIATION, reason 8; MARVIS_EVENT_CLIENT_AUTH_FAILURE, reason 8, authorization_reason_code 23, text codes 769 and 23 |
after 11.0 s, EAP-TLS and the 4-way |
| The phone: Forget This Network | 22:39:38.263 | the phone's protected disassociation at 8 ms, as above | CLIENT_DEASSOCIATION, reason 8 |
by hand after 3 min 19 s, with another private address: eduroam asked for a username and password, and EAP-TLS took the certificate again |
| The phone: Wi-Fi off in Settings, with a download | 22:43:23.6, from rvi0 |
not captured: the session followed the phone's old address | CLIENT_DEASSOCIATION, reason 8, nothing else |
after 12 s |
| The Mac: Disconnect in the Wi-Fi menu (Option-click) | 22:50:45.148 | the AP's deauthentication in the clear, reason 36, at 14 ms; the Mac's SA Query 0.7 ms after it; its protected disassociation at 175 ms | CLIENT_DEAUTHENTICATION, reason 36; no auth failure |
after 9.1 s, EAP-TLS and the 4-way |
The download ran at about 140 Mbit/s to the phone in rvi0 until 1.5 s before the logoff and at about 3 Mbit/s after, as Safari left the foreground for Settings: the AP had little queued for the phone. 1.4 s after its join the Mac left once more, Mist's reason 8, and joined again 6 s later.
Every disconnect began with the client's EAPOL-Logoff, of 16 bytes of payload where the sensor heard it, after which the AP45 deauthenticated with reason 36 in the clear, or the client disassociated first. Of the iPhone's ways to leave, the Wi-Fi icon in Control Center, which leaves the network with Wi-Fi on, gave the AP's 36 twice, 14 ms after the logoff (2026-10-30, 2026-11-02 at 01:39), as the disconnect on the phone of 2026-10-27 did, its action not noted, 15 ms after it; its Wi-Fi off in Settings gave the AP's 23 once (2026-10-21), 19 ms after it, and its own disassociation three times, before any answer of the AP: 6 and 10 ms after the logoff where the sensor heard it (01:39, 22:35), by Mist's reason 8 alone at 22:43; Forget This Network its own disassociation, 8 ms after it. The Mac's Disconnect gave what the icon gives. On 2026-10-21 a video's chunk was in flight, the AP flushing 171 sequence numbers with 42 BARs: the phone may wait for its queue before it disassociates, and the AP's 23 comes first then. Whether it does is open, as the download of 22:43 had stopped before the Wi-Fi off; which action gave the protected 23 of 2026-10-24 is not known either. The reason names the action the client took, the icon or the switch, not whether the user left or reconnected: each was followed by a join once Wi-Fi was on again.
The logoff from the client's side¶
At 22:35:26.968, 38 ms before the sensor's frame of 16 bytes by the two clocks, the phone sent the AP an EAPOL-Logoff, 01 02 00 00 after the Ethernet header (802.1X-2001, Logoff, length 0), 18 bytes with nothing after it; at 22:39:38.227 and 22:43:23.606 the same. The Mac's logoff at 22:50:45.122 is the same 18 bytes on its en0, and its frame in the air has 16 bytes of payload, as the phone's. The phone's other encrypted frames measure in the air to their size in rvi0 plus LLC/SNAP exactly: of the sizes both captures have most, 60, 67, 72, 75, 1236 and 1288 bytes of payload. The logoff alone grows by 4 bytes, below the tap where iOS and macOS capture, in the driver or the firmware: they are no part of the EAPOL frame. What they hold only a decrypted capture at the AP would show (Mist's type radiotap, mist-ap-capture.md). Neither tap shows an EAPOL-Key frame, which the air has: the 4-way runs below it, the EAP frames above. With the Mac's logoff of the same size, encryptedLogoff holds for macOS as for iOS (EventExtractor.logoffPayload).
A wrong password, and Mist's penalty box¶
On 2026-11-03 the iPhone and the MacBook with a wrong password, made as the runbook's setup says, each attempt a tap or click on the network (test data, item 041). Mac time.
On testwlan-psk, WPA2-PSK without PMF: an attempt is the AP's M1 four times, 1 s apart, each answered with the client's M2, then the AP's deauthentication in the clear with reason 14 (MIC failure), 4.0 s after the association. Mist logs per attempt MARVIS_EVENT_CLIENT_AUTH_FAILURE (type_code 50, auth_type psk, authorization_reason_code 14, reason_code 2, text "MIC Failure - possible PSK mismatch(14)") and 8 ms later CLIENT_DEAUTHENTICATION with reason 14. After two failures of a client on a BSS Mist logs REPEATED_AUTH_FAILURES ("Client ignored due to penalty box period", without a reason), and the AP then answers the client's authentication and association but sends no M1: the iPhone ended such an association after 6 s with its deauthentication, reason 15 (Mist's CLIENT_DEAUTHENTICATED, type_code 30), the Mac on 2.4 GHz with its disassociation, reason 8 (CLIENT_DEASSOCIATION). The penalty is per BSS and lasts about a minute: after the Mac's second failure on a BSS its next full 4-way there came 52 to 68 s later, every attempt between them without an M1, and the iPhone's taps 20 s apart fell in it.
On testwlan-1, SAE and PSK in transition mode, both clients take SAE: the AP answers the commit and refuses the client's confirm with status 1, four times as the client sends it again each second. Mist logs MARVIS_EVENT_SAE_AUTH_FAILURE with status 1 per refusal. In the penalty that follows the AP leaves the client's commits unanswered, four per attempt, 1 s apart, up to 82 s after its last refusal with the iPhone and 63 s with the Mac: the engine takes that silence as the refusal's (join-unanswered, penaltyWindow).
Per tap the iPhone tries every BSS of the SSID it hears, here the AP45's 5 GHz, the second AP45's 5 GHz and the AP45's 2.4 GHz, one after the other within a second of each refusal; the Mac alternated between the AP45's 5 and 2.4 GHz. A join after one that got no keys is no roam, as the client has no connection to move from (ConnectionTracker).
Wi-Fi off on the Mac, and a Reconnect without PMF¶
The same day the ways to leave of the iPhone and the MacBook on the three WLANs, each with a YouTube video, and Mist's Reconnect on a WLAN without PMF (test data from testlab-client-leaves-psk-iphone on):
| Client, action, WLAN | In the air | Mist |
|---|---|---|
iPhone, Wi-Fi off in Settings, testwlan-psk |
its disassociation in the clear, reason 8 | CLIENT_DEASSOCIATION, reason 8 |
iPhone, the same, testwlan-1 (PMF) |
its protected disassociation | CLIENT_DEASSOCIATION, reason 8 |
| iPhone, the same, eduroam | its EAPOL-Logoff, its protected disassociation 8 ms later, nothing of the AP between | CLIENT_DEASSOCIATION, reason 8, no auth failure |
MacBook, Wi-Fi off in System Settings, testwlan-psk |
nothing: its last frames data, Block Acks and an RTS; the AP's 812 RTS, 343 Block Ack Requests and 112 action frames to it unanswered for 68 s | nothing, until its next join six minutes later |
MacBook, Wi-Fi off in the menu bar, testwlan-psk |
its disassociation in the clear, reason 8 | CLIENT_DEASSOCIATION, reason 8 |
MacBook, the same, testwlan-1 (PMF) |
its protected disassociation | CLIENT_DEASSOCIATION, reason 8 |
| MacBook, the same, eduroam | its EAPOL-Logoff, the AP's deauthentication in the clear with reason 36 20 ms later, its SA Query, its protected disassociation at 115 ms | CLIENT_DEAUTHENTICATION, reason 36 |
macOS 27 leaves in two ways: the switch in the menu bar disassociates, the switch in System Settings turns the radio off without a frame, which no rule reads yet. On eduroam the Mac's menu bar gives what its Disconnect gave on 2026-11-02, the iPhone's Settings what it gave three times then.
Reconnect on the client's page in the Mist portal, twice per client: on testwlan-psk the AP's deauthentication in the clear with reason 2, and the iPhone's reassociation 115 ms later, the Mac's authentication and reassociation at 120 ms, accepted (CLIENT_DEAUTHENTICATION with reason 2, then CLIENT_AUTH_REASSOCIATION). On eduroam the AP's deauthentication protected, and a new association with a full EAP-TLS at 155 ms (the iPhone) and 215 ms (the Mac), CLIENT_AUTH_ASSOCIATION in Mist. The reason in the clear is Mist's Reconnect as the protected one is: a measured use the reason codes do not hold yet, so the engine leaves these disconnects undecided.
Encrypted action frames by their size¶
With PMF the body of a robust action frame is encrypted, its category and action among them: the air shows a protected action frame, who sent it and its length. A frame from the mt7925 comes without its FCS (eht-capture.md), so the encrypted body is the MPDU less its header of 24 bytes, CCMP's 8 and the MIC, 8 bytes with CCMP-128 on eduroam. The protected action frames of the recordings in the test data and in ~/linkside-captures up to 2026-10-29, about 400, by the size of their body:
| Body | From | Seen | Likely |
|---|---|---|---|
| 4 bytes | the client | at seven disconnects, each 0.6 to 3.2 ms after the AP's deauthentication in the clear (reason 23 or 36), the client's protected disassociation 22 to 60 ms after it, no frame of the AP between | an SA Query request: category, action and transaction ID, PMF's check of a deauthentication that may be forged |
| 9 bytes | either | 298, of which 279 answered from the other side by 9 or 12 bytes within 5 ms | ADDBA request and response |
| 12 bytes | either | 65, of which 29 in such a pair: the testlab clients' 12 against 12, the U7's 12 against the phone's 9; the others mostly from the iPhone on eduroam | ADDBA with the ADDBA Extension element; on eduroam the client's neighbor report request: category, action, dialog token and the SSID element of eduroam, 2 + 7 bytes |
| 3 bytes | the AP45 | 10; twice with the client's 12 bytes before it in the capture, 194 and 400 ms after them | an empty neighbor report response |
| 13 and 43 bytes | the phone and the U7 | the phone's 13 answered by the U7's 43 within 3 ms | a neighbor report request and its response with candidates |
A window of 10 ms for the answer named the same frames as 5 ms; the AP45's own ADDBA after the client's neighbor report request came 14 ms after it or later. No SA Query response came: in each of the seven the AP had dropped the keys before its deauthentication. The engine names the client's 4 bytes within 10 ms after the AP's deauthentication or disassociation in the clear an SA Query (encryptedSAQuery), the AP's 4 bytes after it its response, and a frame of 9 or 12 bytes answered from the other side within 5 ms a Block Ack setup, both frames (encryptedBlockAckSetup), with the MIC of the client's cipher (EventExtractor.protectedAction). A frame of 12 bytes alone stays unnamed, as does the neighbor report.
The delay¶
| Event | First seen after its timestamp |
|---|---|
CLIENT_AUTH_ASSOCIATION |
9.2 s |
CLIENT_GW_ARP_OK |
10.7 s |
MARVIS_EVENT_CLIENT_AUTH_FAILURE |
11.0 s |
CLIENT_DEAUTHENTICATED |
11.0 s |
CLIENT_IP_ASSIGNED |
12.2 s |
CLIENT_DEAUTHENTICATION |
20.4 s |
CLIENT_DNS_OK |
26.4 s |
At one poll per 5.4 s each value is up to 5.4 s late itself.
- The stats refresh every 60 s (once 62 s), and a refresh appears 3 to 10 s after its
last_seen. - While the client was away the stats endpoint kept answering with the stats from before it left (
last_seen12:59:26), not with a 404; the refresh of 13:00:26 is missing. The client left is visible in the events and in the age oflast_seen. - The client search on the site found nothing about 80 s after the association, while the AP's device stats already counted one client, and found the client within two minutes. A wildcard on the MAC is refused (400, "invalid mac");
*ontextand*@*onusernamework.random_macwas right; the phone sent no hostname.
The counters¶
linkside-cli mist stats every 20 s from 17:38 to 18:02, during a download and a video on the phone with the sensor on the AP's channel (power-save.md), its timestamps corrected by the session's clock offset.
tx_* is the AP to the client: in the four refreshes of the download tx_bytes grew by 2.07 GB and rx_bytes by 40 MB. Per refresh, tx_pkts is the number of data frames the AP sent the client for the first time and tx_retries the number it sent again; the sensor counted the AP's data frames to the phone between the two last_seen times, without and with the retry bit:
last_seen |
tx_pkts |
Sensor, first time | tx_retries |
Sensor, again |
|---|---|---|---|---|
| 17:44:24 | 50,387 | 48,267 | 6,554 | 6,258 |
| 17:45:24 | 280,139 | 274,905 | 14,556 | 13,557 |
| 17:46:26 | 249,655 | 250,674 | 13,208 | 13,065 |
| 17:47:26 | 278,385 | 273,743 | 10,697 | 10,368 |
| 17:54:34 | 2,122 | 2,096 | 761 | 709 |
| 17:55:36 | 1,898 | 1,896 | 1,284 | 1,270 |
| 17:56:38 | 3,022 | 3,012 | 380 | 375 |
| 17:57:38 | 2,500 | 2,492 | 477 | 466 |
| 17:58:38 | 271 | 270 | 57 | 57 |
Mist counts up to 7 % more than the sensor, which captured 99.6 to 100 % of the downlink. The counts line up on last_seen to about a second: last_seen is the time of the counters. tx_retries per tx_pkts is therefore the AP's retransmissions per frame, 3.8 to 5.3 % a minute during the download and 12.6 to 67.7 % during the video. With the phone on 2.4 GHz and going off the channel every 70 ms when last captured, Mist counted 618 retries against 10 frames in one minute: a client away from its channel runs the ratio far past 100 %. The stats of this AP carry no power_saving.
Over the whole of each recording with mist.json, 2026-10-23: the retry bit against Mist's share of the AP's frames sent again, tx_retries / (tx_pkts + tx_retries), which counts the same (HintFacts.mistSentAgain):
| Recording | Downlink captured | Retry bit | Mist |
|---|---|---|---|
testlab-power-save-video |
100 % | 22.6 % | 23.5 % |
testlab-power-save-second-client |
99.9 % | 21.2 % | 17.8 % |
testlab-ap-kick-eduroam |
98.7 % | 31.9 % | 25.6 % |
testlab-client-leaves-eduroam |
99.4 % | 18.3 % | 10.8 % |
testlab-long-quiet |
99.6 % | 14.6 % | 8.2 % |
ap45-phone-band-roam |
63 % | 27.2 % | 12.5 % |
These sessions predate txPackets in mist.json, so Mist's minutes weigh by time, not by the frames sent in them, and its first and last minute reach past the capture; testlab-long-quiet is cut to four stretches of its 51 minutes, while Mist counts all of them. The table above, aligned on last_seen, is the measurement. At 63 % captured the retry bit reads twice Mist's share: the frames the sensor misses are the AP's fast ones (eht-capture.md).
With the MacBook as the client, both ways, 2026-10-23: on eduroam on the AP45, 5 GHz ch 52/20 (HE, two streams), 1 m from the sensor, recorded by the app with txPackets and rxPackets in mist.json. Four minutes of download from 17:19:02 and four of upload from 17:24:04 with networkQuality, a quiet minute after each. The sensor captured 99.9 % of the downlink and 99.2 % of the uplink, BA success 99.6 % both ways; the recording is ~/linkside-captures/2026-10-23-mist-counters, outside the repo. Per refresh, the sensor's counts between the two last_seen times, the AP's data frames to the MacBook, those with the retry bit of an MPDU the sensor had not seen on the air before, and the AP's RTS to it that went unanswered (no CTS within 200 µs on the TSF):
last_seen |
tx_pkts |
Sensor, first time | tx_retries |
Sensor, again | Again, not on the air before | Unanswered RTS |
|---|---|---|---|---|---|---|
| 17:19:29 | 199,163 | 192,741 | 15,122 | 13,423 | 2,181 | 135 |
| 17:20:29 | 443,809 | 437,733 | 12,366 | 9,128 | 3,867 | 215 |
| 17:21:31 | 419,148 | 414,846 | 22,650 | 19,183 | 4,811 | 266 |
| 17:22:33 | 422,116 | 416,322 | 17,232 | 13,699 | 4,697 | 233 |
| 17:23:33 | 219,052 | 220,305 | 5,768 | 4,166 | 2,058 | 110 |
| 17:24:35 | 74,767 | 72,060 | 2,705 | 1,638 | 1,090 | 91 |
| 17:25:37 | 151,140 | 148,094 | 6,953 | 4,044 | 2,982 | 162 |
| 17:26:39 | 164,997 | 161,113 | 7,251 | 4,598 | 3,202 | 220 |
| 17:27:41 | 153,792 | 151,039 | 6,857 | 4,207 | 2,752 | 169 |
| 17:28:43 | 70,248 | 69,691 | 3,473 | 2,440 | 1,404 | 72 |
tx_pkts is 0.8 to 3.8 % above the sensor's first-time frames, once 0.6 % below, as with the phone. tx_retries is 13 to 72 % above the retry bit, 1,000 to 3,500 frames a minute, and the excess goes with the RTS the MacBook left unanswered: 12 to 18 frames per unanswered RTS, about the 9 to 17 MPDUs of a TXOP that began with an answered one. The AP sent about as many MPDUs with the retry bit that had not been on the air before, 12 to 20 per unanswered RTS: the MPDUs of the TXOP whose RTS failed, sent the next time as a retransmission. tx_retries thus also counts attempts that never went on the air; how many per MPDU these counts do not settle. Over the ten minutes Mist's share of the AP's frames sent again, tx_retries / (tx_pkts + tx_retries), is 4.2 % against 3.2 % by the retry bit. The phone's minutes above were not checked for unanswered RTS.
The MacBook's data frames to the AP: the MPDUs the AP acknowledged in its Block Acks, each once, first time and again, and the frames with the retry bit:
last_seen |
rx_pkts |
Received by the AP | rx_retries |
Sensor, again |
|---|---|---|---|---|
| 17:19:29 | 64,348 | 63,065 | 1,127 | 1,520 |
| 17:20:29 | 146,627 | 145,339 | 239 | 331 |
| 17:21:31 | 116,733 | 116,449 | 209 | 362 |
| 17:22:33 | 125,138 | 124,028 | 274 | 488 |
| 17:23:33 | 62,290 | 62,782 | 47 | 76 |
| 17:24:35 | 195,938 | 191,671 | 3,527 | 8,710 |
| 17:25:37 | 394,208 | 391,632 | 6,954 | 14,371 |
| 17:26:39 | 397,670 | 394,474 | 8,216 | 17,199 |
| 17:27:41 | 394,140 | 390,521 | 8,027 | 18,341 |
| 17:28:43 | 185,692 | 186,664 | 1,987 | 4,990 |
rx_pkts is the client's MPDUs the AP received, each once: 0.8 % below to 2.2 % above the MPDUs it acknowledged. rx_retries is not the retry bit: 40 to 74 % of the MacBook's frames with it, of which the AP acknowledged 91 to 100 %, and in the upload 96 to 98 % were MPDUs the MacBook had sent before. Nor is it the A-MPDUs with a retransmission in them, 425 to 1,361 a minute in the upload. What it counts stays open, so Mist gives no share of the uplink sent again yet.
A deauthentication on a BSS the client had left¶
In the long session without a problem (testlab-long-quiet) the phone roamed by FT from the AP45's 5 GHz radio to its 2.4 GHz radio at 20:25:04, as it fell asleep at the end of a video, and back at 20:26:05 when the next one started. At 20:56:48, 30 min 43 s after it left the 2.4 GHz BSS, that radio sent the phone two protected deauthentications on ch 1, the second repeated six times, none acknowledged: the phone was on ch 52, and its data, Block Acks and RTS went on there. Mist logged CLIENT_DEAUTHENTICATION with reason 4 (inactivity) for the 2.4 GHz BSSID, 14 ms after the first frame, and gave it with the poll 8.5 s later. The radio kept the phone's entry after the roam to its other radio and timed it out.
The event types¶
GET /api/v1/const/client_events lists every client event type with Mist's name, without a token: 71 on 2026-10-22 (linkside-cli mist const client_events, testdata/mist). The ones about the address, the gateway and DNS:
| Type | Mist's name |
|---|---|
CLIENT_IP_ASSIGNED |
DHCP Success |
MARVIS_EVENT_CLIENT_DHCP_ACK |
DHCP ACK |
MARVIS_EVENT_CLIENT_DHCP_FAILURE |
DHCP Timed Out |
MARVIS_EVENT_CLIENT_DHCP_NAK |
DHCP Denied |
MARVIS_EVENT_CLIENT_DHCP_STUCK |
DHCP Aborted |
MARVIS_EVENT_CLIENT_FAILED_DHCP_INFORM |
DHCP Inform Timed Out |
CLIENT_IPV6_ASSIGNED |
DHCPv6 Success |
MARVIS_EVENT_CLIENT_DHCPV6_FAILURE |
DHCPv6 Timed Out |
MARVIS_EVENT_CLIENT_DHCPV6_NAK |
DHCPv6 Denied |
MARVIS_EVENT_CLIENT_DHCPV6_STUCK |
DHCPv6 Aborted |
CLIENT_GW_ARP_OK |
Gateway ARP Success |
CLIENT_GW_ARP_FAILURE |
Gateway ARP Timeout |
CLIENT_ARP_FAILURE |
ARP Timed Out |
CLIENT_EXCESSIVE_ARPING_GW |
Excessive ARPing |
DEFAULT_GATEWAY_SPOOFING_DETECTED |
Gateway Spoofing |
CLIENT_DNS_OK |
DNS Success |
MARVIS_DNS_FAILURE |
DNS Failure |
MARVIS_EVENT_CLIENT_DNS_RECOVERY |
DNS Recovery |
MARVIS_EVENT_CLIENT_STATIC_DNS_BLOCKED |
Blocked: Static DNS Address |
MARVIS_EVENT_CLIENT_STATIC_IP_BLOCKED |
Blocked: Static IP Address |
MARVIS_EVENT_INVALID_CLIENT_IP |
Invalid IP |
MARVIS_HEALTH_EVENT_BAD_IP_ASSIGNMENT_PATTERN |
Bad IP Assigned |
The failures, 2026-10-23: the phone on eduroam on the AP45, three sessions recorded by the app (ip-services), each with the phone's Wi-Fi off and on after the change, and the phone's events fetched again afterwards with linkside-cli mist events:
- A DNS server of its own that does not answer, 192.0.2.1:
MARVIS_DNS_FAILURE(type_code3) at 17:57:17, 34 s before the reconnect: iOS took the server at once, and its first query was_dns.resolver.arpa, the discovery of designated resolvers (RFC 9462), which the event's text names with the server and the VLAN. Nodns_latency,time_since_assocor channel; the poll had it 28 to 58 s after its time. After the reconnectCLIENT_IP_ASSIGNED(2.0 s) andCLIENT_GW_ARP_OK(4 ms), no second failure;CLIENT_DNS_OKwith the campus server's address followed at 18:00:02, the setting back on Automatic. The app: upstream, "DNS fails". - A gateway no host has, the phone's own address with .2 and then .3 of its subnet as router, where DHCP gives .1: no event about the gateway in four minutes, nor later. Mist checks the gateway after a DHCP Ack:
CLIENT_GW_ARP_OKcame 2 s after eachCLIENT_IP_ASSIGNED, and never without one. The WLAN does not block static addresses (noMARVIS_EVENT_CLIENT_STATIC_IP_BLOCKED). In the air the phone sent the gateway nothing from then on, only broadcasts, up to 22 per 20 s against at most 7 in the first session (its ARP for the gateway, encrypted), and got next to nothing back; iOS loaded the web pages over mobile data. The app: undecided, nothing abnormal. - An address of another subnet, 198.51.100.10/24 with router 198.51.100.1: in the 1.5 minutes it lasted no
MARVIS_EVENT_INVALID_CLIENT_IPand no blocked static address; in the air again only broadcasts. The app: undecided, nothing abnormal.
The Wi-Fi off and on gave Mist's pattern of Wi-Fi off on the client twice in the second session, reason 23 with MARVIS_EVENT_CLIENT_AUTH_FAILURE and reason 6 from the client, and in the first and third a CLIENT_DEASSOCIATION with reason 8, the disassociation encrypted in the air.
The list also names what the rest of the Mist work reads (the plan, docs/status.md):
| What | Types, with Mist's name |
|---|---|
| Disconnects | CLIENT_DEAUTHENTICATION AP Deauthentication, CLIENT_DEAUTHENTICATED Client Deauthentication (as the Wi-Fi off and the Reconnect above showed), CLIENT_DEASSOCIATION Disassociation, SA_QUERY_TIMEOUT SA Query Timed Out, RADIUS_DAS_NOTIFY (the RADIUS server's disconnect or change of authorization) |
| Roams by method | CLIENT_AUTHENTICATED_11R 11r Roam, CLIENT_AUTHENTICATED_OKC OKC Roam, CLIENT_ASSOCIATION_PMKC and CLIENT_REASSOCIATION_PMKC, CLIENT_AUTH_REASSOCIATION_11R and _OKC, MARVIS_EVENT_CLIENT_FBT_SUCCESS and _FAILURE 11r FBT, MARVIS_EVENT_WLC_FT_KEY_NOT_FOUND 11r Key Lookup Failure, MARVIS_EVENT_STA_LEAVING Client Roamed Away |
| Marvis on a roam | MARVIS_EVENT_ROAMING_ SUCCESS, SLOW_ROAM (full re-authentication), SLOW_LLR_ROAM (11r with high latency), SLOW_OKC_ROAM, NOT_FAST_ROAM, SIGNAL_SUBOPTIMAL_ROAM, INTERBAND_ROAM and ERROR_STICKY_CLIENT; on the AP45 SUCCESS carries prev_ap, prev_band, prev_channel, prev_rssi and rssi, no BSSID (a roam between two APs): where a roam to an unwatched channel went |
| The login | MARVIS_EVENT_CLIENT_AUTH_FAILURE Authorization Failure, _AUTH_FAILURE_11R and _AUTH_FAILURE_OKC, MARVIS_EVENT_SAE_AUTH_FAILURE SAE Auth Failure, MARVIS_EVENT_CLIENT_AUTH_DENIED 802.11 Auth Denied, MARVIS_EVENT_CLIENT_MAC_AUTH_FAILURE, REPEATED_AUTH_FAILURES Blocked: Repeated Authorization Failure (a penalty box) |
A roam between two APs¶
2026-11-02, the phone walked from the AP45 to the second AP45 with the app recording (roam-ap45.md); its events fetched raw afterwards (linkside-cli mist events --raw yes, kept beside the recording outside the repo). Each 802.11r roam gave three events and a DNS answer after it:
| Event | Fields beside the common ones |
|---|---|
MARVIS_EVENT_ROAMING_SUCCESS (type_code 3) |
ap, band and channel of the new AP, rssi there, prev_ap (the old AP's device MAC), prev_band, prev_channel, prev_rssi, client_os ("iOS 19"); no BSSID, no key_mgmt, its timestamp on the whole second |
MARVIS_EVENT_STA_LEAVING (type_code 40) |
on the old BSS, with reason_code 8 (the client leaving) and time_since_assoc of the connection it ends |
CLIENT_AUTH_REASSOCIATION_11R (type_code 49) |
on the new BSS, auth_type "eap-11r", capabilities "11r", time_since_assoc 8 and 4 ms |
The roam within the second AP45, from its 2.4 GHz to its 5 GHz radio, gave prev_ap its own AP with prev_band 24 and prev_channel 6, and no MARVIS_EVENT_STA_LEAVING then: the 2.4 GHz radio logged the phone leaving at 16:06:45, 6.5 minutes later, with the phone's next roam, as the AP45 kept a client's entry on a BSS it had left (above). prev_rssi of the first roam, −68 dBm, was the phone at the AP45; the sensor next to that AP heard the phone at −67 to −71 dBm in its last frames there.
The session polled every 30 s. CLIENT_AUTH_REASSOCIATION_11R of the first roam came within 28 s, and its MARVIS_EVENT_ROAMING_SUCCESS, MARVIS_EVENT_STA_LEAVING and CLIENT_DNS_OK 28 to 58 s after their time; the second roam's events within 28 s.
RRM neighbors¶
GET /api/v1/sites/{site_id}/rrm/neighbors/band/{band} answered on the site of the AP45, 2026-10-26, for each band, 24, 5 and 6 (linkside-cli mist neighbors): band, limit (100 by default), page, total and results, one entry per AP with its device MAC in mac and neighbors, empty on a site of one AP, which was disconnected then. A neighbor's fields, mac and rssi in dBm, those of Mist's OpenAPI (rrm_neighbors_neighbor), were seen on 2026-10-26 on a larger site with neighbors: New Session's roam target menu listed the client's AP and about a dozen APs heard by it on 5 GHz, ordered by RSSI from −67 to −91 dBm. New Session orders the roam target's APs by them (MistRRMNeighbors); a neighbor matches an AP by its device MAC or a radio's MAC.
What it means for Linkside¶
- A disconnect counts only on the BSS the client is on (one on another is a
staleDisconnect), and Mist's reason only from an event on the same BSS: the AP45 deauthenticates a client on a BSS it left, half an hour later. - The reason of a disconnect PMF encrypted comes from
reason_code, nottype_code;mist.jsonkeepsreason_code,status_code,authorization_reason_code,auth_type,time_since_assocand the latencies of DHCP, ARP and DNS. - A Mist auth failure is no proof of a failed login: a client that leaves on its own can give one, its Wi-Fi off in Settings with reason 23 (2026-10-21), its disconnect in Control Center with reason 36 (2026-11-02), and its Wi-Fi off in Settings with reason 8 after its own disassociation (2026-11-02, 22:35); its two other Wi-Fi offs in Settings, Forget This Network and the Mac's Disconnect gave none. The reason 6 after a deauthentication with reason 23 follows from it, did not go over the air, and is no disconnect of its own. The AP's deauthentication with reason 23 went out in the clear after the Wi-Fi off and protected after the reconnect of 2026-10-24: the client's logoff before it, not the protection, says who began (reason codes).
- The AP's BARs past its own queue before the deauthentication are a flush, no loss: BA success books what a BAR gives up within 0.2 s before a disconnect as flushed (
flushWindow). - Reason 2 after a completed login is the AP ending a working connection, as Mist's Reconnect does:
ap-disconnecttakes it then, and as a failed login only while the client logs in. - DHCP, ARP and DNS each have an event with its latency: a slow DHCP or DNS can be a finding instead of an elimination.
- Mist checks the gateway only after a DHCP Ack: a static address with a gateway that does not answer gives no event, and neither did an address of another subnet in 1.5 minutes. There only the air shows it, a client that sends nothing but broadcasts.
- With events 10 to 26 s late, a roam's Marvis events up to a minute, and the stats once a minute, a window of 20 s gets its Mist values one poll late at best, and a session needs about a minute of polls after Stop before its verdict holds.
tx_retriespertx_pktsis the AP's own retransmission rate to the client per minute, and it matched the sensor's count with the phone where the sensor captured the whole downlink. It also counts attempts that never went on the air, after an RTS the client left unanswered: with the MacBook 4.2 against 3.2 % of the AP's frames sent again by the retry bit.rx_pktscounts the client's MPDUs the AP received;rx_retriesis not the uplink's retry bit. Where the sensor captures too little of the downlink to count it, Mist still gives it; BA success does not measure it (power-save.md).