pub struct NetflowParser { /* private fields */ }Expand description
Main parser for Netflow packets supporting V5, V7, V9, and IPFIX.
Use NetflowParser::builder() for ergonomic configuration with the builder pattern,
or NetflowParser::default() for quick setup with defaults.
§⚠️ Multi-Source Deployments
IMPORTANT: If you’re parsing NetFlow from multiple routers or sources,
use AutoScopedParser instead of NetflowParser
to prevent template cache collisions.
Template IDs are NOT unique across sources. Different routers can (and often do)
use the same template ID with completely different schemas. When multiple sources
share a single NetflowParser, their templates collide in the cache, causing:
- Template thrashing (constant eviction and re-learning)
- Parsing failures (data parsed with wrong template)
- Performance degradation (high cache miss rate)
§Single Source (✅ Use NetflowParser)
use netflow_parser::NetflowParser;
let mut parser = NetflowParser::default();
let data = [0u8; 72]; // Example NetFlow data
// Single router/source - no collisions possible
let packets = parser.parse_bytes(&data);§Multiple Sources (✅ Use AutoScopedParser)
use netflow_parser::AutoScopedParser;
use std::net::SocketAddr;
let mut parser = AutoScopedParser::new();
let source: SocketAddr = "192.168.1.1:2055".parse().unwrap();
let data = [0u8; 72]; // Example NetFlow data
// Each source gets isolated template cache (RFC-compliant)
let packets = parser.parse_from_source(source, &data);§Examples
use netflow_parser::NetflowParser;
use netflow_parser::variable_versions::ttl::TtlConfig;
use std::time::Duration;
// Using builder pattern (recommended)
let parser = NetflowParser::builder()
.with_cache_size(2000)
.with_ttl(TtlConfig::new(Duration::from_secs(7200)))
.build()
.expect("Failed to build parser");
// Using default
let parser = NetflowParser::default();Implementations§
Source§impl NetflowParser
impl NetflowParser
Sourcepub fn builder() -> NetflowParserBuilder
pub fn builder() -> NetflowParserBuilder
Creates a new builder for configuring a NetflowParser.
§Examples
use netflow_parser::NetflowParser;
use netflow_parser::variable_versions::ttl::TtlConfig;
use std::time::Duration;
let parser = NetflowParser::builder()
.with_cache_size(2000)
.with_ttl(TtlConfig::new(Duration::from_secs(7200)))
.build()
.expect("Failed to build parser");Sourcepub fn set_template_store_scope(&mut self, scope: impl Into<Arc<str>>)
pub fn set_template_store_scope(&mut self, scope: impl Into<Arc<str>>)
Override the scope string used for TemplateStore reads/writes by
the underlying V9 and IPFIX parsers.
Used by AutoScopedParser to give each per-source parser a scope
derived from the exporter’s SocketAddr. Callers managing their own
per-source parsers may also use this to retrofit a scope after the
builder has produced a parser.
Accepts anything Into<Arc<str>> — typically &str or String.
Sourcepub fn allowed_versions(&self) -> &[bool; 11]
pub fn allowed_versions(&self) -> &[bool; 11]
Returns the allowed versions array.
Indexed by version number: index 5 = V5, 7 = V7, 9 = V9, 10 = IPFIX.
true means the version is accepted for parsing.
Sourcepub fn is_version_allowed(&self, version: u16) -> bool
pub fn is_version_allowed(&self, version: u16) -> bool
Returns whether the given NetFlow version is allowed for parsing.
Returns false for version numbers outside the supported range (0–10).
Sourcepub fn max_error_sample_size(&self) -> usize
pub fn max_error_sample_size(&self) -> usize
Returns the maximum error sample size in bytes.
Sourcepub fn v9_parser_mut(&mut self) -> &mut V9Parser
pub fn v9_parser_mut(&mut self) -> &mut V9Parser
Returns a mutable reference to the V9 parser.
Sourcepub fn ipfix_parser(&self) -> &IPFixParser
pub fn ipfix_parser(&self) -> &IPFixParser
Returns a reference to the IPFIX parser.
Sourcepub fn ipfix_parser_mut(&mut self) -> &mut IPFixParser
pub fn ipfix_parser_mut(&mut self) -> &mut IPFixParser
Returns a mutable reference to the IPFIX parser.
Sourcepub fn v9_cache_info(&self) -> CacheInfo
pub fn v9_cache_info(&self) -> CacheInfo
Gets statistics about the V9 template cache.
§Examples
use netflow_parser::NetflowParser;
let parser = NetflowParser::default();
let stats = parser.v9_cache_info();
println!("V9 cache: {}/{} templates", stats.current_size, stats.max_size_per_cache);Sourcepub fn ipfix_cache_info(&self) -> CacheInfo
pub fn ipfix_cache_info(&self) -> CacheInfo
Gets statistics about the IPFIX template cache.
§Examples
use netflow_parser::NetflowParser;
let parser = NetflowParser::default();
let stats = parser.ipfix_cache_info();
println!("IPFIX cache: {}/{} templates", stats.current_size, stats.max_size_per_cache);Sourcepub fn v9_template_ids(&self) -> Vec<u16>
pub fn v9_template_ids(&self) -> Vec<u16>
Lists all cached V9 template IDs.
Note: This returns template IDs from both regular and options templates.
§Examples
use netflow_parser::NetflowParser;
let parser = NetflowParser::default();
let template_ids = parser.v9_template_ids();
println!("Cached V9 templates: {:?}", template_ids);Sourcepub fn ipfix_template_ids(&self) -> Vec<u16>
pub fn ipfix_template_ids(&self) -> Vec<u16>
Lists all cached IPFIX template IDs.
Note: This returns template IDs from both IPFIX and V9-format templates (IPFIX can contain both).
§Examples
use netflow_parser::NetflowParser;
let parser = NetflowParser::default();
let template_ids = parser.ipfix_template_ids();
println!("Cached IPFIX templates: {:?}", template_ids);Sourcepub fn has_v9_template(&self, template_id: u16) -> bool
pub fn has_v9_template(&self, template_id: u16) -> bool
Checks if a V9 template with the given ID is cached.
Note: This uses peek() which does not affect LRU ordering.
§Arguments
template_id- The template ID to check
§Examples
use netflow_parser::NetflowParser;
let parser = NetflowParser::default();
if parser.has_v9_template(256) {
println!("Template 256 is cached");
}Sourcepub fn has_ipfix_template(&self, template_id: u16) -> bool
pub fn has_ipfix_template(&self, template_id: u16) -> bool
Checks if an IPFIX template with the given ID is cached.
Note: This uses peek() which does not affect LRU ordering.
§Arguments
template_id- The template ID to check
§Examples
use netflow_parser::NetflowParser;
let parser = NetflowParser::default();
if parser.has_ipfix_template(256) {
println!("Template 256 is cached");
}Sourcepub fn clear_v9_templates(&mut self)
pub fn clear_v9_templates(&mut self)
Clears all cached V9 templates.
This is useful for testing or when you need to force template re-learning.
§Examples
use netflow_parser::NetflowParser;
let mut parser = NetflowParser::default();
parser.clear_v9_templates();Sourcepub fn clear_ipfix_templates(&mut self)
pub fn clear_ipfix_templates(&mut self)
Clears all cached IPFIX templates.
This is useful for testing or when you need to force template re-learning.
§Examples
use netflow_parser::NetflowParser;
let mut parser = NetflowParser::default();
parser.clear_ipfix_templates();Sourcepub fn clear_v9_pending_flows(&mut self)
pub fn clear_v9_pending_flows(&mut self)
Clears all pending V9 flows.
Sourcepub fn clear_ipfix_pending_flows(&mut self)
pub fn clear_ipfix_pending_flows(&mut self)
Clears all pending IPFIX flows.
Sourcepub fn trigger_template_event(&mut self, event: TemplateEvent)
pub fn trigger_template_event(&mut self, event: TemplateEvent)
Triggers template event hooks.
This method is called internally by template operations to notify registered hooks about template lifecycle events. It can also be called manually for testing or custom integration scenarios.
§Arguments
event- The template event to trigger
§Examples
use netflow_parser::{NetflowParser, TemplateEvent, TemplateProtocol};
let mut parser = NetflowParser::default();
parser.trigger_template_event(TemplateEvent::Learned {
template_id: Some(256),
protocol: TemplateProtocol::V9,
});Sourcepub fn hook_error_count(&self) -> u64
pub fn hook_error_count(&self) -> u64
Returns the total number of hook errors and panics encountered.
Useful for monitoring hook health in production without affecting parsing.
Sourcepub fn parse_bytes(&mut self, packet: &[u8]) -> ParseResult
pub fn parse_bytes(&mut self, packet: &[u8]) -> ParseResult
Parses NetFlow packets from a byte slice, preserving all successfully parsed packets.
This function parses packets in sequence and returns a ParseResult containing both
successfully parsed packets and an optional error. No data is lost - if parsing fails
partway through, you still get all packets parsed before the error.
§Arguments
packet- Byte slice containing NetFlow packet(s)
§Returns
ParseResult with:
packets- All successfully parsed packets (even if error occurred)error-Noneif fully successful,Some(error)if parsing stopped
§Examples
§Basic usage
use netflow_parser::NetflowParser;
let v5_packet = [0, 5, 2, 0, 3, 0, 4, 0, 5, 0, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7,];
let result = NetflowParser::default().parse_bytes(&v5_packet);
// Process all packets
for packet in result.packets {
println!("Parsed packet");
}
// Check for errors
if let Some(e) = result.error {
eprintln!("Error: {}", e);
}§With JSON serialization
use serde_json::json;
use netflow_parser::NetflowParser;
let v5_packet = [0, 5, 2, 0, 3, 0, 4, 0, 5, 0, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7,];
let result = NetflowParser::default().parse_bytes(&v5_packet);
println!("{}", json!(result.packets).to_string());Sourcepub fn iter_packets<'a>(
&'a mut self,
packet: &'a [u8],
) -> NetflowPacketIterator<'a> ⓘ
pub fn iter_packets<'a>( &'a mut self, packet: &'a [u8], ) -> NetflowPacketIterator<'a> ⓘ
Returns an iterator that yields NetflowPacket items without allocating a Vec. This is useful for processing large batches of packets without collecting all results in memory.
§Examples
use netflow_parser::{NetflowParser, NetflowPacket};
let v5_packet = [0, 5, 0, 1, 3, 0, 4, 0, 5, 0, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7,];
let mut parser = NetflowParser::default();
for result in parser.iter_packets(&v5_packet) {
match result {
Ok(NetflowPacket::V5(v5)) => println!("V5 packet: {:?}", v5.header.version),
Err(e) => println!("Error: {:?}", e),
_ => (),
}
}Sourcepub fn parse_bytes_as_netflow_common_flowsets(
&mut self,
packet: &[u8],
) -> (Vec<NetflowCommonFlowSet>, Option<NetflowError>)
pub fn parse_bytes_as_netflow_common_flowsets( &mut self, packet: &[u8], ) -> (Vec<NetflowCommonFlowSet>, Option<NetflowError>)
Takes a Netflow packet slice and returns parsed NetflowCommonFlowSets
along with any parse error.
Packets that fail as_netflow_common() conversion (e.g., V9/IPFIX data
flowsets without matching templates) are skipped. The returned error, if
any, comes from the underlying parse_bytes call.