2018-12-29 11:16:51 +01:00
|
|
|
|
{
|
|
|
|
|
config,
|
|
|
|
|
lib,
|
|
|
|
|
utils,
|
|
|
|
|
pkgs,
|
|
|
|
|
...
|
|
|
|
|
}:
|
2014-11-20 02:37:48 -08:00
|
|
|
|
|
|
|
|
|
with utils;
|
2014-12-10 19:28:45 -05:00
|
|
|
|
with lib;
|
2014-11-20 02:37:48 -08:00
|
|
|
|
|
|
|
|
|
let
|
|
|
|
|
|
|
|
|
|
cfg = config.networking;
|
|
|
|
|
interfaces = attrValues cfg.interfaces;
|
|
|
|
|
|
2017-12-03 05:13:14 +01:00
|
|
|
|
interfaceIps = i: i.ipv4.addresses ++ optionals cfg.enableIPv6 i.ipv6.addresses;
|
2014-11-20 02:37:48 -08:00
|
|
|
|
|
2021-11-04 00:19:54 +01:00
|
|
|
|
interfaceRoutes = i: i.ipv4.routes ++ optionals cfg.enableIPv6 i.ipv6.routes;
|
|
|
|
|
|
2019-09-24 11:33:31 +02:00
|
|
|
|
dhcpStr = useDHCP: if useDHCP == true || useDHCP == null then "yes" else "no";
|
2014-11-20 02:37:48 -08:00
|
|
|
|
|
|
|
|
|
slaves =
|
|
|
|
|
concatLists (map (bond: bond.interfaces) (attrValues cfg.bonds))
|
|
|
|
|
++ concatLists (map (bridge: bridge.interfaces) (attrValues cfg.bridges))
|
|
|
|
|
++ map (sit: sit.dev) (attrValues cfg.sits)
|
2021-12-07 15:44:00 +00:00
|
|
|
|
++ map (gre: gre.dev) (attrValues cfg.greTunnels)
|
2018-12-29 11:16:51 +01:00
|
|
|
|
++ map (vlan: vlan.interface) (attrValues cfg.vlans)
|
|
|
|
|
# add dependency to physical or independently created vswitch member interface
|
|
|
|
|
# TODO: warn the user that any address configured on those interfaces will be useless
|
|
|
|
|
++ concatMap (i: attrNames (filterAttrs (_: config: config.type != "internal") i.interfaces)) (
|
2022-10-16 19:59:41 -04:00
|
|
|
|
attrValues cfg.vswitches
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
defaultGateways = mkMerge (
|
|
|
|
|
forEach [ cfg.defaultGateway cfg.defaultGateway6 ] (
|
|
|
|
|
gateway:
|
|
|
|
|
optionalAttrs (gateway != null && gateway.interface != null) {
|
|
|
|
|
networks."40-${gateway.interface}" = {
|
|
|
|
|
matchConfig.Name = gateway.interface;
|
2024-05-17 18:21:52 +02:00
|
|
|
|
routes = [
|
2024-12-10 20:26:33 +01:00
|
|
|
|
(
|
|
|
|
|
{
|
2022-10-16 19:59:41 -04:00
|
|
|
|
Gateway = gateway.address;
|
|
|
|
|
}
|
|
|
|
|
// optionalAttrs (gateway.metric != null) {
|
|
|
|
|
Metric = gateway.metric;
|
2024-12-10 20:26:33 +01:00
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
];
|
2022-10-16 19:59:41 -04:00
|
|
|
|
};
|
2024-05-31 13:05:19 +02:00
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
);
|
2022-10-16 19:59:41 -04:00
|
|
|
|
|
2025-01-26 14:47:59 +02:00
|
|
|
|
genericDhcpNetworks = mkIf cfg.useDHCP {
|
|
|
|
|
networks."99-ethernet-default-dhcp" = {
|
|
|
|
|
matchConfig = {
|
|
|
|
|
Type = "ether";
|
|
|
|
|
Kind = "!*"; # physical interfaces have no kind
|
2023-08-25 10:44:43 -04:00
|
|
|
|
};
|
2025-01-26 14:47:59 +02:00
|
|
|
|
DHCP = "yes";
|
|
|
|
|
networkConfig.IPv6PrivacyExtensions = "kernel";
|
|
|
|
|
};
|
|
|
|
|
networks."99-wireless-client-dhcp" = {
|
|
|
|
|
matchConfig.WLANInterfaceType = "station";
|
|
|
|
|
DHCP = "yes";
|
|
|
|
|
networkConfig.IPv6PrivacyExtensions = "kernel";
|
|
|
|
|
# We also set the route metric to one more than the default
|
|
|
|
|
# of 1024, so that Ethernet is preferred if both are
|
|
|
|
|
# available.
|
|
|
|
|
dhcpV4Config.RouteMetric = 1025;
|
|
|
|
|
ipv6AcceptRAConfig.RouteMetric = 1025;
|
2023-08-25 10:44:43 -04:00
|
|
|
|
};
|
2025-01-26 14:47:59 +02:00
|
|
|
|
};
|
2022-10-16 19:59:41 -04:00
|
|
|
|
|
2023-10-02 20:26:13 -04:00
|
|
|
|
interfaceNetworks = mkMerge (
|
|
|
|
|
forEach interfaces (i: {
|
2021-08-11 11:02:47 +02:00
|
|
|
|
netdevs = mkIf i.virtual ({
|
2014-11-20 02:37:48 -08:00
|
|
|
|
"40-${i.name}" = {
|
|
|
|
|
netdevConfig = {
|
|
|
|
|
Name = i.name;
|
|
|
|
|
Kind = i.virtualType;
|
|
|
|
|
};
|
2017-02-03 02:20:47 +01:00
|
|
|
|
"${i.virtualType}Config" = optionalAttrs (i.virtualOwner != null) {
|
|
|
|
|
User = i.virtualOwner;
|
2014-11-26 15:42:32 -08:00
|
|
|
|
};
|
|
|
|
|
};
|
2024-12-10 20:26:33 +01:00
|
|
|
|
});
|
2023-10-02 20:26:13 -04:00
|
|
|
|
networks."40-${i.name}" = {
|
2022-10-16 19:59:41 -04:00
|
|
|
|
name = mkDefault i.name;
|
|
|
|
|
DHCP = mkForce (
|
2024-12-10 20:26:33 +01:00
|
|
|
|
dhcpStr (
|
2023-10-02 20:26:13 -04:00
|
|
|
|
if i.useDHCP != null then i.useDHCP else (config.networking.useDHCP && i.ipv4.addresses == [ ])
|
2024-12-10 20:26:33 +01:00
|
|
|
|
)
|
|
|
|
|
);
|
2022-10-16 19:59:41 -04:00
|
|
|
|
address = forEach (interfaceIps i) (ip: "${ip.address}/${toString ip.prefixLength}");
|
2023-10-02 20:26:13 -04:00
|
|
|
|
routes = forEach (interfaceRoutes i) (
|
2021-08-11 11:02:47 +02:00
|
|
|
|
route:
|
|
|
|
|
mkMerge [
|
|
|
|
|
# Most of these route options have not been tested.
|
|
|
|
|
# Please fix or report any mistakes you may find.
|
|
|
|
|
(mkIf (route.address != null && route.prefixLength != null) {
|
|
|
|
|
Destination = "${route.address}/${toString route.prefixLength}";
|
2024-12-10 20:26:33 +01:00
|
|
|
|
})
|
2021-08-11 11:02:47 +02:00
|
|
|
|
(mkIf (route.options ? fastopen_no_cookie) {
|
|
|
|
|
FastOpenNoCookie = route.options.fastopen_no_cookie;
|
2024-12-10 20:26:33 +01:00
|
|
|
|
})
|
2021-08-11 11:02:47 +02:00
|
|
|
|
(mkIf (route.via != null) {
|
2024-05-31 13:05:19 +02:00
|
|
|
|
Gateway = route.via;
|
2024-12-10 20:26:33 +01:00
|
|
|
|
})
|
2024-05-31 13:05:19 +02:00
|
|
|
|
(mkIf (route.type != null) {
|
|
|
|
|
Type = route.type;
|
2024-12-10 20:26:33 +01:00
|
|
|
|
})
|
2024-05-31 13:05:19 +02:00
|
|
|
|
(mkIf (route.options ? onlink) {
|
|
|
|
|
GatewayOnLink = true;
|
2024-12-10 20:26:33 +01:00
|
|
|
|
})
|
2024-05-31 13:05:19 +02:00
|
|
|
|
(mkIf (route.options ? initrwnd) {
|
|
|
|
|
InitialAdvertisedReceiveWindow = route.options.initrwnd;
|
2024-12-10 20:26:33 +01:00
|
|
|
|
})
|
2024-05-31 13:05:19 +02:00
|
|
|
|
(mkIf (route.options ? initcwnd) {
|
|
|
|
|
InitialCongestionWindow = route.options.initcwnd;
|
2024-12-10 20:26:33 +01:00
|
|
|
|
})
|
2024-05-31 13:05:19 +02:00
|
|
|
|
(mkIf (route.options ? pref) {
|
|
|
|
|
IPv6Preference = route.options.pref;
|
2024-12-10 20:26:33 +01:00
|
|
|
|
})
|
2024-05-31 13:05:19 +02:00
|
|
|
|
(mkIf (route.options ? mtu) {
|
|
|
|
|
MTUBytes = route.options.mtu;
|
2024-12-10 20:26:33 +01:00
|
|
|
|
})
|
2024-05-31 13:05:19 +02:00
|
|
|
|
(mkIf (route.options ? metric) {
|
2021-08-11 11:02:47 +02:00
|
|
|
|
Metric = route.options.metric;
|
2024-12-10 20:26:33 +01:00
|
|
|
|
})
|
2024-05-31 13:05:19 +02:00
|
|
|
|
(mkIf (route.options ? src) {
|
|
|
|
|
PreferredSource = route.options.src;
|
2024-12-10 20:26:33 +01:00
|
|
|
|
})
|
2024-05-31 13:05:19 +02:00
|
|
|
|
(mkIf (route.options ? protocol) {
|
|
|
|
|
Protocol = route.options.protocol;
|
2024-12-10 20:26:33 +01:00
|
|
|
|
})
|
2024-05-31 13:05:19 +02:00
|
|
|
|
(mkIf (route.options ? quickack) {
|
|
|
|
|
QuickAck = route.options.quickack;
|
2024-12-10 20:26:33 +01:00
|
|
|
|
})
|
2021-08-11 11:02:47 +02:00
|
|
|
|
(mkIf (route.options ? scope) {
|
2024-05-31 13:05:19 +02:00
|
|
|
|
Scope = route.options.scope;
|
2024-12-10 20:26:33 +01:00
|
|
|
|
})
|
2024-05-31 13:05:19 +02:00
|
|
|
|
(mkIf (route.options ? from) {
|
|
|
|
|
Source = route.options.from;
|
2024-12-10 20:26:33 +01:00
|
|
|
|
})
|
2024-05-31 13:05:19 +02:00
|
|
|
|
(mkIf (route.options ? table) {
|
|
|
|
|
Table = route.options.table;
|
2024-12-10 20:26:33 +01:00
|
|
|
|
})
|
2024-05-31 13:05:19 +02:00
|
|
|
|
(mkIf (route.options ? advmss) {
|
|
|
|
|
TCPAdvertisedMaximumSegmentSize = route.options.advmss;
|
2024-12-10 20:26:33 +01:00
|
|
|
|
})
|
2024-05-31 13:05:19 +02:00
|
|
|
|
(mkIf (route.options ? ttl-propagate) {
|
|
|
|
|
TTLPropagate = route.options.ttl-propagate == "enabled";
|
2024-12-10 20:26:33 +01:00
|
|
|
|
})
|
|
|
|
|
]
|
|
|
|
|
);
|
2021-08-11 11:02:47 +02:00
|
|
|
|
networkConfig.IPv6PrivacyExtensions = "kernel";
|
|
|
|
|
linkConfig =
|
|
|
|
|
optionalAttrs (i.macAddress != null) {
|
|
|
|
|
MACAddress = i.macAddress;
|
2024-12-10 20:26:33 +01:00
|
|
|
|
}
|
2021-08-11 11:02:47 +02:00
|
|
|
|
// optionalAttrs (i.mtu != null) {
|
|
|
|
|
MTUBytes = toString i.mtu;
|
|
|
|
|
};
|
2024-12-10 20:26:33 +01:00
|
|
|
|
};
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
|
2021-08-11 11:02:47 +02:00
|
|
|
|
bridgeNetworks = mkMerge (
|
2014-11-20 02:37:48 -08:00
|
|
|
|
flip mapAttrsToList cfg.bridges (
|
|
|
|
|
name: bridge: {
|
|
|
|
|
netdevs."40-${name}" = {
|
|
|
|
|
netdevConfig = {
|
|
|
|
|
Name = name;
|
2021-08-11 12:48:43 +02:00
|
|
|
|
Kind = "bridge";
|
2023-10-02 20:26:13 -04:00
|
|
|
|
};
|
2014-11-20 02:37:48 -08:00
|
|
|
|
};
|
2019-08-05 14:03:38 +03:00
|
|
|
|
networks = listToAttrs (
|
2021-12-07 15:44:00 +00:00
|
|
|
|
forEach bridge.interfaces (
|
|
|
|
|
bi:
|
|
|
|
|
nameValuePair "40-${bi}" {
|
|
|
|
|
DHCP = mkOverride 0 (dhcpStr false);
|
2014-11-20 02:37:48 -08:00
|
|
|
|
networkConfig.Bridge = name;
|
2024-12-10 20:26:33 +01:00
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
|
2021-12-07 15:44:00 +00:00
|
|
|
|
vlanNetworks = mkMerge (
|
|
|
|
|
flip mapAttrsToList cfg.vlans (
|
|
|
|
|
name: vlan: {
|
|
|
|
|
netdevs."40-${name}" = {
|
|
|
|
|
netdevConfig = {
|
|
|
|
|
Name = name;
|
|
|
|
|
Kind = "vlan";
|
|
|
|
|
};
|
|
|
|
|
vlanConfig.Id = vlan.id;
|
|
|
|
|
};
|
|
|
|
|
networks."40-${vlan.interface}" = {
|
|
|
|
|
vlan = [ name ];
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
)
|
2014-11-20 02:37:48 -08:00
|
|
|
|
);
|
2024-12-10 20:26:33 +01:00
|
|
|
|
|
|
|
|
|
in
|
|
|
|
|
|
|
|
|
|
{
|
2022-10-16 19:59:41 -04:00
|
|
|
|
config = mkMerge [
|
2014-11-20 02:37:48 -08:00
|
|
|
|
|
|
|
|
|
(mkIf config.boot.initrd.network.enable {
|
|
|
|
|
# Note this is if initrd.network.enable, not if
|
|
|
|
|
# initrd.systemd.network.enable. By setting the latter and not the
|
|
|
|
|
# former, the user retains full control over the configuration.
|
|
|
|
|
boot.initrd.systemd.network = mkMerge [
|
|
|
|
|
defaultGateways
|
2025-01-26 14:47:59 +02:00
|
|
|
|
genericDhcpNetworks
|
2014-11-20 02:37:48 -08:00
|
|
|
|
interfaceNetworks
|
2023-08-25 13:11:40 -04:00
|
|
|
|
bridgeNetworks
|
2023-08-25 10:44:43 -04:00
|
|
|
|
vlanNetworks
|
2024-12-10 20:26:33 +01:00
|
|
|
|
];
|
2014-11-20 02:37:48 -08:00
|
|
|
|
boot.initrd.availableKernelModules =
|
|
|
|
|
optional (cfg.bridges != { }) "bridge"
|
|
|
|
|
++ optional (cfg.vlans != { }) "8021q";
|
2024-12-10 20:26:33 +01:00
|
|
|
|
})
|
2014-11-20 02:37:48 -08:00
|
|
|
|
|
2018-12-29 11:16:51 +01:00
|
|
|
|
(mkIf cfg.useNetworkd {
|
|
|
|
|
|
2014-11-20 02:37:48 -08:00
|
|
|
|
assertions =
|
2024-12-10 20:26:33 +01:00
|
|
|
|
[
|
|
|
|
|
{
|
2014-11-20 02:37:48 -08:00
|
|
|
|
assertion = cfg.defaultGatewayWindowSize == null;
|
|
|
|
|
message = "networking.defaultGatewayWindowSize is not supported by networkd.";
|
2024-12-10 20:26:33 +01:00
|
|
|
|
}
|
|
|
|
|
{
|
2023-10-02 20:26:13 -04:00
|
|
|
|
assertion = cfg.defaultGateway != null -> cfg.defaultGateway.interface != null;
|
|
|
|
|
message = "networking.defaultGateway.interface is not optional when using networkd.";
|
2024-12-10 20:26:33 +01:00
|
|
|
|
}
|
|
|
|
|
{
|
2023-10-02 20:26:13 -04:00
|
|
|
|
assertion = cfg.defaultGateway6 != null -> cfg.defaultGateway6.interface != null;
|
|
|
|
|
message = "networking.defaultGateway6.interface is not optional when using networkd.";
|
2024-12-10 20:26:33 +01:00
|
|
|
|
}
|
|
|
|
|
]
|
2015-02-24 13:09:06 -08:00
|
|
|
|
++ flip mapAttrsToList cfg.bridges (
|
2024-12-10 20:26:33 +01:00
|
|
|
|
n:
|
2015-02-24 13:09:06 -08:00
|
|
|
|
{ rstp, ... }:
|
2024-12-10 20:26:33 +01:00
|
|
|
|
{
|
2015-02-24 13:09:06 -08:00
|
|
|
|
assertion = !rstp;
|
|
|
|
|
message = "networking.bridges.${n}.rstp is not supported by networkd.";
|
2024-12-10 20:26:33 +01:00
|
|
|
|
}
|
|
|
|
|
)
|
2021-08-11 11:02:47 +02:00
|
|
|
|
++ flip mapAttrsToList cfg.fooOverUDP (
|
2024-12-10 20:26:33 +01:00
|
|
|
|
n:
|
2021-08-11 11:02:47 +02:00
|
|
|
|
{ local, ... }:
|
2024-12-10 20:26:33 +01:00
|
|
|
|
{
|
2021-08-11 11:02:47 +02:00
|
|
|
|
assertion = local == null;
|
|
|
|
|
message = "networking.fooOverUDP.${n}.local is not supported by networkd.";
|
2024-12-10 20:26:33 +01:00
|
|
|
|
}
|
|
|
|
|
);
|
2018-12-29 11:16:51 +01:00
|
|
|
|
|
2016-09-13 07:55:17 +02:00
|
|
|
|
networking.dhcpcd.enable = mkDefault false;
|
2024-12-10 20:26:33 +01:00
|
|
|
|
|
2023-08-25 10:44:43 -04:00
|
|
|
|
systemd.network = mkMerge [
|
2024-12-10 20:26:33 +01:00
|
|
|
|
{
|
2018-12-29 11:16:51 +01:00
|
|
|
|
enable = true;
|
2024-12-10 20:26:33 +01:00
|
|
|
|
}
|
2023-10-02 19:19:48 -04:00
|
|
|
|
defaultGateways
|
2025-01-26 14:47:59 +02:00
|
|
|
|
genericDhcpNetworks
|
2022-10-16 19:59:41 -04:00
|
|
|
|
interfaceNetworks
|
2023-08-25 13:11:40 -04:00
|
|
|
|
bridgeNetworks
|
2014-11-26 15:42:32 -08:00
|
|
|
|
(mkMerge (
|
2018-12-29 11:16:51 +01:00
|
|
|
|
flip mapAttrsToList cfg.bonds (
|
2014-11-20 02:37:48 -08:00
|
|
|
|
name: bond: {
|
2018-12-29 11:16:51 +01:00
|
|
|
|
netdevs."40-${name}" = {
|
|
|
|
|
netdevConfig = {
|
2014-11-26 15:42:32 -08:00
|
|
|
|
Name = name;
|
2024-10-03 15:52:32 +07:00
|
|
|
|
Kind = "bond";
|
2024-12-10 20:26:33 +01:00
|
|
|
|
};
|
2017-02-03 02:20:47 +01:00
|
|
|
|
bondConfig =
|
2024-12-10 20:26:33 +01:00
|
|
|
|
let
|
2017-02-03 02:20:47 +01:00
|
|
|
|
# manual mapping as of 2017-02-03
|
|
|
|
|
# man 5 systemd.netdev [BOND]
|
2018-12-29 11:16:51 +01:00
|
|
|
|
# to https://www.kernel.org/doc/Documentation/networking/bonding.txt
|
2017-02-03 02:20:47 +01:00
|
|
|
|
# driver options.
|
|
|
|
|
driverOptionMapping =
|
2024-12-10 20:26:33 +01:00
|
|
|
|
let
|
2017-02-03 02:20:47 +01:00
|
|
|
|
trans = f: optName: {
|
|
|
|
|
valTransform = f;
|
2018-12-29 11:16:51 +01:00
|
|
|
|
optNames = [ optName ];
|
2024-12-10 20:26:33 +01:00
|
|
|
|
};
|
2017-02-03 02:20:47 +01:00
|
|
|
|
simp = trans id;
|
|
|
|
|
ms = trans (v: v + "ms");
|
2024-12-10 20:26:33 +01:00
|
|
|
|
in
|
|
|
|
|
{
|
2017-02-03 02:20:47 +01:00
|
|
|
|
Mode = simp "mode";
|
2017-02-18 15:51:07 +01:00
|
|
|
|
TransmitHashPolicy = simp "xmit_hash_policy";
|
2017-02-03 02:20:47 +01:00
|
|
|
|
LACPTransmitRate = simp "lacp_rate";
|
|
|
|
|
MIIMonitorSec = ms "miimon";
|
|
|
|
|
UpDelaySec = ms "updelay";
|
|
|
|
|
DownDelaySec = ms "downdelay";
|
|
|
|
|
LearnPacketIntervalSec = simp "lp_interval";
|
2018-12-29 11:16:51 +01:00
|
|
|
|
AdSelect = simp "ad_select";
|
|
|
|
|
FailOverMACPolicy = simp "fail_over_mac";
|
2017-02-03 02:20:47 +01:00
|
|
|
|
ARPValidate = simp "arp_validate";
|
2018-12-29 11:16:51 +01:00
|
|
|
|
# apparently in ms for this value?! Upstream bug?
|
2017-02-03 02:20:47 +01:00
|
|
|
|
ARPIntervalSec = simp "arp_interval";
|
|
|
|
|
ARPIPTargets = simp "arp_ip_target";
|
|
|
|
|
ARPAllTargets = simp "arp_all_targets";
|
|
|
|
|
PrimaryReselectPolicy = simp "primary_reselect";
|
2018-12-29 11:16:51 +01:00
|
|
|
|
ResendIGMP = simp "resend_igmp";
|
|
|
|
|
PacketsPerSlave = simp "packets_per_slave";
|
2017-02-03 02:20:47 +01:00
|
|
|
|
GratuitousARP = {
|
|
|
|
|
valTransform = id;
|
|
|
|
|
optNames = [
|
|
|
|
|
"num_grat_arp"
|
|
|
|
|
"num_unsol_na"
|
2024-12-10 20:26:33 +01:00
|
|
|
|
];
|
|
|
|
|
};
|
2017-02-03 02:20:47 +01:00
|
|
|
|
AllSlavesActive = simp "all_slaves_active";
|
|
|
|
|
MinLinks = simp "min_links";
|
2024-12-10 20:26:33 +01:00
|
|
|
|
};
|
|
|
|
|
|
2017-02-03 02:20:47 +01:00
|
|
|
|
do = bond.driverOptions;
|
|
|
|
|
assertNoUnknownOption =
|
2024-12-10 20:26:33 +01:00
|
|
|
|
let
|
2017-02-03 02:20:47 +01:00
|
|
|
|
knownOptions = flatten (mapAttrsToList (_: kOpts: kOpts.optNames) driverOptionMapping);
|
|
|
|
|
# options that apparently don’t exist in the networkd config
|
|
|
|
|
unknownOptions = [ "primary" ];
|
|
|
|
|
assertTrace = bool: msg: if bool then true else builtins.trace msg false;
|
2024-12-10 20:26:33 +01:00
|
|
|
|
in
|
2017-02-03 02:20:47 +01:00
|
|
|
|
assert all (
|
|
|
|
|
driverOpt:
|
|
|
|
|
assertTrace (elem driverOpt (knownOptions ++ unknownOptions))
|
2018-12-29 11:16:51 +01:00
|
|
|
|
"The bond.driverOption `${driverOpt}` cannot be mapped to the list of known networkd bond options. Please add it to the mapping above the assert or to `unknownOptions` should it not exist in networkd."
|
2017-02-03 02:20:47 +01:00
|
|
|
|
) (mapAttrsToList (k: _: k) do);
|
2024-12-10 20:26:33 +01:00
|
|
|
|
"";
|
2017-02-03 02:20:47 +01:00
|
|
|
|
# get those driverOptions that have been set
|
2018-12-29 11:16:51 +01:00
|
|
|
|
filterSystemdOptions = filterAttrs (sysDOpt: kOpts: any (kOpt: do ? ${kOpt}) kOpts.optNames);
|
|
|
|
|
# build final set of systemd options to bond values
|
2017-02-03 02:20:47 +01:00
|
|
|
|
buildOptionSet = mapAttrs (
|
2024-12-10 20:26:33 +01:00
|
|
|
|
_: kOpts:
|
2017-02-03 02:20:47 +01:00
|
|
|
|
with kOpts;
|
|
|
|
|
# we simply take the first set kernel bond option
|
2018-12-29 11:16:51 +01:00
|
|
|
|
# (one option has multiple names, which is silly)
|
2024-12-10 20:26:33 +01:00
|
|
|
|
head (
|
2018-12-29 11:16:51 +01:00
|
|
|
|
map (optN: valTransform (do.${optN}))
|
2017-02-03 02:20:47 +01:00
|
|
|
|
# only map those that exist
|
2018-12-29 11:16:51 +01:00
|
|
|
|
(filter (o: do ? ${o}) optNames)
|
2024-12-10 20:26:33 +01:00
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
in
|
2018-12-29 11:16:51 +01:00
|
|
|
|
seq assertNoUnknownOption (buildOptionSet (filterSystemdOptions driverOptionMapping));
|
2024-12-10 20:26:33 +01:00
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
2019-08-05 14:03:38 +03:00
|
|
|
|
networks = listToAttrs (
|
|
|
|
|
forEach bond.interfaces (
|
2024-12-10 20:26:33 +01:00
|
|
|
|
bi:
|
2023-10-02 20:26:13 -04:00
|
|
|
|
nameValuePair "40-${bi}" {
|
2014-11-20 02:37:48 -08:00
|
|
|
|
DHCP = mkOverride 0 (dhcpStr false);
|
|
|
|
|
networkConfig.Bond = name;
|
2018-12-29 11:16:51 +01:00
|
|
|
|
}
|
2024-12-10 20:26:33 +01:00
|
|
|
|
)
|
|
|
|
|
);
|
2018-12-29 11:16:51 +01:00
|
|
|
|
}
|
2024-12-10 20:26:33 +01:00
|
|
|
|
)
|
|
|
|
|
))
|
2014-11-26 15:42:32 -08:00
|
|
|
|
(mkMerge (
|
2018-12-29 11:16:51 +01:00
|
|
|
|
flip mapAttrsToList cfg.macvlans (
|
2014-11-26 15:42:32 -08:00
|
|
|
|
name: macvlan: {
|
2018-12-29 11:16:51 +01:00
|
|
|
|
netdevs."40-${name}" = {
|
2021-12-07 15:44:00 +00:00
|
|
|
|
netdevConfig = {
|
|
|
|
|
Name = name;
|
2014-11-26 15:42:32 -08:00
|
|
|
|
Kind = "macvlan";
|
2024-12-10 20:26:33 +01:00
|
|
|
|
};
|
2014-11-30 01:19:33 -08:00
|
|
|
|
macvlanConfig = optionalAttrs (macvlan.mode != null) { Mode = macvlan.mode; };
|
2024-12-10 20:26:33 +01:00
|
|
|
|
};
|
2023-10-02 20:26:13 -04:00
|
|
|
|
networks."40-${macvlan.interface}" = {
|
2014-11-26 15:42:32 -08:00
|
|
|
|
macvlan = [ name ];
|
2024-12-10 20:26:33 +01:00
|
|
|
|
};
|
2018-12-29 11:16:51 +01:00
|
|
|
|
}
|
2024-12-10 20:26:33 +01:00
|
|
|
|
)
|
|
|
|
|
))
|
2014-11-26 15:42:32 -08:00
|
|
|
|
(mkMerge (
|
2018-12-29 11:16:51 +01:00
|
|
|
|
flip mapAttrsToList cfg.fooOverUDP (
|
2017-02-03 02:20:47 +01:00
|
|
|
|
name: fou: {
|
2021-12-07 15:44:00 +00:00
|
|
|
|
netdevs."40-${name}" = {
|
|
|
|
|
netdevConfig = {
|
|
|
|
|
Name = name;
|
2014-11-20 02:37:48 -08:00
|
|
|
|
Kind = "fou";
|
2024-12-10 20:26:33 +01:00
|
|
|
|
};
|
2018-12-29 11:16:51 +01:00
|
|
|
|
# unfortunately networkd cannot encode dependencies of netdevs on addresses/routes,
|
|
|
|
|
# so we cannot specify Local=, Peer=, PeerPort=. this looks like a missing feature
|
2021-08-11 11:02:47 +02:00
|
|
|
|
# in networkd.
|
|
|
|
|
fooOverUDPConfig =
|
2024-12-10 20:26:33 +01:00
|
|
|
|
{
|
2021-08-11 11:02:47 +02:00
|
|
|
|
Port = fou.port;
|
2018-12-29 11:16:51 +01:00
|
|
|
|
Encapsulation = if fou.protocol != null then "FooOverUDP" else "GenericUDPEncapsulation";
|
2024-12-10 20:26:33 +01:00
|
|
|
|
}
|
2018-12-29 11:16:51 +01:00
|
|
|
|
// (optionalAttrs (fou.protocol != null) {
|
|
|
|
|
Protocol = fou.protocol;
|
2024-12-10 20:26:33 +01:00
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
))
|
2014-11-26 15:42:32 -08:00
|
|
|
|
(mkMerge (
|
2018-12-29 11:16:51 +01:00
|
|
|
|
flip mapAttrsToList cfg.sits (
|
2024-12-10 20:26:33 +01:00
|
|
|
|
name: sit: {
|
2021-12-07 15:44:00 +00:00
|
|
|
|
netdevs."40-${name}" = {
|
|
|
|
|
netdevConfig = {
|
|
|
|
|
Name = name;
|
2014-11-20 02:37:48 -08:00
|
|
|
|
Kind = "sit";
|
2024-12-10 20:26:33 +01:00
|
|
|
|
};
|
2014-11-20 02:37:48 -08:00
|
|
|
|
tunnelConfig =
|
|
|
|
|
(optionalAttrs (sit.remote != null) {
|
|
|
|
|
Remote = sit.remote;
|
2024-12-10 20:26:33 +01:00
|
|
|
|
})
|
2014-11-20 02:37:48 -08:00
|
|
|
|
// (optionalAttrs (sit.local != null) {
|
|
|
|
|
Local = sit.local;
|
2024-12-10 20:26:33 +01:00
|
|
|
|
})
|
2014-11-20 02:37:48 -08:00
|
|
|
|
// (optionalAttrs (sit.ttl != null) {
|
|
|
|
|
TTL = sit.ttl;
|
2024-12-10 20:26:33 +01:00
|
|
|
|
})
|
2021-08-11 12:48:43 +02:00
|
|
|
|
// (optionalAttrs (sit.encapsulation != null) (
|
2024-12-10 20:26:33 +01:00
|
|
|
|
{
|
2021-08-11 12:48:43 +02:00
|
|
|
|
FooOverUDP = true;
|
2018-12-29 11:16:51 +01:00
|
|
|
|
Encapsulation = if sit.encapsulation.type == "fou" then "FooOverUDP" else "GenericUDPEncapsulation";
|
2021-08-11 12:48:43 +02:00
|
|
|
|
FOUDestinationPort = sit.encapsulation.port;
|
2024-12-10 20:26:33 +01:00
|
|
|
|
}
|
2021-08-11 12:48:43 +02:00
|
|
|
|
// (optionalAttrs (sit.encapsulation.sourcePort != null) {
|
|
|
|
|
FOUSourcePort = sit.encapsulation.sourcePort;
|
2024-12-10 20:26:33 +01:00
|
|
|
|
})
|
|
|
|
|
));
|
|
|
|
|
};
|
2014-11-20 02:37:48 -08:00
|
|
|
|
networks = mkIf (sit.dev != null) {
|
2023-10-02 20:26:13 -04:00
|
|
|
|
"40-${sit.dev}" = {
|
2014-11-20 02:37:48 -08:00
|
|
|
|
tunnel = [ name ];
|
2024-12-10 20:26:33 +01:00
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
))
|
2014-11-26 15:42:32 -08:00
|
|
|
|
(mkMerge (
|
2015-02-24 13:09:06 -08:00
|
|
|
|
flip mapAttrsToList cfg.greTunnels (
|
2024-12-10 20:26:33 +01:00
|
|
|
|
name: gre: {
|
2021-12-07 15:44:00 +00:00
|
|
|
|
netdevs."40-${name}" = {
|
|
|
|
|
netdevConfig = {
|
|
|
|
|
Name = name;
|
2024-12-10 20:26:33 +01:00
|
|
|
|
Kind = gre.type;
|
|
|
|
|
};
|
2014-11-20 02:37:48 -08:00
|
|
|
|
tunnelConfig =
|
2021-12-07 15:44:00 +00:00
|
|
|
|
(optionalAttrs (gre.remote != null) {
|
|
|
|
|
Remote = gre.remote;
|
2024-12-10 20:26:33 +01:00
|
|
|
|
})
|
2021-12-07 15:44:00 +00:00
|
|
|
|
// (optionalAttrs (gre.local != null) {
|
|
|
|
|
Local = gre.local;
|
2024-12-10 20:26:33 +01:00
|
|
|
|
})
|
2022-03-22 20:24:25 +05:30
|
|
|
|
// (optionalAttrs (gre.ttl != null) {
|
|
|
|
|
TTL = gre.ttl;
|
2024-12-10 20:26:33 +01:00
|
|
|
|
});
|
|
|
|
|
};
|
2014-11-20 02:37:48 -08:00
|
|
|
|
networks = mkIf (gre.dev != null) {
|
2023-10-02 20:26:13 -04:00
|
|
|
|
"40-${gre.dev}" = {
|
2014-11-20 02:37:48 -08:00
|
|
|
|
tunnel = [ name ];
|
2024-12-10 20:26:33 +01:00
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
))
|
2018-12-29 11:16:51 +01:00
|
|
|
|
vlanNetworks
|
2024-12-10 20:26:33 +01:00
|
|
|
|
];
|
|
|
|
|
|
2014-11-20 02:37:48 -08:00
|
|
|
|
# We need to prefill the slaved devices with networking options
|
2018-12-29 11:16:51 +01:00
|
|
|
|
# This forces the network interface creator to initialize slaves.
|
|
|
|
|
networking.interfaces = listToAttrs (map (i: nameValuePair i { }) slaves);
|
2024-12-10 20:26:33 +01:00
|
|
|
|
|
2018-12-29 11:16:51 +01:00
|
|
|
|
systemd.services =
|
|
|
|
|
let
|
|
|
|
|
# We must escape interfaces due to the systemd interpretation
|
|
|
|
|
subsystemDevice = interface: "sys-subsystem-net-devices-${escapeSystemdPath interface}.device";
|
|
|
|
|
# support for creating openvswitch switches
|
|
|
|
|
createVswitchDevice =
|
2024-12-10 20:26:33 +01:00
|
|
|
|
n: v:
|
2018-12-29 11:16:51 +01:00
|
|
|
|
nameValuePair "${n}-netdev" (
|
2024-12-10 20:26:33 +01:00
|
|
|
|
let
|
2018-12-29 11:16:51 +01:00
|
|
|
|
deps = map subsystemDevice (
|
|
|
|
|
attrNames (filterAttrs (_: config: config.type != "internal") v.interfaces)
|
2024-12-10 20:26:33 +01:00
|
|
|
|
);
|
2018-12-29 11:16:51 +01:00
|
|
|
|
ofRules = pkgs.writeText "vswitch-${n}-openFlowRules" v.openFlowRules;
|
2024-12-10 20:26:33 +01:00
|
|
|
|
in
|
|
|
|
|
{
|
2018-12-29 11:16:51 +01:00
|
|
|
|
description = "Open vSwitch Interface ${n}";
|
|
|
|
|
wantedBy = [
|
2023-05-19 22:11:38 -04:00
|
|
|
|
"network.target"
|
2018-12-29 11:16:51 +01:00
|
|
|
|
(subsystemDevice n)
|
2024-12-10 20:26:33 +01:00
|
|
|
|
];
|
2023-05-19 22:11:38 -04:00
|
|
|
|
# and create bridge before systemd-networkd starts because it might create internal interfaces
|
|
|
|
|
before = [ "systemd-networkd.service" ];
|
|
|
|
|
# shutdown the bridge when network is shutdown
|
2018-12-29 11:16:51 +01:00
|
|
|
|
partOf = [ "network.target" ];
|
|
|
|
|
# requires ovs-vswitchd to be alive at all times
|
|
|
|
|
bindsTo = [ "ovs-vswitchd.service" ];
|
2023-05-19 22:11:38 -04:00
|
|
|
|
# start switch after physical interfaces and vswitch daemon
|
2018-12-29 11:16:51 +01:00
|
|
|
|
after = [
|
|
|
|
|
"network-pre.target"
|
|
|
|
|
"ovs-vswitchd.service"
|
|
|
|
|
] ++ deps;
|
|
|
|
|
wants = deps; # if one or more interface fails, the switch should continue to run
|
|
|
|
|
serviceConfig.Type = "oneshot";
|
|
|
|
|
serviceConfig.RemainAfterExit = true;
|
2024-12-10 20:26:33 +01:00
|
|
|
|
path = [
|
2021-03-14 17:05:16 +01:00
|
|
|
|
pkgs.iproute2
|
|
|
|
|
config.virtualisation.vswitch.package
|
2024-12-10 20:26:33 +01:00
|
|
|
|
];
|
2018-12-29 11:16:51 +01:00
|
|
|
|
preStart = ''
|
2023-05-19 22:11:38 -04:00
|
|
|
|
echo "Resetting Open vSwitch ${n}..."
|
2023-10-29 18:27:16 +01:00
|
|
|
|
ovs-vsctl --if-exists del-br ${n} -- add-br ${n} \
|
|
|
|
|
-- set bridge ${n} protocols=${concatStringsSep "," v.supportedOpenFlowVersions}
|
2024-12-10 20:26:33 +01:00
|
|
|
|
'';
|
2023-10-29 18:27:16 +01:00
|
|
|
|
script = ''
|
|
|
|
|
echo "Configuring Open vSwitch ${n}..."
|
2018-12-29 11:16:51 +01:00
|
|
|
|
ovs-vsctl ${
|
|
|
|
|
concatStrings (
|
2023-10-29 18:27:16 +01:00
|
|
|
|
mapAttrsToList (
|
2018-12-29 11:16:51 +01:00
|
|
|
|
name: config:
|
|
|
|
|
" -- add-port ${n} ${name}" + optionalString (config.vlan != null) " tag=${toString config.vlan}"
|
|
|
|
|
) v.interfaces
|
2024-12-10 20:26:33 +01:00
|
|
|
|
)
|
|
|
|
|
} \
|
|
|
|
|
${
|
2018-12-29 11:16:51 +01:00
|
|
|
|
concatStrings (
|
2014-11-26 15:42:32 -08:00
|
|
|
|
mapAttrsToList (
|
2023-10-29 18:27:16 +01:00
|
|
|
|
name: config: optionalString (config.type != null) " -- set interface ${name} type=${config.type}"
|
2018-12-29 11:16:51 +01:00
|
|
|
|
) v.interfaces
|
2024-12-10 20:26:33 +01:00
|
|
|
|
)
|
|
|
|
|
} \
|
2018-12-29 11:16:51 +01:00
|
|
|
|
${concatMapStrings (x: " -- set-controller ${n} " + x) v.controllers} \
|
|
|
|
|
${concatMapStrings (x: " -- " + x) (splitString "\n" v.extraOvsctlCmds)}
|
2024-12-10 20:26:33 +01:00
|
|
|
|
|
|
|
|
|
|
2023-10-29 18:27:16 +01:00
|
|
|
|
echo "Adding OpenFlow rules for Open vSwitch ${n}..."
|
2018-12-29 11:16:51 +01:00
|
|
|
|
ovs-ofctl --protocols=${v.openFlowVersion} add-flows ${n} ${ofRules}
|
2024-12-10 20:26:33 +01:00
|
|
|
|
'';
|
|
|
|
|
postStop = ''
|
2018-12-29 11:16:51 +01:00
|
|
|
|
echo "Cleaning Open vSwitch ${n}"
|
|
|
|
|
echo "Shutting down internal ${n} interface"
|
|
|
|
|
ip link set dev ${n} down || true
|
|
|
|
|
echo "Deleting flows for ${n}"
|
|
|
|
|
ovs-ofctl --protocols=${v.openFlowVersion} del-flows ${n} || true
|
|
|
|
|
echo "Deleting Open vSwitch ${n}"
|
|
|
|
|
ovs-vsctl --if-exists del-br ${n} || true
|
|
|
|
|
'';
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
in
|
|
|
|
|
mapAttrs' createVswitchDevice cfg.vswitches
|
|
|
|
|
// {
|
|
|
|
|
"network-local-commands" = {
|
|
|
|
|
after = [ "systemd-networkd.service" ];
|
|
|
|
|
bindsTo = [ "systemd-networkd.service" ];
|
|
|
|
|
};
|
|
|
|
|
};
|
2022-10-16 19:59:41 -04:00
|
|
|
|
})
|
2014-11-20 02:37:48 -08:00
|
|
|
|
|
2022-10-16 19:59:41 -04:00
|
|
|
|
];
|
2014-11-20 02:37:48 -08:00
|
|
|
|
}
|