netlink_packet_route/link/sriov/
vf_vlan.rs

1// SPDX-License-Identifier: MIT
2
3use netlink_packet_core::{
4    DecodeError, DefaultNla, Emitable, ErrorContext, Nla, NlaBuffer, Parseable,
5};
6
7use crate::link::VlanProtocol;
8
9const IFLA_VF_VLAN_INFO: u16 = 1;
10
11#[derive(Debug, Clone, Eq, PartialEq)]
12#[non_exhaustive]
13pub enum VfVlan {
14    Info(VfVlanInfo),
15    Other(DefaultNla),
16}
17
18impl Nla for VfVlan {
19    fn value_len(&self) -> usize {
20        match self {
21            Self::Info(v) => v.buffer_len(),
22            Self::Other(v) => v.value_len(),
23        }
24    }
25
26    fn emit_value(&self, buffer: &mut [u8]) {
27        match self {
28            Self::Info(v) => v.emit(buffer),
29            Self::Other(attr) => attr.emit_value(buffer),
30        }
31    }
32
33    fn kind(&self) -> u16 {
34        match self {
35            Self::Info(_) => IFLA_VF_VLAN_INFO,
36            Self::Other(v) => v.kind(),
37        }
38    }
39}
40
41impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for VfVlan {
42    fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
43        let payload = buf.value();
44        Ok(match buf.kind() {
45            IFLA_VF_VLAN_INFO => Self::Info(
46                VfVlanInfo::parse(&VfVlanInfoBuffer::new(payload)).context(
47                    format!("invalid IFLA_VF_VLAN_INFO {payload:?}"),
48                )?,
49            ),
50            kind => Self::Other(DefaultNla::parse(buf).context(format!(
51                "failed to parse {kind} as DefaultNla: {payload:?}"
52            ))?),
53        })
54    }
55}
56
57const VF_VLAN_INFO_LEN: usize = 16; // with 2 bytes padding
58
59#[derive(Debug, Clone, Copy, Eq, PartialEq, Default)]
60#[non_exhaustive]
61pub struct VfVlanInfo {
62    pub vf_id: u32,
63    pub vlan_id: u32,
64    pub qos: u32,
65    pub protocol: VlanProtocol,
66}
67
68impl VfVlanInfo {
69    pub fn new(
70        vf_id: u32,
71        vlan_id: u32,
72        qos: u32,
73        protocol: VlanProtocol,
74    ) -> Self {
75        Self {
76            vf_id,
77            vlan_id,
78            qos,
79            protocol,
80        }
81    }
82}
83
84buffer!(VfVlanInfoBuffer(VF_VLAN_INFO_LEN) {
85    vf_id: (u32, 0..4),
86    vlan_id: (u32, 4..8),
87    qos: (u32, 8..12),
88    protocol: (u16, 12..14),
89});
90
91impl<T: AsRef<[u8]> + ?Sized> Parseable<VfVlanInfoBuffer<&T>> for VfVlanInfo {
92    fn parse(buf: &VfVlanInfoBuffer<&T>) -> Result<Self, DecodeError> {
93        Ok(Self {
94            vf_id: buf.vf_id(),
95            vlan_id: buf.vlan_id(),
96            qos: buf.qos(),
97            protocol: u16::from_be(buf.protocol()).into(),
98        })
99    }
100}
101
102impl Emitable for VfVlanInfo {
103    fn buffer_len(&self) -> usize {
104        VF_VLAN_INFO_LEN
105    }
106
107    fn emit(&self, buffer: &mut [u8]) {
108        let mut buffer = VfVlanInfoBuffer::new(buffer);
109        buffer.set_vf_id(self.vf_id);
110        buffer.set_vlan_id(self.vlan_id);
111        buffer.set_qos(self.qos);
112        buffer.set_protocol(u16::from(self.protocol).to_be());
113    }
114}