1 { system ? builtins.currentSystem
3 , pkgs ? import ../.. { inherit system config; }
4 # bool: whether to use networkd in the tests
7 with import ../lib/testing-python.nix { inherit system pkgs; };
11 qemu-common = import ../lib/qemu-common.nix { inherit (pkgs) lib pkgs; };
13 router = { config, pkgs, lib, ... }:
16 vlanIfs = range 1 (length config.virtualisation.vlans);
18 environment.systemPackages = [ pkgs.iptables ]; # to debug firewall rules
19 virtualisation.vlans = [ 1 2 3 ];
20 boot.kernel.sysctl."net.ipv6.conf.all.forwarding" = true;
23 useNetworkd = networkd;
24 firewall.checkReversePath = true;
25 firewall.allowedUDPPorts = [ 547 ];
26 interfaces = mkOverride 0 (listToAttrs (forEach vlanIfs (n:
27 nameValuePair "eth${toString n}" {
28 ipv4.addresses = [ { address = "192.168.${toString n}.1"; prefixLength = 24; } ];
29 ipv6.addresses = [ { address = "fd00:1234:5678:${toString n}::1"; prefixLength = 64; } ];
37 interfaces = map (n: "eth${toString n}") vlanIfs;
38 dhcp-socket-type = "raw";
39 service-sockets-require-all = true;
40 service-sockets-max-retries = 5;
41 service-sockets-retry-wait-time = 2500;
45 subnet = "192.168.${toString n}.0/24";
46 pools = [{ pool = "192.168.${toString n}.3 - 192.168.${toString n}.254"; }];
47 option-data = [{ name = "routers"; data = "192.168.${toString n}.1"; }];
50 hw-address = qemu-common.qemuNicMac n 1;
51 hostname = "client${toString n}";
52 ip-address = "192.168.${toString n}.2";
61 interfaces = map (n: "eth${toString n}") vlanIfs;
62 service-sockets-require-all = true;
63 service-sockets-max-retries = 5;
64 service-sockets-retry-wait-time = 2500;
69 subnet = "fd00:1234:5678:${toString n}::/64";
70 interface = "eth${toString n}";
71 pools = [{ pool = "fd00:1234:5678:${toString n}::2-fd00:1234:5678:${toString n}::2"; }];
78 config = flip concatMapStrings vlanIfs (n: ''
79 interface eth${toString n} {
82 AdvOtherConfigFlag on;
84 prefix fd00:1234:5678:${toString n}::/64 {
95 nodes.client = { pkgs, ... }: with pkgs.lib; {
96 networking.useDHCP = false;
97 networking.useNetworkd = networkd;
101 client.wait_for_unit("network.target")
102 loopback_addresses = client.succeed("ip addr show lo")
103 assert "inet 127.0.0.1/8" in loopback_addresses
104 assert "inet6 ::1/128" in loopback_addresses
109 nodes.router = router;
110 nodes.client = { pkgs, ... }: with pkgs.lib; {
111 virtualisation.interfaces.enp1s0.vlan = 1;
112 virtualisation.interfaces.enp2s0.vlan = 2;
114 useNetworkd = networkd;
116 defaultGateway = "192.168.1.1";
117 defaultGateway6 = "fd00:1234:5678:1::1";
118 interfaces.enp1s0.ipv4.addresses = [
119 { address = "192.168.1.2"; prefixLength = 24; }
120 { address = "192.168.1.3"; prefixLength = 32; }
121 { address = "192.168.1.10"; prefixLength = 32; }
123 interfaces.enp2s0.ipv4.addresses = [
124 { address = "192.168.2.2"; prefixLength = 24; }
128 testScript = { ... }:
132 client.wait_for_unit("network.target")
133 router.wait_for_unit("network-online.target")
135 with subtest("Make sure DHCP server is not started"):
136 client.fail("systemctl status kea-dhcp4-server.service")
137 client.fail("systemctl status kea-dhcp6-server.service")
139 with subtest("Test vlan 1"):
140 client.wait_until_succeeds("ping -c 1 192.168.1.1")
141 client.wait_until_succeeds("ping -c 1 192.168.1.2")
142 client.wait_until_succeeds("ping -c 1 192.168.1.3")
143 client.wait_until_succeeds("ping -c 1 192.168.1.10")
145 router.wait_until_succeeds("ping -c 1 192.168.1.1")
146 router.wait_until_succeeds("ping -c 1 192.168.1.2")
147 router.wait_until_succeeds("ping -c 1 192.168.1.3")
148 router.wait_until_succeeds("ping -c 1 192.168.1.10")
150 with subtest("Test vlan 2"):
151 client.wait_until_succeeds("ping -c 1 192.168.2.1")
152 client.wait_until_succeeds("ping -c 1 192.168.2.2")
154 router.wait_until_succeeds("ping -c 1 192.168.2.1")
155 router.wait_until_succeeds("ping -c 1 192.168.2.2")
157 with subtest("Test default gateway"):
158 router.wait_until_succeeds("ping -c 1 192.168.3.1")
159 client.wait_until_succeeds("ping -c 1 192.168.3.1")
160 router.wait_until_succeeds("ping -c 1 fd00:1234:5678:3::1")
161 client.wait_until_succeeds("ping -c 1 fd00:1234:5678:3::1")
166 nodes.client = { pkgs, ... }: with pkgs.lib; {
169 useNetworkd = networkd;
170 interfaces.eth1.ipv4.routes = [{
171 address = "192.168.1.127";
179 client.wait_for_unit("network.target")
180 client.succeed("ip -4 route list table local | grep 'local 192.168.1.127'")
184 name = "useDHCP-by-default";
185 nodes.router = router;
186 nodes.client = { lib, ... }: {
187 # Disable test driver default config
188 networking.interfaces = lib.mkForce {};
189 networking.useNetworkd = networkd;
190 virtualisation.interfaces.enp1s0.vlan = 1;
194 client.wait_for_unit("multi-user.target")
195 client.wait_until_succeeds("ip addr show dev enp1s0 | grep '192.168.1'")
196 client.shell_interact()
197 client.succeed("ping -c 1 192.168.1.1")
198 router.succeed("ping -c 1 192.168.1.1")
199 router.succeed("ping -c 1 192.168.1.2")
200 client.succeed("ping -c 1 192.168.1.2")
205 nodes.router = router;
206 nodes.client = { pkgs, ... }: with pkgs.lib; {
207 virtualisation.interfaces.enp1s0.vlan = 1;
208 virtualisation.interfaces.enp2s0.vlan = 2;
210 useNetworkd = networkd;
212 interfaces.enp1s0.useDHCP = true;
213 interfaces.enp2s0.useDHCP = true;
216 testScript = { ... }:
220 client.wait_for_unit("network.target")
221 router.wait_for_unit("network-online.target")
223 with subtest("Wait until we have an ip address on each interface"):
224 client.wait_until_succeeds("ip addr show dev enp1s0 | grep -q '192.168.1'")
225 client.wait_until_succeeds("ip addr show dev enp1s0 | grep -q 'fd00:1234:5678:1:'")
226 client.wait_until_succeeds("ip addr show dev enp2s0 | grep -q '192.168.2'")
227 client.wait_until_succeeds("ip addr show dev enp2s0 | grep -q 'fd00:1234:5678:2:'")
229 with subtest("Test vlan 1"):
230 client.wait_until_succeeds("ping -c 1 192.168.1.1")
231 client.wait_until_succeeds("ping -c 1 192.168.1.2")
232 client.wait_until_succeeds("ping -c 1 fd00:1234:5678:1::1")
233 client.wait_until_succeeds("ping -c 1 fd00:1234:5678:1::2")
235 router.wait_until_succeeds("ping -c 1 192.168.1.1")
236 router.wait_until_succeeds("ping -c 1 192.168.1.2")
237 router.wait_until_succeeds("ping -c 1 fd00:1234:5678:1::1")
238 router.wait_until_succeeds("ping -c 1 fd00:1234:5678:1::2")
240 with subtest("Test vlan 2"):
241 client.wait_until_succeeds("ping -c 1 192.168.2.1")
242 client.wait_until_succeeds("ping -c 1 192.168.2.2")
243 client.wait_until_succeeds("ping -c 1 fd00:1234:5678:2::1")
244 client.wait_until_succeeds("ping -c 1 fd00:1234:5678:2::2")
246 router.wait_until_succeeds("ping -c 1 192.168.2.1")
247 router.wait_until_succeeds("ping -c 1 192.168.2.2")
248 router.wait_until_succeeds("ping -c 1 fd00:1234:5678:2::1")
249 router.wait_until_succeeds("ping -c 1 fd00:1234:5678:2::2")
253 name = "OneInterfaceDHCP";
254 nodes.router = router;
255 nodes.client = { pkgs, ... }: with pkgs.lib; {
256 virtualisation.interfaces.enp1s0.vlan = 1;
257 virtualisation.interfaces.enp2s0.vlan = 2;
259 useNetworkd = networkd;
261 interfaces.enp1s0 = {
267 testScript = { ... }:
271 with subtest("Wait for networking to come up"):
272 client.wait_for_unit("network.target")
273 router.wait_for_unit("network.target")
275 with subtest("Wait until we have an ip address on each interface"):
276 client.wait_until_succeeds("ip addr show dev enp1s0 | grep -q '192.168.1'")
278 with subtest("ensure MTU is set"):
279 assert "mtu 1343" in client.succeed("ip link show dev enp1s0")
281 with subtest("Test vlan 1"):
282 client.wait_until_succeeds("ping -c 1 192.168.1.1")
283 client.wait_until_succeeds("ping -c 1 192.168.1.2")
285 router.wait_until_succeeds("ping -c 1 192.168.1.1")
286 router.wait_until_succeeds("ping -c 1 192.168.1.2")
288 with subtest("Test vlan 2"):
289 client.wait_until_succeeds("ping -c 1 192.168.2.1")
290 client.fail("ping -c 1 192.168.2.2")
292 router.wait_until_succeeds("ping -c 1 192.168.2.1")
293 router.fail("ping -c 1 192.168.2.2")
297 node = address: { pkgs, ... }: with pkgs.lib; {
298 virtualisation.interfaces.enp1s0.vlan = 1;
299 virtualisation.interfaces.enp2s0.vlan = 2;
301 useNetworkd = networkd;
304 interfaces = [ "enp1s0" "enp2s0" ];
305 driverOptions.mode = "802.3ad";
307 interfaces.bond0.ipv4.addresses = mkOverride 0
308 [ { inherit address; prefixLength = 30; } ];
313 nodes.client1 = node "192.168.1.1";
314 nodes.client2 = node "192.168.1.2";
315 testScript = { ... }:
319 with subtest("Wait for networking to come up"):
320 client1.wait_for_unit("network.target")
321 client2.wait_for_unit("network.target")
323 with subtest("Test bonding"):
324 client1.wait_until_succeeds("ping -c 2 192.168.1.1")
325 client1.wait_until_succeeds("ping -c 2 192.168.1.2")
327 client2.wait_until_succeeds("ping -c 2 192.168.1.1")
328 client2.wait_until_succeeds("ping -c 2 192.168.1.2")
330 with subtest("Verify bonding mode"):
331 for client in client1, client2:
332 client.succeed('grep -q "Bonding Mode: IEEE 802.3ad Dynamic link aggregation" /proc/net/bonding/bond0')
336 node = { address, vlan }: { pkgs, ... }: with pkgs.lib; {
337 virtualisation.interfaces.enp1s0.vlan = vlan;
339 useNetworkd = networkd;
341 interfaces.enp1s0.ipv4.addresses = [ { inherit address; prefixLength = 24; } ];
346 nodes.client1 = node { address = "192.168.1.2"; vlan = 1; };
347 nodes.client2 = node { address = "192.168.1.3"; vlan = 2; };
348 nodes.router = { pkgs, ... }: with pkgs.lib; {
349 virtualisation.interfaces.enp1s0.vlan = 1;
350 virtualisation.interfaces.enp2s0.vlan = 2;
352 useNetworkd = networkd;
354 bridges.bridge.interfaces = [ "enp1s0" "enp2s0" ];
355 interfaces.eth1.ipv4.addresses = mkOverride 0 [ ];
356 interfaces.eth2.ipv4.addresses = mkOverride 0 [ ];
357 interfaces.bridge.ipv4.addresses = mkOverride 0
358 [ { address = "192.168.1.1"; prefixLength = 24; } ];
361 testScript = { ... }:
365 with subtest("Wait for networking to come up"):
366 for machine in client1, client2, router:
367 machine.wait_for_unit("network.target")
369 with subtest("Test bridging"):
370 client1.wait_until_succeeds("ping -c 1 192.168.1.1")
371 client1.wait_until_succeeds("ping -c 1 192.168.1.2")
372 client1.wait_until_succeeds("ping -c 1 192.168.1.3")
374 client2.wait_until_succeeds("ping -c 1 192.168.1.1")
375 client2.wait_until_succeeds("ping -c 1 192.168.1.2")
376 client2.wait_until_succeeds("ping -c 1 192.168.1.3")
378 router.wait_until_succeeds("ping -c 1 192.168.1.1")
379 router.wait_until_succeeds("ping -c 1 192.168.1.2")
380 router.wait_until_succeeds("ping -c 1 192.168.1.3")
385 nodes.router = router;
386 nodes.client = { pkgs, ... }: with pkgs.lib; {
387 environment.systemPackages = [ pkgs.iptables ]; # to debug firewall rules
388 virtualisation.interfaces.enp1s0.vlan = 1;
390 useNetworkd = networkd;
392 firewall.logReversePathDrops = true; # to debug firewall rules
393 # reverse path filtering rules for the macvlan interface seem
394 # to be incorrect, causing the test to fail. Disable temporarily.
395 firewall.checkReversePath = false;
396 macvlans.macvlan.interface = "enp1s0";
397 interfaces.enp1s0.useDHCP = true;
398 interfaces.macvlan.useDHCP = true;
401 testScript = { ... }:
405 with subtest("Wait for networking to come up"):
406 client.wait_for_unit("network.target")
407 router.wait_for_unit("network.target")
409 with subtest("Wait until we have an ip address on each interface"):
410 client.wait_until_succeeds("ip addr show dev enp1s0 | grep -q '192.168.1'")
411 client.wait_until_succeeds("ip addr show dev macvlan | grep -q '192.168.1'")
413 with subtest("Print lots of diagnostic information"):
414 router.log("**********************************************")
415 router.succeed("ip addr >&2")
416 router.succeed("ip route >&2")
417 router.execute("iptables-save >&2")
418 client.log("==============================================")
419 client.succeed("ip addr >&2")
420 client.succeed("ip route >&2")
421 client.execute("iptables-save >&2")
422 client.log("##############################################")
424 with subtest("Test macvlan creates routable ips"):
425 client.wait_until_succeeds("ping -c 1 192.168.1.1")
426 client.wait_until_succeeds("ping -c 1 192.168.1.2")
427 client.wait_until_succeeds("ping -c 1 192.168.1.3")
429 router.wait_until_succeeds("ping -c 1 192.168.1.1")
430 router.wait_until_succeeds("ping -c 1 192.168.1.2")
431 router.wait_until_succeeds("ping -c 1 192.168.1.3")
435 name = "foo-over-udp";
436 nodes.machine = { ... }: {
437 virtualisation.interfaces.enp1s0.vlan = 1;
439 useNetworkd = networkd;
441 interfaces.enp1s0.ipv4.addresses = [ { address = "192.168.1.1"; prefixLength = 24; } ];
443 fou1 = { port = 9001; };
444 fou2 = { port = 9002; protocol = 41; };
445 fou3 = mkIf (!networkd)
446 { port = 9003; local.address = "192.168.1.1"; };
447 fou4 = mkIf (!networkd)
448 { port = 9004; local = { address = "192.168.1.1"; dev = "enp1s0"; }; };
452 fou3-fou-encap.after = optional (!networkd) "network-addresses-enp1s0.service";
455 testScript = { ... }:
459 machine.wait_for_unit("network.target")
460 fous = json.loads(machine.succeed("ip -json fou show"))
461 assert {"port": 9001, "gue": None, "family": "inet"} in fous, "fou1 exists"
462 assert {"port": 9002, "ipproto": 41, "family": "inet"} in fous, "fou2 exists"
463 '' + optionalString (!networkd) ''
468 "local": "192.168.1.1",
469 } in fous, "fou3 exists"
474 "local": "192.168.1.1",
476 } in fous, "fou4 exists"
480 node = { address4, remote, address6 }: { pkgs, ... }: with pkgs.lib; {
481 virtualisation.interfaces.enp1s0.vlan = 1;
483 useNetworkd = networkd;
490 interfaces.enp1s0.ipv4.addresses = mkOverride 0
491 [ { address = address4; prefixLength = 24; } ];
492 interfaces.sit.ipv6.addresses = mkOverride 0
493 [ { address = address6; prefixLength = 64; } ];
498 # note on firewalling: the two nodes are explicitly asymmetric.
499 # client1 sends SIT packets in UDP, but accepts only proto-41 incoming.
500 # client2 does the reverse, sending in proto-41 and accepting only UDP incoming.
501 # that way we'll notice when either SIT itself or FOU breaks.
502 nodes.client1 = args@{ pkgs, ... }:
504 (node { address4 = "192.168.1.1"; remote = "192.168.1.2"; address6 = "fc00::1"; } args)
507 firewall.extraCommands = "iptables -A INPUT -p 41 -j ACCEPT";
508 sits.sit.encapsulation = { type = "fou"; port = 9001; };
512 nodes.client2 = args@{ pkgs, ... }:
514 (node { address4 = "192.168.1.2"; remote = "192.168.1.1"; address6 = "fc00::2"; } args)
517 firewall.allowedUDPPorts = [ 9001 ];
518 fooOverUDP.fou1 = { port = 9001; protocol = 41; };
522 testScript = { ... }:
526 with subtest("Wait for networking to be configured"):
527 client1.wait_for_unit("network.target")
528 client2.wait_for_unit("network.target")
530 # Print diagnostic information
531 client1.succeed("ip addr >&2")
532 client2.succeed("ip addr >&2")
534 with subtest("Test ipv6"):
535 client1.wait_until_succeeds("ping -c 1 fc00::1")
536 client1.wait_until_succeeds("ping -c 1 fc00::2")
538 client2.wait_until_succeeds("ping -c 1 fc00::1")
539 client2.wait_until_succeeds("ping -c 1 fc00::2")
543 node = { pkgs, ... }: with pkgs.lib; {
545 useNetworkd = networkd;
547 firewall.extraCommands = "ip6tables -A nixos-fw -p gre -j nixos-fw-accept";
552 nodes.client1 = args@{ pkgs, ... }:
556 virtualisation.vlans = [ 1 2 4 ];
560 local = "192.168.2.1";
561 remote = "192.168.2.2";
567 local = "fd00:1234:5678:4::1";
568 remote = "fd00:1234:5678:4::2";
574 bridges.bridge.interfaces = [ "greTunnel" "eth1" ];
575 interfaces.eth1.ipv4.addresses = mkOverride 0 [];
576 interfaces.bridge.ipv4.addresses = mkOverride 0 [
577 { address = "192.168.1.1"; prefixLength = 24; }
579 interfaces.eth3.ipv6.addresses = [
580 { address = "fd00:1234:5678:4::1"; prefixLength = 64; }
582 interfaces.gre6Tunnel.ipv6.addresses = mkOverride 0 [
583 { address = "fc00::1"; prefixLength = 64; }
588 nodes.client2 = args@{ pkgs, ... }:
592 virtualisation.vlans = [ 2 3 4 ];
596 local = "192.168.2.2";
597 remote = "192.168.2.1";
603 local = "fd00:1234:5678:4::2";
604 remote = "fd00:1234:5678:4::1";
610 bridges.bridge.interfaces = [ "greTunnel" "eth2" ];
611 interfaces.eth2.ipv4.addresses = mkOverride 0 [];
612 interfaces.bridge.ipv4.addresses = mkOverride 0 [
613 { address = "192.168.1.2"; prefixLength = 24; }
615 interfaces.eth3.ipv6.addresses = [
616 { address = "fd00:1234:5678:4::2"; prefixLength = 64; }
618 interfaces.gre6Tunnel.ipv6.addresses = mkOverride 0 [
619 { address = "fc00::2"; prefixLength = 64; }
624 testScript = { ... }:
629 with subtest("Wait for networking to be configured"):
630 client1.wait_for_unit("network.target")
631 client2.wait_for_unit("network.target")
633 # Print diagnostic information
634 client1.succeed("ip addr >&2")
635 client2.succeed("ip addr >&2")
637 with subtest("Test GRE tunnel bridge over VLAN"):
638 client1.wait_until_succeeds("ping -c 1 192.168.1.2")
640 client2.wait_until_succeeds("ping -c 1 192.168.1.1")
642 client1.wait_until_succeeds("ping -c 1 fc00::2")
644 client2.wait_until_succeeds("ping -c 1 fc00::1")
646 with subtest("Test GRE tunnel TTL"):
647 links = json.loads(client1.succeed("ip -details -json link show greTunnel"))
648 assert links[0]['linkinfo']['info_data']['ttl'] == 225, "ttl not set for greTunnel"
650 links = json.loads(client2.succeed("ip -details -json link show gre6Tunnel"))
651 assert links[0]['linkinfo']['info_data']['ttl'] == 255, "ttl not set for gre6Tunnel"
655 node = address: { pkgs, ... }: with pkgs.lib; {
656 #virtualisation.vlans = [ 1 ];
658 useNetworkd = networkd;
664 interfaces.eth0.ipv4.addresses = mkOverride 0 [ ];
665 interfaces.eth1.ipv4.addresses = mkOverride 0 [ ];
666 interfaces.vlan.ipv4.addresses = mkOverride 0
667 [ { inherit address; prefixLength = 24; } ];
672 nodes.client1 = node "192.168.1.1";
673 nodes.client2 = node "192.168.1.2";
674 testScript = { ... }:
678 with subtest("Wait for networking to be configured"):
679 client1.wait_for_unit("network.target")
680 client2.wait_for_unit("network.target")
682 with subtest("Test vlan is setup"):
683 client1.succeed("ip addr show dev vlan >&2")
684 client2.succeed("ip addr show dev vlan >&2")
688 baseIP = number: "10.10.10.${number}";
689 vlanIP = number: "10.1.1.${number}";
690 baseInterface = "enp1s0";
691 vlanInterface = "vlan42";
692 node = number: {pkgs, ... }: with pkgs.lib; {
693 virtualisation.interfaces.enp1s0.vlan = 1;
695 #useNetworkd = networkd;
697 vlans.${vlanInterface} = { id = 42; interface = baseInterface; };
698 interfaces.${baseInterface}.ipv4.addresses = mkOverride 0 [{ address = baseIP number; prefixLength = 24; }];
699 interfaces.${vlanInterface}.ipv4.addresses = mkOverride 0 [{ address = vlanIP number; prefixLength = 24; }];
708 nodes.server = node serverNodeNum;
709 nodes.client = node clientNodeNum;
710 testScript = { ... }:
714 with subtest("Wait for networking to be configured"):
715 server.wait_for_unit("network.target")
716 client.wait_for_unit("network.target")
718 with subtest("Test ping on base interface in setup"):
719 client.succeed("ping -I ${baseInterface} -c 1 ${baseIP serverNodeNum}")
720 server.succeed("ping -I ${baseInterface} -c 1 ${baseIP clientNodeNum}")
722 with subtest("Test ping on vlan subinterface in setup"):
723 client.succeed("ping -I ${vlanInterface} -c 1 ${vlanIP serverNodeNum}")
724 server.succeed("ping -I ${vlanInterface} -c 1 ${vlanIP clientNodeNum}")
730 networking.useNetworkd = networkd;
731 networking.useDHCP = false;
732 networking.interfaces.tap0 = {
733 ipv4.addresses = [ { address = "192.168.1.1"; prefixLength = 24; } ];
734 ipv6.addresses = [ { address = "2001:1470:fffd:2096::"; prefixLength = 64; } ];
737 macAddress = "02:de:ad:be:ef:01";
739 networking.interfaces.tun0 = {
740 ipv4.addresses = [ { address = "192.168.1.2"; prefixLength = 24; } ];
741 ipv6.addresses = [ { address = "2001:1470:fffd:2097::"; prefixLength = 64; } ];
749 tap0: tap persist user 0
750 tun0: tun persist user 0
753 with subtest("Wait for networking to come up"):
755 machine.wait_for_unit("network.target")
757 with subtest("Test interfaces set up"):
758 list = machine.succeed("ip tuntap list | sort").strip()
762 The list of virtual interfaces does not match the expected one:
770 with subtest("Test MTU and MAC Address are configured"):
771 machine.wait_until_succeeds("ip link show dev tap0 | grep 'mtu 1342'")
772 machine.wait_until_succeeds("ip link show dev tun0 | grep 'mtu 1343'")
773 assert "02:de:ad:be:ef:01" in machine.succeed("ip link show dev tap0")
774 '' # network-addresses-* only exist in scripted networking
775 + optionalString (!networkd) ''
776 with subtest("Test interfaces clean up"):
777 machine.succeed("systemctl stop network-addresses-tap0")
779 machine.succeed("systemctl stop network-addresses-tun0")
781 residue = machine.succeed("ip tuntap list")
784 ), "Some virtual interface has not been properly cleaned:\n{}".format(residue)
789 nodes.router = { ... }: {
790 virtualisation.interfaces.enp1s0.vlan = 1;
791 boot.kernel.sysctl."net.ipv6.conf.all.forwarding" = true;
793 useNetworkd = networkd;
795 interfaces.enp1s0.ipv6.addresses = singleton {
796 address = "fd00:1234:5678:1::1";
806 AdvOtherConfigFlag on;
808 prefix fd00:1234:5678:1::/64 {
816 nodes.client_with_privacy = { pkgs, ... }: with pkgs.lib; {
817 virtualisation.interfaces.enp1s0.vlan = 1;
819 useNetworkd = networkd;
821 interfaces.enp1s0 = {
822 tempAddress = "default";
823 ipv4.addresses = mkOverride 0 [ ];
824 ipv6.addresses = mkOverride 0 [ ];
829 nodes.client = { pkgs, ... }: with pkgs.lib; {
830 virtualisation.interfaces.enp1s0.vlan = 1;
832 useNetworkd = networkd;
834 interfaces.enp1s0 = {
835 tempAddress = "enabled";
836 ipv4.addresses = mkOverride 0 [ ];
837 ipv6.addresses = mkOverride 0 [ ];
842 testScript = { ... }:
846 client.wait_for_unit("network.target")
847 client_with_privacy.wait_for_unit("network.target")
848 router.wait_for_unit("network-online.target")
850 with subtest("Wait until we have an ip address"):
851 client_with_privacy.wait_until_succeeds(
852 "ip addr show dev enp1s0 | grep -q 'fd00:1234:5678:1:'"
854 client.wait_until_succeeds("ip addr show dev enp1s0 | grep -q 'fd00:1234:5678:1:'")
856 with subtest("Test vlan 1"):
857 client_with_privacy.wait_until_succeeds("ping -c 1 fd00:1234:5678:1::1")
858 client.wait_until_succeeds("ping -c 1 fd00:1234:5678:1::1")
860 with subtest("Test address used is temporary"):
861 client_with_privacy.wait_until_succeeds(
862 "! ip route get fd00:1234:5678:1::1 | grep -q ':[a-f0-9]*ff:fe[a-f0-9]*:'"
865 with subtest("Test address used is EUI-64"):
866 client.wait_until_succeeds(
867 "ip route get fd00:1234:5678:1::1 | grep -q ':[a-f0-9]*ff:fe[a-f0-9]*:'"
874 networking.useNetworkd = networkd;
875 networking.useDHCP = false;
876 networking.interfaces.eth0 = {
877 ipv4.addresses = [ { address = "192.168.1.2"; prefixLength = 24; } ];
878 ipv6.addresses = [ { address = "2001:1470:fffd:2097::"; prefixLength = 64; } ];
880 { address = "fdfd:b3f0::"; prefixLength = 48; }
881 { address = "2001:1470:fffd:2098::"; prefixLength = 64; via = "fdfd:b3f0::1"; }
884 { address = "10.0.0.0"; prefixLength = 16; options = {
886 # Explicitly set scope because iproute and systemd-networkd
887 # disagree on what the scope should be
888 # if the type is the default "unicast"
891 { address = "192.168.2.0"; prefixLength = 24; via = "192.168.1.1"; }
894 virtualisation.vlans = [ ];
899 "10.0.0.0/16 proto static scope link mtu 1500",
900 "192.168.1.0/24 proto kernel scope link src 192.168.1.2",
901 "192.168.2.0/24 via 192.168.1.1 proto static",
905 "2001:1470:fffd:2097::/64 proto kernel metric 256 pref medium",
906 "2001:1470:fffd:2098::/64 via fdfd:b3f0::1 proto static metric 1024 pref medium",
907 "fdfd:b3f0::/48 proto static metric 1024 pref medium",
911 machine.wait_for_unit("network.target")
913 with subtest("test routing tables"):
914 ipv4Table = machine.succeed("ip -4 route list dev eth0 | head -n3").strip()
915 ipv6Table = machine.succeed("ip -6 route list dev eth0 | head -n3").strip()
917 l.strip() for l in ipv4Table.splitlines()
918 ] == targetIPv4Table, """
919 The IPv4 routing table does not match the expected one:
925 ipv4Table, targetIPv4Table
928 l.strip() for l in ipv6Table.splitlines()
929 ] == targetIPv6Table, """
930 The IPv6 routing table does not match the expected one:
936 ipv6Table, targetIPv6Table
939 '' + optionalString (!networkd) ''
940 with subtest("test clean-up of the tables"):
941 machine.succeed("systemctl stop network-addresses-eth0")
942 ipv4Residue = machine.succeed("ip -4 route list dev eth0 | head -n-3").strip()
943 ipv6Residue = machine.succeed("ip -6 route list dev eth0 | head -n-3").strip()
946 ), "The IPv4 routing table has not been properly cleaned:\n{}".format(ipv4Residue)
949 ), "The IPv6 routing table has not been properly cleaned:\n{}".format(ipv6Residue)
952 rename = if networkd then {
953 name = "RenameInterface";
954 nodes.machine = { pkgs, ... }: {
955 virtualisation.vlans = [ 1 ];
957 useNetworkd = networkd;
960 systemd.network.links."10-custom_name" = {
961 matchConfig.MACAddress = "52:54:00:12:01:01";
962 linkConfig.Name = "custom_name";
966 machine.succeed("udevadm settle")
967 print(machine.succeed("ip link show dev custom_name"))
970 name = "RenameInterface";
974 # even with disabled networkd, systemd.network.links should work
975 # (as it's handled by udev, not networkd)
978 nodes.client = { pkgs, ... }: {
979 virtualisation.vlans = [ 1 ];
981 useNetworkd = networkd;
984 systemd.network.links."50-foo" = {
989 linkConfig.MTUBytes = "1442";
993 print(client.succeed("ip l add name foo type dummy"))
994 print(client.succeed("stat /etc/systemd/network/50-foo.link"))
995 client.succeed("udevadm settle")
996 assert "mtu 1442" in client.succeed("ip l show dev foo")
1000 testMac = "06:00:00:00:02:00";
1002 name = "WlanInterface";
1003 nodes.machine = { pkgs, ... }: {
1004 boot.kernelModules = [ "mac80211_hwsim" ];
1005 networking.wlanInterfaces = {
1006 wlan0 = { device = "wlan0"; };
1007 wap0 = { device = "wlan0"; mac = testMac; };
1012 machine.wait_for_unit("network.target")
1013 machine.wait_until_succeeds("ip address show wap0 | grep -q ${testMac}")
1014 machine.fail("ip address show wlan0 | grep -q ${testMac}")
1017 naughtyInterfaceNames = let
1019 # flags of ip-address
1020 "home" "temporary" "optimistic"
1021 "bridge_slave" "flush"
1023 "up" "type" "nomaster" "address"
1025 "very_loong_name" "lowerUpper" "-"
1028 name = "naughtyInterfaceNames";
1029 nodes.machine = { pkgs, ... }: {
1030 networking.useNetworkd = networkd;
1031 networking.bridges = listToAttrs
1033 (name: { inherit name; value.interfaces = []; }));
1037 machine.wait_for_unit("network.target")
1038 for ifname in ${builtins.toJSON ifnames}:
1039 machine.wait_until_succeeds(f"ip link show dev '{ifname}' | grep -q '{ifname}'")
1042 caseSensitiveRenaming = {
1043 name = "CaseSensitiveRenaming";
1044 nodes.machine = { pkgs, ... }: {
1045 virtualisation.interfaces.enCustom.vlan = 11;
1047 useNetworkd = networkd;
1052 machine.succeed("udevadm settle")
1053 print(machine.succeed("ip link show dev enCustom"))
1054 machine.wait_until_succeeds("ip link show dev enCustom | grep -q 52:54:00:12:0b:01")
1059 in mapAttrs (const (attrs: makeTest (attrs // {
1060 name = "${attrs.name}-Networking-${if networkd then "Networkd" else "Scripted"}";