xref: /aosp_15_r20/external/libnl/lib/route/qdisc/cbq.c (revision 4dc78e53d49367fa8e61b07018507c90983a077d)
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