Skip to content

Wifi misc - #1680

Merged
troglobit merged 45 commits into
mainfrom
wifi-wds
Oct 11, 2026
Merged

troglobit merged 45 commits into
mainfrom
wifi-wds

Conversation

@mattiaswal

@mattiaswal mattiaswal commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

This branch bringing Infix to the next level of Wi-Fi support.

New feature:

  • WDS support in AP/Station, enables creating wifi-repeaters
  • In AP mode, it actively steer the stations connected, before going down for reconfiguration or reboot
  • VPD is now possible to be on a flash partition named factory
  • Wi-FI VIFs MAC addresses is derived from the base MAC, no more requirement of custom-phys-address
  • Enable WED on BPI-r3 and its derivatives (hardware acceleration)

This also change existing YANG model syntaxes:

  • WiFi domain is moved to hardware/wifi (boxlevel), since it is configured this way
  • A huge fixup of the country codes, remove NOP codes, add missing.
  • Adding a seperate secret for 802.11r, default SSID secret, but adds additional secret above if the user like it
  • The survey has been removed from operational, and is instead an action that user can call. So now the survey
    actually show something useful, web and CLI is fixed.

Migrate scripts added

And of course, a bunch of bugfixes

Fix #1679

Description

Checklist

Tick relevant boxes, this PR is-a or has-a:

  • Bugfix
    • Regression tests
    • ChangeLog updates (for next release)
  • Feature
    • YANG model change => revision updated?
    • Regression tests added?
    • ChangeLog updates (for next release)
    • Documentation added?
  • Test changes
    • Checked in changed Readme.adoc (make test-spec)
    • Added new test to group Readme.adoc and yaml file
  • Code style update (formatting, renaming)
  • Refactoring (please detail in commit messages)
  • Build related changes
  • Documentation content changes
    • ChangeLog updated (for major changes)
  • Other (please describe):

@mattiaswal
mattiaswal force-pushed the wifi-wds branch 16 times, most recently from 461b205 to ceae4a0 Compare October 9, 2026 11:35
@mattiaswal mattiaswal added the ci:main Build default defconfig, not minimal label Oct 9, 2026
@mattiaswal
mattiaswal force-pushed the wifi-wds branch 2 times, most recently from f81dfbe to 1c694af Compare October 11, 2026 08:18
@mattiaswal mattiaswal changed the title Wifi wds Wifi misc Oct 11, 2026
@mattiaswal
mattiaswal force-pushed the wifi-wds branch 2 times, most recently from 2aedf60 to 9cfe39e Compare October 11, 2026 14:17
@mattiaswal
mattiaswal marked this pull request as ready for review October 11, 2026 15:45
@mattiaswal
mattiaswal requested a review from troglobit October 11, 2026 15:45
Signed-off-by: Mattias Walström <lazzer@gmail.com>
Signed-off-by: Mattias Walström <lazzer@gmail.com>
The rootfs image loaded at 0x4A000000 covered the WiFi firmware and WED
regions at 0x4fc00000, so the kernel could not reserve them.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
hostapd only creates the socket for the BSS with a ctrl_interface line,
so hostapd_cli could not reach the secondary SSIDs on a radio.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
Adds wds_sta_ifname=<mac> <ifname>, so a 4-address station can be bound
to a port that already exists and is bridged by someone else.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
A wds-link interface is a bridge port of a local access point for one
remote 4-address station, created as an AP_VLAN up front and bound by
hostapd via wds_sta_ifname.  A station with wds enabled may be a bridge
port.  Also judge hostapd config by the APs left in config on commit,
since the changed interface on a radio need not be an AP anymore.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
The country moves from each radio's form to a WiFi card on the hardware
page.  The interface editor and the wizard still offer it next to the
radio fields, so a first radio can be set up in one go, but write it to
the shared leaf.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
A WPA3-only access point requires it, and on 6 GHz every access point
does.  wpa_supplicant silently skipped those networks as candidates, so
the station saw them in the scan but never tried to associate.  Set it
as capable rather than required, WPA2 networks without it still work.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
wpa_supplicant labels every RSN network WPA2, so an SAE-only network
showed up as WPA2-Personal.  Classify by key management instead.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
The chart is capped at 220 px in the radio card, too small to read on
a radio with many channels.  A click opens a copy in a dialog sized to
the window, closed with the button, the backdrop or Escape.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
A module file cut short, left by a restart in the middle of a download,
made goyang dereference nil at every start.  Write cached files through a
temporary name, turn a parser panic into an error, drop a cache that
fails to load so the next refresh fetches it again, and prune files the
device no longer lists so two revisions of a module never load together.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
hostapd binds to WiFi netdevs.  With the hardware handler first, a
commit that recreates an access point netdev, e.g. for a new MAC
address, restarted hostapd before the interface pipeline rebuilt the
netdev.  hostapd bound to the one about to be deleted and kept reporting
the access point enabled while the new netdev sat idle.  Run the
interfaces first, then the hardware.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
The exchange is sent on the bridge the BSS is a port of.  On a VLAN
filtering bridge a frame from the bridge device lands in the bridge's
own untagged VLAN, if any, not in the access points' VLAN, and naming
another interface as the bridge makes hostapd move the BSS into it.
Add a per-BSS ft_iface option for the interface to use instead.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
Fast transition to an access point on another device failed for WPA3
clients with status 53, invalid PMKID: their PMK comes from the SAE
handshake, so the target cannot regenerate it from the passphrase like
ft_psk_generate_local does for WPA2.  Give every access point of the
SSID wildcard R0KH/R1KH entries with a key derived from the mobility
domain and a shared secret, so the target fetches the PMK-R1 from the
access point the client came from, and tell hostapd about the bridge so
that exchange reaches the other devices.

The secret is the passphrase unless an optional key-holder-secret, a
keystore reference under dot11r, is set.  Every client knows the
passphrase and whoever holds the key is handed every client's keys, so
a shared network wants a key of its own.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
A client with a good signal has no reason to roam, so when its access
point goes away it only notices once the beacons stop, and then scans
for a new network.  Run hostapd through a wrapper that, when stopped,
sends every station an 802.11v BSS transition request with
disassociation imminent and waits for them to leave, so clients that
support it roam while the radio is still up.  Give finit ten seconds
before SIGKILL to make room for that.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
Withholding probe responses only sways a client that is choosing a
network, a client already connected on 2.4 GHz stays there.  Ask such
clients to move with an 802.11v request naming the higher-band twin,
from a steering loop the hostapd wrapper runs per pair, as long as the
twin is up and the client's 2.4 GHz signal makes the move worthwhile; a
client that shrugs off a couple of requests is left alone for an hour.
Refusing authentication on 2.4 GHz for clients the twin has seen was
tried and dropped: it locks a client out when the twin cannot take it.
Keep the seen-on list to one minute.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
A client asked to move needs to know where to, wpa_supplicant ignores a
transition request without candidates, and a node does not know the
other nodes' access points.  Every 30 seconds a node announces its
access points in one frame per network they are bridged to, the network
the 802.11r key exchange uses, and listens for the other nodes' frames.
What it hears goes to hostapd as 802.11k neighbors of every access
point with the same SSID, and into the handover request.  No radio
leaves its channel for it.

Anything on that network can send such a frame, so each line is tagged
with the 802.11r key of its SSID and checked before use.  The frame
starts with a version; a node drops frames of another version and logs
it once per sender, so bump the version when the format changes.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
Signed-off-by: Mattias Walström <lazzer@gmail.com>
Signed-off-by: Mattias Walström <lazzer@gmail.com>
With WED on, the built-in radio of a BPI-R3 or W6m stalled its WPDMA RX
ring after a few thousand frames: clients associated and nothing else
arrived.  The radio is bound to band 1 and never set up ring 0, which
the WED drives alike.  Give it an empty ring 0.  Also pull in the WDS
with WED support, the WED v2 reserve buffer and the wcid publish order
from upstream.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
Applies to every MT7986 board built from this BSP: BPI-R3, BPI-R3 Mini
and the Acer Connect Vero W6m.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
The encode and decode functions were never imported in the CLI entry point.
SBCs have no VPD EEPROM, so they boot with a random base MAC and a new
hostname every time.  Fall back to an ONIE TLV at the start of the
partition labelled factory, never trusted since anyone with the disk
can write it.
The board has no MAC EEPROM, so ports come up random and the switch
ports inherit the conduit's address.  A product init script hands each
port base + N from the VPD, in interface name order.
Every VIF inherited the radio's address, which on boards with the
default EEPROM is the same on every unit, so two BPI-R3 could not even
authenticate to each other: mac80211 rejects a peer with the local
address with EINVAL.  Encode the interface number in the first octet so
the result never overlaps the chassis + N port addresses.
hostapd pushes a client's key to the key holders known when it
authenticated and never again, so an access point learned later has
nothing for that client until it re-authenticates.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
A roam to an access point that has to fetch the client's key fails once
the access point the client first connected to is gone.  Enable
pmk_r1_push and keep the key holders in a file that wifi-neighbors.py
fills with the access points it hears of and has hostapd reload, so
every node holds the key before it is needed.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
U-Boot patches its per-boot random ethaddr into the ethernet0 node, so
the kernel reports gmac0 and all switch ports as having a permanent
address and 22-macaddr leaves them alone.  Without the aliases the
ports come up random and get their chassis-derived address.
Optional, the WiFi password is used when none is chosen.
A key holder learned through a wildcard entry is freed by a timer, and
every entry may hold sequence state with a timer of its own.  The reload
freed the lists under both, so a timer could later fire on whatever
entry had taken the address.
Dynamic entries were baked into the generated ipset XML to survive a
firewalld reload, which resurrected entries removed while a reload was
in flight.  The XML now holds static entries only, and 'firewall
reload' re-applies the dynamic ones from confd's shadow files once
firewalld is back, dropping any it rejects.

Signed-off-by: Mattias Walström <lazzer@gmail.com>

@troglobit troglobit left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very cool, nice work!

@troglobit

Copy link
Copy Markdown
Contributor

100% PASS in regression tests across the board!

@troglobit
troglobit merged commit 282f8be into main Oct 11, 2026
11 checks passed
@troglobit
troglobit deleted the wifi-wds branch October 11, 2026 20:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci:main Build default defconfig, not minimal

Projects

None yet

Development

Successfully merging this pull request may close these issues.

WiFi station settings added to a scan-only interface do not take effect until reboot

2 participants