Skip to content

Commit f36fe1c

Browse files
jpirkodavem330
authored andcommitted
net: sched: introduce block mechanism to handle netif_keep_dst calls
Couple of classifiers call netif_keep_dst directly on q->dev. That is not possible to do directly for shared blocke where multiple qdiscs are owning the block. So introduce a infrastructure to keep track of the block owners in list and use this list to implement block variant of netif_keep_dst. Signed-off-by: Jiri Pirko <[email protected]> Acked-by: Jamal Hadi Salim <[email protected]> Acked-by: David Ahern <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 9d3aaff commit f36fe1c

File tree

6 files changed

+76
-4
lines changed

6 files changed

+76
-4
lines changed

include/net/pkt_cls.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ bool tcf_queue_work(struct work_struct *work);
3939
struct tcf_chain *tcf_chain_get(struct tcf_block *block, u32 chain_index,
4040
bool create);
4141
void tcf_chain_put(struct tcf_chain *chain);
42+
void tcf_block_netif_keep_dst(struct tcf_block *block);
4243
int tcf_block_get(struct tcf_block **p_block,
4344
struct tcf_proto __rcu **p_filter_chain, struct Qdisc *q,
4445
struct netlink_ext_ack *extack);

include/net/sch_generic.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,8 @@ struct tcf_block {
289289
struct net *net;
290290
struct Qdisc *q;
291291
struct list_head cb_list;
292+
struct list_head owner_list;
293+
bool keep_dst;
292294
};
293295

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

net/sched/cls_api.c

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,7 @@ static struct tcf_block *tcf_block_create(struct net *net, struct Qdisc *q,
375375
}
376376
INIT_LIST_HEAD(&block->chain_list);
377377
INIT_LIST_HEAD(&block->cb_list);
378+
INIT_LIST_HEAD(&block->owner_list);
378379

379380
/* Create chain 0 by default, it has to be always present. */
380381
chain = tcf_chain_create(block, 0);
@@ -406,6 +407,65 @@ static struct tcf_chain *tcf_block_chain_zero(struct tcf_block *block)
406407
return list_first_entry(&block->chain_list, struct tcf_chain, list);
407408
}
408409

410+
struct tcf_block_owner_item {
411+
struct list_head list;
412+
struct Qdisc *q;
413+
enum tcf_block_binder_type binder_type;
414+
};
415+
416+
static void
417+
tcf_block_owner_netif_keep_dst(struct tcf_block *block,
418+
struct Qdisc *q,
419+
enum tcf_block_binder_type binder_type)
420+
{
421+
if (block->keep_dst &&
422+
binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS &&
423+
binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_EGRESS)
424+
netif_keep_dst(qdisc_dev(q));
425+
}
426+
427+
void tcf_block_netif_keep_dst(struct tcf_block *block)
428+
{
429+
struct tcf_block_owner_item *item;
430+
431+
block->keep_dst = true;
432+
list_for_each_entry(item, &block->owner_list, list)
433+
tcf_block_owner_netif_keep_dst(block, item->q,
434+
item->binder_type);
435+
}
436+
EXPORT_SYMBOL(tcf_block_netif_keep_dst);
437+
438+
static int tcf_block_owner_add(struct tcf_block *block,
439+
struct Qdisc *q,
440+
enum tcf_block_binder_type binder_type)
441+
{
442+
struct tcf_block_owner_item *item;
443+
444+
item = kmalloc(sizeof(*item), GFP_KERNEL);
445+
if (!item)
446+
return -ENOMEM;
447+
item->q = q;
448+
item->binder_type = binder_type;
449+
list_add(&item->list, &block->owner_list);
450+
return 0;
451+
}
452+
453+
static void tcf_block_owner_del(struct tcf_block *block,
454+
struct Qdisc *q,
455+
enum tcf_block_binder_type binder_type)
456+
{
457+
struct tcf_block_owner_item *item;
458+
459+
list_for_each_entry(item, &block->owner_list, list) {
460+
if (item->q == q && item->binder_type == binder_type) {
461+
list_del(&item->list);
462+
kfree(item);
463+
return;
464+
}
465+
}
466+
WARN_ON(1);
467+
}
468+
409469
int tcf_block_get_ext(struct tcf_block **p_block, struct Qdisc *q,
410470
struct tcf_block_ext_info *ei,
411471
struct netlink_ext_ack *extack)
@@ -435,6 +495,12 @@ int tcf_block_get_ext(struct tcf_block **p_block, struct Qdisc *q,
435495
}
436496
}
437497

498+
err = tcf_block_owner_add(block, q, ei->binder_type);
499+
if (err)
500+
goto err_block_owner_add;
501+
502+
tcf_block_owner_netif_keep_dst(block, q, ei->binder_type);
503+
438504
err = tcf_chain_head_change_cb_add(tcf_block_chain_zero(block),
439505
ei, extack);
440506
if (err)
@@ -444,6 +510,8 @@ int tcf_block_get_ext(struct tcf_block **p_block, struct Qdisc *q,
444510
return 0;
445511

446512
err_chain_head_change_cb_add:
513+
tcf_block_owner_del(block, q, ei->binder_type);
514+
err_block_owner_add:
447515
if (created) {
448516
if (tcf_block_shared(block))
449517
tcf_block_remove(block, net);
@@ -489,6 +557,7 @@ void tcf_block_put_ext(struct tcf_block *block, struct Qdisc *q,
489557
if (!block)
490558
return;
491559
tcf_chain_head_change_cb_del(tcf_block_chain_zero(block), ei);
560+
tcf_block_owner_del(block, q, ei->binder_type);
492561

493562
if (--block->refcnt == 0) {
494563
if (tcf_block_shared(block))

net/sched/cls_bpf.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -392,8 +392,8 @@ static int cls_bpf_prog_from_efd(struct nlattr **tb, struct cls_bpf_prog *prog,
392392
prog->bpf_name = name;
393393
prog->filter = fp;
394394

395-
if (fp->dst_needed && !(tp->q->flags & TCQ_F_INGRESS))
396-
netif_keep_dst(qdisc_dev(tp->q));
395+
if (fp->dst_needed)
396+
tcf_block_netif_keep_dst(tp->chain->block);
397397

398398
return 0;
399399
}

net/sched/cls_flow.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -526,7 +526,7 @@ static int flow_change(struct net *net, struct sk_buff *in_skb,
526526

527527
timer_setup(&fnew->perturb_timer, flow_perturbation, TIMER_DEFERRABLE);
528528

529-
netif_keep_dst(qdisc_dev(tp->q));
529+
tcf_block_netif_keep_dst(tp->chain->block);
530530

531531
if (tb[TCA_FLOW_KEYS]) {
532532
fnew->keymask = keymask;

net/sched/cls_route.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,7 @@ static int route4_change(struct net *net, struct sk_buff *in_skb,
527527
if (f->handle < f1->handle)
528528
break;
529529

530-
netif_keep_dst(qdisc_dev(tp->q));
530+
tcf_block_netif_keep_dst(tp->chain->block);
531531
rcu_assign_pointer(f->next, f1);
532532
rcu_assign_pointer(*fp, f);
533533

0 commit comments

Comments
 (0)