use serde::{Deserialize, Serialize};
use crate::{BaseInterface, ErrorKind, InterfaceType, NmstateError};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct MacVlanInterface {
#[serde(flatten)]
pub base: BaseInterface,
#[serde(skip_serializing_if = "Option::is_none", rename = "mac-vlan")]
pub mac_vlan: Option<MacVlanConfig>,
}
impl Default for MacVlanInterface {
fn default() -> Self {
Self {
base: BaseInterface {
iface_type: InterfaceType::MacVlan,
..Default::default()
},
mac_vlan: None,
}
}
}
impl MacVlanInterface {
pub fn new() -> Self {
Self::default()
}
pub(crate) fn sanitize(
&self,
is_desired: bool,
) -> Result<(), NmstateError> {
if is_desired
&& let Some(conf) = &self.mac_vlan
&& conf.accept_all_mac == Some(false)
&& conf.mode != MacVlanMode::Passthru
{
let e = NmstateError::new(
ErrorKind::InvalidArgument,
"Disable accept-all-mac-addresses(promiscuous) is only \
allowed on passthru mode"
.to_string(),
);
log::error!("{e}");
return Err(e);
}
Ok(())
}
pub(crate) fn parent(&self) -> Option<&str> {
self.mac_vlan.as_ref().map(|cfg| cfg.base_iface.as_str())
}
pub(crate) fn change_parent_name(&mut self, name: &str) {
if let Some(mac_vlan_conf) = self.mac_vlan.as_mut() {
mac_vlan_conf.base_iface = name.to_string();
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
#[serde(rename_all = "kebab-case", deny_unknown_fields)]
#[non_exhaustive]
pub struct MacVlanConfig {
pub base_iface: String,
pub mode: MacVlanMode,
#[serde(
skip_serializing_if = "Option::is_none",
rename = "promiscuous",
alias = "accept-all-mac",
default,
deserialize_with = "crate::deserializer::option_bool_or_string"
)]
pub accept_all_mac: Option<bool>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
#[non_exhaustive]
#[derive(Default)]
pub enum MacVlanMode {
Vepa,
Bridge,
Private,
Passthru,
Source,
#[default]
Unknown,
}
impl From<MacVlanMode> for u32 {
fn from(v: MacVlanMode) -> u32 {
match v {
MacVlanMode::Unknown => 0,
MacVlanMode::Vepa => 1,
MacVlanMode::Bridge => 2,
MacVlanMode::Private => 3,
MacVlanMode::Passthru => 4,
MacVlanMode::Source => 5,
}
}
}