Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
2e4d39d
gitignore: Ignore __pycache__ directories
mattiaswal Oct 7, 2026
b3cafec
test: Regenerate the OSPF BFD specifications
mattiaswal Oct 7, 2026
0ce465b
board: bpi-r3: Move ramdisk above the MT7986 WiFi reserved memory
mattiaswal Oct 2, 2026
f48f055
confd: wifi: Create a hostapd control socket for every BSS
mattiaswal Oct 2, 2026
e64f161
hostapd: Allow binding WDS stations to preconfigured interfaces
mattiaswal Oct 2, 2026
b1b7e32
confd: wifi: Add 4-address WDS link and station modes
mattiaswal Oct 2, 2026
3459edd
statd: wifi: Report wds-link state in operational data and CLI
mattiaswal Oct 2, 2026
73dd986
webui: Show wds-link WiFi interfaces
mattiaswal Oct 2, 2026
d426daa
test: Add WiFi WDS link and repeater tests
mattiaswal Oct 2, 2026
e84779e
doc: Document WDS backhaul and repeaters
mattiaswal Oct 2, 2026
49079b3
test: wifimedium: Raise the carrier MTU and drop oversized frames
mattiaswal Oct 3, 2026
89b985e
confd: wifi: Detach a WiFi interface from hostapd before deleting it
mattiaswal Oct 2, 2026
556b93a
confd: wifi: Apply station and mesh changes on commit
mattiaswal Oct 2, 2026
4977570
confd: wifi: Collect the channel survey on request
mattiaswal Oct 5, 2026
7a98e72
cli: Add show hardware <radio> survey
mattiaswal Oct 5, 2026
752370d
webui: Scan channels on request from the WiFi page
mattiaswal Oct 5, 2026
de54120
doc: Document the WiFi channel survey
mattiaswal Oct 5, 2026
3e07731
test: Add WiFi channel survey test
mattiaswal Oct 5, 2026
e15713f
yang: Limit WiFi country codes to the regulatory database
mattiaswal Oct 6, 2026
03ef83f
confd: wifi: Move the country code to a box-wide setting
mattiaswal Oct 6, 2026
8eece19
webui: Use the box-wide WiFi country code
mattiaswal Oct 6, 2026
87ff7b2
confd: wifi: Enable management frame protection on stations
mattiaswal Oct 6, 2026
d96fa2d
statd: wifi: Tell WPA3-only networks apart in scan results
mattiaswal Oct 6, 2026
26f87e5
webui: Click the survey chart to open it in an overlay
mattiaswal Oct 6, 2026
34521de
webui: Survive a broken YANG schema cache
mattiaswal Oct 7, 2026
be8fe35
confd: Run the hardware handler after the interfaces
mattiaswal Oct 7, 2026
1a49699
hostapd: Add ft_iface for the 802.11r key holder exchange
mattiaswal Oct 7, 2026
6eadecf
confd: wifi: Exchange 802.11r keys between access points
mattiaswal Oct 7, 2026
015ad8c
confd: wifi: Hand clients over before hostapd stops
mattiaswal Oct 7, 2026
81b4913
confd: wifi: Steer dual-band clients to the higher band
mattiaswal Oct 7, 2026
26f6224
confd: wifi: Tell the other nodes about our access points
mattiaswal Oct 7, 2026
c8aa85a
patches: linux: Map the WED firmware regions without requesting them
mattiaswal Oct 2, 2026
a91a7f3
patches: linux: Fix WED attach panic on non-DBDC MT7986
mattiaswal Oct 2, 2026
73dbee0
patches: linux: Fix WED on the single-band MT7986 radio
mattiaswal Oct 8, 2026
5f75bdf
board: bpi-r3: Enable WED in mt7915e
mattiaswal Oct 2, 2026
661df01
onieprom: Fix encoding JSON to a TLV
mattiaswal Oct 9, 2026
9d67172
probe: Read the product VPD from a factory partition
mattiaswal Oct 9, 2026
c8579c6
bpi-r3: Give ports a chassis-derived address at boot
mattiaswal Oct 9, 2026
68d77e3
confd: wifi: Derive VIF addresses from the chassis MAC
mattiaswal Oct 9, 2026
8d25af3
hostapd: Push PMK-R1 to the R1KHs added by RELOAD_RXKHS
mattiaswal Oct 9, 2026
732f6d9
confd: wifi: Push the 802.11r keys to the other nodes' access points
mattiaswal Oct 9, 2026
22c6413
bpi-r3: dts: Drop the ethernet aliases
mattiaswal Oct 10, 2026
98841b6
webui: Add the 802.11r key holder secret to the interface editor
mattiaswal Oct 11, 2026
34df16a
hostapd: Cancel the key holder timers before RELOAD_RXKHS frees them
mattiaswal Oct 11, 2026
d6e23cc
confd: firewall: Re-apply dynamic address-set entries after reload
mattiaswal Oct 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ AGENTS.md
/test/.log
/local.mk
/test/spec/Readme.adoc
__pycache__/
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
"name": "radio0",
"class": "infix-hardware:wifi",
"infix-hardware:wifi-radio": {
"country-code": "DE",
"band": "2.4GHz",
"channel": "auto"
}
Expand All @@ -31,7 +30,6 @@
"name": "radio1",
"class": "infix-hardware:wifi",
"infix-hardware:wifi-radio": {
"country-code": "DE",
"band": "6GHz",
"channel": "auto"
}
Expand All @@ -40,12 +38,14 @@
"name": "radio2",
"class": "infix-hardware:wifi",
"infix-hardware:wifi-radio": {
"country-code": "DE",
"band": "5GHz",
"channel": "auto"
}
}
]
],
"infix-hardware:wifi": {
"country-code": "DE"
}
},
"ietf-interfaces:interfaces": {
"interface": [
Expand Down Expand Up @@ -457,7 +457,7 @@
]
},
"infix-meta:meta": {
"version": "1.10"
"version": "1.11"
},
"infix-services:mdns": {
"enabled": true
Expand Down
30 changes: 30 additions & 0 deletions board/aarch64/bananapi-bpi-r3/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,36 @@ sync
2. Set boot switches to eMMC mode (see image above)
3. Power on

## Giving the Board a Permanent MAC Address

The BPI-R3 family has no EEPROM with a factory-programmed MAC address.
Out of the box every Ethernet port therefore gets a random address on
each boot, and the hostname, which is derived from the base address,
changes with it. Worse, both WiFi radios carry the same MediaTek
default address on every board, so two boards cannot even connect to
each other over WiFi: a client refuses to authenticate to an access
point that has its own address.

The eMMC image carries an empty `factory` partition for this purpose.
Write a product record to it once, from the Infix shell, and the board
keeps that identity across reboots and upgrades:

```
echo '{"mac-address":"02:00:00:ba:01:00","serial-number":"banana1","vendor":"Bananapi","product-name":"BPI-R3"}' \
| onieprom -e | dd of=/dev/disk/by-partlabel/factory
```

Give each board its own base address and serial number, then reboot.
The base address becomes the hostname suffix, the wired ports get base
+ 1, base + 2, and so on in name order, and the WiFi interfaces get
addresses derived from the base. With the record above the board is
named `bpi-ba-01-00`, `lan1` is `02:00:00:ba:01:02` and `wifi0` is
`06:00:00:ba:01:00`.

A locally administered address like `02:xx:xx:xx:xx:xx` is fine for a
lab. For boards that will share a network with other equipment, use a
range you own. See [Vital Product Data](../../../doc/vpd.md#factory-partition)
for the record format and what else it can carry.

## Troubleshooting

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,18 @@
/ {
/*
* U-Boot writes its ethaddr, which it generates at random on
* every boot, into the node behind the ethernet0 alias. The
* kernel then reports that port, and every switch port that
* inherits from it, as having a permanent hardware address.
* Drop the aliases so the ports come up with a random address
* instead, which init.d/22-macaddr replaces with a chassis-
* derived one when a product VPD is present.
*/
aliases {
/delete-property/ ethernet0;
/delete-property/ ethernet1;
};

chosen {
infix {
/* Default admin user password: 'admin' */
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Wireless Ethernet Dispatch, the WiFi hardware offload path
options mt7915e wed_enable=1
86 changes: 86 additions & 0 deletions board/aarch64/bananapi-bpi-r3/rootfs/usr/libexec/bpi-r3/macaddr
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#!/usr/bin/env python3
"""Give ports without a hardware MAC address a chassis-derived one.

The BPI-R3 family has no MAC EEPROM, so every port boots with a random
address, and the switch ports inherit that from their conduit. When
the product VPD provides a base MAC, hand each such port a stable
address derived from it: base + 1, base + 2, ... in interface name
order. This mirrors what products with real hardware addresses get
from their device tree. Ports with a permanent address are left alone.

Runs from /etc/product/init.d, before the DSA conduit is renamed, so
it sorts as eth0 and takes base + 1.
"""
import json
import os
import subprocess
import sys

SYSTEM_JSON = "/run/system.json"
NET = "/sys/class/net"
NET_ADDR_PERM = 0


def log(msg):
subprocess.run(["logger", "-k", "-p", "user.notice", "-t", "macaddr", msg],
check=False)


def vpd_base_mac():
try:
with open(SYSTEM_JSON, encoding="ascii") as f:
system = json.load(f)
except (OSError, ValueError):
return None

product = system.get("vpd", {}).get("product", {})
return product.get("data", {}).get("mac-address")


def mac_add(mac, offset):
num = int(mac.replace(":", ""), 16) + offset
num %= 1 << 48
return ":".join(f"{(num >> 8 * i) & 0xff:02x}" for i in range(5, -1, -1))


def read(path):
with open(path, encoding="ascii") as f:
return f.read().strip()


def ports():
"""Wired ports whose address the kernel did not get from hardware."""
for name in sorted(os.listdir(NET)):
path = os.path.join(NET, name)
if not os.path.exists(os.path.join(path, "device")):
continue
if os.path.exists(os.path.join(path, "phy80211")):
continue
try:
if int(read(os.path.join(path, "addr_assign_type"))) == NET_ADDR_PERM:
continue
except (OSError, ValueError):
continue

yield name


def main():
base = vpd_base_mac()
if not base:
return 0

for offset, name in enumerate(ports(), start=1):
mac = mac_add(base, offset)
rc = subprocess.run(["ip", "link", "set", "dev", name, "address", mac],
check=False)
if rc.returncode:
log(f"failed setting {name} address {mac}")
continue
log(f"{name}: {mac} (chassis + {offset})")

return 0


if __name__ == "__main__":
sys.exit(main())
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
"name": "radio0",
"class": "infix-hardware:wifi",
"infix-hardware:wifi-radio": {
"country-code": "DE",
"band": "2.4GHz",
"channel": "auto"
}
Expand All @@ -31,12 +30,14 @@
"name": "radio1",
"class": "infix-hardware:wifi",
"infix-hardware:wifi-radio": {
"country-code": "DE",
"band": "5GHz",
"channel": "auto"
}
}
]
],
"infix-hardware:wifi": {
"country-code": "DE"
}
},
"ietf-interfaces:interfaces": {
"interface": [
Expand Down Expand Up @@ -450,7 +451,7 @@
]
},
"infix-meta:meta": {
"version": "1.10"
"version": "1.11"
},
"infix-services:mdns": {
"enabled": true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
"name": "radio0",
"class": "infix-hardware:wifi",
"infix-hardware:wifi-radio": {
"country-code": "DE",
"band": "2.4GHz",
"channel": "auto"
}
Expand All @@ -31,12 +30,14 @@
"name": "radio1",
"class": "infix-hardware:wifi",
"infix-hardware:wifi-radio": {
"country-code": "DE",
"band": "5GHz",
"channel": "auto"
}
}
]
],
"infix-hardware:wifi": {
"country-code": "DE"
}
},
"ietf-interfaces:interfaces": {
"interface": [
Expand Down Expand Up @@ -416,7 +417,7 @@
]
},
"infix-meta:meta": {
"version": "1.10"
"version": "1.11"
},
"infix-services:mdns": {
"enabled": true
Expand Down
2 changes: 1 addition & 1 deletion board/aarch64/bananapi-bpi-r3/uboot/mt7986-env.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
fdt_addr_r = "0x43f00000";
kernel_addr_r = "0x44000000";
scriptaddr = "0x48000000";
ramdisk_addr_r = "0x4A000000";
ramdisk_addr_r = "0x50000000";

en8811h_fw_part = "0#en8811h_fw";
en8811h_fw_dm_dir = "EthMD32.dm.bin";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@
]
},
"infix-meta:meta": {
"version": "1.10"
"version": "1.11"
},
"infix-services:mdns": {
"enabled": true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@
]
},
"infix-meta:meta": {
"version": "1.10"
"version": "1.11"
},
"infix-services:mdns": {
"enabled": true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@
"name": "radio0",
"class": "infix-hardware:wifi",
"infix-hardware:wifi-radio": {
"country-code": "DE",
"band": "2.4GHz",
"channel": "auto"
}
}
]
],
"infix-hardware:wifi": {
"country-code": "DE"
}
},
"ietf-interfaces:interfaces": {
"interface": [
Expand Down Expand Up @@ -408,7 +410,7 @@
]
},
"infix-meta:meta": {
"version": "1.10"
"version": "1.11"
},
"infix-services:mdns": {
"enabled": true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@
]
},
"infix-meta:meta": {
"version": "1.10"
"version": "1.11"
},
"infix-services:mdns": {
"enabled": true
Expand Down
10 changes: 5 additions & 5 deletions board/aarch64/raspberrypi-rpi64/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,19 +118,19 @@ Then configure the WiFi interface using the keystore reference:

```
admin@infix:/> configure
admin@infix:/config/> set hardware wifi country-code US
admin@infix:/config/> edit interface wifi0
admin@infix:/config/interface/wifi0/> set ipv4 dhcp-client
admin@infix:/config/interface/wifi0/> set wifi ssid YourNetworkName
admin@infix:/config/interface/wifi0/> set wifi secret mywifi
admin@infix:/config/interface/wifi0/> set wifi country-code US
admin@infix:/config/interface/wifi0/> set wifi station ssid YourNetworkName
admin@infix:/config/interface/wifi0/> set wifi station security secret mywifi
admin@infix:/config/interface/wifi0/> leave
```

> [!NOTE]
> The WiFi password (8-63 characters) is stored securely in the keystore as
> `mywifi` (or any name you choose), which is then referenced in the WiFi
> configuration. The country-code must match your location for regulatory
> compliance (e.g., US, SE, DE, JP).
> configuration. The country code is one setting for all radios and must
> match your location for regulatory compliance (e.g., US, SE, DE, JP).

### Touch Screen Support

Expand Down
Loading
Loading