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