From 4cf69a1b7b2518d18e1a62c79a461bca109132fc Mon Sep 17 00:00:00 2001 From: d0u9 Date: Wed, 31 Oct 2018 13:13:13 +0800 Subject: Add 64bit rate/ceil support for htb class Htb class has already supported 64bit rate and ceil settings for times. Now, in this patch, we grant this ability to libnl library. --- doc/route.txt | 8 +++--- include/netlink-private/types.h | 2 ++ include/netlink/route/qdisc/htb.h | 8 +++--- include/netlink/route/tc.h | 4 +-- lib/route/qdisc/htb.c | 54 ++++++++++++++++++++++++++------------- lib/route/tc.c | 4 +-- python/netlink/route/capi.i | 8 +++--- 7 files changed, 54 insertions(+), 34 deletions(-) diff --git a/doc/route.txt b/doc/route.txt index 9d4c23aa..c2a3b1b6 100644 --- a/doc/route.txt +++ b/doc/route.txt @@ -1886,8 +1886,8 @@ or erqual than the rate of its children. + [source,c] ----- -uint32_t rtnl_htb_get_rate(struct rtnl_class *class); -int rtnl_htb_set_rate(struct rtnl_class *class, uint32_t ceil); +uint64_t rtnl_htb_get_rate(struct rtnl_class *class); +int rtnl_htb_set_rate(struct rtnl_class *class, uint64_t ceil); ----- Ceil Rate:: @@ -1899,8 +1899,8 @@ be greater or erqual than the ceil rate of its children. + [source,c] ----- -uint32_t rtnl_htb_get_ceil(struct rtnl_class *class); -int rtnl_htb_set_ceil(struct rtnl_class *class, uint32_t ceil); +uint64_t rtnl_htb_get_ceil(struct rtnl_class *class); +int rtnl_htb_set_ceil(struct rtnl_class *class, uint64_t ceil); ----- Burst:: diff --git a/include/netlink-private/types.h b/include/netlink-private/types.h index 209f0999..f1923797 100644 --- a/include/netlink-private/types.h +++ b/include/netlink-private/types.h @@ -776,6 +776,8 @@ struct rtnl_htb_class uint32_t ch_quantum; uint32_t ch_mask; uint32_t ch_level; + uint64_t ch_rate64; + uint64_t ch_ceil64; }; struct rtnl_cbq diff --git a/include/netlink/route/qdisc/htb.h b/include/netlink/route/qdisc/htb.h index c5065f40..72f7f756 100644 --- a/include/netlink/route/qdisc/htb.h +++ b/include/netlink/route/qdisc/htb.h @@ -30,10 +30,10 @@ extern int rtnl_htb_set_defcls(struct rtnl_qdisc *, uint32_t); extern uint32_t rtnl_htb_get_prio(struct rtnl_class *); extern int rtnl_htb_set_prio(struct rtnl_class *, uint32_t); -extern uint32_t rtnl_htb_get_rate(struct rtnl_class *); -extern int rtnl_htb_set_rate(struct rtnl_class *, uint32_t); -extern uint32_t rtnl_htb_get_ceil(struct rtnl_class *); -extern int rtnl_htb_set_ceil(struct rtnl_class *, uint32_t); +extern uint64_t rtnl_htb_get_rate(struct rtnl_class *); +extern int rtnl_htb_set_rate(struct rtnl_class *, uint64_t); +extern uint64_t rtnl_htb_get_ceil(struct rtnl_class *); +extern int rtnl_htb_set_ceil(struct rtnl_class *, uint64_t); extern uint32_t rtnl_htb_get_rbuffer(struct rtnl_class *); extern int rtnl_htb_set_rbuffer(struct rtnl_class *, uint32_t); extern uint32_t rtnl_htb_get_cbuffer(struct rtnl_class *); diff --git a/include/netlink/route/tc.h b/include/netlink/route/tc.h index 51d670ae..5cfa7a02 100644 --- a/include/netlink/route/tc.h +++ b/include/netlink/route/tc.h @@ -100,8 +100,8 @@ extern uint64_t rtnl_tc_get_stat(struct rtnl_tc *, enum rtnl_tc_stat); extern char * rtnl_tc_stat2str(enum rtnl_tc_stat, char *, size_t); extern int rtnl_tc_str2stat(const char *); -extern int rtnl_tc_calc_txtime(int, int); -extern int rtnl_tc_calc_bufsize(int, int); +extern int rtnl_tc_calc_txtime(int, uint64_t); +extern int rtnl_tc_calc_bufsize(int, uint64_t); extern int rtnl_tc_calc_cell_log(int); extern int rtnl_tc_read_classid_file(void); diff --git a/lib/route/qdisc/htb.c b/lib/route/qdisc/htb.c index c1e32307..eb500a3b 100644 --- a/lib/route/qdisc/htb.c +++ b/lib/route/qdisc/htb.c @@ -45,6 +45,8 @@ static struct nla_policy htb_policy[TCA_HTB_MAX+1] = { [TCA_HTB_INIT] = { .minlen = sizeof(struct tc_htb_glob) }, [TCA_HTB_PARMS] = { .minlen = sizeof(struct tc_htb_opt) }, + [TCA_HTB_RATE64] = { .minlen = sizeof(uint64_t) }, + [TCA_HTB_CEIL64] = { .minlen = sizeof(uint64_t) }, }; static int htb_qdisc_msg_parser(struct rtnl_tc *tc, void *data) @@ -86,10 +88,20 @@ static int htb_class_msg_parser(struct rtnl_tc *tc, void *data) htb->ch_prio = opts.prio; rtnl_copy_ratespec(&htb->ch_rate, &opts.rate); 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; + 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), - opts.rate.rate); + htb->ch_rate64); htb->ch_cbuffer = rtnl_tc_calc_bufsize(nl_ticks2us(opts.cbuffer), - opts.ceil.rate); + htb->ch_ceil64); htb->ch_quantum = opts.quantum; htb->ch_level = opts.level; @@ -135,8 +147,8 @@ static void htb_class_dump_line(struct rtnl_tc *tc, void *data, double r, rbit; char *ru, *rubit; - r = nl_cancel_down_bytes(htb->ch_rate.rs_rate, &ru); - rbit = nl_cancel_down_bits(htb->ch_rate.rs_rate*8, &rubit); + r = nl_cancel_down_bytes(htb->ch_rate64, &ru); + rbit = nl_cancel_down_bits(htb->ch_rate64*8, &rubit); nl_dump(p, " rate %.2f%s/s (%.0f%s) log %u", r, ru, rbit, rubit, 1<ch_rate.rs_cell_log); @@ -156,8 +168,8 @@ static void htb_class_dump_details(struct rtnl_tc *tc, void *data, double r, rbit; char *ru, *rubit; - r = nl_cancel_down_bytes(htb->ch_ceil.rs_rate, &ru); - rbit = nl_cancel_down_bits(htb->ch_ceil.rs_rate*8, &rubit); + r = nl_cancel_down_bytes(htb->ch_ceil64, &ru); + rbit = nl_cancel_down_bits(htb->ch_ceil64*8, &rubit); nl_dump(p, " ceil %.2f%s/s (%.0f%s) log %u", r, ru, rbit, rubit, 1<ch_ceil.rs_cell_log); @@ -242,21 +254,25 @@ static int htb_class_msg_fill(struct rtnl_tc *tc, void *data, if (htb->ch_mask & SCH_HTB_HAS_RBUFFER) buffer = htb->ch_rbuffer; else - buffer = opts.rate.rate / nl_get_psched_hz() + mtu; /* XXX */ + buffer = htb->ch_rate64 / nl_get_psched_hz() + mtu; /* XXX */ - opts.buffer = nl_us2ticks(rtnl_tc_calc_txtime(buffer, opts.rate.rate)); + opts.buffer = nl_us2ticks(rtnl_tc_calc_txtime(buffer, htb->ch_rate64)); if (htb->ch_mask & SCH_HTB_HAS_CBUFFER) cbuffer = htb->ch_cbuffer; else - cbuffer = opts.ceil.rate / nl_get_psched_hz() + mtu; /* XXX */ + cbuffer = htb->ch_ceil64 / nl_get_psched_hz() + mtu; /* XXX */ - opts.cbuffer = nl_us2ticks(rtnl_tc_calc_txtime(cbuffer, opts.ceil.rate)); + opts.cbuffer = nl_us2ticks(rtnl_tc_calc_txtime(cbuffer, htb->ch_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); NLA_PUT(msg, TCA_HTB_RTAB, sizeof(rtable), &rtable); NLA_PUT(msg, TCA_HTB_CTAB, sizeof(ctable), &ctable); @@ -385,13 +401,13 @@ int rtnl_htb_set_prio(struct rtnl_class *class, uint32_t prio) * * @return Rate in bytes/s or 0 if unspecified. */ -uint32_t rtnl_htb_get_rate(struct rtnl_class *class) +uint64_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_rate.rs_rate; + return htb->ch_rate64; return 0; } @@ -403,7 +419,7 @@ uint32_t rtnl_htb_get_rate(struct rtnl_class *class) * * @return 0 on success or a negative error code. */ -int rtnl_htb_set_rate(struct rtnl_class *class, uint32_t rate) +int rtnl_htb_set_rate(struct rtnl_class *class, uint64_t rate) { struct rtnl_htb_class *htb; int err; @@ -412,7 +428,8 @@ int rtnl_htb_set_rate(struct rtnl_class *class, uint32_t rate) return err; htb->ch_rate.rs_cell_log = UINT8_MAX; /* use default value */ - htb->ch_rate.rs_rate = rate; + htb->ch_rate.rs_rate = (rate >= (1ULL << 32)) ? ~0U : rate; + htb->ch_rate64 = rate; htb->ch_mask |= SCH_HTB_HAS_RATE; return 0; @@ -424,13 +441,13 @@ int rtnl_htb_set_rate(struct rtnl_class *class, uint32_t rate) * * @return Ceil rate in bytes/s or 0 if unspecified */ -uint32_t rtnl_htb_get_ceil(struct rtnl_class *class) +uint64_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_ceil.rs_rate; + return htb->ch_ceil64; return 0; } @@ -442,7 +459,7 @@ uint32_t rtnl_htb_get_ceil(struct rtnl_class *class) * * @return 0 on success or a negative error code. */ -int rtnl_htb_set_ceil(struct rtnl_class *class, uint32_t ceil) +int rtnl_htb_set_ceil(struct rtnl_class *class, uint64_t ceil) { struct rtnl_htb_class *htb; int err; @@ -451,7 +468,8 @@ int rtnl_htb_set_ceil(struct rtnl_class *class, uint32_t ceil) return err; htb->ch_ceil.rs_cell_log = UINT8_MAX; /* use default value */ - htb->ch_ceil.rs_rate = ceil; + htb->ch_ceil.rs_rate = (ceil >= (1ULL << 32)) ? ~0U : ceil; + htb->ch_ceil64 = ceil; htb->ch_mask |= SCH_HTB_HAS_CEIL; return 0; diff --git a/lib/route/tc.c b/lib/route/tc.c index f9a533cf..2e1d590f 100644 --- a/lib/route/tc.c +++ b/lib/route/tc.c @@ -646,7 +646,7 @@ int rtnl_tc_str2stat(const char *name) * * @return Required transmit time in micro seconds. */ -int rtnl_tc_calc_txtime(int bufsize, int rate) +int rtnl_tc_calc_txtime(int bufsize, uint64_t rate) { double tx_time_secs; @@ -669,7 +669,7 @@ int rtnl_tc_calc_txtime(int bufsize, int rate) * * @return Size of buffer in bytes. */ -int rtnl_tc_calc_bufsize(int txtime, int rate) +int rtnl_tc_calc_bufsize(int txtime, uint64_t rate) { double bufsize; diff --git a/python/netlink/route/capi.i b/python/netlink/route/capi.i index 2d72bd72..570e7002 100644 --- a/python/netlink/route/capi.i +++ b/python/netlink/route/capi.i @@ -417,10 +417,10 @@ extern int rtnl_htb_set_defcls(struct rtnl_qdisc *, uint32_t); extern uint32_t rtnl_htb_get_prio(struct rtnl_class *); extern int rtnl_htb_set_prio(struct rtnl_class *, uint32_t); -extern uint32_t rtnl_htb_get_rate(struct rtnl_class *); -extern int rtnl_htb_set_rate(struct rtnl_class *, uint32_t); -extern uint32_t rtnl_htb_get_ceil(struct rtnl_class *); -extern int rtnl_htb_set_ceil(struct rtnl_class *, uint32_t); +extern uint64_t rtnl_htb_get_rate(struct rtnl_class *); +extern int rtnl_htb_set_rate(struct rtnl_class *, uint64_t); +extern uint64_t rtnl_htb_get_ceil(struct rtnl_class *); +extern int rtnl_htb_set_ceil(struct rtnl_class *, uint64_t); extern uint32_t rtnl_htb_get_rbuffer(struct rtnl_class *); extern int rtnl_htb_set_rbuffer(struct rtnl_class *, uint32_t); extern uint32_t rtnl_htb_get_cbuffer(struct rtnl_class *); -- cgit v1.2.3 From 03ee05d97565da9ef935ebbdd6d56f7ab3da5bfc Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Sun, 1 Sep 2019 14:56:19 +0200 Subject: route/qdisc: adjust API for 64 bit rate/ceil support for htb class - existing API/ABI must stay unchanged. We cannot change parameter types. Ad most we can add new variants that support 64 bit integers. - rtnl_tc_calc_txtime64() and rtnl_tc_calc_bufsize64() are trivial. We should not blow up the public API of libnl for such a thing. If the users needs it, they can just reimplement it. - getters should return an error code. Especially if the return type does not support encoding an error there. - don't add separate rs_rate64/rs_ceil64 field. Instead, extend the "rs_rate" field of "struct rtnl_ratespec" to 64 bits. It's internal API. --- doc/route.txt | 8 +- include/netlink-private/netlink.h | 14 +++- include/netlink-private/types.h | 6 +- include/netlink/route/qdisc/htb.h | 15 +++- include/netlink/route/tc.h | 4 +- lib/route/qdisc/htb.c | 151 ++++++++++++++++++++++++++++---------- lib/route/qdisc/tbf.c | 42 +++++------ lib/route/tc.c | 18 ++--- libnl-route-3.sym | 4 + python/netlink/route/capi.i | 8 +- 10 files changed, 177 insertions(+), 93 deletions(-) diff --git a/doc/route.txt b/doc/route.txt index c2a3b1b6..9d4c23aa 100644 --- a/doc/route.txt +++ b/doc/route.txt @@ -1886,8 +1886,8 @@ or erqual than the rate of its children. + [source,c] ----- -uint64_t rtnl_htb_get_rate(struct rtnl_class *class); -int rtnl_htb_set_rate(struct rtnl_class *class, uint64_t ceil); +uint32_t rtnl_htb_get_rate(struct rtnl_class *class); +int rtnl_htb_set_rate(struct rtnl_class *class, uint32_t ceil); ----- Ceil Rate:: @@ -1899,8 +1899,8 @@ be greater or erqual than the ceil rate of its children. + [source,c] ----- -uint64_t rtnl_htb_get_ceil(struct rtnl_class *class); -int rtnl_htb_set_ceil(struct rtnl_class *class, uint64_t ceil); +uint32_t rtnl_htb_get_ceil(struct rtnl_class *class); +int rtnl_htb_set_ceil(struct rtnl_class *class, uint32_t ceil); ----- Burst:: diff --git a/include/netlink-private/netlink.h b/include/netlink-private/netlink.h index 0d831cf6..5f6e3f79 100644 --- a/include/netlink-private/netlink.h +++ b/include/netlink-private/netlink.h @@ -186,7 +186,7 @@ static inline void rtnl_copy_ratespec(struct rtnl_ratespec *dst, dst->rs_overhead = src->overhead; dst->rs_cell_align = src->cell_align; dst->rs_mpu = src->mpu; - dst->rs_rate = src->rate; + dst->rs_rate64 = src->rate; } static inline void rtnl_rcopy_ratespec(struct tc_ratespec *dst, @@ -196,7 +196,7 @@ static inline void rtnl_rcopy_ratespec(struct tc_ratespec *dst, dst->overhead = src->rs_overhead; dst->cell_align = src->rs_cell_align; dst->mpu = src->rs_mpu; - dst->rate = src->rs_rate; + dst->rate = src->rs_rate64 > 0xFFFFFFFFull ? 0xFFFFFFFFull : (uint32_t) src->rs_rate64; } static inline const char *nl_cache_name(struct nl_cache *cache) @@ -276,4 +276,14 @@ static inline void nl_write_unlock(pthread_rwlock_t *lock) #define nl_write_unlock(LOCK) do { } while(0) #endif +static inline int rtnl_tc_calc_txtime64(int bufsize, uint64_t rate) +{ + return ((double) bufsize / (double) rate) * 1000000.0; +} + +static inline int rtnl_tc_calc_bufsize64(int txtime, uint64_t rate) +{ + return ((double) txtime * (double) rate) / 1000000.0; +} + #endif diff --git a/include/netlink-private/types.h b/include/netlink-private/types.h index f1923797..97af3e51 100644 --- a/include/netlink-private/types.h +++ b/include/netlink-private/types.h @@ -495,11 +495,11 @@ struct rtnl_neightbl struct rtnl_ratespec { - uint8_t rs_cell_log; + uint64_t rs_rate64; uint16_t rs_overhead; int16_t rs_cell_align; uint16_t rs_mpu; - uint32_t rs_rate; + uint8_t rs_cell_log; }; struct rtnl_tstats @@ -776,8 +776,6 @@ struct rtnl_htb_class uint32_t ch_quantum; uint32_t ch_mask; uint32_t ch_level; - uint64_t ch_rate64; - uint64_t ch_ceil64; }; struct rtnl_cbq diff --git a/include/netlink/route/qdisc/htb.h b/include/netlink/route/qdisc/htb.h index 72f7f756..5d7ca452 100644 --- a/include/netlink/route/qdisc/htb.h +++ b/include/netlink/route/qdisc/htb.h @@ -30,10 +30,17 @@ extern int rtnl_htb_set_defcls(struct rtnl_qdisc *, uint32_t); extern uint32_t rtnl_htb_get_prio(struct rtnl_class *); extern int rtnl_htb_set_prio(struct rtnl_class *, uint32_t); -extern uint64_t rtnl_htb_get_rate(struct rtnl_class *); -extern int rtnl_htb_set_rate(struct rtnl_class *, uint64_t); -extern uint64_t rtnl_htb_get_ceil(struct rtnl_class *); -extern int rtnl_htb_set_ceil(struct rtnl_class *, uint64_t); + +extern uint32_t rtnl_htb_get_rate(struct rtnl_class *); +extern int rtnl_htb_set_rate(struct rtnl_class *, uint32_t); +extern uint32_t rtnl_htb_get_ceil(struct rtnl_class *); +extern int rtnl_htb_set_ceil(struct rtnl_class *, uint32_t); + +extern int rtnl_htb_get_rate64(struct rtnl_class *, uint64_t *); +extern int rtnl_htb_set_rate64(struct rtnl_class *, uint64_t); +extern int rtnl_htb_get_ceil64(struct rtnl_class *, uint64_t *); +extern int rtnl_htb_set_ceil64(struct rtnl_class *, uint64_t); + extern uint32_t rtnl_htb_get_rbuffer(struct rtnl_class *); extern int rtnl_htb_set_rbuffer(struct rtnl_class *, uint32_t); extern uint32_t rtnl_htb_get_cbuffer(struct rtnl_class *); diff --git a/include/netlink/route/tc.h b/include/netlink/route/tc.h index 5cfa7a02..51d670ae 100644 --- a/include/netlink/route/tc.h +++ b/include/netlink/route/tc.h @@ -100,8 +100,8 @@ extern uint64_t rtnl_tc_get_stat(struct rtnl_tc *, enum rtnl_tc_stat); extern char * rtnl_tc_stat2str(enum rtnl_tc_stat, char *, size_t); extern int rtnl_tc_str2stat(const char *); -extern int rtnl_tc_calc_txtime(int, uint64_t); -extern int rtnl_tc_calc_bufsize(int, uint64_t); +extern int rtnl_tc_calc_txtime(int, int); +extern int rtnl_tc_calc_bufsize(int, int); extern int rtnl_tc_calc_cell_log(int); extern int rtnl_tc_read_classid_file(void); diff --git a/lib/route/qdisc/htb.c b/lib/route/qdisc/htb.c index eb500a3b..e426a149 100644 --- a/lib/route/qdisc/htb.c +++ b/lib/route/qdisc/htb.c @@ -90,18 +90,14 @@ static int htb_class_msg_parser(struct rtnl_tc *tc, void *data) 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; @@ -147,8 +143,8 @@ static void htb_class_dump_line(struct rtnl_tc *tc, void *data, 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<ch_rate.rs_cell_log); @@ -168,8 +164,8 @@ static void htb_class_dump_details(struct rtnl_tc *tc, void *data, 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<ch_ceil.rs_cell_log); @@ -225,6 +221,8 @@ static int htb_class_msg_fill(struct rtnl_tc *tc, void *data, 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(); @@ -239,40 +237,43 @@ static int htb_class_msg_fill(struct rtnl_tc *tc, void *data, 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); @@ -399,16 +400,41 @@ int rtnl_htb_set_prio(struct rtnl_class *class, uint32_t prio) * 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; } @@ -419,7 +445,19 @@ uint64_t rtnl_htb_get_rate(struct rtnl_class *class) * * @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; @@ -428,8 +466,7 @@ int rtnl_htb_set_rate(struct rtnl_class *class, uint64_t rate) 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; @@ -439,16 +476,41 @@ int rtnl_htb_set_rate(struct rtnl_class *class, uint64_t rate) * 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; } @@ -459,7 +521,19 @@ uint64_t rtnl_htb_get_ceil(struct rtnl_class *class) * * @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; @@ -468,8 +542,7 @@ int rtnl_htb_set_ceil(struct rtnl_class *class, uint64_t ceil) 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; diff --git a/lib/route/qdisc/tbf.c b/lib/route/qdisc/tbf.c index eb574d95..23cc8454 100644 --- a/lib/route/qdisc/tbf.c +++ b/lib/route/qdisc/tbf.c @@ -44,24 +44,24 @@ static int tbf_msg_parser(struct rtnl_tc *tc, void *data) 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); @@ -83,8 +83,8 @@ static void tbf_dump_line(struct rtnl_tc *tc, void *data, 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", @@ -114,9 +114,9 @@ static void tbf_dump_details(struct rtnl_tc *tc, void *data, 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); @@ -191,7 +191,7 @@ static inline double calc_limit(struct rtnl_ratespec *spec, int latency, { double limit; - limit = (double) spec->rs_rate * ((double) latency / 1000000.); + limit = (double) spec->rs_rate64 * ((double) latency / 1000000.); limit += bucket; return limit; @@ -278,7 +278,7 @@ void rtnl_qdisc_tbf_set_rate(struct rtnl_qdisc *qdisc, int rate, int bucket, { struct rtnl_tbf *tbf; int cell_log; - + if (!(tbf = rtnl_tc_data(TC_CAST(qdisc)))) BUG(); @@ -287,10 +287,10 @@ void rtnl_qdisc_tbf_set_rate(struct rtnl_qdisc *qdisc, int rate, int bucket, 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; } @@ -307,7 +307,7 @@ int rtnl_qdisc_tbf_get_rate(struct rtnl_qdisc *qdisc) BUG(); if (tbf->qt_mask & TBF_ATTR_RATE) - return tbf->qt_rate.rs_rate; + return tbf->qt_rate.rs_rate64; else return -1; } @@ -361,7 +361,7 @@ int rtnl_qdisc_tbf_set_peakrate(struct rtnl_qdisc *qdisc, int rate, int bucket, { struct rtnl_tbf *tbf; int cell_log; - + if (!(tbf = rtnl_tc_data(TC_CAST(qdisc)))) BUG(); @@ -369,11 +369,11 @@ int rtnl_qdisc_tbf_set_peakrate(struct rtnl_qdisc *qdisc, int rate, int bucket, 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; @@ -392,7 +392,7 @@ int rtnl_qdisc_tbf_get_peakrate(struct rtnl_qdisc *qdisc) BUG(); if (tbf->qt_mask & TBF_ATTR_PEAKRATE) - return tbf->qt_peakrate.rs_rate; + return tbf->qt_peakrate.rs_rate64; else return -1; } diff --git a/lib/route/tc.c b/lib/route/tc.c index 2e1d590f..35303f59 100644 --- a/lib/route/tc.c +++ b/lib/route/tc.c @@ -646,13 +646,9 @@ int rtnl_tc_str2stat(const char *name) * * @return Required transmit time in micro seconds. */ -int rtnl_tc_calc_txtime(int bufsize, uint64_t rate) +int rtnl_tc_calc_txtime(int bufsize, int rate) { - double tx_time_secs; - - tx_time_secs = (double) bufsize / (double) rate; - - return tx_time_secs * 1000000.; + return ((double) bufsize / (double) rate) * 1000000.0; } /** @@ -669,13 +665,9 @@ int rtnl_tc_calc_txtime(int bufsize, uint64_t rate) * * @return Size of buffer in bytes. */ -int rtnl_tc_calc_bufsize(int txtime, uint64_t rate) +int rtnl_tc_calc_bufsize(int txtime, int rate) { - double bufsize; - - bufsize = (double) txtime * (double) rate; - - return bufsize / 1000000.; + return ((double) txtime * (double) rate) / 1000000.0; } /** @@ -784,7 +776,7 @@ int rtnl_tc_build_rate_table(struct rtnl_tc *tc, struct rtnl_ratespec *spec, for (i = 0; i < RTNL_TC_RTABLE_SIZE; i++) { size = adjust_size((i + 1) << cell_log, spec->rs_mpu, linktype); - dst[i] = nl_us2ticks(rtnl_tc_calc_txtime(size, spec->rs_rate)); + dst[i] = nl_us2ticks(rtnl_tc_calc_txtime64(size, spec->rs_rate64)); } spec->rs_cell_align = -1; diff --git a/libnl-route-3.sym b/libnl-route-3.sym index 67334abb..4a65503f 100644 --- a/libnl-route-3.sym +++ b/libnl-route-3.sym @@ -1066,6 +1066,10 @@ global: rtnl_class_get_by_parent; rtnl_cls_cache_set_tc_params; rtnl_ematch_tree_clone; + rtnl_htb_get_ceil64; + rtnl_htb_get_rate64; + rtnl_htb_set_ceil64; + rtnl_htb_set_rate64; rtnl_link_geneve_alloc; rtnl_link_geneve_get_flags; rtnl_link_geneve_get_id; diff --git a/python/netlink/route/capi.i b/python/netlink/route/capi.i index 570e7002..2d72bd72 100644 --- a/python/netlink/route/capi.i +++ b/python/netlink/route/capi.i @@ -417,10 +417,10 @@ extern int rtnl_htb_set_defcls(struct rtnl_qdisc *, uint32_t); extern uint32_t rtnl_htb_get_prio(struct rtnl_class *); extern int rtnl_htb_set_prio(struct rtnl_class *, uint32_t); -extern uint64_t rtnl_htb_get_rate(struct rtnl_class *); -extern int rtnl_htb_set_rate(struct rtnl_class *, uint64_t); -extern uint64_t rtnl_htb_get_ceil(struct rtnl_class *); -extern int rtnl_htb_set_ceil(struct rtnl_class *, uint64_t); +extern uint32_t rtnl_htb_get_rate(struct rtnl_class *); +extern int rtnl_htb_set_rate(struct rtnl_class *, uint32_t); +extern uint32_t rtnl_htb_get_ceil(struct rtnl_class *); +extern int rtnl_htb_set_ceil(struct rtnl_class *, uint32_t); extern uint32_t rtnl_htb_get_rbuffer(struct rtnl_class *); extern int rtnl_htb_set_rbuffer(struct rtnl_class *, uint32_t); extern uint32_t rtnl_htb_get_cbuffer(struct rtnl_class *); -- cgit v1.2.3