[pve-devel] [PATCH proxmox-ve-rs v4 06/22] frr: add openfabric types

Wolfgang Bumiller w.bumiller at proxmox.com
Mon Jul 7 13:25:03 CEST 2025


On Wed, Jul 02, 2025 at 04:49:57PM +0200, Gabriel Goller wrote:
> Implement OpenFabric-specific variants of common enums that
> encapsulate protocol properties defined in proxmox-network-types. The
> primary addition is OpenFabricInterface, which stores
> protocol-specific timing parameters: HelloInterval (neighbor discovery
> frequency), CsnpInterval (database synchronization frequency), and
> HelloMultiplier (neighbor failure detection). Added `is_ipv6` flag to
> support FRR's command prefixing requirements during serialization for
> IPv6-specific commands (we need to add a 'ipv6' prefix to some
> commands).
> 
> Signed-off-by: Gabriel Goller <g.goller at proxmox.com>
> ---
>  proxmox-frr/debian/control    |   2 +
>  proxmox-frr/src/lib.rs        |   1 +
>  proxmox-frr/src/openfabric.rs | 114 ++++++++++++++++++++++++++++++++++
>  3 files changed, 117 insertions(+)
>  create mode 100644 proxmox-frr/src/openfabric.rs
> 
> diff --git a/proxmox-frr/debian/control b/proxmox-frr/debian/control
> index 07b4fbe87629..894bfeac8a65 100644
> --- a/proxmox-frr/debian/control
> +++ b/proxmox-frr/debian/control
> @@ -9,6 +9,7 @@ Build-Depends-Arch: cargo:native <!nocheck>,
>   librust-anyhow-1+default-dev <!nocheck>,
>   librust-itoa-1+default-dev (>= 1.0.9-~~) <!nocheck>,
>   librust-proxmox-network-types-0.1+default-dev <!nocheck>,
> + librust-proxmox-sdn-types-0.1+default-dev <!nocheck>,
>   librust-serde-1+default-dev <!nocheck>,
>   librust-serde-1+derive-dev <!nocheck>,
>   librust-serde-with-3+default-dev <!nocheck>,
> @@ -30,6 +31,7 @@ Depends:
>   librust-anyhow-1+default-dev,
>   librust-itoa-1+default-dev (>= 1.0.9-~~),
>   librust-proxmox-network-types-0.1+default-dev,
> + librust-proxmox-sdn-types-0.1+default-dev,
>   librust-serde-1+default-dev,
>   librust-serde-1+derive-dev,
>   librust-serde-with-3+default-dev,
> diff --git a/proxmox-frr/src/lib.rs b/proxmox-frr/src/lib.rs
> index 5e0b34602cf4..ba9eedfb4549 100644
> --- a/proxmox-frr/src/lib.rs
> +++ b/proxmox-frr/src/lib.rs
> @@ -1,3 +1,4 @@
> +pub mod openfabric;
>  use std::{fmt::Display, str::FromStr};
>  
>  use serde::{Deserialize, Serialize};
> diff --git a/proxmox-frr/src/openfabric.rs b/proxmox-frr/src/openfabric.rs
> new file mode 100644
> index 000000000000..91c18dc27254
> --- /dev/null
> +++ b/proxmox-frr/src/openfabric.rs
> @@ -0,0 +1,114 @@
> +use std::fmt::Debug;
> +use std::fmt::Display;
> +
> +use proxmox_sdn_types::net::Net;
> +use serde::{Deserialize, Serialize};
> +use serde_with::SerializeDisplay;
> +
> +use thiserror::Error;
> +
> +use crate::FrrWord;
> +use crate::FrrWordError;
> +
> +/// The name of a OpenFabric router. Is an FrrWord.
> +#[derive(Clone, Debug, PartialEq, Eq, Hash, Deserialize, SerializeDisplay, PartialOrd, Ord)]
> +pub struct OpenfabricRouterName(FrrWord);
> +
> +impl From<FrrWord> for OpenfabricRouterName {
> +    fn from(value: FrrWord) -> Self {
> +        Self(value)
> +    }
> +}
> +
> +impl OpenfabricRouterName {
> +    pub fn new(name: FrrWord) -> Self {
> +        Self(name)
> +    }
> +}
> +
> +impl Display for OpenfabricRouterName {
> +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
> +        write!(f, "openfabric {}", self.0)
> +    }
> +}
> +
> +/// All the properties a OpenFabric router can hold.
> +///
> +/// These can serialized with a " " space prefix as they are in the `router openfabric` block.
> +#[derive(Clone, Debug, PartialEq, Eq, Hash, Deserialize, Serialize, PartialOrd, Ord)]
> +pub struct OpenfabricRouter {
> +    /// The NET address
> +    pub net: Net,
> +}
> +
> +impl OpenfabricRouter {
> +    pub fn new(net: Net) -> Self {
> +        Self { net }
> +    }
> +
> +    pub fn net(&self) -> &Net {
> +        &self.net
> +    }
> +}
> +
> +/// The OpenFabric properties.
> +///
> +/// This struct holds all the OpenFabric interface properties. The most important one here is the
> +/// fabric_id, which ties the interface to a fabric. When serialized these properties all get
> +/// prefixed with a space (" ") as they are inside the interface block. They serialize roughly to:
> +///
> +/// ```text
> +/// interface ens20
> +///  ip router openfabric <fabric_id>
> +///  ipv6 router openfabric <fabric_id>
> +///  openfabric hello-interval <value>
> +///  openfabric hello-multiplier <value>
> +///  openfabric csnp-interval <value>
> +///  openfabric passive <value>
> +/// ```
> +///
> +/// The is_ipv4 and is_ipv6 properties decide if we need to add `ip router openfabric`, `ipv6
> +/// router openfabric`, or both. A interface can only be part of a single fabric.

An*

> +#[derive(Clone, Debug, PartialEq, Eq, Hash, Deserialize, Serialize, PartialOrd, Ord)]
> +pub struct OpenfabricInterface {
> +    // Note: an interface can only be a part of a single fabric (so no vec needed here)
> +    pub fabric_id: OpenfabricRouterName,
> +    pub passive: Option<bool>,

^ So in  `FrrSerializer` we do all this manually - but for the derived
`Serialize` implementation, shouldn't we have a
`#[serde(skip_serializing_if = "Option::is_none")` here?

(and probably also down below...)

> +    pub hello_interval: Option<proxmox_sdn_types::openfabric::HelloInterval>,
> +    pub csnp_interval: Option<proxmox_sdn_types::openfabric::CsnpInterval>,
> +    pub hello_multiplier: Option<proxmox_sdn_types::openfabric::HelloMultiplier>,
> +    pub is_ipv4: bool,
> +    pub is_ipv6: bool,
> +}
> +
> +impl OpenfabricInterface {

If the struct and its fields are all `pub` - why do we need/want getters?

> +    pub fn fabric_id(&self) -> &OpenfabricRouterName {
> +        &self.fabric_id
> +    }
> +    pub fn passive(&self) -> Option<bool> {
> +        self.passive
> +    }
> +    pub fn hello_interval(&self) -> Option<proxmox_sdn_types::openfabric::HelloInterval> {
> +        self.hello_interval
> +    }
> +    pub fn csnp_interval(&self) -> Option<proxmox_sdn_types::openfabric::CsnpInterval> {
> +        self.csnp_interval
> +    }
> +    pub fn hello_multiplier(&self) -> Option<proxmox_sdn_types::openfabric::HelloMultiplier> {
> +        self.hello_multiplier
> +    }
> +    pub fn set_hello_interval(
> +        &mut self,
> +        interval: impl Into<Option<proxmox_sdn_types::openfabric::HelloInterval>>,
> +    ) {
> +        self.hello_interval = interval.into();
> +    }
> +}
> +
> +#[derive(Error, Debug)]
> +pub enum OpenfabricInterfaceError {
> +    #[error("Unknown error converting to OpenFabricInterface")]
> +    UnknownError,
> +    #[error("Error parsing frr word")]
> +    FrrWordParse(#[from] FrrWordError),
> +}
> -- 
> 2.39.5




More information about the pve-devel mailing list