rtnetlink/link/
vlan.rs

1// SPDX-License-Identifier: MIT
2
3use crate::{
4    packet_route::link::{
5        InfoData, InfoKind, InfoVlan, VlanFlags, VlanProtocol, VlanQosMapping,
6    },
7    LinkMessageBuilder,
8};
9
10/// A quality-of-service mapping between the internal priority `from` to the
11/// external vlan priority `to`.
12#[derive(Clone, Copy, Debug, PartialEq, Eq)]
13pub struct QosMapping {
14    pub from: u32,
15    pub to: u32,
16}
17
18impl From<QosMapping> for VlanQosMapping {
19    fn from(QosMapping { from, to }: QosMapping) -> Self {
20        Self::Mapping(from, to)
21    }
22}
23
24/// Represent VLAN interface.
25/// Example code on creating a VLAN interface
26/// ```no_run
27/// use rtnetlink::{new_connection, LinkVlan};
28/// #[tokio::main]
29/// async fn main() -> Result<(), String> {
30///     let (connection, handle, _) = new_connection().unwrap();
31///     tokio::spawn(connection);
32///
33///     handle
34///         .link()
35///         .add(
36///             LinkVlan::new("vlan100", 10, 100)
37///                 .up()
38///                 .build()
39///         )
40///         .execute()
41///         .await
42///         .map_err(|e| format!("{e}"))
43/// }
44/// ```
45///
46/// Please check LinkMessageBuilder::<LinkVlan> for more detail.
47#[derive(Debug)]
48pub struct LinkVlan;
49
50impl LinkVlan {
51    /// Wrapper of `LinkMessageBuilder::<LinkVlan>::new().id().dev()`
52    pub fn new(
53        name: &str,
54        base_iface_index: u32,
55        vlan_id: u16,
56    ) -> LinkMessageBuilder<Self> {
57        LinkMessageBuilder::<LinkVlan>::new(name)
58            .id(vlan_id)
59            .link(base_iface_index)
60    }
61}
62
63impl LinkMessageBuilder<LinkVlan> {
64    /// Create [LinkMessageBuilder] for VLAN
65    pub fn new(name: &str) -> Self {
66        LinkMessageBuilder::<LinkVlan>::new_with_info_kind(InfoKind::Vlan)
67            .name(name.to_string())
68    }
69
70    pub fn append_info_data(mut self, info: InfoVlan) -> Self {
71        if let InfoData::Vlan(infos) = self
72            .info_data
73            .get_or_insert_with(|| InfoData::Vlan(Vec::new()))
74        {
75            infos.push(info);
76        }
77        self
78    }
79
80    /// VLAN ID
81    pub fn id(self, vlan_id: u16) -> Self {
82        self.append_info_data(InfoVlan::Id(vlan_id))
83    }
84
85    /// VLAN protocol
86    pub fn protocol(self, protocol: VlanProtocol) -> Self {
87        self.append_info_data(InfoVlan::Protocol(protocol))
88    }
89
90    /// VLAN flags
91    pub fn flags(self, flags: VlanFlags, mask: VlanFlags) -> Self {
92        self.append_info_data(InfoVlan::Flags((flags, mask)))
93    }
94
95    /// ingress QoS and egress QoS
96    pub fn qos<I, E>(self, ingress_qos: I, egress_qos: E) -> Self
97    where
98        I: IntoIterator<Item = QosMapping>,
99        E: IntoIterator<Item = QosMapping>,
100    {
101        let mut ret = self;
102        let ingress: Vec<_> =
103            ingress_qos.into_iter().map(VlanQosMapping::from).collect();
104        if !ingress.is_empty() {
105            ret = ret.append_info_data(InfoVlan::IngressQos(ingress));
106        }
107
108        let egress: Vec<_> =
109            egress_qos.into_iter().map(VlanQosMapping::from).collect();
110
111        if !egress.is_empty() {
112            ret = ret.append_info_data(InfoVlan::EgressQos(egress));
113        }
114        ret
115    }
116}