at 18.09-beta 9.3 kB view raw
1{ config, lib, utils, ... }: 2 3with utils; 4with lib; 5 6let 7 8 cfg = config.networking; 9 interfaces = attrValues cfg.interfaces; 10 11 interfaceIps = i: 12 i.ipv4.addresses 13 ++ optionals cfg.enableIPv6 i.ipv6.addresses; 14 15 dhcpStr = useDHCP: if useDHCP == true || useDHCP == null then "both" else "none"; 16 17 slaves = 18 concatLists (map (bond: bond.interfaces) (attrValues cfg.bonds)) 19 ++ concatLists (map (bridge: bridge.interfaces) (attrValues cfg.bridges)) 20 ++ map (sit: sit.dev) (attrValues cfg.sits) 21 ++ map (vlan: vlan.interface) (attrValues cfg.vlans); 22 23in 24 25{ 26 27 config = mkIf cfg.useNetworkd { 28 29 assertions = [ { 30 assertion = cfg.defaultGatewayWindowSize == null; 31 message = "networking.defaultGatewayWindowSize is not supported by networkd."; 32 } { 33 assertion = cfg.vswitches == {}; 34 message = "networking.vswichtes are not supported by networkd."; 35 } { 36 assertion = cfg.defaultGateway == null || cfg.defaultGateway.interface == null; 37 message = "networking.defaultGateway.interface is not supported by networkd."; 38 } { 39 assertion = cfg.defaultGateway6 == null || cfg.defaultGateway6.interface == null; 40 message = "networking.defaultGateway6.interface is not supported by networkd."; 41 } ] ++ flip mapAttrsToList cfg.bridges (n: { rstp, ... }: { 42 assertion = !rstp; 43 message = "networking.bridges.${n}.rstp is not supported by networkd."; 44 }); 45 46 networking.dhcpcd.enable = mkDefault false; 47 48 systemd.services.network-local-commands = { 49 after = [ "systemd-networkd.service" ]; 50 bindsTo = [ "systemd-networkd.service" ]; 51 }; 52 53 systemd.network = 54 let 55 domains = cfg.search ++ (optional (cfg.domain != null) cfg.domain); 56 genericNetwork = override: 57 let gateway = optional (cfg.defaultGateway != null) cfg.defaultGateway.address 58 ++ optional (cfg.defaultGateway6 != null) cfg.defaultGateway6.address; 59 in { 60 DHCP = override (dhcpStr cfg.useDHCP); 61 } // optionalAttrs (gateway != [ ]) { 62 gateway = override gateway; 63 } // optionalAttrs (domains != [ ]) { 64 domains = override domains; 65 }; 66 in mkMerge [ { 67 enable = true; 68 networks."99-main" = genericNetwork mkDefault; 69 } 70 (mkMerge (flip map interfaces (i: { 71 netdevs = mkIf i.virtual ({ 72 "40-${i.name}" = { 73 netdevConfig = { 74 Name = i.name; 75 Kind = i.virtualType; 76 }; 77 "${i.virtualType}Config" = optionalAttrs (i.virtualOwner != null) { 78 User = i.virtualOwner; 79 }; 80 }; 81 }); 82 networks."40-${i.name}" = mkMerge [ (genericNetwork mkDefault) { 83 name = mkDefault i.name; 84 DHCP = mkForce (dhcpStr 85 (if i.useDHCP != null then i.useDHCP else cfg.useDHCP && interfaceIps i == [ ])); 86 address = flip map (interfaceIps i) 87 (ip: "${ip.address}/${toString ip.prefixLength}"); 88 networkConfig.IPv6PrivacyExtensions = "kernel"; 89 } ]; 90 }))) 91 (mkMerge (flip mapAttrsToList cfg.bridges (name: bridge: { 92 netdevs."40-${name}" = { 93 netdevConfig = { 94 Name = name; 95 Kind = "bridge"; 96 }; 97 }; 98 networks = listToAttrs (flip map bridge.interfaces (bi: 99 nameValuePair "40-${bi}" (mkMerge [ (genericNetwork (mkOverride 999)) { 100 DHCP = mkOverride 0 (dhcpStr false); 101 networkConfig.Bridge = name; 102 } ]))); 103 }))) 104 (mkMerge (flip mapAttrsToList cfg.bonds (name: bond: { 105 netdevs."40-${name}" = { 106 netdevConfig = { 107 Name = name; 108 Kind = "bond"; 109 }; 110 bondConfig = let 111 # manual mapping as of 2017-02-03 112 # man 5 systemd.netdev [BOND] 113 # to https://www.kernel.org/doc/Documentation/networking/bonding.txt 114 # driver options. 115 driverOptionMapping = let 116 trans = f: optName: { valTransform = f; optNames = [optName]; }; 117 simp = trans id; 118 ms = trans (v: v + "ms"); 119 in { 120 Mode = simp "mode"; 121 TransmitHashPolicy = simp "xmit_hash_policy"; 122 LACPTransmitRate = simp "lacp_rate"; 123 MIIMonitorSec = ms "miimon"; 124 UpDelaySec = ms "updelay"; 125 DownDelaySec = ms "downdelay"; 126 LearnPacketIntervalSec = simp "lp_interval"; 127 AdSelect = simp "ad_select"; 128 FailOverMACPolicy = simp "fail_over_mac"; 129 ARPValidate = simp "arp_validate"; 130 # apparently in ms for this value?! Upstream bug? 131 ARPIntervalSec = simp "arp_interval"; 132 ARPIPTargets = simp "arp_ip_target"; 133 ARPAllTargets = simp "arp_all_targets"; 134 PrimaryReselectPolicy = simp "primary_reselect"; 135 ResendIGMP = simp "resend_igmp"; 136 PacketsPerSlave = simp "packets_per_slave"; 137 GratuitousARP = { valTransform = id; 138 optNames = [ "num_grat_arp" "num_unsol_na" ]; }; 139 AllSlavesActive = simp "all_slaves_active"; 140 MinLinks = simp "min_links"; 141 }; 142 143 do = bond.driverOptions; 144 assertNoUnknownOption = let 145 knownOptions = flatten (mapAttrsToList (_: kOpts: kOpts.optNames) 146 driverOptionMapping); 147 # options that apparently don’t exist in the networkd config 148 unknownOptions = [ "primary" ]; 149 assertTrace = bool: msg: if bool then true else builtins.trace msg false; 150 in assert all (driverOpt: assertTrace 151 (elem driverOpt (knownOptions ++ unknownOptions)) 152 "The bond.driverOption `${driverOpt}` cannot be mapped to the list of known networkd bond options. Please add it to the mapping above the assert or to `unknownOptions` should it not exist in networkd.") 153 (mapAttrsToList (k: _: k) do); ""; 154 # get those driverOptions that have been set 155 filterSystemdOptions = filterAttrs (sysDOpt: kOpts: 156 any (kOpt: do ? "${kOpt}") kOpts.optNames); 157 # build final set of systemd options to bond values 158 buildOptionSet = mapAttrs (_: kOpts: with kOpts; 159 # we simply take the first set kernel bond option 160 # (one option has multiple names, which is silly) 161 head (map (optN: valTransform (do."${optN}")) 162 # only map those that exist 163 (filter (o: do ? "${o}") optNames))); 164 in seq assertNoUnknownOption 165 (buildOptionSet (filterSystemdOptions driverOptionMapping)); 166 167 }; 168 169 networks = listToAttrs (flip map bond.interfaces (bi: 170 nameValuePair "40-${bi}" (mkMerge [ (genericNetwork (mkOverride 999)) { 171 DHCP = mkOverride 0 (dhcpStr false); 172 networkConfig.Bond = name; 173 } ]))); 174 }))) 175 (mkMerge (flip mapAttrsToList cfg.macvlans (name: macvlan: { 176 netdevs."40-${name}" = { 177 netdevConfig = { 178 Name = name; 179 Kind = "macvlan"; 180 }; 181 macvlanConfig = optionalAttrs (macvlan.mode != null) { Mode = macvlan.mode; }; 182 }; 183 networks."40-${macvlan.interface}" = (mkMerge [ (genericNetwork (mkOverride 999)) { 184 macvlan = [ name ]; 185 } ]); 186 }))) 187 (mkMerge (flip mapAttrsToList cfg.sits (name: sit: { 188 netdevs."40-${name}" = { 189 netdevConfig = { 190 Name = name; 191 Kind = "sit"; 192 }; 193 tunnelConfig = 194 (optionalAttrs (sit.remote != null) { 195 Remote = sit.remote; 196 }) // (optionalAttrs (sit.local != null) { 197 Local = sit.local; 198 }) // (optionalAttrs (sit.ttl != null) { 199 TTL = sit.ttl; 200 }); 201 }; 202 networks = mkIf (sit.dev != null) { 203 "40-${sit.dev}" = (mkMerge [ (genericNetwork (mkOverride 999)) { 204 tunnel = [ name ]; 205 } ]); 206 }; 207 }))) 208 (mkMerge (flip mapAttrsToList cfg.vlans (name: vlan: { 209 netdevs."40-${name}" = { 210 netdevConfig = { 211 Name = name; 212 Kind = "vlan"; 213 }; 214 vlanConfig.Id = vlan.id; 215 }; 216 networks."40-${vlan.interface}" = (mkMerge [ (genericNetwork (mkOverride 999)) { 217 vlan = [ name ]; 218 } ]); 219 }))) 220 ]; 221 222 # We need to prefill the slaved devices with networking options 223 # This forces the network interface creator to initialize slaves. 224 networking.interfaces = listToAttrs (map (i: nameValuePair i { }) slaves); 225 226 }; 227 228}