Merge pull request #21875 from abbradar/gateway-interface
Allow specifying interface for default gateway
This commit is contained in:
commit
5247140e57
@ -115,6 +115,11 @@ set -- config.enable ./declare-enable.nix ./define-enable.nix ./define-loaOfSub-
|
|||||||
checkConfigError 'The option .* defined in .* does not exist.' "$@"
|
checkConfigError 'The option .* defined in .* does not exist.' "$@"
|
||||||
checkConfigOutput "true" "$@" ./define-module-check.nix
|
checkConfigOutput "true" "$@" ./define-module-check.nix
|
||||||
|
|
||||||
|
# Check coerced value.
|
||||||
|
checkConfigOutput "\"42\"" config.value ./declare-coerced-value.nix
|
||||||
|
checkConfigOutput "\"24\"" config.value ./declare-coerced-value.nix ./define-value-string.nix
|
||||||
|
checkConfigError 'The option value .* in .* is not a coercedTo.' config.value ./declare-coerced-value.nix ./define-value-list.nix
|
||||||
|
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
====== module tests ======
|
====== module tests ======
|
||||||
$pass Pass
|
$pass Pass
|
||||||
|
10
lib/tests/modules/declare-coerced-value.nix
Normal file
10
lib/tests/modules/declare-coerced-value.nix
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{ lib, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
value = lib.mkOption {
|
||||||
|
default = 42;
|
||||||
|
type = lib.types.coercedTo lib.types.int builtins.toString lib.types.str;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
3
lib/tests/modules/define-value-list.nix
Normal file
3
lib/tests/modules/define-value-list.nix
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
value = [];
|
||||||
|
}
|
3
lib/tests/modules/define-value-string.nix
Normal file
3
lib/tests/modules/define-value-string.nix
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
value = "24";
|
||||||
|
}
|
@ -352,6 +352,28 @@ rec {
|
|||||||
functor = (defaultFunctor name) // { wrapped = [ t1 t2 ]; };
|
functor = (defaultFunctor name) // { wrapped = [ t1 t2 ]; };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
coercedTo = coercedType: coerceFunc: finalType:
|
||||||
|
assert coercedType.getSubModules == null;
|
||||||
|
mkOptionType rec {
|
||||||
|
name = "coercedTo";
|
||||||
|
description = "${finalType.description} or ${coercedType.description}";
|
||||||
|
check = x: finalType.check x || coercedType.check x;
|
||||||
|
merge = loc: defs:
|
||||||
|
let
|
||||||
|
coerceVal = val:
|
||||||
|
if finalType.check val then val
|
||||||
|
else let
|
||||||
|
coerced = coerceFunc val;
|
||||||
|
in assert finalType.check coerced; coerced;
|
||||||
|
|
||||||
|
in finalType.merge loc (map (def: def // { value = coerceVal def.value; }) defs);
|
||||||
|
getSubOptions = finalType.getSubOptions;
|
||||||
|
getSubModules = finalType.getSubModules;
|
||||||
|
substSubModules = m: coercedTo coercedType coerceFunc (finalType.substSubModules m);
|
||||||
|
typeMerge = t1: t2: null;
|
||||||
|
functor = (defaultFunctor name) // { wrapped = finalType; };
|
||||||
|
};
|
||||||
|
|
||||||
# Obsolete alternative to configOf. It takes its option
|
# Obsolete alternative to configOf. It takes its option
|
||||||
# declarations from the ‘options’ attribute of containing option
|
# declarations from the ‘options’ attribute of containing option
|
||||||
# declaration.
|
# declaration.
|
||||||
|
@ -22,5 +22,25 @@ boot.kernel.sysctl."net.ipv6.conf.eth0.disable_ipv6" = true;
|
|||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
<para>As with IPv4 networking interfaces are automatically configured via
|
||||||
|
DHCPv6. You can configure an interface manually:
|
||||||
|
|
||||||
|
<programlisting>
|
||||||
|
networking.interfaces.eth0.ip6 = [ { address = "fe00:aa:bb:cc::2"; prefixLength = 64; } ];
|
||||||
|
</programlisting>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>For configuring a gateway, optionally with explicitly specified interface:
|
||||||
|
|
||||||
|
<programlisting>
|
||||||
|
networking.defaultGateway6 = {
|
||||||
|
address = "fe00::1";
|
||||||
|
interface = "enp0s3";
|
||||||
|
}
|
||||||
|
</programlisting>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>See <xref linkend='sec-ipv4' /> for similar examples and additional information.
|
||||||
|
</para>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
@ -102,17 +102,21 @@ in
|
|||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Set the default gateway.
|
# Set the default gateway.
|
||||||
${optionalString (cfg.defaultGateway != null && cfg.defaultGateway != "") ''
|
${optionalString (cfg.defaultGateway != null && cfg.defaultGateway.address != "") ''
|
||||||
# FIXME: get rid of "|| true" (necessary to make it idempotent).
|
# FIXME: get rid of "|| true" (necessary to make it idempotent).
|
||||||
ip route add default via "${cfg.defaultGateway}" ${
|
ip route add default via "${cfg.defaultGateway.address}" ${
|
||||||
optionalString (cfg.defaultGatewayWindowSize != null)
|
optionalString (cfg.defaultGatewayWindowSize != null)
|
||||||
"window ${toString cfg.defaultGatewayWindowSize}"} || true
|
"window ${toString cfg.defaultGatewayWindowSize}"} ${
|
||||||
|
optionalString (cfg.defaultGateway.interface != null)
|
||||||
|
"dev ${cfg.defaultGateway.interface}"}|| true
|
||||||
''}
|
''}
|
||||||
${optionalString (cfg.defaultGateway6 != null && cfg.defaultGateway6 != "") ''
|
${optionalString (cfg.defaultGateway6 != null && cfg.defaultGateway6.address != "") ''
|
||||||
# FIXME: get rid of "|| true" (necessary to make it idempotent).
|
# FIXME: get rid of "|| true" (necessary to make it idempotent).
|
||||||
ip -6 route add ::/0 via "${cfg.defaultGateway6}" ${
|
ip -6 route add ::/0 via "${cfg.defaultGateway6.address}" ${
|
||||||
optionalString (cfg.defaultGatewayWindowSize != null)
|
optionalString (cfg.defaultGatewayWindowSize != null)
|
||||||
"window ${toString cfg.defaultGatewayWindowSize}"} || true
|
"window ${toString cfg.defaultGatewayWindowSize}"} ${
|
||||||
|
optionalString (cfg.defaultGateway6.interface != null)
|
||||||
|
"dev ${cfg.defaultGateway6.interface}"} || true
|
||||||
''}
|
''}
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
@ -38,6 +38,12 @@ in
|
|||||||
} {
|
} {
|
||||||
assertion = cfg.vswitches == {};
|
assertion = cfg.vswitches == {};
|
||||||
message = "networking.vswichtes are not supported by networkd.";
|
message = "networking.vswichtes are not supported by networkd.";
|
||||||
|
} {
|
||||||
|
assertion = cfg.defaultGateway == null || cfg.defaultGateway.interface == null;
|
||||||
|
message = "networking.defaultGateway.interface is not supported by networkd.";
|
||||||
|
} {
|
||||||
|
assertion = cfg.defaultGateway6 == null || cfg.defaultGateway6.interface == null;
|
||||||
|
message = "networking.defaultGateway6.interface is not supported by networkd.";
|
||||||
} ] ++ flip mapAttrsToList cfg.bridges (n: { rstp, ... }: {
|
} ] ++ flip mapAttrsToList cfg.bridges (n: { rstp, ... }: {
|
||||||
assertion = !rstp;
|
assertion = !rstp;
|
||||||
message = "networking.bridges.${n}.rstp is not supported by networkd.";
|
message = "networking.bridges.${n}.rstp is not supported by networkd.";
|
||||||
|
@ -116,6 +116,28 @@ let
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
gatewayCoerce = address: { inherit address; };
|
||||||
|
|
||||||
|
gatewayOpts = { ... }: {
|
||||||
|
|
||||||
|
options = {
|
||||||
|
|
||||||
|
address = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = "The default gateway address.";
|
||||||
|
};
|
||||||
|
|
||||||
|
interface = mkOption {
|
||||||
|
type = types.nullOr types.str;
|
||||||
|
default = null;
|
||||||
|
example = "enp0s3";
|
||||||
|
description = "The default gateway interface.";
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
interfaceOpts = { name, ... }: {
|
interfaceOpts = { name, ... }: {
|
||||||
|
|
||||||
options = {
|
options = {
|
||||||
@ -327,19 +349,27 @@ in
|
|||||||
|
|
||||||
networking.defaultGateway = mkOption {
|
networking.defaultGateway = mkOption {
|
||||||
default = null;
|
default = null;
|
||||||
example = "131.211.84.1";
|
example = {
|
||||||
type = types.nullOr types.str;
|
address = "131.211.84.1";
|
||||||
|
device = "enp3s0";
|
||||||
|
};
|
||||||
|
type = types.nullOr (types.coercedTo types.str gatewayCoerce (types.submodule gatewayOpts));
|
||||||
description = ''
|
description = ''
|
||||||
The default gateway. It can be left empty if it is auto-detected through DHCP.
|
The default gateway. It can be left empty if it is auto-detected through DHCP.
|
||||||
|
It can be specified as a string or an option set along with a network interface.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
networking.defaultGateway6 = mkOption {
|
networking.defaultGateway6 = mkOption {
|
||||||
default = null;
|
default = null;
|
||||||
example = "2001:4d0:1e04:895::1";
|
example = {
|
||||||
type = types.nullOr types.str;
|
address = "2001:4d0:1e04:895::1";
|
||||||
|
device = "enp3s0";
|
||||||
|
};
|
||||||
|
type = types.nullOr (types.coercedTo types.str gatewayCoerce (types.submodule gatewayOpts));
|
||||||
description = ''
|
description = ''
|
||||||
The default ipv6 gateway. It can be left empty if it is auto-detected through DHCP.
|
The default ipv6 gateway. It can be left empty if it is auto-detected through DHCP.
|
||||||
|
It can be specified as a string or an option set along with a network interface.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user