Skip to content

wifi: mt76: mt7996: use own MAC as BSS BSSID for mesh interfaces - #1132

Open
outbackdingo wants to merge 1 commit into
openwrt:masterfrom
outbackdingo:mt7996-mesh-bssid-addr3
Open

outbackdingo wants to merge 1 commit into
openwrt:masterfrom
outbackdingo:mt7996-mesh-bssid-addr3

Conversation

@outbackdingo

Copy link
Copy Markdown

mt7996 transmits 802.11s Mesh Peering Management frames with
Address 3 = 00:00:00:00:00:00, which breaks mesh interoperability with peers
that filter received management frames on BSSID. A BPI-R4 (mt7996) could not
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() copies that into the hardware BSS entry
(memcpy(bss->bssid, link_conf->bssid, ETH_ALEN)), and the hardware stamps the
programmed BSS BSSID into Address 3 of transmitted management frames.

That value is wrong for the wire. mac80211's own kernel MPM uses the
transmitter's MAC (mesh_plink.c: memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN)),
and hostapd does the same for user-space MPM. bss_conf.bssid == zero is a
"no associated BSS" marker, not something to transmit.

Measurements

Driver entry vs. air, same 25 s window (pr_info at mt7996_tx() entry, plus an
independent monitor-mode station):

observation point addr3
mt7996_tx() entry 1035 frames, 02:0c:43:26:60:11 (own MAC)
on air 915 frames, 00:00:00:00:00:00

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 ath11k peer, same 35 s window:

frame on air delivered to peer host
Mesh Peering Open 217 0
Peering Confirm 194 0
Authentication (SAE) 400 108

The Authentication frames carry a correct addr3 and are delivered, so SAE
completes; the peering frames are ACKed at the MAC layer then silently dropped,
so MPM never completes. The peer closes with reason 56 (MESH_MAX_RETRIES),
reporting our link ID as 0.

Ruled out beforehand by measurement: hostapd/wpad version differences (sources
byte-identical), RF, 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 both sides), and the QCA
firmware build (swapped to a QSDK build, no change).

Validation

With this patch, on the same hardware and configuration:

  • on air: 211 mt7996 management frames now carry addr3 = 02:0c:43:26:60:11
  • the BPI-R4 reaches plink ESTAB with all three ath11k nodes
  • all four nodes report estab=3 and exchange batman-adv originators

Environment

  • mt76 be5ce7910521492d4a2e4ce7ee3843680a46c047
  • BPI-R4, OpenWrt r36157-f3614686ab, kernel 6.18.44, mt7996e
  • peer: IPQ5018 + QCN9074, ath11k, kernel 6.12.77, mac80211 backports-6.18.7
  • 802.11s + SAE, 5 GHz ch36 HE80, batman-adv on top

Note on other drivers

The same pattern appears in the shared helper, so other drivers are likely
affected. I only have mt7996 hardware, so these are unverified:

  • mt76_connac_mcu.c:2945memcpy(bss->bssid, vif->bss_conf.bssid, ETH_ALEN);
    in mt76_connac_mcu_bss_basic_tlv() (mt7615/mt7915/mt7921)
  • mt7925/mcu.c:2736memcpy(basic_req->bssid, link_conf->bssid, ETH_ALEN);

In both, the mesh case falls through the iftype switch without special handling,
so the zero bss_conf.bssid is what gets programmed.

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() copies that value into the hardware BSS entry,
and the hardware stamps the programmed BSS BSSID into Address 3 of the
management frames it transmits. Every Mesh Peering Management frame
(Self-Protected Action, category 15) therefore leaves the radio with
addr3 = 00:00:00:00:00:00.

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 does the same for user-space MPM.
bss_conf.bssid == zero is a "no associated BSS" marker, not a value to
transmit.

This breaks 802.11s interoperability with peers that filter received
management frames on BSSID. Measured against an ath11k (QCN9074) peer over
a 35 s window: 217 Mesh Peering Open and 194 Peering Confirm frames were
transmitted and ACKed at the MAC layer, and none were delivered to the
peer's host, while 108 of 400 SAE Authentication frames from the same
radio -- which carry a correct addr3 -- were delivered normally. SAE
therefore completes and MPM never does; the peer closes with reason 56
(MESH_MAX_RETRIES) reporting our link ID as 0.

Instrumenting mt7996_tx() confirms the header is correct on entry to the
driver and zeroed on air (same 25 s window: 1035 frames with
addr3 = own MAC at mt7996_tx(), 915 frames with addr3 = 0 on air,
captured by an independent monitor-mode station). mld=0 on every sample,
so the MLD address rewrite in mt7996_tx() is not involved.

With this change addr3 is correct on air and a BPI-R4 joins a three-node
ath11k 802.11s/batman-adv mesh: all four nodes reach plink ESTAB and
exchange batman-adv originators.

Signed-off-by: outbackdingo <outbackdingo@gmail.com>
@Headcrabed

Copy link
Copy Markdown

Shouldn't this patch get sent to upstream kernel mail list?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants