polachok / netmap-rs

Higher level interface to netmap
3 stars 2 forks source link

netmap-rs

Higher level interface to netmap

This is a work in progress. And it's totally unsafe.

Be sure to turn all NIC offloads off before testing - netmap doesn't use NIC offloads.

Usage example

extern crate libc;
extern crate netmap;

use std::env;
use netmap::*;

fn move_packets(src: &mut netmap::NetmapDescriptor, dst: &mut netmap::NetmapDescriptor) {
    {
        let mut rx_slots = src.rx_iter().flat_map(|rx_ring| rx_ring.iter());
        'rings: for tx_ring in dst.tx_iter() {
            let mut tx_slot_iter = tx_ring.iter_mut();
            'slots: loop {
                match tx_slot_iter.next() {
                    None => break 'slots,
                    Some(tx_slot_buf) => {
                        match rx_slots.next() {
                            None => {
                                // "End of RX queue.
                                tx_slot_iter.give_back();
                                break 'rings;
                            }
                            Some(rx_slot_buf) => {
                                let tgt_buf =
                                    &mut tx_slot_buf.1[0..rx_slot_buf.0.get_len() as usize];
                                tgt_buf.copy_from_slice(rx_slot_buf.1);
                                tx_slot_buf.0.set_len(rx_slot_buf.0.get_len());
                            }
                        }
                    }
                }
            }
        }
    };
    // Tell the kernel it can use the slots we've consumed.
    for ring in src.rx_iter() {
        ring.head_from_cur();
    }
    // Tell the kernel it can send the slots we've populated.
    for ring in dst.tx_iter() {
        ring.head_from_cur();
    }
}

fn main() {
    let iface = env::args().nth(1).expect("expected interface name as argument (e.g. eth0)");
    let mut nm_wire = NetmapDescriptor::new(&iface).expect("can't open netmap for interface");
    let mut nm_host = NetmapDescriptor::new(&(iface + "^")).expect("can't open netmap host interface");
    let mut pollfds: Vec<libc::pollfd> = Vec::with_capacity(2);
    pollfds.push(libc::pollfd{ nm_wire.get_fd(), events: 0, revents: 0 });
    pollfds.push(libc::pollfd{ nm_host.get_fd(), events: 0, revents: 0 });
    loop {
        for pollfd in pollfdss.iter_mut() {
        pollfd.events = libc::POLLIN;
        pollfd.revents = 0;
    }
    if let Some(first) = pollfds.first_mut() {
        match unsafe {libc::poll(first as *mut libc::pollfd, 2, 1000)} {
          x if x < 0 => panic!("poll failure"),
          x if x == 0 => continue,
          _ => ()
        }
    } else {
      panic!("no fd vec?")
    }
        // A netmap poll error can mean the rings get reset: loop again.
        for pollfd in pollfds.iter() {
            if pollfd.revents & libc::POLLERR == libc::POLLERR {
                continue;
            }
        }
    move_packets(&mut nm_host, &mut nm_wire);
    move_packets(&mut nm_wire, &mut nm_host);
    }
}