diff --git a/modules/clan/router/wifi.nix b/modules/clan/router/wifi.nix index 8b21768..fe8e2cf 100644 --- a/modules/clan/router/wifi.nix +++ b/modules/clan/router/wifi.nix @@ -12,7 +12,6 @@ { config, lib, - pkgs, ... }: let @@ -126,21 +125,6 @@ in # Regulatory database for the kernel, so countryCode actually applies. hardware.wirelessRegulatoryDatabase = true; - # The kernel refuses to bridge a wireless interface in station mode, and - # networkd stops retrying before hostapd switches the radio to AP mode; - # so put it in AP mode the moment it appears (kernel name or the renamed - # one, whichever the user configured). hostapd finds it already there. - services.udev.extraRules = lib.concatMapStrings ( - radio: - let - run = ''RUN+="${pkgs.iw}/bin/iw dev ${radio} set type __ap"''; - in - '' - ACTION=="add", SUBSYSTEM=="net", KERNEL=="${radio}", ${run} - ACTION=="add", SUBSYSTEM=="net", NAME=="${radio}", ${run} - '' - ) (lib.attrNames wifi.radios); - clan.core.vars.generators = lib.genAttrs (map (name: "wifi-${name}-passphrase") secured) ( gen: let @@ -184,12 +168,22 @@ in }; # Each BSS is an untagged access port of its VLAN on br0 (cf. accessPorts - # in network.nix); networkd enslaves the interface once hostapd creates it. + # in network.nix). The kernel refuses to bridge a wireless interface in + # station mode (IFF_DONT_BRIDGE), and a failed enslave parks the link in + # networkd's `failed` state for good: networkd only re-evaluates a link + # when its matching .network file changes. So match on the AP interface + # type as well as the name: the radio's initial station-mode netdev + # matches nothing (unmanaged), and once hostapd switches it to AP and + # brings the carrier up, networkd matches this file for the first time + # and enslaves it. Extra BSSes are created by hostapd in AP mode already. systemd.network.networks = lib.listToAttrs ( map ( b: lib.nameValuePair "27-wifi-${b.iface}" { - matchConfig.Name = b.iface; + matchConfig = { + Name = b.iface; + WLANInterfaceType = "ap"; + }; networkConfig.Bridge = "br0"; bridgeVLANs = [ {