flowparser_sflow/counter_records/
mod.rs1pub mod ethernet_interface;
2pub mod generic_interface;
3pub mod processor;
4pub mod token_ring;
5pub mod vlan;
6
7use nom::IResult;
8use nom::number::complete::be_u32;
9use serde::{Deserialize, Serialize};
10
11pub use ethernet_interface::EthernetInterface;
12pub use generic_interface::GenericInterface;
13pub use processor::Processor;
14pub use token_ring::TokenRing;
15pub use vlan::Vlan;
16
17#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
22pub enum CounterRecord {
23 GenericInterface(GenericInterface),
25 EthernetInterface(EthernetInterface),
27 TokenRing(TokenRing),
29 Vlan(Vlan),
31 Processor(Processor),
33 Unknown {
35 enterprise: u32,
37 format: u32,
39 data: Vec<u8>,
41 },
42}
43
44pub(crate) fn parse_counter_records(
45 mut input: &[u8],
46 num_records: u32,
47) -> IResult<&[u8], Vec<CounterRecord>> {
48 let cap = (num_records as usize).min(input.len() / 8);
50 let mut records = Vec::with_capacity(cap);
51
52 for _ in 0..num_records {
53 let (rest, data_format) = be_u32(input)?;
54 let enterprise = data_format >> 12;
55 let format = data_format & 0xFFF;
56
57 let (rest, record_length) = be_u32(rest)?;
58 let record_length = record_length as usize;
59
60 if rest.len() < record_length {
61 return Err(nom::Err::Error(nom::error::Error::new(
62 rest,
63 nom::error::ErrorKind::Eof,
64 )));
65 }
66
67 let record_data = &rest[..record_length];
68 let after_record = &rest[record_length..];
69
70 let record = if enterprise == 0 {
71 match format {
72 1 => {
73 let (_, r) = generic_interface::parse_generic_interface(record_data)?;
74 CounterRecord::GenericInterface(r)
75 }
76 2 => {
77 let (_, r) = ethernet_interface::parse_ethernet_interface(record_data)?;
78 CounterRecord::EthernetInterface(r)
79 }
80 3 => {
81 let (_, r) = token_ring::parse_token_ring(record_data)?;
82 CounterRecord::TokenRing(r)
83 }
84 5 => {
85 let (_, r) = vlan::parse_vlan(record_data)?;
86 CounterRecord::Vlan(r)
87 }
88 1001 => {
89 let (_, r) = processor::parse_processor(record_data)?;
90 CounterRecord::Processor(r)
91 }
92 _ => CounterRecord::Unknown {
93 enterprise,
94 format,
95 data: record_data.to_vec(),
96 },
97 }
98 } else {
99 CounterRecord::Unknown {
100 enterprise,
101 format,
102 data: record_data.to_vec(),
103 }
104 };
105
106 records.push(record);
107 input = after_record;
108 }
109
110 Ok((input, records))
111}