netring 0.29.0

High-performance zero-copy packet I/O for Linux (AF_PACKET TPACKET_V3 + AF_XDP)
Documentation
//! Typed BPF filter builder demo.
//!
//! Builds a filter that accepts:
//!   `(tcp dst port 443) or (udp dst port 53)`
//! and prints how many packets it would accept on each interface tick.
//!
//! Usage:
//!   cargo run --example bpf_filter -- [interface]
//!
//! Requires CAP_NET_RAW. Run on a host with traffic for visible output.

use netring::{BpfFilter, Capture};

fn main() -> Result<(), netring::Error> {
    env_logger::init();

    let iface = std::env::args().nth(1).unwrap_or_else(|| "lo".into());

    let filter = BpfFilter::builder()
        .tcp()
        .dst_port(443)
        .or(|b| b.udp().dst_port(53))
        .build()?;

    eprintln!(
        "Attaching filter on {iface} ({} cBPF instructions)",
        filter.len()
    );

    let mut cap = Capture::builder()
        .interface(&iface)
        .promiscuous(false)
        .ignore_outgoing(true)
        .bpf_filter(filter)
        .build()?;

    eprintln!("Capturing 50 matching packets... (Ctrl-C to stop early)");

    {
        let mut pkts = cap.packets();
        let mut seen = 0;
        while seen < 50 {
            let Some(pkt) = pkts.next_packet() else { break };
            println!(
                "[{}.{:09}] {} bytes (wire: {})",
                pkt.timestamp().sec,
                pkt.timestamp().nsec,
                pkt.len(),
                pkt.original_len(),
            );
            seen += 1;
        }
    }

    let stats = cap.stats()?;
    eprintln!("{stats}");
    Ok(())
}