Skip to content

Commit

Permalink
Add rust net_device wrappers
Browse files Browse the repository at this point in the history
Signed-off-by: Finn Behrens <me@kloenk.de>
  • Loading branch information
kloenk committed Jul 12, 2021
1 parent e97ba67 commit efda5a1
Show file tree
Hide file tree
Showing 16 changed files with 2,283 additions and 110 deletions.
31 changes: 31 additions & 0 deletions rust/helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <linux/security.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/rtnetlink.h>

void rust_helper_BUG(void)
{
Expand Down Expand Up @@ -212,6 +215,34 @@ int rust_helper_security_binder_transfer_file(struct task_struct *from,
}
EXPORT_SYMBOL_GPL(rust_helper_security_binder_transfer_file);

void *rust_helper_netdev_priv(struct net_device *dev)
{
return netdev_priv(dev);
}
EXPORT_SYMBOL_GPL(rust_helper_netdev_priv);

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

int rust_helper_net_device_set_new_lstats(struct net_device *dev)
{
dev->lstats = netdev_alloc_pcpu_stats(struct pcpu_lstats);
if (!dev->lstats)
return -ENOMEM;

return 0;
}
EXPORT_SYMBOL_GPL(rust_helper_net_device_set_new_lstats);

void rust_helper_dev_lstats_add(struct net_device *dev, unsigned int len)
{
dev_lstats_add(dev, len);
}
EXPORT_SYMBOL_GPL(rust_helper_dev_lstats_add);

/* We use bindgen's --size_t-is-usize option to bind the C size_t type
* as the Rust usize type, so we can use it in contexts where Rust
* expects a usize like slice (array) indices. usize is defined to be
Expand Down
8 changes: 8 additions & 0 deletions rust/kernel/bindings_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,15 @@
#include <linux/platform_device.h>
#include <linux/of_platform.h>
#include <linux/security.h>
#include <linux/netdevice.h>
#include <linux/ethtool.h>
#include <linux/etherdevice.h>
#include <linux/netdev_features.h>
#include <linux/rtnetlink.h>
#include <net/rtnetlink.h>

// `bindgen` gets confused at certain things
const gfp_t BINDINGS_GFP_KERNEL = GFP_KERNEL;
const gfp_t BINDINGS___GFP_ZERO = __GFP_ZERO;

const int BINDINGS_NLA_HDRLEN = NLA_HDRLEN;
5 changes: 4 additions & 1 deletion rust/kernel/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,9 @@ impl Error {
/// Math result not representable.
pub const ERANGE: Self = Error(-(bindings::ERANGE as i32));

/// Cannot assign requested address
pub const EADDRNOTAVAIL: Self = Error(-(bindings::EADDRNOTAVAIL as i32));

/// Restart the system call.
pub const ERESTARTSYS: Self = Error(-(bindings::ERESTARTSYS as i32));

Expand Down Expand Up @@ -276,7 +279,7 @@ where
#[macro_export]
macro_rules! from_kernel_result {
($($tt:tt)*) => {{
$crate::error::from_kernel_result_helper((|| {
$crate::from_kernel_result_helper((|| {
$($tt)*
})())
}};
Expand Down
13 changes: 11 additions & 2 deletions rust/kernel/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
const_raw_ptr_deref,
const_unreachable_unchecked,
receiver_trait,
try_reserve
try_reserve,
doc_cfg
)]

// Ensure conditional compilation based on the kernel configuration works;
Expand All @@ -44,6 +45,11 @@ mod error;
pub mod file;
pub mod file_operations;
pub mod miscdev;

#[cfg(any(CONFIG_NET, doc))]
#[doc(cfg(CONFIG_NET))]
pub mod net;

pub mod pages;
pub mod security;
pub mod str;
Expand Down Expand Up @@ -77,8 +83,11 @@ pub mod user_ptr;
#[doc(hidden)]
pub use build_error::build_error;

#[doc(hidden)]
pub use crate::error::from_kernel_result_helper;

pub use crate::error::{Error, Result};
pub use crate::types::{Mode, ScopeGuard};
pub use crate::types::{Mode, SavedAsPointer, SavedAsPointerMut, ScopeGuard};

/// Page size defined in terms of the `PAGE_SHIFT` macro from C.
///
Expand Down
277 changes: 277 additions & 0 deletions rust/kernel/net/device/flags.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,277 @@
use crate::{bindings, Error};
use core::convert::{From, TryFrom};
use core::ops::{Add, AddAssign, Sub, SubAssign};

/// Holds multiple flags to give to an interface via [`super::NetDevice::add_flag`].
#[repr(transparent)]
#[derive(Debug, Clone, Copy)]
pub struct Features(u64);

impl Features {
/// Create new Flag with value `0`.
#[inline]
pub const fn empty() -> Self {
Self(0)
}

/// Add flag to Self.
#[inline]
pub fn insert(&mut self, flag: u64) {
self.0 |= flag;
}

/// Remove the given flag from Self.
#[inline]
pub fn remove(&mut self, flag: u64) {
self.0 &= !(flag);
}
}

impl Add for Features {
type Output = Self;

#[inline]
#[allow(clippy::suspicious_arithmetic_impl)]
fn add(self, rhs: Self) -> Self::Output {
Self(self.0 | rhs.0)
}
}

impl Add<u64> for Features {
type Output = Self;

#[inline]
#[allow(clippy::suspicious_arithmetic_impl)]
fn add(self, rhs: u64) -> Self::Output {
Self(self.0 | rhs)
}
}

impl Sub for Features {
type Output = Self;

#[inline]
#[allow(clippy::suspicious_arithmetic_impl)]
fn sub(self, rhs: Self) -> Self::Output {
Self(self.0 & !rhs.0)
}
}

impl Sub<u64> for Features {
type Output = Self;

#[inline]
#[allow(clippy::suspicious_arithmetic_impl)]
fn sub(self, rhs: u64) -> Self::Output {
Self(self.0 & !rhs)
}
}

impl AddAssign for Features {
#[inline]
#[allow(clippy::suspicious_op_assign_impl)]
fn add_assign(&mut self, rhs: Self) {
self.0 |= rhs.0
}
}

impl AddAssign<u64> for Features {
#[inline]
#[allow(clippy::suspicious_op_assign_impl)]
fn add_assign(&mut self, rhs: u64) {
self.0 |= rhs
}
}

impl SubAssign for Features {
#[inline]
#[allow(clippy::suspicious_op_assign_impl)]
fn sub_assign(&mut self, rhs: Self) {
self.0 &= !rhs.0
}
}

impl SubAssign<u64> for Features {
#[inline]
#[allow(clippy::suspicious_op_assign_impl)]
fn sub_assign(&mut self, rhs: u64) {
self.0 &= !rhs
}
}

impl TryFrom<u64> for Features {
type Error = Error;

#[inline]
fn try_from(flags: u64) -> Result<Self, Self::Error> {
Ok(Self(flags))
}
}

impl From<Features> for u64 {
#[inline]
fn from(flag: Features) -> Self {
flag.0
}
}

macro_rules! _netif_f {
($name:ident, $binding:ident) => {
#[doc = concat!("[`Features`] flag for `", stringify!($binding), "`")]
pub const $name: Features = Features(1u64 << $crate::bindings::$binding);
};
}

macro_rules! _netif_f_sum {
($name:ident, $($f:ident),+) => {
#[doc = concat!("[`Features`] flag for `NETIF_F_", stringify!($name), "`")]
pub const $name: Features = Features($(Features::$f.0)|*);
};
}

impl Features {
_netif_f!(SG, NETIF_F_SG_BIT);
_netif_f!(FRAGLIST, NETIF_F_FRAGLIST_BIT);
_netif_f!(TSO, NETIF_F_TSO_BIT);
_netif_f!(TSO6, NETIF_F_TSO6_BIT);
_netif_f!(TSO_ECN, NETIF_F_TSO_ECN_BIT);
_netif_f!(TSO_MANGLEID, NETIF_F_TSO_MANGLEID_BIT);
_netif_f!(GSO_SCTP, NETIF_F_GSO_SCTP_BIT);
_netif_f!(GSO_UDP_L4, NETIF_F_GSO_UDP_L4_BIT);
_netif_f!(GSO_FRAGLIST, NETIF_F_GSO_FRAGLIST_BIT);
_netif_f!(HW_CSUM, NETIF_F_HW_CSUM_BIT);
_netif_f!(HIGHDMA, NETIF_F_HIGHDMA_BIT);
_netif_f!(LLTX, NETIF_F_LLTX_BIT);
_netif_f!(GSO_GRE, NETIF_F_GSO_GRE_BIT);
_netif_f!(GSO_GRE_CSUM, NETIF_F_GSO_GRE_CSUM_BIT);
_netif_f!(GSO_IPXIP4, NETIF_F_GSO_IPXIP4_BIT);
_netif_f!(GSO_IPXIP6, NETIF_F_GSO_IPXIP6_BIT);
_netif_f!(GSO_UDP_TUNNEL, NETIF_F_GSO_UDP_TUNNEL_BIT);
_netif_f!(GSO_UDP_TUNNEL_CSUM, NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);

_netif_f_sum!(ALL_TSO, TSO, TSO6, TSO_ECN, TSO_MANGLEID);
_netif_f_sum!(GSO_SOFTWARE, ALL_TSO, GSO_SCTP, GSO_UDP_L4, GSO_FRAGLIST);
_netif_f_sum!(
GSO_ENCAP_ALL,
GSO_GRE,
GSO_GRE_CSUM,
GSO_IPXIP4,
GSO_IPXIP6,
GSO_UDP_TUNNEL,
GSO_UDP_TUNNEL_CSUM
);
}

/// Iff flags
#[repr(u32)]
#[allow(non_camel_case_types)]
pub enum Flag {
/// UP
UP = bindings::net_device_flags_IFF_UP,
/// BROADCAST
BROADCAST = bindings::net_device_flags_IFF_BROADCAST,
/// DEBUG
DEBUG = bindings::net_device_flags_IFF_DEBUG,
/// LOOPBACK
LOOPBACK = bindings::net_device_flags_IFF_LOOPBACK,
/// POINTOPOINT
POINTOPOINT = bindings::net_device_flags_IFF_POINTOPOINT,
/// NOTRAILERS
NOTRAILERS = bindings::net_device_flags_IFF_NOTRAILERS,
/// RUNNING
RUNNING = bindings::net_device_flags_IFF_RUNNING,
/// NOARP
NOARP = bindings::net_device_flags_IFF_NOARP,
/// PROMISC
PROMISC = bindings::net_device_flags_IFF_PROMISC,
/// ALLMULTI
ALLMULTI = bindings::net_device_flags_IFF_ALLMULTI,
/// MASTER
MASTER = bindings::net_device_flags_IFF_MASTER,
/// SLAVE
SLAVE = bindings::net_device_flags_IFF_SLAVE,
/// MULTICAST
MULTICAST = bindings::net_device_flags_IFF_MULTICAST,
/// PORTSEL
PORTSEL = bindings::net_device_flags_IFF_PORTSEL,
/// AUTOMEDIA
AUTOMEDIA = bindings::net_device_flags_IFF_AUTOMEDIA,
/// DYNAMIC
DYNAMIC = bindings::net_device_flags_IFF_DYNAMIC,

// #if __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO // TODO: is this needed?
/// LOWER
LOWER = bindings::net_device_flags_IFF_LOWER_UP,
/// DORMANT
DORMANT = bindings::net_device_flags_IFF_DORMANT,
/// ECHO
ECHO = bindings::net_device_flags_IFF_ECHO,
}

/// Iff private flags
#[repr(i32)]
#[allow(non_camel_case_types)]
pub enum PrivFlag {
/// 802.1Q VLAN device.
IFF_802_1Q_VLAN = bindings::netdev_priv_flags_IFF_802_1Q_VLAN, /* TODO: find a good name without leading 8 */
/// Ethernet bridging device.
EBRIDGE = bindings::netdev_priv_flags_IFF_EBRIDGE,
/// Bonding master or slave.
BONDING = bindings::netdev_priv_flags_IFF_BONDING,
/// ISATAP interface (RFC4214).
ISATAP = bindings::netdev_priv_flags_IFF_ISATAP,
/// WAN HDLC device.
WAN_HDLC = bindings::netdev_priv_flags_IFF_WAN_HDLC,
/// dev_hard_start_xmit() is allowed to release skb->dst
XMIT_DST_RELEASE = bindings::netdev_priv_flags_IFF_XMIT_DST_RELEASE,
/// Disallow bridging this ether dev.
DONT_BRIDGE = bindings::netdev_priv_flags_IFF_DONT_BRIDGE,
/// Disable netpoll at run-time.
DISABLE_NETPOLL = bindings::netdev_priv_flags_IFF_DISABLE_NETPOLL,
/// Device used as macvlan port.
MACVLAN_PORT = bindings::netdev_priv_flags_IFF_MACVLAN_PORT,
/// Device used as bridge port.
BRIDGE_PORT = bindings::netdev_priv_flags_IFF_BRIDGE_PORT,
/// Device used as Open vSwitch datapath port.
OVS_DATAPATH = bindings::netdev_priv_flags_IFF_OVS_DATAPATH,
/// The interface supports sharing skbs on transmit.
TX_SKB_SHARING = bindings::netdev_priv_flags_IFF_TX_SKB_SHARING,
/// Supports unicast filtering.
UNICAST_FLT = bindings::netdev_priv_flags_IFF_UNICAST_FLT,
/// Device used as team port.
TEAM_PORT = bindings::netdev_priv_flags_IFF_TEAM_PORT,
/// Device supports sending custom FCS.
SUPP_NOFCS = bindings::netdev_priv_flags_IFF_SUPP_NOFCS,
/// Device supports hardware address change when it's running.
LIVE_ADDR_CHANGE = bindings::netdev_priv_flags_IFF_LIVE_ADDR_CHANGE,
/// Macvlan device.
MACVLAN = bindings::netdev_priv_flags_IFF_MACVLAN,
/// IFF_XMIT_DST_RELEASE not taking into account underlying stacked devices.
XMIT_DST_RELEASE_PERM = bindings::netdev_priv_flags_IFF_XMIT_DST_RELEASE_PERM,
/// Device is an L3 master device.
L3MDEV_MASTER = bindings::netdev_priv_flags_IFF_L3MDEV_MASTER,
/// Device can run without qdisc attached.
NO_QUEUE = bindings::netdev_priv_flags_IFF_NO_QUEUE,
/// Device is a Open vSwitch master.
OPENVSWITCH = bindings::netdev_priv_flags_IFF_OPENVSWITCH,
/// Device is enslaved to an L3 master device.
L3MDEV_SLAVE = bindings::netdev_priv_flags_IFF_L3MDEV_SLAVE,
/// Device is a team device.
TEAM = bindings::netdev_priv_flags_IFF_TEAM,
/// Device has had Rx Flow indirection table configured.
RXFH_CONFIGURED = bindings::netdev_priv_flags_IFF_RXFH_CONFIGURED,
/// The headroom value is controlled by an external entity (i.e. the master device for bridged veth).
PHONY_HEADROOM = bindings::netdev_priv_flags_IFF_PHONY_HEADROOM,
/// Device is a MACsec device.
MACSEC = bindings::netdev_priv_flags_IFF_MACSEC,
/// Device doesn't support the rx_handler hook.
NO_RX_HANDLER = bindings::netdev_priv_flags_IFF_NO_RX_HANDLER,
/// Device is a failover master device.
FAILOVER = bindings::netdev_priv_flags_IFF_FAILOVER,
/// Device is lower dev of a failover master device.
FAILOVER_SLAVE = bindings::netdev_priv_flags_IFF_FAILOVER_SLAVE,
/// Only invoke the rx handler of L3 master device.
L3MDEV_RX_HANDLER = bindings::netdev_priv_flags_IFF_L3MDEV_RX_HANDLER,
/// Rename is allowed while device is up and running.
LIVE_RENAME_OK = bindings::netdev_priv_flags_IFF_LIVE_RENAME_OK,
}

0 comments on commit efda5a1

Please sign in to comment.