Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
3b377d9
gitignore: Ignore __pycache__ directories
mattiaswal Oct 7, 2026
e8f0958
test: Regenerate the OSPF BFD specifications
mattiaswal Oct 7, 2026
bf34258
board: bpi-r3: Move ramdisk above the MT7986 WiFi reserved memory
mattiaswal Oct 2, 2026
730a014
confd: wifi: Create a hostapd control socket for every BSS
mattiaswal Oct 2, 2026
56793c2
hostapd: Allow binding WDS stations to preconfigured interfaces
mattiaswal Oct 2, 2026
7bb2f5f
confd: wifi: Add 4-address WDS link and station modes
mattiaswal Oct 2, 2026
5de2a37
statd: wifi: Report wds-link state in operational data and CLI
mattiaswal Oct 2, 2026
68ec6e6
webui: Show wds-link WiFi interfaces
mattiaswal Oct 2, 2026
b5b74bd
test: Add WiFi WDS link and repeater tests
mattiaswal Oct 2, 2026
3c735dd
doc: Document WDS backhaul and repeaters
mattiaswal Oct 2, 2026
703978c
test: wifimedium: Raise the carrier MTU and drop oversized frames
mattiaswal Oct 3, 2026
4f1a40c
confd: wifi: Detach a WiFi interface from hostapd before deleting it
mattiaswal Oct 2, 2026
2df123f
confd: wifi: Apply station and mesh changes on commit
mattiaswal Oct 2, 2026
1afa770
confd: wifi: Collect the channel survey on request
mattiaswal Oct 5, 2026
45c7fe9
cli: Add show hardware <radio> survey
mattiaswal Oct 5, 2026
943f8b0
webui: Scan channels on request from the WiFi page
mattiaswal Oct 5, 2026
5e52cd8
doc: Document the WiFi channel survey
mattiaswal Oct 5, 2026
788eccc
test: Add WiFi channel survey test
mattiaswal Oct 5, 2026
8ea6e2d
yang: Limit WiFi country codes to the regulatory database
mattiaswal Oct 6, 2026
57446a8
confd: wifi: Move the country code to a box-wide setting
mattiaswal Oct 6, 2026
6e562f5
webui: Use the box-wide WiFi country code
mattiaswal Oct 6, 2026
b86bd53
confd: wifi: Enable management frame protection on stations
mattiaswal Oct 6, 2026
3ff32db
statd: wifi: Tell WPA3-only networks apart in scan results
mattiaswal Oct 6, 2026
c62532a
webui: Click the survey chart to open it in an overlay
mattiaswal Oct 6, 2026
88bb008
webui: Survive a broken YANG schema cache
mattiaswal Oct 7, 2026
77f0e52
confd: Run the hardware handler after the interfaces
mattiaswal Oct 7, 2026
80668ea
hostapd: Add ft_iface for the 802.11r key holder exchange
mattiaswal Oct 7, 2026
fd63559
confd: wifi: Exchange 802.11r keys between access points
mattiaswal Oct 7, 2026
165058b
confd: wifi: Hand clients over before hostapd stops
mattiaswal Oct 7, 2026
bbcd4fe
confd: wifi: Steer dual-band clients to the higher band
mattiaswal Oct 7, 2026
b0af183
confd: wifi: Tell the other nodes about our access points
mattiaswal Oct 7, 2026
97d331f
patches: linux: Map the WED firmware regions without requesting them
mattiaswal Oct 2, 2026
9d9abf8
patches: linux: Fix WED attach panic on non-DBDC MT7986
mattiaswal Oct 2, 2026
45fed3d
patches: linux: Fix WED on the single-band MT7986 radio
mattiaswal Oct 8, 2026
ceae4a0
board: bpi-r3: Enable WED in mt7915e
mattiaswal Oct 2, 2026
3b78c8d
onieprom: Fix encoding JSON to a TLV
mattiaswal Oct 9, 2026
2a6d225
probe: Read the product VPD from a factory partition
mattiaswal Oct 9, 2026
a79eb3b
bpi-r3: Give ports a chassis-derived address at boot
mattiaswal Oct 9, 2026
1267d95
confd: wifi: Derive VIF addresses from the chassis MAC
mattiaswal Oct 9, 2026
c1a5448
hostapd: Push PMK-R1 to the R1KHs added by RELOAD_RXKHS
mattiaswal Oct 9, 2026
b79714f
confd: wifi: Push the 802.11r keys to the other nodes' access points
mattiaswal Oct 9, 2026
f81dfbe
bpi-r3: dts: Drop the ethernet aliases
mattiaswal Oct 10, 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