1
1
// SPDX-License-Identifier: GPL-2.0
2
2
3
3
//! Rust dummy network driver
4
- //!
4
+ //!
5
5
//! This is a demonstration of what a small driver looks like in Rust, based on drivers/net/dummy.c.
6
6
//! This code is provided as a demonstration only, not as a proposal to mass-rewrite existing drivers in Rust
7
7
8
8
// TODO: copyright (see ./dummy.c)
9
9
10
-
11
10
#![ no_std]
12
11
#![ feature( allocator_api, global_asm) ]
13
12
14
13
use core:: ops:: Deref ;
15
14
16
- use kernel:: { net:: netlink:: { NlAttrVec , NlExtAck } , prelude:: * } ;
17
- use kernel:: net:: prelude:: * ;
18
15
use kernel:: net:: device;
16
+ use kernel:: net:: prelude:: * ;
19
17
use kernel:: net:: rtnl;
20
18
use kernel:: Error ;
19
+ use kernel:: {
20
+ net:: netlink:: { NlAttrVec , NlExtAck } ,
21
+ prelude:: * ,
22
+ } ;
21
23
22
24
module ! {
23
25
type : RustNetDummy ,
24
26
name: b"dummy_rs" ,
25
27
author: b"Rust for Linux Contributors" ,
26
28
description: b"Rust dummy network driver" ,
27
29
license: b"GPL v2" ,
28
- alias : b"rtnl-link- dummy_rs" ,
30
+ alias_rtnl_link : b"dummy_rs" ,
29
31
params: {
30
32
numdummies: usize {
31
33
default : 0 ,
@@ -36,9 +38,10 @@ module! {
36
38
}
37
39
38
40
fn setup ( dev : & mut NetDevice < DummyRsDev > ) {
39
- pr_info ! ( "called rtnl_setup" ) ;
40
41
dev. ether_setup ( ) ;
41
42
43
+ dev. set_ops ( ) ;
44
+
42
45
// Fill in device structure with ethernet-generic values.
43
46
dev. add_flag ( device:: Iff :: NOARP ) ;
44
47
dev. remove_flag ( device:: Iff :: MULTICAST ) ;
@@ -67,18 +70,14 @@ fn setup(dev: &mut NetDevice<DummyRsDev>) {
67
70
}
68
71
69
72
fn validate ( tb : & NlAttrVec , data : & NlAttrVec , ext_ack : & NlExtAck ) -> KernelResult < ( ) > {
70
- pr_info ! ( "validate nlattr" ) ;
71
73
if let Some ( addr) = tb. get ( kernel:: bindings:: IFLA_ADDRESS ) {
72
74
if addr. nla_len ( ) != kernel:: net:: netlink:: ETH_ALEN {
73
75
return Err ( Error :: EINVAL ) ;
74
76
}
75
77
if !addr. is_valid_ether_addr ( ) {
76
78
return Err ( Error :: EADDRNOTAVAIL ) ;
77
79
}
78
- } else {
79
- pr_info ! ( "no IFLA_ADDRESS in nlattr" ) ;
80
80
}
81
- pr_info ! ( "valid nlattr" ) ;
82
81
Ok ( ( ) )
83
82
}
84
83
@@ -90,52 +89,51 @@ rtnl_link_ops! {
90
89
}
91
90
92
91
struct RustNetDummy {
93
- dev : NetDevice < DummyRsDev > ,
92
+ // dev: NetDevice<DummyRsDev>,
94
93
}
95
94
96
-
97
95
impl KernelModule for RustNetDummy {
98
96
fn init ( ) -> KernelResult < Self > {
99
- {
100
- let lock =THIS_MODULE . kernel_param_lock ( ) ;
101
- pr_info ! ( "Rust Network Dummy with {} pseudo devices\n " , numdummies. read( & lock) ) ;
102
- }
103
-
104
- unsafe { dummy_rs_rtnl_link_ops. register ( ) } ?;
105
-
106
- let mut dev = NetDevice :: new ( DummyRsDev , kernel:: cstr!( "dummyrs%d" ) , kernel:: net:: device:: NetNameAssingType :: Enum , 1 , 1 ) ?;
107
- dev. set_rtnl_ops ( unsafe { & dummy_rs_rtnl_link_ops } ) ;
108
-
109
- if let Err ( e) = dev. register ( ) {
110
- pr_warn ! ( "could not register: {}" , e. to_kernel_errno( ) ) ;
111
- return Err ( e) ;
97
+ let num = {
98
+ let lock = THIS_MODULE . kernel_param_lock ( ) ;
99
+ pr_info ! (
100
+ "Rust Network Dummy with {} pseudo devices\n " ,
101
+ numdummies. read( & lock)
102
+ ) ;
103
+ numdummies. read ( & lock) . clone ( )
104
+ } ;
105
+
106
+ unsafe { dummy_rs_link_ops. register ( ) } ?;
107
+
108
+ for x in 0 ..( num) {
109
+ let dev = NetDevice :: new (
110
+ DummyRsDev ,
111
+ kernel:: cstr!( "dummyrs%d" ) ,
112
+ kernel:: net:: device:: NetNameAssingType :: Enum ,
113
+ 1 ,
114
+ 1 ,
115
+ ) ?;
116
+ dev. set_rtnl_ops ( unsafe { & dummy_rs_link_ops } ) ;
117
+
118
+ if let Err ( e) = dev. register ( ) {
119
+ pr_warn ! ( "could not register: {}" , e. to_kernel_errno( ) ) ;
120
+ return Err ( e) ;
121
+ }
112
122
}
113
- pr_info ! ( "device registered" ) ;
114
123
115
124
Ok ( RustNetDummy {
116
- dev,
125
+ // dev,
117
126
} )
118
127
}
119
128
}
120
129
121
130
impl Drop for RustNetDummy {
122
131
fn drop ( & mut self ) {
123
- pr_info ! ( "remove rust net dummy" ) ;
124
-
125
-
126
- unsafe {
127
- //let ptr = &dummy_rs_rtnl_link_ops as *const _ as *mut kernel::bindings::rtnl_link_ops;
128
- pr_info ! ( "rtnl: {:#?}" , & dummy_rs_rtnl_link_ops. 0 ) ;
129
- let ptr = & dummy_rs_rtnl_link_ops. get_ptr ( ) ;
130
- pr_info ! ( "rtnl_link_ops_ptr: {:?}" , ptr) ;
131
- }
132
- // TODO rtnl_link_unregister
133
132
// TODO: remove unsafe somehow
134
- unsafe { dummy_rs_rtnl_link_ops . unregister ( ) } ;
133
+ unsafe { dummy_rs_link_ops . unregister ( ) } ;
135
134
}
136
135
}
137
136
138
-
139
137
struct DummyRsDev ;
140
138
141
139
impl NetDeviceOps < Self > for DummyRsDev {
@@ -159,19 +157,15 @@ impl NetDeviceOps<Self> for DummyRsDev {
159
157
fn start_xmit ( skb : SkBuff , dev : & mut NetDevice < Self > ) -> kernel:: net:: device:: NetdevTX {
160
158
let mut skb = skb;
161
159
162
- // TODO: dev_lstatt_add(dev, skb->len)
163
160
dev. lstats_add ( skb. len ( ) ) ;
164
161
165
162
skb. tx_timestamp ( ) ;
166
163
drop ( skb) ;
167
164
168
- pr_info ! ( "start_xmit called" ) ;
169
-
170
165
kernel:: net:: device:: NetdevTX :: TX_OK
171
166
}
172
167
173
168
fn get_stats64 ( dev : & NetDevice < Self > , stats : & mut rtnl:: RtnlLinkStats64 ) {
174
- pr_info ! ( "get stats64" ) ;
175
169
stats. dev_read ( dev) ;
176
170
}
177
171
@@ -182,18 +176,18 @@ impl NetDeviceOps<Self> for DummyRsDev {
182
176
}
183
177
184
178
fn validate_addr ( dev : & NetDevice < Self > ) -> KernelResult < ( ) > {
185
- pr_info ! ( "eth_validate_addr" ) ;
186
179
device:: helpers:: eth_validate_addr ( dev)
187
180
}
188
181
189
- fn set_mac_addr ( dev : & mut NetDevice < Self > , p : * mut kernel:: c_types:: c_void ) -> KernelResult < ( ) > {
182
+ fn set_mac_addr (
183
+ dev : & mut NetDevice < Self > ,
184
+ p : * mut kernel:: c_types:: c_void ,
185
+ ) -> KernelResult < ( ) > {
190
186
device:: helpers:: eth_mac_addr ( dev, p)
191
187
}
192
188
193
- // Someting about faking multicast
194
- fn set_rx_mode ( dev : & mut NetDevice < Self > ) {
195
- pr_info ! ( "set_rx_mode" ) ;
196
- }
189
+ // [Someting about faking multicast](https://elixir.bootlin.com/linux/v5.12-rc4/source/drivers/net/dummy.c#L48).
190
+ fn set_rx_mode ( _dev : & mut NetDevice < Self > ) { }
197
191
}
198
192
199
193
impl NetDeviceAdapter for DummyRsDev {
@@ -204,9 +198,7 @@ impl NetDeviceAdapter for DummyRsDev {
204
198
type EthOps = Self ;
205
199
206
200
fn setup ( dev : & mut NetDevice < Self > ) {
207
- pr_info ! ( "called netdev_setup" ) ;
208
201
setup ( dev) ;
209
- //dev.set_rtnl_ops( unsafe { &dummy_rs_rtnl_link_ops });
210
202
}
211
203
}
212
204
@@ -218,7 +210,11 @@ impl EthToolOps<Self> for DummyRsDev {
218
210
// FIXME: !!
219
211
let info: & kernel:: bindings:: ethtool_drvinfo = info. deref ( ) ;
220
212
unsafe {
221
- kernel:: bindings:: strlcpy ( & ( info. driver ) as * const _ as * mut i8 , b"dummy_rs\0 " as * const _ as * mut i8 , 32 ) ;
213
+ kernel:: bindings:: strlcpy (
214
+ & ( info. driver ) as * const _ as * mut i8 ,
215
+ b"dummy_rs\0 " as * const _ as * mut i8 ,
216
+ 32 ,
217
+ ) ;
222
218
}
223
219
}
224
220
0 commit comments