@@ -11,7 +11,7 @@ use dummynet::{PacketFilter, Pipe};
11
11
pub mod namespace;
12
12
13
13
pub mod assert;
14
- use assert :: assert_status ;
14
+ pub mod ip_tc ;
15
15
16
16
#[ derive( Debug ) ]
17
17
pub struct SimulationConfig {
@@ -129,142 +129,24 @@ impl Simulation {
129
129
#[ cfg( target_os = "linux" ) ]
130
130
fn start ( & self ) -> io:: Result < ( ) > {
131
131
// Create network namespace
132
- let network_namespace = self . namespace_name ( ) ;
133
-
134
- let status = Command :: new ( "sudo" )
135
- . args ( [ "ip" , "netns" , "add" , & network_namespace] )
136
- . status ( ) ?;
137
-
138
- assert_status ( status, "Failed to create namespace" ) ?;
139
132
140
- // Create Virtual Ethernet (veth) devices and link them
141
- //
142
- // Note: device name length can be max 15 chars long
133
+ let network_namespace = self . namespace_name ( ) ;
143
134
let veth_host = self . veth_host_name ( ) ;
144
135
let veth_namespace = self . veth_namespace_name ( ) ;
145
- let status = Command :: new ( "sudo" )
146
- . args ( [
147
- "ip" ,
148
- "link" ,
149
- "add" ,
150
- & veth_host,
151
- "type" ,
152
- "veth" ,
153
- "peer" ,
154
- "name" ,
155
- & veth_namespace,
156
- ] )
157
- . status ( ) ?;
158
-
159
- assert_status ( status, "Failed add veth devices" ) ?;
160
-
161
- // Move veth namespace device to its namespace
162
- let status = Command :: new ( "sudo" )
163
- . args ( [
164
- "ip" ,
165
- "link" ,
166
- "set" ,
167
- & veth_namespace,
168
- "netns" ,
169
- & network_namespace,
170
- ] )
171
- . status ( ) ?;
172
-
173
- assert_status ( status, "Failed move veth device to network namespace" ) ?;
174
-
175
136
let ip_namespace = format ! ( "{}/24" , self . endpoint) ;
176
137
177
- let mut ip_host: Vec < u64 > = self
178
- . endpoint
179
- . to_string ( )
180
- . split ( '.' )
181
- . map ( |octect| octect. parse :: < u64 > ( ) . unwrap ( ) )
182
- . collect ( ) ;
183
- ip_host[ 3 ] += 1 ;
184
- let ip_host = format ! (
185
- "{}.{}.{}.{}/24" ,
186
- ip_host[ 0 ] , ip_host[ 1 ] , ip_host[ 2 ] , ip_host[ 3 ]
187
- ) ;
138
+ ip_tc:: create_namespace ( & network_namespace) ?;
139
+ ip_tc:: create_veth_pair ( & veth_host, & veth_namespace) ?;
140
+ ip_tc:: move_device_to_namespace ( & veth_namespace, & network_namespace) ?;
188
141
189
- // Associate IP address to host veth device and spin it up
190
- let status = Command :: new ( "sudo" )
191
- . args ( [ "ip" , "addr" , "add" , & ip_host, "dev" , & veth_host] )
192
- . status ( ) ?;
193
- assert_status ( status, "Failed to associate IP address to host veth device" ) ?;
194
- let status = Command :: new ( "sudo" )
195
- . args ( [ "ip" , "link" , "set" , & veth_host, "up" ] )
196
- . status ( ) ?;
197
- assert_status ( status, "Failed to set up the host veth device" ) ?;
198
-
199
- // Associate IP address to namespaced veth device and spin it up
200
- let status = Command :: new ( "sudo" )
201
- . args ( [
202
- "ip" ,
203
- "netns" ,
204
- "exec" ,
205
- & network_namespace,
206
- "ip" ,
207
- "addr" ,
208
- "add" ,
209
- & ip_namespace,
210
- "dev" ,
211
- & veth_namespace,
212
- ] )
213
- . status ( ) ?;
214
- assert_status (
215
- status,
216
- "Failed to associate IP address to namespaced veth device" ,
217
- ) ?;
218
- let status = Command :: new ( "sudo" )
219
- . args ( [
220
- "ip" ,
221
- "netns" ,
222
- "exec" ,
223
- & network_namespace,
224
- "ip" ,
225
- "link" ,
226
- "set" ,
227
- & veth_namespace,
228
- "up" ,
229
- ] )
230
- . status ( ) ?;
231
- assert_status ( status, "Failed to set up the namespaced veth device" ) ?;
232
-
233
- // Spin up also the loopback interface on namespaced environment
234
- let status = Command :: new ( "sudo" )
235
- . args ( [
236
- "ip" ,
237
- "netns" ,
238
- "exec" ,
239
- & network_namespace,
240
- "ip" ,
241
- "link" ,
242
- "set" ,
243
- "lo" ,
244
- "up" ,
245
- ] )
246
- . status ( ) ?;
247
- assert_status ( status, "Failed to set up the namespaced loopback device" ) ?;
142
+ let ip_host = ip_tc:: gen_host_ip_address ( & self . endpoint ) ;
248
143
249
- // Add network emulation parameters (delay, loss) on namespaced veth device
250
- //
251
- // The behaviour is specified on the top-level ("root"),
252
- // with a custom handle for identification
253
- let mut args = vec ! [
254
- "ip" ,
255
- "netns" ,
256
- "exec" ,
257
- & network_namespace,
258
- "tc" ,
259
- "qdisc" ,
260
- "add" ,
261
- "dev" ,
262
- & veth_namespace,
263
- "root" ,
264
- "handle" ,
265
- "1:" ,
266
- "netem" ,
267
- ] ;
144
+ ip_tc:: add_ip_addr_to_device ( & veth_host, & ip_host, None ) ?;
145
+ ip_tc:: spin_up_device ( & veth_host, None ) ?;
146
+
147
+ ip_tc:: add_ip_addr_to_device ( & veth_namespace, & ip_namespace, Some ( & network_namespace) ) ?;
148
+ ip_tc:: spin_up_device ( & veth_namespace, Some ( & network_namespace) ) ?;
149
+ ip_tc:: spin_up_device ( "lo" , Some ( & network_namespace) ) ?;
268
150
269
151
let delay = format ! (
270
152
"{}ms" ,
@@ -274,34 +156,30 @@ impl Simulation {
274
156
. as_millis( )
275
157
) ;
276
158
159
+ let loss = format ! ( "{}%" , self . config. plr. unwrap_or( 0_f64 ) ) ;
160
+
161
+ // Add delay to the host veth device to match MacOS symmetric behaviour
162
+ //
163
+ // The behaviour is specified on the top-level ("root"),
164
+ // with a custom handle for identification
165
+ let mut args = vec ! [ "root" , "handle" , "1:" , "netem" ] ;
277
166
if self . config . latency . is_some ( ) {
278
167
args. push ( "delay" ) ;
279
168
args. push ( & delay) ;
280
169
}
170
+ ip_tc:: add_network_emulation_parameters ( & veth_host, args, None ) ?;
281
171
282
- let loss = format ! ( "{}%" , self . config. plr. unwrap_or( 0_f64 ) ) ;
283
-
172
+ // Add network emulation parameters (delay, loss) on namespaced veth device
173
+ let mut args = vec ! [ "root" , "handle" , "1:" , "netem" ] ;
174
+ if self . config . latency . is_some ( ) {
175
+ args. push ( "delay" ) ;
176
+ args. push ( & delay) ;
177
+ }
284
178
if ( self . config . plr ) . is_some ( ) {
285
179
args. push ( "loss" ) ;
286
180
args. push ( & loss) ;
287
181
}
288
-
289
- let status = Command :: new ( "sudo" ) . args ( args) . status ( ) ?;
290
-
291
- assert_status (
292
- status,
293
- "Failed to set delay and loss network emulation parameters to namespaced device" ,
294
- ) ?;
295
-
296
- // Add delay to the host veth device to match MacOS symmetric behaviour
297
- let status = Command :: new ( "sudo" )
298
- . args ( [
299
- "tc" , "qdisc" , "add" , "dev" , & veth_host, "root" , "handle" , "1:" , "netem" , "delay" ,
300
- & delay,
301
- ] )
302
- . status ( ) ?;
303
-
304
- assert_status ( status, "Failed to set delay to the host veth device" ) ?;
182
+ ip_tc:: add_network_emulation_parameters ( & veth_namespace, args, Some ( & network_namespace) ) ?;
305
183
306
184
// Add bandwidth paramteres on namespaced veth device
307
185
//
@@ -312,47 +190,16 @@ impl Simulation {
312
190
let burst = format ! ( "{}kbit" , self . config. burst. unwrap_or( 32 ) ) ;
313
191
let limit = format ! ( "{}" , self . config. limit. unwrap_or( 10_000 ) ) ;
314
192
315
- let status = Command :: new ( "sudo" )
316
- . args ( [
317
- "ip" ,
318
- "netns" ,
319
- "exec" ,
320
- & network_namespace,
321
- "tc" ,
322
- "qdisc" ,
323
- "add" ,
324
- "dev" ,
325
- & veth_namespace,
326
- "parent" ,
327
- "1:" ,
328
- "handle" ,
329
- "2:" ,
330
- "tbf" ,
331
- "rate" ,
332
- & bandwidth,
333
- "burst" ,
334
- & burst,
335
- "limit" ,
336
- & limit,
337
- ] )
338
- . status ( ) ?;
339
-
340
- assert_status (
341
- status,
342
- "Failed to set bandwidth parameter to the namespaced device" ,
343
- ) ?;
193
+ let args = vec ! [
194
+ "parent" , "1:" , "handle" , "2:" , "tbf" , "rate" , & bandwidth, "burst" , & burst,
195
+ "limit" , & limit,
196
+ ] ;
344
197
345
- // Add bandwidth paramteres on host veth device
346
- let status = Command :: new ( "sudo" )
347
- . args ( [
348
- "tc" , "qdisc" , "add" , "dev" , & veth_host, "parent" , "1:" , "handle" , "2:" , "tbf" ,
349
- "rate" , & bandwidth, "burst" , & burst, "limit" , & limit,
350
- ] )
351
- . status ( ) ?;
352
-
353
- assert_status (
354
- status,
355
- "Failed to set bandwidth parameter to the host veth device" ,
198
+ ip_tc:: add_network_emulation_parameters ( & veth_host, args. clone ( ) , None ) ?;
199
+ ip_tc:: add_network_emulation_parameters (
200
+ & veth_namespace,
201
+ args,
202
+ Some ( & network_namespace) ,
356
203
) ?;
357
204
}
358
205
Ok ( ( ) )
0 commit comments