]> Pileus Git - ~andy/linux/blobdiff - net/sched/sch_tbf.c
sch_tbf: add TBF_BURST/TBF_PBURST attribute
[~andy/linux] / net / sched / sch_tbf.c
index 887e672f9d7d4b185542957bcb7e10b7d8a70cec..fbba5b0ec1215be171d17c70fa5be3a7c79314b9 100644 (file)
@@ -307,6 +307,8 @@ static const struct nla_policy tbf_policy[TCA_TBF_MAX + 1] = {
        [TCA_TBF_PTAB]  = { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
        [TCA_TBF_RATE64]        = { .type = NLA_U64 },
        [TCA_TBF_PRATE64]       = { .type = NLA_U64 },
+       [TCA_TBF_BURST] = { .type = NLA_U32 },
+       [TCA_TBF_PBURST] = { .type = NLA_U32 },
 };
 
 static int tbf_change(struct Qdisc *sch, struct nlattr *opt)
@@ -358,7 +360,12 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt)
                rate64 = nla_get_u64(tb[TCA_TBF_RATE64]);
        psched_ratecfg_precompute(&rate, &qopt->rate, rate64);
 
-       max_size = min_t(u64, psched_ns_t2l(&rate, buffer), ~0U);
+       if (tb[TCA_TBF_BURST]) {
+               max_size = nla_get_u32(tb[TCA_TBF_BURST]);
+               buffer = psched_l2t_ns(&rate, max_size);
+       } else {
+               max_size = min_t(u64, psched_ns_t2l(&rate, buffer), ~0U);
+       }
 
        if (qopt->peakrate.rate) {
                if (tb[TCA_TBF_PRATE64])
@@ -366,12 +373,18 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt)
                psched_ratecfg_precompute(&peak, &qopt->peakrate, prate64);
                if (peak.rate_bytes_ps <= rate.rate_bytes_ps) {
                        pr_warn_ratelimited("sch_tbf: peakrate %llu is lower than or equals to rate %llu !\n",
-                                           peak.rate_bytes_ps, rate.rate_bytes_ps);
+                                       peak.rate_bytes_ps, rate.rate_bytes_ps);
                        err = -EINVAL;
                        goto done;
                }
 
-               max_size = min_t(u64, max_size, psched_ns_t2l(&peak, mtu));
+               if (tb[TCA_TBF_PBURST]) {
+                       u32 pburst = nla_get_u32(tb[TCA_TBF_PBURST]);
+                       max_size = min_t(u32, max_size, pburst);
+                       mtu = psched_l2t_ns(&peak, pburst);
+               } else {
+                       max_size = min_t(u64, max_size, psched_ns_t2l(&peak, mtu));
+               }
        }
 
        if (max_size < psched_mtu(qdisc_dev(sch)))
@@ -391,9 +404,15 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt)
                q->qdisc = child;
        }
        q->limit = qopt->limit;
-       q->mtu = PSCHED_TICKS2NS(qopt->mtu);
+       if (tb[TCA_TBF_PBURST])
+               q->mtu = mtu;
+       else
+               q->mtu = PSCHED_TICKS2NS(qopt->mtu);
        q->max_size = max_size;
-       q->buffer = PSCHED_TICKS2NS(qopt->buffer);
+       if (tb[TCA_TBF_BURST])
+               q->buffer = buffer;
+       else
+               q->buffer = PSCHED_TICKS2NS(qopt->buffer);
        q->tokens = q->buffer;
        q->ptokens = q->mtu;