128 lines
4 KiB
Nix
128 lines
4 KiB
Nix
{
|
|
config,
|
|
lib,
|
|
pkgs,
|
|
...
|
|
}:
|
|
with lib;
|
|
let
|
|
allNetns = config.networking.netns;
|
|
allExtraVeths = flatten (mapAttrsToList (_name: cfg: cfg.extraVeths) allNetns);
|
|
in
|
|
{
|
|
options.networking.netns = mkOption {
|
|
type = types.attrsOf (
|
|
types.submodule (
|
|
{ name, ... }:
|
|
{
|
|
options.extraVeths = mkOption {
|
|
type = types.listOf (
|
|
types.submodule (
|
|
{ config, ... }:
|
|
{
|
|
options = {
|
|
sourceNetns = mkOption {
|
|
type = types.str;
|
|
default = name;
|
|
readOnly = true;
|
|
description = ''
|
|
The current network namespace.
|
|
'';
|
|
};
|
|
targetNetns = mkOption {
|
|
type = types.str;
|
|
description = ''
|
|
The network namespace to connect to.
|
|
'';
|
|
};
|
|
sourceInterface = mkOption {
|
|
type = types.str;
|
|
default = if config.targetNetns == "default" then "host" else config.targetNetns;
|
|
description = ''
|
|
The interface name in the current network namespace;
|
|
'';
|
|
};
|
|
targetInterface = mkOption {
|
|
type = types.str;
|
|
default = if config.sourceNetns == "default" then "host" else config.sourceNetns;
|
|
description = ''
|
|
The interface name in the other network namespace;
|
|
'';
|
|
};
|
|
};
|
|
}
|
|
)
|
|
);
|
|
default = [ ];
|
|
description = ''
|
|
Extra veth-pairs to be created for enabling link-scope connectivity
|
|
between inter-network namespaces.
|
|
Note that a veth-pair only needs to be defined on one end.
|
|
'';
|
|
};
|
|
}
|
|
)
|
|
);
|
|
};
|
|
|
|
config = {
|
|
systemd.services = listToAttrs (
|
|
map (
|
|
ev:
|
|
let
|
|
inherit (ev)
|
|
sourceNetns
|
|
targetNetns
|
|
sourceInterface
|
|
targetInterface
|
|
;
|
|
sourceNetnsPath = config.networking.netns.${sourceNetns}.netnsPath;
|
|
targetNetnsPath = config.networking.netns.${targetNetns}.netnsPath;
|
|
serviceDeps = map (ns: "netns-${ns}.service") (
|
|
filter (ns: ns != "default") [
|
|
sourceNetns
|
|
targetNetns
|
|
]
|
|
);
|
|
mkSetup =
|
|
netns: _netnsPath: interface:
|
|
if netns == "default" then
|
|
"ip link set ${interface} up"
|
|
else
|
|
"ip -n ${netns} link set ${interface} up";
|
|
mkDrop =
|
|
netns: _netnsPath: interface:
|
|
if netns == "default" then "ip link del ${interface}" else "ip -n ${netns} link del ${interface}";
|
|
in
|
|
nameValuePair "netns-extra-veth-1-${sourceNetns}-${targetNetns}" {
|
|
path = with pkgs; [
|
|
coreutils
|
|
iproute2
|
|
procps
|
|
];
|
|
script = ''
|
|
ip link add ${sourceInterface} mtu 1400 address 02:00:00:00:00:01 netns ${sourceNetnsPath} type veth \
|
|
peer ${targetInterface} mtu 1400 address 02:00:00:00:00:00 netns ${targetNetnsPath}
|
|
${mkSetup sourceNetns sourceNetnsPath sourceInterface}
|
|
${mkSetup targetNetns targetNetnsPath targetInterface}
|
|
'';
|
|
preStop = ''
|
|
${mkDrop sourceNetns sourceNetnsPath sourceInterface}
|
|
'';
|
|
serviceConfig = {
|
|
Type = "oneshot";
|
|
RemainAfterExit = true;
|
|
};
|
|
after = [
|
|
"network.target"
|
|
] ++ serviceDeps;
|
|
partOf = serviceDeps;
|
|
wantedBy = [
|
|
"multi-user.target"
|
|
] ++ serviceDeps;
|
|
}
|
|
) allExtraVeths
|
|
);
|
|
};
|
|
}
|