X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=include%2Fnet%2Fsch_generic.h;h=964ffa0d8815139ae22d351590b5673a4dd38850;hb=e4e72fb4de93e3d4047a4ee3f08778422e17ed0d;hp=84d25f2e6188764931268b5b6b6a3b70e4516c18;hpb=1e0d5a5747772182d1bb2525d8153da640fdfb58;p=safe%2Fjmp%2Flinux-2.6 diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index 84d25f2..964ffa0 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -42,24 +42,17 @@ struct Qdisc int (*enqueue)(struct sk_buff *skb, struct Qdisc *dev); struct sk_buff * (*dequeue)(struct Qdisc *dev); unsigned flags; -#define TCQ_F_BUILTIN 1 -#define TCQ_F_THROTTLED 2 -#define TCQ_F_INGRESS 4 +#define TCQ_F_BUILTIN 1 +#define TCQ_F_THROTTLED 2 +#define TCQ_F_INGRESS 4 +#define TCQ_F_WARN_NONWC (1 << 16) int padded; struct Qdisc_ops *ops; struct qdisc_size_table *stab; + struct list_head list; u32 handle; u32 parent; atomic_t refcnt; - unsigned long state; - struct sk_buff *gso_skb; - struct sk_buff_head q; - struct netdev_queue *dev_queue; - struct Qdisc *next_sched; - struct list_head list; - - struct gnet_stats_basic bstats; - struct gnet_stats_queue qstats; struct gnet_stats_rate_est rate_est; int (*reshape_fail)(struct sk_buff *skb, struct Qdisc *q); @@ -70,6 +63,17 @@ struct Qdisc * and it will live until better solution will be invented. */ struct Qdisc *__parent; + struct netdev_queue *dev_queue; + struct Qdisc *next_sched; + + struct sk_buff *gso_skb; + /* + * For performance sake on SMP, we put highly modified fields at the end + */ + unsigned long state; + struct sk_buff_head q; + struct gnet_stats_basic bstats; + struct gnet_stats_queue qstats; }; struct Qdisc_class_ops @@ -110,7 +114,7 @@ struct Qdisc_ops int (*enqueue)(struct sk_buff *, struct Qdisc *); struct sk_buff * (*dequeue)(struct Qdisc *); - int (*requeue)(struct sk_buff *, struct Qdisc *); + struct sk_buff * (*peek)(struct Qdisc *); unsigned int (*drop)(struct Qdisc *); int (*init)(struct Qdisc *, struct nlattr *arg); @@ -193,6 +197,11 @@ static inline struct Qdisc *qdisc_root(struct Qdisc *qdisc) return qdisc->dev_queue->qdisc; } +static inline struct Qdisc *qdisc_root_sleeping(struct Qdisc *qdisc) +{ + return qdisc->dev_queue->qdisc_sleeping; +} + /* The qdisc root lock is a mechanism by which to top level * of a qdisc tree can be locked from any qdisc node in the * forest. This allows changing the configuration of some @@ -212,6 +221,14 @@ static inline spinlock_t *qdisc_root_lock(struct Qdisc *qdisc) return qdisc_lock(root); } +static inline spinlock_t *qdisc_root_sleeping_lock(struct Qdisc *qdisc) +{ + struct Qdisc *root = qdisc_root_sleeping(qdisc); + + ASSERT_RTNL(); + return qdisc_lock(root); +} + static inline struct net_device *qdisc_dev(struct Qdisc *qdisc) { return qdisc->dev_queue->dev; @@ -219,12 +236,12 @@ static inline struct net_device *qdisc_dev(struct Qdisc *qdisc) static inline void sch_tree_lock(struct Qdisc *q) { - spin_lock_bh(qdisc_root_lock(q)); + spin_lock_bh(qdisc_root_sleeping_lock(q)); } static inline void sch_tree_unlock(struct Qdisc *q) { - spin_unlock_bh(qdisc_root_lock(q)); + spin_unlock_bh(qdisc_root_sleeping_lock(q)); } #define tcf_tree_lock(tp) sch_tree_lock((tp)->q) @@ -418,19 +435,38 @@ static inline struct sk_buff *qdisc_dequeue_tail(struct Qdisc *sch) return __qdisc_dequeue_tail(sch, &sch->q); } -static inline int __qdisc_requeue(struct sk_buff *skb, struct Qdisc *sch, - struct sk_buff_head *list) +static inline struct sk_buff *qdisc_peek_head(struct Qdisc *sch) { - __skb_queue_head(list, skb); - sch->qstats.backlog += qdisc_pkt_len(skb); - sch->qstats.requeues++; + return skb_peek(&sch->q); +} - return NET_XMIT_SUCCESS; +/* generic pseudo peek method for non-work-conserving qdisc */ +static inline struct sk_buff *qdisc_peek_dequeued(struct Qdisc *sch) +{ + /* we can reuse ->gso_skb because peek isn't called for root qdiscs */ + if (!sch->gso_skb) { + sch->gso_skb = sch->dequeue(sch); + if (sch->gso_skb) + /* it's still part of the queue */ + sch->q.qlen++; + } + + return sch->gso_skb; } -static inline int qdisc_requeue(struct sk_buff *skb, struct Qdisc *sch) +/* use instead of qdisc->dequeue() for all qdiscs queried with ->peek() */ +static inline struct sk_buff *qdisc_dequeue_peeked(struct Qdisc *sch) { - return __qdisc_requeue(skb, sch, &sch->q); + struct sk_buff *skb = sch->gso_skb; + + if (skb) { + sch->gso_skb = NULL; + sch->q.qlen--; + } else { + skb = sch->dequeue(sch); + } + + return skb; } static inline void __qdisc_reset_queue(struct Qdisc *sch,