From 001aaecf3a79a927a62ad86ed9d6d781ccabdf15 Mon Sep 17 00:00:00 2001 From: Astro Date: Sat, 6 Nov 2021 03:38:01 +0100 Subject: [PATCH] lib/config/options: rewrite getHostLinkNetworks et al --- nix/lib/config/options.nix | 94 +++++++++++++++++++------------------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/nix/lib/config/options.nix b/nix/lib/config/options.nix index 20c6402..bc7ba72 100644 --- a/nix/lib/config/options.nix +++ b/nix/lib/config/options.nix @@ -2,53 +2,49 @@ with lib; let - getHostNets = link: + # A host needs to know a network if it + # - is a configured interface, or + # - is required behind at least two different links + getHostLinkNetworks = hostName: link: let - hostConfig = config.site.hosts.${link}; - sort = nets: lib.unique ( - builtins.sort (net1: net2: - config.site.net.${net1}.vlan < config.site.net.${net2}.vlan - ) nets - ); + hostConfig = config.site.hosts.${hostName}; + # all the host's links + hostLinkNetworks = builtins.mapAttrs (link: _: + networksBehindLink hostName link + ) hostConfig.links; + # how many links have a net in networksBehindLink + networkLinkCount = net: + builtins.length ( + builtins.filter (builtins.elem net) + (builtins.attrValues hostLinkNetworks) + ); in - if config.site.hosts ? ${link} - then - sort ( - builtins.attrNames hostConfig.interfaces ++ - getLinksNets link - ) - - else if config.site.net ? ${link} + # access port + if config.site.net ? ${link} then [ link ] - else builtins.trace "Don't know what nets to configure for link to \"${link}\"" []; + # multiple vlans on this link + else + builtins.filter (net: + # this port and local interface + hostConfig.interfaces ? ${net} + || + # this port and another + networkLinkCount net > 1 + ) hostLinkNetworks.${link}; - # breaks the getHostNets recursion for switches, - # requiring any net to be used by at >1 links - getLinksNets = hostName: - let - linksNets = builtins.mapAttrs (link: _: - unique ( - getLinkNets { "${hostName}" = true; } [ link ] - ) - ) config.site.hosts.${hostName}.links; - allNets = unique ( - builtins.concatLists (builtins.attrValues linksNets) - ); - netLinkCount = net: - builtins.foldl' (netLinkCount: nets: - if builtins.elem net nets - then netLinkCount + 1 - else netLinkCount - ) 0 (builtins.attrValues linksNets); - nets = builtins.filter (net: - netLinkCount net > 1 - ) allNets; - in nets; + networksBehindLink = hostName: name: + networksBehindLink' { + "${hostName}" = true; + } [ name ]; - getLinkNets = seen: links: + networksBehindLink' = seen: links: if links == [] - then [] + then + # Done, result is the seen link names that are networks: + builtins.filter (name: + config.site.net ? ${name} + ) (builtins.attrNames seen) else let link = builtins.head links; @@ -59,13 +55,17 @@ let links' = builtins.tail links; in if config.site.hosts ? ${link} - then getLinkNets seen' ( + then networksBehindLink' seen' ( links' ++ ( + builtins.attrNames config.site.hosts.${link}.interfaces + ) ++ ( onlyUnseen (builtins.attrNames config.site.hosts.${link}.links) ) ) - else getHostNets link ++ - getLinkNets seen' (onlyUnseen links'); + else if config.site.net ? ${link} + then networksBehindLink' seen' links' + + else throw "Link to invalid target ${link}"; dhcpOpts = { start = mkOption { @@ -382,7 +382,7 @@ let links = mkOption { description = "Which port is connected to what other device? Keys are either network names or known hostnames."; default = {}; - type = with types; attrsOf (submodule linkOpts); + type = with types; attrsOf (submodule (linkOpts name)); }; wifi = mkOption { default = {}; @@ -433,7 +433,7 @@ let }; }; - linkOpts = { name, ... }: { + linkOpts = hostName: { name, ... }: { options = { ports = mkOption { type = with types; listOf str; @@ -447,14 +447,14 @@ let nets = mkOption { type = with types; listOf str; description = "Automatically generated"; - default = getHostNets name; + default = getHostLinkNetworks hostName name; }; vlans = mkOption { type = with types; listOf int; description = "Automatically generated, do not set"; default = map (net: config.site.net.${net}.vlan - ) (getHostNets name); + ) config.site.hosts.${hostName}.links.${name}.nets; }; }; };