diff options
Diffstat (limited to 'net/sched/sch_sfb.c')
-rw-r--r-- | net/sched/sch_sfb.c | 25 |
1 files changed, 14 insertions, 11 deletions
diff --git a/net/sched/sch_sfb.c b/net/sched/sch_sfb.c index 9b0f7093d970..5819dd82630d 100644 --- a/net/sched/sch_sfb.c +++ b/net/sched/sch_sfb.c | |||
@@ -55,7 +55,7 @@ struct sfb_bins { | |||
55 | 55 | ||
56 | struct sfb_sched_data { | 56 | struct sfb_sched_data { |
57 | struct Qdisc *qdisc; | 57 | struct Qdisc *qdisc; |
58 | struct tcf_proto *filter_list; | 58 | struct tcf_proto __rcu *filter_list; |
59 | unsigned long rehash_interval; | 59 | unsigned long rehash_interval; |
60 | unsigned long warmup_time; /* double buffering warmup time in jiffies */ | 60 | unsigned long warmup_time; /* double buffering warmup time in jiffies */ |
61 | u32 max; | 61 | u32 max; |
@@ -253,13 +253,13 @@ static bool sfb_rate_limit(struct sk_buff *skb, struct sfb_sched_data *q) | |||
253 | return false; | 253 | return false; |
254 | } | 254 | } |
255 | 255 | ||
256 | static bool sfb_classify(struct sk_buff *skb, struct sfb_sched_data *q, | 256 | static bool sfb_classify(struct sk_buff *skb, struct tcf_proto *fl, |
257 | int *qerr, u32 *salt) | 257 | int *qerr, u32 *salt) |
258 | { | 258 | { |
259 | struct tcf_result res; | 259 | struct tcf_result res; |
260 | int result; | 260 | int result; |
261 | 261 | ||
262 | result = tc_classify(skb, q->filter_list, &res); | 262 | result = tc_classify(skb, fl, &res); |
263 | if (result >= 0) { | 263 | if (result >= 0) { |
264 | #ifdef CONFIG_NET_CLS_ACT | 264 | #ifdef CONFIG_NET_CLS_ACT |
265 | switch (result) { | 265 | switch (result) { |
@@ -281,6 +281,7 @@ static int sfb_enqueue(struct sk_buff *skb, struct Qdisc *sch) | |||
281 | 281 | ||
282 | struct sfb_sched_data *q = qdisc_priv(sch); | 282 | struct sfb_sched_data *q = qdisc_priv(sch); |
283 | struct Qdisc *child = q->qdisc; | 283 | struct Qdisc *child = q->qdisc; |
284 | struct tcf_proto *fl; | ||
284 | int i; | 285 | int i; |
285 | u32 p_min = ~0; | 286 | u32 p_min = ~0; |
286 | u32 minqlen = ~0; | 287 | u32 minqlen = ~0; |
@@ -289,7 +290,7 @@ static int sfb_enqueue(struct sk_buff *skb, struct Qdisc *sch) | |||
289 | struct flow_keys keys; | 290 | struct flow_keys keys; |
290 | 291 | ||
291 | if (unlikely(sch->q.qlen >= q->limit)) { | 292 | if (unlikely(sch->q.qlen >= q->limit)) { |
292 | sch->qstats.overlimits++; | 293 | qdisc_qstats_overlimit(sch); |
293 | q->stats.queuedrop++; | 294 | q->stats.queuedrop++; |
294 | goto drop; | 295 | goto drop; |
295 | } | 296 | } |
@@ -306,9 +307,10 @@ static int sfb_enqueue(struct sk_buff *skb, struct Qdisc *sch) | |||
306 | } | 307 | } |
307 | } | 308 | } |
308 | 309 | ||
309 | if (q->filter_list) { | 310 | fl = rcu_dereference_bh(q->filter_list); |
311 | if (fl) { | ||
310 | /* If using external classifiers, get result and record it. */ | 312 | /* If using external classifiers, get result and record it. */ |
311 | if (!sfb_classify(skb, q, &ret, &salt)) | 313 | if (!sfb_classify(skb, fl, &ret, &salt)) |
312 | goto other_drop; | 314 | goto other_drop; |
313 | keys.src = salt; | 315 | keys.src = salt; |
314 | keys.dst = 0; | 316 | keys.dst = 0; |
@@ -346,7 +348,7 @@ static int sfb_enqueue(struct sk_buff *skb, struct Qdisc *sch) | |||
346 | sfb_skb_cb(skb)->hashes[slot] = 0; | 348 | sfb_skb_cb(skb)->hashes[slot] = 0; |
347 | 349 | ||
348 | if (unlikely(minqlen >= q->max)) { | 350 | if (unlikely(minqlen >= q->max)) { |
349 | sch->qstats.overlimits++; | 351 | qdisc_qstats_overlimit(sch); |
350 | q->stats.bucketdrop++; | 352 | q->stats.bucketdrop++; |
351 | goto drop; | 353 | goto drop; |
352 | } | 354 | } |
@@ -374,7 +376,7 @@ static int sfb_enqueue(struct sk_buff *skb, struct Qdisc *sch) | |||
374 | } | 376 | } |
375 | } | 377 | } |
376 | if (sfb_rate_limit(skb, q)) { | 378 | if (sfb_rate_limit(skb, q)) { |
377 | sch->qstats.overlimits++; | 379 | qdisc_qstats_overlimit(sch); |
378 | q->stats.penaltydrop++; | 380 | q->stats.penaltydrop++; |
379 | goto drop; | 381 | goto drop; |
380 | } | 382 | } |
@@ -409,7 +411,7 @@ enqueue: | |||
409 | increment_qlen(skb, q); | 411 | increment_qlen(skb, q); |
410 | } else if (net_xmit_drop_count(ret)) { | 412 | } else if (net_xmit_drop_count(ret)) { |
411 | q->stats.childdrop++; | 413 | q->stats.childdrop++; |
412 | sch->qstats.drops++; | 414 | qdisc_qstats_drop(sch); |
413 | } | 415 | } |
414 | return ret; | 416 | return ret; |
415 | 417 | ||
@@ -418,7 +420,7 @@ drop: | |||
418 | return NET_XMIT_CN; | 420 | return NET_XMIT_CN; |
419 | other_drop: | 421 | other_drop: |
420 | if (ret & __NET_XMIT_BYPASS) | 422 | if (ret & __NET_XMIT_BYPASS) |
421 | sch->qstats.drops++; | 423 | qdisc_qstats_drop(sch); |
422 | kfree_skb(skb); | 424 | kfree_skb(skb); |
423 | return ret; | 425 | return ret; |
424 | } | 426 | } |
@@ -660,7 +662,8 @@ static void sfb_walk(struct Qdisc *sch, struct qdisc_walker *walker) | |||
660 | } | 662 | } |
661 | } | 663 | } |
662 | 664 | ||
663 | static struct tcf_proto **sfb_find_tcf(struct Qdisc *sch, unsigned long cl) | 665 | static struct tcf_proto __rcu **sfb_find_tcf(struct Qdisc *sch, |
666 | unsigned long cl) | ||
664 | { | 667 | { |
665 | struct sfb_sched_data *q = qdisc_priv(sch); | 668 | struct sfb_sched_data *q = qdisc_priv(sch); |
666 | 669 | ||