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

186 lines
5.3 KiB
Rust
Raw Normal View History

2024-01-03 03:22:36 +00:00
// SPDX-License-Identifier: MPL-2.0
2023-05-30 08:34:28 +00:00
#![no_std]
#![deny(unsafe_code)]
2023-05-30 08:34:28 +00:00
#![feature(trait_alias)]
2023-08-28 07:03:28 +00:00
#![feature(fn_traits)]
2024-03-12 11:01:50 +00:00
#![feature(linked_list_cursors)]
2023-08-28 07:03:28 +00:00
2024-03-12 11:01:50 +00:00
mod buffer;
2024-05-06 15:00:48 +00:00
pub mod dma_pool;
2024-03-12 11:01:50 +00:00
mod driver;
2023-05-30 08:34:28 +00:00
extern crate alloc;
use alloc::{collections::BTreeMap, string::String, sync::Arc, vec::Vec};
use core::{any::Any, fmt::Debug};
2024-09-19 04:16:35 +00:00
use aster_bigtcp::device::DeviceCapabilities;
pub use buffer::{RxBuffer, TxBuffer, RX_BUFFER_POOL, TX_BUFFER_LEN};
use component::{init_component, ComponentInitError};
2024-03-12 11:01:50 +00:00
pub use dma_pool::DmaSegment;
2024-08-09 03:32:27 +00:00
use ostd::{
2024-09-12 01:52:40 +00:00
sync::{LocalIrqDisabled, SpinLock},
2024-08-09 03:32:27 +00:00
Pod,
};
2023-05-30 08:34:28 +00:00
use spin::Once;
2023-08-28 07:03:28 +00:00
#[derive(Debug, Clone, Copy, Pod)]
#[repr(C)]
pub struct EthernetAddr(pub [u8; 6]);
#[derive(Debug, Clone, Copy)]
pub enum VirtioNetError {
NotReady,
WrongToken,
Busy,
2023-08-28 07:03:28 +00:00
Unknown,
}
2023-05-30 08:34:28 +00:00
2023-11-20 12:37:51 +00:00
pub trait AnyNetworkDevice: Send + Sync + Any + Debug {
2023-08-28 07:03:28 +00:00
// ================Device Information=================
2023-05-30 08:34:28 +00:00
fn mac_addr(&self) -> EthernetAddr;
2024-09-19 04:16:35 +00:00
fn capabilities(&self) -> DeviceCapabilities;
2023-08-28 07:03:28 +00:00
// ================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.
2024-03-12 11:01:50 +00:00
fn send(&mut self, packet: &[u8]) -> Result<(), VirtioNetError>;
fn free_processed_tx_buffers(&mut self);
2023-08-28 07:03:28 +00:00
}
pub trait NetDeviceIrqHandler = Fn() + Send + Sync + 'static;
2024-09-12 01:52:40 +00:00
pub fn register_device(
name: String,
device: Arc<SpinLock<dyn AnyNetworkDevice, LocalIrqDisabled>>,
) {
2023-08-28 07:03:28 +00:00
COMPONENT
.get()
.unwrap()
2023-11-20 12:37:51 +00:00
.network_device_table
2024-08-09 03:32:27 +00:00
.lock()
.insert(name, NetworkDeviceIrqCallbackSet::new(device));
2023-08-28 07:03:28 +00:00
}
2024-09-12 01:52:40 +00:00
pub fn get_device(str: &str) -> Option<Arc<SpinLock<dyn AnyNetworkDevice, LocalIrqDisabled>>> {
let table = COMPONENT.get().unwrap().network_device_table.lock();
let callbacks = table.get(str)?;
Some(callbacks.device.clone())
2023-08-28 07:03:28 +00:00
}
2024-03-12 11:01:50 +00:00
/// Registers callback which will be called when receiving message.
///
/// Since the callback will be called in interrupt context,
/// the callback function should NOT sleep.
2023-11-20 12:37:51 +00:00
pub fn register_recv_callback(name: &str, callback: impl NetDeviceIrqHandler) {
2024-09-12 01:52:40 +00:00
let device_table = COMPONENT.get().unwrap().network_device_table.lock();
let Some(callbacks) = device_table.get(name) else {
2023-08-28 07:03:28 +00:00
return;
};
callbacks.recv_callbacks.lock().push(Arc::new(callback));
}
pub fn register_send_callback(name: &str, callback: impl NetDeviceIrqHandler) {
let device_table = COMPONENT.get().unwrap().network_device_table.lock();
let Some(callbacks) = device_table.get(name) else {
return;
};
callbacks.send_callbacks.lock().push(Arc::new(callback));
2023-08-28 07:03:28 +00:00
}
2023-11-20 12:37:51 +00:00
pub fn handle_recv_irq(name: &str) {
2024-09-12 01:52:40 +00:00
let device_table = COMPONENT.get().unwrap().network_device_table.lock();
let Some(callbacks) = device_table.get(name) else {
return;
};
let callbacks = callbacks.recv_callbacks.lock();
for callback in callbacks.iter() {
callback();
}
}
pub fn handle_send_irq(name: &str) {
let device_table = COMPONENT.get().unwrap().network_device_table.lock();
let Some(callbacks) = device_table.get(name) else {
2023-08-28 07:03:28 +00:00
return;
};
let can_send = {
let mut device = callbacks.device.lock();
device.free_processed_tx_buffers();
device.can_send()
};
if !can_send {
return;
}
let callbacks = callbacks.send_callbacks.lock();
2024-03-12 11:01:50 +00:00
for callback in callbacks.iter() {
callback();
2023-08-28 07:03:28 +00:00
}
}
2023-09-04 03:04:42 +00:00
pub fn all_devices() -> Vec<(String, NetworkDeviceRef)> {
2024-09-12 01:52:40 +00:00
let network_devs = COMPONENT.get().unwrap().network_device_table.lock();
2023-11-20 12:37:51 +00:00
network_devs
.iter()
.map(|(name, callbacks)| (name.clone(), callbacks.device.clone()))
2023-11-20 12:37:51 +00:00
.collect()
2023-05-30 08:34:28 +00:00
}
2023-08-28 07:03:28 +00:00
static COMPONENT: Once<Component> = Once::new();
2024-08-09 03:32:27 +00:00
pub(crate) static NETWORK_IRQ_HANDLERS: Once<
2024-09-12 01:52:40 +00:00
SpinLock<Vec<Arc<dyn NetDeviceIrqHandler>>, LocalIrqDisabled>,
2024-08-09 03:32:27 +00:00
> = Once::new();
2023-05-30 08:34:28 +00:00
#[init_component]
fn init() -> Result<(), ComponentInitError> {
2023-08-28 07:03:28 +00:00
let a = Component::init()?;
COMPONENT.call_once(|| a);
2023-05-30 08:34:28 +00:00
NETWORK_IRQ_HANDLERS.call_once(|| SpinLock::new(Vec::new()));
2024-03-12 11:01:50 +00:00
buffer::init();
2023-05-30 08:34:28 +00:00
Ok(())
}
2024-09-12 01:52:40 +00:00
type NetDeviceIrqHandlerListRef =
Arc<SpinLock<Vec<Arc<dyn NetDeviceIrqHandler>>, LocalIrqDisabled>>;
type NetworkDeviceRef = Arc<SpinLock<dyn AnyNetworkDevice, LocalIrqDisabled>>;
2023-09-04 03:04:42 +00:00
2023-08-28 07:03:28 +00:00
struct Component {
/// Device list, the key is device name, value is (callbacks, device);
network_device_table: SpinLock<BTreeMap<String, NetworkDeviceIrqCallbackSet>, LocalIrqDisabled>,
}
/// The send callbacks and recv callbacks for a network device
struct NetworkDeviceIrqCallbackSet {
device: NetworkDeviceRef,
recv_callbacks: NetDeviceIrqHandlerListRef,
send_callbacks: NetDeviceIrqHandlerListRef,
}
impl NetworkDeviceIrqCallbackSet {
fn new(device: NetworkDeviceRef) -> Self {
Self {
device,
recv_callbacks: Arc::new(SpinLock::new(Vec::new())),
send_callbacks: Arc::new(SpinLock::new(Vec::new())),
}
}
2023-05-30 08:34:28 +00:00
}
2023-08-28 07:03:28 +00:00
impl Component {
pub fn init() -> Result<Self, ComponentInitError> {
Ok(Self {
2023-11-20 12:37:51 +00:00
network_device_table: SpinLock::new(BTreeMap::new()),
2023-08-28 07:03:28 +00:00
})
}
2023-05-30 08:34:28 +00:00
}