-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Begin support for supporting multiple DLTs
Wraps existing traits in a macro, creating one for each DLT. Ideally this would be done using generics, however after multiple attempts to get this working I have not succeeded.
- Loading branch information
Showing
6 changed files
with
91 additions
and
83 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
// Copyright (c) 2014, 2015 Robert Clipsham <[email protected]> | ||
// Copyright (c) 2014-2016 Robert Clipsham <[email protected]> | ||
// | ||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | ||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
|
@@ -19,7 +19,8 @@ use std::sync::Arc; | |
use bindings::bpf; | ||
use packet::Packet; | ||
use packet::ethernet::{EthernetPacket, MutableEthernetPacket}; | ||
use datalink::{DataLinkChannelIterator, DataLinkChannelType, DataLinkReceiver, DataLinkSender}; | ||
use datalink::{EthernetDataLinkChannelIterator, DataLinkChannelType, EthernetDataLinkReceiver, | ||
EthernetDataLinkSender}; | ||
use datalink::DataLinkChannelType::{Layer2, Layer3}; | ||
use internal; | ||
use util::NetworkInterface; | ||
|
@@ -30,7 +31,7 @@ pub fn datalink_channel(network_interface: &NetworkInterface, | |
write_buffer_size: usize, | ||
read_buffer_size: usize, | ||
channel_type: DataLinkChannelType) | ||
-> io::Result<(Box<DataLinkSender>, Box<DataLinkReceiver>)> { | ||
-> io::Result<(Box<EthernetDataLinkSender>, Box<EthernetDataLinkReceiver>)> { | ||
#[cfg(target_os = "freebsd")] | ||
fn get_fd() -> libc::c_int { | ||
unsafe { | ||
|
@@ -175,7 +176,7 @@ pub struct DataLinkSenderImpl { | |
header_size: usize, | ||
} | ||
|
||
impl DataLinkSender for DataLinkSenderImpl { | ||
impl EthernetDataLinkSender for DataLinkSenderImpl { | ||
#[inline] | ||
fn build_and_send(&mut self, | ||
num_packets: usize, | ||
|
@@ -234,8 +235,8 @@ pub struct DataLinkReceiverImpl { | |
header_size: usize, | ||
} | ||
|
||
impl DataLinkReceiver for DataLinkReceiverImpl { | ||
fn iter<'a>(&'a mut self) -> Box<DataLinkChannelIterator + 'a> { | ||
impl EthernetDataLinkReceiver for DataLinkReceiverImpl { | ||
fn iter<'a>(&'a mut self) -> Box<EthernetDataLinkChannelIterator + 'a> { | ||
let buflen = self.read_buffer.len(); | ||
Box::new(DataLinkChannelIteratorImpl { | ||
pc: self, | ||
|
@@ -250,7 +251,7 @@ pub struct DataLinkChannelIteratorImpl<'a> { | |
packets: VecDeque<(usize, usize)>, | ||
} | ||
|
||
impl<'a> DataLinkChannelIterator<'a> for DataLinkChannelIteratorImpl<'a> { | ||
impl<'a> EthernetDataLinkChannelIterator<'a> for DataLinkChannelIteratorImpl<'a> { | ||
fn next(&mut self) -> io::Result<EthernetPacket> { | ||
if self.packets.is_empty() { | ||
let buflen = match unsafe { | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
// Copyright (c) 2014, 2015 Robert Clipsham <[email protected]> | ||
// Copyright (c) 2014-2016 Robert Clipsham <[email protected]> | ||
// | ||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | ||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
|
@@ -15,7 +15,8 @@ use std::mem; | |
use std::sync::Arc; | ||
|
||
use bindings::linux; | ||
use datalink::{DataLinkChannelIterator, DataLinkChannelType, DataLinkReceiver, DataLinkSender}; | ||
use datalink::{EthernetDataLinkChannelIterator, DataLinkChannelType, EthernetDataLinkReceiver, | ||
EthernetDataLinkSender}; | ||
use datalink::DataLinkChannelType::{Layer2, Layer3}; | ||
use internal; | ||
use packet::Packet; | ||
|
@@ -44,7 +45,7 @@ pub fn datalink_channel(network_interface: &NetworkInterface, | |
write_buffer_size: usize, | ||
read_buffer_size: usize, | ||
channel_type: DataLinkChannelType) | ||
-> io::Result<(Box<DataLinkSender>, Box<DataLinkReceiver>)> { | ||
-> io::Result<(Box<EthernetDataLinkSender>, Box<EthernetDataLinkReceiver>)> { | ||
let eth_p_all = 0x0003; | ||
let (typ, proto) = match channel_type { | ||
Layer2 => (libc::SOCK_RAW, eth_p_all), | ||
|
@@ -112,7 +113,7 @@ pub struct DataLinkSenderImpl { | |
send_addr_len: usize, | ||
} | ||
|
||
impl DataLinkSender for DataLinkSenderImpl { | ||
impl EthernetDataLinkSender for DataLinkSenderImpl { | ||
// FIXME Layer 3 | ||
#[inline] | ||
fn build_and_send(&mut self, | ||
|
@@ -167,9 +168,9 @@ pub struct DataLinkReceiverImpl { | |
_channel_type: DataLinkChannelType, | ||
} | ||
|
||
impl DataLinkReceiver for DataLinkReceiverImpl { | ||
impl EthernetDataLinkReceiver for DataLinkReceiverImpl { | ||
// FIXME Layer 3 | ||
fn iter<'a>(&'a mut self) -> Box<DataLinkChannelIterator + 'a> { | ||
fn iter<'a>(&'a mut self) -> Box<EthernetDataLinkChannelIterator + 'a> { | ||
Box::new(DataLinkChannelIteratorImpl { pc: self }) | ||
} | ||
} | ||
|
@@ -178,7 +179,7 @@ pub struct DataLinkChannelIteratorImpl<'a> { | |
pc: &'a mut DataLinkReceiverImpl, | ||
} | ||
|
||
impl<'a> DataLinkChannelIterator<'a> for DataLinkChannelIteratorImpl<'a> { | ||
impl<'a> EthernetDataLinkChannelIterator<'a> for DataLinkChannelIteratorImpl<'a> { | ||
fn next(&mut self) -> io::Result<EthernetPacket> { | ||
let mut caddr: libc::sockaddr_storage = unsafe { mem::zeroed() }; | ||
let res = internal::recv_from(self.pc.socket.fd, &mut self.pc.read_buffer, &mut caddr); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
// Copyright (c) 2014, 2015 Robert Clipsham <[email protected]> | ||
// Copyright (c) 2014-2016 Robert Clipsham <[email protected]> | ||
// | ||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | ||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
|
@@ -64,54 +64,65 @@ pub fn datalink_channel(network_interface: &NetworkInterface, | |
write_buffer_size: usize, | ||
read_buffer_size: usize, | ||
channel_type: DataLinkChannelType) | ||
-> io::Result<(Box<DataLinkSender>, Box<DataLinkReceiver>)> { | ||
-> io::Result<(Box<EthernetDataLinkSender>, Box<EthernetDataLinkReceiver>)> { | ||
backend::datalink_channel(network_interface, | ||
write_buffer_size, | ||
read_buffer_size, | ||
channel_type) | ||
} | ||
|
||
/// Structure for sending packets at the data link layer. Should be constructed using | ||
/// datalink_channel(). | ||
pub trait DataLinkSender : Send { | ||
/// Create and send a number of packets | ||
/// | ||
/// This will call `func` `num_packets` times. The function will be provided with a mutable | ||
/// packet to manipulate, which will then be sent. This allows packets to be built in-place, | ||
/// avoiding the copy required for `send`. If there is not sufficient capacity in the buffer, | ||
/// None will be returned. | ||
#[inline] | ||
fn build_and_send(&mut self, | ||
num_packets: usize, | ||
packet_size: usize, | ||
func: &mut FnMut(MutableEthernetPacket)) | ||
-> Option<io::Result<()>>; | ||
macro_rules! dls { | ||
($name:ident, $mut_packet:ident, $packet:ident) => { | ||
/// Trait to enable sending $packet packets | ||
pub trait $name : Send { | ||
/// Create and send a number of packets | ||
/// | ||
/// This will call `func` `num_packets` times. The function will be provided with a | ||
/// mutable packet to manipulate, which will then be sent. This allows packets to be | ||
/// built in-place, avoiding the copy required for `send`. If there is not sufficient | ||
/// capacity in the buffer, None will be returned. | ||
#[inline] | ||
fn build_and_send(&mut self, | ||
num_packets: usize, | ||
packet_size: usize, | ||
func: &mut FnMut($mut_packet)) | ||
-> Option<io::Result<()>>; | ||
|
||
/// Send a packet | ||
/// | ||
/// This may require an additional copy compared to `build_and_send`, depending on the | ||
/// operating system being used. The second parameter is currently ignored, however `None` | ||
/// should be passed. | ||
#[inline] | ||
fn send_to(&mut self, | ||
packet: &EthernetPacket, | ||
dst: Option<NetworkInterface>) | ||
-> Option<io::Result<()>>; | ||
/// Send a packet | ||
/// | ||
/// This may require an additional copy compared to `build_and_send`, depending on the | ||
/// operating system being used. The second parameter is currently ignored, however | ||
/// `None` should be passed. | ||
#[inline] | ||
fn send_to(&mut self, | ||
packet: &$packet, | ||
dst: Option<NetworkInterface>) | ||
-> Option<io::Result<()>>; | ||
} | ||
} | ||
} | ||
|
||
/// Structure for receiving packets at the data link layer. Should be constructed using | ||
/// datalink_channel(). | ||
pub trait DataLinkReceiver : Send { | ||
/// Returns an iterator over `EthernetPacket`s. | ||
/// | ||
/// This will likely be removed once other layer two types are supported. | ||
#[inline] | ||
fn iter<'a>(&'a mut self) -> Box<DataLinkChannelIterator + 'a>; | ||
} | ||
dls!(EthernetDataLinkSender, MutableEthernetPacket, EthernetPacket); | ||
|
||
macro_rules! dlr { | ||
($recv_name:ident, $iter_name:ident, $packet:ident) => { | ||
/// Structure for receiving packets at the data link layer. Should be constructed using | ||
/// datalink_channel(). | ||
pub trait $recv_name : Send { | ||
/// Returns an iterator over `EthernetPacket`s. | ||
/// | ||
/// This will likely be removed once other layer two types are supported. | ||
#[inline] | ||
fn iter<'a>(&'a mut self) -> Box<$iter_name + 'a>; | ||
} | ||
|
||
/// An iterator over data link layer packets | ||
pub trait DataLinkChannelIterator<'a> { | ||
/// Get the next EthernetPacket in the channel | ||
#[inline] | ||
fn next(&mut self) -> io::Result<EthernetPacket>; | ||
/// An iterator over data link layer packets | ||
pub trait $iter_name<'a> { | ||
/// Get the next EthernetPacket in the channel | ||
#[inline] | ||
fn next(&mut self) -> io::Result<$packet>; | ||
} | ||
} | ||
} | ||
|
||
dlr!(EthernetDataLinkReceiver, EthernetDataLinkChannelIterator, EthernetPacket); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
// Copyright (c) 2015, 2015 Robert Clipsham <[email protected]> | ||
// Copyright (c) 2015-2016 Robert Clipsham <[email protected]> | ||
// | ||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | ||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
|
@@ -21,12 +21,12 @@ use std::fs::File; | |
use std::io; | ||
use std::io::Read; | ||
use std::mem; | ||
use std::num; | ||
use std::ptr; | ||
use std::raw; | ||
use std::slice; | ||
use std::sync::Arc; | ||
|
||
use datalink::{DataLinkChannelIterator, DataLinkChannelType, DataLinkReceiver, DataLinkSender}; | ||
use datalink::{EthernetDataLinkChannelIterator, DataLinkChannelType, EthernetDataLinkReceiver, | ||
EthernetDataLinkSender}; | ||
use packet::Packet; | ||
use packet::ethernet::{EthernetPacket, MutableEthernetPacket}; | ||
use util::NetworkInterface; | ||
|
@@ -63,7 +63,7 @@ unsafe impl Sync for NmDesc {} | |
|
||
impl NmDesc { | ||
fn new(iface: &NetworkInterface) -> io::Result<NmDesc> { | ||
let ifname = CString::new(("netmap:".to_string() + &iface.name[..]).as_bytes()); | ||
let ifname = CString::new(("netmap:".to_owned() + &iface.name[..]).as_bytes()); | ||
let desc = unsafe { nm_open(ifname.unwrap().as_ptr(), ptr::null(), 0, ptr::null()) }; | ||
|
||
if desc.is_null() { | ||
|
@@ -95,7 +95,7 @@ pub fn datalink_channel(network_interface: &NetworkInterface, | |
_write_buffer_size: usize, | ||
_read_buffer_size: usize, | ||
_channel_type: DataLinkChannelType) | ||
-> io::Result<(Box<DataLinkSender>, Box<DataLinkReceiver>)> { | ||
-> io::Result<(Box<EthernetDataLinkSender>, Box<EthernetDataLinkReceiver>)> { | ||
// FIXME probably want one for each of send/recv | ||
let desc = NmDesc::new(network_interface); | ||
match desc { | ||
|
@@ -113,7 +113,7 @@ pub struct DataLinkSenderImpl { | |
desc: Arc<NmDesc>, | ||
} | ||
|
||
impl DataLinkSender for DataLinkSenderImpl { | ||
impl EthernetDataLinkSender for DataLinkSenderImpl { | ||
#[inline] | ||
fn build_and_send(&mut self, | ||
num_packets: usize, | ||
|
@@ -138,11 +138,8 @@ impl DataLinkSender for DataLinkSenderImpl { | |
let i = (*ring).cur; | ||
let slot_ptr: *mut netmap_slot = mem::transmute(&mut (*ring).slot); | ||
let buf = NETMAP_BUF(ring, (*slot_ptr.offset(i as isize)).buf_idx as isize); | ||
let slice = raw::Slice { | ||
data: buf, | ||
len: packet_size, | ||
}; | ||
let meh = MutableEthernetPacket::new(mem::transmute(slice)).unwrap(); | ||
let slice = slice::from_raw_parts_mut(buf as *mut u8, packet_size); | ||
let meh = MutableEthernetPacket::new(slice).unwrap(); | ||
(*slot_ptr.offset(i as isize)).len = packet_size as u16; | ||
func(meh); | ||
let next = nm_ring_next(ring, i); | ||
|
@@ -174,9 +171,9 @@ pub struct DataLinkReceiverImpl { | |
desc: Arc<NmDesc>, | ||
} | ||
|
||
impl DataLinkReceiver for DataLinkReceiverImpl { | ||
impl EthernetDataLinkReceiver for DataLinkReceiverImpl { | ||
// FIXME Layer 3 | ||
fn iter<'a>(&'a mut self) -> Box<DataLinkChannelIterator + 'a> { | ||
fn iter<'a>(&'a mut self) -> Box<EthernetDataLinkChannelIterator + 'a> { | ||
Box::new(DataLinkChannelIteratorImpl { pc: self }) | ||
} | ||
} | ||
|
@@ -185,8 +182,8 @@ pub struct DataLinkChannelIteratorImpl<'a> { | |
pc: &'a mut DataLinkReceiverImpl, | ||
} | ||
|
||
impl<'a> DataLinkChannelIterator<'a> for DataLinkChannelIteratorImpl<'a> { | ||
fn next<'c>(&'c mut self) -> io::Result<EthernetPacket<'c>> { | ||
impl<'a> EthernetDataLinkChannelIterator<'a> for DataLinkChannelIteratorImpl<'a> { | ||
fn next(&mut self) -> io::Result<EthernetPacket> { | ||
let desc = self.pc.desc.desc; | ||
let mut h: nm_pkthdr = unsafe { mem::uninitialized() }; | ||
let mut buf = unsafe { nm_nextpkt(desc, &mut h) }; | ||
|
@@ -202,10 +199,7 @@ impl<'a> DataLinkChannelIterator<'a> for DataLinkChannelIteratorImpl<'a> { | |
buf = unsafe { nm_nextpkt(desc, &mut h) }; | ||
} | ||
Ok(EthernetPacket::new(unsafe { | ||
mem::transmute(raw::Slice { | ||
data: buf, | ||
len: h.len as usize, | ||
}) | ||
slice::from_raw_parts(buf, h.len as usize) | ||
}).unwrap()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
// Copyright (c) 2014, 2015 Robert Clipsham <[email protected]> | ||
// Copyright (c) 2014-2016 Robert Clipsham <[email protected]> | ||
// | ||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | ||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
|
@@ -17,7 +17,8 @@ use std::slice; | |
use std::sync::Arc; | ||
|
||
use bindings::{bpf, winpcap}; | ||
use datalink::{DataLinkChannelIterator, DataLinkChannelType, DataLinkReceiver, DataLinkSender}; | ||
use datalink::{EthernetDataLinkChannelIterator, DataLinkChannelType, EthernetDataLinkReceiver, | ||
EthernetDataLinkSender}; | ||
use packet::Packet; | ||
use packet::ethernet::{EthernetPacket, MutableEthernetPacket}; | ||
use util::NetworkInterface; | ||
|
@@ -51,7 +52,7 @@ pub fn datalink_channel(network_interface: &NetworkInterface, | |
read_buffer_size: usize, | ||
write_buffer_size: usize, | ||
_channel_type: DataLinkChannelType) | ||
-> io::Result<(Box<DataLinkSender>, Box<DataLinkReceiver>)> { | ||
-> io::Result<(Box<EthernetDataLinkSender>, Box<EthernetDataLinkReceiver>)> { | ||
let mut read_buffer = Vec::new(); | ||
read_buffer.resize(read_buffer_size, 0u8); | ||
|
||
|
@@ -137,7 +138,7 @@ pub struct DataLinkSenderImpl { | |
packet: WinPcapPacket, | ||
} | ||
|
||
impl DataLinkSender for DataLinkSenderImpl { | ||
impl EthernetDataLinkSender for DataLinkSenderImpl { | ||
#[inline] | ||
fn build_and_send(&mut self, | ||
num_packets: usize, | ||
|
@@ -203,8 +204,8 @@ pub struct DataLinkReceiverImpl { | |
packet: WinPcapPacket, | ||
} | ||
|
||
impl DataLinkReceiver for DataLinkReceiverImpl { | ||
fn iter<'a>(&'a mut self) -> Box<DataLinkChannelIterator + 'a> { | ||
impl EthernetDataLinkReceiver for DataLinkReceiverImpl { | ||
fn iter<'a>(&'a mut self) -> Box<EthernetDataLinkChannelIterator + 'a> { | ||
let buflen = unsafe { (*self.packet.packet).Length } as usize; | ||
Box::new(DataLinkChannelIteratorImpl { | ||
pc: self, | ||
|
@@ -222,7 +223,7 @@ pub struct DataLinkChannelIteratorImpl<'a> { | |
packets: VecDeque<(usize, usize)>, | ||
} | ||
|
||
impl<'a> DataLinkChannelIterator<'a> for DataLinkChannelIteratorImpl<'a> { | ||
impl<'a> EthernetDataLinkChannelIterator<'a> for DataLinkChannelIteratorImpl<'a> { | ||
fn next(&mut self) -> io::Result<EthernetPacket> { | ||
// NOTE Most of the logic here is identical to FreeBSD/OS X | ||
if self.packets.is_empty() { | ||
|