diff options
Diffstat (limited to 'net/sched/sch_generic.c')
-rw-r--r-- | net/sched/sch_generic.c | 40 |
1 files changed, 38 insertions, 2 deletions
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 7c8e5d73d433..797ebef73642 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c | |||
@@ -56,6 +56,35 @@ static inline int dev_requeue_skb(struct sk_buff *skb, struct Qdisc *q) | |||
56 | return 0; | 56 | return 0; |
57 | } | 57 | } |
58 | 58 | ||
59 | static struct sk_buff *try_bulk_dequeue_skb(struct Qdisc *q, | ||
60 | struct sk_buff *head_skb, | ||
61 | int bytelimit) | ||
62 | { | ||
63 | struct sk_buff *skb, *tail_skb = head_skb; | ||
64 | |||
65 | while (bytelimit > 0) { | ||
66 | skb = q->dequeue(q); | ||
67 | if (!skb) | ||
68 | break; | ||
69 | |||
70 | bytelimit -= skb->len; /* covers GSO len */ | ||
71 | skb = validate_xmit_skb(skb, qdisc_dev(q)); | ||
72 | if (!skb) | ||
73 | break; | ||
74 | |||
75 | while (tail_skb->next) /* GSO list goto tail */ | ||
76 | tail_skb = tail_skb->next; | ||
77 | |||
78 | tail_skb->next = skb; | ||
79 | tail_skb = skb; | ||
80 | } | ||
81 | |||
82 | return head_skb; | ||
83 | } | ||
84 | |||
85 | /* Note that dequeue_skb can possibly return a SKB list (via skb->next). | ||
86 | * A requeued skb (via q->gso_skb) can also be a SKB list. | ||
87 | */ | ||
59 | static inline struct sk_buff *dequeue_skb(struct Qdisc *q) | 88 | static inline struct sk_buff *dequeue_skb(struct Qdisc *q) |
60 | { | 89 | { |
61 | struct sk_buff *skb = q->gso_skb; | 90 | struct sk_buff *skb = q->gso_skb; |
@@ -70,10 +99,17 @@ static inline struct sk_buff *dequeue_skb(struct Qdisc *q) | |||
70 | } else | 99 | } else |
71 | skb = NULL; | 100 | skb = NULL; |
72 | } else { | 101 | } else { |
73 | if (!(q->flags & TCQ_F_ONETXQUEUE) || !netif_xmit_frozen_or_stopped(txq)) { | 102 | if (!(q->flags & TCQ_F_ONETXQUEUE) || |
103 | !netif_xmit_frozen_or_stopped(txq)) { | ||
104 | int bytelimit = qdisc_avail_bulklimit(txq); | ||
105 | |||
74 | skb = q->dequeue(q); | 106 | skb = q->dequeue(q); |
75 | if (skb) | 107 | if (skb) { |
108 | bytelimit -= skb->len; | ||
76 | skb = validate_xmit_skb(skb, qdisc_dev(q)); | 109 | skb = validate_xmit_skb(skb, qdisc_dev(q)); |
110 | } | ||
111 | if (skb && qdisc_may_bulk(q)) | ||
112 | skb = try_bulk_dequeue_skb(q, skb, bytelimit); | ||
77 | } | 113 | } |
78 | } | 114 | } |
79 | 115 | ||