Unverified Commit 104f0b61 authored by Florian Klink's avatar Florian Klink Committed by GitHub
Browse files

Merge pull request #304117 from ifd3f/systemd-networkd-bridge-config

nixos/networkd: add [Bridge] section to netdev conf
parents 9b213c7e ed854ed0
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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}";
+3 −0
Original line number Diff line number Diff line
@@ -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}
+42 −0
Original line number Diff line number Diff line
@@ -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"
@@ -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; };
+1 −0
Original line number Diff line number Diff line
@@ -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 {};
+103 −0
Original line number Diff line number Diff line
/* 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")
  '';
})