21 #include <netlink-private/netlink.h> 22 #include <netlink-private/tc.h> 23 #include <netlink/netlink.h> 24 #include <netlink/cache.h> 25 #include <netlink/utils.h> 26 #include <netlink-private/route/tc-api.h> 27 #include <netlink/route/qdisc.h> 28 #include <netlink/route/class.h> 29 #include <netlink/route/link.h> 30 #include <netlink/route/qdisc/htb.h> 33 #define SCH_HTB_HAS_RATE2QUANTUM 0x01 34 #define SCH_HTB_HAS_DEFCLS 0x02 36 #define SCH_HTB_HAS_PRIO 0x001 37 #define SCH_HTB_HAS_RATE 0x002 38 #define SCH_HTB_HAS_CEIL 0x004 39 #define SCH_HTB_HAS_RBUFFER 0x008 40 #define SCH_HTB_HAS_CBUFFER 0x010 41 #define SCH_HTB_HAS_QUANTUM 0x020 42 #define SCH_HTB_HAS_LEVEL 0x040 45 static struct nla_policy htb_policy[TCA_HTB_MAX+1] = {
46 [TCA_HTB_INIT] = { .
minlen =
sizeof(
struct tc_htb_glob) },
47 [TCA_HTB_PARMS] = { .minlen =
sizeof(
struct tc_htb_opt) },
48 [TCA_HTB_RATE64] = { .minlen =
sizeof(uint64_t) },
49 [TCA_HTB_CEIL64] = { .minlen =
sizeof(uint64_t) },
52 static int htb_qdisc_msg_parser(
struct rtnl_tc *tc,
void *data)
54 struct nlattr *tb[TCA_HTB_MAX + 1];
55 struct rtnl_htb_qdisc *htb = data;
58 if ((err = tca_parse(tb, TCA_HTB_MAX, tc, htb_policy)) < 0)
61 if (tb[TCA_HTB_INIT]) {
62 struct tc_htb_glob opts;
64 nla_memcpy(&opts, tb[TCA_HTB_INIT],
sizeof(opts));
65 htb->qh_rate2quantum = opts.rate2quantum;
66 htb->qh_defcls = opts.defcls;
67 htb->qh_direct_pkts = opts.direct_pkts;
69 htb->qh_mask = (SCH_HTB_HAS_RATE2QUANTUM | SCH_HTB_HAS_DEFCLS);
75 static int htb_class_msg_parser(
struct rtnl_tc *tc,
void *data)
77 struct nlattr *tb[TCA_HTB_MAX + 1];
78 struct rtnl_htb_class *htb = data;
81 if ((err = tca_parse(tb, TCA_HTB_MAX, tc, htb_policy)) < 0)
84 if (tb[TCA_HTB_PARMS]) {
85 struct tc_htb_opt opts;
87 nla_memcpy(&opts, tb[TCA_HTB_PARMS],
sizeof(opts));
88 htb->ch_prio = opts.prio;
89 rtnl_copy_ratespec(&htb->ch_rate, &opts.rate);
90 rtnl_copy_ratespec(&htb->ch_ceil, &opts.ceil);
92 if (tb[TCA_HTB_RATE64])
93 nla_memcpy(&htb->ch_rate.rs_rate64, tb[TCA_HTB_RATE64],
sizeof(uint64_t));
94 if (tb[TCA_HTB_CEIL64])
95 nla_memcpy(&htb->ch_ceil.rs_rate64, tb[TCA_HTB_CEIL64],
sizeof(uint64_t));
97 htb->ch_rbuffer = rtnl_tc_calc_bufsize64(
nl_ticks2us(opts.buffer),
98 htb->ch_rate.rs_rate64);
99 htb->ch_cbuffer = rtnl_tc_calc_bufsize64(
nl_ticks2us(opts.cbuffer),
100 htb->ch_ceil.rs_rate64);
101 htb->ch_quantum = opts.quantum;
102 htb->ch_level = opts.level;
107 htb->ch_mask = (SCH_HTB_HAS_PRIO | SCH_HTB_HAS_RATE |
108 SCH_HTB_HAS_CEIL | SCH_HTB_HAS_RBUFFER |
109 SCH_HTB_HAS_CBUFFER | SCH_HTB_HAS_QUANTUM |
116 static void htb_qdisc_dump_line(
struct rtnl_tc *tc,
void *data,
119 struct rtnl_htb_qdisc *htb = data;
124 if (htb->qh_mask & SCH_HTB_HAS_RATE2QUANTUM)
125 nl_dump(p,
" r2q %u", htb->qh_rate2quantum);
127 if (htb->qh_mask & SCH_HTB_HAS_DEFCLS) {
129 nl_dump(p,
" default-class %s",
134 static void htb_class_dump_line(
struct rtnl_tc *tc,
void *data,
137 struct rtnl_htb_class *htb = data;
142 if (htb->ch_mask & SCH_HTB_HAS_RATE) {
149 nl_dump(p,
" rate %.2f%s/s (%.0f%s) log %u",
150 r, ru, rbit, rubit, 1<<htb->ch_rate.rs_cell_log);
154 static void htb_class_dump_details(
struct rtnl_tc *tc,
void *data,
157 struct rtnl_htb_class *htb = data;
163 if (htb->ch_mask & SCH_HTB_HAS_CEIL) {
170 nl_dump(p,
" ceil %.2f%s/s (%.0f%s) log %u",
171 r, ru, rbit, rubit, 1<<htb->ch_ceil.rs_cell_log);
174 if (htb->ch_mask & SCH_HTB_HAS_PRIO)
175 nl_dump(p,
" prio %u", htb->ch_prio);
177 if (htb->ch_mask & SCH_HTB_HAS_RBUFFER) {
182 nl_dump(p,
" rbuffer %.2f%s", b, bu);
185 if (htb->ch_mask & SCH_HTB_HAS_CBUFFER) {
190 nl_dump(p,
" cbuffer %.2f%s", b, bu);
193 if (htb->ch_mask & SCH_HTB_HAS_QUANTUM)
194 nl_dump(p,
" quantum %u", htb->ch_quantum);
197 static int htb_qdisc_msg_fill(
struct rtnl_tc *tc,
void *data,
200 struct rtnl_htb_qdisc *htb = data;
201 struct tc_htb_glob opts = {
202 .version = TC_HTB_PROTOVER,
207 if (htb->qh_mask & SCH_HTB_HAS_RATE2QUANTUM)
208 opts.rate2quantum = htb->qh_rate2quantum;
210 if (htb->qh_mask & SCH_HTB_HAS_DEFCLS)
211 opts.defcls = htb->qh_defcls;
214 return nla_put(msg, TCA_HTB_INIT,
sizeof(opts), &opts);
217 static int htb_class_msg_fill(
struct rtnl_tc *tc,
void *data,
220 struct rtnl_htb_class *htb = data;
221 uint32_t mtu, rtable[RTNL_TC_RTABLE_SIZE], ctable[RTNL_TC_RTABLE_SIZE];
222 struct tc_htb_opt opts;
227 if (!htb || !(htb->ch_mask & SCH_HTB_HAS_RATE))
230 memset(&opts, 0,
sizeof(opts));
233 if (htb->ch_mask & SCH_HTB_HAS_PRIO)
234 opts.prio = htb->ch_prio;
239 rtnl_rcopy_ratespec(&opts.rate, &htb->ch_rate);
240 rate64 = htb->ch_rate.rs_rate64;
242 if (htb->ch_mask & SCH_HTB_HAS_CEIL) {
244 rtnl_rcopy_ratespec(&opts.ceil, &htb->ch_ceil);
245 ceil64 = htb->ch_ceil.rs_rate64;
251 memcpy(&opts.ceil, &opts.rate,
sizeof(
struct tc_ratespec));
255 if (htb->ch_mask & SCH_HTB_HAS_RBUFFER)
256 buffer = htb->ch_rbuffer;
260 opts.buffer =
nl_us2ticks(rtnl_tc_calc_txtime64(buffer, rate64));
262 if (htb->ch_mask & SCH_HTB_HAS_CBUFFER)
263 cbuffer = htb->ch_cbuffer;
267 opts.cbuffer =
nl_us2ticks(rtnl_tc_calc_txtime64(cbuffer, ceil64));
269 if (htb->ch_mask & SCH_HTB_HAS_QUANTUM)
270 opts.quantum = htb->ch_quantum;
272 NLA_PUT(msg, TCA_HTB_PARMS,
sizeof(opts), &opts);
273 if (rate64 > 0xFFFFFFFFull)
274 NLA_PUT(msg, TCA_HTB_RATE64,
sizeof(uint64_t), &rate64);
275 if (ceil64 > 0xFFFFFFFFull)
276 NLA_PUT(msg, TCA_HTB_CEIL64,
sizeof(uint64_t), &ceil64);
277 NLA_PUT(msg, TCA_HTB_RTAB,
sizeof(rtable), &rtable);
278 NLA_PUT(msg, TCA_HTB_CTAB,
sizeof(ctable), &ctable);
286 static struct rtnl_tc_ops htb_qdisc_ops;
287 static struct rtnl_tc_ops htb_class_ops;
289 static struct rtnl_htb_qdisc *htb_qdisc_data(
struct rtnl_qdisc *qdisc,
int *err)
294 static struct rtnl_htb_class *htb_class_data(
struct rtnl_class *
class,
int *err)
312 struct rtnl_htb_qdisc *htb;
314 if ((htb = htb_qdisc_data(qdisc, NULL)) &&
315 (htb->qh_mask & SCH_HTB_HAS_RATE2QUANTUM))
316 return htb->qh_rate2quantum;
321 int rtnl_htb_set_rate2quantum(
struct rtnl_qdisc *qdisc, uint32_t rate2quantum)
323 struct rtnl_htb_qdisc *htb;
326 if (!(htb = htb_qdisc_data(qdisc, &err)))
329 htb->qh_rate2quantum = rate2quantum;
330 htb->qh_mask |= SCH_HTB_HAS_RATE2QUANTUM;
346 struct rtnl_htb_qdisc *htb;
348 if ((htb = htb_qdisc_data(qdisc, NULL)) &&
349 htb->qh_mask & SCH_HTB_HAS_DEFCLS)
350 return htb->qh_defcls;
362 struct rtnl_htb_qdisc *htb;
365 if (!(htb = htb_qdisc_data(qdisc, &err)))
368 htb->qh_defcls = defcls;
369 htb->qh_mask |= SCH_HTB_HAS_DEFCLS;
374 uint32_t rtnl_htb_get_prio(
struct rtnl_class *
class)
376 struct rtnl_htb_class *htb;
378 if ((htb = htb_class_data(
class, NULL)) &&
379 (htb->ch_mask & SCH_HTB_HAS_PRIO))
385 int rtnl_htb_set_prio(
struct rtnl_class *
class, uint32_t prio)
387 struct rtnl_htb_class *htb;
390 if (!(htb = htb_class_data(
class, &err)))
394 htb->ch_mask |= SCH_HTB_HAS_PRIO;
409 struct rtnl_htb_class *htb;
411 if ( !(htb = htb_class_data(
class, NULL))
412 || !(htb->ch_mask & SCH_HTB_HAS_RATE))
415 if (htb->ch_rate.rs_rate64 > 0xFFFFFFFFull)
416 return 0xFFFFFFFFull;
418 return htb->ch_rate.rs_rate64;
430 struct rtnl_htb_class *htb;
432 if (!(htb = htb_class_data(
class, NULL)))
434 if (!(htb->ch_mask & SCH_HTB_HAS_RATE))
437 *out_rate64 = htb->ch_rate.rs_rate64;
462 struct rtnl_htb_class *htb;
465 if (!(htb = htb_class_data(
class, &err)))
468 htb->ch_rate.rs_cell_log = UINT8_MAX;
469 htb->ch_rate.rs_rate64 = rate;
470 htb->ch_mask |= SCH_HTB_HAS_RATE;
485 struct rtnl_htb_class *htb;
487 if ( !(htb = htb_class_data(
class, NULL))
488 || !(htb->ch_mask & SCH_HTB_HAS_CEIL))
491 if (htb->ch_ceil.rs_rate64 > 0xFFFFFFFFull)
492 return 0xFFFFFFFFull;
494 return htb->ch_ceil.rs_rate64;
506 struct rtnl_htb_class *htb;
508 if (!(htb = htb_class_data(
class, NULL)))
510 if (!(htb->ch_mask & SCH_HTB_HAS_CEIL))
513 *out_ceil64 = htb->ch_ceil.rs_rate64;
538 struct rtnl_htb_class *htb;
541 if (!(htb = htb_class_data(
class, &err)))
544 htb->ch_ceil.rs_cell_log = UINT8_MAX;
545 htb->ch_ceil.rs_rate64 = ceil64;
546 htb->ch_mask |= SCH_HTB_HAS_CEIL;
559 struct rtnl_htb_class *htb;
561 if ((htb = htb_class_data(
class, NULL)) &&
562 htb->ch_mask & SCH_HTB_HAS_RBUFFER)
563 return htb->ch_rbuffer;
575 struct rtnl_htb_class *htb;
578 if (!(htb = htb_class_data(
class, &err)))
581 htb->ch_rbuffer = rbuffer;
582 htb->ch_mask |= SCH_HTB_HAS_RBUFFER;
595 struct rtnl_htb_class *htb;
597 if ((htb = htb_class_data(
class, NULL)) &&
598 htb->ch_mask & SCH_HTB_HAS_CBUFFER)
599 return htb->ch_cbuffer;
611 struct rtnl_htb_class *htb;
614 if (!(htb = htb_class_data(
class, &err)))
617 htb->ch_cbuffer = cbuffer;
618 htb->ch_mask |= SCH_HTB_HAS_CBUFFER;
633 struct rtnl_htb_class *htb;
635 if ((htb = htb_class_data(
class, NULL)) &&
636 htb->ch_mask & SCH_HTB_HAS_QUANTUM)
637 return htb->ch_quantum;
653 struct rtnl_htb_class *htb;
656 if (!(htb = htb_class_data(
class, &err)))
659 htb->ch_quantum = quantum;
660 htb->ch_mask |= SCH_HTB_HAS_QUANTUM;
677 struct rtnl_htb_class *htb;
678 int err = -NLE_OPNOTSUPP;
680 if ((htb = htb_class_data(
class, &err)) &&
681 (htb->ch_mask & SCH_HTB_HAS_LEVEL))
682 return htb->ch_level;
701 struct rtnl_htb_class *htb;
704 if (!(htb = htb_class_data(
class, &err)))
707 htb->ch_level = level;
708 htb->ch_mask |= SCH_HTB_HAS_LEVEL;
715 static struct rtnl_tc_ops htb_qdisc_ops = {
717 .to_type = RTNL_TC_TYPE_QDISC,
718 .to_size =
sizeof(
struct rtnl_htb_qdisc),
719 .to_msg_parser = htb_qdisc_msg_parser,
721 .to_msg_fill = htb_qdisc_msg_fill,
724 static struct rtnl_tc_ops htb_class_ops = {
726 .to_type = RTNL_TC_TYPE_CLASS,
727 .to_size =
sizeof(
struct rtnl_htb_class),
728 .to_msg_parser = htb_class_msg_parser,
733 .to_msg_fill = htb_class_msg_fill,
736 static void __init htb_init(
void)
742 static void __exit htb_exit(
void)
int rtnl_htb_get_level(struct rtnl_class *class)
Return level of HTB class.
int rtnl_htb_set_rbuffer(struct rtnl_class *class, uint32_t rbuffer)
Set size of the rate bucket of HTB class.
Dump object briefly on one line.
int rtnl_tc_register(struct rtnl_tc_ops *ops)
Register a traffic control module.
int rtnl_htb_set_cbuffer(struct rtnl_class *class, uint32_t cbuffer)
Set size of the ceil bucket of HTB class.
uint32_t rtnl_htb_get_rate(struct rtnl_class *class)
Return rate of HTB class.
int rtnl_htb_set_level(struct rtnl_class *class, int level)
Set level of HTB class.
uint32_t rtnl_htb_get_quantum(struct rtnl_class *class)
Return quantum of HTB class.
Attribute validation policy.
double nl_cancel_down_bits(unsigned long long l, char **unit)
Cancel down a bit counter.
int rtnl_htb_set_ceil64(struct rtnl_class *class, uint64_t ceil64)
Set ceil rate of HTB class.
uint32_t rtnl_htb_get_defcls(struct rtnl_qdisc *qdisc)
Return default class of HTB qdisc.
int rtnl_htb_set_rate64(struct rtnl_class *class, uint64_t rate)
Set rate of HTB class.
Dump all attributes but no statistics.
void * rtnl_tc_data_check(struct rtnl_tc *tc, struct rtnl_tc_ops *ops, int *err)
Check traffic control object type and return private data section.
void rtnl_tc_unregister(struct rtnl_tc_ops *ops)
Unregister a traffic control module.
int rtnl_htb_get_ceil64(struct rtnl_class *class, uint64_t *out_ceil64)
Return ceil rate of HTB class.
uint32_t rtnl_htb_get_rbuffer(struct rtnl_class *class)
Return burst buffer size of HTB class.
uint32_t rtnl_tc_get_mtu(struct rtnl_tc *tc)
Return the MTU of traffic control object.
double nl_cancel_down_bytes(unsigned long long l, char **unit)
Cancel down a byte counter.
int nla_memcpy(void *dest, const struct nlattr *src, int count)
Copy attribute payload to another memory area.
#define TC_CAST(ptr)
Macro to cast qdisc/class/classifier to tc object.
uint32_t rtnl_htb_get_cbuffer(struct rtnl_class *class)
Return ceil burst buffer size of HTB class.
#define NLA_PUT(msg, attrtype, attrlen, data)
Add unspecific attribute to netlink message.
int nl_get_psched_hz(void)
Return the value of packet scheduler HZ.
int rtnl_htb_get_rate64(struct rtnl_class *class, uint64_t *out_rate64)
Return rate of HTB class.
int rtnl_htb_set_ceil(struct rtnl_class *class, uint32_t ceil)
Set ceil rate of HTB class.
uint32_t nl_ticks2us(uint32_t ticks)
Convert ticks to micro seconds.
int rtnl_htb_set_rate(struct rtnl_class *class, uint32_t rate)
Set rate of HTB class.
uint16_t minlen
Minimal length of payload required.
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_htb_set_quantum(struct rtnl_class *class, uint32_t quantum)
Set quantum of HTB class (overwrites value calculated based on r2q)
int rtnl_htb_set_defcls(struct rtnl_qdisc *qdisc, uint32_t defcls)
Set default class of the htb qdisc to the specified value.
uint32_t nl_us2ticks(uint32_t us)
Convert micro seconds to ticks.
char * rtnl_tc_handle2str(uint32_t handle, char *buf, size_t len)
Convert a traffic control handle to a character string (Reentrant).
int rtnl_tc_build_rate_table(struct rtnl_tc *tc, struct rtnl_ratespec *spec, uint32_t *dst)
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.
uint32_t rtnl_htb_get_rate2quantum(struct rtnl_qdisc *qdisc)
Return rate/quantum ratio of HTB qdisc.
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
uint32_t rtnl_htb_get_ceil(struct rtnl_class *class)
Return ceil rate of HTB class.
int nla_put(struct nl_msg *msg, int attrtype, int datalen, const void *data)
Add a unspecific attribute to netlink message.