diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-07-28 18:07:55 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-07-28 18:07:55 -0400 |
commit | cb28a1bbdb4790378e7366d6c9ee1d2340b84f92 (patch) | |
tree | 316436f77dac75335fd2c3ef5f109e71606c50d3 /include/net/sch_generic.h | |
parent | b6d4f7e3ef25beb8c658c97867d98883e69dc544 (diff) | |
parent | f934fb19ef34730263e6afc01e8ec27a8a71470f (diff) |
Merge branch 'linus' into core/generic-dma-coherent
Conflicts:
arch/x86/Kconfig
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'include/net/sch_generic.h')
-rw-r--r-- | include/net/sch_generic.h | 198 |
1 files changed, 182 insertions, 16 deletions
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index a87fc0312edc..b5f40d7ef724 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h | |||
@@ -23,6 +23,19 @@ struct qdisc_rate_table | |||
23 | int refcnt; | 23 | int refcnt; |
24 | }; | 24 | }; |
25 | 25 | ||
26 | enum qdisc_state_t | ||
27 | { | ||
28 | __QDISC_STATE_RUNNING, | ||
29 | __QDISC_STATE_SCHED, | ||
30 | }; | ||
31 | |||
32 | struct qdisc_size_table { | ||
33 | struct list_head list; | ||
34 | struct tc_sizespec szopts; | ||
35 | int refcnt; | ||
36 | u16 data[]; | ||
37 | }; | ||
38 | |||
26 | struct Qdisc | 39 | struct Qdisc |
27 | { | 40 | { |
28 | int (*enqueue)(struct sk_buff *skb, struct Qdisc *dev); | 41 | int (*enqueue)(struct sk_buff *skb, struct Qdisc *dev); |
@@ -33,21 +46,26 @@ struct Qdisc | |||
33 | #define TCQ_F_INGRESS 4 | 46 | #define TCQ_F_INGRESS 4 |
34 | int padded; | 47 | int padded; |
35 | struct Qdisc_ops *ops; | 48 | struct Qdisc_ops *ops; |
49 | struct qdisc_size_table *stab; | ||
36 | u32 handle; | 50 | u32 handle; |
37 | u32 parent; | 51 | u32 parent; |
38 | atomic_t refcnt; | 52 | atomic_t refcnt; |
53 | unsigned long state; | ||
54 | struct sk_buff *gso_skb; | ||
39 | struct sk_buff_head q; | 55 | struct sk_buff_head q; |
40 | struct net_device *dev; | 56 | struct netdev_queue *dev_queue; |
57 | struct Qdisc *next_sched; | ||
41 | struct list_head list; | 58 | struct list_head list; |
42 | 59 | ||
43 | struct gnet_stats_basic bstats; | 60 | struct gnet_stats_basic bstats; |
44 | struct gnet_stats_queue qstats; | 61 | struct gnet_stats_queue qstats; |
45 | struct gnet_stats_rate_est rate_est; | 62 | struct gnet_stats_rate_est rate_est; |
46 | spinlock_t *stats_lock; | ||
47 | struct rcu_head q_rcu; | 63 | struct rcu_head q_rcu; |
48 | int (*reshape_fail)(struct sk_buff *skb, | 64 | int (*reshape_fail)(struct sk_buff *skb, |
49 | struct Qdisc *q); | 65 | struct Qdisc *q); |
50 | 66 | ||
67 | void *u32_node; | ||
68 | |||
51 | /* This field is deprecated, but it is still used by CBQ | 69 | /* This field is deprecated, but it is still used by CBQ |
52 | * and it will live until better solution will be invented. | 70 | * and it will live until better solution will be invented. |
53 | */ | 71 | */ |
@@ -155,18 +173,96 @@ struct tcf_proto | |||
155 | struct tcf_proto_ops *ops; | 173 | struct tcf_proto_ops *ops; |
156 | }; | 174 | }; |
157 | 175 | ||
176 | struct qdisc_skb_cb { | ||
177 | unsigned int pkt_len; | ||
178 | char data[]; | ||
179 | }; | ||
180 | |||
181 | static inline struct qdisc_skb_cb *qdisc_skb_cb(struct sk_buff *skb) | ||
182 | { | ||
183 | return (struct qdisc_skb_cb *)skb->cb; | ||
184 | } | ||
158 | 185 | ||
159 | extern void qdisc_lock_tree(struct net_device *dev); | 186 | static inline spinlock_t *qdisc_lock(struct Qdisc *qdisc) |
160 | extern void qdisc_unlock_tree(struct net_device *dev); | 187 | { |
188 | return &qdisc->q.lock; | ||
189 | } | ||
161 | 190 | ||
162 | #define sch_tree_lock(q) qdisc_lock_tree((q)->dev) | 191 | static inline struct Qdisc *qdisc_root(struct Qdisc *qdisc) |
163 | #define sch_tree_unlock(q) qdisc_unlock_tree((q)->dev) | 192 | { |
164 | #define tcf_tree_lock(tp) qdisc_lock_tree((tp)->q->dev) | 193 | return qdisc->dev_queue->qdisc; |
165 | #define tcf_tree_unlock(tp) qdisc_unlock_tree((tp)->q->dev) | 194 | } |
195 | |||
196 | static inline spinlock_t *qdisc_root_lock(struct Qdisc *qdisc) | ||
197 | { | ||
198 | struct Qdisc *root = qdisc_root(qdisc); | ||
199 | |||
200 | return qdisc_lock(root); | ||
201 | } | ||
202 | |||
203 | static inline struct net_device *qdisc_dev(struct Qdisc *qdisc) | ||
204 | { | ||
205 | return qdisc->dev_queue->dev; | ||
206 | } | ||
207 | |||
208 | static inline void sch_tree_lock(struct Qdisc *q) | ||
209 | { | ||
210 | spin_lock_bh(qdisc_root_lock(q)); | ||
211 | } | ||
212 | |||
213 | static inline void sch_tree_unlock(struct Qdisc *q) | ||
214 | { | ||
215 | spin_unlock_bh(qdisc_root_lock(q)); | ||
216 | } | ||
217 | |||
218 | #define tcf_tree_lock(tp) sch_tree_lock((tp)->q) | ||
219 | #define tcf_tree_unlock(tp) sch_tree_unlock((tp)->q) | ||
166 | 220 | ||
167 | extern struct Qdisc noop_qdisc; | 221 | extern struct Qdisc noop_qdisc; |
168 | extern struct Qdisc_ops noop_qdisc_ops; | 222 | extern struct Qdisc_ops noop_qdisc_ops; |
169 | 223 | ||
224 | struct Qdisc_class_common | ||
225 | { | ||
226 | u32 classid; | ||
227 | struct hlist_node hnode; | ||
228 | }; | ||
229 | |||
230 | struct Qdisc_class_hash | ||
231 | { | ||
232 | struct hlist_head *hash; | ||
233 | unsigned int hashsize; | ||
234 | unsigned int hashmask; | ||
235 | unsigned int hashelems; | ||
236 | }; | ||
237 | |||
238 | static inline unsigned int qdisc_class_hash(u32 id, u32 mask) | ||
239 | { | ||
240 | id ^= id >> 8; | ||
241 | id ^= id >> 4; | ||
242 | return id & mask; | ||
243 | } | ||
244 | |||
245 | static inline struct Qdisc_class_common * | ||
246 | qdisc_class_find(struct Qdisc_class_hash *hash, u32 id) | ||
247 | { | ||
248 | struct Qdisc_class_common *cl; | ||
249 | struct hlist_node *n; | ||
250 | unsigned int h; | ||
251 | |||
252 | h = qdisc_class_hash(id, hash->hashmask); | ||
253 | hlist_for_each_entry(cl, n, &hash->hash[h], hnode) { | ||
254 | if (cl->classid == id) | ||
255 | return cl; | ||
256 | } | ||
257 | return NULL; | ||
258 | } | ||
259 | |||
260 | extern int qdisc_class_hash_init(struct Qdisc_class_hash *); | ||
261 | extern void qdisc_class_hash_insert(struct Qdisc_class_hash *, struct Qdisc_class_common *); | ||
262 | extern void qdisc_class_hash_remove(struct Qdisc_class_hash *, struct Qdisc_class_common *); | ||
263 | extern void qdisc_class_hash_grow(struct Qdisc *, struct Qdisc_class_hash *); | ||
264 | extern void qdisc_class_hash_destroy(struct Qdisc_class_hash *); | ||
265 | |||
170 | extern void dev_init_scheduler(struct net_device *dev); | 266 | extern void dev_init_scheduler(struct net_device *dev); |
171 | extern void dev_shutdown(struct net_device *dev); | 267 | extern void dev_shutdown(struct net_device *dev); |
172 | extern void dev_activate(struct net_device *dev); | 268 | extern void dev_activate(struct net_device *dev); |
@@ -174,18 +270,88 @@ extern void dev_deactivate(struct net_device *dev); | |||
174 | extern void qdisc_reset(struct Qdisc *qdisc); | 270 | extern void qdisc_reset(struct Qdisc *qdisc); |
175 | extern void qdisc_destroy(struct Qdisc *qdisc); | 271 | extern void qdisc_destroy(struct Qdisc *qdisc); |
176 | extern void qdisc_tree_decrease_qlen(struct Qdisc *qdisc, unsigned int n); | 272 | extern void qdisc_tree_decrease_qlen(struct Qdisc *qdisc, unsigned int n); |
177 | extern struct Qdisc *qdisc_alloc(struct net_device *dev, struct Qdisc_ops *ops); | 273 | extern struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue, |
274 | struct Qdisc_ops *ops); | ||
178 | extern struct Qdisc *qdisc_create_dflt(struct net_device *dev, | 275 | extern struct Qdisc *qdisc_create_dflt(struct net_device *dev, |
276 | struct netdev_queue *dev_queue, | ||
179 | struct Qdisc_ops *ops, u32 parentid); | 277 | struct Qdisc_ops *ops, u32 parentid); |
278 | extern void qdisc_calculate_pkt_len(struct sk_buff *skb, | ||
279 | struct qdisc_size_table *stab); | ||
180 | extern void tcf_destroy(struct tcf_proto *tp); | 280 | extern void tcf_destroy(struct tcf_proto *tp); |
181 | extern void tcf_destroy_chain(struct tcf_proto **fl); | 281 | extern void tcf_destroy_chain(struct tcf_proto **fl); |
182 | 282 | ||
283 | /* Reset all TX qdiscs of a device. */ | ||
284 | static inline void qdisc_reset_all_tx(struct net_device *dev) | ||
285 | { | ||
286 | unsigned int i; | ||
287 | for (i = 0; i < dev->num_tx_queues; i++) | ||
288 | qdisc_reset(netdev_get_tx_queue(dev, i)->qdisc); | ||
289 | } | ||
290 | |||
291 | /* Are all TX queues of the device empty? */ | ||
292 | static inline bool qdisc_all_tx_empty(const struct net_device *dev) | ||
293 | { | ||
294 | unsigned int i; | ||
295 | for (i = 0; i < dev->num_tx_queues; i++) { | ||
296 | struct netdev_queue *txq = netdev_get_tx_queue(dev, i); | ||
297 | const struct Qdisc *q = txq->qdisc; | ||
298 | |||
299 | if (q->q.qlen) | ||
300 | return false; | ||
301 | } | ||
302 | return true; | ||
303 | } | ||
304 | |||
305 | /* Are any of the TX qdiscs changing? */ | ||
306 | static inline bool qdisc_tx_changing(struct net_device *dev) | ||
307 | { | ||
308 | unsigned int i; | ||
309 | for (i = 0; i < dev->num_tx_queues; i++) { | ||
310 | struct netdev_queue *txq = netdev_get_tx_queue(dev, i); | ||
311 | if (txq->qdisc != txq->qdisc_sleeping) | ||
312 | return true; | ||
313 | } | ||
314 | return false; | ||
315 | } | ||
316 | |||
317 | /* Is the device using the noop qdisc on all queues? */ | ||
318 | static inline bool qdisc_tx_is_noop(const struct net_device *dev) | ||
319 | { | ||
320 | unsigned int i; | ||
321 | for (i = 0; i < dev->num_tx_queues; i++) { | ||
322 | struct netdev_queue *txq = netdev_get_tx_queue(dev, i); | ||
323 | if (txq->qdisc != &noop_qdisc) | ||
324 | return false; | ||
325 | } | ||
326 | return true; | ||
327 | } | ||
328 | |||
329 | static inline unsigned int qdisc_pkt_len(struct sk_buff *skb) | ||
330 | { | ||
331 | return qdisc_skb_cb(skb)->pkt_len; | ||
332 | } | ||
333 | |||
334 | static inline int qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch) | ||
335 | { | ||
336 | #ifdef CONFIG_NET_SCHED | ||
337 | if (sch->stab) | ||
338 | qdisc_calculate_pkt_len(skb, sch->stab); | ||
339 | #endif | ||
340 | return sch->enqueue(skb, sch); | ||
341 | } | ||
342 | |||
343 | static inline int qdisc_enqueue_root(struct sk_buff *skb, struct Qdisc *sch) | ||
344 | { | ||
345 | qdisc_skb_cb(skb)->pkt_len = skb->len; | ||
346 | return qdisc_enqueue(skb, sch); | ||
347 | } | ||
348 | |||
183 | static inline int __qdisc_enqueue_tail(struct sk_buff *skb, struct Qdisc *sch, | 349 | static inline int __qdisc_enqueue_tail(struct sk_buff *skb, struct Qdisc *sch, |
184 | struct sk_buff_head *list) | 350 | struct sk_buff_head *list) |
185 | { | 351 | { |
186 | __skb_queue_tail(list, skb); | 352 | __skb_queue_tail(list, skb); |
187 | sch->qstats.backlog += skb->len; | 353 | sch->qstats.backlog += qdisc_pkt_len(skb); |
188 | sch->bstats.bytes += skb->len; | 354 | sch->bstats.bytes += qdisc_pkt_len(skb); |
189 | sch->bstats.packets++; | 355 | sch->bstats.packets++; |
190 | 356 | ||
191 | return NET_XMIT_SUCCESS; | 357 | return NET_XMIT_SUCCESS; |
@@ -202,7 +368,7 @@ static inline struct sk_buff *__qdisc_dequeue_head(struct Qdisc *sch, | |||
202 | struct sk_buff *skb = __skb_dequeue(list); | 368 | struct sk_buff *skb = __skb_dequeue(list); |
203 | 369 | ||
204 | if (likely(skb != NULL)) | 370 | if (likely(skb != NULL)) |
205 | sch->qstats.backlog -= skb->len; | 371 | sch->qstats.backlog -= qdisc_pkt_len(skb); |
206 | 372 | ||
207 | return skb; | 373 | return skb; |
208 | } | 374 | } |
@@ -218,7 +384,7 @@ static inline struct sk_buff *__qdisc_dequeue_tail(struct Qdisc *sch, | |||
218 | struct sk_buff *skb = __skb_dequeue_tail(list); | 384 | struct sk_buff *skb = __skb_dequeue_tail(list); |
219 | 385 | ||
220 | if (likely(skb != NULL)) | 386 | if (likely(skb != NULL)) |
221 | sch->qstats.backlog -= skb->len; | 387 | sch->qstats.backlog -= qdisc_pkt_len(skb); |
222 | 388 | ||
223 | return skb; | 389 | return skb; |
224 | } | 390 | } |
@@ -232,7 +398,7 @@ static inline int __qdisc_requeue(struct sk_buff *skb, struct Qdisc *sch, | |||
232 | struct sk_buff_head *list) | 398 | struct sk_buff_head *list) |
233 | { | 399 | { |
234 | __skb_queue_head(list, skb); | 400 | __skb_queue_head(list, skb); |
235 | sch->qstats.backlog += skb->len; | 401 | sch->qstats.backlog += qdisc_pkt_len(skb); |
236 | sch->qstats.requeues++; | 402 | sch->qstats.requeues++; |
237 | 403 | ||
238 | return NET_XMIT_SUCCESS; | 404 | return NET_XMIT_SUCCESS; |
@@ -250,7 +416,7 @@ static inline void __qdisc_reset_queue(struct Qdisc *sch, | |||
250 | * We do not know the backlog in bytes of this list, it | 416 | * We do not know the backlog in bytes of this list, it |
251 | * is up to the caller to correct it | 417 | * is up to the caller to correct it |
252 | */ | 418 | */ |
253 | skb_queue_purge(list); | 419 | __skb_queue_purge(list); |
254 | } | 420 | } |
255 | 421 | ||
256 | static inline void qdisc_reset_queue(struct Qdisc *sch) | 422 | static inline void qdisc_reset_queue(struct Qdisc *sch) |
@@ -265,7 +431,7 @@ static inline unsigned int __qdisc_queue_drop(struct Qdisc *sch, | |||
265 | struct sk_buff *skb = __qdisc_dequeue_tail(sch, list); | 431 | struct sk_buff *skb = __qdisc_dequeue_tail(sch, list); |
266 | 432 | ||
267 | if (likely(skb != NULL)) { | 433 | if (likely(skb != NULL)) { |
268 | unsigned int len = skb->len; | 434 | unsigned int len = qdisc_pkt_len(skb); |
269 | kfree_skb(skb); | 435 | kfree_skb(skb); |
270 | return len; | 436 | return len; |
271 | } | 437 | } |