nixos/network-interfaces: Add iplvan support
This commit is contained in:
@@ -189,6 +189,8 @@ See <https://github.com/NixOS/nixpkgs/issues/481673>.
|
||||
|
||||
- `services.openssh` now supports generating host SSH keys by setting `services.openssh.generateHostKeys = true` while leaving `services.openssh.enable` disabled. This is particularly useful for systems that have no need of an SSH daemon but want SSH host keys for other purposes such as using agenix or sops-nix.
|
||||
|
||||
- IPVLAN interfaces can now be configured through the `networking.ipvlans` option in the networking module.
|
||||
|
||||
- `services.caddy` now supports setting `httpPort` and `httpsPort` and opening them in the firewall via `openFirewall`.
|
||||
|
||||
- The latest available version of Nextcloud is v33 (available as `pkgs.nextcloud33`). The installation logic is as follows:
|
||||
|
||||
@@ -153,6 +153,9 @@ in
|
||||
+ optionalString (def.macvlan != [ ]) ''
|
||||
${concatStringsSep "\n" (map (s: "MACVLAN=${s}") def.macvlan)}
|
||||
''
|
||||
+ optionalString (def.ipvlan != [ ]) ''
|
||||
${concatStringsSep "\n" (map (s: "IPVLAN=${s}") def.ipvlan)}
|
||||
''
|
||||
+ optionalString (def.macvtap != [ ]) ''
|
||||
${concatStringsSep "\n" (map (s: "MACVTAP=${s}") def.macvtap)}
|
||||
''
|
||||
|
||||
@@ -3037,6 +3037,15 @@ let
|
||||
'';
|
||||
};
|
||||
|
||||
ipvlan = mkOption {
|
||||
default = [ ];
|
||||
type = types.listOf types.str;
|
||||
description = ''
|
||||
A list of ipvlan interfaces to be added to the network section of the
|
||||
unit. See {manpage}`systemd.network(5)` for details.
|
||||
'';
|
||||
};
|
||||
|
||||
macvtap = mkOption {
|
||||
default = [ ];
|
||||
type = types.listOf types.str;
|
||||
|
||||
@@ -21,6 +21,7 @@ let
|
||||
attrValues cfg.vswitches
|
||||
)
|
||||
++ concatMap (i: [ i.interface ]) (attrValues cfg.macvlans)
|
||||
++ concatMap (i: [ i.interface ]) (attrValues cfg.ipvlans)
|
||||
++ concatMap (i: [ i.interface ]) (attrValues cfg.vlans);
|
||||
|
||||
# We must escape interfaces due to the systemd interpretation
|
||||
@@ -106,6 +107,7 @@ let
|
||||
|| (hasAttr dev cfg.bridges)
|
||||
|| (hasAttr dev cfg.bonds)
|
||||
|| (hasAttr dev cfg.macvlans)
|
||||
|| (hasAttr dev cfg.ipvlans)
|
||||
|| (hasAttr dev cfg.sits)
|
||||
|| (hasAttr dev cfg.ipips)
|
||||
|| (hasAttr dev cfg.vlans)
|
||||
@@ -590,6 +592,39 @@ let
|
||||
}
|
||||
);
|
||||
|
||||
createIpvlanDevice =
|
||||
n: v:
|
||||
nameValuePair "${n}-netdev" (
|
||||
let
|
||||
deps = deviceDependency v.interface;
|
||||
in
|
||||
{
|
||||
description = "IPVLAN Interface ${n}";
|
||||
wantedBy = [
|
||||
"network.target"
|
||||
"network-setup.service"
|
||||
(subsystemDevice n)
|
||||
];
|
||||
bindsTo = deps;
|
||||
after = [ "network-pre.target" ] ++ deps;
|
||||
before = [ "network-setup.service" ];
|
||||
serviceConfig.Type = "oneshot";
|
||||
serviceConfig.RemainAfterExit = true;
|
||||
path = [ pkgs.iproute2 ];
|
||||
script = ''
|
||||
# Remove Dead Interfaces
|
||||
ip link show dev "${n}" >/dev/null 2>&1 && ip link delete dev "${n}"
|
||||
ip link add link "${v.interface}" name "${n}" type ipvlan \
|
||||
${optionalString (v.mode != null) "mode ${v.mode}"} \
|
||||
${optionalString (v.flags != null) "${v.flags}"}
|
||||
ip link set dev "${n}" up
|
||||
'';
|
||||
postStop = ''
|
||||
ip link delete dev "${n}" || true
|
||||
'';
|
||||
}
|
||||
);
|
||||
|
||||
createFouEncapsulation =
|
||||
n: v:
|
||||
nameValuePair "${n}-fou-encap" (
|
||||
@@ -803,6 +838,7 @@ let
|
||||
// mapAttrs' createVswitchDevice cfg.vswitches
|
||||
// mapAttrs' createBondDevice cfg.bonds
|
||||
// mapAttrs' createMacvlanDevice cfg.macvlans
|
||||
// mapAttrs' createIpvlanDevice cfg.ipvlans
|
||||
// mapAttrs' createFouEncapsulation cfg.fooOverUDP
|
||||
// mapAttrs' createSitDevice cfg.sits
|
||||
// mapAttrs' createIpipDevice cfg.ipips
|
||||
|
||||
@@ -396,6 +396,24 @@ in
|
||||
}
|
||||
)
|
||||
))
|
||||
(mkMerge (
|
||||
flip mapAttrsToList cfg.ipvlans (
|
||||
name: ipvlan: {
|
||||
netdevs."40-${name}" = {
|
||||
netdevConfig = {
|
||||
Name = name;
|
||||
Kind = "ipvlan";
|
||||
};
|
||||
ipvlanConfig =
|
||||
optionalAttrs (ipvlan.mode != null) { Mode = lib.toUpper ipvlan.mode; }
|
||||
// optionalAttrs (ipvlan.flags != null) { Flags = ipvlan.flags; };
|
||||
};
|
||||
networks."40-${ipvlan.interface}" = {
|
||||
ipvlan = [ name ];
|
||||
};
|
||||
}
|
||||
)
|
||||
))
|
||||
(mkMerge (
|
||||
flip mapAttrsToList cfg.fooOverUDP (
|
||||
name: fou: {
|
||||
|
||||
@@ -1069,6 +1069,54 @@ in
|
||||
});
|
||||
};
|
||||
|
||||
networking.ipvlans = mkOption {
|
||||
default = { };
|
||||
example = literalExpression ''
|
||||
{
|
||||
wan = {
|
||||
interface = "enp2s0";
|
||||
mode = "l2";
|
||||
flags = "vepa";
|
||||
};
|
||||
}
|
||||
'';
|
||||
description = ''
|
||||
This option allows you to define ipvlan interfaces which should
|
||||
be automatically created.
|
||||
'';
|
||||
type =
|
||||
with types;
|
||||
attrsOf (submodule {
|
||||
options = {
|
||||
|
||||
interface = mkOption {
|
||||
example = "enp4s0";
|
||||
type = types.str;
|
||||
description = "The interface the ipvlan will transmit packets through.";
|
||||
};
|
||||
|
||||
mode = mkOption {
|
||||
default = "l2";
|
||||
type = types.enum [
|
||||
"l2"
|
||||
"l3"
|
||||
"l3s"
|
||||
];
|
||||
description = "The mode of the interface.";
|
||||
};
|
||||
|
||||
flags = mkOption {
|
||||
default = null;
|
||||
type = types.nullOr types.str;
|
||||
example = "vepa";
|
||||
description = "The flags of the ipvlan device.";
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
networking.fooOverUDP = mkOption {
|
||||
default = { };
|
||||
example = {
|
||||
|
||||
@@ -436,6 +436,38 @@ let
|
||||
router.wait_until_succeeds("ping -c 1 192.168.1.3")
|
||||
'';
|
||||
};
|
||||
ipvlan = {
|
||||
name = "IPVLAN";
|
||||
nodes.client = {
|
||||
virtualisation.interfaces.enp1s0.vlan = 1;
|
||||
networking = {
|
||||
useNetworkd = networkd;
|
||||
useDHCP = false;
|
||||
ipvlans = {
|
||||
ipvlan1.interface = "enp1s0";
|
||||
ipvlan2.interface = "enp1s0";
|
||||
};
|
||||
};
|
||||
};
|
||||
testScript = ''
|
||||
with subtest("Wait for networking to come up"):
|
||||
client.wait_for_unit("network.target")
|
||||
|
||||
with subtest("Can move IPVLANs to separate network namespaces"):
|
||||
client.succeed("ip netns add ns1 && ip link set dev ipvlan1 netns ns1")
|
||||
client.succeed("ip netns add ns2 && ip link set dev ipvlan2 netns ns2")
|
||||
|
||||
with subtest("Can configure the IPVLAN interfaces"):
|
||||
client.succeed("ip netns exec ns1 ip addr add 192.168.1.1/24 dev ipvlan1")
|
||||
client.succeed("ip netns exec ns2 ip addr add 192.168.1.2/24 dev ipvlan2")
|
||||
client.succeed("ip netns exec ns1 ip link set dev ipvlan1 up")
|
||||
client.succeed("ip netns exec ns2 ip link set dev ipvlan2 up")
|
||||
|
||||
with subtest("IPVLAN interfaces can ping each other"):
|
||||
client.succeed("ip netns exec ns1 ping -c 1 192.168.1.2")
|
||||
client.succeed("ip netns exec ns2 ping -c 1 192.168.1.1")
|
||||
'';
|
||||
};
|
||||
fou = {
|
||||
name = "foo-over-udp";
|
||||
nodes.machine = clientConfig {
|
||||
|
||||
Reference in New Issue
Block a user