nixos/scripted-networking: use udev to configure link MACAddress and MTUBytes
The `network-link-${i.name}` units raced with other things trying to
configure the interface, or ran before the interface was available.
Instead of running our own set of shell scripts on boot, and hoping
they're executed at the right time, we can make use of udev to configure
the interface *while they appear*, by providing `.link` files in
/etc/systemd/network/*.link to set MACAddress and MTUBytes.
This doesn't require networkd to be enabled, and is populated properly
on non-networkd systems since
https://github.com/NixOS/nixpkgs/pull/82941.
This continues clean-up work done in
https://github.com/NixOS/nixpkgs/pull/85170 for the scripted networking
stack.
The only leftover part of the `network-link-${i.name}` unit (bringing
the interface up) is moved to the beginning of the
`network-addresses-${i.name}` unit.
Fixes: https://github.com/NixOS/nixpkgs/issues/74471
Closes: https://github.com/NixOS/nixpkgs/pull/87116
This commit is contained in:
@@ -54,7 +54,16 @@ let
|
||||
};
|
||||
|
||||
normalConfig = {
|
||||
|
||||
systemd.network.links = let
|
||||
createNetworkLink = i: nameValuePair "40-${i.name}" {
|
||||
matchConfig.OriginalName = i.name;
|
||||
linkConfig = optionalAttrs (i.macAddress != null) {
|
||||
MACAddress = i.macAddress;
|
||||
} // optionalAttrs (i.mtu != null) {
|
||||
MTUBytes = toString i.mtu;
|
||||
};
|
||||
};
|
||||
in listToAttrs (map createNetworkLink interfaces);
|
||||
systemd.services =
|
||||
let
|
||||
|
||||
@@ -164,7 +173,6 @@ let
|
||||
{ description = "Address configuration of ${i.name}";
|
||||
wantedBy = [
|
||||
"network-setup.service"
|
||||
"network-link-${i.name}.service"
|
||||
"network.target"
|
||||
];
|
||||
# order before network-setup because the routes that are configured
|
||||
@@ -183,6 +191,8 @@ let
|
||||
state="/run/nixos/network/addresses/${i.name}"
|
||||
mkdir -p $(dirname "$state")
|
||||
|
||||
ip link set "${i.name}" up
|
||||
|
||||
${flip concatMapStrings ips (ip:
|
||||
let
|
||||
cidr = "${ip.address}/${toString ip.prefixLength}";
|
||||
@@ -237,38 +247,6 @@ let
|
||||
'';
|
||||
};
|
||||
|
||||
createNetworkLink = i:
|
||||
let
|
||||
deviceDependency = if (config.boot.isContainer || i.name == "lo")
|
||||
then []
|
||||
else [ (subsystemDevice i.name) ];
|
||||
in
|
||||
nameValuePair "network-link-${i.name}"
|
||||
{ description = "Link configuration of ${i.name}";
|
||||
wantedBy = [ "network-interfaces.target" ];
|
||||
before = [ "network-interfaces.target" ];
|
||||
bindsTo = deviceDependency;
|
||||
after = [ "network-pre.target" ] ++ deviceDependency;
|
||||
path = [ pkgs.iproute ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
script =
|
||||
''
|
||||
echo "Configuring link..."
|
||||
'' + optionalString (i.macAddress != null) ''
|
||||
echo "setting MAC address to ${i.macAddress}..."
|
||||
ip link set "${i.name}" address "${i.macAddress}"
|
||||
'' + optionalString (i.mtu != null) ''
|
||||
echo "setting MTU to ${toString i.mtu}..."
|
||||
ip link set "${i.name}" mtu "${toString i.mtu}"
|
||||
'' + ''
|
||||
echo -n "bringing up interface... "
|
||||
ip link set "${i.name}" up && echo "done" || (echo "failed"; exit 1)
|
||||
'';
|
||||
};
|
||||
|
||||
createTunDevice = i: nameValuePair "${i.name}-netdev"
|
||||
{ description = "Virtual Network Interface ${i.name}";
|
||||
bindsTo = [ "dev-net-tun.device" ];
|
||||
@@ -298,7 +276,7 @@ let
|
||||
bindsTo = deps ++ optional v.rstp "mstpd.service";
|
||||
partOf = [ "network-setup.service" ] ++ optional v.rstp "mstpd.service";
|
||||
after = [ "network-pre.target" ] ++ deps ++ optional v.rstp "mstpd.service"
|
||||
++ concatMap (i: [ "network-addresses-${i}.service" "network-link-${i}.service" ]) v.interfaces;
|
||||
++ map (i: "network-addresses-${i}.service") v.interfaces;
|
||||
before = [ "network-setup.service" ];
|
||||
serviceConfig.Type = "oneshot";
|
||||
serviceConfig.RemainAfterExit = true;
|
||||
@@ -375,7 +353,7 @@ let
|
||||
createVswitchDevice = n: v: nameValuePair "${n}-netdev"
|
||||
(let
|
||||
deps = concatLists (map deviceDependency (attrNames (filterAttrs (_: config: config.type != "internal") v.interfaces)));
|
||||
internalConfigs = concatMap (i: ["network-link-${i}.service" "network-addresses-${i}.service"]) (attrNames (filterAttrs (_: config: config.type == "internal") v.interfaces));
|
||||
internalConfigs = map (i: "network-addresses-${i}.service") (attrNames (filterAttrs (_: config: config.type == "internal") v.interfaces));
|
||||
ofRules = pkgs.writeText "vswitch-${n}-openFlowRules" v.openFlowRules;
|
||||
in
|
||||
{ description = "Open vSwitch Interface ${n}";
|
||||
@@ -427,7 +405,7 @@ let
|
||||
bindsTo = deps;
|
||||
partOf = [ "network-setup.service" ];
|
||||
after = [ "network-pre.target" ] ++ deps
|
||||
++ concatMap (i: [ "network-addresses-${i}.service" "network-link-${i}.service" ]) v.interfaces;
|
||||
++ map (i: "network-addresses-${i}.service") v.interfaces;
|
||||
before = [ "network-setup.service" ];
|
||||
serviceConfig.Type = "oneshot";
|
||||
serviceConfig.RemainAfterExit = true;
|
||||
@@ -540,7 +518,6 @@ let
|
||||
});
|
||||
|
||||
in listToAttrs (
|
||||
map createNetworkLink interfaces ++
|
||||
map configureAddrs interfaces ++
|
||||
map createTunDevice (filter (i: i.virtual) interfaces))
|
||||
// mapAttrs' createBridgeDevice cfg.bridges
|
||||
|
||||
Reference in New Issue
Block a user