aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched
diff options
context:
space:
mode:
Diffstat (limited to 'net/sched')
-rw-r--r--net/sched/sch_netem.c7
-rw-r--r--net/sched/sch_tbf.c32
2 files changed, 29 insertions, 10 deletions
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 75c94e59a3bd..bccd52b36e97 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -215,10 +215,10 @@ static bool loss_4state(struct netem_sched_data *q)
215 if (rnd < clg->a4) { 215 if (rnd < clg->a4) {
216 clg->state = 4; 216 clg->state = 4;
217 return true; 217 return true;
218 } else if (clg->a4 < rnd && rnd < clg->a1) { 218 } else if (clg->a4 < rnd && rnd < clg->a1 + clg->a4) {
219 clg->state = 3; 219 clg->state = 3;
220 return true; 220 return true;
221 } else if (clg->a1 < rnd) 221 } else if (clg->a1 + clg->a4 < rnd)
222 clg->state = 1; 222 clg->state = 1;
223 223
224 break; 224 break;
@@ -268,10 +268,11 @@ static bool loss_gilb_ell(struct netem_sched_data *q)
268 clg->state = 2; 268 clg->state = 2;
269 if (net_random() < clg->a4) 269 if (net_random() < clg->a4)
270 return true; 270 return true;
271 break;
271 case 2: 272 case 2:
272 if (net_random() < clg->a2) 273 if (net_random() < clg->a2)
273 clg->state = 1; 274 clg->state = 1;
274 if (clg->a3 > net_random()) 275 if (net_random() > clg->a3)
275 return true; 276 return true;
276 } 277 }
277 278
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c
index 68f98595819c..a6090051c5db 100644
--- a/net/sched/sch_tbf.c
+++ b/net/sched/sch_tbf.c
@@ -21,6 +21,7 @@
21#include <net/netlink.h> 21#include <net/netlink.h>
22#include <net/sch_generic.h> 22#include <net/sch_generic.h>
23#include <net/pkt_sched.h> 23#include <net/pkt_sched.h>
24#include <net/tcp.h>
24 25
25 26
26/* Simple Token Bucket Filter. 27/* Simple Token Bucket Filter.
@@ -117,6 +118,22 @@ struct tbf_sched_data {
117}; 118};
118 119
119 120
121/*
122 * Return length of individual segments of a gso packet,
123 * including all headers (MAC, IP, TCP/UDP)
124 */
125static unsigned int skb_gso_seglen(const struct sk_buff *skb)
126{
127 unsigned int hdr_len = skb_transport_header(skb) - skb_mac_header(skb);
128 const struct skb_shared_info *shinfo = skb_shinfo(skb);
129
130 if (likely(shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)))
131 hdr_len += tcp_hdrlen(skb);
132 else
133 hdr_len += sizeof(struct udphdr);
134 return hdr_len + shinfo->gso_size;
135}
136
120/* GSO packet is too big, segment it so that tbf can transmit 137/* GSO packet is too big, segment it so that tbf can transmit
121 * each segment in time 138 * each segment in time
122 */ 139 */
@@ -136,12 +153,8 @@ static int tbf_segment(struct sk_buff *skb, struct Qdisc *sch)
136 while (segs) { 153 while (segs) {
137 nskb = segs->next; 154 nskb = segs->next;
138 segs->next = NULL; 155 segs->next = NULL;
139 if (likely(segs->len <= q->max_size)) { 156 qdisc_skb_cb(segs)->pkt_len = segs->len;
140 qdisc_skb_cb(segs)->pkt_len = segs->len; 157 ret = qdisc_enqueue(segs, q->qdisc);
141 ret = qdisc_enqueue(segs, q->qdisc);
142 } else {
143 ret = qdisc_reshape_fail(skb, sch);
144 }
145 if (ret != NET_XMIT_SUCCESS) { 158 if (ret != NET_XMIT_SUCCESS) {
146 if (net_xmit_drop_count(ret)) 159 if (net_xmit_drop_count(ret))
147 sch->qstats.drops++; 160 sch->qstats.drops++;
@@ -163,7 +176,7 @@ static int tbf_enqueue(struct sk_buff *skb, struct Qdisc *sch)
163 int ret; 176 int ret;
164 177
165 if (qdisc_pkt_len(skb) > q->max_size) { 178 if (qdisc_pkt_len(skb) > q->max_size) {
166 if (skb_is_gso(skb)) 179 if (skb_is_gso(skb) && skb_gso_seglen(skb) <= q->max_size)
167 return tbf_segment(skb, sch); 180 return tbf_segment(skb, sch);
168 return qdisc_reshape_fail(skb, sch); 181 return qdisc_reshape_fail(skb, sch);
169 } 182 }
@@ -319,6 +332,11 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt)
319 if (max_size < 0) 332 if (max_size < 0)
320 goto done; 333 goto done;
321 334
335 if (max_size < psched_mtu(qdisc_dev(sch)))
336 pr_warn_ratelimited("sch_tbf: burst %u is lower than device %s mtu (%u) !\n",
337 max_size, qdisc_dev(sch)->name,
338 psched_mtu(qdisc_dev(sch)));
339
322 if (q->qdisc != &noop_qdisc) { 340 if (q->qdisc != &noop_qdisc) {
323 err = fifo_set_limit(q->qdisc, qopt->limit); 341 err = fifo_set_limit(q->qdisc, qopt->limit);
324 if (err) 342 if (err)