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.

This is a forward port of: 1c4192a

Co-authored-by: Christian Theune <ct@flyingcircus.io>
  • Loading branch information
2 people authored and osnyx committed Dec 11, 2024
1 parent d180342 commit bfe6984
Showing 1 changed file with 19 additions and 24 deletions.
43 changes: 19 additions & 24 deletions nixos/modules/tasks/network-interfaces-scripted.nix
Original file line number Diff line number Diff line change
Expand Up @@ -68,23 +68,16 @@ let
let

deviceDependency = dev:
# Use systemd service if we manage device creation, else
# trust udev when not in a container
if (dev == null || dev == "lo") then []
else 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 (!config.boot.isContainer) (subsystemDevice dev);
if (dev == null || dev == "lo" || config.boot.isContainer) then []
else [ "${dev}-netdev.service" ];

hasDefaultGatewaySet = (cfg.defaultGateway != null && cfg.defaultGateway.address != "")
|| (cfg.enableIPv6 && cfg.defaultGateway6 != null && cfg.defaultGateway6.address != "");

needNetworkSetup = cfg.resolvconf.enable || cfg.defaultGateway != null || cfg.defaultGateway6 != null;
# XXX we explicitly rely on network-setup.service being
# unconditionally present for triggering dependencies on
# interface units.
needNetworkSetup = true;

networkLocalCommands = lib.mkIf needNetworkSetup {
after = [ "network-setup.service" ];
Expand All @@ -97,8 +90,8 @@ 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);
# exclude bridges from the requires relationship to fix container networking bug #47210
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 @@ -177,10 +170,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 @@ -260,7 +255,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 @@ -282,7 +277,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 @@ -370,7 +365,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 @@ -411,7 +406,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 @@ -450,7 +445,7 @@ let
{ description = "MACVLAN 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 @@ -485,7 +480,7 @@ let
{ description = "FOU endpoint ${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 @@ -508,7 +503,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 @@ -542,7 +537,7 @@ let
{ description = "GRE 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 @@ -570,7 +565,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

0 comments on commit bfe6984

Please sign in to comment.