diff --git a/drivers/net/dummy_rs.rs b/drivers/net/dummy_rs.rs index 552aebc7e18fbc..ce5406a8c9ebfd 100644 --- a/drivers/net/dummy_rs.rs +++ b/drivers/net/dummy_rs.rs @@ -1,23 +1,25 @@ // SPDX-License-Identifier: GPL-2.0 //! Rust dummy network driver -//! +//! //! This is a demonstration of what a small driver looks like in Rust, based on drivers/net/dummy.c. //! This code is provided as a demonstration only, not as a proposal to mass-rewrite existing drivers in Rust // TODO: copyright (see ./dummy.c) - #![no_std] #![feature(allocator_api, global_asm)] use core::ops::Deref; -use kernel::{net::netlink::{NlAttrVec, NlExtAck}, prelude::*}; -use kernel::net::prelude::*; use kernel::net::device; +use kernel::net::prelude::*; use kernel::net::rtnl; use kernel::Error; +use kernel::{ + net::netlink::{NlAttrVec, NlExtAck}, + prelude::*, +}; module! { type: RustNetDummy, @@ -25,7 +27,7 @@ module! { author: b"Rust for Linux Contributors", description: b"Rust dummy network driver", license: b"GPL v2", - alias: b"rtnl-link-dummy_rs", + alias_rtnl_link: b"dummy_rs", params: { numdummies: usize { default: 0, @@ -36,9 +38,10 @@ module! { } fn setup(dev: &mut NetDevice) { - pr_info!("called rtnl_setup"); dev.ether_setup(); + dev.set_ops(); + // Fill in device structure with ethernet-generic values. dev.add_flag(device::Iff::NOARP); dev.remove_flag(device::Iff::MULTICAST); @@ -67,7 +70,6 @@ fn setup(dev: &mut NetDevice) { } fn validate(tb: &NlAttrVec, data: &NlAttrVec, ext_ack: &NlExtAck) -> KernelResult<()> { - pr_info!("validate nlattr"); if let Some(addr) = tb.get(kernel::bindings::IFLA_ADDRESS) { if addr.nla_len() != kernel::net::netlink::ETH_ALEN { return Err(Error::EINVAL); @@ -75,10 +77,7 @@ fn validate(tb: &NlAttrVec, data: &NlAttrVec, ext_ack: &NlExtAck) -> KernelResul if !addr.is_valid_ether_addr() { return Err(Error::EADDRNOTAVAIL); } - } else { - pr_info!("no IFLA_ADDRESS in nlattr"); } - pr_info!("valid nlattr"); Ok(()) } @@ -90,52 +89,51 @@ rtnl_link_ops! { } struct RustNetDummy { - dev: NetDevice, + //dev: NetDevice, } - impl KernelModule for RustNetDummy { fn init() -> KernelResult { - { - let lock =THIS_MODULE.kernel_param_lock(); - pr_info!("Rust Network Dummy with {} pseudo devices\n", numdummies.read(&lock)); - } - - unsafe { dummy_rs_rtnl_link_ops.register() }?; - - let mut dev = NetDevice::new(DummyRsDev, kernel::cstr!("dummyrs%d"), kernel::net::device::NetNameAssingType::Enum, 1, 1)?; - dev.set_rtnl_ops( unsafe { &dummy_rs_rtnl_link_ops }); - - if let Err(e) = dev.register() { - pr_warn!("could not register: {}", e.to_kernel_errno()); - return Err(e); + let num = { + let lock = THIS_MODULE.kernel_param_lock(); + pr_info!( + "Rust Network Dummy with {} pseudo devices\n", + numdummies.read(&lock) + ); + numdummies.read(&lock).clone() + }; + + unsafe { dummy_rs_link_ops.register() }?; + + for x in 0..(num) { + let dev = NetDevice::new( + DummyRsDev, + kernel::cstr!("dummyrs%d"), + kernel::net::device::NetNameAssingType::Enum, + 1, + 1, + )?; + dev.set_rtnl_ops(unsafe { &dummy_rs_link_ops }); + + if let Err(e) = dev.register() { + pr_warn!("could not register: {}", e.to_kernel_errno()); + return Err(e); + } } - pr_info!("device registered"); Ok(RustNetDummy { - dev, + //dev, }) } } impl Drop for RustNetDummy { fn drop(&mut self) { - pr_info!("remove rust net dummy"); - - - unsafe { - //let ptr = &dummy_rs_rtnl_link_ops as *const _ as *mut kernel::bindings::rtnl_link_ops; - pr_info!("rtnl: {:#?}", &dummy_rs_rtnl_link_ops.0); - let ptr = &dummy_rs_rtnl_link_ops.get_ptr(); - pr_info!("rtnl_link_ops_ptr: {:?}", ptr); - } - // TODO rtnl_link_unregister // TODO: remove unsafe somehow - unsafe { dummy_rs_rtnl_link_ops.unregister() }; + unsafe { dummy_rs_link_ops.unregister() }; } } - struct DummyRsDev; impl NetDeviceOps for DummyRsDev { @@ -159,19 +157,15 @@ impl NetDeviceOps for DummyRsDev { fn start_xmit(skb: SkBuff, dev: &mut NetDevice) -> kernel::net::device::NetdevTX { let mut skb = skb; - // TODO: dev_lstatt_add(dev, skb->len) dev.lstats_add(skb.len()); skb.tx_timestamp(); drop(skb); - pr_info!("start_xmit called"); - kernel::net::device::NetdevTX::TX_OK } fn get_stats64(dev: &NetDevice, stats: &mut rtnl::RtnlLinkStats64) { - pr_info!("get stats64"); stats.dev_read(dev); } @@ -182,18 +176,18 @@ impl NetDeviceOps for DummyRsDev { } fn validate_addr(dev: &NetDevice) -> KernelResult<()> { - pr_info!("eth_validate_addr"); device::helpers::eth_validate_addr(dev) } - fn set_mac_addr(dev: &mut NetDevice, p: *mut kernel::c_types::c_void) -> KernelResult<()> { + fn set_mac_addr( + dev: &mut NetDevice, + p: *mut kernel::c_types::c_void, + ) -> KernelResult<()> { device::helpers::eth_mac_addr(dev, p) } - // Someting about faking multicast - fn set_rx_mode(dev: &mut NetDevice) { - pr_info!("set_rx_mode"); - } + // [Someting about faking multicast](https://elixir.bootlin.com/linux/v5.12-rc4/source/drivers/net/dummy.c#L48). + fn set_rx_mode(_dev: &mut NetDevice) {} } impl NetDeviceAdapter for DummyRsDev { @@ -204,9 +198,7 @@ impl NetDeviceAdapter for DummyRsDev { type EthOps = Self; fn setup(dev: &mut NetDevice) { - pr_info!("called netdev_setup"); setup(dev); - //dev.set_rtnl_ops( unsafe { &dummy_rs_rtnl_link_ops }); } } @@ -218,7 +210,11 @@ impl EthToolOps for DummyRsDev { // FIXME: !! let info: &kernel::bindings::ethtool_drvinfo = info.deref(); unsafe { - kernel::bindings::strlcpy(&(info.driver) as *const _ as *mut i8, b"dummy_rs\0" as *const _ as *mut i8, 32); + kernel::bindings::strlcpy( + &(info.driver) as *const _ as *mut i8, + b"dummy_rs\0" as *const _ as *mut i8, + 32, + ); } } diff --git a/rust/kernel/error.rs b/rust/kernel/error.rs index fdf1f8268794b2..408fdb93e12d0a 100644 --- a/rust/kernel/error.rs +++ b/rust/kernel/error.rs @@ -127,4 +127,4 @@ macro_rules! c_from_kernel_result { $($tt)* })()) }}; -} \ No newline at end of file +} diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 2254fe484e1cd2..f93de4947c543e 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -41,8 +41,8 @@ pub mod c_types; pub mod chrdev; mod error; pub mod file_operations; -pub mod net; pub mod miscdev; +pub mod net; pub mod pages; pub mod linked_list; @@ -65,7 +65,7 @@ pub mod iov_iter; mod types; pub mod user_ptr; -pub use crate::error::{Error, KernelResult, c_from_kernel_result}; +pub use crate::error::{c_from_kernel_result, Error, KernelResult}; pub use crate::types::{CStr, Mode}; /// Page size defined in terms of the `PAGE_SHIFT` macro from C. diff --git a/rust/kernel/net/device.rs b/rust/kernel/net/device.rs index e06007d833bb29..d920fdbc9aec0a 100644 --- a/rust/kernel/net/device.rs +++ b/rust/kernel/net/device.rs @@ -7,29 +7,14 @@ use core::{marker, mem, ops::Deref, ops::DerefMut, ptr}; use crate::bindings; -use crate::{c_types, CStr}; -use crate::error::{Error, KernelResult}; use crate::c_from_kernel_result; -use crate::sync::{CondVar, Ref, RefCounted}; -use crate::user_ptr::{UserSlicePtr, UserSlicePtrReader, UserSlicePtrWriter}; +use crate::error::{Error, KernelResult}; +use crate::{c_types, CStr}; use super::ethtool::EthToolOps; -use super::rtnl::{RtnlLinkOps, RtnlLock, RtnlLinkStats64}; +use super::rtnl::{RtnlLinkStats64, RtnlLock}; use super::skbuff::SkBuff; -/*pub(crate) fn from_kernel_result(r: KernelResult) -> T -where - T: TryFrom, - T::Error: core::fmt::Debug, -{ - match r { - Ok(v) => v, - Err(e) => T::try_from(e.to_kernel_errno()).unwrap(), - } -} -*/ - - extern "C" { #[allow(improper_ctypes)] fn rust_helper_netdev_priv(dev: *const bindings::net_device) -> *mut c_types::c_void; @@ -44,7 +29,7 @@ extern "C" { fn rust_helper_dev_lstats_add(dev: *mut bindings::net_device, len: u32); } -/// interface name assignment types (sysfs name_assign_type attribute) +/// interface name assignment types (sysfs name_assign_type attribute). #[repr(u8)] pub enum NetNameAssingType { Unknown = bindings::NET_NAME_UNKNOWN as u8, @@ -52,11 +37,7 @@ pub enum NetNameAssingType { } unsafe extern "C" fn setup_netdev_callback(dev: *mut bindings::net_device) { - // TODO: pass on dev let mut dev = NetDevice::::from_ptr(dev); - dev.needs_free_netdev = true; // TODO: is this reasonable? - dev.netdev_ops = NetDeviceOperationsVtable::::build(); - dev.ethtool_ops = super::ethtool::EthToolOperationsVtable::::build(); T::setup(&mut dev); } @@ -66,34 +47,61 @@ unsafe extern "C" fn setup_netdev_callback(dev: *mut bindin /// # Invariants /// /// The pointer [`NetDevice::ptr`] is non-null and valid. +#[repr(transparent)] pub struct NetDevice { ptr: *const bindings::net_device, priv_data: marker::PhantomData, } unsafe impl Sync for NetDevice {} -//unsafe impl Send for NetDevice {} impl NetDevice { - pub fn new(priv_data: T, format_name: CStr<'static>, name_assign_type: NetNameAssingType, txqs: u32, rxqs: u32) -> KernelResult { + /// Allocate and create a new NetDevice with private data T. + /// This function locks [`RtnlLock`]. + pub fn new( + priv_data: T, + format_name: CStr<'static>, + name_assign_type: NetNameAssingType, + txqs: u32, + rxqs: u32, + ) -> KernelResult { let _lock = RtnlLock::lock(); - // Lock is hold + // Lock is hold. let dev = unsafe { Self::new_locked(priv_data, format_name, name_assign_type, txqs, rxqs) }; dev } - pub unsafe fn new_locked(priv_data: T, format_name: CStr<'static>, name_assign_type: NetNameAssingType, txqs: u32, rxqs: u32) -> KernelResult { - // TODO: check for {t,r}xqs bigger 0 + /// Allocate and create a new NetDevice with private data T. + /// No lock is accuired by this function, therefor this function is unsafe. + /// + /// # Safety + /// + /// The caller has to hold the [`RtnlLock`]. + pub unsafe fn new_locked( + priv_data: T, + format_name: CStr<'static>, + name_assign_type: NetNameAssingType, + txqs: u32, + rxqs: u32, + ) -> KernelResult { + if txqs < 1 || rxqs < 1 { + return Err(Error::EINVAL); + } let size = mem::size_of::() as i32; - // Safety: TODO - let ptr = bindings::alloc_netdev_mqs(size, format_name.as_ptr() as _, name_assign_type as u8, Some(setup_netdev_callback::), txqs, rxqs); + let ptr = bindings::alloc_netdev_mqs( + size, + format_name.as_ptr() as _, + name_assign_type as u8, + Some(setup_netdev_callback::), + txqs, + rxqs, + ); if ptr.is_null() { return Err(Error::ENOMEM); } if size != 0 { - // Safety: T is valid and dest is created by alloc_netdev_mqs let dest = rust_helper_netdev_priv(ptr) as *mut T; ptr::write(dest, priv_data); } @@ -104,22 +112,22 @@ impl NetDevice { }) } - // TODO: pin? + /// Return a refference to the private data of the [`NetDevice`]. pub fn get_priv_data(&self) -> &T { - // SAFETY: + // SAFETY: self.ptr is valid if self is valid let priv_ptr = unsafe { rust_helper_netdev_priv(self.ptr) } as *mut T; // SAFETY: ptr is valid and of type T unsafe { priv_ptr.as_ref() }.unwrap() } - // TODO: pin? - pub unsafe fn get_priv_data_mut(&mut self) -> &mut T { - // SAFETY: - let priv_ptr = rust_helper_netdev_priv(self.ptr) as *mut T; + /// Return a mutable refference of the private data of the [`NetDevice`] + pub fn get_priv_data_mut(&mut self) -> &mut T { + // SAFETY: self.ptr is valid if self is valid + let priv_ptr = unsafe { rust_helper_netdev_priv(self.ptr) as *mut T }; // SAFETY: ptr is valid and of type T - priv_ptr.as_mut().unwrap() + unsafe { priv_ptr.as_mut().unwrap() } } /// ether_setup - setup Ethernet network device @@ -189,7 +197,7 @@ impl NetDevice { } /// set_rtnl_ops - set the rtnl_link_ops to a network interface - /// + /// /// Takes a static mut created with [`kernel::net::rtnl_link_ops!`] and assing it to self pub fn set_rtnl_ops(&self, ops: &'static super::rtnl::RtnlLinkOps) { // get rtnl_lock @@ -200,16 +208,20 @@ impl NetDevice { } /// set_rtnl_ops_locked - set the rtnl_link_ops to a network interface, while the caller holds the rtnl_lock - /// - /// Takes a static mut created with [`kernel::net::rtnl_link_ops!`] and assing it to self + /// + /// Takes a static mut created with [`kernel::net::rtnl_link_ops!`] and assing it to self. + /// + /// # Safety + /// + /// The caller has to hold the [`RtnlLock`]. pub unsafe fn set_rtnl_ops_locked(&self, ops: &'static super::rtnl::RtnlLinkOps) { // SAFETY: prt is valid if self is valid - let mut dev = (self.ptr as *mut bindings::net_device ).as_mut().unwrap(); + let mut dev = (self.ptr as *mut bindings::net_device).as_mut().unwrap(); - //dev.rtnl_link_ops = (&ops.0) as *const _ as *mut _; dev.rtnl_link_ops = ops.get_ptr() as *mut bindings::rtnl_link_ops; } + /// Add a [`Iff`] flag to the [`NetDevice`]. pub fn add_flag(&mut self, flag: Iff) { // SAFETY: prt is valid if self is valid let mut dev = unsafe { (self.ptr as *mut bindings::net_device).as_mut().unwrap() }; @@ -217,6 +229,7 @@ impl NetDevice { dev.flags |= flag as u32; } + /// Remove a [`Iff`] flag from the [`NetDevice`]. pub fn remove_flag(&mut self, flag: Iff) { // SAFETY: prt is valid if self is valid let mut dev = unsafe { (self.ptr as *mut bindings::net_device).as_mut().unwrap() }; @@ -224,6 +237,7 @@ impl NetDevice { dev.flags &= !(flag as u32); } + /// Add a [`IffPriv`] private_flag to the [`NetDevice`]. pub fn add_private_flag(&mut self, flag: IffPriv) { // SAFETY: prt is valid if self is valid let mut dev = unsafe { (self.ptr as *mut bindings::net_device).as_mut().unwrap() }; @@ -231,6 +245,7 @@ impl NetDevice { dev.priv_flags |= flag as u32; } + /// Remove a [`IffPriv`] private_flag from the [`NetDevice`]. pub fn remove_private_flag(&mut self, flag: IffPriv) { // SAFETY: prt is valid if self is valid let mut dev = unsafe { (self.ptr as *mut bindings::net_device).as_mut().unwrap() }; @@ -238,6 +253,7 @@ impl NetDevice { dev.priv_flags &= !(flag as u32); } + /// Set a [`feature::NetIF`] `feature` set to the [`NetDevice`]. pub fn set_features(&mut self, features: feature::NetIF) { // SAFETY: ptr is valid if self is valid let mut dev = unsafe { (self.ptr as *mut bindings::net_device).as_mut() }.unwrap(); @@ -245,7 +261,7 @@ impl NetDevice { dev.features = features.into(); } - + /// Get the [`feature::NetIF`] `feature` set from the [`NetDevice`]. pub fn get_features(&self) -> feature::NetIF { // SAFETY: ptr is valid if self is valid let dev = unsafe { self.ptr.as_ref() }.unwrap(); @@ -253,6 +269,7 @@ impl NetDevice { feature::NetIF::from(dev.features) } + /// Set a [`feature::NetIF`] `hw_feature` set to the [`NetDevice`]. pub fn set_hw_features(&mut self, features: feature::NetIF) { // SAFETY: ptr is valid if self is valid let mut dev = unsafe { (self.ptr as *mut bindings::net_device).as_mut() }.unwrap(); @@ -260,13 +277,15 @@ impl NetDevice { dev.hw_features = features.into(); } + /// Get the [`feature::NetIF`] `hw_feature` set from the [`NetDevice`]. pub fn get_hw_features(&self) -> feature::NetIF { // SAFETY: ptr is valid if self is valid let dev = unsafe { self.ptr.as_ref() }.unwrap(); feature::NetIF::from(dev.hw_features) } - + + /// Set a [`feature::NetIF`] `hw_enc_feature` set to the [`NetDevice`]. pub fn set_hw_enc_features(&mut self, features: feature::NetIF) { // SAFETY: ptr is valid if self is valid let mut dev = unsafe { (self.ptr as *mut bindings::net_device).as_mut() }.unwrap(); @@ -274,6 +293,7 @@ impl NetDevice { dev.hw_enc_features = features.into(); } + /// Get the [`feature::NetIF`] `hw_enc_feature` set from the [`NetDevice`]. pub fn get_hw_enc_features(&self) -> feature::NetIF { // SAFETY: ptr is valid if self is valid let dev = unsafe { self.ptr.as_ref() }.unwrap(); @@ -281,6 +301,7 @@ impl NetDevice { feature::NetIF::from(dev.hw_enc_features) } + /// Set mut for the [`NetDevice`]. pub fn set_mtu(&mut self, min: u32, max: u32) { // SAFETY: prt is valid if self is valid let mut dev = unsafe { (self.ptr as *mut bindings::net_device).as_mut().unwrap() }; @@ -289,11 +310,11 @@ impl NetDevice { dev.max_mtu = max; } + /// Create a new `pcpu_lstats` struct and assing it to the [`NetDevice`]. pub fn set_new_pcpu_lstats(&mut self) -> KernelResult<()> { // SAFETY: calling c function - let ret = unsafe { - rust_helper_net_device_set_new_lstats(self.ptr as *mut bindings::net_device) - }; + let ret = + unsafe { rust_helper_net_device_set_new_lstats(self.ptr as *mut bindings::net_device) }; if ret != 0 { Err(Error::from_kernel_errno(ret)) @@ -302,24 +323,21 @@ impl NetDevice { } } + /// Free the lstats field /// # Safety /// /// Only call when the same device had set_new_pcpu_lstats called pub unsafe fn free_lstats(&mut self) { // SAFETY: self.ptr->lstats is valid if self is valid - let net_device: &bindings::net_device = self.deref(); - // __bindgen_anon_1: net_device__bindgen_ty_4 - let lstats = net_device.__bindgen_anon_1.lstats; if !lstats.is_null() { - unsafe { - bindings::free_percpu(lstats as *mut _) - } + unsafe { bindings::free_percpu(lstats as *mut _) } } } + /// Add a value the the internal lstats. pub fn lstats_add(&mut self, len: u32) { // SAFETD: calling c function unsafe { @@ -327,6 +345,7 @@ impl NetDevice { } } + /// Set carrier. pub fn carrier_set(&mut self, status: bool) { // SAFETY: self.ptr is valid if self is valid if status { @@ -336,6 +355,16 @@ impl NetDevice { } } + /// Set `netdev_ops` and `ethtool_ops` from the [`NetDeviceAdapter`] T to the [`NetDevice`]. + /// This also sets `needs_free_netdev` to true. + pub fn set_ops(&mut self) { + self.needs_free_netdev = true; + unsafe { + self.netdev_ops = NetDeviceOperationsVtable::::build(); + self.ethtool_ops = super::ethtool::EthToolOperationsVtable::::build(); + } + } + /// Constructs a new [`struct net_device`] wrapper. /// /// # Safety @@ -352,6 +381,7 @@ impl NetDevice { } } + /// Return const pointer to the wrapped type. pub unsafe fn get_ptr(&self) -> *const bindings::net_device { self.ptr } @@ -392,9 +422,8 @@ pub enum NetdevTX { TX_BUSY = bindings::netdev_tx_NETDEV_TX_BUSY, } - unsafe extern "C" fn ndo_init_callback( - dev: *mut bindings::net_device + dev: *mut bindings::net_device, ) -> c_types::c_int { c_from_kernel_result! { T::Ops::init(&mut NetDevice::::from_ptr(dev))?; @@ -402,9 +431,7 @@ unsafe extern "C" fn ndo_init_callback( } } -unsafe extern "C" fn ndo_uninit_callback( - dev: *mut bindings::net_device -) { +unsafe extern "C" fn ndo_uninit_callback(dev: *mut bindings::net_device) { // SAFETY: pointer is valid as it comes form C //let mut device = dev.as_mut().unwrap(); T::Ops::uninit(&mut NetDevice::::from_ptr(dev)); @@ -416,28 +443,43 @@ unsafe extern "C" fn ndo_start_xmit_callback( ) -> bindings::netdev_tx_t { //let device = NetDevice::::from_ptr(dev); - T::Ops::start_xmit(SkBuff::from_ptr(skb), &mut NetDevice::from_ptr(dev)) as bindings::netdev_tx_t + T::Ops::start_xmit(SkBuff::from_ptr(skb), &mut NetDevice::from_ptr(dev)) + as bindings::netdev_tx_t } -unsafe extern "C" fn ndo_get_stats64_callback(dev: *mut bindings::net_device, stats: *mut bindings::rtnl_link_stats64) { - T::Ops::get_stats64(&NetDevice::::from_ptr(dev), &mut RtnlLinkStats64::from_ptr(stats)); +unsafe extern "C" fn ndo_get_stats64_callback( + dev: *mut bindings::net_device, + stats: *mut bindings::rtnl_link_stats64, +) { + T::Ops::get_stats64( + &NetDevice::::from_ptr(dev), + &mut RtnlLinkStats64::from_ptr(stats), + ); } -unsafe extern "C" fn ndo_change_carrier_callback(dev: *mut bindings::net_device, change_carrier: bool) -> c_types::c_int { +unsafe extern "C" fn ndo_change_carrier_callback( + dev: *mut bindings::net_device, + change_carrier: bool, +) -> c_types::c_int { c_from_kernel_result! { T::Ops::change_carrier(&mut NetDevice::::from_ptr(dev), change_carrier)?; Ok(0) } } -unsafe extern "C" fn ndo_validate_addr_callback(dev: *mut bindings::net_device) -> c_types::c_int { +unsafe extern "C" fn ndo_validate_addr_callback( + dev: *mut bindings::net_device, +) -> c_types::c_int { c_from_kernel_result! { T::Ops::validate_addr(&NetDevice::::from_ptr(dev))?; Ok(0) } } -unsafe extern "C" fn ndo_set_mac_address_callback(dev: *mut bindings::net_device, p: *mut c_types::c_void) -> c_types::c_int { +unsafe extern "C" fn ndo_set_mac_address_callback( + dev: *mut bindings::net_device, + p: *mut c_types::c_void, +) -> c_types::c_int { c_from_kernel_result! { T::Ops::set_mac_addr(&mut NetDevice::::from_ptr(dev), p)?; Ok(0) @@ -462,13 +504,19 @@ impl NetDeviceOperationsVtable { ndo_change_rx_flags: None, ndo_set_rx_mode: if T::Ops::TO_USE.set_rx_mode { Some(ndo_set_rx_mode_callback::) - } else { None }, + } else { + None + }, ndo_set_mac_address: if T::Ops::TO_USE.set_mac_addr { Some(ndo_set_mac_address_callback::) - } else { None }, + } else { + None + }, ndo_validate_addr: if T::Ops::TO_USE.validate_addr { Some(ndo_validate_addr_callback::) - } else { None }, + } else { + None + }, ndo_do_ioctl: None, ndo_set_config: None, ndo_change_mtu: None, @@ -476,7 +524,9 @@ impl NetDeviceOperationsVtable { ndo_tx_timeout: None, ndo_get_stats64: if T::Ops::TO_USE.get_stats64 { Some(ndo_get_stats64_callback::) - } else { None }, + } else { + None + }, ndo_has_offload_stats: None, ndo_get_offload_stats: None, ndo_get_stats: None, @@ -541,7 +591,9 @@ impl NetDeviceOperationsVtable { ndo_bridge_dellink: None, ndo_change_carrier: if T::Ops::TO_USE.change_carrier { Some(ndo_change_carrier_callback::) - } else { None }, + } else { + None + }, ndo_get_phys_port_id: None, ndo_get_port_parent_id: None, ndo_get_phys_port_name: None, @@ -560,7 +612,6 @@ impl NetDeviceOperationsVtable { ndo_get_peer_dev: None, }; - /// Builds an instance of [`struct net_device_ops`]. /// /// # Safety @@ -575,7 +626,7 @@ impl NetDeviceOperationsVtable { pub struct ToUse { /// The `ndo_change_carrier` field of [`struct net_device_ops`]. pub change_carrier: bool, - + pub get_stats64: bool, pub validate_addr: bool, @@ -608,7 +659,6 @@ macro_rules! declare_net_device_ops { }; } - /// Corresponds to the kernel's `struct net_device_ops`. /// /// You Implement this trait whenever you would create a `struct net_device_ops`.. @@ -626,7 +676,6 @@ pub trait NetDeviceOps: Send + Sync + Sized { /// fails. It is not called if init fails. fn uninit(dev: &mut NetDevice); - /// Called when a packet needs to be transmitted. /// `Ok(())` returns NETDEV_TX_OK, Error maps to `NETDEV_TX_BUSY` /// Returns NETDEV_TX_OK. Can return NETDEV_TX_BUSY, but you should stop @@ -637,7 +686,7 @@ pub trait NetDeviceOps: Send + Sync + Sized { NetdevTX::TX_OK } - fn get_stats64(dev: &NetDevice, stats: &mut RtnlLinkStats64) { } + fn get_stats64(dev: &NetDevice, stats: &mut RtnlLinkStats64) {} fn change_carrier(dev: &mut NetDevice, new_carrier: bool) -> KernelResult<()> { Err(Error::EINVAL) @@ -651,8 +700,7 @@ pub trait NetDeviceOps: Send + Sync + Sized { Err(Error::EINVAL) } - fn set_rx_mode(dev: &mut NetDevice) { - } + fn set_rx_mode(dev: &mut NetDevice) {} } /// Iff flags @@ -663,68 +711,67 @@ pub enum Iff { BROADCAST = bindings::net_device_flags_IFF_BROADCAST, DEBUG = bindings::net_device_flags_IFF_DEBUG, LOOPBACK = bindings::net_device_flags_IFF_LOOPBACK, - POINTOPOINT = bindings::net_device_flags_IFF_POINTOPOINT, - NOTRAILERS = bindings::net_device_flags_IFF_NOTRAILERS, - RUNNING = bindings::net_device_flags_IFF_RUNNING, - NOARP = bindings::net_device_flags_IFF_NOARP, - PROMISC = bindings::net_device_flags_IFF_PROMISC, - ALLMULTI = bindings::net_device_flags_IFF_ALLMULTI, - MASTER = bindings::net_device_flags_IFF_MASTER, - SLAVE = bindings::net_device_flags_IFF_SLAVE, - MULTICAST = bindings::net_device_flags_IFF_MULTICAST, - PORTSEL = bindings::net_device_flags_IFF_PORTSEL, - AUTOMEDIA = bindings::net_device_flags_IFF_AUTOMEDIA, - DYNAMIC = bindings::net_device_flags_IFF_DYNAMIC, - + POINTOPOINT = bindings::net_device_flags_IFF_POINTOPOINT, + NOTRAILERS = bindings::net_device_flags_IFF_NOTRAILERS, + RUNNING = bindings::net_device_flags_IFF_RUNNING, + NOARP = bindings::net_device_flags_IFF_NOARP, + PROMISC = bindings::net_device_flags_IFF_PROMISC, + ALLMULTI = bindings::net_device_flags_IFF_ALLMULTI, + MASTER = bindings::net_device_flags_IFF_MASTER, + SLAVE = bindings::net_device_flags_IFF_SLAVE, + MULTICAST = bindings::net_device_flags_IFF_MULTICAST, + PORTSEL = bindings::net_device_flags_IFF_PORTSEL, + AUTOMEDIA = bindings::net_device_flags_IFF_AUTOMEDIA, + DYNAMIC = bindings::net_device_flags_IFF_DYNAMIC, + // #if __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO // TODO: is this needed? - LOWER = bindings::net_device_flags_IFF_LOWER_UP, - DORMANT = bindings::net_device_flags_IFF_DORMANT, - ECHO = bindings::net_device_flags_IFF_ECHO, + LOWER = bindings::net_device_flags_IFF_LOWER_UP, + DORMANT = bindings::net_device_flags_IFF_DORMANT, + ECHO = bindings::net_device_flags_IFF_ECHO, } /// Iff private flags #[repr(u32)] #[allow(non_camel_case_types)] pub enum IffPriv { - IFF_802_1Q_VLAN = bindings::netdev_priv_flags_IFF_802_1Q_VLAN, // TODO: find a good name without leading 8 - EBRIDGE = bindings::netdev_priv_flags_IFF_EBRIDGE, - BONDING = bindings::netdev_priv_flags_IFF_BONDING, - ISATAP = bindings::netdev_priv_flags_IFF_ISATAP, - WAN_HDLC = bindings::netdev_priv_flags_IFF_WAN_HDLC, - XMIT_DST_RELEASE = bindings::netdev_priv_flags_IFF_XMIT_DST_RELEASE, - DONT_BRIDGE = bindings::netdev_priv_flags_IFF_DONT_BRIDGE, - DISABLE_NETPOLL = bindings::netdev_priv_flags_IFF_DISABLE_NETPOLL, - MACVLAN_PORT = bindings::netdev_priv_flags_IFF_MACVLAN_PORT, - BRIDGE_PORT = bindings::netdev_priv_flags_IFF_BRIDGE_PORT, - OVS_DATAPATH = bindings::netdev_priv_flags_IFF_OVS_DATAPATH, - TX_SKB_SHARING = bindings::netdev_priv_flags_IFF_TX_SKB_SHARING, - UNICAST_FLT = bindings::netdev_priv_flags_IFF_UNICAST_FLT, - TEAM_PORT = bindings::netdev_priv_flags_IFF_TEAM_PORT, - SUPP_NOFCS = bindings::netdev_priv_flags_IFF_SUPP_NOFCS, - LIVE_ADDR_CHANGE = bindings::netdev_priv_flags_IFF_LIVE_ADDR_CHANGE, - MACVLAN = bindings::netdev_priv_flags_IFF_MACVLAN, - XMIT_DST_RELEASE_PERM = bindings::netdev_priv_flags_IFF_XMIT_DST_RELEASE_PERM, - L3MDEV_MASTER = bindings::netdev_priv_flags_IFF_L3MDEV_MASTER, - NO_QUEUE = bindings::netdev_priv_flags_IFF_NO_QUEUE, - OPENVSWITCH = bindings::netdev_priv_flags_IFF_OPENVSWITCH, - L3MDEV_SLAVE = bindings::netdev_priv_flags_IFF_L3MDEV_SLAVE, - TEAM = bindings::netdev_priv_flags_IFF_TEAM, - RXFH_CONFIGURED = bindings::netdev_priv_flags_IFF_RXFH_CONFIGURED, - PHONY_HEADROOM = bindings::netdev_priv_flags_IFF_PHONY_HEADROOM, - MACSEC = bindings::netdev_priv_flags_IFF_MACSEC, - NO_RX_HANDLER = bindings::netdev_priv_flags_IFF_NO_RX_HANDLER, - FAILOVER = bindings::netdev_priv_flags_IFF_FAILOVER, - FAILOVER_SLAVE = bindings::netdev_priv_flags_IFF_FAILOVER_SLAVE, - L3MDEV_RX_HANDLER = bindings::netdev_priv_flags_IFF_L3MDEV_RX_HANDLER, - LIVE_RENAME_OK = bindings::netdev_priv_flags_IFF_LIVE_RENAME_OK, + IFF_802_1Q_VLAN = bindings::netdev_priv_flags_IFF_802_1Q_VLAN, /* TODO: find a good name without leading 8 */ + EBRIDGE = bindings::netdev_priv_flags_IFF_EBRIDGE, + BONDING = bindings::netdev_priv_flags_IFF_BONDING, + ISATAP = bindings::netdev_priv_flags_IFF_ISATAP, + WAN_HDLC = bindings::netdev_priv_flags_IFF_WAN_HDLC, + XMIT_DST_RELEASE = bindings::netdev_priv_flags_IFF_XMIT_DST_RELEASE, + DONT_BRIDGE = bindings::netdev_priv_flags_IFF_DONT_BRIDGE, + DISABLE_NETPOLL = bindings::netdev_priv_flags_IFF_DISABLE_NETPOLL, + MACVLAN_PORT = bindings::netdev_priv_flags_IFF_MACVLAN_PORT, + BRIDGE_PORT = bindings::netdev_priv_flags_IFF_BRIDGE_PORT, + OVS_DATAPATH = bindings::netdev_priv_flags_IFF_OVS_DATAPATH, + TX_SKB_SHARING = bindings::netdev_priv_flags_IFF_TX_SKB_SHARING, + UNICAST_FLT = bindings::netdev_priv_flags_IFF_UNICAST_FLT, + TEAM_PORT = bindings::netdev_priv_flags_IFF_TEAM_PORT, + SUPP_NOFCS = bindings::netdev_priv_flags_IFF_SUPP_NOFCS, + LIVE_ADDR_CHANGE = bindings::netdev_priv_flags_IFF_LIVE_ADDR_CHANGE, + MACVLAN = bindings::netdev_priv_flags_IFF_MACVLAN, + XMIT_DST_RELEASE_PERM = bindings::netdev_priv_flags_IFF_XMIT_DST_RELEASE_PERM, + L3MDEV_MASTER = bindings::netdev_priv_flags_IFF_L3MDEV_MASTER, + NO_QUEUE = bindings::netdev_priv_flags_IFF_NO_QUEUE, + OPENVSWITCH = bindings::netdev_priv_flags_IFF_OPENVSWITCH, + L3MDEV_SLAVE = bindings::netdev_priv_flags_IFF_L3MDEV_SLAVE, + TEAM = bindings::netdev_priv_flags_IFF_TEAM, + RXFH_CONFIGURED = bindings::netdev_priv_flags_IFF_RXFH_CONFIGURED, + PHONY_HEADROOM = bindings::netdev_priv_flags_IFF_PHONY_HEADROOM, + MACSEC = bindings::netdev_priv_flags_IFF_MACSEC, + NO_RX_HANDLER = bindings::netdev_priv_flags_IFF_NO_RX_HANDLER, + FAILOVER = bindings::netdev_priv_flags_IFF_FAILOVER, + FAILOVER_SLAVE = bindings::netdev_priv_flags_IFF_FAILOVER_SLAVE, + L3MDEV_RX_HANDLER = bindings::netdev_priv_flags_IFF_L3MDEV_RX_HANDLER, + LIVE_RENAME_OK = bindings::netdev_priv_flags_IFF_LIVE_RENAME_OK, } - pub mod feature { use crate::bindings; - use core::ops::{Deref, DerefMut, Add, Sub, AddAssign, SubAssign}; use core::convert::{From, Into}; + use core::ops::{Add, AddAssign, Deref, DerefMut, Sub, SubAssign}; #[derive(Debug, Clone, Copy)] pub struct NetIF(u64); @@ -821,7 +868,7 @@ pub mod feature { impl Into for NetIF { fn into(self) -> u64 { - self.0 + self.0 } } @@ -856,9 +903,29 @@ pub mod feature { _netif_f!(NETIF_F_GSO_UDP_TUNNEL, NETIF_F_GSO_UDP_TUNNEL_BIT); _netif_f!(NETIF_F_GSO_UDP_TUNNEL_CSUM, NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT); - _netif_f_sum!(NETIF_F_ALL_TSO, NETIF_F_TSO, NETIF_F_TSO6, NETIF_F_TSO_ECN, NETIF_F_TSO_MANGLEID); - _netif_f_sum!(NETIF_F_GSO_SOFTWARE, NETIF_F_ALL_TSO, NETIF_F_GSO_SCTP, NETIF_F_GSO_UDP_L4, NETIF_F_GSO_FRAGLIST); - _netif_f_sum!(NETIF_F_GSO_ENCAP_ALL, NETIF_F_GSO_GRE, NETIF_F_GSO_GRE_CSUM, NETIF_F_GSO_IPXIP4, NETIF_F_GSO_IPXIP6, NETIF_F_GSO_UDP_TUNNEL, NETIF_F_GSO_UDP_TUNNEL_CSUM); + _netif_f_sum!( + NETIF_F_ALL_TSO, + NETIF_F_TSO, + NETIF_F_TSO6, + NETIF_F_TSO_ECN, + NETIF_F_TSO_MANGLEID + ); + _netif_f_sum!( + NETIF_F_GSO_SOFTWARE, + NETIF_F_ALL_TSO, + NETIF_F_GSO_SCTP, + NETIF_F_GSO_UDP_L4, + NETIF_F_GSO_FRAGLIST + ); + _netif_f_sum!( + NETIF_F_GSO_ENCAP_ALL, + NETIF_F_GSO_GRE, + NETIF_F_GSO_GRE_CSUM, + NETIF_F_GSO_IPXIP4, + NETIF_F_GSO_IPXIP6, + NETIF_F_GSO_UDP_TUNNEL, + NETIF_F_GSO_UDP_TUNNEL_CSUM + ); } pub mod helpers { @@ -866,7 +933,8 @@ pub mod helpers { pub fn eth_validate_addr(dev: &NetDevice) -> KernelResult<()> { // SAFETY: dev.ptr is valid if dev is valid - let ret = unsafe { bindings::eth_validate_addr(dev.get_ptr() as *mut bindings::net_device) }; + let ret = + unsafe { bindings::eth_validate_addr(dev.get_ptr() as *mut bindings::net_device) }; if ret != 0 { Err(Error::from_kernel_errno(ret)) } else { @@ -874,12 +942,12 @@ pub mod helpers { } } - pub fn eth_mac_addr(dev: &mut NetDevice, p: *mut c_types::c_void) -> KernelResult<()> { + pub fn eth_mac_addr( + dev: &mut NetDevice, + p: *mut c_types::c_void, + ) -> KernelResult<()> { // SAFETY: dev.ptr is valid if dev is valid - let ret = unsafe { bindings::eth_mac_addr( - dev.get_ptr() as *mut bindings::net_device, - p - ) }; + let ret = unsafe { bindings::eth_mac_addr(dev.get_ptr() as *mut bindings::net_device, p) }; if ret != 0 { Err(Error::from_kernel_errno(ret)) @@ -887,4 +955,4 @@ pub mod helpers { Ok(()) } } -} \ No newline at end of file +} diff --git a/rust/kernel/net/ethtool.rs b/rust/kernel/net/ethtool.rs index 65d8bef867501f..1e59283cd4fd30 100644 --- a/rust/kernel/net/ethtool.rs +++ b/rust/kernel/net/ethtool.rs @@ -8,10 +8,10 @@ use core::convert::{TryFrom, TryInto}; use core::{marker, mem, ops::Deref, ops::DerefMut, pin::Pin, ptr}; use crate::bindings; -use crate::{c_types, CStr}; use crate::error::{Error, KernelResult}; +use crate::{c_types, CStr}; -use super::device::{NetDeviceAdapter, NetDevice}; +use super::device::{NetDevice, NetDeviceAdapter}; pub(crate) fn from_kernel_result(r: KernelResult) -> T where @@ -32,14 +32,20 @@ macro_rules! from_kernel_result { }}; } -unsafe extern "C" fn get_drvinfo_callback(dev: *mut bindings::net_device, info: *mut bindings::ethtool_drvinfo) { +unsafe extern "C" fn get_drvinfo_callback( + dev: *mut bindings::net_device, + info: *mut bindings::ethtool_drvinfo, +) { T::EthOps::get_drvinfo( &NetDevice::::from_ptr(dev), - &mut EthtoolDrvinfo::from_ptr(info) + &mut EthtoolDrvinfo::from_ptr(info), ); } -unsafe extern "C" fn get_ts_info_callback(dev: *mut bindings::net_device, info: *mut bindings::ethtool_ts_info) -> c_types::c_int { +unsafe extern "C" fn get_ts_info_callback( + dev: *mut bindings::net_device, + info: *mut bindings::ethtool_ts_info, +) -> c_types::c_int { from_kernel_result! { T::EthOps::get_ts_info( &NetDevice::::from_ptr(dev), @@ -176,7 +182,7 @@ pub trait EthToolOps: Send + Sync + Sized { #[repr(transparent)] pub struct EthToolTsInfo { - ptr: *const bindings::ethtool_ts_info + ptr: *const bindings::ethtool_ts_info, } impl EthToolTsInfo { @@ -187,9 +193,7 @@ impl EthToolTsInfo { /// The pointer `ptr` must be non-null and valid for the lifetime of the object. pub unsafe fn from_ptr(ptr: *const bindings::ethtool_ts_info) -> Self { // INVARIANTS: the safety contract ensures the type invariant will hold. - Self { - ptr, - } + Self { ptr } } pub unsafe fn get_ptr(&self) -> *const bindings::ethtool_ts_info { @@ -214,7 +218,7 @@ impl DerefMut for EthToolTsInfo { } pub struct EthtoolDrvinfo { - ptr: *const bindings::ethtool_drvinfo + ptr: *const bindings::ethtool_drvinfo, } impl EthtoolDrvinfo { @@ -225,9 +229,7 @@ impl EthtoolDrvinfo { /// The pointer `ptr` must be non-null and valid for the lifetime of the object. pub unsafe fn from_ptr(ptr: *const bindings::ethtool_drvinfo) -> Self { // INVARIANTS: the safety contract ensures the type invariant will hold. - Self { - ptr, - } + Self { ptr } } pub unsafe fn get_ptr(&self) -> *const bindings::ethtool_drvinfo { @@ -254,9 +256,17 @@ impl DerefMut for EthtoolDrvinfo { pub mod helpers { use super::*; - pub fn ethtool_op_get_ts_info(dev: &NetDevice, info: &mut EthToolTsInfo) -> KernelResult<()> { + pub fn ethtool_op_get_ts_info( + dev: &NetDevice, + info: &mut EthToolTsInfo, + ) -> KernelResult<()> { // SAFETY: dev.ptr is valid if dev is valid - unsafe { bindings::ethtool_op_get_ts_info(dev.get_ptr() as *mut bindings::net_device, info.get_ptr() as *mut bindings::ethtool_ts_info) }; + unsafe { + bindings::ethtool_op_get_ts_info( + dev.get_ptr() as *mut bindings::net_device, + info.get_ptr() as *mut bindings::ethtool_ts_info, + ) + }; Ok(()) } -} \ No newline at end of file +} diff --git a/rust/kernel/net/mod.rs b/rust/kernel/net/mod.rs index 8d039c15ebb8a8..ddddad1054b7c9 100644 --- a/rust/kernel/net/mod.rs +++ b/rust/kernel/net/mod.rs @@ -2,8 +2,8 @@ use core::mem; pub mod device; pub mod ethtool; -pub mod rtnl; pub mod netlink; +pub mod rtnl; pub mod skbuff; #[doc(inline)] @@ -14,7 +14,7 @@ pub unsafe fn is_multicast_ether_addr(addr: *const u8) -> bool { let a: u32 = *(addr as *const u32); if cfg!(target_endian = "big") { - (0x01 & (a >> (((mem::size_of::() as u32) * 8) -8 ))) != 0 + (0x01 & (a >> (((mem::size_of::() as u32) * 8) - 8))) != 0 } else { (0x01 & a) != 0 } @@ -25,7 +25,7 @@ pub unsafe fn is_multicast_ether_addr(addr: *const u8) -> bool { let a: u16 = *(addr as *const u16); if cfg!(target_endian = "big") { - (0x01 & (a >> (((mem::size_of::() as u16) * 8) -8 ))) != 0 + (0x01 & (a >> (((mem::size_of::() as u16) * 8) - 8))) != 0 } else { (0x01 & a) != 0 } @@ -38,9 +38,10 @@ pub unsafe fn is_zero_ether_addr(addr: *const u8) -> bool { #[cfg(not(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS))] pub unsafe fn is_zero_ether_addr(addr: *const u8) -> bool { - *(addr as *const u16) | - *((addr as usize + 2) as *const u16) | - *((addr as usize + 4) as *const u16) == 0 + *(addr as *const u16) + | *((addr as usize + 2) as *const u16) + | *((addr as usize + 4) as *const u16) + == 0 } pub unsafe fn is_valid_ether_addr(addr: *const u8) -> bool { @@ -48,23 +49,11 @@ pub unsafe fn is_valid_ether_addr(addr: *const u8) -> bool { } pub mod prelude { + pub use super::rtnl_link_ops; pub use super::{ - device::{ - NetDeviceOps, - NetDevice, - NetDeviceAdapter, - }, - ethtool::{ - self, - EthToolOps, - }, - rtnl::{ - RtnlLock, - RtnlLinkOps, - }, - skbuff::{ - SkBuff - }, + device::{NetDevice, NetDeviceAdapter, NetDeviceOps}, + ethtool::{self, EthToolOps}, + rtnl::{RtnlLinkOps, RtnlLock}, + skbuff::SkBuff, }; - pub use super::rtnl_link_ops; } diff --git a/rust/kernel/net/netlink.rs b/rust/kernel/net/netlink.rs index b0f50a98af2291..9998b0edec9d7a 100644 --- a/rust/kernel/net/netlink.rs +++ b/rust/kernel/net/netlink.rs @@ -2,13 +2,16 @@ use alloc::vec::Vec; use core::ops::{Deref, DerefMut}; -use crate::{bindings, linked_list::Wrapper}; -use crate::{c_types, CStr}; use crate::error::{Error, KernelResult}; use crate::sync::Lock; use crate::user_ptr::{UserSlicePtr, UserSlicePtrReader, UserSlicePtrWriter}; +use crate::{bindings, linked_list::Wrapper}; +use crate::{c_types, CStr}; -use super::{device::{NetDeviceAdapter, NetDevice}, is_valid_ether_addr}; +use super::{ + device::{NetDevice, NetDeviceAdapter}, + is_valid_ether_addr, +}; pub const ETH_ALEN: u16 = bindings::ETH_ALEN as u16; @@ -77,7 +80,6 @@ impl NlExtAck { } } - #[repr(transparent)] pub struct NlAttrVec { ptr: *const *const bindings::nlattr, @@ -89,9 +91,7 @@ impl NlAttrVec { return None; } - let vec = unsafe { - &*(self.ptr as *const [NlAttr; __IFLA_MAX]) - }; + let vec = unsafe { &*(self.ptr as *const [NlAttr; __IFLA_MAX]) }; let nlattr = &vec[offset as usize]; if nlattr.is_null() { None @@ -103,9 +103,7 @@ impl NlAttrVec { pub unsafe fn from_ptr(ptr: *const *const bindings::nlattr) -> Self { /*let vec = *(ptr as *const [NlAttr; __IFLA_MAX]); Self(vec)*/ - Self { - ptr, - } + Self { ptr } } } @@ -135,4 +133,4 @@ impl<'a> NlAttrVec<'a> { // TODO: is this correct? Self(core::slice::from_raw_parts_mut(ptr as *mut NlAttr, bindings::__IFLA_MAX as usize)) } -}*/ \ No newline at end of file +}*/ diff --git a/rust/kernel/net/rtnl.rs b/rust/kernel/net/rtnl.rs index b2a8e4a0502a06..12e12ff82551ff 100644 --- a/rust/kernel/net/rtnl.rs +++ b/rust/kernel/net/rtnl.rs @@ -4,22 +4,22 @@ //! //! C header: [`include/linux/rtnetlink.h`](../../../../include/linux/rtnetlink.h) +use core::cell::UnsafeCell; use core::convert::{TryFrom, TryInto}; use core::{marker, mem, ops::Deref, ops::DerefMut, pin::Pin, ptr}; -use core::cell::UnsafeCell; use crate::bindings; -use crate::{c_types, CStr}; use crate::error::{Error, KernelResult}; use crate::sync::Lock; use crate::user_ptr::{UserSlicePtr, UserSlicePtrReader, UserSlicePtrWriter}; +use crate::{c_types, CStr}; -use super::device::{NetDeviceAdapter, NetDevice}; +use super::device::{NetDevice, NetDeviceAdapter}; // TODO: inner bool, to allow other unlock mechanism? #[must_use = "the rtnl unlocks immediately when the guard is unused"] -pub struct RtnlLock{ - _private: () +pub struct RtnlLock { + _private: (), } impl RtnlLock { @@ -27,9 +27,7 @@ impl RtnlLock { // SAFETY: C function without parameters unsafe { bindings::rtnl_lock() }; - Self { - _private: (), - } + Self { _private: () } } } @@ -60,7 +58,7 @@ pub const RTNL_LINK_OPS_EMPTY: bindings::rtnl_link_ops = bindings::rtnl_link_ops fill_xstats: None, get_num_tx_queues: None, get_num_rx_queues: None, - slave_maxtype: 0, + slave_maxtype: 0, slave_policy: ptr::null::(), slave_changelink: None, get_slave_size: None, @@ -103,9 +101,15 @@ impl RtnlLinkOps { } } +impl Drop for RtnlLinkOps { + fn drop(&mut self) { + crate::pr_info!("dropping rtnl_link_ops"); + } +} + #[repr(transparent)] pub struct RtnlLinkStats64 { - ptr: *const bindings::rtnl_link_stats64 + ptr: *const bindings::rtnl_link_stats64, } impl RtnlLinkStats64 { @@ -116,7 +120,7 @@ impl RtnlLinkStats64 { bindings::dev_lstats_read( dev.get_ptr() as *mut bindings::net_device, &stats.tx_packets as *const u64 as *mut u64, - &stats.tx_bytes as *const u64 as *mut u64 + &stats.tx_bytes as *const u64 as *mut u64, ); } } @@ -131,11 +135,8 @@ impl RtnlLinkStats64 { Self { ptr } } - - fn deref_int(&self) -> &bindings::rtnl_link_stats64{ + fn deref_int(&self) -> &bindings::rtnl_link_stats64 { // SAFETY: self.ptr is valid if self is valid - unsafe { - self.ptr.as_ref() - }.unwrap() + unsafe { self.ptr.as_ref() }.unwrap() } -} \ No newline at end of file +} diff --git a/rust/kernel/net/skbuff.rs b/rust/kernel/net/skbuff.rs index ab44598f58e202..c3be4eba445100 100644 --- a/rust/kernel/net/skbuff.rs +++ b/rust/kernel/net/skbuff.rs @@ -13,7 +13,6 @@ pub struct SkBuff { } impl SkBuff { - #[cfg(CONFIG_NETWORK_PHY_TIMESTAMPING)] pub fn clone_tx_timestamp(&mut self) { // SAFETY: self.ptr is valid if self is valid @@ -31,7 +30,7 @@ impl SkBuff { /// /// Ethernet MAC Drivers should call this function in their hard_xmit() /// function immediately before giving the sk_buff to the MAC hardware. - /// + /// /// Specifically, one should make absolutely sure that this function is /// called before TX completion of this packet can trigger. Otherwise /// the packet could potentially already be freed. @@ -62,9 +61,7 @@ impl SkBuff { fn deref_int(&self) -> &bindings::sk_buff { // SAFETY: self.ptr is valid if self is valid - unsafe { - self.ptr.as_ref() - }.unwrap() + unsafe { self.ptr.as_ref() }.unwrap() } pub fn shinfo(&self) -> SkbSharedInfo { @@ -76,7 +73,7 @@ impl SkBuff { } unsafe fn shinfo_int(&self) -> *mut bindings::skb_shared_info { - self.end_pointer() as *mut bindings::skb_shared_info + self.end_pointer() as *mut bindings::skb_shared_info } // NET_SKBUFF_DATA_USES_OFFSET @@ -95,7 +92,6 @@ impl SkBuff { } impl Drop for SkBuff { - #[cfg(CONFIG_TRACEPOINTS)] fn drop(&mut self) { // SAFETY: self.ptr is valid if self is valid @@ -105,7 +101,7 @@ impl Drop for SkBuff { } #[cfg(not(CONFIG_TRACEPOINTS))] - fn drop(&mut self){ + fn drop(&mut self) { // SAFETY: self.ptr is valid if self is valid unsafe { bindings::kfree_skb(self.ptr as *mut bindings::sk_buff); @@ -113,7 +109,6 @@ impl Drop for SkBuff { } } - /// Wraps the kernel's `struct skb_shared_info`. /// /// # Invariants @@ -125,7 +120,6 @@ pub struct SkbSharedInfo { } impl SkbSharedInfo { - pub fn tx_flags(&self) -> u8 { let ref_skb = self.deref_int(); ref_skb.tx_flags @@ -141,11 +135,8 @@ impl SkbSharedInfo { Self { ptr } } - fn deref_int(&self) -> &bindings::skb_shared_info { // SAFETY: self.ptr is valid if self is valid - unsafe { - self.ptr.as_ref() - }.unwrap() + unsafe { self.ptr.as_ref() }.unwrap() } -} \ No newline at end of file +} diff --git a/rust/module.rs b/rust/module.rs index b21d58dad2e970..63369a86f2a732 100644 --- a/rust/module.rs +++ b/rust/module.rs @@ -103,6 +103,14 @@ fn expect_end(it: &mut token_stream::IntoIter) { } } +fn get_ident(it: &mut token_stream::IntoIter, expected_name: &str) -> String { + assert_eq!(expect_ident(it), expected_name); + assert_eq!(expect_punct(it), ':'); + let ident = expect_ident(it); + assert_eq!(expect_punct(it), ','); + ident +} + fn get_literal(it: &mut token_stream::IntoIter, expected_name: &str) -> String { assert_eq!(expect_ident(it), expected_name); assert_eq!(expect_punct(it), ':'); @@ -859,32 +867,32 @@ pub fn module_misc_device(ts: TokenStream) -> TokenStream { } /// Declares a rtnl link operation table. -/// +/// /// The `type` argument should match the type used for `T` in `NetDevice`. -/// +/// /// # Examples -/// +/// /// ```rust,no_run /// use kernel::prelude::*; /// use kernel::net::prelude::*; -/// +/// /// fn setup(dev: &mut NetDevice) { /// dev.ether_setup(); /// // ... /// } -/// +/// /// rtnl_link_ops! { /// kind: b"dummy_rs", /// type: DummyRsDev, /// setup: setup, /// maxtype: 20, /// } -/// +/// /// struct DummyRsDev; -/// +/// /// impl NetDeviceOps for DummyRsDev { /// kernel::declare_net_device_ops!(); -/// +/// /// fn init(dev: &NetDevice) -> KernelResult<()> { /// Ok(()) /// } @@ -893,21 +901,20 @@ pub fn module_misc_device(ts: TokenStream) -> TokenStream { /// /// } /// } -/// +/// /// impl EthToolOps for DummyRsDev { /// kernel::declare_eth_tool_ops!(); /// } -/// +/// /// fn call_from_module_init() -> KernelResult<()> { /// let mut dev = NetDevice::new(DummyRsDev, kernel::cstr!("dummyrs%d"), kernel::net::device::NetNameAssingType::Enum, 1, 1)?; -/// +/// /// dev.register(); /// dev.set_rtnl_ops(dummy_rs_rtnl_link_ops); -/// +/// /// Ok(()) /// } -/// -/// ``` +/// ``` #[proc_macro] pub fn rtnl_link_ops(ts: TokenStream) -> TokenStream { let mut it = ts.into_iter(); @@ -932,7 +939,11 @@ pub fn rtnl_link_ops(ts: TokenStream) -> TokenStream { if literals.contains(&name.as_str()) { let literal = expect_literal(&mut it); - fields.push_str(&format!("{name}: {literal},\n", name = name, literal = literal)); + fields.push_str(&format!( + "{name}: {literal},\n", + name = name, + literal = literal + )); } else { let func = expect_ident(&mut it); callbacks.push_str(&build_rtnl_links_callback(&name, &netdevice, &func, &kind)); @@ -944,14 +955,18 @@ pub fn rtnl_link_ops(ts: TokenStream) -> TokenStream { expect_end(&mut it); - let callback_fields = found_idents.iter().map(|name| - format!("{}: Some(__rtnl_link_{}_callback_{}),", name, name, kind) - ).collect::>().join("\n"); + let callback_fields = found_idents + .iter() + .map(|name| format!("{}: Some(__rtnl_link_{}_callback_{}),", name, name, kind)) + .collect::>() + .join("\n"); - let ops_struct = format!(r#" + let ops_struct = format!( + r#" #[doc(hidden)] #[used] - pub static mut {kind}_rtnl_link_ops: kernel::net::rtnl::RtnlLinkOps = kernel::net::rtnl::RtnlLinkOps(kernel::bindings::rtnl_link_ops {{ + #[no_mangle] + pub static mut {kind}_link_ops: kernel::net::rtnl::RtnlLinkOps = kernel::net::rtnl::RtnlLinkOps(kernel::bindings::rtnl_link_ops {{ priv_size: core::mem::size_of::<<{netdevice} as kernel::net::device::NetDeviceAdapter>::Inner>(), kind: b"{kind}\0".as_ptr() as *const i8, {callback_fields} @@ -977,10 +992,10 @@ pub fn rtnl_link_ops(ts: TokenStream) -> TokenStream { #[cfg(not(any(CONFIG_X86, CONFIG_SPARC64)))] {} "#, - callbacks, - ops_struct, - ops_struct, - ).parse().expect("Error parsing formatted string into token stream.") + callbacks, ops_struct, ops_struct, + ) + .parse() + .expect("Error parsing formatted string into token stream.") } struct RtnlLinkValues { @@ -1004,7 +1019,10 @@ impl RtnlLinkValues { } fn get_rtnl_links_values(name: &str, netdevice: &str) -> RtnlLinkValues { - let setup_dev = format!("let mut dev = kernel::net::device::NetDevice::<{}>::from_ptr(dev);", netdevice); + let setup_dev = format!( + "let mut dev = kernel::net::device::NetDevice::<{}>::from_ptr(dev);", + netdevice + ); match name { "setup" => RtnlLinkValues::new("dev: *mut kernel::bindings::net_device", &setup_dev, "&mut dev"), "validate" => RtnlLinkValues { @@ -1024,7 +1042,8 @@ fn get_rtnl_links_values(name: &str, netdevice: &str) -> RtnlLinkValues { fn build_rtnl_links_callback(name: &str, netdevice: &str, func: &str, kind: &str) -> String { let values = get_rtnl_links_values(name, netdevice); - format!(r#" + format!( + r#" #[doc(hidden)] pub unsafe extern "C" fn __rtnl_link_{name}_callback_{kind}({cb_params}) -> {cb_return} {{ {cb_before}