vxlan-organiser/vm/vm.nix
catvayor e07c904c56
feat: use kea for dhcp
include a patch of kea
2025-02-23 21:45:57 +01:00

398 lines
11 KiB
Nix

{
pkgs,
lib,
...
}:
let
inherit (lib)
imap
flatten
listToAttrs
unique
;
access-topology = [
[
1000
1001
1002
1003
]
[
1000
1001
1002
1003
]
];
vni-list = unique <| flatten access-topology;
br_name = sw: vni: "sw${toString sw}-vni${toString vni}";
client_name = sw: vni: "h-${br_name sw vni}";
vtep_name = sw: vni: "v-${toString sw}-${toString vni}";
sw_name = sw: "sw${toString sw}";
router_vtep_name = vni: "rv-${toString vni}";
vtep_br_name = sw: vni: "br${vtep_name sw vni}";
vtep_vxlan_name = sw: vni: "x${vtep_name sw vni}";
clients =
listToAttrs
<| flatten
<| imap (
sw:
map (vni: {
name = client_name sw vni;
value = {
privateNetwork = true;
ephemeral = true;
hostBridge = br_name sw vni;
autoStart = true;
config = {
imports = [ ./common.nix ];
networking.hostName = client_name sw vni;
services.resolved.enable = false;
systemd.network.networks = {
"10-eth0" = {
name = "eth0";
linkConfig.Promiscuous = true;
DHCP = "ipv4";
};
};
};
};
})
) access-topology;
switchs =
listToAttrs
<| imap (sw: vnis: {
name = sw_name sw;
value = {
privateNetwork = true;
ephemeral = true;
hostBridge = "br0";
autoStart = true;
extraVeths =
listToAttrs
<| map (vni: {
name = vtep_name sw vni;
value.hostBridge = br_name sw vni;
}) vnis;
config = {
imports = [ ./common.nix ];
networking.hostName = sw_name sw;
services.resolved.enable = false;
systemd.network = {
networks =
{
"10-eth0" = {
name = "eth0";
address = [ "10.0.255.${toString (sw + 1)}/24" ];
networkConfig.VXLAN = map (vtep_vxlan_name sw) vnis;
linkConfig.Promiscuous = true;
};
}
// listToAttrs (
flatten
<| map (vni: [
{
name = "10-${vtep_name sw vni}";
value = {
name = vtep_name sw vni;
linkConfig.Promiscuous = true;
networkConfig = {
Bridge = vtep_br_name sw vni;
LinkLocalAddressing = false;
LLDP = false;
EmitLLDP = false;
IPv6AcceptRA = false;
IPv6SendRA = false;
};
};
}
{
name = "10-${vtep_br_name sw vni}";
value = {
name = vtep_br_name sw vni;
linkConfig.Promiscuous = true;
networkConfig = {
LinkLocalAddressing = false;
LLDP = false;
EmitLLDP = false;
IPv6AcceptRA = false;
IPv6SendRA = false;
};
};
}
{
name = "10-${vtep_vxlan_name sw vni}";
value = {
name = vtep_vxlan_name sw vni;
linkConfig.Promiscuous = true;
networkConfig = {
Bridge = vtep_br_name sw vni;
LinkLocalAddressing = false;
LLDP = false;
EmitLLDP = false;
IPv6AcceptRA = false;
IPv6SendRA = false;
};
};
}
]) vnis
);
netdevs = listToAttrs (
flatten
<| map (vni: [
{
name = "10-${vtep_br_name sw vni}";
value = {
netdevConfig = {
Name = vtep_br_name sw vni;
Kind = "bridge";
};
bridgeConfig.STP = false;
};
}
{
name = "10-${vtep_vxlan_name sw vni}";
value = {
netdevConfig = {
Name = vtep_vxlan_name sw vni;
Kind = "vxlan";
};
vxlanConfig = {
VNI = vni;
Local = "10.0.255.${toString (sw + 1)}";
DestinationPort = 4789;
Group = "239.0.0.1";
};
};
}
]) vnis
);
};
};
};
}) access-topology;
in
{
virtualisation = {
memorySize = 4 * 1024;
cores = 4;
diskImage = null;
forwardPorts = [
{
from = "host";
host.port = 2222;
guest.port = 22;
}
];
};
nixos-shell.mounts = {
mountHome = false;
extraMounts."/vxlan" = {
target = ./..;
cache = "none";
};
};
imports = [ ./common.nix ];
services.openssh = {
enable = true;
settings.PermitRootLogin = "yes";
};
environment.defaultPackages = [
pkgs.pwru
];
containers =
{
"router" = {
privateNetwork = true;
ephemeral = true;
hostBridge = "br0";
bindMounts."/vxlan".hostPath = "/vxlan";
autoStart = true;
config = {
imports = [ ./common.nix ];
nixpkgs.overlays = [
(_: super: {
kea = super.kea.overrideAttrs (o: {
patches = o.patches ++ [ ./0001-fix-multiple-interface-with-same-IP.patch ];
});
})
];
services = {
resolved.enable = false;
kea.dhcp4 = {
enable = true;
settings = {
interfaces-config = {
interfaces = [ "*" ];
dhcp-socket-type = "raw";
outbound-interface = "same-as-inbound";
service-sockets-require-all = true;
};
lease-database = {
name = "/var/lib/kea/dhcp4.leases";
persist = true;
type = "memfile";
};
valid-lifetime = 3600;
rebind-timer = 1800;
renew-timer = 900;
subnet4 = [
{
id = 1;
pools = [
{
pool = "10.0.0.32 - 10.0.254.255";
}
];
subnet = "10.0.0.0/16";
}
];
hooks-libraries = [
{
library = "${pkgs.kea}/lib/kea/hooks/libdhcp_run_script.so";
parameters = {
name = pkgs.writeShellScript "hook.sh" ''
echo $1 $QUERY4_IFACE_NAME >> /var/lib/kea/scriptlog
'';
sync = false;
};
}
];
};
};
};
systemd.network =
let
vtep-network =
listToAttrs
<| map (vni: {
name = "10-${router_vtep_name vni}";
value = {
name = router_vtep_name vni;
addresses = [
{
Address = "10.0.0.1/16";
AddPrefixRoute = false;
}
];
linkConfig.Promiscuous = true;
# networkConfig = {
# Bridge = "rbr0";
# LinkLocalAddressing = false;
# LLDP = false;
# EmitLLDP = false;
# IPv6AcceptRA = false;
# IPv6SendRA = false;
# };
# bridgeConfig.Isolated = true;
};
}) vni-list;
vtep-netdevs =
listToAttrs
<| map (vni: {
name = "10-${router_vtep_name vni}";
value = {
netdevConfig = {
Name = router_vtep_name vni;
Kind = "vxlan";
};
vxlanConfig = {
VNI = vni;
Local = "10.0.255.1";
DestinationPort = 4789;
Group = "239.0.0.1";
};
};
}) vni-list;
in
{
networks = {
"10-eth0" = {
name = "eth0";
address = [ "10.0.255.1/24" ];
networkConfig.VXLAN = map router_vtep_name vni-list;
};
# "10-rbr0" = {
# name = "rbr0";
# address = [ "10.0.0.1/16" ];
# };
} // vtep-network;
netdevs = {
# "10-rbr0" = {
# netdevConfig = {
# Name = "rbr0";
# Kind = "bridge";
# };
# };
} // vtep-netdevs;
};
};
};
}
// switchs
// clients;
systemd.network =
let
brs = [ "br0" ] ++ flatten (imap (sw: map (br_name sw)) access-topology);
in
{
networks =
listToAttrs
<|
map (name: {
name = "10-${name}";
value = {
inherit name;
linkConfig.Promiscuous = true;
networkConfig = {
LinkLocalAddressing = false;
LLDP = false;
EmitLLDP = false;
IPv6AcceptRA = false;
IPv6SendRA = false;
};
};
}) brs
++ flatten (
imap (
sw:
map (vni: {
name = "10-${vtep_name sw vni}";
value = {
name = vtep_name sw vni;
linkConfig.Promiscuous = true;
networkConfig = {
LinkLocalAddressing = false;
LLDP = false;
EmitLLDP = false;
IPv6AcceptRA = false;
IPv6SendRA = false;
};
};
})
) access-topology
);
netdevs =
listToAttrs
<| map (name: {
name = "10-${name}";
value = {
netdevConfig = {
Name = name;
Kind = "bridge";
};
bridgeConfig.STP = false;
};
}) brs;
};
}