Local switching between two clients on the same WAP. Summary of two lab runs on WF‑188n pairs.
1.18 fixes client‑to‑client traffic when both clients are on the same WAP but on different sdan ports. That covers two radios of one WAP, and it covers a wired LAN‑port client talking to a wireless one. On 1.16 those combinations fail completely, in both directions.
Two things are not affected and work on both versions: clients on the same radio, and clients on different WAPs. Nothing about north/south (client to gateway, DNS, internet) changes either.
| Both clients are… | 1.16 | 1.18 | Why |
|---|---|---|---|
| on the same radio of one WAP | works | works | the WAP’s own intra‑BSS path forwards it; sdan never sees the frame |
| on different radios of one WAP | fails | works | two dynamic VIFs, nothing bridging them — needs local switching |
| one wired, one wireless, same WAP | fails | works | LAN port and VIF are separate sdan ports — needs local switching |
| on different WAPs (any mix) | works | works | exits to the uplink and comes back; local switching not involved |
This is the part worth passing on to anyone triaging a complaint. On 1.16 the same two devices succeed or fail depending on where they happen to land:
So a guest casting to a TV, a laptop printing to a wired printer in the same unit, or any mDNS‑based discovery (AirPlay, Chromecast, printer discovery) can work, then stop, then start again, with no configuration change and nothing in the logs. Band steering and roaming are enough to move a device between all three states on their own. Reports of “flaky” in‑unit device‑to‑device behaviour on 1.16 are worth re‑reading as this bug rather than as RF.
| Case | 1.16 | 1.18 | Run |
|---|---|---|---|
| Same radio, one WAP | 5/5 | 5/5 | east‑west 1.16 vs 1.18 — 5 trials |
| Different radios, one WAP | 0/5 | 5/5 | east‑west 1.16 vs 1.18 — 5 trials |
| Wired ↔ wireless, one WAP | 0/18 | 6/6 | wired + wireless matrix |
| Across WAPs, all mixes | 42/42 — no difference | wired + wireless matrix | |
| North/south (gateway, DNS, HTTP) | 24/24 — no difference | wired + wireless matrix | |
Both runs used two WF‑188n of identical model, firmware and configuration, on one VLAN, with the kernel module as the only variable. Clients were WF‑189 sensors: a real STA placed on an exact BSSID, and for the wired case a real LAN‑port station authorised by RADIUS MAC‑auth and leased by DHCP.
hostapd runs with vlan_no_bridge=1 and the client VLAN is deliberately absent from the Linux bridge, so each dynamic VIF (wlan0-v301, wlan1-v301) and each wired port (eth1) is its own sdan port with nothing bridging them. Traffic between any two of them has only one possible path, and that path is local switching — which is what 1.18 adds. You can see it in rxg_sdanctl tunnels: 1.18 reports local-switch=true with a climbing local-sw packet counter, while 1.16 (abi 3) has no such capability at all. Traffic that exits to the uplink never needs the feature, which is exactly why cross‑WAP is unaffected, and same‑radio traffic is handled by the WAP before sdan is involved, which is why its counter correctly stays flat there.
Wired ↔ wired on one WAP is untested. It is the same local‑switch path and so should behave the same way, but nothing here demonstrates it. It needs two LAN ports on one WAP — a WF‑189H (LAN1/LAN2) rather than the single‑port setup used here. Worth covering before assuming it, since a unit with two wired devices is a realistic hospitality case.
The wired result is unevenly sampled. 18 measurements on the failing side against 6 on the passing side, because of how the client placements were built. The 0/18 and 6/6 are each internally consistent across three traffic types and both directions, and the earlier cross‑radio case was 0/5 vs 5/5 over five trials — but a balanced re‑run is outstanding.
One uncontrolled difference. The 1.18 WAP also ran a patched rg_wss_client affecting wired tunnel selection. Both WAPs were untunneled plain‑VLAN in these runs, so it should not bear on local switching, but the software was not byte‑identical end to end.