mt76: mt7996 sends 802.11s mesh peering frames with zero addr3, breaking interop with ath11k (patch + validation)

Janusz Dziedzic janusz.dziedzic at gmail.com
Fri Sep 11 01:08:04 PDT 2026


pt., 11 wrz 2026 o 09:05 OpenWrt via openwrt-devel
<openwrt-devel at lists.openwrt.org> napisał(a):
>
> The sender domain has a DMARC Reject/Quarantine policy which disallows
> sending mailing list messages using the original "From" header.
>
> To mitigate this problem, the original message has been wrapped
> automatically by the mailing list software.
>
>
> ---------- Forwarded message ----------
> From: openwrt at optimcloud.com
> To: openwrt-devel at lists.openwrt.org
> Cc:
> Bcc:
> Date: Fri, 11 Sep 2026 14:03:27 +0700
> Subject: mt76: mt7996 sends 802.11s mesh peering frames with zero addr3, breaking interop with ath11k (patch + validation)
> Reporting an 802.11s interoperability bug in mt76/mt7996, with a patch that
> is validated on hardware. Pull request against openwrt/mt76 is open here:
>
>   https://github.com/openwrt/mt76/pull/1132
>
> Details below.
>
> ---
>
> mt7996 transmits 802.11s Mesh Peering Management frames with
> Address 3 = 00:00:00:00:00:00. This breaks mesh interoperability with
> peers that filter received management frames on BSSID; in particular a
> BPI-R4 (mt7996) cannot form a peering with ath11k (QCN9074) nodes.
>
> Root cause
> ----------
> mac80211 deliberately leaves bss_conf.bssid as zero_addr for mesh
> interfaces, because an MBSS has no BSSID in the infrastructure sense:
>
>   net/mac80211/mesh.c:  sdata->vif.bss_conf.bssid = zero_addr;
>
> mt7996_mcu_bss_basic_tlv() (drivers/net/wireless/mediatek/mt76/mt7996/mcu.c)
> copies that value into the hardware BSS entry:
>
>   memcpy(bss->bssid, link_conf->bssid, ETH_ALEN);
>
> and the mt7996 hardware stamps the programmed BSS BSSID into Address 3 of
> management frames it transmits. Every Mesh Peering Management frame
> (Self-Protected Action, category 15) therefore leaves the radio with
> addr3 zeroed.
>
> That value is wrong for the wire. mac80211's own kernel MPM puts the
> transmitter's MAC in addr3:
>
>   net/mac80211/mesh_plink.c:  memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
>
> and hostapd/wpa_supplicant does the same for user-space MPM
> (wpa_driver_nl80211_send_action() is called with bssid = wpa_s->own_addr).
> bss_conf.bssid == zero is a "no associated BSS" marker, not a value to
> transmit.
>
> Observed behaviour
> ------------------
> Measured with a laptop in monitor mode as an independent observer, plus
> instrumentation on both endpoints.
>
> Frames as handed to the driver (pr_info added at mt7996_tx() entry),
> and the same frames on air in the same 25 s window:
>
>   mt7996_tx() entry : 1035 frames, addr3 = 02:0c:43:26:60:11 (own MAC)
>   on air            :  915 frames, addr3 = 00:00:00:00:00:00
>
> so the header is correct when mac80211 hands it over and zeroed by the
> time it is transmitted. mld=0 on every sample, so the MLD address
> rewrite in mt7996_tx() is not involved (it is gated on
> ieee80211_vif_is_mld() and would also have rewritten addr2, which is
> intact).
>
> Effect on the peer (ath11k QCN9074, same 35 s window):
>
>   BPI Mesh Peering Open   -> peer : 217 on air, 0 delivered to host
>   BPI Peering Confirm     -> peer : 194 on air, 0 delivered to host
>   BPI Authentication (SAE)-> peer : 400 on air, 108 delivered to host
>
> The Authentication frames carry a correct addr3 and are delivered, so SAE
> completes; the peering frames are ACKed at the MAC layer and then
> silently discarded, so MPM never completes. The peer eventually closes
> with reason 56 (MESH_MAX_RETRIES) reporting our link ID as 0, i.e. it
> never recorded the peering at all.
>
> Ruled out by measurement before finding this: wpad/hostapd version
> differences (sources byte-identical), RF/signal, sae_pwe, rsn_overriding,
> the EHT elements mt7996 adds (suppressed and verified absent on air,
> still failed), PHY rate (all frames legacy OFDM 6 Mbit/s), the Protected
> bit (clear on both sides), and the QCA firmware build (swapped to a QSDK
> build, no change).
>
> Fix
> ---
> Use the interface's own address as the BSS BSSID for mesh interfaces.
>
> --- a/mt7996/mcu.c
> +++ b/mt7996/mcu.c
> @@ -1260,7 +1260,15 @@
>                 return 0;
>         }
>
> -       memcpy(bss->bssid, link_conf->bssid, ETH_ALEN);
> +       /* mac80211 sets bss_conf.bssid = zero_addr for mesh interfaces, and
> +        * the mt7996 HW stamps the programmed BSS BSSID into addr3 of TXed
> +        * mgmt frames. That would send mesh peering frames with a zero addr3,
> +        * which peers filtering on BSSID (e.g. ath11k) silently drop.
> +        */
> +       if (vif->type == NL80211_IFTYPE_MESH_POINT)
> +               memcpy(bss->bssid, link_conf->addr, ETH_ALEN);
> +       else
> +               memcpy(bss->bssid, link_conf->bssid, ETH_ALEN);
>         bss->bcn_interval = cpu_to_le16(link_conf->beacon_int);
>         bss->dtim_period = link_conf->dtim_period;
>         bss->phymode = mt76_connac_get_phy_mode(phy, vif,
>
> Validation
> ----------
> With the patch applied, on the same hardware and configuration:
>
>   - on air: 211 mt7996 management frames now carry
>     addr3 = 02:0c:43:26:60:11 (previously all zero)
>   - the BPI-R4 reaches plink ESTAB with all three ath11k nodes
>   - all four nodes report estab=3 and exchange batman-adv originators
>
> Environment
> -----------
>   mt76           : openwrt/mt76 be5ce7910521492d4a2e4ce7ee3843680a46c047
>                    (PKG_SOURCE_DATE 2026-09-01)
>   BPI-R4         : OpenWrt r36157-f3614686ab, kernel 6.18.44, mt7996e
>   peer           : IPQ5018 + QCN9074, ath11k, kernel 6.12.77,
>                    mac80211 backports-6.18.7
>   mesh           : 802.11s, SAE, 5 GHz ch36 HE80, batman-adv on top
>
> Note: the same pattern appears in the shared helper used by the other
> drivers, so they are likely affected too. I only have mt7996 hardware, so
> I have not verified these:
>
>   mt76_connac_mcu.c:2945  memcpy(bss->bssid, vif->bss_conf.bssid, ETH_ALEN);
>                           (mt76_connac_mcu_bss_basic_tlv(), used by
>                            mt7615/mt7915/mt7921)
>   mt7925/mcu.c:2736       memcpy(basic_req->bssid, link_conf->bssid, ETH_ALEN);
>
> In both the mesh case falls through the iftype switch without special
> handling, so bss_conf.bssid (zero for mesh) is what gets programmed.
>

Sound like a ath11k/ath12k firmware filtering issue for mesh point
type, while mac80211 setup it zero_addr (should be received).

Anyway I have same workaround for mt7915 in my tree in
mt76_connac_mcu_bss_basic_tlv() to pass with ath12k.
Maybe someone from QCA should fix firmware filtering for mesh point?
Before that, workaround looks good for me.

BR
Janusz



More information about the openwrt-devel mailing list