nixos/networking: support FOU encapsulation for sits

This commit is contained in:
pennae 2021-08-11 12:48:43 +02:00 committed by tomberek
parent f29ea2d15d
commit c1f5155471
6 changed files with 89 additions and 6 deletions

View file

@ -1548,6 +1548,12 @@ Superuser created successfully.
Foo-over-UDP encapsulations.
</para>
</listitem>
<listitem>
<para>
<literal>networking.sits</literal> now supports Foo-over-UDP
encapsulation.
</para>
</listitem>
</itemizedlist>
</section>
</section>

View file

@ -447,3 +447,5 @@ In addition to numerous new and upgraded packages, this release has the followin
- 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.

View file

@ -519,7 +519,12 @@ let
${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 = ''

View file

@ -227,7 +227,17 @@ in
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)) {

View file

@ -10,7 +10,8 @@ let
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)
@ -948,6 +949,44 @@ in
'';
};
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.
'';
};
};
});

View file

@ -431,7 +431,6 @@ let
virtualisation.vlans = [ 1 ];
networking = {
useNetworkd = networkd;
firewall.enable = false;
useDHCP = false;
sits.sit = {
inherit remote;
@ -446,8 +445,30 @@ let
};
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()