1{ system ? builtins.currentSystem, networkd }:
2
3with import ../lib/testing.nix { inherit system; };
4with pkgs.lib;
5
6let
7 router = { config, pkgs, ... }:
8 with pkgs.lib;
9 let
10 vlanIfs = range 1 (length config.virtualisation.vlans);
11 in {
12 virtualisation.vlans = [ 1 2 3 ];
13 networking = {
14 useDHCP = false;
15 useNetworkd = networkd;
16 firewall.allowPing = true;
17 interfaces = mkOverride 0 (listToAttrs (flip map vlanIfs (n:
18 nameValuePair "eth${toString n}" {
19 ipAddress = "192.168.${toString n}.1";
20 prefixLength = 24;
21 })));
22 };
23 services.dhcpd = {
24 enable = true;
25 interfaces = map (n: "eth${toString n}") vlanIfs;
26 extraConfig = ''
27 option subnet-mask 255.255.255.0;
28 '' + flip concatMapStrings vlanIfs (n: ''
29 subnet 192.168.${toString n}.0 netmask 255.255.255.0 {
30 option broadcast-address 192.168.${toString n}.255;
31 option routers 192.168.${toString n}.1;
32 range 192.168.${toString n}.2 192.168.${toString n}.254;
33 }
34 '');
35 };
36 };
37
38 testCases = {
39 loopback = {
40 name = "Loopback";
41 machine.networking.useNetworkd = networkd;
42 testScript = ''
43 startAll;
44 $machine->waitForUnit("network-interfaces.target");
45 $machine->waitForUnit("network.target");
46 $machine->succeed("ip addr show lo | grep -q 'inet 127.0.0.1/8 '");
47 $machine->succeed("ip addr show lo | grep -q 'inet6 ::1/128 '");
48 '';
49 };
50 static = {
51 name = "Static";
52 nodes.router = router;
53 nodes.client = { config, pkgs, ... }: with pkgs.lib; {
54 virtualisation.vlans = [ 1 2 ];
55 networking = {
56 useNetworkd = networkd;
57 firewall.allowPing = true;
58 useDHCP = false;
59 defaultGateway = "192.168.1.1";
60 interfaces.eth1.ip4 = mkOverride 0 [
61 { address = "192.168.1.2"; prefixLength = 24; }
62 { address = "192.168.1.3"; prefixLength = 32; }
63 { address = "192.168.1.10"; prefixLength = 32; }
64 ];
65 interfaces.eth2.ip4 = mkOverride 0 [
66 { address = "192.168.2.2"; prefixLength = 24; }
67 ];
68 };
69 };
70 testScript = { nodes, ... }:
71 ''
72 startAll;
73
74 $client->waitForUnit("network-interfaces.target");
75 $client->waitForUnit("network.target");
76 $router->waitForUnit("network-interfaces.target");
77 $router->waitForUnit("network.target");
78
79 # Make sure dhcpcd is not started
80 $client->fail("systemctl status dhcpcd.service");
81
82 # Test vlan 1
83 $client->waitUntilSucceeds("ping -c 1 192.168.1.1");
84 $client->waitUntilSucceeds("ping -c 1 192.168.1.2");
85 $client->waitUntilSucceeds("ping -c 1 192.168.1.3");
86 $client->waitUntilSucceeds("ping -c 1 192.168.1.10");
87
88 $router->waitUntilSucceeds("ping -c 1 192.168.1.1");
89 $router->waitUntilSucceeds("ping -c 1 192.168.1.2");
90 $router->waitUntilSucceeds("ping -c 1 192.168.1.3");
91 $router->waitUntilSucceeds("ping -c 1 192.168.1.10");
92
93 # Test vlan 2
94 $client->waitUntilSucceeds("ping -c 1 192.168.2.1");
95 $client->waitUntilSucceeds("ping -c 1 192.168.2.2");
96
97 $router->waitUntilSucceeds("ping -c 1 192.168.2.1");
98 $router->waitUntilSucceeds("ping -c 1 192.168.2.2");
99
100 # Test default gateway
101 $router->waitUntilSucceeds("ping -c 1 192.168.3.1");
102 $client->waitUntilSucceeds("ping -c 1 192.168.3.1");
103 '';
104 };
105 dhcpSimple = {
106 name = "SimpleDHCP";
107 nodes.router = router;
108 nodes.client = { config, pkgs, ... }: with pkgs.lib; {
109 virtualisation.vlans = [ 1 2 ];
110 networking = {
111 useNetworkd = networkd;
112 firewall.allowPing = true;
113 useDHCP = true;
114 interfaces.eth1.ip4 = mkOverride 0 [ ];
115 interfaces.eth2.ip4 = mkOverride 0 [ ];
116 };
117 };
118 testScript = { nodes, ... }:
119 ''
120 startAll;
121
122 $client->waitForUnit("network-interfaces.target");
123 $client->waitForUnit("network.target");
124 $router->waitForUnit("network-interfaces.target");
125 $router->waitForUnit("network.target");
126
127 # Wait until we have an ip address on each interface
128 $client->waitUntilSucceeds("ip addr show dev eth1 | grep -q '192.168.1'");
129 $client->waitUntilSucceeds("ip addr show dev eth2 | grep -q '192.168.2'");
130
131 # Test vlan 1
132 $client->waitUntilSucceeds("ping -c 1 192.168.1.1");
133 $client->waitUntilSucceeds("ping -c 1 192.168.1.2");
134
135 $router->waitUntilSucceeds("ping -c 1 192.168.1.1");
136 $router->waitUntilSucceeds("ping -c 1 192.168.1.2");
137
138 # Test vlan 2
139 $client->waitUntilSucceeds("ping -c 1 192.168.2.1");
140 $client->waitUntilSucceeds("ping -c 1 192.168.2.2");
141
142 $router->waitUntilSucceeds("ping -c 1 192.168.2.1");
143 $router->waitUntilSucceeds("ping -c 1 192.168.2.2");
144 '';
145 };
146 dhcpOneIf = {
147 name = "OneInterfaceDHCP";
148 nodes.router = router;
149 nodes.client = { config, pkgs, ... }: with pkgs.lib; {
150 virtualisation.vlans = [ 1 2 ];
151 networking = {
152 useNetworkd = networkd;
153 firewall.allowPing = true;
154 useDHCP = false;
155 interfaces.eth1 = {
156 ip4 = mkOverride 0 [ ];
157 useDHCP = true;
158 };
159 interfaces.eth2.ip4 = mkOverride 0 [ ];
160 };
161 };
162 testScript = { nodes, ... }:
163 ''
164 startAll;
165
166 # Wait for networking to come up
167 $client->waitForUnit("network-interfaces.target");
168 $client->waitForUnit("network.target");
169 $router->waitForUnit("network-interfaces.target");
170 $router->waitForUnit("network.target");
171
172 # Wait until we have an ip address on each interface
173 $client->waitUntilSucceeds("ip addr show dev eth1 | grep -q '192.168.1'");
174
175 # Test vlan 1
176 $client->waitUntilSucceeds("ping -c 1 192.168.1.1");
177 $client->waitUntilSucceeds("ping -c 1 192.168.1.2");
178
179 $router->waitUntilSucceeds("ping -c 1 192.168.1.1");
180 $router->waitUntilSucceeds("ping -c 1 192.168.1.2");
181
182 # Test vlan 2
183 $client->waitUntilSucceeds("ping -c 1 192.168.2.1");
184 $client->fail("ping -c 1 192.168.2.2");
185
186 $router->waitUntilSucceeds("ping -c 1 192.168.2.1");
187 $router->fail("ping -c 1 192.168.2.2");
188 '';
189 };
190 bond = let
191 node = address: { config, pkgs, ... }: with pkgs.lib; {
192 virtualisation.vlans = [ 1 2 ];
193 networking = {
194 useNetworkd = networkd;
195 firewall.allowPing = true;
196 useDHCP = false;
197 bonds.bond = {
198 mode = "balance-rr";
199 interfaces = [ "eth1" "eth2" ];
200 };
201 interfaces.eth1.ip4 = mkOverride 0 [ ];
202 interfaces.eth2.ip4 = mkOverride 0 [ ];
203 interfaces.bond.ip4 = mkOverride 0
204 [ { inherit address; prefixLength = 30; } ];
205 };
206 };
207 in {
208 name = "Bond";
209 nodes.client1 = node "192.168.1.1";
210 nodes.client2 = node "192.168.1.2";
211 testScript = { nodes, ... }:
212 ''
213 startAll;
214
215 # Wait for networking to come up
216 $client1->waitForUnit("network-interfaces.target");
217 $client1->waitForUnit("network.target");
218 $client2->waitForUnit("network-interfaces.target");
219 $client2->waitForUnit("network.target");
220
221 # Test bonding
222 $client1->waitUntilSucceeds("ping -c 2 192.168.1.1");
223 $client1->waitUntilSucceeds("ping -c 2 192.168.1.2");
224
225 $client2->waitUntilSucceeds("ping -c 2 192.168.1.1");
226 $client2->waitUntilSucceeds("ping -c 2 192.168.1.2");
227 '';
228 };
229 bridge = let
230 node = { address, vlan }: { config, pkgs, ... }: with pkgs.lib; {
231 virtualisation.vlans = [ vlan ];
232 networking = {
233 useNetworkd = networkd;
234 firewall.allowPing = true;
235 useDHCP = false;
236 interfaces.eth1.ip4 = mkOverride 0
237 [ { inherit address; prefixLength = 24; } ];
238 };
239 };
240 in {
241 name = "Bridge";
242 nodes.client1 = node { address = "192.168.1.2"; vlan = 1; };
243 nodes.client2 = node { address = "192.168.1.3"; vlan = 2; };
244 nodes.router = { config, pkgs, ... }: with pkgs.lib; {
245 virtualisation.vlans = [ 1 2 ];
246 networking = {
247 useNetworkd = networkd;
248 firewall.allowPing = true;
249 useDHCP = false;
250 bridges.bridge.interfaces = [ "eth1" "eth2" ];
251 interfaces.eth1.ip4 = mkOverride 0 [ ];
252 interfaces.eth2.ip4 = mkOverride 0 [ ];
253 interfaces.bridge.ip4 = mkOverride 0
254 [ { address = "192.168.1.1"; prefixLength = 24; } ];
255 };
256 };
257 testScript = { nodes, ... }:
258 ''
259 startAll;
260
261 # Wait for networking to come up
262 $client1->waitForUnit("network-interfaces.target");
263 $client1->waitForUnit("network.target");
264 $client2->waitForUnit("network-interfaces.target");
265 $client2->waitForUnit("network.target");
266 $router->waitForUnit("network-interfaces.target");
267 $router->waitForUnit("network.target");
268
269 # Test bridging
270 $client1->waitUntilSucceeds("ping -c 1 192.168.1.1");
271 $client1->waitUntilSucceeds("ping -c 1 192.168.1.2");
272 $client1->waitUntilSucceeds("ping -c 1 192.168.1.3");
273
274 $client2->waitUntilSucceeds("ping -c 1 192.168.1.1");
275 $client2->waitUntilSucceeds("ping -c 1 192.168.1.2");
276 $client2->waitUntilSucceeds("ping -c 1 192.168.1.3");
277
278 $router->waitUntilSucceeds("ping -c 1 192.168.1.1");
279 $router->waitUntilSucceeds("ping -c 1 192.168.1.2");
280 $router->waitUntilSucceeds("ping -c 1 192.168.1.3");
281 '';
282 };
283 macvlan = {
284 name = "MACVLAN";
285 nodes.router = router;
286 nodes.client = { config, pkgs, ... }: with pkgs.lib; {
287 virtualisation.vlans = [ 1 ];
288 networking = {
289 useNetworkd = networkd;
290 firewall.allowPing = true;
291 useDHCP = true;
292 macvlans.macvlan.interface = "eth1";
293 interfaces.eth1.ip4 = mkOverride 0 [ ];
294 };
295 };
296 testScript = { nodes, ... }:
297 ''
298 startAll;
299
300 # Wait for networking to come up
301 $client->waitForUnit("network-interfaces.target");
302 $client->waitForUnit("network.target");
303 $router->waitForUnit("network-interfaces.target");
304 $router->waitForUnit("network.target");
305
306 # Wait until we have an ip address on each interface
307 $client->waitUntilSucceeds("ip addr show dev eth1 | grep -q '192.168.1'");
308 $client->waitUntilSucceeds("ip addr show dev macvlan | grep -q '192.168.1'");
309
310 # Print diagnosting information
311 $router->succeed("ip addr >&2");
312 $client->succeed("ip addr >&2");
313
314 # Test macvlan creates routable ips
315 $client->waitUntilSucceeds("ping -c 1 192.168.1.1");
316 $client->waitUntilSucceeds("ping -c 1 192.168.1.2");
317 $client->waitUntilSucceeds("ping -c 1 192.168.1.3");
318
319 $router->waitUntilSucceeds("ping -c 1 192.168.1.1");
320 $router->waitUntilSucceeds("ping -c 1 192.168.1.2");
321 $router->waitUntilSucceeds("ping -c 1 192.168.1.3");
322 '';
323 };
324 sit = let
325 node = { address4, remote, address6 }: { config, pkgs, ... }: with pkgs.lib; {
326 virtualisation.vlans = [ 1 ];
327 networking = {
328 useNetworkd = networkd;
329 firewall.enable = false;
330 useDHCP = false;
331 sits.sit = {
332 inherit remote;
333 local = address4;
334 dev = "eth1";
335 };
336 interfaces.eth1.ip4 = mkOverride 0
337 [ { address = address4; prefixLength = 24; } ];
338 interfaces.sit.ip6 = mkOverride 0
339 [ { address = address6; prefixLength = 64; } ];
340 };
341 };
342 in {
343 name = "Sit";
344 nodes.client1 = node { address4 = "192.168.1.1"; remote = "192.168.1.2"; address6 = "fc00::1"; };
345 nodes.client2 = node { address4 = "192.168.1.2"; remote = "192.168.1.1"; address6 = "fc00::2"; };
346 testScript = { nodes, ... }:
347 ''
348 startAll;
349
350 # Wait for networking to be configured
351 $client1->waitForUnit("network-interfaces.target");
352 $client1->waitForUnit("network.target");
353 $client2->waitForUnit("network-interfaces.target");
354 $client2->waitForUnit("network.target");
355
356 # Print diagnostic information
357 $client1->succeed("ip addr >&2");
358 $client2->succeed("ip addr >&2");
359
360 # Test ipv6
361 $client1->waitUntilSucceeds("ping6 -c 1 fc00::1");
362 $client1->waitUntilSucceeds("ping6 -c 1 fc00::2");
363
364 $client2->waitUntilSucceeds("ping6 -c 1 fc00::1");
365 $client2->waitUntilSucceeds("ping6 -c 1 fc00::2");
366 '';
367 };
368 vlan = let
369 node = address: { config, pkgs, ... }: with pkgs.lib; {
370 #virtualisation.vlans = [ 1 ];
371 networking = {
372 useNetworkd = networkd;
373 firewall.allowPing = true;
374 useDHCP = false;
375 vlans.vlan = {
376 id = 1;
377 interface = "eth0";
378 };
379 interfaces.eth0.ip4 = mkOverride 0 [ ];
380 interfaces.eth1.ip4 = mkOverride 0 [ ];
381 interfaces.vlan.ip4 = mkOverride 0
382 [ { inherit address; prefixLength = 24; } ];
383 };
384 };
385 in {
386 name = "vlan";
387 nodes.client1 = node "192.168.1.1";
388 nodes.client2 = node "192.168.1.2";
389 testScript = { nodes, ... }:
390 ''
391 startAll;
392
393 # Wait for networking to be configured
394 $client1->waitForUnit("network-interfaces.target");
395 $client1->waitForUnit("network.target");
396 $client2->waitForUnit("network-interfaces.target");
397 $client2->waitForUnit("network.target");
398
399 # Test vlan is setup
400 $client1->succeed("ip addr show dev vlan >&2");
401 $client2->succeed("ip addr show dev vlan >&2");
402 '';
403 };
404 };
405
406in mapAttrs (const (attrs: makeTest (attrs // {
407 name = "${attrs.name}-Networking-${if networkd then "Networkd" else "Scripted"}";
408 meta = with pkgs.stdenv.lib.maintainers; {
409 maintainers = [ wkennington ];
410 };
411}))) testCases