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:
2024-10-10 17:53:39 +08:00
committed by GitHub
parent 79eda4bcf9
commit 40d9375b6b
102 changed files with 10497 additions and 3303 deletions

View File

@ -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(());
}

View File

@ -571,6 +571,7 @@ impl DriverManager {
}
// todo: 发送kobj bind的uevent
// kobject_uevent();
}
fn driver_is_bound(&self, device: &Arc<dyn Device>) -> bool {

View File

@ -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(());
}

View File

@ -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);

View File

@ -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

View File

@ -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
}
}

View File

@ -12,3 +12,4 @@ pub mod map;
pub mod platform;
pub mod subsys;
pub mod swnode;
pub mod uevent;

View 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 消息的 skbsocket 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
}

View 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独自添加了。
*/

View File

@ -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 {

View File

@ -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)
}
}

View File

@ -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(());
}

View File

@ -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);
}
}

View File

@ -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

View File

@ -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