1/*
2 This test ensures that we can configure spanning-tree protocol
3 across bridges using systemd-networkd.
4
5 Test topology:
6
7 1 2 3
8 node1 --- sw1 --- sw2 --- node2
9 \ /
10 4 \ / 5
11 sw3
12 |
13 6 |
14 |
15 node3
16
17 where switches 1, 2, and 3 bridge their links and use STP,
18 and each link is labeled with the VLAN we are assigning it in
19 virtualisation.vlans.
20*/
21with builtins;
22let
23 commonConf = {
24 systemd.services.systemd-networkd.environment.SYSTEMD_LOG_LEVEL = "debug";
25 networking.useNetworkd = true;
26 networking.useDHCP = false;
27 networking.firewall.enable = false;
28 };
29
30 generateNodeConf =
31 { octet, vlan }:
32 {
33 lib,
34 pkgs,
35 config,
36 ...
37 }:
38 {
39 imports = [
40 common/user-account.nix
41 commonConf
42 ];
43 virtualisation.vlans = [ vlan ];
44 systemd.network = {
45 enable = true;
46 networks = {
47 "30-eth" = {
48 matchConfig.Name = "eth1";
49 address = [ "10.0.0.${toString octet}/24" ];
50 };
51 };
52 };
53 };
54
55 generateSwitchConf =
56 vlans:
57 {
58 lib,
59 pkgs,
60 config,
61 ...
62 }:
63 {
64 imports = [
65 common/user-account.nix
66 commonConf
67 ];
68 virtualisation.vlans = vlans;
69 systemd.network = {
70 enable = true;
71 netdevs = {
72 "40-br0" = {
73 netdevConfig = {
74 Kind = "bridge";
75 Name = "br0";
76 };
77 bridgeConfig.STP = "yes";
78 };
79 };
80 networks = {
81 "30-eth" = {
82 matchConfig.Name = "eth*";
83 networkConfig.Bridge = "br0";
84 };
85 "40-br0" = {
86 matchConfig.Name = "br0";
87 };
88 };
89 };
90 };
91in
92{ pkgs, ... }:
93{
94 name = "networkd";
95 meta = with pkgs.lib.maintainers; {
96 maintainers = [ picnoir ];
97 };
98 nodes = {
99 node1 = generateNodeConf {
100 octet = 1;
101 vlan = 1;
102 };
103 node2 = generateNodeConf {
104 octet = 2;
105 vlan = 3;
106 };
107 node3 = generateNodeConf {
108 octet = 3;
109 vlan = 6;
110 };
111 sw1 = generateSwitchConf [
112 1
113 2
114 4
115 ];
116 sw2 = generateSwitchConf [
117 2
118 3
119 5
120 ];
121 sw3 = generateSwitchConf [
122 4
123 5
124 6
125 ];
126 };
127 testScript = ''
128 network_nodes = [node1, node2, node3]
129 network_switches = [sw1, sw2, sw3]
130 start_all()
131
132 for n in network_nodes + network_switches:
133 n.systemctl("start systemd-networkd-wait-online.service")
134 n.wait_for_unit("systemd-networkd-wait-online.service")
135
136 node1.succeed("ping 10.0.0.2 -w 10 -c 1")
137 node1.succeed("ping 10.0.0.3 -w 10 -c 1")
138 node2.succeed("ping 10.0.0.1 -w 10 -c 1")
139 node2.succeed("ping 10.0.0.3 -w 10 -c 1")
140 node3.succeed("ping 10.0.0.1 -w 10 -c 1")
141 node3.succeed("ping 10.0.0.2 -w 10 -c 1")
142 '';
143}