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