{ zentralwerk, config, lib, ... }: let inherit (config.networking) hostName; zwNets = zentralwerk.lib.config.site.net; zwHostConfig = zentralwerk.lib.config.site.hosts.${hostName}; zwHostBridges = builtins.attrNames ( lib.filterAttrs (_: { type, ... }: type == "bridge") zwHostConfig.interfaces ); in { options = with lib; { c3d2.server.bridgePorts = mkOption { description = "Additional interfaces to attach to bridges"; type = with types; attrsOf (listOf str); default = {}; }; }; config = { networking = { useDHCP = false; useNetworkd = true; }; boot.kernelParams = [ # Prevents automatic creation of interface bond0 by the kernel "bonding.max_bonds=0" ]; systemd.network = { enable = true; netdevs = { bond0.netdevConfig = { Kind = "bond"; Name = "bond0"; }; # LACP bond0.bondConfig.Mode = "802.3ad"; } // ( builtins.foldl' (result: net: result // { # Bridges are named just like the corresponding net. "${net}" = { netdevConfig = { Kind = "bridge"; Name = "${net}"; }; extraConfig = '' [Bridge] ForwardDelaySec=2 STP=true ''; }; # External VLAN interface "ext-${net}" = { netdevConfig = { Kind = "vlan"; Name = "ext-${net}"; }; vlanConfig.Id = zwNets.${net}.vlan; }; }) {} zwHostBridges ); networks = { en = { # physical ethernet ports matchConfig.Name = "en*"; networkConfig = { Bond = "bond0"; LLDP = true; EmitLLDP = true; }; }; bond0 = { DHCP = "no"; matchConfig.Name = "bond0"; networkConfig = { VLAN = map (net: "ext-${net}") zwHostBridges; LinkLocalAddressing = "no"; LLDP = true; EmitLLDP = true; }; }; } // (builtins.foldl' (result: net: result // { "${net}" = { matchConfig.Name = net; networkConfig = { LLDP = true; EmitLLDP = true; DHCP = "no"; IPv6AcceptRA = "no"; } // (lib.optionalAttrs (! zwNets.${net}.hosts4 ? ${hostName})) { # Disable all automatic addressing on bridges. It will delay # networkd going into operational state. LinkLocalAddressing = lib.mkDefault "no"; }; addresses = let netConfig = zwNets.${net}; address = netConfig.hosts4.${hostName}; prefixLen = netConfig.subnet4Len; in lib.optional (netConfig.hosts4 ? ${hostName}) { addressConfig.Address = "${address}/${toString prefixLen}"; } ++ builtins.concatMap (hosts6: lib.optional (hosts6 ? ${hostName}) { addressConfig.Address = "${hosts6.${hostName}}/64"; } ) (builtins.attrValues netConfig.hosts6); gateway = lib.optionals (net == "cluster") [ zwNets.cluster.hosts4.cls-gw zwNets.cluster.hosts6.dn42.cls-gw ]; }; "ext-${net}" = { matchConfig.Name = "ext-${net}"; # Attach eth*/bond0/VLAN to bridge networkConfig.Bridge = net; }; "ports-${net}" = { matchConfig.Name = "${net}-*"; networkConfig.Bridge = net; }; }) {} zwHostBridges); }; }; }