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) },
50 static int htb_qdisc_msg_parser(
struct rtnl_tc *tc,
void *data)
52 struct nlattr *tb[TCA_HTB_MAX + 1];
53 struct rtnl_htb_qdisc *htb = data;
56 if ((err = tca_parse(tb, TCA_HTB_MAX, tc, htb_policy)) < 0)
59 if (tb[TCA_HTB_INIT]) {
60 struct tc_htb_glob opts;
62 nla_memcpy(&opts, tb[TCA_HTB_INIT],
sizeof(opts));
63 htb->qh_rate2quantum = opts.rate2quantum;
64 htb->qh_defcls = opts.defcls;
65 htb->qh_direct_pkts = opts.direct_pkts;
67 htb->qh_mask = (SCH_HTB_HAS_RATE2QUANTUM | SCH_HTB_HAS_DEFCLS);
73 static int htb_class_msg_parser(
struct rtnl_tc *tc,
void *data)
75 struct nlattr *tb[TCA_HTB_MAX + 1];
76 struct rtnl_htb_class *htb = data;
79 if ((err = tca_parse(tb, TCA_HTB_MAX, tc, htb_policy)) < 0)
82 if (tb[TCA_HTB_PARMS]) {
83 struct tc_htb_opt opts;
85 nla_memcpy(&opts, tb[TCA_HTB_PARMS],
sizeof(opts));
86 htb->ch_prio = opts.prio;
87 rtnl_copy_ratespec(&htb->ch_rate, &opts.rate);
88 rtnl_copy_ratespec(&htb->ch_ceil, &opts.ceil);
93 htb->ch_quantum = opts.quantum;
94 htb->ch_level = opts.level;
99 htb->ch_mask = (SCH_HTB_HAS_PRIO | SCH_HTB_HAS_RATE |
100 SCH_HTB_HAS_CEIL | SCH_HTB_HAS_RBUFFER |
101 SCH_HTB_HAS_CBUFFER | SCH_HTB_HAS_QUANTUM |
108 static void htb_qdisc_dump_line(
struct rtnl_tc *tc,
void *data,
111 struct rtnl_htb_qdisc *htb = data;
116 if (htb->qh_mask & SCH_HTB_HAS_RATE2QUANTUM)
117 nl_dump(p,
" r2q %u", htb->qh_rate2quantum);
119 if (htb->qh_mask & SCH_HTB_HAS_DEFCLS) {
121 nl_dump(p,
" default-class %s",
126 static void htb_class_dump_line(
struct rtnl_tc *tc,
void *data,
129 struct rtnl_htb_class *htb = data;
134 if (htb->ch_mask & SCH_HTB_HAS_RATE) {
141 nl_dump(p,
" rate %.2f%s/s (%.0f%s) log %u",
142 r, ru, rbit, rubit, 1<<htb->ch_rate.rs_cell_log);
146 static void htb_class_dump_details(
struct rtnl_tc *tc,
void *data,
149 struct rtnl_htb_class *htb = data;
155 if (htb->ch_mask & SCH_HTB_HAS_CEIL) {
162 nl_dump(p,
" ceil %.2f%s/s (%.0f%s) log %u",
163 r, ru, rbit, rubit, 1<<htb->ch_ceil.rs_cell_log);
166 if (htb->ch_mask & SCH_HTB_HAS_PRIO)
167 nl_dump(p,
" prio %u", htb->ch_prio);
169 if (htb->ch_mask & SCH_HTB_HAS_RBUFFER) {
174 nl_dump(p,
" rbuffer %.2f%s", b, bu);
177 if (htb->ch_mask & SCH_HTB_HAS_CBUFFER) {
182 nl_dump(p,
" cbuffer %.2f%s", b, bu);
185 if (htb->ch_mask & SCH_HTB_HAS_QUANTUM)
186 nl_dump(p,
" quantum %u", htb->ch_quantum);
189 static int htb_qdisc_msg_fill(
struct rtnl_tc *tc,
void *data,
192 struct rtnl_htb_qdisc *htb = data;
193 struct tc_htb_glob opts = {
194 .version = TC_HTB_PROTOVER,
199 if (htb->qh_mask & SCH_HTB_HAS_RATE2QUANTUM)
200 opts.rate2quantum = htb->qh_rate2quantum;
202 if (htb->qh_mask & SCH_HTB_HAS_DEFCLS)
203 opts.defcls = htb->qh_defcls;
206 return nla_put(msg, TCA_HTB_INIT,
sizeof(opts), &opts);
209 static int htb_class_msg_fill(
struct rtnl_tc *tc,
void *data,
212 struct rtnl_htb_class *htb = data;
213 uint32_t mtu, rtable[RTNL_TC_RTABLE_SIZE], ctable[RTNL_TC_RTABLE_SIZE];
214 struct tc_htb_opt opts;
217 if (!htb || !(htb->ch_mask & SCH_HTB_HAS_RATE))
220 memset(&opts, 0,
sizeof(opts));
223 if (htb->ch_mask & SCH_HTB_HAS_PRIO)
224 opts.prio = htb->ch_prio;
229 rtnl_rcopy_ratespec(&opts.rate, &htb->ch_rate);
231 if (htb->ch_mask & SCH_HTB_HAS_CEIL) {
233 rtnl_rcopy_ratespec(&opts.ceil, &htb->ch_ceil);
239 memcpy(&opts.ceil, &opts.rate,
sizeof(
struct tc_ratespec));
242 if (htb->ch_mask & SCH_HTB_HAS_RBUFFER)
243 buffer = htb->ch_rbuffer;
249 if (htb->ch_mask & SCH_HTB_HAS_CBUFFER)
250 cbuffer = htb->ch_cbuffer;
256 if (htb->ch_mask & SCH_HTB_HAS_QUANTUM)
257 opts.quantum = htb->ch_quantum;
259 NLA_PUT(msg, TCA_HTB_PARMS,
sizeof(opts), &opts);
260 NLA_PUT(msg, TCA_HTB_RTAB,
sizeof(rtable), &rtable);
261 NLA_PUT(msg, TCA_HTB_CTAB,
sizeof(ctable), &ctable);
269 static struct rtnl_tc_ops htb_qdisc_ops;
270 static struct rtnl_tc_ops htb_class_ops;
272 static struct rtnl_htb_qdisc *htb_qdisc_data(
struct rtnl_qdisc *qdisc)
277 static struct rtnl_htb_class *htb_class_data(
struct rtnl_class *
class)
295 struct rtnl_htb_qdisc *htb;
297 if ((htb = htb_qdisc_data(qdisc)) &&
298 htb->qh_mask & SCH_HTB_HAS_RATE2QUANTUM)
299 return htb->qh_rate2quantum;
304 int rtnl_htb_set_rate2quantum(
struct rtnl_qdisc *qdisc, uint32_t rate2quantum)
306 struct rtnl_htb_qdisc *htb;
308 if (!(htb = htb_qdisc_data(qdisc)))
309 return -NLE_OPNOTSUPP;
311 htb->qh_rate2quantum = rate2quantum;
312 htb->qh_mask |= SCH_HTB_HAS_RATE2QUANTUM;
328 struct rtnl_htb_qdisc *htb;
330 if ((htb = htb_qdisc_data(qdisc)) &&
331 htb->qh_mask & SCH_HTB_HAS_DEFCLS)
332 return htb->qh_defcls;
344 struct rtnl_htb_qdisc *htb;
346 if (!(htb = htb_qdisc_data(qdisc)))
347 return -NLE_OPNOTSUPP;
349 htb->qh_defcls = defcls;
350 htb->qh_mask |= SCH_HTB_HAS_DEFCLS;
355 uint32_t rtnl_htb_get_prio(
struct rtnl_class *
class)
357 struct rtnl_htb_class *htb;
359 if ((htb = htb_class_data(
class)) && htb->ch_mask & SCH_HTB_HAS_PRIO)
365 int rtnl_htb_set_prio(
struct rtnl_class *
class, uint32_t prio)
367 struct rtnl_htb_class *htb;
369 if (!(htb = htb_class_data(
class)))
370 return -NLE_OPNOTSUPP;
373 htb->ch_mask |= SCH_HTB_HAS_PRIO;
386 struct rtnl_htb_class *htb;
388 if ((htb = htb_class_data(
class)) && htb->ch_mask & SCH_HTB_HAS_RATE)
389 return htb->ch_rate.rs_rate;
403 struct rtnl_htb_class *htb;
405 if (!(htb = htb_class_data(
class)))
406 return -NLE_OPNOTSUPP;
408 htb->ch_rate.rs_cell_log = UINT8_MAX;
409 htb->ch_rate.rs_rate = rate;
410 htb->ch_mask |= SCH_HTB_HAS_RATE;
423 struct rtnl_htb_class *htb;
425 if ((htb = htb_class_data(
class)) && htb->ch_mask & SCH_HTB_HAS_CEIL)
426 return htb->ch_ceil.rs_rate;
440 struct rtnl_htb_class *htb;
442 if (!(htb = htb_class_data(
class)))
443 return -NLE_OPNOTSUPP;
445 htb->ch_ceil.rs_cell_log = UINT8_MAX;
446 htb->ch_ceil.rs_rate = ceil;
447 htb->ch_mask |= SCH_HTB_HAS_CEIL;
460 struct rtnl_htb_class *htb;
462 if ((htb = htb_class_data(
class)) &&
463 htb->ch_mask & SCH_HTB_HAS_RBUFFER)
464 return htb->ch_rbuffer;
476 struct rtnl_htb_class *htb;
478 if (!(htb = htb_class_data(
class)))
479 return -NLE_OPNOTSUPP;
481 htb->ch_rbuffer = rbuffer;
482 htb->ch_mask |= SCH_HTB_HAS_RBUFFER;
495 struct rtnl_htb_class *htb;
497 if ((htb = htb_class_data(
class)) &&
498 htb->ch_mask & SCH_HTB_HAS_CBUFFER)
499 return htb->ch_cbuffer;
511 struct rtnl_htb_class *htb;
513 if (!(htb = htb_class_data(
class)))
514 return -NLE_OPNOTSUPP;
516 htb->ch_cbuffer = cbuffer;
517 htb->ch_mask |= SCH_HTB_HAS_CBUFFER;
532 struct rtnl_htb_class *htb;
534 if ((htb = htb_class_data(
class)) &&
535 htb->ch_mask & SCH_HTB_HAS_QUANTUM)
536 return htb->ch_quantum;
552 struct rtnl_htb_class *htb;
554 if (!(htb = htb_class_data(
class)))
555 return -NLE_OPNOTSUPP;
557 htb->ch_quantum = quantum;
558 htb->ch_mask |= SCH_HTB_HAS_QUANTUM;
575 struct rtnl_htb_class *htb;
577 if ((htb = htb_class_data(
class)) && htb->ch_mask & SCH_HTB_HAS_LEVEL)
578 return htb->ch_level;
580 return -NLE_OPNOTSUPP;
597 struct rtnl_htb_class *htb;
599 if (!(htb = htb_class_data(
class)))
600 return -NLE_OPNOTSUPP;
602 htb->ch_level = level;
603 htb->ch_mask |= SCH_HTB_HAS_LEVEL;
610 static struct rtnl_tc_ops htb_qdisc_ops = {
612 .to_type = RTNL_TC_TYPE_QDISC,
613 .to_size =
sizeof(
struct rtnl_htb_qdisc),
614 .to_msg_parser = htb_qdisc_msg_parser,
616 .to_msg_fill = htb_qdisc_msg_fill,
619 static struct rtnl_tc_ops htb_class_ops = {
621 .to_type = RTNL_TC_TYPE_CLASS,
622 .to_size =
sizeof(
struct rtnl_htb_class),
623 .to_msg_parser = htb_class_msg_parser,
628 .to_msg_fill = htb_class_msg_fill,
631 static void __init htb_init(
void)
637 static void __exit htb_exit(
void)