blob: 9597fb9415cef9c1471a93f65e16952cc3adc0eb [file] [log] [blame]
// SPDX-License-Identifier: MIT
use crate::{
packet_route::link::{InfoData, InfoKind, InfoVlan, VlanQosMapping},
LinkMessageBuilder,
};
/// A quality-of-service mapping between the internal priority `from` to the
/// external vlan priority `to`.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct QosMapping {
pub from: u32,
pub to: u32,
}
impl From<QosMapping> for VlanQosMapping {
fn from(QosMapping { from, to }: QosMapping) -> Self {
Self::Mapping(from, to)
}
}
/// Represent VLAN interface.
/// Example code on creating a VLAN interface
/// ```no_run
/// use rtnetlink::{new_connection, LinkVlan};
/// #[tokio::main]
/// async fn main() -> Result<(), String> {
/// let (connection, handle, _) = new_connection().unwrap();
/// tokio::spawn(connection);
///
/// handle
/// .link()
/// .add(
/// LinkVlan::new("vlan100", 10, 100)
/// .up()
/// .build()
/// )
/// .execute()
/// .await
/// .map_err(|e| format!("{e}"))
/// }
/// ```
///
/// Please check LinkMessageBuilder::<LinkVlan> for more detail.
#[derive(Debug)]
pub struct LinkVlan;
impl LinkVlan {
/// Wrapper of `LinkMessageBuilder::<LinkVlan>::new().id().dev()`
pub fn new(
name: &str,
base_iface_index: u32,
vlan_id: u16,
) -> LinkMessageBuilder<Self> {
LinkMessageBuilder::<LinkVlan>::new(name)
.id(vlan_id)
.link(base_iface_index)
}
}
impl LinkMessageBuilder<LinkVlan> {
/// Create [LinkMessageBuilder] for VLAN
pub fn new(name: &str) -> Self {
LinkMessageBuilder::<LinkVlan>::new_with_info_kind(InfoKind::Vlan)
.name(name.to_string())
}
pub fn append_info_data(mut self, info: InfoVlan) -> Self {
if let InfoData::Vlan(infos) = self
.info_data
.get_or_insert_with(|| InfoData::Vlan(Vec::new()))
{
infos.push(info);
}
self
}
/// VLAN ID
pub fn id(self, vlan_id: u16) -> Self {
self.append_info_data(InfoVlan::Id(vlan_id))
}
/// ingress QoS and egress QoS
pub fn qos<I, E>(self, ingress_qos: I, egress_qos: E) -> Self
where
I: IntoIterator<Item = QosMapping>,
E: IntoIterator<Item = QosMapping>,
{
let mut ret = self;
let ingress: Vec<_> =
ingress_qos.into_iter().map(VlanQosMapping::from).collect();
if !ingress.is_empty() {
ret = ret.append_info_data(InfoVlan::IngressQos(ingress));
}
let egress: Vec<_> =
egress_qos.into_iter().map(VlanQosMapping::from).collect();
if !egress.is_empty() {
ret = ret.append_info_data(InfoVlan::EgressQos(egress));
}
ret
}
}