DragonOS/kernel/src/driver/net/loopback.rs
LoGin bd70d2d1f4
chore: 将工具链更新到2024-07-23 (#864)
* chore: 将工具链更新到2024-07-23
2024-07-25 00:55:02 +08:00

484 lines
15 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, DeviceType, IdTable};
use crate::driver::base::kobject::{KObjType, KObject, KObjectState};
use crate::init::initcall::INITCALL_DEVICE;
use crate::libs::spinlock::SpinLock;
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::NetDevice;
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>(mut self, f: F) -> R
where
F: FnOnce(&mut [u8]) -> R,
{
f(self.buffer.as_mut_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);
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!");
self.queue.push_back(buffer)
}
}
/// ## driver的包裹器
/// 为实现获得不可变引用的Interface的内部可变性故为Driver提供UnsafeCell包裹器
///
/// 参考virtio_net.rs
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::Ethernet;
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() {
return Option::None;
}
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<'_>> {
Some(LoopbackTxToken {
driver: self.clone(),
})
}
}
/// ## LoopbackInterface结构
/// 封装驱动包裹器和iface设置接口名称
pub struct LoopbackInterface {
driver: LoopbackDriverWapper,
iface_id: usize,
iface: SpinLock<smoltcp::iface::Interface>,
name: String,
}
impl LoopbackInterface {
/// ## `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 mut iface_config = smoltcp::iface::Config::new(HardwareAddress::Ethernet(
smoltcp::wire::EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]),
));
iface_config.random_seed = rand() as u64;
let mut iface =
smoltcp::iface::Interface::new(iface_config, &mut driver, Instant::now().into());
//设置网卡地址为127.0.0.1
iface.update_ip_addrs(|ip_addrs| {
ip_addrs
.push(IpCidr::new(IpAddress::v4(127, 0, 0, 1), 8))
.unwrap();
});
let driver = LoopbackDriverWapper(UnsafeCell::new(driver));
Arc::new(LoopbackInterface {
driver,
iface_id,
iface: SpinLock::new(iface),
name: "lo".to_string(),
})
}
}
impl Debug for LoopbackInterface {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("LoopbackInterface")
.field("iface_id", &self.iface_id)
.field("iface", &"smtoltcp::iface::Interface")
.field("name", &self.name)
.finish()
}
}
//TODO: 向sysfs注册lo设备
impl KObject for LoopbackInterface {
fn as_any_ref(&self) -> &dyn core::any::Any {
self
}
fn set_inode(&self, _inode: Option<Arc<crate::filesystem::kernfs::KernFSInode>>) {
todo!()
}
fn inode(&self) -> Option<Arc<crate::filesystem::kernfs::KernFSInode>> {
todo!()
}
fn parent(&self) -> Option<alloc::sync::Weak<dyn KObject>> {
todo!()
}
fn set_parent(&self, _parent: Option<alloc::sync::Weak<dyn KObject>>) {
todo!()
}
fn kset(&self) -> Option<Arc<crate::driver::base::kset::KSet>> {
todo!()
}
fn set_kset(&self, _kset: Option<Arc<crate::driver::base::kset::KSet>>) {
todo!()
}
fn kobj_type(&self) -> Option<&'static dyn crate::driver::base::kobject::KObjType> {
todo!()
}
fn name(&self) -> String {
self.name.clone()
}
fn set_name(&self, _name: String) {
todo!()
}
fn kobj_state(
&self,
) -> crate::libs::rwlock::RwLockReadGuard<crate::driver::base::kobject::KObjectState> {
todo!()
}
fn kobj_state_mut(
&self,
) -> crate::libs::rwlock::RwLockWriteGuard<crate::driver::base::kobject::KObjectState> {
todo!()
}
fn set_kobj_state(&self, _state: KObjectState) {
todo!()
}
fn set_kobj_type(&self, _ktype: Option<&'static dyn KObjType>) {
todo!()
}
}
impl Device for LoopbackInterface {
fn dev_type(&self) -> DeviceType {
DeviceType::Net
}
fn id_table(&self) -> IdTable {
IdTable::new(DEVICE_NAME.to_string(), None)
}
fn set_bus(&self, _bus: Option<Weak<dyn Bus>>) {
todo!()
}
fn set_class(&self, _class: Option<Weak<dyn Class>>) {
todo!()
}
fn driver(&self) -> Option<Arc<dyn Driver>> {
todo!()
}
fn set_driver(&self, _driver: Option<Weak<dyn Driver>>) {
todo!()
}
fn is_dead(&self) -> bool {
todo!()
}
fn can_match(&self) -> bool {
todo!()
}
fn set_can_match(&self, _can_match: bool) {
todo!()
}
fn state_synced(&self) -> bool {
true
}
}
impl NetDevice for LoopbackInterface {
/// 由于lo网卡设备不是实际的物理设备其mac地址需要手动设置为一个默认值这里默认为0200000001
fn mac(&self) -> smoltcp::wire::EthernetAddress {
let mac = [0x02, 0x00, 0x00, 0x00, 0x00, 0x01];
smoltcp::wire::EthernetAddress(mac)
}
#[inline]
fn nic_id(&self) -> usize {
self.iface_id
}
#[inline]
fn name(&self) -> String {
self.name.clone()
}
/// ## `update_ip_addrs` 用于更新接口的 IP 地址。
///
/// ## 参数
/// - `&self` :自身引用
/// - `ip_addrs` :一个包含 `smoltcp::wire::IpCidr` 的切片,表示要设置的 IP 地址和子网掩码
///
/// ## 返回值
/// - 如果 `ip_addrs` 的长度不为 1返回 `Err(SystemError::EINVAL)`,表示输入参数无效
/// - 如果更新成功,返回 `Ok(())`
fn update_ip_addrs(
&self,
ip_addrs: &[smoltcp::wire::IpCidr],
) -> Result<(), system_error::SystemError> {
if ip_addrs.len() != 1 {
return Err(SystemError::EINVAL);
}
self.iface.lock().update_ip_addrs(|addrs| {
let dest = addrs.iter_mut().next();
if let Some(dest) = dest {
*dest = ip_addrs[0];
} else {
addrs.push(ip_addrs[0]).expect("Push ipCidr failed: full");
}
});
return Ok(());
}
/// ## `poll` 用于轮询接口的状态。
///
/// ## 参数
/// - `&self` :自身引用
/// - `sockets` :一个可变引用到 `smoltcp::iface::SocketSet`,表示要轮询的套接字集
///
/// ## 返回值
/// - 如果轮询成功,返回 `Ok(())`
/// - 如果轮询失败,返回 `Err(SystemError::EAGAIN_OR_EWOULDBLOCK)`,表示需要再次尝试或者操作会阻塞
fn poll(&self, sockets: &mut smoltcp::iface::SocketSet) -> Result<(), SystemError> {
let timestamp: smoltcp::time::Instant = Instant::now().into();
let mut guard = self.iface.lock();
let poll_res = guard.poll(timestamp, self.driver.force_get_mut(), sockets);
if poll_res {
return Ok(());
}
return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
}
#[inline(always)]
fn inner_iface(&self) -> &SpinLock<smoltcp::iface::Interface> {
return &self.iface;
}
}
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);
NET_DEVICES
.write_irqsave()
.insert(iface.iface_id, iface.clone());
}
/// ## lo网卡设备的注册函数
#[unified_init(INITCALL_DEVICE)]
pub fn loopback_init() -> Result<(), SystemError> {
loopback_probe();
return Ok(());
}