1*4dc78e53SAndroid Build Coastguard Worker /* SPDX-License-Identifier: LGPL-2.1-only */
2*4dc78e53SAndroid Build Coastguard Worker /*
3*4dc78e53SAndroid Build Coastguard Worker * Copyright (c) 2003-2011 Thomas Graf <[email protected]>
4*4dc78e53SAndroid Build Coastguard Worker */
5*4dc78e53SAndroid Build Coastguard Worker
6*4dc78e53SAndroid Build Coastguard Worker #include "nl-default.h"
7*4dc78e53SAndroid Build Coastguard Worker
8*4dc78e53SAndroid Build Coastguard Worker #include <netlink/netlink.h>
9*4dc78e53SAndroid Build Coastguard Worker #include <netlink/utils.h>
10*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/qdisc.h>
11*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/class.h>
12*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/link.h>
13*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/qdisc/cbq.h>
14*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/cls/police.h>
15*4dc78e53SAndroid Build Coastguard Worker
16*4dc78e53SAndroid Build Coastguard Worker #include "tc-api.h"
17*4dc78e53SAndroid Build Coastguard Worker
18*4dc78e53SAndroid Build Coastguard Worker struct rtnl_cbq {
19*4dc78e53SAndroid Build Coastguard Worker struct tc_cbq_lssopt cbq_lss;
20*4dc78e53SAndroid Build Coastguard Worker struct tc_ratespec cbq_rate;
21*4dc78e53SAndroid Build Coastguard Worker struct tc_cbq_wrropt cbq_wrr;
22*4dc78e53SAndroid Build Coastguard Worker struct tc_cbq_ovl cbq_ovl;
23*4dc78e53SAndroid Build Coastguard Worker struct tc_cbq_fopt cbq_fopt;
24*4dc78e53SAndroid Build Coastguard Worker struct tc_cbq_police cbq_police;
25*4dc78e53SAndroid Build Coastguard Worker };
26*4dc78e53SAndroid Build Coastguard Worker
27*4dc78e53SAndroid Build Coastguard Worker /**
28*4dc78e53SAndroid Build Coastguard Worker * @ingroup qdisc
29*4dc78e53SAndroid Build Coastguard Worker * @ingroup class
30*4dc78e53SAndroid Build Coastguard Worker * @defgroup qdisc_cbq Class Based Queueing (CBQ)
31*4dc78e53SAndroid Build Coastguard Worker * @{
32*4dc78e53SAndroid Build Coastguard Worker */
33*4dc78e53SAndroid Build Coastguard Worker
34*4dc78e53SAndroid Build Coastguard Worker static const struct trans_tbl ovl_strategies[] = {
35*4dc78e53SAndroid Build Coastguard Worker __ADD(TC_CBQ_OVL_CLASSIC,classic),
36*4dc78e53SAndroid Build Coastguard Worker __ADD(TC_CBQ_OVL_DELAY,delay),
37*4dc78e53SAndroid Build Coastguard Worker __ADD(TC_CBQ_OVL_LOWPRIO,lowprio),
38*4dc78e53SAndroid Build Coastguard Worker __ADD(TC_CBQ_OVL_DROP,drop),
39*4dc78e53SAndroid Build Coastguard Worker __ADD(TC_CBQ_OVL_RCLASSIC,rclassic),
40*4dc78e53SAndroid Build Coastguard Worker };
41*4dc78e53SAndroid Build Coastguard Worker
42*4dc78e53SAndroid Build Coastguard Worker /**
43*4dc78e53SAndroid Build Coastguard Worker * Convert a CBQ OVL strategy to a character string
44*4dc78e53SAndroid Build Coastguard Worker * @arg type CBQ OVL strategy
45*4dc78e53SAndroid Build Coastguard Worker * @arg buf destination buffer
46*4dc78e53SAndroid Build Coastguard Worker * @arg len length of destination buffer
47*4dc78e53SAndroid Build Coastguard Worker *
48*4dc78e53SAndroid Build Coastguard Worker * Converts a CBQ OVL strategy to a character string and stores in the
49*4dc78e53SAndroid Build Coastguard Worker * provided buffer. Returns the destination buffer or the type
50*4dc78e53SAndroid Build Coastguard Worker * encoded in hex if no match was found.
51*4dc78e53SAndroid Build Coastguard Worker */
nl_ovl_strategy2str(int type,char * buf,size_t len)52*4dc78e53SAndroid Build Coastguard Worker char *nl_ovl_strategy2str(int type, char *buf, size_t len)
53*4dc78e53SAndroid Build Coastguard Worker {
54*4dc78e53SAndroid Build Coastguard Worker return __type2str(type, buf, len, ovl_strategies,
55*4dc78e53SAndroid Build Coastguard Worker ARRAY_SIZE(ovl_strategies));
56*4dc78e53SAndroid Build Coastguard Worker }
57*4dc78e53SAndroid Build Coastguard Worker
58*4dc78e53SAndroid Build Coastguard Worker /**
59*4dc78e53SAndroid Build Coastguard Worker * Convert a string to a CBQ OVL strategy
60*4dc78e53SAndroid Build Coastguard Worker * @arg name CBQ OVL stragegy name
61*4dc78e53SAndroid Build Coastguard Worker *
62*4dc78e53SAndroid Build Coastguard Worker * Converts a CBQ OVL stragegy name to it's corresponding CBQ OVL strategy
63*4dc78e53SAndroid Build Coastguard Worker * type. Returns the type or -1 if none was found.
64*4dc78e53SAndroid Build Coastguard Worker */
nl_str2ovl_strategy(const char * name)65*4dc78e53SAndroid Build Coastguard Worker int nl_str2ovl_strategy(const char *name)
66*4dc78e53SAndroid Build Coastguard Worker {
67*4dc78e53SAndroid Build Coastguard Worker return __str2type(name, ovl_strategies, ARRAY_SIZE(ovl_strategies));
68*4dc78e53SAndroid Build Coastguard Worker }
69*4dc78e53SAndroid Build Coastguard Worker
70*4dc78e53SAndroid Build Coastguard Worker static struct nla_policy cbq_policy[TCA_CBQ_MAX+1] = {
71*4dc78e53SAndroid Build Coastguard Worker [TCA_CBQ_LSSOPT] = { .minlen = sizeof(struct tc_cbq_lssopt) },
72*4dc78e53SAndroid Build Coastguard Worker [TCA_CBQ_RATE] = { .minlen = sizeof(struct tc_ratespec) },
73*4dc78e53SAndroid Build Coastguard Worker [TCA_CBQ_WRROPT] = { .minlen = sizeof(struct tc_cbq_wrropt) },
74*4dc78e53SAndroid Build Coastguard Worker [TCA_CBQ_OVL_STRATEGY] = { .minlen = sizeof(struct tc_cbq_ovl) },
75*4dc78e53SAndroid Build Coastguard Worker [TCA_CBQ_FOPT] = { .minlen = sizeof(struct tc_cbq_fopt) },
76*4dc78e53SAndroid Build Coastguard Worker [TCA_CBQ_POLICE] = { .minlen = sizeof(struct tc_cbq_police) },
77*4dc78e53SAndroid Build Coastguard Worker };
78*4dc78e53SAndroid Build Coastguard Worker
cbq_msg_parser(struct rtnl_tc * tc,void * data)79*4dc78e53SAndroid Build Coastguard Worker static int cbq_msg_parser(struct rtnl_tc *tc, void *data)
80*4dc78e53SAndroid Build Coastguard Worker {
81*4dc78e53SAndroid Build Coastguard Worker struct nlattr *tb[TCA_CBQ_MAX + 1];
82*4dc78e53SAndroid Build Coastguard Worker struct rtnl_cbq *cbq = data;
83*4dc78e53SAndroid Build Coastguard Worker int err;
84*4dc78e53SAndroid Build Coastguard Worker
85*4dc78e53SAndroid Build Coastguard Worker err = tca_parse(tb, TCA_CBQ_MAX, tc, cbq_policy);
86*4dc78e53SAndroid Build Coastguard Worker if (err < 0)
87*4dc78e53SAndroid Build Coastguard Worker return err;
88*4dc78e53SAndroid Build Coastguard Worker
89*4dc78e53SAndroid Build Coastguard Worker nla_memcpy(&cbq->cbq_lss, tb[TCA_CBQ_LSSOPT], sizeof(cbq->cbq_lss));
90*4dc78e53SAndroid Build Coastguard Worker nla_memcpy(&cbq->cbq_rate, tb[TCA_CBQ_RATE], sizeof(cbq->cbq_rate));
91*4dc78e53SAndroid Build Coastguard Worker nla_memcpy(&cbq->cbq_wrr, tb[TCA_CBQ_WRROPT], sizeof(cbq->cbq_wrr));
92*4dc78e53SAndroid Build Coastguard Worker nla_memcpy(&cbq->cbq_fopt, tb[TCA_CBQ_FOPT], sizeof(cbq->cbq_fopt));
93*4dc78e53SAndroid Build Coastguard Worker nla_memcpy(&cbq->cbq_ovl, tb[TCA_CBQ_OVL_STRATEGY],
94*4dc78e53SAndroid Build Coastguard Worker sizeof(cbq->cbq_ovl));
95*4dc78e53SAndroid Build Coastguard Worker nla_memcpy(&cbq->cbq_police, tb[TCA_CBQ_POLICE],
96*4dc78e53SAndroid Build Coastguard Worker sizeof(cbq->cbq_police));
97*4dc78e53SAndroid Build Coastguard Worker
98*4dc78e53SAndroid Build Coastguard Worker return 0;
99*4dc78e53SAndroid Build Coastguard Worker }
100*4dc78e53SAndroid Build Coastguard Worker
cbq_dump_line(struct rtnl_tc * tc,void * data,struct nl_dump_params * p)101*4dc78e53SAndroid Build Coastguard Worker static void cbq_dump_line(struct rtnl_tc *tc, void *data,
102*4dc78e53SAndroid Build Coastguard Worker struct nl_dump_params *p)
103*4dc78e53SAndroid Build Coastguard Worker {
104*4dc78e53SAndroid Build Coastguard Worker struct rtnl_cbq *cbq = data;
105*4dc78e53SAndroid Build Coastguard Worker double r, rbit;
106*4dc78e53SAndroid Build Coastguard Worker char *ru, *rubit;
107*4dc78e53SAndroid Build Coastguard Worker
108*4dc78e53SAndroid Build Coastguard Worker if (!cbq)
109*4dc78e53SAndroid Build Coastguard Worker return;
110*4dc78e53SAndroid Build Coastguard Worker
111*4dc78e53SAndroid Build Coastguard Worker r = nl_cancel_down_bytes(cbq->cbq_rate.rate, &ru);
112*4dc78e53SAndroid Build Coastguard Worker rbit = nl_cancel_down_bits(cbq->cbq_rate.rate * 8, &rubit);
113*4dc78e53SAndroid Build Coastguard Worker
114*4dc78e53SAndroid Build Coastguard Worker nl_dump(p, " rate %.2f%s/s (%.0f%s) prio %u",
115*4dc78e53SAndroid Build Coastguard Worker r, ru, rbit, rubit, cbq->cbq_wrr.priority);
116*4dc78e53SAndroid Build Coastguard Worker }
117*4dc78e53SAndroid Build Coastguard Worker
cbq_dump_details(struct rtnl_tc * tc,void * data,struct nl_dump_params * p)118*4dc78e53SAndroid Build Coastguard Worker static void cbq_dump_details(struct rtnl_tc *tc, void *data,
119*4dc78e53SAndroid Build Coastguard Worker struct nl_dump_params *p)
120*4dc78e53SAndroid Build Coastguard Worker {
121*4dc78e53SAndroid Build Coastguard Worker struct rtnl_cbq *cbq = data;
122*4dc78e53SAndroid Build Coastguard Worker char *unit, buf[32];
123*4dc78e53SAndroid Build Coastguard Worker double w;
124*4dc78e53SAndroid Build Coastguard Worker uint32_t el;
125*4dc78e53SAndroid Build Coastguard Worker
126*4dc78e53SAndroid Build Coastguard Worker if (!cbq)
127*4dc78e53SAndroid Build Coastguard Worker return;
128*4dc78e53SAndroid Build Coastguard Worker
129*4dc78e53SAndroid Build Coastguard Worker w = nl_cancel_down_bits(cbq->cbq_wrr.weight * 8, &unit);
130*4dc78e53SAndroid Build Coastguard Worker
131*4dc78e53SAndroid Build Coastguard Worker nl_dump(p, "avgpkt %u mpu %u cell %u allot %u weight %.0f%s\n",
132*4dc78e53SAndroid Build Coastguard Worker cbq->cbq_lss.avpkt,
133*4dc78e53SAndroid Build Coastguard Worker cbq->cbq_rate.mpu,
134*4dc78e53SAndroid Build Coastguard Worker 1 << cbq->cbq_rate.cell_log,
135*4dc78e53SAndroid Build Coastguard Worker cbq->cbq_wrr.allot, w, unit);
136*4dc78e53SAndroid Build Coastguard Worker
137*4dc78e53SAndroid Build Coastguard Worker el = cbq->cbq_lss.ewma_log;
138*4dc78e53SAndroid Build Coastguard Worker nl_dump_line(p, " minidle %uus maxidle %uus offtime "
139*4dc78e53SAndroid Build Coastguard Worker "%uus level %u ewma_log %u\n",
140*4dc78e53SAndroid Build Coastguard Worker nl_ticks2us(cbq->cbq_lss.minidle >> el),
141*4dc78e53SAndroid Build Coastguard Worker nl_ticks2us(cbq->cbq_lss.maxidle >> el),
142*4dc78e53SAndroid Build Coastguard Worker nl_ticks2us(cbq->cbq_lss.offtime >> el),
143*4dc78e53SAndroid Build Coastguard Worker cbq->cbq_lss.level,
144*4dc78e53SAndroid Build Coastguard Worker cbq->cbq_lss.ewma_log);
145*4dc78e53SAndroid Build Coastguard Worker
146*4dc78e53SAndroid Build Coastguard Worker nl_dump_line(p, " penalty %uus strategy %s ",
147*4dc78e53SAndroid Build Coastguard Worker nl_ticks2us(cbq->cbq_ovl.penalty),
148*4dc78e53SAndroid Build Coastguard Worker nl_ovl_strategy2str(cbq->cbq_ovl.strategy, buf, sizeof(buf)));
149*4dc78e53SAndroid Build Coastguard Worker
150*4dc78e53SAndroid Build Coastguard Worker nl_dump(p, "split %s defmap 0x%08x ",
151*4dc78e53SAndroid Build Coastguard Worker rtnl_tc_handle2str(cbq->cbq_fopt.split, buf, sizeof(buf)),
152*4dc78e53SAndroid Build Coastguard Worker cbq->cbq_fopt.defmap);
153*4dc78e53SAndroid Build Coastguard Worker
154*4dc78e53SAndroid Build Coastguard Worker nl_dump(p, "police %s",
155*4dc78e53SAndroid Build Coastguard Worker nl_police2str(cbq->cbq_police.police, buf, sizeof(buf)));
156*4dc78e53SAndroid Build Coastguard Worker }
157*4dc78e53SAndroid Build Coastguard Worker
cbq_dump_stats(struct rtnl_tc * tc,void * data,struct nl_dump_params * p)158*4dc78e53SAndroid Build Coastguard Worker static void cbq_dump_stats(struct rtnl_tc *tc, void *data,
159*4dc78e53SAndroid Build Coastguard Worker struct nl_dump_params *p)
160*4dc78e53SAndroid Build Coastguard Worker {
161*4dc78e53SAndroid Build Coastguard Worker struct tc_cbq_xstats *x;
162*4dc78e53SAndroid Build Coastguard Worker
163*4dc78e53SAndroid Build Coastguard Worker if (!(x = tca_xstats(tc)))
164*4dc78e53SAndroid Build Coastguard Worker return;
165*4dc78e53SAndroid Build Coastguard Worker
166*4dc78e53SAndroid Build Coastguard Worker nl_dump_line(p, " borrows overact "
167*4dc78e53SAndroid Build Coastguard Worker " avgidle undertime\n");
168*4dc78e53SAndroid Build Coastguard Worker nl_dump_line(p, " %10u %10u %10u %10u\n",
169*4dc78e53SAndroid Build Coastguard Worker x->borrows, x->overactions, x->avgidle, x->undertime);
170*4dc78e53SAndroid Build Coastguard Worker }
171*4dc78e53SAndroid Build Coastguard Worker
172*4dc78e53SAndroid Build Coastguard Worker static struct rtnl_tc_ops cbq_qdisc_ops = {
173*4dc78e53SAndroid Build Coastguard Worker .to_kind = "cbq",
174*4dc78e53SAndroid Build Coastguard Worker .to_type = RTNL_TC_TYPE_QDISC,
175*4dc78e53SAndroid Build Coastguard Worker .to_size = sizeof(struct rtnl_cbq),
176*4dc78e53SAndroid Build Coastguard Worker .to_msg_parser = cbq_msg_parser,
177*4dc78e53SAndroid Build Coastguard Worker .to_dump = {
178*4dc78e53SAndroid Build Coastguard Worker [NL_DUMP_LINE] = cbq_dump_line,
179*4dc78e53SAndroid Build Coastguard Worker [NL_DUMP_DETAILS] = cbq_dump_details,
180*4dc78e53SAndroid Build Coastguard Worker [NL_DUMP_STATS] = cbq_dump_stats,
181*4dc78e53SAndroid Build Coastguard Worker },
182*4dc78e53SAndroid Build Coastguard Worker };
183*4dc78e53SAndroid Build Coastguard Worker
184*4dc78e53SAndroid Build Coastguard Worker static struct rtnl_tc_ops cbq_class_ops = {
185*4dc78e53SAndroid Build Coastguard Worker .to_kind = "cbq",
186*4dc78e53SAndroid Build Coastguard Worker .to_type = RTNL_TC_TYPE_CLASS,
187*4dc78e53SAndroid Build Coastguard Worker .to_size = sizeof(struct rtnl_cbq),
188*4dc78e53SAndroid Build Coastguard Worker .to_msg_parser = cbq_msg_parser,
189*4dc78e53SAndroid Build Coastguard Worker .to_dump = {
190*4dc78e53SAndroid Build Coastguard Worker [NL_DUMP_LINE] = cbq_dump_line,
191*4dc78e53SAndroid Build Coastguard Worker [NL_DUMP_DETAILS] = cbq_dump_details,
192*4dc78e53SAndroid Build Coastguard Worker [NL_DUMP_STATS] = cbq_dump_stats,
193*4dc78e53SAndroid Build Coastguard Worker },
194*4dc78e53SAndroid Build Coastguard Worker };
195*4dc78e53SAndroid Build Coastguard Worker
cbq_init(void)196*4dc78e53SAndroid Build Coastguard Worker static void _nl_init cbq_init(void)
197*4dc78e53SAndroid Build Coastguard Worker {
198*4dc78e53SAndroid Build Coastguard Worker rtnl_tc_register(&cbq_qdisc_ops);
199*4dc78e53SAndroid Build Coastguard Worker rtnl_tc_register(&cbq_class_ops);
200*4dc78e53SAndroid Build Coastguard Worker }
201*4dc78e53SAndroid Build Coastguard Worker
cbq_exit(void)202*4dc78e53SAndroid Build Coastguard Worker static void _nl_exit cbq_exit(void)
203*4dc78e53SAndroid Build Coastguard Worker {
204*4dc78e53SAndroid Build Coastguard Worker rtnl_tc_unregister(&cbq_qdisc_ops);
205*4dc78e53SAndroid Build Coastguard Worker rtnl_tc_unregister(&cbq_class_ops);
206*4dc78e53SAndroid Build Coastguard Worker }
207*4dc78e53SAndroid Build Coastguard Worker
208*4dc78e53SAndroid Build Coastguard Worker /** @} */
209