From 3f626519a0f42d4fc837b770272a905c77893c1f Mon Sep 17 00:00:00 2001 From: Fredi Raspall Date: Tue, 30 Dec 2025 17:28:55 +0100 Subject: [PATCH 1/5] feat(remove-grpc): disable gRPC interface and args * Remove launching of gRPC interface in management * Remove args to pass gRPC address Signed-off-by: Fredi Raspall --- args/src/lib.rs | 79 --------------- dataplane/src/main.rs | 9 -- mgmt/src/processor/launch.rs | 183 +---------------------------------- mgmt/src/processor/proc.rs | 2 +- mgmt/src/tests/mgmt.rs | 2 +- 5 files changed, 5 insertions(+), 270 deletions(-) diff --git a/args/src/lib.rs b/args/src/lib.rs index 5ead9fa62..3db50a7e4 100644 --- a/args/src/lib.rs +++ b/args/src/lib.rs @@ -61,7 +61,6 @@ use std::borrow::Borrow; use std::io::{Read, Seek, SeekFrom, Write}; use std::net::SocketAddr; use std::os::fd::{AsFd, AsRawFd, FromRawFd, OwnedFd, RawFd}; -use std::path::PathBuf; use std::str::FromStr; #[derive( @@ -330,18 +329,6 @@ pub struct GeneralConfigSection { name: Option, } -/// Enum to represent either a TCP socket address or a UNIX socket path -#[derive( - Debug, Clone, PartialEq, Eq, serde::Serialize, rkyv::Serialize, rkyv::Deserialize, rkyv::Archive, -)] -#[rkyv(attr(derive(PartialEq, Eq, Debug)))] -pub enum GrpcAddress { - /// TCP socket address (IP address and port) - Tcp(SocketAddr), - /// Unix domain socket path - UnixSocket(String), -} - /// Configuration for the packet processing driver used by the dataplane. /// /// The dataplane supports two packet processing backends: @@ -554,8 +541,6 @@ pub struct RoutingConfigSection { )] #[rkyv(attr(derive(PartialEq, Eq, Debug)))] pub struct ConfigServerSection { - /// gRPC server address (TCP or Unix socket) - pub address: Option, pub config_dir: Option, } @@ -1037,14 +1022,6 @@ impl AsFinalizedMemFile for IntegrityCheck { /// when argument values are invalid or inconsistent. #[derive(Debug, thiserror::Error, miette::Diagnostic)] pub enum InvalidCmdArguments { - /// Invalid gRPC address specification. - /// - /// This occurs when: - /// - TCP address cannot be parsed as `IP:PORT` - /// - Unix socket path is not absolute when `--grpc-unix-socket` is set - #[error("Illegal grpc address: {0}")] - InvalidGrpcAddress(String), // TODO: this should have a stronger error type - /// Invalid PCI device address format. /// /// PCI addresses must follow the format: `domain:bus:device.function` @@ -1090,9 +1067,6 @@ impl TryFrom for LaunchConfiguration { name: value.get_name().cloned(), }, config_server: Some(ConfigServerSection { - address: value - .grpc_address() - .map_err(InvalidCmdArguments::InvalidGrpcAddress)?, config_dir: value.config_dir().cloned(), }), driver: match &value.driver { @@ -1193,19 +1167,6 @@ Note: multiple interfaces can be specified separated by commas and no spaces" )] num_workers: u16, - /// gRPC server address (IP:PORT for TCP or path for UNIX socket) - #[arg( - long, - value_name = "ADDRESS", - help = "IP Address and port or UNIX socket path to listen for GRPC management connections. -If this parameter and --grpc_unix_socket are both absent, the dataplane will directly fetch configuration from K8s" - )] - grpc_address: Option, - - /// Treat grpc-address as a UNIX socket path - #[arg(long, help = "Use a unix socket to listen for management connections")] - grpc_unix_socket: Option, - #[arg( long, value_name = "CPI Unix socket path", @@ -1393,46 +1354,6 @@ impl CmdArgs { self.interface.iter().cloned() } - /// Parse and validate the gRPC server address configuration. - /// - /// This method interprets the `--grpc-address` and `--grpc-unix-socket` arguments - /// to determine the appropriate gRPC listening address. - /// - /// # Errors - /// - /// Returns an error if: - /// - Unix socket path is not absolute when `--grpc-unix-socket` is set - /// - TCP address cannot be parsed as a valid `IP:PORT` combination - pub fn grpc_address(&self) -> Result, String> { - if self.grpc_address.is_none() && self.grpc_unix_socket.is_none() { - return Ok(None); - } - - let grpc_address = if let Some(addr) = self.grpc_address.as_ref() { - addr - } else { - "0.0.0.0:50051" - }; - - // If UNIX socket flag is set, treat the address as a UNIX socket path - if self.grpc_unix_socket.unwrap_or(false) { - // Validate that the address is a valid UNIX socket path - let grpc_path = PathBuf::from(grpc_address); - if !grpc_path.is_absolute() { - return Err(format!( - "Invalid configuration: --grpc-unix-socket flag is set, but --grpc-address '{grpc_address}' is not a valid absolute UNIX socket path", - )); - } - return Ok(Some(GrpcAddress::UnixSocket(grpc_address.to_string()))); - } - - // Otherwise, parse as a TCP socket address - match grpc_address.parse::() { - Ok(addr) => Ok(Some(GrpcAddress::Tcp(addr))), - Err(e) => Err(format!("Invalid gRPC TCP address '{grpc_address}': {e}",)), - } - } - /// Get the control plane interface socket path. /// /// Returns the path where FRR (Free Range Routing) sends route updates to the dataplane. diff --git a/dataplane/src/main.rs b/dataplane/src/main.rs index 4aad85604..5048400c8 100644 --- a/dataplane/src/main.rs +++ b/dataplane/src/main.rs @@ -128,14 +128,6 @@ fn main() { }) .expect("failed to set SIGINT handler"); - let grpc_addr = match args.grpc_address() { - Ok(addr) => addr, - Err(e) => { - error!("Invalid gRPC address configuration: {e}"); - panic!("Management service configuration error. Aborting..."); - } - }; - /* router parameters */ let Ok(config) = RouterParamsBuilder::default() .cli_sock_path(args.cli_sock_path()) @@ -157,7 +149,6 @@ fn main() { /* start management */ start_mgmt(MgmtParams { - grpc_addr, config_dir: args.config_dir().cloned(), hostname: get_gw_name().unwrap_or_else(|| unreachable!()).to_owned(), processor_params: ConfigProcessorParams { diff --git a/mgmt/src/processor/launch.rs b/mgmt/src/processor/launch.rs index 2e6882074..77fd9359d 100644 --- a/mgmt/src/processor/launch.rs +++ b/mgmt/src/processor/launch.rs @@ -5,32 +5,14 @@ use crate::processor::k8s_client::{K8sClient, K8sClientError}; use crate::processor::k8s_less_client::{K8sLess, K8sLessError}; use crate::processor::proc::ConfigProcessor; -use std::fmt::Display; -use std::net::SocketAddr; -use std::os::unix::fs::PermissionsExt; -use std::path::{Path, PathBuf}; -use std::pin::Pin; -use std::task::{Context, Poll}; - -use tokio::io; -use tokio::net::UnixListener; -use tokio_stream::Stream; -use tonic::transport::Server; - -use futures::future::OptionFuture; - -use args::GrpcAddress; use concurrency::sync::Arc; -use tracing::{debug, error, info, warn}; +use futures::future::OptionFuture; +use tracing::{debug, error, warn}; -use crate::grpc::server::create_config_service; -use crate::processor::mgmt_client::ConfigClient; use crate::processor::proc::ConfigProcessorParams; #[derive(Debug, thiserror::Error)] pub enum LaunchError { - #[error("GRPC server error: {0}")] - GrpcServerError(tonic::transport::Error), #[error("IO error: {0}")] IoError(std::io::Error), #[error("Error in K8s client task: {0}")] @@ -39,8 +21,6 @@ pub enum LaunchError { K8sClientJoinError(tokio::task::JoinError), #[error("K8s client exited prematurely")] PrematureK8sClientExit, - #[error("Grpc server exited prematurely")] - PrematureGrpcExit, #[error("Config processor exited prematurely")] PrematureProcessorExit, @@ -53,138 +33,7 @@ pub enum LaunchError { K8LessError(#[from] K8sLessError), } -/// Start the gRPC server on TCP -async fn start_grpc_server_tcp(addr: SocketAddr, client: ConfigClient) -> Result<(), LaunchError> { - info!("Starting gRPC server on TCP address: {addr}"); - let config_service = create_config_service(client); - - Server::builder() - .add_service(config_service) - .serve(addr) - .await - .map_err(|e| { - error!("Failed to start gRPC server"); - LaunchError::GrpcServerError(e) - }) -} - -/// UnixListener wrapper type to implement tokyo Stream trait -/// This is only used/needed when we bind gRPC to a Unix socket -struct UnixAcceptor { - listener: UnixListener, -} - -// Implementation of the Stream trait for UnixAcceptor -impl Stream for UnixAcceptor { - type Item = Result; - - fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - let this = unsafe { self.get_unchecked_mut() }; - match this.listener.poll_accept(cx) { - Poll::Ready(Ok((stream, addr))) => { - debug!("Accepted connection on gRPC unix socket from {addr:?}"); - Poll::Ready(Some(Ok(stream))) - } - Poll::Ready(Err(e)) => { - warn!("Error accepting connection on gRPC unix sock: {e}"); - Poll::Ready(Some(Err(e))) - } - Poll::Pending => Poll::Pending, - } - } -} - -/// Start the gRPC server on UNIX socket -async fn start_grpc_server_unix( - socket_path: &Path, - client: ConfigClient, -) -> Result<(), LaunchError> { - info!( - "Starting gRPC server on UNIX socket: {}", - socket_path.display() - ); - - // Remove existing socket file if present - #[allow(clippy::collapsible_if)] - if socket_path.exists() { - if let Err(e) = std::fs::remove_file(socket_path) { - warn!("Failed to remove existing socket file: {e}"); - } - } - - // Create parent directory if it doesn't exist - #[allow(clippy::collapsible_if)] - if let Some(parent) = socket_path.parent() { - if !parent.exists() { - if let Err(e) = std::fs::create_dir_all(parent) { - error!("Failed to create parent directory: {e}"); - return Err(LaunchError::IoError(e)); - } - } - } - - // Create the UNIX socket listener - let listener = match UnixListener::bind(socket_path) { - Ok(listener) => { - debug!("Bound unix sock to {}", socket_path.display()); - listener - } - Err(e) => { - error!("Failed to bind UNIX socket: {e}"); - return Err(LaunchError::IoError(e)); - } - }; - - // Set socket permissions if needed - match std::fs::set_permissions(socket_path, std::fs::Permissions::from_mode(0o666)) { - Ok(_) => debug!("Socket permissions set to 0666"), - Err(e) => error!("Failed to set socket permissions: {e}"), - } - - // Build Unix acceptor wrapper to asynchronously accept connections inside the server - let acceptor = UnixAcceptor { listener }; - - // Create the gRPC service - let config_service = create_config_service(client); - - // Start the server with UNIX domain socket - Server::builder() - .add_service(config_service) - .serve_with_incoming(acceptor) - .await - .map_err(|e| { - error!("Failed to start gRPC server"); - LaunchError::GrpcServerError(e) - })?; - - // Clean up the socket file after server shutdown - #[allow(clippy::collapsible_if)] - if socket_path.exists() { - if let Err(e) = std::fs::remove_file(socket_path) { - error!("Failed to remove socket file: {e}"); - } - } - Ok(()) -} - -/// Enum for the different types of server addresses -#[derive(Debug)] -enum ServerAddress { - Tcp(SocketAddr), - Unix(PathBuf), -} - -impl Display for ServerAddress { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - ServerAddress::Tcp(addr) => write!(f, "tcp:{addr}"), - ServerAddress::Unix(path) => write!(f, "unix:{}", path.display()), - } - } -} - pub struct MgmtParams { - pub grpc_addr: Option, pub config_dir: Option, pub hostname: String, pub processor_params: ConfigProcessorParams, @@ -208,33 +57,7 @@ pub fn start_mgmt( .build() .expect("Tokio runtime creation failed"); - if let Some(grpc_addr) = params.grpc_addr { - /* build server address from provided grpc address */ - let server_address = match grpc_addr { - GrpcAddress::Tcp(addr) => ServerAddress::Tcp(addr), - GrpcAddress::UnixSocket(path) => ServerAddress::Unix(path.into()), - }; - debug!("Will start gRPC listening on {server_address}"); - - /* block thread to run gRPC and configuration processor */ - rt.block_on(async { - let (processor, client) = ConfigProcessor::new(params.processor_params); - tokio::spawn(async { processor.run().await }); - - // Start the appropriate server based on address type - let result = match server_address { - ServerAddress::Tcp(sock_addr) => start_grpc_server_tcp(sock_addr, client).await, - ServerAddress::Unix(path) => start_grpc_server_unix(&path, client).await, - }; - if let Err(e) = result { - error!("Failed to start gRPC server: {e}"); - Err(e) - } else { - error!("GRPC server exited prematurely"); - Err(LaunchError::PrematureGrpcExit) - } - }) - } else if let Some(config_dir) = ¶ms.config_dir { + if let Some(config_dir) = ¶ms.config_dir { warn!("Running in k8s-less mode...."); rt.block_on(async { let (processor, client) = ConfigProcessor::new(params.processor_params); diff --git a/mgmt/src/processor/proc.rs b/mgmt/src/processor/proc.rs index 91a93a9df..2431c2b3b 100644 --- a/mgmt/src/processor/proc.rs +++ b/mgmt/src/processor/proc.rs @@ -358,7 +358,7 @@ impl ConfigProcessor { pub async fn run(mut self) { info!("Starting config processor..."); loop { - // receive config requests over channel from gRPC server + // receive config requests over channel from a `ConfigClient` match self.rx.recv().await { Some(req) => { let response = match req.request { diff --git a/mgmt/src/tests/mgmt.rs b/mgmt/src/tests/mgmt.rs index 13674e2ea..33337f4b8 100644 --- a/mgmt/src/tests/mgmt.rs +++ b/mgmt/src/tests/mgmt.rs @@ -338,7 +338,7 @@ pub mod test { comtable } - /* build sample external config as it would be received via gRPC */ + /* build sample external config as it would be received via gRPC/k8s */ pub fn sample_external_config() -> ExternalConfig { /* build sample DEVICE config and add it to config */ let device_cfg = sample_device_config(); From 9f85ca360c212a724e4c0994ef20959e065854a6 Mon Sep 17 00:00:00 2001 From: Fredi Raspall Date: Tue, 30 Dec 2025 17:34:26 +0100 Subject: [PATCH 2/5] feat(remove-grpc): remove gRPC server from mgmt Signed-off-by: Fredi Raspall --- dataplane/src/main.rs | 2 - mgmt/src/grpc/mod.rs | 7 -- mgmt/src/grpc/server.rs | 167 ---------------------------------------- mgmt/src/lib.rs | 1 - 4 files changed, 177 deletions(-) delete mode 100644 mgmt/src/grpc/mod.rs delete mode 100644 mgmt/src/grpc/server.rs diff --git a/dataplane/src/main.rs b/dataplane/src/main.rs index 5048400c8..7d4a8bdad 100644 --- a/dataplane/src/main.rs +++ b/dataplane/src/main.rs @@ -27,8 +27,6 @@ use tracectl::{custom_target, get_trace_ctl, trace_target}; use tracing::{error, info, level_filters::LevelFilter}; trace_target!("dataplane", LevelFilter::DEBUG, &[]); -custom_target!("tonic", LevelFilter::ERROR, &[]); -custom_target!("h2", LevelFilter::ERROR, &[]); custom_target!("Pyroscope", LevelFilter::INFO, &[]); fn init_name(args: &CmdArgs) -> Result<(), String> { diff --git a/mgmt/src/grpc/mod.rs b/mgmt/src/grpc/mod.rs deleted file mode 100644 index 8a0ad828c..000000000 --- a/mgmt/src/grpc/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Open Network Fabric Authors - -//! Dataplane gRPC handling module. -//! Implements gRPC request reception and response building. - -pub mod server; diff --git a/mgmt/src/grpc/server.rs b/mgmt/src/grpc/server.rs deleted file mode 100644 index baea9bb33..000000000 --- a/mgmt/src/grpc/server.rs +++ /dev/null @@ -1,167 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Open Network Fabric Authors - -// mgmt/src/grpc/server.rs - -use async_trait::async_trait; -use std::sync::Arc; -use tonic::{Request, Response, Status}; -use tracing::{debug, error}; - -use crate::processor::mgmt_client::ConfigClient; -use config::converters::grpc::{ - convert_dataplane_status_to_grpc, convert_gateway_config_from_grpc_with_defaults, -}; -use config::internal::status::DataplaneStatus; -use config::{GenId, GwConfig}; - -// Import proto-generated types -use gateway_config::{ - ConfigService, ConfigServiceServer, Error, GatewayConfig, GetConfigGenerationRequest, - GetConfigGenerationResponse, GetConfigRequest, GetDataplaneStatusRequest, - GetDataplaneStatusResponse, UpdateConfigRequest, UpdateConfigResponse, -}; - -/// Trait for configuration management -#[async_trait] -pub trait ConfigManager: Send + Sync { - async fn get_current_config(&self) -> Result; - async fn get_generation(&self) -> Result; - async fn apply_config(&self, config: GatewayConfig) -> Result<(), String>; - async fn get_dataplane_status(&self) -> Result; -} - -/// Implementation of the gRPC server -pub struct ConfigServiceImpl { - config_manager: Arc, -} - -impl ConfigServiceImpl { - pub fn new(config_manager: Arc) -> Self { - Self { config_manager } - } -} - -#[async_trait] -impl ConfigService for ConfigServiceImpl { - async fn get_config( - &self, - _request: Request, - ) -> Result, Status> { - // Get current config from manager - let current_config = self - .config_manager - .get_current_config() - .await - .map_err(|e| Status::internal(format!("Failed to get configuration: {e}")))?; - - Ok(Response::new(current_config)) - } - - async fn get_config_generation( - &self, - _request: Request, - ) -> Result, Status> { - let generation = self - .config_manager - .get_generation() - .await - .map_err(|e| Status::internal(format!("Failed to get generation: {e}")))?; - - Ok(Response::new(GetConfigGenerationResponse { generation })) - } - - async fn update_config( - &self, - request: Request, - ) -> Result, Status> { - let update_request = request.into_inner(); - let grpc_config = update_request - .config - .ok_or_else(|| Status::invalid_argument("Missing config in update request"))?; - - // Apply the configuration - match self.config_manager.apply_config(grpc_config).await { - Ok(_) => Ok(Response::new(UpdateConfigResponse { - error: Error::None as i32, - message: "Configuration updated successfully".to_string(), - })), - Err(e) => Ok(Response::new(UpdateConfigResponse { - error: Error::ApplyFailed as i32, - message: format!("Failed to apply configuration: {e}"), - })), - } - } - - async fn get_dataplane_status( - &self, - _request: Request, - ) -> Result, Status> { - let internal = self - .config_manager - .get_dataplane_status() - .await - .map_err(|e| Status::internal(format!("Failed to get dataplane status: {e}")))?; - - let grpc = convert_dataplane_status_to_grpc(&internal) - .map_err(|e| Status::internal(format!("Failed to encode status: {e}")))?; - - Ok(Response::new(grpc)) - } -} - -/// Basic configuration manager implementation -pub struct BasicConfigManager { - client: ConfigClient, -} - -impl BasicConfigManager { - pub fn new(client: ConfigClient) -> Self { - Self { client } - } -} - -#[async_trait] -impl ConfigManager for BasicConfigManager { - async fn get_current_config(&self) -> Result { - let config = self - .client - .get_current_config() - .await - .map_err(|e| e.to_string())?; - gateway_config::GatewayConfig::try_from(&config.external) - } - - async fn get_generation(&self) -> Result { - self.client - .get_generation() - .await - .map_err(|e| e.to_string()) - } - - async fn apply_config(&self, grpc_config: GatewayConfig) -> Result<(), String> { - // Convert config from gRPC to native external model - let external_config = convert_gateway_config_from_grpc_with_defaults(&grpc_config) - .map_err(|e| { - error!("Failed to parse config: {e}"); - e - })?; - - self.client - .apply_config(GwConfig::new(external_config)) - .await - .map_err(|e| e.to_string()) - } - - async fn get_dataplane_status(&self) -> Result { - debug!("Received request to get dataplane status"); - self.client.get_status().await.map_err(|e| e.to_string()) - } -} - -/// Function to create the gRPC service -pub fn create_config_service(client: ConfigClient) -> ConfigServiceServer { - let config_manager = Arc::new(BasicConfigManager::new(client)); - let service = ConfigServiceImpl::new(config_manager); - ConfigServiceServer::new(service) -} diff --git a/mgmt/src/lib.rs b/mgmt/src/lib.rs index 0cb3a5ec7..9847426ab 100644 --- a/mgmt/src/lib.rs +++ b/mgmt/src/lib.rs @@ -3,7 +3,6 @@ //! Dataplane management module -mod grpc; mod processor; mod tests; pub mod vpc_manager; From d502f835ea6a2fcd2f673dbb8162ef6d266473a5 Mon Sep 17 00:00:00 2001 From: Fredi Raspall Date: Tue, 30 Dec 2025 17:35:00 +0100 Subject: [PATCH 3/5] feat(remove-grpc): remove tonic as a dependency Signed-off-by: Fredi Raspall --- Cargo.lock | 1 - Cargo.toml | 1 - mgmt/Cargo.toml | 1 - 3 files changed, 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f03ad6dac..a96fc1914 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1523,7 +1523,6 @@ dependencies = [ "thiserror 2.0.17", "tokio", "tokio-stream", - "tonic", "tracing", "tracing-test", ] diff --git a/Cargo.toml b/Cargo.toml index 2ab35705e..16ec0a9bd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -182,7 +182,6 @@ thiserror = { version = "2.0.17", default-features = false, features = [] } thread_local = { version = "1.1.9", default-features = false, features = [] } tokio = { version = "1.48.0", default-features = false, features = [] } tokio-stream = { version = "0.1.17", default-features = false, features = [] } -tonic = { version = "0.14.2", default-features = false, features = [] } tracing = { version = "0.1.43", default-features = false, features = [] } tracing-error = { version = "0.2.1", default-features = false, features = [] } tracing-subscriber = { version = "0.3.22", default-features = false, features = [] } diff --git a/mgmt/Cargo.toml b/mgmt/Cargo.toml index 97cb77b86..32cb035e2 100644 --- a/mgmt/Cargo.toml +++ b/mgmt/Cargo.toml @@ -53,7 +53,6 @@ serde = { workspace = true, features = ["rc", "derive"] } thiserror = { workspace = true } tokio = { workspace = true, features = ["macros", "rt", "sync", "time"] } tokio-stream = { workspace = true } -tonic = { workspace = true } tracing = { workspace = true, features = ["attributes"] } tracing-test = { workspace = true } From 192ddb013db0efb512fb4c6b3822eb23d064c46d Mon Sep 17 00:00:00 2001 From: Fredi Raspall Date: Tue, 30 Dec 2025 17:45:47 +0100 Subject: [PATCH 4/5] feat(remove-grpc): remove gRPC converters from config Signed-off-by: Fredi Raspall --- config/src/converters/grpc/bgp.rs | 364 -------- config/src/converters/grpc/device.rs | 30 - config/src/converters/grpc/expose.rs | 145 --- config/src/converters/grpc/gateway_config.rs | 165 ---- config/src/converters/grpc/gwgroups.rs | 57 -- config/src/converters/grpc/interface.rs | 285 ------ config/src/converters/grpc/mod.rs | 621 ------------- config/src/converters/grpc/overlay.rs | 72 -- config/src/converters/grpc/peering.rs | 99 -- config/src/converters/grpc/status.rs | 927 ------------------- config/src/converters/grpc/tracecfg.rs | 57 -- config/src/converters/grpc/underlay.rs | 48 - config/src/converters/grpc/vpc.rs | 50 - config/src/converters/grpc/vrf.rs | 100 -- config/src/converters/mod.rs | 1 - 15 files changed, 3021 deletions(-) delete mode 100644 config/src/converters/grpc/bgp.rs delete mode 100644 config/src/converters/grpc/device.rs delete mode 100644 config/src/converters/grpc/expose.rs delete mode 100644 config/src/converters/grpc/gateway_config.rs delete mode 100644 config/src/converters/grpc/gwgroups.rs delete mode 100644 config/src/converters/grpc/interface.rs delete mode 100644 config/src/converters/grpc/mod.rs delete mode 100644 config/src/converters/grpc/overlay.rs delete mode 100644 config/src/converters/grpc/peering.rs delete mode 100644 config/src/converters/grpc/status.rs delete mode 100644 config/src/converters/grpc/tracecfg.rs delete mode 100644 config/src/converters/grpc/underlay.rs delete mode 100644 config/src/converters/grpc/vpc.rs delete mode 100644 config/src/converters/grpc/vrf.rs diff --git a/config/src/converters/grpc/bgp.rs b/config/src/converters/grpc/bgp.rs deleted file mode 100644 index be17e9750..000000000 --- a/config/src/converters/grpc/bgp.rs +++ /dev/null @@ -1,364 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Open Network Fabric Authors - -use gateway_config::config as gateway_config; -use std::convert::TryFrom; -use std::net::{IpAddr, Ipv4Addr}; -use std::str::FromStr; - -use crate::internal::routing::bgp::{ - AfIpv4Ucast, AfIpv6Ucast, AfL2vpnEvpn, BgpConfig, BgpNeighCapabilities, BgpNeighType, - BgpNeighbor, BgpOptions, BgpUpdateSource, NeighSendCommunities, Protocol, Redistribute, -}; - -use lpm::prefix::{Prefix, PrefixString}; - -use gateway_config::bgp_neighbor_update_source::Source; - -#[repr(transparent)] -pub struct OptBgpUpdateSource(pub Option); -#[repr(transparent)] -pub struct OptGRPCBgpNeighborUpdateSource(pub Option); - -fn has_redistribute(redistribute: &[Redistribute], protocol: &Protocol) -> bool { - redistribute.iter().any(|r| r.protocol == *protocol) -} - -impl TryFrom<&gateway_config::BgpAddressFamilyIPv4> for AfIpv4Ucast { - type Error = String; - - fn try_from(ipv4: &gateway_config::BgpAddressFamilyIPv4) -> Result { - let mut afipv4 = AfIpv4Ucast::new(); - - if ipv4.redistribute_static { - afipv4.redistribute(Redistribute::new(Protocol::Static, None, None)); - } - - if ipv4.redistribute_connected { - afipv4.redistribute(Redistribute::new(Protocol::Connected, None, None)); - } - - let networks = ipv4 - .networks - .iter() - .map(|n| { - let prefix = Prefix::try_from(PrefixString(n)) - .map_err(|e| format!("Invalid network prefix {n}: {e}"))?; - if !prefix.is_ipv4() { - return Err(format!("Invalid network prefix {n}: not an IPv4 prefix")); - } - Ok(prefix) - }) - .collect::, _>>()?; - - afipv4.add_networks(networks); - - Ok(afipv4) - } -} - -impl TryFrom<&gateway_config::BgpAddressFamilyIPv6> for AfIpv6Ucast { - type Error = String; - - fn try_from(ipv6: &gateway_config::BgpAddressFamilyIPv6) -> Result { - let mut afipv6 = AfIpv6Ucast::new(); - - if ipv6.redistribute_static { - afipv6 - .redistribute - .push(Redistribute::new(Protocol::Static, None, None)); - } - - if ipv6.redistribute_connected { - afipv6 - .redistribute - .push(Redistribute::new(Protocol::Connected, None, None)); - } - - let networks = ipv6 - .networks - .iter() - .map(|n| { - let prefix = Prefix::try_from(PrefixString(n)) - .map_err(|e| format!("Invalid network prefix {n}: {e}"))?; - if !prefix.is_ipv6() { - return Err(format!("Invalid network prefix {n}: not an IPv6 prefix")); - } - Ok(prefix) - }) - .collect::, _>>()?; - - afipv6.add_networks(networks); - - Ok(afipv6) - } -} - -impl TryFrom<&gateway_config::BgpNeighbor> for BgpNeighbor { - type Error = String; - - fn try_from(neighbor: &gateway_config::BgpNeighbor) -> Result { - // Parse remote ASN - let remote_as = neighbor - .remote_asn - .parse::() - .map_err(|_| format!("Invalid remote ASN format: {}", neighbor.remote_asn))?; - - // Create neighbor address for ntype - let neighbor_addr = IpAddr::from_str(&neighbor.address) - .map_err(|_| format!("Invalid neighbor address: {}", neighbor.address))?; - - // Determine which address families are activated - let mut ipv4_unicast = false; - let mut ipv6_unicast = false; - let mut l2vpn_evpn = false; - - for af in &neighbor.af_activate { - match gateway_config::BgpAf::try_from(*af) { - Ok(gateway_config::BgpAf::Ipv4Unicast) => ipv4_unicast = true, - Ok(gateway_config::BgpAf::Ipv6Unicast) => ipv6_unicast = true, - Ok(gateway_config::BgpAf::L2vpnEvpn) => l2vpn_evpn = true, - Err(_) => return Err(format!("Unknown BGP address family: {af}")), - } - } - - // Create the neighbor config - let mut neigh = BgpNeighbor::new_host(neighbor_addr) - .set_remote_as(remote_as) - .set_capabilities(BgpNeighCapabilities::default()) - .set_send_community(NeighSendCommunities::Both) - .ipv4_unicast_activate(ipv4_unicast) - .ipv6_unicast_activate(ipv6_unicast) - .l2vpn_evpn_activate(l2vpn_evpn); - - // set update source - if let Some(update_source) = &neighbor.update_source { - let upd_source = OptBgpUpdateSource::try_from(update_source) - .map_err(|e| format!("Bad update source: {e}"))?; - neigh = neigh.set_update_source(upd_source.0); - } - - Ok(neigh) - } -} - -impl TryFrom<&BgpNeighbor> for gateway_config::BgpNeighbor { - type Error = String; - - fn try_from(neighbor: &BgpNeighbor) -> Result { - // Get neighbor address safely - let address = match &neighbor.ntype { - BgpNeighType::Host(addr) => addr.to_string(), - BgpNeighType::PeerGroup(name) => { - return Err(format!("Peer group type not supported in gRPC: {name}")); - } - BgpNeighType::Unset => { - return Err("Unset BGP neighbor type not supported in gRPC".to_string()); - } - }; - - // Get remote ASN safely - let remote_asn = neighbor - .remote_as - .as_ref() - .ok_or_else(|| "Missing remote ASN for BGP neighbor".to_string())? - .to_string(); - - // Build address family activation list - let mut af_activate = Vec::new(); - if neighbor.ipv4_unicast { - af_activate.push(gateway_config::BgpAf::Ipv4Unicast.into()); - } - if neighbor.ipv6_unicast { - af_activate.push(gateway_config::BgpAf::Ipv6Unicast.into()); - } - if neighbor.l2vpn_evpn { - af_activate.push(gateway_config::BgpAf::L2vpnEvpn.into()); - } - - let update_source = OptGRPCBgpNeighborUpdateSource::try_from(&neighbor.update_source) - .map_err(|e| format!("Bad update source: {e}"))? - .0; - - Ok(gateway_config::BgpNeighbor { - address, - remote_asn, - af_activate, - update_source, - }) - } -} - -impl TryFrom<&gateway_config::BgpNeighborUpdateSource> for OptBgpUpdateSource { - type Error = String; - - fn try_from(neighbor: &gateway_config::BgpNeighborUpdateSource) -> Result { - match &neighbor.source { - Some(Source::Address(address)) => { - Ok(OptBgpUpdateSource(Some(BgpUpdateSource::Address( - address - .parse() - .map_err(|e| format!("Bad update source address {e}"))?, - )))) - } - Some(Source::Interface(ifname)) => Ok(OptBgpUpdateSource(Some( - BgpUpdateSource::Interface(ifname.to_owned()), - ))), - None => Ok(OptBgpUpdateSource(None)), - } - } -} - -impl TryFrom<&Option> for OptGRPCBgpNeighborUpdateSource { - type Error = String; - - fn try_from(update_source: &Option) -> Result { - match update_source { - Some(BgpUpdateSource::Address(addr)) => Ok(OptGRPCBgpNeighborUpdateSource(Some( - gateway_config::BgpNeighborUpdateSource { - source: Some(gateway_config::bgp_neighbor_update_source::Source::Address( - addr.to_string(), - )), - }, - ))), - - Some(BgpUpdateSource::Interface(iface)) => Ok(OptGRPCBgpNeighborUpdateSource(Some( - gateway_config::BgpNeighborUpdateSource { - source: Some( - gateway_config::bgp_neighbor_update_source::Source::Interface( - iface.clone(), - ), - ), - }, - ))), - None => Ok(OptGRPCBgpNeighborUpdateSource(None)), - } - } -} - -// BgpConfig conversions -impl TryFrom<&gateway_config::RouterConfig> for BgpConfig { - type Error = String; - - fn try_from(router: &gateway_config::RouterConfig) -> Result { - // Parse ASN from string to u32 - let asn = router - .asn - .parse::() - .map_err(|_| format!("Invalid ASN format: {}", router.asn))?; - - // Parse router_id from string to Ipv4Addr - let router_id = router - .router_id - .parse::() - .map_err(|_| format!("Invalid router ID format: {}", router.router_id))?; - - // Use default options - let options = BgpOptions::default(); - - // Convert neighbors - let mut neighbors = Vec::new(); - for neighbor in &router.neighbors { - neighbors.push(BgpNeighbor::try_from(neighbor)?); - } - - // Convert IPv4 Unicast address family if present - let af_ipv4unicast = match &router.ipv4_unicast { - Some(ipv4) => AfIpv4Ucast::try_from(ipv4)?, - None => AfIpv4Ucast::new(), - }; - let af_ipv6unicast = match &router.ipv6_unicast { - Some(ipv6) => AfIpv6Ucast::try_from(ipv6)?, - None => AfIpv6Ucast::new(), - }; - - let af_l2vpnevpn = AfL2vpnEvpn::new() - .set_adv_all_vni(router.l2vpn_evpn.is_none_or(|evpn| evpn.advertise_all_vni)) - .set_adv_default_gw(true) - .set_adv_svi_ip(true) - .set_adv_ipv4_unicast(true) - .set_adv_ipv6_unicast(false) - .set_default_originate_ipv4(false) - .set_default_originate_ipv6(false); - - let mut bgpconfig = BgpConfig::new(asn); - bgpconfig.set_router_id(router_id); - bgpconfig.set_bgp_options(options); - if router.ipv4_unicast.is_some() { - bgpconfig.set_af_ipv4unicast(af_ipv4unicast); - } - if router.ipv6_unicast.is_some() { - bgpconfig.set_af_ipv6unicast(af_ipv6unicast); - } - if router.l2vpn_evpn.is_some() { - bgpconfig.set_af_l2vpn_evpn(af_l2vpnevpn); - } - - // Add each neighbor to the BGP config - for neighbor in &router.neighbors { - bgpconfig.add_neighbor(BgpNeighbor::try_from(neighbor)?); - } - - Ok(bgpconfig) - } -} - -impl TryFrom<&BgpConfig> for gateway_config::RouterConfig { - type Error = String; - - fn try_from(bgp: &BgpConfig) -> Result { - // Convert BGP neighbors - let mut neighbors = Vec::with_capacity(bgp.neighbors.len()); - for neighbor in &bgp.neighbors { - let grpc_neighbor = gateway_config::BgpNeighbor::try_from(neighbor)?; - neighbors.push(grpc_neighbor); - } - - // Get router ID safely - let router_id = bgp - .router_id - .as_ref() - .map_or(String::new(), ToString::to_string); - - // Create IPv4 unicast config if enabled - let ipv4_unicast = - bgp.af_ipv4unicast - .as_ref() - .map(|c| gateway_config::BgpAddressFamilyIPv4 { - redistribute_connected: has_redistribute(&c.redistribute, &Protocol::Connected), - redistribute_static: has_redistribute(&c.redistribute, &Protocol::Static), - networks: c.networks.iter().map(ToString::to_string).collect(), - }); - - // Create IPv6 unicast config if enabled - let ipv6_unicast = - bgp.af_ipv6unicast - .as_ref() - .map(|c| gateway_config::BgpAddressFamilyIPv6 { - redistribute_connected: has_redistribute(&c.redistribute, &Protocol::Connected), - redistribute_static: has_redistribute(&c.redistribute, &Protocol::Static), - networks: c.networks.iter().map(ToString::to_string).collect(), - }); - - // Create L2VPN EVPN config if enabled - let l2vpn_evpn = - bgp.af_l2vpnevpn - .as_ref() - .map(|config| gateway_config::BgpAddressFamilyL2vpnEvpn { - advertise_all_vni: config.adv_all_vni, - }); - - // Create route maps (empty for now) - let route_maps = Vec::new(); // TODO: Implement route map conversion - - Ok(gateway_config::RouterConfig { - asn: bgp.asn.to_string(), - router_id, - neighbors, - ipv4_unicast, - ipv6_unicast, - l2vpn_evpn, - route_maps, - }) - } -} diff --git a/config/src/converters/grpc/device.rs b/config/src/converters/grpc/device.rs deleted file mode 100644 index 0854ea529..000000000 --- a/config/src/converters/grpc/device.rs +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Open Network Fabric Authors - -use ::gateway_config::config as gateway_config; -use gateway_config::TracingConfig as ApiTracingConfig; - -use crate::internal::device::{DeviceConfig, tracecfg::TracingConfig}; - -impl TryFrom<&gateway_config::Device> for DeviceConfig { - type Error = String; - - fn try_from(device: &gateway_config::Device) -> Result { - // Create DeviceConfig - let mut device_config = DeviceConfig::new(); - if let Some(tracing) = &device.tracing { - device_config.set_tracing(TracingConfig::try_from(tracing)?); - } - Ok(device_config) - } -} - -impl TryFrom<&DeviceConfig> for gateway_config::Device { - type Error = String; - - fn try_from(device: &DeviceConfig) -> Result { - let tracing = device.tracing.as_ref().map(ApiTracingConfig::from); - - Ok(gateway_config::Device { tracing }) - } -} diff --git a/config/src/converters/grpc/expose.rs b/config/src/converters/grpc/expose.rs deleted file mode 100644 index 0b6465641..000000000 --- a/config/src/converters/grpc/expose.rs +++ /dev/null @@ -1,145 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Open Network Fabric Authors - -use ::gateway_config::google; -use gateway_config::config as gateway_config; - -use std::convert::TryFrom; - -use crate::external::overlay::vpcpeering::{ - VpcExpose, VpcExposeNatConfig, VpcExposeStatefulNat, VpcExposeStatelessNat, -}; -use lpm::prefix::{Prefix, PrefixString, PrefixWithOptionalPorts}; - -impl TryFrom<&gateway_config::Expose> for VpcExpose { - type Error = String; - - fn try_from(expose: &gateway_config::Expose) -> Result { - // Start with an empty expose - let mut vpc_expose = VpcExpose::empty(); - - // Process PeeringIP rules - for ip in &expose.ips { - if let Some(rule) = &ip.rule { - match rule { - gateway_config::peering_i_ps::Rule::Cidr(cidr) => { - let prefix = Prefix::try_from(PrefixString(cidr)) - .map_err(|e| format!("Invalid CIDR format: {cidr}: {e}"))?; - vpc_expose = vpc_expose.ip(PrefixWithOptionalPorts::new(prefix, None)); // FIXME - } - gateway_config::peering_i_ps::Rule::Not(not) => { - let prefix = Prefix::try_from(PrefixString(not)) - .map_err(|e| format!("Invalid CIDR format: {not}: {e}"))?; - vpc_expose = vpc_expose.not(PrefixWithOptionalPorts::new(prefix, None)); // FIXME - } - } - } else { - return Err("PeeringIPs must have either 'cidr' or 'not' field set".to_string()); - } - } - - // Process PeeringAs rules - for as_rule in &expose.r#as { - if let Some(rule) = &as_rule.rule { - match rule { - gateway_config::peering_as::Rule::Cidr(cidr) => { - let prefix = Prefix::try_from(PrefixString(cidr)) - .map_err(|e| format!("Invalid CIDR format: {cidr}: {e}"))?; - vpc_expose = - vpc_expose.as_range(PrefixWithOptionalPorts::new(prefix, None)); // FIXME - } - gateway_config::peering_as::Rule::Not(ip_exclude) => { - let prefix = Prefix::try_from(PrefixString(ip_exclude)) - .map_err(|e| format!("Invalid CIDR format: {ip_exclude}: {e}"))?; - vpc_expose = vpc_expose.not_as(PrefixWithOptionalPorts::new(prefix, None)); // FIXME - } - } - } else { - return Err("PeeringAs must have either 'cidr' or 'not' field set".to_string()); - } - } - - if !expose.r#as.is_empty() { - vpc_expose = vpc_expose.make_nat(); - if let (Some(grpc_nat), Some(nat)) = (expose.nat.as_ref(), vpc_expose.nat.as_mut()) { - #[allow(clippy::default_constructed_unit_structs)] - match grpc_nat { - gateway_config::expose::Nat::Stateless(_) => { - nat.config = - VpcExposeNatConfig::Stateless(VpcExposeStatelessNat::default()); - } - gateway_config::expose::Nat::Stateful(grpc_s) => { - nat.config = VpcExposeNatConfig::Stateful(VpcExposeStatefulNat { - idle_timeout: grpc_s - .idle_timeout - .ok_or("stateful nat requires idle_timeout, got None".to_string()) - .and_then(|t| { - std::time::Duration::try_from(t) - .map_err(|e| format!("Invalid duration: {e}")) - })?, - }); - } - } - } - } - - Ok(vpc_expose) - } -} - -impl TryFrom<&VpcExpose> for gateway_config::Expose { - type Error = String; - - fn try_from(expose: &VpcExpose) -> Result { - let mut ips = Vec::new(); - let mut as_rules = Vec::new(); - - // Convert IP inclusion rules - for prefix in &expose.ips { - let rule = gateway_config::peering_i_ps::Rule::Cidr(prefix.to_string()); - ips.push(gateway_config::PeeringIPs { rule: Some(rule) }); - } - - // Convert IP exclusion rules - for prefix in &expose.nots { - let rule = gateway_config::peering_i_ps::Rule::Not(prefix.to_string()); - ips.push(gateway_config::PeeringIPs { rule: Some(rule) }); - } - - let nat = if let Some(nat) = expose.nat.as_ref() { - // Convert AS inclusion rules - for prefix in &nat.as_range { - let rule = gateway_config::peering_as::Rule::Cidr(prefix.to_string()); - as_rules.push(gateway_config::PeeringAs { rule: Some(rule) }); - } - - // Convert AS exclusion rules - for prefix in &nat.not_as { - let rule = gateway_config::peering_as::Rule::Not(prefix.to_string()); - as_rules.push(gateway_config::PeeringAs { rule: Some(rule) }); - } - - match &nat.config { - VpcExposeNatConfig::Stateful(config) => { - let idle_timeout = google::protobuf::Duration::try_from(config.idle_timeout) - .map_err(|e| format!("Unable to convert stateful nat idle timeout: {e}"))?; - Some(gateway_config::expose::Nat::Stateful( - gateway_config::PeeringStatefulNat { - idle_timeout: Some(idle_timeout), - }, - )) - } - VpcExposeNatConfig::Stateless(_) => Some(gateway_config::expose::Nat::Stateless( - gateway_config::PeeringStatelessNat {}, - )), - } - } else { - None - }; - Ok(gateway_config::Expose { - ips, - r#as: as_rules, - nat, - }) - } -} diff --git a/config/src/converters/grpc/gateway_config.rs b/config/src/converters/grpc/gateway_config.rs deleted file mode 100644 index 69b542ed1..000000000 --- a/config/src/converters/grpc/gateway_config.rs +++ /dev/null @@ -1,165 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Open Network Fabric Authors - -use tracing::warn; - -use crate::external::ExternalConfigBuilder; -use crate::external::communities::PriorityCommunityTable; -use crate::external::gwgroup::{GwGroup, GwGroupTable}; -use crate::external::overlay::Overlay; -use crate::external::underlay::Underlay; -use crate::internal::device::DeviceConfig; -use crate::{ExternalConfig, GwConfig}; -use gateway_config::config::GatewayGroup; - -// Helper Functions -//-------------------------------------------------------------------------------- - -/// Create a new `GwConfig` from `ExternalConfig` -pub fn create_gw_config(external_config: ExternalConfig) -> GwConfig { - GwConfig::new(external_config) -} - -/// Convert from `GatewayConfig` (gRPC) to `ExternalConfig` with default values -pub fn convert_gateway_config_from_grpc_with_defaults( - grpc_config: &gateway_config::GatewayConfig, -) -> Result { - // convert device if present or provide a default - let device_config = if let Some(device) = &grpc_config.device { - DeviceConfig::try_from(device)? - } else { - warn!("Missing device configuration!"); - DeviceConfig::new() - }; - - // convert underlay or provide a default (empty) - let underlay_config = if let Some(underlay) = &grpc_config.underlay { - Underlay::try_from(underlay)? - } else { - warn!("Missing underlay configuration!"); - Underlay::default() - }; - - // convert overlay or provide a default (empty) - let overlay_config = if let Some(overlay) = &grpc_config.overlay { - Overlay::try_from(overlay)? - } else { - warn!("Missing overlay configuration!"); - Overlay::default() - }; - - // convert gateway groups - let mut gw_groups = GwGroupTable::new(); - for g in &grpc_config.gw_groups { - let group = GwGroup::try_from(g)?; - gw_groups.add_group(group).map_err(|e| e.to_string())?; - } - - // convert community table - let mut comtable = PriorityCommunityTable::new(); - for (prio, community) in &grpc_config.communities { - comtable - .insert(*prio, community) - .map_err(|e| e.to_string())?; - } - - // Create the ExternalConfig using the builder pattern - let external_config = ExternalConfigBuilder::default() - .genid(grpc_config.generation) - .device(device_config) - .underlay(underlay_config) - .overlay(overlay_config) - .gwgroups(gw_groups) - .communities(comtable) - .build() - .map_err(|e| format!("Failed to build ExternalConfig: {e}"))?; - - Ok(external_config) -} - -impl TryFrom<&gateway_config::GatewayConfig> for ExternalConfig { - type Error = String; - - fn try_from(grpc_config: &gateway_config::GatewayConfig) -> Result { - // convert device if present or provide a default - let device_config = if let Some(device) = &grpc_config.device { - DeviceConfig::try_from(device) - } else { - Err("Missing device configuration!".to_string()) - }?; - - // convert underlay or provide a default (empty) - let underlay_config = if let Some(underlay) = &grpc_config.underlay { - Underlay::try_from(underlay) - } else { - Err("Missing underlay configuration!".to_string()) - }?; - - // convert overlay or provide a default (empty) - let overlay_config = if let Some(overlay) = &grpc_config.overlay { - Overlay::try_from(overlay) - } else { - Err("Missing overlay configuration!".to_string()) - }?; - - // convert gateway groups - let mut gw_groups = GwGroupTable::new(); - for g in &grpc_config.gw_groups { - let group = GwGroup::try_from(g)?; - gw_groups.add_group(group).map_err(|e| e.to_string())?; - } - - // convert community table - let mut comtable = PriorityCommunityTable::new(); - for (prio, community) in &grpc_config.communities { - comtable - .insert(*prio, community) - .map_err(|e| e.to_string())?; - } - - // Create the ExternalConfig using the builder pattern - let external_config = ExternalConfigBuilder::default() - .genid(grpc_config.generation) - .device(device_config) - .underlay(underlay_config) - .overlay(overlay_config) - .gwgroups(gw_groups) - .communities(comtable) - .build() - .map_err(|e| format!("Failed to build ExternalConfig: {e}"))?; - - Ok(external_config) - } -} - -impl TryFrom<&ExternalConfig> for gateway_config::GatewayConfig { - type Error = String; - - fn try_from(external_config: &ExternalConfig) -> Result { - // Convert device config - let device = gateway_config::Device::try_from(&external_config.device)?; - - // Convert underlay config - let underlay = gateway_config::Underlay::try_from(&external_config.underlay)?; - - // Convert overlay config - let overlay = gateway_config::Overlay::try_from(&external_config.overlay)?; - - // Convert gateway groups - let gw_groups: Vec<_> = external_config - .gwgroups - .iter() - .map(|g| GatewayGroup::try_from(g).unwrap_or_else(|_| unreachable!())) - .collect(); - - // Create the complete gRPC config - Ok(gateway_config::GatewayConfig { - generation: external_config.genid, - device: Some(device), - underlay: Some(underlay), - overlay: Some(overlay), - gw_groups, - communities: external_config.communities.inner().clone(), - }) - } -} diff --git a/config/src/converters/grpc/gwgroups.rs b/config/src/converters/grpc/gwgroups.rs deleted file mode 100644 index b8edaaf7a..000000000 --- a/config/src/converters/grpc/gwgroups.rs +++ /dev/null @@ -1,57 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Open Network Fabric Authors - -use crate::converters::strings::parse_address; -use crate::external::gwgroup::{GwGroup, GwGroupMember}; -use gateway_config::config as gateway_config; - -impl TryFrom<&gateway_config::GatewayGroupMember> for GwGroupMember { - type Error = String; - - fn try_from(value: &gateway_config::GatewayGroupMember) -> Result { - let address = parse_address(&value.ipaddress) - .map_err(|e| format!("Bad ip address '{}': {e}", value.ipaddress))?; - Ok(GwGroupMember::new(&value.name, value.priority, address)) - } -} -impl TryFrom<&GwGroupMember> for gateway_config::GatewayGroupMember { - type Error = String; - - fn try_from(value: &GwGroupMember) -> Result { - Ok(gateway_config::GatewayGroupMember { - name: value.name.clone(), - priority: value.priority, - ipaddress: value.ipaddress.to_string(), - }) - } -} - -impl TryFrom<&gateway_config::GatewayGroup> for GwGroup { - type Error = String; - - fn try_from(value: &gateway_config::GatewayGroup) -> Result { - let mut rgroup = GwGroup::new(&value.name); - for m in &value.members { - let member = GwGroupMember::try_from(m)?; - rgroup.add_member(member).map_err(|e| e.to_string())?; - } - Ok(rgroup) - } -} - -impl TryFrom<&GwGroup> for gateway_config::GatewayGroup { - type Error = String; - - fn try_from(value: &GwGroup) -> Result { - let members: Vec<_> = value - .iter() - .map(|m| { - gateway_config::GatewayGroupMember::try_from(m).unwrap_or_else(|_| unreachable!()) - }) - .collect(); - Ok(Self { - name: value.name().to_owned(), - members, - }) - } -} diff --git a/config/src/converters/grpc/interface.rs b/config/src/converters/grpc/interface.rs deleted file mode 100644 index b8c86d7e6..000000000 --- a/config/src/converters/grpc/interface.rs +++ /dev/null @@ -1,285 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Open Network Fabric Authors - -use gateway_config::config as gateway_config; -use hardware::pci::address::PciAddress; -use std::net::{IpAddr, Ipv4Addr}; - -use crate::internal::interfaces::interface::{ - IfEthConfig, IfVlanConfig, IfVtepConfig, InterfaceAddress, InterfaceConfig, - InterfaceConfigTable, InterfaceType, -}; -use crate::internal::routing::ospf::{OspfInterface, OspfNetwork}; -use net::eth::mac::{Mac, SourceMac}; -use net::interface::Mtu; -use net::vlan::Vid; - -fn interface_addresses_to_strings(interface: &InterfaceConfig) -> Vec { - interface - .addresses - .iter() - .map(|addr| format!("{addr}")) - .collect() -} - -impl TryFrom<&gateway_config::OspfInterface> for OspfInterface { - type Error = String; - - fn try_from(ospf_interface: &gateway_config::OspfInterface) -> Result { - // Parse area from string to Ipv4Addr - let area = ospf_interface - .area - .parse::() - .map_err(|_| format!("Invalid OSPF area format: {}", ospf_interface.area))?; - - // Create a new OspfInterface instance - let mut ospf_iface = OspfInterface::new(area); - - // Set passive state - ospf_iface = ospf_iface.set_passive(ospf_interface.passive); - - // Set cost if present - if let Some(cost) = ospf_interface.cost { - ospf_iface = ospf_iface.set_cost(cost); - } - - // Set network type if present - if let Some(network_type) = &ospf_interface.network_type { - let network = match gateway_config::OspfNetworkType::try_from(*network_type) { - Ok(gateway_config::OspfNetworkType::Broadcast) => OspfNetwork::Broadcast, - Ok(gateway_config::OspfNetworkType::NonBroadcast) => OspfNetwork::NonBroadcast, - Ok(gateway_config::OspfNetworkType::PointToPoint) => OspfNetwork::Point2Point, - Ok(gateway_config::OspfNetworkType::PointToMultipoint) => { - OspfNetwork::Point2Multipoint - } - Err(_) => return Err(format!("Invalid OSPF network type: {network_type}")), - }; - ospf_iface = ospf_iface.set_network(network); - } - - Ok(ospf_iface) - } -} - -impl TryFrom<&gateway_config::Interface> for InterfaceConfig { - type Error = String; - - fn try_from(iface: &gateway_config::Interface) -> Result { - // Convert interface type - let grpc_if_type = gateway_config::IfType::try_from(iface.r#type) - .map_err(|_| format!("Invalid interface type: {}", iface.r#type))?; - let mac = match &iface.macaddr { - Some(mac) => Some( - SourceMac::try_from( - Mac::try_from(mac.as_str()) - .map_err(|_| format!("String is not a valid MAC address: {mac}"))?, - ) - .map_err(|e| { - format!( - "Interface {} mac address ({mac}) must be a source mac address: {e}", - iface.name - ) - })?, - ), - None => None, - }; - - let iftype = match grpc_if_type { - gateway_config::IfType::Ethernet => InterfaceType::Ethernet(IfEthConfig { - mac: mac.map(SourceMac::inner), - }), - gateway_config::IfType::Vlan => { - // Safely handle the VLAN ID conversion - let vlan_id = iface - .vlan - .ok_or_else(|| "VLAN interface requires vlan ID".to_string())?; - - // Try to convert to u16 - let vlan_u16 = - u16::try_from(vlan_id).map_err(|_| format!("Invalid VLAN ID: {vlan_id}"))?; - - // Create a safe Vid - let vid = - Vid::new(vlan_u16).map_err(|_| format!("Invalid VLAN ID value: {vlan_u16}"))?; - - InterfaceType::Vlan(IfVlanConfig { - mac: mac.map(SourceMac::inner), - vlan_id: vid, - }) - } - gateway_config::IfType::Loopback => InterfaceType::Loopback, - gateway_config::IfType::Vtep => { - let local = match iface.ipaddrs.as_slice() { - [] => Err("VTEP interface requires an IP address".to_string()), - [addr] => { - let addr_mask = addr.parse::().map_err(|e| { - format!("Invalid interface address \"{addr}\" for VTEP interface: {e}",) - })?; - // Purposefully skip unicast check here because fuzzer generates multicast addresses - // Unicast is checked when we build the vtep interface later - let ipv4 = match addr_mask.address { - IpAddr::V4(ipv4) => ipv4, - IpAddr::V6(_) => { - return Err("VTEP interface requires an IPv4 address".to_string()); - } - }; - if addr_mask.mask_len == 32 { - Ok(ipv4) - } else { - Err("VTEP interface requires a /32 IP address".to_string()) - } - } - _ => Err("VTEP interface requires exactly one IP address".to_string()), - }?; - - InterfaceType::Vtep(IfVtepConfig { - mac: mac.map(SourceMac::inner), - vni: None, - ttl: None, - local, - }) - } - }; - - // Create new InterfaceConfig - let mut interface_config: InterfaceConfig = - InterfaceConfig::new(&iface.name, iftype, false); - - // Add the address from gRPC if present, - // But not for VTEP interfaces because we abuse the field to mean local IP - // See https://github.com/githedgehog/gateway-proto/issues/24 - if grpc_if_type != gateway_config::IfType::Vtep && !iface.ipaddrs.is_empty() { - for ips in &iface.ipaddrs { - let ifaddr = ips - .parse::() - .map_err(|e| format!("Invalid interface address \"{ips}\": {e}"))?; - interface_config = interface_config.add_address(ifaddr.address, ifaddr.mask_len); - } - } - - // Add OSPF interface configuration if present - if let Some(ospf_iface) = &iface.ospf { - let ospf_interface = OspfInterface::try_from(ospf_iface)?; - interface_config = interface_config.set_ospf(ospf_interface); - } - - // Set MTU if specified - if let Some(iface_mtu) = iface.mtu { - let mtu = Mtu::try_from(iface_mtu).map_err(|e| format!("Invalid MTU: {e}"))?; - interface_config = interface_config.set_mtu(mtu); - } - - // Set PCI address if specified - if let Some(pci) = &iface.pci { - let pci = PciAddress::try_from(pci.as_str()) - .map_err(|e| format!("Invalid PCI address: {e}"))?; - interface_config = interface_config.set_pci(pci); - } - - Ok(interface_config) - } -} - -impl TryFrom<&OspfInterface> for gateway_config::OspfInterface { - type Error = String; - - fn try_from(ospf_interface: &OspfInterface) -> Result { - // Convert network type if present - let network_type = ospf_interface.network.as_ref().map(|network| { - (match network { - OspfNetwork::Broadcast => gateway_config::OspfNetworkType::Broadcast, - OspfNetwork::NonBroadcast => gateway_config::OspfNetworkType::NonBroadcast, - OspfNetwork::Point2Point => gateway_config::OspfNetworkType::PointToPoint, - OspfNetwork::Point2Multipoint => gateway_config::OspfNetworkType::PointToMultipoint, - }) - .into() - }); - - Ok(gateway_config::OspfInterface { - passive: ospf_interface.passive, - area: ospf_interface.area.to_string(), - cost: ospf_interface.cost, - network_type, - }) - } -} - -impl TryFrom<&InterfaceConfig> for gateway_config::Interface { - type Error = String; - - fn try_from(interface: &InterfaceConfig) -> Result { - // Get IP address safely - //let ipaddr = get_primary_address(interface)?; - let interface_addresses = match &interface.iftype { - InterfaceType::Ethernet(_) | InterfaceType::Vlan(_) | InterfaceType::Loopback => { - interface_addresses_to_strings(interface) - } - InterfaceType::Vtep(vtep) => vec![format!("{}/32", vtep.local.to_string())], - }; - - // Convert interface type - let if_type = match &interface.iftype { - InterfaceType::Ethernet(_) => gateway_config::IfType::Ethernet, - InterfaceType::Vlan(_) => gateway_config::IfType::Vlan, - InterfaceType::Loopback => gateway_config::IfType::Loopback, - InterfaceType::Vtep(_) => gateway_config::IfType::Vtep, - }; - - // Get VLAN ID if available - let vlan = match &interface.iftype { - InterfaceType::Vlan(if_vlan_config) => Some(u32::from(if_vlan_config.vlan_id.as_u16())), - _ => None, - }; - - // Get MAC address if available - let macaddr = match &interface.iftype { - InterfaceType::Ethernet(eth_config) => eth_config.mac.as_ref().map(ToString::to_string), - InterfaceType::Vlan(vlan_config) => vlan_config.mac.as_ref().map(ToString::to_string), - InterfaceType::Vtep(vtep_config) => vtep_config.mac.as_ref().map(ToString::to_string), - InterfaceType::Loopback => None, - }; - - // Convert OSPF interface if present - let ospf = interface - .ospf - .as_ref() - .map(gateway_config::OspfInterface::try_from) - .transpose() - .map_err(|e| format!("Failed to convert OSPF interface: {e}"))?; - - // Convert MTU - let mtu = interface.mtu.map(|mtu| mtu.to_u32()); - - // Convert PCI address - let pci = interface.pci.map(|v| v.to_string()); - - // Create the gRPC interface - Ok(gateway_config::Interface { - name: interface.name.clone(), - ipaddrs: interface_addresses, - r#type: if_type.into(), - vlan, - macaddr, - system_name: None, // TODO: Implement when needed - role: gateway_config::IfRole::Fabric.into(), // Default to Fabric - ospf, - mtu, - pci, - }) - } -} - -impl TryFrom<&InterfaceConfigTable> for Vec { - type Error = String; - - fn try_from(interfaces: &InterfaceConfigTable) -> Result { - let mut grpc_interfaces = Vec::new(); - - for interface in interfaces.values() { - let grpc_iface = gateway_config::Interface::try_from(interface)?; - grpc_interfaces.push(grpc_iface); - } - - Ok(grpc_interfaces) - } -} diff --git a/config/src/converters/grpc/mod.rs b/config/src/converters/grpc/mod.rs deleted file mode 100644 index 5ab37a131..000000000 --- a/config/src/converters/grpc/mod.rs +++ /dev/null @@ -1,621 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Open Network Fabric Authors - -#![deny(clippy::all, clippy::pedantic)] -#![allow(clippy::missing_errors_doc)] -#![allow(clippy::must_use_candidate)] // Do not want to remove pub methods yet - -mod bgp; -mod device; -mod expose; -mod gateway_config; -mod gwgroups; -mod interface; -mod overlay; -mod peering; -mod status; -mod tracecfg; -mod underlay; -mod vpc; -mod vrf; - -pub use bgp::*; -#[allow(unused)] // Remove if we do anything but implement traits -pub use device::*; -#[allow(unused)] // Remove if we do anything but implement traits -pub use expose::*; -pub use gateway_config::*; -#[allow(unused)] // Remove if we do anything but implement traits -pub use gwgroups::*; -#[allow(unused)] // Remove if we do anything but implement traits -pub use interface::*; -#[allow(unused)] // Remove if we do anything but implement traits -pub use overlay::*; -#[allow(unused)] // Remove if we do anything but implement traits -pub use peering::*; -#[allow(unused)] // Remove if we do anything but implement traits -pub use status::*; -#[allow(unused)] // Remove if we do anything but implement traits -pub use tracecfg::*; -#[allow(unused)] // Remove if we do anything but implement traits -pub use underlay::*; -#[allow(unused)] // Remove if we do anything but implement traits -pub use vpc::*; -#[allow(unused)] // Remove if we do anything but implement traits -pub use vrf::*; - -#[cfg(test)] -mod test { - use gateway_config::GatewayConfig; - use gateway_config::GatewayGroupMember; - use gateway_config::config::GatewayGroup; - use gateway_config::config::TracingConfig as ApiTracingConfig; - use pretty_assertions::assert_eq; - - use crate::converters::grpc::convert_gateway_config_from_grpc_with_defaults; - use crate::converters::grpc::{ - convert_dataplane_status_from_grpc, convert_dataplane_status_to_grpc, - }; - use crate::external::communities::PriorityCommunityTable; - use crate::internal::device::DeviceConfig; - use crate::internal::interfaces::interface::InterfaceConfig; - - fn normalize_order(config: &GatewayConfig) -> GatewayConfig { - let mut config = config.clone(); - if let Some(overlay) = &mut config.overlay { - overlay.vpcs.sort_by_key(|vpc| vpc.name.clone()); - overlay.vpcs.iter_mut().for_each(|vpc| { - vpc.interfaces.sort_by_key(|iface| iface.name.clone()); - vpc.interfaces.iter_mut().for_each(|iface| { - iface.ipaddrs.sort_by_key(String::clone); - }); - }); - overlay.peerings.sort_by_key(|peering| peering.name.clone()); - overlay.peerings.iter_mut().for_each(|peering| { - peering.r#for.iter_mut().for_each(|peering_config| { - peering_config.expose.iter_mut().for_each(|expose| { - expose.ips.sort_by_key(|pip| format!("{pip:?}")); - expose - .r#as - .sort_by_key(|as_config| format!("{as_config:?}")); - }); - }); - }); - } - - if let Some(underlay) = &mut config.underlay { - underlay.vrfs.sort_by_key(|vrf| vrf.name.clone()); - underlay.vrfs.iter_mut().for_each(|vrf| { - vrf.interfaces.sort_by_key(|iface| iface.name.clone()); - vrf.interfaces.iter_mut().for_each(|iface| { - iface.ipaddrs.sort_by_key(String::clone); - }); - if let Some(router) = &mut vrf.router { - router.neighbors.iter_mut().for_each(|neighbor| { - neighbor.af_activate.sort_by_key(|af| *af); - }); - } - }); - } - - config - } - - #[test] - #[ignore = "Port ranges not yet supported in conversion"] // FIXME - fn test_bolero_gateway_config_to_external() { - bolero::check!() - .with_type::() - .for_each(|config| { - let external = convert_gateway_config_from_grpc_with_defaults(config).unwrap(); - let reserialized = gateway_config::GatewayConfig::try_from(&external).unwrap(); - assert_eq!(normalize_order(config), normalize_order(&reserialized)); - }); - } - - // Helper function to create a test ApiTracingConfig - fn create_tracing_config() -> ApiTracingConfig { - ApiTracingConfig { - default: 4, - taglevel: [ - ("tag0".to_string(), 0), - ("tag1".to_string(), 1), - ("tag2".to_string(), 2), - ("tag3".to_string(), 3), - ("tag4".to_string(), 4), - ] - .iter() - .cloned() - .collect(), - } - } - - // Helper function to create a test GatewayConfig - #[allow(clippy::too_many_lines)] - fn create_test_gateway_config() -> GatewayConfig { - // Create device - let device = gateway_config::Device { - tracing: Some(create_tracing_config()), - }; - - // Create interfaces for VRF - let eth0 = gateway_config::Interface { - name: "eth0".to_string(), - ipaddrs: vec!["192.168.1.1/24".to_string(), "192.168.2.1/24".to_string()], - r#type: 0, // Ethernet - role: 0, // Fabric - vlan: None, - macaddr: Some("00:11:22:33:44:55".to_string()), - system_name: None, - ospf: None, - mtu: Some(1500), - pci: Some("0000:02:00.1".to_string()), - }; - - let lo0 = gateway_config::Interface { - name: "lo0".to_string(), - ipaddrs: vec!["10.0.0.1/32".to_string()], - r#type: 2, // Loopback - role: 0, // Fabric - vlan: None, - macaddr: None, - system_name: None, - ospf: None, - mtu: None, - pci: None, - }; - - // Create BGP neighbor - let bgp_neighbor = gateway_config::BgpNeighbor { - address: "192.168.1.2".to_string(), - remote_asn: "65002".to_string(), - af_activate: vec![0, 2], // IPv4 Unicast and L2VPN EVPN - update_source: Some(gateway_config::config::BgpNeighborUpdateSource { - source: Some( - gateway_config::config::bgp_neighbor_update_source::Source::Address( - "192.168.1.2".to_string(), - ), - ), - }), - }; - - // Create BGP router config - let router_config = gateway_config::RouterConfig { - asn: "65001".to_string(), - router_id: "10.0.0.1".to_string(), - neighbors: vec![bgp_neighbor], - ipv4_unicast: Some(gateway_config::BgpAddressFamilyIPv4 { - redistribute_connected: true, - redistribute_static: false, - networks: vec!["192.168.1.0/24".to_string()], - }), - ipv6_unicast: None, - l2vpn_evpn: Some(gateway_config::BgpAddressFamilyL2vpnEvpn { - advertise_all_vni: true, - }), - route_maps: Vec::new(), - }; - - // Create VRF - let vrf = gateway_config::Vrf { - name: "default".to_string(), - interfaces: vec![eth0, lo0], - router: Some(router_config), - ospf: None, - }; - - // Create Underlay - let underlay = gateway_config::Underlay { vrfs: vec![vrf] }; - - // Create interfaces for VPCs - let vpc1_if1 = gateway_config::Interface { - name: "vpc1_if1".to_string(), - ipaddrs: vec!["10.1.1.1/24".to_string()], - r#type: 0, // Ethernet - role: 0, // Fabric - vlan: None, - macaddr: None, - system_name: None, - ospf: None, - mtu: None, - pci: Some("0000:02:00.1".to_string()), - }; - - let vpc2_if1 = gateway_config::Interface { - name: "vpc2_if1".to_string(), - ipaddrs: vec!["10.2.1.1/24".to_string()], - r#type: 0, // Ethernet - role: 0, // Fabric - vlan: None, - macaddr: None, - system_name: None, - ospf: None, - mtu: None, - pci: Some("0000:02:00.1".to_string()), - }; - - // Create VPCs - let vpc1 = gateway_config::Vpc { - name: "vpc-1".to_string(), - id: "0x202".to_string(), - vni: 1001, - interfaces: vec![vpc1_if1], - }; - - let vpc2 = gateway_config::Vpc { - name: "vpc-2".to_string(), - id: "2x122".to_string(), - vni: 1002, - interfaces: vec![vpc2_if1], - }; - - // Create PeeringIPs for expose rules - let include_ip = gateway_config::PeeringIPs { - rule: Some(gateway_config::config::peering_i_ps::Rule::Cidr( - "10.1.0.0/16".to_string(), - )), - }; - - let exclude_ip = gateway_config::PeeringIPs { - rule: Some(gateway_config::config::peering_i_ps::Rule::Not( - "10.1.2.0/24".to_string(), - )), - }; - - // Create PeeringAs for expose rules - let include_as = gateway_config::PeeringAs { - rule: Some(gateway_config::config::peering_as::Rule::Cidr( - "192.168.0.0/16".to_string(), - )), - }; - - let exclude_as = gateway_config::PeeringAs { - rule: Some(gateway_config::config::peering_as::Rule::Not( - "192.168.2.0/24".to_string(), - )), - }; - - // Create Expose rules - let vpc1_expose = gateway_config::Expose { - ips: vec![include_ip], - r#as: vec![include_as], - nat: Some(gateway_config::config::expose::Nat::Stateless( - gateway_config::config::PeeringStatelessNat {}, - )), - }; - - let vpc2_expose = gateway_config::Expose { - ips: vec![exclude_ip], - r#as: vec![exclude_as], - nat: Some(gateway_config::config::expose::Nat::Stateless( - gateway_config::config::PeeringStatelessNat {}, - )), - }; - - // Create PeeringEntryFor - let vpc1_entry = gateway_config::PeeringEntryFor { - vpc: "vpc-1".to_string(), - expose: vec![vpc1_expose], - }; - - let vpc2_entry = gateway_config::PeeringEntryFor { - vpc: "vpc-2".to_string(), - expose: vec![vpc2_expose], - }; - - // Create VpcPeering - let peering = gateway_config::VpcPeering { - name: "vpc1-vpc2-peering".to_string(), - r#for: vec![vpc1_entry, vpc2_entry], - gateway_group: "gw-group-1".to_string(), - }; - - // Create Overlay - let overlay = gateway_config::Overlay { - vpcs: vec![vpc1, vpc2], - peerings: vec![peering], - }; - - // Create gateway group - let gw_group = GatewayGroup { - name: "gw-group-1".to_string(), - members: vec![ - GatewayGroupMember { - name: "gw1".to_owned(), - priority: 1, - ipaddress: "172.128.0.1".to_string(), - }, - GatewayGroupMember { - name: "gw2".to_owned(), - priority: 2, - ipaddress: "172.128.0.2".to_string(), - }, - ], - }; - - // Create priority-to-community table - let mut commtable = PriorityCommunityTable::new(); - commtable.insert(0, "65000:800").unwrap(); - commtable.insert(1, "65000:801").unwrap(); - commtable.insert(2, "65000:802").unwrap(); - commtable.insert(3, "65000:803").unwrap(); - commtable.insert(4, "65000:804").unwrap(); - - // Create the full GatewayConfig - GatewayConfig { - generation: 42, - device: Some(device), - underlay: Some(underlay), - overlay: Some(overlay), - gw_groups: vec![gw_group], - communities: commtable.inner().clone(), - } - } - - #[test] - #[ignore = "Port ranges not yet supported in conversion"] // FIXME - fn test_convert_to_grpc_config() { - // Create test data - let grpc_config = create_test_gateway_config(); - // Call the conversion function (gRPC -> ExternalConfig) - let result = convert_gateway_config_from_grpc_with_defaults(&grpc_config); - - // Verify result - assert!( - result.is_ok(), - "Conversion from gRPC failed: {:?}", - result.err() - ); - let external_config = result.unwrap(); - - // ExternalConfig -> gRPC - let result = gateway_config::GatewayConfig::try_from(&external_config); - assert!( - result.is_ok(), - "Conversion to gRPC failed: {:?}", - result.err() - ); - let converted_grpc_config = result.unwrap(); - - assert_eq!(grpc_config, converted_grpc_config); - } - - #[test] - fn test_tryfrom_conversions() { - let tracing = create_tracing_config(); - - // Create test data with specific components - let device = gateway_config::Device { - tracing: Some(tracing.clone()), - }; - - let interface = gateway_config::Interface { - name: "eth0".to_string(), - ipaddrs: vec!["192.168.1.1/24".to_string()], - r#type: 0, // Ethernet - role: 0, // Fabric - vlan: None, - macaddr: Some("00:11:22:33:44:55".to_string()), - system_name: None, - ospf: None, - mtu: Some(9000), - pci: Some("0000:02:00.1".to_string()), - }; - - // DeviceConfig TryFrom - let device_config_result = DeviceConfig::try_from(&device); - assert!( - device_config_result.is_ok(), - "TryFrom for DeviceConfig failed" - ); - let device_config = device_config_result.unwrap(); - - // Back to gRPC - let device_back_result = gateway_config::Device::try_from(&device_config); - assert!(device_back_result.is_ok(), "TryFrom back to Device failed"); - let device_back = device_back_result.unwrap(); - assert_eq!(device_back.tracing.as_ref().unwrap(), &tracing); - - // InterfaceConfig TryFrom - let interface_config_result = InterfaceConfig::try_from(&interface); - assert!( - interface_config_result.is_ok(), - "TryFrom for InterfaceConfig failed" - ); - let interface_config = interface_config_result.unwrap(); - assert_eq!(interface_config.name, "eth0"); - assert!(!interface_config.addresses.is_empty()); - - // Back to gRPC - let interface_back_result = gateway_config::Interface::try_from(&interface_config); - assert!( - interface_back_result.is_ok(), - "TryFrom back to Interface failed" - ); - let interface_back = interface_back_result.unwrap(); - assert_eq!(interface_back.name, interface.name); - assert_eq!(interface_back.r#type, interface.r#type); - assert!(!interface_back.ipaddrs.is_empty()); - } - - #[allow(clippy::too_many_lines)] - fn create_test_status() -> gateway_config::GetDataplaneStatusResponse { - // interface_statuses - let interface_statuses = vec![ - gateway_config::InterfaceStatus { - ifname: "eth0".into(), - oper_status: gateway_config::InterfaceOperStatusType::InterfaceStatusOperUp as i32, - admin_status: gateway_config::InterfaceAdminStatusType::InterfaceAdminStatusUp - as i32, - }, - gateway_config::InterfaceStatus { - ifname: "eth1".into(), - oper_status: gateway_config::InterfaceOperStatusType::InterfaceStatusOperDown - as i32, - admin_status: gateway_config::InterfaceAdminStatusType::InterfaceAdminStatusDown - as i32, - }, - ]; - - // FRR - let frr_status = Some(gateway_config::FrrStatus { - zebra_status: gateway_config::ZebraStatusType::ZebraStatusConnected as i32, - frr_agent_status: gateway_config::FrrAgentStatusType::FrrAgentStatusConnected as i32, - applied_config_gen: 42, - restarts: 1, - applied_configs: 10, - failed_configs: 0, - }); - - // Dataplane overall - let dataplane_status = Some(gateway_config::DataplaneStatusInfo { - status: gateway_config::DataplaneStatusType::DataplaneStatusHealthy as i32, - }); - - // interface_runtime - let mut interface_runtime = std::collections::HashMap::new(); - interface_runtime.insert( - "eth0".to_string(), - gateway_config::InterfaceRuntimeStatus { - admin_status: gateway_config::InterfaceAdminStatusType::InterfaceAdminStatusUp - as i32, - oper_status: gateway_config::InterfaceOperStatusType::InterfaceStatusOperUp as i32, - mac: "00:11:22:33:44:55".into(), - mtu: 1500, - counters: Some(gateway_config::InterfaceCounters { - tx_bits: 1_000_000, - tx_bps: 1000.0, - tx_errors: 1, - rx_bits: 2_000_000, - rx_bps: 2000.0, - rx_errors: 2, - }), - }, - ); - - // BGP runtime - let bgp_msgs = Some(gateway_config::BgpMessages { - received: Some(gateway_config::BgpMessageCounters { - capability: 1, - keepalive: 10, - notification: 0, - open: 1, - route_refresh: 0, - update: 42, - }), - sent: Some(gateway_config::BgpMessageCounters { - capability: 1, - keepalive: 11, - notification: 0, - open: 1, - route_refresh: 0, - update: 40, - }), - }); - let v4pfx = Some(gateway_config::BgpNeighborPrefixes { - received: 100, - received_pre_policy: 120, - sent: 90, - }); - - let mut neighbors = std::collections::HashMap::new(); - neighbors.insert( - "192.0.2.1".to_string(), - gateway_config::BgpNeighborStatus { - enabled: true, - local_as: 65001, - peer_as: 65002, - peer_port: 179, - peer_group: "spines".into(), - remote_router_id: "10.0.0.2".into(), - session_state: gateway_config::BgpNeighborSessionState::BgpStateEstablished as i32, - connections_dropped: 0, - established_transitions: 3, - last_reset_reason: String::new(), - messages: bgp_msgs, - ipv4_unicast_prefixes: v4pfx, - ipv6_unicast_prefixes: None, - l2vpn_evpn_prefixes: None, - }, - ); - let mut vrfs = std::collections::HashMap::new(); - vrfs.insert("default".into(), gateway_config::BgpVrfStatus { neighbors }); - let bgp = Some(gateway_config::BgpStatus { vrfs }); - - // VPCs + VPC peering counters - let mut vpc_ifaces = std::collections::HashMap::new(); - vpc_ifaces.insert( - "veth0".into(), - gateway_config::VpcInterfaceStatus { - ifname: "veth0".into(), - admin_status: gateway_config::InterfaceAdminStatusType::InterfaceAdminStatusUp - as i32, - oper_status: gateway_config::InterfaceOperStatusType::InterfaceStatusOperUp as i32, - }, - ); - let mut vpcs = std::collections::HashMap::new(); - vpcs.insert( - "vpc-1".into(), - gateway_config::VpcStatus { - id: "0x202".into(), - name: "vpc-1".into(), - vni: 1001, - route_count: 17, - interfaces: vpc_ifaces, - }, - ); - - let mut vpc_peering_counters = std::collections::HashMap::new(); - vpc_peering_counters.insert( - "peering-1".into(), - gateway_config::VpcPeeringCounters { - name: "peering-1".into(), - src_vpc: "vpc-1".into(), - dst_vpc: "vpc-2".into(), - packets: 12_345, - bytes: 987_654, - drops: 12, - pps: 321.0, - bps: 123_456.0, - }, - ); - - // vpc_counters - let mut vpc_counters = std::collections::HashMap::new(); - vpc_counters.insert( - "vpc-1".into(), - gateway_config::VpcCounters { - name: "vpc-1".into(), - packets: 100_000, - drops: 42, - bytes: 6_400_000, - }, - ); - - gateway_config::GetDataplaneStatusResponse { - interface_statuses, - frr_status, - dataplane_status, - interface_runtime, - bgp, - vpcs, - vpc_peering_counters, - vpc_counters, - } - } - - #[test] - fn test_convert_to_from_grpc_status() { - let grpc_status = create_test_status(); - - // gRPC -> internal - let internal = convert_dataplane_status_from_grpc(&grpc_status) - .expect("conversion from gRPC status failed"); - - // internal -> gRPC - let back = - convert_dataplane_status_to_grpc(&internal).expect("conversion to gRPC status failed"); - - assert_eq!(grpc_status, back); - } -} diff --git a/config/src/converters/grpc/overlay.rs b/config/src/converters/grpc/overlay.rs deleted file mode 100644 index e053ea8b9..000000000 --- a/config/src/converters/grpc/overlay.rs +++ /dev/null @@ -1,72 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Open Network Fabric Authors - -use gateway_config::config as gateway_config; - -use tracing::error; - -use crate::external::overlay::Overlay; -use crate::external::overlay::vpc::{Vpc, VpcTable}; -use crate::external::overlay::vpcpeering::{VpcPeering, VpcPeeringTable}; - -// Overlay conversions -impl TryFrom<&gateway_config::Overlay> for Overlay { - type Error = String; - - fn try_from(overlay: &gateway_config::Overlay) -> Result { - // Create VPC table - let mut vpc_table = VpcTable::new(); - - // Add VPCs - for vpc_grpc in &overlay.vpcs { - // Convert VPC - let vpc = Vpc::try_from(vpc_grpc)?; - - vpc_table.add(vpc).map_err(|e| { - let msg = format!("Failed to add VPC {}: {e}", vpc_grpc.name); - error!("{msg}"); - msg - })?; - } - - // Create peering table - let mut peering_table = VpcPeeringTable::new(); - - // Add peerings - for peering_grpc in &overlay.peerings { - // Convert peering - let peering = VpcPeering::try_from(peering_grpc)?; - - // Add to table - peering_table - .add(peering) - .map_err(|e| format!("Failed to add peering {}: {e}", peering_grpc.name))?; - } - - // Create overlay with the tables - Ok(Overlay::new(vpc_table, peering_table)) - } -} - -impl TryFrom<&Overlay> for gateway_config::Overlay { - type Error = String; - - fn try_from(overlay: &Overlay) -> Result { - let mut vpcs = Vec::new(); - let mut peerings = Vec::new(); - - // Convert VPCs - for vpc in overlay.vpc_table.values() { - let grpc_vpc = gateway_config::Vpc::try_from(vpc)?; - vpcs.push(grpc_vpc); - } - - // Convert peerings - for peering in overlay.peering_table.values() { - let grpc_peering = gateway_config::VpcPeering::try_from(peering)?; - peerings.push(grpc_peering); - } - - Ok(gateway_config::Overlay { vpcs, peerings }) - } -} diff --git a/config/src/converters/grpc/peering.rs b/config/src/converters/grpc/peering.rs deleted file mode 100644 index 4937f19df..000000000 --- a/config/src/converters/grpc/peering.rs +++ /dev/null @@ -1,99 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Open Network Fabric Authors - -use gateway_config::config as gateway_config; - -use crate::external::overlay::vpcpeering::VpcExpose; -use crate::external::overlay::vpcpeering::VpcManifest; -use crate::external::overlay::vpcpeering::VpcPeering; - -// VPC Peering conversions -impl TryFrom<&gateway_config::VpcPeering> for VpcPeering { - type Error = String; - - fn try_from(peering: &gateway_config::VpcPeering) -> Result { - let (vpc1_manifest, vpc2_manifest) = match peering.r#for.as_slice() { - [vpc1, vpc2] => { - let vpc1_manifest = VpcManifest::try_from(vpc1)?; - let vpc2_manifest = VpcManifest::try_from(vpc2)?; - Ok((vpc1_manifest, vpc2_manifest)) - } - _ => Err(format!( - "VPC peering {} must have exactly two VPCs", - peering.name - )), - }?; - - let gwgroup = if peering.gateway_group.is_empty() { - None - } else { - Some(peering.gateway_group.clone()) - }; - - // Create the peering using the constructor - Ok(VpcPeering::new( - &peering.name, - vpc1_manifest, - vpc2_manifest, - gwgroup, - )) - } -} - -impl TryFrom<&VpcPeering> for gateway_config::VpcPeering { - type Error = String; - - fn try_from(peering: &VpcPeering) -> Result { - // Convert the left and right VPC manifests - let left_for = gateway_config::PeeringEntryFor::try_from(&peering.left)?; - let right_for = gateway_config::PeeringEntryFor::try_from(&peering.right)?; - - Ok(gateway_config::VpcPeering { - name: peering.name.clone(), - r#for: vec![left_for, right_for], - gateway_group: peering.gw_group.clone().unwrap_or_default(), - }) - } -} - -// VPC Manifest conversions -impl TryFrom<&gateway_config::PeeringEntryFor> for VpcManifest { - type Error = String; - - fn try_from(entry: &gateway_config::PeeringEntryFor) -> Result { - // Create a new VPC manifest with the VPC name - let mut manifest = VpcManifest::new(&entry.vpc); - - // Process each expose rule - for expose_grpc in &entry.expose { - let expose = VpcExpose::try_from(expose_grpc)?; - manifest.add_expose(expose).map_err(|e| { - format!( - "Failed to add expose to manifest for VPC {}: {e}", - entry.vpc - ) - })?; - } - - Ok(manifest) - } -} - -impl TryFrom<&VpcManifest> for gateway_config::PeeringEntryFor { - type Error = String; - - fn try_from(manifest: &VpcManifest) -> Result { - let mut expose_rules = Vec::new(); - - // Convert each expose rule - for expose in &manifest.exposes { - let grpc_expose = gateway_config::Expose::try_from(expose)?; - expose_rules.push(grpc_expose); - } - - Ok(gateway_config::PeeringEntryFor { - vpc: manifest.name.clone(), - expose: expose_rules, - }) - } -} diff --git a/config/src/converters/grpc/status.rs b/config/src/converters/grpc/status.rs deleted file mode 100644 index 1b0a66d70..000000000 --- a/config/src/converters/grpc/status.rs +++ /dev/null @@ -1,927 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Open Network Fabric Authors - -//! Conversions between gRPC (prost) status structs and internal status model. - -use gateway_config::config as gateway_config; -use std::collections::HashMap; -use std::convert::TryFrom; - -pub fn convert_dataplane_status_from_grpc( - grpc_status: &gateway_config::GetDataplaneStatusResponse, -) -> Result { - DataplaneStatus::try_from(grpc_status) -} - -pub fn convert_dataplane_status_to_grpc( - internal: &DataplaneStatus, -) -> Result { - gateway_config::GetDataplaneStatusResponse::try_from(internal) -} - -use crate::internal::status::{ - BgpMessageCounters, BgpMessages, BgpNeighborPrefixes, BgpNeighborSessionState, - BgpNeighborStatus, BgpStatus, BgpVrfStatus, DataplaneStatus, DataplaneStatusInfo, - DataplaneStatusType, FrrAgentStatusType, FrrStatus, InterfaceAdminStatusType, - InterfaceCounters, InterfaceOperStatusType, InterfaceRuntimeStatus, InterfaceStatus, - VpcCounters, VpcInterfaceStatus, VpcPeeringCounters, VpcStatus, ZebraStatusType, -}; - -impl TryFrom<&gateway_config::InterfaceStatus> for InterfaceStatus { - type Error = String; - - fn try_from(p: &gateway_config::InterfaceStatus) -> Result { - let oper = match gateway_config::InterfaceOperStatusType::try_from(p.oper_status) { - Ok(gateway_config::InterfaceOperStatusType::InterfaceStatusUnknown) => { - InterfaceOperStatusType::Unknown - } - Ok(gateway_config::InterfaceOperStatusType::InterfaceStatusOperUp) => { - InterfaceOperStatusType::OperUp - } - Ok(gateway_config::InterfaceOperStatusType::InterfaceStatusOperDown) => { - InterfaceOperStatusType::OperDown - } - Ok(gateway_config::InterfaceOperStatusType::InterfaceStatusError) => { - InterfaceOperStatusType::Error - } - Err(_) => { - return Err(format!( - "Invalid InterfaceOperStatusType: {}", - p.oper_status - )); - } - }; - - let admin = match gateway_config::InterfaceAdminStatusType::try_from(p.admin_status) { - Ok(gateway_config::InterfaceAdminStatusType::InterfaceAdminStatusUnknown) => { - InterfaceAdminStatusType::Unknown - } - Ok(gateway_config::InterfaceAdminStatusType::InterfaceAdminStatusUp) => { - InterfaceAdminStatusType::Up - } - Ok(gateway_config::InterfaceAdminStatusType::InterfaceAdminStatusDown) => { - InterfaceAdminStatusType::Down - } - Err(_) => { - return Err(format!( - "Invalid InterfaceAdminStatusType: {}", - p.admin_status - )); - } - }; - - Ok(InterfaceStatus { - ifname: p.ifname.clone(), - oper_status: oper, - admin_status: admin, - }) - } -} - -impl TryFrom<&InterfaceStatus> for gateway_config::InterfaceStatus { - type Error = String; - - fn try_from(s: &InterfaceStatus) -> Result { - let oper = match s.oper_status { - InterfaceOperStatusType::Unknown => { - gateway_config::InterfaceOperStatusType::InterfaceStatusUnknown - } - InterfaceOperStatusType::OperUp => { - gateway_config::InterfaceOperStatusType::InterfaceStatusOperUp - } - InterfaceOperStatusType::OperDown => { - gateway_config::InterfaceOperStatusType::InterfaceStatusOperDown - } - InterfaceOperStatusType::Error => { - gateway_config::InterfaceOperStatusType::InterfaceStatusError - } - }; - - let admin = match s.admin_status { - InterfaceAdminStatusType::Unknown => { - gateway_config::InterfaceAdminStatusType::InterfaceAdminStatusUnknown - } - InterfaceAdminStatusType::Up => { - gateway_config::InterfaceAdminStatusType::InterfaceAdminStatusUp - } - InterfaceAdminStatusType::Down => { - gateway_config::InterfaceAdminStatusType::InterfaceAdminStatusDown - } - }; - - Ok(gateway_config::InterfaceStatus { - ifname: s.ifname.clone(), - oper_status: oper.into(), - admin_status: admin.into(), - }) - } -} - -impl TryFrom<&gateway_config::InterfaceCounters> for InterfaceCounters { - type Error = String; - - fn try_from(p: &gateway_config::InterfaceCounters) -> Result { - Ok(InterfaceCounters { - tx_bits: p.tx_bits, - tx_bps: p.tx_bps, - tx_errors: p.tx_errors, - rx_bits: p.rx_bits, - rx_bps: p.rx_bps, - rx_errors: p.rx_errors, - }) - } -} - -impl TryFrom<&InterfaceCounters> for gateway_config::InterfaceCounters { - type Error = String; - - fn try_from(c: &InterfaceCounters) -> Result { - Ok(gateway_config::InterfaceCounters { - tx_bits: c.tx_bits, - tx_bps: c.tx_bps, - tx_errors: c.tx_errors, - rx_bits: c.rx_bits, - rx_bps: c.rx_bps, - rx_errors: c.rx_errors, - }) - } -} - -impl TryFrom<&gateway_config::InterfaceRuntimeStatus> for InterfaceRuntimeStatus { - type Error = String; - - fn try_from(p: &gateway_config::InterfaceRuntimeStatus) -> Result { - let admin = match gateway_config::InterfaceAdminStatusType::try_from(p.admin_status) { - Ok(gateway_config::InterfaceAdminStatusType::InterfaceAdminStatusUnknown) => { - InterfaceAdminStatusType::Unknown - } - Ok(gateway_config::InterfaceAdminStatusType::InterfaceAdminStatusUp) => { - InterfaceAdminStatusType::Up - } - Ok(gateway_config::InterfaceAdminStatusType::InterfaceAdminStatusDown) => { - InterfaceAdminStatusType::Down - } - Err(_) => { - return Err(format!( - "Invalid InterfaceAdminStatusType: {}", - p.admin_status - )); - } - }; - let oper = match gateway_config::InterfaceOperStatusType::try_from(p.oper_status) { - Ok(gateway_config::InterfaceOperStatusType::InterfaceStatusUnknown) => { - InterfaceOperStatusType::Unknown - } - Ok(gateway_config::InterfaceOperStatusType::InterfaceStatusOperUp) => { - InterfaceOperStatusType::OperUp - } - Ok(gateway_config::InterfaceOperStatusType::InterfaceStatusOperDown) => { - InterfaceOperStatusType::OperDown - } - Ok(gateway_config::InterfaceOperStatusType::InterfaceStatusError) => { - InterfaceOperStatusType::Error - } - Err(_) => { - return Err(format!( - "Invalid InterfaceOperStatusType: {}", - p.oper_status - )); - } - }; - - Ok(InterfaceRuntimeStatus { - admin_status: admin, - oper_status: oper, - mac: p.mac.clone(), - mtu: p.mtu, - counters: p - .counters - .as_ref() - .map(InterfaceCounters::try_from) - .transpose()?, - }) - } -} - -impl TryFrom<&InterfaceRuntimeStatus> for gateway_config::InterfaceRuntimeStatus { - type Error = String; - - fn try_from(r: &InterfaceRuntimeStatus) -> Result { - let admin = match r.admin_status { - InterfaceAdminStatusType::Unknown => { - gateway_config::InterfaceAdminStatusType::InterfaceAdminStatusUnknown - } - InterfaceAdminStatusType::Up => { - gateway_config::InterfaceAdminStatusType::InterfaceAdminStatusUp - } - InterfaceAdminStatusType::Down => { - gateway_config::InterfaceAdminStatusType::InterfaceAdminStatusDown - } - }; - let oper = match r.oper_status { - InterfaceOperStatusType::Unknown => { - gateway_config::InterfaceOperStatusType::InterfaceStatusUnknown - } - InterfaceOperStatusType::OperUp => { - gateway_config::InterfaceOperStatusType::InterfaceStatusOperUp - } - InterfaceOperStatusType::OperDown => { - gateway_config::InterfaceOperStatusType::InterfaceStatusOperDown - } - InterfaceOperStatusType::Error => { - gateway_config::InterfaceOperStatusType::InterfaceStatusError - } - }; - - Ok(gateway_config::InterfaceRuntimeStatus { - admin_status: admin.into(), - oper_status: oper.into(), - mac: r.mac.clone(), - mtu: r.mtu, - counters: r - .counters - .as_ref() - .map(gateway_config::InterfaceCounters::try_from) - .transpose()?, - }) - } -} - -impl TryFrom<&gateway_config::FrrStatus> for FrrStatus { - type Error = String; - - fn try_from(p: &gateway_config::FrrStatus) -> Result { - let zebra = match gateway_config::ZebraStatusType::try_from(p.zebra_status) { - Ok(gateway_config::ZebraStatusType::ZebraStatusNotConnected) => { - ZebraStatusType::NotConnected - } - Ok(gateway_config::ZebraStatusType::ZebraStatusConnected) => ZebraStatusType::Connected, - Err(_) => return Err(format!("Invalid ZebraStatusType: {}", p.zebra_status)), - }; - let agent = match gateway_config::FrrAgentStatusType::try_from(p.frr_agent_status) { - Ok(gateway_config::FrrAgentStatusType::FrrAgentStatusNotConnected) => { - FrrAgentStatusType::NotConnected - } - Ok(gateway_config::FrrAgentStatusType::FrrAgentStatusConnected) => { - FrrAgentStatusType::Connected - } - Err(_) => { - return Err(format!( - "Invalid FrrAgentStatusType: {}", - p.frr_agent_status - )); - } - }; - - Ok(FrrStatus { - zebra_status: zebra, - frr_agent_status: agent, - applied_config_gen: p.applied_config_gen, - restarts: p.restarts, - applied_configs: p.applied_configs, - failed_configs: p.failed_configs, - }) - } -} - -impl TryFrom<&FrrStatus> for gateway_config::FrrStatus { - type Error = String; - - fn try_from(s: &FrrStatus) -> Result { - let zebra = match s.zebra_status { - ZebraStatusType::NotConnected => { - gateway_config::ZebraStatusType::ZebraStatusNotConnected - } - ZebraStatusType::Connected => gateway_config::ZebraStatusType::ZebraStatusConnected, - }; - let agent = match s.frr_agent_status { - FrrAgentStatusType::NotConnected => { - gateway_config::FrrAgentStatusType::FrrAgentStatusNotConnected - } - FrrAgentStatusType::Connected => { - gateway_config::FrrAgentStatusType::FrrAgentStatusConnected - } - }; - - Ok(gateway_config::FrrStatus { - zebra_status: zebra.into(), - frr_agent_status: agent.into(), - applied_config_gen: s.applied_config_gen, - restarts: s.restarts, - applied_configs: s.applied_configs, - failed_configs: s.failed_configs, - }) - } -} - -impl TryFrom<&gateway_config::DataplaneStatusInfo> for DataplaneStatusInfo { - type Error = String; - - fn try_from(p: &gateway_config::DataplaneStatusInfo) -> Result { - let stat = match gateway_config::DataplaneStatusType::try_from(p.status) { - Ok(gateway_config::DataplaneStatusType::DataplaneStatusUnknown) => { - DataplaneStatusType::Unknown - } - Ok(gateway_config::DataplaneStatusType::DataplaneStatusHealthy) => { - DataplaneStatusType::Healthy - } - Ok(gateway_config::DataplaneStatusType::DataplaneStatusInit) => { - DataplaneStatusType::Init - } - Ok(gateway_config::DataplaneStatusType::DataplaneStatusError) => { - DataplaneStatusType::Error - } - Err(_) => return Err(format!("Invalid DataplaneStatusType: {}", p.status)), - }; - Ok(DataplaneStatusInfo { status: stat }) - } -} - -impl TryFrom<&DataplaneStatusInfo> for gateway_config::DataplaneStatusInfo { - type Error = String; - - fn try_from(s: &DataplaneStatusInfo) -> Result { - let stat = match s.status { - DataplaneStatusType::Unknown => { - gateway_config::DataplaneStatusType::DataplaneStatusUnknown - } - DataplaneStatusType::Healthy => { - gateway_config::DataplaneStatusType::DataplaneStatusHealthy - } - DataplaneStatusType::Init => gateway_config::DataplaneStatusType::DataplaneStatusInit, - DataplaneStatusType::Error => gateway_config::DataplaneStatusType::DataplaneStatusError, - }; - Ok(gateway_config::DataplaneStatusInfo { - status: stat.into(), - }) - } -} - -impl TryFrom<&gateway_config::BgpMessageCounters> for BgpMessageCounters { - type Error = String; - - fn try_from(p: &gateway_config::BgpMessageCounters) -> Result { - Ok(BgpMessageCounters { - capability: p.capability, - keepalive: p.keepalive, - notification: p.notification, - open: p.open, - route_refresh: p.route_refresh, - update: p.update, - }) - } -} - -impl TryFrom<&BgpMessageCounters> for gateway_config::BgpMessageCounters { - type Error = String; - - fn try_from(c: &BgpMessageCounters) -> Result { - Ok(gateway_config::BgpMessageCounters { - capability: c.capability, - keepalive: c.keepalive, - notification: c.notification, - open: c.open, - route_refresh: c.route_refresh, - update: c.update, - }) - } -} - -impl TryFrom<&gateway_config::BgpMessages> for BgpMessages { - type Error = String; - - fn try_from(p: &gateway_config::BgpMessages) -> Result { - Ok(BgpMessages { - received: p - .received - .as_ref() - .map(BgpMessageCounters::try_from) - .transpose()?, - sent: p - .sent - .as_ref() - .map(BgpMessageCounters::try_from) - .transpose()?, - }) - } -} - -impl TryFrom<&BgpMessages> for gateway_config::BgpMessages { - type Error = String; - - fn try_from(m: &BgpMessages) -> Result { - Ok(gateway_config::BgpMessages { - received: m - .received - .as_ref() - .map(gateway_config::BgpMessageCounters::try_from) - .transpose()?, - sent: m - .sent - .as_ref() - .map(gateway_config::BgpMessageCounters::try_from) - .transpose()?, - }) - } -} - -impl TryFrom<&gateway_config::BgpNeighborPrefixes> for BgpNeighborPrefixes { - type Error = String; - - fn try_from(p: &gateway_config::BgpNeighborPrefixes) -> Result { - Ok(BgpNeighborPrefixes { - received: p.received, - received_pre_policy: p.received_pre_policy, - sent: p.sent, - }) - } -} - -impl TryFrom<&BgpNeighborPrefixes> for gateway_config::BgpNeighborPrefixes { - type Error = String; - - fn try_from(p: &BgpNeighborPrefixes) -> Result { - Ok(gateway_config::BgpNeighborPrefixes { - received: p.received, - received_pre_policy: p.received_pre_policy, - sent: p.sent, - }) - } -} - -impl TryFrom<&gateway_config::BgpNeighborStatus> for BgpNeighborStatus { - type Error = String; - - fn try_from(p: &gateway_config::BgpNeighborStatus) -> Result { - let state = match gateway_config::BgpNeighborSessionState::try_from(p.session_state) { - Ok(gateway_config::BgpNeighborSessionState::BgpStateUnset) => { - BgpNeighborSessionState::Unset - } - Ok(gateway_config::BgpNeighborSessionState::BgpStateIdle) => { - BgpNeighborSessionState::Idle - } - Ok(gateway_config::BgpNeighborSessionState::BgpStateConnect) => { - BgpNeighborSessionState::Connect - } - Ok(gateway_config::BgpNeighborSessionState::BgpStateActive) => { - BgpNeighborSessionState::Active - } - Ok(gateway_config::BgpNeighborSessionState::BgpStateOpen) => { - BgpNeighborSessionState::Open - } - Ok(gateway_config::BgpNeighborSessionState::BgpStateEstablished) => { - BgpNeighborSessionState::Established - } - Err(_) => { - return Err(format!( - "Invalid BgpNeighborSessionState: {}", - p.session_state - )); - } - }; - - Ok(BgpNeighborStatus { - enabled: p.enabled, - local_as: p.local_as, - peer_as: p.peer_as, - peer_port: p.peer_port, - peer_group: p.peer_group.clone(), - remote_router_id: p.remote_router_id.clone(), - session_state: state, - connections_dropped: p.connections_dropped, - established_transitions: p.established_transitions, - last_reset_reason: p.last_reset_reason.clone(), - messages: p.messages.as_ref().map(BgpMessages::try_from).transpose()?, - ipv4_unicast_prefixes: p - .ipv4_unicast_prefixes - .as_ref() - .map(BgpNeighborPrefixes::try_from) - .transpose()?, - ipv6_unicast_prefixes: p - .ipv6_unicast_prefixes - .as_ref() - .map(BgpNeighborPrefixes::try_from) - .transpose()?, - l2vpn_evpn_prefixes: p - .l2vpn_evpn_prefixes - .as_ref() - .map(BgpNeighborPrefixes::try_from) - .transpose()?, - }) - } -} - -impl TryFrom<&BgpNeighborStatus> for gateway_config::BgpNeighborStatus { - type Error = String; - - fn try_from(s: &BgpNeighborStatus) -> Result { - let state = match s.session_state { - BgpNeighborSessionState::Unset => { - gateway_config::BgpNeighborSessionState::BgpStateUnset - } - BgpNeighborSessionState::Idle => gateway_config::BgpNeighborSessionState::BgpStateIdle, - BgpNeighborSessionState::Connect => { - gateway_config::BgpNeighborSessionState::BgpStateConnect - } - BgpNeighborSessionState::Active => { - gateway_config::BgpNeighborSessionState::BgpStateActive - } - BgpNeighborSessionState::Open => gateway_config::BgpNeighborSessionState::BgpStateOpen, - BgpNeighborSessionState::Established => { - gateway_config::BgpNeighborSessionState::BgpStateEstablished - } - }; - - Ok(gateway_config::BgpNeighborStatus { - enabled: s.enabled, - local_as: s.local_as, - peer_as: s.peer_as, - peer_port: s.peer_port, - peer_group: s.peer_group.clone(), - remote_router_id: s.remote_router_id.clone(), - session_state: state.into(), - connections_dropped: s.connections_dropped, - established_transitions: s.established_transitions, - last_reset_reason: s.last_reset_reason.clone(), - messages: s - .messages - .as_ref() - .map(gateway_config::BgpMessages::try_from) - .transpose()?, - ipv4_unicast_prefixes: s - .ipv4_unicast_prefixes - .as_ref() - .map(gateway_config::BgpNeighborPrefixes::try_from) - .transpose()?, - ipv6_unicast_prefixes: s - .ipv6_unicast_prefixes - .as_ref() - .map(gateway_config::BgpNeighborPrefixes::try_from) - .transpose()?, - l2vpn_evpn_prefixes: s - .l2vpn_evpn_prefixes - .as_ref() - .map(gateway_config::BgpNeighborPrefixes::try_from) - .transpose()?, - }) - } -} - -impl TryFrom<&gateway_config::BgpVrfStatus> for BgpVrfStatus { - type Error = String; - - fn try_from(p: &gateway_config::BgpVrfStatus) -> Result { - let mut neighbors = HashMap::with_capacity(p.neighbors.len()); - for (k, v) in &p.neighbors { - neighbors.insert(k.clone(), BgpNeighborStatus::try_from(v)?); - } - Ok(BgpVrfStatus { neighbors }) - } -} - -impl TryFrom<&BgpVrfStatus> for gateway_config::BgpVrfStatus { - type Error = String; - - fn try_from(s: &BgpVrfStatus) -> Result { - let mut neighbors = HashMap::with_capacity(s.neighbors.len()); - for (k, v) in &s.neighbors { - neighbors.insert(k.clone(), gateway_config::BgpNeighborStatus::try_from(v)?); - } - Ok(gateway_config::BgpVrfStatus { neighbors }) - } -} - -impl TryFrom<&gateway_config::BgpStatus> for BgpStatus { - type Error = String; - - fn try_from(p: &gateway_config::BgpStatus) -> Result { - let mut vrfs = HashMap::with_capacity(p.vrfs.len()); - for (k, v) in &p.vrfs { - vrfs.insert(k.clone(), BgpVrfStatus::try_from(v)?); - } - Ok(BgpStatus { vrfs }) - } -} - -impl TryFrom<&BgpStatus> for gateway_config::BgpStatus { - type Error = String; - - fn try_from(s: &BgpStatus) -> Result { - let mut vrfs = HashMap::with_capacity(s.vrfs.len()); - for (k, v) in &s.vrfs { - vrfs.insert(k.clone(), gateway_config::BgpVrfStatus::try_from(v)?); - } - Ok(gateway_config::BgpStatus { vrfs }) - } -} - -impl TryFrom<&gateway_config::VpcInterfaceStatus> for VpcInterfaceStatus { - type Error = String; - - fn try_from(p: &gateway_config::VpcInterfaceStatus) -> Result { - let admin = match gateway_config::InterfaceAdminStatusType::try_from(p.admin_status) { - Ok(gateway_config::InterfaceAdminStatusType::InterfaceAdminStatusUnknown) => { - InterfaceAdminStatusType::Unknown - } - Ok(gateway_config::InterfaceAdminStatusType::InterfaceAdminStatusUp) => { - InterfaceAdminStatusType::Up - } - Ok(gateway_config::InterfaceAdminStatusType::InterfaceAdminStatusDown) => { - InterfaceAdminStatusType::Down - } - Err(_) => { - return Err(format!( - "Invalid InterfaceAdminStatusType: {}", - p.admin_status - )); - } - }; - let oper = match gateway_config::InterfaceOperStatusType::try_from(p.oper_status) { - Ok(gateway_config::InterfaceOperStatusType::InterfaceStatusUnknown) => { - InterfaceOperStatusType::Unknown - } - Ok(gateway_config::InterfaceOperStatusType::InterfaceStatusOperUp) => { - InterfaceOperStatusType::OperUp - } - Ok(gateway_config::InterfaceOperStatusType::InterfaceStatusOperDown) => { - InterfaceOperStatusType::OperDown - } - Ok(gateway_config::InterfaceOperStatusType::InterfaceStatusError) => { - InterfaceOperStatusType::Error - } - Err(_) => { - return Err(format!( - "Invalid InterfaceOperStatusType: {}", - p.oper_status - )); - } - }; - - Ok(VpcInterfaceStatus { - ifname: p.ifname.clone(), - admin_status: admin, - oper_status: oper, - }) - } -} - -impl TryFrom<&VpcInterfaceStatus> for gateway_config::VpcInterfaceStatus { - type Error = String; - - fn try_from(s: &VpcInterfaceStatus) -> Result { - let admin = match s.admin_status { - InterfaceAdminStatusType::Unknown => { - gateway_config::InterfaceAdminStatusType::InterfaceAdminStatusUnknown - } - InterfaceAdminStatusType::Up => { - gateway_config::InterfaceAdminStatusType::InterfaceAdminStatusUp - } - InterfaceAdminStatusType::Down => { - gateway_config::InterfaceAdminStatusType::InterfaceAdminStatusDown - } - }; - let oper = match s.oper_status { - InterfaceOperStatusType::Unknown => { - gateway_config::InterfaceOperStatusType::InterfaceStatusUnknown - } - InterfaceOperStatusType::OperUp => { - gateway_config::InterfaceOperStatusType::InterfaceStatusOperUp - } - InterfaceOperStatusType::OperDown => { - gateway_config::InterfaceOperStatusType::InterfaceStatusOperDown - } - InterfaceOperStatusType::Error => { - gateway_config::InterfaceOperStatusType::InterfaceStatusError - } - }; - - Ok(gateway_config::VpcInterfaceStatus { - ifname: s.ifname.clone(), - admin_status: admin.into(), - oper_status: oper.into(), - }) - } -} - -impl TryFrom<&gateway_config::VpcStatus> for VpcStatus { - type Error = String; - - fn try_from(p: &gateway_config::VpcStatus) -> Result { - let mut interfaces = HashMap::with_capacity(p.interfaces.len()); - for (k, v) in &p.interfaces { - interfaces.insert(k.clone(), VpcInterfaceStatus::try_from(v)?); - } - - Ok(VpcStatus { - id: p.id.clone(), - name: p.name.clone(), - vni: p.vni, - route_count: p.route_count, - interfaces, - }) - } -} - -impl TryFrom<&VpcStatus> for gateway_config::VpcStatus { - type Error = String; - - fn try_from(s: &VpcStatus) -> Result { - let mut interfaces = HashMap::with_capacity(s.interfaces.len()); - for (k, v) in &s.interfaces { - interfaces.insert(k.clone(), gateway_config::VpcInterfaceStatus::try_from(v)?); - } - - Ok(gateway_config::VpcStatus { - id: s.id.clone(), - name: s.name.clone(), - vni: s.vni, - route_count: s.route_count, - interfaces, - }) - } -} - -impl TryFrom<&gateway_config::VpcPeeringCounters> for VpcPeeringCounters { - type Error = String; - - fn try_from(p: &gateway_config::VpcPeeringCounters) -> Result { - Ok(VpcPeeringCounters { - name: p.name.clone(), - src_vpc: p.src_vpc.clone(), - dst_vpc: p.dst_vpc.clone(), - packets: p.packets, - bytes: p.bytes, - drops: p.drops, - pps: p.pps, - bps: p.bps, - }) - } -} - -impl TryFrom<&VpcPeeringCounters> for gateway_config::VpcPeeringCounters { - type Error = String; - - fn try_from(c: &VpcPeeringCounters) -> Result { - Ok(gateway_config::VpcPeeringCounters { - name: c.name.clone(), - src_vpc: c.src_vpc.clone(), - dst_vpc: c.dst_vpc.clone(), - packets: c.packets, - bytes: c.bytes, - drops: c.drops, - pps: c.pps, - bps: c.bps, - }) - } -} - -/* ========================= */ -/* ===== VpcCounters ======= */ -/* ========================= */ - -impl TryFrom<&gateway_config::VpcCounters> for VpcCounters { - type Error = String; - - fn try_from(p: &gateway_config::VpcCounters) -> Result { - Ok(VpcCounters { - name: p.name.clone(), - packets: p.packets, - drops: p.drops, - bytes: p.bytes, - }) - } -} - -impl TryFrom<&VpcCounters> for gateway_config::VpcCounters { - type Error = String; - - fn try_from(c: &VpcCounters) -> Result { - Ok(gateway_config::VpcCounters { - name: c.name.clone(), - packets: c.packets, - drops: c.drops, - bytes: c.bytes, - }) - } -} - -impl TryFrom<&gateway_config::GetDataplaneStatusResponse> for DataplaneStatus { - type Error = String; - - fn try_from(p: &gateway_config::GetDataplaneStatusResponse) -> Result { - // interface_statuses - let mut interface_statuses = Vec::with_capacity(p.interface_statuses.len()); - for s in &p.interface_statuses { - interface_statuses.push(InterfaceStatus::try_from(s)?); - } - - // interface_runtime - let mut interface_runtime: HashMap = - HashMap::with_capacity(p.interface_runtime.len()); - for (k, v) in &p.interface_runtime { - interface_runtime.insert(k.clone(), InterfaceRuntimeStatus::try_from(v)?); - } - - // vpcs - let mut vpcs: HashMap = HashMap::with_capacity(p.vpcs.len()); - for (k, v) in &p.vpcs { - vpcs.insert(k.clone(), VpcStatus::try_from(v)?); - } - - // vpc peering counters - let mut vpc_peering_counters: HashMap = - HashMap::with_capacity(p.vpc_peering_counters.len()); - for (k, v) in &p.vpc_peering_counters { - vpc_peering_counters.insert(k.clone(), VpcPeeringCounters::try_from(v)?); - } - - // vpc counters - let mut vpc_counters: HashMap = - HashMap::with_capacity(p.vpc_counters.len()); - for (k, v) in &p.vpc_counters { - vpc_counters.insert(k.clone(), VpcCounters::try_from(v)?); - } - - Ok(DataplaneStatus { - interface_statuses, - frr_status: p.frr_status.as_ref().map(FrrStatus::try_from).transpose()?, - dataplane_status: p - .dataplane_status - .as_ref() - .map(DataplaneStatusInfo::try_from) - .transpose()?, - interface_runtime, - bgp: p.bgp.as_ref().map(BgpStatus::try_from).transpose()?, - vpcs, - vpc_peering_counters, - vpc_counters, - }) - } -} - -impl TryFrom<&DataplaneStatus> for gateway_config::GetDataplaneStatusResponse { - type Error = String; - - fn try_from(s: &DataplaneStatus) -> Result { - // interface_statuses - let mut interface_statuses = Vec::with_capacity(s.interface_statuses.len()); - for st in &s.interface_statuses { - interface_statuses.push(gateway_config::InterfaceStatus::try_from(st)?); - } - - // interface_runtime - let mut interface_runtime: HashMap = - HashMap::with_capacity(s.interface_runtime.len()); - for (k, v) in &s.interface_runtime { - interface_runtime.insert( - k.clone(), - gateway_config::InterfaceRuntimeStatus::try_from(v)?, - ); - } - - // vpcs - let mut vpcs: HashMap = - HashMap::with_capacity(s.vpcs.len()); - for (k, v) in &s.vpcs { - vpcs.insert(k.clone(), gateway_config::VpcStatus::try_from(v)?); - } - - // vpc peering counters - let mut vpc_peering_counters: HashMap = - HashMap::with_capacity(s.vpc_peering_counters.len()); - for (k, v) in &s.vpc_peering_counters { - vpc_peering_counters - .insert(k.clone(), gateway_config::VpcPeeringCounters::try_from(v)?); - } - - // vpc counters - let mut vpc_counters: HashMap = - HashMap::with_capacity(s.vpc_counters.len()); - for (k, v) in &s.vpc_counters { - vpc_counters.insert(k.clone(), gateway_config::VpcCounters::try_from(v)?); - } - - Ok(gateway_config::GetDataplaneStatusResponse { - interface_statuses, - frr_status: s - .frr_status - .as_ref() - .map(gateway_config::FrrStatus::try_from) - .transpose()?, - dataplane_status: s - .dataplane_status - .as_ref() - .map(gateway_config::DataplaneStatusInfo::try_from) - .transpose()?, - interface_runtime, - bgp: s - .bgp - .as_ref() - .map(gateway_config::BgpStatus::try_from) - .transpose()?, - vpcs, - vpc_peering_counters, - vpc_counters, - }) - } -} diff --git a/config/src/converters/grpc/tracecfg.rs b/config/src/converters/grpc/tracecfg.rs deleted file mode 100644 index 55822312e..000000000 --- a/config/src/converters/grpc/tracecfg.rs +++ /dev/null @@ -1,57 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Open Network Fabric Authors - -use crate::internal::device::tracecfg::TracingConfig; -use ::gateway_config::config::TracingConfig as ApiTracingConfig; -use std::collections::HashMap; -use tracectl::LevelFilter; - -fn loglevel_to_levelfilter(value: i32) -> Result { - match gateway_config::LogLevel::try_from(value) { - Ok(::gateway_config::LogLevel::Off) => Ok(LevelFilter::OFF), - Ok(::gateway_config::LogLevel::Error) => Ok(LevelFilter::ERROR), - Ok(::gateway_config::LogLevel::Warning) => Ok(LevelFilter::WARN), - Ok(::gateway_config::LogLevel::Info) => Ok(LevelFilter::INFO), - Ok(::gateway_config::LogLevel::Debug) => Ok(LevelFilter::DEBUG), - Ok(::gateway_config::LogLevel::Trace) => Ok(LevelFilter::TRACE), - Err(_) => Err(format!("Invalid log level value: {value:?}")), - } -} -fn levelfilter_to_loglevel(value: LevelFilter) -> gateway_config::LogLevel { - match value { - LevelFilter::OFF => ::gateway_config::LogLevel::Off, - LevelFilter::ERROR => ::gateway_config::LogLevel::Error, - LevelFilter::WARN => ::gateway_config::LogLevel::Warning, - LevelFilter::INFO => ::gateway_config::LogLevel::Info, - LevelFilter::DEBUG => ::gateway_config::LogLevel::Debug, - LevelFilter::TRACE => ::gateway_config::LogLevel::Trace, - } -} - -// API to internal -impl TryFrom<&ApiTracingConfig> for TracingConfig { - type Error = String; - fn try_from(cfg: &ApiTracingConfig) -> Result { - let default_loglevel = loglevel_to_levelfilter(cfg.default)?; - let mut config = TracingConfig::new(default_loglevel); - for (tag, level) in &cfg.taglevel { - let level = loglevel_to_levelfilter(*level)?; - config.add_tag(tag, level); - } - Ok(config) - } -} - -// Internal to API -impl From<&TracingConfig> for ApiTracingConfig { - fn from(value: &TracingConfig) -> Self { - ApiTracingConfig { - default: levelfilter_to_loglevel(value.default).into(), - taglevel: value - .tags - .iter() - .map(|(tag, level)| (tag.clone(), levelfilter_to_loglevel(*level).into())) - .collect::>(), - } - } -} diff --git a/config/src/converters/grpc/underlay.rs b/config/src/converters/grpc/underlay.rs deleted file mode 100644 index d83099220..000000000 --- a/config/src/converters/grpc/underlay.rs +++ /dev/null @@ -1,48 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Open Network Fabric Authors - -use gateway_config::config as gateway_config; -use std::string::ToString; - -use crate::external::underlay::Underlay; -use crate::internal::routing::vrf::VrfConfig; - -impl TryFrom<&gateway_config::Underlay> for Underlay { - type Error = String; - - fn try_from(underlay: &gateway_config::Underlay) -> Result { - // Find the default VRF or first VRF if default not found - if underlay.vrfs.is_empty() { - return Err("Underlay must contain at least one VRF".to_string()); - } - - // Look for the default VRF or use the first one - let default_vrf = underlay - .vrfs - .iter() - .find(|vrf| vrf.name == "default") - .unwrap_or(&underlay.vrfs[0]); // FIXME(manish): This should be an error, preserving the original behavior for now - - // Convert VRF to VrfConfig - let vrf_config = VrfConfig::try_from(default_vrf)?; - - // Create Underlay with the VRF config - Ok(Underlay { - vrf: vrf_config, - vtep: None, - }) - } -} - -impl TryFrom<&Underlay> for gateway_config::Underlay { - type Error = String; - - fn try_from(underlay: &Underlay) -> Result { - // Convert the VRF - let vrf_grpc = gateway_config::Vrf::try_from(&underlay.vrf)?; - - Ok(gateway_config::Underlay { - vrfs: vec![vrf_grpc], - }) - } -} diff --git a/config/src/converters/grpc/vpc.rs b/config/src/converters/grpc/vpc.rs deleted file mode 100644 index 8513039da..000000000 --- a/config/src/converters/grpc/vpc.rs +++ /dev/null @@ -1,50 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Open Network Fabric Authors - -use gateway_config::config as gateway_config; -use std::convert::TryFrom; - -use crate::external::overlay::vpc::Vpc; -use crate::internal::interfaces::interface::InterfaceConfig; - -impl TryFrom<&gateway_config::Vpc> for Vpc { - type Error = String; - - fn try_from(vpc_grpc: &gateway_config::Vpc) -> Result { - // Create a new VPC with name and VNI - let mut vpc = Vpc::new(&vpc_grpc.name, &vpc_grpc.id, vpc_grpc.vni) - .map_err(|e| format!("Failed to create VPC: {e}"))?; - - // Convert and add interfaces if any - // SMATOV: TODO: We will add this handling later. TBD - if !vpc_grpc.interfaces.is_empty() { - // For each interface from gRPC - for iface in &vpc_grpc.interfaces { - let interface = InterfaceConfig::try_from(iface)?; - vpc.add_interface_config(interface); - } - } - - Ok(vpc) - } -} - -impl TryFrom<&Vpc> for gateway_config::Vpc { - type Error = String; - - fn try_from(vpc: &Vpc) -> Result { - // Convert VPC interfaces - let interfaces = vpc - .interfaces - .values() - .map(gateway_config::Interface::try_from) - .collect::, _>>()?; - - Ok(gateway_config::Vpc { - name: vpc.name.clone(), - id: vpc.id.to_string(), - vni: vpc.vni.as_u32(), - interfaces, - }) - } -} diff --git a/config/src/converters/grpc/vrf.rs b/config/src/converters/grpc/vrf.rs deleted file mode 100644 index 4e9c79e13..000000000 --- a/config/src/converters/grpc/vrf.rs +++ /dev/null @@ -1,100 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Open Network Fabric Authors - -use gateway_config::config as gateway_config; -use std::convert::TryFrom; -use std::net::Ipv4Addr; - -use crate::internal::interfaces::interface::InterfaceConfig; -use crate::internal::routing::bgp::BgpConfig; -use crate::internal::routing::ospf::Ospf; -use crate::internal::routing::vrf::VrfConfig; - -// OSPF conversions -impl TryFrom<&gateway_config::OspfConfig> for Ospf { - type Error = String; - - fn try_from(ospf_config: &gateway_config::OspfConfig) -> Result { - // Parse router_id from string to Ipv4Addr - let router_id = ospf_config - .router_id - .parse::() - .map_err(|_| format!("Invalid OSPF router ID format: {}", ospf_config.router_id))?; - - // Create a new Ospf instance - let mut ospf = Ospf::new(router_id); - - // Set VRF name if present - #[allow(clippy::collapsible_if)] - if let Some(vrf_name) = &ospf_config.vrf { - if !vrf_name.is_empty() { - ospf.set_vrf_name(vrf_name.clone()); - } - } - - Ok(ospf) - } -} - -impl From<&Ospf> for gateway_config::OspfConfig { - fn from(ospf: &Ospf) -> Self { - gateway_config::OspfConfig { - router_id: ospf.router_id.to_string(), - vrf: ospf.vrf.clone(), - } - } -} - -impl TryFrom<&gateway_config::Vrf> for VrfConfig { - type Error = String; - - fn try_from(vrf: &gateway_config::Vrf) -> Result { - // Create VRF config - let mut vrf_config = VrfConfig::new(&vrf.name, None, true /* default vrf */); - - // Convert BGP config if present and add it to VRF - if let Some(router) = &vrf.router { - let bgp = BgpConfig::try_from(router)?; - vrf_config.set_bgp(bgp); - } - - // convert each interface - for iface in &vrf.interfaces { - let iface_config = InterfaceConfig::try_from(iface)?; - vrf_config.add_interface_config(iface_config); - } - - // Convert ospf config if present - if let Some(ospf_config) = &vrf.ospf { - let ospf = Ospf::try_from(ospf_config)?; - vrf_config.set_ospf(ospf); - } - - Ok(vrf_config) - } -} - -impl TryFrom<&VrfConfig> for gateway_config::Vrf { - type Error = String; - - fn try_from(vrf: &VrfConfig) -> Result { - // Convert interfaces - let interfaces = Vec::::try_from(&vrf.interfaces)?; - - // Convert router config if BGP is configured - let router = match &vrf.bgp { - Some(bgp) => Some(gateway_config::RouterConfig::try_from(bgp)?), - None => None, - }; - - // Convert OSPF config if present - let ospf = vrf.ospf.as_ref().map(gateway_config::OspfConfig::from); - - Ok(gateway_config::Vrf { - name: vrf.name.clone(), - interfaces, - router, - ospf, - }) - } -} diff --git a/config/src/converters/mod.rs b/config/src/converters/mod.rs index 0b7db5bf2..ddad87934 100644 --- a/config/src/converters/mod.rs +++ b/config/src/converters/mod.rs @@ -3,6 +3,5 @@ //! Converters -pub mod grpc; pub mod k8s; pub mod strings; From 5854951c23f9f332b0a533fa5f4dc037bedb581a Mon Sep 17 00:00:00 2001 From: Fredi Raspall Date: Tue, 30 Dec 2025 17:55:22 +0100 Subject: [PATCH 5/5] feat(remove-grpc): remove gateway-proto dependency Signed-off-by: Fredi Raspall --- Cargo.lock | 98 +---------------------------------------------- Cargo.toml | 1 - config/Cargo.toml | 2 - mgmt/Cargo.toml | 2 - 4 files changed, 2 insertions(+), 101 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a96fc1914..b810e9268 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1261,7 +1261,6 @@ dependencies = [ "dataplane-pipeline", "dataplane-tracectl", "derive_builder 0.20.2", - "gateway_config", "ipnet", "linkme", "multi_index_map", @@ -1512,7 +1511,6 @@ dependencies = [ "derive_builder 0.20.2", "fixin", "futures", - "gateway_config", "ipnet", "linkme", "multi_index_map", @@ -2311,23 +2309,6 @@ dependencies = [ "thread_local", ] -[[package]] -name = "gateway_config" -version = "0.20.0" -source = "git+https://github.com/githedgehog/gateway-proto?tag=v0.20.0#387d60479182a3c90ad8f06c6af08995092d20e4" -dependencies = [ - "async-trait", - "bolero", - "futures", - "prost 0.14.1", - "serde", - "serde_json", - "thiserror 2.0.17", - "tokio", - "tonic", - "tonic-prost", -] - [[package]] name = "generator" version = "0.7.5" @@ -2935,15 +2916,6 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" -dependencies = [ - "either", -] - [[package]] name = "itoa" version = "1.0.15" @@ -4158,17 +4130,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" dependencies = [ "bytes", - "prost-derive 0.11.9", -] - -[[package]] -name = "prost" -version = "0.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7231bd9b3d3d33c86b58adbac74b5ec0ad9f496b19d22801d773636feaa95f3d" -dependencies = [ - "bytes", - "prost-derive 0.14.1", + "prost-derive", ] [[package]] @@ -4184,19 +4146,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "prost-derive" -version = "0.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9120690fafc389a67ba3803df527d0ec9cbbc9cc45e4cc20b332996dfb672425" -dependencies = [ - "anyhow", - "itertools 0.14.0", - "proc-macro2", - "quote", - "syn 2.0.111", -] - [[package]] name = "ptr_meta" version = "0.3.1" @@ -4227,7 +4176,7 @@ dependencies = [ "libflate", "log", "names", - "prost 0.11.9", + "prost", "reqwest", "serde_json", "thiserror 1.0.69", @@ -5492,7 +5441,6 @@ dependencies = [ "bytes", "libc 0.2.178", "mio", - "parking_lot", "pin-project-lite", "signal-hook-registry", "socket2", @@ -5626,46 +5574,6 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" -[[package]] -name = "tonic" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb7613188ce9f7df5bfe185db26c5814347d110db17920415cf2fbcad85e7203" -dependencies = [ - "async-trait", - "axum", - "base64 0.22.1", - "bytes", - "h2", - "http 1.4.0", - "http-body", - "http-body-util", - "hyper", - "hyper-timeout", - "hyper-util", - "percent-encoding", - "pin-project", - "socket2", - "sync_wrapper", - "tokio", - "tokio-stream", - "tower", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "tonic-prost" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66bd50ad6ce1252d87ef024b3d64fe4c3cf54a86fb9ef4c631fdd0ded7aeaa67" -dependencies = [ - "bytes", - "prost 0.14.1", - "tonic", -] - [[package]] name = "tower" version = "0.5.2" @@ -5674,9 +5582,7 @@ checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" dependencies = [ "futures-core", "futures-util", - "indexmap 2.12.1", "pin-project-lite", - "slab", "sync_wrapper", "tokio", "tokio-util", diff --git a/Cargo.toml b/Cargo.toml index 16ec0a9bd..ffffa5fdf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -59,7 +59,6 @@ dpdk-sysroot-helper = { path = "./dpdk-sysroot-helper", package = "dataplane-dpd dplane-rpc = { git = "https://github.com/githedgehog/dplane-rpc.git", rev = "e8fc33db10e1d00785f2a2b90cbadcad7900f200", features = [] } errno = { path = "./errno", package = "dataplane-errno", features = [] } flow-info = { path = "./flow-info", package = "dataplane-flow-info", features = [] } -gateway_config = { git = "https://github.com/githedgehog/gateway-proto", tag = "v0.20.0", features = [] } gwname = { path = "./gwname", package = "dataplane-gwname", features = [] } hardware = { path = "./hardware", package = "dataplane-hardware", features = [] } id = { path = "./id", package = "dataplane-id", features = [] } diff --git a/config/Cargo.toml b/config/Cargo.toml index 9a3884c08..48bf4bd39 100644 --- a/config/Cargo.toml +++ b/config/Cargo.toml @@ -7,7 +7,6 @@ version.workspace = true [dependencies] # internal -gateway_config = { workspace = true } gwname = { workspace = true } hardware = { workspace = true } net = { workspace = true } @@ -37,7 +36,6 @@ k8s-intf = { workspace = true, features = ["bolero"] } # external bolero = { workspace = true, default-features = false, features = ["alloc"] } caps = { workspace = true } -gateway_config = { workspace = true, features = ["bolero"] } ipnet = { workspace = true } pretty_assertions = { workspace = true, features = ["std"] } tracing-test = { workspace = true, features = [] } diff --git a/mgmt/Cargo.toml b/mgmt/Cargo.toml index 32cb035e2..d846d7324 100644 --- a/mgmt/Cargo.toml +++ b/mgmt/Cargo.toml @@ -20,7 +20,6 @@ bolero = ["dep:bolero", "interface-manager/bolero", "id/bolero", "net/bolero", " args = { workspace = true } config = { workspace = true } concurrency = { workspace = true } -gateway_config = { workspace = true } id = { workspace = true } interface-manager = { workspace = true } k8s-intf = { workspace = true } @@ -70,7 +69,6 @@ test-utils = { workspace = true } # external bolero = { workspace = true, default-features = false, features = ["alloc"] } caps = { workspace = true } -gateway_config = { workspace = true, features = ["bolero"] } ipnet = { workspace = true } pretty_assertions = { workspace = true, features = ["std"] } tracing-test = { workspace = true, features = [] }