From patchwork Mon Jul 10 07:36:59 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: FUJITA Tomonori X-Patchwork-Id: 13306372 X-Patchwork-Delegate: kuba@kernel.org Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C20F88837 for ; Mon, 10 Jul 2023 07:39:07 +0000 (UTC) Received: from mail-pf1-x436.google.com (mail-pf1-x436.google.com [IPv6:2607:f8b0:4864:20::436]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D758EE55; Mon, 10 Jul 2023 00:38:53 -0700 (PDT) Received: by mail-pf1-x436.google.com with SMTP id d2e1a72fcca58-682a5465e9eso616244b3a.1; Mon, 10 Jul 2023 00:38:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1688974732; x=1691566732; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Ba+ud/bJX6+UuWaPNLfdYg9gMAViu7WzsURm7s3i/Pg=; b=EFbQDbnhug51h9KKjoZJ6DB1f2fsNMJsRufU7Z3Ld3xIXzU62rvvpz9EIJ/JBY0gtm qwXOUhowF7IgfQ15l7/QRJQrps/EgPX9dMKpb1HyFjBnjBkJStzyHTI4yre+c0LfguNF w2XhUyB3y1mem5dss4DYyzzFBKkCALDPBzjzQtUhGLl2Uya0Wge4jS3ke0YIa0u6peWw P5GbziIGlAoke7XZuWQACEx6vNbqxscCFNPGVi5HVxKVxm/59QjyQQIaOaLqWQDKBoDB pUid9t3DeDCKbP4ndBXjqWyiuOJExPKWwIzQeo2tlkNuVIvePcJ7dOwEisekE6xulYri NZ4w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1688974732; x=1691566732; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Ba+ud/bJX6+UuWaPNLfdYg9gMAViu7WzsURm7s3i/Pg=; b=AsDB5IXFB2l9HYzQ+E/L1b8MOkaGnZ7thgWwL3hofCQ+HnleLL6aF0fGpJO6n/Vncv NlKEiHCYNFBJV9jaEE2aWwqCd21stt7rvffws6Df7l1eOGrf/+xLxB4n7nhsRFHgp0E2 Pz3KMkD/hnViZBqNkKXeKcTp14Z+D7PLRUvJ4pPt8u4Bc5qPXzYggi+fkirJP3bMoSh0 prAGOycCpfHYTCk7mhyWZxpfsR21Y1P1n+QwbycLx9HyrfGzOZt0ssO1mAVuQx85DnF6 9yZSmA8Mw/dAlq+bHiSLoHIfS1MyXEF8LheON3X4KydgJlLZ3WA9VPn+fdI72Lxs80Ru mh2A== X-Gm-Message-State: ABy/qLa4Ge7l6F+Gs4MGRZ9EfEG2DjMqUZzAyax2OFyJedu9Ypmnd9Ja nY9dyE4OufLluPTicuP5Clv+5O7unHvPCA== X-Google-Smtp-Source: APBJJlGVDh+uOTvpbLfWf2miYm1whjndxXzlFX6rmxpp2SWFOjqYZ4gLgOsQgd6Egjwkm0ZYi8a4cA== X-Received: by 2002:a05:6a00:3387:b0:675:8627:a291 with SMTP id cm7-20020a056a00338700b006758627a291mr12242820pfb.3.1688974731893; Mon, 10 Jul 2023 00:38:51 -0700 (PDT) Received: from ip-172-30-47-114.us-west-2.compute.internal (ec2-54-68-170-188.us-west-2.compute.amazonaws.com. [54.68.170.188]) by smtp.gmail.com with ESMTPSA id r20-20020a62e414000000b0063f2a5a59d1sm6514483pfh.190.2023.07.10.00.38.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Jul 2023 00:38:51 -0700 (PDT) From: FUJITA Tomonori To: rust-for-linux@vger.kernel.org, netdev@vger.kernel.org Cc: kuba@kernel.org, andrew@lunn.ch, aliceryhl@google.com, miguel.ojeda.sandonis@gmail.com, benno.lossin@proton.me Subject: [PATCH v2 1/5] rust: core abstractions for network device drivers Date: Mon, 10 Jul 2023 16:36:59 +0900 Message-Id: <20230710073703.147351-2-fujita.tomonori@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230710073703.147351-1-fujita.tomonori@gmail.com> References: <20230710073703.147351-1-fujita.tomonori@gmail.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM, RCVD_IN_DNSWL_BLOCKED,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net This patch adds very basic abstractions to implement network device drivers, corresponds to the kernel's net_device and net_device_ops structs with support for register_netdev/unregister_netdev functions. allows the const_maybe_uninit_zeroed feature for core::mem::MaybeUinit::::zeroed() in const function. Signed-off-by: FUJITA Tomonori --- rust/bindings/bindings_helper.h | 2 + rust/helpers.c | 16 ++ rust/kernel/lib.rs | 3 + rust/kernel/net.rs | 5 + rust/kernel/net/dev.rs | 330 ++++++++++++++++++++++++++++++++ 5 files changed, 356 insertions(+) create mode 100644 rust/kernel/net.rs create mode 100644 rust/kernel/net/dev.rs diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h index 3e601ce2548d..468bf606f174 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -7,6 +7,8 @@ */ #include +#include +#include #include #include #include diff --git a/rust/helpers.c b/rust/helpers.c index bb594da56137..70d50767ff4e 100644 --- a/rust/helpers.c +++ b/rust/helpers.c @@ -24,10 +24,26 @@ #include #include #include +#include +#include #include #include #include +#ifdef CONFIG_NET +void *rust_helper_netdev_priv(const struct net_device *dev) +{ + return netdev_priv(dev); +} +EXPORT_SYMBOL_GPL(rust_helper_netdev_priv); + +void rust_helper_skb_tx_timestamp(struct sk_buff *skb) +{ + skb_tx_timestamp(skb); +} +EXPORT_SYMBOL_GPL(rust_helper_skb_tx_timestamp); +#endif + __noreturn void rust_helper_BUG(void) { BUG(); diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 85b261209977..fc7d048d359d 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -13,6 +13,7 @@ #![no_std] #![feature(allocator_api)] +#![feature(const_maybe_uninit_zeroed)] #![feature(coerce_unsized)] #![feature(dispatch_from_dyn)] #![feature(new_uninit)] @@ -34,6 +35,8 @@ pub mod error; pub mod init; pub mod ioctl; +#[cfg(CONFIG_NET)] +pub mod net; pub mod prelude; pub mod print; mod static_assert; diff --git a/rust/kernel/net.rs b/rust/kernel/net.rs new file mode 100644 index 000000000000..28fe8f398463 --- /dev/null +++ b/rust/kernel/net.rs @@ -0,0 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Networking core. + +pub mod dev; diff --git a/rust/kernel/net/dev.rs b/rust/kernel/net/dev.rs new file mode 100644 index 000000000000..fe20616668a9 --- /dev/null +++ b/rust/kernel/net/dev.rs @@ -0,0 +1,330 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Network device. +//! +//! C headers: [`include/linux/etherdevice.h`](../../../../include/linux/etherdevice.h), +//! [`include/linux/ethtool.h`](../../../../include/linux/ethtool.h), +//! [`include/linux/netdevice.h`](../../../../include/linux/netdevice.h), +//! [`include/linux/skbuff.h`](../../../../include/linux/skbuff.h), +//! [`include/uapi/linux/if_link.h`](../../../../include/uapi/linux/if_link.h). + +use crate::{bindings, build_error, error::*, prelude::vtable, types::ForeignOwnable}; +use {core::ffi::c_void, core::marker::PhantomData}; + +/// Corresponds to the kernel's `struct net_device`. +/// +/// # Invariants +/// +/// The `ptr` points to the contiguous memory for `struct net_device` and a pointer, +/// which stores an address returned by `ForeignOwnable::into_foreign()`. +pub struct Device { + ptr: *mut bindings::net_device, + _p: PhantomData, +} + +impl Device { + /// Creates a new [`Device`] instance. + /// + /// # Safety + /// + /// Callers must ensure that `ptr` must point to the contiguous memory + /// for `struct net_device` and a pointer, which stores an address returned + /// by `ForeignOwnable::into_foreign()`. + unsafe fn from_ptr(ptr: *mut bindings::net_device) -> Self { + // INVARIANT: The safety requirements ensure the invariant. + Self { + ptr, + _p: PhantomData, + } + } + + /// Gets the private data of a device driver. + pub fn drv_priv_data(&self) -> D::Borrowed<'_> { + // SAFETY: The type invariants guarantee that self.ptr is valid and + // bindings::netdev_priv(self.ptr) returns a pointer that stores an address + // returned by `ForeignOwnable::into_foreign()`. + unsafe { + D::borrow(core::ptr::read( + bindings::netdev_priv(self.ptr) as *const *const c_void + )) + } + } +} + +// SAFETY: `Device` is just a wrapper for the kernel`s `struct net_device`, which can be used +// from any thread. `struct net_device` stores a pointer to an object, which is `Sync` +// so it's safe to sharing its pointer. +unsafe impl Send for Device {} +// SAFETY: `Device` is just a wrapper for the kernel`s `struct net_device`, which can be used +// from any thread. `struct net_device` stores a pointer to an object, which is `Sync`, +// can be used from any thread too. +unsafe impl Sync for Device {} + +/// Registration structure for a network device driver. +/// +/// This allocates and owns a `struct net_device` object. +/// Once the `net_device` object is registered via `register_netdev` function, +/// the kernel calls various functions such as `struct net_device_ops` operations with +/// the `net_device` object. +/// +/// A driver must implement `struct net_device_ops` so the trait for it is tied. +/// Other operations like `struct ethtool_ops` are optional. +pub struct Registration { + dev: Device, + is_registered: bool, + _p: PhantomData, +} + +impl Drop for Registration { + fn drop(&mut self) { + // SAFETY: The type invariants of `Device` guarantee that `self.dev.ptr` is valid and + // bindings::netdev_priv(self.ptr) returns a pointer that stores an address + // returned by `ForeignOwnable::into_foreign()`. + unsafe { + let _ = T::from_foreign(core::ptr::read( + bindings::netdev_priv(self.dev.ptr) as *const *const c_void + )); + } + // SAFETY: The type invariants of `Device` guarantee that `self.dev.ptr` is valid. + unsafe { + if self.is_registered { + bindings::unregister_netdev(self.dev.ptr); + } + bindings::free_netdev(self.dev.ptr); + } + } +} + +impl Registration { + /// Creates a new [`Registration`] instance for ethernet device. + /// + /// A device driver can pass private data. + pub fn try_new_ether(tx_queue_size: u32, rx_queue_size: u32, data: T) -> Result { + // SAFETY: Just an FFI call with no additional safety requirements. + let ptr = unsafe { + bindings::alloc_etherdev_mqs( + core::mem::size_of::<*const c_void>() as i32, + tx_queue_size, + rx_queue_size, + ) + }; + if ptr.is_null() { + return Err(code::ENOMEM); + } + + // SAFETY: It's safe to write an address returned pointer + // from `netdev_priv()` because `alloc_etherdev_mqs()` allocates + // contiguous memory for `struct net_device` and a pointer. + unsafe { + let priv_ptr = bindings::netdev_priv(ptr) as *mut *const c_void; + core::ptr::write(priv_ptr, data.into_foreign()); + } + + // SAFETY: `ptr` points to contiguous memory for `struct net_device` and a pointer, + // which stores an address returned by `ForeignOwnable::into_foreign()`. + let dev = unsafe { Device::from_ptr(ptr) }; + Ok(Registration { + dev, + is_registered: false, + _p: PhantomData, + }) + } + + /// Returns a network device. + /// + /// A device driver normally configures the device before registration. + pub fn dev_get(&mut self) -> &mut Device { + &mut self.dev + } + + /// Registers a network device. + pub fn register(&mut self) -> Result { + if self.is_registered { + return Err(code::EINVAL); + } + // SAFETY: The type invariants guarantee that `self.dev.ptr` is valid. + let ret = unsafe { + (*self.dev.ptr).netdev_ops = &Self::DEVICE_OPS; + bindings::register_netdev(self.dev.ptr) + }; + if ret != 0 { + Err(Error::from_errno(ret)) + } else { + self.is_registered = true; + Ok(()) + } + } + + const DEVICE_OPS: bindings::net_device_ops = bindings::net_device_ops { + ndo_init: if ::HAS_INIT { + Some(Self::init_callback) + } else { + None + }, + ndo_uninit: if ::HAS_UNINIT { + Some(Self::uninit_callback) + } else { + None + }, + ndo_open: if ::HAS_OPEN { + Some(Self::open_callback) + } else { + None + }, + ndo_stop: if ::HAS_STOP { + Some(Self::stop_callback) + } else { + None + }, + ndo_start_xmit: if ::HAS_START_XMIT { + Some(Self::start_xmit_callback) + } else { + None + }, + // SAFETY: The rest is zeroed out to initialize `struct net_device_ops`, + // set `Option<&F>` to be `None`. + ..unsafe { core::mem::MaybeUninit::::zeroed().assume_init() } + }; + + unsafe extern "C" fn init_callback(netdev: *mut bindings::net_device) -> core::ffi::c_int { + from_result(|| { + // SAFETY: The C API guarantees that `netdev` is valid while this function is running. + let dev = unsafe { Device::from_ptr(netdev) }; + T::init(dev)?; + Ok(0) + }) + } + + unsafe extern "C" fn uninit_callback(netdev: *mut bindings::net_device) { + // SAFETY: The C API guarantees that `netdev` is valid while this function is running. + let dev = unsafe { Device::from_ptr(netdev) }; + T::uninit(dev); + } + + unsafe extern "C" fn open_callback(netdev: *mut bindings::net_device) -> core::ffi::c_int { + from_result(|| { + // SAFETY: The C API guarantees that `netdev` is valid while this function is running. + let dev = unsafe { Device::from_ptr(netdev) }; + T::open(dev)?; + Ok(0) + }) + } + + unsafe extern "C" fn stop_callback(netdev: *mut bindings::net_device) -> core::ffi::c_int { + from_result(|| { + // SAFETY: The C API guarantees that `netdev` is valid while this function is running. + let dev = unsafe { Device::from_ptr(netdev) }; + T::stop(dev)?; + Ok(0) + }) + } + + unsafe extern "C" fn start_xmit_callback( + skb: *mut bindings::sk_buff, + netdev: *mut bindings::net_device, + ) -> bindings::netdev_tx_t { + // SAFETY: The C API guarantees that `netdev` is valid while this function is running. + let dev = unsafe { Device::from_ptr(netdev) }; + // SAFETY: The C API guarantees that `skb` is valid until a driver releases the skb. + let skb = unsafe { SkBuff::from_ptr(skb) }; + T::start_xmit(dev, skb) as bindings::netdev_tx_t + } +} + +// SAFETY: `Registration` exposes only `Device` object which can be used from any thread. +unsafe impl Send for Registration {} +// SAFETY: `Registration` exposes only `Device` object which can be used from any thread. +unsafe impl Sync for Registration {} + +/// Corresponds to the kernel's `enum netdev_tx`. +#[repr(i32)] +pub enum TxCode { + /// Driver took care of packet. + Ok = bindings::netdev_tx_NETDEV_TX_OK, + /// Driver tx path was busy. + Busy = bindings::netdev_tx_NETDEV_TX_BUSY, +} + +/// Corresponds to the kernel's `struct net_device_ops`. +/// +/// A device driver must implement this. Only very basic operations are supported for now. +#[vtable] +pub trait DeviceOperations: ForeignOwnable + Send + Sync { + /// Corresponds to `ndo_init` in `struct net_device_ops`. + fn init(_dev: Device) -> Result { + Ok(()) + } + + /// Corresponds to `ndo_uninit` in `struct net_device_ops`. + fn uninit(_dev: Device) {} + + /// Corresponds to `ndo_open` in `struct net_device_ops`. + fn open(_dev: Device) -> Result { + Ok(()) + } + + /// Corresponds to `ndo_stop` in `struct net_device_ops`. + fn stop(_dev: Device) -> Result { + Ok(()) + } + + /// Corresponds to `ndo_start_xmit` in `struct net_device_ops`. + fn start_xmit(_dev: Device, _skb: SkBuff) -> TxCode { + TxCode::Busy + } +} + +/// Corresponds to the kernel's `struct sk_buff`. +/// +/// A driver manages `struct sk_buff` in two ways. In both ways, the ownership is transferred +/// between C and Rust. The allocation and release are done asymmetrically. +/// +/// On the tx side (`ndo_start_xmit` operation in `struct net_device_ops`), the kernel allocates +/// a `sk_buff' object and passes it to the driver. The driver is responsible for the release +/// after transmission. +/// On the rx side, the driver allocates a `sk_buff` object then passes it to the kernel +/// after receiving data. +/// +/// A driver must explicitly call a function to drop a `sk_buff` object. +/// The code to let a `SkBuff` object go out of scope can't be compiled. +/// +/// # Invariants +/// +/// The pointer is valid. +pub struct SkBuff(*mut bindings::sk_buff); + +impl SkBuff { + /// Creates a new [`SkBuff`] instance. + /// + /// # Safety + /// + /// Callers must ensure that `ptr` must be valid. + unsafe fn from_ptr(ptr: *mut bindings::sk_buff) -> Self { + // INVARIANT: The safety requirements ensure the invariant. + Self(ptr) + } + + /// Provides a time stamp. + pub fn tx_timestamp(&mut self) { + // SAFETY: The type invariants guarantee that `self.0` is valid. + unsafe { + bindings::skb_tx_timestamp(self.0); + } + } + + /// Consumes a [`sk_buff`] object. + pub fn consume(self) { + // SAFETY: The type invariants guarantee that `self.0` is valid. + unsafe { + bindings::kfree_skb_reason(self.0, bindings::skb_drop_reason_SKB_CONSUMED); + } + core::mem::forget(self); + } +} + +impl Drop for SkBuff { + #[inline(always)] + fn drop(&mut self) { + build_error!("skb must be released explicitly"); + } +} From patchwork Mon Jul 10 07:37:00 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: FUJITA Tomonori X-Patchwork-Id: 13306373 X-Patchwork-Delegate: kuba@kernel.org Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A7F79C2C0 for ; Mon, 10 Jul 2023 07:39:08 +0000 (UTC) Received: from mail-pf1-x42b.google.com (mail-pf1-x42b.google.com [IPv6:2607:f8b0:4864:20::42b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9FB1FE5D; Mon, 10 Jul 2023 00:38:54 -0700 (PDT) Received: by mail-pf1-x42b.google.com with SMTP id d2e1a72fcca58-682ae5d4184so902931b3a.1; Mon, 10 Jul 2023 00:38:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1688974733; x=1691566733; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=bRvsjomO7b3OWqiYBdrZZKEA2t4LQKVW3Z+rDt4uBL4=; b=pU9OZRaou+Rt68Z+fZ/Dz9N/ylGc9a7wpRjRYNEs6STo+2uh3XrriCh2g71hW5mkKi w9omeoDS9U4VzweocjDCNtA3LQpSmuAcOFDDnCpUC5vQ+6U/+YzetTQrkl8KMhiZWpIT 6ArhBbE0a0pSWEeEyKNZHFxyeA9CVfLsWhlh8I342XtmtSUVRt9uUEp3ufxbKRMlLqu+ 4iPozXT6plxZPztYWOdf+SBSPCkOWDJyJf+lQhOxzvZcW22/qQQlYd+5zDx3yQHfzYzt Wx6JYxuBmuV8Iem90CaXt2yGN1ucSabuTbFRXvzvTksvRAquyrz7cVhla25UZqKidPKq yKHQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1688974733; x=1691566733; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=bRvsjomO7b3OWqiYBdrZZKEA2t4LQKVW3Z+rDt4uBL4=; b=Y8YtiR5dTu9oGH18TqZYXMSYuS1B0ZFLCSf//cz5XzQNKTqrSeWjyM59sSJQcir9Fu XhF9O9FYJSh/x5klszkhxbMH6n90mYQNpbd7c19K1/fGWTvYIXRxIyj+pxr803olTONU vQRjo4fRBCQULzgHnDXQ1J4WDn3mykVf+9H8oiXH2MubpwBsrfLJLUypvMXiyAHo+ize aL6FREGtV4XgeZiMH5EhQ38zJ+LQQtOI2MaRglycuc2H+d+5pWVB37zCL07SKLCkAMFU bJ/Dk+tCP4++zyx+4dYUNX1kf4mZo3iYdH8d61NojSZtRPABFIm8J/3/PHHZ31l8Otbw 3hfQ== X-Gm-Message-State: ABy/qLbUBBstgAcPOhUxOD1hQHBlmOkVDIqUXVeuzPsqfZG+JV4nxGQM UT7vro47+gKvWbq6QI3mq772tRMXWtJv4A== X-Google-Smtp-Source: APBJJlFHR34vYwdl3x1qhId87A9s3hXR+3Q3CZ7Ju6HeoN/EdSI4n8uJvRIED4bS1RHsHXsBGF8Kkg== X-Received: by 2002:a05:6a00:2daa:b0:66f:3fc5:6167 with SMTP id fb42-20020a056a002daa00b0066f3fc56167mr14274134pfb.1.1688974733050; Mon, 10 Jul 2023 00:38:53 -0700 (PDT) Received: from ip-172-30-47-114.us-west-2.compute.internal (ec2-54-68-170-188.us-west-2.compute.amazonaws.com. [54.68.170.188]) by smtp.gmail.com with ESMTPSA id r20-20020a62e414000000b0063f2a5a59d1sm6514483pfh.190.2023.07.10.00.38.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Jul 2023 00:38:52 -0700 (PDT) From: FUJITA Tomonori To: rust-for-linux@vger.kernel.org, netdev@vger.kernel.org Cc: kuba@kernel.org, andrew@lunn.ch, aliceryhl@google.com, miguel.ojeda.sandonis@gmail.com, benno.lossin@proton.me Subject: [PATCH v2 2/5] rust: add support for ethernet operations Date: Mon, 10 Jul 2023 16:37:00 +0900 Message-Id: <20230710073703.147351-3-fujita.tomonori@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230710073703.147351-1-fujita.tomonori@gmail.com> References: <20230710073703.147351-1-fujita.tomonori@gmail.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM, RCVD_IN_DNSWL_BLOCKED,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net This improves abstractions for network device drivers to implement struct ethtool_ops, the majority of ethernet device drivers need to do. struct ethtool_ops also needs to access to device private data like struct net_device_ops. Currently, only get_ts_info operation is supported. The following patch adds the Rust version of the dummy network driver, which uses the operation. Signed-off-by: FUJITA Tomonori --- rust/bindings/bindings_helper.h | 1 + rust/kernel/net/dev.rs | 87 ++++++++++++++++++++++++++++++++- 2 files changed, 87 insertions(+), 1 deletion(-) diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h index 468bf606f174..6446ff764980 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -8,6 +8,7 @@ #include #include +#include #include #include #include diff --git a/rust/kernel/net/dev.rs b/rust/kernel/net/dev.rs index fe20616668a9..ff00616e4fef 100644 --- a/rust/kernel/net/dev.rs +++ b/rust/kernel/net/dev.rs @@ -142,7 +142,7 @@ pub fn register(&mut self) -> Result { if self.is_registered { return Err(code::EINVAL); } - // SAFETY: The type invariants guarantee that `self.dev.ptr` is valid. + // SAFETY: The type invariants of `Device` guarantee that `self.dev.ptr` is valid. let ret = unsafe { (*self.dev.ptr).netdev_ops = &Self::DEVICE_OPS; bindings::register_netdev(self.dev.ptr) @@ -155,6 +155,18 @@ pub fn register(&mut self) -> Result { } } + /// Sets `ethtool_ops` of `net_device`. + pub fn set_ether_operations(&mut self) -> Result { + if self.is_registered { + return Err(code::EINVAL); + } + // SAFETY: The type invariants of `Device` guarantee that `self.dev.ptr` is valid. + unsafe { + (*(self.dev.ptr)).ethtool_ops = &EtherOperationsAdapter::::ETHER_OPS; + } + Ok(()) + } + const DEVICE_OPS: bindings::net_device_ops = bindings::net_device_ops { ndo_init: if ::HAS_INIT { Some(Self::init_callback) @@ -328,3 +340,76 @@ fn drop(&mut self) { build_error!("skb must be released explicitly"); } } + +/// Builds the kernel's `struct ethtool_ops`. +struct EtherOperationsAdapter { + _p: PhantomData, +} + +impl EtherOperationsAdapter { + unsafe extern "C" fn get_ts_info_callback( + netdev: *mut bindings::net_device, + info: *mut bindings::ethtool_ts_info, + ) -> core::ffi::c_int { + from_result(|| { + // SAFETY: The C API guarantees that `netdev` is valid while this function is running. + let dev = unsafe { Device::from_ptr(netdev) }; + // SAFETY: The C API guarantees that `info` is valid while this function is running. + let info = unsafe { EthtoolTsInfo::from_ptr(info) }; + E::get_ts_info(dev, info)?; + Ok(0) + }) + } + + const ETHER_OPS: bindings::ethtool_ops = bindings::ethtool_ops { + get_ts_info: if ::HAS_GET_TS_INFO { + Some(Self::get_ts_info_callback) + } else { + None + }, + // SAFETY: The rest is zeroed out to initialize `struct ethtool_ops`, + // set `Option<&F>` to be `None`. + ..unsafe { core::mem::MaybeUninit::::zeroed().assume_init() } + }; +} + +/// Corresponds to the kernel's `struct ethtool_ops`. +#[vtable] +pub trait EtherOperations: ForeignOwnable + Send + Sync { + /// Corresponds to `get_ts_info` in `struct ethtool_ops`. + fn get_ts_info(_dev: Device, _info: EthtoolTsInfo) -> Result { + Err(Error::from_errno(bindings::EOPNOTSUPP as i32)) + } +} + +/// Corresponds to the kernel's `struct ethtool_ts_info`. +/// +/// # Invariants +/// +/// The pointer is valid. +pub struct EthtoolTsInfo(*mut bindings::ethtool_ts_info); + +impl EthtoolTsInfo { + /// Creates a new `EthtoolTsInfo' instance. + /// + /// # Safety + /// + /// Callers must ensure that `ptr` must be valid. + unsafe fn from_ptr(ptr: *mut bindings::ethtool_ts_info) -> Self { + // INVARIANT: The safety requirements ensure the invariant. + Self(ptr) + } + + /// Sets up the info for software timestamping. + pub fn ethtool_op_get_ts_info( + dev: &Device, + info: &mut EthtoolTsInfo, + ) -> Result { + // SAFETY: The type invariants of `Device` guarantee that `dev.ptr` are valid. + // The type invariants guarantee that `info.0` are valid. + unsafe { + bindings::ethtool_op_get_ts_info(dev.ptr, info.0); + } + Ok(()) + } +} From patchwork Mon Jul 10 07:37:01 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: FUJITA Tomonori X-Patchwork-Id: 13306374 X-Patchwork-Delegate: kuba@kernel.org Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 62A30C8CC for ; Mon, 10 Jul 2023 07:39:11 +0000 (UTC) Received: from mail-pf1-x42c.google.com (mail-pf1-x42c.google.com [IPv6:2607:f8b0:4864:20::42c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B6554E6F; Mon, 10 Jul 2023 00:38:56 -0700 (PDT) Received: by mail-pf1-x42c.google.com with SMTP id d2e1a72fcca58-66872dbc2efso1116517b3a.0; Mon, 10 Jul 2023 00:38:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1688974735; x=1691566735; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=N0cvgCuH/2UE9JLFG5tGldADsplPGRbN7ePmEMFuXak=; b=UutFIxk+Hmq9V098LLNWlzZ1Z1dRbmxcMS0MT50WAJxzW9GNNNWBTt3kg+vABHp0KP lhcg5xpzImGLBdr2+N48AbZD2KHJAqEE2N+XL4ZfMmmPaHNjj4whJbyBZPRrkCFdQ8cV +u9+QFp/c+Qw9CFKs/wJ8FXLC1VDrCa8/5MTN5+abLSyKSEnC9BbtsWwezLYaHuB0Kqh VQdvitvu8X/mD7IiLwIs6plMX7zNjitOjA5O6wgugjnLOAStRlTMvxMa3xDCNC+xPEb+ K0Jxn4FyBHOrCqItFsYHPmYxdpVPb3sjhDmhCXq7A+ZTXFkXVZ23ocv8EMnKWfHAQ5mJ 1OqA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1688974735; x=1691566735; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=N0cvgCuH/2UE9JLFG5tGldADsplPGRbN7ePmEMFuXak=; b=KV0nQpClJDFYO8dOLSwLx2zZrRXM39aYGPXuIQFF6LzucwWvleeeIDkGGpi90sEioW 1iJshw/O402DeTa7l3QdjTDt1oRTUTg7NaqdDPFr6FwVLS04Y24Umxe1LGgOZsWKkTdH 3OJc4H5yPFMqMrWwRHh3LxndBLTnshmPtwhGmRmkOCQbRgfHMcU1AjoytzaMSXC5XJMo uk4DqMLrv0GvC2R+Vmf8VEKrk5mOTi+ilPlLaBqn8591roqYtfwp0sIzQqYtvdkbi2V6 YkRCruuvmIVSUiEH/DTOwcOXPlo+jjGOdv7pya1zmf/O6ndPaEH3iRqfAX7zizfRd/Y2 cpxQ== X-Gm-Message-State: ABy/qLYYyTKYgxN1zLmyrbNnTn412f9o4my9xqQKMBLShn44j0KenSV8 e6gnNr+9jJuKEUyBq1yXrxop00i7aQYU6CwN X-Google-Smtp-Source: APBJJlFnjmb5qzv534zFkRQuJwhanRa+Q0xoodeeohGNpnu8ZOuowvWqjOKOi5RRWpjIiSEil5LYWA== X-Received: by 2002:a05:6a00:14c9:b0:682:59aa:178d with SMTP id w9-20020a056a0014c900b0068259aa178dmr12718760pfu.1.1688974734733; Mon, 10 Jul 2023 00:38:54 -0700 (PDT) Received: from ip-172-30-47-114.us-west-2.compute.internal (ec2-54-68-170-188.us-west-2.compute.amazonaws.com. [54.68.170.188]) by smtp.gmail.com with ESMTPSA id r20-20020a62e414000000b0063f2a5a59d1sm6514483pfh.190.2023.07.10.00.38.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Jul 2023 00:38:53 -0700 (PDT) From: FUJITA Tomonori To: rust-for-linux@vger.kernel.org, netdev@vger.kernel.org Cc: kuba@kernel.org, andrew@lunn.ch, aliceryhl@google.com, miguel.ojeda.sandonis@gmail.com, benno.lossin@proton.me Subject: [PATCH v2 3/5] rust: add methods for configure net_device Date: Mon, 10 Jul 2023 16:37:01 +0900 Message-Id: <20230710073703.147351-4-fujita.tomonori@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230710073703.147351-1-fujita.tomonori@gmail.com> References: <20230710073703.147351-1-fujita.tomonori@gmail.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM, RCVD_IN_DNSWL_BLOCKED,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net adds methods to net::Device for the basic configurations of net_device. Signed-off-by: FUJITA Tomonori --- rust/helpers.c | 7 ++ rust/kernel/net/dev.rs | 185 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 191 insertions(+), 1 deletion(-) diff --git a/rust/helpers.c b/rust/helpers.c index 70d50767ff4e..6c51deb18dc1 100644 --- a/rust/helpers.c +++ b/rust/helpers.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -31,6 +32,12 @@ #include #ifdef CONFIG_NET +void rust_helper_eth_hw_addr_random(struct net_device *dev) +{ + eth_hw_addr_random(dev); +} +EXPORT_SYMBOL_GPL(rust_helper_eth_hw_addr_random); + void *rust_helper_netdev_priv(const struct net_device *dev) { return netdev_priv(dev); diff --git a/rust/kernel/net/dev.rs b/rust/kernel/net/dev.rs index ff00616e4fef..e4d8d8260c10 100644 --- a/rust/kernel/net/dev.rs +++ b/rust/kernel/net/dev.rs @@ -8,9 +8,116 @@ //! [`include/linux/skbuff.h`](../../../../include/linux/skbuff.h), //! [`include/uapi/linux/if_link.h`](../../../../include/uapi/linux/if_link.h). -use crate::{bindings, build_error, error::*, prelude::vtable, types::ForeignOwnable}; +use crate::{bindings, build_error, error::*, prelude::vtable, str::CStr, types::ForeignOwnable}; use {core::ffi::c_void, core::marker::PhantomData}; +/// Flags associated with a [`Device`]. +pub mod flags { + /// Interface is up. + pub const IFF_UP: u32 = bindings::net_device_flags_IFF_UP; + /// Broadcast address valid. + pub const IFF_BROADCAST: u32 = bindings::net_device_flags_IFF_BROADCAST; + /// Device on debugging. + pub const IFF_DEBUG: u32 = bindings::net_device_flags_IFF_DEBUG; + /// Loopback device. + pub const IFF_LOOPBACK: u32 = bindings::net_device_flags_IFF_LOOPBACK; + /// Has p-p link. + pub const IFF_POINTOPOINT: u32 = bindings::net_device_flags_IFF_POINTOPOINT; + /// Avoids use of trailers. + pub const IFF_NOTRAILERS: u32 = bindings::net_device_flags_IFF_NOTRAILERS; + /// Interface RFC2863 OPER_UP. + pub const IFF_RUNNING: u32 = bindings::net_device_flags_IFF_RUNNING; + /// No ARP protocol. + pub const IFF_NOARP: u32 = bindings::net_device_flags_IFF_NOARP; + /// Receives all packets. + pub const IFF_PROMISC: u32 = bindings::net_device_flags_IFF_PROMISC; + /// Receive all multicast packets. + pub const IFF_ALLMULTI: u32 = bindings::net_device_flags_IFF_ALLMULTI; + /// Master of a load balancer. + pub const IFF_MASTER: u32 = bindings::net_device_flags_IFF_MASTER; + /// Slave of a load balancer. + pub const IFF_SLAVE: u32 = bindings::net_device_flags_IFF_SLAVE; + /// Supports multicast. + pub const IFF_MULTICAST: u32 = bindings::net_device_flags_IFF_MULTICAST; + /// Capable of setting media type. + pub const IFF_PORTSEL: u32 = bindings::net_device_flags_IFF_PORTSEL; + /// Auto media select active. + pub const IFF_AUTOMEDIA: u32 = bindings::net_device_flags_IFF_AUTOMEDIA; + /// Dialup device with changing addresses. + pub const IFF_DYNAMIC: u32 = bindings::net_device_flags_IFF_DYNAMIC; +} + +/// Private flags associated with a [`Device`]. +pub mod priv_flags { + /// 802.1Q VLAN device. + pub const IFF_802_1Q_VLAN: u64 = bindings::netdev_priv_flags_IFF_802_1Q_VLAN; + /// Ethernet bridging device. + pub const IFF_EBRIDGE: u64 = bindings::netdev_priv_flags_IFF_EBRIDGE; + /// Bonding master or slave device. + pub const IFF_BONDING: u64 = bindings::netdev_priv_flags_IFF_BONDING; + /// ISATAP interface (RFC4214). + pub const IFF_ISATAP: u64 = bindings::netdev_priv_flags_IFF_ISATAP; + /// WAN HDLC device. + pub const IFF_WAN_HDLC: u64 = bindings::netdev_priv_flags_IFF_WAN_HDLC; + /// dev_hard_start_xmit() is allowed to release skb->dst. + pub const IFF_XMIT_DST_RELEASE: u64 = bindings::netdev_priv_flags_IFF_XMIT_DST_RELEASE; + /// Disallows bridging this ether device. + pub const IFF_DONT_BRIDGE: u64 = bindings::netdev_priv_flags_IFF_DONT_BRIDGE; + /// Disables netpoll at run-time. + pub const IFF_DISABLE_NETPOLL: u64 = bindings::netdev_priv_flags_IFF_DISABLE_NETPOLL; + /// Device used as macvlan port. + pub const IFF_MACVLAN_PORT: u64 = bindings::netdev_priv_flags_IFF_MACVLAN_PORT; + /// Device used as bridge port. + pub const IFF_BRIDGE_PORT: u64 = bindings::netdev_priv_flags_IFF_BRIDGE_PORT; + /// Device used as Open vSwitch datapath port. + pub const IFF_OVS_DATAPATH: u64 = bindings::netdev_priv_flags_IFF_OVS_DATAPATH; + /// The interface supports sharing skbs on transmit. + pub const IFF_TX_SKB_SHARING: u64 = bindings::netdev_priv_flags_IFF_TX_SKB_SHARING; + /// Supports unicast filtering. + pub const IFF_UNICAST_FLT: u64 = bindings::netdev_priv_flags_IFF_UNICAST_FLT; + /// Device used as team port. + pub const IFF_TEAM_PORT: u64 = bindings::netdev_priv_flags_IFF_TEAM_PORT; + /// Device supports sending custom FCS. + pub const IFF_SUPP_NOFCS: u64 = bindings::netdev_priv_flags_IFF_SUPP_NOFCS; + /// Device supports hardware address change when it's running. + pub const IFF_LIVE_ADDR_CHANGE: u64 = bindings::netdev_priv_flags_IFF_LIVE_ADDR_CHANGE; + /// Macvlan device. + pub const IFF_MACVLAN: u64 = bindings::netdev_priv_flags_IFF_MACVLAN; + /// IFF_XMIT_DST_RELEASE not taking into account underlying stacked devices. + pub const IFF_XMIT_DST_RELEASE_PERM: u64 = + bindings::netdev_priv_flags_IFF_XMIT_DST_RELEASE_PERM; + /// L3 master device. + pub const IFF_L3MDEV_MASTER: u64 = bindings::netdev_priv_flags_IFF_L3MDEV_MASTER; + /// Device can run without qdisc attached. + pub const IFF_NO_QUEUE: u64 = bindings::netdev_priv_flags_IFF_NO_QUEUE; + /// Device is a Open vSwitch master. + pub const IFF_OPENVSWITCH: u64 = bindings::netdev_priv_flags_IFF_OPENVSWITCH; + /// Device is enslaved to an L3 master. + pub const IFF_L3MDEV_SLAVE: u64 = bindings::netdev_priv_flags_IFF_L3MDEV_SLAVE; + /// Team device. + pub const IFF_TEAM: u64 = bindings::netdev_priv_flags_IFF_TEAM; + /// Device has had Rx Flow indirection table configured. + pub const IFF_RXFH_CONFIGURED: u64 = bindings::netdev_priv_flags_IFF_RXFH_CONFIGURED; + /// The headroom value is controlled by an external entity. + pub const IFF_PHONY_HEADROOM: u64 = bindings::netdev_priv_flags_IFF_PHONY_HEADROOM; + /// MACsec device. + pub const IFF_MACSEC: u64 = bindings::netdev_priv_flags_IFF_MACSEC; + /// Device doesn't support the rx_handler hook. + pub const IFF_NO_RX_HANDLER: u64 = bindings::netdev_priv_flags_IFF_NO_RX_HANDLER; + /// Failover master device. + pub const IFF_FAILOVER: u64 = bindings::netdev_priv_flags_IFF_FAILOVER; + /// Lower device of a failover master device. + pub const IFF_FAILOVER_SLAVE: u64 = bindings::netdev_priv_flags_IFF_FAILOVER_SLAVE; + /// Only invokes the rx handler of L3 master device. + pub const IFF_L3MDEV_RX_HANDLER: u64 = bindings::netdev_priv_flags_IFF_L3MDEV_RX_HANDLER; + /// Prevents ipv6 addrconf. + pub const IFF_NO_ADDRCONF: u64 = bindings::netdev_priv_flags_IFF_NO_ADDRCONF; + /// Capable of xmitting frames with skb_headlen(skb) == 0. + pub const IFF_TX_SKB_NO_LINEAR: u64 = bindings::netdev_priv_flags_IFF_TX_SKB_NO_LINEAR; + /// Supports setting carrier via IFLA_PROTO_DOWN. + pub const IFF_CHANGE_PROTO_DOWN: u64 = bindings::netdev_priv_flags_IFF_CHANGE_PROTO_DOWN; +} + /// Corresponds to the kernel's `struct net_device`. /// /// # Invariants @@ -49,6 +156,82 @@ pub fn drv_priv_data(&self) -> D::Borrowed<'_> { )) } } + + /// Sets the name of a device. + pub fn set_name(&mut self, name: &CStr) -> Result { + // SAFETY: The type invariants guarantee that `self.ptr` is valid. + unsafe { + if name.len() > (*self.ptr).name.len() { + return Err(code::EINVAL); + } + (*self.ptr) + .name + .as_mut_ptr() + .copy_from_nonoverlapping(name.as_char_ptr(), name.len()); + } + Ok(()) + } + + /// Sets carrier. + pub fn netif_carrier_on(&mut self) { + // SAFETY: The type invariants guarantee that `self.ptr` is valid. + unsafe { bindings::netif_carrier_on(self.ptr) } + } + + /// Clears carrier. + pub fn netif_carrier_off(&mut self) { + // SAFETY: The type invariants guarantee that `self.ptr` is valid. + unsafe { bindings::netif_carrier_off(self.ptr) } + } + + /// Sets the max mtu of the device. + pub fn set_max_mtu(&mut self, max_mtu: u32) { + // SAFETY: The type invariants guarantee that `self.ptr` is valid. + unsafe { + (*self.ptr).max_mtu = max_mtu; + } + } + + /// Sets the minimum mtu of the device. + pub fn set_min_mtu(&mut self, min_mtu: u32) { + // SAFETY: The type invariants guarantee that `self.ptr` is valid. + unsafe { + (*self.ptr).min_mtu = min_mtu; + } + } + + /// Returns the flags of the device. + pub fn get_flags(&self) -> u32 { + // SAFETY: The type invariants guarantee that `self.ptr` is valid. + unsafe { (*self.ptr).flags } + } + + /// Sets the flags of the device. + pub fn set_flags(&mut self, flags: u32) { + // SAFETY: The type invariants guarantee that `self.ptr` is valid. + unsafe { + (*self.ptr).flags = flags; + } + } + + /// Returns the priv_flags of the device. + pub fn get_priv_flags(&self) -> u64 { + // SAFETY: The type invariants guarantee that `self.ptr` is valid. + unsafe { (*self.ptr).priv_flags } + } + + /// Sets the priv_flags of the device. + pub fn set_priv_flags(&mut self, flags: u64) { + // SAFETY: The type invariants guarantee that `self.ptr` is valid. + unsafe { (*self.ptr).priv_flags = flags } + } + + /// Generate a random Ethernet address (MAC) to be used by a net device + /// and set addr_assign_type. + pub fn set_random_eth_hw_addr(&mut self) { + // SAFETY: The type invariants guarantee that `self.ptr` is valid. + unsafe { bindings::eth_hw_addr_random(self.ptr) } + } } // SAFETY: `Device` is just a wrapper for the kernel`s `struct net_device`, which can be used From patchwork Mon Jul 10 07:37:02 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: FUJITA Tomonori X-Patchwork-Id: 13306375 X-Patchwork-Delegate: kuba@kernel.org Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 53B99C8CC for ; Mon, 10 Jul 2023 07:39:12 +0000 (UTC) Received: from mail-pf1-x435.google.com (mail-pf1-x435.google.com [IPv6:2607:f8b0:4864:20::435]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5316AE77; Mon, 10 Jul 2023 00:38:57 -0700 (PDT) Received: by mail-pf1-x435.google.com with SMTP id d2e1a72fcca58-66d6a9851f3so612120b3a.0; Mon, 10 Jul 2023 00:38:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1688974736; x=1691566736; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=cvWjzWyFKI2pPo1p6eQdrq9RKByhHwpQNo4P07gJwcY=; b=jVQjD4lw3c7pfmKN6CHCW+s8gwwWrPswqaPE1kUojRGMFWS7Mv2Kq0eBrDgFfkSoaz sDaOP8iVtzYJDIm6TM+v3Lz3aaCobDNPsmrWonQZPp4W2F3Pv6NHPgji9Z/2zVXiSqug JFJB/yTeMMU4gPaKTh75E8otIAm+0ccO38Dj753kyJK4Pn/yg75YAhtdr3B137PzIwhJ aSJv3mKBM0wqQUhlosgqTEVlWVkBY8lHobz47LZTUxjq80oudrMS4jYKEjzfo/w0N7Ma 1Fds8r5YQdvyJvT9eOtQl7WteBfivpVM+R5y4cIg6gNrSt/crMRkdbXfnvTU2MV6gotF mw9A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1688974736; x=1691566736; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=cvWjzWyFKI2pPo1p6eQdrq9RKByhHwpQNo4P07gJwcY=; b=ePT2w/EdfdNZB9LvvY7HvBhNEBN1YczWdSt0e0dPl8EYUutdD+gTLjt2BRKV0XRP0V /v17vH97qds9ZsxFMwDH39Ly5qmzDC6CcIBGLdA0xxdX9cKCsnUIegp6Uh8RqFJMYKss qzvzQoqmyUmHqaJO6rP5OsyXt+uHquaPCA9D1n4Qa658hqiZKXziLMuAe4N9BATUcePY wlP4X9A59y1QGhzYsaN+lUTnGs94M2bgTm6D0xBosynT/1vBY7f6ST/yPKpe3KUc5YW1 P8aJCulgTRQORhmCMsKdB3XvcjXJOVht+uxhheE7JRs5tKU9auNw98PVIDMXFmW8PW0i wt4w== X-Gm-Message-State: ABy/qLaZEaHrXlmDiCkw8hydUskcGsW80cKGX/SGjIsds3yfmgIuwqg9 B8g4YKpx1rugdWgvZPLmSBYMm+rLLC3EGpHs X-Google-Smtp-Source: APBJJlEuaaOWrQYx5CzCg2H6QF2pidZTjjA5+vccsiHPwjAcsk5iWIlAMpUOnjL1fJkOLkdJRr08Dg== X-Received: by 2002:a05:6a00:3387:b0:675:8627:a291 with SMTP id cm7-20020a056a00338700b006758627a291mr12242941pfb.3.1688974735917; Mon, 10 Jul 2023 00:38:55 -0700 (PDT) Received: from ip-172-30-47-114.us-west-2.compute.internal (ec2-54-68-170-188.us-west-2.compute.amazonaws.com. [54.68.170.188]) by smtp.gmail.com with ESMTPSA id r20-20020a62e414000000b0063f2a5a59d1sm6514483pfh.190.2023.07.10.00.38.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Jul 2023 00:38:55 -0700 (PDT) From: FUJITA Tomonori To: rust-for-linux@vger.kernel.org, netdev@vger.kernel.org Cc: kuba@kernel.org, andrew@lunn.ch, aliceryhl@google.com, miguel.ojeda.sandonis@gmail.com, benno.lossin@proton.me Subject: [PATCH v2 4/5] samples: rust: add dummy network driver Date: Mon, 10 Jul 2023 16:37:02 +0900 Message-Id: <20230710073703.147351-5-fujita.tomonori@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230710073703.147351-1-fujita.tomonori@gmail.com> References: <20230710073703.147351-1-fujita.tomonori@gmail.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM, RCVD_IN_DNSWL_BLOCKED,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net This is a simpler version of drivers/net/dummy.c. This demonstrates the usage of abstractions for network device drivers. Allows allocator_api feature for Box::try_new(); Signed-off-by: FUJITA Tomonori --- samples/rust/Kconfig | 13 ++++++ samples/rust/Makefile | 1 + samples/rust/rust_net_dummy.rs | 75 ++++++++++++++++++++++++++++++++++ scripts/Makefile.build | 2 +- 4 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 samples/rust/rust_net_dummy.rs diff --git a/samples/rust/Kconfig b/samples/rust/Kconfig index b0f74a81c8f9..02bda7bdf722 100644 --- a/samples/rust/Kconfig +++ b/samples/rust/Kconfig @@ -30,6 +30,19 @@ config SAMPLE_RUST_PRINT If unsure, say N. +config SAMPLE_RUST_NET_DUMMY + tristate "Dummy network driver" + depends on NET + help + This is the simpler version of drivers/net/dummy.c. + No intention to replace it. This provides educational information + for Rust abstractions for network device drivers. + + To compile this as a module, choose M here: + the module will be called rust_net_dummy. + + If unsure, say N. + config SAMPLE_RUST_HOSTPROGS bool "Host programs" help diff --git a/samples/rust/Makefile b/samples/rust/Makefile index 03086dabbea4..440dee2971ba 100644 --- a/samples/rust/Makefile +++ b/samples/rust/Makefile @@ -2,5 +2,6 @@ obj-$(CONFIG_SAMPLE_RUST_MINIMAL) += rust_minimal.o obj-$(CONFIG_SAMPLE_RUST_PRINT) += rust_print.o +obj-$(CONFIG_SAMPLE_RUST_NET_DUMMY) += rust_net_dummy.o subdir-$(CONFIG_SAMPLE_RUST_HOSTPROGS) += hostprogs diff --git a/samples/rust/rust_net_dummy.rs b/samples/rust/rust_net_dummy.rs new file mode 100644 index 000000000000..78f8f3321fd2 --- /dev/null +++ b/samples/rust/rust_net_dummy.rs @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: GPL-2.0 +// +//! Rust dummy netdev. + +//use kernel::types::ForeignOwnable; +use kernel::{ + c_str, + net::dev::{ + flags, priv_flags, Device, DeviceOperations, EtherOperations, EthtoolTsInfo, Registration, + SkBuff, TxCode, + }, + prelude::*, +}; + +module! { + type: DummyNetdev, + name: "rust_net_dummy", + author: "Rust for Linux Contributors", + description: "Rust dummy netdev", + license: "GPL v2", +} + +#[vtable] +impl DeviceOperations for Box { + fn init(dev: Device>) -> Result { + // how to access to the driver private data. + let _ = dev.drv_priv_data(); + Ok(()) + } + + fn start_xmit(_dev: Device>, mut skb: SkBuff) -> TxCode { + skb.tx_timestamp(); + skb.consume(); + TxCode::Ok + } +} + +/// For device driver specific information. +struct DriverData {} + +struct DummyNetdev { + _r: Registration>, +} + +#[vtable] +impl EtherOperations for Box { + fn get_ts_info(dev: Device>, mut info: EthtoolTsInfo) -> Result { + EthtoolTsInfo::ethtool_op_get_ts_info(&dev, &mut info) + } +} + +impl kernel::Module for DummyNetdev { + fn init(_module: &'static ThisModule) -> Result { + let data = Box::try_new(DriverData {})?; + let mut r = Registration::>::try_new_ether(1, 1, data)?; + r.set_ether_operations::>()?; + + let netdev = r.dev_get(); + netdev.set_name(c_str!("dummy%d"))?; + + netdev.set_flags(netdev.get_flags() | flags::IFF_NOARP & !flags::IFF_MULTICAST); + netdev.set_priv_flags( + netdev.get_priv_flags() | priv_flags::IFF_LIVE_ADDR_CHANGE | priv_flags::IFF_NO_QUEUE, + ); + netdev.set_random_eth_hw_addr(); + netdev.set_min_mtu(0); + netdev.set_max_mtu(0); + + r.register()?; + + // TODO: Replaces pr_info with the wrapper of netdev_info(). + pr_info!("Hello Rust dummy netdev!"); + Ok(DummyNetdev { _r: r }) + } +} diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 78175231c969..1404967e908e 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -277,7 +277,7 @@ $(obj)/%.lst: $(src)/%.c FORCE # Compile Rust sources (.rs) # --------------------------------------------------------------------------- -rust_allowed_features := new_uninit +rust_allowed_features := allocator_api,new_uninit rust_common_cmd = \ RUST_MODFILE=$(modfile) $(RUSTC_OR_CLIPPY) $(rust_flags) \ From patchwork Mon Jul 10 07:37:03 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: FUJITA Tomonori X-Patchwork-Id: 13306376 X-Patchwork-Delegate: kuba@kernel.org Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5A29DD2EC for ; Mon, 10 Jul 2023 07:39:13 +0000 (UTC) Received: from mail-pf1-x436.google.com (mail-pf1-x436.google.com [IPv6:2607:f8b0:4864:20::436]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0CD5EE7C; Mon, 10 Jul 2023 00:38:59 -0700 (PDT) Received: by mail-pf1-x436.google.com with SMTP id d2e1a72fcca58-66d6a9851f3so612130b3a.0; Mon, 10 Jul 2023 00:38:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1688974738; x=1691566738; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=BsQMEaCs3k1dlBLgyXTPYSUjzDqURbd4pdB1RY6xh1k=; b=S5gJ4BxbDkGfukmtMvb5QI2fe3sotCh3JApFSWTTEeD88C3aNxv7GEvNUVgWpTlDrp XisGArgHa7xFZqvMB6vmTDRqXKVARRsXOPpuqM85WlmN9JVQWgHtUM/E2RaHTaGrshvb wvQ8+bKVNFw1DfByqGQWUZqI8kaPNpnYXBV764Ode43smk40hwsDNpYaEDf1cDlYHaeI hs3FNzxY7wi4M0VAmcPdA8dNiGLsInxamCtG7LV/L4E5iezkiq2uOafxL4tkkkiciI8I fvra7iOSobp08grcVah+YZyxdr72hORagieZWHVeVp4lC2y9GMF2FuBPn3+/+eGRdI3V 5dLA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1688974738; x=1691566738; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=BsQMEaCs3k1dlBLgyXTPYSUjzDqURbd4pdB1RY6xh1k=; b=Xgpr/l0cWqC4H8lN9VreV8LkECfl0/LVuccTiW+BbwQDdRI/P/MzI8bwv1anux5HV+ bHtX6eiWwUDBHxR4Up7pdxSQ5QskqRJwPLya5JDrTzrfkBnZGuxL8y/R3mvadvzHV6ey liZIY3xR/sUi1tctHfGbhKACF/dE3i1zX4AQWo6Ns2QtPqdPfi4gq0JMi63aSPyHEaPI y5+tLkotmt0qwYrG2iecryw+zjedvG+c0j0ZahHsWzjy792qCoZxvAaY/RuY7cKpzJO7 +bqtelB+CgL+ZD6zc3zKyx81mK82P7/UYbUfykDaAmiKhhKLvOcfXUYQfvbOuFoA3h9C zgLQ== X-Gm-Message-State: ABy/qLYw9CsuZ5D5XZYnzkBU1auEHSvkq1t8P0g1DYC2Jqqe172wzrde 7DNgcNNVMh5J2SnY5T3wH6gpR0agoQTcVTc4 X-Google-Smtp-Source: APBJJlGFbyw59LLFw59QxK58EARZfGw/4tLQBrhhDAU5HtqVHq5PFCZz8bdEGwLeJPeNVoQmnSHJvw== X-Received: by 2002:a05:6a20:4424:b0:111:a0e5:d2b7 with SMTP id ce36-20020a056a20442400b00111a0e5d2b7mr17505660pzb.4.1688974737589; Mon, 10 Jul 2023 00:38:57 -0700 (PDT) Received: from ip-172-30-47-114.us-west-2.compute.internal (ec2-54-68-170-188.us-west-2.compute.amazonaws.com. [54.68.170.188]) by smtp.gmail.com with ESMTPSA id r20-20020a62e414000000b0063f2a5a59d1sm6514483pfh.190.2023.07.10.00.38.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Jul 2023 00:38:56 -0700 (PDT) From: FUJITA Tomonori To: rust-for-linux@vger.kernel.org, netdev@vger.kernel.org Cc: kuba@kernel.org, andrew@lunn.ch, aliceryhl@google.com, miguel.ojeda.sandonis@gmail.com, benno.lossin@proton.me Subject: [PATCH v2 5/5] MAINTAINERS: add Rust network abstractions files to the NETWORKING DRIVERS entry Date: Mon, 10 Jul 2023 16:37:03 +0900 Message-Id: <20230710073703.147351-6-fujita.tomonori@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230710073703.147351-1-fujita.tomonori@gmail.com> References: <20230710073703.147351-1-fujita.tomonori@gmail.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM, RCVD_IN_DNSWL_BLOCKED,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net The files are placed at rust/kernel/ directory for now but the files are likely to be moved to net/ directory if things go well. Signed-off-by: FUJITA Tomonori --- MAINTAINERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 250518fc70ff..66b8e43b05a2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14581,6 +14581,8 @@ F: include/linux/inetdevice.h F: include/linux/netdevice.h F: include/uapi/linux/if_* F: include/uapi/linux/netdevice.h +F: rust/kernel/net.rs +F: rust/kernel/net/ NETWORKING DRIVERS (WIRELESS) M: Kalle Valo