Merge pull request #167327 from lheckemann/networkd-usedhcp

nixos/networkd: reimplement useDHCP in a sensible way

Changed files
+86 -16
nixos
doc
manual
from_md
release-notes
release-notes
modules
tests
+15
nixos/doc/manual/from_md/release-notes/rl-2205.section.xml
···
hosts.
</para>
</listitem>
+
<listitem>
+
<para>
+
The option
+
<link xlink:href="options.html#opt-networking.useDHCP">networking.useDHCP</link>
+
isn’t deprecated anymore. When using
+
<link xlink:href="options.html#opt-networking.useNetworkd"><literal>systemd-networkd</literal></link>,
+
a generic <literal>.network</literal>-unit is added which
+
enables DHCP for each interface matching
+
<literal>en*</literal>, <literal>eth*</literal> or
+
<literal>wl*</literal> with priority 99 (which means that it
+
doesn’t have any effect if such an interface is matched by a
+
<literal>.network-</literal>unit with a lower priority). In
+
case of scripted networking, no behavior was changed.
+
</para>
+
</listitem>
</itemizedlist>
</section>
</section>
+7
nixos/doc/manual/release-notes/rl-2205.section.md
···
`true` starting with NixOS 22.11. Enable it explicitly if you need to control
Snapserver remotely or connect streamig clients from other hosts.
+
- The option [networking.useDHCP](options.html#opt-networking.useDHCP) isn't deprecated anymore.
+
When using [`systemd-networkd`](options.html#opt-networking.useNetworkd), a generic
+
`.network`-unit is added which enables DHCP for each interface matching `en*`, `eth*`
+
or `wl*` with priority 99 (which means that it doesn't have any effect if such an interface is matched
+
by a `.network-`unit with a lower priority). In case of scripted networking, no behavior
+
was changed.
+
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
+7 -5
nixos/modules/installer/tools/nixos-generate-config.pl
···
EOF
sub generateNetworkingDhcpConfig {
+
# FIXME disable networking.useDHCP by default when switching to networkd.
my $config = <<EOF;
-
# The global useDHCP flag is deprecated, therefore explicitly set to false here.
-
# Per-interface useDHCP will be mandatory in the future, so this generated config
-
# replicates the default behaviour.
-
networking.useDHCP = lib.mkDefault false;
+
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
+
# (the default) this is the recommended approach. When using systemd-networkd it's
+
# still possible to use this option, but it's recommended to use it in conjunction
+
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
+
networking.useDHCP = lib.mkDefault true;
EOF
foreach my $path (glob "/sys/class/net/*") {
my $dev = basename($path);
if ($dev ne "lo") {
-
$config .= " networking.interfaces.$dev.useDHCP = lib.mkDefault true;\n";
+
$config .= " # networking.interfaces.$dev.useDHCP = lib.mkDefault true;\n";
}
}
+1
nixos/modules/system/boot/networkd.nix
···
"RouteDenyList"
"RouteAllowList"
"DHCPv6Client"
+
"RouteMetric"
])
(assertValueOneOf "UseDNS" boolValues)
(assertValueOneOf "UseDomains" (boolValues ++ ["route"]))
+36 -6
nixos/modules/tasks/network-interfaces-systemd.nix
···
} {
assertion = cfg.defaultGateway6 == null || cfg.defaultGateway6.interface == null;
message = "networking.defaultGateway6.interface is not supported by networkd.";
-
} {
-
assertion = cfg.useDHCP == false;
-
message = ''
-
networking.useDHCP is not supported by networkd.
-
Please use per interface configuration and set the global option to false.
-
'';
} ] ++ flip mapAttrsToList cfg.bridges (n: { rstp, ... }: {
assertion = !rstp;
message = "networking.bridges.${n}.rstp is not supported by networkd.";
···
in mkMerge [ {
enable = true;
}
+
(mkIf cfg.useDHCP {
+
networks."99-ethernet-default-dhcp" = lib.mkIf cfg.useDHCP {
+
# We want to match physical ethernet interfaces as commonly
+
# found on laptops, desktops and servers, to provide an
+
# "out-of-the-box" setup that works for common cases. This
+
# heuristic isn't perfect (it could match interfaces with
+
# custom names that _happen_ to start with en or eth), but
+
# should be good enough to make the common case easy and can
+
# be overridden on a case-by-case basis using
+
# higher-priority networks or by disabling useDHCP.
+
+
# Type=ether matches veth interfaces as well, and this is
+
# more likely to result in interfaces being configured to
+
# use DHCP when they shouldn't.
+
+
# We set RequiredForOnline to false, because it's fairly
+
# common for such devices to have multiple interfaces and
+
# only one of them to be connected (e.g. a laptop with
+
# ethernet and WiFi interfaces). Maybe one day networkd will
+
# support "any"-style RequiredForOnline...
+
matchConfig.Name = ["en*" "eth*"];
+
DHCP = "yes";
+
linkConfig.RequiredForOnline = lib.mkDefault false;
+
};
+
networks."99-wireless-client-dhcp" = lib.mkIf cfg.useDHCP {
+
# Like above, but this is much more likely to be correct.
+
matchConfig.WLANInterfaceType = "station";
+
DHCP = "yes";
+
linkConfig.RequiredForOnline = lib.mkDefault false;
+
# We also set the route metric to one more than the default
+
# of 1024, so that Ethernet is preferred if both are
+
# available.
+
dhcpV4Config.RouteMetric = 1025;
+
ipv6AcceptRAConfig.RouteMetric = 1025;
+
};
+
})
(mkMerge (forEach interfaces (i: {
netdevs = mkIf i.virtual ({
"40-${i.name}" = {
-5
nixos/modules/tasks/network-interfaces.nix
···
Whether to use DHCP to obtain an IP address and other
configuration for all network interfaces that are not manually
configured.
-
-
Using this option is highly discouraged and also incompatible with
-
<option>networking.useNetworkd</option>. Please use
-
<option>networking.interfaces.&lt;name&gt;.useDHCP</option> instead
-
and set this to false.
'';
};
+20
nixos/tests/networking.nix
···
client.wait_until_succeeds("ping -c 1 192.168.3.1")
'';
};
+
dhcpDefault = {
+
name = "useDHCP-by-default";
+
nodes.router = router;
+
nodes.client = { lib, ... }: {
+
# Disable test driver default config
+
networking.interfaces = lib.mkForce {};
+
networking.useNetworkd = networkd;
+
virtualisation.vlans = [ 1 ];
+
};
+
testScript = ''
+
start_all()
+
client.wait_for_unit("multi-user.target")
+
client.wait_until_succeeds("ip addr show dev eth1 | grep '192.168.1'")
+
client.shell_interact()
+
client.succeed("ping -c 1 192.168.1.1")
+
router.succeed("ping -c 1 192.168.1.1")
+
router.succeed("ping -c 1 192.168.1.2")
+
client.succeed("ping -c 1 192.168.1.2")
+
'';
+
};
dhcpSimple = {
name = "SimpleDHCP";
nodes.router = router;