Reuse Rxbuffer and update qemu_args.sh for vsock

This commit is contained in:
Anmin Liu
2024-06-08 18:06:22 +00:00
committed by Tate, Hongliang Tian
parent 878e8a88f4
commit 9f67fcdc58
11 changed files with 89 additions and 209 deletions

View File

@ -4,7 +4,10 @@ use alloc::{boxed::Box, string::ToString, sync::Arc};
use core::{fmt::Debug, hint::spin_loop, mem::size_of};
use aster_frame::{offset_of, sync::SpinLock, trap::TrapFrame};
use aster_network::{AnyNetworkDevice, EthernetAddr, RxBuffer, TxBuffer, VirtioNetError};
use aster_network::{
AnyNetworkDevice, EthernetAddr, RxBuffer, TxBuffer, VirtioNetError, RX_BUFFER_POOL,
TX_BUFFER_POOL,
};
use aster_util::{field_ptr, slot_vec::SlotVec};
use log::debug;
use smoltcp::phy::{DeviceCapabilities, Medium};
@ -55,7 +58,8 @@ impl NetworkDevice {
let mut rx_buffers = SlotVec::new();
for i in 0..QUEUE_SIZE {
let rx_buffer = RxBuffer::new(size_of::<VirtioNetHdr>());
let rx_pool = RX_BUFFER_POOL.get().unwrap();
let rx_buffer = RxBuffer::new(size_of::<VirtioNetHdr>(), rx_pool);
// FIEME: Replace rx_buffer with VM segment-based data structure to use dma mapping.
let token = recv_queue.add_dma_buf(&[], &[&rx_buffer])?;
assert_eq!(i, token);
@ -128,7 +132,8 @@ impl NetworkDevice {
rx_buffer.set_packet_len(len as usize);
// FIXME: Ideally, we can reuse the returned buffer without creating new buffer.
// But this requires locking device to be compatible with smoltcp interface.
let new_rx_buffer = RxBuffer::new(size_of::<VirtioNetHdr>());
let rx_pool = RX_BUFFER_POOL.get().unwrap();
let new_rx_buffer = RxBuffer::new(size_of::<VirtioNetHdr>(), rx_pool);
self.add_rx_buffer(new_rx_buffer)?;
Ok(rx_buffer)
}
@ -137,7 +142,8 @@ impl NetworkDevice {
/// FIEME: Replace tx_buffer with VM segment-based data structure to use dma mapping.
fn send(&mut self, packet: &[u8]) -> Result<(), VirtioNetError> {
let header = VirtioNetHdr::default();
let tx_buffer = TxBuffer::new(&header, packet);
let tx_pool = TX_BUFFER_POOL.get().unwrap();
let tx_buffer = TxBuffer::new(&header, packet, tx_pool);
let token = self
.send_queue

View File

@ -2,147 +2,16 @@
use alloc::{collections::LinkedList, sync::Arc};
use align_ext::AlignExt;
use aster_frame::{
mm::{DmaDirection, DmaStream},
sync::SpinLock,
vm::{Daddr, DmaDirection, DmaStream, HasDaddr, VmAllocOptions, VmReader, VmWriter, PAGE_SIZE},
};
use aster_network::dma_pool::{DmaPool, DmaSegment};
use pod::Pod;
use aster_network::dma_pool::DmaPool;
use spin::Once;
pub struct TxBuffer {
dma_stream: DmaStream,
nbytes: usize,
}
impl TxBuffer {
pub fn new<H: Pod>(header: &H, packet: &[u8]) -> Self {
let header = header.as_bytes();
let nbytes = header.len() + packet.len();
let dma_stream = if let Some(stream) = get_tx_stream_from_pool(nbytes) {
stream
} else {
let segment = {
let nframes = (nbytes.align_up(PAGE_SIZE)) / PAGE_SIZE;
VmAllocOptions::new(nframes).alloc_contiguous().unwrap()
};
DmaStream::map(segment, DmaDirection::ToDevice, false).unwrap()
};
let mut writer = dma_stream.writer().unwrap();
writer.write(&mut VmReader::from(header));
writer.write(&mut VmReader::from(packet));
let tx_buffer = Self { dma_stream, nbytes };
tx_buffer.sync();
tx_buffer
}
pub fn writer(&self) -> VmWriter<'_> {
self.dma_stream.writer().unwrap().limit(self.nbytes)
}
fn sync(&self) {
self.dma_stream.sync(0..self.nbytes).unwrap();
}
pub fn nbytes(&self) -> usize {
self.nbytes
}
}
impl HasDaddr for TxBuffer {
fn daddr(&self) -> Daddr {
self.dma_stream.daddr()
}
}
impl Drop for TxBuffer {
fn drop(&mut self) {
TX_BUFFER_POOL
.get()
.unwrap()
.lock_irq_disabled()
.push_back(self.dma_stream.clone());
}
}
pub struct RxBuffer {
segment: DmaSegment,
header_len: usize,
packet_len: usize,
}
impl RxBuffer {
pub fn new(header_len: usize) -> Self {
assert!(header_len <= RX_BUFFER_LEN);
let segment = RX_BUFFER_POOL.get().unwrap().alloc_segment().unwrap();
Self {
segment,
header_len,
packet_len: 0,
}
}
pub const fn packet_len(&self) -> usize {
self.packet_len
}
pub fn set_packet_len(&mut self, packet_len: usize) {
assert!(self.header_len + packet_len <= RX_BUFFER_LEN);
self.packet_len = packet_len;
}
pub fn packet(&self) -> VmReader<'_> {
self.segment
.sync(self.header_len..self.header_len + self.packet_len)
.unwrap();
self.segment
.reader()
.unwrap()
.skip(self.header_len)
.limit(self.packet_len)
}
pub fn buf(&self) -> VmReader<'_> {
self.segment
.sync(0..self.header_len + self.packet_len)
.unwrap();
self.segment
.reader()
.unwrap()
.limit(self.header_len + self.packet_len)
}
pub const fn buf_len(&self) -> usize {
self.segment.size()
}
}
impl HasDaddr for RxBuffer {
fn daddr(&self) -> Daddr {
self.segment.daddr()
}
}
pub const RX_BUFFER_LEN: usize = 4096;
static RX_BUFFER_POOL: Once<Arc<DmaPool>> = Once::new();
static TX_BUFFER_POOL: Once<SpinLock<LinkedList<DmaStream>>> = Once::new();
fn get_tx_stream_from_pool(nbytes: usize) -> Option<DmaStream> {
let mut pool = TX_BUFFER_POOL.get().unwrap().lock_irq_disabled();
let mut cursor = pool.cursor_front_mut();
while let Some(current) = cursor.current() {
if current.nbytes() >= nbytes {
return cursor.remove_current();
}
cursor.move_next();
}
None
}
const RX_BUFFER_LEN: usize = 4096;
pub static RX_BUFFER_POOL: Once<Arc<DmaPool>> = Once::new();
pub static TX_BUFFER_POOL: Once<SpinLock<LinkedList<DmaStream>>> = Once::new();
pub fn init() {
const POOL_INIT_SIZE: usize = 32;

View File

@ -3,13 +3,13 @@
use alloc::{boxed::Box, string::ToString, sync::Arc, vec, vec::Vec};
use core::{fmt::Debug, hint::spin_loop, mem::size_of};
use aster_frame::{offset_of, sync::SpinLock, trap::TrapFrame, vm::VmWriter};
use aster_frame::{mm::VmWriter, offset_of, sync::SpinLock, trap::TrapFrame};
use aster_network::{RxBuffer, TxBuffer};
use aster_util::{field_ptr, slot_vec::SlotVec};
use log::debug;
use pod::Pod;
use super::{
buffer::RxBuffer,
config::{VirtioVsockConfig, VsockFeatures},
connect::{ConnectionInfo, VsockEvent},
error::SocketError,
@ -18,7 +18,10 @@ use super::{
};
use crate::{
device::{
socket::{buffer::TxBuffer, handle_recv_irq, register_device},
socket::{
buffer::{RX_BUFFER_POOL, TX_BUFFER_POOL},
handle_recv_irq, register_device,
},
VirtioDeviceError,
},
queue::{QueueError, VirtQueue},
@ -68,7 +71,8 @@ impl SocketDevice {
// Allocate and add buffers for the RX queue.
let mut rx_buffers = SlotVec::new();
for i in 0..QUEUE_SIZE {
let rx_buffer = RxBuffer::new(size_of::<VirtioVsockHdr>());
let rx_pool = RX_BUFFER_POOL.get().unwrap();
let rx_buffer = RxBuffer::new(size_of::<VirtioVsockHdr>(), rx_pool);
let token = recv_queue.add_dma_buf(&[], &[&rx_buffer])?;
assert_eq!(i, token);
assert_eq!(rx_buffers.put(rx_buffer) as u16, i);
@ -187,7 +191,8 @@ impl SocketDevice {
) -> Result<(), SocketError> {
debug!("Sent packet {:?}. Op {:?}", header, header.op());
debug!("buffer in send_packet_to_tx_queue: {:?}", buffer);
let tx_buffer = TxBuffer::new(header, buffer);
let tx_pool = TX_BUFFER_POOL.get().unwrap();
let tx_buffer = TxBuffer::new(header, buffer, tx_pool);
let token = self.send_queue.add_dma_buf(&[&tx_buffer], &[])?;
@ -269,7 +274,8 @@ impl SocketDevice {
.ok_or(QueueError::WrongToken)?;
rx_buffer.set_packet_len(len as usize);
let new_rx_buffer = RxBuffer::new(size_of::<VirtioVsockHdr>());
let rx_pool = RX_BUFFER_POOL.get().unwrap();
let new_rx_buffer = RxBuffer::new(size_of::<VirtioVsockHdr>(), rx_pool);
self.add_rx_buffer(new_rx_buffer, token)?;
Ok(rx_buffer)

View File

@ -3,8 +3,6 @@
use aster_frame::mm::{DmaCoherent, DmaStream, DmaStreamSlice, HasDaddr};
use aster_network::{DmaSegment, RxBuffer, TxBuffer};
use crate::device;
/// A DMA-capable buffer.
///
/// Any type implements this trait should also implements `HasDaddr` trait,
@ -50,15 +48,3 @@ impl DmaBuf for RxBuffer {
self.buf_len()
}
}
impl DmaBuf for device::socket::buffer::TxBuffer {
fn len(&self) -> usize {
self.nbytes()
}
}
impl DmaBuf for device::socket::buffer::RxBuffer {
fn len(&self) -> usize {
self.buf_len()
}
}