use etherparse::{SlicedPacket, TransportSlice};
use netflow_parser::NetflowParser;
use pcap_parser::traits::PcapReaderIterator;
use pcap_parser::{LegacyPcapReader, PcapBlockOwned, PcapError};
use std::fs::File;
const PCAP_PATH: &str = "pcaps/IPFIX.pcap";
#[test]
fn test_pcap_file_parsing() {
let file = File::open(PCAP_PATH).expect("Failed to open PCAP file");
let mut reader = LegacyPcapReader::new(65536, file).expect("Failed to create PCAP reader");
let mut parser = NetflowParser::default();
let mut packet_count = 0;
let mut netflow_packets = 0;
loop {
match reader.next() {
Ok((offset, block)) => {
match block {
PcapBlockOwned::LegacyHeader(_) => (),
PcapBlockOwned::Legacy(pcap_block) => {
packet_count += 1;
if let Ok(eth) = SlicedPacket::from_ethernet(pcap_block.data)
&& let Some(transport) = eth.transport
&& let TransportSlice::Udp(udp) = transport
{
let parsed = parser.parse_bytes(udp.payload());
netflow_packets += parsed.packets.len();
}
}
PcapBlockOwned::NG(_) => {}
}
reader.consume(offset);
}
Err(PcapError::Eof) => break,
Err(PcapError::Incomplete(_)) => {
reader.refill().expect("Failed to refill buffer");
}
Err(_) => break,
}
}
assert_eq!(packet_count, 6666, "Expected exact PCAP packet count");
assert_eq!(netflow_packets, 6666, "Expected exact NetFlow packet count");
}
#[test]
fn test_pcap_ipfix_parsing() {
let file = File::open(PCAP_PATH).expect("Failed to open PCAP file");
let mut reader = LegacyPcapReader::new(65536, file).expect("Failed to create PCAP reader");
let mut parser = NetflowParser::default();
let mut ipfix_count = 0;
loop {
match reader.next() {
Ok((offset, block)) => {
match block {
PcapBlockOwned::LegacyHeader(_) => (),
PcapBlockOwned::Legacy(pcap_block) => {
if let Ok(eth) = SlicedPacket::from_ethernet(pcap_block.data)
&& let Some(transport) = eth.transport
&& let TransportSlice::Udp(udp) = transport
{
let parsed = parser.parse_bytes(udp.payload());
for pkt in parsed.packets {
if pkt.is_ipfix() {
ipfix_count += 1;
}
}
}
}
PcapBlockOwned::NG(_) => {}
}
reader.consume(offset);
}
Err(PcapError::Eof) => break,
Err(PcapError::Incomplete(_)) => {
reader.refill().expect("Failed to refill buffer");
}
Err(_) => break,
}
}
assert_eq!(
ipfix_count, 6666,
"Expected exact IPFIX packet count from PCAP"
);
}
#[test]
fn test_pcap_template_caching() {
let file = File::open(PCAP_PATH).expect("Failed to open PCAP file");
let mut reader = LegacyPcapReader::new(65536, file).expect("Failed to create PCAP reader");
let mut parser = NetflowParser::default();
loop {
match reader.next() {
Ok((offset, block)) => {
match block {
PcapBlockOwned::LegacyHeader(_) => (),
PcapBlockOwned::Legacy(pcap_block) => {
if let Ok(eth) = SlicedPacket::from_ethernet(pcap_block.data)
&& let Some(transport) = eth.transport
&& let TransportSlice::Udp(udp) = transport
{
let _ = parser.parse_bytes(udp.payload());
}
}
PcapBlockOwned::NG(_) => {}
}
reader.consume(offset);
}
Err(PcapError::Eof) => break,
Err(PcapError::Incomplete(_)) => {
reader.refill().expect("Failed to refill buffer");
}
Err(_) => break,
}
}
let ipfix_info = parser.ipfix_cache_info();
let template_ids = parser.ipfix_template_ids();
assert_eq!(
ipfix_info.current_size, 17,
"Expected exact IPFIX template cache size"
);
assert_eq!(
template_ids,
vec![
256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270
],
"Expected exact cached template IDs"
);
}
#[test]
fn test_pcap_cache_metrics() {
let file = File::open(PCAP_PATH).expect("Failed to open PCAP file");
let mut reader = LegacyPcapReader::new(65536, file).expect("Failed to create PCAP reader");
let mut parser = NetflowParser::default();
loop {
match reader.next() {
Ok((offset, block)) => {
match block {
PcapBlockOwned::LegacyHeader(_) => (),
PcapBlockOwned::Legacy(pcap_block) => {
if let Ok(eth) = SlicedPacket::from_ethernet(pcap_block.data)
&& let Some(transport) = eth.transport
&& let TransportSlice::Udp(udp) = transport
{
let _ = parser.parse_bytes(udp.payload());
}
}
PcapBlockOwned::NG(_) => {}
}
reader.consume(offset);
}
Err(PcapError::Eof) => break,
Err(PcapError::Incomplete(_)) => {
reader.refill().expect("Failed to refill buffer");
}
Err(_) => break,
}
}
let ipfix_info = parser.ipfix_cache_info();
let metrics = &ipfix_info.metrics;
assert_eq!(
ipfix_info.current_size, 17,
"Expected exact IPFIX template cache size"
);
assert_eq!(metrics.hits, 5754, "Expected exact cache hit count");
assert_eq!(metrics.misses, 901, "Expected exact cache miss count");
}
#[test]
fn test_pcap_iterator_api() {
let file = File::open(PCAP_PATH).expect("Failed to open PCAP file");
let mut reader = LegacyPcapReader::new(65536, file).expect("Failed to create PCAP reader");
let mut parser = NetflowParser::default();
let mut netflow_count = 0;
loop {
match reader.next() {
Ok((offset, block)) => {
match block {
PcapBlockOwned::LegacyHeader(_) => (),
PcapBlockOwned::Legacy(pcap_block) => {
if let Ok(eth) = SlicedPacket::from_ethernet(pcap_block.data)
&& let Some(transport) = eth.transport
&& let TransportSlice::Udp(udp) = transport
{
for pkt in parser.iter_packets(udp.payload()) {
if pkt.is_ok() {
netflow_count += 1;
}
}
}
}
PcapBlockOwned::NG(_) => {}
}
reader.consume(offset);
}
Err(PcapError::Eof) => break,
Err(PcapError::Incomplete(_)) => {
reader.refill().expect("Failed to refill buffer");
}
Err(_) => break,
}
}
assert_eq!(
netflow_count, 6666,
"Expected exact NetFlow packet count via iterator API"
);
}