@@ -240,8 +240,36 @@ tcf_chain_filter_chain_ptr_set(struct tcf_chain *chain,
240
240
chain -> p_filter_chain = p_filter_chain ;
241
241
}
242
242
243
- int tcf_block_get (struct tcf_block * * p_block ,
244
- struct tcf_proto __rcu * * p_filter_chain , struct Qdisc * q )
243
+ static void tcf_block_offload_cmd (struct tcf_block * block , struct Qdisc * q ,
244
+ struct tcf_block_ext_info * ei ,
245
+ enum tc_block_command command )
246
+ {
247
+ struct net_device * dev = q -> dev_queue -> dev ;
248
+ struct tc_block_offload bo = {};
249
+
250
+ if (!tc_can_offload (dev ))
251
+ return ;
252
+ bo .command = command ;
253
+ bo .binder_type = ei -> binder_type ;
254
+ bo .block = block ;
255
+ dev -> netdev_ops -> ndo_setup_tc (dev , TC_SETUP_BLOCK , & bo );
256
+ }
257
+
258
+ static void tcf_block_offload_bind (struct tcf_block * block , struct Qdisc * q ,
259
+ struct tcf_block_ext_info * ei )
260
+ {
261
+ tcf_block_offload_cmd (block , q , ei , TC_BLOCK_BIND );
262
+ }
263
+
264
+ static void tcf_block_offload_unbind (struct tcf_block * block , struct Qdisc * q ,
265
+ struct tcf_block_ext_info * ei )
266
+ {
267
+ tcf_block_offload_cmd (block , q , ei , TC_BLOCK_UNBIND );
268
+ }
269
+
270
+ int tcf_block_get_ext (struct tcf_block * * p_block ,
271
+ struct tcf_proto __rcu * * p_filter_chain , struct Qdisc * q ,
272
+ struct tcf_block_ext_info * ei )
245
273
{
246
274
struct tcf_block * block = kzalloc (sizeof (* block ), GFP_KERNEL );
247
275
struct tcf_chain * chain ;
@@ -259,22 +287,36 @@ int tcf_block_get(struct tcf_block **p_block,
259
287
tcf_chain_filter_chain_ptr_set (chain , p_filter_chain );
260
288
block -> net = qdisc_net (q );
261
289
block -> q = q ;
290
+ tcf_block_offload_bind (block , q , ei );
262
291
* p_block = block ;
263
292
return 0 ;
264
293
265
294
err_chain_create :
266
295
kfree (block );
267
296
return err ;
268
297
}
298
+ EXPORT_SYMBOL (tcf_block_get_ext );
299
+
300
+ int tcf_block_get (struct tcf_block * * p_block ,
301
+ struct tcf_proto __rcu * * p_filter_chain , struct Qdisc * q )
302
+ {
303
+ struct tcf_block_ext_info ei = {0 , };
304
+
305
+ return tcf_block_get_ext (p_block , p_filter_chain , q , & ei );
306
+ }
269
307
EXPORT_SYMBOL (tcf_block_get );
270
308
271
- void tcf_block_put (struct tcf_block * block )
309
+ void tcf_block_put_ext (struct tcf_block * block ,
310
+ struct tcf_proto __rcu * * p_filter_chain , struct Qdisc * q ,
311
+ struct tcf_block_ext_info * ei )
272
312
{
273
313
struct tcf_chain * chain , * tmp ;
274
314
275
315
if (!block )
276
316
return ;
277
317
318
+ tcf_block_offload_unbind (block , q , ei );
319
+
278
320
/* XXX: Standalone actions are not allowed to jump to any chain, and
279
321
* bound actions should be all removed after flushing. However,
280
322
* filters are destroyed in RCU callbacks, we have to hold the chains
@@ -302,6 +344,14 @@ void tcf_block_put(struct tcf_block *block)
302
344
tcf_chain_put (chain );
303
345
kfree (block );
304
346
}
347
+ EXPORT_SYMBOL (tcf_block_put_ext );
348
+
349
+ void tcf_block_put (struct tcf_block * block )
350
+ {
351
+ struct tcf_block_ext_info ei = {0 , };
352
+
353
+ tcf_block_put_ext (block , NULL , block -> q , & ei );
354
+ }
305
355
EXPORT_SYMBOL (tcf_block_put );
306
356
307
357
/* Main classifier routine: scans classifier chain attached
0 commit comments