DragonOS/kernel/src/driver/net/loopback.rs
longjin 17aa298971 refactor: 将设备名称 "lo" 提取为常量 DEVICE_NAME
Signed-off-by: longjin <longjin@DragonOS.org>
2025-03-13 13:33:20 +08:00

538 lines
16 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use crate::arch::rand::rand;
use crate::driver::base::class::Class;
use crate::driver::base::device::bus::Bus;
use crate::driver::base::device::driver::Driver;
use crate::driver::base::device::{Device, DeviceCommonData, DeviceType, IdTable};
use crate::driver::base::kobject::{
KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState,
};
use crate::driver::base::kset::KSet;
use crate::filesystem::kernfs::KernFSInode;
use crate::init::initcall::INITCALL_DEVICE;
use crate::libs::rwlock::{RwLockReadGuard, RwLockWriteGuard};
use crate::libs::spinlock::{SpinLock, SpinLockGuard};
use crate::net::{generate_iface_id, NET_DEVICES};
use crate::time::Instant;
use alloc::collections::VecDeque;
use alloc::fmt::Debug;
use alloc::string::{String, ToString};
use alloc::sync::{Arc, Weak};
use alloc::vec::Vec;
use core::cell::UnsafeCell;
use core::ops::{Deref, DerefMut};
use smoltcp::wire::HardwareAddress;
use smoltcp::{
phy::{self},
wire::{IpAddress, IpCidr},
};
use system_error::SystemError;
use unified_init::macros::unified_init;
use super::{register_netdevice, NetDeivceState, NetDeviceCommonData, Operstate};
use super::{Iface, IfaceCommon};
const DEVICE_NAME: &str = "loopback";
/// ## 环回接收令牌
/// 用于储存lo网卡接收到的数据
pub struct LoopbackRxToken {
buffer: Vec<u8>,
}
impl phy::RxToken for LoopbackRxToken {
/// ## 实现Rxtoken的consume函数
/// 接受一个函数 `f`,并在 `self.buffer` 上调用它。
///
/// ## 参数
/// - mut self :一个可变的 `LoopbackRxToken` 实例。
/// - f :接受一个可变的 u8 切片,并返回类型 `R` 的结果。
///
/// ## 返回值
/// 返回函数 `f` 在 `self.buffer` 上的调用结果。
fn consume<R, F>(self, f: F) -> R
where
F: FnOnce(&[u8]) -> R,
{
f(self.buffer.as_slice())
}
}
/// ## 环回发送令牌
/// 返回驱动用于操作lo设备
pub struct LoopbackTxToken {
driver: LoopbackDriver,
}
impl phy::TxToken for LoopbackTxToken {
/// ## 实现TxToken的consume函数
/// 向lo的队列推入待发送的数据报实现环回
///
/// ## 参数
/// - self
/// - len数据包的长度
/// - f接受一个可变的 u8 切片,并返回类型 `R` 的结果。
///
/// ## 返回值
/// 返回f对数据包操纵的结果
fn consume<R, F>(self, len: usize, f: F) -> R
where
F: FnOnce(&mut [u8]) -> R,
{
let mut buffer = vec![0; len];
let result = f(buffer.as_mut_slice());
let mut device = self.driver.inner.lock();
device.loopback_transmit(buffer);
// debug!("lo transmit!");
result
}
}
/// ## Loopback设备
/// 成员是一个队列,用来存放接受到的数据包。
/// 当使用lo发送数据包时不会把数据包传到link层而是直接发送到该队列实现环回。
pub struct Loopback {
//回环设备的缓冲区,接受的数据包会存放在这里,发送的数据包也会发送到这里,实现环回
queue: VecDeque<Vec<u8>>,
}
impl Loopback {
/// ## Loopback创建函数
/// 创建lo设备
pub fn new() -> Self {
let queue = VecDeque::new();
Loopback { queue }
}
/// ## Loopback处理接受到的数据包函数
/// Loopback接受到数据后会调用这个函数来弹出接收的数据返回给协议栈
///
/// ## 参数
/// - &mut self :自身可变引用
///
/// ## 返回值
/// - queue的头部数据包
pub fn loopback_receive(&mut self) -> Vec<u8> {
let buffer = self.queue.pop_front();
match buffer {
Some(buffer) => {
// debug!("lo receive:{:?}", buffer);
return buffer;
}
None => {
return Vec::new();
}
}
}
/// ## Loopback发送数据包的函数
/// Loopback发送数据包给自己的接收队列实现环回
///
/// ## 参数
/// - &mut self自身可变引用
/// - buffer需要发送的数据包
pub fn loopback_transmit(&mut self, buffer: Vec<u8>) {
// debug!("lo transmit:{:?}", buffer);
self.queue.push_back(buffer)
}
}
/// ## driver的包裹器
/// 为实现获得不可变引用的Interface的内部可变性故为Driver提供UnsafeCell包裹器
///
/// 参考virtio_net.rs
#[derive(Debug)]
struct LoopbackDriverWapper(UnsafeCell<LoopbackDriver>);
unsafe impl Send for LoopbackDriverWapper {}
unsafe impl Sync for LoopbackDriverWapper {}
/// ## deref 方法返回一个指向 `LoopbackDriver` 的引用。
impl Deref for LoopbackDriverWapper {
type Target = LoopbackDriver;
fn deref(&self) -> &Self::Target {
unsafe { &*self.0.get() }
}
}
/// ## `deref_mut` 方法返回一个指向可变 `LoopbackDriver` 的引用。
impl DerefMut for LoopbackDriverWapper {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *self.0.get() }
}
}
impl LoopbackDriverWapper {
/// ## force_get_mut返回一个指向可变 `LoopbackDriver` 的引用。
#[allow(clippy::mut_from_ref)]
#[allow(clippy::mut_from_ref)]
fn force_get_mut(&self) -> &mut LoopbackDriver {
unsafe { &mut *self.0.get() }
}
}
/// ## Loopback驱动
/// 负责操作Loopback设备实现基本的网卡功能
pub struct LoopbackDriver {
pub inner: Arc<SpinLock<Loopback>>,
}
impl LoopbackDriver {
/// ## LoopbackDriver创建函数
pub fn new() -> Self {
let inner = Arc::new(SpinLock::new(Loopback::new()));
LoopbackDriver { inner }
}
}
impl Clone for LoopbackDriver {
fn clone(&self) -> Self {
LoopbackDriver {
inner: self.inner.clone(),
}
}
}
impl phy::Device for LoopbackDriver {
type RxToken<'a>
= LoopbackRxToken
where
Self: 'a;
type TxToken<'a>
= LoopbackTxToken
where
Self: 'a;
/// ## 返回设备的物理层特性。
/// lo设备的最大传输单元为65535最大突发大小为1传输介质默认为Ethernet
fn capabilities(&self) -> phy::DeviceCapabilities {
let mut result = phy::DeviceCapabilities::default();
result.max_transmission_unit = 65535;
result.max_burst_size = Some(1);
result.medium = smoltcp::phy::Medium::Ip;
return result;
}
/// ## Loopback驱动处理接受数据事件
/// 驱动调用Loopback的receive函数处理buffer封装成rxtx返回给上层
///
/// ## 参数
/// - `&mut self` :自身可变引用
/// - `_timestamp`
///
/// ## 返回值
/// - None: 如果接收队列为空,返回 `None`,以通知上层没有可以接收的包
/// - Option::Some((rx, tx)):如果接收队列不为空,返回 `Some`,其中包含一个接收令牌 `rx` 和一个发送令牌 `tx`
fn receive(
&mut self,
_timestamp: smoltcp::time::Instant,
) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
let buffer = self.inner.lock().loopback_receive();
//receive队列为为空返回NONE值以通知上层没有可以receive的包
if buffer.is_empty() {
// log::debug!("lo receive none!");
return Option::None;
}
// log::debug!("lo receive!");
let rx = LoopbackRxToken { buffer };
let tx = LoopbackTxToken {
driver: self.clone(),
};
return Option::Some((rx, tx));
}
/// ## Loopback驱动处理发送数据包事件
/// Loopback驱动在需要发送数据时会调用这个函数来获取一个发送令牌。
///
/// ## 参数
/// - `&mut self` :自身可变引用
/// - `_timestamp`
///
/// ## 返回值
/// - 返回一个 `Some`,其中包含一个发送令牌,该令牌包含一个对自身的克隆引用
fn transmit(&mut self, _timestamp: smoltcp::time::Instant) -> Option<Self::TxToken<'_>> {
// log::debug!("lo transmit!");
Some(LoopbackTxToken {
driver: self.clone(),
})
}
}
/// ## LoopbackInterface结构
/// 封装驱动包裹器和iface设置接口名称
#[cast_to([sync] Iface)]
#[cast_to([sync] Device)]
#[derive(Debug)]
pub struct LoopbackInterface {
driver: LoopbackDriverWapper,
common: IfaceCommon,
inner: SpinLock<InnerLoopbackInterface>,
locked_kobj_state: LockedKObjectState,
}
#[derive(Debug)]
pub struct InnerLoopbackInterface {
netdevice_common: NetDeviceCommonData,
device_common: DeviceCommonData,
kobj_common: KObjectCommonData,
}
impl LoopbackInterface {
pub const DEVICE_NAME: &str = "lo";
/// ## `new` 是一个公共函数,用于创建一个新的 `LoopbackInterface` 实例。
/// 生成一个新的接口 ID。创建一个新的接口配置设置其硬件地址和随机种子使用接口配置和驱动器创建一个新的 `smoltcp::iface::Interface` 实例。
/// 设置接口的 IP 地址为 127.0.0.1。
/// 创建一个新的 `LoopbackDriverWapper` 实例,包装驱动器。
/// 创建一个新的 `LoopbackInterface` 实例,包含驱动器、接口 ID、接口和名称并将其封装在一个 `Arc` 中。
/// ## 参数
/// - `driver`:一个 `LoopbackDriver` 实例,用于驱动网络环回操作。
///
/// ## 返回值
/// 返回一个 `Arc<Self>`,即一个指向新创建的 `LoopbackInterface` 实例的智能指针。
pub fn new(mut driver: LoopbackDriver) -> Arc<Self> {
let iface_id = generate_iface_id();
// let hardware_addr = HardwareAddress::Ethernet(smoltcp::wire::EthernetAddress([
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// ]));
let hardware_addr = HardwareAddress::Ip;
let mut iface_config = smoltcp::iface::Config::new(hardware_addr);
iface_config.random_seed = rand() as u64;
let mut iface =
smoltcp::iface::Interface::new(iface_config, &mut driver, Instant::now().into());
iface.set_any_ip(true);
let addr = IpAddress::v4(127, 0, 0, 1);
let cidr = IpCidr::new(addr, 8);
//设置网卡地址为127.0.0.1
iface.update_ip_addrs(|ip_addrs| {
ip_addrs.push(cidr).expect("Push ipCidr failed: full");
});
iface.routes_mut().update(|routes_map| {
routes_map
.push(smoltcp::iface::Route {
cidr,
via_router: addr,
preferred_until: None,
expires_at: None,
})
.expect("Add default ipv4 route failed: full");
});
Arc::new(LoopbackInterface {
driver: LoopbackDriverWapper(UnsafeCell::new(driver)),
common: IfaceCommon::new(iface_id, false, iface),
inner: SpinLock::new(InnerLoopbackInterface {
netdevice_common: NetDeviceCommonData::default(),
device_common: DeviceCommonData::default(),
kobj_common: KObjectCommonData::default(),
}),
locked_kobj_state: LockedKObjectState::default(),
})
}
fn inner(&self) -> SpinLockGuard<InnerLoopbackInterface> {
return self.inner.lock();
}
}
//TODO: 向sysfs注册lo设备
impl KObject for LoopbackInterface {
fn as_any_ref(&self) -> &dyn core::any::Any {
self
}
fn set_inode(&self, inode: Option<Arc<KernFSInode>>) {
self.inner().kobj_common.kern_inode = inode;
}
fn inode(&self) -> Option<Arc<KernFSInode>> {
self.inner().kobj_common.kern_inode.clone()
}
fn parent(&self) -> Option<Weak<dyn KObject>> {
self.inner().kobj_common.parent.clone()
}
fn set_parent(&self, parent: Option<Weak<dyn KObject>>) {
self.inner().kobj_common.parent = parent;
}
fn kset(&self) -> Option<Arc<KSet>> {
self.inner().kobj_common.kset.clone()
}
fn set_kset(&self, kset: Option<Arc<KSet>>) {
self.inner().kobj_common.kset = kset;
}
fn kobj_type(&self) -> Option<&'static dyn KObjType> {
self.inner().kobj_common.kobj_type
}
fn name(&self) -> String {
Self::DEVICE_NAME.to_string()
}
fn set_name(&self, _name: String) {
// do nothing
}
fn kobj_state(&self) -> RwLockReadGuard<KObjectState> {
self.locked_kobj_state.read()
}
fn kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState> {
self.locked_kobj_state.write()
}
fn set_kobj_state(&self, state: KObjectState) {
*self.locked_kobj_state.write() = state;
}
fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>) {
self.inner().kobj_common.kobj_type = ktype;
}
}
impl Device for LoopbackInterface {
fn dev_type(&self) -> DeviceType {
DeviceType::Net
}
fn id_table(&self) -> IdTable {
IdTable::new(DEVICE_NAME.to_string(), None)
}
fn bus(&self) -> Option<Weak<dyn Bus>> {
self.inner().device_common.bus.clone()
}
fn set_bus(&self, bus: Option<Weak<dyn Bus>>) {
self.inner().device_common.bus = bus;
}
fn class(&self) -> Option<Arc<dyn Class>> {
let mut guard = self.inner();
let r = guard.device_common.class.clone()?.upgrade();
if r.is_none() {
guard.device_common.class = None;
}
return r;
}
fn set_class(&self, class: Option<Weak<dyn Class>>) {
self.inner().device_common.class = class;
}
fn driver(&self) -> Option<Arc<dyn Driver>> {
let r = self.inner().device_common.driver.clone()?.upgrade();
if r.is_none() {
self.inner().device_common.driver = None;
}
return r;
}
fn set_driver(&self, driver: Option<Weak<dyn Driver>>) {
self.inner().device_common.driver = driver;
}
fn is_dead(&self) -> bool {
false
}
fn can_match(&self) -> bool {
self.inner().device_common.can_match
}
fn set_can_match(&self, can_match: bool) {
self.inner().device_common.can_match = can_match;
}
fn state_synced(&self) -> bool {
true
}
fn dev_parent(&self) -> Option<Weak<dyn Device>> {
self.inner().device_common.get_parent_weak_or_clear()
}
fn set_dev_parent(&self, parent: Option<Weak<dyn Device>>) {
self.inner().device_common.parent = parent;
}
}
impl Iface for LoopbackInterface {
fn common(&self) -> &IfaceCommon {
&self.common
}
fn iface_name(&self) -> String {
Self::DEVICE_NAME.to_string()
}
/// 由于lo网卡设备不是实际的物理设备其mac地址需要手动设置为一个默认值这里默认为00:00:00:00:00
fn mac(&self) -> smoltcp::wire::EthernetAddress {
let mac = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
smoltcp::wire::EthernetAddress(mac)
}
fn poll(&self) {
self.common.poll(self.driver.force_get_mut())
}
fn addr_assign_type(&self) -> u8 {
return self.inner().netdevice_common.addr_assign_type;
}
fn net_device_type(&self) -> u16 {
self.inner().netdevice_common.net_device_type = 24; // 环回设备
return self.inner().netdevice_common.net_device_type;
}
fn net_state(&self) -> NetDeivceState {
return self.inner().netdevice_common.state;
}
fn set_net_state(&self, state: NetDeivceState) {
self.inner().netdevice_common.state |= state;
}
fn operstate(&self) -> Operstate {
return self.inner().netdevice_common.operstate;
}
fn set_operstate(&self, state: Operstate) {
self.inner().netdevice_common.operstate = state;
}
}
pub fn loopback_probe() {
loopback_driver_init();
}
/// # lo网卡设备初始化函数
/// 创建驱动和iface初始化一个lo网卡添加到全局NET_DEVICES中
pub fn loopback_driver_init() {
let driver = LoopbackDriver::new();
let iface = LoopbackInterface::new(driver);
// 标识网络设备已经启动
iface.set_net_state(NetDeivceState::__LINK_STATE_START);
NET_DEVICES
.write_irqsave()
.insert(iface.nic_id(), iface.clone());
register_netdevice(iface.clone()).expect("register lo device failed");
}
/// ## lo网卡设备的注册函数
#[unified_init(INITCALL_DEVICE)]
pub fn loopback_init() -> Result<(), SystemError> {
loopback_probe();
log::debug!("Successfully init loopback device");
return Ok(());
}