netlink_packet_route/link/sriov/
vf_list.rs

1// SPDX-License-Identifier: MIT
2
3use anyhow::Context;
4use netlink_packet_utils::{
5    nla::{DefaultNla, Nla, NlaBuffer, NlasIterator},
6    DecodeError, Emitable, Parseable,
7};
8
9use crate::link::{
10    VfInfoBroadcast, VfInfoBroadcastBuffer, VfInfoGuid, VfInfoGuidBuffer,
11    VfInfoLinkState, VfInfoLinkStateBuffer, VfInfoMac, VfInfoMacBuffer,
12    VfInfoRate, VfInfoRateBuffer, VfInfoRssQueryEn, VfInfoRssQueryEnBuffer,
13    VfInfoSpoofCheck, VfInfoSpoofCheckBuffer, VfInfoTrust, VfInfoTrustBuffer,
14    VfInfoTxRate, VfInfoTxRateBuffer, VfInfoVlan, VfInfoVlanBuffer, VfStats,
15    VfVlan,
16};
17
18const IFLA_VF_INFO: u16 = 1;
19
20#[derive(Debug, Clone, Eq, PartialEq)]
21pub(crate) struct VecLinkVfInfo(pub(crate) Vec<LinkVfInfo>);
22
23impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>>
24    for VecLinkVfInfo
25{
26    fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
27        let mut nlas = vec![];
28        for nla in NlasIterator::new(buf.into_inner()) {
29            let nla = &nla.context(format!(
30                "invalid IFLA_VFINFO_LIST value: {:?}",
31                buf.value()
32            ))?;
33            if nla.kind() == IFLA_VF_INFO {
34                nlas.push(LinkVfInfo::parse(&NlaBuffer::new_checked(
35                    nla.value(),
36                )?)?);
37            } else {
38                log::warn!(
39                    "BUG: Expecting IFLA_VF_INFO in IFLA_VFINFO_LIST, \
40                    but got {}",
41                    nla.kind()
42                );
43            }
44        }
45        Ok(Self(nlas))
46    }
47}
48
49#[derive(Debug, Clone, Default, Eq, PartialEq)]
50pub struct LinkVfInfo(pub Vec<VfInfo>);
51
52impl Nla for LinkVfInfo {
53    fn value_len(&self) -> usize {
54        self.0.as_slice().buffer_len()
55    }
56
57    fn emit_value(&self, buffer: &mut [u8]) {
58        self.0.as_slice().emit(buffer)
59    }
60
61    fn kind(&self) -> u16 {
62        IFLA_VF_INFO
63    }
64}
65
66impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for LinkVfInfo {
67    fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
68        let mut nlas = vec![];
69        for nla in NlasIterator::new(buf.into_inner()) {
70            let nla = &nla.context(format!(
71                "invalid IFLA_VF_INFO value {:?}",
72                buf.value()
73            ))?;
74            nlas.push(VfInfo::parse(nla)?);
75        }
76        Ok(Self(nlas))
77    }
78}
79
80const IFLA_VF_MAC: u16 = 1;
81const IFLA_VF_VLAN: u16 = 2;
82const IFLA_VF_TX_RATE: u16 = 3;
83const IFLA_VF_SPOOFCHK: u16 = 4;
84const IFLA_VF_LINK_STATE: u16 = 5;
85const IFLA_VF_RATE: u16 = 6;
86const IFLA_VF_RSS_QUERY_EN: u16 = 7;
87const IFLA_VF_STATS: u16 = 8;
88const IFLA_VF_TRUST: u16 = 9;
89const IFLA_VF_IB_NODE_GUID: u16 = 10;
90const IFLA_VF_IB_PORT_GUID: u16 = 11;
91const IFLA_VF_VLAN_LIST: u16 = 12;
92const IFLA_VF_BROADCAST: u16 = 13;
93
94#[derive(Debug, Clone, Eq, PartialEq)]
95#[non_exhaustive]
96pub enum VfInfo {
97    Mac(VfInfoMac),
98    Broadcast(VfInfoBroadcast),
99    Vlan(VfInfoVlan),
100    Rate(VfInfoRate),
101    TxRate(VfInfoTxRate),
102    SpoofCheck(VfInfoSpoofCheck),
103    LinkState(VfInfoLinkState),
104    RssQueryEn(VfInfoRssQueryEn),
105    Trust(VfInfoTrust),
106    IbNodeGuid(VfInfoGuid),
107    IbPortGuid(VfInfoGuid),
108    VlanList(Vec<VfVlan>),
109    Stats(Vec<VfStats>),
110    Other(DefaultNla),
111}
112
113impl Nla for VfInfo {
114    fn value_len(&self) -> usize {
115        match self {
116            Self::Mac(v) => v.buffer_len(),
117            Self::Vlan(v) => v.buffer_len(),
118            Self::Broadcast(v) => v.buffer_len(),
119            Self::Rate(v) => v.buffer_len(),
120            Self::TxRate(v) => v.buffer_len(),
121            Self::SpoofCheck(v) => v.buffer_len(),
122            Self::LinkState(v) => v.buffer_len(),
123            Self::RssQueryEn(v) => v.buffer_len(),
124            Self::Trust(v) => v.buffer_len(),
125            Self::IbNodeGuid(v) => v.buffer_len(),
126            Self::IbPortGuid(v) => v.buffer_len(),
127            Self::VlanList(v) => v.as_slice().buffer_len(),
128            Self::Stats(v) => v.as_slice().buffer_len(),
129            Self::Other(v) => v.value_len(),
130        }
131    }
132
133    fn emit_value(&self, buffer: &mut [u8]) {
134        match self {
135            Self::Mac(v) => v.emit(buffer),
136            Self::Vlan(v) => v.emit(buffer),
137            Self::Broadcast(v) => v.emit(buffer),
138            Self::Rate(v) => v.emit(buffer),
139            Self::TxRate(v) => v.emit(buffer),
140            Self::SpoofCheck(v) => v.emit(buffer),
141            Self::LinkState(v) => v.emit(buffer),
142            Self::RssQueryEn(v) => v.emit(buffer),
143            Self::Trust(v) => v.emit(buffer),
144            Self::IbNodeGuid(v) => v.emit(buffer),
145            Self::IbPortGuid(v) => v.emit(buffer),
146            Self::VlanList(v) => v.as_slice().emit(buffer),
147            Self::Stats(v) => v.as_slice().emit(buffer),
148            Self::Other(attr) => attr.emit_value(buffer),
149        }
150    }
151
152    fn kind(&self) -> u16 {
153        match self {
154            Self::Mac(_) => IFLA_VF_MAC,
155            Self::Vlan(_) => IFLA_VF_VLAN,
156            Self::Broadcast(_) => IFLA_VF_BROADCAST,
157            Self::Rate(_) => IFLA_VF_RATE,
158            Self::TxRate(_) => IFLA_VF_TX_RATE,
159            Self::SpoofCheck(_) => IFLA_VF_SPOOFCHK,
160            Self::LinkState(_) => IFLA_VF_LINK_STATE,
161            Self::RssQueryEn(_) => IFLA_VF_RSS_QUERY_EN,
162            Self::Trust(_) => IFLA_VF_TRUST,
163            Self::IbNodeGuid(_) => IFLA_VF_IB_NODE_GUID,
164            Self::IbPortGuid(_) => IFLA_VF_IB_PORT_GUID,
165            Self::VlanList(_) => IFLA_VF_VLAN_LIST,
166            Self::Stats(_) => IFLA_VF_STATS,
167            Self::Other(v) => v.kind(),
168        }
169    }
170}
171
172impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for VfInfo {
173    fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
174        let payload = buf.value();
175        Ok(match buf.kind() {
176            IFLA_VF_MAC => Self::Mac(
177                VfInfoMac::parse(&VfInfoMacBuffer::new(payload))
178                    .context(format!("invalid IFLA_VF_MAC {payload:?}"))?,
179            ),
180            IFLA_VF_VLAN => Self::Vlan(
181                VfInfoVlan::parse(&VfInfoVlanBuffer::new(payload))
182                    .context(format!("invalid IFLA_VF_VLAN {payload:?}"))?,
183            ),
184            IFLA_VF_BROADCAST => Self::Broadcast(
185                VfInfoBroadcast::parse(&VfInfoBroadcastBuffer::new(payload))
186                    .context(format!(
187                        "invalid IFLA_VF_BROADCAST {payload:?}"
188                    ))?,
189            ),
190            IFLA_VF_RATE => Self::Rate(
191                VfInfoRate::parse(&VfInfoRateBuffer::new(payload))
192                    .context(format!("invalid IFLA_VF_RATE {payload:?}"))?,
193            ),
194            IFLA_VF_TX_RATE => Self::TxRate(
195                VfInfoTxRate::parse(&VfInfoTxRateBuffer::new(payload))
196                    .context(format!("invalid IFLA_VF_TX_RATE {payload:?}"))?,
197            ),
198            IFLA_VF_SPOOFCHK => Self::SpoofCheck(
199                VfInfoSpoofCheck::parse(&VfInfoSpoofCheckBuffer::new(payload))
200                    .context(format!("invalid IFLA_VF_SPOOFCHK {payload:?}"))?,
201            ),
202            IFLA_VF_LINK_STATE => Self::LinkState(
203                VfInfoLinkState::parse(&VfInfoLinkStateBuffer::new(payload))
204                    .context(format!(
205                        "invalid IFLA_VF_LINK_STATE {payload:?}"
206                    ))?,
207            ),
208            IFLA_VF_RSS_QUERY_EN => Self::RssQueryEn(
209                VfInfoRssQueryEn::parse(&VfInfoRssQueryEnBuffer::new(payload))
210                    .context(format!(
211                        "invalid IFLA_VF_RSS_QUERY_EN {payload:?}"
212                    ))?,
213            ),
214            IFLA_VF_TRUST => Self::Trust(
215                VfInfoTrust::parse(&VfInfoTrustBuffer::new(payload))
216                    .context(format!("invalid IFLA_VF_TRUST {payload:?}"))?,
217            ),
218            IFLA_VF_IB_NODE_GUID => Self::IbNodeGuid(
219                VfInfoGuid::parse(&VfInfoGuidBuffer::new(payload)).context(
220                    format!("invalid IFLA_VF_IB_NODE_GUID {payload:?}"),
221                )?,
222            ),
223            IFLA_VF_IB_PORT_GUID => Self::IbPortGuid(
224                VfInfoGuid::parse(&VfInfoGuidBuffer::new(payload)).context(
225                    format!("invalid IFLA_VF_IB_PORT_GUID {payload:?}"),
226                )?,
227            ),
228            IFLA_VF_VLAN_LIST => {
229                let mut nlas: Vec<VfVlan> = Vec::new();
230                for nla in NlasIterator::new(payload) {
231                    let nla = &nla.context(format!(
232                        "invalid IFLA_VF_VLAN_LIST value: {:?}",
233                        buf.value()
234                    ))?;
235
236                    nlas.push(VfVlan::parse(nla)?);
237                }
238                Self::VlanList(nlas)
239            }
240            IFLA_VF_STATS => {
241                let mut nlas: Vec<VfStats> = Vec::new();
242                for nla in NlasIterator::new(payload) {
243                    let nla = &nla.context(format!(
244                        "invalid IFLA_VF_STATS value: {:?}",
245                        buf.value()
246                    ))?;
247
248                    nlas.push(VfStats::parse(nla)?);
249                }
250                Self::Stats(nlas)
251            }
252            kind => Self::Other(DefaultNla::parse(buf).context(format!(
253                "failed to parse {kind} as DefaultNla: {payload:?}"
254            ))?),
255        })
256    }
257}