mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-18 12:06:43 +00:00
Refactor project structure
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
bd878dd1c9
commit
e3c227ae06
91
kernel/comps/network/src/buffer.rs
Normal file
91
kernel/comps/network/src/buffer.rs
Normal file
@ -0,0 +1,91 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use core::mem::size_of;
|
||||
|
||||
use align_ext::AlignExt;
|
||||
use bytes::BytesMut;
|
||||
use pod::Pod;
|
||||
|
||||
/// Buffer for receive packet
|
||||
#[derive(Debug)]
|
||||
pub struct RxBuffer {
|
||||
/// Packet Buffer, length align 8.
|
||||
buf: BytesMut,
|
||||
/// Header len
|
||||
header_len: usize,
|
||||
/// Packet len
|
||||
packet_len: usize,
|
||||
}
|
||||
|
||||
impl RxBuffer {
|
||||
pub fn new(len: usize, header_len: usize) -> Self {
|
||||
let len = len.align_up(8);
|
||||
let buf = BytesMut::zeroed(len);
|
||||
Self {
|
||||
buf,
|
||||
packet_len: 0,
|
||||
header_len,
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn packet_len(&self) -> usize {
|
||||
self.packet_len
|
||||
}
|
||||
|
||||
pub fn set_packet_len(&mut self, packet_len: usize) {
|
||||
self.packet_len = packet_len;
|
||||
}
|
||||
|
||||
pub fn buf(&self) -> &[u8] {
|
||||
&self.buf
|
||||
}
|
||||
|
||||
pub fn buf_mut(&mut self) -> &mut [u8] {
|
||||
&mut self.buf
|
||||
}
|
||||
|
||||
/// Packet payload slice, which is inner buffer excluding VirtioNetHdr.
|
||||
pub fn packet(&self) -> &[u8] {
|
||||
debug_assert!(self.header_len + self.packet_len <= self.buf.len());
|
||||
&self.buf[self.header_len..self.header_len + self.packet_len]
|
||||
}
|
||||
|
||||
/// Mutable packet payload slice.
|
||||
pub fn packet_mut(&mut self) -> &mut [u8] {
|
||||
debug_assert!(self.header_len + self.packet_len <= self.buf.len());
|
||||
&mut self.buf[self.header_len..self.header_len + self.packet_len]
|
||||
}
|
||||
|
||||
pub fn header<H: Pod>(&self) -> H {
|
||||
debug_assert_eq!(size_of::<H>(), self.header_len);
|
||||
H::from_bytes(&self.buf[..size_of::<H>()])
|
||||
}
|
||||
}
|
||||
|
||||
/// Buffer for transmit packet
|
||||
#[derive(Debug)]
|
||||
pub struct TxBuffer {
|
||||
buf: BytesMut,
|
||||
}
|
||||
|
||||
impl TxBuffer {
|
||||
pub fn with_len(buf_len: usize) -> Self {
|
||||
Self {
|
||||
buf: BytesMut::zeroed(buf_len),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(buf: &[u8]) -> Self {
|
||||
Self {
|
||||
buf: BytesMut::from(buf),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn buf(&self) -> &[u8] {
|
||||
&self.buf
|
||||
}
|
||||
|
||||
pub fn buf_mut(&mut self) -> &mut [u8] {
|
||||
&mut self.buf
|
||||
}
|
||||
}
|
62
kernel/comps/network/src/driver.rs
Normal file
62
kernel/comps/network/src/driver.rs
Normal file
@ -0,0 +1,62 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use alloc::vec;
|
||||
|
||||
use smoltcp::{phy, time::Instant};
|
||||
|
||||
use crate::{
|
||||
buffer::{RxBuffer, TxBuffer},
|
||||
AnyNetworkDevice,
|
||||
};
|
||||
|
||||
impl phy::Device for dyn AnyNetworkDevice {
|
||||
type RxToken<'a> = RxToken;
|
||||
type TxToken<'a> = TxToken<'a>;
|
||||
|
||||
fn receive(&mut self, _timestamp: Instant) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
|
||||
if self.can_receive() {
|
||||
let rx_buffer = self.receive().unwrap();
|
||||
Some((RxToken(rx_buffer), TxToken(self)))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn transmit(&mut self, _timestamp: Instant) -> Option<Self::TxToken<'_>> {
|
||||
if self.can_send() {
|
||||
Some(TxToken(self))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn capabilities(&self) -> phy::DeviceCapabilities {
|
||||
self.capabilities()
|
||||
}
|
||||
}
|
||||
pub struct RxToken(RxBuffer);
|
||||
|
||||
impl phy::RxToken for RxToken {
|
||||
fn consume<R, F>(mut self, f: F) -> R
|
||||
where
|
||||
F: FnOnce(&mut [u8]) -> R,
|
||||
{
|
||||
let packet_but = self.0.packet_mut();
|
||||
f(packet_but)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TxToken<'a>(&'a mut dyn AnyNetworkDevice);
|
||||
|
||||
impl<'a> phy::TxToken for TxToken<'a> {
|
||||
fn consume<R, F>(self, len: usize, f: F) -> R
|
||||
where
|
||||
F: FnOnce(&mut [u8]) -> R,
|
||||
{
|
||||
let mut buffer = vec![0u8; len];
|
||||
let res = f(&mut buffer);
|
||||
let tx_buffer = TxBuffer::new(&buffer);
|
||||
self.0.send(tx_buffer).expect("Send packet failed");
|
||||
res
|
||||
}
|
||||
}
|
123
kernel/comps/network/src/lib.rs
Normal file
123
kernel/comps/network/src/lib.rs
Normal file
@ -0,0 +1,123 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#![no_std]
|
||||
#![forbid(unsafe_code)]
|
||||
#![feature(trait_alias)]
|
||||
#![feature(fn_traits)]
|
||||
|
||||
pub mod buffer;
|
||||
pub mod driver;
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
use alloc::{boxed::Box, collections::BTreeMap, string::String, sync::Arc, vec::Vec};
|
||||
use core::{any::Any, fmt::Debug};
|
||||
|
||||
use aster_frame::sync::SpinLock;
|
||||
use aster_util::safe_ptr::Pod;
|
||||
use buffer::{RxBuffer, TxBuffer};
|
||||
use component::{init_component, ComponentInitError};
|
||||
use smoltcp::phy;
|
||||
use spin::Once;
|
||||
|
||||
#[derive(Debug, Clone, Copy, Pod)]
|
||||
#[repr(C)]
|
||||
pub struct EthernetAddr(pub [u8; 6]);
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum VirtioNetError {
|
||||
NotReady,
|
||||
WrongToken,
|
||||
Unknown,
|
||||
}
|
||||
|
||||
pub trait AnyNetworkDevice: Send + Sync + Any + Debug {
|
||||
// ================Device Information=================
|
||||
|
||||
fn mac_addr(&self) -> EthernetAddr;
|
||||
fn capabilities(&self) -> phy::DeviceCapabilities;
|
||||
|
||||
// ================Device Operation===================
|
||||
|
||||
fn can_receive(&self) -> bool;
|
||||
fn can_send(&self) -> bool;
|
||||
/// Receive a packet from network. If packet is ready, returns a RxBuffer containing the packet.
|
||||
/// Otherwise, return NotReady error.
|
||||
fn receive(&mut self) -> Result<RxBuffer, VirtioNetError>;
|
||||
/// Send a packet to network. Return until the request completes.
|
||||
fn send(&mut self, tx_buffer: TxBuffer) -> Result<(), VirtioNetError>;
|
||||
}
|
||||
|
||||
pub trait NetDeviceIrqHandler = Fn() + Send + Sync + 'static;
|
||||
|
||||
pub fn register_device(name: String, device: Arc<SpinLock<Box<dyn AnyNetworkDevice>>>) {
|
||||
COMPONENT
|
||||
.get()
|
||||
.unwrap()
|
||||
.network_device_table
|
||||
.lock()
|
||||
.insert(name, (Arc::new(SpinLock::new(Vec::new())), device));
|
||||
}
|
||||
|
||||
pub fn get_device(str: &str) -> Option<Arc<SpinLock<Box<dyn AnyNetworkDevice>>>> {
|
||||
let lock = COMPONENT.get().unwrap().network_device_table.lock();
|
||||
let (_, device) = lock.get(str)?;
|
||||
Some(device.clone())
|
||||
}
|
||||
|
||||
pub fn register_recv_callback(name: &str, callback: impl NetDeviceIrqHandler) {
|
||||
let lock = COMPONENT.get().unwrap().network_device_table.lock();
|
||||
let Some((callbacks, _)) = lock.get(name) else {
|
||||
return;
|
||||
};
|
||||
callbacks.lock().push(Arc::new(callback));
|
||||
}
|
||||
|
||||
pub fn handle_recv_irq(name: &str) {
|
||||
let lock = COMPONENT.get().unwrap().network_device_table.lock();
|
||||
let Some((callbacks, _)) = lock.get(name) else {
|
||||
return;
|
||||
};
|
||||
let callbacks = callbacks.clone();
|
||||
let lock = callbacks.lock();
|
||||
for callback in lock.iter() {
|
||||
callback.call(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn all_devices() -> Vec<(String, NetworkDeviceRef)> {
|
||||
let network_devs = COMPONENT.get().unwrap().network_device_table.lock();
|
||||
network_devs
|
||||
.iter()
|
||||
.map(|(name, (_, device))| (name.clone(), device.clone()))
|
||||
.collect()
|
||||
}
|
||||
|
||||
static COMPONENT: Once<Component> = Once::new();
|
||||
pub(crate) static NETWORK_IRQ_HANDLERS: Once<SpinLock<Vec<Arc<dyn NetDeviceIrqHandler>>>> =
|
||||
Once::new();
|
||||
|
||||
#[init_component]
|
||||
fn init() -> Result<(), ComponentInitError> {
|
||||
let a = Component::init()?;
|
||||
COMPONENT.call_once(|| a);
|
||||
NETWORK_IRQ_HANDLERS.call_once(|| SpinLock::new(Vec::new()));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
type NetDeviceIrqHandlerListRef = Arc<SpinLock<Vec<Arc<dyn NetDeviceIrqHandler>>>>;
|
||||
type NetworkDeviceRef = Arc<SpinLock<Box<dyn AnyNetworkDevice>>>;
|
||||
|
||||
struct Component {
|
||||
/// Device list, the key is device name, value is (callbacks, device);
|
||||
network_device_table:
|
||||
SpinLock<BTreeMap<String, (NetDeviceIrqHandlerListRef, NetworkDeviceRef)>>,
|
||||
}
|
||||
|
||||
impl Component {
|
||||
pub fn init() -> Result<Self, ComponentInitError> {
|
||||
Ok(Self {
|
||||
network_device_table: SpinLock::new(BTreeMap::new()),
|
||||
})
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user