vxlan over wireless: first try

This commit is contained in:
Astro 2022-01-18 01:05:16 +01:00
parent 5f675b13d2
commit 1327680612
6 changed files with 214 additions and 52 deletions

View File

@ -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 = {

13
config/net/roof.nix Normal file
View File

@ -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";
};
}

View File

@ -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";

View File

@ -252,6 +252,8 @@
serv.ports = [ "6-9" ];
# Starlink
up3.ports = [ "3" ];
# unifiac-mesh
ap57.ports = [ "5" ];
};
};
};

View File

@ -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 ];
}

View File

@ -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))}