diff --git a/nixos/doc/manual/configuration/ipv4-config.xml b/nixos/doc/manual/configuration/ipv4-config.xml index 053501b1736d..68238b547d60 100644 --- a/nixos/doc/manual/configuration/ipv4-config.xml +++ b/nixos/doc/manual/configuration/ipv4-config.xml @@ -12,7 +12,7 @@ interfaces. However, you can configure an interface manually as follows: -networking.interfaces.eth0.ip4 = [ { address = "192.168.1.2"; prefixLength = 24; } ]; +networking.interfaces.eth0.ipv4.addresses = [ { address = "192.168.1.2"; prefixLength = 24; } ]; Typically you’ll also want to set a default gateway and set of name diff --git a/nixos/doc/manual/configuration/ipv6-config.xml b/nixos/doc/manual/configuration/ipv6-config.xml index 6d9e0a164e9e..74a21e18ec3f 100644 --- a/nixos/doc/manual/configuration/ipv6-config.xml +++ b/nixos/doc/manual/configuration/ipv6-config.xml @@ -26,7 +26,7 @@ boot.kernel.sysctl."net.ipv6.conf.eth0.disable_ipv6" = true; DHCPv6. You can configure an interface manually: -networking.interfaces.eth0.ip6 = [ { address = "fe00:aa:bb:cc::2"; prefixLength = 64; } ]; +networking.interfaces.eth0.ipv6.addresses = [ { address = "fe00:aa:bb:cc::2"; prefixLength = 64; } ]; diff --git a/nixos/doc/manual/release-notes/rl-1803.xml b/nixos/doc/manual/release-notes/rl-1803.xml index 2494e487da15..09d34b6f0356 100644 --- a/nixos/doc/manual/release-notes/rl-1803.xml +++ b/nixos/doc/manual/release-notes/rl-1803.xml @@ -261,10 +261,42 @@ following incompatible changes: - The option is now none by default. - An assertion failure is thrown if WM's and DM's default are none. - To explicitly run a plain X session without and DM or WM, the newly introduced option - must be set to true. + In the module the + following options have been removed: + + + + + + + + + + + + + + + + + + To assign static addresses to an interface the options + and + should be used instead. + The options and have been + renamed to + respectively. + The new options and + have been added to set up static routing. + + + + + The option is now + none by default. An assertion failure is thrown if WM's + and DM's default are none. + To explicitly run a plain X session without and DM or WM, the newly + introduced option must be set to true. diff --git a/nixos/lib/build-vms.nix b/nixos/lib/build-vms.nix index 4685fe6914a2..e14105f5f011 100644 --- a/nixos/lib/build-vms.nix +++ b/nixos/lib/build-vms.nix @@ -51,7 +51,7 @@ rec { let interfacesNumbered = zipLists config.virtualisation.vlans (range 1 255); interfaces = flip map interfacesNumbered ({ fst, snd }: - nameValuePair "eth${toString snd}" { ip4 = + nameValuePair "eth${toString snd}" { ipv4.addresses = [ { address = "192.168.${toString fst}.${toString m.snd}"; prefixLength = 24; } ]; @@ -64,7 +64,7 @@ rec { networking.interfaces = listToAttrs interfaces; networking.primaryIPAddress = - optionalString (interfaces != []) (head (head interfaces).value.ip4).address; + optionalString (interfaces != []) (head (head interfaces).value.ipv4.addresses).address; # Put the IP addresses of all VMs in this machine's # /etc/hosts file. If a machine has multiple diff --git a/nixos/modules/services/networking/dhcpcd.nix b/nixos/modules/services/networking/dhcpcd.nix index d283c7624335..d10b72ecf058 100644 --- a/nixos/modules/services/networking/dhcpcd.nix +++ b/nixos/modules/services/networking/dhcpcd.nix @@ -16,7 +16,7 @@ let # Don't start dhcpcd on explicitly configured interfaces or on # interfaces that are part of a bridge, bond or sit device. ignoredInterfaces = - map (i: i.name) (filter (i: if i.useDHCP != null then !i.useDHCP else i.ip4 != [ ] || i.ipAddress != null) interfaces) + map (i: i.name) (filter (i: if i.useDHCP != null then !i.useDHCP else i.ipv4.addresses != [ ]) interfaces) ++ mapAttrsToList (i: _: i) config.networking.sits ++ concatLists (attrValues (mapAttrs (n: v: v.interfaces) config.networking.bridges)) ++ concatLists (attrValues (mapAttrs (n: v: v.interfaces) config.networking.vswitches)) diff --git a/nixos/modules/services/security/hologram-agent.nix b/nixos/modules/services/security/hologram-agent.nix index 6c53a2df6306..39ed506f7617 100644 --- a/nixos/modules/services/security/hologram-agent.nix +++ b/nixos/modules/services/security/hologram-agent.nix @@ -35,10 +35,9 @@ in { config = mkIf cfg.enable { boot.kernelModules = [ "dummy" ]; - networking.interfaces.dummy0 = { - ipAddress = "169.254.169.254"; - prefixLength = 32; - }; + networking.interfaces.dummy0.ipv4.addresses = [ + { address = "169.254.169.254"; prefixLength = 32; } + ]; systemd.services.hologram-agent = { description = "Provide EC2 instance credentials to machines outside of EC2"; diff --git a/nixos/modules/tasks/network-interfaces-scripted.nix b/nixos/modules/tasks/network-interfaces-scripted.nix index 63d07832d105..66732ce7732e 100644 --- a/nixos/modules/tasks/network-interfaces-scripted.nix +++ b/nixos/modules/tasks/network-interfaces-scripted.nix @@ -20,14 +20,8 @@ let "sys-subsystem-net-devices-${escapeSystemdPath interface}.device"; interfaceIps = i: - i.ip4 ++ optionals cfg.enableIPv6 i.ip6 - ++ optional (i.ipAddress != null) { - address = i.ipAddress; - prefixLength = i.prefixLength; - } ++ optional (cfg.enableIPv6 && i.ipv6Address != null) { - address = i.ipv6Address; - prefixLength = i.ipv6PrefixLength; - }; + i.ipv4.addresses + ++ optionals cfg.enableIPv6 i.ipv6.addresses; destroyBond = i: '' while true; do @@ -185,33 +179,58 @@ let path = [ pkgs.iproute ]; script = '' - # FIXME: shouldn't this be done in network-link? - echo "bringing up interface..." - ip link set "${i.name}" up - state="/run/nixos/network/addresses/${i.name}" - mkdir -p $(dirname "$state") - '' + flip concatMapStrings (ips) (ip: - let - address = "${ip.address}/${toString ip.prefixLength}"; - in - '' - echo "${address}" >> $state - if out=$(ip addr add "${address}" dev "${i.name}" 2>&1); then - echo "added ip ${address}" - elif ! echo "$out" | grep "File exists" >/dev/null 2>&1; then - echo "failed to add ${address}" - exit 1 - fi - ''); + ${flip concatMapStrings ips (ip: + let + cidr = "${ip.address}/${toString ip.prefixLength}"; + in + '' + echo "${cidr}" >> $state + echo -n "adding address ${cidr}... " + if out=$(ip addr add "${cidr}" dev "${i.name}" 2>&1); then + echo "done" + elif ! echo "$out" | grep "File exists" >/dev/null 2>&1; then + echo "failed" + exit 1 + fi + '' + )} + + state="/run/nixos/network/routes/${i.name}" + mkdir -p $(dirname "$state") + + ${flip concatMapStrings (i.ipv4.routes ++ i.ipv6.routes) (route: + let + cidr = "${route.address}/${toString route.prefixLength}"; + via = optionalString (route.via != null) ''via "${route.via}"''; + options = concatStrings (mapAttrsToList (name: val: "${name} ${val} ") route.options); + in + '' + echo "${cidr}" >> $state + echo -n "adding route ${cidr}... " + if out=$(ip route add "${cidr}" ${options} ${via} dev "${i.name}" 2>&1); then + echo "done" + elif ! echo "$out" | grep "File exists" >/dev/null 2>&1; then + echo "failed" + exit 1 + fi + '' + )} + ''; preStop = '' + state="/run/nixos/network/routes/${i.name}" + while read cidr; do + echo -n "deleting route $cidr... " + ip route del "$cidr" dev "${i.name}" >/dev/null 2>&1 && echo "done" || echo "failed" + done < "$state" + rm -f "$state" + state="/run/nixos/network/addresses/${i.name}" - while read address; do - echo -n "deleting $address..." - ip addr del "$address" dev "${i.name}" >/dev/null 2>&1 || echo -n " Failed" - echo "" + while read cidr; do + echo -n "deleting address $cidr... " + ip addr del "$cidr" dev "${i.name}" >/dev/null 2>&1 && echo "done" || echo "failed" done < "$state" rm -f "$state" ''; diff --git a/nixos/modules/tasks/network-interfaces-systemd.nix b/nixos/modules/tasks/network-interfaces-systemd.nix index be7f52a76def..c640e886fca8 100644 --- a/nixos/modules/tasks/network-interfaces-systemd.nix +++ b/nixos/modules/tasks/network-interfaces-systemd.nix @@ -9,14 +9,8 @@ let interfaces = attrValues cfg.interfaces; interfaceIps = i: - i.ip4 ++ optionals cfg.enableIPv6 i.ip6 - ++ optional (i.ipAddress != null) { - address = i.ipAddress; - prefixLength = i.prefixLength; - } ++ optional (cfg.enableIPv6 && i.ipv6Address != null) { - address = i.ipv6Address; - prefixLength = i.ipv6PrefixLength; - }; + i.ipv4.addresses + ++ optionals cfg.enableIPv6 i.ipv6.addresses; dhcpStr = useDHCP: if useDHCP == true || useDHCP == null then "both" else "none"; diff --git a/nixos/modules/tasks/network-interfaces.nix b/nixos/modules/tasks/network-interfaces.nix index f80c5045c07d..5036b701bd86 100644 --- a/nixos/modules/tasks/network-interfaces.nix +++ b/nixos/modules/tasks/network-interfaces.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, utils, stdenv, ... }: +{ config, options, lib, pkgs, utils, stdenv, ... }: with lib; with utils; @@ -101,7 +101,7 @@ let address = mkOption { type = types.str; description = '' - IPv${toString v} address of the interface. Leave empty to configure the + IPv${toString v} address of the interface. Leave empty to configure the interface using DHCP. ''; }; @@ -116,6 +116,40 @@ let }; }; + routeOpts = v: + { options = { + address = mkOption { + type = types.str; + description = "IPv${toString v} address of the network."; + }; + + prefixLength = mkOption { + type = types.addCheck types.int (n: n >= 0 && n <= (if v == 4 then 32 else 128)); + description = '' + Subnet mask of the network, specified as the number of + bits in the prefix (${if v == 4 then "24" else "64"}). + ''; + }; + + via = mkOption { + type = types.nullOr types.str; + default = null; + description = "IPv${toString v} address of the next hop."; + }; + + options = mkOption { + type = types.attrsOf types.str; + default = { }; + example = { mtu = "1492"; window = "524288"; }; + description = '' + Other route options. See the symbol OPTION + in the ip-route(8) manual page for the details. + ''; + }; + + }; + }; + gatewayCoerce = address: { inherit address; }; gatewayOpts = { ... }: { @@ -148,7 +182,6 @@ let interfaceOpts = { name, ... }: { options = { - name = mkOption { example = "eth0"; type = types.str; @@ -175,7 +208,7 @@ let ''; }; - ip4 = mkOption { + ipv4.addresses = mkOption { default = [ ]; example = [ { address = "10.0.0.1"; prefixLength = 16; } @@ -187,7 +220,7 @@ let ''; }; - ip6 = mkOption { + ipv6.addresses = mkOption { default = [ ]; example = [ { address = "fdfd:b3f0:482::1"; prefixLength = 48; } @@ -199,50 +232,27 @@ let ''; }; - ipAddress = mkOption { - default = null; - example = "10.0.0.1"; - type = types.nullOr types.str; + ipv4.routes = mkOption { + default = []; + example = [ + { address = "10.0.0.0"; prefixLength = 16; } + { address = "192.168.2.0"; prefixLength = 24; via = "192.168.1.1"; } + ]; + type = with types; listOf (submodule (routeOpts 4)); description = '' - IP address of the interface. Leave empty to configure the - interface using DHCP. + List of extra IPv4 static routes that will be assigned to the interface. ''; }; - prefixLength = mkOption { - default = null; - example = 24; - type = types.nullOr types.int; + ipv6.routes = mkOption { + default = []; + example = [ + { address = "fdfd:b3f0::"; prefixLength = 48; } + { address = "2001:1470:fffd:2098::"; prefixLength = 64; via = "fdfd:b3f0::1"; } + ]; + type = with types; listOf (submodule (routeOpts 6)); description = '' - Subnet mask of the interface, specified as the number of - bits in the prefix (24). - ''; - }; - - subnetMask = mkOption { - default = null; - description = '' - Defunct, supply the prefix length instead. - ''; - }; - - ipv6Address = mkOption { - default = null; - example = "2001:1470:fffd:2098::e006"; - type = types.nullOr types.str; - description = '' - IPv6 address of the interface. Leave empty to configure the - interface using NDP. - ''; - }; - - ipv6PrefixLength = mkOption { - default = 64; - example = 64; - type = types.int; - description = '' - Subnet mask of the interface, specified as the number of - bits in the prefix (64). + List of extra IPv6 static routes that will be assigned to the interface. ''; }; @@ -317,6 +327,32 @@ let name = mkDefault name; }; + # Renamed or removed options + imports = + let + defined = x: x != "_mkMergedOptionModule"; + in [ + (mkRenamedOptionModule [ "ip4" ] [ "ipv4" "addresses"]) + (mkRenamedOptionModule [ "ip6" ] [ "ipv6" "addresses"]) + (mkRemovedOptionModule [ "subnetMask" ] '' + Supply a prefix length instead; use option + networking.interfaces..ipv{4,6}.addresses'') + (mkMergedOptionModule + [ [ "ipAddress" ] [ "prefixLength" ] ] + [ "ipv4" "addresses" ] + (cfg: with cfg; + optional (defined ipAddress && defined prefixLength) + { address = ipAddress; prefixLength = prefixLength; })) + (mkMergedOptionModule + [ [ "ipv6Address" ] [ "ipv6PrefixLength" ] ] + [ "ipv6" "addresses" ] + (cfg: with cfg; + optional (defined ipv6Address && defined ipv6PrefixLength) + { address = ipv6Address; prefixLength = ipv6PrefixLength; })) + + ({ options.warnings = options.warnings; }) + ]; + }; hexChars = stringToCharacters "0123456789abcdef"; @@ -453,7 +489,7 @@ in networking.interfaces = mkOption { default = {}; example = - { eth0.ip4 = [ { + { eth0.ipv4 = [ { address = "131.211.84.78"; prefixLength = 25; } ]; @@ -932,13 +968,10 @@ in config = { + warnings = concatMap (i: i.warnings) interfaces; + assertions = (flip map interfaces (i: { - assertion = i.subnetMask == null; - message = '' - The networking.interfaces."${i.name}".subnetMask option is defunct. Use prefixLength instead. - ''; - })) ++ (flip map interfaces (i: { # With the linux kernel, interface name length is limited by IFNAMSIZ # to 16 bytes, including the trailing null byte. # See include/linux/if.h in the kernel sources @@ -947,7 +980,7 @@ in The name of networking.interfaces."${i.name}" is too long, it needs to be less than 16 characters. ''; })) ++ (flip map slaveIfs (i: { - assertion = i.ip4 == [ ] && i.ipAddress == null && i.ip6 == [ ] && i.ipv6Address == null; + assertion = i.ipv4.addresses == [ ] && i.ipv6.addresses == [ ]; message = '' The networking.interfaces."${i.name}" must not have any defined ips when it is a slave. ''; @@ -1089,6 +1122,9 @@ in '' + optionalString (i.mtu != null) '' echo "setting MTU to ${toString i.mtu}..." ip link set "${i.name}" mtu "${toString i.mtu}" + '' + '' + echo -n "bringing up interface... " + ip link set "${i.name}" up && echo "done" || (echo "failed"; exit 1) ''; }))); diff --git a/nixos/modules/virtualisation/virtualbox-host.nix b/nixos/modules/virtualisation/virtualbox-host.nix index bb0c38bd4eb8..91a46ac852b2 100644 --- a/nixos/modules/virtualisation/virtualbox-host.nix +++ b/nixos/modules/virtualisation/virtualbox-host.nix @@ -124,7 +124,7 @@ in ''; }; - networking.interfaces.vboxnet0.ip4 = [ { address = "192.168.56.1"; prefixLength = 24; } ]; + networking.interfaces.vboxnet0.ipv4.addresses = { address = "192.168.56.1"; prefixLength = 24; }; # Make sure NetworkManager won't assume this interface being up # means we have internet access. networking.networkmanager.unmanaged = ["vboxnet0"]; diff --git a/nixos/tests/bittorrent.nix b/nixos/tests/bittorrent.nix index 3a718a798315..50c98664660a 100644 --- a/nixos/tests/bittorrent.nix +++ b/nixos/tests/bittorrent.nix @@ -16,7 +16,7 @@ let miniupnpdConf = nodes: pkgs.writeText "miniupnpd.conf" '' ext_ifname=eth1 - listening_ip=${(pkgs.lib.head nodes.router.config.networking.interfaces.eth2.ip4).address}/24 + listening_ip=${(pkgs.lib.head nodes.router.config.networking.interfaces.eth2.ipv4.addresses).address}/24 allow 1024-65535 192.168.2.0/24 1024-65535 ''; @@ -56,7 +56,7 @@ in { environment.systemPackages = [ pkgs.transmission ]; virtualisation.vlans = [ 2 ]; networking.defaultGateway = - (pkgs.lib.head nodes.router.config.networking.interfaces.eth2.ip4).address; + (pkgs.lib.head nodes.router.config.networking.interfaces.eth2.ipv4.addresses).address; networking.firewall.enable = false; }; @@ -84,7 +84,7 @@ in # Create the torrent. $tracker->succeed("mkdir /tmp/data"); $tracker->succeed("cp ${file} /tmp/data/test.tar.bz2"); - $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"); + $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"); $tracker->succeed("chmod 644 /tmp/test.torrent"); # Start the tracker. !!! use a less crappy tracker diff --git a/nixos/tests/cjdns.nix b/nixos/tests/cjdns.nix index 466663799241..4d3b58abc6e5 100644 --- a/nixos/tests/cjdns.nix +++ b/nixos/tests/cjdns.nix @@ -12,7 +12,6 @@ let # the sequence of address assignment less stochastic. networking.useDHCP = false; - networking.interfaces.eth1.prefixLength = 24; # CJDNS output is incompatible with the XML log. systemd.services.cjdns.serviceConfig.StandardOutput = "null"; #networking.firewall.enable = true; @@ -49,7 +48,9 @@ import ./make-test.nix ({ pkgs, ...} : { { imports = [ basicConfig ]; - networking.interfaces.eth1.ipAddress = "192.168.0.2"; + networking.interfaces.eth1.ipv4.addresses = [ + { address = "192.168.0.2"; prefixLength = 24; } + ]; services.cjdns = { UDPInterface = @@ -76,7 +77,9 @@ import ./make-test.nix ({ pkgs, ...} : { CJDNS_ADMIN_PASSWORD=FOOBAR ''; - networking.interfaces.eth1.ipAddress = "192.168.0.1"; + networking.interfaces.eth1.ipv4.addresses = [ + { address = "192.168.0.1"; prefixLength = 24; } + ]; services.cjdns = { authorizedPasswords = [ carolPassword ]; diff --git a/nixos/tests/containers-bridge.nix b/nixos/tests/containers-bridge.nix index b8d4759684cc..dfef46a2ada4 100644 --- a/nixos/tests/containers-bridge.nix +++ b/nixos/tests/containers-bridge.nix @@ -26,8 +26,8 @@ import ./make-test.nix ({ pkgs, ...} : { }; networking.interfaces = { br0 = { - ip4 = [{ address = hostIp; prefixLength = 24; }]; - ip6 = [{ address = hostIp6; prefixLength = 7; }]; + ipv4.addresses = [{ address = hostIp; prefixLength = 24; }]; + ipv6.addresses = [{ address = hostIp6; prefixLength = 7; }]; }; }; diff --git a/nixos/tests/containers-extra_veth.nix b/nixos/tests/containers-extra_veth.nix index 6339c8c558b9..df3f3354b2d9 100644 --- a/nixos/tests/containers-extra_veth.nix +++ b/nixos/tests/containers-extra_veth.nix @@ -21,11 +21,11 @@ import ./make-test.nix ({ pkgs, ...} : { }; networking.interfaces = { br0 = { - ip4 = [{ address = "192.168.0.1"; prefixLength = 24; }]; - ip6 = [{ address = "fc00::1"; prefixLength = 7; }]; + ipv4.addresses = [{ address = "192.168.0.1"; prefixLength = 24; }]; + ipv6.addresses = [{ address = "fc00::1"; prefixLength = 7; }]; }; br1 = { - ip4 = [{ address = "192.168.1.1"; prefixLength = 24; }]; + ipv4.addresses = [{ address = "192.168.1.1"; prefixLength = 24; }]; }; }; diff --git a/nixos/tests/containers-hosts.nix b/nixos/tests/containers-hosts.nix index c7a85f190a5d..df1ef6d14936 100644 --- a/nixos/tests/containers-hosts.nix +++ b/nixos/tests/containers-hosts.nix @@ -13,9 +13,9 @@ import ./make-test.nix ({ pkgs, ...} : { virtualisation.vlans = []; networking.bridges.br0.interfaces = []; - networking.interfaces.br0 = { - ip4 = [ { address = "10.11.0.254"; prefixLength = 24; } ]; - }; + networking.interfaces.br0.ipv4.addresses = [ + { address = "10.11.0.254"; prefixLength = 24; } + ]; # Force /etc/hosts to be the only source for host name resolution environment.etc."nsswitch.conf".text = lib.mkForce '' diff --git a/nixos/tests/containers-macvlans.nix b/nixos/tests/containers-macvlans.nix index 721f98481497..390dc4ad2c29 100644 --- a/nixos/tests/containers-macvlans.nix +++ b/nixos/tests/containers-macvlans.nix @@ -26,9 +26,9 @@ import ./make-test.nix ({ pkgs, ...} : { interface = "eth1"; mode = "bridge"; }; - networking.interfaces.eth1.ip4 = lib.mkForce []; + networking.interfaces.eth1.ipv4.addresses = lib.mkForce []; networking.interfaces.mv-eth1-host = { - ip4 = [ { address = "192.168.1.1"; prefixLength = 24; } ]; + ipv4.addresses = [ { address = "192.168.1.1"; prefixLength = 24; } ]; }; containers.test1 = { @@ -37,7 +37,7 @@ import ./make-test.nix ({ pkgs, ...} : { config = { networking.interfaces.mv-eth1 = { - ip4 = [ { address = containerIp1; prefixLength = 24; } ]; + ipv4.addresses = [ { address = containerIp1; prefixLength = 24; } ]; }; }; }; @@ -48,7 +48,7 @@ import ./make-test.nix ({ pkgs, ...} : { config = { networking.interfaces.mv-eth1 = { - ip4 = [ { address = containerIp2; prefixLength = 24; } ]; + ipv4.addresses = [ { address = containerIp2; prefixLength = 24; } ]; }; }; }; diff --git a/nixos/tests/containers-physical_interfaces.nix b/nixos/tests/containers-physical_interfaces.nix index a3b0b29951bf..bd1228b8e37d 100644 --- a/nixos/tests/containers-physical_interfaces.nix +++ b/nixos/tests/containers-physical_interfaces.nix @@ -16,9 +16,9 @@ import ./make-test.nix ({ pkgs, ...} : { interfaces = [ "eth1" ]; config = { - networking.interfaces.eth1 = { - ip4 = [ { address = "10.10.0.1"; prefixLength = 24; } ]; - }; + networking.interfaces.eth1.ipv4.addresses = [ + { address = "10.10.0.1"; prefixLength = 24; } + ]; networking.firewall.enable = false; }; }; @@ -33,9 +33,9 @@ import ./make-test.nix ({ pkgs, ...} : { config = { networking.bridges.br0.interfaces = [ "eth1" ]; - networking.interfaces.br0 = { - ip4 = [ { address = "10.10.0.2"; prefixLength = 24; } ]; - }; + networking.interfaces.br0.ipv4.addresses = [ + { address = "10.10.0.2"; prefixLength = 24; } + ]; networking.firewall.enable = false; }; }; @@ -54,9 +54,9 @@ import ./make-test.nix ({ pkgs, ...} : { interfaces = [ "eth1" ]; mode = "active-backup"; }; - networking.interfaces.bond0 = { - ip4 = [ { address = "10.10.0.3"; prefixLength = 24; } ]; - }; + networking.interfaces.bond0.ipv4.addresses = [ + { address = "10.10.0.3"; prefixLength = 24; } + ]; networking.firewall.enable = false; }; }; @@ -76,9 +76,9 @@ import ./make-test.nix ({ pkgs, ...} : { mode = "active-backup"; }; networking.bridges.br0.interfaces = [ "bond0" ]; - networking.interfaces.br0 = { - ip4 = [ { address = "10.10.0.4"; prefixLength = 24; } ]; - }; + networking.interfaces.br0.ipv4.addresses = [ + { address = "10.10.0.4"; prefixLength = 24; } + ]; networking.firewall.enable = false; }; }; diff --git a/nixos/tests/containers-reloadable.nix b/nixos/tests/containers-reloadable.nix index b5867c6f6ab1..5fb42f2272b3 100644 --- a/nixos/tests/containers-reloadable.nix +++ b/nixos/tests/containers-reloadable.nix @@ -11,7 +11,7 @@ let # prevent make-test.nix to change IP networking.interfaces = { - eth1.ip4 = lib.mkOverride 0 [ ]; + eth1.ipv4.addresses = lib.mkOverride 0 [ ]; }; }; in { diff --git a/nixos/tests/containers-restart_networking.nix b/nixos/tests/containers-restart_networking.nix index 086d056c51cd..f68c9b07759b 100644 --- a/nixos/tests/containers-restart_networking.nix +++ b/nixos/tests/containers-restart_networking.nix @@ -11,7 +11,7 @@ let config = { networking.firewall.enable = false; networking.firewall.allowPing = true; - networking.interfaces.eth0.ip4 = [ + networking.interfaces.eth0.ipv4.addresses = [ { address = "192.168.1.122"; prefixLength = 24; } ]; }; @@ -33,8 +33,8 @@ in import ./make-test.nix ({ pkgs, lib, ...} : rstp = false; }; networking.interfaces = { - eth1.ip4 = lib.mkOverride 0 [ ]; - br0.ip4 = [{ address = "192.168.1.1"; prefixLength = 24; }]; + eth1.ipv4.addresses = lib.mkOverride 0 [ ]; + br0.ipv4.addresses = [ { address = "192.168.1.1"; prefixLength = 24; } ]; }; }; @@ -44,8 +44,8 @@ in import ./make-test.nix ({ pkgs, lib, ...} : rstp = false; }; networking.interfaces = { - eth1.ip4 = lib.mkOverride 0 [ ]; - br0.ip4 = [{ address = "192.168.1.2"; prefixLength = 24; }]; + eth1.ipv4.addresses = lib.mkOverride 0 [ ]; + br0.ipv4.addresses = [ { address = "192.168.1.2"; prefixLength = 24; } ]; }; }; client_eth1_rstp = { lib, pkgs, ... }: client_base // { @@ -54,8 +54,8 @@ in import ./make-test.nix ({ pkgs, lib, ...} : rstp = true; }; networking.interfaces = { - eth1.ip4 = lib.mkOverride 0 [ ]; - br0.ip4 = [{ address = "192.168.1.2"; prefixLength = 24; }]; + eth1.ipv4.addresses = lib.mkOverride 0 [ ]; + br0.ipv4.addresses = [ { address = "192.168.1.2"; prefixLength = 24; } ]; }; }; }; diff --git a/nixos/tests/ferm.nix b/nixos/tests/ferm.nix index 8f2a8c01eebc..bb7daae118c0 100644 --- a/nixos/tests/ferm.nix +++ b/nixos/tests/ferm.nix @@ -11,8 +11,8 @@ import ./make-test.nix ({ pkgs, ...} : { with pkgs.lib; { networking = { - interfaces.eth1.ip6 = mkOverride 0 [ { address = "fd00::2"; prefixLength = 64; } ]; - interfaces.eth1.ip4 = mkOverride 0 [ { address = "192.168.1.2"; prefixLength = 24; } ]; + interfaces.eth1.ipv6.addresses = mkOverride 0 [ { address = "fd00::2"; prefixLength = 64; } ]; + interfaces.eth1.ipv4.addresses = mkOverride 0 [ { address = "192.168.1.2"; prefixLength = 24; } ]; }; }; server = @@ -20,8 +20,8 @@ import ./make-test.nix ({ pkgs, ...} : { with pkgs.lib; { networking = { - interfaces.eth1.ip6 = mkOverride 0 [ { address = "fd00::1"; prefixLength = 64; } ]; - interfaces.eth1.ip4 = mkOverride 0 [ { address = "192.168.1.1"; prefixLength = 24; } ]; + interfaces.eth1.ipv6.addresses = mkOverride 0 [ { address = "fd00::1"; prefixLength = 64; } ]; + interfaces.eth1.ipv4.addresses = mkOverride 0 [ { address = "192.168.1.1"; prefixLength = 24; } ]; }; services = { diff --git a/nixos/tests/initrd-network-ssh/default.nix b/nixos/tests/initrd-network-ssh/default.nix index 9d476cb1a967..b1f3d147e862 100644 --- a/nixos/tests/initrd-network-ssh/default.nix +++ b/nixos/tests/initrd-network-ssh/default.nix @@ -11,9 +11,7 @@ import ../make-test.nix ({ pkgs, lib, ... }: { config, pkgs, ... }: { boot.kernelParams = [ - "ip=${ - (head config.networking.interfaces.eth1.ip4).address - }:::255.255.255.0::eth1:none" + "ip=${config.networking.primaryIPAddress}:::255.255.255.0::eth1:none" ]; boot.initrd.network = { enable = true; diff --git a/nixos/tests/nat.nix b/nixos/tests/nat.nix index a12b7645bc28..7057158a829b 100644 --- a/nixos/tests/nat.nix +++ b/nixos/tests/nat.nix @@ -35,7 +35,7 @@ import ./make-test.nix ({ pkgs, lib, withFirewall, withConntrackHelpers ? false, { virtualisation.vlans = [ 1 ]; networking.firewall.allowPing = true; networking.defaultGateway = - (pkgs.lib.head nodes.router.config.networking.interfaces.eth2.ip4).address; + (pkgs.lib.head nodes.router.config.networking.interfaces.eth2.ipv4.addresses).address; } (lib.optionalAttrs withConntrackHelpers { networking.firewall.connectionTrackingModules = [ "ftp" ]; diff --git a/nixos/tests/networking.nix b/nixos/tests/networking.nix index bcdbad3bab0c..5cb40af5799e 100644 --- a/nixos/tests/networking.nix +++ b/nixos/tests/networking.nix @@ -21,10 +21,8 @@ let firewall.allowedUDPPorts = [ 547 ]; interfaces = mkOverride 0 (listToAttrs (flip map vlanIfs (n: nameValuePair "eth${toString n}" { - ipAddress = "192.168.${toString n}.1"; - prefixLength = 24; - ipv6Address = "fd00:1234:5678:${toString n}::1"; - ipv6PrefixLength = 64; + ipv4.addresses = [ { address = "192.168.${toString n}.1"; prefixLength = 24; } ]; + ipv6.addresses = [ { address = "fd00:1234:5678:${toString n}::1"; prefixLength = 64; } ]; }))); }; services.dhcpd4 = { @@ -90,12 +88,12 @@ let firewall.allowPing = true; useDHCP = false; defaultGateway = "192.168.1.1"; - interfaces.eth1.ip4 = mkOverride 0 [ + interfaces.eth1.ipv4.addresses = mkOverride 0 [ { address = "192.168.1.2"; prefixLength = 24; } { address = "192.168.1.3"; prefixLength = 32; } { address = "192.168.1.10"; prefixLength = 32; } ]; - interfaces.eth2.ip4 = mkOverride 0 [ + interfaces.eth2.ipv4.addresses = mkOverride 0 [ { address = "192.168.2.2"; prefixLength = 24; } ]; }; @@ -143,12 +141,12 @@ let firewall.allowPing = true; useDHCP = true; interfaces.eth1 = { - ip4 = mkOverride 0 [ ]; - ip6 = mkOverride 0 [ ]; + ipv4.addresses = mkOverride 0 [ ]; + ipv6.addresses = mkOverride 0 [ ]; }; interfaces.eth2 = { - ip4 = mkOverride 0 [ ]; - ip6 = mkOverride 0 [ ]; + ipv4.addresses = mkOverride 0 [ ]; + ipv6.addresses = mkOverride 0 [ ]; }; }; }; @@ -198,10 +196,10 @@ let firewall.allowPing = true; useDHCP = false; interfaces.eth1 = { - ip4 = mkOverride 0 [ ]; + ipv4.addresses = mkOverride 0 [ ]; useDHCP = true; }; - interfaces.eth2.ip4 = mkOverride 0 [ ]; + interfaces.eth2.ipv4.addresses = mkOverride 0 [ ]; }; }; testScript = { nodes, ... }: @@ -241,9 +239,9 @@ let interfaces = [ "eth1" "eth2" ]; driverOptions.mode = "balance-rr"; }; - interfaces.eth1.ip4 = mkOverride 0 [ ]; - interfaces.eth2.ip4 = mkOverride 0 [ ]; - interfaces.bond.ip4 = mkOverride 0 + interfaces.eth1.ipv4.addresses = mkOverride 0 [ ]; + interfaces.eth2.ipv4.addresses = mkOverride 0 [ ]; + interfaces.bond.ipv4.addresses = mkOverride 0 [ { inherit address; prefixLength = 30; } ]; }; }; @@ -274,7 +272,7 @@ let useNetworkd = networkd; firewall.allowPing = true; useDHCP = false; - interfaces.eth1.ip4 = mkOverride 0 + interfaces.eth1.ipv4.addresses = mkOverride 0 [ { inherit address; prefixLength = 24; } ]; }; }; @@ -289,9 +287,9 @@ let firewall.allowPing = true; useDHCP = false; bridges.bridge.interfaces = [ "eth1" "eth2" ]; - interfaces.eth1.ip4 = mkOverride 0 [ ]; - interfaces.eth2.ip4 = mkOverride 0 [ ]; - interfaces.bridge.ip4 = mkOverride 0 + interfaces.eth1.ipv4.addresses = mkOverride 0 [ ]; + interfaces.eth2.ipv4.addresses = mkOverride 0 [ ]; + interfaces.bridge.ipv4.addresses = mkOverride 0 [ { address = "192.168.1.1"; prefixLength = 24; } ]; }; }; @@ -328,7 +326,7 @@ let firewall.allowPing = true; useDHCP = true; macvlans.macvlan.interface = "eth1"; - interfaces.eth1.ip4 = mkOverride 0 [ ]; + interfaces.eth1.ipv4.addresses = mkOverride 0 [ ]; }; }; testScript = { nodes, ... }: @@ -369,9 +367,9 @@ let local = address4; dev = "eth1"; }; - interfaces.eth1.ip4 = mkOverride 0 + interfaces.eth1.ipv4.addresses = mkOverride 0 [ { address = address4; prefixLength = 24; } ]; - interfaces.sit.ip6 = mkOverride 0 + interfaces.sit.ipv6.addresses = mkOverride 0 [ { address = address6; prefixLength = 64; } ]; }; }; @@ -410,9 +408,9 @@ let id = 1; interface = "eth0"; }; - interfaces.eth0.ip4 = mkOverride 0 [ ]; - interfaces.eth1.ip4 = mkOverride 0 [ ]; - interfaces.vlan.ip4 = mkOverride 0 + interfaces.eth0.ipv4.addresses = mkOverride 0 [ ]; + interfaces.eth1.ipv4.addresses = mkOverride 0 [ ]; + interfaces.vlan.ipv4.addresses = mkOverride 0 [ { inherit address; prefixLength = 24; } ]; }; }; @@ -437,13 +435,13 @@ let name = "Virtual"; machine = { networking.interfaces."tap0" = { - ip4 = [ { address = "192.168.1.1"; prefixLength = 24; } ]; - ip6 = [ { address = "2001:1470:fffd:2096::"; prefixLength = 64; } ]; + ipv4.addresses = [ { address = "192.168.1.1"; prefixLength = 24; } ]; + ipv6.addresses = [ { address = "2001:1470:fffd:2096::"; prefixLength = 64; } ]; virtual = true; }; networking.interfaces."tun0" = { - ip4 = [ { address = "192.168.1.2"; prefixLength = 24; } ]; - ip6 = [ { address = "2001:1470:fffd:2097::"; prefixLength = 64; } ]; + ipv4.addresses = [ { address = "192.168.1.2"; prefixLength = 24; } ]; + ipv6.addresses = [ { address = "2001:1470:fffd:2097::"; prefixLength = 64; } ]; virtual = true; }; }; @@ -483,9 +481,9 @@ let boot.kernel.sysctl."net.ipv6.conf.all.forwarding" = true; networking = { useNetworkd = networkd; - interfaces.eth1 = { - ipv6Address = "fd00:1234:5678:1::1"; - ipv6PrefixLength = 64; + interfaces.eth1.ipv6.addresses = singleton { + address = "fd00:1234:5678:1::1"; + prefixLength = 64; }; }; services.radvd = { @@ -511,8 +509,8 @@ let useDHCP = true; interfaces.eth1 = { preferTempAddress = true; - ip4 = mkOverride 0 [ ]; - ip6 = mkOverride 0 [ ]; + ipv4.addresses = mkOverride 0 [ ]; + ipv6.addresses = mkOverride 0 [ ]; }; }; }; @@ -533,6 +531,69 @@ let $client->waitUntilSucceeds("! ip route get fd00:1234:5678:1::1 | grep -q ':[a-f0-9]*ff:fe[a-f0-9]*:'"); ''; }; + routes = { + name = "routes"; + machine = { + networking.useDHCP = false; + networking.interfaces."eth0" = { + ipv4.addresses = [ { address = "192.168.1.2"; prefixLength = 24; } ]; + ipv6.addresses = [ { address = "2001:1470:fffd:2097::"; prefixLength = 64; } ]; + ipv6.routes = [ + { address = "fdfd:b3f0::"; prefixLength = 48; } + { address = "2001:1470:fffd:2098::"; prefixLength = 64; via = "fdfd:b3f0::1"; } + ]; + ipv4.routes = [ + { address = "10.0.0.0"; prefixLength = 16; options = { mtu = "1500"; }; } + { address = "192.168.2.0"; prefixLength = 24; via = "192.168.1.1"; } + ]; + }; + virtualisation.vlans = [ ]; + }; + + testScript = '' + my $targetIPv4Table = <<'END'; + 10.0.0.0/16 scope link mtu 1500 + 192.168.1.0/24 proto kernel scope link src 192.168.1.2 + 192.168.2.0/24 via 192.168.1.1 + END + + my $targetIPv6Table = <<'END'; + 2001:1470:fffd:2097::/64 proto kernel metric 256 pref medium + 2001:1470:fffd:2098::/64 via fdfd:b3f0::1 metric 1024 pref medium + fdfd:b3f0::/48 metric 1024 pref medium + END + + $machine->start; + $machine->waitForUnit("network.target"); + + # test routing tables + my $ipv4Table = $machine->succeed("ip -4 route list dev eth0 | head -n3"); + my $ipv6Table = $machine->succeed("ip -6 route list dev eth0 | head -n3"); + "$ipv4Table" eq "$targetIPv4Table" or die( + "The IPv4 routing table does not match the expected one:\n", + "Result:\n", "$ipv4Table\n", + "Expected:\n", "$targetIPv4Table\n" + ); + "$ipv6Table" eq "$targetIPv6Table" or die( + "The IPv6 routing table does not match the expected one:\n", + "Result:\n", "$ipv6Table\n", + "Expected:\n", "$targetIPv6Table\n" + ); + + # test clean-up of the tables + $machine->succeed("systemctl stop network-addresses-eth0"); + my $ipv4Residue = $machine->succeed("ip -4 route list dev eth0 | head -n-3"); + my $ipv6Residue = $machine->succeed("ip -6 route list dev eth0 | head -n-3"); + $ipv4Residue eq "" or die( + "The IPv4 routing table has not been properly cleaned:\n", + "$ipv4Residue\n" + ); + $ipv6Residue eq "" or die( + "The IPv6 routing table has not been properly cleaned:\n", + "$ipv6Residue\n" + ); + ''; + }; }; in mapAttrs (const (attrs: makeTest (attrs // { diff --git a/nixos/tests/nsd.nix b/nixos/tests/nsd.nix index 0b1082056f6f..ad4d4f822435 100644 --- a/nixos/tests/nsd.nix +++ b/nixos/tests/nsd.nix @@ -15,25 +15,31 @@ in import ./make-test.nix ({ pkgs, ...} : { clientv4 = { lib, nodes, ... }: { imports = [ common ]; networking.nameservers = lib.mkForce [ - nodes.server.config.networking.interfaces.eth1.ipAddress + (lib.head nodes.server.config.networking.interfaces.eth1.ipv4.addresses).address + ]; + networking.interfaces.eth1.ipv4.addresses = [ + { address = "192.168.0.2"; prefixLength = 24; } ]; - networking.interfaces.eth1.ipAddress = "192.168.0.2"; - networking.interfaces.eth1.prefixLength = 24; }; clientv6 = { lib, nodes, ... }: { imports = [ common ]; networking.nameservers = lib.mkForce [ - nodes.server.config.networking.interfaces.eth1.ipv6Address + (lib.head nodes.server.config.networking.interfaces.eth1.ipv6.addresses).address + ]; + networking.interfaces.eth1.ipv4.addresses = [ + { address = "dead:beef::2"; prefixLength = 24; } ]; - networking.interfaces.eth1.ipv6Address = "dead:beef::2"; }; server = { lib, ... }: { imports = [ common ]; - networking.interfaces.eth1.ipAddress = "192.168.0.1"; - networking.interfaces.eth1.prefixLength = 24; - networking.interfaces.eth1.ipv6Address = "dead:beef::1"; + networking.interfaces.eth1.ipv4.addresses = [ + { address = "192.168.0.1"; prefixLength = 24; } + ]; + networking.interfaces.eth1.ipv6.addresses = [ + { address = "dead:beef::1"; prefixLength = 64; } + ]; services.nsd.enable = true; services.nsd.interfaces = lib.mkForce []; services.nsd.zones."example.com.".data = '' diff --git a/nixos/tests/quagga.nix b/nixos/tests/quagga.nix index b9644b4768c0..613180942c41 100644 --- a/nixos/tests/quagga.nix +++ b/nixos/tests/quagga.nix @@ -8,7 +8,7 @@ import ./make-test.nix ({ pkgs, ... }: let - ifAddr = node: iface: (pkgs.lib.head node.config.networking.interfaces.${iface}.ip4).address; + ifAddr = node: iface: (pkgs.lib.head node.config.networking.interfaces.${iface}.ipv4.addresses).address; ospfConf = '' interface eth2