12#include "nl-default.h"
14#include <netlink/netlink.h>
15#include <netlink/cache.h>
16#include <netlink/utils.h>
17#include <netlink/route/qdisc.h>
18#include <netlink/route/class.h>
19#include <netlink/route/link.h>
20#include <netlink/route/qdisc/tbf.h>
28 uint32_t qt_rate_bucket;
29 uint32_t qt_rate_txtime;
31 uint32_t qt_peakrate_bucket;
32 uint32_t qt_peakrate_txtime;
36#define TBF_ATTR_LIMIT 0x01
37#define TBF_ATTR_RATE 0x02
38#define TBF_ATTR_PEAKRATE 0x10
45static int tbf_msg_parser(
struct rtnl_tc *tc,
void *data)
47 struct nlattr *tb[TCA_TBF_MAX + 1];
48 struct rtnl_tbf *tbf = data;
51 if ((err = tca_parse(tb, TCA_TBF_MAX, tc, tbf_policy)) < 0)
54 if (tb[TCA_TBF_PARMS]) {
55 struct tc_tbf_qopt opts;
58 nla_memcpy(&opts, tb[TCA_TBF_PARMS],
sizeof(opts));
59 tbf->qt_limit = opts.limit;
61 rtnl_copy_ratespec(&tbf->qt_rate, &opts.rate);
62 tbf->qt_rate_txtime = opts.buffer;
63 bufsize = rtnl_tc_calc_bufsize64(
nl_ticks2us(opts.buffer),
64 tbf->qt_rate.rs_rate64);
65 tbf->qt_rate_bucket = bufsize;
67 rtnl_copy_ratespec(&tbf->qt_peakrate, &opts.peakrate);
68 tbf->qt_peakrate_txtime = opts.mtu;
69 bufsize = rtnl_tc_calc_bufsize64(
nl_ticks2us(opts.mtu),
70 tbf->qt_peakrate.rs_rate64);
71 tbf->qt_peakrate_bucket = bufsize;
76 tbf->qt_mask = (TBF_ATTR_LIMIT | TBF_ATTR_RATE | TBF_ATTR_PEAKRATE);
82static void tbf_dump_line(
struct rtnl_tc *tc,
void *data,
86 char *ru, *rubit, *limu;
87 struct rtnl_tbf *tbf = data;
96 nl_dump(p,
" rate %.2f%s/s (%.0f%s) limit %.2f%s",
97 r, ru, rbit, rubit, lim, limu);
100static void tbf_dump_details(
struct rtnl_tc *tc,
void *data,
103 struct rtnl_tbf *tbf = data;
114 nl_dump(p,
"rate-bucket-size %1.f%s "
115 "rate-cell-size %.1f%s\n",
120 if (tbf->qt_mask & TBF_ATTR_PEAKRATE) {
121 char *pru, *prbu, *bsu, *clu;
122 double pr, prb, bs, cl;
131 " peak-rate %.2f%s/s (%.0f%s) "
132 "bucket-size %.1f%s cell-size %.1f%s",
133 pr, pru, prb, prbu, bs, bsu, cl, clu);
137static int tbf_msg_fill(
struct rtnl_tc *tc,
void *data,
struct nl_msg *msg)
139 uint32_t rtab[RTNL_TC_RTABLE_SIZE], ptab[RTNL_TC_RTABLE_SIZE];
140 struct tc_tbf_qopt opts;
141 struct rtnl_tbf *tbf = data;
142 const uint32_t REQUIRED = TBF_ATTR_RATE | TBF_ATTR_LIMIT;
144 if ((tbf->qt_mask & REQUIRED) != REQUIRED)
145 return -NLE_MISSING_ATTR;
147 memset(&opts, 0,
sizeof(opts));
148 opts.limit = tbf->qt_limit;
149 opts.buffer = tbf->qt_rate_txtime;
152 rtnl_rcopy_ratespec(&opts.rate, &tbf->qt_rate);
154 if (tbf->qt_mask & TBF_ATTR_PEAKRATE) {
155 opts.mtu = tbf->qt_peakrate_txtime;
157 rtnl_rcopy_ratespec(&opts.peakrate, &tbf->qt_peakrate);
161 NLA_PUT(msg, TCA_TBF_PARMS,
sizeof(opts), &opts);
162 NLA_PUT(msg, TCA_TBF_RTAB,
sizeof(rtab), rtab);
164 if (tbf->qt_mask & TBF_ATTR_PEAKRATE)
165 NLA_PUT(msg, TCA_TBF_PTAB,
sizeof(ptab), ptab);
186 struct rtnl_tbf *tbf;
191 tbf->qt_limit = limit;
192 tbf->qt_mask |= TBF_ATTR_LIMIT;
195static inline double calc_limit(
struct rtnl_ratespec *spec,
int latency,
200 limit = (double) spec->rs_rate64 * ((
double) latency / 1000000.);
226 struct rtnl_tbf *tbf;
227 double limit, limit2;
232 if (!(tbf->qt_mask & TBF_ATTR_RATE))
233 return -NLE_MISSING_ATTR;
235 limit = calc_limit(&tbf->qt_rate, latency, tbf->qt_rate_bucket);
237 if (tbf->qt_mask & TBF_ATTR_PEAKRATE) {
238 limit2 = calc_limit(&tbf->qt_peakrate, latency,
239 tbf->qt_peakrate_bucket);
257 struct rtnl_tbf *tbf;
262 if (tbf->qt_mask & TBF_ATTR_LIMIT)
263 return tbf->qt_limit;
268static inline int calc_cell_log(
int cell,
int bucket)
285 struct rtnl_tbf *tbf;
292 cell_log = UINT8_MAX;
296 tbf->qt_rate.rs_rate64 = (uint32_t)rate;
297 tbf->qt_rate_bucket = bucket;
298 tbf->qt_rate.rs_cell_log = cell_log;
299 tbf->qt_rate_txtime =
nl_us2ticks(rtnl_tc_calc_txtime64(bucket, tbf->qt_rate.rs_rate64));
300 tbf->qt_mask |= TBF_ATTR_RATE;
310 struct rtnl_tbf *tbf;
315 if (tbf->qt_mask & TBF_ATTR_RATE)
316 return tbf->qt_rate.rs_rate64;
328 struct rtnl_tbf *tbf;
333 if (tbf->qt_mask & TBF_ATTR_RATE)
334 return tbf->qt_rate_bucket;
346 struct rtnl_tbf *tbf;
351 if (tbf->qt_mask & TBF_ATTR_RATE)
352 return (1 << tbf->qt_rate.rs_cell_log);
368 struct rtnl_tbf *tbf;
374 cell_log = calc_cell_log(cell, bucket);
378 tbf->qt_peakrate.rs_rate64 = (uint32_t)rate;
379 tbf->qt_peakrate_bucket = bucket;
380 tbf->qt_peakrate.rs_cell_log = cell_log;
381 tbf->qt_peakrate_txtime =
nl_us2ticks(rtnl_tc_calc_txtime64(bucket, tbf->qt_peakrate.rs_rate64));
383 tbf->qt_mask |= TBF_ATTR_PEAKRATE;
395 struct rtnl_tbf *tbf;
400 if (tbf->qt_mask & TBF_ATTR_PEAKRATE)
401 return tbf->qt_peakrate.rs_rate64;
413 struct rtnl_tbf *tbf;
418 if (tbf->qt_mask & TBF_ATTR_PEAKRATE)
419 return tbf->qt_peakrate_bucket;
431 struct rtnl_tbf *tbf;
436 if (tbf->qt_mask & TBF_ATTR_PEAKRATE)
437 return (1 << tbf->qt_peakrate.rs_cell_log);
444static struct rtnl_tc_ops tbf_tc_ops = {
446 .to_type = RTNL_TC_TYPE_QDISC,
447 .to_size =
sizeof(
struct rtnl_tbf),
448 .to_msg_parser = tbf_msg_parser,
453 .to_msg_fill = tbf_msg_fill,
456static void _nl_init tbf_init(
void)
461static void _nl_exit tbf_exit(
void)
#define NLA_PUT(msg, attrtype, attrlen, data)
Add unspecific attribute to netlink message.
int nla_memcpy(void *dest, const struct nlattr *src, int count)
Copy attribute payload to another memory area.
int rtnl_qdisc_tbf_set_limit_by_latency(struct rtnl_qdisc *qdisc, int latency)
Set limit of TBF qdisc by latency.
int rtnl_qdisc_tbf_get_rate(struct rtnl_qdisc *qdisc)
Get rate of TBF qdisc.
int rtnl_qdisc_tbf_get_peakrate_bucket(struct rtnl_qdisc *qdisc)
Get peak rate bucket size of TBF qdisc.
int rtnl_qdisc_tbf_get_rate_cell(struct rtnl_qdisc *qdisc)
Get rate cell size of TBF qdisc.
int rtnl_qdisc_tbf_get_rate_bucket(struct rtnl_qdisc *qdisc)
Get rate bucket size of TBF qdisc.
void rtnl_qdisc_tbf_set_limit(struct rtnl_qdisc *qdisc, int limit)
Set limit of TBF qdisc.
int rtnl_qdisc_tbf_get_limit(struct rtnl_qdisc *qdisc)
Get limit of TBF qdisc.
int rtnl_qdisc_tbf_set_peakrate(struct rtnl_qdisc *qdisc, int rate, int bucket, int cell)
Set peak rate of TBF qdisc.
int rtnl_qdisc_tbf_get_peakrate_cell(struct rtnl_qdisc *qdisc)
Get peak rate cell size of TBF qdisc.
void rtnl_qdisc_tbf_set_rate(struct rtnl_qdisc *qdisc, int rate, int bucket, int cell)
Set rate of TBF qdisc.
int rtnl_qdisc_tbf_get_peakrate(struct rtnl_qdisc *qdisc)
Get peak rate of TBF qdisc.
void rtnl_tc_set_mpu(struct rtnl_tc *tc, uint32_t mpu)
Set the Minimum Packet Unit (MPU) of a traffic control object.
int rtnl_tc_calc_cell_log(int cell_size)
Calculate the binary logarithm for a specific cell size.
int rtnl_tc_build_rate_table(struct rtnl_tc *tc, struct rtnl_ratespec *, uint32_t *)
Compute a transmission time lookup table.
void rtnl_tc_set_overhead(struct rtnl_tc *tc, uint32_t overhead)
Set per packet overhead of a traffic control object.
#define TC_CAST(ptr)
Macro to cast qdisc/class/classifier to tc object.
void * rtnl_tc_data(struct rtnl_tc *)
Return pointer to private data of traffic control object.
int rtnl_tc_register(struct rtnl_tc_ops *)
Register a traffic control module.
void rtnl_tc_unregister(struct rtnl_tc_ops *)
Unregister a traffic control module.
double nl_cancel_down_bits(unsigned long long l, char **unit)
Cancel down a bit counter.
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
double nl_cancel_down_bytes(unsigned long long l, char **unit)
Cancel down a byte counter.
uint32_t nl_ticks2us(uint32_t ticks)
Convert ticks to micro seconds.
uint32_t nl_us2ticks(uint32_t us)
Convert micro seconds to ticks.
@ NL_DUMP_LINE
Dump object briefly on one line.
@ NL_DUMP_DETAILS
Dump all attributes but no statistics.
Attribute validation policy.
uint16_t minlen
Minimal length of payload required.
uint16_t type
Type of attribute or NLA_UNSPEC.