Commit d51ebb61 authored by mutantmell's avatar mutantmell
Browse files

nixos/networkd: refactor

Reduces size of networkd module by moving unit file generation code into a util.
parent f7cb1f3d
Loading
Loading
Loading
Loading
+238 −0
Original line number Diff line number Diff line
{ lib, systemdUtils }:

with lib;

let
  attrsToSection = systemdUtils.lib.attrsToSection;
  commonMatchText = def:
    optionalString (def.matchConfig != { }) ''
      [Match]
      ${attrsToSection def.matchConfig}
    '';
in {
  linkToUnit = def:
    commonMatchText def + ''
      [Link]
      ${attrsToSection def.linkConfig}
    '' + def.extraConfig;

  netdevToUnit = def:
    commonMatchText def + ''
      [NetDev]
      ${attrsToSection def.netdevConfig}
    '' + optionalString (def.vlanConfig != { }) ''
      [VLAN]
      ${attrsToSection def.vlanConfig}
    '' + optionalString (def.macvlanConfig != { }) ''
      [MACVLAN]
      ${attrsToSection def.macvlanConfig}
    '' + optionalString (def.vxlanConfig != { }) ''
      [VXLAN]
      ${attrsToSection def.vxlanConfig}
    '' + optionalString (def.tunnelConfig != { }) ''
      [Tunnel]
      ${attrsToSection def.tunnelConfig}
    '' + optionalString (def.fooOverUDPConfig != { }) ''
      [FooOverUDP]
      ${attrsToSection def.fooOverUDPConfig}
    '' + optionalString (def.peerConfig != { }) ''
      [Peer]
      ${attrsToSection def.peerConfig}
    '' + optionalString (def.tunConfig != { }) ''
      [Tun]
      ${attrsToSection def.tunConfig}
    '' + optionalString (def.tapConfig != { }) ''
      [Tap]
      ${attrsToSection def.tapConfig}
    '' + optionalString (def.l2tpConfig != { }) ''
      [L2TP]
      ${attrsToSection def.l2tpConfig}
    '' + flip concatMapStrings def.l2tpSessions (x: ''
      [L2TPSession]
      ${attrsToSection x.l2tpSessionConfig}
    '') + optionalString (def.wireguardConfig != { }) ''
      [WireGuard]
      ${attrsToSection def.wireguardConfig}
    '' + flip concatMapStrings def.wireguardPeers (x: ''
      [WireGuardPeer]
      ${attrsToSection x.wireguardPeerConfig}
    '') + optionalString (def.bondConfig != { }) ''
      [Bond]
      ${attrsToSection def.bondConfig}
    '' + optionalString (def.xfrmConfig != { }) ''
      [Xfrm]
      ${attrsToSection def.xfrmConfig}
    '' + optionalString (def.vrfConfig != { }) ''
      [VRF]
      ${attrsToSection def.vrfConfig}
    '' + optionalString (def.batmanAdvancedConfig != { }) ''
      [BatmanAdvanced]
      ${attrsToSection def.batmanAdvancedConfig}
    '' + def.extraConfig;

  networkToUnit = def:
    commonMatchText def + optionalString (def.linkConfig != { }) ''
      [Link]
      ${attrsToSection def.linkConfig}
    '' + ''
      [Network]
    '' + attrsToSection def.networkConfig
    + optionalString (def.address != [ ]) ''
      ${concatStringsSep "\n" (map (s: "Address=${s}") def.address)}
    '' + optionalString (def.gateway != [ ]) ''
      ${concatStringsSep "\n" (map (s: "Gateway=${s}") def.gateway)}
    '' + optionalString (def.dns != [ ]) ''
      ${concatStringsSep "\n" (map (s: "DNS=${s}") def.dns)}
    '' + optionalString (def.ntp != [ ]) ''
      ${concatStringsSep "\n" (map (s: "NTP=${s}") def.ntp)}
    '' + optionalString (def.bridge != [ ]) ''
      ${concatStringsSep "\n" (map (s: "Bridge=${s}") def.bridge)}
    '' + optionalString (def.bond != [ ]) ''
      ${concatStringsSep "\n" (map (s: "Bond=${s}") def.bond)}
    '' + optionalString (def.vrf != [ ]) ''
      ${concatStringsSep "\n" (map (s: "VRF=${s}") def.vrf)}
    '' + optionalString (def.vlan != [ ]) ''
      ${concatStringsSep "\n" (map (s: "VLAN=${s}") def.vlan)}
    '' + optionalString (def.macvlan != [ ]) ''
      ${concatStringsSep "\n" (map (s: "MACVLAN=${s}") def.macvlan)}
    '' + optionalString (def.vxlan != [ ]) ''
      ${concatStringsSep "\n" (map (s: "VXLAN=${s}") def.vxlan)}
    '' + optionalString (def.tunnel != [ ]) ''
      ${concatStringsSep "\n" (map (s: "Tunnel=${s}") def.tunnel)}
    '' + optionalString (def.xfrm != [ ]) ''
      ${concatStringsSep "\n" (map (s: "Xfrm=${s}") def.xfrm)}
    '' + "\n" + flip concatMapStrings def.addresses (x: ''
      [Address]
      ${attrsToSection x.addressConfig}
    '') + flip concatMapStrings def.routingPolicyRules (x: ''
      [RoutingPolicyRule]
      ${attrsToSection x.routingPolicyRuleConfig}
    '') + flip concatMapStrings def.routes (x: ''
      [Route]
      ${attrsToSection x.routeConfig}
    '') + optionalString (def.dhcpV4Config != { }) ''
      [DHCPv4]
      ${attrsToSection def.dhcpV4Config}
    '' + optionalString (def.dhcpV6Config != { }) ''
      [DHCPv6]
      ${attrsToSection def.dhcpV6Config}
    '' + optionalString (def.dhcpPrefixDelegationConfig != { }) ''
      [DHCPPrefixDelegation]
      ${attrsToSection def.dhcpPrefixDelegationConfig}
    '' + optionalString (def.ipv6AcceptRAConfig != { }) ''
      [IPv6AcceptRA]
      ${attrsToSection def.ipv6AcceptRAConfig}
    '' + optionalString (def.dhcpServerConfig != { }) ''
      [DHCPServer]
      ${attrsToSection def.dhcpServerConfig}
    '' + optionalString (def.ipv6SendRAConfig != { }) ''
      [IPv6SendRA]
      ${attrsToSection def.ipv6SendRAConfig}
    '' + flip concatMapStrings def.ipv6Prefixes (x: ''
      [IPv6Prefix]
      ${attrsToSection x.ipv6PrefixConfig}
    '') + flip concatMapStrings def.ipv6RoutePrefixes (x: ''
      [IPv6RoutePrefix]
      ${attrsToSection x.ipv6RoutePrefixConfig}
    '') + flip concatMapStrings def.dhcpServerStaticLeases (x: ''
      [DHCPServerStaticLease]
      ${attrsToSection x.dhcpServerStaticLeaseConfig}
    '') + optionalString (def.bridgeConfig != { }) ''
      [Bridge]
      ${attrsToSection def.bridgeConfig}
    '' + flip concatMapStrings def.bridgeFDBs (x: ''
      [BridgeFDB]
      ${attrsToSection x.bridgeFDBConfig}
    '') + flip concatMapStrings def.bridgeMDBs (x: ''
      [BridgeMDB]
      ${attrsToSection x.bridgeMDBConfig}
    '') + optionalString (def.lldpConfig != { }) ''
      [LLDP]
      ${attrsToSection def.lldpConfig}
    '' + optionalString (def.canConfig != { }) ''
      [CAN]
      ${attrsToSection def.canConfig}
    '' + optionalString (def.ipoIBConfig != { }) ''
      [IPoIB]
      ${attrsToSection def.ipoIBConfig}
    '' + optionalString (def.qdiscConfig != { }) ''
      [QDisc]
      ${attrsToSection def.qdiscConfig}
    '' + optionalString (def.networkEmulatorConfig != { }) ''
      [NetworkEmulator]
      ${attrsToSection def.networkEmulatorConfig}
    '' + optionalString (def.tokenBucketFilterConfig != { }) ''
      [TokenBucketFilter]
      ${attrsToSection def.tokenBucketFilterConfig}
    '' + optionalString (def.pieConfig != { }) ''
      [PIE]
      ${attrsToSection def.pieConfig}
    '' + optionalString (def.flowQueuePIEConfig != { }) ''
      [FlowQueuePIE]
      ${attrsToSection def.flowQueuePIEConfig}
    '' + optionalString (def.stochasticFairBlueConfig != { }) ''
      [StochasticFairBlue]
      ${attrsToSection def.stochasticFairBlueConfig}
    '' + optionalString (def.stochasticFairnessQueueingConfig != { }) ''
      [StochasticFairnessQueueing]
      ${attrsToSection def.stochasticFairnessQueueingConfig}
    '' + optionalString (def.bfifoConfig != { }) ''
      [BFIFO]
      ${attrsToSection def.bfifoConfig}
    '' + optionalString (def.pfifoConfig != { }) ''
      [PFIFO]
      ${attrsToSection def.pfifoConfig}
    '' + optionalString (def.pfifoHeadDropConfig != { }) ''
      [PFIFOHeadDrop]
      ${attrsToSection def.pfifoHeadDropConfig}
    '' + optionalString (def.pfifoFastConfig != { }) ''
      [PFIFOFast]
      ${attrsToSection def.pfifoFastConfig}
    '' + optionalString (def.cakeConfig != { }) ''
      [CAKE]
      ${attrsToSection def.cakeConfig}
    '' + optionalString (def.controlledDelayConfig != { }) ''
      [ControlledDelay]
      ${attrsToSection def.controlledDelayConfig}
    '' + optionalString (def.deficitRoundRobinSchedulerConfig != { }) ''
      [DeficitRoundRobinScheduler]
      ${attrsToSection def.deficitRoundRobinSchedulerConfig}
    '' + optionalString (def.deficitRoundRobinSchedulerClassConfig != { }) ''
      [DeficitRoundRobinSchedulerClass]
      ${attrsToSection def.deficitRoundRobinSchedulerClassConfig}
    '' + optionalString (def.enhancedTransmissionSelectionConfig != { }) ''
      [EnhancedTransmissionSelection]
      ${attrsToSection def.enhancedTransmissionSelectionConfig}
    '' + optionalString (def.genericRandomEarlyDetectionConfig != { }) ''
      [GenericRandomEarlyDetection]
      ${attrsToSection def.genericRandomEarlyDetectionConfig}
    '' + optionalString (def.fairQueueingControlledDelayConfig != { }) ''
      [FairQueueingControlledDelay]
      ${attrsToSection def.fairQueueingControlledDelayConfig}
    '' + optionalString (def.fairQueueingConfig != { }) ''
      [FairQueueing]
      ${attrsToSection def.fairQueueingConfig}
    '' + optionalString (def.trivialLinkEqualizerConfig != { }) ''
      [TrivialLinkEqualizer]
      ${attrsToSection def.trivialLinkEqualizerConfig}
    '' + optionalString (def.hierarchyTokenBucketConfig != { }) ''
      [HierarchyTokenBucket]
      ${attrsToSection def.hierarchyTokenBucketConfig}
    '' + optionalString (def.hierarchyTokenBucketClassConfig != { }) ''
      [HierarchyTokenBucketClass]
      ${attrsToSection def.hierarchyTokenBucketClassConfig}
    '' + optionalString (def.heavyHitterFilterConfig != { }) ''
      [HeavyHitterFilter]
      ${attrsToSection def.heavyHitterFilterConfig}
    '' + optionalString (def.quickFairQueueingConfig != { }) ''
      [QuickFairQueueing]
      ${attrsToSection def.quickFairQueueingConfig}
    '' + optionalString (def.quickFairQueueingConfigClass != { }) ''
      [QuickFairQueueingClass]
      ${attrsToSection def.quickFairQueueingConfigClass}
    '' + flip concatMapStrings def.bridgeVLANs (x: ''
      [BridgeVLAN]
      ${attrsToSection x.bridgeVLANConfig}
    '') + def.extraConfig;

}
+3 −0
Original line number Diff line number Diff line
@@ -226,5 +226,8 @@ rec {
    lib = import ./systemd-lib.nix { inherit lib config pkgs; };
    unitOptions = import ./systemd-unit-options.nix { inherit lib systemdUtils; };
    types = import ./systemd-types.nix { inherit lib systemdUtils pkgs; };
    network = {
      units = import ./systemd-network-units.nix { inherit lib systemdUtils; };
    };
  };
}
+8 −322
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@

with utils.systemdUtils.unitOptions;
with utils.systemdUtils.lib;
with utils.systemdUtils.network.units;
with lib;

let
@@ -2604,95 +2605,6 @@ let
    };
  };

  commonMatchText = def: optionalString (def.matchConfig != { }) ''
    [Match]
    ${attrsToSection def.matchConfig}
  '';

  linkToUnit = name: def:
    { inherit (def) enable;
      text = commonMatchText def
        + ''
          [Link]
          ${attrsToSection def.linkConfig}
        ''
        + def.extraConfig;
    };

  netdevToUnit = name: def:
    { inherit (def) enable;
      text = commonMatchText def
        + ''
          [NetDev]
          ${attrsToSection def.netdevConfig}
        ''
        + optionalString (def.vlanConfig != { }) ''
          [VLAN]
          ${attrsToSection def.vlanConfig}
        ''
        + optionalString (def.macvlanConfig != { }) ''
          [MACVLAN]
          ${attrsToSection def.macvlanConfig}
        ''
        + optionalString (def.vxlanConfig != { }) ''
          [VXLAN]
          ${attrsToSection def.vxlanConfig}
        ''
        + optionalString (def.tunnelConfig != { }) ''
          [Tunnel]
          ${attrsToSection def.tunnelConfig}
        ''
        + optionalString (def.fooOverUDPConfig != { }) ''
          [FooOverUDP]
          ${attrsToSection def.fooOverUDPConfig}
        ''
        + optionalString (def.peerConfig != { }) ''
          [Peer]
          ${attrsToSection def.peerConfig}
        ''
        + optionalString (def.tunConfig != { }) ''
          [Tun]
          ${attrsToSection def.tunConfig}
        ''
        + optionalString (def.tapConfig != { }) ''
          [Tap]
          ${attrsToSection def.tapConfig}
        ''
        + optionalString (def.l2tpConfig != { }) ''
          [L2TP]
          ${attrsToSection def.l2tpConfig}
        ''
        + flip concatMapStrings def.l2tpSessions (x: ''
          [L2TPSession]
          ${attrsToSection x.l2tpSessionConfig}
        '')
        + optionalString (def.wireguardConfig != { }) ''
          [WireGuard]
          ${attrsToSection def.wireguardConfig}
        ''
        + flip concatMapStrings def.wireguardPeers (x: ''
          [WireGuardPeer]
          ${attrsToSection x.wireguardPeerConfig}
        '')
        + optionalString (def.bondConfig != { }) ''
          [Bond]
          ${attrsToSection def.bondConfig}
        ''
        + optionalString (def.xfrmConfig != { }) ''
          [Xfrm]
          ${attrsToSection def.xfrmConfig}
        ''
        + optionalString (def.vrfConfig != { }) ''
          [VRF]
          ${attrsToSection def.vrfConfig}
        ''
        + optionalString (def.batmanAdvancedConfig != { }) ''
          [BatmanAdvanced]
          ${attrsToSection def.batmanAdvancedConfig}
        ''
        + def.extraConfig;
    };

  renderConfig = def:
    { text = ''
        [Network]
@@ -2707,235 +2619,6 @@ let
        ${attrsToSection def.dhcpV6Config}
      ''; };

  networkToUnit = name: def:
    { inherit (def) enable;
      text = commonMatchText def
        + optionalString (def.linkConfig != { }) ''
          [Link]
          ${attrsToSection def.linkConfig}
        ''
        + ''
          [Network]
        ''
        + attrsToSection def.networkConfig
        + optionalString (def.address != [ ]) ''
          ${concatStringsSep "\n" (map (s: "Address=${s}") def.address)}
        ''
        + optionalString (def.gateway != [ ]) ''
          ${concatStringsSep "\n" (map (s: "Gateway=${s}") def.gateway)}
        ''
        + optionalString (def.dns != [ ]) ''
          ${concatStringsSep "\n" (map (s: "DNS=${s}") def.dns)}
        ''
        + optionalString (def.ntp != [ ]) ''
          ${concatStringsSep "\n" (map (s: "NTP=${s}") def.ntp)}
        ''
        + optionalString (def.bridge != [ ]) ''
          ${concatStringsSep "\n" (map (s: "Bridge=${s}") def.bridge)}
        ''
        + optionalString (def.bond != [ ]) ''
          ${concatStringsSep "\n" (map (s: "Bond=${s}") def.bond)}
        ''
        + optionalString (def.vrf != [ ]) ''
          ${concatStringsSep "\n" (map (s: "VRF=${s}") def.vrf)}
        ''
        + optionalString (def.vlan != [ ]) ''
          ${concatStringsSep "\n" (map (s: "VLAN=${s}") def.vlan)}
        ''
        + optionalString (def.macvlan != [ ]) ''
          ${concatStringsSep "\n" (map (s: "MACVLAN=${s}") def.macvlan)}
        ''
        + optionalString (def.vxlan != [ ]) ''
          ${concatStringsSep "\n" (map (s: "VXLAN=${s}") def.vxlan)}
        ''
        + optionalString (def.tunnel != [ ]) ''
          ${concatStringsSep "\n" (map (s: "Tunnel=${s}") def.tunnel)}
        ''
        + optionalString (def.xfrm != [ ]) ''
          ${concatStringsSep "\n" (map (s: "Xfrm=${s}") def.xfrm)}
        ''
        + ''

        ''
        + flip concatMapStrings def.addresses (x: ''
          [Address]
          ${attrsToSection x.addressConfig}
        '')
        + flip concatMapStrings def.routingPolicyRules (x: ''
          [RoutingPolicyRule]
          ${attrsToSection x.routingPolicyRuleConfig}
        '')
        + flip concatMapStrings def.routes (x: ''
          [Route]
          ${attrsToSection x.routeConfig}
        '')
        + optionalString (def.dhcpV4Config != { }) ''
          [DHCPv4]
          ${attrsToSection def.dhcpV4Config}
        ''
        + optionalString (def.dhcpV6Config != { }) ''
          [DHCPv6]
          ${attrsToSection def.dhcpV6Config}
        ''
        + optionalString (def.dhcpPrefixDelegationConfig != { }) ''
          [DHCPPrefixDelegation]
          ${attrsToSection def.dhcpPrefixDelegationConfig}
        ''
        + optionalString (def.ipv6AcceptRAConfig != { }) ''
          [IPv6AcceptRA]
          ${attrsToSection def.ipv6AcceptRAConfig}
        ''
        + optionalString (def.dhcpServerConfig != { }) ''
          [DHCPServer]
          ${attrsToSection def.dhcpServerConfig}
        ''
        + optionalString (def.ipv6SendRAConfig != { }) ''
          [IPv6SendRA]
          ${attrsToSection def.ipv6SendRAConfig}
        ''
        + flip concatMapStrings def.ipv6Prefixes (x: ''
          [IPv6Prefix]
          ${attrsToSection x.ipv6PrefixConfig}
        '')
        + flip concatMapStrings def.ipv6RoutePrefixes (x: ''
          [IPv6RoutePrefix]
          ${attrsToSection x.ipv6RoutePrefixConfig}
        '')
        + flip concatMapStrings def.dhcpServerStaticLeases (x: ''
          [DHCPServerStaticLease]
          ${attrsToSection x.dhcpServerStaticLeaseConfig}
        '')
        + optionalString (def.bridgeConfig != { }) ''
          [Bridge]
          ${attrsToSection def.bridgeConfig}
        ''
        + flip concatMapStrings def.bridgeFDBs (x: ''
          [BridgeFDB]
          ${attrsToSection x.bridgeFDBConfig}
        '')
        + flip concatMapStrings def.bridgeMDBs (x: ''
          [BridgeMDB]
          ${attrsToSection x.bridgeMDBConfig}
        '')
        + optionalString (def.lldpConfig != { }) ''
          [LLDP]
          ${attrsToSection def.lldpConfig}
        ''
        + optionalString (def.canConfig != { }) ''
          [CAN]
          ${attrsToSection def.canConfig}
        ''
        + optionalString (def.ipoIBConfig != { }) ''
          [IPoIB]
          ${attrsToSection def.ipoIBConfig}
        ''
        + optionalString (def.qdiscConfig != { }) ''
          [QDisc]
          ${attrsToSection def.qdiscConfig}
        ''
        + optionalString (def.networkEmulatorConfig != { }) ''
          [NetworkEmulator]
          ${attrsToSection def.networkEmulatorConfig}
        ''
        + optionalString (def.tokenBucketFilterConfig != { }) ''
          [TokenBucketFilter]
          ${attrsToSection def.tokenBucketFilterConfig}
        ''
        + optionalString (def.pieConfig != { }) ''
          [PIE]
          ${attrsToSection def.pieConfig}
        ''
        + optionalString (def.flowQueuePIEConfig != { }) ''
          [FlowQueuePIE]
          ${attrsToSection def.flowQueuePIEConfig}
        ''
        + optionalString (def.stochasticFairBlueConfig != { }) ''
          [StochasticFairBlue]
          ${attrsToSection def.stochasticFairBlueConfig}
        ''
        + optionalString (def.stochasticFairnessQueueingConfig != { }) ''
          [StochasticFairnessQueueing]
          ${attrsToSection def.stochasticFairnessQueueingConfig}
        ''
        + optionalString (def.bfifoConfig != { }) ''
          [BFIFO]
          ${attrsToSection def.bfifoConfig}
        ''
        + optionalString (def.pfifoConfig != { }) ''
          [PFIFO]
          ${attrsToSection def.pfifoConfig}
        ''
        + optionalString (def.pfifoHeadDropConfig != { }) ''
          [PFIFOHeadDrop]
          ${attrsToSection def.pfifoHeadDropConfig}
        ''
        + optionalString (def.pfifoFastConfig != { }) ''
          [PFIFOFast]
          ${attrsToSection def.pfifoFastConfig}
        ''
        + optionalString (def.cakeConfig != { }) ''
          [CAKE]
          ${attrsToSection def.cakeConfig}
        ''
        + optionalString (def.controlledDelayConfig != { }) ''
          [ControlledDelay]
          ${attrsToSection def.controlledDelayConfig}
        ''
        + optionalString (def.deficitRoundRobinSchedulerConfig != { }) ''
          [DeficitRoundRobinScheduler]
          ${attrsToSection def.deficitRoundRobinSchedulerConfig}
        ''
        + optionalString (def.deficitRoundRobinSchedulerClassConfig != { }) ''
          [DeficitRoundRobinSchedulerClass]
          ${attrsToSection def.deficitRoundRobinSchedulerClassConfig}
        ''
        + optionalString (def.enhancedTransmissionSelectionConfig != { }) ''
          [EnhancedTransmissionSelection]
          ${attrsToSection def.enhancedTransmissionSelectionConfig}
        ''
        + optionalString (def.genericRandomEarlyDetectionConfig != { }) ''
          [GenericRandomEarlyDetection]
          ${attrsToSection def.genericRandomEarlyDetectionConfig}
        ''
        + optionalString (def.fairQueueingControlledDelayConfig != { }) ''
          [FairQueueingControlledDelay]
          ${attrsToSection def.fairQueueingControlledDelayConfig}
        ''
        + optionalString (def.fairQueueingConfig != { }) ''
          [FairQueueing]
          ${attrsToSection def.fairQueueingConfig}
        ''
        + optionalString (def.trivialLinkEqualizerConfig != { }) ''
          [TrivialLinkEqualizer]
          ${attrsToSection def.trivialLinkEqualizerConfig}
        ''
        + optionalString (def.hierarchyTokenBucketConfig != { }) ''
          [HierarchyTokenBucket]
          ${attrsToSection def.hierarchyTokenBucketConfig}
        ''
        + optionalString (def.hierarchyTokenBucketClassConfig != { }) ''
          [HierarchyTokenBucketClass]
          ${attrsToSection def.hierarchyTokenBucketClassConfig}
        ''
        + optionalString (def.heavyHitterFilterConfig != { }) ''
          [HeavyHitterFilter]
          ${attrsToSection def.heavyHitterFilterConfig}
        ''
        + optionalString (def.quickFairQueueingConfig != { }) ''
          [QuickFairQueueing]
          ${attrsToSection def.quickFairQueueingConfig}
        ''
        + optionalString (def.quickFairQueueingConfigClass != { }) ''
          [QuickFairQueueingClass]
          ${attrsToSection def.quickFairQueueingConfigClass}
        ''
        + flip concatMapStrings def.bridgeVLANs (x: ''
          [BridgeVLAN]
          ${attrsToSection x.bridgeVLANConfig}
        '')
        + def.extraConfig;
    };

  mkUnitFiles = prefix: cfg: listToAttrs (map (name: {
    name = "${prefix}systemd/network/${name}";
    value.source = "${cfg.units.${name}.unit}/${name}";
@@ -3048,11 +2731,14 @@ let

  };

  commonConfig = config: let cfg = config.systemd.network; in mkMerge [
  commonConfig = config: let
    cfg = config.systemd.network;
    mkUnit = f: def: { inherit (def) enable; text = f def; };
  in 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;
      systemd.network.units = mapAttrs' (n: v: nameValuePair "${n}.link" (mkUnit linkToUnit v)) cfg.links;

      systemd.network.wait-online.extraArgs =
        [ "--timeout=${toString cfg.wait-online.timeout}" ]
@@ -3062,8 +2748,8 @@ let

    (mkIf config.systemd.network.enable {

      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.network.units = mapAttrs' (n: v: nameValuePair "${n}.netdev" (mkUnit netdevToUnit v)) cfg.netdevs
        // mapAttrs' (n: v: nameValuePair "${n}.network" (mkUnit networkToUnit v)) cfg.networks;

      # systemd-networkd is socket-activated by kernel netlink route change
      # messages. It is important to have systemd buffer those on behalf of