aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched/sch_tbf.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sched/sch_tbf.c')
-rw-r--r--net/sched/sch_tbf.c139
1 files changed, 92 insertions, 47 deletions
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c
index 68f98595819c..887e672f9d7d 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,48 @@ struct tbf_sched_data {
117}; 118};
118 119
119 120
121/* Time to Length, convert time in ns to length in bytes
122 * to determinate how many bytes can be sent in given time.
123 */
124static u64 psched_ns_t2l(const struct psched_ratecfg *r,
125 u64 time_in_ns)
126{
127 /* The formula is :
128 * len = (time_in_ns * r->rate_bytes_ps) / NSEC_PER_SEC
129 */
130 u64 len = time_in_ns * r->rate_bytes_ps;
131
132 do_div(len, NSEC_PER_SEC);
133
134 if (unlikely(r->linklayer == TC_LINKLAYER_ATM)) {
135 do_div(len, 53);
136 len = len * 48;
137 }
138
139 if (len > r->overhead)
140 len -= r->overhead;
141 else
142 len = 0;
143
144 return len;
145}
146
147/*
148 * Return length of individual segments of a gso packet,
149 * including all headers (MAC, IP, TCP/UDP)
150 */
151static unsigned int skb_gso_seglen(const struct sk_buff *skb)
152{
153 unsigned int hdr_len = skb_transport_header(skb) - skb_mac_header(skb);
154 const struct skb_shared_info *shinfo = skb_shinfo(skb);
155
156 if (likely(shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)))
157 hdr_len += tcp_hdrlen(skb);
158 else
159 hdr_len += sizeof(struct udphdr);
160 return hdr_len + shinfo->gso_size;
161}
162
120/* GSO packet is too big, segment it so that tbf can transmit 163/* GSO packet is too big, segment it so that tbf can transmit
121 * each segment in time 164 * each segment in time
122 */ 165 */
@@ -136,12 +179,8 @@ static int tbf_segment(struct sk_buff *skb, struct Qdisc *sch)
136 while (segs) { 179 while (segs) {
137 nskb = segs->next; 180 nskb = segs->next;
138 segs->next = NULL; 181 segs->next = NULL;
139 if (likely(segs->len <= q->max_size)) { 182 qdisc_skb_cb(segs)->pkt_len = segs->len;
140 qdisc_skb_cb(segs)->pkt_len = segs->len; 183 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) { 184 if (ret != NET_XMIT_SUCCESS) {
146 if (net_xmit_drop_count(ret)) 185 if (net_xmit_drop_count(ret))
147 sch->qstats.drops++; 186 sch->qstats.drops++;
@@ -163,7 +202,7 @@ static int tbf_enqueue(struct sk_buff *skb, struct Qdisc *sch)
163 int ret; 202 int ret;
164 203
165 if (qdisc_pkt_len(skb) > q->max_size) { 204 if (qdisc_pkt_len(skb) > q->max_size) {
166 if (skb_is_gso(skb)) 205 if (skb_is_gso(skb) && skb_gso_seglen(skb) <= q->max_size)
167 return tbf_segment(skb, sch); 206 return tbf_segment(skb, sch);
168 return qdisc_reshape_fail(skb, sch); 207 return qdisc_reshape_fail(skb, sch);
169 } 208 }
@@ -276,10 +315,11 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt)
276 struct tbf_sched_data *q = qdisc_priv(sch); 315 struct tbf_sched_data *q = qdisc_priv(sch);
277 struct nlattr *tb[TCA_TBF_MAX + 1]; 316 struct nlattr *tb[TCA_TBF_MAX + 1];
278 struct tc_tbf_qopt *qopt; 317 struct tc_tbf_qopt *qopt;
279 struct qdisc_rate_table *rtab = NULL;
280 struct qdisc_rate_table *ptab = NULL;
281 struct Qdisc *child = NULL; 318 struct Qdisc *child = NULL;
282 int max_size, n; 319 struct psched_ratecfg rate;
320 struct psched_ratecfg peak;
321 u64 max_size;
322 s64 buffer, mtu;
283 u64 rate64 = 0, prate64 = 0; 323 u64 rate64 = 0, prate64 = 0;
284 324
285 err = nla_parse_nested(tb, TCA_TBF_MAX, opt, tbf_policy); 325 err = nla_parse_nested(tb, TCA_TBF_MAX, opt, tbf_policy);
@@ -291,33 +331,13 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt)
291 goto done; 331 goto done;
292 332
293 qopt = nla_data(tb[TCA_TBF_PARMS]); 333 qopt = nla_data(tb[TCA_TBF_PARMS]);
294 rtab = qdisc_get_rtab(&qopt->rate, tb[TCA_TBF_RTAB]); 334 if (qopt->rate.linklayer == TC_LINKLAYER_UNAWARE)
295 if (rtab == NULL) 335 qdisc_put_rtab(qdisc_get_rtab(&qopt->rate,
296 goto done; 336 tb[TCA_TBF_RTAB]));
297 337
298 if (qopt->peakrate.rate) { 338 if (qopt->peakrate.linklayer == TC_LINKLAYER_UNAWARE)
299 if (qopt->peakrate.rate > qopt->rate.rate) 339 qdisc_put_rtab(qdisc_get_rtab(&qopt->peakrate,
300 ptab = qdisc_get_rtab(&qopt->peakrate, tb[TCA_TBF_PTAB]); 340 tb[TCA_TBF_PTAB]));
301 if (ptab == NULL)
302 goto done;
303 }
304
305 for (n = 0; n < 256; n++)
306 if (rtab->data[n] > qopt->buffer)
307 break;
308 max_size = (n << qopt->rate.cell_log) - 1;
309 if (ptab) {
310 int size;
311
312 for (n = 0; n < 256; n++)
313 if (ptab->data[n] > qopt->mtu)
314 break;
315 size = (n << qopt->peakrate.cell_log) - 1;
316 if (size < max_size)
317 max_size = size;
318 }
319 if (max_size < 0)
320 goto done;
321 341
322 if (q->qdisc != &noop_qdisc) { 342 if (q->qdisc != &noop_qdisc) {
323 err = fifo_set_limit(q->qdisc, qopt->limit); 343 err = fifo_set_limit(q->qdisc, qopt->limit);
@@ -331,6 +351,39 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt)
331 } 351 }
332 } 352 }
333 353
354 buffer = min_t(u64, PSCHED_TICKS2NS(qopt->buffer), ~0U);
355 mtu = min_t(u64, PSCHED_TICKS2NS(qopt->mtu), ~0U);
356
357 if (tb[TCA_TBF_RATE64])
358 rate64 = nla_get_u64(tb[TCA_TBF_RATE64]);
359 psched_ratecfg_precompute(&rate, &qopt->rate, rate64);
360
361 max_size = min_t(u64, psched_ns_t2l(&rate, buffer), ~0U);
362
363 if (qopt->peakrate.rate) {
364 if (tb[TCA_TBF_PRATE64])
365 prate64 = nla_get_u64(tb[TCA_TBF_PRATE64]);
366 psched_ratecfg_precompute(&peak, &qopt->peakrate, prate64);
367 if (peak.rate_bytes_ps <= rate.rate_bytes_ps) {
368 pr_warn_ratelimited("sch_tbf: peakrate %llu is lower than or equals to rate %llu !\n",
369 peak.rate_bytes_ps, rate.rate_bytes_ps);
370 err = -EINVAL;
371 goto done;
372 }
373
374 max_size = min_t(u64, max_size, psched_ns_t2l(&peak, mtu));
375 }
376
377 if (max_size < psched_mtu(qdisc_dev(sch)))
378 pr_warn_ratelimited("sch_tbf: burst %llu is lower than device %s mtu (%u) !\n",
379 max_size, qdisc_dev(sch)->name,
380 psched_mtu(qdisc_dev(sch)));
381
382 if (!max_size) {
383 err = -EINVAL;
384 goto done;
385 }
386
334 sch_tree_lock(sch); 387 sch_tree_lock(sch);
335 if (child) { 388 if (child) {
336 qdisc_tree_decrease_qlen(q->qdisc, q->qdisc->q.qlen); 389 qdisc_tree_decrease_qlen(q->qdisc, q->qdisc->q.qlen);
@@ -344,13 +397,9 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt)
344 q->tokens = q->buffer; 397 q->tokens = q->buffer;
345 q->ptokens = q->mtu; 398 q->ptokens = q->mtu;
346 399
347 if (tb[TCA_TBF_RATE64]) 400 memcpy(&q->rate, &rate, sizeof(struct psched_ratecfg));
348 rate64 = nla_get_u64(tb[TCA_TBF_RATE64]); 401 if (qopt->peakrate.rate) {
349 psched_ratecfg_precompute(&q->rate, &rtab->rate, rate64); 402 memcpy(&q->peak, &peak, sizeof(struct psched_ratecfg));
350 if (ptab) {
351 if (tb[TCA_TBF_PRATE64])
352 prate64 = nla_get_u64(tb[TCA_TBF_PRATE64]);
353 psched_ratecfg_precompute(&q->peak, &ptab->rate, prate64);
354 q->peak_present = true; 403 q->peak_present = true;
355 } else { 404 } else {
356 q->peak_present = false; 405 q->peak_present = false;
@@ -359,10 +408,6 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt)
359 sch_tree_unlock(sch); 408 sch_tree_unlock(sch);
360 err = 0; 409 err = 0;
361done: 410done:
362 if (rtab)
363 qdisc_put_rtab(rtab);
364 if (ptab)
365 qdisc_put_rtab(ptab);
366 return err; 411 return err;
367} 412}
368 413