Skip to content

Commit

Permalink
Merge pull request NixOS#304117 from ifd3f/systemd-networkd-bridge-co…
Browse files Browse the repository at this point in the history
…nfig

nixos/networkd: add [Bridge] section to netdev conf
  • Loading branch information
flokli authored Apr 15, 2024
2 parents 9b213c7 + ed854ed commit 104f0b6
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 0 deletions.
4 changes: 4 additions & 0 deletions nixos/lib/systemd-lib.nix
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,10 @@ in rec {
optional (attr ? ${name} && !(min <= attr.${name} && max >= attr.${name}))
"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:
optional (attr ? ${name} && attr.${name} < min)
"Systemd ${group} field `${name}' must be greater than or equal to ${toString min}";
Expand Down
3 changes: 3 additions & 0 deletions nixos/lib/systemd-network-units.nix
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ in {
commonMatchText def + ''
[NetDev]
${attrsToSection def.netdevConfig}
'' + optionalString (def.bridgeConfig != { }) ''
[Bridge]
${attrsToSection def.bridgeConfig}
'' + optionalString (def.vlanConfig != { }) ''
[VLAN]
${attrsToSection def.vlanConfig}
Expand Down
42 changes: 42 additions & 0 deletions nixos/modules/system/boot/networkd.nix
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,37 @@ let
(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" [
(assertOnlyFields [
"Id"
Expand Down Expand Up @@ -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 {
default = {};
example = { Id = 4; };
Expand Down
1 change: 1 addition & 0 deletions nixos/tests/all-tests.nix
Original file line number Diff line number Diff line change
Expand Up @@ -900,6 +900,7 @@ in {
systemd-lock-handler = runTestOn ["aarch64-linux" "x86_64-linux"] ./systemd-lock-handler.nix;
systemd-machinectl = handleTest ./systemd-machinectl.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-static-leases = handleTest ./systemd-networkd-dhcpserver-static-leases.nix {};
systemd-networkd-ipv6-prefix-delegation = handleTest ./systemd-networkd-ipv6-prefix-delegation.nix {};
Expand Down
103 changes: 103 additions & 0 deletions nixos/tests/systemd-networkd-bridge.nix
Original file line number Diff line number Diff line change
@@ -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")
'';
})

0 comments on commit 104f0b6

Please sign in to comment.