aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched
diff options
context:
space:
mode:
authorJohn Fastabend <john.fastabend@gmail.com>2014-09-12 23:09:16 -0400
committerDavid S. Miller <davem@davemloft.net>2014-09-13 12:30:26 -0400
commit1ce87720d456e471de0fbd814dc5d1fe10fc1c44 (patch)
treef4c7e4870211b78e1626f57deecfafff5622907a /net/sched
parent459d5f626da75573e985a7197b0919c3b143146c (diff)
net: sched: make cls_u32 lockless
Make cls_u32 classifier safe to run without holding lock. This patch converts statistics that are kept in read section u32_classify into per cpu counters. This patch was tested with a tight u32 filter add/delete loop while generating traffic with pktgen. By running pktgen on vlan devices created on top of a physical device we can hit the qdisc layer correctly. For ingress qdisc's a loopback cable was used. for i in {1..100}; do q=`echo $i%8|bc`; echo -n "u32 tos: iteration $i on queue $q"; tc filter add dev p3p2 parent $p prio $i u32 match ip tos 0x10 0xff \ action skbedit queue_mapping $q; sleep 1; tc filter del dev p3p2 prio $i; echo -n "u32 tos hash table: iteration $i on queue $q"; tc filter add dev p3p2 parent $p protocol ip prio $i handle 628: u32 divisor 1 tc filter add dev p3p2 parent $p protocol ip prio $i u32 \ match ip protocol 17 0xff link 628: offset at 0 mask 0xf00 shift 6 plus 0 tc filter add dev p3p2 parent $p protocol ip prio $i u32 \ ht 628:0 match ip tos 0x10 0xff action skbedit queue_mapping $q sleep 2; tc filter del dev p3p2 prio $i sleep 1; done Signed-off-by: John Fastabend <john.r.fastabend@intel.com> Acked-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sched')
-rw-r--r--net/sched/cls_u32.c183
1 files changed, 110 insertions, 73 deletions
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index f3227d73a7ae..5ed5ac4361b1 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -36,6 +36,7 @@
36#include <linux/kernel.h> 36#include <linux/kernel.h>
37#include <linux/string.h> 37#include <linux/string.h>
38#include <linux/errno.h> 38#include <linux/errno.h>
39#include <linux/percpu.h>
39#include <linux/rtnetlink.h> 40#include <linux/rtnetlink.h>
40#include <linux/skbuff.h> 41#include <linux/skbuff.h>
41#include <linux/bitmap.h> 42#include <linux/bitmap.h>
@@ -44,16 +45,16 @@
44#include <net/pkt_cls.h> 45#include <net/pkt_cls.h>
45 46
46struct tc_u_knode { 47struct tc_u_knode {
47 struct tc_u_knode *next; 48 struct tc_u_knode __rcu *next;
48 u32 handle; 49 u32 handle;
49 struct tc_u_hnode *ht_up; 50 struct tc_u_hnode __rcu *ht_up;
50 struct tcf_exts exts; 51 struct tcf_exts exts;
51#ifdef CONFIG_NET_CLS_IND 52#ifdef CONFIG_NET_CLS_IND
52 int ifindex; 53 int ifindex;
53#endif 54#endif
54 u8 fshift; 55 u8 fshift;
55 struct tcf_result res; 56 struct tcf_result res;
56 struct tc_u_hnode *ht_down; 57 struct tc_u_hnode __rcu *ht_down;
57#ifdef CONFIG_CLS_U32_PERF 58#ifdef CONFIG_CLS_U32_PERF
58 struct tc_u32_pcnt __percpu *pf; 59 struct tc_u32_pcnt __percpu *pf;
59#endif 60#endif
@@ -62,24 +63,28 @@ struct tc_u_knode {
62 u32 mask; 63 u32 mask;
63 u32 __percpu *pcpu_success; 64 u32 __percpu *pcpu_success;
64#endif 65#endif
66 struct tcf_proto *tp;
65 struct tc_u32_sel sel; 67 struct tc_u32_sel sel;
68 struct rcu_head rcu;
66}; 69};
67 70
68struct tc_u_hnode { 71struct tc_u_hnode {
69 struct tc_u_hnode *next; 72 struct tc_u_hnode __rcu *next;
70 u32 handle; 73 u32 handle;
71 u32 prio; 74 u32 prio;
72 struct tc_u_common *tp_c; 75 struct tc_u_common *tp_c;
73 int refcnt; 76 int refcnt;
74 unsigned int divisor; 77 unsigned int divisor;
75 struct tc_u_knode *ht[1]; 78 struct tc_u_knode __rcu *ht[1];
79 struct rcu_head rcu;
76}; 80};
77 81
78struct tc_u_common { 82struct tc_u_common {
79 struct tc_u_hnode *hlist; 83 struct tc_u_hnode __rcu *hlist;
80 struct Qdisc *q; 84 struct Qdisc *q;
81 int refcnt; 85 int refcnt;
82 u32 hgenerator; 86 u32 hgenerator;
87 struct rcu_head rcu;
83}; 88};
84 89
85static inline unsigned int u32_hash_fold(__be32 key, 90static inline unsigned int u32_hash_fold(__be32 key,
@@ -98,7 +103,7 @@ static int u32_classify(struct sk_buff *skb, const struct tcf_proto *tp, struct
98 unsigned int off; 103 unsigned int off;
99 } stack[TC_U32_MAXDEPTH]; 104 } stack[TC_U32_MAXDEPTH];
100 105
101 struct tc_u_hnode *ht = tp->root; 106 struct tc_u_hnode *ht = rcu_dereference_bh(tp->root);
102 unsigned int off = skb_network_offset(skb); 107 unsigned int off = skb_network_offset(skb);
103 struct tc_u_knode *n; 108 struct tc_u_knode *n;
104 int sdepth = 0; 109 int sdepth = 0;
@@ -110,7 +115,7 @@ static int u32_classify(struct sk_buff *skb, const struct tcf_proto *tp, struct
110 int i, r; 115 int i, r;
111 116
112next_ht: 117next_ht:
113 n = ht->ht[sel]; 118 n = rcu_dereference_bh(ht->ht[sel]);
114 119
115next_knode: 120next_knode:
116 if (n) { 121 if (n) {
@@ -123,7 +128,7 @@ next_knode:
123 128
124#ifdef CONFIG_CLS_U32_MARK 129#ifdef CONFIG_CLS_U32_MARK
125 if ((skb->mark & n->mask) != n->val) { 130 if ((skb->mark & n->mask) != n->val) {
126 n = n->next; 131 n = rcu_dereference_bh(n->next);
127 goto next_knode; 132 goto next_knode;
128 } else { 133 } else {
129 __this_cpu_inc(*n->pcpu_success); 134 __this_cpu_inc(*n->pcpu_success);
@@ -141,7 +146,7 @@ next_knode:
141 if (!data) 146 if (!data)
142 goto out; 147 goto out;
143 if ((*data ^ key->val) & key->mask) { 148 if ((*data ^ key->val) & key->mask) {
144 n = n->next; 149 n = rcu_dereference_bh(n->next);
145 goto next_knode; 150 goto next_knode;
146 } 151 }
147#ifdef CONFIG_CLS_U32_PERF 152#ifdef CONFIG_CLS_U32_PERF
@@ -149,14 +154,16 @@ next_knode:
149 j++; 154 j++;
150#endif 155#endif
151 } 156 }
152 if (n->ht_down == NULL) { 157
158 ht = rcu_dereference_bh(n->ht_down);
159 if (!ht) {
153check_terminal: 160check_terminal:
154 if (n->sel.flags & TC_U32_TERMINAL) { 161 if (n->sel.flags & TC_U32_TERMINAL) {
155 162
156 *res = n->res; 163 *res = n->res;
157#ifdef CONFIG_NET_CLS_IND 164#ifdef CONFIG_NET_CLS_IND
158 if (!tcf_match_indev(skb, n->ifindex)) { 165 if (!tcf_match_indev(skb, n->ifindex)) {
159 n = n->next; 166 n = rcu_dereference_bh(n->next);
160 goto next_knode; 167 goto next_knode;
161 } 168 }
162#endif 169#endif
@@ -165,13 +172,13 @@ check_terminal:
165#endif 172#endif
166 r = tcf_exts_exec(skb, &n->exts, res); 173 r = tcf_exts_exec(skb, &n->exts, res);
167 if (r < 0) { 174 if (r < 0) {
168 n = n->next; 175 n = rcu_dereference_bh(n->next);
169 goto next_knode; 176 goto next_knode;
170 } 177 }
171 178
172 return r; 179 return r;
173 } 180 }
174 n = n->next; 181 n = rcu_dereference_bh(n->next);
175 goto next_knode; 182 goto next_knode;
176 } 183 }
177 184
@@ -182,7 +189,7 @@ check_terminal:
182 stack[sdepth].off = off; 189 stack[sdepth].off = off;
183 sdepth++; 190 sdepth++;
184 191
185 ht = n->ht_down; 192 ht = rcu_dereference_bh(n->ht_down);
186 sel = 0; 193 sel = 0;
187 if (ht->divisor) { 194 if (ht->divisor) {
188 __be32 *data, hdata; 195 __be32 *data, hdata;
@@ -224,7 +231,7 @@ check_terminal:
224 /* POP */ 231 /* POP */
225 if (sdepth--) { 232 if (sdepth--) {
226 n = stack[sdepth].knode; 233 n = stack[sdepth].knode;
227 ht = n->ht_up; 234 ht = rcu_dereference_bh(n->ht_up);
228 off = stack[sdepth].off; 235 off = stack[sdepth].off;
229 goto check_terminal; 236 goto check_terminal;
230 } 237 }
@@ -241,7 +248,9 @@ u32_lookup_ht(struct tc_u_common *tp_c, u32 handle)
241{ 248{
242 struct tc_u_hnode *ht; 249 struct tc_u_hnode *ht;
243 250
244 for (ht = tp_c->hlist; ht; ht = ht->next) 251 for (ht = rtnl_dereference(tp_c->hlist);
252 ht;
253 ht = rtnl_dereference(ht->next))
245 if (ht->handle == handle) 254 if (ht->handle == handle)
246 break; 255 break;
247 256
@@ -258,7 +267,9 @@ u32_lookup_key(struct tc_u_hnode *ht, u32 handle)
258 if (sel > ht->divisor) 267 if (sel > ht->divisor)
259 goto out; 268 goto out;
260 269
261 for (n = ht->ht[sel]; n; n = n->next) 270 for (n = rtnl_dereference(ht->ht[sel]);
271 n;
272 n = rtnl_dereference(n->next))
262 if (n->handle == handle) 273 if (n->handle == handle)
263 break; 274 break;
264out: 275out:
@@ -272,7 +283,7 @@ static unsigned long u32_get(struct tcf_proto *tp, u32 handle)
272 struct tc_u_common *tp_c = tp->data; 283 struct tc_u_common *tp_c = tp->data;
273 284
274 if (TC_U32_HTID(handle) == TC_U32_ROOT) 285 if (TC_U32_HTID(handle) == TC_U32_ROOT)
275 ht = tp->root; 286 ht = rtnl_dereference(tp->root);
276 else 287 else
277 ht = u32_lookup_ht(tp_c, TC_U32_HTID(handle)); 288 ht = u32_lookup_ht(tp_c, TC_U32_HTID(handle));
278 289
@@ -293,6 +304,9 @@ static u32 gen_new_htid(struct tc_u_common *tp_c)
293{ 304{
294 int i = 0x800; 305 int i = 0x800;
295 306
307 /* hgenerator only used inside rtnl lock it is safe to increment
308 * without read _copy_ update semantics
309 */
296 do { 310 do {
297 if (++tp_c->hgenerator == 0x7FF) 311 if (++tp_c->hgenerator == 0x7FF)
298 tp_c->hgenerator = 1; 312 tp_c->hgenerator = 1;
@@ -328,11 +342,11 @@ static int u32_init(struct tcf_proto *tp)
328 } 342 }
329 343
330 tp_c->refcnt++; 344 tp_c->refcnt++;
331 root_ht->next = tp_c->hlist; 345 RCU_INIT_POINTER(root_ht->next, tp_c->hlist);
332 tp_c->hlist = root_ht; 346 rcu_assign_pointer(tp_c->hlist, root_ht);
333 root_ht->tp_c = tp_c; 347 root_ht->tp_c = tp_c;
334 348
335 tp->root = root_ht; 349 rcu_assign_pointer(tp->root, root_ht);
336 tp->data = tp_c; 350 tp->data = tp_c;
337 return 0; 351 return 0;
338} 352}
@@ -350,19 +364,27 @@ static int u32_destroy_key(struct tcf_proto *tp, struct tc_u_knode *n)
350 return 0; 364 return 0;
351} 365}
352 366
367static void u32_delete_key_rcu(struct rcu_head *rcu)
368{
369 struct tc_u_knode *key = container_of(rcu, struct tc_u_knode, rcu);
370
371 u32_destroy_key(key->tp, key);
372}
373
353static int u32_delete_key(struct tcf_proto *tp, struct tc_u_knode *key) 374static int u32_delete_key(struct tcf_proto *tp, struct tc_u_knode *key)
354{ 375{
355 struct tc_u_knode **kp; 376 struct tc_u_knode __rcu **kp;
377 struct tc_u_knode *pkp;
356 struct tc_u_hnode *ht = key->ht_up; 378 struct tc_u_hnode *ht = key->ht_up;
357 379
358 if (ht) { 380 if (ht) {
359 for (kp = &ht->ht[TC_U32_HASH(key->handle)]; *kp; kp = &(*kp)->next) { 381 kp = &ht->ht[TC_U32_HASH(key->handle)];
360 if (*kp == key) { 382 for (pkp = rtnl_dereference(*kp); pkp;
361 tcf_tree_lock(tp); 383 kp = &pkp->next, pkp = rtnl_dereference(*kp)) {
362 *kp = key->next; 384 if (pkp == key) {
363 tcf_tree_unlock(tp); 385 RCU_INIT_POINTER(*kp, key->next);
364 386
365 u32_destroy_key(tp, key); 387 call_rcu(&key->rcu, u32_delete_key_rcu);
366 return 0; 388 return 0;
367 } 389 }
368 } 390 }
@@ -371,16 +393,16 @@ static int u32_delete_key(struct tcf_proto *tp, struct tc_u_knode *key)
371 return 0; 393 return 0;
372} 394}
373 395
374static void u32_clear_hnode(struct tcf_proto *tp, struct tc_u_hnode *ht) 396static void u32_clear_hnode(struct tc_u_hnode *ht)
375{ 397{
376 struct tc_u_knode *n; 398 struct tc_u_knode *n;
377 unsigned int h; 399 unsigned int h;
378 400
379 for (h = 0; h <= ht->divisor; h++) { 401 for (h = 0; h <= ht->divisor; h++) {
380 while ((n = ht->ht[h]) != NULL) { 402 while ((n = rtnl_dereference(ht->ht[h])) != NULL) {
381 ht->ht[h] = n->next; 403 RCU_INIT_POINTER(ht->ht[h],
382 404 rtnl_dereference(n->next));
383 u32_destroy_key(tp, n); 405 call_rcu(&n->rcu, u32_delete_key_rcu);
384 } 406 }
385 } 407 }
386} 408}
@@ -388,28 +410,31 @@ static void u32_clear_hnode(struct tcf_proto *tp, struct tc_u_hnode *ht)
388static int u32_destroy_hnode(struct tcf_proto *tp, struct tc_u_hnode *ht) 410static int u32_destroy_hnode(struct tcf_proto *tp, struct tc_u_hnode *ht)
389{ 411{
390 struct tc_u_common *tp_c = tp->data; 412 struct tc_u_common *tp_c = tp->data;
391 struct tc_u_hnode **hn; 413 struct tc_u_hnode __rcu **hn;
414 struct tc_u_hnode *phn;
392 415
393 WARN_ON(ht->refcnt); 416 WARN_ON(ht->refcnt);
394 417
395 u32_clear_hnode(tp, ht); 418 u32_clear_hnode(ht);
396 419
397 for (hn = &tp_c->hlist; *hn; hn = &(*hn)->next) { 420 hn = &tp_c->hlist;
398 if (*hn == ht) { 421 for (phn = rtnl_dereference(*hn);
399 *hn = ht->next; 422 phn;
400 kfree(ht); 423 hn = &phn->next, phn = rtnl_dereference(*hn)) {
424 if (phn == ht) {
425 RCU_INIT_POINTER(*hn, ht->next);
426 kfree_rcu(ht, rcu);
401 return 0; 427 return 0;
402 } 428 }
403 } 429 }
404 430
405 WARN_ON(1);
406 return -ENOENT; 431 return -ENOENT;
407} 432}
408 433
409static void u32_destroy(struct tcf_proto *tp) 434static void u32_destroy(struct tcf_proto *tp)
410{ 435{
411 struct tc_u_common *tp_c = tp->data; 436 struct tc_u_common *tp_c = tp->data;
412 struct tc_u_hnode *root_ht = tp->root; 437 struct tc_u_hnode *root_ht = rtnl_dereference(tp->root);
413 438
414 WARN_ON(root_ht == NULL); 439 WARN_ON(root_ht == NULL);
415 440
@@ -421,17 +446,16 @@ static void u32_destroy(struct tcf_proto *tp)
421 446
422 tp->q->u32_node = NULL; 447 tp->q->u32_node = NULL;
423 448
424 for (ht = tp_c->hlist; ht; ht = ht->next) { 449 for (ht = rtnl_dereference(tp_c->hlist);
450 ht;
451 ht = rtnl_dereference(ht->next)) {
425 ht->refcnt--; 452 ht->refcnt--;
426 u32_clear_hnode(tp, ht); 453 u32_clear_hnode(ht);
427 } 454 }
428 455
429 while ((ht = tp_c->hlist) != NULL) { 456 while ((ht = rtnl_dereference(tp_c->hlist)) != NULL) {
430 tp_c->hlist = ht->next; 457 RCU_INIT_POINTER(tp_c->hlist, ht->next);
431 458 kfree_rcu(ht, rcu);
432 WARN_ON(ht->refcnt != 0);
433
434 kfree(ht);
435 } 459 }
436 460
437 kfree(tp_c); 461 kfree(tp_c);
@@ -443,6 +467,7 @@ static void u32_destroy(struct tcf_proto *tp)
443static int u32_delete(struct tcf_proto *tp, unsigned long arg) 467static int u32_delete(struct tcf_proto *tp, unsigned long arg)
444{ 468{
445 struct tc_u_hnode *ht = (struct tc_u_hnode *)arg; 469 struct tc_u_hnode *ht = (struct tc_u_hnode *)arg;
470 struct tc_u_hnode *root_ht = rtnl_dereference(tp->root);
446 471
447 if (ht == NULL) 472 if (ht == NULL)
448 return 0; 473 return 0;
@@ -450,7 +475,7 @@ static int u32_delete(struct tcf_proto *tp, unsigned long arg)
450 if (TC_U32_KEY(ht->handle)) 475 if (TC_U32_KEY(ht->handle))
451 return u32_delete_key(tp, (struct tc_u_knode *)ht); 476 return u32_delete_key(tp, (struct tc_u_knode *)ht);
452 477
453 if (tp->root == ht) 478 if (root_ht == ht)
454 return -EINVAL; 479 return -EINVAL;
455 480
456 if (ht->refcnt == 1) { 481 if (ht->refcnt == 1) {
@@ -473,7 +498,9 @@ static u32 gen_new_kid(struct tc_u_hnode *ht, u32 handle)
473 if (!bitmap) 498 if (!bitmap)
474 return handle | 0xFFF; 499 return handle | 0xFFF;
475 500
476 for (n = ht->ht[TC_U32_HASH(handle)]; n; n = n->next) 501 for (n = rtnl_dereference(ht->ht[TC_U32_HASH(handle)]);
502 n;
503 n = rtnl_dereference(n->next))
477 set_bit(TC_U32_NODE(n->handle), bitmap); 504 set_bit(TC_U32_NODE(n->handle), bitmap);
478 505
479 i = find_next_zero_bit(bitmap, NR_U32_NODE, 0x800); 506 i = find_next_zero_bit(bitmap, NR_U32_NODE, 0x800);
@@ -523,10 +550,8 @@ static int u32_set_parms(struct net *net, struct tcf_proto *tp,
523 ht_down->refcnt++; 550 ht_down->refcnt++;
524 } 551 }
525 552
526 tcf_tree_lock(tp); 553 ht_old = rtnl_dereference(n->ht_down);
527 ht_old = n->ht_down; 554 rcu_assign_pointer(n->ht_down, ht_down);
528 n->ht_down = ht_down;
529 tcf_tree_unlock(tp);
530 555
531 if (ht_old) 556 if (ht_old)
532 ht_old->refcnt--; 557 ht_old->refcnt--;
@@ -606,8 +631,8 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
606 ht->divisor = divisor; 631 ht->divisor = divisor;
607 ht->handle = handle; 632 ht->handle = handle;
608 ht->prio = tp->prio; 633 ht->prio = tp->prio;
609 ht->next = tp_c->hlist; 634 RCU_INIT_POINTER(ht->next, tp_c->hlist);
610 tp_c->hlist = ht; 635 rcu_assign_pointer(tp_c->hlist, ht);
611 *arg = (unsigned long)ht; 636 *arg = (unsigned long)ht;
612 return 0; 637 return 0;
613 } 638 }
@@ -615,7 +640,7 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
615 if (tb[TCA_U32_HASH]) { 640 if (tb[TCA_U32_HASH]) {
616 htid = nla_get_u32(tb[TCA_U32_HASH]); 641 htid = nla_get_u32(tb[TCA_U32_HASH]);
617 if (TC_U32_HTID(htid) == TC_U32_ROOT) { 642 if (TC_U32_HTID(htid) == TC_U32_ROOT) {
618 ht = tp->root; 643 ht = rtnl_dereference(tp->root);
619 htid = ht->handle; 644 htid = ht->handle;
620 } else { 645 } else {
621 ht = u32_lookup_ht(tp->data, TC_U32_HTID(htid)); 646 ht = u32_lookup_ht(tp->data, TC_U32_HTID(htid));
@@ -623,7 +648,7 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
623 return -EINVAL; 648 return -EINVAL;
624 } 649 }
625 } else { 650 } else {
626 ht = tp->root; 651 ht = rtnl_dereference(tp->root);
627 htid = ht->handle; 652 htid = ht->handle;
628 } 653 }
629 654
@@ -660,6 +685,7 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
660 n->handle = handle; 685 n->handle = handle;
661 n->fshift = s->hmask ? ffs(ntohl(s->hmask)) - 1 : 0; 686 n->fshift = s->hmask ? ffs(ntohl(s->hmask)) - 1 : 0;
662 tcf_exts_init(&n->exts, TCA_U32_ACT, TCA_U32_POLICE); 687 tcf_exts_init(&n->exts, TCA_U32_ACT, TCA_U32_POLICE);
688 n->tp = tp;
663 689
664#ifdef CONFIG_CLS_U32_MARK 690#ifdef CONFIG_CLS_U32_MARK
665 n->pcpu_success = alloc_percpu(u32); 691 n->pcpu_success = alloc_percpu(u32);
@@ -675,21 +701,23 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
675 701
676 err = u32_set_parms(net, tp, base, ht, n, tb, tca[TCA_RATE], ovr); 702 err = u32_set_parms(net, tp, base, ht, n, tb, tca[TCA_RATE], ovr);
677 if (err == 0) { 703 if (err == 0) {
678 struct tc_u_knode **ins; 704 struct tc_u_knode __rcu **ins;
679 for (ins = &ht->ht[TC_U32_HASH(handle)]; *ins; ins = &(*ins)->next) 705 struct tc_u_knode *pins;
680 if (TC_U32_NODE(handle) < TC_U32_NODE((*ins)->handle)) 706
707 ins = &ht->ht[TC_U32_HASH(handle)];
708 for (pins = rtnl_dereference(*ins); pins;
709 ins = &pins->next, pins = rtnl_dereference(*ins))
710 if (TC_U32_NODE(handle) < TC_U32_NODE(pins->handle))
681 break; 711 break;
682 712
683 n->next = *ins; 713 RCU_INIT_POINTER(n->next, pins);
684 tcf_tree_lock(tp); 714 rcu_assign_pointer(*ins, n);
685 *ins = n;
686 tcf_tree_unlock(tp);
687 715
688 *arg = (unsigned long)n; 716 *arg = (unsigned long)n;
689 return 0; 717 return 0;
690 } 718 }
691#ifdef CONFIG_CLS_U32_PERF 719#ifdef CONFIG_CLS_U32_PERF
692 kfree(n->pf); 720 free_percpu(n->pf);
693#endif 721#endif
694 kfree(n); 722 kfree(n);
695 return err; 723 return err;
@@ -705,7 +733,9 @@ static void u32_walk(struct tcf_proto *tp, struct tcf_walker *arg)
705 if (arg->stop) 733 if (arg->stop)
706 return; 734 return;
707 735
708 for (ht = tp_c->hlist; ht; ht = ht->next) { 736 for (ht = rtnl_dereference(tp_c->hlist);
737 ht;
738 ht = rtnl_dereference(ht->next)) {
709 if (ht->prio != tp->prio) 739 if (ht->prio != tp->prio)
710 continue; 740 continue;
711 if (arg->count >= arg->skip) { 741 if (arg->count >= arg->skip) {
@@ -716,7 +746,9 @@ static void u32_walk(struct tcf_proto *tp, struct tcf_walker *arg)
716 } 746 }
717 arg->count++; 747 arg->count++;
718 for (h = 0; h <= ht->divisor; h++) { 748 for (h = 0; h <= ht->divisor; h++) {
719 for (n = ht->ht[h]; n; n = n->next) { 749 for (n = rtnl_dereference(ht->ht[h]);
750 n;
751 n = rtnl_dereference(n->next)) {
720 if (arg->count < arg->skip) { 752 if (arg->count < arg->skip) {
721 arg->count++; 753 arg->count++;
722 continue; 754 continue;
@@ -735,6 +767,7 @@ static int u32_dump(struct net *net, struct tcf_proto *tp, unsigned long fh,
735 struct sk_buff *skb, struct tcmsg *t) 767 struct sk_buff *skb, struct tcmsg *t)
736{ 768{
737 struct tc_u_knode *n = (struct tc_u_knode *)fh; 769 struct tc_u_knode *n = (struct tc_u_knode *)fh;
770 struct tc_u_hnode *ht_up, *ht_down;
738 struct nlattr *nest; 771 struct nlattr *nest;
739 772
740 if (n == NULL) 773 if (n == NULL)
@@ -762,7 +795,9 @@ static int u32_dump(struct net *net, struct tcf_proto *tp, unsigned long fh,
762 sizeof(n->sel) + n->sel.nkeys*sizeof(struct tc_u32_key), 795 sizeof(n->sel) + n->sel.nkeys*sizeof(struct tc_u32_key),
763 &n->sel)) 796 &n->sel))
764 goto nla_put_failure; 797 goto nla_put_failure;
765 if (n->ht_up) { 798
799 ht_up = rtnl_dereference(n->ht_up);
800 if (ht_up) {
766 u32 htid = n->handle & 0xFFFFF000; 801 u32 htid = n->handle & 0xFFFFF000;
767 if (nla_put_u32(skb, TCA_U32_HASH, htid)) 802 if (nla_put_u32(skb, TCA_U32_HASH, htid))
768 goto nla_put_failure; 803 goto nla_put_failure;
@@ -770,8 +805,10 @@ static int u32_dump(struct net *net, struct tcf_proto *tp, unsigned long fh,
770 if (n->res.classid && 805 if (n->res.classid &&
771 nla_put_u32(skb, TCA_U32_CLASSID, n->res.classid)) 806 nla_put_u32(skb, TCA_U32_CLASSID, n->res.classid))
772 goto nla_put_failure; 807 goto nla_put_failure;
773 if (n->ht_down && 808
774 nla_put_u32(skb, TCA_U32_LINK, n->ht_down->handle)) 809 ht_down = rtnl_dereference(n->ht_down);
810 if (ht_down &&
811 nla_put_u32(skb, TCA_U32_LINK, ht_down->handle))
775 goto nla_put_failure; 812 goto nla_put_failure;
776 813
777#ifdef CONFIG_CLS_U32_MARK 814#ifdef CONFIG_CLS_U32_MARK