[pve-devel] [PATCH proxmox-ve-rs v2 1/2] frr: make room for deserialization structs
Gabriel Goller
g.goller at proxmox.com
Fri Aug 22 11:00:33 CEST 2025
Move all the serialization structs to a new subfolder `ser`. This makes
place for the deserialization structs which will land in a new folder
`de`. The deserialization structs will be used to parse the output of
`vtysh` commands, so that we can show statistics of various sdn objects.
Also update all the callsites to use the new subfolder.
Signed-off-by: Gabriel Goller <g.goller at proxmox.com>
---
proxmox-frr/src/lib.rs | 242 +-----------------------
proxmox-frr/src/ser/mod.rs | 241 +++++++++++++++++++++++
proxmox-frr/src/{ => ser}/openfabric.rs | 4 +-
proxmox-frr/src/{ => ser}/ospf.rs | 2 +-
proxmox-frr/src/{ => ser}/route_map.rs | 0
proxmox-frr/src/{ => ser}/serializer.rs | 2 +-
proxmox-ve-config/src/sdn/fabric/frr.rs | 170 +++++++++--------
proxmox-ve-config/src/sdn/frr.rs | 2 +-
proxmox-ve-config/tests/fabric/main.rs | 2 +-
9 files changed, 340 insertions(+), 325 deletions(-)
create mode 100644 proxmox-frr/src/ser/mod.rs
rename proxmox-frr/src/{ => ser}/openfabric.rs (97%)
rename proxmox-frr/src/{ => ser}/ospf.rs (99%)
rename proxmox-frr/src/{ => ser}/route_map.rs (100%)
rename proxmox-frr/src/{ => ser}/serializer.rs (99%)
diff --git a/proxmox-frr/src/lib.rs b/proxmox-frr/src/lib.rs
index 86101182fafd..35b62cb39c91 100644
--- a/proxmox-frr/src/lib.rs
+++ b/proxmox-frr/src/lib.rs
@@ -1,241 +1 @@
-pub mod openfabric;
-pub mod ospf;
-pub mod route_map;
-pub mod serializer;
-
-use std::collections::{BTreeMap, BTreeSet};
-use std::fmt::Display;
-use std::str::FromStr;
-
-use crate::route_map::{AccessList, ProtocolRouteMap, RouteMap};
-
-use thiserror::Error;
-
-/// Generic FRR router.
-///
-/// This generic FRR router contains all the protocols that we implement.
-/// In FRR this is e.g.:
-/// ```text
-/// router openfabric test
-/// !....
-/// ! or
-/// router ospf
-/// !....
-/// ```
-#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
-pub enum Router {
- Openfabric(openfabric::OpenfabricRouter),
- Ospf(ospf::OspfRouter),
-}
-
-impl From<openfabric::OpenfabricRouter> for Router {
- fn from(value: openfabric::OpenfabricRouter) -> Self {
- Router::Openfabric(value)
- }
-}
-
-/// Generic FRR routername.
-///
-/// The variants represent different protocols. Some have `router <protocol> <name>`, others have
-/// `router <protocol> <process-id>`, some only have `router <protocol>`.
-#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
-pub enum RouterName {
- Openfabric(openfabric::OpenfabricRouterName),
- Ospf(ospf::OspfRouterName),
-}
-
-impl From<openfabric::OpenfabricRouterName> for RouterName {
- fn from(value: openfabric::OpenfabricRouterName) -> Self {
- Self::Openfabric(value)
- }
-}
-
-impl Display for RouterName {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- match self {
- Self::Openfabric(r) => r.fmt(f),
- Self::Ospf(r) => r.fmt(f),
- }
- }
-}
-
-/// The interface name is the same on ospf and openfabric, but it is an enum so that we can have
-/// two different entries in the btreemap. This allows us to have an interface in a ospf and
-/// openfabric fabric.
-#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
-pub enum InterfaceName {
- Openfabric(CommonInterfaceName),
- Ospf(CommonInterfaceName),
-}
-
-impl Display for InterfaceName {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- match self {
- InterfaceName::Openfabric(frr_word) => frr_word.fmt(f),
- InterfaceName::Ospf(frr_word) => frr_word.fmt(f),
- }
- }
-}
-
-/// Generic FRR Interface.
-///
-/// In FRR config it looks like this:
-/// ```text
-/// interface <name>
-/// ! ...
-#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
-pub enum Interface {
- Openfabric(openfabric::OpenfabricInterface),
- Ospf(ospf::OspfInterface),
-}
-
-impl From<openfabric::OpenfabricInterface> for Interface {
- fn from(value: openfabric::OpenfabricInterface) -> Self {
- Self::Openfabric(value)
- }
-}
-
-impl From<ospf::OspfInterface> for Interface {
- fn from(value: ospf::OspfInterface) -> Self {
- Self::Ospf(value)
- }
-}
-
-#[derive(Error, Debug)]
-pub enum FrrWordError {
- #[error("word is empty")]
- IsEmpty,
- #[error("word contains invalid character")]
- InvalidCharacter,
-}
-
-/// A simple FRR Word.
-///
-/// Every string argument or value in FRR is an FrrWord. FrrWords must only contain ascii
-/// characters and must not have a whitespace.
-#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
-pub struct FrrWord(String);
-
-impl FrrWord {
- pub fn new<T: AsRef<str> + Into<String>>(name: T) -> Result<Self, FrrWordError> {
- if name.as_ref().is_empty() {
- return Err(FrrWordError::IsEmpty);
- }
-
- if name
- .as_ref()
- .as_bytes()
- .iter()
- .any(|c| !c.is_ascii() || c.is_ascii_whitespace())
- {
- eprintln!("invalid char in: \"{}\"", name.as_ref());
- return Err(FrrWordError::InvalidCharacter);
- }
-
- Ok(Self(name.into()))
- }
-}
-
-impl FromStr for FrrWord {
- type Err = FrrWordError;
-
- fn from_str(s: &str) -> Result<Self, Self::Err> {
- Self::new(s)
- }
-}
-
-impl Display for FrrWord {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- self.0.fmt(f)
- }
-}
-
-impl AsRef<str> for FrrWord {
- fn as_ref(&self) -> &str {
- &self.0
- }
-}
-
-#[derive(Error, Debug)]
-pub enum CommonInterfaceNameError {
- #[error("interface name too long")]
- TooLong,
-}
-
-/// Name of a interface, which is common between all protocols.
-///
-/// FRR itself doesn't enforce any limits, but the kernel does. Linux only allows interface names
-/// to be a maximum of 16 bytes. This is enforced by this struct.
-#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
-pub struct CommonInterfaceName(String);
-
-impl TryFrom<&str> for CommonInterfaceName {
- type Error = CommonInterfaceNameError;
-
- fn try_from(value: &str) -> Result<Self, Self::Error> {
- Self::new(value)
- }
-}
-
-impl TryFrom<String> for CommonInterfaceName {
- type Error = CommonInterfaceNameError;
-
- fn try_from(value: String) -> Result<Self, Self::Error> {
- Self::new(value)
- }
-}
-
-impl CommonInterfaceName {
- pub fn new<T: AsRef<str> + Into<String>>(s: T) -> Result<Self, CommonInterfaceNameError> {
- if s.as_ref().len() <= 15 {
- Ok(Self(s.into()))
- } else {
- Err(CommonInterfaceNameError::TooLong)
- }
- }
-}
-
-impl Display for CommonInterfaceName {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- self.0.fmt(f)
- }
-}
-
-/// Main FRR config.
-///
-/// Contains the two main frr building blocks: routers and interfaces. It also holds other
-/// top-level FRR options, such as access-lists, router-maps and protocol-routemaps. This struct
-/// gets generated using the `FrrConfigBuilder` in `proxmox-ve-config`.
-#[derive(Clone, Debug, PartialEq, Eq, Default)]
-pub struct FrrConfig {
- pub router: BTreeMap<RouterName, Router>,
- pub interfaces: BTreeMap<InterfaceName, Interface>,
- pub access_lists: Vec<AccessList>,
- pub routemaps: Vec<RouteMap>,
- pub protocol_routemaps: BTreeSet<ProtocolRouteMap>,
-}
-
-impl FrrConfig {
- pub fn new() -> Self {
- Self::default()
- }
-
- pub fn router(&self) -> impl Iterator<Item = (&RouterName, &Router)> + '_ {
- self.router.iter()
- }
-
- pub fn interfaces(&self) -> impl Iterator<Item = (&InterfaceName, &Interface)> + '_ {
- self.interfaces.iter()
- }
-
- pub fn access_lists(&self) -> impl Iterator<Item = &AccessList> + '_ {
- self.access_lists.iter()
- }
- pub fn routemaps(&self) -> impl Iterator<Item = &RouteMap> + '_ {
- self.routemaps.iter()
- }
-
- pub fn protocol_routemaps(&self) -> impl Iterator<Item = &ProtocolRouteMap> + '_ {
- self.protocol_routemaps.iter()
- }
-}
+pub mod ser;
diff --git a/proxmox-frr/src/ser/mod.rs b/proxmox-frr/src/ser/mod.rs
new file mode 100644
index 000000000000..a90397b59a9b
--- /dev/null
+++ b/proxmox-frr/src/ser/mod.rs
@@ -0,0 +1,241 @@
+pub mod openfabric;
+pub mod ospf;
+pub mod route_map;
+pub mod serializer;
+
+use std::collections::{BTreeMap, BTreeSet};
+use std::fmt::Display;
+use std::str::FromStr;
+
+use crate::ser::route_map::{AccessList, ProtocolRouteMap, RouteMap};
+
+use thiserror::Error;
+
+/// Generic FRR router.
+///
+/// This generic FRR router contains all the protocols that we implement.
+/// In FRR this is e.g.:
+/// ```text
+/// router openfabric test
+/// !....
+/// ! or
+/// router ospf
+/// !....
+/// ```
+#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+pub enum Router {
+ Openfabric(openfabric::OpenfabricRouter),
+ Ospf(ospf::OspfRouter),
+}
+
+impl From<openfabric::OpenfabricRouter> for Router {
+ fn from(value: openfabric::OpenfabricRouter) -> Self {
+ Router::Openfabric(value)
+ }
+}
+
+/// Generic FRR routername.
+///
+/// The variants represent different protocols. Some have `router <protocol> <name>`, others have
+/// `router <protocol> <process-id>`, some only have `router <protocol>`.
+#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+pub enum RouterName {
+ Openfabric(openfabric::OpenfabricRouterName),
+ Ospf(ospf::OspfRouterName),
+}
+
+impl From<openfabric::OpenfabricRouterName> for RouterName {
+ fn from(value: openfabric::OpenfabricRouterName) -> Self {
+ Self::Openfabric(value)
+ }
+}
+
+impl Display for RouterName {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ match self {
+ Self::Openfabric(r) => r.fmt(f),
+ Self::Ospf(r) => r.fmt(f),
+ }
+ }
+}
+
+/// The interface name is the same on ospf and openfabric, but it is an enum so that we can have
+/// two different entries in the btreemap. This allows us to have an interface in a ospf and
+/// openfabric fabric.
+#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+pub enum InterfaceName {
+ Openfabric(CommonInterfaceName),
+ Ospf(CommonInterfaceName),
+}
+
+impl Display for InterfaceName {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ match self {
+ InterfaceName::Openfabric(frr_word) => frr_word.fmt(f),
+ InterfaceName::Ospf(frr_word) => frr_word.fmt(f),
+ }
+ }
+}
+
+/// Generic FRR Interface.
+///
+/// In FRR config it looks like this:
+/// ```text
+/// interface <name>
+/// ! ...
+#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+pub enum Interface {
+ Openfabric(openfabric::OpenfabricInterface),
+ Ospf(ospf::OspfInterface),
+}
+
+impl From<openfabric::OpenfabricInterface> for Interface {
+ fn from(value: openfabric::OpenfabricInterface) -> Self {
+ Self::Openfabric(value)
+ }
+}
+
+impl From<ospf::OspfInterface> for Interface {
+ fn from(value: ospf::OspfInterface) -> Self {
+ Self::Ospf(value)
+ }
+}
+
+#[derive(Error, Debug)]
+pub enum FrrWordError {
+ #[error("word is empty")]
+ IsEmpty,
+ #[error("word contains invalid character")]
+ InvalidCharacter,
+}
+
+/// A simple FRR Word.
+///
+/// Every string argument or value in FRR is an FrrWord. FrrWords must only contain ascii
+/// characters and must not have a whitespace.
+#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+pub struct FrrWord(String);
+
+impl FrrWord {
+ pub fn new<T: AsRef<str> + Into<String>>(name: T) -> Result<Self, FrrWordError> {
+ if name.as_ref().is_empty() {
+ return Err(FrrWordError::IsEmpty);
+ }
+
+ if name
+ .as_ref()
+ .as_bytes()
+ .iter()
+ .any(|c| !c.is_ascii() || c.is_ascii_whitespace())
+ {
+ eprintln!("invalid char in: \"{}\"", name.as_ref());
+ return Err(FrrWordError::InvalidCharacter);
+ }
+
+ Ok(Self(name.into()))
+ }
+}
+
+impl FromStr for FrrWord {
+ type Err = FrrWordError;
+
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ Self::new(s)
+ }
+}
+
+impl Display for FrrWord {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ self.0.fmt(f)
+ }
+}
+
+impl AsRef<str> for FrrWord {
+ fn as_ref(&self) -> &str {
+ &self.0
+ }
+}
+
+#[derive(Error, Debug)]
+pub enum CommonInterfaceNameError {
+ #[error("interface name too long")]
+ TooLong,
+}
+
+/// Name of a interface, which is common between all protocols.
+///
+/// FRR itself doesn't enforce any limits, but the kernel does. Linux only allows interface names
+/// to be a maximum of 16 bytes. This is enforced by this struct.
+#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+pub struct CommonInterfaceName(String);
+
+impl TryFrom<&str> for CommonInterfaceName {
+ type Error = CommonInterfaceNameError;
+
+ fn try_from(value: &str) -> Result<Self, Self::Error> {
+ Self::new(value)
+ }
+}
+
+impl TryFrom<String> for CommonInterfaceName {
+ type Error = CommonInterfaceNameError;
+
+ fn try_from(value: String) -> Result<Self, Self::Error> {
+ Self::new(value)
+ }
+}
+
+impl CommonInterfaceName {
+ pub fn new<T: AsRef<str> + Into<String>>(s: T) -> Result<Self, CommonInterfaceNameError> {
+ if s.as_ref().len() <= 15 {
+ Ok(Self(s.into()))
+ } else {
+ Err(CommonInterfaceNameError::TooLong)
+ }
+ }
+}
+
+impl Display for CommonInterfaceName {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ self.0.fmt(f)
+ }
+}
+
+/// Main FRR config.
+///
+/// Contains the two main frr building blocks: routers and interfaces. It also holds other
+/// top-level FRR options, such as access-lists, router-maps and protocol-routemaps. This struct
+/// gets generated using the `FrrConfigBuilder` in `proxmox-ve-config`.
+#[derive(Clone, Debug, PartialEq, Eq, Default)]
+pub struct FrrConfig {
+ pub router: BTreeMap<RouterName, Router>,
+ pub interfaces: BTreeMap<InterfaceName, Interface>,
+ pub access_lists: Vec<AccessList>,
+ pub routemaps: Vec<RouteMap>,
+ pub protocol_routemaps: BTreeSet<ProtocolRouteMap>,
+}
+
+impl FrrConfig {
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ pub fn router(&self) -> impl Iterator<Item = (&RouterName, &Router)> + '_ {
+ self.router.iter()
+ }
+
+ pub fn interfaces(&self) -> impl Iterator<Item = (&InterfaceName, &Interface)> + '_ {
+ self.interfaces.iter()
+ }
+
+ pub fn access_lists(&self) -> impl Iterator<Item = &AccessList> + '_ {
+ self.access_lists.iter()
+ }
+ pub fn routemaps(&self) -> impl Iterator<Item = &RouteMap> + '_ {
+ self.routemaps.iter()
+ }
+
+ pub fn protocol_routemaps(&self) -> impl Iterator<Item = &ProtocolRouteMap> + '_ {
+ self.protocol_routemaps.iter()
+ }
+}
diff --git a/proxmox-frr/src/openfabric.rs b/proxmox-frr/src/ser/openfabric.rs
similarity index 97%
rename from proxmox-frr/src/openfabric.rs
rename to proxmox-frr/src/ser/openfabric.rs
index 6e2a7200ab37..0f0c65062d36 100644
--- a/proxmox-frr/src/openfabric.rs
+++ b/proxmox-frr/src/ser/openfabric.rs
@@ -5,8 +5,8 @@ use proxmox_sdn_types::net::Net;
use thiserror::Error;
-use crate::FrrWord;
-use crate::FrrWordError;
+use crate::ser::FrrWord;
+use crate::ser::FrrWordError;
/// The name of a OpenFabric router. Is an FrrWord.
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
diff --git a/proxmox-frr/src/ospf.rs b/proxmox-frr/src/ser/ospf.rs
similarity index 99%
rename from proxmox-frr/src/ospf.rs
rename to proxmox-frr/src/ser/ospf.rs
index d0e098e099d2..67e39a45b8de 100644
--- a/proxmox-frr/src/ospf.rs
+++ b/proxmox-frr/src/ser/ospf.rs
@@ -4,7 +4,7 @@ use std::net::Ipv4Addr;
use thiserror::Error;
-use crate::{FrrWord, FrrWordError};
+use crate::ser::{FrrWord, FrrWordError};
/// The name of the ospf frr router.
///
diff --git a/proxmox-frr/src/route_map.rs b/proxmox-frr/src/ser/route_map.rs
similarity index 100%
rename from proxmox-frr/src/route_map.rs
rename to proxmox-frr/src/ser/route_map.rs
diff --git a/proxmox-frr/src/serializer.rs b/proxmox-frr/src/ser/serializer.rs
similarity index 99%
rename from proxmox-frr/src/serializer.rs
rename to proxmox-frr/src/ser/serializer.rs
index f8a3c7238d94..3a681e2f0d7a 100644
--- a/proxmox-frr/src/serializer.rs
+++ b/proxmox-frr/src/ser/serializer.rs
@@ -1,6 +1,6 @@
use std::fmt::{self, Write};
-use crate::{
+use crate::ser::{
openfabric::{OpenfabricInterface, OpenfabricRouter},
ospf::{OspfInterface, OspfRouter},
route_map::{AccessList, AccessListName, ProtocolRouteMap, RouteMap},
diff --git a/proxmox-ve-config/src/sdn/fabric/frr.rs b/proxmox-ve-config/src/sdn/fabric/frr.rs
index 486f7dc51dcb..10025b3544b9 100644
--- a/proxmox-ve-config/src/sdn/fabric/frr.rs
+++ b/proxmox-ve-config/src/sdn/fabric/frr.rs
@@ -1,12 +1,7 @@
use std::net::{IpAddr, Ipv4Addr};
use tracing;
-use proxmox_frr::ospf::{self, NetworkType};
-use proxmox_frr::route_map::{
- AccessAction, AccessList, AccessListName, AccessListRule, ProtocolRouteMap, ProtocolType,
- RouteMap, RouteMapMatch, RouteMapMatchInner, RouteMapName, RouteMapSet,
-};
-use proxmox_frr::{FrrConfig, FrrWord, Interface, InterfaceName, Router, RouterName};
+use proxmox_frr::ser::{self};
use proxmox_network_types::ip_address::Cidr;
use proxmox_sdn_types::net::Net;
@@ -26,7 +21,7 @@ use crate::sdn::fabric::{FabricConfig, FabricEntry};
pub fn build_fabric(
current_node: NodeId,
config: Valid<FabricConfig>,
- frr_config: &mut FrrConfig,
+ frr_config: &mut ser::FrrConfig,
) -> Result<(), anyhow::Error> {
let mut routemap_seq = 100;
let mut current_router_id: Option<Ipv4Addr> = None;
@@ -93,27 +88,31 @@ pub fn build_fabric(
}
if let Some(ipv4cidr) = fabric.ip_prefix() {
- let rule = AccessListRule {
- action: AccessAction::Permit,
+ let rule = ser::route_map::AccessListRule {
+ action: ser::route_map::AccessAction::Permit,
network: Cidr::from(ipv4cidr),
seq: None,
};
- let access_list_name =
- AccessListName::new(format!("pve_openfabric_{}_ips", fabric_id));
- frr_config.access_lists.push(AccessList {
+ let access_list_name = ser::route_map::AccessListName::new(format!(
+ "pve_openfabric_{}_ips",
+ fabric_id
+ ));
+ frr_config.access_lists.push(ser::route_map::AccessList {
name: access_list_name,
rules: vec![rule],
});
}
if let Some(ipv6cidr) = fabric.ip6_prefix() {
- let rule = AccessListRule {
- action: AccessAction::Permit,
+ let rule = ser::route_map::AccessListRule {
+ action: ser::route_map::AccessAction::Permit,
network: Cidr::from(ipv6cidr),
seq: None,
};
- let access_list_name =
- AccessListName::new(format!("pve_openfabric_{}_ip6s", fabric_id));
- frr_config.access_lists.push(AccessList {
+ let access_list_name = ser::route_map::AccessListName::new(format!(
+ "pve_openfabric_{}_ip6s",
+ fabric_id
+ ));
+ frr_config.access_lists.push(ser::route_map::AccessList {
name: access_list_name,
rules: vec![rule],
});
@@ -128,10 +127,12 @@ pub fn build_fabric(
));
routemap_seq += 10;
- let protocol_routemap = ProtocolRouteMap {
+ let protocol_routemap = ser::route_map::ProtocolRouteMap {
is_ipv6: false,
- protocol: ProtocolType::Openfabric,
- routemap_name: RouteMapName::new("pve_openfabric".to_owned()),
+ protocol: ser::route_map::ProtocolType::Openfabric,
+ routemap_name: ser::route_map::RouteMapName::new(
+ "pve_openfabric".to_owned(),
+ ),
};
frr_config.protocol_routemaps.insert(protocol_routemap);
@@ -145,10 +146,12 @@ pub fn build_fabric(
));
routemap_seq += 10;
- let protocol_routemap = ProtocolRouteMap {
+ let protocol_routemap = ser::route_map::ProtocolRouteMap {
is_ipv6: true,
- protocol: ProtocolType::Openfabric,
- routemap_name: RouteMapName::new("pve_openfabric6".to_owned()),
+ protocol: ser::route_map::ProtocolType::Openfabric,
+ routemap_name: ser::route_map::RouteMapName::new(
+ "pve_openfabric6".to_owned(),
+ ),
};
frr_config.protocol_routemaps.insert(protocol_routemap);
@@ -164,8 +167,8 @@ pub fn build_fabric(
let fabric = ospf_entry.fabric_section();
- let frr_word_area = FrrWord::new(fabric.properties().area.to_string())?;
- let frr_area = ospf::Area::new(frr_word_area)?;
+ let frr_word_area = ser::FrrWord::new(fabric.properties().area.to_string())?;
+ let frr_area = ser::ospf::Area::new(frr_word_area)?;
let (router_name, router_item) = build_ospf_router(*router_id)?;
frr_config.router.insert(router_name, router_item);
@@ -196,17 +199,18 @@ pub fn build_fabric(
}
}
- let access_list_name = AccessListName::new(format!("pve_ospf_{}_ips", fabric_id));
+ let access_list_name =
+ ser::route_map::AccessListName::new(format!("pve_ospf_{}_ips", fabric_id));
- let rule = AccessListRule {
- action: AccessAction::Permit,
+ let rule = ser::route_map::AccessListRule {
+ action: ser::route_map::AccessAction::Permit,
network: Cidr::from(
fabric.ip_prefix().expect("fabric must have a ipv4 prefix"),
),
seq: None,
};
- frr_config.access_lists.push(AccessList {
+ frr_config.access_lists.push(ser::route_map::AccessList {
name: access_list_name,
rules: vec![rule],
});
@@ -220,10 +224,10 @@ pub fn build_fabric(
routemap_seq += 10;
frr_config.routemaps.push(routemap);
- let protocol_routemap = ProtocolRouteMap {
+ let protocol_routemap = ser::route_map::ProtocolRouteMap {
is_ipv6: false,
- protocol: ProtocolType::Ospf,
- routemap_name: RouteMapName::new("pve_ospf".to_owned()),
+ protocol: ser::route_map::ProtocolType::Ospf,
+ routemap_name: ser::route_map::RouteMapName::new("pve_ospf".to_owned()),
};
frr_config.protocol_routemaps.insert(protocol_routemap);
@@ -234,10 +238,10 @@ pub fn build_fabric(
}
/// Helper that builds a OSPF router with a the router_id.
-fn build_ospf_router(router_id: Ipv4Addr) -> Result<(RouterName, Router), anyhow::Error> {
- let ospf_router = proxmox_frr::ospf::OspfRouter { router_id };
- let router_item = Router::Ospf(ospf_router);
- let router_name = RouterName::Ospf(proxmox_frr::ospf::OspfRouterName);
+fn build_ospf_router(router_id: Ipv4Addr) -> Result<(ser::RouterName, ser::Router), anyhow::Error> {
+ let ospf_router = ser::ospf::OspfRouter { router_id };
+ let router_item = ser::Router::Ospf(ospf_router);
+ let router_name = ser::RouterName::Ospf(ser::ospf::OspfRouterName);
Ok((router_name, router_item))
}
@@ -245,45 +249,45 @@ fn build_ospf_router(router_id: Ipv4Addr) -> Result<(RouterName, Router), anyhow
fn build_openfabric_router(
fabric_id: &FabricId,
net: Net,
-) -> Result<(RouterName, Router), anyhow::Error> {
- let ofr = proxmox_frr::openfabric::OpenfabricRouter { net };
- let router_item = Router::Openfabric(ofr);
- let frr_word_id = FrrWord::new(fabric_id.to_string())?;
- let router_name = RouterName::Openfabric(frr_word_id.into());
+) -> Result<(ser::RouterName, ser::Router), anyhow::Error> {
+ let ofr = ser::openfabric::OpenfabricRouter { net };
+ let router_item = ser::Router::Openfabric(ofr);
+ let frr_word_id = ser::FrrWord::new(fabric_id.to_string())?;
+ let router_name = ser::RouterName::Openfabric(frr_word_id.into());
Ok((router_name, router_item))
}
/// Helper that builds a OSPF interface from an [`ospf::Area`] and the [`OspfInterfaceProperties`].
fn build_ospf_interface(
- area: ospf::Area,
+ area: ser::ospf::Area,
interface: &OspfInterfaceProperties,
-) -> Result<(Interface, InterfaceName), anyhow::Error> {
- let frr_interface = proxmox_frr::ospf::OspfInterface {
+) -> Result<(ser::Interface, ser::InterfaceName), anyhow::Error> {
+ let frr_interface = ser::ospf::OspfInterface {
area,
// Interfaces are always none-passive
passive: None,
network_type: if interface.ip.is_some() {
None
} else {
- Some(NetworkType::PointToPoint)
+ Some(ser::ospf::NetworkType::PointToPoint)
},
};
- let interface_name = InterfaceName::Ospf(interface.name.as_str().try_into()?);
+ let interface_name = ser::InterfaceName::Ospf(interface.name.as_str().try_into()?);
Ok((frr_interface.into(), interface_name))
}
/// Helper that builds the OSPF dummy interface using the [`FabricId`] and the [`ospf::Area`].
fn build_ospf_dummy_interface(
fabric_id: &FabricId,
- area: ospf::Area,
-) -> Result<(Interface, InterfaceName), anyhow::Error> {
- let frr_interface = proxmox_frr::ospf::OspfInterface {
+ area: ser::ospf::Area,
+) -> Result<(ser::Interface, ser::InterfaceName), anyhow::Error> {
+ let frr_interface = ser::ospf::OspfInterface {
area,
passive: Some(true),
network_type: None,
};
- let interface_name = InterfaceName::Openfabric(format!("dummy_{}", fabric_id).try_into()?);
+ let interface_name = ser::InterfaceName::Openfabric(format!("dummy_{}", fabric_id).try_into()?);
Ok((frr_interface.into(), interface_name))
}
@@ -297,9 +301,9 @@ fn build_openfabric_interface(
fabric_config: &OpenfabricProperties,
is_ipv4: bool,
is_ipv6: bool,
-) -> Result<(Interface, InterfaceName), anyhow::Error> {
- let frr_word = FrrWord::new(fabric_id.to_string())?;
- let mut frr_interface = proxmox_frr::openfabric::OpenfabricInterface {
+) -> Result<(ser::Interface, ser::InterfaceName), anyhow::Error> {
+ let frr_word = ser::FrrWord::new(fabric_id.to_string())?;
+ let mut frr_interface = ser::openfabric::OpenfabricInterface {
fabric_id: frr_word.into(),
// Every interface is not passive by default
passive: None,
@@ -315,7 +319,7 @@ fn build_openfabric_interface(
if frr_interface.hello_interval.is_none() {
frr_interface.hello_interval = fabric_config.hello_interval;
}
- let interface_name = InterfaceName::Openfabric(interface.name.as_str().try_into()?);
+ let interface_name = ser::InterfaceName::Openfabric(interface.name.as_str().try_into()?);
Ok((frr_interface.into(), interface_name))
}
@@ -324,9 +328,9 @@ fn build_openfabric_dummy_interface(
fabric_id: &FabricId,
is_ipv4: bool,
is_ipv6: bool,
-) -> Result<(Interface, InterfaceName), anyhow::Error> {
- let frr_word = FrrWord::new(fabric_id.to_string())?;
- let frr_interface = proxmox_frr::openfabric::OpenfabricInterface {
+) -> Result<(ser::Interface, ser::InterfaceName), anyhow::Error> {
+ let frr_word = ser::FrrWord::new(fabric_id.to_string())?;
+ let frr_interface = ser::openfabric::OpenfabricInterface {
fabric_id: frr_word.into(),
hello_interval: None,
passive: Some(true),
@@ -335,29 +339,37 @@ fn build_openfabric_dummy_interface(
is_ipv4,
is_ipv6,
};
- let interface_name = InterfaceName::Openfabric(format!("dummy_{}", fabric_id).try_into()?);
+ let interface_name = ser::InterfaceName::Openfabric(format!("dummy_{}", fabric_id).try_into()?);
Ok((frr_interface.into(), interface_name))
}
/// Helper that builds a RouteMap for the OpenFabric protocol.
-fn build_openfabric_routemap(fabric_id: &FabricId, router_ip: IpAddr, seq: u32) -> RouteMap {
+fn build_openfabric_routemap(
+ fabric_id: &FabricId,
+ router_ip: IpAddr,
+ seq: u32,
+) -> ser::route_map::RouteMap {
let routemap_name = match router_ip {
- IpAddr::V4(_) => RouteMapName::new("pve_openfabric".to_owned()),
- IpAddr::V6(_) => RouteMapName::new("pve_openfabric6".to_owned()),
+ IpAddr::V4(_) => ser::route_map::RouteMapName::new("pve_openfabric".to_owned()),
+ IpAddr::V6(_) => ser::route_map::RouteMapName::new("pve_openfabric6".to_owned()),
};
- RouteMap {
+ ser::route_map::RouteMap {
name: routemap_name.clone(),
seq,
- action: AccessAction::Permit,
+ action: ser::route_map::AccessAction::Permit,
matches: vec![match router_ip {
- IpAddr::V4(_) => RouteMapMatch::V4(RouteMapMatchInner::IpAddress(AccessListName::new(
- format!("pve_openfabric_{fabric_id}_ips"),
- ))),
- IpAddr::V6(_) => RouteMapMatch::V6(RouteMapMatchInner::IpAddress(AccessListName::new(
- format!("pve_openfabric_{fabric_id}_ip6s"),
- ))),
+ IpAddr::V4(_) => {
+ ser::route_map::RouteMapMatch::V4(ser::route_map::RouteMapMatchInner::IpAddress(
+ ser::route_map::AccessListName::new(format!("pve_openfabric_{fabric_id}_ips")),
+ ))
+ }
+ IpAddr::V6(_) => {
+ ser::route_map::RouteMapMatch::V6(ser::route_map::RouteMapMatchInner::IpAddress(
+ ser::route_map::AccessListName::new(format!("pve_openfabric_{fabric_id}_ip6s")),
+ ))
+ }
}],
- sets: vec![RouteMapSet::IpSrc(router_ip)],
+ sets: vec![ser::route_map::RouteMapSet::IpSrc(router_ip)],
}
}
@@ -366,17 +378,19 @@ fn build_ospf_dummy_routemap(
fabric_id: &FabricId,
router_ip: Ipv4Addr,
seq: u32,
-) -> Result<RouteMap, anyhow::Error> {
- let routemap_name = RouteMapName::new("pve_ospf".to_owned());
+) -> Result<ser::route_map::RouteMap, anyhow::Error> {
+ let routemap_name = ser::route_map::RouteMapName::new("pve_ospf".to_owned());
// create route-map
- let routemap = RouteMap {
+ let routemap = ser::route_map::RouteMap {
name: routemap_name.clone(),
seq,
- action: AccessAction::Permit,
- matches: vec![RouteMapMatch::V4(RouteMapMatchInner::IpAddress(
- AccessListName::new(format!("pve_ospf_{fabric_id}_ips")),
- ))],
- sets: vec![RouteMapSet::IpSrc(IpAddr::from(router_ip))],
+ action: ser::route_map::AccessAction::Permit,
+ matches: vec![ser::route_map::RouteMapMatch::V4(
+ ser::route_map::RouteMapMatchInner::IpAddress(ser::route_map::AccessListName::new(
+ format!("pve_ospf_{fabric_id}_ips"),
+ )),
+ )],
+ sets: vec![ser::route_map::RouteMapSet::IpSrc(IpAddr::from(router_ip))],
};
Ok(routemap)
diff --git a/proxmox-ve-config/src/sdn/frr.rs b/proxmox-ve-config/src/sdn/frr.rs
index f7929c1f6c16..5d4e4b2ebdbd 100644
--- a/proxmox-ve-config/src/sdn/frr.rs
+++ b/proxmox-ve-config/src/sdn/frr.rs
@@ -1,6 +1,6 @@
use std::collections::{BTreeMap, BTreeSet};
-use proxmox_frr::FrrConfig;
+use proxmox_frr::ser::FrrConfig;
use crate::common::valid::Valid;
use crate::sdn::fabric::{section_config::node::NodeId, FabricConfig};
diff --git a/proxmox-ve-config/tests/fabric/main.rs b/proxmox-ve-config/tests/fabric/main.rs
index 47bbbeb77886..09629d406449 100644
--- a/proxmox-ve-config/tests/fabric/main.rs
+++ b/proxmox-ve-config/tests/fabric/main.rs
@@ -1,5 +1,5 @@
#![cfg(feature = "frr")]
-use proxmox_frr::serializer::dump;
+use proxmox_frr::ser::serializer::dump;
use proxmox_ve_config::sdn::{
fabric::{section_config::node::NodeId, FabricConfig},
frr::FrrConfigBuilder,
--
2.47.2
More information about the pve-devel
mailing list