[pve-devel] [PATCH proxmox-ve-rs v4 16/22] config: sdn: fabrics: add section config

Wolfgang Bumiller w.bumiller at proxmox.com
Tue Jul 8 10:18:46 CEST 2025


On Wed, Jul 02, 2025 at 04:50:07PM +0200, Gabriel Goller wrote:
> From: Stefan Hanreich <s.hanreich at proxmox.com>
> 
> The Section type represents the configuration as stored in
> '/etc/pve/sdn/fabrics.cfg'. It can contain a mix of fabric and node
> sections, which are in turn unique to each protocol. We utilize the
> generic FabricSection and NodeSection types to define every possible
> section type in the section config. We also provide a helper for
> sorting the sections in the configuration file into Fabrics and Nodes,
> as well as conversion from / to the Fabric and Node types.
> 
> Co-authored-by: Gabriel Goller <g.goller at proxmox.com>
> Signed-off-by: Stefan Hanreich <s.hanreich at proxmox.com>
> ---
>  .../src/sdn/fabric/section_config/mod.rs      | 105 ++++++++++++++++++
>  1 file changed, 105 insertions(+)
> 
> diff --git a/proxmox-ve-config/src/sdn/fabric/section_config/mod.rs b/proxmox-ve-config/src/sdn/fabric/section_config/mod.rs
> index 7db378837eb1..174ea4d126c5 100644
> --- a/proxmox-ve-config/src/sdn/fabric/section_config/mod.rs
> +++ b/proxmox-ve-config/src/sdn/fabric/section_config/mod.rs
> @@ -2,3 +2,108 @@ pub mod fabric;
>  pub mod interface;
>  pub mod node;
>  pub mod protocol;
> +
> +use const_format::concatcp;
> +use serde::{Deserialize, Serialize};
> +
> +use crate::sdn::fabric::section_config::{
> +    fabric::{Fabric, FabricSection, FABRIC_ID_REGEX_STR},
> +    node::{Node, NodeSection, NODE_ID_REGEX_STR},
> +    protocol::{
> +        openfabric::{OpenfabricNodeProperties, OpenfabricProperties},
> +        ospf::{OspfNodeProperties, OspfProperties},
> +    },
> +};
> +
> +use proxmox_schema::{api, const_regex, ApiStringFormat};
> +
> +/// Represents a value that can be one of two given types.
> +///
> +/// This is used for the fabrics section config, where values could either be Fabrics or Nodes. It

Then please make it  `Fabric(F)` and `Node(N)` instead of `Left` and
`Right`...

A local helper type with a completely generic name and variant names is
just confusing otherwise.

> +/// can be used to split the sections contained in the config into their concrete types safely.
> +pub enum Either<L, R> {
> +    Left(L),
> +    Right(R),
> +}
> +
> +impl From<Section> for Either<Fabric, Node> {
> +    fn from(section: Section) -> Self {
> +        match section {
> +            Section::OpenfabricFabric(fabric_section) => Self::Left(fabric_section.into()),
> +            Section::OspfFabric(fabric_section) => Self::Left(fabric_section.into()),
> +            Section::OpenfabricNode(node_section) => Self::Right(node_section.into()),
> +            Section::OspfNode(node_section) => Self::Right(node_section.into()),
> +        }
> +    }
> +}
> +
> +const_regex! {
> +    pub SECTION_ID_REGEX = concatcp!(r"^", FABRIC_ID_REGEX_STR, r"(?:_", NODE_ID_REGEX_STR, r")?$");
> +}
> +
> +pub const SECTION_ID_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&SECTION_ID_REGEX);
> +
> +/// A section in the SDN fabrics config.
> +///
> +/// It contains two variants for every protocol: The fabric and the node. They are represented
> +/// respectively by [`FabricSection`] and [`NodeSection`] which encapsulate the common properties
> +/// of fabrics and nodes and take the specific properties for the protocol as a type parameter.
> +#[api(
> +    "id-property": "id",
> +    "id-schema": {
> +        type: String,
> +        description: "fabric/node id",
> +        format: &SECTION_ID_FORMAT,
> +    },
> +    "type-key": "type",
> +)]
> +#[derive(Debug, Clone, Serialize, Deserialize)]
> +#[serde(rename_all = "snake_case", tag = "type")]
> +pub enum Section {
> +    OpenfabricFabric(FabricSection<OpenfabricProperties>),
> +    OspfFabric(FabricSection<OspfProperties>),
> +    OpenfabricNode(NodeSection<OpenfabricNodeProperties>),
> +    OspfNode(NodeSection<OspfNodeProperties>),
> +}
> +
> +impl From<FabricSection<OpenfabricProperties>> for Section {
> +    fn from(section: FabricSection<OpenfabricProperties>) -> Self {
> +        Self::OpenfabricFabric(section)
> +    }
> +}
> +
> +impl From<FabricSection<OspfProperties>> for Section {
> +    fn from(section: FabricSection<OspfProperties>) -> Self {
> +        Self::OspfFabric(section)
> +    }
> +}
> +
> +impl From<NodeSection<OpenfabricNodeProperties>> for Section {
> +    fn from(section: NodeSection<OpenfabricNodeProperties>) -> Self {
> +        Self::OpenfabricNode(section)
> +    }
> +}
> +
> +impl From<NodeSection<OspfNodeProperties>> for Section {
> +    fn from(section: NodeSection<OspfNodeProperties>) -> Self {
> +        Self::OspfNode(section)
> +    }
> +}
> +
> +impl From<Fabric> for Section {
> +    fn from(fabric: Fabric) -> Self {
> +        match fabric {
> +            Fabric::Openfabric(fabric_section) => fabric_section.into(),
> +            Fabric::Ospf(fabric_section) => fabric_section.into(),
> +        }
> +    }
> +}
> +
> +impl From<Node> for Section {
> +    fn from(node: Node) -> Self {
> +        match node {
> +            Node::Openfabric(node_section) => node_section.into(),
> +            Node::Ospf(node_section) => node_section.into(),
> +        }
> +    }
> +}
> -- 
> 2.39.5




More information about the pve-devel mailing list