netlink_packet_route/link/sriov/
vf_vlan.rs

1// SPDX-License-Identifier: MIT
2
3use anyhow::Context;
4use netlink_packet_utils::nla::{DefaultNla, Nla, NlaBuffer};
5use netlink_packet_utils::{DecodeError, Emitable, Parseable};
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    type Error = DecodeError;
43    fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
44        let payload = buf.value();
45        Ok(match buf.kind() {
46            IFLA_VF_VLAN_INFO => Self::Info(
47                VfVlanInfo::parse(&VfVlanInfoBuffer::new(payload))
48                    .context(format!("invalid IFLA_VF_VLAN_INFO {payload:?}"))?,
49            ),
50            kind => Self::Other(
51                DefaultNla::parse(buf)
52                    .context(format!("failed to parse {kind} as DefaultNla: {payload:?}"))?,
53            ),
54        })
55    }
56}
57
58const VF_VLAN_INFO_LEN: usize = 16; // with 2 bytes padding
59
60#[derive(Debug, Clone, Copy, Eq, PartialEq, Default)]
61#[non_exhaustive]
62pub struct VfVlanInfo {
63    pub vf_id: u32,
64    pub vlan_id: u32,
65    pub qos: u32,
66    pub protocol: VlanProtocol,
67}
68
69impl VfVlanInfo {
70    pub fn new(vf_id: u32, vlan_id: u32, qos: u32, protocol: VlanProtocol) -> Self {
71        Self { vf_id, vlan_id, qos, protocol }
72    }
73}
74
75buffer!(VfVlanInfoBuffer(VF_VLAN_INFO_LEN) {
76    vf_id: (u32, 0..4),
77    vlan_id: (u32, 4..8),
78    qos: (u32, 8..12),
79    protocol: (u16, 12..14),
80});
81
82impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<VfVlanInfoBuffer<&'a T>> for VfVlanInfo {
83    type Error = DecodeError;
84    fn parse(buf: &VfVlanInfoBuffer<&T>) -> Result<Self, DecodeError> {
85        Ok(Self {
86            vf_id: buf.vf_id(),
87            vlan_id: buf.vlan_id(),
88            qos: buf.qos(),
89            protocol: u16::from_be(buf.protocol()).into(),
90        })
91    }
92}
93
94impl Emitable for VfVlanInfo {
95    fn buffer_len(&self) -> usize {
96        VF_VLAN_INFO_LEN
97    }
98
99    fn emit(&self, buffer: &mut [u8]) {
100        let mut buffer = VfVlanInfoBuffer::new(buffer);
101        buffer.set_vf_id(self.vf_id);
102        buffer.set_vlan_id(self.vlan_id);
103        buffer.set_qos(self.qos);
104        buffer.set_protocol(u16::from(self.protocol).to_be());
105    }
106}