xref: /aosp_15_r20/external/libnl/lib/route/qdisc/htb.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  * Copyright (c) 2005-2006 Petr Gotthard <[email protected]>
5*4dc78e53SAndroid Build Coastguard Worker  * Copyright (c) 2005-2006 Siemens AG Oesterreich
6*4dc78e53SAndroid Build Coastguard Worker  */
7*4dc78e53SAndroid Build Coastguard Worker 
8*4dc78e53SAndroid Build Coastguard Worker /**
9*4dc78e53SAndroid Build Coastguard Worker  * @ingroup qdisc
10*4dc78e53SAndroid Build Coastguard Worker  * @ingroup class
11*4dc78e53SAndroid Build Coastguard Worker  * @defgroup qdisc_htb Hierachical Token Bucket (HTB)
12*4dc78e53SAndroid Build Coastguard Worker  * @{
13*4dc78e53SAndroid Build Coastguard Worker  */
14*4dc78e53SAndroid Build Coastguard Worker 
15*4dc78e53SAndroid Build Coastguard Worker #include "nl-default.h"
16*4dc78e53SAndroid Build Coastguard Worker 
17*4dc78e53SAndroid Build Coastguard Worker #include <netlink/netlink.h>
18*4dc78e53SAndroid Build Coastguard Worker #include <netlink/cache.h>
19*4dc78e53SAndroid Build Coastguard Worker #include <netlink/utils.h>
20*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/qdisc.h>
21*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/class.h>
22*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/link.h>
23*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/qdisc/htb.h>
24*4dc78e53SAndroid Build Coastguard Worker 
25*4dc78e53SAndroid Build Coastguard Worker #include "tc-api.h"
26*4dc78e53SAndroid Build Coastguard Worker 
27*4dc78e53SAndroid Build Coastguard Worker /** @cond SKIP */
28*4dc78e53SAndroid Build Coastguard Worker struct rtnl_htb_qdisc {
29*4dc78e53SAndroid Build Coastguard Worker 	uint32_t qh_rate2quantum;
30*4dc78e53SAndroid Build Coastguard Worker 	uint32_t qh_defcls;
31*4dc78e53SAndroid Build Coastguard Worker 	uint32_t qh_mask;
32*4dc78e53SAndroid Build Coastguard Worker 	uint32_t qh_direct_pkts;
33*4dc78e53SAndroid Build Coastguard Worker };
34*4dc78e53SAndroid Build Coastguard Worker 
35*4dc78e53SAndroid Build Coastguard Worker struct rtnl_htb_class {
36*4dc78e53SAndroid Build Coastguard Worker 	uint32_t ch_prio;
37*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_ratespec ch_rate;
38*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_ratespec ch_ceil;
39*4dc78e53SAndroid Build Coastguard Worker 	uint32_t ch_rbuffer;
40*4dc78e53SAndroid Build Coastguard Worker 	uint32_t ch_cbuffer;
41*4dc78e53SAndroid Build Coastguard Worker 	uint32_t ch_quantum;
42*4dc78e53SAndroid Build Coastguard Worker 	uint32_t ch_mask;
43*4dc78e53SAndroid Build Coastguard Worker 	uint32_t ch_level;
44*4dc78e53SAndroid Build Coastguard Worker };
45*4dc78e53SAndroid Build Coastguard Worker 
46*4dc78e53SAndroid Build Coastguard Worker #define SCH_HTB_HAS_RATE2QUANTUM	0x01
47*4dc78e53SAndroid Build Coastguard Worker #define SCH_HTB_HAS_DEFCLS		0x02
48*4dc78e53SAndroid Build Coastguard Worker 
49*4dc78e53SAndroid Build Coastguard Worker #define SCH_HTB_HAS_PRIO		0x001
50*4dc78e53SAndroid Build Coastguard Worker #define SCH_HTB_HAS_RATE		0x002
51*4dc78e53SAndroid Build Coastguard Worker #define SCH_HTB_HAS_CEIL		0x004
52*4dc78e53SAndroid Build Coastguard Worker #define SCH_HTB_HAS_RBUFFER		0x008
53*4dc78e53SAndroid Build Coastguard Worker #define SCH_HTB_HAS_CBUFFER		0x010
54*4dc78e53SAndroid Build Coastguard Worker #define SCH_HTB_HAS_QUANTUM		0x020
55*4dc78e53SAndroid Build Coastguard Worker #define SCH_HTB_HAS_LEVEL		0x040
56*4dc78e53SAndroid Build Coastguard Worker /** @endcond */
57*4dc78e53SAndroid Build Coastguard Worker 
58*4dc78e53SAndroid Build Coastguard Worker static struct nla_policy htb_policy[TCA_HTB_MAX+1] = {
59*4dc78e53SAndroid Build Coastguard Worker 	[TCA_HTB_INIT]	= { .minlen = sizeof(struct tc_htb_glob) },
60*4dc78e53SAndroid Build Coastguard Worker 	[TCA_HTB_PARMS] = { .minlen = sizeof(struct tc_htb_opt) },
61*4dc78e53SAndroid Build Coastguard Worker 	[TCA_HTB_RATE64] = { .minlen = sizeof(uint64_t) },
62*4dc78e53SAndroid Build Coastguard Worker 	[TCA_HTB_CEIL64] = { .minlen = sizeof(uint64_t) },
63*4dc78e53SAndroid Build Coastguard Worker };
64*4dc78e53SAndroid Build Coastguard Worker 
htb_qdisc_msg_parser(struct rtnl_tc * tc,void * data)65*4dc78e53SAndroid Build Coastguard Worker static int htb_qdisc_msg_parser(struct rtnl_tc *tc, void *data)
66*4dc78e53SAndroid Build Coastguard Worker {
67*4dc78e53SAndroid Build Coastguard Worker 	struct nlattr *tb[TCA_HTB_MAX + 1];
68*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_htb_qdisc *htb = data;
69*4dc78e53SAndroid Build Coastguard Worker 	int err;
70*4dc78e53SAndroid Build Coastguard Worker 
71*4dc78e53SAndroid Build Coastguard Worker 	if ((err = tca_parse(tb, TCA_HTB_MAX, tc, htb_policy)) < 0)
72*4dc78e53SAndroid Build Coastguard Worker 		return err;
73*4dc78e53SAndroid Build Coastguard Worker 
74*4dc78e53SAndroid Build Coastguard Worker 	if (tb[TCA_HTB_INIT]) {
75*4dc78e53SAndroid Build Coastguard Worker 		struct tc_htb_glob opts;
76*4dc78e53SAndroid Build Coastguard Worker 
77*4dc78e53SAndroid Build Coastguard Worker 		nla_memcpy(&opts, tb[TCA_HTB_INIT], sizeof(opts));
78*4dc78e53SAndroid Build Coastguard Worker 		htb->qh_rate2quantum = opts.rate2quantum;
79*4dc78e53SAndroid Build Coastguard Worker 		htb->qh_defcls = opts.defcls;
80*4dc78e53SAndroid Build Coastguard Worker 		htb->qh_direct_pkts = opts.direct_pkts;
81*4dc78e53SAndroid Build Coastguard Worker 
82*4dc78e53SAndroid Build Coastguard Worker 		htb->qh_mask = (SCH_HTB_HAS_RATE2QUANTUM | SCH_HTB_HAS_DEFCLS);
83*4dc78e53SAndroid Build Coastguard Worker 	}
84*4dc78e53SAndroid Build Coastguard Worker 
85*4dc78e53SAndroid Build Coastguard Worker 	return 0;
86*4dc78e53SAndroid Build Coastguard Worker }
87*4dc78e53SAndroid Build Coastguard Worker 
htb_class_msg_parser(struct rtnl_tc * tc,void * data)88*4dc78e53SAndroid Build Coastguard Worker static int htb_class_msg_parser(struct rtnl_tc *tc, void *data)
89*4dc78e53SAndroid Build Coastguard Worker {
90*4dc78e53SAndroid Build Coastguard Worker 	struct nlattr *tb[TCA_HTB_MAX + 1];
91*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_htb_class *htb = data;
92*4dc78e53SAndroid Build Coastguard Worker 	int err;
93*4dc78e53SAndroid Build Coastguard Worker 
94*4dc78e53SAndroid Build Coastguard Worker 	if ((err = tca_parse(tb, TCA_HTB_MAX, tc, htb_policy)) < 0)
95*4dc78e53SAndroid Build Coastguard Worker 		return err;
96*4dc78e53SAndroid Build Coastguard Worker 
97*4dc78e53SAndroid Build Coastguard Worker 	if (tb[TCA_HTB_PARMS]) {
98*4dc78e53SAndroid Build Coastguard Worker 		struct tc_htb_opt opts;
99*4dc78e53SAndroid Build Coastguard Worker 
100*4dc78e53SAndroid Build Coastguard Worker 		nla_memcpy(&opts, tb[TCA_HTB_PARMS], sizeof(opts));
101*4dc78e53SAndroid Build Coastguard Worker 		htb->ch_prio = opts.prio;
102*4dc78e53SAndroid Build Coastguard Worker 		rtnl_copy_ratespec(&htb->ch_rate, &opts.rate);
103*4dc78e53SAndroid Build Coastguard Worker 		rtnl_copy_ratespec(&htb->ch_ceil, &opts.ceil);
104*4dc78e53SAndroid Build Coastguard Worker 
105*4dc78e53SAndroid Build Coastguard Worker 		if (tb[TCA_HTB_RATE64])
106*4dc78e53SAndroid Build Coastguard Worker 		        nla_memcpy(&htb->ch_rate.rs_rate64, tb[TCA_HTB_RATE64], sizeof(uint64_t));
107*4dc78e53SAndroid Build Coastguard Worker 		if (tb[TCA_HTB_CEIL64])
108*4dc78e53SAndroid Build Coastguard Worker 		        nla_memcpy(&htb->ch_ceil.rs_rate64, tb[TCA_HTB_CEIL64], sizeof(uint64_t));
109*4dc78e53SAndroid Build Coastguard Worker 
110*4dc78e53SAndroid Build Coastguard Worker 		htb->ch_rbuffer = rtnl_tc_calc_bufsize64(nl_ticks2us(opts.buffer),
111*4dc78e53SAndroid Build Coastguard Worker 		                                         htb->ch_rate.rs_rate64);
112*4dc78e53SAndroid Build Coastguard Worker 		htb->ch_cbuffer = rtnl_tc_calc_bufsize64(nl_ticks2us(opts.cbuffer),
113*4dc78e53SAndroid Build Coastguard Worker 		                                         htb->ch_ceil.rs_rate64);
114*4dc78e53SAndroid Build Coastguard Worker 		htb->ch_quantum = opts.quantum;
115*4dc78e53SAndroid Build Coastguard Worker 		htb->ch_level = opts.level;
116*4dc78e53SAndroid Build Coastguard Worker 
117*4dc78e53SAndroid Build Coastguard Worker 		rtnl_tc_set_mpu(tc, htb->ch_rate.rs_mpu);
118*4dc78e53SAndroid Build Coastguard Worker 		rtnl_tc_set_overhead(tc, htb->ch_rate.rs_overhead);
119*4dc78e53SAndroid Build Coastguard Worker 
120*4dc78e53SAndroid Build Coastguard Worker 		htb->ch_mask = (SCH_HTB_HAS_PRIO | SCH_HTB_HAS_RATE |
121*4dc78e53SAndroid Build Coastguard Worker 				SCH_HTB_HAS_CEIL | SCH_HTB_HAS_RBUFFER |
122*4dc78e53SAndroid Build Coastguard Worker 				SCH_HTB_HAS_CBUFFER | SCH_HTB_HAS_QUANTUM |
123*4dc78e53SAndroid Build Coastguard Worker 				SCH_HTB_HAS_LEVEL);
124*4dc78e53SAndroid Build Coastguard Worker 	}
125*4dc78e53SAndroid Build Coastguard Worker 
126*4dc78e53SAndroid Build Coastguard Worker 	return 0;
127*4dc78e53SAndroid Build Coastguard Worker }
128*4dc78e53SAndroid Build Coastguard Worker 
htb_qdisc_dump_line(struct rtnl_tc * tc,void * data,struct nl_dump_params * p)129*4dc78e53SAndroid Build Coastguard Worker static void htb_qdisc_dump_line(struct rtnl_tc *tc, void *data,
130*4dc78e53SAndroid Build Coastguard Worker 				struct nl_dump_params *p)
131*4dc78e53SAndroid Build Coastguard Worker {
132*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_htb_qdisc *htb = data;
133*4dc78e53SAndroid Build Coastguard Worker 
134*4dc78e53SAndroid Build Coastguard Worker 	if (!htb)
135*4dc78e53SAndroid Build Coastguard Worker 		return;
136*4dc78e53SAndroid Build Coastguard Worker 
137*4dc78e53SAndroid Build Coastguard Worker 	if (htb->qh_mask & SCH_HTB_HAS_RATE2QUANTUM)
138*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, " r2q %u", htb->qh_rate2quantum);
139*4dc78e53SAndroid Build Coastguard Worker 
140*4dc78e53SAndroid Build Coastguard Worker 	if (htb->qh_mask & SCH_HTB_HAS_DEFCLS) {
141*4dc78e53SAndroid Build Coastguard Worker 		char buf[64];
142*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, " default-class %s",
143*4dc78e53SAndroid Build Coastguard Worker 			rtnl_tc_handle2str(htb->qh_defcls, buf, sizeof(buf)));
144*4dc78e53SAndroid Build Coastguard Worker 	}
145*4dc78e53SAndroid Build Coastguard Worker }
146*4dc78e53SAndroid Build Coastguard Worker 
htb_class_dump_line(struct rtnl_tc * tc,void * data,struct nl_dump_params * p)147*4dc78e53SAndroid Build Coastguard Worker static void htb_class_dump_line(struct rtnl_tc *tc, void *data,
148*4dc78e53SAndroid Build Coastguard Worker 				struct nl_dump_params *p)
149*4dc78e53SAndroid Build Coastguard Worker {
150*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_htb_class *htb = data;
151*4dc78e53SAndroid Build Coastguard Worker 
152*4dc78e53SAndroid Build Coastguard Worker 	if (!htb)
153*4dc78e53SAndroid Build Coastguard Worker 		return;
154*4dc78e53SAndroid Build Coastguard Worker 
155*4dc78e53SAndroid Build Coastguard Worker 	if (htb->ch_mask & SCH_HTB_HAS_RATE) {
156*4dc78e53SAndroid Build Coastguard Worker 		double r, rbit;
157*4dc78e53SAndroid Build Coastguard Worker 		char *ru, *rubit;
158*4dc78e53SAndroid Build Coastguard Worker 
159*4dc78e53SAndroid Build Coastguard Worker 		r = nl_cancel_down_bytes(htb->ch_rate.rs_rate64, &ru);
160*4dc78e53SAndroid Build Coastguard Worker 		rbit = nl_cancel_down_bits(htb->ch_rate.rs_rate64*8, &rubit);
161*4dc78e53SAndroid Build Coastguard Worker 
162*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, " rate %.2f%s/s (%.0f%s) log %u",
163*4dc78e53SAndroid Build Coastguard Worker 			r, ru, rbit, rubit, 1<<htb->ch_rate.rs_cell_log);
164*4dc78e53SAndroid Build Coastguard Worker 	}
165*4dc78e53SAndroid Build Coastguard Worker }
166*4dc78e53SAndroid Build Coastguard Worker 
htb_class_dump_details(struct rtnl_tc * tc,void * data,struct nl_dump_params * p)167*4dc78e53SAndroid Build Coastguard Worker static void htb_class_dump_details(struct rtnl_tc *tc, void *data,
168*4dc78e53SAndroid Build Coastguard Worker 				   struct nl_dump_params *p)
169*4dc78e53SAndroid Build Coastguard Worker {
170*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_htb_class *htb = data;
171*4dc78e53SAndroid Build Coastguard Worker 
172*4dc78e53SAndroid Build Coastguard Worker 	if (!htb)
173*4dc78e53SAndroid Build Coastguard Worker 		return;
174*4dc78e53SAndroid Build Coastguard Worker 
175*4dc78e53SAndroid Build Coastguard Worker 	/* line 1 */
176*4dc78e53SAndroid Build Coastguard Worker 	if (htb->ch_mask & SCH_HTB_HAS_CEIL) {
177*4dc78e53SAndroid Build Coastguard Worker 		double r, rbit;
178*4dc78e53SAndroid Build Coastguard Worker 		char *ru, *rubit;
179*4dc78e53SAndroid Build Coastguard Worker 
180*4dc78e53SAndroid Build Coastguard Worker 		r = nl_cancel_down_bytes(htb->ch_ceil.rs_rate64, &ru);
181*4dc78e53SAndroid Build Coastguard Worker 		rbit = nl_cancel_down_bits(htb->ch_ceil.rs_rate64*8, &rubit);
182*4dc78e53SAndroid Build Coastguard Worker 
183*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, " ceil %.2f%s/s (%.0f%s) log %u",
184*4dc78e53SAndroid Build Coastguard Worker 			r, ru, rbit, rubit, 1<<htb->ch_ceil.rs_cell_log);
185*4dc78e53SAndroid Build Coastguard Worker 	}
186*4dc78e53SAndroid Build Coastguard Worker 
187*4dc78e53SAndroid Build Coastguard Worker 	if (htb->ch_mask & SCH_HTB_HAS_PRIO)
188*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, " prio %u", htb->ch_prio);
189*4dc78e53SAndroid Build Coastguard Worker 
190*4dc78e53SAndroid Build Coastguard Worker 	if (htb->ch_mask & SCH_HTB_HAS_RBUFFER) {
191*4dc78e53SAndroid Build Coastguard Worker 		double b;
192*4dc78e53SAndroid Build Coastguard Worker 		char *bu;
193*4dc78e53SAndroid Build Coastguard Worker 
194*4dc78e53SAndroid Build Coastguard Worker 		b = nl_cancel_down_bytes(htb->ch_rbuffer, &bu);
195*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, " rbuffer %.2f%s", b, bu);
196*4dc78e53SAndroid Build Coastguard Worker 	}
197*4dc78e53SAndroid Build Coastguard Worker 
198*4dc78e53SAndroid Build Coastguard Worker 	if (htb->ch_mask & SCH_HTB_HAS_CBUFFER) {
199*4dc78e53SAndroid Build Coastguard Worker 		double b;
200*4dc78e53SAndroid Build Coastguard Worker 		char *bu;
201*4dc78e53SAndroid Build Coastguard Worker 
202*4dc78e53SAndroid Build Coastguard Worker 		b = nl_cancel_down_bytes(htb->ch_cbuffer, &bu);
203*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, " cbuffer %.2f%s", b, bu);
204*4dc78e53SAndroid Build Coastguard Worker 	}
205*4dc78e53SAndroid Build Coastguard Worker 
206*4dc78e53SAndroid Build Coastguard Worker 	if (htb->ch_mask & SCH_HTB_HAS_QUANTUM)
207*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, " quantum %u", htb->ch_quantum);
208*4dc78e53SAndroid Build Coastguard Worker }
209*4dc78e53SAndroid Build Coastguard Worker 
htb_qdisc_msg_fill(struct rtnl_tc * tc,void * data,struct nl_msg * msg)210*4dc78e53SAndroid Build Coastguard Worker static int htb_qdisc_msg_fill(struct rtnl_tc *tc, void *data,
211*4dc78e53SAndroid Build Coastguard Worker 			      struct nl_msg *msg)
212*4dc78e53SAndroid Build Coastguard Worker {
213*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_htb_qdisc *htb = data;
214*4dc78e53SAndroid Build Coastguard Worker 	struct tc_htb_glob opts = {
215*4dc78e53SAndroid Build Coastguard Worker 		.version = TC_HTB_PROTOVER,
216*4dc78e53SAndroid Build Coastguard Worker 		.rate2quantum = 10,
217*4dc78e53SAndroid Build Coastguard Worker 	};
218*4dc78e53SAndroid Build Coastguard Worker 
219*4dc78e53SAndroid Build Coastguard Worker 	if (htb) {
220*4dc78e53SAndroid Build Coastguard Worker 		if (htb->qh_mask & SCH_HTB_HAS_RATE2QUANTUM)
221*4dc78e53SAndroid Build Coastguard Worker 			opts.rate2quantum = htb->qh_rate2quantum;
222*4dc78e53SAndroid Build Coastguard Worker 
223*4dc78e53SAndroid Build Coastguard Worker 		if (htb->qh_mask & SCH_HTB_HAS_DEFCLS)
224*4dc78e53SAndroid Build Coastguard Worker 			opts.defcls = htb->qh_defcls;
225*4dc78e53SAndroid Build Coastguard Worker 	}
226*4dc78e53SAndroid Build Coastguard Worker 
227*4dc78e53SAndroid Build Coastguard Worker 	return nla_put(msg, TCA_HTB_INIT, sizeof(opts), &opts);
228*4dc78e53SAndroid Build Coastguard Worker }
229*4dc78e53SAndroid Build Coastguard Worker 
htb_class_msg_fill(struct rtnl_tc * tc,void * data,struct nl_msg * msg)230*4dc78e53SAndroid Build Coastguard Worker static int htb_class_msg_fill(struct rtnl_tc *tc, void *data,
231*4dc78e53SAndroid Build Coastguard Worker 			      struct nl_msg *msg)
232*4dc78e53SAndroid Build Coastguard Worker {
233*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_htb_class *htb = data;
234*4dc78e53SAndroid Build Coastguard Worker 	uint32_t mtu, rtable[RTNL_TC_RTABLE_SIZE], ctable[RTNL_TC_RTABLE_SIZE];
235*4dc78e53SAndroid Build Coastguard Worker 	struct tc_htb_opt opts;
236*4dc78e53SAndroid Build Coastguard Worker 	int buffer, cbuffer;
237*4dc78e53SAndroid Build Coastguard Worker 	uint64_t rate64;
238*4dc78e53SAndroid Build Coastguard Worker 	uint64_t ceil64;
239*4dc78e53SAndroid Build Coastguard Worker 
240*4dc78e53SAndroid Build Coastguard Worker 	if (!htb || !(htb->ch_mask & SCH_HTB_HAS_RATE))
241*4dc78e53SAndroid Build Coastguard Worker 		BUG();
242*4dc78e53SAndroid Build Coastguard Worker 
243*4dc78e53SAndroid Build Coastguard Worker 	memset(&opts, 0, sizeof(opts));
244*4dc78e53SAndroid Build Coastguard Worker 
245*4dc78e53SAndroid Build Coastguard Worker 	/* if not set, zero (0) is used as priority */
246*4dc78e53SAndroid Build Coastguard Worker 	if (htb->ch_mask & SCH_HTB_HAS_PRIO)
247*4dc78e53SAndroid Build Coastguard Worker 		opts.prio = htb->ch_prio;
248*4dc78e53SAndroid Build Coastguard Worker 
249*4dc78e53SAndroid Build Coastguard Worker 	mtu = rtnl_tc_get_mtu(tc);
250*4dc78e53SAndroid Build Coastguard Worker 
251*4dc78e53SAndroid Build Coastguard Worker 	rtnl_tc_build_rate_table(tc, &htb->ch_rate, rtable);
252*4dc78e53SAndroid Build Coastguard Worker 	rtnl_rcopy_ratespec(&opts.rate, &htb->ch_rate);
253*4dc78e53SAndroid Build Coastguard Worker 	rate64 = htb->ch_rate.rs_rate64;
254*4dc78e53SAndroid Build Coastguard Worker 
255*4dc78e53SAndroid Build Coastguard Worker 	if (htb->ch_mask & SCH_HTB_HAS_CEIL) {
256*4dc78e53SAndroid Build Coastguard Worker 		rtnl_tc_build_rate_table(tc, &htb->ch_ceil, ctable);
257*4dc78e53SAndroid Build Coastguard Worker 		rtnl_rcopy_ratespec(&opts.ceil, &htb->ch_ceil);
258*4dc78e53SAndroid Build Coastguard Worker 		ceil64 = htb->ch_ceil.rs_rate64;
259*4dc78e53SAndroid Build Coastguard Worker 	} else {
260*4dc78e53SAndroid Build Coastguard Worker 		/*
261*4dc78e53SAndroid Build Coastguard Worker 		 * If not set, configured rate is used as ceil, which implies
262*4dc78e53SAndroid Build Coastguard Worker 		 * no borrowing.
263*4dc78e53SAndroid Build Coastguard Worker 		 */
264*4dc78e53SAndroid Build Coastguard Worker 		memcpy(&opts.ceil, &opts.rate, sizeof(struct tc_ratespec));
265*4dc78e53SAndroid Build Coastguard Worker 		ceil64 = rate64;
266*4dc78e53SAndroid Build Coastguard Worker 	}
267*4dc78e53SAndroid Build Coastguard Worker 
268*4dc78e53SAndroid Build Coastguard Worker 	if (htb->ch_mask & SCH_HTB_HAS_RBUFFER)
269*4dc78e53SAndroid Build Coastguard Worker 		buffer = htb->ch_rbuffer;
270*4dc78e53SAndroid Build Coastguard Worker 	else
271*4dc78e53SAndroid Build Coastguard Worker 		buffer = rate64 / nl_get_psched_hz() + mtu; /* XXX */
272*4dc78e53SAndroid Build Coastguard Worker 
273*4dc78e53SAndroid Build Coastguard Worker 	opts.buffer = nl_us2ticks(rtnl_tc_calc_txtime64(buffer, rate64));
274*4dc78e53SAndroid Build Coastguard Worker 
275*4dc78e53SAndroid Build Coastguard Worker 	if (htb->ch_mask & SCH_HTB_HAS_CBUFFER)
276*4dc78e53SAndroid Build Coastguard Worker 		cbuffer = htb->ch_cbuffer;
277*4dc78e53SAndroid Build Coastguard Worker 	else
278*4dc78e53SAndroid Build Coastguard Worker 		cbuffer = ceil64 / nl_get_psched_hz() + mtu; /* XXX */
279*4dc78e53SAndroid Build Coastguard Worker 
280*4dc78e53SAndroid Build Coastguard Worker 	opts.cbuffer = nl_us2ticks(rtnl_tc_calc_txtime64(cbuffer, ceil64));
281*4dc78e53SAndroid Build Coastguard Worker 
282*4dc78e53SAndroid Build Coastguard Worker 	if (htb->ch_mask & SCH_HTB_HAS_QUANTUM)
283*4dc78e53SAndroid Build Coastguard Worker 		opts.quantum = htb->ch_quantum;
284*4dc78e53SAndroid Build Coastguard Worker 
285*4dc78e53SAndroid Build Coastguard Worker 	NLA_PUT(msg, TCA_HTB_PARMS, sizeof(opts), &opts);
286*4dc78e53SAndroid Build Coastguard Worker 	if (rate64 > 0xFFFFFFFFull)
287*4dc78e53SAndroid Build Coastguard Worker 		NLA_PUT(msg, TCA_HTB_RATE64, sizeof(uint64_t), &rate64);
288*4dc78e53SAndroid Build Coastguard Worker 	if (ceil64 > 0xFFFFFFFFull)
289*4dc78e53SAndroid Build Coastguard Worker 		NLA_PUT(msg, TCA_HTB_CEIL64, sizeof(uint64_t), &ceil64);
290*4dc78e53SAndroid Build Coastguard Worker 	NLA_PUT(msg, TCA_HTB_RTAB, sizeof(rtable), &rtable);
291*4dc78e53SAndroid Build Coastguard Worker 	NLA_PUT(msg, TCA_HTB_CTAB, sizeof(ctable), &ctable);
292*4dc78e53SAndroid Build Coastguard Worker 
293*4dc78e53SAndroid Build Coastguard Worker 	return 0;
294*4dc78e53SAndroid Build Coastguard Worker 
295*4dc78e53SAndroid Build Coastguard Worker nla_put_failure:
296*4dc78e53SAndroid Build Coastguard Worker 	return -NLE_MSGSIZE;
297*4dc78e53SAndroid Build Coastguard Worker }
298*4dc78e53SAndroid Build Coastguard Worker 
299*4dc78e53SAndroid Build Coastguard Worker static struct rtnl_tc_ops htb_qdisc_ops;
300*4dc78e53SAndroid Build Coastguard Worker static struct rtnl_tc_ops htb_class_ops;
301*4dc78e53SAndroid Build Coastguard Worker 
htb_qdisc_data(struct rtnl_qdisc * qdisc,int * err)302*4dc78e53SAndroid Build Coastguard Worker static struct rtnl_htb_qdisc *htb_qdisc_data(struct rtnl_qdisc *qdisc, int *err)
303*4dc78e53SAndroid Build Coastguard Worker {
304*4dc78e53SAndroid Build Coastguard Worker 	return rtnl_tc_data_check(TC_CAST(qdisc), &htb_qdisc_ops, err);
305*4dc78e53SAndroid Build Coastguard Worker }
306*4dc78e53SAndroid Build Coastguard Worker 
htb_class_data(struct rtnl_class * class,int * err)307*4dc78e53SAndroid Build Coastguard Worker static struct rtnl_htb_class *htb_class_data(struct rtnl_class *class, int *err)
308*4dc78e53SAndroid Build Coastguard Worker {
309*4dc78e53SAndroid Build Coastguard Worker 	return rtnl_tc_data_check(TC_CAST(class), &htb_class_ops, err);
310*4dc78e53SAndroid Build Coastguard Worker }
311*4dc78e53SAndroid Build Coastguard Worker 
312*4dc78e53SAndroid Build Coastguard Worker /**
313*4dc78e53SAndroid Build Coastguard Worker  * @name Attribute Modifications
314*4dc78e53SAndroid Build Coastguard Worker  * @{
315*4dc78e53SAndroid Build Coastguard Worker  */
316*4dc78e53SAndroid Build Coastguard Worker 
317*4dc78e53SAndroid Build Coastguard Worker /**
318*4dc78e53SAndroid Build Coastguard Worker  * Return rate/quantum ratio of HTB qdisc
319*4dc78e53SAndroid Build Coastguard Worker  * @arg qdisc		htb qdisc object
320*4dc78e53SAndroid Build Coastguard Worker  *
321*4dc78e53SAndroid Build Coastguard Worker  * @return rate/quantum ratio or 0 if unspecified
322*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_htb_get_rate2quantum(struct rtnl_qdisc * qdisc)323*4dc78e53SAndroid Build Coastguard Worker uint32_t rtnl_htb_get_rate2quantum(struct rtnl_qdisc *qdisc)
324*4dc78e53SAndroid Build Coastguard Worker {
325*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_htb_qdisc *htb;
326*4dc78e53SAndroid Build Coastguard Worker 
327*4dc78e53SAndroid Build Coastguard Worker 	if ((htb = htb_qdisc_data(qdisc, NULL)) &&
328*4dc78e53SAndroid Build Coastguard Worker 	    (htb->qh_mask & SCH_HTB_HAS_RATE2QUANTUM))
329*4dc78e53SAndroid Build Coastguard Worker 		return htb->qh_rate2quantum;
330*4dc78e53SAndroid Build Coastguard Worker 
331*4dc78e53SAndroid Build Coastguard Worker 	return 0;
332*4dc78e53SAndroid Build Coastguard Worker }
333*4dc78e53SAndroid Build Coastguard Worker 
rtnl_htb_set_rate2quantum(struct rtnl_qdisc * qdisc,uint32_t rate2quantum)334*4dc78e53SAndroid Build Coastguard Worker int rtnl_htb_set_rate2quantum(struct rtnl_qdisc *qdisc, uint32_t rate2quantum)
335*4dc78e53SAndroid Build Coastguard Worker {
336*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_htb_qdisc *htb;
337*4dc78e53SAndroid Build Coastguard Worker 	int err;
338*4dc78e53SAndroid Build Coastguard Worker 
339*4dc78e53SAndroid Build Coastguard Worker 	if (!(htb = htb_qdisc_data(qdisc, &err)))
340*4dc78e53SAndroid Build Coastguard Worker 		return err;
341*4dc78e53SAndroid Build Coastguard Worker 
342*4dc78e53SAndroid Build Coastguard Worker 	htb->qh_rate2quantum = rate2quantum;
343*4dc78e53SAndroid Build Coastguard Worker 	htb->qh_mask |= SCH_HTB_HAS_RATE2QUANTUM;
344*4dc78e53SAndroid Build Coastguard Worker 
345*4dc78e53SAndroid Build Coastguard Worker 	return 0;
346*4dc78e53SAndroid Build Coastguard Worker }
347*4dc78e53SAndroid Build Coastguard Worker 
348*4dc78e53SAndroid Build Coastguard Worker /**
349*4dc78e53SAndroid Build Coastguard Worker  * Return default class of HTB qdisc
350*4dc78e53SAndroid Build Coastguard Worker  * @arg qdisc		htb qdisc object
351*4dc78e53SAndroid Build Coastguard Worker  *
352*4dc78e53SAndroid Build Coastguard Worker  * Returns the classid of the class where all unclassified traffic
353*4dc78e53SAndroid Build Coastguard Worker  * goes to.
354*4dc78e53SAndroid Build Coastguard Worker  *
355*4dc78e53SAndroid Build Coastguard Worker  * @return classid or TC_H_UNSPEC if unspecified.
356*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_htb_get_defcls(struct rtnl_qdisc * qdisc)357*4dc78e53SAndroid Build Coastguard Worker uint32_t rtnl_htb_get_defcls(struct rtnl_qdisc *qdisc)
358*4dc78e53SAndroid Build Coastguard Worker {
359*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_htb_qdisc *htb;
360*4dc78e53SAndroid Build Coastguard Worker 
361*4dc78e53SAndroid Build Coastguard Worker 	if ((htb = htb_qdisc_data(qdisc, NULL)) &&
362*4dc78e53SAndroid Build Coastguard Worker 	    htb->qh_mask & SCH_HTB_HAS_DEFCLS)
363*4dc78e53SAndroid Build Coastguard Worker 		return htb->qh_defcls;
364*4dc78e53SAndroid Build Coastguard Worker 
365*4dc78e53SAndroid Build Coastguard Worker 	return TC_H_UNSPEC;
366*4dc78e53SAndroid Build Coastguard Worker }
367*4dc78e53SAndroid Build Coastguard Worker 
368*4dc78e53SAndroid Build Coastguard Worker /**
369*4dc78e53SAndroid Build Coastguard Worker  * Set default class of the htb qdisc to the specified value
370*4dc78e53SAndroid Build Coastguard Worker  * @arg qdisc		qdisc to change
371*4dc78e53SAndroid Build Coastguard Worker  * @arg defcls		new default class
372*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_htb_set_defcls(struct rtnl_qdisc * qdisc,uint32_t defcls)373*4dc78e53SAndroid Build Coastguard Worker int rtnl_htb_set_defcls(struct rtnl_qdisc *qdisc, uint32_t defcls)
374*4dc78e53SAndroid Build Coastguard Worker {
375*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_htb_qdisc *htb;
376*4dc78e53SAndroid Build Coastguard Worker 	int err;
377*4dc78e53SAndroid Build Coastguard Worker 
378*4dc78e53SAndroid Build Coastguard Worker 	if (!(htb = htb_qdisc_data(qdisc, &err)))
379*4dc78e53SAndroid Build Coastguard Worker 		return err;
380*4dc78e53SAndroid Build Coastguard Worker 
381*4dc78e53SAndroid Build Coastguard Worker 	htb->qh_defcls = defcls;
382*4dc78e53SAndroid Build Coastguard Worker 	htb->qh_mask |= SCH_HTB_HAS_DEFCLS;
383*4dc78e53SAndroid Build Coastguard Worker 
384*4dc78e53SAndroid Build Coastguard Worker 	return 0;
385*4dc78e53SAndroid Build Coastguard Worker }
386*4dc78e53SAndroid Build Coastguard Worker 
rtnl_htb_get_prio(struct rtnl_class * class)387*4dc78e53SAndroid Build Coastguard Worker uint32_t rtnl_htb_get_prio(struct rtnl_class *class)
388*4dc78e53SAndroid Build Coastguard Worker {
389*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_htb_class *htb;
390*4dc78e53SAndroid Build Coastguard Worker 
391*4dc78e53SAndroid Build Coastguard Worker 	if ((htb = htb_class_data(class, NULL)) &&
392*4dc78e53SAndroid Build Coastguard Worker 	    (htb->ch_mask & SCH_HTB_HAS_PRIO))
393*4dc78e53SAndroid Build Coastguard Worker 		return htb->ch_prio;
394*4dc78e53SAndroid Build Coastguard Worker 
395*4dc78e53SAndroid Build Coastguard Worker 	return 0;
396*4dc78e53SAndroid Build Coastguard Worker }
397*4dc78e53SAndroid Build Coastguard Worker 
rtnl_htb_set_prio(struct rtnl_class * class,uint32_t prio)398*4dc78e53SAndroid Build Coastguard Worker int rtnl_htb_set_prio(struct rtnl_class *class, uint32_t prio)
399*4dc78e53SAndroid Build Coastguard Worker {
400*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_htb_class *htb;
401*4dc78e53SAndroid Build Coastguard Worker 	int err;
402*4dc78e53SAndroid Build Coastguard Worker 
403*4dc78e53SAndroid Build Coastguard Worker 	if (!(htb = htb_class_data(class, &err)))
404*4dc78e53SAndroid Build Coastguard Worker 		return err;
405*4dc78e53SAndroid Build Coastguard Worker 
406*4dc78e53SAndroid Build Coastguard Worker 	htb->ch_prio = prio;
407*4dc78e53SAndroid Build Coastguard Worker 	htb->ch_mask |= SCH_HTB_HAS_PRIO;
408*4dc78e53SAndroid Build Coastguard Worker 
409*4dc78e53SAndroid Build Coastguard Worker 	return 0;
410*4dc78e53SAndroid Build Coastguard Worker }
411*4dc78e53SAndroid Build Coastguard Worker 
412*4dc78e53SAndroid Build Coastguard Worker /**
413*4dc78e53SAndroid Build Coastguard Worker  * Return rate of HTB class
414*4dc78e53SAndroid Build Coastguard Worker  * @arg class		htb class object
415*4dc78e53SAndroid Build Coastguard Worker  *
416*4dc78e53SAndroid Build Coastguard Worker  * @return Rate in bytes/s or 0 if unspecified. If the value
417*4dc78e53SAndroid Build Coastguard Worker  *   cannot be represented as 32 bit integer, (1<<32) is returned.
418*4dc78e53SAndroid Build Coastguard Worker  *   Use rtnl_htb_get_rate64() instead.
419*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_htb_get_rate(struct rtnl_class * class)420*4dc78e53SAndroid Build Coastguard Worker uint32_t rtnl_htb_get_rate(struct rtnl_class *class)
421*4dc78e53SAndroid Build Coastguard Worker {
422*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_htb_class *htb;
423*4dc78e53SAndroid Build Coastguard Worker 
424*4dc78e53SAndroid Build Coastguard Worker 	if (   !(htb = htb_class_data(class, NULL))
425*4dc78e53SAndroid Build Coastguard Worker 	    || !(htb->ch_mask & SCH_HTB_HAS_RATE))
426*4dc78e53SAndroid Build Coastguard Worker 	    return 0;
427*4dc78e53SAndroid Build Coastguard Worker 
428*4dc78e53SAndroid Build Coastguard Worker 	if (htb->ch_rate.rs_rate64 > 0xFFFFFFFFull)
429*4dc78e53SAndroid Build Coastguard Worker 		return 0xFFFFFFFFull;
430*4dc78e53SAndroid Build Coastguard Worker 
431*4dc78e53SAndroid Build Coastguard Worker 	return htb->ch_rate.rs_rate64;
432*4dc78e53SAndroid Build Coastguard Worker }
433*4dc78e53SAndroid Build Coastguard Worker 
434*4dc78e53SAndroid Build Coastguard Worker /**
435*4dc78e53SAndroid Build Coastguard Worker  * Return rate of HTB class
436*4dc78e53SAndroid Build Coastguard Worker  * @arg class		htb class object
437*4dc78e53SAndroid Build Coastguard Worker  * @arg out_rate64      on success, the set rate.
438*4dc78e53SAndroid Build Coastguard Worker  *
439*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
440*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_htb_get_rate64(struct rtnl_class * class,uint64_t * out_rate64)441*4dc78e53SAndroid Build Coastguard Worker int rtnl_htb_get_rate64(struct rtnl_class *class, uint64_t *out_rate64)
442*4dc78e53SAndroid Build Coastguard Worker {
443*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_htb_class *htb;
444*4dc78e53SAndroid Build Coastguard Worker 
445*4dc78e53SAndroid Build Coastguard Worker 	if (!(htb = htb_class_data(class, NULL)))
446*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_INVAL;
447*4dc78e53SAndroid Build Coastguard Worker 	if (!(htb->ch_mask & SCH_HTB_HAS_RATE))
448*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_NOATTR;
449*4dc78e53SAndroid Build Coastguard Worker 
450*4dc78e53SAndroid Build Coastguard Worker 	*out_rate64 = htb->ch_rate.rs_rate64;
451*4dc78e53SAndroid Build Coastguard Worker 	return 0;
452*4dc78e53SAndroid Build Coastguard Worker }
453*4dc78e53SAndroid Build Coastguard Worker 
454*4dc78e53SAndroid Build Coastguard Worker /**
455*4dc78e53SAndroid Build Coastguard Worker  * Set rate of HTB class
456*4dc78e53SAndroid Build Coastguard Worker  * @arg class		htb class object
457*4dc78e53SAndroid Build Coastguard Worker  * @arg rate		new rate in bytes per second
458*4dc78e53SAndroid Build Coastguard Worker  *
459*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
460*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_htb_set_rate(struct rtnl_class * class,uint32_t rate)461*4dc78e53SAndroid Build Coastguard Worker int rtnl_htb_set_rate(struct rtnl_class *class, uint32_t rate)
462*4dc78e53SAndroid Build Coastguard Worker {
463*4dc78e53SAndroid Build Coastguard Worker 	return rtnl_htb_set_rate64(class, rate);
464*4dc78e53SAndroid Build Coastguard Worker }
465*4dc78e53SAndroid Build Coastguard Worker 
466*4dc78e53SAndroid Build Coastguard Worker /**
467*4dc78e53SAndroid Build Coastguard Worker  * Set rate of HTB class
468*4dc78e53SAndroid Build Coastguard Worker  * @arg class		htb class object
469*4dc78e53SAndroid Build Coastguard Worker  * @arg rate		new rate in bytes per second
470*4dc78e53SAndroid Build Coastguard Worker  *
471*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
472*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_htb_set_rate64(struct rtnl_class * class,uint64_t rate)473*4dc78e53SAndroid Build Coastguard Worker int rtnl_htb_set_rate64(struct rtnl_class *class, uint64_t rate)
474*4dc78e53SAndroid Build Coastguard Worker {
475*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_htb_class *htb;
476*4dc78e53SAndroid Build Coastguard Worker 	int err;
477*4dc78e53SAndroid Build Coastguard Worker 
478*4dc78e53SAndroid Build Coastguard Worker 	if (!(htb = htb_class_data(class, &err)))
479*4dc78e53SAndroid Build Coastguard Worker 		return err;
480*4dc78e53SAndroid Build Coastguard Worker 
481*4dc78e53SAndroid Build Coastguard Worker 	htb->ch_rate.rs_cell_log = UINT8_MAX; /* use default value */
482*4dc78e53SAndroid Build Coastguard Worker 	htb->ch_rate.rs_rate64 = rate;
483*4dc78e53SAndroid Build Coastguard Worker 	htb->ch_mask |= SCH_HTB_HAS_RATE;
484*4dc78e53SAndroid Build Coastguard Worker 
485*4dc78e53SAndroid Build Coastguard Worker 	return 0;
486*4dc78e53SAndroid Build Coastguard Worker }
487*4dc78e53SAndroid Build Coastguard Worker 
488*4dc78e53SAndroid Build Coastguard Worker /**
489*4dc78e53SAndroid Build Coastguard Worker  * Return ceil rate of HTB class
490*4dc78e53SAndroid Build Coastguard Worker  * @arg class		htb class object
491*4dc78e53SAndroid Build Coastguard Worker  *
492*4dc78e53SAndroid Build Coastguard Worker  * @return Ceil rate in bytes/s or 0 if unspecified.  If the value
493*4dc78e53SAndroid Build Coastguard Worker  *   cannot be represented as 32 bit integer, (1<<32) is returned.
494*4dc78e53SAndroid Build Coastguard Worker  *   Use rtnl_htb_get_ceil64() instead.
495*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_htb_get_ceil(struct rtnl_class * class)496*4dc78e53SAndroid Build Coastguard Worker uint32_t rtnl_htb_get_ceil(struct rtnl_class *class)
497*4dc78e53SAndroid Build Coastguard Worker {
498*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_htb_class *htb;
499*4dc78e53SAndroid Build Coastguard Worker 
500*4dc78e53SAndroid Build Coastguard Worker 	if (   !(htb = htb_class_data(class, NULL))
501*4dc78e53SAndroid Build Coastguard Worker 	    || !(htb->ch_mask & SCH_HTB_HAS_CEIL))
502*4dc78e53SAndroid Build Coastguard Worker 		return 0;
503*4dc78e53SAndroid Build Coastguard Worker 
504*4dc78e53SAndroid Build Coastguard Worker 	if (htb->ch_ceil.rs_rate64 > 0xFFFFFFFFull)
505*4dc78e53SAndroid Build Coastguard Worker 		return 0xFFFFFFFFull;
506*4dc78e53SAndroid Build Coastguard Worker 
507*4dc78e53SAndroid Build Coastguard Worker 	return htb->ch_ceil.rs_rate64;
508*4dc78e53SAndroid Build Coastguard Worker }
509*4dc78e53SAndroid Build Coastguard Worker 
510*4dc78e53SAndroid Build Coastguard Worker /**
511*4dc78e53SAndroid Build Coastguard Worker  * Return ceil rate of HTB class
512*4dc78e53SAndroid Build Coastguard Worker  * @arg class		htb class object
513*4dc78e53SAndroid Build Coastguard Worker  * @arg out_ceil64      on success, the set ceil value.
514*4dc78e53SAndroid Build Coastguard Worker  *
515*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
516*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_htb_get_ceil64(struct rtnl_class * class,uint64_t * out_ceil64)517*4dc78e53SAndroid Build Coastguard Worker int rtnl_htb_get_ceil64(struct rtnl_class *class, uint64_t *out_ceil64)
518*4dc78e53SAndroid Build Coastguard Worker {
519*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_htb_class *htb;
520*4dc78e53SAndroid Build Coastguard Worker 
521*4dc78e53SAndroid Build Coastguard Worker 	if (!(htb = htb_class_data(class, NULL)))
522*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_INVAL;
523*4dc78e53SAndroid Build Coastguard Worker 	if (!(htb->ch_mask & SCH_HTB_HAS_CEIL))
524*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_NOATTR;
525*4dc78e53SAndroid Build Coastguard Worker 
526*4dc78e53SAndroid Build Coastguard Worker 	*out_ceil64 = htb->ch_ceil.rs_rate64;
527*4dc78e53SAndroid Build Coastguard Worker 	return 0;
528*4dc78e53SAndroid Build Coastguard Worker }
529*4dc78e53SAndroid Build Coastguard Worker 
530*4dc78e53SAndroid Build Coastguard Worker /**
531*4dc78e53SAndroid Build Coastguard Worker  * Set ceil rate of HTB class
532*4dc78e53SAndroid Build Coastguard Worker  * @arg class		htb class object
533*4dc78e53SAndroid Build Coastguard Worker  * @arg ceil		new ceil rate number of bytes per second
534*4dc78e53SAndroid Build Coastguard Worker  *
535*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
536*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_htb_set_ceil(struct rtnl_class * class,uint32_t ceil)537*4dc78e53SAndroid Build Coastguard Worker int rtnl_htb_set_ceil(struct rtnl_class *class, uint32_t ceil)
538*4dc78e53SAndroid Build Coastguard Worker {
539*4dc78e53SAndroid Build Coastguard Worker 	return rtnl_htb_set_ceil64(class, ceil);
540*4dc78e53SAndroid Build Coastguard Worker }
541*4dc78e53SAndroid Build Coastguard Worker 
542*4dc78e53SAndroid Build Coastguard Worker /**
543*4dc78e53SAndroid Build Coastguard Worker  * Set ceil rate of HTB class
544*4dc78e53SAndroid Build Coastguard Worker  * @arg class		htb class object
545*4dc78e53SAndroid Build Coastguard Worker  * @arg ceil64		new ceil rate number of bytes per second
546*4dc78e53SAndroid Build Coastguard Worker  *
547*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
548*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_htb_set_ceil64(struct rtnl_class * class,uint64_t ceil64)549*4dc78e53SAndroid Build Coastguard Worker int rtnl_htb_set_ceil64(struct rtnl_class *class, uint64_t ceil64)
550*4dc78e53SAndroid Build Coastguard Worker {
551*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_htb_class *htb;
552*4dc78e53SAndroid Build Coastguard Worker 	int err;
553*4dc78e53SAndroid Build Coastguard Worker 
554*4dc78e53SAndroid Build Coastguard Worker 	if (!(htb = htb_class_data(class, &err)))
555*4dc78e53SAndroid Build Coastguard Worker 		return err;
556*4dc78e53SAndroid Build Coastguard Worker 
557*4dc78e53SAndroid Build Coastguard Worker 	htb->ch_ceil.rs_cell_log = UINT8_MAX; /* use default value */
558*4dc78e53SAndroid Build Coastguard Worker 	htb->ch_ceil.rs_rate64 = ceil64;
559*4dc78e53SAndroid Build Coastguard Worker 	htb->ch_mask |= SCH_HTB_HAS_CEIL;
560*4dc78e53SAndroid Build Coastguard Worker 
561*4dc78e53SAndroid Build Coastguard Worker 	return 0;
562*4dc78e53SAndroid Build Coastguard Worker }
563*4dc78e53SAndroid Build Coastguard Worker 
564*4dc78e53SAndroid Build Coastguard Worker /**
565*4dc78e53SAndroid Build Coastguard Worker  * Return burst buffer size of HTB class
566*4dc78e53SAndroid Build Coastguard Worker  * @arg class		htb class object
567*4dc78e53SAndroid Build Coastguard Worker  *
568*4dc78e53SAndroid Build Coastguard Worker  * @return Burst buffer size or 0 if unspecified
569*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_htb_get_rbuffer(struct rtnl_class * class)570*4dc78e53SAndroid Build Coastguard Worker uint32_t rtnl_htb_get_rbuffer(struct rtnl_class *class)
571*4dc78e53SAndroid Build Coastguard Worker {
572*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_htb_class *htb;
573*4dc78e53SAndroid Build Coastguard Worker 
574*4dc78e53SAndroid Build Coastguard Worker 	if ((htb = htb_class_data(class, NULL)) &&
575*4dc78e53SAndroid Build Coastguard Worker 	     htb->ch_mask & SCH_HTB_HAS_RBUFFER)
576*4dc78e53SAndroid Build Coastguard Worker 		return htb->ch_rbuffer;
577*4dc78e53SAndroid Build Coastguard Worker 
578*4dc78e53SAndroid Build Coastguard Worker 	return 0;
579*4dc78e53SAndroid Build Coastguard Worker }
580*4dc78e53SAndroid Build Coastguard Worker 
581*4dc78e53SAndroid Build Coastguard Worker /**
582*4dc78e53SAndroid Build Coastguard Worker  * Set size of the rate bucket of HTB class.
583*4dc78e53SAndroid Build Coastguard Worker  * @arg class		HTB class to be modified.
584*4dc78e53SAndroid Build Coastguard Worker  * @arg rbuffer		New size in bytes.
585*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_htb_set_rbuffer(struct rtnl_class * class,uint32_t rbuffer)586*4dc78e53SAndroid Build Coastguard Worker int rtnl_htb_set_rbuffer(struct rtnl_class *class, uint32_t rbuffer)
587*4dc78e53SAndroid Build Coastguard Worker {
588*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_htb_class *htb;
589*4dc78e53SAndroid Build Coastguard Worker 	int err;
590*4dc78e53SAndroid Build Coastguard Worker 
591*4dc78e53SAndroid Build Coastguard Worker 	if (!(htb = htb_class_data(class, &err)))
592*4dc78e53SAndroid Build Coastguard Worker 		return err;
593*4dc78e53SAndroid Build Coastguard Worker 
594*4dc78e53SAndroid Build Coastguard Worker 	htb->ch_rbuffer = rbuffer;
595*4dc78e53SAndroid Build Coastguard Worker 	htb->ch_mask |= SCH_HTB_HAS_RBUFFER;
596*4dc78e53SAndroid Build Coastguard Worker 
597*4dc78e53SAndroid Build Coastguard Worker 	return 0;
598*4dc78e53SAndroid Build Coastguard Worker }
599*4dc78e53SAndroid Build Coastguard Worker 
600*4dc78e53SAndroid Build Coastguard Worker /**
601*4dc78e53SAndroid Build Coastguard Worker  * Return ceil burst buffer size of HTB class
602*4dc78e53SAndroid Build Coastguard Worker  * @arg class		htb class object
603*4dc78e53SAndroid Build Coastguard Worker  *
604*4dc78e53SAndroid Build Coastguard Worker  * @return Ceil burst buffer size or 0 if unspecified
605*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_htb_get_cbuffer(struct rtnl_class * class)606*4dc78e53SAndroid Build Coastguard Worker uint32_t rtnl_htb_get_cbuffer(struct rtnl_class *class)
607*4dc78e53SAndroid Build Coastguard Worker {
608*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_htb_class *htb;
609*4dc78e53SAndroid Build Coastguard Worker 
610*4dc78e53SAndroid Build Coastguard Worker 	if ((htb = htb_class_data(class, NULL)) &&
611*4dc78e53SAndroid Build Coastguard Worker 	     htb->ch_mask & SCH_HTB_HAS_CBUFFER)
612*4dc78e53SAndroid Build Coastguard Worker 		return htb->ch_cbuffer;
613*4dc78e53SAndroid Build Coastguard Worker 
614*4dc78e53SAndroid Build Coastguard Worker 	return 0;
615*4dc78e53SAndroid Build Coastguard Worker }
616*4dc78e53SAndroid Build Coastguard Worker 
617*4dc78e53SAndroid Build Coastguard Worker /**
618*4dc78e53SAndroid Build Coastguard Worker  * Set size of the ceil bucket of HTB class.
619*4dc78e53SAndroid Build Coastguard Worker  * @arg class		HTB class to be modified.
620*4dc78e53SAndroid Build Coastguard Worker  * @arg cbuffer		New size in bytes.
621*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_htb_set_cbuffer(struct rtnl_class * class,uint32_t cbuffer)622*4dc78e53SAndroid Build Coastguard Worker int rtnl_htb_set_cbuffer(struct rtnl_class *class, uint32_t cbuffer)
623*4dc78e53SAndroid Build Coastguard Worker {
624*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_htb_class *htb;
625*4dc78e53SAndroid Build Coastguard Worker 	int err;
626*4dc78e53SAndroid Build Coastguard Worker 
627*4dc78e53SAndroid Build Coastguard Worker 	if (!(htb = htb_class_data(class, &err)))
628*4dc78e53SAndroid Build Coastguard Worker 		return err;
629*4dc78e53SAndroid Build Coastguard Worker 
630*4dc78e53SAndroid Build Coastguard Worker 	htb->ch_cbuffer = cbuffer;
631*4dc78e53SAndroid Build Coastguard Worker 	htb->ch_mask |= SCH_HTB_HAS_CBUFFER;
632*4dc78e53SAndroid Build Coastguard Worker 
633*4dc78e53SAndroid Build Coastguard Worker 	return 0;
634*4dc78e53SAndroid Build Coastguard Worker }
635*4dc78e53SAndroid Build Coastguard Worker 
636*4dc78e53SAndroid Build Coastguard Worker /**
637*4dc78e53SAndroid Build Coastguard Worker  * Return quantum of HTB class
638*4dc78e53SAndroid Build Coastguard Worker  * @arg class		htb class object
639*4dc78e53SAndroid Build Coastguard Worker  *
640*4dc78e53SAndroid Build Coastguard Worker  * See XXX[quantum def]
641*4dc78e53SAndroid Build Coastguard Worker  *
642*4dc78e53SAndroid Build Coastguard Worker  * @return Quantum or 0 if unspecified.
643*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_htb_get_quantum(struct rtnl_class * class)644*4dc78e53SAndroid Build Coastguard Worker uint32_t rtnl_htb_get_quantum(struct rtnl_class *class)
645*4dc78e53SAndroid Build Coastguard Worker {
646*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_htb_class *htb;
647*4dc78e53SAndroid Build Coastguard Worker 
648*4dc78e53SAndroid Build Coastguard Worker 	if ((htb = htb_class_data(class, NULL)) &&
649*4dc78e53SAndroid Build Coastguard Worker 	    htb->ch_mask & SCH_HTB_HAS_QUANTUM)
650*4dc78e53SAndroid Build Coastguard Worker 		return htb->ch_quantum;
651*4dc78e53SAndroid Build Coastguard Worker 
652*4dc78e53SAndroid Build Coastguard Worker 	return 0;
653*4dc78e53SAndroid Build Coastguard Worker }
654*4dc78e53SAndroid Build Coastguard Worker 
655*4dc78e53SAndroid Build Coastguard Worker /**
656*4dc78e53SAndroid Build Coastguard Worker  * Set quantum of HTB class (overwrites value calculated based on r2q)
657*4dc78e53SAndroid Build Coastguard Worker  * @arg class		htb class object
658*4dc78e53SAndroid Build Coastguard Worker  * @arg quantum		new quantum in number of bytes
659*4dc78e53SAndroid Build Coastguard Worker  *
660*4dc78e53SAndroid Build Coastguard Worker  * See XXX[quantum def]
661*4dc78e53SAndroid Build Coastguard Worker  *
662*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
663*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_htb_set_quantum(struct rtnl_class * class,uint32_t quantum)664*4dc78e53SAndroid Build Coastguard Worker int rtnl_htb_set_quantum(struct rtnl_class *class, uint32_t quantum)
665*4dc78e53SAndroid Build Coastguard Worker {
666*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_htb_class *htb;
667*4dc78e53SAndroid Build Coastguard Worker 	int err;
668*4dc78e53SAndroid Build Coastguard Worker 
669*4dc78e53SAndroid Build Coastguard Worker 	if (!(htb = htb_class_data(class, &err)))
670*4dc78e53SAndroid Build Coastguard Worker 		return err;
671*4dc78e53SAndroid Build Coastguard Worker 
672*4dc78e53SAndroid Build Coastguard Worker 	htb->ch_quantum = quantum;
673*4dc78e53SAndroid Build Coastguard Worker 	htb->ch_mask |= SCH_HTB_HAS_QUANTUM;
674*4dc78e53SAndroid Build Coastguard Worker 
675*4dc78e53SAndroid Build Coastguard Worker 	return 0;
676*4dc78e53SAndroid Build Coastguard Worker }
677*4dc78e53SAndroid Build Coastguard Worker 
678*4dc78e53SAndroid Build Coastguard Worker /**
679*4dc78e53SAndroid Build Coastguard Worker  * Return level of HTB class
680*4dc78e53SAndroid Build Coastguard Worker  * @arg class		htb class object
681*4dc78e53SAndroid Build Coastguard Worker  *
682*4dc78e53SAndroid Build Coastguard Worker  * Returns the level of the HTB class. Leaf classes are assigned level
683*4dc78e53SAndroid Build Coastguard Worker  * 0, root classes have level (TC_HTB_MAXDEPTH - 1). Interior classes
684*4dc78e53SAndroid Build Coastguard Worker  * have a level of one less than their parent.
685*4dc78e53SAndroid Build Coastguard Worker  *
686*4dc78e53SAndroid Build Coastguard Worker  * @return Level or a negative error code.
687*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_htb_get_level(struct rtnl_class * class)688*4dc78e53SAndroid Build Coastguard Worker int rtnl_htb_get_level(struct rtnl_class *class)
689*4dc78e53SAndroid Build Coastguard Worker {
690*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_htb_class *htb;
691*4dc78e53SAndroid Build Coastguard Worker 	int err = -NLE_OPNOTSUPP;
692*4dc78e53SAndroid Build Coastguard Worker 
693*4dc78e53SAndroid Build Coastguard Worker 	if ((htb = htb_class_data(class, &err)) &&
694*4dc78e53SAndroid Build Coastguard Worker 	    (htb->ch_mask & SCH_HTB_HAS_LEVEL))
695*4dc78e53SAndroid Build Coastguard Worker 		return htb->ch_level;
696*4dc78e53SAndroid Build Coastguard Worker 
697*4dc78e53SAndroid Build Coastguard Worker 	return err;
698*4dc78e53SAndroid Build Coastguard Worker }
699*4dc78e53SAndroid Build Coastguard Worker 
700*4dc78e53SAndroid Build Coastguard Worker /**
701*4dc78e53SAndroid Build Coastguard Worker  * Set level of HTB class
702*4dc78e53SAndroid Build Coastguard Worker  * @arg class		htb class object
703*4dc78e53SAndroid Build Coastguard Worker  * @arg level		new level of HTB class
704*4dc78e53SAndroid Build Coastguard Worker  *
705*4dc78e53SAndroid Build Coastguard Worker  * Sets the level of a HTB class. Note that changing the level of a HTB
706*4dc78e53SAndroid Build Coastguard Worker  * class does not change the level of its in kernel counterpart. This
707*4dc78e53SAndroid Build Coastguard Worker  * function is provided only to create HTB objects which can be compared
708*4dc78e53SAndroid Build Coastguard Worker  * against or filtered upon.
709*4dc78e53SAndroid Build Coastguard Worker  *
710*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
711*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_htb_set_level(struct rtnl_class * class,int level)712*4dc78e53SAndroid Build Coastguard Worker int rtnl_htb_set_level(struct rtnl_class *class, int level)
713*4dc78e53SAndroid Build Coastguard Worker {
714*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_htb_class *htb;
715*4dc78e53SAndroid Build Coastguard Worker 	int err;
716*4dc78e53SAndroid Build Coastguard Worker 
717*4dc78e53SAndroid Build Coastguard Worker 	if (!(htb = htb_class_data(class, &err)))
718*4dc78e53SAndroid Build Coastguard Worker 		return err;
719*4dc78e53SAndroid Build Coastguard Worker 
720*4dc78e53SAndroid Build Coastguard Worker 	htb->ch_level = level;
721*4dc78e53SAndroid Build Coastguard Worker 	htb->ch_mask |= SCH_HTB_HAS_LEVEL;
722*4dc78e53SAndroid Build Coastguard Worker 
723*4dc78e53SAndroid Build Coastguard Worker 	return 0;
724*4dc78e53SAndroid Build Coastguard Worker }
725*4dc78e53SAndroid Build Coastguard Worker 
726*4dc78e53SAndroid Build Coastguard Worker /** @} */
727*4dc78e53SAndroid Build Coastguard Worker 
728*4dc78e53SAndroid Build Coastguard Worker static struct rtnl_tc_ops htb_qdisc_ops = {
729*4dc78e53SAndroid Build Coastguard Worker 	.to_kind		= "htb",
730*4dc78e53SAndroid Build Coastguard Worker 	.to_type		= RTNL_TC_TYPE_QDISC,
731*4dc78e53SAndroid Build Coastguard Worker 	.to_size		= sizeof(struct rtnl_htb_qdisc),
732*4dc78e53SAndroid Build Coastguard Worker 	.to_msg_parser		= htb_qdisc_msg_parser,
733*4dc78e53SAndroid Build Coastguard Worker 	.to_dump[NL_DUMP_LINE]	= htb_qdisc_dump_line,
734*4dc78e53SAndroid Build Coastguard Worker 	.to_msg_fill		= htb_qdisc_msg_fill,
735*4dc78e53SAndroid Build Coastguard Worker };
736*4dc78e53SAndroid Build Coastguard Worker 
737*4dc78e53SAndroid Build Coastguard Worker static struct rtnl_tc_ops htb_class_ops = {
738*4dc78e53SAndroid Build Coastguard Worker 	.to_kind		= "htb",
739*4dc78e53SAndroid Build Coastguard Worker 	.to_type		= RTNL_TC_TYPE_CLASS,
740*4dc78e53SAndroid Build Coastguard Worker 	.to_size		= sizeof(struct rtnl_htb_class),
741*4dc78e53SAndroid Build Coastguard Worker 	.to_msg_parser		= htb_class_msg_parser,
742*4dc78e53SAndroid Build Coastguard Worker 	.to_dump = {
743*4dc78e53SAndroid Build Coastguard Worker 	    [NL_DUMP_LINE]	= htb_class_dump_line,
744*4dc78e53SAndroid Build Coastguard Worker 	    [NL_DUMP_DETAILS]	= htb_class_dump_details,
745*4dc78e53SAndroid Build Coastguard Worker 	},
746*4dc78e53SAndroid Build Coastguard Worker 	.to_msg_fill		= htb_class_msg_fill,
747*4dc78e53SAndroid Build Coastguard Worker };
748*4dc78e53SAndroid Build Coastguard Worker 
htb_init(void)749*4dc78e53SAndroid Build Coastguard Worker static void _nl_init htb_init(void)
750*4dc78e53SAndroid Build Coastguard Worker {
751*4dc78e53SAndroid Build Coastguard Worker 	rtnl_tc_register(&htb_qdisc_ops);
752*4dc78e53SAndroid Build Coastguard Worker 	rtnl_tc_register(&htb_class_ops);
753*4dc78e53SAndroid Build Coastguard Worker }
754*4dc78e53SAndroid Build Coastguard Worker 
htb_exit(void)755*4dc78e53SAndroid Build Coastguard Worker static void _nl_exit htb_exit(void)
756*4dc78e53SAndroid Build Coastguard Worker {
757*4dc78e53SAndroid Build Coastguard Worker 	rtnl_tc_unregister(&htb_qdisc_ops);
758*4dc78e53SAndroid Build Coastguard Worker 	rtnl_tc_unregister(&htb_class_ops);
759*4dc78e53SAndroid Build Coastguard Worker }
760*4dc78e53SAndroid Build Coastguard Worker 
761*4dc78e53SAndroid Build Coastguard Worker /** @} */
762