nixos/networkd: respect systemd.network.links also with disabled systemd-networkd

This mirrors the behaviour of systemd - It's udev that parses `.link`
files, not `systemd-networkd`.

This was originally applied in 36ef112a477034fc6d1d9170bf1bcda0140a8d1d,
but was reverted due to 1115959a8d4d73ad73341563dc8bbf52230a281e causing
evaluation errors on hydra.

Changed files
+78 -32
nixos
doc
manual
release-notes
modules
system
tests
+9 -1
nixos/doc/manual/release-notes/rl-2003.xml
···
</para></listitem>
</itemizedlist>
</para>
-
</listitem>
+
</listitem>
+
<listitem>
+
<para>
+
The <link linkend="opt-systemd.network.links">systemd.network.links</link> option is now respected
+
even when <link linkend="opt-systemd.network.enable">systemd-networkd</command> is disabled.
+
This mirrors the behaviour of systemd - It's udev that parses <literal>.link</literal> files,
+
not <command>systemd-networkd</command>.
+
</para>
+
</listitem>
</itemizedlist>
</section>
</section>
+44 -31
nixos/modules/system/boot/networkd.nix
···
};
linkOptions = commonNetworkOptions // {
+
# overwrite enable option from above
+
enable = mkOption {
+
default = true;
+
type = types.bool;
+
description = ''
+
Whether to enable this .link unit. It's handled by udev no matter if <command>systemd-networkd</command> is enabled or not
+
'';
+
};
linkConfig = mkOption {
default = {};
···
};
-
config = mkIf config.systemd.network.enable {
+
config = mkMerge [
+
# .link units are honored by udev, no matter if systemd-networkd is enabled or not.
+
{
+
systemd.network.units = mapAttrs' (n: v: nameValuePair "${n}.link" (linkToUnit n v)) cfg.links;
+
environment.etc = unitFiles;
+
}
-
users.users.systemd-network.group = "systemd-network";
+
(mkIf config.systemd.network.enable {
-
systemd.additionalUpstreamSystemUnits = [
-
"systemd-networkd.service" "systemd-networkd-wait-online.service"
-
];
+
users.users.systemd-network.group = "systemd-network";
-
systemd.network.units = mapAttrs' (n: v: nameValuePair "${n}.link" (linkToUnit n v)) cfg.links
-
// mapAttrs' (n: v: nameValuePair "${n}.netdev" (netdevToUnit n v)) cfg.netdevs
-
// mapAttrs' (n: v: nameValuePair "${n}.network" (networkToUnit n v)) cfg.networks;
+
systemd.additionalUpstreamSystemUnits = [
+
"systemd-networkd.service" "systemd-networkd-wait-online.service"
+
];
-
environment.etc = unitFiles;
+
systemd.network.units = mapAttrs' (n: v: nameValuePair "${n}.netdev" (netdevToUnit n v)) cfg.netdevs
+
// mapAttrs' (n: v: nameValuePair "${n}.network" (networkToUnit n v)) cfg.networks;
-
systemd.services.systemd-networkd = {
-
wantedBy = [ "multi-user.target" ];
-
restartTriggers = attrNames unitFiles;
-
# prevent race condition with interface renaming (#39069)
-
requires = [ "systemd-udev-settle.service" ];
-
after = [ "systemd-udev-settle.service" ];
-
};
+
systemd.services.systemd-networkd = {
+
wantedBy = [ "multi-user.target" ];
+
restartTriggers = attrNames unitFiles;
+
# prevent race condition with interface renaming (#39069)
+
requires = [ "systemd-udev-settle.service" ];
+
after = [ "systemd-udev-settle.service" ];
+
};
-
systemd.services.systemd-networkd-wait-online = {
-
wantedBy = [ "network-online.target" ];
-
};
+
systemd.services.systemd-networkd-wait-online = {
+
wantedBy = [ "network-online.target" ];
+
};
-
systemd.services."systemd-network-wait-online@" = {
-
description = "Wait for Network Interface %I to be Configured";
-
conflicts = [ "shutdown.target" ];
-
requisite = [ "systemd-networkd.service" ];
-
after = [ "systemd-networkd.service" ];
-
serviceConfig = {
-
Type = "oneshot";
-
RemainAfterExit = true;
-
ExecStart = "${config.systemd.package}/lib/systemd/systemd-networkd-wait-online -i %I";
+
systemd.services."systemd-network-wait-online@" = {
+
description = "Wait for Network Interface %I to be Configured";
+
conflicts = [ "shutdown.target" ];
+
requisite = [ "systemd-networkd.service" ];
+
after = [ "systemd-networkd.service" ];
+
serviceConfig = {
+
Type = "oneshot";
+
RemainAfterExit = true;
+
ExecStart = "${config.systemd.package}/lib/systemd/systemd-networkd-wait-online -i %I";
+
};
};
-
};
-
services.resolved.enable = mkDefault true;
-
};
+
services.resolved.enable = mkDefault true;
+
})
+
];
+25
nixos/tests/networking.nix
···
), "The IPv6 routing table has not been properly cleaned:\n{}".format(ipv6Residue)
'';
};
+
# even with disabled networkd, systemd.network.links should work
+
# (as it's handled by udev, not networkd)
+
link = {
+
name = "Link";
+
nodes.client = { pkgs, ... }: {
+
virtualisation.vlans = [ 1 ];
+
networking = {
+
useNetworkd = networkd;
+
useDHCP = false;
+
};
+
systemd.network.links."50-foo" = {
+
matchConfig = {
+
Name = "foo";
+
Driver = "dummy";
+
};
+
linkConfig.MTUBytes = "1442";
+
};
+
};
+
testScript = ''
+
print(client.succeed("ip l add name foo type dummy"))
+
print(client.succeed("stat /etc/systemd/network/50-foo.link"))
+
client.succeed("udevadm settle")
+
assert "mtu 1442" in client.succeed("ip l show dummy0")
+
'';
+
};
};
in mapAttrs (const (attrs: makeTest (attrs // {