|
@@ -997,6 +997,8 @@ static const struct nla_policy htb_policy[TCA_HTB_MAX + 1] = {
|
|
|
[TCA_HTB_CTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
|
|
|
[TCA_HTB_RTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
|
|
|
[TCA_HTB_DIRECT_QLEN] = { .type = NLA_U32 },
|
|
|
+ [TCA_HTB_RATE64] = { .type = NLA_U64 },
|
|
|
+ [TCA_HTB_CEIL64] = { .type = NLA_U64 },
|
|
|
};
|
|
|
|
|
|
static void htb_work_func(struct work_struct *work)
|
|
@@ -1114,6 +1116,12 @@ static int htb_dump_class(struct Qdisc *sch, unsigned long arg,
|
|
|
opt.level = cl->level;
|
|
|
if (nla_put(skb, TCA_HTB_PARMS, sizeof(opt), &opt))
|
|
|
goto nla_put_failure;
|
|
|
+ if ((cl->rate.rate_bytes_ps >= (1ULL << 32)) &&
|
|
|
+ nla_put_u64(skb, TCA_HTB_RATE64, cl->rate.rate_bytes_ps))
|
|
|
+ goto nla_put_failure;
|
|
|
+ if ((cl->ceil.rate_bytes_ps >= (1ULL << 32)) &&
|
|
|
+ nla_put_u64(skb, TCA_HTB_CEIL64, cl->ceil.rate_bytes_ps))
|
|
|
+ goto nla_put_failure;
|
|
|
|
|
|
nla_nest_end(skb, nest);
|
|
|
spin_unlock_bh(root_lock);
|
|
@@ -1332,6 +1340,7 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
|
|
|
struct qdisc_rate_table *rtab = NULL, *ctab = NULL;
|
|
|
struct nlattr *tb[TCA_HTB_MAX + 1];
|
|
|
struct tc_htb_opt *hopt;
|
|
|
+ u64 rate64, ceil64;
|
|
|
|
|
|
/* extract all subattrs from opt attr */
|
|
|
if (!opt)
|
|
@@ -1491,8 +1500,12 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
|
|
|
cl->prio = TC_HTB_NUMPRIO - 1;
|
|
|
}
|
|
|
|
|
|
- psched_ratecfg_precompute(&cl->rate, &hopt->rate, 0);
|
|
|
- psched_ratecfg_precompute(&cl->ceil, &hopt->ceil, 0);
|
|
|
+ rate64 = tb[TCA_HTB_RATE64] ? nla_get_u64(tb[TCA_HTB_RATE64]) : 0;
|
|
|
+
|
|
|
+ ceil64 = tb[TCA_HTB_CEIL64] ? nla_get_u64(tb[TCA_HTB_CEIL64]) : 0;
|
|
|
+
|
|
|
+ psched_ratecfg_precompute(&cl->rate, &hopt->rate, rate64);
|
|
|
+ psched_ratecfg_precompute(&cl->ceil, &hopt->ceil, ceil64);
|
|
|
|
|
|
cl->buffer = PSCHED_TICKS2NS(hopt->buffer);
|
|
|
cl->cbuffer = PSCHED_TICKS2NS(hopt->cbuffer);
|