1{ system ? builtins.currentSystem
2, config ? {}
3, pkgs ? import ../.. { inherit system config; }
4# bool: whether to use networkd in the tests
5, networkd }:
6
7with import ../lib/testing-python.nix { inherit system pkgs; };
8with pkgs.lib;
9
10let
11 qemu-flags = import ../lib/qemu-flags.nix { inherit pkgs; };
12
13 router = { config, pkgs, lib, ... }:
14 with pkgs.lib;
15 let
16 vlanIfs = range 1 (length config.virtualisation.vlans);
17 in {
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;
21 networking = {
22 useDHCP = false;
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; } ];
30 })));
31 };
32 services.dhcpd4 = {
33 enable = true;
34 interfaces = map (n: "eth${toString n}") vlanIfs;
35 extraConfig = flip concatMapStrings vlanIfs (n: ''
36 subnet 192.168.${toString n}.0 netmask 255.255.255.0 {
37 option routers 192.168.${toString n}.1;
38 range 192.168.${toString n}.3 192.168.${toString n}.254;
39 }
40 '')
41 ;
42 machines = flip map vlanIfs (vlan:
43 {
44 hostName = "client${toString vlan}";
45 ethernetAddress = qemu-flags.qemuNicMac vlan 1;
46 ipAddress = "192.168.${toString vlan}.2";
47 }
48 );
49 };
50 services.radvd = {
51 enable = true;
52 config = flip concatMapStrings vlanIfs (n: ''
53 interface eth${toString n} {
54 AdvSendAdvert on;
55 AdvManagedFlag on;
56 AdvOtherConfigFlag on;
57
58 prefix fd00:1234:5678:${toString n}::/64 {
59 AdvAutonomous off;
60 };
61 };
62 '');
63 };
64 services.dhcpd6 = {
65 enable = true;
66 interfaces = map (n: "eth${toString n}") vlanIfs;
67 extraConfig = ''
68 authoritative;
69 '' + flip concatMapStrings vlanIfs (n: ''
70 subnet6 fd00:1234:5678:${toString n}::/64 {
71 range6 fd00:1234:5678:${toString n}::2 fd00:1234:5678:${toString n}::2;
72 }
73 '');
74 };
75 };
76
77 testCases = {
78 loopback = {
79 name = "Loopback";
80 machine.networking.useDHCP = false;
81 machine.networking.useNetworkd = networkd;
82 testScript = ''
83 start_all()
84 machine.wait_for_unit("network.target")
85 loopback_addresses = machine.succeed("ip addr show lo")
86 assert "inet 127.0.0.1/8" in loopback_addresses
87 assert "inet6 ::1/128" in loopback_addresses
88 '';
89 };
90 static = {
91 name = "Static";
92 nodes.router = router;
93 nodes.client = { pkgs, ... }: with pkgs.lib; {
94 virtualisation.vlans = [ 1 2 ];
95 networking = {
96 useNetworkd = networkd;
97 useDHCP = false;
98 defaultGateway = "192.168.1.1";
99 interfaces.eth1.ipv4.addresses = mkOverride 0 [
100 { address = "192.168.1.2"; prefixLength = 24; }
101 { address = "192.168.1.3"; prefixLength = 32; }
102 { address = "192.168.1.10"; prefixLength = 32; }
103 ];
104 interfaces.eth2.ipv4.addresses = mkOverride 0 [
105 { address = "192.168.2.2"; prefixLength = 24; }
106 ];
107 };
108 };
109 testScript = { ... }:
110 ''
111 start_all()
112
113 client.wait_for_unit("network.target")
114 router.wait_for_unit("network-online.target")
115
116 with subtest("Make sure dhcpcd is not started"):
117 client.fail("systemctl status dhcpcd.service")
118
119 with subtest("Test vlan 1"):
120 client.wait_until_succeeds("ping -c 1 192.168.1.1")
121 client.wait_until_succeeds("ping -c 1 192.168.1.2")
122 client.wait_until_succeeds("ping -c 1 192.168.1.3")
123 client.wait_until_succeeds("ping -c 1 192.168.1.10")
124
125 router.wait_until_succeeds("ping -c 1 192.168.1.1")
126 router.wait_until_succeeds("ping -c 1 192.168.1.2")
127 router.wait_until_succeeds("ping -c 1 192.168.1.3")
128 router.wait_until_succeeds("ping -c 1 192.168.1.10")
129
130 with subtest("Test vlan 2"):
131 client.wait_until_succeeds("ping -c 1 192.168.2.1")
132 client.wait_until_succeeds("ping -c 1 192.168.2.2")
133
134 router.wait_until_succeeds("ping -c 1 192.168.2.1")
135 router.wait_until_succeeds("ping -c 1 192.168.2.2")
136
137 with subtest("Test default gateway"):
138 router.wait_until_succeeds("ping -c 1 192.168.3.1")
139 client.wait_until_succeeds("ping -c 1 192.168.3.1")
140 '';
141 };
142 dhcpSimple = {
143 name = "SimpleDHCP";
144 nodes.router = router;
145 nodes.client = { pkgs, ... }: with pkgs.lib; {
146 virtualisation.vlans = [ 1 2 ];
147 networking = {
148 useNetworkd = networkd;
149 useDHCP = false;
150 interfaces.eth1 = {
151 ipv4.addresses = mkOverride 0 [ ];
152 ipv6.addresses = mkOverride 0 [ ];
153 useDHCP = true;
154 };
155 interfaces.eth2 = {
156 ipv4.addresses = mkOverride 0 [ ];
157 ipv6.addresses = mkOverride 0 [ ];
158 useDHCP = true;
159 };
160 };
161 };
162 testScript = { ... }:
163 ''
164 start_all()
165
166 client.wait_for_unit("network.target")
167 router.wait_for_unit("network-online.target")
168
169 with subtest("Wait until we have an ip address on each interface"):
170 client.wait_until_succeeds("ip addr show dev eth1 | grep -q '192.168.1'")
171 client.wait_until_succeeds("ip addr show dev eth1 | grep -q 'fd00:1234:5678:1:'")
172 client.wait_until_succeeds("ip addr show dev eth2 | grep -q '192.168.2'")
173 client.wait_until_succeeds("ip addr show dev eth2 | grep -q 'fd00:1234:5678:2:'")
174
175 with subtest("Test vlan 1"):
176 client.wait_until_succeeds("ping -c 1 192.168.1.1")
177 client.wait_until_succeeds("ping -c 1 192.168.1.2")
178 client.wait_until_succeeds("ping -c 1 fd00:1234:5678:1::1")
179 client.wait_until_succeeds("ping -c 1 fd00:1234:5678:1::2")
180
181 router.wait_until_succeeds("ping -c 1 192.168.1.1")
182 router.wait_until_succeeds("ping -c 1 192.168.1.2")
183 router.wait_until_succeeds("ping -c 1 fd00:1234:5678:1::1")
184 router.wait_until_succeeds("ping -c 1 fd00:1234:5678:1::2")
185
186 with subtest("Test vlan 2"):
187 client.wait_until_succeeds("ping -c 1 192.168.2.1")
188 client.wait_until_succeeds("ping -c 1 192.168.2.2")
189 client.wait_until_succeeds("ping -c 1 fd00:1234:5678:2::1")
190 client.wait_until_succeeds("ping -c 1 fd00:1234:5678:2::2")
191
192 router.wait_until_succeeds("ping -c 1 192.168.2.1")
193 router.wait_until_succeeds("ping -c 1 192.168.2.2")
194 router.wait_until_succeeds("ping -c 1 fd00:1234:5678:2::1")
195 router.wait_until_succeeds("ping -c 1 fd00:1234:5678:2::2")
196 '';
197 };
198 dhcpOneIf = {
199 name = "OneInterfaceDHCP";
200 nodes.router = router;
201 nodes.client = { pkgs, ... }: with pkgs.lib; {
202 virtualisation.vlans = [ 1 2 ];
203 networking = {
204 useNetworkd = networkd;
205 useDHCP = false;
206 interfaces.eth1 = {
207 ipv4.addresses = mkOverride 0 [ ];
208 mtu = 1343;
209 useDHCP = true;
210 };
211 interfaces.eth2.ipv4.addresses = mkOverride 0 [ ];
212 };
213 };
214 testScript = { ... }:
215 ''
216 start_all()
217
218 with subtest("Wait for networking to come up"):
219 client.wait_for_unit("network.target")
220 router.wait_for_unit("network.target")
221
222 with subtest("Wait until we have an ip address on each interface"):
223 client.wait_until_succeeds("ip addr show dev eth1 | grep -q '192.168.1'")
224
225 with subtest("ensure MTU is set"):
226 assert "mtu 1343" in client.succeed("ip link show dev eth1")
227
228 with subtest("Test vlan 1"):
229 client.wait_until_succeeds("ping -c 1 192.168.1.1")
230 client.wait_until_succeeds("ping -c 1 192.168.1.2")
231
232 router.wait_until_succeeds("ping -c 1 192.168.1.1")
233 router.wait_until_succeeds("ping -c 1 192.168.1.2")
234
235 with subtest("Test vlan 2"):
236 client.wait_until_succeeds("ping -c 1 192.168.2.1")
237 client.fail("ping -c 1 192.168.2.2")
238
239 router.wait_until_succeeds("ping -c 1 192.168.2.1")
240 router.fail("ping -c 1 192.168.2.2")
241 '';
242 };
243 bond = let
244 node = address: { pkgs, ... }: with pkgs.lib; {
245 virtualisation.vlans = [ 1 2 ];
246 networking = {
247 useNetworkd = networkd;
248 useDHCP = false;
249 bonds.bond = {
250 interfaces = [ "eth1" "eth2" ];
251 driverOptions.mode = "balance-rr";
252 };
253 interfaces.eth1.ipv4.addresses = mkOverride 0 [ ];
254 interfaces.eth2.ipv4.addresses = mkOverride 0 [ ];
255 interfaces.bond.ipv4.addresses = mkOverride 0
256 [ { inherit address; prefixLength = 30; } ];
257 };
258 };
259 in {
260 name = "Bond";
261 nodes.client1 = node "192.168.1.1";
262 nodes.client2 = node "192.168.1.2";
263 testScript = { ... }:
264 ''
265 start_all()
266
267 with subtest("Wait for networking to come up"):
268 client1.wait_for_unit("network.target")
269 client2.wait_for_unit("network.target")
270
271 with subtest("Test bonding"):
272 client1.wait_until_succeeds("ping -c 2 192.168.1.1")
273 client1.wait_until_succeeds("ping -c 2 192.168.1.2")
274
275 client2.wait_until_succeeds("ping -c 2 192.168.1.1")
276 client2.wait_until_succeeds("ping -c 2 192.168.1.2")
277 '';
278 };
279 bridge = let
280 node = { address, vlan }: { pkgs, ... }: with pkgs.lib; {
281 virtualisation.vlans = [ vlan ];
282 networking = {
283 useNetworkd = networkd;
284 useDHCP = false;
285 interfaces.eth1.ipv4.addresses = mkOverride 0
286 [ { inherit address; prefixLength = 24; } ];
287 };
288 };
289 in {
290 name = "Bridge";
291 nodes.client1 = node { address = "192.168.1.2"; vlan = 1; };
292 nodes.client2 = node { address = "192.168.1.3"; vlan = 2; };
293 nodes.router = { pkgs, ... }: with pkgs.lib; {
294 virtualisation.vlans = [ 1 2 ];
295 networking = {
296 useNetworkd = networkd;
297 useDHCP = false;
298 bridges.bridge.interfaces = [ "eth1" "eth2" ];
299 interfaces.eth1.ipv4.addresses = mkOverride 0 [ ];
300 interfaces.eth2.ipv4.addresses = mkOverride 0 [ ];
301 interfaces.bridge.ipv4.addresses = mkOverride 0
302 [ { address = "192.168.1.1"; prefixLength = 24; } ];
303 };
304 };
305 testScript = { ... }:
306 ''
307 start_all()
308
309 with subtest("Wait for networking to come up"):
310 for machine in client1, client2, router:
311 machine.wait_for_unit("network.target")
312
313 with subtest("Test bridging"):
314 client1.wait_until_succeeds("ping -c 1 192.168.1.1")
315 client1.wait_until_succeeds("ping -c 1 192.168.1.2")
316 client1.wait_until_succeeds("ping -c 1 192.168.1.3")
317
318 client2.wait_until_succeeds("ping -c 1 192.168.1.1")
319 client2.wait_until_succeeds("ping -c 1 192.168.1.2")
320 client2.wait_until_succeeds("ping -c 1 192.168.1.3")
321
322 router.wait_until_succeeds("ping -c 1 192.168.1.1")
323 router.wait_until_succeeds("ping -c 1 192.168.1.2")
324 router.wait_until_succeeds("ping -c 1 192.168.1.3")
325 '';
326 };
327 macvlan = {
328 name = "MACVLAN";
329 nodes.router = router;
330 nodes.client = { pkgs, ... }: with pkgs.lib; {
331 environment.systemPackages = [ pkgs.iptables ]; # to debug firewall rules
332 virtualisation.vlans = [ 1 ];
333 networking = {
334 useNetworkd = networkd;
335 useDHCP = false;
336 firewall.logReversePathDrops = true; # to debug firewall rules
337 # reverse path filtering rules for the macvlan interface seem
338 # to be incorrect, causing the test to fail. Disable temporarily.
339 firewall.checkReversePath = false;
340 macvlans.macvlan.interface = "eth1";
341 interfaces.eth1 = {
342 ipv4.addresses = mkOverride 0 [ ];
343 useDHCP = true;
344 };
345 interfaces.macvlan = {
346 useDHCP = true;
347 };
348 };
349 };
350 testScript = { ... }:
351 ''
352 start_all()
353
354 with subtest("Wait for networking to come up"):
355 client.wait_for_unit("network.target")
356 router.wait_for_unit("network.target")
357
358 with subtest("Wait until we have an ip address on each interface"):
359 client.wait_until_succeeds("ip addr show dev eth1 | grep -q '192.168.1'")
360 client.wait_until_succeeds("ip addr show dev macvlan | grep -q '192.168.1'")
361
362 with subtest("Print lots of diagnostic information"):
363 router.log("**********************************************")
364 router.succeed("ip addr >&2")
365 router.succeed("ip route >&2")
366 router.execute("iptables-save >&2")
367 client.log("==============================================")
368 client.succeed("ip addr >&2")
369 client.succeed("ip route >&2")
370 client.execute("iptables-save >&2")
371 client.log("##############################################")
372
373 with subtest("Test macvlan creates routable ips"):
374 client.wait_until_succeeds("ping -c 1 192.168.1.1")
375 client.wait_until_succeeds("ping -c 1 192.168.1.2")
376 client.wait_until_succeeds("ping -c 1 192.168.1.3")
377
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")
381 '';
382 };
383 sit = let
384 node = { address4, remote, address6 }: { pkgs, ... }: with pkgs.lib; {
385 virtualisation.vlans = [ 1 ];
386 networking = {
387 useNetworkd = networkd;
388 firewall.enable = false;
389 useDHCP = false;
390 sits.sit = {
391 inherit remote;
392 local = address4;
393 dev = "eth1";
394 };
395 interfaces.eth1.ipv4.addresses = mkOverride 0
396 [ { address = address4; prefixLength = 24; } ];
397 interfaces.sit.ipv6.addresses = mkOverride 0
398 [ { address = address6; prefixLength = 64; } ];
399 };
400 };
401 in {
402 name = "Sit";
403 nodes.client1 = node { address4 = "192.168.1.1"; remote = "192.168.1.2"; address6 = "fc00::1"; };
404 nodes.client2 = node { address4 = "192.168.1.2"; remote = "192.168.1.1"; address6 = "fc00::2"; };
405 testScript = { ... }:
406 ''
407 start_all()
408
409 with subtest("Wait for networking to be configured"):
410 client1.wait_for_unit("network.target")
411 client2.wait_for_unit("network.target")
412
413 # Print diagnostic information
414 client1.succeed("ip addr >&2")
415 client2.succeed("ip addr >&2")
416
417 with subtest("Test ipv6"):
418 client1.wait_until_succeeds("ping -c 1 fc00::1")
419 client1.wait_until_succeeds("ping -c 1 fc00::2")
420
421 client2.wait_until_succeeds("ping -c 1 fc00::1")
422 client2.wait_until_succeeds("ping -c 1 fc00::2")
423 '';
424 };
425 vlan = let
426 node = address: { pkgs, ... }: with pkgs.lib; {
427 #virtualisation.vlans = [ 1 ];
428 networking = {
429 useNetworkd = networkd;
430 useDHCP = false;
431 vlans.vlan = {
432 id = 1;
433 interface = "eth0";
434 };
435 interfaces.eth0.ipv4.addresses = mkOverride 0 [ ];
436 interfaces.eth1.ipv4.addresses = mkOverride 0 [ ];
437 interfaces.vlan.ipv4.addresses = mkOverride 0
438 [ { inherit address; prefixLength = 24; } ];
439 };
440 };
441 in {
442 name = "vlan";
443 nodes.client1 = node "192.168.1.1";
444 nodes.client2 = node "192.168.1.2";
445 testScript = { ... }:
446 ''
447 start_all()
448
449 with subtest("Wait for networking to be configured"):
450 client1.wait_for_unit("network.target")
451 client2.wait_for_unit("network.target")
452
453 with subtest("Test vlan is setup"):
454 client1.succeed("ip addr show dev vlan >&2")
455 client2.succeed("ip addr show dev vlan >&2")
456 '';
457 };
458 virtual = {
459 name = "Virtual";
460 machine = {
461 networking.useNetworkd = networkd;
462 networking.useDHCP = false;
463 networking.interfaces.tap0 = {
464 ipv4.addresses = [ { address = "192.168.1.1"; prefixLength = 24; } ];
465 ipv6.addresses = [ { address = "2001:1470:fffd:2096::"; prefixLength = 64; } ];
466 virtual = true;
467 mtu = 1342;
468 macAddress = "02:de:ad:be:ef:01";
469 };
470 networking.interfaces.tun0 = {
471 ipv4.addresses = [ { address = "192.168.1.2"; prefixLength = 24; } ];
472 ipv6.addresses = [ { address = "2001:1470:fffd:2097::"; prefixLength = 64; } ];
473 virtual = true;
474 mtu = 1343;
475 };
476 };
477
478 testScript = ''
479 targetList = """
480 tap0: tap persist user 0
481 tun0: tun persist user 0
482 """.strip()
483
484 with subtest("Wait for networking to come up"):
485 machine.start()
486 machine.wait_for_unit("network.target")
487
488 with subtest("Test interfaces set up"):
489 list = machine.succeed("ip tuntap list | sort").strip()
490 assert (
491 list == targetList
492 ), """
493 The list of virtual interfaces does not match the expected one:
494 Result:
495 {}
496 Expected:
497 {}
498 """.format(
499 list, targetList
500 )
501 with subtest("Test MTU and MAC Address are configured"):
502 machine.wait_until_succeeds("ip link show dev tap0 | grep 'mtu 1342'")
503 machine.wait_until_succeeds("ip link show dev tun0 | grep 'mtu 1343'")
504 assert "02:de:ad:be:ef:01" in machine.succeed("ip link show dev tap0")
505 '' # network-addresses-* only exist in scripted networking
506 + optionalString (!networkd) ''
507 with subtest("Test interfaces clean up"):
508 machine.succeed("systemctl stop network-addresses-tap0")
509 machine.sleep(10)
510 machine.succeed("systemctl stop network-addresses-tun0")
511 machine.sleep(10)
512 residue = machine.succeed("ip tuntap list")
513 assert (
514 residue == ""
515 ), "Some virtual interface has not been properly cleaned:\n{}".format(residue)
516 '';
517 };
518 privacy = {
519 name = "Privacy";
520 nodes.router = { ... }: {
521 virtualisation.vlans = [ 1 ];
522 boot.kernel.sysctl."net.ipv6.conf.all.forwarding" = true;
523 networking = {
524 useNetworkd = networkd;
525 useDHCP = false;
526 interfaces.eth1.ipv6.addresses = singleton {
527 address = "fd00:1234:5678:1::1";
528 prefixLength = 64;
529 };
530 };
531 services.radvd = {
532 enable = true;
533 config = ''
534 interface eth1 {
535 AdvSendAdvert on;
536 AdvManagedFlag on;
537 AdvOtherConfigFlag on;
538
539 prefix fd00:1234:5678:1::/64 {
540 AdvAutonomous on;
541 AdvOnLink on;
542 };
543 };
544 '';
545 };
546 };
547 nodes.client_with_privacy = { pkgs, ... }: with pkgs.lib; {
548 virtualisation.vlans = [ 1 ];
549 networking = {
550 useNetworkd = networkd;
551 useDHCP = false;
552 interfaces.eth1 = {
553 tempAddress = "default";
554 ipv4.addresses = mkOverride 0 [ ];
555 ipv6.addresses = mkOverride 0 [ ];
556 useDHCP = true;
557 };
558 };
559 };
560 nodes.client = { pkgs, ... }: with pkgs.lib; {
561 virtualisation.vlans = [ 1 ];
562 networking = {
563 useNetworkd = networkd;
564 useDHCP = false;
565 interfaces.eth1 = {
566 tempAddress = "enabled";
567 ipv4.addresses = mkOverride 0 [ ];
568 ipv6.addresses = mkOverride 0 [ ];
569 useDHCP = true;
570 };
571 };
572 };
573 testScript = { ... }:
574 ''
575 start_all()
576
577 client.wait_for_unit("network.target")
578 client_with_privacy.wait_for_unit("network.target")
579 router.wait_for_unit("network-online.target")
580
581 with subtest("Wait until we have an ip address"):
582 client_with_privacy.wait_until_succeeds(
583 "ip addr show dev eth1 | grep -q 'fd00:1234:5678:1:'"
584 )
585 client.wait_until_succeeds("ip addr show dev eth1 | grep -q 'fd00:1234:5678:1:'")
586
587 with subtest("Test vlan 1"):
588 client_with_privacy.wait_until_succeeds("ping -c 1 fd00:1234:5678:1::1")
589 client.wait_until_succeeds("ping -c 1 fd00:1234:5678:1::1")
590
591 with subtest("Test address used is temporary"):
592 client_with_privacy.wait_until_succeeds(
593 "! ip route get fd00:1234:5678:1::1 | grep -q ':[a-f0-9]*ff:fe[a-f0-9]*:'"
594 )
595
596 with subtest("Test address used is EUI-64"):
597 client.wait_until_succeeds(
598 "ip route get fd00:1234:5678:1::1 | grep -q ':[a-f0-9]*ff:fe[a-f0-9]*:'"
599 )
600 '';
601 };
602 routes = {
603 name = "routes";
604 machine = {
605 networking.useDHCP = false;
606 networking.interfaces.eth0 = {
607 ipv4.addresses = [ { address = "192.168.1.2"; prefixLength = 24; } ];
608 ipv6.addresses = [ { address = "2001:1470:fffd:2097::"; prefixLength = 64; } ];
609 ipv6.routes = [
610 { address = "fdfd:b3f0::"; prefixLength = 48; }
611 { address = "2001:1470:fffd:2098::"; prefixLength = 64; via = "fdfd:b3f0::1"; }
612 ];
613 ipv4.routes = [
614 { address = "10.0.0.0"; prefixLength = 16; options = { mtu = "1500"; }; }
615 { address = "192.168.2.0"; prefixLength = 24; via = "192.168.1.1"; }
616 ];
617 };
618 virtualisation.vlans = [ ];
619 };
620
621 testScript = ''
622 targetIPv4Table = [
623 "10.0.0.0/16 proto static scope link mtu 1500",
624 "192.168.1.0/24 proto kernel scope link src 192.168.1.2",
625 "192.168.2.0/24 via 192.168.1.1 proto static",
626 ]
627
628 targetIPv6Table = [
629 "2001:1470:fffd:2097::/64 proto kernel metric 256 pref medium",
630 "2001:1470:fffd:2098::/64 via fdfd:b3f0::1 proto static metric 1024 pref medium",
631 "fdfd:b3f0::/48 proto static metric 1024 pref medium",
632 ]
633
634 machine.start()
635 machine.wait_for_unit("network.target")
636
637 with subtest("test routing tables"):
638 ipv4Table = machine.succeed("ip -4 route list dev eth0 | head -n3").strip()
639 ipv6Table = machine.succeed("ip -6 route list dev eth0 | head -n3").strip()
640 assert [
641 l.strip() for l in ipv4Table.splitlines()
642 ] == targetIPv4Table, """
643 The IPv4 routing table does not match the expected one:
644 Result:
645 {}
646 Expected:
647 {}
648 """.format(
649 ipv4Table, targetIPv4Table
650 )
651 assert [
652 l.strip() for l in ipv6Table.splitlines()
653 ] == targetIPv6Table, """
654 The IPv6 routing table does not match the expected one:
655 Result:
656 {}
657 Expected:
658 {}
659 """.format(
660 ipv6Table, targetIPv6Table
661 )
662
663 with subtest("test clean-up of the tables"):
664 machine.succeed("systemctl stop network-addresses-eth0")
665 ipv4Residue = machine.succeed("ip -4 route list dev eth0 | head -n-3").strip()
666 ipv6Residue = machine.succeed("ip -6 route list dev eth0 | head -n-3").strip()
667 assert (
668 ipv4Residue == ""
669 ), "The IPv4 routing table has not been properly cleaned:\n{}".format(ipv4Residue)
670 assert (
671 ipv6Residue == ""
672 ), "The IPv6 routing table has not been properly cleaned:\n{}".format(ipv6Residue)
673 '';
674 };
675 rename = {
676 name = "RenameInterface";
677 machine = { pkgs, ... }: {
678 virtualisation.vlans = [ 1 ];
679 networking = {
680 useNetworkd = networkd;
681 useDHCP = false;
682 };
683 } //
684 (if networkd
685 then { systemd.network.links."10-custom_name" = {
686 matchConfig.MACAddress = "52:54:00:12:01:01";
687 linkConfig.Name = "custom_name";
688 };
689 }
690 else { services.udev.initrdRules = ''
691 SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="52:54:00:12:01:01", KERNEL=="eth*", NAME="custom_name"
692 '';
693 });
694 testScript = ''
695 machine.succeed("udevadm settle")
696 print(machine.succeed("ip link show dev custom_name"))
697 '';
698 };
699 # even with disabled networkd, systemd.network.links should work
700 # (as it's handled by udev, not networkd)
701 link = {
702 name = "Link";
703 nodes.client = { pkgs, ... }: {
704 virtualisation.vlans = [ 1 ];
705 networking = {
706 useNetworkd = networkd;
707 useDHCP = false;
708 };
709 systemd.network.links."50-foo" = {
710 matchConfig = {
711 Name = "foo";
712 Driver = "dummy";
713 };
714 linkConfig.MTUBytes = "1442";
715 };
716 };
717 testScript = ''
718 print(client.succeed("ip l add name foo type dummy"))
719 print(client.succeed("stat /etc/systemd/network/50-foo.link"))
720 client.succeed("udevadm settle")
721 assert "mtu 1442" in client.succeed("ip l show dummy0")
722 '';
723 };
724 };
725
726in mapAttrs (const (attrs: makeTest (attrs // {
727 name = "${attrs.name}-Networking-${if networkd then "Networkd" else "Scripted"}";
728}))) testCases