From 02269f3dba326ce52a515565fae51e1d75f439a9 Mon Sep 17 00:00:00 2001 From: Dietmar Maurer Date: Thu, 23 Apr 2020 08:45:03 +0200 Subject: [PATCH] src/config/network.rs: introduce NetworkInterfaceType --- src/api2/types.rs | 30 +++++++++++++++++++++++++++-- src/bin/proxmox-backup-manager.rs | 1 + src/config/network.rs | 6 +++--- src/config/network/parser.rs | 32 +++++++++++++++++++++++++------ 4 files changed, 58 insertions(+), 11 deletions(-) diff --git a/src/api2/types.rs b/src/api2/types.rs index fb8c01c7..c53ef967 100644 --- a/src/api2/types.rs +++ b/src/api2/types.rs @@ -521,6 +521,29 @@ pub enum NetworkConfigMethod { Loopback, } +#[api()] +#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "lowercase")] +/// Network interface type +pub enum NetworkInterfaceType { + /// Loopback + Loopback, + /// Physical Ethernet device + Ethernet, + /// Name looks like a physical ethernet device, but device is not found + Vanished, + /// Linux Bridge + Bridge, + /// Linux Bond + Bond, + /// Linux VLAN (eth.10) + Vlan, + /// Interface Alias (eth:1) + Alias, + /// Unknown interface type + Unknown, +} + pub const NETWORK_INTERFACE_NAME_SCHEMA: Schema = StringSchema::new("Network interface name.") .format(&NETWORK_INTERFACE_FORMAT) .min_length(1) @@ -532,6 +555,9 @@ pub const NETWORK_INTERFACE_NAME_SCHEMA: Schema = StringSchema::new("Network int name: { schema: NETWORK_INTERFACE_NAME_SCHEMA, }, + interface_type: { + type: NetworkInterfaceType, + }, method_v4: { type: NetworkConfigMethod, optional: true, @@ -563,12 +589,12 @@ pub const NETWORK_INTERFACE_NAME_SCHEMA: Schema = StringSchema::new("Network int pub struct Interface { /// Autostart interface pub auto: bool, - /// Interface is a physical network device - pub exists: bool, /// Interface is active (UP) pub active: bool, /// Interface name pub name: String, + /// Interface type + pub interface_type: NetworkInterfaceType, #[serde(skip_serializing_if="Option::is_none")] pub method_v4: Option, #[serde(skip_serializing_if="Option::is_none")] diff --git a/src/bin/proxmox-backup-manager.rs b/src/bin/proxmox-backup-manager.rs index 6209f6b6..ff29fe7b 100644 --- a/src/bin/proxmox-backup-manager.rs +++ b/src/bin/proxmox-backup-manager.rs @@ -283,6 +283,7 @@ fn list_network_devices(param: Value, rpcenv: &mut dyn RpcEnvironment) -> Result } let options = default_table_format_options() + .column(ColumnConfig::new("interface_type").header("type")) .column(ColumnConfig::new("name")) .column(ColumnConfig::new("auto")) .column(ColumnConfig::new("method_v4")) diff --git a/src/config/network.rs b/src/config/network.rs index 29b88dfb..3e7f349d 100644 --- a/src/config/network.rs +++ b/src/config/network.rs @@ -14,15 +14,15 @@ pub use lexer::*; mod parser; pub use parser::*; -use crate::api2::types::{Interface, NetworkConfigMethod}; +use crate::api2::types::{Interface, NetworkConfigMethod, NetworkInterfaceType}; impl Interface { pub fn new(name: String) -> Self { Self { name, + interface_type: NetworkInterfaceType::Unknown, auto: false, - exists: false, active: false, method_v4: None, method_v6: None, @@ -153,8 +153,8 @@ impl Interface { options_v6, // the rest does not matter name: _name, + interface_type: _interface_type, auto: _auto, - exists: _exists, active: _active, cidr_v4: _cidr_v4, cidr_v6: _cidr_v6, diff --git a/src/config/network/parser.rs b/src/config/network/parser.rs index 5389e143..cf6928c5 100644 --- a/src/config/network/parser.rs +++ b/src/config/network/parser.rs @@ -9,7 +9,7 @@ use regex::Regex; use super::helper::*; use super::lexer::*; -use super::{NetworkConfig, NetworkOrderEntry, Interface, NetworkConfigMethod}; +use super::{NetworkConfig, NetworkOrderEntry, Interface, NetworkConfigMethod, NetworkInterfaceType}; pub struct NetworkParser { input: Peekable>, @@ -288,24 +288,44 @@ impl NetworkParser { let existing_interfaces = get_network_interfaces()?; lazy_static!{ - static ref PHYSICAL_NIC_REGEX: Regex = Regex::new(r"(?:eth\d+|en[^:.]+|ib\d+)").unwrap(); + static ref PHYSICAL_NIC_REGEX: Regex = Regex::new(r"^(?:eth\d+|en[^:.]+|ib\d+)$").unwrap(); + static ref INTERFACE_ALIAS_REGEX: Regex = Regex::new(r"^\S+:\d+$").unwrap(); + static ref VLAN_INTERFACE_REGEX: Regex = Regex::new(r"^\S+\.\d+$").unwrap(); } for (iface, active) in existing_interfaces.iter() { - let exists = PHYSICAL_NIC_REGEX.is_match(iface); if let Some(interface) = config.interfaces.get_mut(iface) { - interface.exists = exists; interface.active = *active; - } else if exists { // also add all physical NICs + } else if PHYSICAL_NIC_REGEX.is_match(iface) { // also add all physical NICs let mut interface = Interface::new(iface.clone()); interface.set_method_v4(NetworkConfigMethod::Manual)?; - interface.exists = true; + interface.interface_type = NetworkInterfaceType::Ethernet; interface.active = *active; config.interfaces.insert(interface.name.clone(), interface); config.order.push(NetworkOrderEntry::Iface(iface.to_string())); } } + for (name, interface) in config.interfaces.iter_mut() { + if interface.interface_type != NetworkInterfaceType::Unknown { continue; } + if name == "lo" { + interface.interface_type = NetworkInterfaceType::Loopback; + continue; + } + if INTERFACE_ALIAS_REGEX.is_match(name) { + interface.interface_type = NetworkInterfaceType::Alias; + continue; + } + if VLAN_INTERFACE_REGEX.is_match(name) { + interface.interface_type = NetworkInterfaceType::Vlan; + continue; + } + if PHYSICAL_NIC_REGEX.is_match(name) { + interface.interface_type = NetworkInterfaceType::Ethernet; + continue; + } + } + Ok(config) } }