mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-19 09:06:32 +00:00
ready for merge in master (#964)
uevent should be format Enum of smoltcp socket should be optimized. need to add interface for routing subsys actix is still not abled to run. clean some casual added code to other places
This commit is contained in:
@ -22,7 +22,8 @@ use log::{debug, error, warn};
|
||||
use system_error::SystemError;
|
||||
|
||||
use super::{acpi_kset, AcpiManager};
|
||||
|
||||
use crate::driver::base::uevent::kobject_uevent::kobject_uevent;
|
||||
use crate::driver::base::uevent::KobjectAction;
|
||||
static mut __HOTPLUG_KSET_INSTANCE: Option<Arc<KSet>> = None;
|
||||
static mut __ACPI_TABLES_KSET_INSTANCE: Option<Arc<KSet>> = None;
|
||||
static mut __ACPI_TABLES_DATA_KSET_INSTANCE: Option<Arc<KSet>> = None;
|
||||
@ -115,7 +116,27 @@ impl AcpiManager {
|
||||
acpi_table_attr_list().write().push(attr);
|
||||
self.acpi_table_data_init(&header)?;
|
||||
}
|
||||
|
||||
// TODO:UEVENT
|
||||
unsafe {
|
||||
let _ = kobject_uevent(
|
||||
acpi_tables_kset.clone() as Arc<dyn KObject>,
|
||||
KobjectAction::KOBJADD,
|
||||
);
|
||||
let _ = kobject_uevent(
|
||||
__ACPI_TABLES_DATA_KSET_INSTANCE
|
||||
.as_ref()
|
||||
.map(|kset| kset.clone() as Arc<dyn KObject>)
|
||||
.unwrap(),
|
||||
KobjectAction::KOBJADD,
|
||||
);
|
||||
let _ = kobject_uevent(
|
||||
__ACPI_TABLES_DYNAMIC_KSET_INSTANCE
|
||||
.as_ref()
|
||||
.map(|kset| kset.clone() as Arc<dyn KObject>)
|
||||
.unwrap(),
|
||||
KobjectAction::KOBJADD,
|
||||
);
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
|
@ -571,6 +571,7 @@ impl DriverManager {
|
||||
}
|
||||
|
||||
// todo: 发送kobj bind的uevent
|
||||
// kobject_uevent();
|
||||
}
|
||||
|
||||
fn driver_is_bound(&self, device: &Arc<dyn Device>) -> bool {
|
||||
|
@ -2,6 +2,8 @@ use super::{
|
||||
bus::{bus_manager, Bus},
|
||||
Device, DeviceMatchName, DeviceMatcher, IdTable,
|
||||
};
|
||||
use crate::driver::base::uevent::kobject_uevent::kobject_uevent;
|
||||
use crate::driver::base::uevent::KobjectAction;
|
||||
use crate::{
|
||||
driver::base::{
|
||||
device::{bus::BusNotifyEvent, dd::DeviceAttrCoredump, device_manager},
|
||||
@ -17,7 +19,6 @@ use alloc::{
|
||||
use core::fmt::Debug;
|
||||
use log::error;
|
||||
use system_error::SystemError;
|
||||
|
||||
/// @brief: Driver error
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
@ -218,7 +219,9 @@ impl DriverManager {
|
||||
bus_manager().remove_driver(&driver);
|
||||
})?;
|
||||
|
||||
// todo: 发送uevent
|
||||
// todo: 发送uevent,类型问题
|
||||
let _ = kobject_uevent(driver.clone() as Arc<dyn KObject>, KobjectAction::KOBJADD);
|
||||
// deferred_probe_extend_timeout();
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
@ -506,7 +506,7 @@ impl DeviceManager {
|
||||
}
|
||||
let kobject_parent = self.get_device_parent(&device, deivce_parent)?;
|
||||
if let Some(ref kobj) = kobject_parent {
|
||||
log::debug!("kobject parent: {:?}", kobj.name());
|
||||
log::info!("kobject parent: {:?}", kobj.name());
|
||||
}
|
||||
if let Some(kobject_parent) = kobject_parent {
|
||||
// debug!(
|
||||
@ -547,7 +547,7 @@ impl DeviceManager {
|
||||
}
|
||||
|
||||
// todo: 发送uevent: KOBJ_ADD
|
||||
|
||||
// kobject_uevent();
|
||||
// probe drivers for a new device
|
||||
bus_probe_device(&device);
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
use core::{any::Any, fmt::Debug, hash::Hash, ops::Deref};
|
||||
|
||||
use alloc::{
|
||||
boxed::Box,
|
||||
string::String,
|
||||
sync::{Arc, Weak},
|
||||
};
|
||||
@ -21,7 +22,7 @@ use crate::{
|
||||
|
||||
use system_error::SystemError;
|
||||
|
||||
use super::kset::KSet;
|
||||
use super::{kset::KSet, uevent::kobject_uevent};
|
||||
|
||||
pub trait KObject: Any + Send + Sync + Debug + CastFromSync {
|
||||
fn as_any_ref(&self) -> &dyn core::any::Any;
|
||||
@ -103,10 +104,9 @@ bitflags! {
|
||||
const ADD_UEVENT_SENT = 1 << 1;
|
||||
const REMOVE_UEVENT_SENT = 1 << 2;
|
||||
const INITIALIZED = 1 << 3;
|
||||
const UEVENT_SUPPRESS = 1 << 4;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct LockedKObjectState(RwLock<KObjectState>);
|
||||
|
||||
@ -251,7 +251,7 @@ impl KObjectManager {
|
||||
}
|
||||
|
||||
// todo: 发送uevent: KOBJ_REMOVE
|
||||
|
||||
// kobject_uevent();
|
||||
sysfs_instance().remove_dir(&kobj);
|
||||
kobj.update_kobj_state(None, Some(KObjectState::IN_SYSFS));
|
||||
let kset = kobj.kset();
|
||||
@ -260,6 +260,105 @@ impl KObjectManager {
|
||||
}
|
||||
kobj.set_parent(None);
|
||||
}
|
||||
|
||||
fn get_kobj_path_length(kobj: &Arc<dyn KObject>) -> usize {
|
||||
log::info!("get_kobj_path_length() kobj:{:?}", kobj.name());
|
||||
let mut length = 1;
|
||||
let mut parent = kobj.parent().unwrap().upgrade().unwrap();
|
||||
/* walk up the ancestors until we hit the one pointing to the
|
||||
* root.
|
||||
* Add 1 to strlen for leading '/' of each level.
|
||||
*/
|
||||
let mut length = 0; // 确保 length 被正确初始化
|
||||
let mut iteration_count = 0; // 用于记录迭代次数
|
||||
const MAX_ITERATIONS: usize = 10; // 最大迭代次数
|
||||
|
||||
loop {
|
||||
log::info!(
|
||||
"Iteration {}: parent.name():{:?}",
|
||||
iteration_count,
|
||||
parent.name()
|
||||
);
|
||||
length += parent.name().len() + 1;
|
||||
if let Some(weak_parent) = parent.parent() {
|
||||
if let Some(upgraded_parent) = weak_parent.upgrade() {
|
||||
parent = upgraded_parent;
|
||||
} else {
|
||||
log::error!("Failed to upgrade weak reference to parent");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
log::error!("Parent has no parent");
|
||||
break;
|
||||
}
|
||||
|
||||
iteration_count += 1;
|
||||
if iteration_count >= MAX_ITERATIONS {
|
||||
log::error!("Reached maximum iteration count, breaking to avoid infinite loop");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
/*
|
||||
static void fill_kobj_path(struct kobject *kobj, char *path, int length)
|
||||
{
|
||||
struct kobject *parent;
|
||||
|
||||
--length;
|
||||
for (parent = kobj; parent; parent = parent->parent) {
|
||||
int cur = strlen(kobject_name(parent));
|
||||
/* back up enough to print this name with '/' */
|
||||
length -= cur;
|
||||
memcpy(path + length, kobject_name(parent), cur);
|
||||
*(path + --length) = '/';
|
||||
}
|
||||
|
||||
pr_debug("kobject: '%s' (%p): %s: path = '%s'\n", kobject_name(kobj),
|
||||
kobj, __func__, path);
|
||||
}
|
||||
*/
|
||||
fn fill_kobj_path(kobj: &Arc<dyn KObject>, path: &mut [u8], length: usize) {
|
||||
let mut parent = kobj.parent().unwrap().upgrade().unwrap();
|
||||
let mut length = length;
|
||||
length -= 1;
|
||||
loop {
|
||||
log::info!("fill_kobj_path parent.name():{:?}", parent.name());
|
||||
let cur = parent.name().len();
|
||||
if length < cur + 1 {
|
||||
// 如果剩余长度不足以容纳当前名称和分隔符,则退出
|
||||
break;
|
||||
}
|
||||
length -= cur;
|
||||
let parent_name = parent.name();
|
||||
let name = parent_name.as_bytes();
|
||||
for i in 0..cur {
|
||||
path[length + i] = name[i];
|
||||
}
|
||||
length -= 1;
|
||||
path[length] = '/' as u8;
|
||||
if let Some(weak_parent) = parent.parent() {
|
||||
if let Some(upgraded_parent) = weak_parent.upgrade() {
|
||||
parent = upgraded_parent;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO: 实现kobject_get_path
|
||||
// https://code.dragonos.org.cn/xref/linux-6.1.9/lib/kobject.c#139
|
||||
pub fn kobject_get_path(kobj: &Arc<dyn KObject>) -> String {
|
||||
log::debug!("kobject_get_path() kobj:{:?}", kobj.name());
|
||||
let length = Self::get_kobj_path_length(kobj);
|
||||
let path: &mut [u8] = &mut vec![0; length];
|
||||
Self::fill_kobj_path(kobj, path, length);
|
||||
let path_string = String::from_utf8(path.to_vec()).unwrap();
|
||||
return path_string;
|
||||
}
|
||||
}
|
||||
|
||||
/// 动态创建的kobject对象的ktype
|
||||
|
@ -6,8 +6,11 @@ use alloc::{
|
||||
|
||||
use core::hash::Hash;
|
||||
|
||||
use super::kobject::{
|
||||
DynamicKObjKType, KObjType, KObject, KObjectManager, KObjectState, LockedKObjectState,
|
||||
use super::{
|
||||
kobject::{
|
||||
DynamicKObjKType, KObjType, KObject, KObjectManager, KObjectState, LockedKObjectState,
|
||||
},
|
||||
uevent::KobjUeventEnv,
|
||||
};
|
||||
use crate::{
|
||||
filesystem::kernfs::KernFSInode,
|
||||
@ -26,6 +29,8 @@ pub struct KSet {
|
||||
/// 与父节点有关的一些信息
|
||||
parent_data: RwLock<KSetParentData>,
|
||||
self_ref: Weak<KSet>,
|
||||
/// kset用于发送uevent的操作函数集。kset能够发送它所包含的各种子kobj、孙kobj的消息,即kobj或其父辈、爷爷辈,都可以发送消息;优先父辈,然后是爷爷辈,以此类推
|
||||
pub uevent_ops: Option<Arc<dyn KSetUeventOps>>,
|
||||
}
|
||||
|
||||
impl Hash for KSet {
|
||||
@ -51,6 +56,7 @@ impl KSet {
|
||||
kobj_state: LockedKObjectState::new(None),
|
||||
parent_data: RwLock::new(KSetParentData::new(None, None)),
|
||||
self_ref: Weak::default(),
|
||||
uevent_ops: Some(Arc::new(KSetUeventOpsDefault)),
|
||||
};
|
||||
|
||||
let r = Arc::new(r);
|
||||
@ -91,6 +97,7 @@ impl KSet {
|
||||
pub fn register(&self, join_kset: Option<Arc<KSet>>) -> Result<(), SystemError> {
|
||||
return KObjectManager::add_kobj(self.self_ref.upgrade().unwrap(), join_kset);
|
||||
// todo: 引入uevent之后,发送uevent
|
||||
// kobject_uevent();
|
||||
}
|
||||
|
||||
/// 注销一个kset
|
||||
@ -232,3 +239,26 @@ impl InnerKSet {
|
||||
}
|
||||
}
|
||||
}
|
||||
//https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/kobject.h#137
|
||||
use core::fmt::Debug;
|
||||
pub trait KSetUeventOps: Debug + Send + Sync {
|
||||
fn filter(&self) -> Option<i32>;
|
||||
fn uevent_name(&self) -> String;
|
||||
fn uevent(&self, env: &KobjUeventEnv) -> i32;
|
||||
}
|
||||
#[derive(Debug)]
|
||||
pub struct KSetUeventOpsDefault;
|
||||
|
||||
impl KSetUeventOps for KSetUeventOpsDefault {
|
||||
fn filter(&self) -> Option<i32> {
|
||||
Some(0)
|
||||
}
|
||||
|
||||
fn uevent_name(&self) -> String {
|
||||
String::new()
|
||||
}
|
||||
|
||||
fn uevent(&self, env: &KobjUeventEnv) -> i32 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
@ -12,3 +12,4 @@ pub mod map;
|
||||
pub mod platform;
|
||||
pub mod subsys;
|
||||
pub mod swnode;
|
||||
pub mod uevent;
|
||||
|
504
kernel/src/driver/base/uevent/kobject_uevent.rs
Normal file
504
kernel/src/driver/base/uevent/kobject_uevent.rs
Normal file
@ -0,0 +1,504 @@
|
||||
// https://code.dragonos.org.cn/xref/linux-6.1.9/lib/kobject_uevent.c
|
||||
use super::KObject;
|
||||
use super::KobjUeventEnv;
|
||||
use super::KobjectAction;
|
||||
use super::{UEVENT_BUFFER_SIZE, UEVENT_NUM_ENVP};
|
||||
use crate::driver::base::kobject::{KObjectManager, KObjectState};
|
||||
use crate::init::initcall::INITCALL_POSTCORE;
|
||||
use crate::libs::mutex::Mutex;
|
||||
use crate::libs::rwlock::RwLock;
|
||||
use crate::net::socket::netlink::af_netlink::netlink_has_listeners;
|
||||
use crate::net::socket::netlink::af_netlink::NetlinkSocket;
|
||||
use crate::net::socket::netlink::af_netlink::{netlink_broadcast, NetlinkSock};
|
||||
use crate::net::socket::netlink::netlink::{
|
||||
netlink_kernel_create, NetlinkKernelCfg, NETLINK_KOBJECT_UEVENT, NL_CFG_F_NONROOT_RECV,
|
||||
};
|
||||
use crate::net::socket::netlink::skbuff::SkBuff;
|
||||
use alloc::boxed::Box;
|
||||
use alloc::collections::LinkedList;
|
||||
use alloc::string::{String, ToString};
|
||||
use alloc::sync::Arc;
|
||||
use alloc::vec::Vec;
|
||||
use core::fmt::Write;
|
||||
use num::Zero;
|
||||
use system_error::SystemError;
|
||||
use unified_init::macros::unified_init;
|
||||
// 全局变量
|
||||
pub static UEVENT_SEQNUM: u64 = 0;
|
||||
// #ifdef CONFIG_UEVENT_HELPER
|
||||
// char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH;
|
||||
// #endif
|
||||
|
||||
struct UeventSock {
|
||||
inner: NetlinkSock,
|
||||
}
|
||||
impl UeventSock {
|
||||
pub fn new(inner: NetlinkSock) -> Self {
|
||||
UeventSock { inner }
|
||||
}
|
||||
}
|
||||
|
||||
// 用于存储所有用于发送 uevent 消息的 netlink sockets。这些 sockets 用于在内核和用户空间之间传递设备事件通知。
|
||||
// 每当需要发送 uevent 消息时,内核会遍历这个链表,并通过其中的每一个 socket 发送消息。
|
||||
// 使用 Mutex 保护全局链表
|
||||
lazy_static::lazy_static! {
|
||||
static ref UEVENT_SOCK_LIST: Mutex<LinkedList<UeventSock>> = Mutex::new(LinkedList::new());
|
||||
}
|
||||
// 回调函数,当接收到 uevent 消息时调用
|
||||
fn uevent_net_rcv() {
|
||||
// netlink_rcv_skb(skb, &uevent_net_rcv_skb);
|
||||
}
|
||||
|
||||
/// 内核初始化的时候,在设备初始化之前执行
|
||||
#[unified_init(INITCALL_POSTCORE)]
|
||||
fn kobejct_uevent_init() -> Result<(), SystemError> {
|
||||
// todo: net namespace
|
||||
return uevent_net_init();
|
||||
}
|
||||
// TODO:等net namespace实现后添加 net 参数和相关操作
|
||||
// 内核启动的时候,即使没有进行网络命名空间的隔离也需要调用这个函数
|
||||
// 支持 net namespace 之后需要在每个 net namespace 初始化的时候调用这个函数
|
||||
/// 为每一个 net namespace 初始化 uevent
|
||||
fn uevent_net_init() -> Result<(), SystemError> {
|
||||
let cfg = NetlinkKernelCfg {
|
||||
groups: 1,
|
||||
flags: NL_CFG_F_NONROOT_RECV,
|
||||
..Default::default()
|
||||
};
|
||||
// 创建一个内核 netlink socket
|
||||
let ue_sk = UeventSock::new(netlink_kernel_create(NETLINK_KOBJECT_UEVENT, Some(cfg)).unwrap());
|
||||
|
||||
// todo: net namespace
|
||||
// net.uevent_sock = ue_sk;
|
||||
|
||||
// 每个 net namespace 向链表中添加一个新的 uevent socket
|
||||
UEVENT_SOCK_LIST.lock().push_back(ue_sk);
|
||||
log::info!("uevent_net_init finish");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// 系统关闭时清理
|
||||
fn uevent_net_exit() {
|
||||
// 清理链表
|
||||
UEVENT_SOCK_LIST.lock().clear();
|
||||
}
|
||||
|
||||
// /* This lock protects uevent_seqnum and uevent_sock_list */
|
||||
// static DEFINE_MUTEX(uevent_sock_mutex);
|
||||
|
||||
// to be adjust
|
||||
pub const BUFFERSIZE: usize = 666;
|
||||
|
||||
/*
|
||||
kobject_uevent_env,以envp为环境变量,上报一个指定action的uevent。环境变量的作用是为执行用户空间程序指定运行环境。具体动作如下:
|
||||
|
||||
查找kobj本身或者其parent是否从属于某个kset,如果不是,则报错返回(注2:由此可以说明,如果一个kobject没有加入kset,是不允许上报uevent的)
|
||||
查看kobj->uevent_suppress是否设置,如果设置,则忽略所有的uevent上报并返回(注3:由此可知,可以通过Kobject的uevent_suppress标志,管控Kobject的uevent的上报)
|
||||
如果所属的kset有kset->filter函数,则调用该函数,过滤此次上报(注4:这佐证了3.2小节有关filter接口的说明,kset可以通过filter接口过滤不希望上报的event,从而达到整体的管理效果)
|
||||
判断所属的kset是否有合法的名称(称作subsystem,和前期的内核版本有区别),否则不允许上报uevent
|
||||
分配一个用于此次上报的、存储环境变量的buffer(结果保存在env指针中),并获得该Kobject在sysfs中路径信息(用户空间软件需要依据该路径信息在sysfs中访问它)
|
||||
调用add_uevent_var接口(下面会介绍),将Action、路径信息、subsystem等信息,添加到env指针中
|
||||
如果传入的envp不空,则解析传入的环境变量中,同样调用add_uevent_var接口,添加到env指针中
|
||||
如果所属的kset存在kset->uevent接口,调用该接口,添加kset统一的环境变量到env指针
|
||||
根据ACTION的类型,设置kobj->state_add_uevent_sent和kobj->state_remove_uevent_sent变量,以记录正确的状态
|
||||
调用add_uevent_var接口,添加格式为"SEQNUM=%llu”的序列号
|
||||
如果定义了"CONFIG_NET”,则使用netlink发送该uevent
|
||||
以uevent_helper、subsystem以及添加了标准环境变量(HOME=/,PATH=/sbin:/bin:/usr/sbin:/usr/bin)的env指针为参数,调用kmod模块提供的call_usermodehelper函数,上报uevent。
|
||||
其中uevent_helper的内容是由内核配置项CONFIG_UEVENT_HELPER_PATH(位于./drivers/base/Kconfig)决定的(可参考lib/kobject_uevent.c, line 32),该配置项指定了一个用户空间程序(或者脚本),用于解析上报的uevent,例如"/sbin/hotplug”。
|
||||
call_usermodehelper的作用,就是fork一个进程,以uevent为参数,执行uevent_helper。
|
||||
|
||||
kobject_uevent,和kobject_uevent_env功能一样,只是没有指定任何的环境变量。
|
||||
|
||||
add_uevent_var,以格式化字符的形式(类似printf、printk等),将环境变量copy到env指针中。
|
||||
|
||||
kobject_action_type,将enum kobject_action类型的Action,转换为字符串
|
||||
*/
|
||||
|
||||
//kobject_uevent->kobject_uevent_env
|
||||
pub fn kobject_uevent(kobj: Arc<dyn KObject>, action: KobjectAction) -> Result<(), SystemError> {
|
||||
// kobject_uevent和kobject_uevent_env功能一样,只是没有指定任何的环境变量
|
||||
match kobject_uevent_env(kobj, action, None) {
|
||||
Ok(_) => Ok(()),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
pub fn kobject_uevent_env(
|
||||
kobj: Arc<dyn KObject>,
|
||||
action: KobjectAction,
|
||||
envp_ext: Option<Vec<String>>,
|
||||
) -> Result<i32, SystemError> {
|
||||
log::info!("kobject_uevent_env: kobj: {:?}, action: {:?}", kobj, action);
|
||||
let mut state = KObjectState::empty();
|
||||
let mut top_kobj = kobj.parent().unwrap().upgrade().unwrap();
|
||||
let mut retval: i32;
|
||||
let action_string = match action {
|
||||
KobjectAction::KOBJADD => "add".to_string(),
|
||||
KobjectAction::KOBJREMOVE => "remove".to_string(),
|
||||
KobjectAction::KOBJCHANGE => "change".to_string(),
|
||||
KobjectAction::KOBJMOVE => "move".to_string(),
|
||||
KobjectAction::KOBJONLINE => "online".to_string(),
|
||||
KobjectAction::KOBJOFFLINE => "offline".to_string(),
|
||||
KobjectAction::KOBJBIND => "bind".to_string(),
|
||||
KobjectAction::KOBJUNBIND => "unbind".to_string(),
|
||||
};
|
||||
/*
|
||||
* Mark "remove" event done regardless of result, for some subsystems
|
||||
* do not want to re-trigger "remove" event via automatic cleanup.
|
||||
*/
|
||||
if let KobjectAction::KOBJREMOVE = action {
|
||||
log::info!("kobject_uevent_env: action: remove");
|
||||
state.insert(KObjectState::REMOVE_UEVENT_SENT);
|
||||
}
|
||||
|
||||
// 不断向上查找,直到找到最顶层的kobject
|
||||
while let Some(weak_parent) = top_kobj.parent() {
|
||||
log::info!("kobject_uevent_env: top_kobj: {:?}", top_kobj);
|
||||
top_kobj = weak_parent.upgrade().unwrap();
|
||||
}
|
||||
/* 查找当前kobject或其parent是否从属于某个kset;如果都不从属于某个kset,则返回错误。(说明一个kobject若没有加入kset,是不会上报uevent的) */
|
||||
if kobj.kset().is_none() && top_kobj.kset().is_none() {
|
||||
log::info!("attempted to send uevent without kset!\n");
|
||||
return Err(SystemError::EINVAL);
|
||||
}
|
||||
|
||||
let kset = top_kobj.kset();
|
||||
// 判断该 kobject 的状态是否设置了uevent_suppress,如果设置了,则忽略所有的uevent上报并返回
|
||||
if kobj.kobj_state().contains(KObjectState::UEVENT_SUPPRESS) {
|
||||
log::info!("uevent_suppress caused the event to drop!");
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
// 如果所属的kset的kset->filter返回的是0,过滤此次上报
|
||||
if let Some(kset_ref) = kset.as_ref() {
|
||||
if let Some(uevent_ops) = &kset_ref.uevent_ops {
|
||||
if uevent_ops.filter() == Some(0) {
|
||||
log::info!("filter caused the event to drop!");
|
||||
return Ok(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 判断所属的kset是否有合法的名称(称作subsystem,和前期的内核版本有区别),否则不允许上报uevent
|
||||
// originating subsystem
|
||||
let subsystem: String = if let Some(kset_ref) = kset.as_ref() {
|
||||
if let Some(uevent_ops) = &kset_ref.uevent_ops {
|
||||
let name = uevent_ops.uevent_name();
|
||||
if !name.is_empty() {
|
||||
name
|
||||
} else {
|
||||
kobj.name()
|
||||
}
|
||||
} else {
|
||||
kobj.name()
|
||||
}
|
||||
} else {
|
||||
kobj.name()
|
||||
};
|
||||
if subsystem.is_empty() {
|
||||
log::info!("unset subsystem caused the event to drop!");
|
||||
}
|
||||
log::info!("kobject_uevent_env: subsystem: {}", subsystem);
|
||||
|
||||
// 创建一个用于环境变量的缓冲区
|
||||
let mut env = Box::new(KobjUeventEnv {
|
||||
argv: Vec::with_capacity(UEVENT_NUM_ENVP),
|
||||
envp: Vec::with_capacity(UEVENT_NUM_ENVP),
|
||||
envp_idx: 0,
|
||||
buf: vec![0; UEVENT_BUFFER_SIZE],
|
||||
buflen: 0,
|
||||
});
|
||||
if env.buf.is_empty() {
|
||||
log::error!("kobject_uevent_env: failed to allocate buffer");
|
||||
return Err(SystemError::ENOMEM);
|
||||
}
|
||||
|
||||
// 获取设备的完整对象路径
|
||||
let devpath: String = KObjectManager::kobject_get_path(&kobj);
|
||||
log::info!("kobject_uevent_env: devpath: {}", devpath);
|
||||
if devpath.is_empty() {
|
||||
retval = SystemError::ENOENT.to_posix_errno();
|
||||
// goto exit
|
||||
drop(devpath);
|
||||
drop(env);
|
||||
log::warn!("kobject_uevent_env: devpath is empty");
|
||||
return Ok(retval);
|
||||
}
|
||||
retval = add_uevent_var(&mut env, "ACTION=%s", &action_string).unwrap();
|
||||
log::info!("kobject_uevent_env: retval: {}", retval);
|
||||
if !retval.is_zero() {
|
||||
drop(devpath);
|
||||
drop(env);
|
||||
log::info!("add_uevent_var failed ACTION");
|
||||
return Ok(retval);
|
||||
};
|
||||
retval = add_uevent_var(&mut env, "DEVPATH=%s", &devpath).unwrap();
|
||||
if !retval.is_zero() {
|
||||
drop(devpath);
|
||||
drop(env);
|
||||
log::info!("add_uevent_var failed DEVPATH");
|
||||
return Ok(retval);
|
||||
};
|
||||
retval = add_uevent_var(&mut env, "SUBSYSTEM=%s", &subsystem).unwrap();
|
||||
if !retval.is_zero() {
|
||||
drop(devpath);
|
||||
drop(env);
|
||||
log::info!("add_uevent_var failed SUBSYSTEM");
|
||||
return Ok(retval);
|
||||
};
|
||||
|
||||
/* keys passed in from the caller */
|
||||
if let Some(env_ext) = envp_ext {
|
||||
for var in env_ext {
|
||||
let retval = add_uevent_var(&mut env, "%s", &var).unwrap();
|
||||
if !retval.is_zero() {
|
||||
drop(devpath);
|
||||
drop(env);
|
||||
log::info!("add_uevent_var failed");
|
||||
return Ok(retval);
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(kset_ref) = kset.as_ref() {
|
||||
if let Some(uevent_ops) = kset_ref.uevent_ops.as_ref() {
|
||||
if uevent_ops.uevent(&env) != 0 {
|
||||
retval = uevent_ops.uevent(&env);
|
||||
if retval.is_zero() {
|
||||
log::info!("kset uevent caused the event to drop!");
|
||||
// goto exit
|
||||
drop(devpath);
|
||||
drop(env);
|
||||
return Ok(retval);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
match action {
|
||||
KobjectAction::KOBJADD => {
|
||||
state.insert(KObjectState::ADD_UEVENT_SENT);
|
||||
}
|
||||
KobjectAction::KOBJUNBIND => {
|
||||
zap_modalias_env(&mut env);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
//mutex_lock(&uevent_sock_mutex);
|
||||
/* we will send an event, so request a new sequence number */
|
||||
retval = add_uevent_var(&mut env, "SEQNUM=%llu", &(UEVENT_SEQNUM + 1).to_string()).unwrap();
|
||||
if !retval.is_zero() {
|
||||
drop(devpath);
|
||||
drop(env);
|
||||
log::info!("add_uevent_var failed");
|
||||
return Ok(retval);
|
||||
}
|
||||
retval = kobject_uevent_net_broadcast(kobj, &env, &action_string, &devpath);
|
||||
//mutex_unlock(&uevent_sock_mutex);
|
||||
|
||||
#[cfg(feature = "UEVENT_HELPER")]
|
||||
fn handle_uevent_helper() {
|
||||
// TODO
|
||||
// 在特性 `UEVENT_HELPER` 开启的情况下,这里的代码会执行
|
||||
// 指定处理uevent的用户空间程序,通常是热插拔程序mdev、udevd等
|
||||
// /* call uevent_helper, usually only enabled during early boot */
|
||||
// if (uevent_helper[0] && !kobj_usermode_filter(kobj)) {
|
||||
// struct subprocess_info *info;
|
||||
|
||||
// retval = add_uevent_var(env, "HOME=/");
|
||||
// if (retval)
|
||||
// goto exit;
|
||||
// retval = add_uevent_var(env,
|
||||
// "PATH=/sbin:/bin:/usr/sbin:/usr/bin");
|
||||
// if (retval)
|
||||
// goto exit;
|
||||
// retval = init_uevent_argv(env, subsystem);
|
||||
// if (retval)
|
||||
// goto exit;
|
||||
|
||||
// retval = -ENOMEM;
|
||||
// info = call_usermodehelper_setup(env->argv[0], env->argv,
|
||||
// env->envp, GFP_KERNEL,
|
||||
// NULL, cleanup_uevent_env, env);
|
||||
// if (info) {
|
||||
// retval = call_usermodehelper_exec(info, UMH_NO_WAIT);
|
||||
// env = NULL; /* freed by cleanup_uevent_env */
|
||||
// }
|
||||
// }
|
||||
}
|
||||
#[cfg(not(feature = "UEVENT_HELPER"))]
|
||||
fn handle_uevent_helper() {
|
||||
// 在特性 `UEVENT_HELPER` 关闭的情况下,这里的代码会执行
|
||||
}
|
||||
handle_uevent_helper();
|
||||
drop(devpath);
|
||||
drop(env);
|
||||
log::info!("kobject_uevent_env: retval: {}", retval);
|
||||
return Ok(retval);
|
||||
}
|
||||
|
||||
pub fn add_uevent_var(
|
||||
env: &mut Box<KobjUeventEnv>,
|
||||
format: &str,
|
||||
args: &str,
|
||||
) -> Result<i32, SystemError> {
|
||||
log::info!("add_uevent_var: format: {}, args: {}", format, args);
|
||||
if env.envp_idx >= env.envp.capacity() {
|
||||
log::info!("add_uevent_var: too many keys");
|
||||
return Err(SystemError::ENOMEM);
|
||||
}
|
||||
|
||||
let mut buffer = String::new();
|
||||
write!(&mut buffer, "{} {}", format, args).map_err(|_| SystemError::ENOMEM)?;
|
||||
let len = buffer.len();
|
||||
|
||||
if len >= env.buf.capacity() - env.buflen {
|
||||
log::info!("add_uevent_var: buffer size too small");
|
||||
return Err(SystemError::ENOMEM);
|
||||
}
|
||||
|
||||
// Convert the buffer to bytes and add to env.buf
|
||||
env.buf.extend_from_slice(buffer.as_bytes());
|
||||
env.buf.push(0); // Null-terminate the string
|
||||
env.buflen += len + 1;
|
||||
|
||||
// Add the string to envp
|
||||
env.envp.push(buffer);
|
||||
env.envp_idx += 1;
|
||||
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
// 用于处理设备树中与模块相关的环境变量
|
||||
fn zap_modalias_env(env: &mut Box<KobjUeventEnv>) {
|
||||
// 定义一个静态字符串
|
||||
const MODALIAS_PREFIX: &str = "MODALIAS=";
|
||||
let mut len: usize;
|
||||
|
||||
let mut i = 0;
|
||||
while i < env.envp_idx {
|
||||
// 如果是以 MODALIAS= 开头的字符串
|
||||
if env.envp[i].starts_with(MODALIAS_PREFIX) {
|
||||
len = env.envp[i].len() + 1;
|
||||
// 如果不是最后一个元素
|
||||
if i != env.envp_idx - 1 {
|
||||
// 将后续的环境变量向前移动,以覆盖掉 "MODALIAS=" 前缀的环境变量
|
||||
for j in i..env.envp_idx - 1 {
|
||||
env.envp[j] = env.envp[j + 1].clone();
|
||||
}
|
||||
}
|
||||
// 减少环境变量数组的索引,因为一个变量已经被移除
|
||||
env.envp_idx -= 1;
|
||||
// 减少环境变量的总长度
|
||||
env.buflen -= len;
|
||||
} else {
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 用于处理网络相关的uevent(通用事件)广播
|
||||
// https://code.dragonos.org.cn/xref/linux-6.1.9/lib/kobject_uevent.c#381
|
||||
pub fn kobject_uevent_net_broadcast(
|
||||
kobj: Arc<dyn KObject>,
|
||||
env: &KobjUeventEnv,
|
||||
action_string: &str,
|
||||
devpath: &str,
|
||||
) -> i32 {
|
||||
let mut ret = 0;
|
||||
// let net:Net = None;
|
||||
// let mut ops = kobj_ns_ops(kobj);
|
||||
|
||||
// if (!ops && kobj.kset().is_some()) {
|
||||
// let ksobj:KObject = &kobj.kset().kobj();
|
||||
|
||||
// if (ksobj.parent() != NULL){
|
||||
// ops = kobj_ns_ops(ksobj.parent());
|
||||
// }
|
||||
|
||||
// }
|
||||
// TODO: net结构体?
|
||||
// https://code.dragonos.org.cn/xref/linux-6.1.9/include/net/net_namespace.h#60
|
||||
/* kobjects currently only carry network namespace tags and they
|
||||
* are the only tag relevant here since we want to decide which
|
||||
* network namespaces to broadcast the uevent into.
|
||||
*/
|
||||
// if (ops && ops.netlink_ns() && kobj.ktype().namespace())
|
||||
// if (ops.type() == KOBJ_NS_TYPE_NET)
|
||||
// net = kobj.ktype().namespace(kobj);
|
||||
// 如果有网络命名空间,则广播标记的uevent;如果没有,则广播未标记的uevent
|
||||
// if !net.is_none() {
|
||||
// ret = uevent_net_broadcast_tagged(net.unwrap(), env, action_string, devpath);
|
||||
// } else {
|
||||
ret = uevent_net_broadcast_untagged(env, action_string, devpath);
|
||||
// }
|
||||
log::info!("kobject_uevent_net_broadcast finish. ret: {}", ret);
|
||||
ret
|
||||
}
|
||||
|
||||
pub fn uevent_net_broadcast_tagged(
|
||||
sk: &dyn NetlinkSocket,
|
||||
env: &KobjUeventEnv,
|
||||
action_string: &str,
|
||||
devpath: &str,
|
||||
) -> i32 {
|
||||
let ret = 0;
|
||||
ret
|
||||
}
|
||||
|
||||
/// 分配一个用于 uevent 消息的 skb(socket buffer)。
|
||||
pub fn alloc_uevent_skb<'a>(
|
||||
env: &'a KobjUeventEnv,
|
||||
action_string: &'a str,
|
||||
devpath: &'a str,
|
||||
) -> Arc<RwLock<SkBuff>> {
|
||||
let skb = Arc::new(RwLock::new(SkBuff::new()));
|
||||
skb
|
||||
}
|
||||
// https://code.dragonos.org.cn/xref/linux-6.1.9/lib/kobject_uevent.c#309
|
||||
/// 广播一个未标记的 uevent 消息
|
||||
pub fn uevent_net_broadcast_untagged(
|
||||
env: &KobjUeventEnv,
|
||||
action_string: &str,
|
||||
devpath: &str,
|
||||
) -> i32 {
|
||||
log::info!(
|
||||
"uevent_net_broadcast_untagged: action_string: {}, devpath: {}",
|
||||
action_string,
|
||||
devpath
|
||||
);
|
||||
let mut retval = 0;
|
||||
let mut skb = Arc::new(RwLock::new(SkBuff::new()));
|
||||
|
||||
// 锁定 UEVENT_SOCK_LIST 并遍历
|
||||
let ue_sk_list = UEVENT_SOCK_LIST.lock();
|
||||
for ue_sk in ue_sk_list.iter() {
|
||||
// 如果没有监听者,则跳过
|
||||
if netlink_has_listeners(&ue_sk.inner, 1) == 0 {
|
||||
log::info!("uevent_net_broadcast_untagged: no listeners");
|
||||
continue;
|
||||
}
|
||||
// 如果 skb 为空,则分配一个新的 skb
|
||||
if skb.read().is_empty() {
|
||||
log::info!("uevent_net_broadcast_untagged: alloc_uevent_skb failed");
|
||||
retval = SystemError::ENOMEM.to_posix_errno();
|
||||
skb = alloc_uevent_skb(env, action_string, devpath);
|
||||
if skb.read().is_empty() {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
log::info!("next is netlink_broadcast");
|
||||
let netlink_socket: Arc<dyn NetlinkSocket> = Arc::new(ue_sk.inner.clone());
|
||||
retval = match netlink_broadcast(&netlink_socket, Arc::clone(&skb), 0, 1, 1) {
|
||||
Ok(_) => 0,
|
||||
Err(err) => err.to_posix_errno(),
|
||||
};
|
||||
log::info!("finished netlink_broadcast");
|
||||
// ENOBUFS should be handled in userspace
|
||||
if retval == SystemError::ENOBUFS.to_posix_errno()
|
||||
|| retval == SystemError::ESRCH.to_posix_errno()
|
||||
{
|
||||
retval = 0;
|
||||
}
|
||||
}
|
||||
// consume_skb(skb);
|
||||
retval
|
||||
}
|
102
kernel/src/driver/base/uevent/mod.rs
Normal file
102
kernel/src/driver/base/uevent/mod.rs
Normal file
@ -0,0 +1,102 @@
|
||||
// include/linux/kobject.h
|
||||
// lib/kobject_uevent.c
|
||||
|
||||
/*
|
||||
UEVENT_HELPER_PATH_LEN
|
||||
UEVENT_NUM_ENVP
|
||||
_KOBJECT_H_
|
||||
|
||||
Variable
|
||||
|
||||
__randomize_layout
|
||||
|
||||
Enum
|
||||
|
||||
kobject_action
|
||||
|
||||
Struct
|
||||
|
||||
kobj_attribute
|
||||
kobj_type
|
||||
kobj_uevent_env
|
||||
kobject
|
||||
kset
|
||||
kset_uevent_ops
|
||||
|
||||
Function
|
||||
|
||||
get_ktype
|
||||
kobject_name
|
||||
kset_get
|
||||
kset_put
|
||||
to_kset
|
||||
*/
|
||||
use crate::driver::base::kobject::KObject;
|
||||
use alloc::string::String;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
pub mod kobject_uevent;
|
||||
|
||||
// https://code.dragonos.org.cn/xref/linux-6.1.9/lib/kobject_uevent.c?fi=kobject_uevent#457
|
||||
// kobject_action
|
||||
#[derive(Debug)]
|
||||
pub enum KobjectAction {
|
||||
KOBJADD,
|
||||
KOBJREMOVE, //Kobject(或上层数据结构)的添加/移除事件
|
||||
KOBJCHANGE, //Kobject(或上层数据结构)的状态或者内容发生改变; 如果设备驱动需要上报的事件不再上面事件的范围内,或者是自定义的事件,可以使用该event,并携带相应的参数。
|
||||
KOBJMOVE, //Kobject(或上层数据结构)更改名称或者更改Parent(意味着在sysfs中更改了目录结构)
|
||||
KOBJONLINE,
|
||||
KOBJOFFLINE, //Kobject(或上层数据结构)的上线/下线事件,其实是是否使能
|
||||
KOBJBIND,
|
||||
KOBJUNBIND,
|
||||
}
|
||||
|
||||
/*
|
||||
@parament:
|
||||
|
||||
envp,指针数组,用于保存每个环境变量的地址,最多可支持的环境变量数量为UEVENT_NUM_ENVP。
|
||||
|
||||
envp_idx,用于访问环境变量指针数组的index。
|
||||
|
||||
buf,保存环境变量的buffer,最大为UEVENT_BUFFER_SIZE。
|
||||
|
||||
buflen,访问buf的变量。
|
||||
|
||||
*/
|
||||
|
||||
//https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/kobject.h#31
|
||||
|
||||
pub const UEVENT_NUM_ENVP: usize = 64;
|
||||
pub const UEVENT_BUFFER_SIZE: usize = 2048;
|
||||
pub const UEVENT_HELPER_PATH_LEN: usize = 256;
|
||||
|
||||
/// Represents the environment for handling kernel object uevents.
|
||||
/*
|
||||
envp,指针数组,用于保存每个环境变量的地址,最多可支持的环境变量数量为UEVENT_NUM_ENVP。
|
||||
|
||||
envp_idx,用于访问环境变量指针数组的index。
|
||||
|
||||
buf,保存环境变量的buffer,最大为UEVENT_BUFFER_SIZE。
|
||||
|
||||
buflen,访问buf的变量。
|
||||
|
||||
*/
|
||||
// 表示一个待发送的uevent
|
||||
#[derive(Debug)]
|
||||
pub struct KobjUeventEnv {
|
||||
argv: Vec<String>,
|
||||
envp: Vec<String>,
|
||||
envp_idx: usize,
|
||||
buf: Vec<u8>,
|
||||
buflen: usize,
|
||||
}
|
||||
|
||||
// kset_uevent_ops是为kset量身订做的一个数据结构,里面包含filter和uevent两个回调函数,用处如下:
|
||||
/*
|
||||
filter,当任何Kobject需要上报uevent时,它所属的kset可以通过该接口过滤,阻止不希望上报的event,从而达到从整体上管理的目的。
|
||||
|
||||
name,该接口可以返回kset的名称。如果一个kset没有合法的名称,则其下的所有Kobject将不允许上报uvent
|
||||
|
||||
uevent,当任何Kobject需要上报uevent时,它所属的kset可以通过该接口统一为这些event添加环境变量。因为很多时候上报uevent时的环境变量都是相同的,因此可以由kset统一处理,就不需要让每个Kobject独自添加了。
|
||||
|
||||
*/
|
@ -8,7 +8,9 @@ use crate::{
|
||||
device::{bus::Bus, driver::Driver, Device, DeviceCommonData, DeviceType, IdTable},
|
||||
kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState},
|
||||
},
|
||||
net::{register_netdevice, NetDeivceState, NetDevice, NetDeviceCommonData, Operstate},
|
||||
net::{
|
||||
register_netdevice, Iface, IfaceCommon, NetDeivceState, NetDeviceCommonData, Operstate,
|
||||
},
|
||||
},
|
||||
libs::{
|
||||
rwlock::{RwLockReadGuard, RwLockWriteGuard},
|
||||
@ -27,11 +29,8 @@ use core::{
|
||||
ops::{Deref, DerefMut},
|
||||
};
|
||||
use log::info;
|
||||
use smoltcp::{
|
||||
phy,
|
||||
wire::{self, HardwareAddress},
|
||||
};
|
||||
use system_error::SystemError;
|
||||
use smoltcp::{phy, wire::HardwareAddress};
|
||||
// use system_error::SystemError;
|
||||
|
||||
use super::e1000e::{E1000EBuffer, E1000EDevice};
|
||||
|
||||
@ -78,12 +77,12 @@ impl Debug for E1000EDriverWrapper {
|
||||
}
|
||||
}
|
||||
|
||||
#[cast_to([sync] NetDevice)]
|
||||
#[cast_to([sync] Iface)]
|
||||
#[cast_to([sync] Device)]
|
||||
#[derive(Debug)]
|
||||
pub struct E1000EInterface {
|
||||
driver: E1000EDriverWrapper,
|
||||
iface_id: usize,
|
||||
iface: SpinLock<smoltcp::iface::Interface>,
|
||||
common: IfaceCommon,
|
||||
name: String,
|
||||
inner: SpinLock<InnerE1000EInterface>,
|
||||
locked_kobj_state: LockedKObjectState,
|
||||
@ -201,11 +200,9 @@ impl E1000EInterface {
|
||||
let iface =
|
||||
smoltcp::iface::Interface::new(iface_config, &mut driver, Instant::now().into());
|
||||
|
||||
let driver: E1000EDriverWrapper = E1000EDriverWrapper(UnsafeCell::new(driver));
|
||||
let result = Arc::new(E1000EInterface {
|
||||
driver,
|
||||
iface_id,
|
||||
iface: SpinLock::new(iface),
|
||||
driver: E1000EDriverWrapper(UnsafeCell::new(driver)),
|
||||
common: IfaceCommon::new(iface_id, iface),
|
||||
name: format!("eth{}", iface_id),
|
||||
inner: SpinLock::new(InnerE1000EInterface {
|
||||
netdevice_common: NetDeviceCommonData::default(),
|
||||
@ -223,16 +220,6 @@ impl E1000EInterface {
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for E1000EInterface {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
f.debug_struct("E1000EInterface")
|
||||
.field("iface_id", &self.iface_id)
|
||||
.field("iface", &"smoltcp::iface::Interface")
|
||||
.field("name", &self.name)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Device for E1000EInterface {
|
||||
fn dev_type(&self) -> DeviceType {
|
||||
DeviceType::Net
|
||||
@ -302,52 +289,23 @@ impl Device for E1000EInterface {
|
||||
}
|
||||
}
|
||||
|
||||
impl NetDevice for E1000EInterface {
|
||||
impl Iface for E1000EInterface {
|
||||
fn common(&self) -> &IfaceCommon {
|
||||
return &self.common;
|
||||
}
|
||||
|
||||
fn mac(&self) -> smoltcp::wire::EthernetAddress {
|
||||
let mac = self.driver.inner.lock().mac_address();
|
||||
return smoltcp::wire::EthernetAddress::from_bytes(&mac);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn nic_id(&self) -> usize {
|
||||
return self.iface_id;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn iface_name(&self) -> String {
|
||||
return self.name.clone();
|
||||
}
|
||||
|
||||
fn update_ip_addrs(&self, ip_addrs: &[wire::IpCidr]) -> Result<(), 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(());
|
||||
}
|
||||
|
||||
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;
|
||||
fn poll(&self) {
|
||||
self.common.poll(self.driver.force_get_mut())
|
||||
}
|
||||
|
||||
fn addr_assign_type(&self) -> u8 {
|
||||
|
@ -7,7 +7,8 @@ use crate::{
|
||||
irqdesc::{IrqHandler, IrqReturn},
|
||||
IrqNumber,
|
||||
},
|
||||
net::net_core::poll_ifaces_try_lock_onetime,
|
||||
// net::net_core::poll_ifaces_try_lock_onetime,
|
||||
net::net_core::poll_ifaces,
|
||||
};
|
||||
|
||||
/// 默认的网卡中断处理函数
|
||||
@ -21,7 +22,9 @@ impl IrqHandler for DefaultNetIrqHandler {
|
||||
_static_data: Option<&dyn IrqHandlerData>,
|
||||
_dynamic_data: Option<Arc<dyn IrqHandlerData>>,
|
||||
) -> Result<IrqReturn, SystemError> {
|
||||
poll_ifaces_try_lock_onetime().ok();
|
||||
// poll_ifaces_try_lock_onetime().ok();
|
||||
log::warn!("DefaultNetIrqHandler: poll_ifaces_try_lock_onetime -> poll_ifaces");
|
||||
poll_ifaces();
|
||||
Ok(IrqReturn::Handled)
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,9 @@ use smoltcp::{
|
||||
use system_error::SystemError;
|
||||
use unified_init::macros::unified_init;
|
||||
|
||||
use super::{register_netdevice, NetDeivceState, NetDevice, NetDeviceCommonData, Operstate};
|
||||
use super::{register_netdevice, NetDeivceState, NetDeviceCommonData, Operstate};
|
||||
|
||||
use super::{Iface, IfaceCommon};
|
||||
|
||||
const DEVICE_NAME: &str = "loopback";
|
||||
|
||||
@ -81,6 +83,7 @@ impl phy::TxToken for LoopbackTxToken {
|
||||
let result = f(buffer.as_mut_slice());
|
||||
let mut device = self.driver.inner.lock();
|
||||
device.loopback_transmit(buffer);
|
||||
// debug!("lo transmit!");
|
||||
result
|
||||
}
|
||||
}
|
||||
@ -112,7 +115,7 @@ impl Loopback {
|
||||
let buffer = self.queue.pop_front();
|
||||
match buffer {
|
||||
Some(buffer) => {
|
||||
//debug!("lo receive:{:?}", buffer);
|
||||
// debug!("lo receive:{:?}", buffer);
|
||||
return buffer;
|
||||
}
|
||||
None => {
|
||||
@ -127,7 +130,7 @@ impl Loopback {
|
||||
/// - &mut self:自身可变引用
|
||||
/// - buffer:需要发送的数据包
|
||||
pub fn loopback_transmit(&mut self, buffer: Vec<u8>) {
|
||||
//debug!("lo transmit!");
|
||||
// debug!("lo transmit:{:?}", buffer);
|
||||
self.queue.push_back(buffer)
|
||||
}
|
||||
}
|
||||
@ -136,6 +139,7 @@ impl Loopback {
|
||||
/// 为实现获得不可变引用的Interface的内部可变性,故为Driver提供UnsafeCell包裹器
|
||||
///
|
||||
/// 参考virtio_net.rs
|
||||
#[derive(Debug)]
|
||||
struct LoopbackDriverWapper(UnsafeCell<LoopbackDriver>);
|
||||
unsafe impl Send for LoopbackDriverWapper {}
|
||||
unsafe impl Sync for LoopbackDriverWapper {}
|
||||
@ -214,8 +218,10 @@ impl phy::Device for LoopbackDriver {
|
||||
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(),
|
||||
@ -232,6 +238,7 @@ impl phy::Device for LoopbackDriver {
|
||||
/// ## 返回值
|
||||
/// - 返回一个 `Some`,其中包含一个发送令牌,该令牌包含一个对自身的克隆引用
|
||||
fn transmit(&mut self, _timestamp: smoltcp::time::Instant) -> Option<Self::TxToken<'_>> {
|
||||
// log::debug!("lo transmit!");
|
||||
Some(LoopbackTxToken {
|
||||
driver: self.clone(),
|
||||
})
|
||||
@ -240,13 +247,12 @@ impl phy::Device for LoopbackDriver {
|
||||
|
||||
/// ## LoopbackInterface结构
|
||||
/// 封装驱动包裹器和iface,设置接口名称
|
||||
#[cast_to([sync] NetDevice)]
|
||||
#[cast_to([sync] Iface)]
|
||||
#[cast_to([sync] Device)]
|
||||
#[derive(Debug)]
|
||||
pub struct LoopbackInterface {
|
||||
driver: LoopbackDriverWapper,
|
||||
iface_id: usize,
|
||||
iface: SpinLock<smoltcp::iface::Interface>,
|
||||
name: String,
|
||||
common: IfaceCommon,
|
||||
inner: SpinLock<InnerLoopbackInterface>,
|
||||
locked_kobj_state: LockedKObjectState,
|
||||
}
|
||||
@ -280,16 +286,20 @@ impl LoopbackInterface {
|
||||
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();
|
||||
for i in 1..=2 {
|
||||
ip_addrs
|
||||
.push(IpCidr::new(IpAddress::v4(127, 0, 0, i), 8))
|
||||
.expect("Push ipCidr failed: full");
|
||||
}
|
||||
});
|
||||
let driver = LoopbackDriverWapper(UnsafeCell::new(driver));
|
||||
|
||||
// iface.routes_mut().update(|routes_map| {
|
||||
// routes_map[0].
|
||||
// });
|
||||
|
||||
Arc::new(LoopbackInterface {
|
||||
driver,
|
||||
iface_id,
|
||||
iface: SpinLock::new(iface),
|
||||
name: "lo".to_string(),
|
||||
driver: LoopbackDriverWapper(UnsafeCell::new(driver)),
|
||||
common: IfaceCommon::new(iface_id, iface),
|
||||
inner: SpinLock::new(InnerLoopbackInterface {
|
||||
netdevice_common: NetDeviceCommonData::default(),
|
||||
device_common: DeviceCommonData::default(),
|
||||
@ -304,16 +314,7 @@ impl LoopbackInterface {
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
@ -348,7 +349,7 @@ impl KObject for LoopbackInterface {
|
||||
}
|
||||
|
||||
fn name(&self) -> String {
|
||||
self.name.clone()
|
||||
"lo".to_string()
|
||||
}
|
||||
|
||||
fn set_name(&self, _name: String) {
|
||||
@ -441,72 +442,23 @@ impl Device for LoopbackInterface {
|
||||
}
|
||||
}
|
||||
|
||||
impl NetDevice for LoopbackInterface {
|
||||
impl Iface for LoopbackInterface {
|
||||
fn common(&self) -> &IfaceCommon {
|
||||
&self.common
|
||||
}
|
||||
|
||||
fn iface_name(&self) -> String {
|
||||
"lo".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)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn nic_id(&self) -> usize {
|
||||
self.iface_id
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn iface_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;
|
||||
fn poll(&self) {
|
||||
self.common.poll(self.driver.force_get_mut())
|
||||
}
|
||||
|
||||
fn addr_assign_type(&self) -> u8 {
|
||||
@ -538,7 +490,7 @@ impl NetDevice for LoopbackInterface {
|
||||
pub fn loopback_probe() {
|
||||
loopback_driver_init();
|
||||
}
|
||||
/// ## lo网卡设备初始化函数
|
||||
/// # lo网卡设备初始化函数
|
||||
/// 创建驱动和iface,初始化一个lo网卡,添加到全局NET_DEVICES中
|
||||
pub fn loopback_driver_init() {
|
||||
let driver = LoopbackDriver::new();
|
||||
@ -548,14 +500,16 @@ pub fn loopback_driver_init() {
|
||||
|
||||
NET_DEVICES
|
||||
.write_irqsave()
|
||||
.insert(iface.iface_id, iface.clone());
|
||||
.insert(iface.nic_id(), iface.clone());
|
||||
|
||||
register_netdevice(iface.clone()).expect("register lo device failed");
|
||||
}
|
||||
|
||||
/// ## lo网卡设备的注册函数
|
||||
#[unified_init(INITCALL_DEVICE)]
|
||||
//TODO: 现在先不用初始化宏进行注册,使virtonet排在网卡列表头,待网络子系统重构后再使用初始化宏并修复该bug
|
||||
// #[unified_init(INITCALL_DEVICE)]
|
||||
pub fn loopback_init() -> Result<(), SystemError> {
|
||||
loopback_probe();
|
||||
log::debug!("Successfully init loopback device");
|
||||
return Ok(());
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
use alloc::{fmt, vec::Vec};
|
||||
use alloc::{string::String, sync::Arc};
|
||||
use smoltcp::{
|
||||
iface,
|
||||
@ -5,8 +6,12 @@ use smoltcp::{
|
||||
};
|
||||
use sysfs::netdev_register_kobject;
|
||||
|
||||
use super::base::device::Device;
|
||||
use crate::libs::spinlock::SpinLock;
|
||||
use crate::{
|
||||
libs::{rwlock::RwLock, spinlock::SpinLock},
|
||||
net::socket::inet::{common::PortManager, InetSocket},
|
||||
process::ProcessState,
|
||||
};
|
||||
use smoltcp;
|
||||
use system_error::SystemError;
|
||||
|
||||
pub mod class;
|
||||
@ -52,23 +57,63 @@ pub enum Operstate {
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub trait NetDevice: Device {
|
||||
/// @brief 获取网卡的MAC地址
|
||||
fn mac(&self) -> EthernetAddress;
|
||||
pub trait Iface: crate::driver::base::device::Device {
|
||||
/// # `common`
|
||||
/// 获取网卡的公共信息
|
||||
fn common(&self) -> &IfaceCommon;
|
||||
|
||||
/// # `mac`
|
||||
/// 获取网卡的MAC地址
|
||||
fn mac(&self) -> smoltcp::wire::EthernetAddress;
|
||||
|
||||
/// # `name`
|
||||
/// 获取网卡名
|
||||
fn iface_name(&self) -> String;
|
||||
|
||||
/// @brief 获取网卡的id
|
||||
fn nic_id(&self) -> usize;
|
||||
/// # `nic_id`
|
||||
/// 获取网卡id
|
||||
fn nic_id(&self) -> usize {
|
||||
self.common().iface_id
|
||||
}
|
||||
|
||||
fn poll(&self, sockets: &mut iface::SocketSet) -> Result<(), SystemError>;
|
||||
/// # `poll`
|
||||
/// 用于轮询接口的状态。
|
||||
/// ## 参数
|
||||
/// - `sockets` :一个可变引用到 `smoltcp::iface::SocketSet`,表示要轮询的套接字集
|
||||
/// ## 返回值
|
||||
/// - 成功返回 `Ok(())`
|
||||
/// - 如果轮询失败,返回 `Err(SystemError::EAGAIN_OR_EWOULDBLOCK)`,表示需要再次尝试或者操作会阻塞
|
||||
fn poll(&self);
|
||||
|
||||
fn update_ip_addrs(&self, ip_addrs: &[wire::IpCidr]) -> Result<(), SystemError>;
|
||||
/// # `update_ip_addrs`
|
||||
/// 用于更新接口的 IP 地址
|
||||
/// ## 参数
|
||||
/// - `ip_addrs` :一个包含 `smoltcp::wire::IpCidr` 的切片,表示要设置的 IP 地址和子网掩码
|
||||
/// ## 返回值
|
||||
/// - 如果 `ip_addrs` 的长度不为 1,返回 `Err(SystemError::EINVAL)`,表示输入参数无效
|
||||
fn update_ip_addrs(&self, ip_addrs: &[smoltcp::wire::IpCidr]) -> Result<(), SystemError> {
|
||||
self.common().update_ip_addrs(ip_addrs)
|
||||
}
|
||||
|
||||
/// @brief 获取smoltcp的网卡接口类型
|
||||
fn inner_iface(&self) -> &SpinLock<smoltcp::iface::Interface>;
|
||||
#[inline(always)]
|
||||
fn smol_iface(&self) -> &SpinLock<smoltcp::iface::Interface> {
|
||||
&self.common().smol_iface
|
||||
}
|
||||
// fn as_any_ref(&'static self) -> &'static dyn core::any::Any;
|
||||
|
||||
/// # `sockets`
|
||||
/// 获取网卡的套接字集
|
||||
fn sockets(&self) -> &SpinLock<smoltcp::iface::SocketSet<'static>> {
|
||||
&self.common().sockets
|
||||
}
|
||||
|
||||
/// # `port_manager`
|
||||
/// 用于管理网卡的端口
|
||||
fn port_manager(&self) -> &PortManager {
|
||||
&self.common().port_manager
|
||||
}
|
||||
|
||||
fn addr_assign_type(&self) -> u8;
|
||||
|
||||
fn net_device_type(&self) -> u16;
|
||||
@ -108,7 +153,7 @@ impl Default for NetDeviceCommonData {
|
||||
|
||||
/// 将网络设备注册到sysfs中
|
||||
/// 参考:https://code.dragonos.org.cn/xref/linux-2.6.39/net/core/dev.c?fi=register_netdev#5373
|
||||
fn register_netdevice(dev: Arc<dyn NetDevice>) -> Result<(), SystemError> {
|
||||
fn register_netdevice(dev: Arc<dyn Iface>) -> Result<(), SystemError> {
|
||||
// 在sysfs中注册设备
|
||||
netdev_register_kobject(dev.clone())?;
|
||||
|
||||
@ -117,3 +162,124 @@ fn register_netdevice(dev: Arc<dyn NetDevice>) -> Result<(), SystemError> {
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
pub struct IfaceCommon {
|
||||
iface_id: usize,
|
||||
smol_iface: SpinLock<smoltcp::iface::Interface>,
|
||||
/// 存smoltcp网卡的套接字集
|
||||
sockets: SpinLock<smoltcp::iface::SocketSet<'static>>,
|
||||
/// 存 kernel wrap smoltcp socket 的集合
|
||||
bounds: RwLock<Vec<Arc<dyn InetSocket>>>,
|
||||
/// 端口管理器
|
||||
port_manager: PortManager,
|
||||
/// 下次轮询的时间
|
||||
poll_at_ms: core::sync::atomic::AtomicU64,
|
||||
}
|
||||
|
||||
impl fmt::Debug for IfaceCommon {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("IfaceCommon")
|
||||
.field("iface_id", &self.iface_id)
|
||||
.field("sockets", &self.sockets)
|
||||
.field("bounds", &self.bounds)
|
||||
.field("port_manager", &self.port_manager)
|
||||
.field("poll_at_ms", &self.poll_at_ms)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl IfaceCommon {
|
||||
pub fn new(iface_id: usize, iface: smoltcp::iface::Interface) -> Self {
|
||||
IfaceCommon {
|
||||
iface_id,
|
||||
smol_iface: SpinLock::new(iface),
|
||||
sockets: SpinLock::new(smoltcp::iface::SocketSet::new(Vec::new())),
|
||||
bounds: RwLock::new(Vec::new()),
|
||||
port_manager: PortManager::new(),
|
||||
poll_at_ms: core::sync::atomic::AtomicU64::new(0),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn poll<D>(&self, device: &mut D)
|
||||
where
|
||||
D: smoltcp::phy::Device + ?Sized,
|
||||
{
|
||||
let timestamp = crate::time::Instant::now().into();
|
||||
let mut sockets = self.sockets.lock_irqsave();
|
||||
let mut interface = self.smol_iface.lock_irqsave();
|
||||
|
||||
let (has_events, poll_at) = {
|
||||
let mut has_events = false;
|
||||
let mut poll_at;
|
||||
loop {
|
||||
has_events |= interface.poll(timestamp, device, &mut sockets);
|
||||
poll_at = interface.poll_at(timestamp, &sockets);
|
||||
let Some(instant) = poll_at else {
|
||||
break;
|
||||
};
|
||||
if instant > timestamp {
|
||||
break;
|
||||
}
|
||||
}
|
||||
(has_events, poll_at)
|
||||
};
|
||||
|
||||
// drop sockets here to avoid deadlock
|
||||
drop(interface);
|
||||
drop(sockets);
|
||||
|
||||
use core::sync::atomic::Ordering;
|
||||
if let Some(instant) = poll_at {
|
||||
let _old_instant = self.poll_at_ms.load(Ordering::Relaxed);
|
||||
let new_instant = instant.total_millis() as u64;
|
||||
self.poll_at_ms.store(new_instant, Ordering::Relaxed);
|
||||
|
||||
// if old_instant == 0 || new_instant < old_instant {
|
||||
// self.polling_wait_queue.wake_all();
|
||||
// }
|
||||
} else {
|
||||
self.poll_at_ms.store(0, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
if has_events {
|
||||
// log::debug!("IfaceCommon::poll: has_events");
|
||||
// We never try to hold the write lock in the IRQ context, and we disable IRQ when
|
||||
// holding the write lock. So we don't need to disable IRQ when holding the read lock.
|
||||
self.bounds.read().iter().for_each(|bound_socket| {
|
||||
bound_socket.on_iface_events();
|
||||
bound_socket
|
||||
.wait_queue()
|
||||
.wakeup(Some(ProcessState::Blocked(true)));
|
||||
});
|
||||
|
||||
// let closed_sockets = self
|
||||
// .closing_sockets
|
||||
// .lock_irq_disabled()
|
||||
// .extract_if(|closing_socket| closing_socket.is_closed())
|
||||
// .collect::<Vec<_>>();
|
||||
// drop(closed_sockets);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_ip_addrs(&self, ip_addrs: &[smoltcp::wire::IpCidr]) -> Result<(), SystemError> {
|
||||
if ip_addrs.len() != 1 {
|
||||
return Err(SystemError::EINVAL);
|
||||
}
|
||||
|
||||
self.smol_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(());
|
||||
}
|
||||
|
||||
// 需要bounds储存具体的Inet Socket信息,以提供不同种类inet socket的事件分发
|
||||
pub fn bind_socket(&self, socket: Arc<dyn InetSocket>) {
|
||||
self.bounds.write().push(socket);
|
||||
}
|
||||
}
|
||||
|
@ -17,11 +17,11 @@ use intertrait::cast::CastArc;
|
||||
use log::error;
|
||||
use system_error::SystemError;
|
||||
|
||||
use super::{class::sys_class_net_instance, NetDeivceState, NetDevice, Operstate};
|
||||
use super::{class::sys_class_net_instance, Iface, NetDeivceState, Operstate};
|
||||
|
||||
/// 将设备注册到`/sys/class/net`目录下
|
||||
/// 参考:https://code.dragonos.org.cn/xref/linux-2.6.39/net/core/net-sysfs.c?fi=netdev_register_kobject#1311
|
||||
pub fn netdev_register_kobject(dev: Arc<dyn NetDevice>) -> Result<(), SystemError> {
|
||||
pub fn netdev_register_kobject(dev: Arc<dyn Iface>) -> Result<(), SystemError> {
|
||||
// 初始化设备
|
||||
device_manager().device_default_initialize(&(dev.clone() as Arc<dyn Device>));
|
||||
|
||||
@ -103,8 +103,8 @@ impl Attribute for AttrAddrAssignType {
|
||||
}
|
||||
|
||||
fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
|
||||
let net_device = kobj.cast::<dyn NetDevice>().map_err(|_| {
|
||||
error!("AttrAddrAssignType::show() failed: kobj is not a NetDevice");
|
||||
let net_device = kobj.cast::<dyn Iface>().map_err(|_| {
|
||||
error!("AttrAddrAssignType::show() failed: kobj is not a Iface");
|
||||
SystemError::EINVAL
|
||||
})?;
|
||||
let addr_assign_type = net_device.addr_assign_type();
|
||||
@ -271,8 +271,8 @@ impl Attribute for AttrType {
|
||||
}
|
||||
|
||||
fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
|
||||
let net_deive = kobj.cast::<dyn NetDevice>().map_err(|_| {
|
||||
error!("AttrType::show() failed: kobj is not a NetDevice");
|
||||
let net_deive = kobj.cast::<dyn Iface>().map_err(|_| {
|
||||
error!("AttrType::show() failed: kobj is not a Iface");
|
||||
SystemError::EINVAL
|
||||
})?;
|
||||
let net_type = net_deive.net_device_type();
|
||||
@ -322,8 +322,8 @@ impl Attribute for AttrAddress {
|
||||
}
|
||||
|
||||
fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
|
||||
let net_device = kobj.cast::<dyn NetDevice>().map_err(|_| {
|
||||
error!("AttrAddress::show() failed: kobj is not a NetDevice");
|
||||
let net_device = kobj.cast::<dyn Iface>().map_err(|_| {
|
||||
error!("AttrAddress::show() failed: kobj is not a Iface");
|
||||
SystemError::EINVAL
|
||||
})?;
|
||||
let mac_addr = net_device.mac();
|
||||
@ -373,8 +373,8 @@ impl Attribute for AttrCarrier {
|
||||
}
|
||||
|
||||
fn show(&self, kobj: Arc<dyn KObject>, buf: &mut [u8]) -> Result<usize, SystemError> {
|
||||
let net_device = kobj.cast::<dyn NetDevice>().map_err(|_| {
|
||||
error!("AttrCarrier::show() failed: kobj is not a NetDevice");
|
||||
let net_device = kobj.cast::<dyn Iface>().map_err(|_| {
|
||||
error!("AttrCarrier::show() failed: kobj is not a Iface");
|
||||
SystemError::EINVAL
|
||||
})?;
|
||||
if net_device
|
||||
@ -489,8 +489,8 @@ impl Attribute for AttrOperstate {
|
||||
}
|
||||
|
||||
fn show(&self, _kobj: Arc<dyn KObject>, _buf: &mut [u8]) -> Result<usize, SystemError> {
|
||||
let net_device = _kobj.cast::<dyn NetDevice>().map_err(|_| {
|
||||
error!("AttrOperstate::show() failed: kobj is not a NetDevice");
|
||||
let net_device = _kobj.cast::<dyn Iface>().map_err(|_| {
|
||||
error!("AttrOperstate::show() failed: kobj is not a Iface");
|
||||
SystemError::EINVAL
|
||||
})?;
|
||||
if !net_device
|
||||
|
@ -16,7 +16,7 @@ use smoltcp::{iface, phy, wire};
|
||||
use unified_init::macros::unified_init;
|
||||
use virtio_drivers::device::net::VirtIONet;
|
||||
|
||||
use super::{NetDeivceState, NetDevice, NetDeviceCommonData, Operstate};
|
||||
use super::{Iface, NetDeivceState, NetDeviceCommonData, Operstate};
|
||||
use crate::{
|
||||
arch::rand::rand,
|
||||
driver::{
|
||||
@ -47,7 +47,7 @@ use crate::{
|
||||
rwlock::{RwLockReadGuard, RwLockWriteGuard},
|
||||
spinlock::{SpinLock, SpinLockGuard},
|
||||
},
|
||||
net::{generate_iface_id, net_core::poll_ifaces_try_lock_onetime, NET_DEVICES},
|
||||
net::{generate_iface_id, net_core::poll_ifaces, NET_DEVICES},
|
||||
time::Instant,
|
||||
};
|
||||
use system_error::SystemError;
|
||||
@ -253,7 +253,8 @@ impl Device for VirtIONetDevice {
|
||||
|
||||
impl VirtIODevice for VirtIONetDevice {
|
||||
fn handle_irq(&self, _irq: IrqNumber) -> Result<IrqReturn, SystemError> {
|
||||
poll_ifaces_try_lock_onetime().ok();
|
||||
log::warn!("VirtioInterface: poll_ifaces_try_lock_onetime -> poll_ifaces");
|
||||
poll_ifaces();
|
||||
return Ok(IrqReturn::Handled);
|
||||
}
|
||||
|
||||
@ -362,13 +363,13 @@ impl Debug for VirtIONicDeviceInner {
|
||||
}
|
||||
}
|
||||
|
||||
#[cast_to([sync] NetDevice)]
|
||||
#[cast_to([sync] Iface)]
|
||||
#[cast_to([sync] Device)]
|
||||
#[derive(Debug)]
|
||||
pub struct VirtioInterface {
|
||||
device_inner: VirtIONicDeviceInnerWrapper,
|
||||
iface_id: usize,
|
||||
iface_name: String,
|
||||
iface: SpinLock<iface::Interface>,
|
||||
iface_common: super::IfaceCommon,
|
||||
inner: SpinLock<InnerVirtIOInterface>,
|
||||
locked_kobj_state: LockedKObjectState,
|
||||
}
|
||||
@ -380,17 +381,6 @@ struct InnerVirtIOInterface {
|
||||
netdevice_common: NetDeviceCommonData,
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for VirtioInterface {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
f.debug_struct("VirtioInterface")
|
||||
.field("iface_id", &self.iface_id)
|
||||
.field("iface_name", &self.iface_name)
|
||||
.field("inner", &self.inner)
|
||||
.field("locked_kobj_state", &self.locked_kobj_state)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl VirtioInterface {
|
||||
pub fn new(mut device_inner: VirtIONicDeviceInner) -> Arc<Self> {
|
||||
let iface_id = generate_iface_id();
|
||||
@ -403,10 +393,9 @@ impl VirtioInterface {
|
||||
|
||||
let result = Arc::new(VirtioInterface {
|
||||
device_inner: VirtIONicDeviceInnerWrapper(UnsafeCell::new(device_inner)),
|
||||
iface_id,
|
||||
locked_kobj_state: LockedKObjectState::default(),
|
||||
iface: SpinLock::new(iface),
|
||||
iface_name: format!("eth{}", iface_id),
|
||||
iface_common: super::IfaceCommon::new(iface_id, iface),
|
||||
inner: SpinLock::new(InnerVirtIOInterface {
|
||||
kobj_common: KObjectCommonData::default(),
|
||||
device_common: DeviceCommonData::default(),
|
||||
@ -431,7 +420,7 @@ impl VirtioInterface {
|
||||
impl Drop for VirtioInterface {
|
||||
fn drop(&mut self) {
|
||||
// 从全局的网卡接口信息表中删除这个网卡的接口信息
|
||||
NET_DEVICES.write_irqsave().remove(&self.iface_id);
|
||||
NET_DEVICES.write_irqsave().remove(&self.nic_id());
|
||||
}
|
||||
}
|
||||
|
||||
@ -624,57 +613,25 @@ pub fn virtio_net(
|
||||
}
|
||||
}
|
||||
|
||||
impl NetDevice for VirtioInterface {
|
||||
impl Iface for VirtioInterface {
|
||||
fn common(&self) -> &super::IfaceCommon {
|
||||
&self.iface_common
|
||||
}
|
||||
|
||||
fn mac(&self) -> wire::EthernetAddress {
|
||||
let mac: [u8; 6] = self.device_inner.inner.lock().mac_address();
|
||||
return wire::EthernetAddress::from_bytes(&mac);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn nic_id(&self) -> usize {
|
||||
return self.iface_id;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn iface_name(&self) -> String {
|
||||
return self.iface_name.clone();
|
||||
}
|
||||
|
||||
fn update_ip_addrs(&self, ip_addrs: &[wire::IpCidr]) -> Result<(), 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 wire::IpCidr failed: full");
|
||||
}
|
||||
});
|
||||
return Ok(());
|
||||
fn poll(&self) {
|
||||
self.iface_common.poll(self.device_inner.force_get_mut())
|
||||
}
|
||||
|
||||
fn poll(&self, sockets: &mut 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.device_inner.force_get_mut(), sockets);
|
||||
// todo: notify!!!
|
||||
// debug!("Virtio Interface poll:{poll_res}");
|
||||
if poll_res {
|
||||
return Ok(());
|
||||
}
|
||||
return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn inner_iface(&self) -> &SpinLock<iface::Interface> {
|
||||
return &self.iface;
|
||||
}
|
||||
// fn as_any_ref(&'static self) -> &'static dyn core::any::Any {
|
||||
// return self;
|
||||
// }
|
||||
@ -839,7 +796,7 @@ impl VirtIODriver for VirtIONetDriver {
|
||||
// 设置iface的父设备为virtio_net_device
|
||||
iface.set_dev_parent(Some(Arc::downgrade(&virtio_net_device) as Weak<dyn Device>));
|
||||
// 在sysfs中注册iface
|
||||
register_netdevice(iface.clone() as Arc<dyn NetDevice>)?;
|
||||
register_netdevice(iface.clone() as Arc<dyn Iface>)?;
|
||||
|
||||
// 将网卡的接口信息注册到全局的网卡接口信息表中
|
||||
NET_DEVICES
|
||||
|
Reference in New Issue
Block a user