{ config, lib, ... }: with lib; let intf-mod = { config, ... }: { options = { enable = mkEnableOption "this interface" // { default = config.inet.enable || config.inet6.enable || config.ethernet-switching.enable; defaultText = ''config.inet.enable || config.inet6.enable || config.ethernet-switching.enable''; }; poe = mkEnableOption "the PoE on this interface"; ethernet-switching = { enable = mkEnableOption "the ethernet switching on this interface" // { default = config.ethernet-switching.interface-mode != null; defaultText = ''config.ethernet-switching.interface-mode != null''; }; rstp = mkEnableOption "RSTP on this interface" // { default = config.ethernet-switching.enable; defaultText = ''config.ethernet-switching.enable''; }; interface-mode = mkOption { type = types.nullOr ( types.enum [ "trunk" "access" ] ); default = null; 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. Use null to desactivate the switching. ''; }; vlans = mkOption { type = types.listOf (types.either types.str types.ints.unsigned); default = [ ]; description = '' Vlans that can be used on this interface. Only one ID should be here for "access" mode of operation. ''; }; }; inet = { enable = mkEnableOption "the ipv4 on this interface" // { default = config.inet.addresses != [ ]; defaultText = ''config.inet.addresses != [ ]''; }; addresses = mkOption { type = types.listOf types.str; default = [ ]; description = '' ipv4 addresses of this interface. ''; }; }; inet6 = { enable = mkEnableOption "the ipv6 on this interface" // { default = config.inet6.addresses != [ ]; defaultText = ''config.inet6.addresses != [ ]''; }; addresses = mkOption { type = types.listOf types.str; default = [ ]; description = '' ipv6 addresses of this interface. ''; }; }; }; }; cfg = config.dgn-interfaces; in { options.dgn-interfaces = mkOption { type = types.attrsOf (types.submodule intf-mod); default = { }; description = '' Unified configuration of interfaces adapted to DGNum usage: - each interfaces have only one logical subinterface; - enabling ethernet-switching also enable RSTP; - automatic enabling interface and relevant config family when configuring; - allows enabling PoE along other configurations. ''; }; config = { interfaces = mapAttrs (_: intf: { inherit (intf) enable; unit."0".family = { inherit (intf) inet inet6; ethernet-switching = mkIf intf.ethernet-switching.enable (removeAttrs intf.ethernet-switching [ "rstp" ]); }; }) cfg; poe.interfaces = filterAttrs ( name: _: config.netconf.mandatoryInterfaces.${name}.supportPoE or false ) (mapAttrs (_: intf: { enable = intf.poe; }) cfg); protocols.rstp = attrNames (filterAttrs (_: intf: intf.ethernet-switching.rstp) cfg); }; }