{ lib, config, xml, ... }: let inherit (lib) mkEnableOption mkOption optionalString mapAttrsToList mkMerge mkIf ; inherit (lib.types) enum listOf either str ints submodule attrsOf ; interface = { name, config, ... }: let unit = { name, config, ... }: { options = { enable = mkEnableOption "this logical interface" // { default = true; example = false; }; family = { ethernet-switching = { enable = mkEnableOption "the ethernet switching on this logical interface"; interface-mode = mkOption { type = enum [ "trunk" "access" ]; description = '' Mode of operation for vlan addressing of this interface. "trunk" means that the traffic is tagged, "access" means the traffic is tagged by the switch. ''; }; vlans = mkOption { type = listOf (either str ints.unsigned); default = [ ]; description = '' Vlans that can be used on this interface. Only one ID should be here for "access" mode of operation. ''; }; }; #TODO : DHCP inet = { enable = mkEnableOption "the IPv4 configuration of this logical interface"; addresses = mkOption { type = listOf str; default = [ ]; description = '' ipv4 addresses of this interface. ''; }; }; inet6 = { enable = mkEnableOption "the IPv6 configuration of this logical interface"; addresses = mkOption { type = listOf str; default = [ ]; description = '' ipv6 addresses of this interface. ''; }; }; }; xml = mkOption { type = xml.type; visible = false; readOnly = true; }; }; config.xml = let eth = mkIf config.family.ethernet-switching.enable { family.ethernet-switching = { interface-mode = config.family.ethernet-switching.interface-mode; vlan.members = map toString config.family.ethernet-switching.vlans; storm-control.profile-name = "default"; }; }; addr4 = map (name: { inherit name; }) config.family.inet.addresses; inet = mkIf config.family.inet.enable { family.inet.address = addr4; }; addr6 = map (name: { inherit name; }) config.family.inet6.addresses; inet6 = mkIf config.family.inet6.enable { family.inet6.address = addr6; }; in mkMerge [ { inherit name; } (mkIf (!config.enable) { disable = { }; }) eth inet inet6 ]; }; in { options = { enable = mkEnableOption "this physical interface"; unit = mkOption { type = attrsOf (submodule unit); default = { }; description = '' Configuration of the logical interfaces on this physical interface. ''; }; xml = mkOption { type = xml.type; visible = false; readOnly = true; }; }; config.xml = let unit = mapAttrsToList (_: unit: unit.xml) config.unit; in mkMerge [ { inherit name unit; } (mkIf (!config.enable) { disable = { }; }) ]; }; in { options = { interfaces = mkOption { type = attrsOf (submodule interface); description = '' The interfaces configuration. ''; }; }; config.netconf.xml.interfaces = { "@operation" = "replace"; interface = mapAttrsToList (_: intf: intf.xml) config.interfaces; }; }