nixos/networkd: add [Bridge] section to netdev conf
This setting was missing from netdev. This commit additionally adds a test using the new section, ensuring that STP can be enabled.
This commit is contained in:
parent
ed817f4699
commit
ed854ed0e3
5 changed files with 153 additions and 0 deletions
|
@ -148,6 +148,10 @@ in rec {
|
||||||
optional (attr ? ${name} && !(min <= attr.${name} && max >= attr.${name}))
|
optional (attr ? ${name} && !(min <= attr.${name} && max >= attr.${name}))
|
||||||
"Systemd ${group} field `${name}' is outside the range [${toString min},${toString max}]";
|
"Systemd ${group} field `${name}' is outside the range [${toString min},${toString max}]";
|
||||||
|
|
||||||
|
assertRangeOrOneOf = name: min: max: values: group: attr:
|
||||||
|
optional (attr ? ${name} && !((min <= attr.${name} && max >= attr.${name}) || elem attr.${name} values))
|
||||||
|
"Systemd ${group} field `${name}' is not a value in range [${toString min},${toString max}], or one of ${toString values}";
|
||||||
|
|
||||||
assertMinimum = name: min: group: attr:
|
assertMinimum = name: min: group: attr:
|
||||||
optional (attr ? ${name} && attr.${name} < min)
|
optional (attr ? ${name} && attr.${name} < min)
|
||||||
"Systemd ${group} field `${name}' must be greater than or equal to ${toString min}";
|
"Systemd ${group} field `${name}' must be greater than or equal to ${toString min}";
|
||||||
|
|
|
@ -25,6 +25,9 @@ in {
|
||||||
commonMatchText def + ''
|
commonMatchText def + ''
|
||||||
[NetDev]
|
[NetDev]
|
||||||
${attrsToSection def.netdevConfig}
|
${attrsToSection def.netdevConfig}
|
||||||
|
'' + optionalString (def.bridgeConfig != { }) ''
|
||||||
|
[Bridge]
|
||||||
|
${attrsToSection def.bridgeConfig}
|
||||||
'' + optionalString (def.vlanConfig != { }) ''
|
'' + optionalString (def.vlanConfig != { }) ''
|
||||||
[VLAN]
|
[VLAN]
|
||||||
${attrsToSection def.vlanConfig}
|
${attrsToSection def.vlanConfig}
|
||||||
|
|
|
@ -186,6 +186,37 @@ let
|
||||||
(assertNetdevMacAddress "MACAddress")
|
(assertNetdevMacAddress "MACAddress")
|
||||||
];
|
];
|
||||||
|
|
||||||
|
sectionBridge = checkUnitConfig "Bridge" [
|
||||||
|
(assertOnlyFields [
|
||||||
|
"HelloTimeSec"
|
||||||
|
"MaxAgeSec"
|
||||||
|
"ForwardDelaySec"
|
||||||
|
"AgeingTimeSec"
|
||||||
|
"Priority"
|
||||||
|
"GroupForwardMask"
|
||||||
|
"DefaultPVID"
|
||||||
|
"MulticastQuerier"
|
||||||
|
"MulticastSnooping"
|
||||||
|
"VLANFiltering"
|
||||||
|
"VLANProtocol"
|
||||||
|
"STP"
|
||||||
|
"MulticastIGMPVersion"
|
||||||
|
])
|
||||||
|
(assertInt "HelloTimeSec")
|
||||||
|
(assertInt "MaxAgeSec")
|
||||||
|
(assertInt "ForwardDelaySec")
|
||||||
|
(assertInt "AgeingTimeSec")
|
||||||
|
(assertRange "Priority" 0 65535)
|
||||||
|
(assertRange "GroupForwardMask" 0 65535)
|
||||||
|
(assertRangeOrOneOf "DefaultPVID" 0 4094 ["none"])
|
||||||
|
(assertValueOneOf "MulticastQuerier" boolValues)
|
||||||
|
(assertValueOneOf "MulticastSnooping" boolValues)
|
||||||
|
(assertValueOneOf "VLANFiltering" boolValues)
|
||||||
|
(assertValueOneOf "VLANProtocol" ["802.1q" "802.ad"])
|
||||||
|
(assertValueOneOf "STP" boolValues)
|
||||||
|
(assertValueOneOf "MulticastIGMPVersion" [2 3])
|
||||||
|
];
|
||||||
|
|
||||||
sectionVLAN = checkUnitConfig "VLAN" [
|
sectionVLAN = checkUnitConfig "VLAN" [
|
||||||
(assertOnlyFields [
|
(assertOnlyFields [
|
||||||
"Id"
|
"Id"
|
||||||
|
@ -1635,6 +1666,17 @@ let
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bridgeConfig = mkOption {
|
||||||
|
default = {};
|
||||||
|
example = { STP = true; };
|
||||||
|
type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionBridge;
|
||||||
|
description = ''
|
||||||
|
Each attribute in this set specifies an option in the
|
||||||
|
`[Bridge]` section of the unit. See
|
||||||
|
{manpage}`systemd.netdev(5)` for details.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
vlanConfig = mkOption {
|
vlanConfig = mkOption {
|
||||||
default = {};
|
default = {};
|
||||||
example = { Id = 4; };
|
example = { Id = 4; };
|
||||||
|
|
|
@ -899,6 +899,7 @@ in {
|
||||||
systemd-lock-handler = runTestOn ["aarch64-linux" "x86_64-linux"] ./systemd-lock-handler.nix;
|
systemd-lock-handler = runTestOn ["aarch64-linux" "x86_64-linux"] ./systemd-lock-handler.nix;
|
||||||
systemd-machinectl = handleTest ./systemd-machinectl.nix {};
|
systemd-machinectl = handleTest ./systemd-machinectl.nix {};
|
||||||
systemd-networkd = handleTest ./systemd-networkd.nix {};
|
systemd-networkd = handleTest ./systemd-networkd.nix {};
|
||||||
|
systemd-networkd-bridge = handleTest ./systemd-networkd-bridge.nix {};
|
||||||
systemd-networkd-dhcpserver = handleTest ./systemd-networkd-dhcpserver.nix {};
|
systemd-networkd-dhcpserver = handleTest ./systemd-networkd-dhcpserver.nix {};
|
||||||
systemd-networkd-dhcpserver-static-leases = handleTest ./systemd-networkd-dhcpserver-static-leases.nix {};
|
systemd-networkd-dhcpserver-static-leases = handleTest ./systemd-networkd-dhcpserver-static-leases.nix {};
|
||||||
systemd-networkd-ipv6-prefix-delegation = handleTest ./systemd-networkd-ipv6-prefix-delegation.nix {};
|
systemd-networkd-ipv6-prefix-delegation = handleTest ./systemd-networkd-ipv6-prefix-delegation.nix {};
|
||||||
|
|
103
nixos/tests/systemd-networkd-bridge.nix
Normal file
103
nixos/tests/systemd-networkd-bridge.nix
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
/* This test ensures that we can configure spanning-tree protocol
|
||||||
|
across bridges using systemd-networkd.
|
||||||
|
|
||||||
|
Test topology:
|
||||||
|
|
||||||
|
1 2 3
|
||||||
|
node1 --- sw1 --- sw2 --- node2
|
||||||
|
\ /
|
||||||
|
4 \ / 5
|
||||||
|
sw3
|
||||||
|
|
|
||||||
|
6 |
|
||||||
|
|
|
||||||
|
node3
|
||||||
|
|
||||||
|
where switches 1, 2, and 3 bridge their links and use STP,
|
||||||
|
and each link is labeled with the VLAN we are assigning it in
|
||||||
|
virtualisation.vlans.
|
||||||
|
*/
|
||||||
|
with builtins;
|
||||||
|
let
|
||||||
|
commonConf = {
|
||||||
|
systemd.services.systemd-networkd.environment.SYSTEMD_LOG_LEVEL = "debug";
|
||||||
|
networking.useNetworkd = true;
|
||||||
|
networking.useDHCP = false;
|
||||||
|
networking.firewall.enable = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
generateNodeConf = { octet, vlan }:
|
||||||
|
{ lib, pkgs, config, ... }: {
|
||||||
|
imports = [ common/user-account.nix commonConf ];
|
||||||
|
virtualisation.vlans = [ vlan ];
|
||||||
|
systemd.network = {
|
||||||
|
enable = true;
|
||||||
|
networks = {
|
||||||
|
"30-eth" = {
|
||||||
|
matchConfig.Name = "eth1";
|
||||||
|
address = [ "10.0.0.${toString octet}/24" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
generateSwitchConf = vlans:
|
||||||
|
{ lib, pkgs, config, ... }: {
|
||||||
|
imports = [ common/user-account.nix commonConf ];
|
||||||
|
virtualisation.vlans = vlans;
|
||||||
|
systemd.network = {
|
||||||
|
enable = true;
|
||||||
|
netdevs = {
|
||||||
|
"40-br0" = {
|
||||||
|
netdevConfig = {
|
||||||
|
Kind = "bridge";
|
||||||
|
Name = "br0";
|
||||||
|
};
|
||||||
|
bridgeConfig.STP = "yes";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
networks = {
|
||||||
|
"30-eth" = {
|
||||||
|
matchConfig.Name = "eth*";
|
||||||
|
networkConfig.Bridge = "br0";
|
||||||
|
};
|
||||||
|
"40-br0" = { matchConfig.Name = "br0"; };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
in import ./make-test-python.nix ({ pkgs, ... }: {
|
||||||
|
name = "networkd";
|
||||||
|
meta = with pkgs.lib.maintainers; { maintainers = [ picnoir ]; };
|
||||||
|
nodes = {
|
||||||
|
node1 = generateNodeConf {
|
||||||
|
octet = 1;
|
||||||
|
vlan = 1;
|
||||||
|
};
|
||||||
|
node2 = generateNodeConf {
|
||||||
|
octet = 2;
|
||||||
|
vlan = 3;
|
||||||
|
};
|
||||||
|
node3 = generateNodeConf {
|
||||||
|
octet = 3;
|
||||||
|
vlan = 6;
|
||||||
|
};
|
||||||
|
sw1 = generateSwitchConf [ 1 2 4 ];
|
||||||
|
sw2 = generateSwitchConf [ 2 3 5 ];
|
||||||
|
sw3 = generateSwitchConf [ 4 5 6 ];
|
||||||
|
};
|
||||||
|
testScript = ''
|
||||||
|
network_nodes = [node1, node2, node3]
|
||||||
|
network_switches = [sw1, sw2, sw3]
|
||||||
|
start_all()
|
||||||
|
|
||||||
|
for n in network_nodes + network_switches:
|
||||||
|
n.wait_for_unit("systemd-networkd-wait-online.service")
|
||||||
|
|
||||||
|
node1.succeed("ping 10.0.0.2 -w 10 -c 1")
|
||||||
|
node1.succeed("ping 10.0.0.3 -w 10 -c 1")
|
||||||
|
node2.succeed("ping 10.0.0.1 -w 10 -c 1")
|
||||||
|
node2.succeed("ping 10.0.0.3 -w 10 -c 1")
|
||||||
|
node3.succeed("ping 10.0.0.1 -w 10 -c 1")
|
||||||
|
node3.succeed("ping 10.0.0.2 -w 10 -c 1")
|
||||||
|
'';
|
||||||
|
})
|
Loading…
Reference in a new issue