Add BufferPool.

This commit is contained in:
Egor Karavaev
2017-09-18 23:26:16 +03:00
parent 0c5fff907c
commit 203fa64580
4 changed files with 115 additions and 16 deletions
+92
View File
@@ -0,0 +1,92 @@
use std::ops::{Deref, DerefMut, Drop};
use std::rc::Rc;
use std::cell::RefCell;
use std::mem::swap;
type BufferStack = Rc<RefCell<Vec<Vec<u8>>>>;
pub struct Buffer {
buffer: Vec<u8>,
stack: BufferStack,
}
impl Buffer {
pub fn resize(&mut self, new_len: usize) {
self.buffer.resize(new_len, 0u8);
}
}
impl AsRef<[u8]> for Buffer {
fn as_ref(&self) -> &[u8] {
&self.buffer
}
}
impl AsMut<[u8]> for Buffer {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.buffer
}
}
impl Deref for Buffer {
type Target = [u8];
fn deref(&self) -> &Self::Target {
&self.buffer
}
}
impl DerefMut for Buffer {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.buffer
}
}
impl Drop for Buffer {
fn drop(&mut self) {
let mut tmp = vec![];
swap(&mut tmp, &mut self.buffer);
{
let mut stack = self.stack.borrow_mut();
trace!("Returning buffer: {}", stack.len());
stack.push(tmp);
}
}
}
pub struct BufferPool {
buffers_size: usize,
stack: BufferStack,
}
impl BufferPool {
pub fn new(buffers_size: usize) -> BufferPool {
BufferPool {
buffers_size,
stack: Rc::new(RefCell::new(vec![])),
}
}
pub fn get_buffer(&mut self) -> Buffer {
let buffer = match self.stack.borrow_mut().pop() {
None => {
trace!("Allocating ingress buffer");
vec![0u8; self.buffers_size]
}
Some(mut v) => {
trace!("Reusing ingress buffer");
// memsetting the buffer with `resize` would be a waste of time
let capacity = v.capacity();
unsafe {
v.set_len(capacity);
}
v
}
};
Buffer {
buffer,
stack: self.stack.clone(),
}
}
}
+4 -3
View File
@@ -4,10 +4,11 @@ use std::cell::RefCell;
use std::io::Write;
use std::collections::VecDeque;
use smoltcp;
use buffer_pool::Buffer;
pub struct NetworkDevice {
network_file: Rc<RefCell<File>>,
input_queue: Rc<RefCell<VecDeque<Vec<u8>>>>,
input_queue: Rc<RefCell<VecDeque<Buffer>>>,
}
impl NetworkDevice {
@@ -15,7 +16,7 @@ impl NetworkDevice {
pub fn new(
network_file: Rc<RefCell<File>>,
input_queue: Rc<RefCell<VecDeque<Vec<u8>>>>,
input_queue: Rc<RefCell<VecDeque<Buffer>>>,
) -> NetworkDevice {
NetworkDevice {
network_file,
@@ -48,7 +49,7 @@ impl Drop for TxBuffer {
}
impl smoltcp::phy::Device for NetworkDevice {
type RxBuffer = Vec<u8>;
type RxBuffer = Buffer;
type TxBuffer = TxBuffer;
fn limits(&self) -> smoltcp::phy::DeviceLimits {
+1
View File
@@ -15,6 +15,7 @@ use std::process;
use std::rc::Rc;
mod error;
mod buffer_pool;
mod device;
mod scheme;
mod logger;
+18 -13
View File
@@ -1,5 +1,3 @@
use device::NetworkDevice;
use error::{Error, Result};
use netutils::{getcfg, MacAddr};
use smoltcp;
use std::collections::{BTreeMap, VecDeque};
@@ -15,6 +13,10 @@ use smoltcp::socket::AsSocket;
use syscall::SchemeMut;
use syscall;
use device::NetworkDevice;
use error::{Error, Result};
use buffer_pool::{Buffer, BufferPool};
struct RawHandle {
flags: usize,
events: usize,
@@ -43,14 +45,16 @@ pub struct Smolnetd {
raw_sockets: BTreeMap<usize, RawHandle>,
udp_sockets: BTreeMap<usize, UdpHandle>,
input_queue: Rc<RefCell<VecDeque<Vec<u8>>>>,
input_queue: Rc<RefCell<VecDeque<Buffer>>>,
input_buffer_pool: BufferPool,
}
struct IpScheme<'a>(&'a mut Smolnetd);
struct UdpScheme<'a>(&'a mut Smolnetd);
impl Smolnetd {
const IP_BUFFER_SIZE: usize = 128;
const INGRESS_PACKET_SIZE: usize = 2048;
const SOCKET_BUFFER_SIZE: usize = 128; //packets
const CHECK_TIMEOUT_MS: i64 = 1000;
pub fn new(network_file: File, ip_file: File, udp_file: File, time_file: File) -> Smolnetd {
@@ -93,6 +97,7 @@ impl Smolnetd {
next_fd: 0,
input_queue,
network_file,
input_buffer_pool: BufferPool::new(Self::INGRESS_PACKET_SIZE),
}
}
@@ -155,7 +160,7 @@ impl Smolnetd {
fn read_frames(&mut self) -> Result<usize> {
let mut total_frames = 0;
loop {
let mut buffer = vec![0; 65536];
let mut buffer = self.input_buffer_pool.get_buffer();
let count = self.network_file
.borrow_mut()
.read(&mut buffer)
@@ -166,7 +171,7 @@ impl Smolnetd {
break;
}
trace!("got frame {}", count);
buffer.resize(count, 0);
buffer.resize(count);
self.input_queue.borrow_mut().push_back(buffer);
total_frames += 1;
}
@@ -206,9 +211,9 @@ impl<'a> syscall::SchemeMut for IpScheme<'a> {
let path = str::from_utf8(url).or_else(|_| Err(syscall::Error::new(syscall::EINVAL)))?;
let proto = u8::from_str_radix(path, 16).or(Err(syscall::Error::new(syscall::ENOENT)))?;
let mut rx_packets = Vec::with_capacity(Smolnetd::IP_BUFFER_SIZE);
let mut tx_packets = Vec::with_capacity(Smolnetd::IP_BUFFER_SIZE);
for _ in 0..Smolnetd::IP_BUFFER_SIZE {
let mut rx_packets = Vec::with_capacity(Smolnetd::SOCKET_BUFFER_SIZE);
let mut tx_packets = Vec::with_capacity(Smolnetd::SOCKET_BUFFER_SIZE);
for _ in 0..Smolnetd::SOCKET_BUFFER_SIZE {
rx_packets.push(smoltcp::socket::RawPacketBuffer::new(
vec![0; NetworkDevice::MTU],
));
@@ -269,7 +274,6 @@ impl<'a> syscall::SchemeMut for IpScheme<'a> {
}
fn read(&mut self, fd: usize, buf: &mut [u8]) -> syscall::Result<usize> {
trace!("Read {}", fd);
use smoltcp::socket::AsSocket;
let handle = self.0
@@ -280,6 +284,7 @@ impl<'a> syscall::SchemeMut for IpScheme<'a> {
self.0.socket_set.get_mut(handle.socket_handle).as_socket();
if socket.can_recv() {
let length = socket.recv_slice(buf).expect("Can't receive slice");
trace!("Read fd {} len {}", fd, length);
Ok(length)
} else if handle.flags & syscall::O_NONBLOCK == syscall::O_NONBLOCK {
Ok(0)
@@ -322,9 +327,9 @@ impl<'a> syscall::SchemeMut for UdpScheme<'a> {
let (remote_ip, remote_port) = parse_socket(parts.next().unwrap_or(""));
let (local_ip, local_port) = parse_socket(parts.next().unwrap_or(""));
let mut rx_packets = Vec::with_capacity(Smolnetd::IP_BUFFER_SIZE);
let mut tx_packets = Vec::with_capacity(Smolnetd::IP_BUFFER_SIZE);
for _ in 0..Smolnetd::IP_BUFFER_SIZE {
let mut rx_packets = Vec::with_capacity(Smolnetd::SOCKET_BUFFER_SIZE);
let mut tx_packets = Vec::with_capacity(Smolnetd::SOCKET_BUFFER_SIZE);
for _ in 0..Smolnetd::SOCKET_BUFFER_SIZE {
rx_packets.push(smoltcp::socket::UdpPacketBuffer::new(
vec![0; NetworkDevice::MTU],
));