netlink_packet_route/link/sriov/
stats.rs

1// SPDX-License-Identifier: MIT
2
3use anyhow::Context;
4use byteorder::{ByteOrder, NativeEndian};
5use netlink_packet_utils::nla::{DefaultNla, Nla, NlaBuffer};
6use netlink_packet_utils::parsers::parse_u64;
7use netlink_packet_utils::{DecodeError, Parseable};
8
9const IFLA_VF_STATS_RX_PACKETS: u16 = 0;
10const IFLA_VF_STATS_TX_PACKETS: u16 = 1;
11const IFLA_VF_STATS_RX_BYTES: u16 = 2;
12const IFLA_VF_STATS_TX_BYTES: u16 = 3;
13const IFLA_VF_STATS_BROADCAST: u16 = 4;
14const IFLA_VF_STATS_MULTICAST: u16 = 5;
15// const IFLA_VF_STATS_PAD: u16 = 6;
16const IFLA_VF_STATS_RX_DROPPED: u16 = 7;
17const IFLA_VF_STATS_TX_DROPPED: u16 = 8;
18
19#[derive(Debug, Clone, Eq, PartialEq)]
20#[non_exhaustive]
21pub enum VfStats {
22    RxPackets(u64),
23    TxPackets(u64),
24    RxBytes(u64),
25    TxBytes(u64),
26    Broadcast(u64),
27    Multicast(u64),
28    RxDropped(u64),
29    TxDropped(u64),
30    Other(DefaultNla),
31}
32
33impl Nla for VfStats {
34    fn value_len(&self) -> usize {
35        match self {
36            Self::Other(v) => v.value_len(),
37            _ => 8,
38        }
39    }
40
41    fn emit_value(&self, buffer: &mut [u8]) {
42        match self {
43            Self::RxPackets(v)
44            | Self::TxPackets(v)
45            | Self::RxBytes(v)
46            | Self::TxBytes(v)
47            | Self::Broadcast(v)
48            | Self::Multicast(v)
49            | Self::RxDropped(v)
50            | Self::TxDropped(v) => NativeEndian::write_u64(buffer, *v),
51            Self::Other(attr) => attr.emit_value(buffer),
52        }
53    }
54
55    fn kind(&self) -> u16 {
56        match self {
57            Self::RxPackets(_) => IFLA_VF_STATS_RX_PACKETS,
58            Self::TxPackets(_) => IFLA_VF_STATS_TX_PACKETS,
59            Self::RxBytes(_) => IFLA_VF_STATS_RX_BYTES,
60            Self::TxBytes(_) => IFLA_VF_STATS_TX_BYTES,
61            Self::Broadcast(_) => IFLA_VF_STATS_BROADCAST,
62            Self::Multicast(_) => IFLA_VF_STATS_MULTICAST,
63            Self::RxDropped(_) => IFLA_VF_STATS_RX_DROPPED,
64            Self::TxDropped(_) => IFLA_VF_STATS_TX_DROPPED,
65            Self::Other(v) => v.kind(),
66        }
67    }
68}
69
70impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for VfStats {
71    type Error = DecodeError;
72    fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
73        let payload = buf.value();
74        Ok(match buf.kind() {
75            IFLA_VF_STATS_RX_PACKETS => Self::RxPackets(
76                parse_u64(payload)
77                    .context(format!("invalid IFLA_VF_STATS_RX_PACKETS value {payload:?}"))?,
78            ),
79            IFLA_VF_STATS_TX_PACKETS => Self::TxPackets(
80                parse_u64(payload)
81                    .context(format!("invalid IFLA_VF_STATS_TX_PACKETS value {payload:?}"))?,
82            ),
83            IFLA_VF_STATS_RX_BYTES => Self::RxBytes(
84                parse_u64(payload)
85                    .context(format!("invalid IFLA_VF_STATS_RX_BYTES value {payload:?}"))?,
86            ),
87            IFLA_VF_STATS_TX_BYTES => Self::TxBytes(
88                parse_u64(payload)
89                    .context(format!("invalid IFLA_VF_STATS_TX_BYTES value {payload:?}"))?,
90            ),
91            IFLA_VF_STATS_BROADCAST => Self::Broadcast(
92                parse_u64(payload)
93                    .context(format!("invalid IFLA_VF_STATS_BROADCAST value {payload:?}"))?,
94            ),
95            IFLA_VF_STATS_MULTICAST => Self::Multicast(
96                parse_u64(payload)
97                    .context(format!("invalid IFLA_VF_STATS_MULTICAST value {payload:?}"))?,
98            ),
99            IFLA_VF_STATS_RX_DROPPED => Self::RxDropped(
100                parse_u64(payload)
101                    .context(format!("invalid IFLA_VF_STATS_RX_DROPPED value {payload:?}"))?,
102            ),
103            IFLA_VF_STATS_TX_DROPPED => Self::TxDropped(
104                parse_u64(payload)
105                    .context(format!("invalid IFLA_VF_STATS_TX_DROPPED value {payload:?}"))?,
106            ),
107            kind => Self::Other(
108                DefaultNla::parse(buf)
109                    .context(format!("failed to parse {kind} as DefaultNla: {payload:?}"))?,
110            ),
111        })
112    }
113}