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