2011-02-19 20:21:19 +01:00
|
|
|
# Test of IPv6 functionality in NixOS, including whether router
|
|
|
|
# solicication/advertisement using radvd works.
|
|
|
|
|
2019-12-01 01:08:44 +01:00
|
|
|
import ./make-test-python.nix ({ pkgs, lib, ...} : {
|
2014-06-28 16:04:49 +02:00
|
|
|
name = "ipv6";
|
2015-07-12 12:09:40 +02:00
|
|
|
meta = with pkgs.stdenv.lib.maintainers; {
|
2019-02-22 16:14:13 +01:00
|
|
|
maintainers = [ eelco ];
|
2015-07-12 12:09:40 +02:00
|
|
|
};
|
2011-02-19 20:21:19 +01:00
|
|
|
|
|
|
|
nodes =
|
2019-04-11 19:41:47 +02:00
|
|
|
# Remove the interface configuration provided by makeTest so that the
|
|
|
|
# interfaces are all configured implicitly
|
|
|
|
{ client = { ... }: { networking.interfaces = lib.mkForce {}; };
|
2011-09-14 20:20:50 +02:00
|
|
|
|
2011-02-19 20:21:19 +01:00
|
|
|
server =
|
2018-07-20 22:56:59 +02:00
|
|
|
{ ... }:
|
2011-02-19 20:21:19 +01:00
|
|
|
{ services.httpd.enable = true;
|
|
|
|
services.httpd.adminAddr = "foo@example.org";
|
2014-04-11 17:15:56 +02:00
|
|
|
networking.firewall.allowedTCPPorts = [ 80 ];
|
2011-02-19 20:21:19 +01:00
|
|
|
};
|
|
|
|
|
2011-09-14 20:20:50 +02:00
|
|
|
router =
|
2018-07-20 22:56:59 +02:00
|
|
|
{ ... }:
|
2011-02-19 20:21:19 +01:00
|
|
|
{ services.radvd.enable = true;
|
|
|
|
services.radvd.config =
|
|
|
|
''
|
|
|
|
interface eth1 {
|
|
|
|
AdvSendAdvert on;
|
|
|
|
# ULA prefix (RFC 4193).
|
|
|
|
prefix fd60:cc69:b537:1::/64 { };
|
|
|
|
};
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
testScript =
|
|
|
|
''
|
2019-12-01 01:08:44 +01:00
|
|
|
import re
|
|
|
|
|
2011-02-19 20:21:19 +01:00
|
|
|
# Start the router first so that it respond to router solicitations.
|
2019-12-01 01:08:44 +01:00
|
|
|
router.wait_for_unit("radvd")
|
2011-09-14 20:20:50 +02:00
|
|
|
|
2019-12-01 01:08:44 +01:00
|
|
|
start_all()
|
2011-09-14 20:20:50 +02:00
|
|
|
|
2019-12-01 01:08:44 +01:00
|
|
|
client.wait_for_unit("network.target")
|
|
|
|
server.wait_for_unit("network.target")
|
|
|
|
server.wait_for_unit("httpd.service")
|
2011-02-19 20:21:19 +01:00
|
|
|
|
|
|
|
# Wait until the given interface has a non-tentative address of
|
|
|
|
# the desired scope (i.e. has completed Duplicate Address
|
|
|
|
# Detection).
|
2019-12-08 19:47:15 +01:00
|
|
|
def wait_for_address(machine, iface, scope, temporary=False):
|
|
|
|
temporary_flag = "temporary" if temporary else "-temporary"
|
|
|
|
cmd = f"ip -o -6 addr show dev {iface} scope {scope} -tentative {temporary_flag}"
|
|
|
|
|
|
|
|
machine.wait_until_succeeds(f"[ `{cmd} | wc -l` -eq 1 ]")
|
|
|
|
output = machine.succeed(cmd)
|
2019-12-01 01:08:44 +01:00
|
|
|
ip = re.search(r"inet6 ([0-9a-f:]{2,})/", output).group(1)
|
2019-12-08 19:47:15 +01:00
|
|
|
|
|
|
|
if temporary:
|
|
|
|
scope = scope + " temporary"
|
2019-12-01 01:08:44 +01:00
|
|
|
machine.log(f"{scope} address on {iface} is {ip}")
|
|
|
|
return ip
|
|
|
|
|
|
|
|
|
|
|
|
with subtest("Loopback address can be pinged"):
|
|
|
|
client.succeed("ping -c 1 ::1 >&2")
|
|
|
|
client.fail("ping -c 1 ::2 >&2")
|
2011-09-14 20:20:50 +02:00
|
|
|
|
2019-12-01 01:08:44 +01:00
|
|
|
with subtest("Local link addresses can be obtained and pinged"):
|
|
|
|
client_ip = wait_for_address(client, "eth1", "link")
|
|
|
|
server_ip = wait_for_address(server, "eth1", "link")
|
|
|
|
client.succeed(f"ping -c 1 {client_ip}%eth1 >&2")
|
|
|
|
client.succeed(f"ping -c 1 {server_ip}%eth1 >&2")
|
2011-09-14 20:20:50 +02:00
|
|
|
|
2019-12-01 01:08:44 +01:00
|
|
|
with subtest("Global addresses can be obtained, pinged, and reached via http"):
|
|
|
|
client_ip = wait_for_address(client, "eth1", "global")
|
|
|
|
server_ip = wait_for_address(server, "eth1", "global")
|
|
|
|
client.succeed(f"ping -c 1 {client_ip} >&2")
|
|
|
|
client.succeed(f"ping -c 1 {server_ip} >&2")
|
|
|
|
client.succeed(f"curl --fail -g http://[{server_ip}]")
|
|
|
|
client.fail(f"curl --fail -g http://[{client_ip}]")
|
2011-02-19 20:21:19 +01:00
|
|
|
|
2019-12-01 01:08:44 +01:00
|
|
|
with subtest("Privacy extensions: Global temporary address can be obtained and pinged"):
|
2019-12-08 19:47:15 +01:00
|
|
|
ip = wait_for_address(client, "eth1", "global", temporary=True)
|
2019-04-11 19:41:47 +02:00
|
|
|
# Default route should have "src <temporary address>" in it
|
2019-12-01 01:08:44 +01:00
|
|
|
client.succeed(f"ip r g ::2 | grep {ip}")
|
2011-02-19 20:21:19 +01:00
|
|
|
|
|
|
|
# TODO: test reachability of a machine on another network.
|
|
|
|
'';
|
2015-07-12 12:09:40 +02:00
|
|
|
})
|