Skip to content

Commit efda5a1

Browse files
committed
Add rust net_device wrappers
Signed-off-by: Finn Behrens <[email protected]>
1 parent e97ba67 commit efda5a1

File tree

16 files changed

+2283
-110
lines changed

16 files changed

+2283
-110
lines changed

rust/helpers.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
#include <linux/mutex.h>
1212
#include <linux/platform_device.h>
1313
#include <linux/security.h>
14+
#include <linux/netdevice.h>
15+
#include <linux/etherdevice.h>
16+
#include <linux/rtnetlink.h>
1417

1518
void rust_helper_BUG(void)
1619
{
@@ -212,6 +215,34 @@ int rust_helper_security_binder_transfer_file(struct task_struct *from,
212215
}
213216
EXPORT_SYMBOL_GPL(rust_helper_security_binder_transfer_file);
214217

218+
void *rust_helper_netdev_priv(struct net_device *dev)
219+
{
220+
return netdev_priv(dev);
221+
}
222+
EXPORT_SYMBOL_GPL(rust_helper_netdev_priv);
223+
224+
void rust_helper_eth_hw_addr_random(struct net_device *dev)
225+
{
226+
eth_hw_addr_random(dev);
227+
}
228+
EXPORT_SYMBOL_GPL(rust_helper_eth_hw_addr_random);
229+
230+
int rust_helper_net_device_set_new_lstats(struct net_device *dev)
231+
{
232+
dev->lstats = netdev_alloc_pcpu_stats(struct pcpu_lstats);
233+
if (!dev->lstats)
234+
return -ENOMEM;
235+
236+
return 0;
237+
}
238+
EXPORT_SYMBOL_GPL(rust_helper_net_device_set_new_lstats);
239+
240+
void rust_helper_dev_lstats_add(struct net_device *dev, unsigned int len)
241+
{
242+
dev_lstats_add(dev, len);
243+
}
244+
EXPORT_SYMBOL_GPL(rust_helper_dev_lstats_add);
245+
215246
/* We use bindgen's --size_t-is-usize option to bind the C size_t type
216247
* as the Rust usize type, so we can use it in contexts where Rust
217248
* expects a usize like slice (array) indices. usize is defined to be

rust/kernel/bindings_helper.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,15 @@
1818
#include <linux/platform_device.h>
1919
#include <linux/of_platform.h>
2020
#include <linux/security.h>
21+
#include <linux/netdevice.h>
22+
#include <linux/ethtool.h>
23+
#include <linux/etherdevice.h>
24+
#include <linux/netdev_features.h>
25+
#include <linux/rtnetlink.h>
26+
#include <net/rtnetlink.h>
2127

2228
// `bindgen` gets confused at certain things
2329
const gfp_t BINDINGS_GFP_KERNEL = GFP_KERNEL;
2430
const gfp_t BINDINGS___GFP_ZERO = __GFP_ZERO;
31+
32+
const int BINDINGS_NLA_HDRLEN = NLA_HDRLEN;

rust/kernel/error.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,9 @@ impl Error {
126126
/// Math result not representable.
127127
pub const ERANGE: Self = Error(-(bindings::ERANGE as i32));
128128

129+
/// Cannot assign requested address
130+
pub const EADDRNOTAVAIL: Self = Error(-(bindings::EADDRNOTAVAIL as i32));
131+
129132
/// Restart the system call.
130133
pub const ERESTARTSYS: Self = Error(-(bindings::ERESTARTSYS as i32));
131134

@@ -276,7 +279,7 @@ where
276279
#[macro_export]
277280
macro_rules! from_kernel_result {
278281
($($tt:tt)*) => {{
279-
$crate::error::from_kernel_result_helper((|| {
282+
$crate::from_kernel_result_helper((|| {
280283
$($tt)*
281284
})())
282285
}};

rust/kernel/lib.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
const_raw_ptr_deref,
2323
const_unreachable_unchecked,
2424
receiver_trait,
25-
try_reserve
25+
try_reserve,
26+
doc_cfg
2627
)]
2728

2829
// Ensure conditional compilation based on the kernel configuration works;
@@ -44,6 +45,11 @@ mod error;
4445
pub mod file;
4546
pub mod file_operations;
4647
pub mod miscdev;
48+
49+
#[cfg(any(CONFIG_NET, doc))]
50+
#[doc(cfg(CONFIG_NET))]
51+
pub mod net;
52+
4753
pub mod pages;
4854
pub mod security;
4955
pub mod str;
@@ -77,8 +83,11 @@ pub mod user_ptr;
7783
#[doc(hidden)]
7884
pub use build_error::build_error;
7985

86+
#[doc(hidden)]
87+
pub use crate::error::from_kernel_result_helper;
88+
8089
pub use crate::error::{Error, Result};
81-
pub use crate::types::{Mode, ScopeGuard};
90+
pub use crate::types::{Mode, SavedAsPointer, SavedAsPointerMut, ScopeGuard};
8291

8392
/// Page size defined in terms of the `PAGE_SHIFT` macro from C.
8493
///

rust/kernel/net/device/flags.rs

Lines changed: 277 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,277 @@
1+
use crate::{bindings, Error};
2+
use core::convert::{From, TryFrom};
3+
use core::ops::{Add, AddAssign, Sub, SubAssign};
4+
5+
/// Holds multiple flags to give to an interface via [`super::NetDevice::add_flag`].
6+
#[repr(transparent)]
7+
#[derive(Debug, Clone, Copy)]
8+
pub struct Features(u64);
9+
10+
impl Features {
11+
/// Create new Flag with value `0`.
12+
#[inline]
13+
pub const fn empty() -> Self {
14+
Self(0)
15+
}
16+
17+
/// Add flag to Self.
18+
#[inline]
19+
pub fn insert(&mut self, flag: u64) {
20+
self.0 |= flag;
21+
}
22+
23+
/// Remove the given flag from Self.
24+
#[inline]
25+
pub fn remove(&mut self, flag: u64) {
26+
self.0 &= !(flag);
27+
}
28+
}
29+
30+
impl Add for Features {
31+
type Output = Self;
32+
33+
#[inline]
34+
#[allow(clippy::suspicious_arithmetic_impl)]
35+
fn add(self, rhs: Self) -> Self::Output {
36+
Self(self.0 | rhs.0)
37+
}
38+
}
39+
40+
impl Add<u64> for Features {
41+
type Output = Self;
42+
43+
#[inline]
44+
#[allow(clippy::suspicious_arithmetic_impl)]
45+
fn add(self, rhs: u64) -> Self::Output {
46+
Self(self.0 | rhs)
47+
}
48+
}
49+
50+
impl Sub for Features {
51+
type Output = Self;
52+
53+
#[inline]
54+
#[allow(clippy::suspicious_arithmetic_impl)]
55+
fn sub(self, rhs: Self) -> Self::Output {
56+
Self(self.0 & !rhs.0)
57+
}
58+
}
59+
60+
impl Sub<u64> for Features {
61+
type Output = Self;
62+
63+
#[inline]
64+
#[allow(clippy::suspicious_arithmetic_impl)]
65+
fn sub(self, rhs: u64) -> Self::Output {
66+
Self(self.0 & !rhs)
67+
}
68+
}
69+
70+
impl AddAssign for Features {
71+
#[inline]
72+
#[allow(clippy::suspicious_op_assign_impl)]
73+
fn add_assign(&mut self, rhs: Self) {
74+
self.0 |= rhs.0
75+
}
76+
}
77+
78+
impl AddAssign<u64> for Features {
79+
#[inline]
80+
#[allow(clippy::suspicious_op_assign_impl)]
81+
fn add_assign(&mut self, rhs: u64) {
82+
self.0 |= rhs
83+
}
84+
}
85+
86+
impl SubAssign for Features {
87+
#[inline]
88+
#[allow(clippy::suspicious_op_assign_impl)]
89+
fn sub_assign(&mut self, rhs: Self) {
90+
self.0 &= !rhs.0
91+
}
92+
}
93+
94+
impl SubAssign<u64> for Features {
95+
#[inline]
96+
#[allow(clippy::suspicious_op_assign_impl)]
97+
fn sub_assign(&mut self, rhs: u64) {
98+
self.0 &= !rhs
99+
}
100+
}
101+
102+
impl TryFrom<u64> for Features {
103+
type Error = Error;
104+
105+
#[inline]
106+
fn try_from(flags: u64) -> Result<Self, Self::Error> {
107+
Ok(Self(flags))
108+
}
109+
}
110+
111+
impl From<Features> for u64 {
112+
#[inline]
113+
fn from(flag: Features) -> Self {
114+
flag.0
115+
}
116+
}
117+
118+
macro_rules! _netif_f {
119+
($name:ident, $binding:ident) => {
120+
#[doc = concat!("[`Features`] flag for `", stringify!($binding), "`")]
121+
pub const $name: Features = Features(1u64 << $crate::bindings::$binding);
122+
};
123+
}
124+
125+
macro_rules! _netif_f_sum {
126+
($name:ident, $($f:ident),+) => {
127+
#[doc = concat!("[`Features`] flag for `NETIF_F_", stringify!($name), "`")]
128+
pub const $name: Features = Features($(Features::$f.0)|*);
129+
};
130+
}
131+
132+
impl Features {
133+
_netif_f!(SG, NETIF_F_SG_BIT);
134+
_netif_f!(FRAGLIST, NETIF_F_FRAGLIST_BIT);
135+
_netif_f!(TSO, NETIF_F_TSO_BIT);
136+
_netif_f!(TSO6, NETIF_F_TSO6_BIT);
137+
_netif_f!(TSO_ECN, NETIF_F_TSO_ECN_BIT);
138+
_netif_f!(TSO_MANGLEID, NETIF_F_TSO_MANGLEID_BIT);
139+
_netif_f!(GSO_SCTP, NETIF_F_GSO_SCTP_BIT);
140+
_netif_f!(GSO_UDP_L4, NETIF_F_GSO_UDP_L4_BIT);
141+
_netif_f!(GSO_FRAGLIST, NETIF_F_GSO_FRAGLIST_BIT);
142+
_netif_f!(HW_CSUM, NETIF_F_HW_CSUM_BIT);
143+
_netif_f!(HIGHDMA, NETIF_F_HIGHDMA_BIT);
144+
_netif_f!(LLTX, NETIF_F_LLTX_BIT);
145+
_netif_f!(GSO_GRE, NETIF_F_GSO_GRE_BIT);
146+
_netif_f!(GSO_GRE_CSUM, NETIF_F_GSO_GRE_CSUM_BIT);
147+
_netif_f!(GSO_IPXIP4, NETIF_F_GSO_IPXIP4_BIT);
148+
_netif_f!(GSO_IPXIP6, NETIF_F_GSO_IPXIP6_BIT);
149+
_netif_f!(GSO_UDP_TUNNEL, NETIF_F_GSO_UDP_TUNNEL_BIT);
150+
_netif_f!(GSO_UDP_TUNNEL_CSUM, NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT);
151+
152+
_netif_f_sum!(ALL_TSO, TSO, TSO6, TSO_ECN, TSO_MANGLEID);
153+
_netif_f_sum!(GSO_SOFTWARE, ALL_TSO, GSO_SCTP, GSO_UDP_L4, GSO_FRAGLIST);
154+
_netif_f_sum!(
155+
GSO_ENCAP_ALL,
156+
GSO_GRE,
157+
GSO_GRE_CSUM,
158+
GSO_IPXIP4,
159+
GSO_IPXIP6,
160+
GSO_UDP_TUNNEL,
161+
GSO_UDP_TUNNEL_CSUM
162+
);
163+
}
164+
165+
/// Iff flags
166+
#[repr(u32)]
167+
#[allow(non_camel_case_types)]
168+
pub enum Flag {
169+
/// UP
170+
UP = bindings::net_device_flags_IFF_UP,
171+
/// BROADCAST
172+
BROADCAST = bindings::net_device_flags_IFF_BROADCAST,
173+
/// DEBUG
174+
DEBUG = bindings::net_device_flags_IFF_DEBUG,
175+
/// LOOPBACK
176+
LOOPBACK = bindings::net_device_flags_IFF_LOOPBACK,
177+
/// POINTOPOINT
178+
POINTOPOINT = bindings::net_device_flags_IFF_POINTOPOINT,
179+
/// NOTRAILERS
180+
NOTRAILERS = bindings::net_device_flags_IFF_NOTRAILERS,
181+
/// RUNNING
182+
RUNNING = bindings::net_device_flags_IFF_RUNNING,
183+
/// NOARP
184+
NOARP = bindings::net_device_flags_IFF_NOARP,
185+
/// PROMISC
186+
PROMISC = bindings::net_device_flags_IFF_PROMISC,
187+
/// ALLMULTI
188+
ALLMULTI = bindings::net_device_flags_IFF_ALLMULTI,
189+
/// MASTER
190+
MASTER = bindings::net_device_flags_IFF_MASTER,
191+
/// SLAVE
192+
SLAVE = bindings::net_device_flags_IFF_SLAVE,
193+
/// MULTICAST
194+
MULTICAST = bindings::net_device_flags_IFF_MULTICAST,
195+
/// PORTSEL
196+
PORTSEL = bindings::net_device_flags_IFF_PORTSEL,
197+
/// AUTOMEDIA
198+
AUTOMEDIA = bindings::net_device_flags_IFF_AUTOMEDIA,
199+
/// DYNAMIC
200+
DYNAMIC = bindings::net_device_flags_IFF_DYNAMIC,
201+
202+
// #if __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO // TODO: is this needed?
203+
/// LOWER
204+
LOWER = bindings::net_device_flags_IFF_LOWER_UP,
205+
/// DORMANT
206+
DORMANT = bindings::net_device_flags_IFF_DORMANT,
207+
/// ECHO
208+
ECHO = bindings::net_device_flags_IFF_ECHO,
209+
}
210+
211+
/// Iff private flags
212+
#[repr(i32)]
213+
#[allow(non_camel_case_types)]
214+
pub enum PrivFlag {
215+
/// 802.1Q VLAN device.
216+
IFF_802_1Q_VLAN = bindings::netdev_priv_flags_IFF_802_1Q_VLAN, /* TODO: find a good name without leading 8 */
217+
/// Ethernet bridging device.
218+
EBRIDGE = bindings::netdev_priv_flags_IFF_EBRIDGE,
219+
/// Bonding master or slave.
220+
BONDING = bindings::netdev_priv_flags_IFF_BONDING,
221+
/// ISATAP interface (RFC4214).
222+
ISATAP = bindings::netdev_priv_flags_IFF_ISATAP,
223+
/// WAN HDLC device.
224+
WAN_HDLC = bindings::netdev_priv_flags_IFF_WAN_HDLC,
225+
/// dev_hard_start_xmit() is allowed to release skb->dst
226+
XMIT_DST_RELEASE = bindings::netdev_priv_flags_IFF_XMIT_DST_RELEASE,
227+
/// Disallow bridging this ether dev.
228+
DONT_BRIDGE = bindings::netdev_priv_flags_IFF_DONT_BRIDGE,
229+
/// Disable netpoll at run-time.
230+
DISABLE_NETPOLL = bindings::netdev_priv_flags_IFF_DISABLE_NETPOLL,
231+
/// Device used as macvlan port.
232+
MACVLAN_PORT = bindings::netdev_priv_flags_IFF_MACVLAN_PORT,
233+
/// Device used as bridge port.
234+
BRIDGE_PORT = bindings::netdev_priv_flags_IFF_BRIDGE_PORT,
235+
/// Device used as Open vSwitch datapath port.
236+
OVS_DATAPATH = bindings::netdev_priv_flags_IFF_OVS_DATAPATH,
237+
/// The interface supports sharing skbs on transmit.
238+
TX_SKB_SHARING = bindings::netdev_priv_flags_IFF_TX_SKB_SHARING,
239+
/// Supports unicast filtering.
240+
UNICAST_FLT = bindings::netdev_priv_flags_IFF_UNICAST_FLT,
241+
/// Device used as team port.
242+
TEAM_PORT = bindings::netdev_priv_flags_IFF_TEAM_PORT,
243+
/// Device supports sending custom FCS.
244+
SUPP_NOFCS = bindings::netdev_priv_flags_IFF_SUPP_NOFCS,
245+
/// Device supports hardware address change when it's running.
246+
LIVE_ADDR_CHANGE = bindings::netdev_priv_flags_IFF_LIVE_ADDR_CHANGE,
247+
/// Macvlan device.
248+
MACVLAN = bindings::netdev_priv_flags_IFF_MACVLAN,
249+
/// IFF_XMIT_DST_RELEASE not taking into account underlying stacked devices.
250+
XMIT_DST_RELEASE_PERM = bindings::netdev_priv_flags_IFF_XMIT_DST_RELEASE_PERM,
251+
/// Device is an L3 master device.
252+
L3MDEV_MASTER = bindings::netdev_priv_flags_IFF_L3MDEV_MASTER,
253+
/// Device can run without qdisc attached.
254+
NO_QUEUE = bindings::netdev_priv_flags_IFF_NO_QUEUE,
255+
/// Device is a Open vSwitch master.
256+
OPENVSWITCH = bindings::netdev_priv_flags_IFF_OPENVSWITCH,
257+
/// Device is enslaved to an L3 master device.
258+
L3MDEV_SLAVE = bindings::netdev_priv_flags_IFF_L3MDEV_SLAVE,
259+
/// Device is a team device.
260+
TEAM = bindings::netdev_priv_flags_IFF_TEAM,
261+
/// Device has had Rx Flow indirection table configured.
262+
RXFH_CONFIGURED = bindings::netdev_priv_flags_IFF_RXFH_CONFIGURED,
263+
/// The headroom value is controlled by an external entity (i.e. the master device for bridged veth).
264+
PHONY_HEADROOM = bindings::netdev_priv_flags_IFF_PHONY_HEADROOM,
265+
/// Device is a MACsec device.
266+
MACSEC = bindings::netdev_priv_flags_IFF_MACSEC,
267+
/// Device doesn't support the rx_handler hook.
268+
NO_RX_HANDLER = bindings::netdev_priv_flags_IFF_NO_RX_HANDLER,
269+
/// Device is a failover master device.
270+
FAILOVER = bindings::netdev_priv_flags_IFF_FAILOVER,
271+
/// Device is lower dev of a failover master device.
272+
FAILOVER_SLAVE = bindings::netdev_priv_flags_IFF_FAILOVER_SLAVE,
273+
/// Only invoke the rx handler of L3 master device.
274+
L3MDEV_RX_HANDLER = bindings::netdev_priv_flags_IFF_L3MDEV_RX_HANDLER,
275+
/// Rename is allowed while device is up and running.
276+
LIVE_RENAME_OK = bindings::netdev_priv_flags_IFF_LIVE_RENAME_OK,
277+
}

0 commit comments

Comments
 (0)