nixos/networking: support FOU encapsulation for sits

pennae c1f51554 f29ea2d1

Changed files
+89 -6
nixos
+6
nixos/doc/manual/from_md/release-notes/rl-2111.section.xml
···
Foo-over-UDP encapsulations.
</para>
</listitem>
+
<listitem>
+
<para>
+
<literal>networking.sits</literal> now supports Foo-over-UDP
+
encapsulation.
+
</para>
+
</listitem>
</itemizedlist>
</section>
</section>
+2
nixos/doc/manual/release-notes/rl-2111.section.md
···
- 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.
+
+
- `networking.sits` now supports Foo-over-UDP encapsulation.
+6 -1
nixos/modules/tasks/network-interfaces-scripted.nix
···
${optionalString (v.remote != null) "remote \"${v.remote}\""} \
${optionalString (v.local != null) "local \"${v.local}\""} \
${optionalString (v.ttl != null) "ttl ${toString v.ttl}"} \
-
${optionalString (v.dev != null) "dev \"${v.dev}\""}
+
${optionalString (v.dev != null) "dev \"${v.dev}\""} \
+
${optionalString (v.encapsulation != null)
+
"encap ${v.encapsulation.type} encap-dport ${toString v.encapsulation.port} ${
+
optionalString (v.encapsulation.sourcePort != null)
+
"encap-sport ${toString v.encapsulation.sourcePort}"
+
}"}
ip link set "${n}" up
'';
postStop = ''
+11 -1
nixos/modules/tasks/network-interfaces-systemd.nix
···
Local = sit.local;
}) // (optionalAttrs (sit.ttl != null) {
TTL = sit.ttl;
-
});
+
}) // (optionalAttrs (sit.encapsulation != null) (
+
{
+
FooOverUDP = true;
+
Encapsulation =
+
if sit.encapsulation.type == "fou"
+
then "FooOverUDP"
+
else "GenericUDPEncapsulation";
+
FOUDestinationPort = sit.encapsulation.port;
+
} // (optionalAttrs (sit.encapsulation.sourcePort != null) {
+
FOUSourcePort = sit.encapsulation.sourcePort;
+
})));
};
networks = mkIf (sit.dev != null) {
"40-${sit.dev}" = (mkMerge [ (genericNetwork (mkOverride 999)) {
+40 -1
nixos/modules/tasks/network-interfaces.nix
···
hasVirtuals = any (i: i.virtual) interfaces;
hasSits = cfg.sits != { };
hasBonds = cfg.bonds != { };
-
hasFous = cfg.fooOverUDP != { };
+
hasFous = cfg.fooOverUDP != { }
+
|| filterAttrs (_: s: s.encapsulation != null) cfg.sits != { };
slaves = concatMap (i: i.interfaces) (attrValues cfg.bonds)
++ concatMap (i: i.interfaces) (attrValues cfg.bridges)
···
example = "enp4s0f0";
description = ''
The underlying network device on which the tunnel resides.
+
'';
+
};
+
+
encapsulation = with types; mkOption {
+
type = nullOr (submodule {
+
options = {
+
type = mkOption {
+
type = enum [ "fou" "gue" ];
+
description = ''
+
Selects encapsulation type. See
+
<citerefentry><refentrytitle>ip-link</refentrytitle>
+
<manvolnum>8</manvolnum></citerefentry> for details.
+
'';
+
};
+
+
port = mkOption {
+
type = port;
+
example = 9001;
+
description = ''
+
Destination port for encapsulated packets.
+
'';
+
};
+
+
sourcePort = mkOption {
+
type = nullOr types.port;
+
default = null;
+
example = 9002;
+
description = ''
+
Source port for encapsulated packets. Will be chosen automatically by
+
the kernel if unset.
+
'';
+
};
+
};
+
});
+
default = null;
+
example = { type = "fou"; port = 9001; };
+
description = ''
+
Configures encapsulation in UDP packets.
'';
};
+24 -3
nixos/tests/networking.nix
···
virtualisation.vlans = [ 1 ];
networking = {
useNetworkd = networkd;
-
firewall.enable = false;
useDHCP = false;
sits.sit = {
inherit remote;
···
};
in {
name = "Sit";
-
nodes.client1 = node { address4 = "192.168.1.1"; remote = "192.168.1.2"; address6 = "fc00::1"; };
-
nodes.client2 = node { address4 = "192.168.1.2"; remote = "192.168.1.1"; address6 = "fc00::2"; };
+
# note on firewalling: the two nodes are explicitly asymmetric.
+
# client1 sends SIT packets in UDP, but accepts only proto-41 incoming.
+
# client2 does the reverse, sending in proto-41 and accepting only UDP incoming.
+
# that way we'll notice when either SIT itself or FOU breaks.
+
nodes.client1 = args@{ pkgs, ... }:
+
mkMerge [
+
(node { address4 = "192.168.1.1"; remote = "192.168.1.2"; address6 = "fc00::1"; } args)
+
{
+
networking = {
+
firewall.extraCommands = "iptables -A INPUT -p 41 -j ACCEPT";
+
sits.sit.encapsulation = { type = "fou"; port = 9001; };
+
};
+
}
+
];
+
nodes.client2 = args@{ pkgs, ... }:
+
mkMerge [
+
(node { address4 = "192.168.1.2"; remote = "192.168.1.1"; address6 = "fc00::2"; } args)
+
{
+
networking = {
+
firewall.allowedUDPPorts = [ 9001 ];
+
fooOverUDP.fou1 = { port = 9001; protocol = 41; };
+
};
+
}
+
];
testScript = { ... }:
''
start_all()