2 * lib/route/sch/cbq.c Class Based Queueing
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation version 2.1
9 * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
12 #include <netlink-local.h>
13 #include <netlink-tc.h>
14 #include <netlink/netlink.h>
15 #include <netlink/utils.h>
16 #include <netlink/route/qdisc.h>
17 #include <netlink/route/qdisc-modules.h>
18 #include <netlink/route/class.h>
19 #include <netlink/route/class-modules.h>
20 #include <netlink/route/link.h>
21 #include <netlink/route/sch/cbq.h>
22 #include <netlink/route/cls/police.h>
27 * @defgroup cbq Class Based Queueing (CBQ)
31 static struct trans_tbl ovl_strategies[] = {
32 __ADD(TC_CBQ_OVL_CLASSIC,classic)
33 __ADD(TC_CBQ_OVL_DELAY,delay)
34 __ADD(TC_CBQ_OVL_LOWPRIO,lowprio)
35 __ADD(TC_CBQ_OVL_DROP,drop)
36 __ADD(TC_CBQ_OVL_RCLASSIC,rclassic)
40 * Convert a CBQ OVL strategy to a character string
41 * @arg type CBQ OVL strategy
42 * @arg buf destination buffer
43 * @arg len length of destination buffer
45 * Converts a CBQ OVL strategy to a character string and stores in the
46 * provided buffer. Returns the destination buffer or the type
47 * encoded in hex if no match was found.
49 char *nl_ovl_strategy2str(int type, char *buf, size_t len)
51 return __type2str(type, buf, len, ovl_strategies,
52 ARRAY_SIZE(ovl_strategies));
56 * Convert a string to a CBQ OVL strategy
57 * @arg name CBQ OVL stragegy name
59 * Converts a CBQ OVL stragegy name to it's corresponding CBQ OVL strategy
60 * type. Returns the type or -1 if none was found.
62 int nl_str2ovl_strategy(const char *name)
64 return __str2type(name, ovl_strategies, ARRAY_SIZE(ovl_strategies));
67 static struct nla_policy cbq_policy[TCA_CBQ_MAX+1] = {
68 [TCA_CBQ_LSSOPT] = { .minlen = sizeof(struct tc_cbq_lssopt) },
69 [TCA_CBQ_RATE] = { .minlen = sizeof(struct tc_ratespec) },
70 [TCA_CBQ_WRROPT] = { .minlen = sizeof(struct tc_cbq_wrropt) },
71 [TCA_CBQ_OVL_STRATEGY] = { .minlen = sizeof(struct tc_cbq_ovl) },
72 [TCA_CBQ_FOPT] = { .minlen = sizeof(struct tc_cbq_fopt) },
73 [TCA_CBQ_POLICE] = { .minlen = sizeof(struct tc_cbq_police) },
76 static inline struct rtnl_cbq *cbq_qdisc(struct rtnl_tca *tca)
78 return (struct rtnl_cbq *) tca->tc_subdata;
81 static inline struct rtnl_cbq *cbq_alloc(struct rtnl_tca *tca)
84 tca->tc_subdata = calloc(1, sizeof(struct rtnl_qdisc));
86 return cbq_qdisc(tca);
90 static int cbq_msg_parser(struct rtnl_tca *tca)
92 struct nlattr *tb[TCA_CBQ_MAX + 1];
96 err = tca_parse(tb, TCA_CBQ_MAX, tca, cbq_policy);
100 cbq = cbq_alloc(tca);
102 return nl_errno(ENOMEM);
104 nla_memcpy(&cbq->cbq_lss, tb[TCA_CBQ_LSSOPT], sizeof(cbq->cbq_lss));
105 nla_memcpy(&cbq->cbq_rate, tb[TCA_CBQ_RATE], sizeof(cbq->cbq_rate));
106 nla_memcpy(&cbq->cbq_wrr, tb[TCA_CBQ_WRROPT], sizeof(cbq->cbq_wrr));
107 nla_memcpy(&cbq->cbq_fopt, tb[TCA_CBQ_FOPT], sizeof(cbq->cbq_fopt));
108 nla_memcpy(&cbq->cbq_ovl, tb[TCA_CBQ_OVL_STRATEGY],
109 sizeof(cbq->cbq_ovl));
110 nla_memcpy(&cbq->cbq_police, tb[TCA_CBQ_POLICE],
111 sizeof(cbq->cbq_police));
116 static int cbq_qdisc_msg_parser(struct rtnl_qdisc *qdisc)
118 return cbq_msg_parser((struct rtnl_tca *) qdisc);
121 static int cbq_class_msg_parser(struct rtnl_class *class)
123 return cbq_msg_parser((struct rtnl_tca *) class);
126 static void cbq_qdisc_free_data(struct rtnl_qdisc *qdisc)
128 free(qdisc->q_subdata);
131 static void cbq_class_free_data(struct rtnl_class *class)
133 free(class->c_subdata);
136 static int cbq_dump_brief(struct rtnl_tca *tca, struct nl_dump_params *p,
139 struct rtnl_cbq *cbq;
143 cbq = cbq_qdisc(tca);
147 r = nl_cancel_down_bytes(cbq->cbq_rate.rate, &ru);
148 rbit = nl_cancel_down_bits(cbq->cbq_rate.rate * 8, &rubit);
150 dp_dump(p, " rate %.2f%s/s (%.0f%s) prio %u",
151 r, ru, rbit, rubit, cbq->cbq_wrr.priority);
157 static int cbq_qdisc_dump_brief(struct rtnl_qdisc *qdisc,
158 struct nl_dump_params *p, int line)
160 return cbq_dump_brief((struct rtnl_tca *) qdisc, p, line);
163 static int cbq_class_dump_brief(struct rtnl_class *class,
164 struct nl_dump_params *p, int line)
166 return cbq_dump_brief((struct rtnl_tca *) class, p, line);
169 static int cbq_dump_full(struct rtnl_tca *tca, struct nl_dump_params *p,
172 struct rtnl_cbq *cbq;
177 cbq = cbq_qdisc(tca);
181 w = nl_cancel_down_bits(cbq->cbq_wrr.weight * 8, &unit);
183 dp_dump(p, "avgpkt %u mpu %u cell %u allot %u weight %.0f%s\n",
186 1 << cbq->cbq_rate.cell_log,
187 cbq->cbq_wrr.allot, w, unit);
189 el = cbq->cbq_lss.ewma_log;
190 dp_dump_line(p, line++, " minidle %uus maxidle %uus offtime "
191 "%uus level %u ewma_log %u\n",
192 nl_ticks2us(cbq->cbq_lss.minidle >> el),
193 nl_ticks2us(cbq->cbq_lss.maxidle >> el),
194 nl_ticks2us(cbq->cbq_lss.offtime >> el),
196 cbq->cbq_lss.ewma_log);
198 dp_dump_line(p, line++, " penalty %uus strategy %s ",
199 nl_ticks2us(cbq->cbq_ovl.penalty),
200 nl_ovl_strategy2str(cbq->cbq_ovl.strategy, buf, sizeof(buf)));
202 dp_dump(p, "split %s defmap 0x%08x ",
203 rtnl_tc_handle2str(cbq->cbq_fopt.split, buf, sizeof(buf)),
204 cbq->cbq_fopt.defmap);
206 dp_dump(p, "police %s",
207 nl_police2str(cbq->cbq_police.police, buf, sizeof(buf)));
213 static int cbq_qdisc_dump_full(struct rtnl_qdisc *qdisc,
214 struct nl_dump_params *p, int line)
216 return cbq_dump_full((struct rtnl_tca *) qdisc, p, line);
219 static int cbq_class_dump_full(struct rtnl_class *class,
220 struct nl_dump_params *p, int line)
222 return cbq_dump_full((struct rtnl_tca *) class, p, line);
225 static int cbq_dump_with_stats(struct rtnl_tca *tca, struct nl_dump_params *p,
228 struct tc_cbq_xstats *x = tca_xstats(tca);
233 dp_dump_line(p, line++, " borrows overact "
234 " avgidle undertime\n");
235 dp_dump_line(p, line++, " %10u %10u %10u %10u\n",
236 x->borrows, x->overactions, x->avgidle, x->undertime);
242 static int cbq_qdisc_dump_with_stats(struct rtnl_qdisc *qdisc,
243 struct nl_dump_params *p, int line)
245 return cbq_dump_with_stats((struct rtnl_tca *) qdisc, p, line);
248 static int cbq_class_dump_with_stats(struct rtnl_class *class,
249 struct nl_dump_params *p, int line)
251 return cbq_dump_with_stats((struct rtnl_tca *) class, p, line);
254 static struct rtnl_qdisc_ops cbq_qdisc_ops = {
256 .qo_msg_parser = cbq_qdisc_msg_parser,
257 .qo_free_data = cbq_qdisc_free_data,
258 .qo_dump[NL_DUMP_BRIEF] = cbq_qdisc_dump_brief,
259 .qo_dump[NL_DUMP_FULL] = cbq_qdisc_dump_full,
260 .qo_dump[NL_DUMP_STATS] = cbq_qdisc_dump_with_stats,
263 static struct rtnl_class_ops cbq_class_ops = {
265 .co_msg_parser = cbq_class_msg_parser,
266 .co_free_data = cbq_class_free_data,
267 .co_dump[NL_DUMP_BRIEF] = cbq_class_dump_brief,
268 .co_dump[NL_DUMP_FULL] = cbq_class_dump_full,
269 .co_dump[NL_DUMP_STATS] = cbq_class_dump_with_stats,
272 static void __init cbq_init(void)
274 rtnl_qdisc_register(&cbq_qdisc_ops);
275 rtnl_class_register(&cbq_class_ops);
278 static void __exit cbq_exit(void)
280 rtnl_qdisc_unregister(&cbq_qdisc_ops);
281 rtnl_class_unregister(&cbq_class_ops);