From 5cbcd3af69d859a6d919ad26261c57649e9c888f Mon Sep 17 00:00:00 2001 From: Nikolay Amiantov Date: Sat, 14 Jan 2017 04:14:01 +0300 Subject: [PATCH 1/4] types library: add coercedTo --- lib/types.nix | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/lib/types.nix b/lib/types.nix index 9366d394da73..0d1a88a00f2d 100644 --- a/lib/types.nix +++ b/lib/types.nix @@ -352,6 +352,28 @@ rec { 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 # declarations from the ‘options’ attribute of containing option # declaration. From fcb20b9feecb33c60d15a98766f7fd1bfbeae13e Mon Sep 17 00:00:00 2001 From: Nikolay Amiantov Date: Thu, 2 Feb 2017 01:52:40 +0300 Subject: [PATCH 2/4] module tests: add tests for coercedTo --- lib/tests/modules.sh | 5 +++++ lib/tests/modules/declare-coerced-value.nix | 10 ++++++++++ lib/tests/modules/define-value-list.nix | 3 +++ lib/tests/modules/define-value-string.nix | 3 +++ 4 files changed, 21 insertions(+) create mode 100644 lib/tests/modules/declare-coerced-value.nix create mode 100644 lib/tests/modules/define-value-list.nix create mode 100644 lib/tests/modules/define-value-string.nix diff --git a/lib/tests/modules.sh b/lib/tests/modules.sh index 65de8e378c7e..e0774383720b 100755 --- a/lib/tests/modules.sh +++ b/lib/tests/modules.sh @@ -115,6 +115,11 @@ set -- config.enable ./declare-enable.nix ./define-enable.nix ./define-loaOfSub- checkConfigError 'The option .* defined in .* does not exist.' "$@" 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 < Date: Sat, 14 Jan 2017 04:14:16 +0300 Subject: [PATCH 3/4] network-interfaces service: add defaultGateway{,6}.interface --- .../tasks/network-interfaces-scripted.nix | 16 ++++--- .../tasks/network-interfaces-systemd.nix | 6 +++ nixos/modules/tasks/network-interfaces.nix | 42 ++++++++++++++++--- 3 files changed, 52 insertions(+), 12 deletions(-) diff --git a/nixos/modules/tasks/network-interfaces-scripted.nix b/nixos/modules/tasks/network-interfaces-scripted.nix index c50ea5c79643..aa86fc85feb6 100644 --- a/nixos/modules/tasks/network-interfaces-scripted.nix +++ b/nixos/modules/tasks/network-interfaces-scripted.nix @@ -102,17 +102,21 @@ in EOF # 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). - ip route add default via "${cfg.defaultGateway}" ${ + ip route add default via "${cfg.defaultGateway.address}" ${ 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). - ip -6 route add ::/0 via "${cfg.defaultGateway6}" ${ + ip -6 route add ::/0 via "${cfg.defaultGateway6.address}" ${ optionalString (cfg.defaultGatewayWindowSize != null) - "window ${toString cfg.defaultGatewayWindowSize}"} || true + "window ${toString cfg.defaultGatewayWindowSize}"} ${ + optionalString (cfg.defaultGateway6.interface != null) + "dev ${cfg.defaultGateway6.interface}"} || true ''} ''; }; diff --git a/nixos/modules/tasks/network-interfaces-systemd.nix b/nixos/modules/tasks/network-interfaces-systemd.nix index 974041d7e1a5..a1212c905560 100644 --- a/nixos/modules/tasks/network-interfaces-systemd.nix +++ b/nixos/modules/tasks/network-interfaces-systemd.nix @@ -38,6 +38,12 @@ in } { assertion = cfg.vswitches == {}; 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, ... }: { assertion = !rstp; message = "networking.bridges.${n}.rstp is not supported by networkd."; diff --git a/nixos/modules/tasks/network-interfaces.nix b/nixos/modules/tasks/network-interfaces.nix index 83d9854d3517..3f56419d2a6d 100644 --- a/nixos/modules/tasks/network-interfaces.nix +++ b/nixos/modules/tasks/network-interfaces.nix @@ -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, ... }: { options = { @@ -327,19 +349,27 @@ in networking.defaultGateway = mkOption { default = null; - example = "131.211.84.1"; - type = types.nullOr types.str; + example = { + address = "131.211.84.1"; + device = "enp3s0"; + }; + type = types.nullOr (types.coercedTo types.str gatewayCoerce (types.submodule gatewayOpts)); 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 { default = null; - example = "2001:4d0:1e04:895::1"; - type = types.nullOr types.str; + example = { + address = "2001:4d0:1e04:895::1"; + device = "enp3s0"; + }; + type = types.nullOr (types.coercedTo types.str gatewayCoerce (types.submodule gatewayOpts)); 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. ''; }; From 4feb0a998adc60c1ff8a3e31b7a79455fe27f6d5 Mon Sep 17 00:00:00 2001 From: Nikolay Amiantov Date: Sat, 14 Jan 2017 13:49:03 +0300 Subject: [PATCH 4/4] manual: mention needed options for IPv6 --- .../doc/manual/configuration/ipv6-config.xml | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/nixos/doc/manual/configuration/ipv6-config.xml b/nixos/doc/manual/configuration/ipv6-config.xml index bf86926f9bf5..6d9e0a164e9e 100644 --- a/nixos/doc/manual/configuration/ipv6-config.xml +++ b/nixos/doc/manual/configuration/ipv6-config.xml @@ -22,5 +22,25 @@ boot.kernel.sysctl."net.ipv6.conf.eth0.disable_ipv6" = true; +As with IPv4 networking interfaces are automatically configured via +DHCPv6. You can configure an interface manually: + + +networking.interfaces.eth0.ip6 = [ { address = "fe00:aa:bb:cc::2"; prefixLength = 64; } ]; + + + +For configuring a gateway, optionally with explicitly specified interface: + + +networking.defaultGateway6 = { + address = "fe00::1"; + interface = "enp0s3"; +} + + + +See for similar examples and additional information. +