From d7be7deebcd6b5fe531f8af66af7da1272061b27 Mon Sep 17 00:00:00 2001 From: val213 <1042594899@qq.com> Date: Tue, 15 Oct 2024 23:06:41 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B8=85=E7=90=86=E7=A7=AF=E5=BC=8A=EF=BC=8C?= =?UTF-8?q?=E4=B8=8D=E5=BF=85=E8=A6=81=E7=9A=84=E5=8A=A8=E6=80=81=E5=88=86?= =?UTF-8?q?=E5=8F=91=E5=92=8C=E6=99=BA=E8=83=BD=E6=8C=87=E9=92=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kernel/src/driver/base/block/block_device.rs | 7 +- kernel/src/driver/base/kobject.rs | 4 +- kernel/src/driver/base/kset.rs | 2 +- .../src/driver/base/uevent/kobject_uevent.rs | 94 +----- kernel/src/driver/base/uevent/mod.rs | 13 +- kernel/src/net/socket/netlink/af_netlink.rs | 293 ++++++------------ kernel/src/net/socket/netlink/mod.rs | 19 +- kernel/src/net/socket/netlink/skbuff.rs | 89 +----- kernel/src/net/syscall_util.rs | 1 - user/apps/test-uevent/README.md | 16 +- user/apps/test-uevent/src/main.rs | 6 +- 11 files changed, 145 insertions(+), 399 deletions(-) diff --git a/kernel/src/driver/base/block/block_device.rs b/kernel/src/driver/base/block/block_device.rs index 623b5008..2a9a9b1e 100644 --- a/kernel/src/driver/base/block/block_device.rs +++ b/kernel/src/driver/base/block/block_device.rs @@ -1,8 +1,9 @@ /// 引入Module -use crate::{driver::{ +use crate::driver::{ base::{ device::{ - device_number::{DeviceNumber, Major}, Device, DeviceError, IdTable, BLOCKDEVS + device_number::{DeviceNumber, Major}, + Device, DeviceError, IdTable, BLOCKDEVS, }, map::{ DeviceStruct, DEV_MAJOR_DYN_END, DEV_MAJOR_DYN_EXT_END, DEV_MAJOR_DYN_EXT_START, @@ -10,7 +11,7 @@ use crate::{driver::{ }, }, block::cache::{cached_block_device::BlockCache, BlockCacheError, BLOCK_SIZE}, -}, filesystem::sysfs::AttributeGroup}; +}; use alloc::{string::String, sync::Arc, vec::Vec}; use core::{any::Any, fmt::Display, ops::Deref}; 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..e1569c4c 100644 --- a/kernel/src/driver/base/kset.rs +++ b/kernel/src/driver/base/kset.rs @@ -259,6 +259,6 @@ impl KSetUeventOps for KSetUeventOpsDefault { } fn uevent(&self, env: &KobjUeventEnv) -> i32 { - 0 + todo!() } } diff --git a/kernel/src/driver/base/uevent/kobject_uevent.rs b/kernel/src/driver/base/uevent/kobject_uevent.rs index b55e3e3b..3357d0a6 100644 --- a/kernel/src/driver/base/uevent/kobject_uevent.rs +++ b/kernel/src/driver/base/uevent/kobject_uevent.rs @@ -83,15 +83,6 @@ 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功能一样,只是没有指定任何的环境变量 @@ -101,7 +92,7 @@ pub fn kobject_uevent(kobj: Arc, action: KobjectAction) -> Result<( } } -/// kobject_uevent_env,以envp为环境变量,上报一个指定action的uevent。环境变量的作用是为执行用户空间程序指定运行环境。 +/// kobject_uevent_env,以 envp 为环境变量,上报一个指定 action 的 uevent。环境变量的作用是为执行用户空间程序指定运行环境。 pub fn kobject_uevent_env( kobj: Arc, action: KobjectAction, @@ -271,43 +262,7 @@ pub fn kobject_uevent_env( 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(); + // todo: 设置了 UEVENT_HELP 编译条件之后,使用 handle_uevent_helper() 对指定的 uevent 进行处理,通常是热插拔程序 mdev、udev 等 drop(devpath); drop(env); log::info!("kobject_uevent_env: retval: {}", retval); @@ -383,53 +338,20 @@ pub fn kobject_uevent_net_broadcast( 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); + // TODO: net namespace // 如果有网络命名空间,则广播标记的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())); + let skb = Arc::new(RwLock::new(SkBuff::new(None))); skb } // https://code.dragonos.org.cn/xref/linux-6.1.9/lib/kobject_uevent.c#309 @@ -445,7 +367,7 @@ pub fn uevent_net_broadcast_untagged( devpath ); let mut retval = 0; - let mut skb = Arc::new(RwLock::new(SkBuff::new())); + let mut skb = Arc::new(RwLock::new(SkBuff::new(None))); // 锁定 UEVENT_SOCK_LIST 并遍历 let ue_sk_list = UEVENT_SOCK_LIST.lock(); @@ -456,16 +378,16 @@ pub fn uevent_net_broadcast_untagged( continue; } // 如果 skb 为空,则分配一个新的 skb - if skb.read().is_empty() { + if skb.read().inner.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() { + if skb.read().inner.is_empty() { continue; } } log::info!("next is netlink_broadcast"); - let netlink_socket: Arc = Arc::new(ue_sk.inner.clone()); + let netlink_socket = 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(), diff --git a/kernel/src/driver/base/uevent/mod.rs b/kernel/src/driver/base/uevent/mod.rs index e85c1df1..442551b8 100644 --- a/kernel/src/driver/base/uevent/mod.rs +++ b/kernel/src/driver/base/uevent/mod.rs @@ -157,10 +157,14 @@ impl Attribute for UeventAttr { 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 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(); @@ -200,7 +204,6 @@ impl Attribute for UeventAttr { } } - /// 将设备的基本信息写入 uevent 文件 fn sysfs_emit_str(buf: &mut [u8], content: &str) -> Result { log::info!("sysfs_emit_str"); diff --git a/kernel/src/net/socket/netlink/af_netlink.rs b/kernel/src/net/socket/netlink/af_netlink.rs index bed04672..593db14f 100644 --- a/kernel/src/net/socket/netlink/af_netlink.rs +++ b/kernel/src/net/socket/netlink/af_netlink.rs @@ -19,7 +19,7 @@ use hashbrown::HashMap; use intertrait::CastFromSync; use netlink::{ sk_data_ready, NetlinkKernelCfg, NETLINK_ADD_MEMBERSHIP, NETLINK_DROP_MEMBERSHIP, - NETLINK_PKTINFO, + NETLINK_KOBJECT_UEVENT, NETLINK_PKTINFO, }; use num::Zero; use system_error::SystemError; @@ -57,7 +57,7 @@ pub struct HListHead { } #[derive(Debug)] pub struct HListNode { - data: Arc>>, + data: Arc>, next: Option>, } impl HListHead { @@ -73,7 +73,7 @@ struct HListHeadIter<'a> { } impl<'a> Iterator for HListHeadIter<'a> { - type Item = &'a Arc>>; + type Item = &'a Arc>; fn next(&mut self) -> Option { match self.current { @@ -88,7 +88,7 @@ impl<'a> Iterator for HListHeadIter<'a> { type NetlinkSockComparator = Arc bool + Send + Sync>; /// 每一个netlink协议族都有一个NetlinkTable,用于保存该协议族的所有netlink套接字 pub struct NetlinkTable { - hash: HashMap>>>, + hash: HashMap>>, listeners: Option, registered: u32, flags: u32, @@ -102,9 +102,7 @@ impl NetlinkTable { fn new() -> NetlinkTable { NetlinkTable { hash: HashMap::new(), - listeners: Some(Listeners { - masks: Vec::with_capacity(32), - }), + listeners: Some(Listeners { masks: vec![0; 32] }), registered: 0, flags: 0, groups: 32, @@ -114,15 +112,6 @@ impl NetlinkTable { 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; } @@ -178,27 +167,8 @@ fn netlink_proto_init() -> Result<(), SystemError> { 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 { @@ -221,76 +191,61 @@ pub fn netlink_add_usersock_entry(nl_table: &mut RwLockWriteGuard>>, - portid: u32, -) -> Result<(), SystemError> { +pub fn netlink_insert(nlk: 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.lock(); + let index = nlk_guard.sk_protocol(); + // 检查端口是否匹配 + if nlk_guard.portid != portid { + log::debug!( + "netlink_insert: portid mismatch. nlk_guard.portid: {}, portid: {}", + nlk_guard.portid, + portid + ); + return Err(SystemError::EINVAL); } - { - 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"); - } + // 设置套接字已绑定 + nlk_guard.bound = portid != 0; + // 将套接字插入哈希表 + nl_table[index].hash.insert(portid, Arc::clone(&nlk)); + log::debug!("netlink_insert: inserted socket\n"); Ok(()) } - +// https://code.dragonos.org.cn/xref/linux-6.1.9/net/netlink/af_netlink.c#990 +/// netlink 套接字绑定多播组 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() + let nlk = { + let sock_guard = sock.lock(); + let netlink_sock = sock_guard .deref() .as_any() .downcast_ref::() .ok_or(SystemError::EINVAL)? - .clone(), - )); + .clone(); + Arc::new(Mutex::new(netlink_sock)) + }; + let nladdr = addr; + let mut nlk_guard = nlk.lock(); + nlk_guard.portid = addr.nl_pid; + + log::info!("netlink_bind: nlk.portid: {}", nlk_guard.portid); let mut groups: u32; log::info!("netlink_bind: nl_family: {:?}", nladdr.nl_family); if nladdr.nl_family != AddressFamily::Netlink { @@ -299,80 +254,49 @@ fn netlink_bind( } groups = nladdr.nl_groups; log::info!("netlink_bind: groups: {}", groups); - let mut nlk = nlk.lock(); - // Only superuser is allowed to listen multicasts + // todo: 只有 root 用户才能绑定多播组 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); + nlk_guard.ngroups = group_count; + netlink_realloc_groups(&mut nlk_guard).expect("netlink_realloc_groups failed"); } - // BITS_PER_LONG = __WORDSIZE = 64 - if nlk.ngroups < 64 { - groups &= (1 << nlk.ngroups) - 1; + if nlk_guard.ngroups < 32 { + groups &= (1 << nlk_guard.ngroups) - 1; } - let bound = nlk.bound; + let bound = nlk_guard.bound; log::info!("netlink_bind: bound: {}", bound); if bound { - // Ensure nlk.portid is up-to-date. - if nladdr.nl_pid != nlk.portid { + if nladdr.nl_pid != nlk_guard.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); + netlink_insert(nlk.clone(), nladdr.nl_pid).expect("netlink_insert failed"); } else { log::info!("netlink_bind: autobind"); - netlink_autobind(sock, &mut nlk.portid); + netlink_autobind(nlk.clone(), &mut nlk_guard.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); + + log::info!("netlink_bind: nlk.groups: {:?}", nlk_guard.groups); + nlk_guard.groups[0] = groups; + log::info!("netlink_bind: nlk.groups: {:?}", nlk_guard.groups); + netlink_update_listeners(&mut nlk_guard); Ok(()) } -/// 自动为netlink套接字选择一个端口号,并在netlink table 中插入这个端口。如果端口已经被使用,它会尝试使用不同的端口号直到找到一个可用的端口。如果有多个线程同时尝试绑定,则认为是正常情况,并成功返回. -fn netlink_autobind(sk: Arc>>, portid: &mut u32) { +/// 自动为netlink套接字选择一个端口号,并在 netlink table 中插入这个端口。如果端口已经被使用,它会尝试使用不同的端口号直到找到一个可用的端口。如果有多个线程同时尝试绑定,则认为是正常情况,并成功返回. +fn netlink_autobind(nlk: Arc>, portid: &mut u32) { let mut rover: u32 = 0; loop { // 假设 netlink_lookup 是一个函数,返回一个 Option>>> 类型 - let ret = netlink_lookup(sk.lock().sk_protocol(), *portid); + let ret = netlink_lookup(nlk.lock().sk_protocol(), *portid); // 如果查询成功 if ret.is_some() { @@ -392,12 +316,13 @@ fn netlink_autobind(sk: Arc>>, portid: &mut u32) { break; } } - let _ = netlink_insert(sk, *portid); + + netlink_insert(nlk, *portid).expect("netlink_insert failed"); } // 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>>> { +fn netlink_lookup(protocol: usize, portid: u32) -> Option>> { // todo: net 支持 let nl_table = NL_TABLE.read(); let index = protocol; @@ -417,7 +342,7 @@ pub trait NetlinkSocket: Socket + Any { fn sk_rcvbuf(&self) -> usize; fn enqueue_skb(&mut self, skb: Arc>); fn is_kernel(&self) -> bool; - fn equals(&self, other: Arc>>) -> bool; + fn equals(&self, other: Arc>) -> bool; fn portid(&self) -> u32; fn ngroups(&self) -> u64; fn groups(&self) -> Vec; @@ -444,7 +369,6 @@ impl NetlinkSockMetadata { #[cast_to([sync] Socket)] #[cast_to([sync] NetlinkSocket)] pub struct NetlinkSock { - // sk: Option>, portid: u32, node: Arc, dst_portid: u32, @@ -453,7 +377,7 @@ pub struct NetlinkSock { subscriptions: u32, ngroups: u32, groups: Vec, - pub protocol: usize, + protocol: usize, bound: bool, state: NetlinkState, max_recvmsg_len: usize, @@ -577,7 +501,7 @@ impl NetlinkSocket for NetlinkSock { return self.state; } fn sk_protocol(&self) -> usize { - return self.protocol; + return self.protocol as usize; } fn sk_rmem_alloc(&self) -> usize { 0 @@ -591,7 +515,7 @@ impl NetlinkSocket for NetlinkSock { fn is_kernel(&self) -> bool { self.flags & NetlinkFlags::NETLINK_F_KERNEL_SOCKET.bits() != 0 } - fn equals(&self, other: Arc>>) -> bool { + fn equals(&self, other: Arc>) -> bool { let binding = other.lock(); let nlk = binding .deref() @@ -636,12 +560,11 @@ impl NetlinkSock { pub const DEFAULT_RX_BUF_SIZE: usize = 512 * 1024; /// 默认的发送缓冲区的大小 transmiss pub const DEFAULT_TX_BUF_SIZE: usize = 512 * 1024; - pub fn new() -> NetlinkSock { + pub fn new(_protocol: Option) -> 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, @@ -652,7 +575,7 @@ impl NetlinkSock { groups: vec![0; 32], bound: false, state: NetlinkState::NetlinkUnconnected, - protocol: 1, + protocol: _protocol.unwrap_or(0), max_recvmsg_len: 0, dump_done_errno: 0, cb_running: false, @@ -763,6 +686,10 @@ impl NetlinkSock { log::debug!("netlink_recv: copied: {}, endpoint: {:?}", copied, endpoint); Ok((copied, endpoint)) } + + pub fn set_protocol(&mut self, protocol: usize) { + self.protocol = protocol; + } } #[derive(Clone)] @@ -784,6 +711,8 @@ fn initialize_netlink_table() -> RwLock> { for _ in 0..MAX_LINKS { tables.push(NetlinkTable::new()); } + // uevent 协议注册 + tables[NETLINK_KOBJECT_UEVENT].set_registered(1); log::info!("initialize_netlink_table,len:{}", tables.len()); RwLock::new(tables) } @@ -833,7 +762,7 @@ pub fn netlink_has_listeners(sk: &NetlinkSock, group: u32) -> i32 { res } struct NetlinkBroadcastData<'a> { - exclude_sk: &'a Arc, + exclude_sk: &'a Arc, // net: &'a Net, portid: u32, group: u64, @@ -858,7 +787,7 @@ impl<'a> NetlinkBroadcastData<'a> { /// ## 备注: /// 传入的 netlink 套接字跟组播消息属于同一种 netlink 协议类型,并且这个套接字开启了组播阅订,除了这些,其他信息(比如阅订了具体哪些组播)都是不确定的 fn do_one_broadcast( - sk: Arc>>, + sk: Arc>, info: &mut Box, ) -> Result<(), SystemError> { log::info!("do_one_broadcast"); @@ -880,18 +809,7 @@ fn do_one_broadcast( { 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; - // } - // } + // TODO: net namespace // 如果 netlink 组播消息的管理块携带了 failure 标志, 则对该 netlink 套接字设置缓冲区溢出状态 if info.failure != 0 { @@ -899,7 +817,7 @@ fn do_one_broadcast( return Err(SystemError::EINVAL); } // 设置 skb2,其内容来自 skb - if info.skb_2.read().is_empty() { + if info.skb_2.read().inner.is_empty() { if skb_shared(&info.skb) { info.copy_skb_to_skb_2(); } else { @@ -908,7 +826,7 @@ fn do_one_broadcast( } } // 到这里如果 skb2 还是 NULL,意味着上一步中 clone 失败 - if info.skb_2.read().is_empty() { + if info.skb_2.read().inner.is_empty() { netlink_overrun(&sk); info.failure = 1; if sk.lock().flags().is_some() & !NetlinkFlags::BROADCAST_SEND_ERROR.bits().is_zero() { @@ -953,18 +871,15 @@ fn do_one_broadcast( /// [2]. kernel --组播--> 用户进程 /// pub fn netlink_broadcast( - ssk: &Arc, + 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, @@ -973,7 +888,7 @@ pub fn netlink_broadcast( delivered: 0, allocation, skb, - skb_2: Arc::new(RwLock::new(SkBuff::new())), + skb_2: Arc::new(RwLock::new(SkBuff::new(None))), }); // While we sleep in clone, do not allow to change socket list @@ -1000,7 +915,7 @@ pub fn netlink_broadcast( } /// 对网络套接字(sk)和网络数据包(skb)进行过滤 -fn sk_filter(sk: &Arc>>, skb: &Arc>) -> bool { +fn sk_filter(sk: &Arc>, skb: &Arc>) -> bool { // TODO: Implementation of the function false } @@ -1021,10 +936,7 @@ fn sk_filter(sk: &Arc>>, skb: &Arc>) /// ## 备注: /// - 到这里,已经确定了传入的 netlink 套接字跟组播消息匹配正确; /// - netlink 组播消息不支持阻塞 -fn netlink_broadcast_deliver( - sk: Arc>>, - skb: &Arc>, -) -> i32 { +fn netlink_broadcast_deliver(sk: Arc>, skb: &Arc>) -> i32 { log::info!("netlink_broadcast_deliver"); let nlk: Arc> = Arc::clone(&sk) .arc_any() @@ -1048,27 +960,15 @@ fn netlink_broadcast_deliver( } -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); +fn netlink_skb_set_owner_r(skb: &Arc>, sk: Arc>) { 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 { +fn netlink_sendskb(sk: Arc>, skb: &Arc>) -> u32 { let len = skb.read().len; { // 将 skb 放入该 netlink 套接字接收队列末尾 @@ -1090,14 +990,12 @@ fn netlink_sendskb(sk: Arc>>, skb: &Arc>>, + 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 { @@ -1139,8 +1037,8 @@ fn netlink_unicast( /// ## 备注: /// - skb的所有者在本函数中发生了变化 fn netlink_unicast_kernel( - sk: Arc>>, - ssk: Arc>>, + sk: Arc>, + ssk: Arc>, skb: Arc>, ) -> u32 { let mut ret: u32; @@ -1177,17 +1075,17 @@ fn netlink_unicast_kernel( /// - 0:表示继续执行,skb可以被附加到套接字上。 /// - 1:表示需要重新查找,可能因为等待超时或接收缓冲区不足。 fn netlink_attachskb( - sk: Arc>>, + sk: Arc>, skb: Arc>, mut timeo: i64, - ssk: Arc>>, + 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()); + let ssk_option = Some(ssk.clone()); /* 如果目的netlink套接字上已经接收尚未处理的数据大小超过了接收缓冲区大小, @@ -1242,11 +1140,10 @@ fn netlink_attachskb( } fn netlink_getsockbyportid( - ssk: Arc>>, + ssk: Arc>, portid: u32, -) -> Result>>, SystemError> { - let sock: Arc>> = - netlink_lookup(ssk.lock().sk_protocol(), portid).unwrap(); +) -> Result>, SystemError> { + let sock = netlink_lookup(ssk.lock().sk_protocol(), portid).unwrap(); if Some(sock.clone()).is_none() { return Err(SystemError::ECONNREFUSED); } @@ -1316,6 +1213,7 @@ fn netlink_setsockopt( } } NETLINK_PKTINFO => { + todo!(); // if val != 0 { // nlk.flags |= NetlinkFlags::RECV_PKTINFO.bits(); // } else { @@ -1329,7 +1227,7 @@ fn netlink_setsockopt( Ok(()) } -fn netlink_update_listeners(nlk: MutexGuard) { +fn netlink_update_listeners(nlk: &mut MutexGuard) { log::info!("netlink_update_listeners"); let mut nl_table = NL_TABLE.write(); let netlink_table = &mut nl_table[nlk.protocol]; @@ -1341,8 +1239,6 @@ fn netlink_update_listeners(nlk: MutexGuard) { 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, @@ -1350,6 +1246,7 @@ fn netlink_update_listeners(nlk: MutexGuard) { idx, listeners.masks ); + listeners.masks[idx as usize] |= mask; } } @@ -1357,6 +1254,7 @@ fn netlink_update_listeners(nlk: MutexGuard) { fn netlink_realloc_groups(nlk: &mut MutexGuard) -> Result<(), SystemError> { let nl_table = NL_TABLE.write(); let groups = nl_table[nlk.protocol].groups; + log::info!("nlk.protocol:{},groups:{:?}", nlk.protocol, groups); if nl_table[nlk.protocol].registered == 0 { // 没有注册任何组 log::warn!("netlink_realloc_groups: not registered"); @@ -1368,11 +1266,12 @@ fn netlink_realloc_groups(nlk: &mut MutexGuard) -> Result<(), Syste 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); + let mut new_groups = vec![0u32; 32]; + log::info!("nlk.groups:{:?},len = {}", nlk.groups, nlk.groups.len()); + log::info!("new_groups:{:?},len = {}", new_groups, new_groups.len()); // 当 nlk.ngroups 大于 0 时复制数据 if nlk.ngroups > 0 { - new_groups[..nlk.ngroups as usize].copy_from_slice(&nlk.groups); + new_groups.copy_from_slice(&nlk.groups); } nlk.groups = new_groups; nlk.ngroups = groups; diff --git a/kernel/src/net/socket/netlink/mod.rs b/kernel/src/net/socket/netlink/mod.rs index 8bcc16d8..4b72ce3f 100644 --- a/kernel/src/net/socket/netlink/mod.rs +++ b/kernel/src/net/socket/netlink/mod.rs @@ -261,14 +261,13 @@ impl VecExt for Vec { } } -// todo: net namespace +/// 创建一个新的内核netlink套接字 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 mut nlk: NetlinkSock = NetlinkSock::new(Some(unit)); + let sk: Arc> = Arc::new(Mutex::new(nlk.clone())); let groups: u32; if unit >= MAX_LINKS { return Err(SystemError::EINVAL); @@ -314,9 +313,9 @@ pub fn netlink_kernel_create( } fn __netlink_create(nlk: &mut NetlinkSock, unit: usize, kern: usize) -> Result { - // 其他的初始化配置参数 + // 初始化配置参数 nlk.flags = kern as u32; - nlk.protocol = unit; + nlk.set_protocol(unit); return Ok(0); } @@ -330,14 +329,14 @@ pub struct Netlink; impl family::Family for Netlink { /// 用户空间创建一个新的套接字的入口 fn socket(stype: Type, _protocol: u32) -> Result, SystemError> { - let socket = create_netlink_socket(_protocol)?; + let socket = create_netlink_socket(_protocol as usize)?; 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())), +fn create_netlink_socket(_protocol: usize) -> Result, SystemError> { + match _protocol { + NETLINK_KOBJECT_UEVENT => Ok(Arc::new(af_netlink::NetlinkSock::new(Some(_protocol)))), _ => Err(SystemError::EPROTONOSUPPORT), } } diff --git a/kernel/src/net/socket/netlink/skbuff.rs b/kernel/src/net/socket/netlink/skbuff.rs index 99fbe66d..1c567ca6 100644 --- a/kernel/src/net/socket/netlink/skbuff.rs +++ b/kernel/src/net/socket/netlink/skbuff.rs @@ -1,97 +1,32 @@ use super::af_netlink::{NetlinkSock, NetlinkSocket}; use crate::libs::{mutex::Mutex, rwlock::RwLock}; -use alloc::{boxed::Box, sync::Arc}; -// 曾用方案:在 smoltcp::PacketBuffer 的基础上封装了一层,用于处理 netlink 协议中网络数据包(skb)的相关操作 -// 暂时弃用,目前尝试使用更简单的方式处理 skb +use alloc::{boxed::Box, sync::Arc, vec::Vec}; +use uefi_raw::protocol; +const SKB_SIZE: usize = 4096; // 定义 SKB 的大小 #[derive(Debug, Clone)] pub struct SkBuff { - pub sk: Arc>>, + 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, + pub inner: Vec, } impl SkBuff { - pub fn new() -> Self { + pub fn new(protocol: Option) -> Self { SkBuff { - sk: Arc::new(Mutex::new(Box::new(NetlinkSock::new()))), + sk: Arc::new(Mutex::new(NetlinkSock::new(protocol))), 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, + inner: vec![0u8; SKB_SIZE], } } - pub fn is_empty(&self) -> bool { - self.len == 0 - } } // 处理网络套接字的过度运行情况 -pub fn netlink_overrun(sk: &Arc>>) { - // Implementation of the function +pub fn netlink_overrun(sk: &Arc>) { + todo!() } // 用于检查网络数据包(skb)是否被共享 pub fn skb_shared(skb: &RwLock) -> bool { - // Implementation of the function + // todo!() false } @@ -99,7 +34,7 @@ pub fn skb_shared(skb: &RwLock) -> bool { /// 孤儿化网络数据包意味着数据包不再与任何套接字关联, /// 通常是因为发送数据包时指定了 MSG_DONTWAIT 标志,这告诉内核不要等待必要的资源(如内存),而是尽可能快地发送数据包。 pub fn skb_orphan(skb: &Arc>) { - // TODO: Implementation of the function + // todo!() } fn skb_recv_datagram() {} diff --git a/kernel/src/net/syscall_util.rs b/kernel/src/net/syscall_util.rs index 298ec84e..468ffca1 100644 --- a/kernel/src/net/syscall_util.rs +++ b/kernel/src/net/syscall_util.rs @@ -187,7 +187,6 @@ impl SockAddr { return Err(SystemError::EINVAL); } AddressFamily::Netlink => { - // TODO: support netlink socket let addr: SockAddrNl = addr.addr_nl; return Ok(Endpoint::Netlink(NetlinkEndpoint::new(addr))); } diff --git a/user/apps/test-uevent/README.md b/user/apps/test-uevent/README.md index 74b00a90..c24d8cc9 100644 --- a/user/apps/test-uevent/README.md +++ b/user/apps/test-uevent/README.md @@ -1,14 +1,4 @@ -# DragonOS Rust-Application Template +# test_uevent +这是一个测试 uevent 机制的应用,用于测试uevent的功能。 -您可以使用此模板来创建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 index d4831326..0ac1b7c0 100644 --- a/user/apps/test-uevent/src/main.rs +++ b/user/apps/test-uevent/src/main.rs @@ -1,4 +1,4 @@ -use libc::{sockaddr, sockaddr_storage, recvfrom, bind, sendto, socket, AF_NETLINK, SOCK_DGRAM, SOCK_CLOEXEC, getpid, c_void}; +use libc::{sockaddr, recvfrom, bind, sendto, socket, AF_NETLINK, SOCK_DGRAM, getpid, c_void}; use nix::libc; use std::os::unix::io::RawFd; use std::{ mem, io}; @@ -14,7 +14,7 @@ struct Nlmsghdr { fn create_netlink_socket() -> io::Result { let sockfd = unsafe { - socket(AF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, libc::NETLINK_KOBJECT_UEVENT) + socket(AF_NETLINK, SOCK_DGRAM, libc::NETLINK_KOBJECT_UEVENT) }; if sockfd < 0 { @@ -30,7 +30,7 @@ fn bind_netlink_socket(sock: RawFd) -> io::Result<()> { 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; + addr.nl_groups = 1; let ret = unsafe { bind(sock, &addr as *const _ as *const sockaddr, mem::size_of::() as u32)