Merge pull request #27688 from rnhmjoj/routes

nixos/networking-interfaces: make static routes configurable

+1 -1
nixos/doc/manual/configuration/ipv4-config.xml
···
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
+1 -1
nixos/doc/manual/configuration/ipv6-config.xml
···
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>
+36 -4
nixos/doc/manual/release-notes/rl-1803.xml
···
</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>
+2 -2
nixos/lib/build-vms.nix
···
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;
} ];
···
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
+1 -1
nixos/modules/services/networking/dhcpcd.nix
···
# 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))
+3 -4
nixos/modules/services/security/hologram-agent.nix
···
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";
+48 -29
nixos/modules/tasks/network-interfaces-scripted.nix
···
"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
···
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"
'';
+2 -8
nixos/modules/tasks/network-interfaces-systemd.nix
···
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";
+87 -51
nixos/modules/tasks/network-interfaces.nix
···
-
{ config, lib, pkgs, utils, stdenv, ... }:
+
{ config, options, lib, pkgs, utils, stdenv, ... }:
with lib;
with utils;
···
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.
'';
};
···
};
};
+
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 = { ... }: {
···
interfaceOpts = { name, ... }: {
options = {
-
name = mkOption {
example = "eth0";
type = types.str;
···
'';
};
-
ip4 = mkOption {
+
ipv4.addresses = mkOption {
default = [ ];
example = [
{ address = "10.0.0.1"; prefixLength = 16; }
···
'';
};
-
ip6 = mkOption {
+
ipv6.addresses = mkOption {
default = [ ];
example = [
{ address = "fdfd:b3f0:482::1"; prefixLength = 48; }
···
'';
};
-
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.
'';
};
···
config = {
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; })
+
];
};
···
networking.interfaces = mkOption {
default = {};
example =
-
{ eth0.ip4 = [ {
+
{ eth0.ipv4 = [ {
address = "131.211.84.78";
prefixLength = 25;
} ];
···
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
···
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.
'';
···
'' + 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)
'';
})));
+1 -1
nixos/modules/virtualisation/virtualbox-host.nix
···
'';
};
-
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"];
+3 -3
nixos/tests/bittorrent.nix
···
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
'';
···
{ 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;
};
···
# 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
+6 -3
nixos/tests/cjdns.nix
···
# 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;
···
{ 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 =
···
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 ];
+2 -2
nixos/tests/containers-bridge.nix
···
};
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; }];
};
};
+3 -3
nixos/tests/containers-extra_veth.nix
···
};
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; }];
};
};
+3 -3
nixos/tests/containers-hosts.nix
···
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 ''
+4 -4
nixos/tests/containers-macvlans.nix
···
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 = {
···
config = {
networking.interfaces.mv-eth1 = {
-
ip4 = [ { address = containerIp1; prefixLength = 24; } ];
+
ipv4.addresses = [ { address = containerIp1; prefixLength = 24; } ];
};
};
};
···
config = {
networking.interfaces.mv-eth1 = {
-
ip4 = [ { address = containerIp2; prefixLength = 24; } ];
+
ipv4.addresses = [ { address = containerIp2; prefixLength = 24; } ];
};
};
};
+12 -12
nixos/tests/containers-physical_interfaces.nix
···
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;
};
};
···
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;
};
};
···
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;
};
};
···
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;
};
};
+1 -1
nixos/tests/containers-reloadable.nix
···
# prevent make-test.nix to change IP
networking.interfaces = {
-
eth1.ip4 = lib.mkOverride 0 [ ];
+
eth1.ipv4.addresses = lib.mkOverride 0 [ ];
};
};
in {
+7 -7
nixos/tests/containers-restart_networking.nix
···
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; }
];
};
···
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; } ];
};
};
···
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 // {
···
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; } ];
};
};
};
+4 -4
nixos/tests/ferm.nix
···
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 =
···
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 = {
+1 -3
nixos/tests/initrd-network-ssh/default.nix
···
{ 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;
+1 -1
nixos/tests/nat.nix
···
{ 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" ];
+95 -34
nixos/tests/networking.nix
···
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 = {
···
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; }
];
};
···
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 [ ];
};
};
};
···
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, ... }:
···
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; } ];
};
};
···
useNetworkd = networkd;
firewall.allowPing = true;
useDHCP = false;
-
interfaces.eth1.ip4 = mkOverride 0
+
interfaces.eth1.ipv4.addresses = mkOverride 0
[ { inherit address; prefixLength = 24; } ];
};
};
···
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; } ];
};
};
···
firewall.allowPing = true;
useDHCP = true;
macvlans.macvlan.interface = "eth1";
-
interfaces.eth1.ip4 = mkOverride 0 [ ];
+
interfaces.eth1.ipv4.addresses = mkOverride 0 [ ];
};
};
testScript = { nodes, ... }:
···
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; } ];
};
};
···
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; } ];
};
};
···
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;
};
};
···
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 = {
···
useDHCP = true;
interfaces.eth1 = {
preferTempAddress = true;
-
ip4 = mkOverride 0 [ ];
-
ip6 = mkOverride 0 [ ];
+
ipv4.addresses = mkOverride 0 [ ];
+
ipv6.addresses = mkOverride 0 [ ];
};
};
};
···
# Test address used is temporary
$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"
+
);
+
'';
};
};
+14 -8
nixos/tests/nsd.nix
···
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.ipAddress = "192.168.0.2";
-
networking.interfaces.eth1.prefixLength = 24;
+
networking.interfaces.eth1.ipv4.addresses = [
+
{ address = "192.168.0.2"; 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.ipv6Address = "dead:beef::2";
+
networking.interfaces.eth1.ipv4.addresses = [
+
{ address = "dead:beef::2"; prefixLength = 24; }
+
];
};
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 = ''
+1 -1
nixos/tests/quagga.nix
···
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