use std::error::Error;
use std::os::unix::io::AsRawFd;
use std::time::Duration;
use netmap_rs::prelude::*;
use polling::{Event, Events, Poller};
const PIPE_NAME_POLL: &str = "netmap:pipe{poll456}";
const NUM_PACKETS_TO_SEND: usize = 5;
fn main() -> Result<(), Box<dyn Error>> {
println!("Netmap Polling Example using '{}'", PIPE_NAME_POLL);
let pipe_a = NetmapBuilder::new(PIPE_NAME_POLL)
.num_tx_rings(1)
.num_rx_rings(1)
.build()
.expect("Failed to open pipe endpoint A");
let pipe_b = NetmapBuilder::new(PIPE_NAME_POLL)
.num_tx_rings(1)
.num_rx_rings(1)
.build()
.expect("Failed to open pipe endpoint B");
let mut tx_a = pipe_a.tx_ring(0).expect("Pipe A: Failed to get TX ring");
let mut rx_b = pipe_b.rx_ring(0).expect("Pipe B: Failed to get RX ring");
let fd_b = pipe_b.as_raw_fd();
let fd_a = pipe_a.as_raw_fd();
let poller = Poller::new().expect("Failed to create Poller");
unsafe {
poller
.add(fd_b, Event::readable(0))
.expect("Failed to register fd_b with Poller");
poller
.add(fd_a, Event::writable(1))
.expect("Failed to register fd_a with Poller");
}
let mut packets_sent = 0;
let mut packets_received = 0;
let mut main_loop_iterations = 0;
let mut events = Events::new();
println!(
"Starting event loop. Will send {} packets.",
NUM_PACKETS_TO_SEND
);
println!(
"Monitoring pipe_b's fd ({}) for readable events (packets from pipe_a).",
fd_b
);
loop {
main_loop_iterations += 1;
events.clear();
if packets_sent < NUM_PACKETS_TO_SEND {
match poller.wait(&mut events, Some(Duration::from_millis(0))) {
Ok(_) => {
let mut can_write_to_a = false;
for ev in events.iter() {
if ev.key == 1 && ev.writable {
can_write_to_a = true;
break;
}
}
if can_write_to_a || tx_a.has_free_slots() {
let mut payload = format!("Packet #{}", packets_sent).into_bytes();
payload.resize(60, 0);
match tx_a.send(&payload) {
Ok(_) => {
tx_a.sync(); println!(
"[Sender A] Sent packet #{} ({} bytes)",
packets_sent,
payload.len()
);
packets_sent += 1;
}
Err(netmap_rs::Error::InsufficientSpace) => {
println!("[Sender A] TX ring full, will try later.");
}
Err(e) => {
eprintln!("[Sender A] Error sending packet: {:?}", e);
break; }
}
}
}
Err(e) if e.kind() == std::io::ErrorKind::TimedOut => { }
Err(e) => {
eprintln!("[Sender A] Polling error for fd_a: {:?}", e);
break;
}
}
}
match poller.wait(&mut events, Some(Duration::from_millis(100))) {
Ok(_) => {
for ev in events.iter() {
if ev.key == 0 && ev.readable {
rx_b.sync();
while let Some(frame) = rx_b.recv() {
if frame.is_empty() {
continue;
}
packets_received += 1;
let len = frame
.payload()
.iter()
.position(|&x| x == 0)
.unwrap_or(frame.len());
println!(
"[Receiver B] Received packet #{} ({} bytes): {:?}",
packets_received,
frame.len(),
String::from_utf8_lossy(&frame.payload()[..len])
);
}
}
}
}
Err(e) if e.kind() == std::io::ErrorKind::TimedOut => {
}
Err(e) => {
eprintln!("[Event Loop] Polling error: {:?}", e);
break; }
}
if packets_received >= NUM_PACKETS_TO_SEND && packets_sent >= NUM_PACKETS_TO_SEND {
println!(
"All {} packets sent and received. Exiting.",
NUM_PACKETS_TO_SEND
);
break;
}
if main_loop_iterations > (NUM_PACKETS_TO_SEND * 10) + 20
&& (packets_received < NUM_PACKETS_TO_SEND)
{
println!(
"Potential stall or slow processing, exiting. Sent: {}, Received: {}",
packets_sent, packets_received
);
break;
}
}
println!(
"Example finished. Total iterations: {}",
main_loop_iterations
);
Ok(())
}