infrastructure/lib/netconf-junos/interfaces.nix

172 lines
5.1 KiB
Nix

# SPDX-FileCopyrightText: 2024 Lubin Bailly <lubin.bailly@dgnum.eu>
#
# SPDX-License-Identifier: EUPL-1.2
{ config, lib, ... }:
let
inherit (lib)
mapAttrsToList
mkEnableOption
mkOption
optionalString
;
inherit (lib.types)
attrsOf
either
enum
ints
listOf
str
submodule
;
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 = str;
visible = false;
readOnly = true;
};
};
config.xml =
let
members = map (
vlan: "<members>${builtins.toString vlan}</members>"
) config.family.ethernet-switching.vlans;
eth = optionalString config.family.ethernet-switching.enable ''
<ethernet-switching>
<interface-mode>${config.family.ethernet-switching.interface-mode}</interface-mode>
<vlan>${builtins.concatStringsSep "" members}</vlan>
<storm-control><profile-name>default</profile-name></storm-control>
</ethernet-switching>
'';
addr4 = map (addr: "<name>${addr}</name>") config.family.inet.addresses;
inet = optionalString config.family.inet.enable ''
<inet>
<address>${builtins.concatStringsSep "" addr4}</address>
</inet>
'';
addr6 = map (addr: "<name>${addr}</name>") config.family.inet6.addresses;
inet6 = optionalString config.family.inet6.enable ''
<inet6>
<address>${builtins.concatStringsSep "" addr6}</address>
</inet6>
'';
in
''
<unit>
<name>${name}</name>
${optionalString (!config.enable) "<disable/>"}
<family>
${eth}${inet}${inet6}
</family>
</unit>'';
};
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 = str;
visible = false;
readOnly = true;
};
};
config.xml =
let
units = mapAttrsToList (_: unit: unit.xml) config.unit;
in
''
<interface>
<name>${name}</name>
${optionalString (!config.enable) "<disable/>"}
${builtins.concatStringsSep "" units}
</interface>
'';
};
in
{
options = {
interfaces = mkOption {
type = attrsOf (submodule interface);
description = ''
The interfaces configuration.
'';
};
netconf.xmls.interfaces = mkOption {
type = str;
visible = false;
readOnly = true;
};
};
config.netconf.xmls.interfaces = ''
<interfaces operation="replace">
${builtins.concatStringsSep "" (mapAttrsToList (_: intf: intf.xml) config.interfaces)}
</interfaces>
'';
}