pub struct NetflowParser {
pub v9_parser: V9Parser,
pub ipfix_parser: IPFixParser,
pub allowed_versions: HashSet<u16>,
pub max_error_sample_size: usize,
/* 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();Fields§
§v9_parser: V9Parser§ipfix_parser: IPFixParser§allowed_versions: HashSet<u16>§max_error_sample_size: usizeMaximum number of bytes to include in error samples to prevent memory exhaustion. Defaults to 256 bytes.
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 v9_cache_stats(&self) -> CacheStats
pub fn v9_cache_stats(&self) -> CacheStats
Gets statistics about the V9 template cache.
§Examples
use netflow_parser::NetflowParser;
let parser = NetflowParser::default();
let stats = parser.v9_cache_stats();
println!("V9 cache: {}/{} templates", stats.current_size, stats.max_size);Sourcepub fn ipfix_cache_stats(&self) -> CacheStats
pub fn ipfix_cache_stats(&self) -> CacheStats
Gets statistics about the IPFIX template cache.
§Examples
use netflow_parser::NetflowParser;
let parser = NetflowParser::default();
let stats = parser.ipfix_cache_stats();
println!("IPFIX cache: {}/{} templates", stats.current_size, stats.max_size);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 trigger_template_event(&self, event: TemplateEvent)
pub fn trigger_template_event(&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 parser = NetflowParser::default();
parser.trigger_template_event(TemplateEvent::Learned {
template_id: 256,
protocol: TemplateProtocol::V9,
});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>
pub fn parse_bytes_as_netflow_common_flowsets( &mut self, packet: &[u8], ) -> Vec<NetflowCommonFlowSet>
Takes a Netflow packet slice and returns a vector of Parsed NetflowCommonFlowSet