2024-01-03 03:22:36 +00:00
|
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
|
|
2023-05-30 08:34:28 +00:00
|
|
|
#![no_std]
|
|
|
|
|
#![forbid(unsafe_code)]
|
|
|
|
|
#![feature(trait_alias)]
|
2023-08-28 07:03:28 +00:00
|
|
|
#![feature(fn_traits)]
|
|
|
|
|
|
|
|
|
|
pub mod buffer;
|
|
|
|
|
pub mod driver;
|
2023-05-30 08:34:28 +00:00
|
|
|
|
|
|
|
|
extern crate alloc;
|
|
|
|
|
|
2024-04-12 05:00:19 +00:00
|
|
|
use alloc::{collections::BTreeMap, string::String, sync::Arc, vec::Vec};
|
2024-02-25 14:09:24 +00:00
|
|
|
use core::{any::Any, fmt::Debug};
|
|
|
|
|
|
2023-12-25 03:12:25 +00:00
|
|
|
use aster_frame::sync::SpinLock;
|
|
|
|
|
use aster_util::safe_ptr::Pod;
|
2024-02-25 14:09:24 +00:00
|
|
|
use buffer::{RxBuffer, TxBuffer};
|
|
|
|
|
use component::{init_component, ComponentInitError};
|
2023-08-28 07:03:28 +00:00
|
|
|
use smoltcp::phy;
|
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,
|
|
|
|
|
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;
|
2023-08-28 07:03:28 +00:00
|
|
|
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;
|
|
|
|
|
|
2024-04-12 05:00:19 +00:00
|
|
|
pub fn register_device(name: String, device: Arc<SpinLock<dyn AnyNetworkDevice>>) {
|
2023-08-28 07:03:28 +00:00
|
|
|
COMPONENT
|
|
|
|
|
.get()
|
|
|
|
|
.unwrap()
|
2023-11-20 12:37:51 +00:00
|
|
|
.network_device_table
|
2023-08-28 07:03:28 +00:00
|
|
|
.lock()
|
|
|
|
|
.insert(name, (Arc::new(SpinLock::new(Vec::new())), device));
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-12 05:00:19 +00:00
|
|
|
pub fn get_device(str: &str) -> Option<Arc<SpinLock<dyn AnyNetworkDevice>>> {
|
2023-11-20 12:37:51 +00:00
|
|
|
let lock = COMPONENT.get().unwrap().network_device_table.lock();
|
2024-02-27 03:23:06 +00:00
|
|
|
let (_, device) = lock.get(str)?;
|
2023-08-28 07:03:28 +00:00
|
|
|
Some(device.clone())
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-20 12:37:51 +00:00
|
|
|
pub fn register_recv_callback(name: &str, callback: impl NetDeviceIrqHandler) {
|
|
|
|
|
let lock = COMPONENT.get().unwrap().network_device_table.lock();
|
2023-08-28 07:03:28 +00:00
|
|
|
let Some((callbacks, _)) = lock.get(name) else {
|
|
|
|
|
return;
|
|
|
|
|
};
|
|
|
|
|
callbacks.lock().push(Arc::new(callback));
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-20 12:37:51 +00:00
|
|
|
pub fn handle_recv_irq(name: &str) {
|
|
|
|
|
let lock = COMPONENT.get().unwrap().network_device_table.lock();
|
2023-08-28 07:03:28 +00:00
|
|
|
let Some((callbacks, _)) = lock.get(name) else {
|
|
|
|
|
return;
|
|
|
|
|
};
|
|
|
|
|
let callbacks = callbacks.clone();
|
|
|
|
|
let lock = callbacks.lock();
|
|
|
|
|
for callback in lock.iter() {
|
|
|
|
|
callback.call(())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-04 03:04:42 +00:00
|
|
|
pub fn all_devices() -> Vec<(String, NetworkDeviceRef)> {
|
2023-11-20 12:37:51 +00:00
|
|
|
let network_devs = COMPONENT.get().unwrap().network_device_table.lock();
|
|
|
|
|
network_devs
|
|
|
|
|
.iter()
|
|
|
|
|
.map(|(name, (_, device))| (name.clone(), device.clone()))
|
|
|
|
|
.collect()
|
2023-05-30 08:34:28 +00:00
|
|
|
}
|
|
|
|
|
|
2023-08-28 07:03:28 +00:00
|
|
|
static COMPONENT: Once<Component> = Once::new();
|
2023-05-30 08:34:28 +00:00
|
|
|
pub(crate) static NETWORK_IRQ_HANDLERS: Once<SpinLock<Vec<Arc<dyn NetDeviceIrqHandler>>>> =
|
|
|
|
|
Once::new();
|
|
|
|
|
|
|
|
|
|
#[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()));
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-04 03:04:42 +00:00
|
|
|
type NetDeviceIrqHandlerListRef = Arc<SpinLock<Vec<Arc<dyn NetDeviceIrqHandler>>>>;
|
2024-04-12 05:00:19 +00:00
|
|
|
type NetworkDeviceRef = Arc<SpinLock<dyn AnyNetworkDevice>>;
|
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);
|
2023-11-20 12:37:51 +00:00
|
|
|
network_device_table:
|
|
|
|
|
SpinLock<BTreeMap<String, (NetDeviceIrqHandlerListRef, NetworkDeviceRef)>>,
|
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
|
|
|
}
|