fork
Configure Feed
Select the types of activity you want to include in your feed.
lol
fork
Configure Feed
Select the types of activity you want to include in your feed.
1{ system ? builtins.currentSystem
2# bool: whether to use networkd in the tests
3, networkd }:
4
5with import ../lib/testing.nix { inherit system; };
6with pkgs.lib;
7
8let
9 router = { config, pkgs, ... }:
10 with pkgs.lib;
11 let
12 vlanIfs = range 1 (length config.virtualisation.vlans);
13 in {
14 virtualisation.vlans = [ 1 2 3 ];
15 boot.kernel.sysctl."net.ipv6.conf.all.forwarding" = true;
16 networking = {
17 useDHCP = false;
18 useNetworkd = networkd;
19 firewall.allowPing = true;
20 firewall.checkReversePath = true;
21 firewall.allowedUDPPorts = [ 547 ];
22 interfaces = mkOverride 0 (listToAttrs (flip map vlanIfs (n:
23 nameValuePair "eth${toString n}" {
24 ipv4.addresses = [ { address = "192.168.${toString n}.1"; prefixLength = 24; } ];
25 ipv6.addresses = [ { address = "fd00:1234:5678:${toString n}::1"; prefixLength = 64; } ];
26 })));
27 };
28 services.dhcpd4 = {
29 enable = true;
30 interfaces = map (n: "eth${toString n}") vlanIfs;
31 extraConfig = ''
32 authoritative;
33 '' + flip concatMapStrings vlanIfs (n: ''
34 subnet 192.168.${toString n}.0 netmask 255.255.255.0 {
35 option routers 192.168.${toString n}.1;
36 # XXX: technically it's _not guaranteed_ that IP addresses will be
37 # issued from the first item in range onwards! We assume that in
38 # our tests however.
39 range 192.168.${toString n}.2 192.168.${toString n}.254;
40 }
41 '');
42 };
43 services.radvd = {
44 enable = true;
45 config = flip concatMapStrings vlanIfs (n: ''
46 interface eth${toString n} {
47 AdvSendAdvert on;
48 AdvManagedFlag on;
49 AdvOtherConfigFlag on;
50
51 prefix fd00:1234:5678:${toString n}::/64 {
52 AdvAutonomous off;
53 };
54 };
55 '');
56 };
57 services.dhcpd6 = {
58 enable = true;
59 interfaces = map (n: "eth${toString n}") vlanIfs;
60 extraConfig = ''
61 authoritative;
62 '' + flip concatMapStrings vlanIfs (n: ''
63 subnet6 fd00:1234:5678:${toString n}::/64 {
64 range6 fd00:1234:5678:${toString n}::2 fd00:1234:5678:${toString n}::2;
65 }
66 '');
67 };
68 };
69
70 testCases = {
71 loopback = {
72 name = "Loopback";
73 machine.networking.useNetworkd = networkd;
74 testScript = ''
75 startAll;
76 $machine->waitForUnit("network.target");
77 $machine->succeed("ip addr show lo | grep -q 'inet 127.0.0.1/8 '");
78 $machine->succeed("ip addr show lo | grep -q 'inet6 ::1/128 '");
79 '';
80 };
81 static = {
82 name = "Static";
83 nodes.router = router;
84 nodes.client = { config, pkgs, ... }: with pkgs.lib; {
85 virtualisation.vlans = [ 1 2 ];
86 networking = {
87 useNetworkd = networkd;
88 firewall.allowPing = true;
89 useDHCP = false;
90 defaultGateway = "192.168.1.1";
91 interfaces.eth1.ipv4.addresses = mkOverride 0 [
92 { address = "192.168.1.2"; prefixLength = 24; }
93 { address = "192.168.1.3"; prefixLength = 32; }
94 { address = "192.168.1.10"; prefixLength = 32; }
95 ];
96 interfaces.eth2.ipv4.addresses = mkOverride 0 [
97 { address = "192.168.2.2"; prefixLength = 24; }
98 ];
99 };
100 };
101 testScript = { nodes, ... }:
102 ''
103 startAll;
104
105 $client->waitForUnit("network.target");
106 $router->waitForUnit("network-online.target");
107
108 # Make sure dhcpcd is not started
109 $client->fail("systemctl status dhcpcd.service");
110
111 # Test vlan 1
112 $client->waitUntilSucceeds("ping -c 1 192.168.1.1");
113 $client->waitUntilSucceeds("ping -c 1 192.168.1.2");
114 $client->waitUntilSucceeds("ping -c 1 192.168.1.3");
115 $client->waitUntilSucceeds("ping -c 1 192.168.1.10");
116
117 $router->waitUntilSucceeds("ping -c 1 192.168.1.1");
118 $router->waitUntilSucceeds("ping -c 1 192.168.1.2");
119 $router->waitUntilSucceeds("ping -c 1 192.168.1.3");
120 $router->waitUntilSucceeds("ping -c 1 192.168.1.10");
121
122 # Test vlan 2
123 $client->waitUntilSucceeds("ping -c 1 192.168.2.1");
124 $client->waitUntilSucceeds("ping -c 1 192.168.2.2");
125
126 $router->waitUntilSucceeds("ping -c 1 192.168.2.1");
127 $router->waitUntilSucceeds("ping -c 1 192.168.2.2");
128
129 # Test default gateway
130 $router->waitUntilSucceeds("ping -c 1 192.168.3.1");
131 $client->waitUntilSucceeds("ping -c 1 192.168.3.1");
132 '';
133 };
134 dhcpSimple = {
135 name = "SimpleDHCP";
136 nodes.router = router;
137 nodes.client = { config, pkgs, ... }: with pkgs.lib; {
138 virtualisation.vlans = [ 1 2 ];
139 networking = {
140 useNetworkd = networkd;
141 firewall.allowPing = true;
142 useDHCP = true;
143 interfaces.eth1 = {
144 ipv4.addresses = mkOverride 0 [ ];
145 ipv6.addresses = mkOverride 0 [ ];
146 };
147 interfaces.eth2 = {
148 ipv4.addresses = mkOverride 0 [ ];
149 ipv6.addresses = mkOverride 0 [ ];
150 };
151 };
152 };
153 testScript = { nodes, ... }:
154 ''
155 startAll;
156
157 $client->waitForUnit("network.target");
158 $router->waitForUnit("network-online.target");
159
160 # Wait until we have an ip address on each interface
161 $client->waitUntilSucceeds("ip addr show dev eth1 | grep -q '192.168.1'");
162 $client->waitUntilSucceeds("ip addr show dev eth1 | grep -q 'fd00:1234:5678:1:'");
163 $client->waitUntilSucceeds("ip addr show dev eth2 | grep -q '192.168.2'");
164 $client->waitUntilSucceeds("ip addr show dev eth2 | grep -q 'fd00:1234:5678:2:'");
165
166 # Test vlan 1
167 $client->waitUntilSucceeds("ping -c 1 192.168.1.1");
168 $client->waitUntilSucceeds("ping -c 1 192.168.1.2");
169 $client->waitUntilSucceeds("ping -c 1 fd00:1234:5678:1::1");
170 $client->waitUntilSucceeds("ping -c 1 fd00:1234:5678:1::2");
171
172 $router->waitUntilSucceeds("ping -c 1 192.168.1.1");
173 $router->waitUntilSucceeds("ping -c 1 192.168.1.2");
174 $router->waitUntilSucceeds("ping -c 1 fd00:1234:5678:1::1");
175 $router->waitUntilSucceeds("ping -c 1 fd00:1234:5678:1::2");
176
177 # Test vlan 2
178 $client->waitUntilSucceeds("ping -c 1 192.168.2.1");
179 $client->waitUntilSucceeds("ping -c 1 192.168.2.2");
180 $client->waitUntilSucceeds("ping -c 1 fd00:1234:5678:2::1");
181 $client->waitUntilSucceeds("ping -c 1 fd00:1234:5678:2::2");
182
183 $router->waitUntilSucceeds("ping -c 1 192.168.2.1");
184 $router->waitUntilSucceeds("ping -c 1 192.168.2.2");
185 $router->waitUntilSucceeds("ping -c 1 fd00:1234:5678:2::1");
186 $router->waitUntilSucceeds("ping -c 1 fd00:1234:5678:2::2");
187 '';
188 };
189 dhcpOneIf = {
190 name = "OneInterfaceDHCP";
191 nodes.router = router;
192 nodes.client = { config, pkgs, ... }: with pkgs.lib; {
193 virtualisation.vlans = [ 1 2 ];
194 networking = {
195 useNetworkd = networkd;
196 firewall.allowPing = true;
197 useDHCP = false;
198 interfaces.eth1 = {
199 ipv4.addresses = mkOverride 0 [ ];
200 useDHCP = true;
201 };
202 interfaces.eth2.ipv4.addresses = mkOverride 0 [ ];
203 };
204 };
205 testScript = { nodes, ... }:
206 ''
207 startAll;
208
209 # Wait for networking to come up
210 $client->waitForUnit("network.target");
211 $router->waitForUnit("network.target");
212
213 # Wait until we have an ip address on each interface
214 $client->waitUntilSucceeds("ip addr show dev eth1 | grep -q '192.168.1'");
215
216 # Test vlan 1
217 $client->waitUntilSucceeds("ping -c 1 192.168.1.1");
218 $client->waitUntilSucceeds("ping -c 1 192.168.1.2");
219
220 $router->waitUntilSucceeds("ping -c 1 192.168.1.1");
221 $router->waitUntilSucceeds("ping -c 1 192.168.1.2");
222
223 # Test vlan 2
224 $client->waitUntilSucceeds("ping -c 1 192.168.2.1");
225 $client->fail("ping -c 1 192.168.2.2");
226
227 $router->waitUntilSucceeds("ping -c 1 192.168.2.1");
228 $router->fail("ping -c 1 192.168.2.2");
229 '';
230 };
231 bond = let
232 node = address: { config, pkgs, ... }: with pkgs.lib; {
233 virtualisation.vlans = [ 1 2 ];
234 networking = {
235 useNetworkd = networkd;
236 firewall.allowPing = true;
237 useDHCP = false;
238 bonds.bond = {
239 interfaces = [ "eth1" "eth2" ];
240 driverOptions.mode = "balance-rr";
241 };
242 interfaces.eth1.ipv4.addresses = mkOverride 0 [ ];
243 interfaces.eth2.ipv4.addresses = mkOverride 0 [ ];
244 interfaces.bond.ipv4.addresses = mkOverride 0
245 [ { inherit address; prefixLength = 30; } ];
246 };
247 };
248 in {
249 name = "Bond";
250 nodes.client1 = node "192.168.1.1";
251 nodes.client2 = node "192.168.1.2";
252 testScript = { nodes, ... }:
253 ''
254 startAll;
255
256 # Wait for networking to come up
257 $client1->waitForUnit("network.target");
258 $client2->waitForUnit("network.target");
259
260 # Test bonding
261 $client1->waitUntilSucceeds("ping -c 2 192.168.1.1");
262 $client1->waitUntilSucceeds("ping -c 2 192.168.1.2");
263
264 $client2->waitUntilSucceeds("ping -c 2 192.168.1.1");
265 $client2->waitUntilSucceeds("ping -c 2 192.168.1.2");
266 '';
267 };
268 bridge = let
269 node = { address, vlan }: { config, pkgs, ... }: with pkgs.lib; {
270 virtualisation.vlans = [ vlan ];
271 networking = {
272 useNetworkd = networkd;
273 firewall.allowPing = true;
274 useDHCP = false;
275 interfaces.eth1.ipv4.addresses = mkOverride 0
276 [ { inherit address; prefixLength = 24; } ];
277 };
278 };
279 in {
280 name = "Bridge";
281 nodes.client1 = node { address = "192.168.1.2"; vlan = 1; };
282 nodes.client2 = node { address = "192.168.1.3"; vlan = 2; };
283 nodes.router = { config, pkgs, ... }: with pkgs.lib; {
284 virtualisation.vlans = [ 1 2 ];
285 networking = {
286 useNetworkd = networkd;
287 firewall.allowPing = true;
288 useDHCP = false;
289 bridges.bridge.interfaces = [ "eth1" "eth2" ];
290 interfaces.eth1.ipv4.addresses = mkOverride 0 [ ];
291 interfaces.eth2.ipv4.addresses = mkOverride 0 [ ];
292 interfaces.bridge.ipv4.addresses = mkOverride 0
293 [ { address = "192.168.1.1"; prefixLength = 24; } ];
294 };
295 };
296 testScript = { nodes, ... }:
297 ''
298 startAll;
299
300 # Wait for networking to come up
301 $client1->waitForUnit("network.target");
302 $client2->waitForUnit("network.target");
303 $router->waitForUnit("network.target");
304
305 # Test bridging
306 $client1->waitUntilSucceeds("ping -c 1 192.168.1.1");
307 $client1->waitUntilSucceeds("ping -c 1 192.168.1.2");
308 $client1->waitUntilSucceeds("ping -c 1 192.168.1.3");
309
310 $client2->waitUntilSucceeds("ping -c 1 192.168.1.1");
311 $client2->waitUntilSucceeds("ping -c 1 192.168.1.2");
312 $client2->waitUntilSucceeds("ping -c 1 192.168.1.3");
313
314 $router->waitUntilSucceeds("ping -c 1 192.168.1.1");
315 $router->waitUntilSucceeds("ping -c 1 192.168.1.2");
316 $router->waitUntilSucceeds("ping -c 1 192.168.1.3");
317 '';
318 };
319 macvlan = {
320 name = "MACVLAN";
321 nodes.router = router;
322 nodes.client = { config, pkgs, ... }: with pkgs.lib; {
323 virtualisation.vlans = [ 1 ];
324 networking = {
325 useNetworkd = networkd;
326 firewall.allowPing = true;
327 useDHCP = true;
328 macvlans.macvlan.interface = "eth1";
329 interfaces.eth1.ipv4.addresses = mkOverride 0 [ ];
330 };
331 };
332 testScript = { nodes, ... }:
333 ''
334 startAll;
335
336 # Wait for networking to come up
337 $client->waitForUnit("network.target");
338 $router->waitForUnit("network.target");
339
340 # Wait until we have an ip address on each interface
341 $client->waitUntilSucceeds("ip addr show dev eth1 | grep -q '192.168.1'");
342 $client->waitUntilSucceeds("ip addr show dev macvlan | grep -q '192.168.1'");
343
344 # Print diagnosting information
345 $router->succeed("ip addr >&2");
346 $client->succeed("ip addr >&2");
347
348 # Test macvlan creates routable ips
349 $client->waitUntilSucceeds("ping -c 1 192.168.1.1");
350 $client->waitUntilSucceeds("ping -c 1 192.168.1.2");
351 $client->waitUntilSucceeds("ping -c 1 192.168.1.3");
352
353 $router->waitUntilSucceeds("ping -c 1 192.168.1.1");
354 $router->waitUntilSucceeds("ping -c 1 192.168.1.2");
355 $router->waitUntilSucceeds("ping -c 1 192.168.1.3");
356 '';
357 };
358 sit = let
359 node = { address4, remote, address6 }: { config, pkgs, ... }: with pkgs.lib; {
360 virtualisation.vlans = [ 1 ];
361 networking = {
362 useNetworkd = networkd;
363 firewall.enable = false;
364 useDHCP = false;
365 sits.sit = {
366 inherit remote;
367 local = address4;
368 dev = "eth1";
369 };
370 interfaces.eth1.ipv4.addresses = mkOverride 0
371 [ { address = address4; prefixLength = 24; } ];
372 interfaces.sit.ipv6.addresses = mkOverride 0
373 [ { address = address6; prefixLength = 64; } ];
374 };
375 };
376 in {
377 name = "Sit";
378 nodes.client1 = node { address4 = "192.168.1.1"; remote = "192.168.1.2"; address6 = "fc00::1"; };
379 nodes.client2 = node { address4 = "192.168.1.2"; remote = "192.168.1.1"; address6 = "fc00::2"; };
380 testScript = { nodes, ... }:
381 ''
382 startAll;
383
384 # Wait for networking to be configured
385 $client1->waitForUnit("network.target");
386 $client2->waitForUnit("network.target");
387
388 # Print diagnostic information
389 $client1->succeed("ip addr >&2");
390 $client2->succeed("ip addr >&2");
391
392 # Test ipv6
393 $client1->waitUntilSucceeds("ping -c 1 fc00::1");
394 $client1->waitUntilSucceeds("ping -c 1 fc00::2");
395
396 $client2->waitUntilSucceeds("ping -c 1 fc00::1");
397 $client2->waitUntilSucceeds("ping -c 1 fc00::2");
398 '';
399 };
400 vlan = let
401 node = address: { config, pkgs, ... }: with pkgs.lib; {
402 #virtualisation.vlans = [ 1 ];
403 networking = {
404 useNetworkd = networkd;
405 firewall.allowPing = true;
406 useDHCP = false;
407 vlans.vlan = {
408 id = 1;
409 interface = "eth0";
410 };
411 interfaces.eth0.ipv4.addresses = mkOverride 0 [ ];
412 interfaces.eth1.ipv4.addresses = mkOverride 0 [ ];
413 interfaces.vlan.ipv4.addresses = mkOverride 0
414 [ { inherit address; prefixLength = 24; } ];
415 };
416 };
417 in {
418 name = "vlan";
419 nodes.client1 = node "192.168.1.1";
420 nodes.client2 = node "192.168.1.2";
421 testScript = { nodes, ... }:
422 ''
423 startAll;
424
425 # Wait for networking to be configured
426 $client1->waitForUnit("network.target");
427 $client2->waitForUnit("network.target");
428
429 # Test vlan is setup
430 $client1->succeed("ip addr show dev vlan >&2");
431 $client2->succeed("ip addr show dev vlan >&2");
432 '';
433 };
434 virtual = {
435 name = "Virtual";
436 machine = {
437 networking.interfaces."tap0" = {
438 ipv4.addresses = [ { address = "192.168.1.1"; prefixLength = 24; } ];
439 ipv6.addresses = [ { address = "2001:1470:fffd:2096::"; prefixLength = 64; } ];
440 virtual = true;
441 };
442 networking.interfaces."tun0" = {
443 ipv4.addresses = [ { address = "192.168.1.2"; prefixLength = 24; } ];
444 ipv6.addresses = [ { address = "2001:1470:fffd:2097::"; prefixLength = 64; } ];
445 virtual = true;
446 };
447 };
448
449 testScript = ''
450 my $targetList = <<'END';
451 tap0: tap UNKNOWN_FLAGS:800 user 0
452 tun0: tun UNKNOWN_FLAGS:800 user 0
453 END
454
455 # Wait for networking to come up
456 $machine->start;
457 $machine->waitForUnit("network.target");
458
459 # Test interfaces set up
460 my $list = $machine->succeed("ip tuntap list | sort");
461 "$list" eq "$targetList" or die(
462 "The list of virtual interfaces does not match the expected one:\n",
463 "Result:\n", "$list\n",
464 "Expected:\n", "$targetList\n"
465 );
466
467 # Test interfaces clean up
468 $machine->succeed("systemctl stop network-addresses-tap0");
469 $machine->succeed("systemctl stop network-addresses-tun0");
470 my $residue = $machine->succeed("ip tuntap list");
471 $residue eq "" or die(
472 "Some virtual interface has not been properly cleaned:\n",
473 "$residue\n"
474 );
475 '';
476 };
477 privacy = {
478 name = "Privacy";
479 nodes.router = { config, pkgs, ... }: {
480 virtualisation.vlans = [ 1 ];
481 boot.kernel.sysctl."net.ipv6.conf.all.forwarding" = true;
482 networking = {
483 useNetworkd = networkd;
484 interfaces.eth1.ipv6.addresses = singleton {
485 address = "fd00:1234:5678:1::1";
486 prefixLength = 64;
487 };
488 };
489 services.radvd = {
490 enable = true;
491 config = ''
492 interface eth1 {
493 AdvSendAdvert on;
494 AdvManagedFlag on;
495 AdvOtherConfigFlag on;
496
497 prefix fd00:1234:5678:1::/64 {
498 AdvAutonomous on;
499 AdvOnLink on;
500 };
501 };
502 '';
503 };
504 };
505 nodes.client = { config, pkgs, ... }: with pkgs.lib; {
506 virtualisation.vlans = [ 1 ];
507 networking = {
508 useNetworkd = networkd;
509 useDHCP = true;
510 interfaces.eth1 = {
511 preferTempAddress = true;
512 ipv4.addresses = mkOverride 0 [ ];
513 ipv6.addresses = mkOverride 0 [ ];
514 };
515 };
516 };
517 testScript = { nodes, ... }:
518 ''
519 startAll;
520
521 $client->waitForUnit("network.target");
522 $router->waitForUnit("network-online.target");
523
524 # Wait until we have an ip address
525 $client->waitUntilSucceeds("ip addr show dev eth1 | grep -q 'fd00:1234:5678:1:'");
526
527 # Test vlan 1
528 $client->waitUntilSucceeds("ping -c 1 fd00:1234:5678:1::1");
529
530 # Test address used is temporary
531 $client->waitUntilSucceeds("! ip route get fd00:1234:5678:1::1 | grep -q ':[a-f0-9]*ff:fe[a-f0-9]*:'");
532 '';
533 };
534 routes = {
535 name = "routes";
536 machine = {
537 networking.useDHCP = false;
538 networking.interfaces."eth0" = {
539 ipv4.addresses = [ { address = "192.168.1.2"; prefixLength = 24; } ];
540 ipv6.addresses = [ { address = "2001:1470:fffd:2097::"; prefixLength = 64; } ];
541 ipv6.routes = [
542 { address = "fdfd:b3f0::"; prefixLength = 48; }
543 { address = "2001:1470:fffd:2098::"; prefixLength = 64; via = "fdfd:b3f0::1"; }
544 ];
545 ipv4.routes = [
546 { address = "10.0.0.0"; prefixLength = 16; options = { mtu = "1500"; }; }
547 { address = "192.168.2.0"; prefixLength = 24; via = "192.168.1.1"; }
548 ];
549 };
550 virtualisation.vlans = [ ];
551 };
552
553 testScript = ''
554 my $targetIPv4Table = <<'END';
555 10.0.0.0/16 scope link mtu 1500
556 192.168.1.0/24 proto kernel scope link src 192.168.1.2
557 192.168.2.0/24 via 192.168.1.1
558 END
559
560 my $targetIPv6Table = <<'END';
561 2001:1470:fffd:2097::/64 proto kernel metric 256 pref medium
562 2001:1470:fffd:2098::/64 via fdfd:b3f0::1 metric 1024 pref medium
563 fdfd:b3f0::/48 metric 1024 pref medium
564 END
565
566 $machine->start;
567 $machine->waitForUnit("network.target");
568
569 # test routing tables
570 my $ipv4Table = $machine->succeed("ip -4 route list dev eth0 | head -n3");
571 my $ipv6Table = $machine->succeed("ip -6 route list dev eth0 | head -n3");
572 "$ipv4Table" eq "$targetIPv4Table" or die(
573 "The IPv4 routing table does not match the expected one:\n",
574 "Result:\n", "$ipv4Table\n",
575 "Expected:\n", "$targetIPv4Table\n"
576 );
577 "$ipv6Table" eq "$targetIPv6Table" or die(
578 "The IPv6 routing table does not match the expected one:\n",
579 "Result:\n", "$ipv6Table\n",
580 "Expected:\n", "$targetIPv6Table\n"
581 );
582
583 # test clean-up of the tables
584 $machine->succeed("systemctl stop network-addresses-eth0");
585 my $ipv4Residue = $machine->succeed("ip -4 route list dev eth0 | head -n-3");
586 my $ipv6Residue = $machine->succeed("ip -6 route list dev eth0 | head -n-3");
587 $ipv4Residue eq "" or die(
588 "The IPv4 routing table has not been properly cleaned:\n",
589 "$ipv4Residue\n"
590 );
591 $ipv6Residue eq "" or die(
592 "The IPv6 routing table has not been properly cleaned:\n",
593 "$ipv6Residue\n"
594 );
595 '';
596 };
597 };
598
599in mapAttrs (const (attrs: makeTest (attrs // {
600 name = "${attrs.name}-Networking-${if networkd then "Networkd" else "Scripted"}";
601 meta = with pkgs.stdenv.lib.maintainers; {
602 maintainers = [ wkennington ];
603 };
604}))) testCases