netlink_packet_route/link/sriov/
vf_vlan.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
// SPDX-License-Identifier: MIT

use anyhow::Context;
use netlink_packet_utils::nla::{DefaultNla, Nla, NlaBuffer};
use netlink_packet_utils::{DecodeError, Emitable, Parseable};

use crate::link::VlanProtocol;

const IFLA_VF_VLAN_INFO: u16 = 1;

#[derive(Debug, Clone, Eq, PartialEq)]
#[non_exhaustive]
pub enum VfVlan {
    Info(VfVlanInfo),
    Other(DefaultNla),
}

impl Nla for VfVlan {
    fn value_len(&self) -> usize {
        match self {
            Self::Info(v) => v.buffer_len(),
            Self::Other(v) => v.value_len(),
        }
    }

    fn emit_value(&self, buffer: &mut [u8]) {
        match self {
            Self::Info(v) => v.emit(buffer),
            Self::Other(attr) => attr.emit_value(buffer),
        }
    }

    fn kind(&self) -> u16 {
        match self {
            Self::Info(_) => IFLA_VF_VLAN_INFO,
            Self::Other(v) => v.kind(),
        }
    }
}

impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for VfVlan {
    type Error = DecodeError;
    fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
        let payload = buf.value();
        Ok(match buf.kind() {
            IFLA_VF_VLAN_INFO => Self::Info(
                VfVlanInfo::parse(&VfVlanInfoBuffer::new(payload))
                    .context(format!("invalid IFLA_VF_VLAN_INFO {payload:?}"))?,
            ),
            kind => Self::Other(
                DefaultNla::parse(buf)
                    .context(format!("failed to parse {kind} as DefaultNla: {payload:?}"))?,
            ),
        })
    }
}

const VF_VLAN_INFO_LEN: usize = 16; // with 2 bytes padding

#[derive(Debug, Clone, Copy, Eq, PartialEq, Default)]
#[non_exhaustive]
pub struct VfVlanInfo {
    pub vf_id: u32,
    pub vlan_id: u32,
    pub qos: u32,
    pub protocol: VlanProtocol,
}

impl VfVlanInfo {
    pub fn new(vf_id: u32, vlan_id: u32, qos: u32, protocol: VlanProtocol) -> Self {
        Self { vf_id, vlan_id, qos, protocol }
    }
}

buffer!(VfVlanInfoBuffer(VF_VLAN_INFO_LEN) {
    vf_id: (u32, 0..4),
    vlan_id: (u32, 4..8),
    qos: (u32, 8..12),
    protocol: (u16, 12..14),
});

impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<VfVlanInfoBuffer<&'a T>> for VfVlanInfo {
    type Error = DecodeError;
    fn parse(buf: &VfVlanInfoBuffer<&T>) -> Result<Self, DecodeError> {
        Ok(Self {
            vf_id: buf.vf_id(),
            vlan_id: buf.vlan_id(),
            qos: buf.qos(),
            protocol: u16::from_be(buf.protocol()).into(),
        })
    }
}

impl Emitable for VfVlanInfo {
    fn buffer_len(&self) -> usize {
        VF_VLAN_INFO_LEN
    }

    fn emit(&self, buffer: &mut [u8]) {
        let mut buffer = VfVlanInfoBuffer::new(buffer);
        buffer.set_vf_id(self.vf_id);
        buffer.set_vlan_id(self.vlan_id);
        buffer.set_qos(self.qos);
        buffer.set_protocol(u16::from(self.protocol).to_be());
    }
}