Skip to content

Commit acb6744

Browse files
jpirkodavem330
authored andcommitted
net: sched: introduce per-block callbacks
Introduce infrastructure that allows drivers to register callbacks that are called whenever tc would offload inserted rule for a specific block. Signed-off-by: Jiri Pirko <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 6e40cf2 commit acb6744

File tree

3 files changed

+187
-0
lines changed

3 files changed

+187
-0
lines changed

include/net/pkt_cls.h

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ struct tcf_block_ext_info {
2727
enum tcf_block_binder_type binder_type;
2828
};
2929

30+
struct tcf_block_cb;
31+
3032
#ifdef CONFIG_NET_CLS
3133
struct tcf_chain *tcf_chain_get(struct tcf_block *block, u32 chain_index,
3234
bool create);
@@ -51,6 +53,21 @@ static inline struct net_device *tcf_block_dev(struct tcf_block *block)
5153
return tcf_block_q(block)->dev_queue->dev;
5254
}
5355

56+
void *tcf_block_cb_priv(struct tcf_block_cb *block_cb);
57+
struct tcf_block_cb *tcf_block_cb_lookup(struct tcf_block *block,
58+
tc_setup_cb_t *cb, void *cb_ident);
59+
void tcf_block_cb_incref(struct tcf_block_cb *block_cb);
60+
unsigned int tcf_block_cb_decref(struct tcf_block_cb *block_cb);
61+
struct tcf_block_cb *__tcf_block_cb_register(struct tcf_block *block,
62+
tc_setup_cb_t *cb, void *cb_ident,
63+
void *cb_priv);
64+
int tcf_block_cb_register(struct tcf_block *block,
65+
tc_setup_cb_t *cb, void *cb_ident,
66+
void *cb_priv);
67+
void __tcf_block_cb_unregister(struct tcf_block_cb *block_cb);
68+
void tcf_block_cb_unregister(struct tcf_block *block,
69+
tc_setup_cb_t *cb, void *cb_ident);
70+
5471
int tcf_classify(struct sk_buff *skb, const struct tcf_proto *tp,
5572
struct tcf_result *res, bool compat_mode);
5673

@@ -91,6 +108,70 @@ static inline struct net_device *tcf_block_dev(struct tcf_block *block)
91108
return NULL;
92109
}
93110

111+
static inline
112+
int tc_setup_cb_block_register(struct tcf_block *block, tc_setup_cb_t *cb,
113+
void *cb_priv)
114+
{
115+
return 0;
116+
}
117+
118+
static inline
119+
void tc_setup_cb_block_unregister(struct tcf_block *block, tc_setup_cb_t *cb,
120+
void *cb_priv)
121+
{
122+
}
123+
124+
static inline
125+
void *tcf_block_cb_priv(struct tcf_block_cb *block_cb)
126+
{
127+
return NULL;
128+
}
129+
130+
static inline
131+
struct tcf_block_cb *tcf_block_cb_lookup(struct tcf_block *block,
132+
tc_setup_cb_t *cb, void *cb_ident)
133+
{
134+
return NULL;
135+
}
136+
137+
static inline
138+
void tcf_block_cb_incref(struct tcf_block_cb *block_cb)
139+
{
140+
}
141+
142+
static inline
143+
unsigned int tcf_block_cb_decref(struct tcf_block_cb *block_cb)
144+
{
145+
return 0;
146+
}
147+
148+
static inline
149+
struct tcf_block_cb *__tcf_block_cb_register(struct tcf_block *block,
150+
tc_setup_cb_t *cb, void *cb_ident,
151+
void *cb_priv)
152+
{
153+
return NULL;
154+
}
155+
156+
static inline
157+
int tcf_block_cb_register(struct tcf_block *block,
158+
tc_setup_cb_t *cb, void *cb_ident,
159+
void *cb_priv)
160+
{
161+
return 0;
162+
}
163+
164+
static inline
165+
void __tcf_block_cb_unregister(struct tcf_block_cb *block_cb)
166+
{
167+
}
168+
169+
static inline
170+
void tcf_block_cb_unregister(struct tcf_block *block,
171+
tc_setup_cb_t *cb, void *cb_ident)
172+
{
173+
}
174+
94175
static inline int tcf_classify(struct sk_buff *skb, const struct tcf_proto *tp,
95176
struct tcf_result *res, bool compat_mode)
96177
{

include/net/sch_generic.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,7 @@ struct tcf_block {
272272
struct list_head chain_list;
273273
struct net *net;
274274
struct Qdisc *q;
275+
struct list_head cb_list;
275276
};
276277

277278
static inline void qdisc_cb_private_validate(const struct sk_buff *skb, int sz)

net/sched/cls_api.c

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,8 @@ int tcf_block_get_ext(struct tcf_block **p_block,
278278
if (!block)
279279
return -ENOMEM;
280280
INIT_LIST_HEAD(&block->chain_list);
281+
INIT_LIST_HEAD(&block->cb_list);
282+
281283
/* Create chain 0 by default, it has to be always present. */
282284
chain = tcf_chain_create(block, 0);
283285
if (!chain) {
@@ -354,6 +356,109 @@ void tcf_block_put(struct tcf_block *block)
354356
}
355357
EXPORT_SYMBOL(tcf_block_put);
356358

359+
struct tcf_block_cb {
360+
struct list_head list;
361+
tc_setup_cb_t *cb;
362+
void *cb_ident;
363+
void *cb_priv;
364+
unsigned int refcnt;
365+
};
366+
367+
void *tcf_block_cb_priv(struct tcf_block_cb *block_cb)
368+
{
369+
return block_cb->cb_priv;
370+
}
371+
EXPORT_SYMBOL(tcf_block_cb_priv);
372+
373+
struct tcf_block_cb *tcf_block_cb_lookup(struct tcf_block *block,
374+
tc_setup_cb_t *cb, void *cb_ident)
375+
{ struct tcf_block_cb *block_cb;
376+
377+
list_for_each_entry(block_cb, &block->cb_list, list)
378+
if (block_cb->cb == cb && block_cb->cb_ident == cb_ident)
379+
return block_cb;
380+
return NULL;
381+
}
382+
EXPORT_SYMBOL(tcf_block_cb_lookup);
383+
384+
void tcf_block_cb_incref(struct tcf_block_cb *block_cb)
385+
{
386+
block_cb->refcnt++;
387+
}
388+
EXPORT_SYMBOL(tcf_block_cb_incref);
389+
390+
unsigned int tcf_block_cb_decref(struct tcf_block_cb *block_cb)
391+
{
392+
return --block_cb->refcnt;
393+
}
394+
EXPORT_SYMBOL(tcf_block_cb_decref);
395+
396+
struct tcf_block_cb *__tcf_block_cb_register(struct tcf_block *block,
397+
tc_setup_cb_t *cb, void *cb_ident,
398+
void *cb_priv)
399+
{
400+
struct tcf_block_cb *block_cb;
401+
402+
block_cb = kzalloc(sizeof(*block_cb), GFP_KERNEL);
403+
if (!block_cb)
404+
return NULL;
405+
block_cb->cb = cb;
406+
block_cb->cb_ident = cb_ident;
407+
block_cb->cb_priv = cb_priv;
408+
list_add(&block_cb->list, &block->cb_list);
409+
return block_cb;
410+
}
411+
EXPORT_SYMBOL(__tcf_block_cb_register);
412+
413+
int tcf_block_cb_register(struct tcf_block *block,
414+
tc_setup_cb_t *cb, void *cb_ident,
415+
void *cb_priv)
416+
{
417+
struct tcf_block_cb *block_cb;
418+
419+
block_cb = __tcf_block_cb_register(block, cb, cb_ident, cb_priv);
420+
return block_cb ? 0 : -ENOMEM;
421+
}
422+
EXPORT_SYMBOL(tcf_block_cb_register);
423+
424+
void __tcf_block_cb_unregister(struct tcf_block_cb *block_cb)
425+
{
426+
list_del(&block_cb->list);
427+
kfree(block_cb);
428+
}
429+
EXPORT_SYMBOL(__tcf_block_cb_unregister);
430+
431+
void tcf_block_cb_unregister(struct tcf_block *block,
432+
tc_setup_cb_t *cb, void *cb_ident)
433+
{
434+
struct tcf_block_cb *block_cb;
435+
436+
block_cb = tcf_block_cb_lookup(block, cb, cb_ident);
437+
if (!block_cb)
438+
return;
439+
__tcf_block_cb_unregister(block_cb);
440+
}
441+
EXPORT_SYMBOL(tcf_block_cb_unregister);
442+
443+
static int tcf_block_cb_call(struct tcf_block *block, enum tc_setup_type type,
444+
void *type_data, bool err_stop)
445+
{
446+
struct tcf_block_cb *block_cb;
447+
int ok_count = 0;
448+
int err;
449+
450+
list_for_each_entry(block_cb, &block->cb_list, list) {
451+
err = block_cb->cb(type, type_data, block_cb->cb_priv);
452+
if (err) {
453+
if (err_stop)
454+
return err;
455+
} else {
456+
ok_count++;
457+
}
458+
}
459+
return ok_count;
460+
}
461+
357462
/* Main classifier routine: scans classifier chain attached
358463
* to this qdisc, (optionally) tests for protocol and asks
359464
* specific classifiers.

0 commit comments

Comments
 (0)