You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
-**Zero allocation**: Packets are yielded one-by-one without allocating a `Vec`
196
-
-**Memory efficient**: Ideal for processing large batches or continuous streams
197
-
-**Lazy evaluation**: Only parses packets as you consume them
198
-
-**Template caching preserved**: V9/IPFIX template state is maintained across iterations
199
-
-**Composable**: Works with standard Rust iterator methods (`.filter()`, `.map()`, `.take()`, etc.)
200
-
-**Buffer inspection**: Access unconsumed bytes via `.remaining()` and check completion with `.is_complete()`
201
-
202
-
### Iterator Examples
161
+
The iterator is zero-allocation, lazy, preserves V9/IPFIX template state, and composes with standard Rust iterator methods (`.filter()`, `.map()`, `.take()`, etc.). You can also inspect unconsumed bytes via `.remaining()` and check completion with `.is_complete()`.
203
162
204
163
```rust,ignore
205
164
// Count V5 packets without collecting
@@ -213,23 +172,6 @@ for result in parser.iter_packets(&buffer).take(10) {
213
172
// Handle packet
214
173
}
215
174
}
216
-
217
-
// Collect only if needed (equivalent to parse_bytes())
218
-
let packets: Vec<_> = parser.iter_packets(&buffer)
219
-
.filter_map(Result::ok)
220
-
.collect();
221
-
222
-
// Check unconsumed bytes (useful for mixed protocol streams)
223
-
let mut iter = parser.iter_packets(&buffer);
224
-
for result in &mut iter {
225
-
if let Ok(packet) = result {
226
-
// Process packet
227
-
}
228
-
}
229
-
if !iter.is_complete() {
230
-
let remaining = iter.remaining();
231
-
// Handle non-netflow data at end of buffer
232
-
}
233
175
```
234
176
235
177
## Parser Configuration
@@ -506,54 +448,6 @@ let parser = NetflowParser::builder()
506
448
507
449
This setting helps prevent memory exhaustion when processing malformed or malicious packets while still providing enough context for debugging.
508
450
509
-
#### Migration Guide
510
-
511
-
##### From 0.7.x to 0.8.0
512
-
513
-
**What changed:** Two major improvements to error handling:
514
-
515
-
1.**ParseResult** - `parse_bytes()` now returns `ParseResult` to preserve partial results on errors
516
-
2.**Error Handling** - `NetflowPacket::Error` variant removed, errors now use `Result`
517
-
518
-
**ParseResult (prevents data loss):**
519
-
520
-
```rust,ignore
521
-
// ❌ Old (0.7.x) - loses packets 1-4 if packet 5 errors
522
-
let packets = parser.parse_bytes(&data); // Returns Vec<NetflowPacket>
523
-
// Silent error: if parsing stopped at packet 5, you lost packets 1-4
524
-
525
-
// ✅ New (0.8.0) - keep packets 1-4 even if packet 5 errors
526
-
let result = parser.parse_bytes(&data); // Returns ParseResult
527
-
for packet in result.packets {
528
-
// Process successfully parsed packets 1-4
529
-
}
530
-
if let Some(e) = result.error {
531
-
eprintln!("Error at packet 5: {}", e); // But still got partial results!
532
-
}
533
-
```
534
-
535
-
**Error Handling (use Result instead of Error variant):**
536
-
537
-
```rust,ignore
538
-
// ❌ Old (0.7.x) - errors inline with packets
539
-
for packet in parser.parse_bytes(&data) {
540
-
match packet {
541
-
NetflowPacket::V5(v5) => { /* process */ }
542
-
NetflowPacket::Error(e) => { /* error */ }
543
-
_ => {}
544
-
}
545
-
}
546
-
547
-
// ✅ New (0.8.0) - use iter_packets() for Result-based errors
548
-
for result in parser.iter_packets(&data) {
549
-
match result {
550
-
Ok(NetflowPacket::V5(v5)) => { /* process */ }
551
-
Err(e) => { /* error */ }
552
-
_ => {}
553
-
}
554
-
}
555
-
```
556
-
557
451
### Custom Enterprise Fields (IPFIX)
558
452
559
453
IPFIX supports vendor-specific enterprise fields that extend the standard IANA field set. The library provides built-in support for several vendors (Cisco, VMWare, Netscaler, etc.), but you can also register your own custom enterprise fields:
@@ -643,116 +537,21 @@ When registering enterprise fields, you can use any of these built-in data types
643
537
644
538
See `examples/custom_enterprise_fields.rs` for a complete working example.
// For multi-source deployments, use AutoScopedParser instead:
688
-
// let scoped_parser = NetflowParser::builder()./* config */.try_multi_source().expect("valid config");
689
-
```
690
-
691
540
## Netflow Common
692
541
693
-
We have included a `NetflowCommon` and `NetflowCommonFlowSet` structure.
694
-
This will allow you to use common fields without unpacking values from specific versions.
695
-
If the packet flow does not have the matching field it will simply be left as `None`.
696
-
697
-
### NetflowCommon and NetflowCommonFlowSet Struct:
698
-
```rust
699
-
usestd::net::IpAddr;
700
-
usenetflow_parser::protocol::ProtocolTypes;
701
-
702
-
#[derive(Debug, Default)]
703
-
pubstructNetflowCommon {
704
-
pubversion:u16,
705
-
pubtimestamp:u32,
706
-
pubflowsets:Vec<NetflowCommonFlowSet>,
707
-
}
708
-
709
-
#[derive(Debug, Default, Clone)]
710
-
pubstructNetflowCommonFlowSet {
711
-
pubsrc_addr:Option<IpAddr>,
712
-
pubdst_addr:Option<IpAddr>,
713
-
pubsrc_port:Option<u16>,
714
-
pubdst_port:Option<u16>,
715
-
pubprotocol_number:Option<u8>,
716
-
pubprotocol_type:Option<ProtocolTypes>,
717
-
pubfirst_seen:Option<u64>,
718
-
publast_seen:Option<u64>,
719
-
pubsrc_mac:Option<String>,
720
-
pubdst_mac:Option<String>,
721
-
}
722
-
```
723
-
724
-
### Converting NetflowPacket to NetflowCommon
542
+
`NetflowCommon` and `NetflowCommonFlowSet` let you work with common fields (src/dst addr, ports, protocol, etc.) without unpacking version-specific structures. Fields not present in a given version are `None`.
725
543
726
544
```rust,ignore
727
545
use netflow_parser::{NetflowParser, NetflowPacket};
@@ -857,21 +651,11 @@ if let Some(NetflowPacket::V5(v5)) = result.packets.first() {
857
651
}
858
652
```
859
653
860
-
## V9/IPFIX Notes
861
-
862
-
Parse the data (`&[u8]`) like any other version. The parser (`NetflowParser`) caches parsed templates using LRU eviction, so you can send header/data flowset combos and it will use the cached templates. Templates are automatically cached and evicted when the cache limit is reached.
863
-
864
-
**Template Management:** For comprehensive information about template caching, introspection, multi-source deployments, and best practices, see the [Template Management Guide](#template-management-guide) section below.
865
-
866
-
**IPFIX Note:** We only parse sequence number and domain id, it is up to you if you wish to validate it.
867
-
868
-
**FlowSet Access:** To access templates flowset of a processed V9/IPFIX flowset you can find the `flowsets` attribute on the Parsed Record. In there you can find `Templates`, `Option Templates`, and `Data` Flowsets.
869
-
870
654
## Template Management Guide
871
655
872
-
### Overview
656
+
NetFlow V9 and IPFIX are template-based protocols where templates define the structure of flow records. The parser caches templates using LRU eviction, so you can send header/data flowset combos and it will use the cached templates. Access parsed templates, option templates, and data flowsets via the `flowsets` attribute on the parsed record.
873
657
874
-
NetFlow V9 and IPFIX are template-based protocols where templates define the structure of flow records. This library provides comprehensive template management features to handle various deployment scenarios.
658
+
**IPFIX Note:** We only parse sequence number and domain id; it is up to you if you wish to validate them.
875
659
876
660
### Template Cache Metrics
877
661
@@ -907,8 +691,7 @@ if let Some(hit_rate) = metrics.hit_rate() {
907
691
-**Hits**: Successful template lookups
908
692
-**Misses**: Failed template lookups (template not in cache)
909
693
-**Evictions**: Templates removed due to LRU policy when cache is full
910
-
-**Collisions**: Template ID reused with a **different definition** (same ID, different schema)
911
-
- Note: RFC-compliant template retransmissions (same ID, same definition) are NOT counted as collisions
694
+
-**Collisions**: Template ID reused with a **different definition** (same ID, different schema). RFC-compliant retransmissions (same ID, identical definition) are NOT counted as collisions. High collision rates suggest you need scoped parsing (see below).
912
695
-**Expired**: Templates removed due to TTL expiration
913
696
914
697
### Multi-Source Deployments (RFC-Compliant)
@@ -1006,57 +789,6 @@ let router_builder = NetflowParser::builder()
1006
789
let mut scoped = RouterScopedParser::<String>::try_with_builder(router_builder).expect("valid config");
1007
790
```
1008
791
1009
-
### Template Collision Detection
1010
-
1011
-
Monitor when template IDs are reused with different definitions:
0 commit comments