rtnl_copy_ratespec(&htb->ch_ceil, &opts.ceil);
if (tb[TCA_HTB_RATE64])
- nla_memcpy(&htb->ch_rate64, tb[TCA_HTB_RATE64], sizeof(uint64_t));
- else
- htb->ch_rate64 = htb->ch_rate.rs_rate;
+ nla_memcpy(&htb->ch_rate.rs_rate64, tb[TCA_HTB_RATE64], sizeof(uint64_t));
if (tb[TCA_HTB_CEIL64])
- nla_memcpy(&htb->ch_ceil64, tb[TCA_HTB_CEIL64], sizeof(uint64_t));
- else
- htb->ch_ceil64 = htb->ch_ceil.rs_rate;
-
- htb->ch_rbuffer = rtnl_tc_calc_bufsize(nl_ticks2us(opts.buffer),
- htb->ch_rate64);
- htb->ch_cbuffer = rtnl_tc_calc_bufsize(nl_ticks2us(opts.cbuffer),
- htb->ch_ceil64);
+ nla_memcpy(&htb->ch_ceil.rs_rate64, tb[TCA_HTB_CEIL64], sizeof(uint64_t));
+
+ htb->ch_rbuffer = rtnl_tc_calc_bufsize64(nl_ticks2us(opts.buffer),
+ htb->ch_rate.rs_rate64);
+ htb->ch_cbuffer = rtnl_tc_calc_bufsize64(nl_ticks2us(opts.cbuffer),
+ htb->ch_ceil.rs_rate64);
htb->ch_quantum = opts.quantum;
htb->ch_level = opts.level;
double r, rbit;
char *ru, *rubit;
- r = nl_cancel_down_bytes(htb->ch_rate64, &ru);
- rbit = nl_cancel_down_bits(htb->ch_rate64*8, &rubit);
+ r = nl_cancel_down_bytes(htb->ch_rate.rs_rate64, &ru);
+ rbit = nl_cancel_down_bits(htb->ch_rate.rs_rate64*8, &rubit);
nl_dump(p, " rate %.2f%s/s (%.0f%s) log %u",
r, ru, rbit, rubit, 1<<htb->ch_rate.rs_cell_log);
double r, rbit;
char *ru, *rubit;
- r = nl_cancel_down_bytes(htb->ch_ceil64, &ru);
- rbit = nl_cancel_down_bits(htb->ch_ceil64*8, &rubit);
+ r = nl_cancel_down_bytes(htb->ch_ceil.rs_rate64, &ru);
+ rbit = nl_cancel_down_bits(htb->ch_ceil.rs_rate64*8, &rubit);
nl_dump(p, " ceil %.2f%s/s (%.0f%s) log %u",
r, ru, rbit, rubit, 1<<htb->ch_ceil.rs_cell_log);
uint32_t mtu, rtable[RTNL_TC_RTABLE_SIZE], ctable[RTNL_TC_RTABLE_SIZE];
struct tc_htb_opt opts;
int buffer, cbuffer;
+ uint64_t rate64;
+ uint64_t ceil64;
if (!htb || !(htb->ch_mask & SCH_HTB_HAS_RATE))
BUG();
rtnl_tc_build_rate_table(tc, &htb->ch_rate, rtable);
rtnl_rcopy_ratespec(&opts.rate, &htb->ch_rate);
+ rate64 = htb->ch_rate.rs_rate64;
if (htb->ch_mask & SCH_HTB_HAS_CEIL) {
rtnl_tc_build_rate_table(tc, &htb->ch_ceil, ctable);
rtnl_rcopy_ratespec(&opts.ceil, &htb->ch_ceil);
+ ceil64 = htb->ch_ceil.rs_rate64;
} else {
/*
* If not set, configured rate is used as ceil, which implies
* no borrowing.
*/
memcpy(&opts.ceil, &opts.rate, sizeof(struct tc_ratespec));
+ ceil64 = rate64;
}
if (htb->ch_mask & SCH_HTB_HAS_RBUFFER)
buffer = htb->ch_rbuffer;
else
- buffer = htb->ch_rate64 / nl_get_psched_hz() + mtu; /* XXX */
+ buffer = rate64 / nl_get_psched_hz() + mtu; /* XXX */
- opts.buffer = nl_us2ticks(rtnl_tc_calc_txtime(buffer, htb->ch_rate64));
+ opts.buffer = nl_us2ticks(rtnl_tc_calc_txtime64(buffer, rate64));
if (htb->ch_mask & SCH_HTB_HAS_CBUFFER)
cbuffer = htb->ch_cbuffer;
else
- cbuffer = htb->ch_ceil64 / nl_get_psched_hz() + mtu; /* XXX */
+ cbuffer = ceil64 / nl_get_psched_hz() + mtu; /* XXX */
- opts.cbuffer = nl_us2ticks(rtnl_tc_calc_txtime(cbuffer, htb->ch_ceil64));
+ opts.cbuffer = nl_us2ticks(rtnl_tc_calc_txtime64(cbuffer, ceil64));
if (htb->ch_mask & SCH_HTB_HAS_QUANTUM)
opts.quantum = htb->ch_quantum;
NLA_PUT(msg, TCA_HTB_PARMS, sizeof(opts), &opts);
- if (htb->ch_rate64 >= (1ULL << 32))
- NLA_PUT(msg, TCA_HTB_RATE64, sizeof(uint64_t), &htb->ch_rate64);
- if (htb->ch_ceil64 >= (1ULL << 32))
- NLA_PUT(msg, TCA_HTB_CEIL64, sizeof(uint64_t), &htb->ch_ceil64);
+ if (rate64 > 0xFFFFFFFFull)
+ NLA_PUT(msg, TCA_HTB_RATE64, sizeof(uint64_t), &rate64);
+ if (ceil64 > 0xFFFFFFFFull)
+ NLA_PUT(msg, TCA_HTB_CEIL64, sizeof(uint64_t), &ceil64);
NLA_PUT(msg, TCA_HTB_RTAB, sizeof(rtable), &rtable);
NLA_PUT(msg, TCA_HTB_CTAB, sizeof(ctable), &ctable);
* Return rate of HTB class
* @arg class htb class object
*
- * @return Rate in bytes/s or 0 if unspecified.
+ * @return Rate in bytes/s or 0 if unspecified. If the value
+ * cannot be represented as 32 bit integer, (1<<32) is returned.
+ * Use rtnl_htb_get_rate64() instead.
*/
-uint64_t rtnl_htb_get_rate(struct rtnl_class *class)
+uint32_t rtnl_htb_get_rate(struct rtnl_class *class)
{
struct rtnl_htb_class *htb;
- if ((htb = htb_class_data(class, NULL)) &&
- (htb->ch_mask & SCH_HTB_HAS_RATE))
- return htb->ch_rate64;
+ if ( !(htb = htb_class_data(class, NULL))
+ || !(htb->ch_mask & SCH_HTB_HAS_RATE))
+ return 0;
+
+ if (htb->ch_rate.rs_rate64 > 0xFFFFFFFFull)
+ return 0xFFFFFFFFull;
+
+ return htb->ch_rate.rs_rate64;
+}
+
+/**
+ * Return rate of HTB class
+ * @arg class htb class object
+ * @arg out_rate64 on success, the set rate.
+ *
+ * @return 0 on success or a negative error code.
+ */
+int rtnl_htb_get_rate64(struct rtnl_class *class, uint64_t *out_rate64)
+{
+ struct rtnl_htb_class *htb;
+
+ if (!(htb = htb_class_data(class, NULL)))
+ return -NLE_INVAL;
+ if (!(htb->ch_mask & SCH_HTB_HAS_RATE))
+ return -NLE_NOATTR;
+ *out_rate64 = htb->ch_rate.rs_rate64;
return 0;
}
*
* @return 0 on success or a negative error code.
*/
-int rtnl_htb_set_rate(struct rtnl_class *class, uint64_t rate)
+int rtnl_htb_set_rate(struct rtnl_class *class, uint32_t rate)
+{
+ return rtnl_htb_set_rate64(class, rate);
+}
+
+/**
+ * Set rate of HTB class
+ * @arg class htb class object
+ * @arg rate new rate in bytes per second
+ *
+ * @return 0 on success or a negative error code.
+ */
+int rtnl_htb_set_rate64(struct rtnl_class *class, uint64_t rate)
{
struct rtnl_htb_class *htb;
int err;
return err;
htb->ch_rate.rs_cell_log = UINT8_MAX; /* use default value */
- htb->ch_rate.rs_rate = (rate >= (1ULL << 32)) ? ~0U : rate;
- htb->ch_rate64 = rate;
+ htb->ch_rate.rs_rate64 = rate;
htb->ch_mask |= SCH_HTB_HAS_RATE;
return 0;
* Return ceil rate of HTB class
* @arg class htb class object
*
- * @return Ceil rate in bytes/s or 0 if unspecified
+ * @return Ceil rate in bytes/s or 0 if unspecified. If the value
+ * cannot be represented as 32 bit integer, (1<<32) is returned.
+ * Use rtnl_htb_get_ceil64() instead.
*/
-uint64_t rtnl_htb_get_ceil(struct rtnl_class *class)
+uint32_t rtnl_htb_get_ceil(struct rtnl_class *class)
{
struct rtnl_htb_class *htb;
- if ((htb = htb_class_data(class, NULL)) &&
- (htb->ch_mask & SCH_HTB_HAS_CEIL))
- return htb->ch_ceil64;
+ if ( !(htb = htb_class_data(class, NULL))
+ || !(htb->ch_mask & SCH_HTB_HAS_CEIL))
+ return 0;
+
+ if (htb->ch_ceil.rs_rate64 > 0xFFFFFFFFull)
+ return 0xFFFFFFFFull;
+
+ return htb->ch_ceil.rs_rate64;
+}
+
+/**
+ * Return ceil rate of HTB class
+ * @arg class htb class object
+ * @arg out_ceil64 on success, the set ceil value.
+ *
+ * @return 0 on success or a negative error code.
+ */
+int rtnl_htb_get_ceil64(struct rtnl_class *class, uint64_t *out_ceil64)
+{
+ struct rtnl_htb_class *htb;
+
+ if (!(htb = htb_class_data(class, NULL)))
+ return -NLE_INVAL;
+ if (!(htb->ch_mask & SCH_HTB_HAS_CEIL))
+ return -NLE_NOATTR;
+ *out_ceil64 = htb->ch_ceil.rs_rate64;
return 0;
}
*
* @return 0 on success or a negative error code.
*/
-int rtnl_htb_set_ceil(struct rtnl_class *class, uint64_t ceil)
+int rtnl_htb_set_ceil(struct rtnl_class *class, uint32_t ceil)
+{
+ return rtnl_htb_set_ceil64(class, ceil);
+}
+
+/**
+ * Set ceil rate of HTB class
+ * @arg class htb class object
+ * @arg ceil64 new ceil rate number of bytes per second
+ *
+ * @return 0 on success or a negative error code.
+ */
+int rtnl_htb_set_ceil64(struct rtnl_class *class, uint64_t ceil64)
{
struct rtnl_htb_class *htb;
int err;
return err;
htb->ch_ceil.rs_cell_log = UINT8_MAX; /* use default value */
- htb->ch_ceil.rs_rate = (ceil >= (1ULL << 32)) ? ~0U : ceil;
- htb->ch_ceil64 = ceil;
+ htb->ch_ceil.rs_rate64 = ceil64;
htb->ch_mask |= SCH_HTB_HAS_CEIL;
return 0;
if ((err = tca_parse(tb, TCA_TBF_MAX, tc, tbf_policy)) < 0)
return err;
-
+
if (tb[TCA_TBF_PARMS]) {
struct tc_tbf_qopt opts;
int bufsize;
nla_memcpy(&opts, tb[TCA_TBF_PARMS], sizeof(opts));
tbf->qt_limit = opts.limit;
-
+
rtnl_copy_ratespec(&tbf->qt_rate, &opts.rate);
tbf->qt_rate_txtime = opts.buffer;
- bufsize = rtnl_tc_calc_bufsize(nl_ticks2us(opts.buffer),
- opts.rate.rate);
+ bufsize = rtnl_tc_calc_bufsize64(nl_ticks2us(opts.buffer),
+ tbf->qt_rate.rs_rate64);
tbf->qt_rate_bucket = bufsize;
rtnl_copy_ratespec(&tbf->qt_peakrate, &opts.peakrate);
tbf->qt_peakrate_txtime = opts.mtu;
- bufsize = rtnl_tc_calc_bufsize(nl_ticks2us(opts.mtu),
- opts.peakrate.rate);
+ bufsize = rtnl_tc_calc_bufsize64(nl_ticks2us(opts.mtu),
+ tbf->qt_peakrate.rs_rate64);
tbf->qt_peakrate_bucket = bufsize;
rtnl_tc_set_mpu(tc, tbf->qt_rate.rs_mpu);
if (!tbf)
return;
- r = nl_cancel_down_bytes(tbf->qt_rate.rs_rate, &ru);
- rbit = nl_cancel_down_bits(tbf->qt_rate.rs_rate*8, &rubit);
+ r = nl_cancel_down_bytes(tbf->qt_rate.rs_rate64, &ru);
+ rbit = nl_cancel_down_bits(tbf->qt_rate.rs_rate64*8, &rubit);
lim = nl_cancel_down_bytes(tbf->qt_limit, &limu);
nl_dump(p, " rate %.2f%s/s (%.0f%s) limit %.2f%s",
if (tbf->qt_mask & TBF_ATTR_PEAKRATE) {
char *pru, *prbu, *bsu, *clu;
double pr, prb, bs, cl;
-
- pr = nl_cancel_down_bytes(tbf->qt_peakrate.rs_rate, &pru);
- prb = nl_cancel_down_bits(tbf->qt_peakrate.rs_rate * 8, &prbu);
+
+ pr = nl_cancel_down_bytes(tbf->qt_peakrate.rs_rate64, &pru);
+ prb = nl_cancel_down_bits(tbf->qt_peakrate.rs_rate64 * 8, &prbu);
bs = nl_cancel_down_bits(tbf->qt_peakrate_bucket, &bsu);
cl = nl_cancel_down_bits(1 << tbf->qt_peakrate.rs_cell_log,
&clu);
{
double limit;
- limit = (double) spec->rs_rate * ((double) latency / 1000000.);
+ limit = (double) spec->rs_rate64 * ((double) latency / 1000000.);
limit += bucket;
return limit;
{
struct rtnl_tbf *tbf;
int cell_log;
-
+
if (!(tbf = rtnl_tc_data(TC_CAST(qdisc))))
BUG();
else
cell_log = rtnl_tc_calc_cell_log(cell);
- tbf->qt_rate.rs_rate = rate;
+ tbf->qt_rate.rs_rate64 = (uint32_t)rate;
tbf->qt_rate_bucket = bucket;
tbf->qt_rate.rs_cell_log = cell_log;
- tbf->qt_rate_txtime = nl_us2ticks(rtnl_tc_calc_txtime(bucket, rate));
+ tbf->qt_rate_txtime = nl_us2ticks(rtnl_tc_calc_txtime64(bucket, tbf->qt_rate.rs_rate64));
tbf->qt_mask |= TBF_ATTR_RATE;
}
BUG();
if (tbf->qt_mask & TBF_ATTR_RATE)
- return tbf->qt_rate.rs_rate;
+ return tbf->qt_rate.rs_rate64;
else
return -1;
}
{
struct rtnl_tbf *tbf;
int cell_log;
-
+
if (!(tbf = rtnl_tc_data(TC_CAST(qdisc))))
BUG();
if (cell_log < 0)
return cell_log;
- tbf->qt_peakrate.rs_rate = rate;
+ tbf->qt_peakrate.rs_rate64 = (uint32_t)rate;
tbf->qt_peakrate_bucket = bucket;
tbf->qt_peakrate.rs_cell_log = cell_log;
- tbf->qt_peakrate_txtime = nl_us2ticks(rtnl_tc_calc_txtime(bucket, rate));
-
+ tbf->qt_peakrate_txtime = nl_us2ticks(rtnl_tc_calc_txtime64(bucket, tbf->qt_peakrate.rs_rate64));
+
tbf->qt_mask |= TBF_ATTR_PEAKRATE;
return 0;
BUG();
if (tbf->qt_mask & TBF_ATTR_PEAKRATE)
- return tbf->qt_peakrate.rs_rate;
+ return tbf->qt_peakrate.rs_rate64;
else
return -1;
}