diff options
author | pennae <github@quasiparticle.net> | 2021-08-11 11:02:47 +0200 |
---|---|---|
committer | tomberek <tomberek@users.noreply.github.com> | 2021-10-16 20:48:03 -0400 |
commit | f29ea2d15d833494f7e97e0231b03ca70a8e7db4 (patch) | |
tree | 636d34b80a85598e045fb5e0f190c6330a51efdf | |
parent | eebfe7199d9e543acea19de4af15a91ab7774e7c (diff) | |
download | nixpkgs-f29ea2d15d833494f7e97e0231b03ca70a8e7db4.tar nixpkgs-f29ea2d15d833494f7e97e0231b03ca70a8e7db4.tar.gz nixpkgs-f29ea2d15d833494f7e97e0231b03ca70a8e7db4.tar.bz2 nixpkgs-f29ea2d15d833494f7e97e0231b03ca70a8e7db4.tar.lz nixpkgs-f29ea2d15d833494f7e97e0231b03ca70a8e7db4.tar.xz nixpkgs-f29ea2d15d833494f7e97e0231b03ca70a8e7db4.tar.zst nixpkgs-f29ea2d15d833494f7e97e0231b03ca70a8e7db4.zip |
nixos/networking: add foo-over-udp endpoint support
allows configuration of foo-over-udp decapsulation endpoints. sadly networkd seems to lack the features necessary to support local and peer address configuration, so those are only supported when using scripted configuration.
-rw-r--r-- | nixos/doc/manual/from_md/release-notes/rl-2111.section.xml | 13 | ||||
-rw-r--r-- | nixos/doc/manual/release-notes/rl-2111.section.md | 4 | ||||
-rw-r--r-- | nixos/modules/system/boot/networkd.nix | 26 | ||||
-rw-r--r-- | nixos/modules/tasks/network-interfaces-scripted.nix | 34 | ||||
-rw-r--r-- | nixos/modules/tasks/network-interfaces-systemd.nix | 20 | ||||
-rw-r--r-- | nixos/modules/tasks/network-interfaces.nix | 69 | ||||
-rw-r--r-- | nixos/tests/networking.nix | 46 |
7 files changed, 211 insertions, 1 deletions
diff --git a/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml index 73baf71f5ef..c0f407e11a9 100644 --- a/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml +++ b/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml @@ -1535,6 +1535,19 @@ Superuser created successfully. release notes</link> for changes and upgrade instructions. </para> </listitem> + <listitem> + <para> + The <literal>systemd.network</literal> module has gained + support for the FooOverUDP link type. + </para> + </listitem> + <listitem> + <para> + The <literal>networking</literal> module has a new + <literal>networking.fooOverUDP</literal> option to configure + Foo-over-UDP encapsulations. + </para> + </listitem> </itemizedlist> </section> </section> diff --git a/nixos/doc/manual/release-notes/rl-2111.section.md b/nixos/doc/manual/release-notes/rl-2111.section.md index b7fa2cf0f25..6dadcde3ccc 100644 --- a/nixos/doc/manual/release-notes/rl-2111.section.md +++ b/nixos/doc/manual/release-notes/rl-2111.section.md @@ -443,3 +443,7 @@ In addition to numerous new and upgraded packages, this release has the followin - Three new options, [xdg.mime.addedAssociations](#opt-xdg.mime.addedAssociations), [xdg.mime.defaultApplications](#opt-xdg.mime.defaultApplications), and [xdg.mime.removedAssociations](#opt-xdg.mime.removedAssociations) have been added to the [xdg.mime](#opt-xdg.mime.enable) module to allow the configuration of `/etc/xdg/mimeapps.list`. - Kopia was upgraded from 0.8.x to 0.9.x. Please read the [upstream release notes](https://github.com/kopia/kopia/releases/tag/v0.9.0) for changes and upgrade instructions. + +- The `systemd.network` module has gained support for the FooOverUDP link type. + +- The `networking` module has a new `networking.fooOverUDP` option to configure Foo-over-UDP encapsulations. diff --git a/nixos/modules/system/boot/networkd.nix b/nixos/modules/system/boot/networkd.nix index 51e105bf627..662dfe2db98 100644 --- a/nixos/modules/system/boot/networkd.nix +++ b/nixos/modules/system/boot/networkd.nix @@ -250,6 +250,16 @@ let (assertRange "ERSPANIndex" 1 1048575) ]; + sectionFooOverUDP = checkUnitConfig "FooOverUDP" [ + (assertOnlyFields [ + "Port" + "Encapsulation" + "Protocol" + ]) + (assertPort "Port") + (assertValueOneOf "Encapsulation" ["FooOverUDP" "GenericUDPEncapsulation"]) + ]; + sectionPeer = checkUnitConfig "Peer" [ (assertOnlyFields [ "Name" @@ -919,6 +929,18 @@ let ''; }; + fooOverUDPConfig = mkOption { + default = { }; + example = { Port = 9001; }; + type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionFooOverUDP; + description = '' + Each attribute in this set specifies an option in the + <literal>[FooOverUDP]</literal> section of the unit. See + <citerefentry><refentrytitle>systemd.netdev</refentrytitle> + <manvolnum>5</manvolnum></citerefentry> for details. + ''; + }; + peerConfig = mkOption { default = {}; example = { Name = "veth2"; }; @@ -1449,6 +1471,10 @@ let [Tunnel] ${attrsToSection def.tunnelConfig} '' + + optionalString (def.fooOverUDPConfig != { }) '' + [FooOverUDP] + ${attrsToSection def.fooOverUDPConfig} + '' + optionalString (def.peerConfig != { }) '' [Peer] ${attrsToSection def.peerConfig} diff --git a/nixos/modules/tasks/network-interfaces-scripted.nix b/nixos/modules/tasks/network-interfaces-scripted.nix index 79624ec7072..055580e3ea2 100644 --- a/nixos/modules/tasks/network-interfaces-scripted.nix +++ b/nixos/modules/tasks/network-interfaces-scripted.nix @@ -466,6 +466,39 @@ let ''; }); + createFouEncapsulation = n: v: nameValuePair "${n}-fou-encap" + (let + # if we have a device to bind to we can wait for its addresses to be + # configured, otherwise external sequencing is required. + deps = optionals (v.local != null && v.local.dev != null) + (deviceDependency v.local.dev ++ [ "network-addresses-${v.local.dev}.service" ]); + fouSpec = "port ${toString v.port} ${ + if v.protocol != null then "ipproto ${toString v.protocol}" else "gue" + } ${ + optionalString (v.local != null) "local ${escapeShellArg v.local.address} ${ + optionalString (v.local.dev != null) "dev ${escapeShellArg v.local.dev}" + }" + }"; + in + { description = "FOU endpoint ${n}"; + wantedBy = [ "network-setup.service" (subsystemDevice n) ]; + bindsTo = deps; + partOf = [ "network-setup.service" ]; + after = [ "network-pre.target" ] ++ deps; + before = [ "network-setup.service" ]; + serviceConfig.Type = "oneshot"; + serviceConfig.RemainAfterExit = true; + path = [ pkgs.iproute2 ]; + script = '' + # always remove previous incarnation since show can't filter + ip fou del ${fouSpec} >/dev/null 2>&1 || true + ip fou add ${fouSpec} + ''; + postStop = '' + ip fou del ${fouSpec} || true + ''; + }); + createSitDevice = n: v: nameValuePair "${n}-netdev" (let deps = deviceDependency v.dev; @@ -530,6 +563,7 @@ let // mapAttrs' createVswitchDevice cfg.vswitches // mapAttrs' createBondDevice cfg.bonds // mapAttrs' createMacvlanDevice cfg.macvlans + // mapAttrs' createFouEncapsulation cfg.fooOverUDP // mapAttrs' createSitDevice cfg.sits // mapAttrs' createVlanDevice cfg.vlans // { diff --git a/nixos/modules/tasks/network-interfaces-systemd.nix b/nixos/modules/tasks/network-interfaces-systemd.nix index 225f9dc67fc..516764b87db 100644 --- a/nixos/modules/tasks/network-interfaces-systemd.nix +++ b/nixos/modules/tasks/network-interfaces-systemd.nix @@ -47,6 +47,9 @@ in } ] ++ flip mapAttrsToList cfg.bridges (n: { rstp, ... }: { assertion = !rstp; message = "networking.bridges.${n}.rstp is not supported by networkd."; + }) ++ flip mapAttrsToList cfg.fooOverUDP (n: { local, ... }: { + assertion = local == null; + message = "networking.fooOverUDP.${n}.local is not supported by networkd."; }); networking.dhcpcd.enable = mkDefault false; @@ -194,6 +197,23 @@ in macvlan = [ name ]; } ]); }))) + (mkMerge (flip mapAttrsToList cfg.fooOverUDP (name: fou: { + netdevs."40-${name}" = { + netdevConfig = { + Name = name; + Kind = "fou"; + }; + # unfortunately networkd cannot encode dependencies of netdevs on addresses/routes, + # so we cannot specify Local=, Peer=, PeerPort=. this looks like a missing feature + # in networkd. + fooOverUDPConfig = { + Port = fou.port; + Encapsulation = if fou.protocol != null then "FooOverUDP" else "GenericUDPEncapsulation"; + } // (optionalAttrs (fou.protocol != null) { + Protocol = fou.protocol; + }); + }; + }))) (mkMerge (flip mapAttrsToList cfg.sits (name: sit: { netdevs."40-${name}" = { netdevConfig = { diff --git a/nixos/modules/tasks/network-interfaces.nix b/nixos/modules/tasks/network-interfaces.nix index 313b0fac7da..a3b41326168 100644 --- a/nixos/modules/tasks/network-interfaces.nix +++ b/nixos/modules/tasks/network-interfaces.nix @@ -10,6 +10,7 @@ let hasVirtuals = any (i: i.virtual) interfaces; hasSits = cfg.sits != { }; hasBonds = cfg.bonds != { }; + hasFous = cfg.fooOverUDP != { }; slaves = concatMap (i: i.interfaces) (attrValues cfg.bonds) ++ concatMap (i: i.interfaces) (attrValues cfg.bridges) @@ -823,6 +824,71 @@ in }); }; + networking.fooOverUDP = mkOption { + default = { }; + example = + { + primary = { port = 9001; local = { address = "192.0.2.1"; dev = "eth0"; }; }; + backup = { port = 9002; }; + }; + description = '' + This option allows you to configure Foo Over UDP and Generic UDP Encapsulation + endpoints. See <citerefentry><refentrytitle>ip-fou</refentrytitle> + <manvolnum>8</manvolnum></citerefentry> for details. + ''; + type = with types; attrsOf (submodule { + options = { + port = mkOption { + type = port; + description = '' + Local port of the encapsulation UDP socket. + ''; + }; + + protocol = mkOption { + type = nullOr (ints.between 1 255); + default = null; + description = '' + Protocol number of the encapsulated packets. Specifying <literal>null</literal> + (the default) creates a GUE endpoint, specifying a protocol number will create + a FOU endpoint. + ''; + }; + + local = mkOption { + type = nullOr (submodule { + options = { + address = mkOption { + type = types.str; + description = '' + Local address to bind to. The address must be available when the FOU + endpoint is created, using the scripted network setup this can be achieved + either by setting <literal>dev</literal> or adding dependency information to + <literal>systemd.services.<name>-fou-encap</literal>; it isn't supported + when using networkd. + ''; + }; + + dev = mkOption { + type = nullOr str; + default = null; + example = "eth0"; + description = '' + Network device to bind to. + ''; + }; + }; + }); + default = null; + example = { address = "203.0.113.22"; }; + description = '' + Local address (and optionally device) to bind to using the given port. + ''; + }; + }; + }); + }; + networking.sits = mkOption { default = { }; example = literalExpression '' @@ -1116,7 +1182,8 @@ in boot.kernelModules = [ ] ++ optional hasVirtuals "tun" ++ optional hasSits "sit" - ++ optional hasBonds "bonding"; + ++ optional hasBonds "bonding" + ++ optional hasFous "fou"; boot.extraModprobeConfig = # This setting is intentional as it prevents default bond devices diff --git a/nixos/tests/networking.nix b/nixos/tests/networking.nix index 8b947ddf0cf..fdcf67f1126 100644 --- a/nixos/tests/networking.nix +++ b/nixos/tests/networking.nix @@ -380,6 +380,52 @@ let router.wait_until_succeeds("ping -c 1 192.168.1.3") ''; }; + fou = { + name = "foo-over-udp"; + nodes.machine = { ... }: { + virtualisation.vlans = [ 1 ]; + networking = { + useNetworkd = networkd; + useDHCP = false; + interfaces.eth1.ipv4.addresses = mkOverride 0 + [ { address = "192.168.1.1"; prefixLength = 24; } ]; + fooOverUDP = { + fou1 = { port = 9001; }; + fou2 = { port = 9002; protocol = 41; }; + fou3 = mkIf (!networkd) + { port = 9003; local.address = "192.168.1.1"; }; + fou4 = mkIf (!networkd) + { port = 9004; local = { address = "192.168.1.1"; dev = "eth1"; }; }; + }; + }; + systemd.services = { + fou3-fou-encap.after = optional (!networkd) "network-addresses-eth1.service"; + }; + }; + testScript = { ... }: + '' + import json + + machine.wait_for_unit("network.target") + fous = json.loads(machine.succeed("ip -json fou show")) + assert {"port": 9001, "gue": None, "family": "inet"} in fous, "fou1 exists" + assert {"port": 9002, "ipproto": 41, "family": "inet"} in fous, "fou2 exists" + '' + optionalString (!networkd) '' + assert { + "port": 9003, + "gue": None, + "family": "inet", + "local": "192.168.1.1", + } in fous, "fou3 exists" + assert { + "port": 9004, + "gue": None, + "family": "inet", + "local": "192.168.1.1", + "dev": "eth1", + } in fous, "fou4 exists" + ''; + }; sit = let node = { address4, remote, address6 }: { pkgs, ... }: with pkgs.lib; { virtualisation.vlans = [ 1 ]; |