2025-02-22 19:08:31 +01:00
|
|
|
{
|
|
|
|
pkgs,
|
|
|
|
lib,
|
|
|
|
...
|
|
|
|
}:
|
|
|
|
let
|
|
|
|
inherit (lib)
|
|
|
|
imap
|
|
|
|
flatten
|
|
|
|
listToAttrs
|
2025-02-23 11:45:05 +01:00
|
|
|
unique
|
2025-02-22 19:08:31 +01:00
|
|
|
;
|
|
|
|
access-topology = [
|
|
|
|
[
|
|
|
|
1000
|
|
|
|
1001
|
|
|
|
1002
|
|
|
|
1003
|
|
|
|
]
|
|
|
|
[
|
|
|
|
1000
|
|
|
|
1001
|
|
|
|
1002
|
|
|
|
1003
|
|
|
|
]
|
|
|
|
];
|
2025-02-23 21:45:57 +01:00
|
|
|
|
|
|
|
vni-list = unique <| flatten access-topology;
|
|
|
|
|
2025-02-22 19:08:31 +01:00
|
|
|
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}";
|
2025-02-23 11:45:05 +01:00
|
|
|
router_vtep_name = vni: "rv-${toString vni}";
|
2025-02-22 19:08:31 +01:00
|
|
|
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;
|
2025-02-23 21:45:57 +01:00
|
|
|
DHCP = "ipv4";
|
2025-02-22 19:08:31 +01:00
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
})
|
|
|
|
) 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";
|
2025-02-23 21:45:57 +01:00
|
|
|
address = [ "10.0.255.${toString (sw + 1)}/24" ];
|
2025-02-22 19:08:31 +01:00
|
|
|
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;
|
2025-02-23 21:45:57 +01:00
|
|
|
Local = "10.0.255.${toString (sw + 1)}";
|
2025-02-22 19:08:31 +01:00
|
|
|
DestinationPort = 4789;
|
2025-02-23 11:45:05 +01:00
|
|
|
Group = "239.0.0.1";
|
2025-02-22 19:08:31 +01:00
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|
|
|
|
]) 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 ];
|
2025-02-23 21:45:57 +01:00
|
|
|
nixpkgs.overlays = [
|
|
|
|
(_: super: {
|
|
|
|
kea = super.kea.overrideAttrs (o: {
|
|
|
|
patches = o.patches ++ [ ./0001-fix-multiple-interface-with-same-IP.patch ];
|
|
|
|
});
|
|
|
|
})
|
|
|
|
];
|
2025-02-25 17:38:01 +01:00
|
|
|
systemd.services.kea-dhcp4-server.serviceConfig = {
|
|
|
|
AmbientCapabilities = [ "CAP_NET_ADMIN" ];
|
|
|
|
CapabilityBoundingSet = [ "CAP_NET_ADMIN" ];
|
|
|
|
};
|
2025-02-23 21:45:57 +01:00
|
|
|
services = {
|
|
|
|
resolved.enable = false;
|
|
|
|
kea.dhcp4 = {
|
|
|
|
enable = true;
|
|
|
|
settings = {
|
|
|
|
interfaces-config = {
|
2025-02-25 17:38:01 +01:00
|
|
|
interfaces = map router_vtep_name vni-list;
|
2025-02-23 21:45:57 +01:00
|
|
|
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 = {
|
2025-02-25 17:38:01 +01:00
|
|
|
name = lib.getExe <| pkgs.writeShellApplication {
|
|
|
|
name = "hook.sh";
|
|
|
|
runtimeInputs = [ pkgs.busybox ];
|
|
|
|
text = ''
|
|
|
|
case "$1" in
|
|
|
|
"leases4_committed")
|
|
|
|
for i in $(seq 0 $((LEASES4_SIZE-1))); do
|
|
|
|
LEASE4_ADDRESS=$(eval "echo \$LEASES4_AT''${i}_ADDRESS")
|
|
|
|
ip r add dev "$QUERY4_IFACE_NAME" "$LEASE4_ADDRESS"
|
|
|
|
done
|
|
|
|
for i in $(seq 0 $((DELETED_LEASES4_SIZE-1))); do
|
|
|
|
LEASE4_ADDRESS=$(eval "echo \$DELETED_LEASES4_AT''${i}_ADDRESS")
|
|
|
|
ip r del dev "$QUERY4_IFACE_NAME" "$LEASE4_ADDRESS"
|
|
|
|
done
|
|
|
|
;;
|
|
|
|
*) echo "$1" unmanaged;;
|
|
|
|
esac
|
|
|
|
'';
|
|
|
|
};
|
2025-02-23 21:45:57 +01:00
|
|
|
sync = false;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
];
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
2025-02-23 11:45:05 +01:00
|
|
|
systemd.network =
|
|
|
|
let
|
|
|
|
vtep-network =
|
|
|
|
listToAttrs
|
|
|
|
<| map (vni: {
|
|
|
|
name = "10-${router_vtep_name vni}";
|
|
|
|
value = {
|
|
|
|
name = router_vtep_name vni;
|
2025-02-23 21:45:57 +01:00
|
|
|
addresses = [
|
|
|
|
{
|
|
|
|
Address = "10.0.0.1/16";
|
|
|
|
AddPrefixRoute = false;
|
|
|
|
}
|
|
|
|
];
|
2025-02-23 11:45:05 +01:00
|
|
|
linkConfig.Promiscuous = true;
|
2025-02-23 21:45:57 +01:00
|
|
|
# networkConfig = {
|
|
|
|
# Bridge = "rbr0";
|
2025-02-23 11:45:05 +01:00
|
|
|
|
2025-02-23 21:45:57 +01:00
|
|
|
# LinkLocalAddressing = false;
|
|
|
|
# LLDP = false;
|
|
|
|
# EmitLLDP = false;
|
|
|
|
# IPv6AcceptRA = false;
|
|
|
|
# IPv6SendRA = false;
|
|
|
|
# };
|
|
|
|
# bridgeConfig.Isolated = true;
|
2025-02-23 11:45:05 +01:00
|
|
|
};
|
|
|
|
}) 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;
|
2025-02-23 21:45:57 +01:00
|
|
|
Local = "10.0.255.1";
|
2025-02-23 11:45:05 +01:00
|
|
|
DestinationPort = 4789;
|
|
|
|
Group = "239.0.0.1";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}) vni-list;
|
|
|
|
in
|
|
|
|
{
|
|
|
|
networks = {
|
|
|
|
"10-eth0" = {
|
|
|
|
name = "eth0";
|
2025-02-23 21:45:57 +01:00
|
|
|
address = [ "10.0.255.1/24" ];
|
2025-02-23 11:45:05 +01:00
|
|
|
networkConfig.VXLAN = map router_vtep_name vni-list;
|
|
|
|
};
|
2025-02-23 21:45:57 +01:00
|
|
|
# "10-rbr0" = {
|
|
|
|
# name = "rbr0";
|
|
|
|
# address = [ "10.0.0.1/16" ];
|
|
|
|
# };
|
2025-02-23 11:45:05 +01:00
|
|
|
} // vtep-network;
|
|
|
|
netdevs = {
|
2025-02-23 21:45:57 +01:00
|
|
|
# "10-rbr0" = {
|
|
|
|
# netdevConfig = {
|
|
|
|
# Name = "rbr0";
|
|
|
|
# Kind = "bridge";
|
|
|
|
# };
|
|
|
|
# };
|
2025-02-23 11:45:05 +01:00
|
|
|
} // vtep-netdevs;
|
2025-02-22 19:08:31 +01:00
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|
|
|
|
// 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;
|
|
|
|
};
|
|
|
|
}
|