aboutsummaryrefslogtreecommitdiffstats
path: root/include/net/sch_generic.h
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-07-28 18:07:55 -0400
committerIngo Molnar <mingo@elte.hu>2008-07-28 18:07:55 -0400
commitcb28a1bbdb4790378e7366d6c9ee1d2340b84f92 (patch)
tree316436f77dac75335fd2c3ef5f109e71606c50d3 /include/net/sch_generic.h
parentb6d4f7e3ef25beb8c658c97867d98883e69dc544 (diff)
parentf934fb19ef34730263e6afc01e8ec27a8a71470f (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.h198
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
26enum qdisc_state_t
27{
28 __QDISC_STATE_RUNNING,
29 __QDISC_STATE_SCHED,
30};
31
32struct qdisc_size_table {
33 struct list_head list;
34 struct tc_sizespec szopts;
35 int refcnt;
36 u16 data[];
37};
38
26struct Qdisc 39struct 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
176struct qdisc_skb_cb {
177 unsigned int pkt_len;
178 char data[];
179};
180
181static inline struct qdisc_skb_cb *qdisc_skb_cb(struct sk_buff *skb)
182{
183 return (struct qdisc_skb_cb *)skb->cb;
184}
158 185
159extern void qdisc_lock_tree(struct net_device *dev); 186static inline spinlock_t *qdisc_lock(struct Qdisc *qdisc)
160extern 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) 191static 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
196static 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
203static inline struct net_device *qdisc_dev(struct Qdisc *qdisc)
204{
205 return qdisc->dev_queue->dev;
206}
207
208static inline void sch_tree_lock(struct Qdisc *q)
209{
210 spin_lock_bh(qdisc_root_lock(q));
211}
212
213static 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
167extern struct Qdisc noop_qdisc; 221extern struct Qdisc noop_qdisc;
168extern struct Qdisc_ops noop_qdisc_ops; 222extern struct Qdisc_ops noop_qdisc_ops;
169 223
224struct Qdisc_class_common
225{
226 u32 classid;
227 struct hlist_node hnode;
228};
229
230struct Qdisc_class_hash
231{
232 struct hlist_head *hash;
233 unsigned int hashsize;
234 unsigned int hashmask;
235 unsigned int hashelems;
236};
237
238static 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
245static inline struct Qdisc_class_common *
246qdisc_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
260extern int qdisc_class_hash_init(struct Qdisc_class_hash *);
261extern void qdisc_class_hash_insert(struct Qdisc_class_hash *, struct Qdisc_class_common *);
262extern void qdisc_class_hash_remove(struct Qdisc_class_hash *, struct Qdisc_class_common *);
263extern void qdisc_class_hash_grow(struct Qdisc *, struct Qdisc_class_hash *);
264extern void qdisc_class_hash_destroy(struct Qdisc_class_hash *);
265
170extern void dev_init_scheduler(struct net_device *dev); 266extern void dev_init_scheduler(struct net_device *dev);
171extern void dev_shutdown(struct net_device *dev); 267extern void dev_shutdown(struct net_device *dev);
172extern void dev_activate(struct net_device *dev); 268extern void dev_activate(struct net_device *dev);
@@ -174,18 +270,88 @@ extern void dev_deactivate(struct net_device *dev);
174extern void qdisc_reset(struct Qdisc *qdisc); 270extern void qdisc_reset(struct Qdisc *qdisc);
175extern void qdisc_destroy(struct Qdisc *qdisc); 271extern void qdisc_destroy(struct Qdisc *qdisc);
176extern void qdisc_tree_decrease_qlen(struct Qdisc *qdisc, unsigned int n); 272extern void qdisc_tree_decrease_qlen(struct Qdisc *qdisc, unsigned int n);
177extern struct Qdisc *qdisc_alloc(struct net_device *dev, struct Qdisc_ops *ops); 273extern struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
274 struct Qdisc_ops *ops);
178extern struct Qdisc *qdisc_create_dflt(struct net_device *dev, 275extern 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);
278extern void qdisc_calculate_pkt_len(struct sk_buff *skb,
279 struct qdisc_size_table *stab);
180extern void tcf_destroy(struct tcf_proto *tp); 280extern void tcf_destroy(struct tcf_proto *tp);
181extern void tcf_destroy_chain(struct tcf_proto **fl); 281extern void tcf_destroy_chain(struct tcf_proto **fl);
182 282
283/* Reset all TX qdiscs of a device. */
284static 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? */
292static 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? */
306static 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? */
318static 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
329static inline unsigned int qdisc_pkt_len(struct sk_buff *skb)
330{
331 return qdisc_skb_cb(skb)->pkt_len;
332}
333
334static 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
343static 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
183static inline int __qdisc_enqueue_tail(struct sk_buff *skb, struct Qdisc *sch, 349static 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
256static inline void qdisc_reset_queue(struct Qdisc *sch) 422static 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 }