flowparser_sflow/samples/
mod.rs1pub mod counter_sample;
2pub mod flow_sample;
3
4use nom::number::complete::be_u32;
5use serde::{Deserialize, Serialize};
6
7use crate::error::{ParseContext, ParseErrorKind, SflowError};
8pub use counter_sample::{CounterSample, ExpandedCounterSample};
9pub use flow_sample::{ExpandedFlowSample, FlowSample};
10
11#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
17pub enum SflowSample {
18 Flow(FlowSample),
20 Counter(CounterSample),
22 ExpandedFlow(ExpandedFlowSample),
24 ExpandedCounter(ExpandedCounterSample),
26 Unknown {
28 enterprise: u32,
30 format: u32,
32 data: Vec<u8>,
34 },
35}
36
37pub(crate) fn parse_samples(
38 mut input: &[u8],
39 num_samples: u32,
40) -> Result<(&[u8], Vec<SflowSample>), SflowError> {
41 let cap = (num_samples as usize).min(input.len() / 8);
43 let mut samples = Vec::with_capacity(cap);
44
45 for _ in 0..num_samples {
46 let (rest, data_format) =
47 be_u32(input).map_err(|_: nom::Err<nom::error::Error<&[u8]>>| {
48 SflowError::Incomplete {
49 available: input.len(),
50 expected: None,
51 context: ParseContext::SampleDataFormat,
52 }
53 })?;
54
55 let enterprise = data_format >> 12;
56 let format = data_format & 0xFFF;
57
58 let (rest, sample_length) =
59 be_u32(rest).map_err(|_: nom::Err<nom::error::Error<&[u8]>>| {
60 SflowError::Incomplete {
61 available: rest.len(),
62 expected: None,
63 context: ParseContext::SampleLength,
64 }
65 })?;
66
67 let sample_length = sample_length as usize;
68 if rest.len() < sample_length {
69 return Err(SflowError::Incomplete {
70 available: rest.len(),
71 expected: Some(sample_length),
72 context: ParseContext::SampleData,
73 });
74 }
75
76 let sample_data = &rest[..sample_length];
77 let after_sample = &rest[sample_length..];
78
79 let sample = if enterprise == 0 {
80 match format {
81 1 => {
82 let (_, fs) = flow_sample::parse_flow_sample(sample_data).map_err(|e| {
83 SflowError::ParseError {
84 offset: 0,
85 context: ParseContext::FlowSample,
86 kind: nom_err_to_kind(&e),
87 }
88 })?;
89 SflowSample::Flow(fs)
90 }
91 2 => {
92 let (_, cs) =
93 counter_sample::parse_counter_sample(sample_data).map_err(|e| {
94 SflowError::ParseError {
95 offset: 0,
96 context: ParseContext::CounterSample,
97 kind: nom_err_to_kind(&e),
98 }
99 })?;
100 SflowSample::Counter(cs)
101 }
102 3 => {
103 let (_, efs) = flow_sample::parse_expanded_flow_sample(sample_data)
104 .map_err(|e| SflowError::ParseError {
105 offset: 0,
106 context: ParseContext::ExpandedFlowSample,
107 kind: nom_err_to_kind(&e),
108 })?;
109 SflowSample::ExpandedFlow(efs)
110 }
111 4 => {
112 let (_, ecs) = counter_sample::parse_expanded_counter_sample(sample_data)
113 .map_err(|e| SflowError::ParseError {
114 offset: 0,
115 context: ParseContext::ExpandedCounterSample,
116 kind: nom_err_to_kind(&e),
117 })?;
118 SflowSample::ExpandedCounter(ecs)
119 }
120 _ => SflowSample::Unknown {
121 enterprise,
122 format,
123 data: sample_data.to_vec(),
124 },
125 }
126 } else {
127 SflowSample::Unknown {
128 enterprise,
129 format,
130 data: sample_data.to_vec(),
131 }
132 };
133
134 samples.push(sample);
135 input = after_sample;
136 }
137
138 Ok((input, samples))
139}
140
141fn nom_err_to_kind(e: &nom::Err<nom::error::Error<&[u8]>>) -> ParseErrorKind {
142 match e {
143 nom::Err::Error(e) | nom::Err::Failure(e) => ParseErrorKind::NomError(e.code),
144 nom::Err::Incomplete(_) => ParseErrorKind::NomError(nom::error::ErrorKind::Complete),
145 }
146}