628 lines
22 KiB
Nix
628 lines
22 KiB
Nix
{ system ? builtins.currentSystem
|
|
, config ? {}
|
|
, pkgs ? import ../.. { inherit system config; }
|
|
# bool: whether to use networkd in the tests
|
|
, networkd }:
|
|
|
|
with import ../lib/testing.nix { inherit system pkgs; };
|
|
with pkgs.lib;
|
|
|
|
let
|
|
router = { config, pkgs, ... }:
|
|
with pkgs.lib;
|
|
let
|
|
vlanIfs = range 1 (length config.virtualisation.vlans);
|
|
in {
|
|
environment.systemPackages = [ pkgs.iptables ]; # to debug firewall rules
|
|
virtualisation.vlans = [ 1 2 3 ];
|
|
boot.kernel.sysctl."net.ipv6.conf.all.forwarding" = true;
|
|
networking = {
|
|
useDHCP = false;
|
|
useNetworkd = networkd;
|
|
firewall.checkReversePath = true;
|
|
firewall.allowedUDPPorts = [ 547 ];
|
|
interfaces = mkOverride 0 (listToAttrs (forEach vlanIfs (n:
|
|
nameValuePair "eth${toString n}" {
|
|
ipv4.addresses = [ { address = "192.168.${toString n}.1"; prefixLength = 24; } ];
|
|
ipv6.addresses = [ { address = "fd00:1234:5678:${toString n}::1"; prefixLength = 64; } ];
|
|
})));
|
|
};
|
|
services.dhcpd4 = {
|
|
enable = true;
|
|
interfaces = map (n: "eth${toString n}") vlanIfs;
|
|
extraConfig = ''
|
|
authoritative;
|
|
'' + flip concatMapStrings vlanIfs (n: ''
|
|
subnet 192.168.${toString n}.0 netmask 255.255.255.0 {
|
|
option routers 192.168.${toString n}.1;
|
|
# XXX: technically it's _not guaranteed_ that IP addresses will be
|
|
# issued from the first item in range onwards! We assume that in
|
|
# our tests however.
|
|
range 192.168.${toString n}.2 192.168.${toString n}.254;
|
|
}
|
|
'');
|
|
};
|
|
services.radvd = {
|
|
enable = true;
|
|
config = flip concatMapStrings vlanIfs (n: ''
|
|
interface eth${toString n} {
|
|
AdvSendAdvert on;
|
|
AdvManagedFlag on;
|
|
AdvOtherConfigFlag on;
|
|
|
|
prefix fd00:1234:5678:${toString n}::/64 {
|
|
AdvAutonomous off;
|
|
};
|
|
};
|
|
'');
|
|
};
|
|
services.dhcpd6 = {
|
|
enable = true;
|
|
interfaces = map (n: "eth${toString n}") vlanIfs;
|
|
extraConfig = ''
|
|
authoritative;
|
|
'' + flip concatMapStrings vlanIfs (n: ''
|
|
subnet6 fd00:1234:5678:${toString n}::/64 {
|
|
range6 fd00:1234:5678:${toString n}::2 fd00:1234:5678:${toString n}::2;
|
|
}
|
|
'');
|
|
};
|
|
};
|
|
|
|
testCases = {
|
|
loopback = {
|
|
name = "Loopback";
|
|
machine.networking.useNetworkd = networkd;
|
|
testScript = ''
|
|
startAll;
|
|
$machine->waitForUnit("network.target");
|
|
$machine->succeed("ip addr show lo | grep -q 'inet 127.0.0.1/8 '");
|
|
$machine->succeed("ip addr show lo | grep -q 'inet6 ::1/128 '");
|
|
'';
|
|
};
|
|
static = {
|
|
name = "Static";
|
|
nodes.router = router;
|
|
nodes.client = { pkgs, ... }: with pkgs.lib; {
|
|
virtualisation.vlans = [ 1 2 ];
|
|
networking = {
|
|
useNetworkd = networkd;
|
|
useDHCP = false;
|
|
defaultGateway = "192.168.1.1";
|
|
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.ipv4.addresses = mkOverride 0 [
|
|
{ address = "192.168.2.2"; prefixLength = 24; }
|
|
];
|
|
};
|
|
};
|
|
testScript = { ... }:
|
|
''
|
|
startAll;
|
|
|
|
$client->waitForUnit("network.target");
|
|
$router->waitForUnit("network-online.target");
|
|
|
|
# Make sure dhcpcd is not started
|
|
$client->fail("systemctl status dhcpcd.service");
|
|
|
|
# Test vlan 1
|
|
$client->waitUntilSucceeds("ping -c 1 192.168.1.1");
|
|
$client->waitUntilSucceeds("ping -c 1 192.168.1.2");
|
|
$client->waitUntilSucceeds("ping -c 1 192.168.1.3");
|
|
$client->waitUntilSucceeds("ping -c 1 192.168.1.10");
|
|
|
|
$router->waitUntilSucceeds("ping -c 1 192.168.1.1");
|
|
$router->waitUntilSucceeds("ping -c 1 192.168.1.2");
|
|
$router->waitUntilSucceeds("ping -c 1 192.168.1.3");
|
|
$router->waitUntilSucceeds("ping -c 1 192.168.1.10");
|
|
|
|
# Test vlan 2
|
|
$client->waitUntilSucceeds("ping -c 1 192.168.2.1");
|
|
$client->waitUntilSucceeds("ping -c 1 192.168.2.2");
|
|
|
|
$router->waitUntilSucceeds("ping -c 1 192.168.2.1");
|
|
$router->waitUntilSucceeds("ping -c 1 192.168.2.2");
|
|
|
|
# Test default gateway
|
|
$router->waitUntilSucceeds("ping -c 1 192.168.3.1");
|
|
$client->waitUntilSucceeds("ping -c 1 192.168.3.1");
|
|
'';
|
|
};
|
|
dhcpSimple = {
|
|
name = "SimpleDHCP";
|
|
nodes.router = router;
|
|
nodes.client = { pkgs, ... }: with pkgs.lib; {
|
|
virtualisation.vlans = [ 1 2 ];
|
|
networking = {
|
|
useNetworkd = networkd;
|
|
useDHCP = true;
|
|
interfaces.eth1 = {
|
|
ipv4.addresses = mkOverride 0 [ ];
|
|
ipv6.addresses = mkOverride 0 [ ];
|
|
};
|
|
interfaces.eth2 = {
|
|
ipv4.addresses = mkOverride 0 [ ];
|
|
ipv6.addresses = mkOverride 0 [ ];
|
|
};
|
|
};
|
|
};
|
|
testScript = { ... }:
|
|
''
|
|
startAll;
|
|
|
|
$client->waitForUnit("network.target");
|
|
$router->waitForUnit("network-online.target");
|
|
|
|
# Wait until we have an ip address on each interface
|
|
$client->waitUntilSucceeds("ip addr show dev eth1 | grep -q '192.168.1'");
|
|
$client->waitUntilSucceeds("ip addr show dev eth1 | grep -q 'fd00:1234:5678:1:'");
|
|
$client->waitUntilSucceeds("ip addr show dev eth2 | grep -q '192.168.2'");
|
|
$client->waitUntilSucceeds("ip addr show dev eth2 | grep -q 'fd00:1234:5678:2:'");
|
|
|
|
# Test vlan 1
|
|
$client->waitUntilSucceeds("ping -c 1 192.168.1.1");
|
|
$client->waitUntilSucceeds("ping -c 1 192.168.1.2");
|
|
$client->waitUntilSucceeds("ping -c 1 fd00:1234:5678:1::1");
|
|
$client->waitUntilSucceeds("ping -c 1 fd00:1234:5678:1::2");
|
|
|
|
$router->waitUntilSucceeds("ping -c 1 192.168.1.1");
|
|
$router->waitUntilSucceeds("ping -c 1 192.168.1.2");
|
|
$router->waitUntilSucceeds("ping -c 1 fd00:1234:5678:1::1");
|
|
$router->waitUntilSucceeds("ping -c 1 fd00:1234:5678:1::2");
|
|
|
|
# Test vlan 2
|
|
$client->waitUntilSucceeds("ping -c 1 192.168.2.1");
|
|
$client->waitUntilSucceeds("ping -c 1 192.168.2.2");
|
|
$client->waitUntilSucceeds("ping -c 1 fd00:1234:5678:2::1");
|
|
$client->waitUntilSucceeds("ping -c 1 fd00:1234:5678:2::2");
|
|
|
|
$router->waitUntilSucceeds("ping -c 1 192.168.2.1");
|
|
$router->waitUntilSucceeds("ping -c 1 192.168.2.2");
|
|
$router->waitUntilSucceeds("ping -c 1 fd00:1234:5678:2::1");
|
|
$router->waitUntilSucceeds("ping -c 1 fd00:1234:5678:2::2");
|
|
'';
|
|
};
|
|
dhcpOneIf = {
|
|
name = "OneInterfaceDHCP";
|
|
nodes.router = router;
|
|
nodes.client = { pkgs, ... }: with pkgs.lib; {
|
|
virtualisation.vlans = [ 1 2 ];
|
|
networking = {
|
|
useNetworkd = networkd;
|
|
useDHCP = false;
|
|
interfaces.eth1 = {
|
|
ipv4.addresses = mkOverride 0 [ ];
|
|
useDHCP = true;
|
|
};
|
|
interfaces.eth2.ipv4.addresses = mkOverride 0 [ ];
|
|
};
|
|
};
|
|
testScript = { ... }:
|
|
''
|
|
startAll;
|
|
|
|
# Wait for networking to come up
|
|
$client->waitForUnit("network.target");
|
|
$router->waitForUnit("network.target");
|
|
|
|
# Wait until we have an ip address on each interface
|
|
$client->waitUntilSucceeds("ip addr show dev eth1 | grep -q '192.168.1'");
|
|
|
|
# Test vlan 1
|
|
$client->waitUntilSucceeds("ping -c 1 192.168.1.1");
|
|
$client->waitUntilSucceeds("ping -c 1 192.168.1.2");
|
|
|
|
$router->waitUntilSucceeds("ping -c 1 192.168.1.1");
|
|
$router->waitUntilSucceeds("ping -c 1 192.168.1.2");
|
|
|
|
# Test vlan 2
|
|
$client->waitUntilSucceeds("ping -c 1 192.168.2.1");
|
|
$client->fail("ping -c 1 192.168.2.2");
|
|
|
|
$router->waitUntilSucceeds("ping -c 1 192.168.2.1");
|
|
$router->fail("ping -c 1 192.168.2.2");
|
|
'';
|
|
};
|
|
bond = let
|
|
node = address: { pkgs, ... }: with pkgs.lib; {
|
|
virtualisation.vlans = [ 1 2 ];
|
|
networking = {
|
|
useNetworkd = networkd;
|
|
useDHCP = false;
|
|
bonds.bond = {
|
|
interfaces = [ "eth1" "eth2" ];
|
|
driverOptions.mode = "balance-rr";
|
|
};
|
|
interfaces.eth1.ipv4.addresses = mkOverride 0 [ ];
|
|
interfaces.eth2.ipv4.addresses = mkOverride 0 [ ];
|
|
interfaces.bond.ipv4.addresses = mkOverride 0
|
|
[ { inherit address; prefixLength = 30; } ];
|
|
};
|
|
};
|
|
in {
|
|
name = "Bond";
|
|
nodes.client1 = node "192.168.1.1";
|
|
nodes.client2 = node "192.168.1.2";
|
|
testScript = { ... }:
|
|
''
|
|
startAll;
|
|
|
|
# Wait for networking to come up
|
|
$client1->waitForUnit("network.target");
|
|
$client2->waitForUnit("network.target");
|
|
|
|
# Test bonding
|
|
$client1->waitUntilSucceeds("ping -c 2 192.168.1.1");
|
|
$client1->waitUntilSucceeds("ping -c 2 192.168.1.2");
|
|
|
|
$client2->waitUntilSucceeds("ping -c 2 192.168.1.1");
|
|
$client2->waitUntilSucceeds("ping -c 2 192.168.1.2");
|
|
'';
|
|
};
|
|
bridge = let
|
|
node = { address, vlan }: { pkgs, ... }: with pkgs.lib; {
|
|
virtualisation.vlans = [ vlan ];
|
|
networking = {
|
|
useNetworkd = networkd;
|
|
useDHCP = false;
|
|
interfaces.eth1.ipv4.addresses = mkOverride 0
|
|
[ { inherit address; prefixLength = 24; } ];
|
|
};
|
|
};
|
|
in {
|
|
name = "Bridge";
|
|
nodes.client1 = node { address = "192.168.1.2"; vlan = 1; };
|
|
nodes.client2 = node { address = "192.168.1.3"; vlan = 2; };
|
|
nodes.router = { pkgs, ... }: with pkgs.lib; {
|
|
virtualisation.vlans = [ 1 2 ];
|
|
networking = {
|
|
useNetworkd = networkd;
|
|
useDHCP = false;
|
|
bridges.bridge.interfaces = [ "eth1" "eth2" ];
|
|
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; } ];
|
|
};
|
|
};
|
|
testScript = { ... }:
|
|
''
|
|
startAll;
|
|
|
|
# Wait for networking to come up
|
|
$client1->waitForUnit("network.target");
|
|
$client2->waitForUnit("network.target");
|
|
$router->waitForUnit("network.target");
|
|
|
|
# Test bridging
|
|
$client1->waitUntilSucceeds("ping -c 1 192.168.1.1");
|
|
$client1->waitUntilSucceeds("ping -c 1 192.168.1.2");
|
|
$client1->waitUntilSucceeds("ping -c 1 192.168.1.3");
|
|
|
|
$client2->waitUntilSucceeds("ping -c 1 192.168.1.1");
|
|
$client2->waitUntilSucceeds("ping -c 1 192.168.1.2");
|
|
$client2->waitUntilSucceeds("ping -c 1 192.168.1.3");
|
|
|
|
$router->waitUntilSucceeds("ping -c 1 192.168.1.1");
|
|
$router->waitUntilSucceeds("ping -c 1 192.168.1.2");
|
|
$router->waitUntilSucceeds("ping -c 1 192.168.1.3");
|
|
'';
|
|
};
|
|
macvlan = {
|
|
name = "MACVLAN";
|
|
nodes.router = router;
|
|
nodes.client = { pkgs, ... }: with pkgs.lib; {
|
|
environment.systemPackages = [ pkgs.iptables ]; # to debug firewall rules
|
|
virtualisation.vlans = [ 1 ];
|
|
networking = {
|
|
useNetworkd = networkd;
|
|
firewall.logReversePathDrops = true; # to debug firewall rules
|
|
# reverse path filtering rules for the macvlan interface seem
|
|
# to be incorrect, causing the test to fail. Disable temporarily.
|
|
firewall.checkReversePath = false;
|
|
useDHCP = true;
|
|
macvlans.macvlan.interface = "eth1";
|
|
interfaces.eth1.ipv4.addresses = mkOverride 0 [ ];
|
|
};
|
|
};
|
|
testScript = { ... }:
|
|
''
|
|
startAll;
|
|
|
|
# Wait for networking to come up
|
|
$client->waitForUnit("network.target");
|
|
$router->waitForUnit("network.target");
|
|
|
|
# Wait until we have an ip address on each interface
|
|
$client->waitUntilSucceeds("ip addr show dev eth1 | grep -q '192.168.1'");
|
|
$client->waitUntilSucceeds("ip addr show dev macvlan | grep -q '192.168.1'");
|
|
|
|
# Print lots of diagnostic information
|
|
$router->log('**********************************************');
|
|
$router->succeed("ip addr >&2");
|
|
$router->succeed("ip route >&2");
|
|
$router->execute("iptables-save >&2");
|
|
$client->log('==============================================');
|
|
$client->succeed("ip addr >&2");
|
|
$client->succeed("ip route >&2");
|
|
$client->execute("iptables-save >&2");
|
|
$client->log('##############################################');
|
|
|
|
# Test macvlan creates routable ips
|
|
$client->waitUntilSucceeds("ping -c 1 192.168.1.1");
|
|
$client->waitUntilSucceeds("ping -c 1 192.168.1.2");
|
|
$client->waitUntilSucceeds("ping -c 1 192.168.1.3");
|
|
|
|
$router->waitUntilSucceeds("ping -c 1 192.168.1.1");
|
|
$router->waitUntilSucceeds("ping -c 1 192.168.1.2");
|
|
$router->waitUntilSucceeds("ping -c 1 192.168.1.3");
|
|
'';
|
|
};
|
|
sit = let
|
|
node = { address4, remote, address6 }: { pkgs, ... }: with pkgs.lib; {
|
|
virtualisation.vlans = [ 1 ];
|
|
networking = {
|
|
useNetworkd = networkd;
|
|
firewall.enable = false;
|
|
useDHCP = false;
|
|
sits.sit = {
|
|
inherit remote;
|
|
local = address4;
|
|
dev = "eth1";
|
|
};
|
|
interfaces.eth1.ipv4.addresses = mkOverride 0
|
|
[ { address = address4; prefixLength = 24; } ];
|
|
interfaces.sit.ipv6.addresses = mkOverride 0
|
|
[ { address = address6; prefixLength = 64; } ];
|
|
};
|
|
};
|
|
in {
|
|
name = "Sit";
|
|
nodes.client1 = node { address4 = "192.168.1.1"; remote = "192.168.1.2"; address6 = "fc00::1"; };
|
|
nodes.client2 = node { address4 = "192.168.1.2"; remote = "192.168.1.1"; address6 = "fc00::2"; };
|
|
testScript = { ... }:
|
|
''
|
|
startAll;
|
|
|
|
# Wait for networking to be configured
|
|
$client1->waitForUnit("network.target");
|
|
$client2->waitForUnit("network.target");
|
|
|
|
# Print diagnostic information
|
|
$client1->succeed("ip addr >&2");
|
|
$client2->succeed("ip addr >&2");
|
|
|
|
# Test ipv6
|
|
$client1->waitUntilSucceeds("ping -c 1 fc00::1");
|
|
$client1->waitUntilSucceeds("ping -c 1 fc00::2");
|
|
|
|
$client2->waitUntilSucceeds("ping -c 1 fc00::1");
|
|
$client2->waitUntilSucceeds("ping -c 1 fc00::2");
|
|
'';
|
|
};
|
|
vlan = let
|
|
node = address: { pkgs, ... }: with pkgs.lib; {
|
|
#virtualisation.vlans = [ 1 ];
|
|
networking = {
|
|
useNetworkd = networkd;
|
|
useDHCP = false;
|
|
vlans.vlan = {
|
|
id = 1;
|
|
interface = "eth0";
|
|
};
|
|
interfaces.eth0.ipv4.addresses = mkOverride 0 [ ];
|
|
interfaces.eth1.ipv4.addresses = mkOverride 0 [ ];
|
|
interfaces.vlan.ipv4.addresses = mkOverride 0
|
|
[ { inherit address; prefixLength = 24; } ];
|
|
};
|
|
};
|
|
in {
|
|
name = "vlan";
|
|
nodes.client1 = node "192.168.1.1";
|
|
nodes.client2 = node "192.168.1.2";
|
|
testScript = { ... }:
|
|
''
|
|
startAll;
|
|
|
|
# Wait for networking to be configured
|
|
$client1->waitForUnit("network.target");
|
|
$client2->waitForUnit("network.target");
|
|
|
|
# Test vlan is setup
|
|
$client1->succeed("ip addr show dev vlan >&2");
|
|
$client2->succeed("ip addr show dev vlan >&2");
|
|
'';
|
|
};
|
|
virtual = {
|
|
name = "Virtual";
|
|
machine = {
|
|
networking.interfaces.tap0 = {
|
|
ipv4.addresses = [ { address = "192.168.1.1"; prefixLength = 24; } ];
|
|
ipv6.addresses = [ { address = "2001:1470:fffd:2096::"; prefixLength = 64; } ];
|
|
virtual = true;
|
|
};
|
|
networking.interfaces.tun0 = {
|
|
ipv4.addresses = [ { address = "192.168.1.2"; prefixLength = 24; } ];
|
|
ipv6.addresses = [ { address = "2001:1470:fffd:2097::"; prefixLength = 64; } ];
|
|
virtual = true;
|
|
};
|
|
};
|
|
|
|
testScript = ''
|
|
my $targetList = <<'END';
|
|
tap0: tap persist user 0
|
|
tun0: tun persist user 0
|
|
END
|
|
|
|
# Wait for networking to come up
|
|
$machine->start;
|
|
$machine->waitForUnit("network-online.target");
|
|
|
|
# Test interfaces set up
|
|
my $list = $machine->succeed("ip tuntap list | sort");
|
|
"$list" eq "$targetList" or die(
|
|
"The list of virtual interfaces does not match the expected one:\n",
|
|
"Result:\n", "$list\n",
|
|
"Expected:\n", "$targetList\n"
|
|
);
|
|
|
|
# Test interfaces clean up
|
|
$machine->succeed("systemctl stop network-addresses-tap0");
|
|
$machine->sleep(10);
|
|
$machine->succeed("systemctl stop network-addresses-tun0");
|
|
$machine->sleep(10);
|
|
my $residue = $machine->succeed("ip tuntap list");
|
|
$residue eq "" or die(
|
|
"Some virtual interface has not been properly cleaned:\n",
|
|
"$residue\n"
|
|
);
|
|
'';
|
|
};
|
|
privacy = {
|
|
name = "Privacy";
|
|
nodes.router = { ... }: {
|
|
virtualisation.vlans = [ 1 ];
|
|
boot.kernel.sysctl."net.ipv6.conf.all.forwarding" = true;
|
|
networking = {
|
|
useNetworkd = networkd;
|
|
interfaces.eth1.ipv6.addresses = singleton {
|
|
address = "fd00:1234:5678:1::1";
|
|
prefixLength = 64;
|
|
};
|
|
};
|
|
services.radvd = {
|
|
enable = true;
|
|
config = ''
|
|
interface eth1 {
|
|
AdvSendAdvert on;
|
|
AdvManagedFlag on;
|
|
AdvOtherConfigFlag on;
|
|
|
|
prefix fd00:1234:5678:1::/64 {
|
|
AdvAutonomous on;
|
|
AdvOnLink on;
|
|
};
|
|
};
|
|
'';
|
|
};
|
|
};
|
|
nodes.clientWithPrivacy = { pkgs, ... }: with pkgs.lib; {
|
|
virtualisation.vlans = [ 1 ];
|
|
networking = {
|
|
useNetworkd = networkd;
|
|
useDHCP = true;
|
|
interfaces.eth1 = {
|
|
preferTempAddress = true;
|
|
ipv4.addresses = mkOverride 0 [ ];
|
|
ipv6.addresses = mkOverride 0 [ ];
|
|
};
|
|
};
|
|
};
|
|
nodes.client = { pkgs, ... }: with pkgs.lib; {
|
|
virtualisation.vlans = [ 1 ];
|
|
networking = {
|
|
useNetworkd = networkd;
|
|
useDHCP = true;
|
|
interfaces.eth1 = {
|
|
preferTempAddress = false;
|
|
ipv4.addresses = mkOverride 0 [ ];
|
|
ipv6.addresses = mkOverride 0 [ ];
|
|
};
|
|
};
|
|
};
|
|
testScript = { ... }:
|
|
''
|
|
startAll;
|
|
|
|
$client->waitForUnit("network.target");
|
|
$clientWithPrivacy->waitForUnit("network.target");
|
|
$router->waitForUnit("network-online.target");
|
|
|
|
# Wait until we have an ip address
|
|
$clientWithPrivacy->waitUntilSucceeds("ip addr show dev eth1 | grep -q 'fd00:1234:5678:1:'");
|
|
$client->waitUntilSucceeds("ip addr show dev eth1 | grep -q 'fd00:1234:5678:1:'");
|
|
|
|
# Test vlan 1
|
|
$clientWithPrivacy->waitUntilSucceeds("ping -c 1 fd00:1234:5678:1::1");
|
|
$client->waitUntilSucceeds("ping -c 1 fd00:1234:5678:1::1");
|
|
|
|
# Test address used is temporary
|
|
$clientWithPrivacy->waitUntilSucceeds("! ip route get fd00:1234:5678:1::1 | grep -q ':[a-f0-9]*ff:fe[a-f0-9]*:'");
|
|
|
|
# Test address used is EUI-64
|
|
$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 proto static 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 proto static
|
|
END
|
|
|
|
my $targetIPv6Table = <<'END';
|
|
2001:1470:fffd:2097::/64 proto kernel metric 256 pref medium
|
|
2001:1470:fffd:2098::/64 via fdfd:b3f0::1 proto static metric 1024 pref medium
|
|
fdfd:b3f0::/48 proto static 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 // {
|
|
name = "${attrs.name}-Networking-${if networkd then "Networkd" else "Scripted"}";
|
|
}))) testCases
|