Skip to content

Commit

Permalink
network: simplify network interface units to make them more reliable
Browse files Browse the repository at this point in the history
All network interface now use "-netdev.service" units, even if they
have underlying physical devices and were previously depending on
systemd device units. This proved to be unreliable when trying to
transform systems between complex configuration states without
requiring a reboot and ended up in undefined states.

Includes a backport of NixOS#240295

Re PL-132441
  • Loading branch information
ctheune committed Apr 30, 2024
1 parent 6e3cc0a commit 1c4192a
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 21 deletions.
34 changes: 14 additions & 20 deletions nixos/modules/tasks/network-interfaces-scripted.nix
Original file line number Diff line number Diff line change
Expand Up @@ -67,18 +67,8 @@ let
systemd.services =
let

deviceDependency = dev:
# Use systemd service if we manage device creation, else
# trust udev when not in a container
if (hasAttr dev (filterAttrs (k: v: v.virtual) cfg.interfaces)) ||
(hasAttr dev cfg.bridges) ||
(hasAttr dev cfg.bonds) ||
(hasAttr dev cfg.macvlans) ||
(hasAttr dev cfg.sits) ||
(hasAttr dev cfg.vlans) ||
(hasAttr dev cfg.vswitches)
then [ "${dev}-netdev.service" ]
else optional (dev != null && dev != "lo" && !config.boot.isContainer) (subsystemDevice dev);
deviceDependency = dev:
if (dev != null && dev != "lo" && !config.boot.isContainer) then [ "${dev}-netdev.service" ] else [];

hasDefaultGatewaySet = (cfg.defaultGateway != null && cfg.defaultGateway.address != "")
|| (cfg.enableIPv6 && cfg.defaultGateway6 != null && cfg.defaultGateway6.address != "");
Expand All @@ -94,8 +84,10 @@ let
after = [ "network-pre.target" "systemd-udevd.service" "systemd-sysctl.service" ];
before = [ "network.target" "shutdown.target" ];
wants = [ "network.target" ];

# exclude bridges from the partOf relationship to fix container networking bug #47210
partOf = map (i: "network-addresses-${i.name}.service") (filter (i: !(hasAttr i.name cfg.bridges)) interfaces);
requiredBy = map (i: "network-addresses-${i.name}.service") (filter (i: !(hasAttr i.name cfg.bridges)) interfaces);

conflicts = [ "shutdown.target" ];
wantedBy = [ "multi-user.target" ] ++ optional hasDefaultGatewaySet "network-online.target";

Expand Down Expand Up @@ -174,10 +166,12 @@ let
wantedBy = [
"network-setup.service"
"network.target"
"multi-user.target"
];
# order before network-setup because the routes that are configured
# there may need ip addresses configured
before = [ "network-setup.service" ];
requires = [ "network-setup.service" ];
bindsTo = deviceDependency i.name;
after = [ "network-pre.target" ] ++ (deviceDependency i.name);
serviceConfig.Type = "oneshot";
Expand Down Expand Up @@ -256,7 +250,7 @@ let
bindsTo = optional (!config.boot.isContainer) "dev-net-tun.device";
after = optional (!config.boot.isContainer) "dev-net-tun.device" ++ [ "network-pre.target" ];
wantedBy = [ "network-setup.service" (subsystemDevice i.name) ];
partOf = [ "network-setup.service" ];
requires = [ "network-setup.service" ];
before = [ "network-setup.service" ];
path = [ pkgs.iproute2 ];
serviceConfig = {
Expand All @@ -278,7 +272,7 @@ let
{ description = "Bridge Interface ${n}";
wantedBy = [ "network-setup.service" (subsystemDevice n) ];
bindsTo = deps ++ optional v.rstp "mstpd.service";
partOf = [ "network-setup.service" ] ++ optional v.rstp "mstpd.service";
requires = [ "network-setup.service" ] ++ optional v.rstp "mstpd.service";
after = [ "network-pre.target" ] ++ deps ++ optional v.rstp "mstpd.service"
++ map (i: "network-addresses-${i}.service") v.interfaces;
before = [ "network-setup.service" ];
Expand Down Expand Up @@ -366,7 +360,7 @@ let
# should work without internalConfigs dependencies because address/link configuration depends
# on the device, which is created by ovs-vswitchd with type=internal, but it does not...
before = [ "network-setup.service" ] ++ internalConfigs;
partOf = [ "network-setup.service" ]; # shutdown the bridge when network is shutdown
requires = [ "network-setup.service" ]; # shutdown the bridge when network is shutdown
bindsTo = [ "ovs-vswitchd.service" ]; # requires ovs-vswitchd to be alive at all times
after = [ "network-pre.target" "ovs-vswitchd.service" ] ++ deps; # start switch after physical interfaces and vswitch daemon
wants = deps; # if one or more interface fails, the switch should continue to run
Expand Down Expand Up @@ -407,7 +401,7 @@ let
{ description = "Bond Interface ${n}";
wantedBy = [ "network-setup.service" (subsystemDevice n) ];
bindsTo = deps;
partOf = [ "network-setup.service" ];
requires = [ "network-setup.service" ];
after = [ "network-pre.target" ] ++ deps
++ map (i: "network-addresses-${i}.service") v.interfaces;
before = [ "network-setup.service" ];
Expand Down Expand Up @@ -446,7 +440,7 @@ let
{ description = "Vlan Interface ${n}";
wantedBy = [ "network-setup.service" (subsystemDevice n) ];
bindsTo = deps;
partOf = [ "network-setup.service" ];
requires = [ "network-setup.service" ];
after = [ "network-pre.target" ] ++ deps;
before = [ "network-setup.service" ];
serviceConfig.Type = "oneshot";
Expand All @@ -471,7 +465,7 @@ let
{ description = "6-to-4 Tunnel Interface ${n}";
wantedBy = [ "network-setup.service" (subsystemDevice n) ];
bindsTo = deps;
partOf = [ "network-setup.service" ];
requires = [ "network-setup.service" ];
after = [ "network-pre.target" ] ++ deps;
before = [ "network-setup.service" ];
serviceConfig.Type = "oneshot";
Expand Down Expand Up @@ -499,7 +493,7 @@ let
{ description = "Vlan Interface ${n}";
wantedBy = [ "network-setup.service" (subsystemDevice n) ];
bindsTo = deps;
partOf = [ "network-setup.service" ];
requires = [ "network-setup.service" ];
after = [ "network-pre.target" ] ++ deps;
before = [ "network-setup.service" ];
serviceConfig.Type = "oneshot";
Expand Down
2 changes: 1 addition & 1 deletion nixos/modules/tasks/network-interfaces.nix
Original file line number Diff line number Diff line change
Expand Up @@ -1249,7 +1249,7 @@ in
in
''
# override to ${msg} for ${i.name}
ACTION=="add", SUBSYSTEM=="net", RUN+="${pkgs.procps}/bin/sysctl net.ipv6.conf.${replaceChars ["."] ["/"] i.name}.use_tempaddr=${val}"
ACTION=="add", SUBSYSTEM=="net", NAME=="${i.name}", RUN+="${pkgs.procps}/bin/sysctl net.ipv6.conf.${replaceChars ["."] ["/"] i.name}.use_tempaddr=${val}"
'') (filter (i: i.tempAddress != cfg.tempAddresses) interfaces);
})
] ++ lib.optional (cfg.wlanInterfaces != {})
Expand Down

0 comments on commit 1c4192a

Please sign in to comment.