diff --git a/config/ap.nix b/config/ap.nix index 1d76031..0f98ba3 100644 --- a/config/ap.nix +++ b/config/ap.nix @@ -1,3 +1,4 @@ +{ config, ... }: { site.hosts = { ap-test1 = { @@ -1722,8 +1723,90 @@ }; }; }; - ap57 = { }; - ap58 = { }; + ap57 = { + role = "ap"; + model = "unifiac-mesh"; + location = "Dach"; + interfaces = { + mgmt = { + gw4 = "mgmt-gw"; + gw6 = "mgmt-gw"; + type = "bridge"; + }; + pub.type = "bridge"; + roof.type = "phys"; + ap58 = { + type = "vxlan"; + vxlan.peer = config.site.net.roof.hosts6.dn42.ap58; + }; + priv43.type = "bridge"; + }; + wifi = { + "pci0000:00/0000:00:00.0" = { + channel = 100; + htmode = "VHT80"; + ssids = { + "Zentralwerk" = { + net = "roof"; + }; + }; + }; + "platform/ahb/18100000.wmac" = { + channel = 1; + htmode = "HT20"; + ssids = { + # wifi on the roof + "ZW public".net = "pub"; + }; + }; + }; + links = { + switch-dach.ports = [ "lan" ]; + ap58.ports = [ "ap58" ]; + }; + }; + ap58 = { + role = "ap"; + model = "unifiac-mesh"; + location = "Coswiger Str."; + interfaces = { + mgmt = { + gw4 = "mgmt-gw"; + gw6 = "mgmt-gw"; + type = "phys"; + }; + pub.type = "bridge"; + ap57 = { + type = "vxlan"; + vxlan.peer = config.site.net.roof.hosts6.dn42.ap57; + }; + priv43.type = "bridge"; + }; + wifi = { + "pci0000:00/0000:00:00.0" = { + channel = 100; + htmode = "VHT80"; + ssids = { + "Zentralwerk" = { + net = "roof"; + type = "sta"; + }; + }; + }; + "platform/ahb/18100000.wmac" = { + channel = 9; + htmode = "HT20"; + ssids = { + "ZW public".net = "pub"; + "LIZA".net = "priv43"; + }; + }; + }; + links = { + priv43.ports = [ "lan" ]; + ap57.ports = [ "ap57" ]; + }; + }; ap59 = { }; ap6 = { interfaces = { diff --git a/config/net/roof.nix b/config/net/roof.nix new file mode 100644 index 000000000..a65ed67 --- /dev/null +++ b/config/net/roof.nix @@ -0,0 +1,13 @@ +{ + site.net.roof = { + # not switched, only a wifi + vlan = null; + # leave space for vxlan + mtu = 2048; + hosts6.dn42 = { + ap57 = "fd23:42:c3d2:584::39"; + ap58 = "fd23:42:c3d2:584::40"; + }; + subnets6.dn42 = "fd23:42:c3d2:584::/64"; + }; +} diff --git a/config/secrets.nix b/config/secrets.nix index c318298..07103f0 100644 --- a/config/secrets.nix +++ b/config/secrets.nix @@ -57,6 +57,8 @@ ap54.password = "encrypted"; ap55.password = "encrypted"; ap56.password = "encrypted"; + ap57.password = "encrypted"; + ap58.password = "encrypted"; switch-a1.password = "encrypted"; switch-b1.password = "encrypted"; switch-b2.password = "encrypted"; @@ -234,6 +236,13 @@ "pci0000:00/0000:00:00.0".ssids."MagLAN".psk = "encrypted"; "platform/qca956x_wmac".ssids."MagLAN (legacy)".psk = "encrypted"; }; + ap57.wifi = { + "pci0000:00/0000:00:00.0".ssids."Zentralwerk".psk = "encrypted"; + }; + ap58.wifi = { + "pci0000:00/0000:00:00.0".ssids."Zentralwerk".psk = "encrypted"; + "platform/ahb/18100000.wmac".ssids."LIZA".psk = "encrypted"; + }; ap7.wifi."platform/qca953x_wmac".ssids."mino".psk = "encrypted"; ap8.wifi = { "pci0000:00/0000:00:00.0".ssids."C3D2".psk = "encrypted"; diff --git a/config/switch.nix b/config/switch.nix index bfdc2ae..a9db63b 100644 --- a/config/switch.nix +++ b/config/switch.nix @@ -252,6 +252,8 @@ serv.ports = [ "6-9" ]; # Starlink up3.ports = [ "3" ]; + # unifiac-mesh + ap57.ports = [ "5" ]; }; }; }; diff --git a/nix/lib/config/options.nix b/nix/lib/config/options.nix index 918be04..c9ad2fa 100644 --- a/nix/lib/config/options.nix +++ b/nix/lib/config/options.nix @@ -55,13 +55,13 @@ let links' = builtins.tail links; in if config.site.hosts ? ${link} - then networksBehindLink' seen' ( + then networksBehindLink' seen' (builtins.filter (link: ! seen' ? ${link}) ( links' ++ ( builtins.attrNames config.site.hosts.${link}.interfaces ) ++ ( onlyUnseen (builtins.attrNames config.site.hosts.${link}.links) ) - ) + )) else if config.site.net ? ${link} then networksBehindLink' seen' links' @@ -102,7 +102,7 @@ let options = { vlan = mkOption { description = "VLAN tag number"; - type = types.int; + type = with types; nullOr int; }; subnet4 = mkOption { description = "v.w.x.y/z"; @@ -185,6 +185,10 @@ let default = false; description = "Domain updated by DHCP server?"; }; + mtu = mkOption { + type = with types; nullOr int; + default = null; + }; }; }; @@ -228,7 +232,7 @@ let description = "Static MAC address"; }; type = mkOption { - type = types.enum [ "phys" "veth" "pppoe" "bridge" "wireguard" ]; + type = types.enum [ "phys" "veth" "pppoe" "bridge" "wireguard" "vxlan" ]; description = '' veth: Virtual ethernet to be attached to a bridge. @@ -271,6 +275,16 @@ let }; }); }; + vxlan = mkOption { + default = null; + type = with types; nullOr (submodule { + options = { + peer = mkOption { + type = str; + }; + }; + }); + }; }; }; @@ -438,6 +452,10 @@ let type = nullOr str; default = null; }; + type = mkOption { + type = enum [ "ap" "sta" ]; + default = "ap"; + }; }; } )); @@ -484,8 +502,12 @@ let vlans = mkOption { type = with types; listOf int; description = "Automatically generated, do not set"; - default = map (net: - config.site.net.${net}.vlan + default = builtins.concatMap (net: + let + inherit (config.site.net.${net}) vlan; + in if vlan != null + then [ vlan ] + else [] ) config.site.hosts.${hostName}.links.${name}.nets; }; trunk = mkOption { @@ -614,7 +636,7 @@ in let vlan = toString config.site.net.${net}.vlan; in - if result ? ${vlan} + if config.site.net.${net}.vlan != null && result ? ${vlan} then result // { "${vlan}" = result.${vlan} ++ [ net ]; } diff --git a/nix/pkgs/ap.nix b/nix/pkgs/ap.nix index e1e072c..b5ff070 100644 --- a/nix/pkgs/ap.nix +++ b/nix/pkgs/ap.nix @@ -20,8 +20,12 @@ let openwrtModel = self.lib.getOpenwrtModel hostConfig.model; hasSwitch = - any ({ switch ? null, ... }: switch != null) - (builtins.attrValues openwrtModel.ports); + if hostConfig.model == "unifiac-mesh" + # ours don't come with a switch. + then false + else + any ({ switch ? null, ... }: switch != null) + (builtins.attrValues openwrtModel.ports); portsDoc = let @@ -104,39 +108,35 @@ let networkInterfaces = net: let inherit (config.site.net.${net}) vlan; - - ifaces = - unique ( - builtins.concatMap ({ trunk, ports, switch ? null, ... }: - builtins.concatMap (port: - builtins.concatMap (portData: - if portData ? port && port == portData.port - then [ (( - if portData ? switch - then switchHostInterface - else if portData ? interface - then portData.interface - else throw "Cannot find interface for ${port} on OpenWRT model ${hostConfig.model}" - ) + ( - if trunk || switch != null - then ".${toString vlan}" - else "" - )) ] - else [] - ) (builtins.attrValues openwrtModel.ports) - ) ports - ) ( - builtins.attrValues ( - filterAttrs (link: { nets, ... }: - link == net || builtins.elem net nets - ) hostConfig.links - ) - ) - ); - in - if ifaces == [] - then throw "No interfaces found for ${net} on ${hostName}" - else ifaces; + in unique ( + builtins.concatMap ({ trunk, ports, switch ? null, ... }: + builtins.concatMap (port: + builtins.concatMap (portData: + if portData ? port && port == portData.port + then [ (( + if portData ? switch + then switchHostInterface + else if portData ? interface + then portData.interface + else throw "Cannot find interface for ${port} on OpenWRT model ${hostConfig.model}" + ) + ( + if trunk || switch != null + then ".${toString vlan}" + else "" + )) ] + else [] + ) (builtins.attrValues openwrtModel.ports) + ++ + lib.optionals (hostConfig.interfaces ? ${port}) [ "${port}.${toString vlan}" ] + ) ports + ) ( + builtins.attrValues ( + filterAttrs (link: { nets, ... }: + link == net || builtins.elem net nets + ) hostConfig.links + ) + ) + ); in '' #! ${pkgs.runtimeShell} -e @@ -193,12 +193,14 @@ in '' # mgmt network uci set network.mgmt=interface - uci set network.mgmt.ifname=${if builtins.length (networkInterfaces "mgmt") == 1 then builtins.head (networkInterfaces "mgmt") else throw "No interface for mgmt"} + uci set network.mgmt.ifname=${ + if builtins.length (networkInterfaces "mgmt") > 0 + then lib.concatStringsSep " " (networkInterfaces "mgmt") + else throw "No interface for mgmt" + } uci set network.mgmt.proto=static uci set network.mgmt.ipaddr=${config.site.net.mgmt.hosts4.${hostName}} - uci set network.mgmt.netmask=${self.lib.netmasks.${elemAt ( - builtins.split "/" config.site.net.mgmt.subnet4 - ) 2}} + uci set network.mgmt.netmask=${self.lib.netmasks.${toString config.site.net.mgmt.subnet4Len}} uci set network.mgmt.gateway=${config.site.net.mgmt.hosts4.mgmt-gw} uci set network.mgmt.ip6addr=${config.site.net.mgmt.hosts6.dn42.${hostName}}/64 uci set network.mgmt.ip6gw=${config.site.net.mgmt.hosts6.dn42.mgmt-gw} @@ -214,15 +216,47 @@ in '' '' ) ([ "lan" "wan" "wan6" ] ++ builtins.attrNames config.site.net)} - # bridged networks + # bridged and static networks ${concatMapStrings (net: let iface = hostConfig.interfaces.${net}; - in optionalString (net != "mgmt" && iface.type == "bridge") '' + in optionalString (net != "mgmt" && builtins.elem iface.type ["bridge" "phys"]) '' uci set network.${net}=interface - uci set network.${net}.type=bridge + ${lib.optionalString (iface.type == "bridge") '' + uci set network.${net}.type=bridge + ''} uci set network.${net}.proto=static uci set network.${net}.ifname='${concatStringsSep " " (networkInterfaces net)}' + ${lib.optionalString (config.site.net.${net}.mtu != null) '' + uci set network.${net}.mtu=${toString config.site.net.${net}.mtu} + ''} + + + ${lib.optionalString (config.site.net.${net}.hosts4 ? ${hostName}) '' + # address in net + uci set network.${net}.ipaddr=${config.site.net.${net}.hosts4.${hostName}} + uci set network.${net}.netmask=${self.lib.netmasks.${toString config.site.net.${net}.subnet4Len}} + ''} + ${lib.concatMapStrings (ctx: lib.optionalString (ctx ? ${hostName}) '' + uci set network.mgmt.ip6addr=${config.site.net.${net}.hosts6.${ctx}.${hostName}}/64 + '') (builtins.attrNames config.site.net.${net}.hosts6)} + '') (builtins.attrNames hostConfig.interfaces) + } + + # vxlan trunks + ${concatMapStrings (name: + let + iface = hostConfig.interfaces.${name}; + in optionalString (iface.type == "vxlan") '' + uci set network.${name}=interface + uci set network.${name}.proto=vxlan + uci set network.${name}.tunlink='${name}' + uci set network.${name}.peeraddr='${iface.vxlan.peer}' + uci set network.${name}.port=4789 + uci set network.${name}.mtu=1600 + uci set network.${name}.rxcsum=0 + uci set network.${name}.txcsum=0 + uci set network.${name}.delegate=0 '') (builtins.attrNames hostConfig.interfaces) } @@ -265,7 +299,6 @@ in '' uci set wireless.@wifi-iface[-1].encryption=none uci -q delete wireless.@wifi-iface[-1].key || true ''} - '' ) (builtins.attrNames radioConfig.ssids)} '') (builtins.attrNames hostConfig.wifi))}