systemd-networkd switch

After a long time fiddling with trying to get a VLAN aware systemd-networkd switch to function using systemd-networkd I’ve finally been able to come up with a recipe that will configure it properly.

UPDATE: Now includes complete nix configuration.

Systemd files

switch

# switch.netdev
[NetDev]
Kind=bridge
Name=switch

[Bridge]
DefaultPVID=1
VLANFiltering=yes

# switch.network
[Match]
Name=switch

[Network]
VLAN=lan
VLAN=isolated
VLAN=iot
VLAN=mgmt

[BridgeVLAN]
VLAN=1
[BridgeVLAN]
VLAN=66
[BridgeVLAN]
VLAN=99
[BridgeVLAN]
VLAN=255

example vlan

# lan.netdev
[NetDev]
Kind=vlan
Name=lan

[VLAN]
Id=1

# lan.network
[Match]
Name=lan

[Network]
ConfigureWithoutCarrier=yes
MulticastDNS=yes
Address=172.16.1.1/24

physical switchports

# switchdevs.network
[Match]
Name=en*

[Network]
Bridge=switch

[BridgeVLAN]
PVID=1
VLAN=1
EgressUntagged=1
[BridgeVLAN]
VLAN=66
[BridgeVLAN]
VLAN=99
[BridgeVLAN]
VLAN=255

nix configuration

This is the complete configuration for a “home router” type box, written as nix config. It includes renaming the “WAN” interface to WAN so that it’s easier to separate out the switch part of the network interfaces.

{ pkgs, config, ... }:{
    config = {
        services.udev.extraRules = ''
        ATTR{address}=="<SNIP>", NAME="WAN"
        '';
        systemd.network = {
            links = {
                "WAN" = {
                    enable = true;
                    matchConfig = {
                        PermanentMACAddress="<SNIP>";
                    };
                    linkConfig = {
                        Name="WAN";
                        Description="WAN Interface";
                    };
                };
            };
            networks = {
                "WAN" = {
                    name="WAN";
                    enable = true;
                    matchConfig = { Name="WAN"; };
                    networkConfig = { DHCP="yes"; };
                    dhcpConfig = { RouteMetric="10"; };
                };
                "switch" = {
                    enable = true;
                    matchConfig = { Name="switch"; };
                    networkConfig = { VLAN = [ "lan" "isolated" "iot" "mgmt" ]; };
                    extraConfig = ''
                        [BridgeVLAN]
                        VLAN=1
                        [BridgeVLAN]
                        VLAN=66
                        [BridgeVLAN]
                        VLAN=99
                        [BridgeVLAN]
                        VLAN=255
                    '';
                };
                "switchdevs" = {
                    enable = true;
                    matchConfig = { Name="en*"; };
                    networkConfig = { Bridge = "switch"; };
                    extraConfig = ''
                        [BridgeVLAN]
                        PVID=1
                        VLAN=1
                        EgressUntagged=1
                        [BridgeVLAN]
                        VLAN=66
                        [BridgeVLAN]
                        VLAN=99
                        [BridgeVLAN]
                        VLAN=255
                    '';
                };
                "lan" = {
                    name="lan";
                    enable = true;
                    matchConfig = { Name="lan"; };
                    networkConfig = { ConfigureWithoutCarrier="yes"; MulticastDNS="yes"; };
                    address = [ "172.16.1.1/24" ];
                };
                "isolated" = {
                    name="isolated";
                    enable = true;
                    matchConfig = { Name="isolated"; };
                    networkConfig = { ConfigureWithoutCarrier="yes"; MulticastDNS="no"; };
                    address = [ "172.16.66.1/24" ];
                };
                "iot" = {
                    name="iot";
                    enable = true;
                    matchConfig = { Name="iot"; };
                    networkConfig = { ConfigureWithoutCarrier="yes"; MulticastDNS="no"; };
                    address = [ "172.16.99.1/24" ];
                };
                "mgmt" = {
                    name="mgmt";
                    enable = true;
                    matchConfig = { Name="mgmt"; };
                    networkConfig = { ConfigureWithoutCarrier="yes"; MulticastDNS="no"; };
                    address = [ "172.16.255.1/24" ];
                };
            };
            netdevs = {
                "lan" = {
                    enable = true;
                    netdevConfig = { Name = "lan"; Kind = "vlan"; };
                    vlanConfig = { Id = 1; };
                };
                "isolated" = {
                    enable = true;
                    netdevConfig = { Name = "guest"; Kind = "vlan"; };
                    vlanConfig = { Id = 66; };
                };
                "iot" = {
                    enable = true;
                    netdevConfig = { Name = "iot"; Kind = "vlan"; };
                    vlanConfig = { Id = 99; };
                };
                "mgmt" = {
                    enable = true;
                    netdevConfig = { Name = "mgmt"; Kind = "vlan"; };
                    vlanConfig = { Id = 255; };
                };
                "switch" = {
                    enable = true;
                    netdevConfig = {
                        Name="switch";
                        Kind="bridge";
                    };
                    extraConfig = ''
                        [Bridge]
                        DefaultPVID=1
                        VLANFiltering=yes
                    '';
                };
            };
        };
    };
}