mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-22 00:43:24 +00:00
Reuse Rxbuffer and update qemu_args.sh
for vsock
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
878e8a88f4
commit
9f67fcdc58
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user