src/config/network.rs: introduce NetworkInterfaceType

This commit is contained in:
Dietmar Maurer 2020-04-23 08:45:03 +02:00
parent d5ca9bd5df
commit 02269f3dba
4 changed files with 58 additions and 11 deletions

View File

@ -521,6 +521,29 @@ pub enum NetworkConfigMethod {
Loopback, 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.") pub const NETWORK_INTERFACE_NAME_SCHEMA: Schema = StringSchema::new("Network interface name.")
.format(&NETWORK_INTERFACE_FORMAT) .format(&NETWORK_INTERFACE_FORMAT)
.min_length(1) .min_length(1)
@ -532,6 +555,9 @@ pub const NETWORK_INTERFACE_NAME_SCHEMA: Schema = StringSchema::new("Network int
name: { name: {
schema: NETWORK_INTERFACE_NAME_SCHEMA, schema: NETWORK_INTERFACE_NAME_SCHEMA,
}, },
interface_type: {
type: NetworkInterfaceType,
},
method_v4: { method_v4: {
type: NetworkConfigMethod, type: NetworkConfigMethod,
optional: true, optional: true,
@ -563,12 +589,12 @@ pub const NETWORK_INTERFACE_NAME_SCHEMA: Schema = StringSchema::new("Network int
pub struct Interface { pub struct Interface {
/// Autostart interface /// Autostart interface
pub auto: bool, pub auto: bool,
/// Interface is a physical network device
pub exists: bool,
/// Interface is active (UP) /// Interface is active (UP)
pub active: bool, pub active: bool,
/// Interface name /// Interface name
pub name: String, pub name: String,
/// Interface type
pub interface_type: NetworkInterfaceType,
#[serde(skip_serializing_if="Option::is_none")] #[serde(skip_serializing_if="Option::is_none")]
pub method_v4: Option<NetworkConfigMethod>, pub method_v4: Option<NetworkConfigMethod>,
#[serde(skip_serializing_if="Option::is_none")] #[serde(skip_serializing_if="Option::is_none")]

View File

@ -283,6 +283,7 @@ fn list_network_devices(param: Value, rpcenv: &mut dyn RpcEnvironment) -> Result
} }
let options = default_table_format_options() let options = default_table_format_options()
.column(ColumnConfig::new("interface_type").header("type"))
.column(ColumnConfig::new("name")) .column(ColumnConfig::new("name"))
.column(ColumnConfig::new("auto")) .column(ColumnConfig::new("auto"))
.column(ColumnConfig::new("method_v4")) .column(ColumnConfig::new("method_v4"))

View File

@ -14,15 +14,15 @@ pub use lexer::*;
mod parser; mod parser;
pub use parser::*; pub use parser::*;
use crate::api2::types::{Interface, NetworkConfigMethod}; use crate::api2::types::{Interface, NetworkConfigMethod, NetworkInterfaceType};
impl Interface { impl Interface {
pub fn new(name: String) -> Self { pub fn new(name: String) -> Self {
Self { Self {
name, name,
interface_type: NetworkInterfaceType::Unknown,
auto: false, auto: false,
exists: false,
active: false, active: false,
method_v4: None, method_v4: None,
method_v6: None, method_v6: None,
@ -153,8 +153,8 @@ impl Interface {
options_v6, options_v6,
// the rest does not matter // the rest does not matter
name: _name, name: _name,
interface_type: _interface_type,
auto: _auto, auto: _auto,
exists: _exists,
active: _active, active: _active,
cidr_v4: _cidr_v4, cidr_v4: _cidr_v4,
cidr_v6: _cidr_v6, cidr_v6: _cidr_v6,

View File

@ -9,7 +9,7 @@ use regex::Regex;
use super::helper::*; use super::helper::*;
use super::lexer::*; use super::lexer::*;
use super::{NetworkConfig, NetworkOrderEntry, Interface, NetworkConfigMethod}; use super::{NetworkConfig, NetworkOrderEntry, Interface, NetworkConfigMethod, NetworkInterfaceType};
pub struct NetworkParser<R: BufRead> { pub struct NetworkParser<R: BufRead> {
input: Peekable<Lexer<R>>, input: Peekable<Lexer<R>>,
@ -288,24 +288,44 @@ impl <R: BufRead> NetworkParser<R> {
let existing_interfaces = get_network_interfaces()?; let existing_interfaces = get_network_interfaces()?;
lazy_static!{ 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() { for (iface, active) in existing_interfaces.iter() {
let exists = PHYSICAL_NIC_REGEX.is_match(iface);
if let Some(interface) = config.interfaces.get_mut(iface) { if let Some(interface) = config.interfaces.get_mut(iface) {
interface.exists = exists;
interface.active = *active; 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()); let mut interface = Interface::new(iface.clone());
interface.set_method_v4(NetworkConfigMethod::Manual)?; interface.set_method_v4(NetworkConfigMethod::Manual)?;
interface.exists = true; interface.interface_type = NetworkInterfaceType::Ethernet;
interface.active = *active; interface.active = *active;
config.interfaces.insert(interface.name.clone(), interface); config.interfaces.insert(interface.name.clone(), interface);
config.order.push(NetworkOrderEntry::Iface(iface.to_string())); 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) Ok(config)
} }
} }