diff options
author | WANG Cong <xiyou.wangcong@gmail.com> | 2015-08-25 19:38:12 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-08-25 20:02:48 -0400 |
commit | a6c1aea044e490da3e59124ec55991fe316818d5 (patch) | |
tree | 80260a1e1e08d619e508574bc5ef407755b3ab15 /net/sched | |
parent | aac27c7a0d76683f7f4bdf41cec174db2819f635 (diff) |
cls_u32: complete the check for non-forced case in u32_destroy()
In commit 1e052be69d04 ("net_sched: destroy proto tp when all filters are gone")
I added a check in u32_destroy() to see if all real filters are gone
for each tp, however, that is only done for root_ht, same is needed
for others.
This can be reproduced by the following tc commands:
tc filter add dev eth0 parent 1:0 prio 5 handle 15: protocol ip u32 divisor 256
tc filter add dev eth0 protocol ip parent 1: prio 5 handle 15:2:2 u32
ht 15:2: match ip src 10.0.0.2 flowid 1:10
tc filter add dev eth0 protocol ip parent 1: prio 5 handle 15:2:3 u32
ht 15:2: match ip src 10.0.0.3 flowid 1:10
Fixes: 1e052be69d04 ("net_sched: destroy proto tp when all filters are gone")
Reported-by: Akshat Kakkar <akshat.1984@gmail.com>
Cc: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: Cong Wang <cwang@twopensource.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sched')
-rw-r--r-- | net/sched/cls_u32.c | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index cab9e9b43967..4fbb67430ce4 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c | |||
@@ -490,6 +490,19 @@ static bool u32_destroy(struct tcf_proto *tp, bool force) | |||
490 | return false; | 490 | return false; |
491 | } | 491 | } |
492 | } | 492 | } |
493 | |||
494 | if (tp_c->refcnt > 1) | ||
495 | return false; | ||
496 | |||
497 | if (tp_c->refcnt == 1) { | ||
498 | struct tc_u_hnode *ht; | ||
499 | |||
500 | for (ht = rtnl_dereference(tp_c->hlist); | ||
501 | ht; | ||
502 | ht = rtnl_dereference(ht->next)) | ||
503 | if (!ht_empty(ht)) | ||
504 | return false; | ||
505 | } | ||
493 | } | 506 | } |
494 | 507 | ||
495 | if (root_ht && --root_ht->refcnt == 0) | 508 | if (root_ht && --root_ht->refcnt == 0) |