Merge pull request #27688 from rnhmjoj/routes

nixos/networking-interfaces: make static routes configurable

authored by Michael Raskin and committed by GitHub 10b3f7d3 e37b756b

+339 -191
+1 -1
nixos/doc/manual/configuration/ipv4-config.xml
··· 12 12 follows: 13 13 14 14 <programlisting> 15 - networking.interfaces.eth0.ip4 = [ { address = "192.168.1.2"; prefixLength = 24; } ]; 15 + networking.interfaces.eth0.ipv4.addresses = [ { address = "192.168.1.2"; prefixLength = 24; } ]; 16 16 </programlisting> 17 17 18 18 Typically you’ll also want to set a default gateway and set of name
+1 -1
nixos/doc/manual/configuration/ipv6-config.xml
··· 26 26 DHCPv6. You can configure an interface manually: 27 27 28 28 <programlisting> 29 - networking.interfaces.eth0.ip6 = [ { address = "fe00:aa:bb:cc::2"; prefixLength = 64; } ]; 29 + networking.interfaces.eth0.ipv6.addresses = [ { address = "fe00:aa:bb:cc::2"; prefixLength = 64; } ]; 30 30 </programlisting> 31 31 </para> 32 32
+36 -4
nixos/doc/manual/release-notes/rl-1803.xml
··· 261 261 </listitem> 262 262 <listitem> 263 263 <para> 264 - The option <option>services.xserver.desktopManager.default</option> is now <literal>none</literal> by default. 265 - An assertion failure is thrown if WM's and DM's default are <literal>none</literal>. 266 - To explicitly run a plain X session without and DM or WM, the newly introduced option <option>services.xserver.plainX</option> 267 - must be set to true. 264 + In the module <option>networking.interfaces.&lt;name&gt;</option> the 265 + following options have been removed: 266 + <itemizedlist> 267 + <listitem> 268 + <para><option>ipAddress</option></para> 269 + </listitem> 270 + <listitem> 271 + <para><option>ipv6Address</option></para> 272 + </listitem> 273 + <listitem> 274 + <para><option>prefixLength</option></para> 275 + </listitem> 276 + <listitem> 277 + <para><option>ipv6PrefixLength</option></para> 278 + </listitem> 279 + <listitem> 280 + <para><option>subnetMask</option></para> 281 + </listitem> 282 + </itemizedlist> 283 + To assign static addresses to an interface the options 284 + <option>ipv4.addresses</option> and <option>ipv6.addresses</option> 285 + should be used instead. 286 + The options <option>ip4</option> and <option>ip6</option> have been 287 + renamed to <option>ipv4.addresses</option> <option>ipv6.addresses</option> 288 + respectively. 289 + The new options <option>ipv4.routes</option> and <option>ipv6.routes</option> 290 + have been added to set up static routing. 291 + </para> 292 + </listitem> 293 + <listitem> 294 + <para> 295 + The option <option>services.xserver.desktopManager.default</option> is now 296 + <literal>none</literal> by default. An assertion failure is thrown if WM's 297 + and DM's default are <literal>none</literal>. 298 + To explicitly run a plain X session without and DM or WM, the newly 299 + introduced option <option>services.xserver.plainX</option> must be set to true. 268 300 </para> 269 301 </listitem> 270 302 <listitem>
+2 -2
nixos/lib/build-vms.nix
··· 51 51 let 52 52 interfacesNumbered = zipLists config.virtualisation.vlans (range 1 255); 53 53 interfaces = flip map interfacesNumbered ({ fst, snd }: 54 - nameValuePair "eth${toString snd}" { ip4 = 54 + nameValuePair "eth${toString snd}" { ipv4.addresses = 55 55 [ { address = "192.168.${toString fst}.${toString m.snd}"; 56 56 prefixLength = 24; 57 57 } ]; ··· 64 64 networking.interfaces = listToAttrs interfaces; 65 65 66 66 networking.primaryIPAddress = 67 - optionalString (interfaces != []) (head (head interfaces).value.ip4).address; 67 + optionalString (interfaces != []) (head (head interfaces).value.ipv4.addresses).address; 68 68 69 69 # Put the IP addresses of all VMs in this machine's 70 70 # /etc/hosts file. If a machine has multiple
+1 -1
nixos/modules/services/networking/dhcpcd.nix
··· 16 16 # Don't start dhcpcd on explicitly configured interfaces or on 17 17 # interfaces that are part of a bridge, bond or sit device. 18 18 ignoredInterfaces = 19 - map (i: i.name) (filter (i: if i.useDHCP != null then !i.useDHCP else i.ip4 != [ ] || i.ipAddress != null) interfaces) 19 + map (i: i.name) (filter (i: if i.useDHCP != null then !i.useDHCP else i.ipv4.addresses != [ ]) interfaces) 20 20 ++ mapAttrsToList (i: _: i) config.networking.sits 21 21 ++ concatLists (attrValues (mapAttrs (n: v: v.interfaces) config.networking.bridges)) 22 22 ++ concatLists (attrValues (mapAttrs (n: v: v.interfaces) config.networking.vswitches))
+3 -4
nixos/modules/services/security/hologram-agent.nix
··· 35 35 config = mkIf cfg.enable { 36 36 boot.kernelModules = [ "dummy" ]; 37 37 38 - networking.interfaces.dummy0 = { 39 - ipAddress = "169.254.169.254"; 40 - prefixLength = 32; 41 - }; 38 + networking.interfaces.dummy0.ipv4.addresses = [ 39 + { address = "169.254.169.254"; prefixLength = 32; } 40 + ]; 42 41 43 42 systemd.services.hologram-agent = { 44 43 description = "Provide EC2 instance credentials to machines outside of EC2";
+48 -29
nixos/modules/tasks/network-interfaces-scripted.nix
··· 20 20 "sys-subsystem-net-devices-${escapeSystemdPath interface}.device"; 21 21 22 22 interfaceIps = i: 23 - i.ip4 ++ optionals cfg.enableIPv6 i.ip6 24 - ++ optional (i.ipAddress != null) { 25 - address = i.ipAddress; 26 - prefixLength = i.prefixLength; 27 - } ++ optional (cfg.enableIPv6 && i.ipv6Address != null) { 28 - address = i.ipv6Address; 29 - prefixLength = i.ipv6PrefixLength; 30 - }; 23 + i.ipv4.addresses 24 + ++ optionals cfg.enableIPv6 i.ipv6.addresses; 31 25 32 26 destroyBond = i: '' 33 27 while true; do ··· 185 179 path = [ pkgs.iproute ]; 186 180 script = 187 181 '' 188 - # FIXME: shouldn't this be done in network-link? 189 - echo "bringing up interface..." 190 - ip link set "${i.name}" up 191 - 192 182 state="/run/nixos/network/addresses/${i.name}" 183 + mkdir -p $(dirname "$state") 193 184 185 + ${flip concatMapStrings ips (ip: 186 + let 187 + cidr = "${ip.address}/${toString ip.prefixLength}"; 188 + in 189 + '' 190 + echo "${cidr}" >> $state 191 + echo -n "adding address ${cidr}... " 192 + if out=$(ip addr add "${cidr}" dev "${i.name}" 2>&1); then 193 + echo "done" 194 + elif ! echo "$out" | grep "File exists" >/dev/null 2>&1; then 195 + echo "failed" 196 + exit 1 197 + fi 198 + '' 199 + )} 200 + 201 + state="/run/nixos/network/routes/${i.name}" 194 202 mkdir -p $(dirname "$state") 195 203 196 - '' + flip concatMapStrings (ips) (ip: 197 - let 198 - address = "${ip.address}/${toString ip.prefixLength}"; 199 - in 200 - '' 201 - echo "${address}" >> $state 202 - if out=$(ip addr add "${address}" dev "${i.name}" 2>&1); then 203 - echo "added ip ${address}" 204 - elif ! echo "$out" | grep "File exists" >/dev/null 2>&1; then 205 - echo "failed to add ${address}" 206 - exit 1 207 - fi 208 - ''); 204 + ${flip concatMapStrings (i.ipv4.routes ++ i.ipv6.routes) (route: 205 + let 206 + cidr = "${route.address}/${toString route.prefixLength}"; 207 + via = optionalString (route.via != null) ''via "${route.via}"''; 208 + options = concatStrings (mapAttrsToList (name: val: "${name} ${val} ") route.options); 209 + in 210 + '' 211 + echo "${cidr}" >> $state 212 + echo -n "adding route ${cidr}... " 213 + if out=$(ip route add "${cidr}" ${options} ${via} dev "${i.name}" 2>&1); then 214 + echo "done" 215 + elif ! echo "$out" | grep "File exists" >/dev/null 2>&1; then 216 + echo "failed" 217 + exit 1 218 + fi 219 + '' 220 + )} 221 + ''; 209 222 preStop = '' 223 + state="/run/nixos/network/routes/${i.name}" 224 + while read cidr; do 225 + echo -n "deleting route $cidr... " 226 + ip route del "$cidr" dev "${i.name}" >/dev/null 2>&1 && echo "done" || echo "failed" 227 + done < "$state" 228 + rm -f "$state" 229 + 210 230 state="/run/nixos/network/addresses/${i.name}" 211 - while read address; do 212 - echo -n "deleting $address..." 213 - ip addr del "$address" dev "${i.name}" >/dev/null 2>&1 || echo -n " Failed" 214 - echo "" 231 + while read cidr; do 232 + echo -n "deleting address $cidr... " 233 + ip addr del "$cidr" dev "${i.name}" >/dev/null 2>&1 && echo "done" || echo "failed" 215 234 done < "$state" 216 235 rm -f "$state" 217 236 '';
+2 -8
nixos/modules/tasks/network-interfaces-systemd.nix
··· 9 9 interfaces = attrValues cfg.interfaces; 10 10 11 11 interfaceIps = i: 12 - i.ip4 ++ optionals cfg.enableIPv6 i.ip6 13 - ++ optional (i.ipAddress != null) { 14 - address = i.ipAddress; 15 - prefixLength = i.prefixLength; 16 - } ++ optional (cfg.enableIPv6 && i.ipv6Address != null) { 17 - address = i.ipv6Address; 18 - prefixLength = i.ipv6PrefixLength; 19 - }; 12 + i.ipv4.addresses 13 + ++ optionals cfg.enableIPv6 i.ipv6.addresses; 20 14 21 15 dhcpStr = useDHCP: if useDHCP == true || useDHCP == null then "both" else "none"; 22 16
+87 -51
nixos/modules/tasks/network-interfaces.nix
··· 1 - { config, lib, pkgs, utils, stdenv, ... }: 1 + { config, options, lib, pkgs, utils, stdenv, ... }: 2 2 3 3 with lib; 4 4 with utils; ··· 101 101 address = mkOption { 102 102 type = types.str; 103 103 description = '' 104 - IPv${toString v} address of the interface. Leave empty to configure the 104 + IPv${toString v} address of the interface. Leave empty to configure the 105 105 interface using DHCP. 106 106 ''; 107 107 }; ··· 116 116 }; 117 117 }; 118 118 119 + routeOpts = v: 120 + { options = { 121 + address = mkOption { 122 + type = types.str; 123 + description = "IPv${toString v} address of the network."; 124 + }; 125 + 126 + prefixLength = mkOption { 127 + type = types.addCheck types.int (n: n >= 0 && n <= (if v == 4 then 32 else 128)); 128 + description = '' 129 + Subnet mask of the network, specified as the number of 130 + bits in the prefix (<literal>${if v == 4 then "24" else "64"}</literal>). 131 + ''; 132 + }; 133 + 134 + via = mkOption { 135 + type = types.nullOr types.str; 136 + default = null; 137 + description = "IPv${toString v} address of the next hop."; 138 + }; 139 + 140 + options = mkOption { 141 + type = types.attrsOf types.str; 142 + default = { }; 143 + example = { mtu = "1492"; window = "524288"; }; 144 + description = '' 145 + Other route options. See the symbol <literal>OPTION</literal> 146 + in the <literal>ip-route(8)</literal> manual page for the details. 147 + ''; 148 + }; 149 + 150 + }; 151 + }; 152 + 119 153 gatewayCoerce = address: { inherit address; }; 120 154 121 155 gatewayOpts = { ... }: { ··· 148 182 interfaceOpts = { name, ... }: { 149 183 150 184 options = { 151 - 152 185 name = mkOption { 153 186 example = "eth0"; 154 187 type = types.str; ··· 175 208 ''; 176 209 }; 177 210 178 - ip4 = mkOption { 211 + ipv4.addresses = mkOption { 179 212 default = [ ]; 180 213 example = [ 181 214 { address = "10.0.0.1"; prefixLength = 16; } ··· 187 220 ''; 188 221 }; 189 222 190 - ip6 = mkOption { 223 + ipv6.addresses = mkOption { 191 224 default = [ ]; 192 225 example = [ 193 226 { address = "fdfd:b3f0:482::1"; prefixLength = 48; } ··· 199 232 ''; 200 233 }; 201 234 202 - ipAddress = mkOption { 203 - default = null; 204 - example = "10.0.0.1"; 205 - type = types.nullOr types.str; 206 - description = '' 207 - IP address of the interface. Leave empty to configure the 208 - interface using DHCP. 209 - ''; 210 - }; 211 - 212 - prefixLength = mkOption { 213 - default = null; 214 - example = 24; 215 - type = types.nullOr types.int; 216 - description = '' 217 - Subnet mask of the interface, specified as the number of 218 - bits in the prefix (<literal>24</literal>). 219 - ''; 220 - }; 221 - 222 - subnetMask = mkOption { 223 - default = null; 224 - description = '' 225 - Defunct, supply the prefix length instead. 226 - ''; 227 - }; 228 - 229 - ipv6Address = mkOption { 230 - default = null; 231 - example = "2001:1470:fffd:2098::e006"; 232 - type = types.nullOr types.str; 235 + ipv4.routes = mkOption { 236 + default = []; 237 + example = [ 238 + { address = "10.0.0.0"; prefixLength = 16; } 239 + { address = "192.168.2.0"; prefixLength = 24; via = "192.168.1.1"; } 240 + ]; 241 + type = with types; listOf (submodule (routeOpts 4)); 233 242 description = '' 234 - IPv6 address of the interface. Leave empty to configure the 235 - interface using NDP. 243 + List of extra IPv4 static routes that will be assigned to the interface. 236 244 ''; 237 245 }; 238 246 239 - ipv6PrefixLength = mkOption { 240 - default = 64; 241 - example = 64; 242 - type = types.int; 247 + ipv6.routes = mkOption { 248 + default = []; 249 + example = [ 250 + { address = "fdfd:b3f0::"; prefixLength = 48; } 251 + { address = "2001:1470:fffd:2098::"; prefixLength = 64; via = "fdfd:b3f0::1"; } 252 + ]; 253 + type = with types; listOf (submodule (routeOpts 6)); 243 254 description = '' 244 - Subnet mask of the interface, specified as the number of 245 - bits in the prefix (<literal>64</literal>). 255 + List of extra IPv6 static routes that will be assigned to the interface. 246 256 ''; 247 257 }; 248 258 ··· 316 326 config = { 317 327 name = mkDefault name; 318 328 }; 329 + 330 + # Renamed or removed options 331 + imports = 332 + let 333 + defined = x: x != "_mkMergedOptionModule"; 334 + in [ 335 + (mkRenamedOptionModule [ "ip4" ] [ "ipv4" "addresses"]) 336 + (mkRenamedOptionModule [ "ip6" ] [ "ipv6" "addresses"]) 337 + (mkRemovedOptionModule [ "subnetMask" ] '' 338 + Supply a prefix length instead; use option 339 + networking.interfaces.<name>.ipv{4,6}.addresses'') 340 + (mkMergedOptionModule 341 + [ [ "ipAddress" ] [ "prefixLength" ] ] 342 + [ "ipv4" "addresses" ] 343 + (cfg: with cfg; 344 + optional (defined ipAddress && defined prefixLength) 345 + { address = ipAddress; prefixLength = prefixLength; })) 346 + (mkMergedOptionModule 347 + [ [ "ipv6Address" ] [ "ipv6PrefixLength" ] ] 348 + [ "ipv6" "addresses" ] 349 + (cfg: with cfg; 350 + optional (defined ipv6Address && defined ipv6PrefixLength) 351 + { address = ipv6Address; prefixLength = ipv6PrefixLength; })) 352 + 353 + ({ options.warnings = options.warnings; }) 354 + ]; 319 355 320 356 }; 321 357 ··· 453 489 networking.interfaces = mkOption { 454 490 default = {}; 455 491 example = 456 - { eth0.ip4 = [ { 492 + { eth0.ipv4 = [ { 457 493 address = "131.211.84.78"; 458 494 prefixLength = 25; 459 495 } ]; ··· 932 968 933 969 config = { 934 970 971 + warnings = concatMap (i: i.warnings) interfaces; 972 + 935 973 assertions = 936 974 (flip map interfaces (i: { 937 - assertion = i.subnetMask == null; 938 - message = '' 939 - The networking.interfaces."${i.name}".subnetMask option is defunct. Use prefixLength instead. 940 - ''; 941 - })) ++ (flip map interfaces (i: { 942 975 # With the linux kernel, interface name length is limited by IFNAMSIZ 943 976 # to 16 bytes, including the trailing null byte. 944 977 # See include/linux/if.h in the kernel sources ··· 947 980 The name of networking.interfaces."${i.name}" is too long, it needs to be less than 16 characters. 948 981 ''; 949 982 })) ++ (flip map slaveIfs (i: { 950 - assertion = i.ip4 == [ ] && i.ipAddress == null && i.ip6 == [ ] && i.ipv6Address == null; 983 + assertion = i.ipv4.addresses == [ ] && i.ipv6.addresses == [ ]; 951 984 message = '' 952 985 The networking.interfaces."${i.name}" must not have any defined ips when it is a slave. 953 986 ''; ··· 1089 1122 '' + optionalString (i.mtu != null) '' 1090 1123 echo "setting MTU to ${toString i.mtu}..." 1091 1124 ip link set "${i.name}" mtu "${toString i.mtu}" 1125 + '' + '' 1126 + echo -n "bringing up interface... " 1127 + ip link set "${i.name}" up && echo "done" || (echo "failed"; exit 1) 1092 1128 ''; 1093 1129 }))); 1094 1130
+1 -1
nixos/modules/virtualisation/virtualbox-host.nix
··· 124 124 ''; 125 125 }; 126 126 127 - networking.interfaces.vboxnet0.ip4 = [ { address = "192.168.56.1"; prefixLength = 24; } ]; 127 + networking.interfaces.vboxnet0.ipv4.addresses = { address = "192.168.56.1"; prefixLength = 24; }; 128 128 # Make sure NetworkManager won't assume this interface being up 129 129 # means we have internet access. 130 130 networking.networkmanager.unmanaged = ["vboxnet0"];
+3 -3
nixos/tests/bittorrent.nix
··· 16 16 miniupnpdConf = nodes: pkgs.writeText "miniupnpd.conf" 17 17 '' 18 18 ext_ifname=eth1 19 - listening_ip=${(pkgs.lib.head nodes.router.config.networking.interfaces.eth2.ip4).address}/24 19 + listening_ip=${(pkgs.lib.head nodes.router.config.networking.interfaces.eth2.ipv4.addresses).address}/24 20 20 allow 1024-65535 192.168.2.0/24 1024-65535 21 21 ''; 22 22 ··· 56 56 { environment.systemPackages = [ pkgs.transmission ]; 57 57 virtualisation.vlans = [ 2 ]; 58 58 networking.defaultGateway = 59 - (pkgs.lib.head nodes.router.config.networking.interfaces.eth2.ip4).address; 59 + (pkgs.lib.head nodes.router.config.networking.interfaces.eth2.ipv4.addresses).address; 60 60 networking.firewall.enable = false; 61 61 }; 62 62 ··· 84 84 # Create the torrent. 85 85 $tracker->succeed("mkdir /tmp/data"); 86 86 $tracker->succeed("cp ${file} /tmp/data/test.tar.bz2"); 87 - $tracker->succeed("transmission-create /tmp/data/test.tar.bz2 -p -t http://${(pkgs.lib.head nodes.tracker.config.networking.interfaces.eth1.ip4).address}:6969/announce -o /tmp/test.torrent"); 87 + $tracker->succeed("transmission-create /tmp/data/test.tar.bz2 -p -t http://${(pkgs.lib.head nodes.tracker.config.networking.interfaces.eth1.ipv4.addresses).address}:6969/announce -o /tmp/test.torrent"); 88 88 $tracker->succeed("chmod 644 /tmp/test.torrent"); 89 89 90 90 # Start the tracker. !!! use a less crappy tracker
+6 -3
nixos/tests/cjdns.nix
··· 12 12 # the sequence of address assignment less stochastic. 13 13 networking.useDHCP = false; 14 14 15 - networking.interfaces.eth1.prefixLength = 24; 16 15 # CJDNS output is incompatible with the XML log. 17 16 systemd.services.cjdns.serviceConfig.StandardOutput = "null"; 18 17 #networking.firewall.enable = true; ··· 49 48 50 49 { imports = [ basicConfig ]; 51 50 52 - networking.interfaces.eth1.ipAddress = "192.168.0.2"; 51 + networking.interfaces.eth1.ipv4.addresses = [ 52 + { address = "192.168.0.2"; prefixLength = 24; } 53 + ]; 53 54 54 55 services.cjdns = 55 56 { UDPInterface = ··· 76 77 CJDNS_ADMIN_PASSWORD=FOOBAR 77 78 ''; 78 79 79 - networking.interfaces.eth1.ipAddress = "192.168.0.1"; 80 + networking.interfaces.eth1.ipv4.addresses = [ 81 + { address = "192.168.0.1"; prefixLength = 24; } 82 + ]; 80 83 81 84 services.cjdns = 82 85 { authorizedPasswords = [ carolPassword ];
+2 -2
nixos/tests/containers-bridge.nix
··· 26 26 }; 27 27 networking.interfaces = { 28 28 br0 = { 29 - ip4 = [{ address = hostIp; prefixLength = 24; }]; 30 - ip6 = [{ address = hostIp6; prefixLength = 7; }]; 29 + ipv4.addresses = [{ address = hostIp; prefixLength = 24; }]; 30 + ipv6.addresses = [{ address = hostIp6; prefixLength = 7; }]; 31 31 }; 32 32 }; 33 33
+3 -3
nixos/tests/containers-extra_veth.nix
··· 21 21 }; 22 22 networking.interfaces = { 23 23 br0 = { 24 - ip4 = [{ address = "192.168.0.1"; prefixLength = 24; }]; 25 - ip6 = [{ address = "fc00::1"; prefixLength = 7; }]; 24 + ipv4.addresses = [{ address = "192.168.0.1"; prefixLength = 24; }]; 25 + ipv6.addresses = [{ address = "fc00::1"; prefixLength = 7; }]; 26 26 }; 27 27 br1 = { 28 - ip4 = [{ address = "192.168.1.1"; prefixLength = 24; }]; 28 + ipv4.addresses = [{ address = "192.168.1.1"; prefixLength = 24; }]; 29 29 }; 30 30 }; 31 31
+3 -3
nixos/tests/containers-hosts.nix
··· 13 13 virtualisation.vlans = []; 14 14 15 15 networking.bridges.br0.interfaces = []; 16 - networking.interfaces.br0 = { 17 - ip4 = [ { address = "10.11.0.254"; prefixLength = 24; } ]; 18 - }; 16 + networking.interfaces.br0.ipv4.addresses = [ 17 + { address = "10.11.0.254"; prefixLength = 24; } 18 + ]; 19 19 20 20 # Force /etc/hosts to be the only source for host name resolution 21 21 environment.etc."nsswitch.conf".text = lib.mkForce ''
+4 -4
nixos/tests/containers-macvlans.nix
··· 26 26 interface = "eth1"; 27 27 mode = "bridge"; 28 28 }; 29 - networking.interfaces.eth1.ip4 = lib.mkForce []; 29 + networking.interfaces.eth1.ipv4.addresses = lib.mkForce []; 30 30 networking.interfaces.mv-eth1-host = { 31 - ip4 = [ { address = "192.168.1.1"; prefixLength = 24; } ]; 31 + ipv4.addresses = [ { address = "192.168.1.1"; prefixLength = 24; } ]; 32 32 }; 33 33 34 34 containers.test1 = { ··· 37 37 38 38 config = { 39 39 networking.interfaces.mv-eth1 = { 40 - ip4 = [ { address = containerIp1; prefixLength = 24; } ]; 40 + ipv4.addresses = [ { address = containerIp1; prefixLength = 24; } ]; 41 41 }; 42 42 }; 43 43 }; ··· 48 48 49 49 config = { 50 50 networking.interfaces.mv-eth1 = { 51 - ip4 = [ { address = containerIp2; prefixLength = 24; } ]; 51 + ipv4.addresses = [ { address = containerIp2; prefixLength = 24; } ]; 52 52 }; 53 53 }; 54 54 };
+12 -12
nixos/tests/containers-physical_interfaces.nix
··· 16 16 interfaces = [ "eth1" ]; 17 17 18 18 config = { 19 - networking.interfaces.eth1 = { 20 - ip4 = [ { address = "10.10.0.1"; prefixLength = 24; } ]; 21 - }; 19 + networking.interfaces.eth1.ipv4.addresses = [ 20 + { address = "10.10.0.1"; prefixLength = 24; } 21 + ]; 22 22 networking.firewall.enable = false; 23 23 }; 24 24 }; ··· 33 33 34 34 config = { 35 35 networking.bridges.br0.interfaces = [ "eth1" ]; 36 - networking.interfaces.br0 = { 37 - ip4 = [ { address = "10.10.0.2"; prefixLength = 24; } ]; 38 - }; 36 + networking.interfaces.br0.ipv4.addresses = [ 37 + { address = "10.10.0.2"; prefixLength = 24; } 38 + ]; 39 39 networking.firewall.enable = false; 40 40 }; 41 41 }; ··· 54 54 interfaces = [ "eth1" ]; 55 55 mode = "active-backup"; 56 56 }; 57 - networking.interfaces.bond0 = { 58 - ip4 = [ { address = "10.10.0.3"; prefixLength = 24; } ]; 59 - }; 57 + networking.interfaces.bond0.ipv4.addresses = [ 58 + { address = "10.10.0.3"; prefixLength = 24; } 59 + ]; 60 60 networking.firewall.enable = false; 61 61 }; 62 62 }; ··· 76 76 mode = "active-backup"; 77 77 }; 78 78 networking.bridges.br0.interfaces = [ "bond0" ]; 79 - networking.interfaces.br0 = { 80 - ip4 = [ { address = "10.10.0.4"; prefixLength = 24; } ]; 81 - }; 79 + networking.interfaces.br0.ipv4.addresses = [ 80 + { address = "10.10.0.4"; prefixLength = 24; } 81 + ]; 82 82 networking.firewall.enable = false; 83 83 }; 84 84 };
+1 -1
nixos/tests/containers-reloadable.nix
··· 11 11 12 12 # prevent make-test.nix to change IP 13 13 networking.interfaces = { 14 - eth1.ip4 = lib.mkOverride 0 [ ]; 14 + eth1.ipv4.addresses = lib.mkOverride 0 [ ]; 15 15 }; 16 16 }; 17 17 in {
+7 -7
nixos/tests/containers-restart_networking.nix
··· 11 11 config = { 12 12 networking.firewall.enable = false; 13 13 networking.firewall.allowPing = true; 14 - networking.interfaces.eth0.ip4 = [ 14 + networking.interfaces.eth0.ipv4.addresses = [ 15 15 { address = "192.168.1.122"; prefixLength = 24; } 16 16 ]; 17 17 }; ··· 33 33 rstp = false; 34 34 }; 35 35 networking.interfaces = { 36 - eth1.ip4 = lib.mkOverride 0 [ ]; 37 - br0.ip4 = [{ address = "192.168.1.1"; prefixLength = 24; }]; 36 + eth1.ipv4.addresses = lib.mkOverride 0 [ ]; 37 + br0.ipv4.addresses = [ { address = "192.168.1.1"; prefixLength = 24; } ]; 38 38 }; 39 39 40 40 }; ··· 44 44 rstp = false; 45 45 }; 46 46 networking.interfaces = { 47 - eth1.ip4 = lib.mkOverride 0 [ ]; 48 - br0.ip4 = [{ address = "192.168.1.2"; prefixLength = 24; }]; 47 + eth1.ipv4.addresses = lib.mkOverride 0 [ ]; 48 + br0.ipv4.addresses = [ { address = "192.168.1.2"; prefixLength = 24; } ]; 49 49 }; 50 50 }; 51 51 client_eth1_rstp = { lib, pkgs, ... }: client_base // { ··· 54 54 rstp = true; 55 55 }; 56 56 networking.interfaces = { 57 - eth1.ip4 = lib.mkOverride 0 [ ]; 58 - br0.ip4 = [{ address = "192.168.1.2"; prefixLength = 24; }]; 57 + eth1.ipv4.addresses = lib.mkOverride 0 [ ]; 58 + br0.ipv4.addresses = [ { address = "192.168.1.2"; prefixLength = 24; } ]; 59 59 }; 60 60 }; 61 61 };
+4 -4
nixos/tests/ferm.nix
··· 11 11 with pkgs.lib; 12 12 { 13 13 networking = { 14 - interfaces.eth1.ip6 = mkOverride 0 [ { address = "fd00::2"; prefixLength = 64; } ]; 15 - interfaces.eth1.ip4 = mkOverride 0 [ { address = "192.168.1.2"; prefixLength = 24; } ]; 14 + interfaces.eth1.ipv6.addresses = mkOverride 0 [ { address = "fd00::2"; prefixLength = 64; } ]; 15 + interfaces.eth1.ipv4.addresses = mkOverride 0 [ { address = "192.168.1.2"; prefixLength = 24; } ]; 16 16 }; 17 17 }; 18 18 server = ··· 20 20 with pkgs.lib; 21 21 { 22 22 networking = { 23 - interfaces.eth1.ip6 = mkOverride 0 [ { address = "fd00::1"; prefixLength = 64; } ]; 24 - interfaces.eth1.ip4 = mkOverride 0 [ { address = "192.168.1.1"; prefixLength = 24; } ]; 23 + interfaces.eth1.ipv6.addresses = mkOverride 0 [ { address = "fd00::1"; prefixLength = 64; } ]; 24 + interfaces.eth1.ipv4.addresses = mkOverride 0 [ { address = "192.168.1.1"; prefixLength = 24; } ]; 25 25 }; 26 26 27 27 services = {
+1 -3
nixos/tests/initrd-network-ssh/default.nix
··· 11 11 { config, pkgs, ... }: 12 12 { 13 13 boot.kernelParams = [ 14 - "ip=${ 15 - (head config.networking.interfaces.eth1.ip4).address 16 - }:::255.255.255.0::eth1:none" 14 + "ip=${config.networking.primaryIPAddress}:::255.255.255.0::eth1:none" 17 15 ]; 18 16 boot.initrd.network = { 19 17 enable = true;
+1 -1
nixos/tests/nat.nix
··· 35 35 { virtualisation.vlans = [ 1 ]; 36 36 networking.firewall.allowPing = true; 37 37 networking.defaultGateway = 38 - (pkgs.lib.head nodes.router.config.networking.interfaces.eth2.ip4).address; 38 + (pkgs.lib.head nodes.router.config.networking.interfaces.eth2.ipv4.addresses).address; 39 39 } 40 40 (lib.optionalAttrs withConntrackHelpers { 41 41 networking.firewall.connectionTrackingModules = [ "ftp" ];
+95 -34
nixos/tests/networking.nix
··· 21 21 firewall.allowedUDPPorts = [ 547 ]; 22 22 interfaces = mkOverride 0 (listToAttrs (flip map vlanIfs (n: 23 23 nameValuePair "eth${toString n}" { 24 - ipAddress = "192.168.${toString n}.1"; 25 - prefixLength = 24; 26 - ipv6Address = "fd00:1234:5678:${toString n}::1"; 27 - ipv6PrefixLength = 64; 24 + ipv4.addresses = [ { address = "192.168.${toString n}.1"; prefixLength = 24; } ]; 25 + ipv6.addresses = [ { address = "fd00:1234:5678:${toString n}::1"; prefixLength = 64; } ]; 28 26 }))); 29 27 }; 30 28 services.dhcpd4 = { ··· 90 88 firewall.allowPing = true; 91 89 useDHCP = false; 92 90 defaultGateway = "192.168.1.1"; 93 - interfaces.eth1.ip4 = mkOverride 0 [ 91 + interfaces.eth1.ipv4.addresses = mkOverride 0 [ 94 92 { address = "192.168.1.2"; prefixLength = 24; } 95 93 { address = "192.168.1.3"; prefixLength = 32; } 96 94 { address = "192.168.1.10"; prefixLength = 32; } 97 95 ]; 98 - interfaces.eth2.ip4 = mkOverride 0 [ 96 + interfaces.eth2.ipv4.addresses = mkOverride 0 [ 99 97 { address = "192.168.2.2"; prefixLength = 24; } 100 98 ]; 101 99 }; ··· 143 141 firewall.allowPing = true; 144 142 useDHCP = true; 145 143 interfaces.eth1 = { 146 - ip4 = mkOverride 0 [ ]; 147 - ip6 = mkOverride 0 [ ]; 144 + ipv4.addresses = mkOverride 0 [ ]; 145 + ipv6.addresses = mkOverride 0 [ ]; 148 146 }; 149 147 interfaces.eth2 = { 150 - ip4 = mkOverride 0 [ ]; 151 - ip6 = mkOverride 0 [ ]; 148 + ipv4.addresses = mkOverride 0 [ ]; 149 + ipv6.addresses = mkOverride 0 [ ]; 152 150 }; 153 151 }; 154 152 }; ··· 198 196 firewall.allowPing = true; 199 197 useDHCP = false; 200 198 interfaces.eth1 = { 201 - ip4 = mkOverride 0 [ ]; 199 + ipv4.addresses = mkOverride 0 [ ]; 202 200 useDHCP = true; 203 201 }; 204 - interfaces.eth2.ip4 = mkOverride 0 [ ]; 202 + interfaces.eth2.ipv4.addresses = mkOverride 0 [ ]; 205 203 }; 206 204 }; 207 205 testScript = { nodes, ... }: ··· 241 239 interfaces = [ "eth1" "eth2" ]; 242 240 driverOptions.mode = "balance-rr"; 243 241 }; 244 - interfaces.eth1.ip4 = mkOverride 0 [ ]; 245 - interfaces.eth2.ip4 = mkOverride 0 [ ]; 246 - interfaces.bond.ip4 = mkOverride 0 242 + interfaces.eth1.ipv4.addresses = mkOverride 0 [ ]; 243 + interfaces.eth2.ipv4.addresses = mkOverride 0 [ ]; 244 + interfaces.bond.ipv4.addresses = mkOverride 0 247 245 [ { inherit address; prefixLength = 30; } ]; 248 246 }; 249 247 }; ··· 274 272 useNetworkd = networkd; 275 273 firewall.allowPing = true; 276 274 useDHCP = false; 277 - interfaces.eth1.ip4 = mkOverride 0 275 + interfaces.eth1.ipv4.addresses = mkOverride 0 278 276 [ { inherit address; prefixLength = 24; } ]; 279 277 }; 280 278 }; ··· 289 287 firewall.allowPing = true; 290 288 useDHCP = false; 291 289 bridges.bridge.interfaces = [ "eth1" "eth2" ]; 292 - interfaces.eth1.ip4 = mkOverride 0 [ ]; 293 - interfaces.eth2.ip4 = mkOverride 0 [ ]; 294 - interfaces.bridge.ip4 = mkOverride 0 290 + interfaces.eth1.ipv4.addresses = mkOverride 0 [ ]; 291 + interfaces.eth2.ipv4.addresses = mkOverride 0 [ ]; 292 + interfaces.bridge.ipv4.addresses = mkOverride 0 295 293 [ { address = "192.168.1.1"; prefixLength = 24; } ]; 296 294 }; 297 295 }; ··· 328 326 firewall.allowPing = true; 329 327 useDHCP = true; 330 328 macvlans.macvlan.interface = "eth1"; 331 - interfaces.eth1.ip4 = mkOverride 0 [ ]; 329 + interfaces.eth1.ipv4.addresses = mkOverride 0 [ ]; 332 330 }; 333 331 }; 334 332 testScript = { nodes, ... }: ··· 369 367 local = address4; 370 368 dev = "eth1"; 371 369 }; 372 - interfaces.eth1.ip4 = mkOverride 0 370 + interfaces.eth1.ipv4.addresses = mkOverride 0 373 371 [ { address = address4; prefixLength = 24; } ]; 374 - interfaces.sit.ip6 = mkOverride 0 372 + interfaces.sit.ipv6.addresses = mkOverride 0 375 373 [ { address = address6; prefixLength = 64; } ]; 376 374 }; 377 375 }; ··· 410 408 id = 1; 411 409 interface = "eth0"; 412 410 }; 413 - interfaces.eth0.ip4 = mkOverride 0 [ ]; 414 - interfaces.eth1.ip4 = mkOverride 0 [ ]; 415 - interfaces.vlan.ip4 = mkOverride 0 411 + interfaces.eth0.ipv4.addresses = mkOverride 0 [ ]; 412 + interfaces.eth1.ipv4.addresses = mkOverride 0 [ ]; 413 + interfaces.vlan.ipv4.addresses = mkOverride 0 416 414 [ { inherit address; prefixLength = 24; } ]; 417 415 }; 418 416 }; ··· 437 435 name = "Virtual"; 438 436 machine = { 439 437 networking.interfaces."tap0" = { 440 - ip4 = [ { address = "192.168.1.1"; prefixLength = 24; } ]; 441 - ip6 = [ { address = "2001:1470:fffd:2096::"; prefixLength = 64; } ]; 438 + ipv4.addresses = [ { address = "192.168.1.1"; prefixLength = 24; } ]; 439 + ipv6.addresses = [ { address = "2001:1470:fffd:2096::"; prefixLength = 64; } ]; 442 440 virtual = true; 443 441 }; 444 442 networking.interfaces."tun0" = { 445 - ip4 = [ { address = "192.168.1.2"; prefixLength = 24; } ]; 446 - ip6 = [ { address = "2001:1470:fffd:2097::"; prefixLength = 64; } ]; 443 + ipv4.addresses = [ { address = "192.168.1.2"; prefixLength = 24; } ]; 444 + ipv6.addresses = [ { address = "2001:1470:fffd:2097::"; prefixLength = 64; } ]; 447 445 virtual = true; 448 446 }; 449 447 }; ··· 483 481 boot.kernel.sysctl."net.ipv6.conf.all.forwarding" = true; 484 482 networking = { 485 483 useNetworkd = networkd; 486 - interfaces.eth1 = { 487 - ipv6Address = "fd00:1234:5678:1::1"; 488 - ipv6PrefixLength = 64; 484 + interfaces.eth1.ipv6.addresses = singleton { 485 + address = "fd00:1234:5678:1::1"; 486 + prefixLength = 64; 489 487 }; 490 488 }; 491 489 services.radvd = { ··· 511 509 useDHCP = true; 512 510 interfaces.eth1 = { 513 511 preferTempAddress = true; 514 - ip4 = mkOverride 0 [ ]; 515 - ip6 = mkOverride 0 [ ]; 512 + ipv4.addresses = mkOverride 0 [ ]; 513 + ipv6.addresses = mkOverride 0 [ ]; 516 514 }; 517 515 }; 518 516 }; ··· 532 530 # Test address used is temporary 533 531 $client->waitUntilSucceeds("! ip route get fd00:1234:5678:1::1 | grep -q ':[a-f0-9]*ff:fe[a-f0-9]*:'"); 534 532 ''; 533 + }; 534 + routes = { 535 + name = "routes"; 536 + machine = { 537 + networking.useDHCP = false; 538 + networking.interfaces."eth0" = { 539 + ipv4.addresses = [ { address = "192.168.1.2"; prefixLength = 24; } ]; 540 + ipv6.addresses = [ { address = "2001:1470:fffd:2097::"; prefixLength = 64; } ]; 541 + ipv6.routes = [ 542 + { address = "fdfd:b3f0::"; prefixLength = 48; } 543 + { address = "2001:1470:fffd:2098::"; prefixLength = 64; via = "fdfd:b3f0::1"; } 544 + ]; 545 + ipv4.routes = [ 546 + { address = "10.0.0.0"; prefixLength = 16; options = { mtu = "1500"; }; } 547 + { address = "192.168.2.0"; prefixLength = 24; via = "192.168.1.1"; } 548 + ]; 549 + }; 550 + virtualisation.vlans = [ ]; 551 + }; 552 + 553 + testScript = '' 554 + my $targetIPv4Table = <<'END'; 555 + 10.0.0.0/16 scope link mtu 1500 556 + 192.168.1.0/24 proto kernel scope link src 192.168.1.2 557 + 192.168.2.0/24 via 192.168.1.1 558 + END 559 + 560 + my $targetIPv6Table = <<'END'; 561 + 2001:1470:fffd:2097::/64 proto kernel metric 256 pref medium 562 + 2001:1470:fffd:2098::/64 via fdfd:b3f0::1 metric 1024 pref medium 563 + fdfd:b3f0::/48 metric 1024 pref medium 564 + END 565 + 566 + $machine->start; 567 + $machine->waitForUnit("network.target"); 568 + 569 + # test routing tables 570 + my $ipv4Table = $machine->succeed("ip -4 route list dev eth0 | head -n3"); 571 + my $ipv6Table = $machine->succeed("ip -6 route list dev eth0 | head -n3"); 572 + "$ipv4Table" eq "$targetIPv4Table" or die( 573 + "The IPv4 routing table does not match the expected one:\n", 574 + "Result:\n", "$ipv4Table\n", 575 + "Expected:\n", "$targetIPv4Table\n" 576 + ); 577 + "$ipv6Table" eq "$targetIPv6Table" or die( 578 + "The IPv6 routing table does not match the expected one:\n", 579 + "Result:\n", "$ipv6Table\n", 580 + "Expected:\n", "$targetIPv6Table\n" 581 + ); 582 + 583 + # test clean-up of the tables 584 + $machine->succeed("systemctl stop network-addresses-eth0"); 585 + my $ipv4Residue = $machine->succeed("ip -4 route list dev eth0 | head -n-3"); 586 + my $ipv6Residue = $machine->succeed("ip -6 route list dev eth0 | head -n-3"); 587 + $ipv4Residue eq "" or die( 588 + "The IPv4 routing table has not been properly cleaned:\n", 589 + "$ipv4Residue\n" 590 + ); 591 + $ipv6Residue eq "" or die( 592 + "The IPv6 routing table has not been properly cleaned:\n", 593 + "$ipv6Residue\n" 594 + ); 595 + ''; 535 596 }; 536 597 }; 537 598
+14 -8
nixos/tests/nsd.nix
··· 15 15 clientv4 = { lib, nodes, ... }: { 16 16 imports = [ common ]; 17 17 networking.nameservers = lib.mkForce [ 18 - nodes.server.config.networking.interfaces.eth1.ipAddress 18 + (lib.head nodes.server.config.networking.interfaces.eth1.ipv4.addresses).address 19 19 ]; 20 - networking.interfaces.eth1.ipAddress = "192.168.0.2"; 21 - networking.interfaces.eth1.prefixLength = 24; 20 + networking.interfaces.eth1.ipv4.addresses = [ 21 + { address = "192.168.0.2"; prefixLength = 24; } 22 + ]; 22 23 }; 23 24 24 25 clientv6 = { lib, nodes, ... }: { 25 26 imports = [ common ]; 26 27 networking.nameservers = lib.mkForce [ 27 - nodes.server.config.networking.interfaces.eth1.ipv6Address 28 + (lib.head nodes.server.config.networking.interfaces.eth1.ipv6.addresses).address 28 29 ]; 29 - networking.interfaces.eth1.ipv6Address = "dead:beef::2"; 30 + networking.interfaces.eth1.ipv4.addresses = [ 31 + { address = "dead:beef::2"; prefixLength = 24; } 32 + ]; 30 33 }; 31 34 32 35 server = { lib, ... }: { 33 36 imports = [ common ]; 34 - networking.interfaces.eth1.ipAddress = "192.168.0.1"; 35 - networking.interfaces.eth1.prefixLength = 24; 36 - networking.interfaces.eth1.ipv6Address = "dead:beef::1"; 37 + networking.interfaces.eth1.ipv4.addresses = [ 38 + { address = "192.168.0.1"; prefixLength = 24; } 39 + ]; 40 + networking.interfaces.eth1.ipv6.addresses = [ 41 + { address = "dead:beef::1"; prefixLength = 64; } 42 + ]; 37 43 services.nsd.enable = true; 38 44 services.nsd.interfaces = lib.mkForce []; 39 45 services.nsd.zones."example.com.".data = ''
+1 -1
nixos/tests/quagga.nix
··· 8 8 import ./make-test.nix ({ pkgs, ... }: 9 9 let 10 10 11 - ifAddr = node: iface: (pkgs.lib.head node.config.networking.interfaces.${iface}.ip4).address; 11 + ifAddr = node: iface: (pkgs.lib.head node.config.networking.interfaces.${iface}.ipv4.addresses).address; 12 12 13 13 ospfConf = '' 14 14 interface eth2