diff options
Diffstat (limited to 'include/net/sch_generic.h')
-rw-r--r-- | include/net/sch_generic.h | 60 |
1 files changed, 44 insertions, 16 deletions
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index 04f8556313d5..a9505b6a18e3 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h | |||
@@ -31,10 +31,12 @@ enum qdisc_state_t { | |||
31 | * following bits are only changed while qdisc lock is held | 31 | * following bits are only changed while qdisc lock is held |
32 | */ | 32 | */ |
33 | enum qdisc___state_t { | 33 | enum qdisc___state_t { |
34 | __QDISC___STATE_RUNNING, | 34 | __QDISC___STATE_RUNNING = 1, |
35 | __QDISC___STATE_THROTTLED = 2, | ||
35 | }; | 36 | }; |
36 | 37 | ||
37 | struct qdisc_size_table { | 38 | struct qdisc_size_table { |
39 | struct rcu_head rcu; | ||
38 | struct list_head list; | 40 | struct list_head list; |
39 | struct tc_sizespec szopts; | 41 | struct tc_sizespec szopts; |
40 | int refcnt; | 42 | int refcnt; |
@@ -46,14 +48,13 @@ struct Qdisc { | |||
46 | struct sk_buff * (*dequeue)(struct Qdisc *dev); | 48 | struct sk_buff * (*dequeue)(struct Qdisc *dev); |
47 | unsigned flags; | 49 | unsigned flags; |
48 | #define TCQ_F_BUILTIN 1 | 50 | #define TCQ_F_BUILTIN 1 |
49 | #define TCQ_F_THROTTLED 2 | 51 | #define TCQ_F_INGRESS 2 |
50 | #define TCQ_F_INGRESS 4 | 52 | #define TCQ_F_CAN_BYPASS 4 |
51 | #define TCQ_F_CAN_BYPASS 8 | 53 | #define TCQ_F_MQROOT 8 |
52 | #define TCQ_F_MQROOT 16 | ||
53 | #define TCQ_F_WARN_NONWC (1 << 16) | 54 | #define TCQ_F_WARN_NONWC (1 << 16) |
54 | int padded; | 55 | int padded; |
55 | struct Qdisc_ops *ops; | 56 | struct Qdisc_ops *ops; |
56 | struct qdisc_size_table *stab; | 57 | struct qdisc_size_table __rcu *stab; |
57 | struct list_head list; | 58 | struct list_head list; |
58 | u32 handle; | 59 | u32 handle; |
59 | u32 parent; | 60 | u32 parent; |
@@ -78,25 +79,44 @@ struct Qdisc { | |||
78 | unsigned long state; | 79 | unsigned long state; |
79 | struct sk_buff_head q; | 80 | struct sk_buff_head q; |
80 | struct gnet_stats_basic_packed bstats; | 81 | struct gnet_stats_basic_packed bstats; |
81 | unsigned long __state; | 82 | unsigned int __state; |
82 | struct gnet_stats_queue qstats; | 83 | struct gnet_stats_queue qstats; |
83 | struct rcu_head rcu_head; | 84 | struct rcu_head rcu_head; |
84 | spinlock_t busylock; | 85 | spinlock_t busylock; |
86 | u32 limit; | ||
85 | }; | 87 | }; |
86 | 88 | ||
87 | static inline bool qdisc_is_running(struct Qdisc *qdisc) | 89 | static inline bool qdisc_is_running(const struct Qdisc *qdisc) |
88 | { | 90 | { |
89 | return test_bit(__QDISC___STATE_RUNNING, &qdisc->__state); | 91 | return (qdisc->__state & __QDISC___STATE_RUNNING) ? true : false; |
90 | } | 92 | } |
91 | 93 | ||
92 | static inline bool qdisc_run_begin(struct Qdisc *qdisc) | 94 | static inline bool qdisc_run_begin(struct Qdisc *qdisc) |
93 | { | 95 | { |
94 | return !__test_and_set_bit(__QDISC___STATE_RUNNING, &qdisc->__state); | 96 | if (qdisc_is_running(qdisc)) |
97 | return false; | ||
98 | qdisc->__state |= __QDISC___STATE_RUNNING; | ||
99 | return true; | ||
95 | } | 100 | } |
96 | 101 | ||
97 | static inline void qdisc_run_end(struct Qdisc *qdisc) | 102 | static inline void qdisc_run_end(struct Qdisc *qdisc) |
98 | { | 103 | { |
99 | __clear_bit(__QDISC___STATE_RUNNING, &qdisc->__state); | 104 | qdisc->__state &= ~__QDISC___STATE_RUNNING; |
105 | } | ||
106 | |||
107 | static inline bool qdisc_is_throttled(const struct Qdisc *qdisc) | ||
108 | { | ||
109 | return (qdisc->__state & __QDISC___STATE_THROTTLED) ? true : false; | ||
110 | } | ||
111 | |||
112 | static inline void qdisc_throttled(struct Qdisc *qdisc) | ||
113 | { | ||
114 | qdisc->__state |= __QDISC___STATE_THROTTLED; | ||
115 | } | ||
116 | |||
117 | static inline void qdisc_unthrottled(struct Qdisc *qdisc) | ||
118 | { | ||
119 | qdisc->__state &= ~__QDISC___STATE_THROTTLED; | ||
100 | } | 120 | } |
101 | 121 | ||
102 | struct Qdisc_class_ops { | 122 | struct Qdisc_class_ops { |
@@ -331,8 +351,8 @@ extern struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue, | |||
331 | struct Qdisc_ops *ops); | 351 | struct Qdisc_ops *ops); |
332 | extern struct Qdisc *qdisc_create_dflt(struct netdev_queue *dev_queue, | 352 | extern struct Qdisc *qdisc_create_dflt(struct netdev_queue *dev_queue, |
333 | struct Qdisc_ops *ops, u32 parentid); | 353 | struct Qdisc_ops *ops, u32 parentid); |
334 | extern void qdisc_calculate_pkt_len(struct sk_buff *skb, | 354 | extern void __qdisc_calculate_pkt_len(struct sk_buff *skb, |
335 | struct qdisc_size_table *stab); | 355 | const struct qdisc_size_table *stab); |
336 | extern void tcf_destroy(struct tcf_proto *tp); | 356 | extern void tcf_destroy(struct tcf_proto *tp); |
337 | extern void tcf_destroy_chain(struct tcf_proto **fl); | 357 | extern void tcf_destroy_chain(struct tcf_proto **fl); |
338 | 358 | ||
@@ -411,12 +431,20 @@ enum net_xmit_qdisc_t { | |||
411 | #define net_xmit_drop_count(e) (1) | 431 | #define net_xmit_drop_count(e) (1) |
412 | #endif | 432 | #endif |
413 | 433 | ||
414 | static inline int qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch) | 434 | static inline void qdisc_calculate_pkt_len(struct sk_buff *skb, |
435 | const struct Qdisc *sch) | ||
415 | { | 436 | { |
416 | #ifdef CONFIG_NET_SCHED | 437 | #ifdef CONFIG_NET_SCHED |
417 | if (sch->stab) | 438 | struct qdisc_size_table *stab = rcu_dereference_bh(sch->stab); |
418 | qdisc_calculate_pkt_len(skb, sch->stab); | 439 | |
440 | if (stab) | ||
441 | __qdisc_calculate_pkt_len(skb, stab); | ||
419 | #endif | 442 | #endif |
443 | } | ||
444 | |||
445 | static inline int qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch) | ||
446 | { | ||
447 | qdisc_calculate_pkt_len(skb, sch); | ||
420 | return sch->enqueue(skb, sch); | 448 | return sch->enqueue(skb, sch); |
421 | } | 449 | } |
422 | 450 | ||