about summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
authorMichael Raskin <7c6f434c@mail.ru>2018-02-19 14:12:58 +0000
committerGitHub <noreply@github.com>2018-02-19 14:12:58 +0000
commit10b3f7d3564d4ef1deeaed7ece130588d5ba1905 (patch)
tree5c551c6f5aa44f598d1bdc00ba23006fb65e13d4 /nixos
parente37b756b91a0713cefdf8a53d78feadcd00a40fc (diff)
parent06517547519737cd4c719b0c8ef78d046816f57e (diff)
downloadnixlib-10b3f7d3564d4ef1deeaed7ece130588d5ba1905.tar
nixlib-10b3f7d3564d4ef1deeaed7ece130588d5ba1905.tar.gz
nixlib-10b3f7d3564d4ef1deeaed7ece130588d5ba1905.tar.bz2
nixlib-10b3f7d3564d4ef1deeaed7ece130588d5ba1905.tar.lz
nixlib-10b3f7d3564d4ef1deeaed7ece130588d5ba1905.tar.xz
nixlib-10b3f7d3564d4ef1deeaed7ece130588d5ba1905.tar.zst
nixlib-10b3f7d3564d4ef1deeaed7ece130588d5ba1905.zip
Merge pull request #27688 from rnhmjoj/routes
nixos/networking-interfaces: make static routes configurable
Diffstat (limited to 'nixos')
-rw-r--r--nixos/doc/manual/configuration/ipv4-config.xml2
-rw-r--r--nixos/doc/manual/configuration/ipv6-config.xml2
-rw-r--r--nixos/doc/manual/release-notes/rl-1803.xml40
-rw-r--r--nixos/lib/build-vms.nix4
-rw-r--r--nixos/modules/services/networking/dhcpcd.nix2
-rw-r--r--nixos/modules/services/security/hologram-agent.nix7
-rw-r--r--nixos/modules/tasks/network-interfaces-scripted.nix77
-rw-r--r--nixos/modules/tasks/network-interfaces-systemd.nix10
-rw-r--r--nixos/modules/tasks/network-interfaces.nix138
-rw-r--r--nixos/modules/virtualisation/virtualbox-host.nix2
-rw-r--r--nixos/tests/bittorrent.nix6
-rw-r--r--nixos/tests/cjdns.nix9
-rw-r--r--nixos/tests/containers-bridge.nix4
-rw-r--r--nixos/tests/containers-extra_veth.nix6
-rw-r--r--nixos/tests/containers-hosts.nix6
-rw-r--r--nixos/tests/containers-macvlans.nix8
-rw-r--r--nixos/tests/containers-physical_interfaces.nix24
-rw-r--r--nixos/tests/containers-reloadable.nix2
-rw-r--r--nixos/tests/containers-restart_networking.nix14
-rw-r--r--nixos/tests/ferm.nix8
-rw-r--r--nixos/tests/initrd-network-ssh/default.nix4
-rw-r--r--nixos/tests/nat.nix2
-rw-r--r--nixos/tests/networking.nix129
-rw-r--r--nixos/tests/nsd.nix22
-rw-r--r--nixos/tests/quagga.nix2
25 files changed, 339 insertions, 191 deletions
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:
 
 <programlisting>
-networking.interfaces.eth0.ip4 = [ { address = "192.168.1.2"; prefixLength = 24; } ];
+networking.interfaces.eth0.ipv4.addresses = [ { address = "192.168.1.2"; prefixLength = 24; } ];
 </programlisting>
 
 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:
 
 <programlisting>
-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; } ];
 </programlisting>
 </para>
 
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:</para>
   </listitem>
   <listitem>
     <para>
-      The option <option>services.xserver.desktopManager.default</option> is now <literal>none</literal> by default.
-      An assertion failure is thrown if WM's and DM's default are <literal>none</literal>.
-      To explicitly run a plain X session without and DM or WM, the newly introduced option <option>services.xserver.plainX</option>
-      must be set to true.
+      In the module <option>networking.interfaces.&lt;name&gt;</option> the
+      following options have been removed:
+      <itemizedlist>
+        <listitem>
+          <para><option>ipAddress</option></para>
+        </listitem>
+        <listitem>
+          <para><option>ipv6Address</option></para>
+        </listitem>
+        <listitem>
+          <para><option>prefixLength</option></para>
+        </listitem>
+        <listitem>
+          <para><option>ipv6PrefixLength</option></para>
+        </listitem>
+        <listitem>
+          <para><option>subnetMask</option></para>
+        </listitem>
+      </itemizedlist>
+      To assign static addresses to an interface the options
+      <option>ipv4.addresses</option> and <option>ipv6.addresses</option>
+      should be used instead.
+      The options <option>ip4</option> and <option>ip6</option> have been
+      renamed to <option>ipv4.addresses</option> <option>ipv6.addresses</option>
+      respectively.
+      The new options <option>ipv4.routes</option> and <option>ipv6.routes</option>
+      have been added to set up static routing.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      The option <option>services.xserver.desktopManager.default</option> is now
+      <literal>none</literal> by default. An assertion failure is thrown if WM's
+      and DM's default are <literal>none</literal>.
+      To explicitly run a plain X session without and DM or WM, the newly
+      introduced option <option>services.xserver.plainX</option> must be set to true.
     </para>
   </listitem>
   <listitem>
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
+                    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 (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 (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 (<literal>${if v == 4 then "24" else "64"}</literal>).
+        '';
+      };
+
+      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 <literal>OPTION</literal>
+          in the <literal>ip-route(8)</literal> 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;
-        description = ''
-          IP address of the interface.  Leave empty to configure the
-          interface using DHCP.
-        '';
-      };
-
-      prefixLength = mkOption {
-        default = null;
-        example = 24;
-        type = types.nullOr types.int;
-        description = ''
-          Subnet mask of the interface, specified as the number of
-          bits in the prefix (<literal>24</literal>).
-        '';
-      };
-
-      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;
+      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 = ''
-          IPv6 address of the interface.  Leave empty to configure the
-          interface using NDP.
+          List of extra IPv4 static routes that will be assigned to the interface.
         '';
       };
 
-      ipv6PrefixLength = mkOption {
-        default = 64;
-        example = 64;
-        type = 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 (<literal>64</literal>).
+          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.<name>.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