Skip to content

Commit cd56aa6

Browse files
mikemiles-devMichael Mileusnich
and
Michael Mileusnich
authored
ipfix options cleanup (#46)
* ipfix options cleanup * Releases --------- Co-authored-by: Michael Mileusnich <[email protected]>
1 parent df6f736 commit cd56aa6

File tree

2 files changed

+40
-29
lines changed

2 files changed

+40
-29
lines changed

RELEASES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# 0.2.5
22
* More code-reorg. Added tests.rs just for tests. Added parsing.rs for majority of parsing.
3+
* Removed uneeded ipfix Option Template Code.
34

45
# 0.2.4
56
* Fixes for V9 parsing. Now supports processing multiple templates.

src/variable_versions/ipfix.rs

Lines changed: 39 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
use super::common::*;
1010
use crate::variable_versions::ipfix_lookup::*;
1111

12-
use nom::bytes::complete::take;
1312
use nom::combinator::complete;
1413
use nom::error::{Error as NomError, ErrorKind};
1514
use nom::multi::{count, many0};
@@ -47,26 +46,47 @@ pub struct IPFix {
4746

4847
#[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Nom)]
4948
pub struct Header {
50-
/// Version of Flow Record format that is exported in this message. The value of this field is 0x000a for the current version, incrementing by one the version that is used in the NetFlow services export version 9
49+
/// Version of Flow Record format that is exported in this message. The value of this
50+
/// field is 0x000a for the current version, incrementing by one the version that is
51+
/// used in the NetFlow services export version 9
5152
#[nom(Value = "10")]
5253
pub version: u16,
53-
/// Total length of the IPFIX Message, which is measured in octets, including Message Header and Sets.
54+
/// Total length of the IPFIX Message, which is measured in octets, including Message
55+
/// Header and Sets.
5456
pub length: u16,
55-
/// Time, in seconds, since 0000 Coordinated Universal Time Jan 1, 1970, at which the IPFIX Message Header leaves the Exporter.
57+
/// Time, in seconds, since 0000 Coordinated Universal Time Jan 1, 1970, at which the
58+
/// IPFIX Message Header leaves the Exporter.
5659
#[nom(Map = "|i| Duration::from_secs(i as u64)", Parse = "be_u32")]
5760
pub export_time: Duration,
58-
/// Incremental sequence counter-modulo 2^32 of all IPFIX Data Records sent on this PR-SCTP stream from the current Observation Domain by the Exporting Process. Check the specific meaning of this field in the subsections of Section 10 when UDP or TCP is selected as the transport protocol. This value must be used by the Collecting Process to identify whether any IPFIX Data Records are missed. Template and Options Template Records do not increase the Sequence Number.
61+
/// Incremental sequence counter-modulo 2^32 of all IPFIX Data Records sent on this PR-SCTP
62+
/// stream from the current Observation Domain by the Exporting Process. Check the specific
63+
/// meaning of this field in the subsections of Section 10 when UDP or TCP is selected as the
64+
/// transport protocol. This value must be used by the Collecting Process to identify whether
65+
/// any IPFIX Data Records are missed. Template and Options Template Records do not increase
66+
/// the Sequence Number.
5967
pub sequence_number: u32,
60-
/// A 32-bit identifier of the Observation Domain that is locally unique to the Exporting Process. The Exporting Process uses the Observation Domain ID to uniquely identify to the Collector. Process the Observation Domain that metered the Flows. It is recommended that this identifier is unique per IPFIX Device. Collecting Processes must use the Transport Session. Observation Domain ID field to separate different export streams that originate from the same Exporting Process. The Observation Domain ID must be 0 when no specific Observation Domain ID is relevant for the entire IPFIX Message. For example, when the Exporting Process Statistics are exported, or in a hierarchy of Collectors when aggregated Data Records are exported.
68+
/// A 32-bit identifier of the Observation Domain that is locally unique to the Exporting Process.
69+
/// The Exporting Process uses the Observation Domain ID to uniquely identify to the Collector.
70+
/// Process the Observation Domain that metered the Flows. It is recommended that this identifier
71+
/// is unique per IPFIX Device. Collecting Processes must use the Transport Session. Observation
72+
/// Domain ID field to separate different export streams that originate from the same Exporting Process.
73+
/// The Observation Domain ID must be 0 when no specific Observation Domain ID is relevant for the
74+
/// entire IPFIX Message. For example, when the Exporting Process Statistics are exported, or in a hierarchy
75+
/// of Collectors when aggregated Data Records are exported.
6176
pub observation_domain_id: u32,
6277
}
6378

6479
#[derive(Debug, PartialEq, Clone, Serialize, Nom)]
6580
#[nom(ExtraArgs(parser: &mut IPFixParser))]
6681
pub struct Set {
67-
/// Set ID value identifies the Set. A value of 2 is reserved for the Template Set. A value of 3 is reserved for the Option Template Set. All other values 4-255 are reserved for future use. Values more than 255 are used for Data Sets. The Set ID values of 0 and 1 are not used for historical reasons
82+
/// Set ID value identifies the Set. A value of 2 is reserved for the Template Set.
83+
/// A value of 3 is reserved for the Option Template Set. All other values 4-255 are
84+
/// reserved for future use. Values more than 255 are used for Data Sets. The Set ID
85+
/// values of 0 and 1 are not used for historical reasons
6886
pub id: u16,
69-
/// Total length of the Set, in octets, including the Set Header, all records, and the optional padding. Because an individual Set MAY contain multiple records, the Length value must be used to determine the position of the next Set.
87+
/// Total length of the Set, in octets, including the Set Header, all records, and the
88+
/// optional padding. Because an individual Set MAY contain multiple records, the Length
89+
/// value must be used to determine the position of the next Set.
7090
pub length: u16,
7191
#[nom(
7292
Cond = "id == TEMPLATE_ID",
@@ -77,9 +97,12 @@ pub struct Set {
7797
pub template: Option<Template>,
7898
#[nom(
7999
Cond = "id == OPTIONS_TEMPLATE_ID",
80-
Parse = "{ |i| parse_options_template(i, length) }",
100+
PreExec = "let set_length = length.checked_sub(4).unwrap_or(length);",
101+
Parse = "{ |i| OptionsTemplate::parse(i, set_length) }",
81102
// Save our templates
82-
PostExec = "if let Some(options_template) = options_template.clone() { parser.options_templates.insert(options_template.template_id, options_template); }"
103+
PostExec = "if let Some(options_template) = options_template.clone() {
104+
parser.options_templates.insert(options_template.template_id, options_template);
105+
}"
83106
)]
84107
#[serde(skip_serializing_if = "Option::is_none")]
85108
pub options_template: Option<OptionsTemplate>,
@@ -116,17 +139,19 @@ pub struct OptionsData {
116139
}
117140

118141
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Nom)]
142+
#[nom(ExtraArgs(set_length: u16))]
119143
pub struct OptionsTemplate {
120144
pub template_id: u16,
121145
pub field_count: u16,
122146
pub scope_field_count: u16,
123147
#[nom(
124148
PreExec = "let combined_count = scope_field_count as usize +
125149
field_count.checked_sub(scope_field_count).unwrap_or(field_count) as usize;",
126-
Parse = "count(|i| TemplateField::parse(i, true), combined_count)"
150+
Parse = "count(|i| TemplateField::parse(i, true), combined_count)",
151+
PostExec = "let options_remaining = set_length.checked_sub(field_count * 4).unwrap_or(set_length) > 0;"
127152
)]
128153
pub fields: Vec<TemplateField>,
129-
#[nom(Cond = "!i.is_empty()")]
154+
#[nom(Cond = "options_remaining && !i.is_empty()")]
130155
#[serde(skip_serializing)]
131156
padding: Option<u16>,
132157
}
@@ -151,29 +176,14 @@ pub struct TemplateField {
151176
PostExec = "let field_type_number = if options_template {
152177
field_type_number.overflowing_sub(32768).0
153178
} else { field_type_number };",
154-
PostExec = "let field_type = if options_template {
155-
set_entperprise_field(field_type, enterprise_number)
179+
PostExec = "let field_type = if options_template && enterprise_number.is_some() {
180+
IPFixField::Enterprise
156181
} else { field_type };"
157182
)]
158183
#[serde(skip_serializing_if = "Option::is_none")]
159184
pub enterprise_number: Option<u32>,
160185
}
161186

162-
fn set_entperprise_field(field_type: IPFixField, enterprise_number: Option<u32>) -> IPFixField {
163-
if enterprise_number.is_some() {
164-
IPFixField::Enterprise
165-
} else {
166-
field_type
167-
}
168-
}
169-
170-
/// Parses options template
171-
fn parse_options_template(i: &[u8], length: u16) -> IResult<&[u8], OptionsTemplate> {
172-
let (remaining, taken) = take(length.checked_sub(4).unwrap_or(length))(i)?;
173-
let (_, option_template) = OptionsTemplate::parse(taken)?;
174-
Ok((remaining, option_template))
175-
}
176-
177187
// Common trait for both templates. Mainly for fetching fields.
178188
trait CommonTemplate {
179189
fn get_fields(&self) -> &Vec<TemplateField>;

0 commit comments

Comments
 (0)