diff --git a/kernel/src/driver/acpi/sysfs.rs b/kernel/src/driver/acpi/sysfs.rs index 2b9e22e8..d382ed12 100644 --- a/kernel/src/driver/acpi/sysfs.rs +++ b/kernel/src/driver/acpi/sysfs.rs @@ -22,8 +22,6 @@ 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> = None; static mut __ACPI_TABLES_KSET_INSTANCE: Option> = None; static mut __ACPI_TABLES_DATA_KSET_INSTANCE: Option> = None; @@ -117,26 +115,6 @@ impl AcpiManager { self.acpi_table_data_init(&header)?; } // TODO:UEVENT - unsafe { - let _ = kobject_uevent( - acpi_tables_kset.clone() as Arc, - KobjectAction::KOBJADD, - ); - let _ = kobject_uevent( - __ACPI_TABLES_DATA_KSET_INSTANCE - .as_ref() - .map(|kset| kset.clone() as Arc) - .unwrap(), - KobjectAction::KOBJADD, - ); - let _ = kobject_uevent( - __ACPI_TABLES_DYNAMIC_KSET_INSTANCE - .as_ref() - .map(|kset| kset.clone() as Arc) - .unwrap(), - KobjectAction::KOBJADD, - ); - } return Ok(()); } diff --git a/kernel/src/driver/base/block/block_device.rs b/kernel/src/driver/base/block/block_device.rs index 369d9bc1..2a9a9b1e 100644 --- a/kernel/src/driver/base/block/block_device.rs +++ b/kernel/src/driver/base/block/block_device.rs @@ -1,19 +1,16 @@ /// 引入Module -use crate::{ - driver::{ - base::{ - device::{ - device_number::{DeviceNumber, Major}, - Device, DeviceError, IdTable, BLOCKDEVS, - }, - map::{ - DeviceStruct, DEV_MAJOR_DYN_END, DEV_MAJOR_DYN_EXT_END, DEV_MAJOR_DYN_EXT_START, - DEV_MAJOR_HASH_SIZE, DEV_MAJOR_MAX, - }, +use crate::driver::{ + base::{ + device::{ + device_number::{DeviceNumber, Major}, + Device, DeviceError, IdTable, BLOCKDEVS, + }, + map::{ + DeviceStruct, DEV_MAJOR_DYN_END, DEV_MAJOR_DYN_EXT_END, DEV_MAJOR_DYN_EXT_START, + DEV_MAJOR_HASH_SIZE, DEV_MAJOR_MAX, }, - block::cache::{cached_block_device::BlockCache, BlockCacheError, BLOCK_SIZE}, }, - filesystem::sysfs::AttributeGroup, + block::cache::{cached_block_device::BlockCache, BlockCacheError, BLOCK_SIZE}, }; use alloc::{string::String, sync::Arc, vec::Vec}; diff --git a/kernel/src/driver/base/device/driver.rs b/kernel/src/driver/base/device/driver.rs index 1adac84a..3df9878a 100644 --- a/kernel/src/driver/base/device/driver.rs +++ b/kernel/src/driver/base/device/driver.rs @@ -2,8 +2,6 @@ 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}, @@ -220,7 +218,6 @@ impl DriverManager { })?; // todo: 发送uevent,类型问题 - let _ = kobject_uevent(driver.clone() as Arc, KobjectAction::KOBJADD); // deferred_probe_extend_timeout(); return Ok(()); diff --git a/kernel/src/driver/base/device/mod.rs b/kernel/src/driver/base/device/mod.rs index 04c93dcc..108508c9 100644 --- a/kernel/src/driver/base/device/mod.rs +++ b/kernel/src/driver/base/device/mod.rs @@ -43,7 +43,6 @@ use super::{ }, kset::KSet, swnode::software_node_notify, - uevent::UeventAttr, }; pub mod bus; @@ -1026,25 +1025,6 @@ impl Eq for DeviceId {} impl IrqHandlerData for DeviceId {} -/// sysfs下设备的通用属性组 -#[derive(Debug)] -pub struct CommonAttrGroup; -impl AttributeGroup for CommonAttrGroup { - fn name(&self) -> Option<&str> { - None - } - fn attrs(&self) -> &[&'static dyn Attribute] { - &[&UeventAttr] - } - fn is_visible( - &self, - _kobj: alloc::sync::Arc, - attr: &'static dyn Attribute, - ) -> Option { - Some(attr.mode()) - } -} - lazy_static! { /// class_dir列表,通过parent kobject的name和class_dir的name来索引class_dir实例 static ref CLASS_DIR_KSET_INSTANCE: RwLock>> = RwLock::new(BTreeMap::new()); diff --git a/kernel/src/driver/base/kobject.rs b/kernel/src/driver/base/kobject.rs index 678155d4..ee157ab7 100644 --- a/kernel/src/driver/base/kobject.rs +++ b/kernel/src/driver/base/kobject.rs @@ -1,7 +1,6 @@ use core::{any::Any, fmt::Debug, hash::Hash, ops::Deref}; use alloc::{ - boxed::Box, string::String, sync::{Arc, Weak}, }; @@ -22,7 +21,7 @@ use crate::{ use system_error::SystemError; -use super::{device::CommonAttrGroup, kset::KSet, uevent::kobject_uevent}; +use super::kset::KSet; pub trait KObject: Any + Send + Sync + Debug + CastFromSync { fn as_any_ref(&self) -> &dyn core::any::Any; @@ -263,7 +262,6 @@ impl KObjectManager { fn get_kobj_path_length(kobj: &Arc) -> 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. diff --git a/kernel/src/driver/base/kset.rs b/kernel/src/driver/base/kset.rs index e55aba84..4d890d72 100644 --- a/kernel/src/driver/base/kset.rs +++ b/kernel/src/driver/base/kset.rs @@ -6,11 +6,8 @@ use alloc::{ use core::hash::Hash; -use super::{ - kobject::{ - DynamicKObjKType, KObjType, KObject, KObjectManager, KObjectState, LockedKObjectState, - }, - uevent::KobjUeventEnv, +use super::kobject::{ + DynamicKObjKType, KObjType, KObject, KObjectManager, KObjectState, LockedKObjectState, }; use crate::{ filesystem::kernfs::KernFSInode, @@ -29,8 +26,6 @@ pub struct KSet { /// 与父节点有关的一些信息 parent_data: RwLock, self_ref: Weak, - /// kset用于发送uevent的操作函数集。kset能够发送它所包含的各种子kobj、孙kobj的消息,即kobj或其父辈、爷爷辈,都可以发送消息;优先父辈,然后是爷爷辈,以此类推 - pub uevent_ops: Option>, } impl Hash for KSet { @@ -56,7 +51,6 @@ 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); @@ -239,26 +233,3 @@ 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; - fn uevent_name(&self) -> String; - fn uevent(&self, env: &KobjUeventEnv) -> i32; -} -#[derive(Debug)] -pub struct KSetUeventOpsDefault; - -impl KSetUeventOps for KSetUeventOpsDefault { - fn filter(&self) -> Option { - Some(0) - } - - fn uevent_name(&self) -> String { - String::new() - } - - fn uevent(&self, env: &KobjUeventEnv) -> i32 { - 0 - } -} diff --git a/kernel/src/driver/base/mod.rs b/kernel/src/driver/base/mod.rs index 3c399c68..3d4df393 100644 --- a/kernel/src/driver/base/mod.rs +++ b/kernel/src/driver/base/mod.rs @@ -12,4 +12,3 @@ pub mod map; pub mod platform; pub mod subsys; pub mod swnode; -pub mod uevent; diff --git a/kernel/src/driver/base/platform/platform_device.rs b/kernel/src/driver/base/platform/platform_device.rs index c9c17d9e..062a69aa 100644 --- a/kernel/src/driver/base/platform/platform_device.rs +++ b/kernel/src/driver/base/platform/platform_device.rs @@ -11,7 +11,7 @@ use crate::{ bus::{Bus, BusState}, device_manager, driver::Driver, - CommonAttrGroup, Device, DeviceCommonData, DevicePrivateData, DeviceType, IdTable, + Device, DeviceCommonData, DevicePrivateData, DeviceType, IdTable, }, kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState}, kset::KSet, @@ -331,6 +331,6 @@ impl Device for PlatformBusDevice { } fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> { - Some(&[&CommonAttrGroup]) + None } } diff --git a/kernel/src/driver/base/uevent/kobject_uevent.rs b/kernel/src/driver/base/uevent/kobject_uevent.rs deleted file mode 100644 index b55e3e3b..00000000 --- a/kernel/src/driver/base/uevent/kobject_uevent.rs +++ /dev/null @@ -1,483 +0,0 @@ -// 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::skbuff::SkBuff; -use crate::net::socket::netlink::{ - netlink_kernel_create, NetlinkKernelCfg, NETLINK_KOBJECT_UEVENT, NL_CFG_F_NONROOT_RECV, -}; -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> = 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); - -/* - - - -*/ - -/// kobject_uevent,和kobject_uevent_env功能一样,只是没有指定任何的环境变量 -pub fn kobject_uevent(kobj: Arc, action: KobjectAction) -> Result<(), SystemError> { - // kobject_uevent和kobject_uevent_env功能一样,只是没有指定任何的环境变量 - match kobject_uevent_env(kobj, action, Vec::new()) { - Ok(_) => Ok(()), - Err(e) => Err(e), - } -} - -/// kobject_uevent_env,以envp为环境变量,上报一个指定action的uevent。环境变量的作用是为执行用户空间程序指定运行环境。 -pub fn kobject_uevent_env( - kobj: Arc, - action: KobjectAction, - envp_ext: Vec, -) -> Result { - 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 */ - - for var in envp_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); -} - -/// 以格式化字符的形式,将环境变量copy到env指针中。 -pub fn add_uevent_var( - env: &mut Box, - format: &str, - args: &str, -) -> Result { - 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) { - // 定义一个静态字符串 - 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, - env: &KobjUeventEnv, - action_string: &str, - devpath: &str, -) -> i32 { - // 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 { - let 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> { - 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 = 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 -} diff --git a/kernel/src/driver/base/uevent/mod.rs b/kernel/src/driver/base/uevent/mod.rs deleted file mode 100644 index 442551b8..00000000 --- a/kernel/src/driver/base/uevent/mod.rs +++ /dev/null @@ -1,239 +0,0 @@ -use crate::driver::base::uevent::kobject_uevent::kobject_uevent_env; -use core::fmt::Write; -/* -Struct - kset_uevent_ops - -Function - - get_ktype - kobject_name - kset_get - kset_put - to_kset -*/ -use crate::driver::base::kobject::KObject; -use crate::driver::net::Iface; -use crate::filesystem::sysfs::{Attribute, SysFSOpsSupport, SYSFS_ATTR_MODE_RW}; -use alloc::string::{String, ToString}; -use alloc::sync::Arc; -use alloc::vec::Vec; -use intertrait::cast::CastArc; -use log::warn; -use system_error::SystemError; - -use super::block::block_device::{BlockDevice, BlockDeviceOps}; -use super::char::CharDevice; -use super::device::{Device, DeviceType}; - -pub mod kobject_uevent; - -// https://code.dragonos.org.cn/xref/linux-6.1.9/lib/kobject_uevent.c?fi=kobject_uevent#457 -#[derive(Debug)] -pub enum KobjectAction { - KOBJADD, - KOBJREMOVE, // Kobject(或上层数据结构)的添加/移除事件 - KOBJCHANGE, // Kobject(或上层数据结构)的状态或者内容发生改变; 如果设备驱动需要上报的事件不再上面事件的范围内,或者是自定义的事件,可以使用该event,并携带相应的参数。 - KOBJMOVE, // Kobject(或上层数据结构)更改名称或者更改Parent(意味着在sysfs中更改了目录结构) - KOBJONLINE, - KOBJOFFLINE, // Kobject(或上层数据结构)的上线/下线事件,其实是是否使能 - KOBJBIND, - KOBJUNBIND, -} - -/// 解析一个字符串,以确定它代表的是哪个 kobject_action,并提取出随后的参数(如果有的话) -fn kobject_action_type(buf: &[u8]) -> Result<(KobjectAction, Vec), SystemError> { - let mut action = KobjectAction::KOBJCHANGE; - let mut action_args: Vec = Vec::new(); - let mut count = buf.len(); - if count != 0 && (buf[count - 1] == b'\n' || buf[count - 1] == b'\0') { - count -= 1; - } - if count == 0 { - return Err(SystemError::EINVAL); - } - - let arg_start = buf.iter().position(|&c| c == b' ').unwrap_or(count); - let count_first = arg_start; - let args_start = arg_start + 1; - - // 匹配KobjectAction - match &buf[..count_first] { - b"add" => action = KobjectAction::KOBJADD, - b"remove" => action = KobjectAction::KOBJREMOVE, - b"change" => action = KobjectAction::KOBJCHANGE, - b"move" => action = KobjectAction::KOBJMOVE, - b"online" => action = KobjectAction::KOBJONLINE, - b"offline" => action = KobjectAction::KOBJOFFLINE, - b"bind" => action = KobjectAction::KOBJBIND, - b"unbind" => action = KobjectAction::KOBJUNBIND, - _ => return Err(SystemError::EINVAL), - } - - // 如果有参数,提取参数 - if count - args_start > 0 { - action_args = buf[args_start..] - .split(|&c| c == b' ') - .map(|s| String::from_utf8_lossy(s).to_string()) - .collect::>(); - } - - Ok((action, action_args)) -} - -pub const UEVENT_NUM_ENVP: usize = 64; -pub const UEVENT_BUFFER_SIZE: usize = 2048; -pub const UEVENT_HELPER_PATH_LEN: usize = 256; - -/// 表示处理内核对象 uevents 的环境 -/// - 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 -#[derive(Debug)] -pub struct KobjUeventEnv { - argv: Vec, - envp: Vec, - envp_idx: usize, - buf: Vec, - 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独自添加了。 - -*/ - -/// 设备文件夹下的`uevent`文件的属性 -#[derive(Debug, Clone, Copy)] -pub struct UeventAttr; - -impl Attribute for UeventAttr { - fn name(&self) -> &str { - "uevent" - } - - fn mode(&self) -> crate::filesystem::vfs::syscall::ModeType { - SYSFS_ATTR_MODE_RW - } - - fn support(&self) -> crate::filesystem::sysfs::SysFSOpsSupport { - SysFSOpsSupport::ATTR_SHOW | SysFSOpsSupport::ATTR_STORE - } - - /// 用户空间读取 uevent 文件,返回 uevent 信息 - fn show(&self, _kobj: Arc, _buf: &mut [u8]) -> Result { - let device = _kobj.cast::().map_err(|e: Arc| { - warn!("device:{:?} is not a device!", e); - SystemError::EINVAL - })?; - log::info!("show uevent"); - let device_type = device.dev_type(); - let mut uevent_content = String::new(); - log::info!("device_type: {:?}", device_type); - match device_type { - DeviceType::Block => { - let major = device.id_table().device_number().major().data(); - let minor = device.id_table().device_number().minor(); - let device_name = device.id_table().name(); - writeln!(&mut uevent_content, "MAJOR={:?}", major).unwrap(); - writeln!(&mut uevent_content, "MINOR={:?}", minor).unwrap(); - writeln!(&mut uevent_content, "DEVNAME={}", device_name).unwrap(); - writeln!(&mut uevent_content, "DEVTYPE=disk").unwrap(); - } - DeviceType::Char => { - let major = device.id_table().device_number().major().data(); - let minor = device.id_table().device_number().minor(); - let device_name = device.id_table().name(); - writeln!(&mut uevent_content, "MAJOR={}", major).unwrap(); - writeln!(&mut uevent_content, "MINOR={}", minor).unwrap(); - writeln!(&mut uevent_content, "DEVNAME={}", device_name).unwrap(); - writeln!(&mut uevent_content, "DEVTYPE=char").unwrap(); - } - DeviceType::Net => { - let net_device = - device - .clone() - .cast::() - .map_err(|e: Arc| { - warn!("device:{:?} is not a net device!", e); - SystemError::EINVAL - })?; - let iface_id = net_device.nic_id(); - let device_name = device.name(); - writeln!(&mut uevent_content, "INTERFACE={}", device_name).unwrap(); - writeln!(&mut uevent_content, "IFINDEX={}", iface_id).unwrap(); - } - DeviceType::Bus => { - // 处理总线设备类型 - let device_name = device.name(); - writeln!(&mut uevent_content, "DEVNAME={}", device_name).unwrap(); - writeln!(&mut uevent_content, "DEVTYPE=bus").unwrap(); - } - DeviceType::Rtc => { - // 处理RTC设备类型 - let device_name = device.name(); - writeln!(&mut uevent_content, "DEVNAME={}", device_name).unwrap(); - writeln!(&mut uevent_content, "DEVTYPE=rtc").unwrap(); - } - DeviceType::Pci => { - // 处理PCI设备类型 - let device_name = device.name(); - writeln!(&mut uevent_content, "DEVNAME={}", device_name).unwrap(); - writeln!(&mut uevent_content, "DEVTYPE=pci").unwrap(); - } - _ => { - // 处理其他设备类型 - let device_name = device.name(); - writeln!(&mut uevent_content, "DEVNAME={}", device_name).unwrap(); - writeln!(&mut uevent_content, "DEVTYPE={:?}", device_type).unwrap(); - } - } - sysfs_emit_str(_buf, &uevent_content) - } - /// 捕获来自用户空间对 uevent 文件的写操作,触发uevent事件 - fn store(&self, _kobj: Arc, _buf: &[u8]) -> Result { - log::info!("store uevent"); - return kobject_synth_uevent(_buf, _kobj); - } -} - -/// 将设备的基本信息写入 uevent 文件 -fn sysfs_emit_str(buf: &mut [u8], content: &str) -> Result { - log::info!("sysfs_emit_str"); - let bytes = content.as_bytes(); - if buf.len() < bytes.len() { - return Err(SystemError::ENOMEM); - } - buf[..bytes.len()].copy_from_slice(bytes); - Ok(bytes.len()) -} - -/// 解析用户空间写入的 uevent 信息,触发 uevent 事件 -fn kobject_synth_uevent(buf: &[u8], kobj: Arc) -> Result { - let no_uuid_envp = vec!["SYNTH_UUID=0".to_string()]; - let (action, action_args) = kobject_action_type(buf)?; - - let result = if action_args.is_empty() { - kobject_uevent_env(kobj.clone(), action, no_uuid_envp) - } else { - kobject_uevent_env(kobj.clone(), action, action_args) - }; - - if let Err(e) = result { - let device = kobj.cast::().map_err(|e: Arc| { - warn!("device:{:?} is not a device!", e); - SystemError::EINVAL - })?; - let devname = device.name(); - log::error!("synth uevent: {}: {:?}", devname, e); - return Err(SystemError::EINVAL); - } - Ok(buf.len()) -} diff --git a/kernel/src/driver/block/virtio_blk.rs b/kernel/src/driver/block/virtio_blk.rs index 8a626655..74e1fbf6 100644 --- a/kernel/src/driver/block/virtio_blk.rs +++ b/kernel/src/driver/block/virtio_blk.rs @@ -24,7 +24,7 @@ use crate::{ device::{ bus::Bus, driver::{Driver, DriverCommonData}, - CommonAttrGroup, Device, DeviceCommonData, DeviceId, DeviceType, IdTable, + Device, DeviceCommonData, DeviceId, DeviceType, IdTable, }, kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState}, kset::KSet, @@ -409,7 +409,7 @@ impl Device for VirtIOBlkDevice { } fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> { - Some(&[&CommonAttrGroup]) + None } } diff --git a/kernel/src/driver/net/class.rs b/kernel/src/driver/net/class.rs index 34c86063..2512c1e9 100644 --- a/kernel/src/driver/net/class.rs +++ b/kernel/src/driver/net/class.rs @@ -1,7 +1,7 @@ use crate::{ driver::base::{ class::{class_manager, Class}, - device::{sys_dev_char_kset, CommonAttrGroup}, + device::sys_dev_char_kset, kobject::KObject, subsys::SubSysPrivate, }, @@ -78,6 +78,6 @@ impl Class for NetClass { } fn dev_groups(&self) -> &'static [&'static dyn AttributeGroup] { - return &[&NetAttrGroup, &CommonAttrGroup]; + return &[&NetAttrGroup]; } } diff --git a/kernel/src/driver/net/virtio_net.rs b/kernel/src/driver/net/virtio_net.rs index 331a5ee6..477dc1cf 100644 --- a/kernel/src/driver/net/virtio_net.rs +++ b/kernel/src/driver/net/virtio_net.rs @@ -25,7 +25,7 @@ use crate::{ device::{ bus::Bus, driver::{Driver, DriverCommonData}, - CommonAttrGroup, Device, DeviceCommonData, DeviceId, DeviceType, IdTable, + Device, DeviceCommonData, DeviceId, DeviceType, IdTable, }, kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState}, kset::KSet, @@ -251,7 +251,7 @@ impl Device for VirtIONetDevice { } fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> { - Some(&[&CommonAttrGroup]) + None } } diff --git a/kernel/src/driver/pci/raw_device.rs b/kernel/src/driver/pci/raw_device.rs index f1186c58..a93478c0 100644 --- a/kernel/src/driver/pci/raw_device.rs +++ b/kernel/src/driver/pci/raw_device.rs @@ -8,10 +8,7 @@ use alloc::{ use crate::{ driver::base::{ class::Class, - device::{ - bus::Bus, driver::Driver, CommonAttrGroup, Device, DeviceCommonData, DeviceType, - IdTable, - }, + device::{bus::Bus, driver::Driver, Device, DeviceCommonData, DeviceType, IdTable}, kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState}, kset::KSet, }, @@ -87,7 +84,7 @@ impl PciDevice for PciGeneralDevice { impl Device for PciGeneralDevice { fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> { - Some(&[&BasicPciReadOnlyAttrs, &CommonAttrGroup]) + Some(&[&BasicPciReadOnlyAttrs]) } fn bus(&self) -> Option> { diff --git a/kernel/src/driver/pci/test/pt_device.rs b/kernel/src/driver/pci/test/pt_device.rs index 381a1622..8c39d598 100644 --- a/kernel/src/driver/pci/test/pt_device.rs +++ b/kernel/src/driver/pci/test/pt_device.rs @@ -10,10 +10,7 @@ use crate::{ driver::{ base::{ class::Class, - device::{ - bus::Bus, driver::Driver, CommonAttrGroup, Device, DeviceCommonData, DeviceType, - IdTable, - }, + device::{bus::Bus, driver::Driver, Device, DeviceCommonData, DeviceType, IdTable}, kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState}, kset::KSet, }, @@ -77,7 +74,7 @@ impl PciDevice for TestDevice { impl Device for TestDevice { fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> { - Some(&[&HelloAttr, &CommonAttrGroup]) + Some(&[&HelloAttr]) } fn bus(&self) -> Option> { diff --git a/kernel/src/driver/rtc/class.rs b/kernel/src/driver/rtc/class.rs index 04063f13..6ed46b97 100644 --- a/kernel/src/driver/rtc/class.rs +++ b/kernel/src/driver/rtc/class.rs @@ -9,7 +9,7 @@ use unified_init::macros::unified_init; use crate::{ driver::base::{ class::{class_manager, Class}, - device::{device_manager, sys_dev_char_kset, CommonAttrGroup}, + device::{device_manager, sys_dev_char_kset}, kobject::KObject, subsys::SubSysPrivate, }, @@ -80,7 +80,7 @@ impl Class for RtcClass { return &self.subsystem; } fn dev_groups(&self) -> &'static [&'static dyn AttributeGroup] { - return &[&CommonAttrGroup]; + return &[]; } } diff --git a/kernel/src/driver/rtc/sysfs.rs b/kernel/src/driver/rtc/sysfs.rs index bd1c9ca6..079967d0 100644 --- a/kernel/src/driver/rtc/sysfs.rs +++ b/kernel/src/driver/rtc/sysfs.rs @@ -9,8 +9,7 @@ use crate::{ driver::base::{ class::Class, device::{ - bus::Bus, device_manager, driver::Driver, CommonAttrGroup, Device, DeviceCommonData, - DeviceType, IdTable, + bus::Bus, device_manager, driver::Driver, Device, DeviceCommonData, DeviceType, IdTable, }, kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState}, kset::KSet, @@ -173,7 +172,7 @@ impl Device for RtcGeneralDevice { true } fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> { - Some(&[&RtcAttrGroup, &CommonAttrGroup]) + Some(&[&RtcAttrGroup]) } fn dev_parent(&self) -> Option> { diff --git a/kernel/src/driver/tty/sysfs.rs b/kernel/src/driver/tty/sysfs.rs index a384d2f7..b731ab04 100644 --- a/kernel/src/driver/tty/sysfs.rs +++ b/kernel/src/driver/tty/sysfs.rs @@ -8,11 +8,10 @@ use unified_init::macros::unified_init; use crate::{ driver::base::{ class::{class_manager, Class}, - device::{sys_dev_char_kset, CommonAttrGroup}, + device::sys_dev_char_kset, kobject::KObject, subsys::SubSysPrivate, }, - filesystem::sysfs::AttributeGroup, init::initcall::INITCALL_SUBSYS, }; @@ -62,10 +61,6 @@ impl Class for TtyClass { fn subsystem(&self) -> &SubSysPrivate { return &self.subsystem; } - - fn dev_groups(&self) -> &'static [&'static dyn AttributeGroup] { - return &[&CommonAttrGroup]; - } } /// 初始化帧缓冲区子系统 diff --git a/kernel/src/driver/video/fbdev/base/fbcon/mod.rs b/kernel/src/driver/video/fbdev/base/fbcon/mod.rs index 59120e33..3a5c6f9c 100644 --- a/kernel/src/driver/video/fbdev/base/fbcon/mod.rs +++ b/kernel/src/driver/video/fbdev/base/fbcon/mod.rs @@ -11,8 +11,8 @@ use crate::{ base::{ class::Class, device::{ - bus::Bus, device_manager, driver::Driver, CommonAttrGroup, Device, - DeviceCommonData, DeviceType, IdTable, + bus::Bus, device_manager, driver::Driver, Device, DeviceCommonData, DeviceType, + IdTable, }, kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState}, kset::KSet, @@ -235,7 +235,7 @@ impl Device for FbConsoleDevice { } fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> { - return Some(&[&AnonymousAttributeGroup, &CommonAttrGroup]); + return Some(&[&AnonymousAttributeGroup]); } fn dev_parent(&self) -> Option> { diff --git a/kernel/src/driver/video/fbdev/base/fbmem.rs b/kernel/src/driver/video/fbdev/base/fbmem.rs index 0b87bd2a..f85cdf06 100644 --- a/kernel/src/driver/video/fbdev/base/fbmem.rs +++ b/kernel/src/driver/video/fbdev/base/fbmem.rs @@ -18,7 +18,7 @@ use crate::{ device_manager, device_number::{DeviceNumber, Major}, driver::Driver, - sys_dev_char_kset, CommonAttrGroup, Device, DeviceCommonData, DeviceType, IdTable, + sys_dev_char_kset, Device, DeviceCommonData, DeviceType, IdTable, }, kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState}, kset::KSet, @@ -114,7 +114,7 @@ impl Class for GraphicsClass { } fn dev_groups(&self) -> &'static [&'static dyn AttributeGroup] { - return &[&CommonAttrGroup]; + return &[]; } } @@ -377,7 +377,7 @@ impl Device for FbDevice { } fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> { - Some(&[&FbDeviceAttrGroup, &CommonAttrGroup]) + Some(&[&FbDeviceAttrGroup]) } fn dev_parent(&self) -> Option> { diff --git a/kernel/src/exception/sysfs.rs b/kernel/src/exception/sysfs.rs index bcecb129..1e499bf5 100644 --- a/kernel/src/exception/sysfs.rs +++ b/kernel/src/exception/sysfs.rs @@ -5,7 +5,6 @@ use unified_init::macros::unified_init; use crate::{ driver::base::{ - device::CommonAttrGroup, kobject::{KObjType, KObject, KObjectManager, KObjectSysFSOps}, kset::KSet, }, @@ -46,7 +45,7 @@ impl KObjType for IrqKObjType { } fn attribute_groups(&self) -> Option<&'static [&'static dyn AttributeGroup]> { - Some(&[&IrqAttrGroup, &CommonAttrGroup]) + Some(&[&IrqAttrGroup]) } fn release(&self, _kobj: Arc) { diff --git a/kernel/src/net/socket/endpoint.rs b/kernel/src/net/socket/endpoint.rs index 9cd46103..4becdacd 100644 --- a/kernel/src/net/socket/endpoint.rs +++ b/kernel/src/net/socket/endpoint.rs @@ -2,7 +2,6 @@ use crate::{filesystem::vfs::InodeId, net::socket}; use alloc::{string::String, sync::Arc}; pub use smoltcp::wire::IpEndpoint; -pub use socket::netlink::endpoint::NetlinkEndpoint; #[derive(Debug, Clone)] pub enum Endpoint { @@ -14,8 +13,6 @@ pub enum Endpoint { Inode((Arc, String)), /// Unix传递id索引和path所用的端点 Unixpath((InodeId, String)), - /// NetLink端点 - Netlink(NetlinkEndpoint), } /// @brief 链路层端点 diff --git a/kernel/src/net/socket/mod.rs b/kernel/src/net/socket/mod.rs index c784dbf3..4c3dbe19 100644 --- a/kernel/src/net/socket/mod.rs +++ b/kernel/src/net/socket/mod.rs @@ -6,7 +6,6 @@ mod endpoint; mod family; pub mod inet; mod inode; -pub mod netlink; pub mod unix; mod utils; diff --git a/kernel/src/net/socket/netlink/af_netlink.rs b/kernel/src/net/socket/netlink/af_netlink.rs deleted file mode 100644 index bed04672..00000000 --- a/kernel/src/net/socket/netlink/af_netlink.rs +++ /dev/null @@ -1,1381 +0,0 @@ -// 参考https://code.dragonos.org.cn/xref/linux-6.1.9/net/netlink/af_netlink.c -use crate::filesystem::vfs::{FilePrivateData, FileSystem, IndexNode}; -use crate::libs::mutex::{Mutex, MutexGuard}; -use crate::libs::rwlock::RwLockWriteGuard; -use crate::libs::spinlock::SpinLockGuard; -use crate::net::socket::netlink::skbuff::SkBuff; -use crate::net::socket::*; -use crate::net::syscall::SockAddrNl; -use crate::time::timer::schedule_timeout; -use crate::{libs::rwlock::RwLock, syscall::Syscall}; -use alloc::string::String; -use alloc::sync::Arc; -use alloc::{boxed::Box, vec::Vec}; -use core::mem; -use core::ops::Deref; -use core::ptr::copy_nonoverlapping; -use core::{any::Any, fmt::Debug, hash::Hash}; -use hashbrown::HashMap; -use intertrait::CastFromSync; -use netlink::{ - sk_data_ready, NetlinkKernelCfg, NETLINK_ADD_MEMBERSHIP, NETLINK_DROP_MEMBERSHIP, - NETLINK_PKTINFO, -}; -use num::Zero; -use system_error::SystemError; -use system_error::SystemError::ECONNREFUSED; -use unified_init::macros::unified_init; - -use crate::net::socket::{AddressFamily, Endpoint, Inode, MessageFlag, Socket}; -use lazy_static::lazy_static; - -use super::callback::NetlinkCallback; -use super::endpoint::NetlinkEndpoint; -use super::netlink_proto::{proto_register, NETLINK_PROTO}; -use super::skbuff::{netlink_overrun, skb_orphan, skb_shared}; -use super::sock::SockFlags; -use super::{NLmsgFlags, NLmsgType, NLmsghdr, VecExt, NETLINK_USERSOCK, NL_CFG_F_NONROOT_SEND}; -use crate::init::initcall::INITCALL_CORE; -use crate::net::socket::netlink::NetlinkState; -// Flags constants -bitflags! { - pub struct NetlinkFlags: u32 { - const KERNEL_SOCKET = 0x1; - const RECV_PKTINFO = 0x2; - const BROADCAST_SEND_ERROR = 0x4; - const RECV_NO_ENOBUFS = 0x8; - const LISTEN_ALL_NSID = 0x10; - const CAP_ACK = 0x20; - const EXT_ACK = 0x40; - const STRICT_CHK = 0x80; - const NETLINK_F_KERNEL_SOCKET = 0x100; - } -} -#[derive(Clone, Debug)] -pub struct HListHead { - first: Option>, -} -#[derive(Debug)] -pub struct HListNode { - data: Arc>>, - next: Option>, -} -impl HListHead { - fn iter(&self) -> HListHeadIter { - HListHeadIter { - current: self.first.as_ref(), - } - } -} - -struct HListHeadIter<'a> { - current: Option<&'a Arc>, -} - -impl<'a> Iterator for HListHeadIter<'a> { - type Item = &'a Arc>>; - - fn next(&mut self) -> Option { - match self.current { - Some(node) => { - self.current = node.next.as_ref(); - Some(&node.data) - } - None => None, - } - } -} -type NetlinkSockComparator = Arc bool + Send + Sync>; -/// 每一个netlink协议族都有一个NetlinkTable,用于保存该协议族的所有netlink套接字 -pub struct NetlinkTable { - hash: HashMap>>>, - listeners: Option, - registered: u32, - flags: u32, - groups: u32, - mc_list: HListHead, - pub bind: Option i32 + Send + Sync>>, - pub unbind: Option i32 + Send + Sync>>, - pub compare: Option, -} -impl NetlinkTable { - fn new() -> NetlinkTable { - NetlinkTable { - hash: HashMap::new(), - listeners: Some(Listeners { - masks: Vec::with_capacity(32), - }), - registered: 0, - flags: 0, - groups: 32, - mc_list: HListHead { first: None }, - bind: None, - unbind: None, - compare: None, - } - } - fn listeners(&self) -> Listeners { - Listeners::new() - } - fn flags(&self) -> u32 { - 0 - } - fn groups(&self) -> u32 { - 0 - } - pub fn set_registered(&mut self, registered: u32) { - self.registered = registered; - } - pub fn set_flags(&mut self, flags: u32) { - self.flags = flags; - } - pub fn set_groups(&mut self, groups: u32) { - self.groups = groups; - } - pub fn get_registered(&self) -> u32 { - self.registered - } - fn set_callbacks(&mut self, cfg: NetlinkKernelCfg) { - self.bind = cfg.bind; - self.unbind = cfg.unbind; - self.compare = cfg.compare; - } -} - -// https://code.dragonos.org.cn/xref/linux-6.1.9/net/netlink/af_netlink.c#2916 -/// netlink 协议的最大数量 -const MAX_LINKS: usize = 32; -#[unified_init(INITCALL_CORE)] -/// netlink 协议的初始化函数 -fn netlink_proto_init() -> Result<(), SystemError> { - unsafe { - let err = proto_register(&mut NETLINK_PROTO, 0); - if err.is_err() { - return Err(SystemError::ENOSYS); - } - } - // 创建NetlinkTable,每种netlink协议类型占数组中的一项,后续内核中创建的不同种协议类型的netlink都将保存在这个表中,由该表统一维护 - // 检查NetlinkTable的大小是否符合预期 - let mut nl_table = NL_TABLE.write(); - // let mut nl_table = [0; MAX_LINKS]; - if nl_table.is_empty() { - panic!("netlink_init: Cannot allocate nl_table"); - } - // 初始化哈希表 - for i in 0..MAX_LINKS { - nl_table[i].hash = HashMap::new(); - } - // 将读写锁守卫作为参数传递,避免锁的重复获取造成阻塞 - netlink_add_usersock_entry(&mut nl_table); - // TODO: 以下函数需要 net namespace 支持 - sock_register(&NETLINK_FAMILY_OPS); - // register_pernet_subsys(&netlink_net_ops); - // register_pernet_subsys(&netlink_tap_net_ops); - /* The netlink device handler may be needed early. */ - // rtnetlink_init(); - Ok(()) -} - -pub struct NetlinkFamulyOps { - family: AddressFamily, - // owner: Module, -} - -// impl NetProtoFamily for NetlinkFamulyOps { -// // https://code.dragonos.org.cn/s?refs=netlink_create&project=linux-6.1.9 -// /// netlink_create() 用户空间创建一个netlink套接字 -// fn create(socket: &mut dyn Socket, protocol: i32, _kern: bool) -> Result<(), Error> { -// // 假设我们有一个类型来跟踪协议最大值 -// const MAX_LINKS: i32 = 1024; -// // if socket.type_ != SocketType::Raw && socket.type_ != SocketType::Dgram { -// // return Err(Error::SocketTypeNotSupported); -// // } -// if !(0..MAX_LINKS).contains(&protocol) { -// // todo: 这里不符合规范,后续待修改为 SystemError -// return Err(Error::ProtocolNotSupported); -// } -// // 安全的数组索引封装 -// let protocol = protocol as usize; -// Ok(()) -// } -// } - -lazy_static! { - static ref NETLINK_FAMILY_OPS: NetlinkFamulyOps = NetlinkFamulyOps { - family: AddressFamily::Netlink, - }; -} - -pub fn sock_register(ops: &NetlinkFamulyOps) {} -/// 初始化和注册一个用户套接字条目,并将其添加到全局的NetlinkTable向量中 -pub fn netlink_add_usersock_entry(nl_table: &mut RwLockWriteGuard>) { - let listeners: Option = Some(Listeners::new()); - let groups: u32 = 32; - if listeners.is_none() { - panic!("netlink_add_usersock_entry: Cannot allocate listeners\n"); - } - - let index = NETLINK_USERSOCK; - nl_table[index].groups = groups; - log::debug!( - "netlink_add_usersock_entry: nl_table[index].groups: {}", - nl_table[index].groups - ); - // rcu_assign_pointer(nl_table[index].listeners, listeners); - // nl_table[index].module = THIS_MODULE; - nl_table[index].registered = 1; - nl_table[index].flags = NL_CFG_F_NONROOT_SEND; -} -// https://code.dragonos.org.cn/xref/linux-6.1.9/net/netlink/af_netlink.c#572 -/// 内核套接字插入 nl_table -pub fn netlink_insert( - sk: Arc>>, - portid: u32, -) -> Result<(), SystemError> { - let mut nl_table: RwLockWriteGuard> = NL_TABLE.write(); - - let index = sk.lock().sk_protocol(); - - let nlk = Arc::new(RwLock::new( - sk.lock() - .deref() - .as_any() - .downcast_ref::() - .ok_or(SystemError::EINVAL)? - .clone(), - )); - { - let nlk_guard = nlk.read(); - // 检查端口是否匹配 - if nlk_guard.portid != portid { - log::debug!("netlink_insert: portid mismatch\n"); - return Err(SystemError::EOVERFLOW); - } - } - - { - let mut nlk_guard = nlk.write(); - // 绑定端口 - nlk_guard.portid = portid; - // 设置套接字已绑定 - nlk_guard.bound = portid != 0; - // 将套接字插入哈希表 - nl_table[index].hash.insert(portid, Arc::clone(&sk)); - log::debug!("netlink_insert: inserted socket\n"); - } - - Ok(()) -} - -fn netlink_bind( - sock: Arc>>, - addr: &SockAddrNl, -) -> Result<(), SystemError> { - log::info!("netlink_bind here!"); - let sk: Arc>> = Arc::clone(&sock); - // todo: net namespace支持 - // let net = sock_net(sk); - log::info!("netlink_bind: nl_family: {:?}", addr.nl_family); - // let nlk: Arc> = sock - // .clone() - // .arc_any() - // .downcast() - // .map_err(|_| SystemError::EINVAL)?; - - let nlk = Arc::new(Mutex::new( - sock.lock() - .deref() - .as_any() - .downcast_ref::() - .ok_or(SystemError::EINVAL)? - .clone(), - )); - let nladdr = addr; - let mut groups: u32; - log::info!("netlink_bind: nl_family: {:?}", nladdr.nl_family); - if nladdr.nl_family != AddressFamily::Netlink { - log::warn!("netlink_bind: nl_family != AF_NETLINK"); - return Err(SystemError::EINVAL); - } - groups = nladdr.nl_groups; - log::info!("netlink_bind: groups: {}", groups); - let mut nlk = nlk.lock(); - // Only superuser is allowed to listen multicasts - if groups != 0 { - let group_count = addr.nl_groups.count_ones(); // 计算多播组数量 - nlk.ngroups = group_count; - // if !netlink_allowed(sock, NL_CFG_F_NONROOT_RECV) { - // return Err(-EPERM); - // } - let _ = netlink_realloc_groups(&mut nlk); - } - - // BITS_PER_LONG = __WORDSIZE = 64 - if nlk.ngroups < 64 { - groups &= (1 << nlk.ngroups) - 1; - } - - let bound = nlk.bound; - log::info!("netlink_bind: bound: {}", bound); - if bound { - // Ensure nlk.portid is up-to-date. - if nladdr.nl_pid != nlk.portid { - return Err(SystemError::EINVAL); - } - } - - if groups != 0 { - for group in 0..(mem::size_of::() * 8) as u32 { - if group != groups { - continue; - } - // 尝试绑定到第 group + 1 个组播组。如果绑定成功(错误码err为0),则继续绑定下一个组播组。 - // err = nlk.bind().unwrap()(group + 1); - // if err == 0 { - // continue; - // } - // netlink_undo_bind(group, groups, sk); - // return Err(SystemError::EINVAL); - } - } - - // No need for barriers here as we return to user-space without - // using any of the bound attributes. - if !bound { - if nladdr.nl_pid != 0 { - log::info!("netlink_bind: insert"); - let _ = netlink_insert(sk, nladdr.nl_pid); - } else { - log::info!("netlink_bind: autobind"); - netlink_autobind(sock, &mut nlk.portid); - }; - // if err != 0 { - // BITS_PER_TYPE = SIZEOF TYPE * BITS PER BYTES - // todo - // netlink_undo_bind(mem::size_of::() * 8, groups, sk); - // netlink_unlock_table(); - // return Err(SystemError::EINVAL); - // } - } - // todo - // netlink_update_subscriptions(sk, nlk.subscriptions + hweight32(groups) - hweight32(nlk.groups.unwrap()[0])); - log::info!("netlink_bind: nlk.groups: {:?}", nlk.groups); - nlk.groups[0] = groups; - log::info!("netlink_bind: nlk.groups: {:?}", nlk.groups); - netlink_update_listeners(nlk); - - Ok(()) -} - -/// 自动为netlink套接字选择一个端口号,并在netlink table 中插入这个端口。如果端口已经被使用,它会尝试使用不同的端口号直到找到一个可用的端口。如果有多个线程同时尝试绑定,则认为是正常情况,并成功返回. -fn netlink_autobind(sk: Arc>>, portid: &mut u32) { - let mut rover: u32 = 0; - loop { - // 假设 netlink_lookup 是一个函数,返回一个 Option>>> 类型 - let ret = netlink_lookup(sk.lock().sk_protocol(), *portid); - - // 如果查询成功 - if ret.is_some() { - // 如果 rover 是 0,重置为 1 - if rover == 0 { - // todo:随机 - rover = 1; // 在 Rust 中不能有 -4096 这样的u32值,因此我们从 1 开始递减 - } else { - // 否则递减 rover - rover -= 1; - } - *portid = rover; - } else { - // 如果查询失败,增加 rover - rover += 1; - *portid = rover; - break; - } - } - let _ = netlink_insert(sk, *portid); -} -// TODO: net namespace支持 -// https://code.dragonos.org.cn/xref/linux-6.1.9/net/netlink/af_netlink.c#532 -/// 在 netlink_table 中查找 netlink 套接字 -fn netlink_lookup(protocol: usize, portid: u32) -> Option>>> { - // todo: net 支持 - let nl_table = NL_TABLE.read(); - let index = protocol; - let sk = nl_table[index].hash.get(&portid).unwrap(); - Some(Arc::clone(sk)) -} - -// https://code.dragonos.org.cn/xref/linux-6.1.9/net/netlink/af_netlink.c#672 - -// netlink机制特定的内核抽象,不同于标准的trait Socket -pub trait NetlinkSocket: Socket + Any { - // fn sk_prot(&self) -> &dyn proto; - fn sk_family(&self) -> i32; - fn sk_state(&self) -> NetlinkState; - fn sk_protocol(&self) -> usize; - fn sk_rmem_alloc(&self) -> usize; - fn sk_rcvbuf(&self) -> usize; - fn enqueue_skb(&mut self, skb: Arc>); - fn is_kernel(&self) -> bool; - fn equals(&self, other: Arc>>) -> bool; - fn portid(&self) -> u32; - fn ngroups(&self) -> u64; - fn groups(&self) -> Vec; - fn flags(&self) -> Option; - fn sock_sndtimeo(&self, noblock: bool) -> i64; - fn as_any(&self) -> &dyn Any; -} - -pub trait NetlinkSocketWithCallback { - fn sk_data_ready(&self, callback: impl Fn(i32) -> i32); -} -/* linux:struct sock has to be the first member of netlink_sock */ -// linux 6.1.9中的netlink_sock结构体里,sock是一个很大的结构体,这里简化 -// 意义是:netlink_sock(NetlinkSock)是一个sock(NetlinkSocket), 实现了 Netlinksocket trait 和 Sock trait. - -#[derive(Debug, Clone)] -struct NetlinkSockMetadata {} -impl NetlinkSockMetadata { - fn new() -> NetlinkSockMetadata { - NetlinkSockMetadata {} - } -} -#[derive(Debug, Clone)] -#[cast_to([sync] Socket)] -#[cast_to([sync] NetlinkSocket)] -pub struct NetlinkSock { - // sk: Option>, - portid: u32, - node: Arc, - dst_portid: u32, - dst_group: u32, - pub flags: u32, - subscriptions: u32, - ngroups: u32, - groups: Vec, - pub protocol: usize, - bound: bool, - state: NetlinkState, - max_recvmsg_len: usize, - dump_done_errno: i32, - cb_running: bool, - queue: Vec>>, - data: Arc>>>, - sk_sndtimeo: i64, - sk_rcvtimeo: i64, - callback: Option<&'static dyn NetlinkCallback>, -} -impl Socket for NetlinkSock { - fn connect(&self, _endpoint: Endpoint) -> Result<(), SystemError> { - self.netlink_connect(_endpoint) - } - fn shutdown(&self, _type: ShutdownTemp) -> Result<(), SystemError> { - todo!() - } - fn bind(&self, _endpoint: Endpoint) -> Result<(), SystemError> { - log::debug!("NetlinkSock bind to {:?}", _endpoint); - match _endpoint { - Endpoint::Netlink(netlinkendpoint) => { - let addr = netlinkendpoint.addr; - let sock: Arc>> = - Arc::new(Mutex::new(Box::new(self.clone()))); - return netlink_bind(sock, &addr); - } - _ => { - return Err(SystemError::EINVAL); - } - } - } - fn close(&self) -> Result<(), SystemError> { - Ok(()) - } - fn listen(&self, _backlog: usize) -> Result<(), SystemError> { - todo!() - } - fn accept(&self) -> Result<(Arc, Endpoint), SystemError> { - todo!() - } - - fn wait_queue(&self) -> &WaitQueue { - todo!() - } - - fn poll(&self) -> usize { - todo!() - } - // 借用 send_to 的接口模拟netlink_sendmsg的功能 - fn send_to( - &self, - buffer: &[u8], - flags: MessageFlag, - address: Endpoint, - ) -> Result { - log::debug!("NetlinkSock send_to"); - return self.netlink_send(buffer, address); - } - // 借用 recv_from 的接口模拟netlink_recvmsg的功能 - fn recv_from( - &self, - msg: &mut [u8], - flags: MessageFlag, - address: Option, - ) -> Result<(usize, Endpoint), SystemError> { - log::debug!("NetlinkSock recv_from"); - return self.netlink_recv(msg, flags); - } - fn send_buffer_size(&self) -> usize { - log::warn!("send_buffer_size is implemented to 0"); - 0 - } - fn recv_buffer_size(&self) -> usize { - log::warn!("recv_buffer_size is implemented to 0"); - 0 - } - - fn set_option(&self, level: OptionsLevel, name: usize, val: &[u8]) -> Result<(), SystemError> { - return netlink_setsockopt(self, level, name, val); - } -} -impl IndexNode for NetlinkSock { - fn read_at( - &self, - offset: usize, - len: usize, - buf: &mut [u8], - _data: SpinLockGuard, - ) -> Result { - // Implementation of the function - Ok(0) - } - fn write_at( - &self, - offset: usize, - len: usize, - buf: &[u8], - _data: SpinLockGuard, - ) -> Result { - // Implementation of the function - Ok(0) - } - fn fs(&self) -> Arc { - todo!() - } - fn as_any_ref(&self) -> &dyn Any { - self - } - fn list(&self) -> Result, SystemError> { - // Implementation of the function - Ok(Vec::new()) - } -} -// TODO: 实现 NetlinkSocket trait -impl NetlinkSocket for NetlinkSock { - fn sk_family(&self) -> i32 { - 0 - } - fn sk_state(&self) -> NetlinkState { - return self.state; - } - fn sk_protocol(&self) -> usize { - return self.protocol; - } - fn sk_rmem_alloc(&self) -> usize { - 0 - } - fn sk_rcvbuf(&self) -> usize { - 0 - } - fn enqueue_skb(&mut self, skb: Arc>) { - self.queue.push(skb); - } - fn is_kernel(&self) -> bool { - self.flags & NetlinkFlags::NETLINK_F_KERNEL_SOCKET.bits() != 0 - } - fn equals(&self, other: Arc>>) -> bool { - let binding = other.lock(); - let nlk = binding - .deref() - .as_any() - .downcast_ref::() - .ok_or(SystemError::EINVAL) - .clone() - .unwrap(); - return self.portid == nlk.portid; - } - fn portid(&self) -> u32 { - 0 - } - fn ngroups(&self) -> u64 { - 0 - } - fn groups(&self) -> Vec { - Vec::new() - } - fn flags(&self) -> Option { - Some(SockFlags::Dead) - } - fn sock_sndtimeo(&self, noblock: bool) -> i64 { - if noblock { - return 0; - } else { - return self.sk_sndtimeo; - } - } - fn as_any(&self) -> &dyn Any { - self - } -} -impl NetlinkSocketWithCallback for NetlinkSock { - fn sk_data_ready(&self, callback: impl Fn(i32) -> i32) { /* 实现 */ - } -} -impl NetlinkSock { - /// 元数据的缓冲区的大小 - pub const DEFAULT_METADATA_BUF_SIZE: usize = 1024; - /// 默认的接收缓冲区的大小 receive - pub const DEFAULT_RX_BUF_SIZE: usize = 512 * 1024; - /// 默认的发送缓冲区的大小 transmiss - pub const DEFAULT_TX_BUF_SIZE: usize = 512 * 1024; - pub fn new() -> NetlinkSock { - let vec_of_vec_u8: Vec> = Vec::new(); - let mutex_protected = Mutex::new(vec_of_vec_u8); - let data: Arc>>> = Arc::new(mutex_protected); - NetlinkSock { - // sk: None, - portid: 0, - node: Arc::new(HListHead { first: None }), - dst_portid: 0, - dst_group: 0, - flags: 0, - subscriptions: 0, - ngroups: 0, - groups: vec![0; 32], - bound: false, - state: NetlinkState::NetlinkUnconnected, - protocol: 1, - max_recvmsg_len: 0, - dump_done_errno: 0, - cb_running: false, - queue: Vec::new(), - data, - sk_sndtimeo: 0, - sk_rcvtimeo: 0, - callback: None, - } - } - // https://code.dragonos.org.cn/xref/linux-6.1.9/net/netlink/af_netlink.c#1078 - fn netlink_connect(&self, _endpoint: Endpoint) -> Result<(), SystemError> { - Ok(()) - } - - // https://code.dragonos.org.cn/xref/linux-6.1.9/net/netlink/af_netlink.c#1849 - /// 用户进程对netlink套接字调用 sendmsg() 系统调用后,内核执行netlink操作的总入口函数 - /// ## 参数 - /// - sock - 指向用户进程的netlink套接字,也就是发送方的 - /// - msg - 承载了发送方传递的netlink消息 - /// - len - netlink消息长度 - /// ## 备注 - /// netlink套接字在创建的过程中(具体是在 netlink_create 开头),已经和 netlink_ops (socket层netlink协议族的通用操作集合)关联,其中注册的 sendmsg 回调就是指向本函数 - fn netlink_send(&self, data: &[u8], address: Endpoint) -> Result { - log::info!("netlink_send: data: {:?}", data); - // 一个有效的 Netlink 消息至少应该包含一个消息头 - if data.len() < size_of::() { - log::warn!("netlink_send: data too short, len: {}", data.len()); - return Err(SystemError::EINVAL); - } - #[allow(unsafe_code)] - let header = unsafe { &*(data.as_ptr() as *const NLmsghdr) }; - if header.nlmsg_len > data.len() { - log::warn!( - "netlink_send: data too short, nlmsg_len: {}", - header.nlmsg_len - ); - return Err(SystemError::ENAVAIL); - } - // let message_type = NLmsgType::from(header.nlmsg_type); - let mut buffer = self.data.lock(); - buffer.clear(); - - let mut msg = Vec::new(); - let new_header = NLmsghdr { - nlmsg_len: 0, // to be determined later - nlmsg_type: NLmsgType::NLMSG_DONE, - nlmsg_flags: NLmsgFlags::NLM_F_MULTI, - nlmsg_seq: header.nlmsg_seq, - nlmsg_pid: header.nlmsg_pid, - }; - // 将新消息头序列化到 msg 中 - msg.push_ext(new_header); - // 将消息体数据追加到 msg 中 - msg.extend_from_slice(data); - // 确保 msg 的长度按照 4 字节对齐 - msg.align4(); - // msg 的开头设置消息长度。 - msg.set_ext(0, msg.len() as u32); - // 将序列化后的 msg 添加到发送缓冲区 buffer 中 - buffer.push(msg); - Ok(data.len()) - } - - // https://code.dragonos.org.cn/xref/linux-6.1.9/net/netlink/af_netlink.c#1938 - /// 用户进程对 netlink 套接字调用 recvmsg() 系统调用后,内核执行 netlink 操作的总入口函数 - /// ## 参数 - /// - sock - 指向用户进程的netlink套接字,也就是接收方的 - /// - msg - 用于存放接收到的netlink消息 - /// - len - 用户空间支持的netlink消息接收长度上限 - /// - flags - 跟本次接收操作有关的标志位集合(主要来源于用户空间) - fn netlink_recv( - &self, - msg: &mut [u8], - flags: MessageFlag, - ) -> Result<(usize, Endpoint), SystemError> { - let mut copied: usize = 0; - let mut buffer = self.data.lock(); - let msg_kernel = buffer.remove(0); - - // 判断是否是带外消息,如果是带外消息,直接返回错误码 - if flags == MessageFlag::OOB { - log::warn!("netlink_recv: OOB message is not supported"); - return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); - } - - // 计算实际要复制的数据长度,不能超过 msg_from 的长度 或 msg 缓冲区的长度 - let actual_len = msg_kernel.len().min(msg.len()); - - if !msg_kernel.is_empty() { - msg[..actual_len].copy_from_slice(&msg_kernel[..actual_len]); - copied = actual_len; - } else { - // 如果没有数据可复制,返回 0 字节被复制 - copied = 0; - } - - let endpoint = Endpoint::Netlink(NetlinkEndpoint { - addr: SockAddrNl { - nl_family: AddressFamily::Netlink, - nl_pad: 0, - nl_pid: self.portid, - nl_groups: 0, - }, - }); - - // 返回复制的字节数和端点信息 - log::debug!("netlink_recv: copied: {}, endpoint: {:?}", copied, endpoint); - Ok((copied, endpoint)) - } -} - -#[derive(Clone)] -pub struct Listeners { - // todo: rcu - // 动态位图,每一位代表一个组播组,如果对应位为 1,表示有监听 - masks: Vec, -} -impl Listeners { - /// 创建一个新的 `Listeners` 实例,并将 `masks` 的所有位初始化为 0 - pub fn new() -> Listeners { - let masks = vec![0u64; 32]; - Listeners { masks } - } -} - -fn initialize_netlink_table() -> RwLock> { - let mut tables = Vec::with_capacity(MAX_LINKS); - for _ in 0..MAX_LINKS { - tables.push(NetlinkTable::new()); - } - log::info!("initialize_netlink_table,len:{}", tables.len()); - RwLock::new(tables) -} - -lazy_static! { - /// 一个维护全局的 NetlinkTable 向量,每一个元素代表一个 netlink 协议类型,最大数量为 MAX_LINKS - pub static ref NL_TABLE: RwLock> = initialize_netlink_table(); -} -pub fn netlink_has_listeners(sk: &NetlinkSock, group: u32) -> i32 { - log::info!("netlink_has_listeners"); - let mut res = 0; - let protocol = sk.sk_protocol(); - - // 获取读锁 - let nl_table = NL_TABLE.read(); - - // 检查 protocol 是否在范围内 - if protocol >= nl_table.len() { - log::error!( - "Protocol {} is out of bounds, table's len is {}", - protocol, - nl_table.len() - ); - return res; - } - - // 获取对应的 NetlinkTable - let netlink_table = &nl_table[protocol]; - - // 检查 listeners 是否存在 - if let Some(listeners) = &netlink_table.listeners { - // 检查 group 是否在范围内 - log::info!("listeners.masks:{:?}", listeners.masks); - if group > 0 && (group as usize - 1) < listeners.masks.len() { - res = listeners.masks[group as usize - 1] as i32; - } else { - log::error!( - "Group {} is out of bounds, len is {}", - group, - listeners.masks.len() - ); - } - } else { - log::error!("Listeners for protocol {} are None", protocol); - } - - res -} -struct NetlinkBroadcastData<'a> { - exclude_sk: &'a Arc, - // net: &'a Net, - portid: u32, - group: u64, - failure: i32, - delivery_failure: i32, - congested: i32, - delivered: i32, - allocation: u32, - skb: Arc>, - skb_2: Arc>, -} -impl<'a> NetlinkBroadcastData<'a> { - pub fn copy_skb_to_skb_2(&mut self) { - let skb = self.skb.read().clone(); - *self.skb_2.write() = skb; - } -} -/// 尝试向指定用户进程 netlink 套接字发送组播消息 -/// ## 参数: -/// - sk: 指向一个 sock 结构,对应一个用户进程 netlink 套接字 -/// - info: 指向一个 netlink 组播消息的管理块 -/// ## 备注: -/// 传入的 netlink 套接字跟组播消息属于同一种 netlink 协议类型,并且这个套接字开启了组播阅订,除了这些,其他信息(比如阅订了具体哪些组播)都是不确定的 -fn do_one_broadcast( - sk: Arc>>, - info: &mut Box, -) -> Result<(), SystemError> { - log::info!("do_one_broadcast"); - // 从Arc中获取NetlinkSock - let nlk: Arc = Arc::clone(&sk) - .arc_any() - .downcast() - .map_err(|_| SystemError::EINVAL)?; - // 如果源 sock 和目的 sock 是同一个则直接返回 - if info.exclude_sk.equals(sk.clone()) { - return Err(SystemError::EINVAL); - } - // 如果目的单播地址就是该 netlink 套接字 - // 或者目的组播地址超出了该 netlink 套接字的上限 - // 或者该 netlink 套接字没有阅订这条组播消息,都直接返回 - if nlk.portid() == info.portid - || info.group > nlk.ngroups() - || !nlk.groups().contains(&(info.group - 1)) - { - return Err(SystemError::EINVAL); - } - // TODO: 需要net namespace支持 - // if !net_eq(sock_net(sk), info.net) { - // if !(nlk.flags & NetlinkFlags::LISTEN_ALL_NSID.bits()) { - // return; - // } - // if !peernet_has_id(sock_net(sk), info.net) { - // return; - // } - // if !file_ns_capable(sk.sk_socket.file, info.net.user_ns, CAP_NET_BROADCAST) { - // return; - // } - // } - - // 如果 netlink 组播消息的管理块携带了 failure 标志, 则对该 netlink 套接字设置缓冲区溢出状态 - if info.failure != 0 { - netlink_overrun(&sk); - return Err(SystemError::EINVAL); - } - // 设置 skb2,其内容来自 skb - if info.skb_2.read().is_empty() { - if skb_shared(&info.skb) { - info.copy_skb_to_skb_2(); - } else { - info.skb_2 = Arc::new(RwLock::new(info.skb.read().clone())); - skb_orphan(&info.skb_2); - } - } - // 到这里如果 skb2 还是 NULL,意味着上一步中 clone 失败 - if info.skb_2.read().is_empty() { - netlink_overrun(&sk); - info.failure = 1; - if sk.lock().flags().is_some() & !NetlinkFlags::BROADCAST_SEND_ERROR.bits().is_zero() { - info.delivery_failure = 1; - } - return Err(SystemError::EINVAL); - } - if sk_filter(&sk, &info.skb_2) { - return Err(SystemError::EINVAL); - } - // TODO: 需要net namespace支持 - // peernet2id用于检索与给定网络(net)相关联的对等网络(peer)的ID - // NETLINK_CB(info.skb_2).nsid = peernet2id(sock_net(sk), info.net); - // if NETLINK_CB(info.skb_2).nsid != NETNSA_NSID_NOT_ASSIGNED { - // NETLINK_CB(info.skb_2).nsid_is_set = true; - // } - let ret = netlink_broadcast_deliver(Arc::clone(&sk), &info.skb_2); - // 如果将承载了组播消息的 skb 发送到该用户进程 netlink 套接字失败 - if ret < 0 { - netlink_overrun(&sk); - if sk.lock().flags().is_some() & !NetlinkFlags::BROADCAST_SEND_ERROR.bits().is_zero() { - info.delivery_failure = 1; - } - } else { - info.congested |= ret; - info.delivered = 1; - info.skb_2 = Arc::new(RwLock::new(info.skb.read().clone())); - } - drop(sk); - log::info!("do_one_broadcast success"); - Ok(()) -} -/// 发送 netlink 组播消息 -/// ## 参数 -/// - ssk: 源 sock -/// - skb: 属于发送方的承载了netlink消息的skb -/// - portid: 目的单播地址 -/// - group: 目的组播地址 -/// -/// ## 备注: 以下2种情况都会调用到本函数: -/// [1]. 用户进程 --组播--> 用户进程 -/// [2]. kernel --组播--> 用户进程 -/// -pub fn netlink_broadcast( - ssk: &Arc, - skb: Arc>, - portid: u32, - group: u64, - allocation: u32, -) -> Result<(), SystemError> { - log::info!("netlink_broadcast"); - // TODO: 需要net namespace支持 - // let net = sock_net(ssk); - let mut info = Box::new(NetlinkBroadcastData { - exclude_sk: ssk, - // net, - portid, - group, - failure: 0, - delivery_failure: 0, - congested: 0, - delivered: 0, - allocation, - skb, - skb_2: Arc::new(RwLock::new(SkBuff::new())), - }); - - // While we sleep in clone, do not allow to change socket list - let nl_table = NL_TABLE.read(); - // 遍历该 netlink 套接字所在协议类型中所有阅订了组播功能的套接字,然后尝试向其发送该组播消息 - for sk in &mut nl_table[ssk.sk_protocol()].mc_list.iter() { - let _ = do_one_broadcast(Arc::clone(sk), &mut info); - } - - drop(info.skb); - - if info.delivery_failure != 0 { - return Err(SystemError::ENOBUFS); - } - drop(info.skb_2); - - if info.delivered != 0 { - if info.congested != 0 { - Syscall::do_sched_yield()?; - } - return Ok(()); - } - return Err(SystemError::ESRCH); -} - -/// 对网络套接字(sk)和网络数据包(skb)进行过滤 -fn sk_filter(sk: &Arc>>, skb: &Arc>) -> bool { - // TODO: Implementation of the function - false -} - -// https://code.dragonos.org.cn/xref/linux-6.1.9/net/netlink/af_netlink.c?fi=netlink_has_listeners#1400 -/// 处理Netlink套接字的广播消息传递 -/// - 将携带了 netlink 组播消息的 skb 发送到指定目的用户进程 netlink 套接字 -/// -/// ## 参数 -/// - sk: 指向一个 sock 结构,对应一个用户进程 netlink 套接字 -/// - skb: 指向一个网络缓冲区 skb,携带了 netlink 组播消息 -/// -/// ## 返回值 -/// - -1: 套接字接收条件不满足 -/// - 0: netlink组播消息发送成功,套接字已经接收但尚未处理数据长度小于等于其接收缓冲的1/2 -/// - 1: netlink组播消息发送成功,套接字已经接收但尚未处理数据长度大于其接收缓冲的1/2(这种情况似乎意味着套接字处于拥挤状态) -/// -/// ## 备注: -/// - 到这里,已经确定了传入的 netlink 套接字跟组播消息匹配正确; -/// - netlink 组播消息不支持阻塞 -fn netlink_broadcast_deliver( - sk: Arc>>, - skb: &Arc>, -) -> i32 { - log::info!("netlink_broadcast_deliver"); - let nlk: Arc> = Arc::clone(&sk) - .arc_any() - .downcast() - .expect("Invalid downcast to LockedNetlinkSock"); - let nlk_guard = nlk.read(); - // 如果接收缓冲区的已分配内存小于或等于其总大小,并且套接字没有被标记为拥塞,则继续执行内部的代码块。 - if (sk.lock().sk_rmem_alloc() <= sk.lock().sk_rcvbuf()) - && !(nlk_guard.state == NetlinkState::NETLINK_S_CONGESTED) - { - // 如果满足接收条件,则设置skb的所有者是该netlink套接字 - netlink_skb_set_owner_r(skb, sk.clone()); - // 将 skb 发送到该 netlink 套接字,实际也就是将该 skb 放入了该套接字的接收队列中 - let _ = netlink_sendskb(sk.clone(), skb); - // 如果套接字的接收缓冲区已经接收但尚未处理数据长度大于其接收缓冲的1/2,则返回1 - if sk.lock().sk_rmem_alloc() > (sk.lock().sk_rcvbuf() >> 1) { - return 1; - } else { - return 0; - } - } - -1 -} -// https://code.dragonos.org.cn/xref/linux-6.1.9/net/netlink/af_netlink.c?fi=netlink_has_listeners#387 -/// 设置一个网络缓冲区skb的所有者为指定的源套接字sk -fn netlink_skb_set_owner_r(skb: &Arc>, sk: Arc>>) { - // WARN_ON(skb->sk != NULL); - let mut skb_write = skb.write(); - skb_write.sk = sk; - // skb->destructor = netlink_skb_destructor; - // atomic_add(skb->truesize, &sk->sk_rmem_alloc); - // sk_mem_charge(sk, skb->truesize); -} -pub struct NetlinkSocketWrapper { - sk: Arc, -} -impl NetlinkSocketWrapper { - pub fn new(sk: Arc) -> NetlinkSocketWrapper { - NetlinkSocketWrapper { sk } - } -} -// https://code.dragonos.org.cn/xref/linux-6.1.9/net/netlink/af_netlink.c?fi=netlink_has_listeners#1268 -/// 将一个网络缓冲区 skb 中的数据发送到指定的 目标进程套接字 sk -fn netlink_sendskb(sk: Arc>>, skb: &Arc>) -> u32 { - let len = skb.read().len; - { - // 将 skb 放入该 netlink 套接字接收队列末尾 - sk.lock().enqueue_skb(skb.clone()); - // 执行 sk_data_ready 回调通知该套接字有数据可读 - let nlk: Arc = Arc::clone(&sk) - .arc_any() - .downcast() - .expect("Invalid downcast to NetlinkSock"); - let _ = sk_data_ready(nlk); - } - return len; -} -// https://code.dragonos.org.cn/xref/linux-6.1.9/net/netlink/af_netlink.c#1337 -/// 内核执行 netlink 单播消息 -/// ## 参数 -/// - ssk:源sock结构 -/// - skb: 属于发送方的承载了 netlink 消息的 skb -/// - portid: 目的单播地址 -/// - nonblock - 1:非阻塞调用,2:阻塞调用 -fn netlink_unicast( - ssk: Arc>>, - skb: Arc>, - portid: u32, - nonblock: bool, -) -> Result { - let mut err: i32; - // todo:重新调整skb的大小 - // skb = netlink_trim(skb, gfp_any()); - // 计算发送超时时间(如果是非阻塞调用,则返回 0) - let timeo: i64 = ssk.lock().sock_sndtimeo(nonblock); - loop { - // 根据源sock结构和目的单播地址,得到目的sock结构 - let sk = netlink_getsockbyportid(ssk.clone(), portid); - if sk.is_err() { - drop(skb); - return Err(sk.err().unwrap()); - } - let sk = sk.unwrap(); - - if sk.lock().is_kernel() { - return Ok(netlink_unicast_kernel(sk, ssk, skb)); - } - - if sk_filter(&sk, &skb) { - let err = skb.read().len; - drop(skb); - return Err(SystemError::EINVAL); - } - - err = netlink_attachskb(sk.clone(), skb.clone(), timeo, ssk.clone()).unwrap() as i32; - if err == 1 { - continue; // 重试 - } - if err != 0 { - return Err(SystemError::EAGAIN_OR_EWOULDBLOCK); - } - return Ok(netlink_sendskb(sk, &skb)); - } -} - -// https://code.dragonos.org.cn/xref/linux-6.1.9/net/netlink/af_netlink.c#1316 -/// 来自用户进程的 netlink 消息 单播 发往内核 netlink 套接字 -/// ## 参数 -/// - sk:目的sock结构 -/// - skb:属于发送方的承载了netlink消息的skb -/// - ssk:源sock结构 -/// ## 备注: -/// - skb的所有者在本函数中发生了变化 -fn netlink_unicast_kernel( - sk: Arc>>, - ssk: Arc>>, - skb: Arc>, -) -> u32 { - let mut ret: u32; - let nlk: Arc> = Arc::clone(&sk) - .arc_any() - .downcast() - .map_err(|_| SystemError::EINVAL) - .expect("Invalid downcast to LockedNetlinkSock"); - let nlk_guard = nlk.read(); - // ret = ECONNREFUSED = 111; - ret = 111; - // 检查内核netlink套接字是否注册了netlink_rcv回调(就是各个协议在创建内核netlink套接字时通常会传入的input函数) - if nlk_guard.callback.is_some() { - ret = skb.read().len; - netlink_skb_set_owner_r(&skb, sk); - // todo: netlink_deliver_tap_kernel(sk, ssk, skb); - nlk_guard.callback.unwrap().netlink_rcv(skb.clone()); - drop(skb); - } else { - // 如果指定的内核netlink套接字没有注册netlink_rcv回调,就直接丢弃所有收到的netlink消息 - drop(skb); - } - return ret; -} -// https://code.dragonos.org.cn/s?refs=netlink_attachskb&project=linux-6.1.9 -/// 将一个指定skb绑定到一个指定的属于用户进程的netlink套接字上 -/// ## 参数 -/// - sk: 目的套接字 -/// - ssk: 源套接字 -/// - skb: 待绑定的skb -/// - timeo: 超时时间 -/// ## 返回值 -/// - 小于0:表示错误,skb已经被释放,对套接字的引用也被释放。 -/// - 0:表示继续执行,skb可以被附加到套接字上。 -/// - 1:表示需要重新查找,可能因为等待超时或接收缓冲区不足。 -fn netlink_attachskb( - sk: Arc>>, - skb: Arc>, - mut timeo: i64, - ssk: Arc>>, -) -> Result { - let nlk: Arc> = Arc::clone(&sk) - .arc_any() - .downcast() - .map_err(|_| SystemError::EINVAL)?; - let nlk_guard = nlk.read(); - let ssk_option: Option>>> = Some(ssk.clone()); - - /* - 如果目的netlink套接字上已经接收尚未处理的数据大小超过了接收缓冲区大小, - 或者目的netlink套接字被设置了拥挤标志, - 意味着该sbk不能立即被目的netlink套接字接收,需要加入等待队列 - */ - if sk.lock().sk_rmem_alloc() > sk.lock().sk_rcvbuf() - || nlk_guard.state == NetlinkState::NETLINK_S_CONGESTED - { - // 申请一个等待队列 - let mut wq = WaitQueue::default(); - // 如果传入的超时时间为0, 意味着非阻塞调用,则丢弃这条 netlink 消息,并返回 EAGAIN - if timeo == 0 { - /* 如果该netlink消息对应的源sock结构不存在,或者该netlink消息来自kernel - * 则对目的netlink套接字设置缓冲区溢出状态 - */ - if ssk_option.is_none() || ssk.lock().is_kernel() { - netlink_overrun(&sk); - } - drop(skb); - return Err(SystemError::EAGAIN_OR_EWOULDBLOCK); - } - // 程序运行到这里意味着是阻塞调用 - // 改变当前进程状态为可中断 - // __set_current_state(TASK_INTERRUPTIBLE); - // todo: 将目的netlink套接字加入等待队列 - // add_wait_queue(&nlk_guard.wait, &wait); - - // 程序到这里意味着被唤醒了 - // 如果接收条件还是不满足,则要计算剩余的超时时间 - if (sk.lock().sk_rmem_alloc() > sk.lock().sk_rcvbuf() || - nlk_guard.state == NetlinkState::NETLINK_S_CONGESTED) && - // todo: sock_flag - sk.lock().flags() != Some(SockFlags::Dead) - { - timeo = schedule_timeout(timeo)?; - } - // 改变当前进程状态为运行 - // __set_current_state(TASK_RUNNING); - // 将目的 netlink 套接字从等待队列中删除 - // remove_wait_queue(&nlk_guard.wait, &wait); - - // todo: 如果在等待期间接收到信号 - // if (signal_pending(current)) { - // drop(skb); - // return sock_intr_errno(*timeo); - // } - return Ok(1); - } - netlink_skb_set_owner_r(&skb, sk); - return Ok(0); -} - -fn netlink_getsockbyportid( - ssk: Arc>>, - portid: u32, -) -> Result>>, SystemError> { - let sock: Arc>> = - netlink_lookup(ssk.lock().sk_protocol(), portid).unwrap(); - if Some(sock.clone()).is_none() { - return Err(SystemError::ECONNREFUSED); - } - - /* Don't bother queuing skb if kernel socket has no input function */ - let nlk_sock: Arc> = Arc::clone(&sock) - .arc_any() - .downcast() - .map_err(|_| SystemError::EINVAL)?; - let nlk_sock_guard = nlk_sock.read(); - let nlk_ssk: Arc> = Arc::clone(&ssk) - .arc_any() - .downcast() - .map_err(|_| SystemError::EINVAL)?; - let nlk_ssk_guard = nlk_ssk.read(); - /* dst_portid and sk_state can be changed in netlink_connect() */ - if sock.lock().sk_state() == NetlinkState::NetlinkUnconnected - && (nlk_sock_guard.dst_portid) != nlk_ssk_guard.portid - { - return Err(SystemError::ECONNREFUSED); - } - return Ok(sock); -} - -/// 设置 netlink 套接字的选项 -fn netlink_setsockopt( - nlk: &NetlinkSock, - level: OptionsLevel, - optname: usize, - optval: &[u8], -) -> Result<(), SystemError> { - if level != OptionsLevel::NETLINK { - return Err(SystemError::ENOPROTOOPT); - } - let optlen = optval.len(); - let mut val: usize = 0; - if optlen >= size_of::() { - unsafe { - if optval.len() >= size_of::() { - // 将 optval 中的数据拷贝到 val 中 - copy_nonoverlapping( - optval.as_ptr(), - &mut val as *mut usize as *mut u8, - size_of::(), - ); - } else { - return Err(SystemError::EFAULT); - } - } - } else { - return Err(SystemError::EINVAL); - } - match optname { - // add 和 drop 对应同一段代码 - NETLINK_ADD_MEMBERSHIP | NETLINK_DROP_MEMBERSHIP => { - let group = val as u64; - let mut nl_table = NL_TABLE.write(); - let netlink_table = &mut nl_table[nlk.protocol]; - let listeners = netlink_table.listeners.as_mut().unwrap(); - let group = group - 1; - let mask = 1 << (group % 64); - let idx = group / 64; - if optname == NETLINK_ADD_MEMBERSHIP { - listeners.masks[idx as usize] |= mask; - } else { - listeners.masks[idx as usize] &= !mask; - } - } - NETLINK_PKTINFO => { - // if val != 0 { - // nlk.flags |= NetlinkFlags::RECV_PKTINFO.bits(); - // } else { - // nlk.flags &= !NetlinkFlags::RECV_PKTINFO.bits(); - // } - } - _ => { - return Err(SystemError::ENOPROTOOPT); - } - } - Ok(()) -} - -fn netlink_update_listeners(nlk: MutexGuard) { - log::info!("netlink_update_listeners"); - let mut nl_table = NL_TABLE.write(); - let netlink_table = &mut nl_table[nlk.protocol]; - let listeners = netlink_table.listeners.as_mut().unwrap(); - listeners.masks.clear(); - log::info!("nlk.ngroups:{}", nlk.ngroups); - listeners.masks.resize(nlk.ngroups as usize, 0); - log::info!("nlk.groups:{:?}", nlk.groups); - for group in &nlk.groups { - let mask = 1 << (group % 64); - let idx = group / 64; - - listeners.masks[idx as usize] |= mask; - log::info!( - "group:{},mask:{},idx:{},masks:{:?}", - group, - mask, - idx, - listeners.masks - ); - } -} - -/// 重新分配 netlink 套接字的组 -fn netlink_realloc_groups(nlk: &mut MutexGuard) -> Result<(), SystemError> { - let nl_table = NL_TABLE.write(); - let groups = nl_table[nlk.protocol].groups; - if nl_table[nlk.protocol].registered == 0 { - // 没有注册任何组 - log::warn!("netlink_realloc_groups: not registered"); - return Err(SystemError::ENOENT); - } - if nlk.ngroups >= groups { - // 当前已分配的组数量 大于或等于 groups(当前协议的组数量),则没有必要重新分配\ - log::info!("netlink_realloc_groups: no need to realloc"); - return Ok(()); - } - log::info!("nlk.ngroups:{},groups:{}", nlk.ngroups, groups); - let mut new_groups = vec![0u32; groups as usize]; - log::info!("nlk.groups:{:?}", nlk.groups); - // 当 nlk.ngroups 大于 0 时复制数据 - if nlk.ngroups > 0 { - new_groups[..nlk.ngroups as usize].copy_from_slice(&nlk.groups); - } - nlk.groups = new_groups; - nlk.ngroups = groups; - log::info!("nlk.groups:{:?}", nlk.groups); - Ok(()) -} diff --git a/kernel/src/net/socket/netlink/callback.rs b/kernel/src/net/socket/netlink/callback.rs deleted file mode 100644 index 20c219d5..00000000 --- a/kernel/src/net/socket/netlink/callback.rs +++ /dev/null @@ -1,9 +0,0 @@ -use super::skbuff::SkBuff; -use crate::libs::rwlock::RwLock; -use alloc::sync::Arc; -use core::fmt::Debug; -pub trait NetlinkCallback: Send + Sync + Debug { - /// 接收到netlink数据包时的回调函数 - fn netlink_rcv(&self, skb: Arc>) -> i32; -} -struct NetlinkCallbackData {} diff --git a/kernel/src/net/socket/netlink/endpoint.rs b/kernel/src/net/socket/netlink/endpoint.rs deleted file mode 100644 index e8e1248b..00000000 --- a/kernel/src/net/socket/netlink/endpoint.rs +++ /dev/null @@ -1,10 +0,0 @@ -use crate::net::syscall::SockAddrNl; -#[derive(Debug, Clone)] -pub struct NetlinkEndpoint { - pub addr: SockAddrNl, -} -impl NetlinkEndpoint { - pub fn new(addr: SockAddrNl) -> Self { - NetlinkEndpoint { addr } - } -} diff --git a/kernel/src/net/socket/netlink/mod.rs b/kernel/src/net/socket/netlink/mod.rs deleted file mode 100644 index 8bcc16d8..00000000 --- a/kernel/src/net/socket/netlink/mod.rs +++ /dev/null @@ -1,343 +0,0 @@ -pub mod af_netlink; -pub mod callback; -pub mod endpoint; -pub mod netlink_proto; -pub mod skbuff; -pub mod sock; - -use super::{family, inet::datagram, Inode, Socket, Type}; -use crate::driver::base::uevent::KobjUeventEnv; -use alloc::sync::Arc; -use alloc::{boxed::Box, slice, vec::Vec}; -use system_error::SystemError; - -// https://code.dragonos.org.cn/xref/linux-6.1.9/net/netlink/ - -use crate::libs::mutex::Mutex; -use core::mem; - -use af_netlink::{netlink_insert, Listeners, NetlinkFlags, NetlinkSock, NetlinkSocket, NL_TABLE}; -// 监听事件类型 -pub const NETLINK_ADD_MEMBERSHIP: usize = 1; -pub const NETLINK_DROP_MEMBERSHIP: usize = 2; -pub const NETLINK_PKTINFO: usize = 3; // 接收包信息。如果设置了这个选项,套接字将接收包含发送者信息(如发送者的端口号和地址)的消息 - // Netlink protocol family -pub const NETLINK_ROUTE: usize = 0; -pub const NETLINK_UNUSED: usize = 1; -pub const NETLINK_USERSOCK: usize = 2; -pub const NETLINK_FIREWALL: usize = 3; -pub const NETLINK_SOCK_DIAG: usize = 4; -pub const NETLINK_NFLOG: usize = 5; -pub const NETLINK_XFRM: usize = 6; -pub const NETLINK_SELINUX: usize = 7; -pub const NETLINK_ISCSI: usize = 8; -pub const NETLINK_AUDIT: usize = 9; -pub const NETLINK_FIB_LOOKUP: usize = 10; -pub const NETLINK_CONNECTOR: usize = 11; -pub const NETLINK_NETFILTER: usize = 12; -pub const NETLINK_IP6_FW: usize = 13; -pub const NETLINK_DNRTMSG: usize = 14; -// implemente uevent needed -pub const NETLINK_KOBJECT_UEVENT: usize = 15; -pub const NETLINK_GENERIC: usize = 16; -// pub const NETLINK_DM : usize = 17; // Assuming DM Events is unused, not defined -pub const NETLINK_SCSITRANSPORT: usize = 18; -pub const NETLINK_ECRYPTFS: usize = 19; -pub const NETLINK_RDMA: usize = 20; -pub const NETLINK_CRYPTO: usize = 21; -pub const NETLINK_SMC: usize = 22; - -//pub const NETLINK_INET_DIAG = NETLINK_SOCK_DIAG; -pub const NETLINK_INET_DIAG: usize = 4; - -pub const MAX_LINKS: usize = 32; - -pub const NL_CFG_F_NONROOT_RECV: u32 = 1 << 0; -pub const NL_CFG_F_NONROOT_SEND: u32 = 1 << 1; - -bitflags! { -/// 四种通用的消息类型 nlmsg_type -pub struct NLmsgType: u8 { - /* Nothing. */ - const NLMSG_NOOP = 0x1; - /* Error */ - const NLMSG_ERROR = 0x2; - /* End of a dump */ - const NLMSG_DONE = 0x3; - /* Data lost */ - const NLMSG_OVERRUN = 0x4; -} - -//消息标记 nlmsg_flags -// const NLM_F_REQUEST = 1; /* It is request message. */ -// const NLM_F_MULTI = 2; /* Multipart message, terminated by NLMSG_DONE */ -// const NLM_F_ACK = 4; /* Reply with ack, with zero or error code */ -// const NLM_F_ECHO = 8; /* Echo this request */ -// const NLM_F_DUMP_INTR = 16; /* Dump was inconsistent due to sequence change */ -pub struct NLmsgFlags: u16 { - /* Flags values */ - const NLM_F_REQUEST = 0x01; - const NLM_F_MULTI = 0x02; - const NLM_F_ACK = 0x04; - const NLM_F_ECHO = 0x08; - const NLM_F_DUMP_INTR = 0x10; - const NLM_F_DUMP_FILTERED = 0x20; - - /* Modifiers to GET request */ - const NLM_F_ROOT = 0x100; /* specify tree root */ - const NLM_F_MATCH = 0x200; /* return all matching */ - const NLM_F_ATOMIC = 0x400; /* atomic GET */ - //const NLM_F_DUMP = NLM_F_ROOT | NLM_F_MATCH; - const NLM_F_DUMP = 0x100 | 0x200; - - /* Modifiers to NEW request */ - const NLM_F_REPLACE = 0x100; /* Override existing */ - const NLM_F_EXCL = 0x200; /* Do not touch, if it exists */ - const NLM_F_CREATE = 0x400; /* Create, if it does not exist */ - const NLM_F_APPEND = 0x800; /* Add to end of list */ - - /* Modifiers to DELETE request */ - const NLM_F_NONREC = 0x100; /* Do not delete recursively */ - - /* Flags for ACK message */ - const NLM_F_CAPPED = 0x100; /* request was capped */ - const NLM_F_ACK_TLVS = 0x200; /* extended ACK TVLs were included */ -} -} -// 定义Netlink消息的结构体,如NLmsghdr和geNLmsghdr(拓展的netlink消息头),以及用于封包和解包消息的函数。 -// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/netlink.h -/// netlink消息报头 -/** - * struct NLmsghdr - fixed format metadata header of Netlink messages - * @nlmsg_len: Length of message including header - * @nlmsg_type: Message content type - * @nlmsg_flags: Additional flags - * @nlmsg_seq: Sequence number - * @nlmsg_pid: Sending process port ID - */ -pub struct NLmsghdr { - pub nlmsg_len: usize, - pub nlmsg_type: NLmsgType, - pub nlmsg_flags: NLmsgFlags, - pub nlmsg_seq: u32, - pub nlmsg_pid: u32, -} - -const NLMSG_ALIGNTO: usize = 4; -#[derive(Debug, PartialEq, Copy, Clone)] -pub enum NetlinkState { - NetlinkUnconnected = 0, - NetlinkConnected, - NETLINK_S_CONGESTED = 2, -} - -fn nlmsg_align(len: usize) -> usize { - (len + NLMSG_ALIGNTO - 1) & !(NLMSG_ALIGNTO - 1) -} - -fn nlmsg_hdrlen() -> usize { - nlmsg_align(mem::size_of::()) -} - -fn nlmsg_length(len: usize) -> usize { - len + nlmsg_hdrlen() -} - -fn nlmsg_space(len: usize) -> usize { - nlmsg_align(nlmsg_length(len)) -} - -unsafe fn nlmsg_data(nlh: &NLmsghdr) -> *mut u8 { - ((nlh as *const NLmsghdr) as *mut u8).add(nlmsg_length(0)) -} - -unsafe fn nlmsg_next(nlh: *mut NLmsghdr, len: usize) -> *mut NLmsghdr { - let nlmsg_len = (*nlh).nlmsg_len; - let new_len = len - nlmsg_align(nlmsg_len); - nlh.add(nlmsg_align(nlmsg_len)) -} - -fn nlmsg_ok(nlh: &NLmsghdr, len: usize) -> bool { - len >= nlmsg_hdrlen() && nlh.nlmsg_len >= nlmsg_hdrlen() && nlh.nlmsg_len <= len -} - -fn nlmsg_payload(nlh: &NLmsghdr, len: usize) -> usize { - nlh.nlmsg_len - nlmsg_space(len) -} -// 定义类型别名来简化闭包类型的定义 -type InputCallback = Arc; -type BindCallback = Arc i32 + Send + Sync>; -type UnbindCallback = Arc i32 + Send + Sync>; -type CompareCallback = Arc bool + Send + Sync>; -/// 该结构包含了内核netlink的可选参数: -#[derive(Default)] -pub struct NetlinkKernelCfg { - pub groups: u32, - pub flags: u32, - pub input: Option, - pub bind: Option, - pub unbind: Option, - pub compare: Option, -} - -impl NetlinkKernelCfg { - pub fn new() -> Self { - NetlinkKernelCfg { - groups: 32, - flags: 0, - input: None, - bind: None, - unbind: None, - compare: None, - } - } - - pub fn set_input(&mut self, callback: F) - where - F: FnMut() + Send + Sync + 'static, - { - self.input = Some(Arc::new(callback)); - } - - pub fn set_bind(&mut self, callback: F) - where - F: Fn(i32) -> i32 + Send + Sync + 'static, - { - self.bind = Some(Arc::new(callback)); - } - - pub fn set_unbind(&mut self, callback: F) - where - F: Fn(i32) -> i32 + Send + Sync + 'static, - { - self.unbind = Some(Arc::new(callback)); - } - - pub fn set_compare(&mut self, callback: F) - where - F: Fn(&NetlinkSock) -> bool + Send + Sync + 'static, - { - self.compare = Some(Arc::new(callback)); - } -} -// https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/netlink.h#229 -// netlink属性头 -struct NLattr { - nla_len: u16, - nla_type: u16, -} - -pub trait VecExt { - fn align4(&mut self); - fn push_ext(&mut self, data: T); - fn set_ext(&mut self, offset: usize, data: T); -} - -impl VecExt for Vec { - fn align4(&mut self) { - let len = (self.len() + 3) & !3; - if len > self.len() { - self.resize(len, 0); - } - } - - fn push_ext(&mut self, data: T) { - #[allow(unsafe_code)] - let bytes = - unsafe { slice::from_raw_parts(&data as *const T as *const u8, size_of::()) }; - for byte in bytes { - self.push(*byte); - } - } - - fn set_ext(&mut self, offset: usize, data: T) { - if self.len() < offset + size_of::() { - self.resize(offset + size_of::(), 0); - } - #[allow(unsafe_code)] - let bytes = - unsafe { slice::from_raw_parts(&data as *const T as *const u8, size_of::()) }; - self[offset..(bytes.len() + offset)].copy_from_slice(bytes); - } -} - -// todo: net namespace -pub fn netlink_kernel_create( - unit: usize, - cfg: Option, -) -> Result { - // THIS_MODULE - let mut nlk: NetlinkSock = NetlinkSock::new(); - let sk: Arc>> = Arc::new(Mutex::new(Box::new(nlk.clone()))); - let groups: u32; - if unit >= MAX_LINKS { - return Err(SystemError::EINVAL); - } - __netlink_create(&mut nlk, unit, 1).expect("__netlink_create failed"); - - if let Some(cfg) = cfg.as_ref() { - if cfg.groups < 32 { - groups = 32; - } else { - groups = cfg.groups; - } - } else { - groups = 32; - } - let listeners = Listeners::new(); - // todo:设计和实现回调函数 - // sk.sk_data_read = netlink_data_ready; - // if cfg.is_some() && cfg.unwrap().input.is_some(){ - // nlk.netlink_rcv = cfg.unwrap().input; - // } - netlink_insert(sk, 0).expect("netlink_insert failed"); - nlk.flags |= NetlinkFlags::NETLINK_F_KERNEL_SOCKET.bits(); - - let mut nl_table = NL_TABLE.write(); - if nl_table[unit].get_registered() == 0 { - nl_table[unit].set_groups(groups); - if let Some(cfg) = cfg.as_ref() { - nl_table[unit].bind = cfg.bind.clone(); - nl_table[unit].unbind = cfg.unbind.clone(); - nl_table[unit].set_flags(cfg.flags); - if cfg.compare.is_some() { - nl_table[unit].compare = cfg.compare.clone(); - } - nl_table[unit].set_registered(1); - } else { - drop(listeners); - let registered = nl_table[unit].get_registered(); - nl_table[unit].set_registered(registered + 1); - } - } - return Ok(nlk); -} - -fn __netlink_create(nlk: &mut NetlinkSock, unit: usize, kern: usize) -> Result { - // 其他的初始化配置参数 - nlk.flags = kern as u32; - nlk.protocol = unit; - return Ok(0); -} - -pub fn sk_data_ready(nlk: Arc) -> Result<(), SystemError> { - // 唤醒 - return Ok(()); -} - -pub struct Netlink; - -impl family::Family for Netlink { - /// 用户空间创建一个新的套接字的入口 - fn socket(stype: Type, _protocol: u32) -> Result, SystemError> { - let socket = create_netlink_socket(_protocol)?; - Ok(Inode::new(socket)) - } -} -/// 用户空间创建一个新的Netlink套接字 -fn create_netlink_socket(_protocol: u32) -> Result, SystemError> { - match _protocol as usize { - NETLINK_KOBJECT_UEVENT => Ok(Arc::new(af_netlink::NetlinkSock::new())), - _ => Err(SystemError::EPROTONOSUPPORT), - } -} diff --git a/kernel/src/net/socket/netlink/netlink.rs b/kernel/src/net/socket/netlink/netlink.rs deleted file mode 100644 index e69de29b..00000000 diff --git a/kernel/src/net/socket/netlink/netlink_proto.rs b/kernel/src/net/socket/netlink/netlink_proto.rs deleted file mode 100644 index 2aa8a187..00000000 --- a/kernel/src/net/socket/netlink/netlink_proto.rs +++ /dev/null @@ -1,56 +0,0 @@ -use bitmap::{traits::BitMapOps, AllocBitmap}; -use core::intrinsics::unlikely; -use system_error::SystemError; - -use crate::libs::lazy_init::Lazy; -pub const PROTO_INUSE_NR: usize = 64; -// pub static mut PROTO_INUSE_IDX: Lazy = Lazy::new(); -// pub static PROTO_INUSE_IDX: Lazy = Lazy::new(usize; -} -/// 协议操作集的结构体 -pub struct Proto<'a> { - name: &'a str, - // owner: THIS_MODULE, - obj_size: usize, - inuse_idx: Option, -} -impl Protocol for Proto<'_> { - fn close(&self) {} -} -/// 静态变量,用于注册netlink协议,是一个操作集结构体的实例 -// https://code.dragonos.org.cn/xref/linux-6.1.9/net/netlink/af_netlink.c#634 -pub static mut NETLINK_PROTO: Proto = Proto { - name: "NETLINK", - // owner: THIS_MODULE, - obj_size: core::mem::size_of::(), - // 运行时分配的索引 - inuse_idx: None, -}; -// https://code.dragonos.org.cn/xref/linux-6.1.9/net/core/sock.c?fi=proto_register#3853 -/// 注册协议 -pub fn proto_register(proto: &mut Proto, alloc_slab: i32) -> Result { - let mut ret = Err(SystemError::ENOBUFS); - if alloc_slab != 0 { - log::info!("TODO: netlink_proto: slab allocation not supported\n"); - return ret; - } - ret = assign_proto_idx(proto); - ret -} -// https://code.dragonos.org.cn/xref/linux-6.1.9/net/core/sock.c?fi=proto_register#3752 -/// 为协议分配一个索引 -pub fn assign_proto_idx(prot: &mut Proto) -> Result { - // prot.inuse_idx = unsafe { PROTO_INUSE_IDX.first_false_index() }; - // 如果没有找到空闲的索引 - if unlikely(prot.inuse_idx == Some(PROTO_INUSE_NR - 1)) { - log::info!("PROTO_INUSE_NR exhausted\n"); - return Err(SystemError::ENOSPC); - } - // 为协议分配一个索引 - // unsafe { PROTO_INUSE_IDX.set((prot.inuse_idx).unwrap(), true) }; - return Ok(0); -} diff --git a/kernel/src/net/socket/netlink/skbuff.rs b/kernel/src/net/socket/netlink/skbuff.rs deleted file mode 100644 index 99fbe66d..00000000 --- a/kernel/src/net/socket/netlink/skbuff.rs +++ /dev/null @@ -1,109 +0,0 @@ -use super::af_netlink::{NetlinkSock, NetlinkSocket}; -use crate::libs::{mutex::Mutex, rwlock::RwLock}; -use alloc::{boxed::Box, sync::Arc}; -// 曾用方案:在 smoltcp::PacketBuffer 的基础上封装了一层,用于处理 netlink 协议中网络数据包(skb)的相关操作 -// 暂时弃用,目前尝试使用更简单的方式处理 skb -#[derive(Debug, Clone)] -pub struct SkBuff { - pub sk: Arc>>, - pub len: u32, - pub pkt_type: u32, - pub mark: u32, - pub queue_mapping: u32, - pub protocol: u32, - pub vlan_present: u32, - pub vlan_tci: u32, - pub vlan_proto: u32, - pub priority: u32, - pub ingress_ifindex: u32, - pub ifindex: u32, - pub tc_index: u32, - pub cb: [u32; 5], - pub hash: u32, - pub tc_classid: u32, - pub data: u32, - pub data_end: u32, - pub napi_id: u32, - pub family: u32, - pub remote_ip4: u32, - pub local_ip4: u32, - pub remote_ip6: [u32; 4], - pub local_ip6: [u32; 4], - pub remote_port: u32, - pub local_port: u32, - pub data_meta: u32, - pub tstamp: u64, - pub wire_len: u32, - pub gso_segs: u32, - pub gso_size: u32, - pub tstamp_type: u8, - pub _bitfield_align_1: [u8; 0], - pub hwtstamp: u64, -} -impl SkBuff { - pub fn new() -> Self { - SkBuff { - sk: Arc::new(Mutex::new(Box::new(NetlinkSock::new()))), - len: 0, - pkt_type: 0, - mark: 0, - queue_mapping: 0, - protocol: 0, - vlan_present: 0, - vlan_tci: 0, - vlan_proto: 0, - priority: 0, - ingress_ifindex: 0, - ifindex: 0, - tc_index: 0, - cb: [0; 5], - hash: 0, - tc_classid: 0, - data: 0, - data_end: 0, - napi_id: 0, - family: 0, - remote_ip4: 0, - local_ip4: 0, - remote_ip6: [0; 4], - local_ip6: [0; 4], - remote_port: 0, - local_port: 0, - data_meta: 0, - tstamp: 0, - wire_len: 0, - gso_segs: 0, - gso_size: 0, - tstamp_type: 0, - _bitfield_align_1: [0; 0], - hwtstamp: 0, - } - } - pub fn is_empty(&self) -> bool { - self.len == 0 - } -} - -// 处理网络套接字的过度运行情况 -pub fn netlink_overrun(sk: &Arc>>) { - // Implementation of the function -} - -// 用于检查网络数据包(skb)是否被共享 -pub fn skb_shared(skb: &RwLock) -> bool { - // Implementation of the function - false -} - -/// 处理被孤儿化的网络数据包(skb) -/// 孤儿化网络数据包意味着数据包不再与任何套接字关联, -/// 通常是因为发送数据包时指定了 MSG_DONTWAIT 标志,这告诉内核不要等待必要的资源(如内存),而是尽可能快地发送数据包。 -pub fn skb_orphan(skb: &Arc>) { - // TODO: Implementation of the function -} - -fn skb_recv_datagram() {} - -fn skb_try_recv_datagram() {} - -fn skb_try_recv_from_queue() {} diff --git a/kernel/src/net/socket/netlink/sock.rs b/kernel/src/net/socket/netlink/sock.rs deleted file mode 100644 index 915b118c..00000000 --- a/kernel/src/net/socket/netlink/sock.rs +++ /dev/null @@ -1,33 +0,0 @@ -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum SockFlags { - Dead, - Done, - Urginline, - Keepopen, - Linger, - Destroy, - Broadcast, - Timestamp, - Zapped, - UseWriteQueue, // whether to call sk->sk_write_space in _wfree - Dbg, // %SO_DEBUG setting - Rcvtstamp, // %SO_TIMESTAMP setting - Rcvtstampns, // %SO_TIMESTAMPNS setting - Localroute, // route locally only, %SO_DONTROUTE setting - Memalloc, // VM depends on this et for swapping - TimestampingRxSoftware, // %SOF_TIMESTAMPING_RX_SOFTWARE - Fasync, // fasync() active - RxqOvfl, - Zerocopy, // buffers from userspace - WifiStatus, // push wifi status to userspace - Nofcs, // Tell NIC not to do the Ethernet FCS. - // Will use last 4 bytes of packet sent from - // user-space instead. - FilterLocked, // Filter cannot be changed anymore - SelectErrQueue, // Wake select on error queue - RcuFree, // wait rcu grace period in sk_destruct() - Txtime, - Xdp, // XDP is attached - TstampNew, // Indicates 64 bit timestamps always - Rcvmark, // Receive SO_MARK ancillary data with packet -} diff --git a/kernel/src/net/socket/utils.rs b/kernel/src/net/socket/utils.rs index 3ff64b7c..844b5a46 100644 --- a/kernel/src/net/socket/utils.rs +++ b/kernel/src/net/socket/utils.rs @@ -17,7 +17,6 @@ pub fn create_socket( todo!("AF_INET6 unimplemented"); } AF::Unix => socket::unix::Unix::socket(socket_type, protocol)?, - AF::Netlink => socket::netlink::Netlink::socket(socket_type, protocol)?, _ => { todo!("unsupport address family"); } diff --git a/kernel/src/net/syscall.rs b/kernel/src/net/syscall.rs index 295d688e..81f59576 100644 --- a/kernel/src/net/syscall.rs +++ b/kernel/src/net/syscall.rs @@ -21,7 +21,7 @@ use crate::{ }; use super::socket::{self, Endpoint, Socket}; -use super::socket::{netlink::endpoint, unix::Unix, AddressFamily as AF}; +use super::socket::{unix::Unix, AddressFamily as AF}; pub use super::syscall_util::*; diff --git a/kernel/src/net/syscall_util.rs b/kernel/src/net/syscall_util.rs index 41d521fb..12c47e7a 100644 --- a/kernel/src/net/syscall_util.rs +++ b/kernel/src/net/syscall_util.rs @@ -186,11 +186,6 @@ impl SockAddr { log::warn!("not support address family {:?}", addr.family); return Err(SystemError::EINVAL); } - AddressFamily::Netlink => { - // TODO: support netlink socket - let addr: SockAddrNl = addr.addr_nl; - return Ok(Endpoint::Netlink(NetlinkEndpoint::new(addr))); - } _ => { log::warn!("not support address family {:?}", addr.family); return Err(SystemError::EINVAL); @@ -290,17 +285,6 @@ impl From for SockAddr { return SockAddr { addr_ll }; } - Endpoint::Netlink(netlink_endpoint) => { - let addr_nl = SockAddrNl { - nl_family: AddressFamily::Netlink, - nl_pad: 0, - nl_pid: netlink_endpoint.addr.nl_pid, - nl_groups: netlink_endpoint.addr.nl_groups, - }; - - return SockAddr { addr_nl }; - } - Endpoint::Inode((_, path)) => { log::debug!("from unix path {:?}", path); let bytes = path.as_bytes(); diff --git a/user/apps/test-uevent/.cargo/config.toml b/user/apps/test-uevent/.cargo/config.toml deleted file mode 100644 index c1ca86b1..00000000 --- a/user/apps/test-uevent/.cargo/config.toml +++ /dev/null @@ -1,2 +0,0 @@ -[build] -target = "x86_64-unknown-linux-musl" \ No newline at end of file diff --git a/user/apps/test-uevent/.gitignore b/user/apps/test-uevent/.gitignore deleted file mode 100644 index 1ac35461..00000000 --- a/user/apps/test-uevent/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/target -Cargo.lock -/install/ \ No newline at end of file diff --git a/user/apps/test-uevent/Cargo.toml b/user/apps/test-uevent/Cargo.toml deleted file mode 100644 index 68597ed3..00000000 --- a/user/apps/test-uevent/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "test-uevent" -version = "0.1.0" -edition = "2021" -description = "test for uevent" -authors = [ "val213 " ] - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -netlink-sys = "0.5" -nix = "0.24" diff --git a/user/apps/test-uevent/Makefile b/user/apps/test-uevent/Makefile deleted file mode 100644 index 1b0274d2..00000000 --- a/user/apps/test-uevent/Makefile +++ /dev/null @@ -1,56 +0,0 @@ -TOOLCHAIN="+nightly-2023-08-15-x86_64-unknown-linux-gnu" -RUSTFLAGS+="" - -ifdef DADK_CURRENT_BUILD_DIR -# 如果是在dadk中编译,那么安装到dadk的安装目录中 - INSTALL_DIR = $(DADK_CURRENT_BUILD_DIR) -else -# 如果是在本地编译,那么安装到当前目录下的install目录中 - INSTALL_DIR = ./install -endif - -ifeq ($(ARCH), x86_64) - export RUST_TARGET=x86_64-unknown-linux-musl -else ifeq ($(ARCH), riscv64) - export RUST_TARGET=riscv64gc-unknown-linux-gnu -else -# 默认为x86_86,用于本地编译 - export RUST_TARGET=x86_64-unknown-linux-musl -endif - -run: - RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) run --target $(RUST_TARGET) - -build: - RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) build --target $(RUST_TARGET) - -clean: - RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) clean --target $(RUST_TARGET) - -test: - RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) test --target $(RUST_TARGET) - -doc: - RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) doc --target $(RUST_TARGET) - -fmt: - RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) fmt - -fmt-check: - RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) fmt --check - -run-release: - RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) run --target $(RUST_TARGET) --release - -build-release: - RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) build --target $(RUST_TARGET) --release - -clean-release: - RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) clean --target $(RUST_TARGET) --release - -test-release: - RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) test --target $(RUST_TARGET) --release - -.PHONY: install -install: - RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) install --target $(RUST_TARGET) --path . --no-track --root $(INSTALL_DIR) --force diff --git a/user/apps/test-uevent/README.md b/user/apps/test-uevent/README.md deleted file mode 100644 index 74b00a90..00000000 --- a/user/apps/test-uevent/README.md +++ /dev/null @@ -1,14 +0,0 @@ -# DragonOS Rust-Application Template - -您可以使用此模板来创建DragonOS应用程序。 - -## 使用方法 - -1. 使用DragonOS的tools目录下的`bootstrap.sh`脚本初始化环境 -2. 在终端输入`cargo install cargo-generate` -3. 在终端输入`cargo generate --git https://github.com/DragonOS-Community/Rust-App-Template`即可创建项目 -如果您的网络较慢,请使用镜像站`cargo generate --git https://git.mirrors.dragonos.org/DragonOS-Community/Rust-App-Template` -4. 使用`cargo run`来运行项目 -5. 在DragonOS的`user/dadk/config`目录下,使用`dadk new`命令,创建编译配置,安装到DragonOS的`/`目录下。 -(在dadk的编译命令选项处,请使用Makefile里面的`make install`配置进行编译、安装) -6. 编译DragonOS即可安装 diff --git a/user/apps/test-uevent/src/main.rs b/user/apps/test-uevent/src/main.rs deleted file mode 100644 index 4e6b4d21..00000000 --- a/user/apps/test-uevent/src/main.rs +++ /dev/null @@ -1,173 +0,0 @@ -use libc::{ - bind, c_void, getpid, recvfrom, sendto, sockaddr, sockaddr_storage, socket, AF_NETLINK, - SOCK_CLOEXEC, SOCK_DGRAM, -}; -use nix::libc; -use std::os::unix::io::RawFd; -use std::{io, mem}; - -#[repr(C)] -struct Nlmsghdr { - nlmsg_len: u32, - nlmsg_type: u16, - nlmsg_flags: u16, - nlmsg_seq: u32, - nlmsg_pid: u32, -} - -fn create_netlink_socket() -> io::Result { - let sockfd = unsafe { - socket( - AF_NETLINK, - SOCK_DGRAM | SOCK_CLOEXEC, - libc::NETLINK_KOBJECT_UEVENT, - ) - }; - - if sockfd < 0 { - println!("Error: {}", io::Error::last_os_error()); - return Err(io::Error::last_os_error()); - } - - Ok(sockfd) -} - -fn bind_netlink_socket(sock: RawFd) -> io::Result<()> { - let pid = unsafe { getpid() }; - let mut addr: libc::sockaddr_nl = unsafe { mem::zeroed() }; - addr.nl_family = AF_NETLINK as u16; - addr.nl_pid = pid as u32; - addr.nl_groups = 0; - - let ret = unsafe { - bind( - sock, - &addr as *const _ as *const sockaddr, - mem::size_of::() as u32, - ) - }; - - if ret < 0 { - println!("Error: {}", io::Error::last_os_error()); - return Err(io::Error::last_os_error()); - } - - Ok(()) -} - -fn send_uevent(sock: RawFd, message: &str) -> io::Result<()> { - let mut addr: libc::sockaddr_nl = unsafe { mem::zeroed() }; - addr.nl_family = AF_NETLINK as u16; - addr.nl_pid = 0; - addr.nl_groups = 0; - - let nlmsghdr = Nlmsghdr { - nlmsg_len: (mem::size_of::() + message.len()) as u32, - nlmsg_type: 0, - nlmsg_flags: 0, - nlmsg_seq: 0, - nlmsg_pid: 0, - }; - - let mut buffer = Vec::with_capacity(nlmsghdr.nlmsg_len as usize); - buffer.extend_from_slice(unsafe { - std::slice::from_raw_parts( - &nlmsghdr as *const Nlmsghdr as *const u8, - mem::size_of::(), - ) - }); - buffer.extend_from_slice(message.as_bytes()); - - let ret = unsafe { - sendto( - sock, - buffer.as_ptr() as *const c_void, - buffer.len(), - 0, - &addr as *const _ as *const sockaddr, - mem::size_of::() as u32, - ) - }; - - if ret < 0 { - println!("Error: {}", io::Error::last_os_error()); - return Err(io::Error::last_os_error()); - } - - Ok(()) -} - -fn receive_uevent(sock: RawFd) -> io::Result { - // 检查套接字文件描述符是否有效 - if sock < 0 { - println!("Invalid socket file descriptor: {}", sock); - return Err(io::Error::new( - io::ErrorKind::InvalidInput, - "Invalid socket file descriptor", - )); - } - - let mut buf = [0u8; 1024]; - // let mut addr: sockaddr_storage = unsafe { mem::zeroed() }; - // let mut addr_len = mem::size_of::() as u32; - - // 检查缓冲区指针和长度是否有效 - if buf.is_empty() { - println!("Buffer is empty"); - return Err(io::Error::new( - io::ErrorKind::InvalidInput, - "Buffer is empty", - )); - } - let len = unsafe { - recvfrom( - sock, - buf.as_mut_ptr() as *mut c_void, - buf.len(), - 0, - core::ptr::null_mut(), // 不接收发送方地址 - core::ptr::null_mut(), // 不接收发送方地址长度 - ) - }; - println!("Received {} bytes", len); - println!("Received message: {:?}", &buf[..len as usize]); - if len < 0 { - println!("Error: {}", io::Error::last_os_error()); - return Err(io::Error::last_os_error()); - } - - let nlmsghdr_size = mem::size_of::(); - if (len as usize) < nlmsghdr_size { - println!("Received message is too short"); - return Err(io::Error::new( - io::ErrorKind::InvalidData, - "Received message is too short", - )); - } - - let nlmsghdr = unsafe { &*(buf.as_ptr() as *const Nlmsghdr) }; - if nlmsghdr.nlmsg_len as isize > len { - println!("Received message is incomplete"); - return Err(io::Error::new( - io::ErrorKind::InvalidData, - "Received message is incomplete", - )); - } - - let message_data = &buf[nlmsghdr_size..nlmsghdr.nlmsg_len as usize]; - Ok(String::from_utf8_lossy(message_data).to_string()) -} - -fn main() { - let socket = create_netlink_socket().expect("Failed to create Netlink socket"); - println!("Netlink socket created successfully"); - - bind_netlink_socket(socket).expect("Failed to bind Netlink socket"); - println!("Netlink socket created and bound successfully"); - - send_uevent(socket, "add@/devices/virtual/block/loop0").expect("Failed to send uevent message"); - println!("Custom uevent message sent successfully"); - - let message = receive_uevent(socket).expect("Failed to receive uevent message"); - println!("Received uevent message: {}", message); -} diff --git a/user/dadk/config/test_uevent_0_1_0.dadk b/user/dadk/config/test_uevent_0_1_0.dadk deleted file mode 100644 index 0d9b74bb..00000000 --- a/user/dadk/config/test_uevent_0_1_0.dadk +++ /dev/null @@ -1,29 +0,0 @@ -{ - "name": "test-uevent", - "version": "0.1.0", - "description": "", - "rust_target": null, - "task_type": { - "BuildFromSource": { - "Local": { - "path": "apps/test-uevent" - } - } - }, - "depends": [], - "build": { - "build_command": "make install" - }, - "install": { - "in_dragonos_path": "/" - }, - "clean": { - "clean_command": "make clean" - }, - "envs": [], - "build_once": false, - "install_once": false, - "target_arch": [ - "x86_64" - ] -} \ No newline at end of file