asterinas/kernel/comps/network/src/buffer.rs

162 lines
4.0 KiB
Rust
Raw Normal View History

2024-01-03 03:22:36 +00:00
// SPDX-License-Identifier: MPL-2.0
use alloc::{collections::linked_list::LinkedList, sync::Arc};
2023-08-28 07:03:28 +00:00
use aster_softirq::BottomHalfDisabled;
2024-06-19 08:18:39 +00:00
use ostd::{
mm::{
io_util::HasVmReaderWriter, Daddr, DmaDirection, DmaStream, FrameAllocOptions, HasDaddr,
HasSize, Infallible, VmReader, VmWriter, PAGE_SIZE,
},
sync::SpinLock,
Pod,
2024-03-12 11:01:50 +00:00
};
use spin::Once;
use crate::dma_pool::{DmaPool, DmaSegment};
pub struct TxBuffer {
2025-08-18 08:13:51 +00:00
dma_stream: Arc<DmaStream>,
2024-03-12 11:01:50 +00:00
nbytes: usize,
2025-08-18 08:13:51 +00:00
pool: &'static SpinLock<LinkedList<Arc<DmaStream>>, BottomHalfDisabled>,
2024-03-12 11:01:50 +00:00
}
impl TxBuffer {
pub fn new<H: Pod>(
header: &H,
packet: &[u8],
2025-08-18 08:13:51 +00:00
pool: &'static SpinLock<LinkedList<Arc<DmaStream>>, BottomHalfDisabled>,
) -> Self {
2024-03-12 11:01:50 +00:00
let header = header.as_bytes();
let nbytes = header.len() + packet.len();
assert!(nbytes <= TX_BUFFER_LEN);
let dma_stream = if let Some(stream) = pool.lock().pop_front() {
2024-03-12 11:01:50 +00:00
stream
} else {
let segment = FrameAllocOptions::new()
.alloc_segment(TX_BUFFER_LEN / PAGE_SIZE)
.unwrap();
2025-08-18 08:13:51 +00:00
Arc::new(DmaStream::map(segment.into(), DmaDirection::ToDevice, false).unwrap())
2024-03-12 11:01:50 +00:00
};
let tx_buffer = {
let mut writer = dma_stream.writer().unwrap();
writer.write(&mut VmReader::from(header));
writer.write(&mut VmReader::from(packet));
Self {
dma_stream,
nbytes,
pool,
}
};
2024-03-12 11:01:50 +00:00
tx_buffer.sync();
tx_buffer
}
pub fn writer(&self) -> VmWriter<'_, Infallible> {
let mut writer = self.dma_stream.writer().unwrap();
writer.limit(self.nbytes);
writer
2024-03-12 11:01:50 +00:00
}
fn sync(&self) {
self.dma_stream.sync(0..self.nbytes).unwrap();
}
}
2024-03-12 11:01:50 +00:00
impl HasSize for TxBuffer {
fn size(&self) -> usize {
2024-03-12 11:01:50 +00:00
self.nbytes
}
}
impl HasDaddr for TxBuffer {
fn daddr(&self) -> Daddr {
self.dma_stream.daddr()
}
}
impl Drop for TxBuffer {
fn drop(&mut self) {
self.pool.lock().push_back(self.dma_stream.clone());
2024-03-12 11:01:50 +00:00
}
}
2023-05-30 08:34:28 +00:00
pub struct RxBuffer {
2024-03-12 11:01:50 +00:00
segment: DmaSegment,
2023-08-28 07:03:28 +00:00
header_len: usize,
2023-05-30 08:34:28 +00:00
packet_len: usize,
}
impl RxBuffer {
pub fn new(header_len: usize, pool: &Arc<DmaPool>) -> Self {
assert!(header_len <= pool.segment_size());
let segment = pool.alloc_segment().unwrap();
2023-08-28 07:03:28 +00:00
Self {
2024-03-12 11:01:50 +00:00
segment,
2023-08-28 07:03:28 +00:00
header_len,
2024-03-12 11:01:50 +00:00
packet_len: 0,
2023-08-28 07:03:28 +00:00
}
2023-05-30 08:34:28 +00:00
}
pub const fn packet_len(&self) -> usize {
self.packet_len
}
pub fn set_packet_len(&mut self, packet_len: usize) {
2024-03-12 11:01:50 +00:00
assert!(self.header_len + packet_len <= RX_BUFFER_LEN);
2023-05-30 08:34:28 +00:00
self.packet_len = packet_len;
}
pub fn packet(&self) -> VmReader<'_, Infallible> {
2024-03-12 11:01:50 +00:00
self.segment
.sync(self.header_len..self.header_len + self.packet_len)
.unwrap();
let mut reader = self.segment.reader().unwrap();
reader.skip(self.header_len).limit(self.packet_len);
reader
2023-05-30 08:34:28 +00:00
}
pub fn buf(&self) -> VmReader<'_, Infallible> {
self.segment
.sync(0..self.header_len + self.packet_len)
.unwrap();
let mut reader = self.segment.reader().unwrap();
reader.limit(self.header_len + self.packet_len);
reader
}
}
impl HasSize for RxBuffer {
fn size(&self) -> usize {
2024-03-12 11:01:50 +00:00
self.segment.size()
2023-05-30 08:34:28 +00:00
}
}
2024-03-12 11:01:50 +00:00
impl HasDaddr for RxBuffer {
fn daddr(&self) -> Daddr {
self.segment.daddr()
}
2023-05-30 08:34:28 +00:00
}
pub const RX_BUFFER_LEN: usize = 4096;
pub const TX_BUFFER_LEN: usize = 4096;
pub static RX_BUFFER_POOL: Once<Arc<DmaPool>> = Once::new();
2023-05-30 08:34:28 +00:00
2024-03-12 11:01:50 +00:00
pub fn init() {
const POOL_INIT_SIZE: usize = 64;
const POOL_HIGH_WATERMARK: usize = 128;
2024-03-12 11:01:50 +00:00
RX_BUFFER_POOL.call_once(|| {
DmaPool::new(
RX_BUFFER_LEN,
POOL_INIT_SIZE,
POOL_HIGH_WATERMARK,
DmaDirection::FromDevice,
false,
)
});
2023-05-30 08:34:28 +00:00
}