Implement loopback interfaces.

This also adds a default implementation of Device::limits.
This commit is contained in:
whitequark 2017-07-14 01:05:05 +00:00
parent 5556f09351
commit 63ab7d4e7a
3 changed files with 84 additions and 2 deletions

View File

@ -1,4 +1,5 @@
#![cfg_attr(feature = "alloc", feature(alloc))]
#![cfg_attr(feature = "collections", feature(collections))]
#![no_std]
//! The _smoltcp_ library is built in a layered structure, with the layers corresponding
@ -76,6 +77,9 @@ extern crate std;
extern crate libc;
#[cfg(feature = "alloc")]
extern crate alloc;
#[allow(deprecated)]
#[cfg(feature = "collections")]
extern crate collections;
#[cfg(any(test, feature = "log"))]
#[macro_use(trace, log, log_enabled)]
extern crate log;

72
src/phy/loopback.rs Normal file
View File

@ -0,0 +1,72 @@
use core::mem::swap;
use core::cell::RefCell;
#[cfg(feature = "std")]
use std::rc::Rc;
#[cfg(feature = "alloc")]
use alloc::rc::Rc;
#[cfg(feature = "std")]
use std::vec::Vec;
#[cfg(feature = "std")]
use std::collections::VecDeque;
#[cfg(feature = "collections")]
use collections::{Vec, VecDeque};
use Error;
use super::Device;
/// A loopback interface.
#[derive(Debug)]
pub struct LoopbackInterface(Rc<RefCell<VecDeque<Vec<u8>>>>);
impl LoopbackInterface {
/// Creates a loopback interface.
///
/// Every packet transmitted through this interface will be received through it
/// in FIFO order.
pub fn new() -> LoopbackInterface {
LoopbackInterface(Rc::new(RefCell::new(VecDeque::new())))
}
}
impl Device for LoopbackInterface {
type RxBuffer = Vec<u8>;
type TxBuffer = TxBuffer;
fn receive(&mut self) -> Result<Self::RxBuffer, Error> {
match self.0.borrow_mut().pop_front() {
Some(packet) => Ok(packet),
None => Err(Error::Exhausted)
}
}
fn transmit(&mut self, length: usize) -> Result<Self::TxBuffer, Error> {
let mut buffer = Vec::new();
buffer.resize(length, 0);
Ok(TxBuffer {
queue: self.0.clone(),
buffer: buffer
})
}
}
#[doc(hidden)]
pub struct TxBuffer {
queue: Rc<RefCell<VecDeque<Vec<u8>>>>,
buffer: Vec<u8>
}
impl AsRef<[u8]> for TxBuffer {
fn as_ref(&self) -> &[u8] { self.buffer.as_ref() }
}
impl AsMut<[u8]> for TxBuffer {
fn as_mut(&mut self) -> &mut [u8] { self.buffer.as_mut() }
}
impl Drop for TxBuffer {
fn drop(&mut self) {
let mut buffer = Vec::new();
swap(&mut buffer, &mut self.buffer);
self.queue.borrow_mut().push_back(buffer)
}
}

View File

@ -103,11 +103,13 @@ impl Drop for EthernetTxBuffer {
use Error;
#[cfg(any(feature = "raw_socket", feature="tap_interface"))]
#[cfg(any(feature = "raw_socket", feature = "tap_interface"))]
mod sys;
mod tracer;
mod fault_injector;
#[cfg(any(feature = "std", feature = "collections"))]
mod loopback;
#[cfg(feature = "raw_socket")]
mod raw_socket;
#[cfg(all(feature = "tap_interface", target_os = "linux"))]
@ -115,6 +117,8 @@ mod tap_interface;
pub use self::tracer::Tracer;
pub use self::fault_injector::FaultInjector;
#[cfg(any(feature = "std", feature = "collections"))]
pub use self::loopback::LoopbackInterface;
#[cfg(any(feature = "raw_socket"))]
pub use self::raw_socket::RawSocket;
#[cfg(all(feature = "tap_interface", target_os = "linux"))]
@ -158,7 +162,9 @@ pub trait Device {
type TxBuffer: AsRef<[u8]> + AsMut<[u8]>;
/// Get a description of device limitations.
fn limits(&self) -> DeviceLimits;
fn limits(&self) -> DeviceLimits {
DeviceLimits::default()
}
/// Receive a frame.
///