Merge pull request #312472 from Ma27/networkd-option-rename

nixos/networkd: get rid of *Config attributes in lists
This commit is contained in:
Franz Pletz 2024-05-30 04:06:01 +02:00 committed by GitHub
commit 4e1b4397d9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 172 additions and 302 deletions

@ -182,6 +182,30 @@ in rec {
in if errors == [] then true in if errors == [] then true
else trace (concatStringsSep "\n" errors) false; else trace (concatStringsSep "\n" errors) false;
checkUnitConfigWithLegacyKey = legacyKey: group: checks: attrs:
let
dump = lib.generators.toPretty { }
(lib.generators.withRecursion { depthLimit = 2; throwOnDepthLimit = false; } attrs);
attrs' =
if legacyKey == null
then attrs
else if ! attrs?${legacyKey}
then attrs
else if removeAttrs attrs [ legacyKey ] == {}
then attrs.${legacyKey}
else throw ''
The declaration
${dump}
must not mix unit options with the legacy key '${legacyKey}'.
This can be fixed by moving all settings from within ${legacyKey}
one level up.
'';
in
checkUnitConfig group checks attrs';
toOption = x: toOption = x:
if x == true then "true" if x == true then "true"
else if x == false then "false" else if x == false then "false"

@ -63,13 +63,13 @@ in {
${attrsToSection def.l2tpConfig} ${attrsToSection def.l2tpConfig}
'' + flip concatMapStrings def.l2tpSessions (x: '' '' + flip concatMapStrings def.l2tpSessions (x: ''
[L2TPSession] [L2TPSession]
${attrsToSection x.l2tpSessionConfig} ${attrsToSection x}
'') + optionalString (def.wireguardConfig != { }) '' '') + optionalString (def.wireguardConfig != { }) ''
[WireGuard] [WireGuard]
${attrsToSection def.wireguardConfig} ${attrsToSection def.wireguardConfig}
'' + flip concatMapStrings def.wireguardPeers (x: '' '' + flip concatMapStrings def.wireguardPeers (x: ''
[WireGuardPeer] [WireGuardPeer]
${attrsToSection x.wireguardPeerConfig} ${attrsToSection x}
'') + optionalString (def.bondConfig != { }) '' '') + optionalString (def.bondConfig != { }) ''
[Bond] [Bond]
${attrsToSection def.bondConfig} ${attrsToSection def.bondConfig}
@ -122,13 +122,13 @@ in {
${concatStringsSep "\n" (map (s: "Xfrm=${s}") def.xfrm)} ${concatStringsSep "\n" (map (s: "Xfrm=${s}") def.xfrm)}
'' + "\n" + flip concatMapStrings def.addresses (x: '' '' + "\n" + flip concatMapStrings def.addresses (x: ''
[Address] [Address]
${attrsToSection x.addressConfig} ${attrsToSection x}
'') + flip concatMapStrings def.routingPolicyRules (x: '' '') + flip concatMapStrings def.routingPolicyRules (x: ''
[RoutingPolicyRule] [RoutingPolicyRule]
${attrsToSection x.routingPolicyRuleConfig} ${attrsToSection x}
'') + flip concatMapStrings def.routes (x: '' '') + flip concatMapStrings def.routes (x: ''
[Route] [Route]
${attrsToSection x.routeConfig} ${attrsToSection x}
'') + optionalString (def.dhcpV4Config != { }) '' '') + optionalString (def.dhcpV4Config != { }) ''
[DHCPv4] [DHCPv4]
${attrsToSection def.dhcpV4Config} ${attrsToSection def.dhcpV4Config}
@ -149,22 +149,22 @@ in {
${attrsToSection def.ipv6SendRAConfig} ${attrsToSection def.ipv6SendRAConfig}
'' + flip concatMapStrings def.ipv6Prefixes (x: '' '' + flip concatMapStrings def.ipv6Prefixes (x: ''
[IPv6Prefix] [IPv6Prefix]
${attrsToSection x.ipv6PrefixConfig} ${attrsToSection x}
'') + flip concatMapStrings def.ipv6RoutePrefixes (x: '' '') + flip concatMapStrings def.ipv6RoutePrefixes (x: ''
[IPv6RoutePrefix] [IPv6RoutePrefix]
${attrsToSection x.ipv6RoutePrefixConfig} ${attrsToSection x}
'') + flip concatMapStrings def.dhcpServerStaticLeases (x: '' '') + flip concatMapStrings def.dhcpServerStaticLeases (x: ''
[DHCPServerStaticLease] [DHCPServerStaticLease]
${attrsToSection x.dhcpServerStaticLeaseConfig} ${attrsToSection x}
'') + optionalString (def.bridgeConfig != { }) '' '') + optionalString (def.bridgeConfig != { }) ''
[Bridge] [Bridge]
${attrsToSection def.bridgeConfig} ${attrsToSection def.bridgeConfig}
'' + flip concatMapStrings def.bridgeFDBs (x: '' '' + flip concatMapStrings def.bridgeFDBs (x: ''
[BridgeFDB] [BridgeFDB]
${attrsToSection x.bridgeFDBConfig} ${attrsToSection x}
'') + flip concatMapStrings def.bridgeMDBs (x: '' '') + flip concatMapStrings def.bridgeMDBs (x: ''
[BridgeMDB] [BridgeMDB]
${attrsToSection x.bridgeMDBConfig} ${attrsToSection x}
'') + optionalString (def.lldpConfig != { }) '' '') + optionalString (def.lldpConfig != { }) ''
[LLDP] [LLDP]
${attrsToSection def.lldpConfig} ${attrsToSection def.lldpConfig}
@ -251,7 +251,7 @@ in {
${attrsToSection def.quickFairQueueingConfigClass} ${attrsToSection def.quickFairQueueingConfigClass}
'' + flip concatMapStrings def.bridgeVLANs (x: '' '' + flip concatMapStrings def.bridgeVLANs (x: ''
[BridgeVLAN] [BridgeVLAN]
${attrsToSection x.bridgeVLANConfig} ${attrsToSection x}
'') + def.extraConfig; '') + def.extraConfig;
} }

@ -130,8 +130,8 @@ in
relevant = config.systemd.network.enable; relevant = config.systemd.network.enable;
root = config.systemd.network.netdevs; root = config.systemd.network.netdevs;
peer = (x: x.wireguardPeers); peer = (x: x.wireguardPeers);
key = (x: if x.wireguardPeerConfig ? PublicKey then x.wireguardPeerConfig.PublicKey else null); key = x: x.PublicKey or null;
description = "${options.systemd.network.netdevs}.\"<name>\".wireguardPeers.*.wireguardPeerConfig.PublicKey"; description = "${options.systemd.network.netdevs}.\"<name>\".wireguardPeers.*.PublicKey";
} }
{ {
relevant = config.networking.wireguard.enable; relevant = config.networking.wireguard.enable;

@ -386,7 +386,7 @@ let
(assertValueOneOf "UDP6ZeroChecksumRx" boolValues) (assertValueOneOf "UDP6ZeroChecksumRx" boolValues)
]; ];
sectionL2TPSession = checkUnitConfig "L2TPSession" [ sectionL2TPSession = checkUnitConfigWithLegacyKey "l2tpSessionConfig" "L2TPSession" [
(assertOnlyFields [ (assertOnlyFields [
"Name" "Name"
"SessionId" "SessionId"
@ -421,7 +421,7 @@ let
# NOTE The PresharedKey directive is missing on purpose here, please # NOTE The PresharedKey directive is missing on purpose here, please
# do not add it to this list. The nix store is world-readable,let's # do not add it to this list. The nix store is world-readable,let's
# refrain ourselves from providing a footgun. # refrain ourselves from providing a footgun.
sectionWireGuardPeer = checkUnitConfig "WireGuardPeer" [ sectionWireGuardPeer = checkUnitConfigWithLegacyKey "wireguardPeerConfig" "WireGuardPeer" [
(assertOnlyFields [ (assertOnlyFields [
"PublicKey" "PublicKey"
"PresharedKeyFile" "PresharedKeyFile"
@ -712,7 +712,7 @@ let
(assertValueOneOf "KeepConfiguration" (boolValues ++ ["static" "dhcp-on-stop" "dhcp"])) (assertValueOneOf "KeepConfiguration" (boolValues ++ ["static" "dhcp-on-stop" "dhcp"]))
]; ];
sectionAddress = checkUnitConfig "Address" [ sectionAddress = checkUnitConfigWithLegacyKey "addressConfig" "Address" [
(assertOnlyFields [ (assertOnlyFields [
"Address" "Address"
"Peer" "Peer"
@ -737,7 +737,7 @@ let
(assertValueOneOf "AutoJoin" boolValues) (assertValueOneOf "AutoJoin" boolValues)
]; ];
sectionRoutingPolicyRule = checkUnitConfig "RoutingPolicyRule" [ sectionRoutingPolicyRule = checkUnitConfigWithLegacyKey "routingPolicyRuleConfig" "RoutingPolicyRule" [
(assertOnlyFields [ (assertOnlyFields [
"TypeOfService" "TypeOfService"
"From" "From"
@ -772,7 +772,7 @@ let
(assertRange "SuppressInterfaceGroup" 0 2147483647) (assertRange "SuppressInterfaceGroup" 0 2147483647)
]; ];
sectionRoute = checkUnitConfig "Route" [ sectionRoute = checkUnitConfigWithLegacyKey "routeConfig" "Route" [
(assertOnlyFields [ (assertOnlyFields [
"Gateway" "Gateway"
"GatewayOnLink" "GatewayOnLink"
@ -1033,7 +1033,7 @@ let
(assertValueOneOf "EmitDomains" boolValues) (assertValueOneOf "EmitDomains" boolValues)
]; ];
sectionIPv6Prefix = checkUnitConfig "IPv6Prefix" [ sectionIPv6Prefix = checkUnitConfigWithLegacyKey "ipv6PrefixConfig" "IPv6Prefix" [
(assertOnlyFields [ (assertOnlyFields [
"AddressAutoconfiguration" "AddressAutoconfiguration"
"OnLink" "OnLink"
@ -1048,7 +1048,7 @@ let
(assertValueOneOf "Assign" boolValues) (assertValueOneOf "Assign" boolValues)
]; ];
sectionIPv6RoutePrefix = checkUnitConfig "IPv6RoutePrefix" [ sectionIPv6RoutePrefix = checkUnitConfigWithLegacyKey "ipv6RoutePrefixConfig" "IPv6RoutePrefix" [
(assertOnlyFields [ (assertOnlyFields [
"Route" "Route"
"LifetimeSec" "LifetimeSec"
@ -1057,7 +1057,7 @@ let
(assertInt "LifetimeSec") (assertInt "LifetimeSec")
]; ];
sectionDHCPServerStaticLease = checkUnitConfig "DHCPServerStaticLease" [ sectionDHCPServerStaticLease = checkUnitConfigWithLegacyKey "dhcpServerStaticLeaseConfig" "DHCPServerStaticLease" [
(assertOnlyFields [ (assertOnlyFields [
"MACAddress" "MACAddress"
"Address" "Address"
@ -1104,7 +1104,7 @@ let
(assertRange "Priority" 0 63) (assertRange "Priority" 0 63)
]; ];
sectionBridgeFDB = checkUnitConfig "BridgeFDB" [ sectionBridgeFDB = checkUnitConfigWithLegacyKey "bridgeFDBConfig" "BridgeFDB" [
(assertOnlyFields [ (assertOnlyFields [
"MACAddress" "MACAddress"
"Destination" "Destination"
@ -1121,7 +1121,7 @@ let
(assertValueOneOf "AssociatedWith" [ "use" "self" "master" "router" ]) (assertValueOneOf "AssociatedWith" [ "use" "self" "master" "router" ])
]; ];
sectionBridgeMDB = checkUnitConfig "BridgeMDB" [ sectionBridgeMDB = checkUnitConfigWithLegacyKey "bridgeMDBConfig" "BridgeMDB" [
(assertOnlyFields [ (assertOnlyFields [
"MulticastGroupAddress" "MulticastGroupAddress"
"VLANId" "VLANId"
@ -1524,7 +1524,7 @@ let
(assertRange "Weight" 1 1023) (assertRange "Weight" 1 1023)
]; ];
sectionBridgeVLAN = checkUnitConfig "BridgeVLAN" [ sectionBridgeVLAN = checkUnitConfigWithLegacyKey "bridgeVLANConfig" "BridgeVLAN" [
(assertOnlyFields [ (assertOnlyFields [
"VLAN" "VLAN"
"EgressUntagged" "EgressUntagged"
@ -1627,34 +1627,21 @@ let
}; };
mkSubsectionType = oldKey: checkF:
l2tpSessionOptions = { let
options = { type = types.addCheck (types.attrsOf unitOption) checkF;
l2tpSessionConfig = mkOption { in type // {
default = {}; merge = loc: defs:
type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionL2TPSession; let
description = '' final = type.merge loc defs;
Each attribute in this set specifies an option in the in
`[L2TPSession]` section of the unit. See if final?${oldKey}
{manpage}`systemd.netdev(5)` for details. then warn
''; "Using '${oldKey}' is deprecated! Move all attributes inside one level up and remove it."
}; final.${oldKey}
else
final;
}; };
};
wireguardPeerOptions = {
options = {
wireguardPeerConfig = mkOption {
default = {};
type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionWireGuardPeer;
description = ''
Each attribute in this set specifies an option in the
`[WireGuardPeer]` section of the unit. See
{manpage}`systemd.netdev(5)` for details.
'';
};
};
};
netdevOptions = commonNetworkOptions // { netdevOptions = commonNetworkOptions // {
@ -1805,12 +1792,12 @@ let
l2tpSessions = mkOption { l2tpSessions = mkOption {
default = []; default = [];
example = [ { l2tpSessionConfig={ example = [ {
SessionId = 25; SessionId = 25;
PeerSessionId = 26; PeerSessionId = 26;
Name = "l2tp-sess"; Name = "l2tp-sess";
};}]; }];
type = with types; listOf (submodule l2tpSessionOptions); type = types.listOf (mkSubsectionType "l2tpSessionConfig" check.netdev.sectionL2TPSession);
description = '' description = ''
Each item in this array specifies an option in the Each item in this array specifies an option in the
`[L2TPSession]` section of the unit. See `[L2TPSession]` section of the unit. See
@ -1838,14 +1825,14 @@ let
wireguardPeers = mkOption { wireguardPeers = mkOption {
default = []; default = [];
example = [ { wireguardPeerConfig={ example = [ {
Endpoint = "192.168.1.1:51820"; Endpoint = "192.168.1.1:51820";
PublicKey = "27s0OvaBBdHoJYkH9osZpjpgSOVNw+RaKfboT/Sfq0g="; PublicKey = "27s0OvaBBdHoJYkH9osZpjpgSOVNw+RaKfboT/Sfq0g=";
PresharedKeyFile = "/etc/wireguard/psk.key"; PresharedKeyFile = "/etc/wireguard/psk.key";
AllowedIPs = [ "10.0.0.1/32" ]; AllowedIPs = [ "10.0.0.1/32" ];
PersistentKeepalive = 15; PersistentKeepalive = 15;
};}]; } ];
type = with types; listOf (submodule wireguardPeerOptions); type = types.listOf (mkSubsectionType "wireguardPeerConfig" check.netdev.sectionWireGuardPeer);
description = '' description = ''
Each item in this array specifies an option in the Each item in this array specifies an option in the
`[WireGuardPeer]` section of the unit. See `[WireGuardPeer]` section of the unit. See
@ -1917,143 +1904,6 @@ let
}; };
addressOptions = {
options = {
addressConfig = mkOption {
example = { Address = "192.168.0.100/24"; };
type = types.addCheck (types.attrsOf unitOption) check.network.sectionAddress;
description = ''
Each attribute in this set specifies an option in the
`[Address]` section of the unit. See
{manpage}`systemd.network(5)` for details.
'';
};
};
};
routingPolicyRulesOptions = {
options = {
routingPolicyRuleConfig = mkOption {
default = { };
example = { Table = 10; IncomingInterface = "eth1"; Family = "both"; };
type = types.addCheck (types.attrsOf unitOption) check.network.sectionRoutingPolicyRule;
description = ''
Each attribute in this set specifies an option in the
`[RoutingPolicyRule]` section of the unit. See
{manpage}`systemd.network(5)` for details.
'';
};
};
};
routeOptions = {
options = {
routeConfig = mkOption {
default = {};
example = { Gateway = "192.168.0.1"; };
type = types.addCheck (types.attrsOf unitOption) check.network.sectionRoute;
description = ''
Each attribute in this set specifies an option in the
`[Route]` section of the unit. See
{manpage}`systemd.network(5)` for details.
'';
};
};
};
ipv6PrefixOptions = {
options = {
ipv6PrefixConfig = mkOption {
default = {};
example = { Prefix = "fd00::/64"; };
type = types.addCheck (types.attrsOf unitOption) check.network.sectionIPv6Prefix;
description = ''
Each attribute in this set specifies an option in the
`[IPv6Prefix]` section of the unit. See
{manpage}`systemd.network(5)` for details.
'';
};
};
};
ipv6RoutePrefixOptions = {
options = {
ipv6RoutePrefixConfig = mkOption {
default = {};
example = { Route = "fd00::/64"; };
type = types.addCheck (types.attrsOf unitOption) check.network.sectionIPv6RoutePrefix;
description = ''
Each attribute in this set specifies an option in the
`[IPv6RoutePrefix]` section of the unit. See
{manpage}`systemd.network(5)` for details.
'';
};
};
};
dhcpServerStaticLeaseOptions = {
options = {
dhcpServerStaticLeaseConfig = mkOption {
default = {};
example = { MACAddress = "65:43:4a:5b:d8:5f"; Address = "192.168.1.42"; };
type = types.addCheck (types.attrsOf unitOption) check.network.sectionDHCPServerStaticLease;
description = ''
Each attribute in this set specifies an option in the
`[DHCPServerStaticLease]` section of the unit. See
{manpage}`systemd.network(5)` for details.
Make sure to configure the corresponding client interface to use
`ClientIdentifier=mac`.
'';
};
};
};
bridgeFDBOptions = {
options = {
bridgeFDBConfig = mkOption {
default = {};
example = { MACAddress = "65:43:4a:5b:d8:5f"; Destination = "192.168.1.42"; VNI = 20; };
type = types.addCheck (types.attrsOf unitOption) check.network.sectionBridgeFDB;
description = ''
Each attribute in this set specifies an option in the
`[BridgeFDB]` section of the unit. See
{manpage}`systemd.network(5)` for details.
'';
};
};
};
bridgeMDBOptions = {
options = {
bridgeMDBConfig = mkOption {
default = {};
example = { MulticastGroupAddress = "ff02::1:2:3:4"; VLANId = 10; };
type = types.addCheck (types.attrsOf unitOption) check.network.sectionBridgeMDB;
description = ''
Each attribute in this set specifies an option in the
`[BridgeMDB]` section of the unit. See
{manpage}`systemd.network(5)` for details.
'';
};
};
};
bridgeVLANOptions = {
options = {
bridgeVLANConfig = mkOption {
default = {};
example = { VLAN = 20; };
type = types.addCheck (types.attrsOf unitOption) check.network.sectionBridgeVLAN;
description = ''
Each attribute in this set specifies an option in the
`[BridgeVLAN]` section of the unit. See
{manpage}`systemd.network(5)` for details.
'';
};
};
};
networkOptions = commonNetworkOptions // { networkOptions = commonNetworkOptions // {
linkConfig = mkOption { linkConfig = mkOption {
@ -2165,8 +2015,8 @@ let
dhcpServerStaticLeases = mkOption { dhcpServerStaticLeases = mkOption {
default = []; default = [];
example = [ { dhcpServerStaticLeaseConfig = { MACAddress = "65:43:4a:5b:d8:5f"; Address = "192.168.1.42"; }; } ]; example = [ { MACAddress = "65:43:4a:5b:d8:5f"; Address = "192.168.1.42"; } ];
type = with types; listOf (submodule dhcpServerStaticLeaseOptions); type = types.listOf (mkSubsectionType "dhcpServerStaticLeaseConfig" check.network.sectionDHCPServerStaticLease);
description = '' description = ''
A list of DHCPServerStaticLease sections to be added to the unit. See A list of DHCPServerStaticLease sections to be added to the unit. See
{manpage}`systemd.network(5)` for details. {manpage}`systemd.network(5)` for details.
@ -2175,8 +2025,8 @@ let
ipv6Prefixes = mkOption { ipv6Prefixes = mkOption {
default = []; default = [];
example = [ { ipv6PrefixConfig = { AddressAutoconfiguration = true; OnLink = true; }; } ]; example = [ { AddressAutoconfiguration = true; OnLink = true; } ];
type = with types; listOf (submodule ipv6PrefixOptions); type = types.listOf (mkSubsectionType "ipv6PrefixConfig" check.network.sectionIPv6Prefix);
description = '' description = ''
A list of ipv6Prefix sections to be added to the unit. See A list of ipv6Prefix sections to be added to the unit. See
{manpage}`systemd.network(5)` for details. {manpage}`systemd.network(5)` for details.
@ -2185,8 +2035,8 @@ let
ipv6RoutePrefixes = mkOption { ipv6RoutePrefixes = mkOption {
default = []; default = [];
example = [ { ipv6RoutePrefixConfig = { Route = "fd00::/64"; LifetimeSec = 3600; }; } ]; example = [ { Route = "fd00::/64"; LifetimeSec = 3600; } ];
type = with types; listOf (submodule ipv6RoutePrefixOptions); type = types.listOf (mkSubsectionType "ipv6RoutePrefixConfig" check.network.sectionIPv6RoutePrefix);
description = '' description = ''
A list of ipv6RoutePrefix sections to be added to the unit. See A list of ipv6RoutePrefix sections to be added to the unit. See
{manpage}`systemd.network(5)` for details. {manpage}`systemd.network(5)` for details.
@ -2206,8 +2056,8 @@ let
bridgeFDBs = mkOption { bridgeFDBs = mkOption {
default = []; default = [];
example = [ { bridgeFDBConfig = { MACAddress = "90:e2:ba:43:fc:71"; Destination = "192.168.100.4"; VNI = 3600; }; } ]; example = [ { MACAddress = "90:e2:ba:43:fc:71"; Destination = "192.168.100.4"; VNI = 3600; } ];
type = with types; listOf (submodule bridgeFDBOptions); type = types.listOf (mkSubsectionType "bridgeFDBConfig" check.network.sectionBridgeFDB);
description = '' description = ''
A list of BridgeFDB sections to be added to the unit. See A list of BridgeFDB sections to be added to the unit. See
{manpage}`systemd.network(5)` for details. {manpage}`systemd.network(5)` for details.
@ -2216,8 +2066,8 @@ let
bridgeMDBs = mkOption { bridgeMDBs = mkOption {
default = []; default = [];
example = [ { bridgeMDBConfig = { MulticastGroupAddress = "ff02::1:2:3:4"; VLANId = 10; } ; } ]; example = [ { MulticastGroupAddress = "ff02::1:2:3:4"; VLANId = 10; } ];
type = with types; listOf (submodule bridgeMDBOptions); type = types.listOf (mkSubsectionType "bridgeMDBConfig" check.network.sectionBridgeMDB);
description = '' description = ''
A list of BridgeMDB sections to be added to the unit. See A list of BridgeMDB sections to be added to the unit. See
{manpage}`systemd.network(5)` for details. {manpage}`systemd.network(5)` for details.
@ -2534,8 +2384,8 @@ let
bridgeVLANs = mkOption { bridgeVLANs = mkOption {
default = []; default = [];
example = [ { bridgeVLANConfig = { VLAN = "10-20"; }; } ]; example = [ { VLAN = "10-20"; } ];
type = with types; listOf (submodule bridgeVLANOptions); type = types.listOf (mkSubsectionType "bridgeVLANConfig" check.network.sectionBridgeVLAN);
description = '' description = ''
A list of BridgeVLAN sections to be added to the unit. See A list of BridgeVLAN sections to be added to the unit. See
{manpage}`systemd.network(5)` for details. {manpage}`systemd.network(5)` for details.
@ -2685,7 +2535,8 @@ let
addresses = mkOption { addresses = mkOption {
default = [ ]; default = [ ];
type = with types; listOf (submodule addressOptions); example = [ { Address = "192.168.0.100/24"; } ];
type = types.listOf (mkSubsectionType "addressConfig" check.network.sectionAddress);
description = '' description = ''
A list of address sections to be added to the unit. See A list of address sections to be added to the unit. See
{manpage}`systemd.network(5)` for details. {manpage}`systemd.network(5)` for details.
@ -2694,7 +2545,8 @@ let
routingPolicyRules = mkOption { routingPolicyRules = mkOption {
default = [ ]; default = [ ];
type = with types; listOf (submodule routingPolicyRulesOptions); example = [ { Table = 10; IncomingInterface = "eth1"; Family = "both"; } ];
type = types.listOf (mkSubsectionType "routingPolicyRuleConfig" check.network.sectionRoutingPolicyRule);
description = '' description = ''
A list of routing policy rules sections to be added to the unit. See A list of routing policy rules sections to be added to the unit. See
{manpage}`systemd.network(5)` for details. {manpage}`systemd.network(5)` for details.
@ -2703,7 +2555,8 @@ let
routes = mkOption { routes = mkOption {
default = [ ]; default = [ ];
type = with types; listOf (submodule routeOptions); example = [ { Gateway = "192.168.0.1"; } ];
type = types.listOf (mkSubsectionType "routeConfig" check.network.sectionRoute);
description = '' description = ''
A list of route sections to be added to the unit. See A list of route sections to be added to the unit. See
{manpage}`systemd.network(5)` for details. {manpage}`systemd.network(5)` for details.

@ -32,13 +32,13 @@ let
optionalAttrs (gateway != null && gateway.interface != null) { optionalAttrs (gateway != null && gateway.interface != null) {
networks."40-${gateway.interface}" = { networks."40-${gateway.interface}" = {
matchConfig.Name = gateway.interface; matchConfig.Name = gateway.interface;
routes = [{ routes = [
routeConfig = { ({
Gateway = gateway.address; Gateway = gateway.address;
} // optionalAttrs (gateway.metric != null) { } // optionalAttrs (gateway.metric != null) {
Metric = gateway.metric; Metric = gateway.metric;
}; })
}]; ];
}; };
} }
)); ));
@ -95,65 +95,64 @@ let
address = forEach (interfaceIps i) address = forEach (interfaceIps i)
(ip: "${ip.address}/${toString ip.prefixLength}"); (ip: "${ip.address}/${toString ip.prefixLength}");
routes = forEach (interfaceRoutes i) routes = forEach (interfaceRoutes i)
(route: { (route: mkMerge [
# Most of these route options have not been tested. # Most of these route options have not been tested.
# Please fix or report any mistakes you may find. # Please fix or report any mistakes you may find.
routeConfig = (mkIf (route.address != null && route.prefixLength != null) {
optionalAttrs (route.address != null && route.prefixLength != null) { Destination = "${route.address}/${toString route.prefixLength}";
Destination = "${route.address}/${toString route.prefixLength}"; })
} // (mkIf (route.options ? fastopen_no_cookie) {
optionalAttrs (route.options ? fastopen_no_cookie) { FastOpenNoCookie = route.options.fastopen_no_cookie;
FastOpenNoCookie = route.options.fastopen_no_cookie; })
} // (mkIf (route.via != null) {
optionalAttrs (route.via != null) { Gateway = route.via;
Gateway = route.via; })
} // (mkIf (route.type != null) {
optionalAttrs (route.type != null) { Type = route.type;
Type = route.type; })
} // (mkIf (route.options ? onlink) {
optionalAttrs (route.options ? onlink) { GatewayOnLink = true;
GatewayOnLink = true; })
} // (mkIf (route.options ? initrwnd) {
optionalAttrs (route.options ? initrwnd) { InitialAdvertisedReceiveWindow = route.options.initrwnd;
InitialAdvertisedReceiveWindow = route.options.initrwnd; })
} // (mkIf (route.options ? initcwnd) {
optionalAttrs (route.options ? initcwnd) { InitialCongestionWindow = route.options.initcwnd;
InitialCongestionWindow = route.options.initcwnd; })
} // (mkIf (route.options ? pref) {
optionalAttrs (route.options ? pref) { IPv6Preference = route.options.pref;
IPv6Preference = route.options.pref; })
} // (mkIf (route.options ? mtu) {
optionalAttrs (route.options ? mtu) { MTUBytes = route.options.mtu;
MTUBytes = route.options.mtu; })
} // (mkIf (route.options ? metric) {
optionalAttrs (route.options ? metric) { Metric = route.options.metric;
Metric = route.options.metric; })
} // (mkIf (route.options ? src) {
optionalAttrs (route.options ? src) { PreferredSource = route.options.src;
PreferredSource = route.options.src; })
} // (mkIf (route.options ? protocol) {
optionalAttrs (route.options ? protocol) { Protocol = route.options.protocol;
Protocol = route.options.protocol; })
} // (mkIf (route.options ? quickack) {
optionalAttrs (route.options ? quickack) { QuickAck = route.options.quickack;
QuickAck = route.options.quickack; })
} // (mkIf (route.options ? scope) {
optionalAttrs (route.options ? scope) { Scope = route.options.scope;
Scope = route.options.scope; })
} // (mkIf (route.options ? from) {
optionalAttrs (route.options ? from) { Source = route.options.from;
Source = route.options.from; })
} // (mkIf (route.options ? table) {
optionalAttrs (route.options ? table) { Table = route.options.table;
Table = route.options.table; })
} // (mkIf (route.options ? advmss) {
optionalAttrs (route.options ? advmss) { TCPAdvertisedMaximumSegmentSize = route.options.advmss;
TCPAdvertisedMaximumSegmentSize = route.options.advmss; })
} // (mkIf (route.options ? ttl-propagate) {
optionalAttrs (route.options ? ttl-propagate) { TTLPropagate = route.options.ttl-propagate == "enabled";
TTLPropagate = route.options.ttl-propagate == "enabled"; })
}; ]);
});
networkConfig.IPv6PrivacyExtensions = "kernel"; networkConfig.IPv6PrivacyExtensions = "kernel";
linkConfig = optionalAttrs (i.macAddress != null) { linkConfig = optionalAttrs (i.macAddress != null) {
MACAddress = i.macAddress; MACAddress = i.macAddress;

@ -59,7 +59,7 @@ import ./make-test-python.nix ({ pkgs, lib, ... }:
"100.64.0.2/24" "100.64.0.2/24"
]; ];
routes = [ routes = [
{ routeConfig = { Destination = "192.0.2.0/24"; Gateway = "100.64.0.1"; }; } { Destination = "192.0.2.0/24"; Gateway = "100.64.0.1"; }
]; ];
}; };
}; };
@ -149,7 +149,7 @@ import ./make-test-python.nix ({ pkgs, lib, ... }:
"2001:db8::2/64" "2001:db8::2/64"
]; ];
routes = [ routes = [
{ routeConfig = { Destination = "::/0"; Gateway = "2001:db8::1"; }; } { Destination = "::/0"; Gateway = "2001:db8::1"; }
]; ];
}; };
}; };

@ -74,10 +74,8 @@ in
wireguardConfig.ListenPort = server.wg.listen; wireguardConfig.ListenPort = server.wg.listen;
wireguardPeers = [ wireguardPeers = [
{ {
wireguardPeerConfig = { AllowedIPs = [ "::/0" ];
AllowedIPs = [ "::/0" ]; PublicKey = client.wg.public;
PublicKey = client.wg.public;
};
} }
]; ];
}; };
@ -97,11 +95,9 @@ in
systemd.network.netdevs."10-${deviceName}".wireguardPeers = [ systemd.network.netdevs."10-${deviceName}".wireguardPeers = [
{ {
wireguardPeerConfig = { AllowedIPs = [ "::/0" ];
AllowedIPs = [ "::/0" ]; PublicKey = server.wg.public;
PublicKey = server.wg.public; Endpoint = "server:${builtins.toString server.wg.listen}";
Endpoint = "server:${builtins.toString server.wg.listen}";
};
} }
]; ];

@ -28,10 +28,8 @@ import ./make-test-python.nix ({ lib, ... }: {
Address = "10.0.0.1/24"; Address = "10.0.0.1/24";
}; };
dhcpServerStaticLeases = [{ dhcpServerStaticLeases = [{
dhcpServerStaticLeaseConfig = { MACAddress = "02:de:ad:be:ef:01";
MACAddress = "02:de:ad:be:ef:01"; Address = "10.0.0.10";
Address = "10.0.0.10";
};
}]; }];
}; };
}; };

@ -54,7 +54,7 @@ import ./make-test-python.nix ({pkgs, ...}: {
name = "eth1"; name = "eth1";
networkConfig.Bridge = "br0"; networkConfig.Bridge = "br0";
bridgeVLANs = [ bridgeVLANs = [
{ bridgeVLANConfig = { PVID = 2; EgressUntagged = 2; }; } { PVID = 2; EgressUntagged = 2; }
]; ];
}; };
"02-br0" = { "02-br0" = {
@ -69,8 +69,8 @@ import ./make-test-python.nix ({pkgs, ...}: {
PoolSize = 1; PoolSize = 1;
}; };
bridgeVLANs = [ bridgeVLANs = [
{ bridgeVLANConfig = { PVID = 1; EgressUntagged = 1; }; } { PVID = 1; EgressUntagged = 1; }
{ bridgeVLANConfig = { VLAN = 2; }; } { VLAN = 2; }
]; ];
}; };
"02-vlan2" = { "02-vlan2" = {

@ -259,7 +259,7 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: {
"01-lo" = { "01-lo" = {
name = "lo"; name = "lo";
addresses = [ addresses = [
{ addressConfig.Address = "FD42::1/128"; } { Address = "FD42::1/128"; }
]; ];
}; };
}; };

@ -59,14 +59,14 @@ in {
matchConfig.Name = "vrf1"; matchConfig.Name = "vrf1";
networkConfig.IPForward = "yes"; networkConfig.IPForward = "yes";
routes = [ routes = [
{ routeConfig = { Destination = "192.168.1.2"; Metric = 100; }; } { Destination = "192.168.1.2"; Metric = 100; }
]; ];
}; };
networks."10-vrf2" = { networks."10-vrf2" = {
matchConfig.Name = "vrf2"; matchConfig.Name = "vrf2";
networkConfig.IPForward = "yes"; networkConfig.IPForward = "yes";
routes = [ routes = [
{ routeConfig = { Destination = "192.168.2.3"; Metric = 100; }; } { Destination = "192.168.2.3"; Metric = 100; }
]; ];
}; };

@ -23,13 +23,13 @@ let generateNodeConf = { lib, pkgs, config, privk, pubk, peerId, nodeId, ...}: {
ListenPort = 51820; ListenPort = 51820;
FirewallMark = 42; FirewallMark = 42;
}; };
wireguardPeers = [ {wireguardPeerConfig={ wireguardPeers = [ {
Endpoint = "192.168.1.${peerId}:51820"; Endpoint = "192.168.1.${peerId}:51820";
PublicKey = pubk; PublicKey = pubk;
PresharedKeyFile = pkgs.writeText "psk.key" "yTL3sCOL33Wzi6yCnf9uZQl/Z8laSE+zwpqOHC4HhFU="; PresharedKeyFile = pkgs.writeText "psk.key" "yTL3sCOL33Wzi6yCnf9uZQl/Z8laSE+zwpqOHC4HhFU=";
AllowedIPs = [ "10.0.0.${peerId}/32" ]; AllowedIPs = [ "10.0.0.${peerId}/32" ];
PersistentKeepalive = 15; PersistentKeepalive = 15;
};}]; } ];
}; };
}; };
networks = { networks = {
@ -41,8 +41,8 @@ let generateNodeConf = { lib, pkgs, config, privk, pubk, peerId, nodeId, ...}: {
matchConfig = { Name = "wg0"; }; matchConfig = { Name = "wg0"; };
address = [ "10.0.0.${nodeId}/32" ]; address = [ "10.0.0.${nodeId}/32" ];
routes = [ routes = [
{ routeConfig = { Gateway = "10.0.0.${nodeId}"; Destination = "10.0.0.0/24"; }; } { Gateway = "10.0.0.${nodeId}"; Destination = "10.0.0.0/24"; }
{ routeConfig = { Gateway = "10.0.0.${nodeId}"; Destination = "10.0.0.0/24"; Table = "custom"; }; } { Gateway = "10.0.0.${nodeId}"; Destination = "10.0.0.0/24"; Table = "custom"; }
]; ];
}; };
"30-eth1" = { "30-eth1" = {
@ -52,11 +52,11 @@ let generateNodeConf = { lib, pkgs, config, privk, pubk, peerId, nodeId, ...}: {
"fe80::${nodeId}/64" "fe80::${nodeId}/64"
]; ];
routingPolicyRules = [ routingPolicyRules = [
{ routingPolicyRuleConfig = { Table = 10; IncomingInterface = "eth1"; Family = "both"; };} { Table = 10; IncomingInterface = "eth1"; Family = "both"; }
{ routingPolicyRuleConfig = { Table = 20; OutgoingInterface = "eth1"; };} { Table = 20; OutgoingInterface = "eth1"; }
{ routingPolicyRuleConfig = { Table = 30; From = "192.168.1.1"; To = "192.168.1.2"; SourcePort = 666 ; DestinationPort = 667; };} { Table = 30; From = "192.168.1.1"; To = "192.168.1.2"; SourcePort = 666 ; DestinationPort = 667; }
{ routingPolicyRuleConfig = { Table = 40; IPProtocol = "tcp"; InvertRule = true; };} { Table = 40; IPProtocol = "tcp"; InvertRule = true; }
{ routingPolicyRuleConfig = { Table = 50; IncomingInterface = "eth1"; Family = "ipv4"; };} { Table = 50; IncomingInterface = "eth1"; Family = "ipv4"; }
]; ];
}; };
}; };

@ -55,7 +55,7 @@ import ./make-test-python.nix ({ pkgs, lib, ... }:
"100.64.0.2/24" "100.64.0.2/24"
]; ];
routes = [ routes = [
{ routeConfig = { Destination = "192.0.2.0/24"; Gateway = "100.64.0.1"; }; } { Destination = "192.0.2.0/24"; Gateway = "100.64.0.1"; }
]; ];
}; };
}; };
@ -202,7 +202,7 @@ import ./make-test-python.nix ({ pkgs, lib, ... }:
"2001:db8::2/64" "2001:db8::2/64"
]; ];
routes = [ routes = [
{ routeConfig = { Destination = "64:ff9b::/96"; Gateway = "2001:db8::1"; }; } { Destination = "64:ff9b::/96"; Gateway = "2001:db8::1"; }
]; ];
}; };
}; };