netlink_packet_route/link/sriov/
vf_list.rs

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