All of lore.kernel.org
 help / color / mirror / Atom feed
* [BUG] mac80211: ap_isolate is not applied to AP_VLAN interfaces
@ 2026-11-06  2:07 Christopher Hill
  2026-11-07  3:52 ` [PATCH wireless] wifi: mac80211: apply ap_isolate to AP_VLAN stations Christopher Hill
  0 siblings, 1 reply; 2+ messages in thread
From: Christopher Hill @ 2026-11-06  2:07 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless

Hi,

When an AP uses AP_VLAN interfaces (hostapd dynamic_vlan, e.g. VLAN
assignment via wpa_psk_file or RADIUS), the ap_isolate setting of the
BSS is not applied to stations bound to an AP_VLAN. mac80211 keeps
forwarding frames between stations of the same AP_VLAN even with
ap_isolate=1, so client isolation is silently ineffective for those
stations.

Code (wireless tree as of 2026-11-04, also v6.18 and mainline
7.4-rc1):

1. ieee80211_change_bss() (cfg.c) stores ap_isolate only on the
   sdata the request was issued for, i.e. the AP interface:

   if (params->ap_isolate >= 0) {
       if (params->ap_isolate)
           sdata->flags |= IEEE80211_SDATA_DONT_BRIDGE_PACKETS;
       else
           sdata->flags &= ~IEEE80211_SDATA_DONT_BRIDGE_PACKETS;
       ieee80211_check_fast_rx_iface(sdata);
   }

2. When an AP_VLAN is opened (ieee80211_do_open(), iface.c), several
   settings are copied from the master AP sdata (control_port_*,
   cab_queue, hw_queue, chandef, tailroom count), but not the
   IEEE80211_SDATA_DONT_BRIDGE_PACKETS flag. There is also no
   propagation to existing VLANs when ap_isolate changes later.

3. The intra-BSS forwarding decisions test the flag on the station’s
   own sdata, which is the AP_VLAN sdata for VLAN stations:

   - ieee80211_deliver_skb() (rx.c), sdata = rx->sdata:
     if ((sdata->vif.type == NL80211_IFTYPE_AP ||
          sdata->vif.type == NL80211_IFTYPE_AP_VLAN) &&
         !(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) && …

   - ieee80211_check_fast_rx() (rx.c), sdata = sta->sdata:
     fastrx.internal_forward =
         !(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) && ...

Interestingly, __ieee80211_check_fast_rx_iface() already iterates
stations whose sdata->bss matches the AP, i.e. it re-evaluates fast-rx
for AP_VLAN stations when ap_isolate changes - but the evaluated flag
lives on the AP_VLAN sdata, which is never updated.

By contrast, multicast_to_unicast is stored in struct ieee80211_if_ap
(sdata->u.ap) and read via sdata->bss in
ieee80211_multicast_to_unicast() (tx.c), so it does apply to AP_VLAN
interfaces.

Observed effect:

Linksys E8450 (MT7622 + MT7915E, mt76), OpenWrt 25.12.6 (mac80211
from backports 6.18.55), hostapd 2025-08-26 (ca266cc2), dynamic_vlan=2
with VLANs from wpa_psk_file, ap_isolate=1, multicast_to_unicast=1.
The AP_VLAN netdevs (wlan1-vlanN) are bridge ports with hairpin on (as
OpenWrt sets up for multicast_to_unicast, expecting ap_isolate to stop
mac80211's own intra-BSS forwarding). Every multicast frame from a
station is delivered twice to the other stations on the same AP_VLAN:
once by mac80211 (not isolated) and once by the bridge (hairpin).
E.g. an IPv6 all-nodes ping from one station gets two replies per
sequence from every other station on the same radio/VLAN, one from
wired hosts. Turning hairpin off on the AP_VLAN bridge port stops the
duplicates immediately, while the stations still answer - i.e. the
remaining copy is forwarded by mac80211 despite ap_isolate=1.

The sdata flags in debugfs confirm that the isolation bit
(IEEE80211_SDATA_DONT_BRIDGE_PACKETS, 0x8) is only set on the AP
interfaces, never on the AP_VLANs (ap_isolate=1 in hostapd):

 /sys/kernel/debug/ieee80211/<phy>/netdev:<if>/flags
 wlan0        flags=0x28 (IN_DRIVER|DONT_BRIDGE_PACKETS)
 wlan0-vlan10 flags=0x1  (ALLMULTI)
 wlan0-vlan20 flags=0x1
 wlan0-vlan30 flags=0x1
 wlan0-vlan40 flags=0x1
 wlan1        flags=0x28 (IN_DRIVER|DONT_BRIDGE_PACKETS)
 wlan1-vlan10 flags=0x1  (ALLMULTI)
 wlan1-vlan20 flags=0x1
 wlan1-vlan30 flags=0x1
 wlan1-vlan40 flags=0x1

Reproduction:

1. hostapd AP with dynamic_vlan=1 or 2 and per-station VLAN
   assignment (wpa_psk_file "vlanid=10 ..." or RADIUS), ap_isolate=1.

2. Check the sdata flags: cat
   /sys/kernel/debug/ieee80211/<phy>/netdev:<ap-if>/flags shows 0x8
   set; the same file for the AP_VLAN netdev does not.

3. Bridge the AP_VLAN netdev (e.g. wlan0-vlan10) with hairpin OFF.

4. Associate two stations A and B that both land on VLAN 10 on the
   same radio.

5. With correct isolation, A and B must not reach each other (no
   bridge hairpin, no mac80211 intra-BSS forwarding).

6. Observed: A pings B (IPv4 unicast): replies received.
   ping -6 ff02::1 from A: B replies (once per sequence).
   Both stations on the same radio and VLAN, hairpin off on the
   AP_VLAN bridge port, ap_isolate=1: the traffic can only have been
   forwarded by mac80211.

   Expected: ap_isolate applies to all stations of the BSS, including
   those on AP_VLAN interfaces.

Possible fix (untested sketch, for discussion only): evaluate the
master AP's flag for AP_VLAN sdata in both rx.c places, e.g.

static bool ieee80211_sdata_dont_bridge(struct ieee80211_sub_if_data *sdata)
{
    if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN && sdata->bss)
        sdata = container_of(sdata->bss,
                     struct ieee80211_sub_if_data, u.ap);
    return sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS;
}

or move the setting into struct ieee80211_if_ap next to
multicast_to_unicast.

Thanks,
Christopher Hill

(Disclosure, bug investigation was AI assisted)

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-11-07  3:54 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-06  2:07 [BUG] mac80211: ap_isolate is not applied to AP_VLAN interfaces Christopher Hill
2026-11-07  3:52 ` [PATCH wireless] wifi: mac80211: apply ap_isolate to AP_VLAN stations Christopher Hill

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.