1*4dc78e53SAndroid Build Coastguard Worker /* SPDX-License-Identifier: LGPL-2.1-only */
2*4dc78e53SAndroid Build Coastguard Worker /*
3*4dc78e53SAndroid Build Coastguard Worker * Copyright (c) 2018 Volodymyr Bendiuga <[email protected]>
4*4dc78e53SAndroid Build Coastguard Worker */
5*4dc78e53SAndroid Build Coastguard Worker
6*4dc78e53SAndroid Build Coastguard Worker #include "nl-default.h"
7*4dc78e53SAndroid Build Coastguard Worker
8*4dc78e53SAndroid Build Coastguard Worker #include <netlink/netlink.h>
9*4dc78e53SAndroid Build Coastguard Worker #include <netlink/utils.h>
10*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/qdisc.h>
11*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/qdisc/mqprio.h>
12*4dc78e53SAndroid Build Coastguard Worker
13*4dc78e53SAndroid Build Coastguard Worker #include "tc-api.h"
14*4dc78e53SAndroid Build Coastguard Worker
15*4dc78e53SAndroid Build Coastguard Worker /** @cond SKIP */
16*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mqprio {
17*4dc78e53SAndroid Build Coastguard Worker uint8_t qm_num_tc;
18*4dc78e53SAndroid Build Coastguard Worker uint8_t qm_prio_map[TC_QOPT_BITMASK + 1];
19*4dc78e53SAndroid Build Coastguard Worker uint8_t qm_hw;
20*4dc78e53SAndroid Build Coastguard Worker uint16_t qm_count[TC_QOPT_MAX_QUEUE];
21*4dc78e53SAndroid Build Coastguard Worker uint16_t qm_offset[TC_QOPT_MAX_QUEUE];
22*4dc78e53SAndroid Build Coastguard Worker uint16_t qm_mode;
23*4dc78e53SAndroid Build Coastguard Worker uint16_t qm_shaper;
24*4dc78e53SAndroid Build Coastguard Worker uint64_t qm_min_rate[TC_QOPT_MAX_QUEUE];
25*4dc78e53SAndroid Build Coastguard Worker uint64_t qm_max_rate[TC_QOPT_MAX_QUEUE];
26*4dc78e53SAndroid Build Coastguard Worker uint32_t qm_mask;
27*4dc78e53SAndroid Build Coastguard Worker };
28*4dc78e53SAndroid Build Coastguard Worker
29*4dc78e53SAndroid Build Coastguard Worker #define SCH_MQPRIO_ATTR_NUMTC (1 << 0)
30*4dc78e53SAndroid Build Coastguard Worker #define SCH_MQPRIO_ATTR_PRIOMAP (1 << 1)
31*4dc78e53SAndroid Build Coastguard Worker #define SCH_MQPRIO_ATTR_HW (1 << 2)
32*4dc78e53SAndroid Build Coastguard Worker #define SCH_MQPRIO_ATTR_QUEUE (1 << 3)
33*4dc78e53SAndroid Build Coastguard Worker #define SCH_MQPRIO_ATTR_MODE (1 << 4)
34*4dc78e53SAndroid Build Coastguard Worker #define SCH_MQPRIO_ATTR_SHAPER (1 << 5)
35*4dc78e53SAndroid Build Coastguard Worker #define SCH_MQPRIO_ATTR_MIN_RATE (1 << 6)
36*4dc78e53SAndroid Build Coastguard Worker #define SCH_MQPRIO_ATTR_MAX_RATE (1 << 7)
37*4dc78e53SAndroid Build Coastguard Worker /** @endcond */
38*4dc78e53SAndroid Build Coastguard Worker
39*4dc78e53SAndroid Build Coastguard Worker static struct nla_policy mqprio_policy[TCA_MQPRIO_MAX + 1] = {
40*4dc78e53SAndroid Build Coastguard Worker [TCA_MQPRIO_MODE] = { .minlen = sizeof(uint16_t) },
41*4dc78e53SAndroid Build Coastguard Worker [TCA_MQPRIO_SHAPER] = { .minlen = sizeof(uint16_t) },
42*4dc78e53SAndroid Build Coastguard Worker [TCA_MQPRIO_MIN_RATE64] = { .type = NLA_NESTED },
43*4dc78e53SAndroid Build Coastguard Worker [TCA_MQPRIO_MAX_RATE64] = { .type = NLA_NESTED },
44*4dc78e53SAndroid Build Coastguard Worker };
45*4dc78e53SAndroid Build Coastguard Worker
mqprio_msg_parser(struct rtnl_tc * tc,void * data)46*4dc78e53SAndroid Build Coastguard Worker static int mqprio_msg_parser(struct rtnl_tc *tc, void *data)
47*4dc78e53SAndroid Build Coastguard Worker {
48*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mqprio *mqprio = data;
49*4dc78e53SAndroid Build Coastguard Worker struct tc_mqprio_qopt *qopt;
50*4dc78e53SAndroid Build Coastguard Worker struct nlattr *attr;
51*4dc78e53SAndroid Build Coastguard Worker int len, rem, i, err;
52*4dc78e53SAndroid Build Coastguard Worker
53*4dc78e53SAndroid Build Coastguard Worker if (tc->tc_opts->d_size < sizeof(*qopt))
54*4dc78e53SAndroid Build Coastguard Worker return -NLE_INVAL;
55*4dc78e53SAndroid Build Coastguard Worker
56*4dc78e53SAndroid Build Coastguard Worker qopt = (struct tc_mqprio_qopt *) tc->tc_opts->d_data;
57*4dc78e53SAndroid Build Coastguard Worker mqprio->qm_num_tc = qopt->num_tc;
58*4dc78e53SAndroid Build Coastguard Worker mqprio->qm_hw = qopt->hw;
59*4dc78e53SAndroid Build Coastguard Worker memcpy(mqprio->qm_prio_map, qopt->prio_tc_map,
60*4dc78e53SAndroid Build Coastguard Worker TC_QOPT_MAX_QUEUE * sizeof(uint8_t));
61*4dc78e53SAndroid Build Coastguard Worker memcpy(mqprio->qm_count, qopt->count,
62*4dc78e53SAndroid Build Coastguard Worker TC_QOPT_MAX_QUEUE * sizeof(uint16_t));
63*4dc78e53SAndroid Build Coastguard Worker memcpy(mqprio->qm_offset, qopt->offset,
64*4dc78e53SAndroid Build Coastguard Worker TC_QOPT_MAX_QUEUE * sizeof(uint16_t));
65*4dc78e53SAndroid Build Coastguard Worker mqprio->qm_mask = (SCH_MQPRIO_ATTR_NUMTC | SCH_MQPRIO_ATTR_PRIOMAP |
66*4dc78e53SAndroid Build Coastguard Worker SCH_MQPRIO_ATTR_QUEUE | SCH_MQPRIO_ATTR_HW);
67*4dc78e53SAndroid Build Coastguard Worker
68*4dc78e53SAndroid Build Coastguard Worker len = tc->tc_opts->d_size - NLA_ALIGN(sizeof(*qopt));
69*4dc78e53SAndroid Build Coastguard Worker
70*4dc78e53SAndroid Build Coastguard Worker if (len > 0) {
71*4dc78e53SAndroid Build Coastguard Worker struct nlattr *tb[TCA_MQPRIO_MAX + 1];
72*4dc78e53SAndroid Build Coastguard Worker
73*4dc78e53SAndroid Build Coastguard Worker err = nla_parse(tb, TCA_MQPRIO_MAX, (struct nlattr *)
74*4dc78e53SAndroid Build Coastguard Worker ((char *) tc->tc_opts->d_data + NLA_ALIGN(sizeof(*qopt))),
75*4dc78e53SAndroid Build Coastguard Worker len, mqprio_policy);
76*4dc78e53SAndroid Build Coastguard Worker if (err < 0)
77*4dc78e53SAndroid Build Coastguard Worker return err;
78*4dc78e53SAndroid Build Coastguard Worker
79*4dc78e53SAndroid Build Coastguard Worker if (tb[TCA_MQPRIO_MODE]) {
80*4dc78e53SAndroid Build Coastguard Worker mqprio->qm_mode = nla_get_u16(tb[TCA_MQPRIO_MODE]);
81*4dc78e53SAndroid Build Coastguard Worker mqprio->qm_mask |= SCH_MQPRIO_ATTR_MODE;
82*4dc78e53SAndroid Build Coastguard Worker }
83*4dc78e53SAndroid Build Coastguard Worker
84*4dc78e53SAndroid Build Coastguard Worker if (tb[TCA_MQPRIO_SHAPER]) {
85*4dc78e53SAndroid Build Coastguard Worker mqprio->qm_shaper = nla_get_u16(tb[TCA_MQPRIO_SHAPER]);
86*4dc78e53SAndroid Build Coastguard Worker mqprio->qm_mask |= SCH_MQPRIO_ATTR_SHAPER;
87*4dc78e53SAndroid Build Coastguard Worker }
88*4dc78e53SAndroid Build Coastguard Worker
89*4dc78e53SAndroid Build Coastguard Worker if (tb[TCA_MQPRIO_MIN_RATE64]) {
90*4dc78e53SAndroid Build Coastguard Worker i = 0;
91*4dc78e53SAndroid Build Coastguard Worker nla_for_each_nested(attr, tb[TCA_MQPRIO_MIN_RATE64], rem) {
92*4dc78e53SAndroid Build Coastguard Worker if (nla_type(attr) != TCA_MQPRIO_MIN_RATE64)
93*4dc78e53SAndroid Build Coastguard Worker return -EINVAL;
94*4dc78e53SAndroid Build Coastguard Worker
95*4dc78e53SAndroid Build Coastguard Worker if (i >= mqprio->qm_num_tc)
96*4dc78e53SAndroid Build Coastguard Worker break;
97*4dc78e53SAndroid Build Coastguard Worker
98*4dc78e53SAndroid Build Coastguard Worker mqprio->qm_min_rate[i] = nla_get_u64(attr);
99*4dc78e53SAndroid Build Coastguard Worker }
100*4dc78e53SAndroid Build Coastguard Worker
101*4dc78e53SAndroid Build Coastguard Worker mqprio->qm_mask |= SCH_MQPRIO_ATTR_MIN_RATE;
102*4dc78e53SAndroid Build Coastguard Worker }
103*4dc78e53SAndroid Build Coastguard Worker
104*4dc78e53SAndroid Build Coastguard Worker if (tb[TCA_MQPRIO_MAX_RATE64]) {
105*4dc78e53SAndroid Build Coastguard Worker i = 0;
106*4dc78e53SAndroid Build Coastguard Worker nla_for_each_nested(attr, tb[TCA_MQPRIO_MAX_RATE64], rem) {
107*4dc78e53SAndroid Build Coastguard Worker if (nla_type(attr) != TCA_MQPRIO_MAX_RATE64)
108*4dc78e53SAndroid Build Coastguard Worker return -EINVAL;
109*4dc78e53SAndroid Build Coastguard Worker
110*4dc78e53SAndroid Build Coastguard Worker if (i >= mqprio->qm_num_tc)
111*4dc78e53SAndroid Build Coastguard Worker break;
112*4dc78e53SAndroid Build Coastguard Worker
113*4dc78e53SAndroid Build Coastguard Worker mqprio->qm_max_rate[i] = nla_get_u64(attr);
114*4dc78e53SAndroid Build Coastguard Worker }
115*4dc78e53SAndroid Build Coastguard Worker
116*4dc78e53SAndroid Build Coastguard Worker mqprio->qm_mask |= SCH_MQPRIO_ATTR_MAX_RATE;
117*4dc78e53SAndroid Build Coastguard Worker }
118*4dc78e53SAndroid Build Coastguard Worker }
119*4dc78e53SAndroid Build Coastguard Worker
120*4dc78e53SAndroid Build Coastguard Worker return 0;
121*4dc78e53SAndroid Build Coastguard Worker }
122*4dc78e53SAndroid Build Coastguard Worker
mqprio_msg_fill(struct rtnl_tc * tc,void * data,struct nl_msg * msg)123*4dc78e53SAndroid Build Coastguard Worker static int mqprio_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
124*4dc78e53SAndroid Build Coastguard Worker {
125*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mqprio *mqprio = data;
126*4dc78e53SAndroid Build Coastguard Worker struct tc_mqprio_qopt qopt = { 0 };
127*4dc78e53SAndroid Build Coastguard Worker struct nlattr *nest = NULL;
128*4dc78e53SAndroid Build Coastguard Worker int i;
129*4dc78e53SAndroid Build Coastguard Worker
130*4dc78e53SAndroid Build Coastguard Worker if (!mqprio ||
131*4dc78e53SAndroid Build Coastguard Worker !(mqprio->qm_mask & SCH_MQPRIO_ATTR_NUMTC) ||
132*4dc78e53SAndroid Build Coastguard Worker !(mqprio->qm_mask & SCH_MQPRIO_ATTR_PRIOMAP) ||
133*4dc78e53SAndroid Build Coastguard Worker !(mqprio->qm_mask & SCH_MQPRIO_ATTR_QUEUE))
134*4dc78e53SAndroid Build Coastguard Worker return -NLE_INVAL;
135*4dc78e53SAndroid Build Coastguard Worker
136*4dc78e53SAndroid Build Coastguard Worker if (!(mqprio->qm_mask & SCH_MQPRIO_ATTR_HW))
137*4dc78e53SAndroid Build Coastguard Worker qopt.hw = 0;
138*4dc78e53SAndroid Build Coastguard Worker else
139*4dc78e53SAndroid Build Coastguard Worker qopt.hw = mqprio->qm_hw;
140*4dc78e53SAndroid Build Coastguard Worker
141*4dc78e53SAndroid Build Coastguard Worker qopt.num_tc = mqprio->qm_num_tc;
142*4dc78e53SAndroid Build Coastguard Worker memcpy(qopt.count, mqprio->qm_count, TC_QOPT_MAX_QUEUE * sizeof(uint16_t));
143*4dc78e53SAndroid Build Coastguard Worker memcpy(qopt.offset, mqprio->qm_offset, TC_QOPT_MAX_QUEUE * sizeof(uint16_t));
144*4dc78e53SAndroid Build Coastguard Worker memcpy(qopt.prio_tc_map, mqprio->qm_prio_map, TC_QOPT_MAX_QUEUE * sizeof(uint8_t));
145*4dc78e53SAndroid Build Coastguard Worker
146*4dc78e53SAndroid Build Coastguard Worker nlmsg_append(msg, &qopt, sizeof(qopt), NL_DONTPAD);
147*4dc78e53SAndroid Build Coastguard Worker
148*4dc78e53SAndroid Build Coastguard Worker if (mqprio->qm_hw) {
149*4dc78e53SAndroid Build Coastguard Worker if (mqprio->qm_mask & SCH_MQPRIO_ATTR_MODE)
150*4dc78e53SAndroid Build Coastguard Worker NLA_PUT_U16(msg, TCA_MQPRIO_MODE, mqprio->qm_mode);
151*4dc78e53SAndroid Build Coastguard Worker
152*4dc78e53SAndroid Build Coastguard Worker if (mqprio->qm_mask & SCH_MQPRIO_ATTR_SHAPER)
153*4dc78e53SAndroid Build Coastguard Worker NLA_PUT_U16(msg, TCA_MQPRIO_SHAPER, mqprio->qm_shaper);
154*4dc78e53SAndroid Build Coastguard Worker
155*4dc78e53SAndroid Build Coastguard Worker if (mqprio->qm_mask & SCH_MQPRIO_ATTR_MIN_RATE) {
156*4dc78e53SAndroid Build Coastguard Worker nest = nla_nest_start(msg, TCA_MQPRIO_MIN_RATE64);
157*4dc78e53SAndroid Build Coastguard Worker if (!nest)
158*4dc78e53SAndroid Build Coastguard Worker goto nla_put_failure;
159*4dc78e53SAndroid Build Coastguard Worker
160*4dc78e53SAndroid Build Coastguard Worker for (i = 0; i < mqprio->qm_num_tc; i++) {
161*4dc78e53SAndroid Build Coastguard Worker if (nla_put(msg, TCA_MQPRIO_MIN_RATE64,
162*4dc78e53SAndroid Build Coastguard Worker sizeof(mqprio->qm_min_rate[i]),
163*4dc78e53SAndroid Build Coastguard Worker &mqprio->qm_min_rate[i]) < 0)
164*4dc78e53SAndroid Build Coastguard Worker goto nla_nest_cancel;
165*4dc78e53SAndroid Build Coastguard Worker }
166*4dc78e53SAndroid Build Coastguard Worker nla_nest_end(msg, nest);
167*4dc78e53SAndroid Build Coastguard Worker }
168*4dc78e53SAndroid Build Coastguard Worker
169*4dc78e53SAndroid Build Coastguard Worker if (mqprio->qm_mask & SCH_MQPRIO_ATTR_MAX_RATE) {
170*4dc78e53SAndroid Build Coastguard Worker nest = nla_nest_start(msg, TCA_MQPRIO_MAX_RATE64);
171*4dc78e53SAndroid Build Coastguard Worker if (!nest)
172*4dc78e53SAndroid Build Coastguard Worker goto nla_put_failure;
173*4dc78e53SAndroid Build Coastguard Worker
174*4dc78e53SAndroid Build Coastguard Worker for (i = 0; i < mqprio->qm_num_tc; i++) {
175*4dc78e53SAndroid Build Coastguard Worker if (nla_put(msg, TCA_MQPRIO_MAX_RATE64,
176*4dc78e53SAndroid Build Coastguard Worker sizeof(mqprio->qm_max_rate[i]),
177*4dc78e53SAndroid Build Coastguard Worker &mqprio->qm_max_rate[i]) < 0)
178*4dc78e53SAndroid Build Coastguard Worker goto nla_nest_cancel;
179*4dc78e53SAndroid Build Coastguard Worker }
180*4dc78e53SAndroid Build Coastguard Worker nla_nest_end(msg, nest);
181*4dc78e53SAndroid Build Coastguard Worker }
182*4dc78e53SAndroid Build Coastguard Worker }
183*4dc78e53SAndroid Build Coastguard Worker
184*4dc78e53SAndroid Build Coastguard Worker return 0;
185*4dc78e53SAndroid Build Coastguard Worker
186*4dc78e53SAndroid Build Coastguard Worker nla_nest_cancel:
187*4dc78e53SAndroid Build Coastguard Worker nla_nest_cancel(msg, nest);
188*4dc78e53SAndroid Build Coastguard Worker return -NLE_MSGSIZE;
189*4dc78e53SAndroid Build Coastguard Worker
190*4dc78e53SAndroid Build Coastguard Worker nla_put_failure:
191*4dc78e53SAndroid Build Coastguard Worker return -NLE_MSGSIZE;
192*4dc78e53SAndroid Build Coastguard Worker }
193*4dc78e53SAndroid Build Coastguard Worker
mqprio_dump_line(struct rtnl_tc * tc,void * data,struct nl_dump_params * p)194*4dc78e53SAndroid Build Coastguard Worker static void mqprio_dump_line(struct rtnl_tc *tc, void *data,
195*4dc78e53SAndroid Build Coastguard Worker struct nl_dump_params *p)
196*4dc78e53SAndroid Build Coastguard Worker {
197*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mqprio *mqprio = data;
198*4dc78e53SAndroid Build Coastguard Worker
199*4dc78e53SAndroid Build Coastguard Worker if (mqprio)
200*4dc78e53SAndroid Build Coastguard Worker nl_dump(p, " num_tc %u", mqprio->qm_num_tc);
201*4dc78e53SAndroid Build Coastguard Worker }
202*4dc78e53SAndroid Build Coastguard Worker
mqprio_dump_details(struct rtnl_tc * tc,void * data,struct nl_dump_params * p)203*4dc78e53SAndroid Build Coastguard Worker static void mqprio_dump_details(struct rtnl_tc *tc, void *data,
204*4dc78e53SAndroid Build Coastguard Worker struct nl_dump_params *p)
205*4dc78e53SAndroid Build Coastguard Worker {
206*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mqprio *mqprio = data;
207*4dc78e53SAndroid Build Coastguard Worker int i;
208*4dc78e53SAndroid Build Coastguard Worker
209*4dc78e53SAndroid Build Coastguard Worker if (!mqprio)
210*4dc78e53SAndroid Build Coastguard Worker return;
211*4dc78e53SAndroid Build Coastguard Worker
212*4dc78e53SAndroid Build Coastguard Worker nl_dump(p, "map [");
213*4dc78e53SAndroid Build Coastguard Worker
214*4dc78e53SAndroid Build Coastguard Worker for (i = 0; i <= TC_QOPT_BITMASK; i++)
215*4dc78e53SAndroid Build Coastguard Worker nl_dump(p, "%u%s", mqprio->qm_prio_map[i],
216*4dc78e53SAndroid Build Coastguard Worker i < TC_QOPT_BITMASK ? " " : "");
217*4dc78e53SAndroid Build Coastguard Worker
218*4dc78e53SAndroid Build Coastguard Worker nl_dump(p, "]\n");
219*4dc78e53SAndroid Build Coastguard Worker nl_new_line(p);
220*4dc78e53SAndroid Build Coastguard Worker }
221*4dc78e53SAndroid Build Coastguard Worker
222*4dc78e53SAndroid Build Coastguard Worker /**
223*4dc78e53SAndroid Build Coastguard Worker * @name Attribute Modification
224*4dc78e53SAndroid Build Coastguard Worker * @{
225*4dc78e53SAndroid Build Coastguard Worker */
226*4dc78e53SAndroid Build Coastguard Worker
227*4dc78e53SAndroid Build Coastguard Worker /**
228*4dc78e53SAndroid Build Coastguard Worker * Set number of traffic classes.
229*4dc78e53SAndroid Build Coastguard Worker * @arg qdisc MQPRIO qdisc to be modified.
230*4dc78e53SAndroid Build Coastguard Worker * @arg num_tc Number of traffic classes to create.
231*4dc78e53SAndroid Build Coastguard Worker * @return 0 on success or a negative error code.
232*4dc78e53SAndroid Build Coastguard Worker */
rtnl_qdisc_mqprio_set_num_tc(struct rtnl_qdisc * qdisc,int num_tc)233*4dc78e53SAndroid Build Coastguard Worker int rtnl_qdisc_mqprio_set_num_tc(struct rtnl_qdisc *qdisc, int num_tc)
234*4dc78e53SAndroid Build Coastguard Worker {
235*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mqprio *mqprio;
236*4dc78e53SAndroid Build Coastguard Worker
237*4dc78e53SAndroid Build Coastguard Worker if (!(mqprio = rtnl_tc_data(TC_CAST(qdisc))))
238*4dc78e53SAndroid Build Coastguard Worker return -NLE_NOMEM;
239*4dc78e53SAndroid Build Coastguard Worker
240*4dc78e53SAndroid Build Coastguard Worker mqprio->qm_num_tc = num_tc;
241*4dc78e53SAndroid Build Coastguard Worker mqprio->qm_mask |= SCH_MQPRIO_ATTR_NUMTC;
242*4dc78e53SAndroid Build Coastguard Worker return 0;
243*4dc78e53SAndroid Build Coastguard Worker }
244*4dc78e53SAndroid Build Coastguard Worker
245*4dc78e53SAndroid Build Coastguard Worker /**
246*4dc78e53SAndroid Build Coastguard Worker * Get number of traffic classes of MQPRIO qdisc.
247*4dc78e53SAndroid Build Coastguard Worker * @arg qdisc MQPRIO qdisc.
248*4dc78e53SAndroid Build Coastguard Worker * @return Number of traffic classes or a negative error code.
249*4dc78e53SAndroid Build Coastguard Worker */
rtnl_qdisc_mqprio_get_num_tc(struct rtnl_qdisc * qdisc)250*4dc78e53SAndroid Build Coastguard Worker int rtnl_qdisc_mqprio_get_num_tc(struct rtnl_qdisc *qdisc)
251*4dc78e53SAndroid Build Coastguard Worker {
252*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mqprio *mqprio;
253*4dc78e53SAndroid Build Coastguard Worker
254*4dc78e53SAndroid Build Coastguard Worker if (!(mqprio = rtnl_tc_data_peek(TC_CAST(qdisc))))
255*4dc78e53SAndroid Build Coastguard Worker return -NLE_INVAL;
256*4dc78e53SAndroid Build Coastguard Worker
257*4dc78e53SAndroid Build Coastguard Worker if (mqprio->qm_mask & SCH_MQPRIO_ATTR_NUMTC)
258*4dc78e53SAndroid Build Coastguard Worker return mqprio->qm_num_tc;
259*4dc78e53SAndroid Build Coastguard Worker else
260*4dc78e53SAndroid Build Coastguard Worker return -NLE_MISSING_ATTR;
261*4dc78e53SAndroid Build Coastguard Worker }
262*4dc78e53SAndroid Build Coastguard Worker
263*4dc78e53SAndroid Build Coastguard Worker /**
264*4dc78e53SAndroid Build Coastguard Worker * Set priomap of the MQPRIO qdisc.
265*4dc78e53SAndroid Build Coastguard Worker * @arg qdisc MQPRIO qdisc to be modified.
266*4dc78e53SAndroid Build Coastguard Worker * @arg priomap New priority mapping.
267*4dc78e53SAndroid Build Coastguard Worker * @arg len Length of priomap (# of elements).
268*4dc78e53SAndroid Build Coastguard Worker * @return 0 on success or a negative error code.
269*4dc78e53SAndroid Build Coastguard Worker */
rtnl_qdisc_mqprio_set_priomap(struct rtnl_qdisc * qdisc,uint8_t priomap[],int len)270*4dc78e53SAndroid Build Coastguard Worker int rtnl_qdisc_mqprio_set_priomap(struct rtnl_qdisc *qdisc, uint8_t priomap[],
271*4dc78e53SAndroid Build Coastguard Worker int len)
272*4dc78e53SAndroid Build Coastguard Worker {
273*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mqprio *mqprio;
274*4dc78e53SAndroid Build Coastguard Worker int i;
275*4dc78e53SAndroid Build Coastguard Worker
276*4dc78e53SAndroid Build Coastguard Worker if (!(mqprio = rtnl_tc_data(TC_CAST(qdisc))))
277*4dc78e53SAndroid Build Coastguard Worker return -NLE_NOMEM;
278*4dc78e53SAndroid Build Coastguard Worker
279*4dc78e53SAndroid Build Coastguard Worker if (!(mqprio->qm_mask & SCH_MQPRIO_ATTR_NUMTC))
280*4dc78e53SAndroid Build Coastguard Worker return -NLE_MISSING_ATTR;
281*4dc78e53SAndroid Build Coastguard Worker
282*4dc78e53SAndroid Build Coastguard Worker if (len > TC_QOPT_BITMASK + 1)
283*4dc78e53SAndroid Build Coastguard Worker return -NLE_RANGE;
284*4dc78e53SAndroid Build Coastguard Worker
285*4dc78e53SAndroid Build Coastguard Worker for (i = 0; i < len; i++) {
286*4dc78e53SAndroid Build Coastguard Worker if (priomap[i] > mqprio->qm_num_tc)
287*4dc78e53SAndroid Build Coastguard Worker return -NLE_RANGE;
288*4dc78e53SAndroid Build Coastguard Worker }
289*4dc78e53SAndroid Build Coastguard Worker
290*4dc78e53SAndroid Build Coastguard Worker memset(mqprio->qm_prio_map, 0, sizeof(mqprio->qm_prio_map));
291*4dc78e53SAndroid Build Coastguard Worker memcpy(mqprio->qm_prio_map, priomap, len * sizeof(uint8_t));
292*4dc78e53SAndroid Build Coastguard Worker mqprio->qm_mask |= SCH_MQPRIO_ATTR_PRIOMAP;
293*4dc78e53SAndroid Build Coastguard Worker
294*4dc78e53SAndroid Build Coastguard Worker return 0;
295*4dc78e53SAndroid Build Coastguard Worker }
296*4dc78e53SAndroid Build Coastguard Worker
297*4dc78e53SAndroid Build Coastguard Worker /**
298*4dc78e53SAndroid Build Coastguard Worker * Get priomap of MQPRIO qdisc.
299*4dc78e53SAndroid Build Coastguard Worker * @arg qdisc MQPRIO qdisc.
300*4dc78e53SAndroid Build Coastguard Worker * @return Priority mapping as array of size TC_QOPT_BANDS+1
301*4dc78e53SAndroid Build Coastguard Worker * or NULL if an error occured.
302*4dc78e53SAndroid Build Coastguard Worker */
rtnl_qdisc_mqprio_get_priomap(struct rtnl_qdisc * qdisc)303*4dc78e53SAndroid Build Coastguard Worker uint8_t *rtnl_qdisc_mqprio_get_priomap(struct rtnl_qdisc *qdisc)
304*4dc78e53SAndroid Build Coastguard Worker {
305*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mqprio *mqprio;
306*4dc78e53SAndroid Build Coastguard Worker
307*4dc78e53SAndroid Build Coastguard Worker if (!(mqprio = rtnl_tc_data_peek(TC_CAST(qdisc))))
308*4dc78e53SAndroid Build Coastguard Worker return NULL;
309*4dc78e53SAndroid Build Coastguard Worker
310*4dc78e53SAndroid Build Coastguard Worker if (mqprio->qm_mask & SCH_MQPRIO_ATTR_PRIOMAP)
311*4dc78e53SAndroid Build Coastguard Worker return mqprio->qm_prio_map;
312*4dc78e53SAndroid Build Coastguard Worker else
313*4dc78e53SAndroid Build Coastguard Worker return NULL;
314*4dc78e53SAndroid Build Coastguard Worker }
315*4dc78e53SAndroid Build Coastguard Worker
316*4dc78e53SAndroid Build Coastguard Worker /**
317*4dc78e53SAndroid Build Coastguard Worker * Offload to HW or run in SW (default).
318*4dc78e53SAndroid Build Coastguard Worker * @arg qdisc MQPRIO qdisc to be modified.
319*4dc78e53SAndroid Build Coastguard Worker * @arg offload 1 - offload to HW, 0 - run in SW only (default).
320*4dc78e53SAndroid Build Coastguard Worker * @return 0 on success or a negative error code.
321*4dc78e53SAndroid Build Coastguard Worker */
rtnl_qdisc_mqprio_hw_offload(struct rtnl_qdisc * qdisc,int offload)322*4dc78e53SAndroid Build Coastguard Worker int rtnl_qdisc_mqprio_hw_offload(struct rtnl_qdisc *qdisc, int offload)
323*4dc78e53SAndroid Build Coastguard Worker {
324*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mqprio *mqprio;
325*4dc78e53SAndroid Build Coastguard Worker
326*4dc78e53SAndroid Build Coastguard Worker if (!(mqprio = rtnl_tc_data(TC_CAST(qdisc))))
327*4dc78e53SAndroid Build Coastguard Worker return -NLE_NOMEM;
328*4dc78e53SAndroid Build Coastguard Worker
329*4dc78e53SAndroid Build Coastguard Worker switch (offload) {
330*4dc78e53SAndroid Build Coastguard Worker case 0:
331*4dc78e53SAndroid Build Coastguard Worker case 1:
332*4dc78e53SAndroid Build Coastguard Worker mqprio->qm_hw = offload;
333*4dc78e53SAndroid Build Coastguard Worker break;
334*4dc78e53SAndroid Build Coastguard Worker default:
335*4dc78e53SAndroid Build Coastguard Worker return -NLE_INVAL;
336*4dc78e53SAndroid Build Coastguard Worker }
337*4dc78e53SAndroid Build Coastguard Worker
338*4dc78e53SAndroid Build Coastguard Worker mqprio->qm_mask |= SCH_MQPRIO_ATTR_HW;
339*4dc78e53SAndroid Build Coastguard Worker return 0;
340*4dc78e53SAndroid Build Coastguard Worker }
341*4dc78e53SAndroid Build Coastguard Worker
342*4dc78e53SAndroid Build Coastguard Worker /**
343*4dc78e53SAndroid Build Coastguard Worker * Check whether running in HW or SW.
344*4dc78e53SAndroid Build Coastguard Worker * @arg qdisc MQPRIO qdisc to be modified.
345*4dc78e53SAndroid Build Coastguard Worker * @return 0 if running in SW, otherwise 1 (HW)
346*4dc78e53SAndroid Build Coastguard Worker */
rtnl_qdisc_mqprio_get_hw_offload(struct rtnl_qdisc * qdisc)347*4dc78e53SAndroid Build Coastguard Worker int rtnl_qdisc_mqprio_get_hw_offload(struct rtnl_qdisc *qdisc)
348*4dc78e53SAndroid Build Coastguard Worker {
349*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mqprio *mqprio;
350*4dc78e53SAndroid Build Coastguard Worker
351*4dc78e53SAndroid Build Coastguard Worker if (!(mqprio = rtnl_tc_data_peek(TC_CAST(qdisc))))
352*4dc78e53SAndroid Build Coastguard Worker return -NLE_INVAL;
353*4dc78e53SAndroid Build Coastguard Worker
354*4dc78e53SAndroid Build Coastguard Worker if (mqprio->qm_mask & SCH_MQPRIO_ATTR_HW)
355*4dc78e53SAndroid Build Coastguard Worker return mqprio->qm_hw;
356*4dc78e53SAndroid Build Coastguard Worker
357*4dc78e53SAndroid Build Coastguard Worker return 0;
358*4dc78e53SAndroid Build Coastguard Worker }
359*4dc78e53SAndroid Build Coastguard Worker
360*4dc78e53SAndroid Build Coastguard Worker /**
361*4dc78e53SAndroid Build Coastguard Worker * Set tc queue of the MQPRIO qdisc.
362*4dc78e53SAndroid Build Coastguard Worker * @arg qdisc MQPRIO qdisc to be modified.
363*4dc78e53SAndroid Build Coastguard Worker * @arg count count of queue range for each traffic class
364*4dc78e53SAndroid Build Coastguard Worker * @arg offset offset of queue range for each traffic class
365*4dc78e53SAndroid Build Coastguard Worker * @return 0 on success or a negative error code.
366*4dc78e53SAndroid Build Coastguard Worker */
rtnl_qdisc_mqprio_set_queue(struct rtnl_qdisc * qdisc,uint16_t count[],uint16_t offset[],int len)367*4dc78e53SAndroid Build Coastguard Worker int rtnl_qdisc_mqprio_set_queue(struct rtnl_qdisc *qdisc, uint16_t count[],
368*4dc78e53SAndroid Build Coastguard Worker uint16_t offset[], int len)
369*4dc78e53SAndroid Build Coastguard Worker {
370*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mqprio *mqprio;
371*4dc78e53SAndroid Build Coastguard Worker
372*4dc78e53SAndroid Build Coastguard Worker if (!(mqprio = rtnl_tc_data(TC_CAST(qdisc))))
373*4dc78e53SAndroid Build Coastguard Worker return -NLE_NOMEM;
374*4dc78e53SAndroid Build Coastguard Worker
375*4dc78e53SAndroid Build Coastguard Worker if (!(mqprio->qm_mask & SCH_MQPRIO_ATTR_NUMTC))
376*4dc78e53SAndroid Build Coastguard Worker return -NLE_MISSING_ATTR;
377*4dc78e53SAndroid Build Coastguard Worker
378*4dc78e53SAndroid Build Coastguard Worker if (len < 0 || len > TC_QOPT_MAX_QUEUE)
379*4dc78e53SAndroid Build Coastguard Worker return -NLE_RANGE;
380*4dc78e53SAndroid Build Coastguard Worker
381*4dc78e53SAndroid Build Coastguard Worker memset(mqprio->qm_count, 0, sizeof(mqprio->qm_count));
382*4dc78e53SAndroid Build Coastguard Worker memset(mqprio->qm_offset, 0, sizeof(mqprio->qm_offset));
383*4dc78e53SAndroid Build Coastguard Worker memcpy(mqprio->qm_count, count, len * sizeof(uint16_t));
384*4dc78e53SAndroid Build Coastguard Worker memcpy(mqprio->qm_offset, offset, len * sizeof(uint16_t));
385*4dc78e53SAndroid Build Coastguard Worker mqprio->qm_mask |= SCH_MQPRIO_ATTR_QUEUE;
386*4dc78e53SAndroid Build Coastguard Worker
387*4dc78e53SAndroid Build Coastguard Worker return 0;
388*4dc78e53SAndroid Build Coastguard Worker }
389*4dc78e53SAndroid Build Coastguard Worker
390*4dc78e53SAndroid Build Coastguard Worker /**
391*4dc78e53SAndroid Build Coastguard Worker * Get tc queue of the MQPRIO qdisc.
392*4dc78e53SAndroid Build Coastguard Worker * @arg qdisc MQPRIO qdisc to be modified.
393*4dc78e53SAndroid Build Coastguard Worker * @arg count count of queue range for each traffic class
394*4dc78e53SAndroid Build Coastguard Worker * @arg offset offset of queue range for each traffic class
395*4dc78e53SAndroid Build Coastguard Worker * @return 0 on success or a negative error code.
396*4dc78e53SAndroid Build Coastguard Worker */
rtnl_qdisc_mqprio_get_queue(struct rtnl_qdisc * qdisc,uint16_t * count,uint16_t * offset)397*4dc78e53SAndroid Build Coastguard Worker int rtnl_qdisc_mqprio_get_queue(struct rtnl_qdisc *qdisc, uint16_t *count,
398*4dc78e53SAndroid Build Coastguard Worker uint16_t *offset)
399*4dc78e53SAndroid Build Coastguard Worker {
400*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mqprio *mqprio;
401*4dc78e53SAndroid Build Coastguard Worker
402*4dc78e53SAndroid Build Coastguard Worker if (!(mqprio = rtnl_tc_data_peek(TC_CAST(qdisc))))
403*4dc78e53SAndroid Build Coastguard Worker return -NLE_INVAL;
404*4dc78e53SAndroid Build Coastguard Worker
405*4dc78e53SAndroid Build Coastguard Worker if (!(mqprio->qm_mask & SCH_MQPRIO_ATTR_QUEUE))
406*4dc78e53SAndroid Build Coastguard Worker return -NLE_MISSING_ATTR;
407*4dc78e53SAndroid Build Coastguard Worker
408*4dc78e53SAndroid Build Coastguard Worker memcpy(count, mqprio->qm_count, TC_QOPT_MAX_QUEUE * sizeof(uint16_t));
409*4dc78e53SAndroid Build Coastguard Worker memcpy(offset, mqprio->qm_offset, TC_QOPT_MAX_QUEUE * sizeof(uint16_t));
410*4dc78e53SAndroid Build Coastguard Worker
411*4dc78e53SAndroid Build Coastguard Worker return 0;
412*4dc78e53SAndroid Build Coastguard Worker }
413*4dc78e53SAndroid Build Coastguard Worker
414*4dc78e53SAndroid Build Coastguard Worker /**
415*4dc78e53SAndroid Build Coastguard Worker * Set mode of mqprio Qdisc
416*4dc78e53SAndroid Build Coastguard Worker * @arg qdisc MQPRIO qdisc to be modified.
417*4dc78e53SAndroid Build Coastguard Worker * @arg mode one of: TC_MQPRIO_MODE_DCB, TC_MQPRIO_MODE_CHANNEL
418*4dc78e53SAndroid Build Coastguard Worker * @return 0 on success or a negative error code.
419*4dc78e53SAndroid Build Coastguard Worker */
rtnl_qdisc_mqprio_set_mode(struct rtnl_qdisc * qdisc,uint16_t mode)420*4dc78e53SAndroid Build Coastguard Worker int rtnl_qdisc_mqprio_set_mode(struct rtnl_qdisc *qdisc, uint16_t mode)
421*4dc78e53SAndroid Build Coastguard Worker {
422*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mqprio *mqprio;
423*4dc78e53SAndroid Build Coastguard Worker
424*4dc78e53SAndroid Build Coastguard Worker if (!(mqprio = rtnl_tc_data(TC_CAST(qdisc))))
425*4dc78e53SAndroid Build Coastguard Worker return -NLE_NOMEM;
426*4dc78e53SAndroid Build Coastguard Worker
427*4dc78e53SAndroid Build Coastguard Worker if (!(mqprio->qm_mask & SCH_MQPRIO_ATTR_HW))
428*4dc78e53SAndroid Build Coastguard Worker return -NLE_MISSING_ATTR;
429*4dc78e53SAndroid Build Coastguard Worker
430*4dc78e53SAndroid Build Coastguard Worker mqprio->qm_mode = mode;
431*4dc78e53SAndroid Build Coastguard Worker mqprio->qm_mask |= SCH_MQPRIO_ATTR_MODE;
432*4dc78e53SAndroid Build Coastguard Worker
433*4dc78e53SAndroid Build Coastguard Worker return 0;
434*4dc78e53SAndroid Build Coastguard Worker }
435*4dc78e53SAndroid Build Coastguard Worker
436*4dc78e53SAndroid Build Coastguard Worker /**
437*4dc78e53SAndroid Build Coastguard Worker * Get mode of mqprio Qdisc
438*4dc78e53SAndroid Build Coastguard Worker * @arg qdisc MQPRIO qdisc.
439*4dc78e53SAndroid Build Coastguard Worker * @return mode on success or negative error code.
440*4dc78e53SAndroid Build Coastguard Worker */
rtnl_qdisc_mqprio_get_mode(struct rtnl_qdisc * qdisc)441*4dc78e53SAndroid Build Coastguard Worker int rtnl_qdisc_mqprio_get_mode(struct rtnl_qdisc *qdisc)
442*4dc78e53SAndroid Build Coastguard Worker {
443*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mqprio *mqprio;
444*4dc78e53SAndroid Build Coastguard Worker
445*4dc78e53SAndroid Build Coastguard Worker if (!(mqprio = rtnl_tc_data_peek(TC_CAST(qdisc))))
446*4dc78e53SAndroid Build Coastguard Worker return -NLE_INVAL;
447*4dc78e53SAndroid Build Coastguard Worker
448*4dc78e53SAndroid Build Coastguard Worker if (mqprio->qm_mask & SCH_MQPRIO_ATTR_MODE)
449*4dc78e53SAndroid Build Coastguard Worker return mqprio->qm_mode;
450*4dc78e53SAndroid Build Coastguard Worker else
451*4dc78e53SAndroid Build Coastguard Worker return -NLE_MISSING_ATTR;
452*4dc78e53SAndroid Build Coastguard Worker }
453*4dc78e53SAndroid Build Coastguard Worker
454*4dc78e53SAndroid Build Coastguard Worker /**
455*4dc78e53SAndroid Build Coastguard Worker * Set shaper of mqprio Qdisc
456*4dc78e53SAndroid Build Coastguard Worker * @arg qdisc MQPRIO qdisc to be modified.
457*4dc78e53SAndroid Build Coastguard Worker * @arg shaper one of: TC_MQPRIO_SHAPER_DCB, TC_MQPRIO_SHAPER_BW_RATE
458*4dc78e53SAndroid Build Coastguard Worker * @return 0 on success or a negative error code.
459*4dc78e53SAndroid Build Coastguard Worker */
rtnl_qdisc_mqprio_set_shaper(struct rtnl_qdisc * qdisc,uint16_t shaper)460*4dc78e53SAndroid Build Coastguard Worker int rtnl_qdisc_mqprio_set_shaper(struct rtnl_qdisc *qdisc, uint16_t shaper)
461*4dc78e53SAndroid Build Coastguard Worker {
462*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mqprio *mqprio;
463*4dc78e53SAndroid Build Coastguard Worker
464*4dc78e53SAndroid Build Coastguard Worker if (!(mqprio = rtnl_tc_data(TC_CAST(qdisc))))
465*4dc78e53SAndroid Build Coastguard Worker return -NLE_NOMEM;
466*4dc78e53SAndroid Build Coastguard Worker
467*4dc78e53SAndroid Build Coastguard Worker if (!(mqprio->qm_mask & SCH_MQPRIO_ATTR_HW))
468*4dc78e53SAndroid Build Coastguard Worker return -NLE_MISSING_ATTR;
469*4dc78e53SAndroid Build Coastguard Worker
470*4dc78e53SAndroid Build Coastguard Worker mqprio->qm_shaper = shaper;
471*4dc78e53SAndroid Build Coastguard Worker mqprio->qm_mask |= SCH_MQPRIO_ATTR_SHAPER;
472*4dc78e53SAndroid Build Coastguard Worker
473*4dc78e53SAndroid Build Coastguard Worker return 0;
474*4dc78e53SAndroid Build Coastguard Worker }
475*4dc78e53SAndroid Build Coastguard Worker
476*4dc78e53SAndroid Build Coastguard Worker /**
477*4dc78e53SAndroid Build Coastguard Worker * Get shaper of mqprio Qdisc
478*4dc78e53SAndroid Build Coastguard Worker * @arg qdisc MQPRIO qdisc.
479*4dc78e53SAndroid Build Coastguard Worker * @return shaper on success or negative error code.
480*4dc78e53SAndroid Build Coastguard Worker */
rtnl_qdisc_mqprio_get_shaper(struct rtnl_qdisc * qdisc)481*4dc78e53SAndroid Build Coastguard Worker int rtnl_qdisc_mqprio_get_shaper(struct rtnl_qdisc *qdisc)
482*4dc78e53SAndroid Build Coastguard Worker {
483*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mqprio *mqprio;
484*4dc78e53SAndroid Build Coastguard Worker
485*4dc78e53SAndroid Build Coastguard Worker if (!(mqprio = rtnl_tc_data_peek(TC_CAST(qdisc))))
486*4dc78e53SAndroid Build Coastguard Worker return -NLE_INVAL;
487*4dc78e53SAndroid Build Coastguard Worker
488*4dc78e53SAndroid Build Coastguard Worker if (mqprio->qm_mask & SCH_MQPRIO_ATTR_SHAPER)
489*4dc78e53SAndroid Build Coastguard Worker return mqprio->qm_shaper;
490*4dc78e53SAndroid Build Coastguard Worker else
491*4dc78e53SAndroid Build Coastguard Worker return -NLE_MISSING_ATTR;
492*4dc78e53SAndroid Build Coastguard Worker }
493*4dc78e53SAndroid Build Coastguard Worker
494*4dc78e53SAndroid Build Coastguard Worker /**
495*4dc78e53SAndroid Build Coastguard Worker * Set minimum value of bandwidth rate limit for each traffic class
496*4dc78e53SAndroid Build Coastguard Worker * @arg qdisc MQPRIO qdisc.
497*4dc78e53SAndroid Build Coastguard Worker * @arg min minimum rate for each traffic class
498*4dc78e53SAndroid Build Coastguard Worker * @return 0 on success or a negative error code.
499*4dc78e53SAndroid Build Coastguard Worker */
rtnl_qdisc_mqprio_set_min_rate(struct rtnl_qdisc * qdisc,uint64_t min[],int len)500*4dc78e53SAndroid Build Coastguard Worker int rtnl_qdisc_mqprio_set_min_rate(struct rtnl_qdisc *qdisc, uint64_t min[], int len)
501*4dc78e53SAndroid Build Coastguard Worker {
502*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mqprio *mqprio;
503*4dc78e53SAndroid Build Coastguard Worker
504*4dc78e53SAndroid Build Coastguard Worker if (!(mqprio = rtnl_tc_data(TC_CAST(qdisc))))
505*4dc78e53SAndroid Build Coastguard Worker return -NLE_NOMEM;
506*4dc78e53SAndroid Build Coastguard Worker
507*4dc78e53SAndroid Build Coastguard Worker if (!(mqprio->qm_mask & SCH_MQPRIO_ATTR_SHAPER))
508*4dc78e53SAndroid Build Coastguard Worker return -NLE_MISSING_ATTR;
509*4dc78e53SAndroid Build Coastguard Worker
510*4dc78e53SAndroid Build Coastguard Worker if (mqprio->qm_shaper != TC_MQPRIO_SHAPER_BW_RATE)
511*4dc78e53SAndroid Build Coastguard Worker return -NLE_INVAL;
512*4dc78e53SAndroid Build Coastguard Worker
513*4dc78e53SAndroid Build Coastguard Worker if (len < 0 || len > TC_QOPT_MAX_QUEUE)
514*4dc78e53SAndroid Build Coastguard Worker return -NLE_RANGE;
515*4dc78e53SAndroid Build Coastguard Worker
516*4dc78e53SAndroid Build Coastguard Worker memset(mqprio->qm_min_rate, 0, sizeof(mqprio->qm_min_rate));
517*4dc78e53SAndroid Build Coastguard Worker memcpy(mqprio->qm_min_rate, min, len * sizeof(uint64_t));
518*4dc78e53SAndroid Build Coastguard Worker mqprio->qm_mask |= SCH_MQPRIO_ATTR_MIN_RATE;
519*4dc78e53SAndroid Build Coastguard Worker
520*4dc78e53SAndroid Build Coastguard Worker return 0;
521*4dc78e53SAndroid Build Coastguard Worker }
522*4dc78e53SAndroid Build Coastguard Worker
523*4dc78e53SAndroid Build Coastguard Worker /**
524*4dc78e53SAndroid Build Coastguard Worker * Get minimum value of bandwidth rate limit for each traffic class
525*4dc78e53SAndroid Build Coastguard Worker * @arg qdisc MQPRIO qdisc.
526*4dc78e53SAndroid Build Coastguard Worker * @arg min minimum rate for each traffic class
527*4dc78e53SAndroid Build Coastguard Worker * @return 0 on success or a negative error code.
528*4dc78e53SAndroid Build Coastguard Worker */
rtnl_qdisc_mqprio_get_min_rate(struct rtnl_qdisc * qdisc,uint64_t * min)529*4dc78e53SAndroid Build Coastguard Worker int rtnl_qdisc_mqprio_get_min_rate(struct rtnl_qdisc *qdisc, uint64_t *min)
530*4dc78e53SAndroid Build Coastguard Worker {
531*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mqprio *mqprio;
532*4dc78e53SAndroid Build Coastguard Worker
533*4dc78e53SAndroid Build Coastguard Worker if (!(mqprio = rtnl_tc_data_peek(TC_CAST(qdisc))))
534*4dc78e53SAndroid Build Coastguard Worker return -NLE_INVAL;
535*4dc78e53SAndroid Build Coastguard Worker
536*4dc78e53SAndroid Build Coastguard Worker if (mqprio->qm_mask & SCH_MQPRIO_ATTR_MIN_RATE) {
537*4dc78e53SAndroid Build Coastguard Worker memcpy(min, mqprio->qm_min_rate, TC_QOPT_MAX_QUEUE * sizeof(uint64_t));
538*4dc78e53SAndroid Build Coastguard Worker return 0;
539*4dc78e53SAndroid Build Coastguard Worker }
540*4dc78e53SAndroid Build Coastguard Worker
541*4dc78e53SAndroid Build Coastguard Worker return -NLE_MISSING_ATTR;
542*4dc78e53SAndroid Build Coastguard Worker }
543*4dc78e53SAndroid Build Coastguard Worker
544*4dc78e53SAndroid Build Coastguard Worker /**
545*4dc78e53SAndroid Build Coastguard Worker * Set maximum value of bandwidth rate limit for each traffic class
546*4dc78e53SAndroid Build Coastguard Worker * @arg qdisc MQPRIO qdisc.
547*4dc78e53SAndroid Build Coastguard Worker * @arg max maximum rate for each traffic class
548*4dc78e53SAndroid Build Coastguard Worker * @return 0 on success or a negative error code.
549*4dc78e53SAndroid Build Coastguard Worker */
rtnl_qdisc_mqprio_set_max_rate(struct rtnl_qdisc * qdisc,uint64_t max[],int len)550*4dc78e53SAndroid Build Coastguard Worker int rtnl_qdisc_mqprio_set_max_rate(struct rtnl_qdisc *qdisc, uint64_t max[], int len)
551*4dc78e53SAndroid Build Coastguard Worker {
552*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mqprio *mqprio;
553*4dc78e53SAndroid Build Coastguard Worker
554*4dc78e53SAndroid Build Coastguard Worker if (!(mqprio = rtnl_tc_data(TC_CAST(qdisc))))
555*4dc78e53SAndroid Build Coastguard Worker return -NLE_NOMEM;
556*4dc78e53SAndroid Build Coastguard Worker
557*4dc78e53SAndroid Build Coastguard Worker if (!(mqprio->qm_mask & SCH_MQPRIO_ATTR_SHAPER))
558*4dc78e53SAndroid Build Coastguard Worker return -NLE_MISSING_ATTR;
559*4dc78e53SAndroid Build Coastguard Worker
560*4dc78e53SAndroid Build Coastguard Worker if (mqprio->qm_shaper != TC_MQPRIO_SHAPER_BW_RATE)
561*4dc78e53SAndroid Build Coastguard Worker return -NLE_INVAL;
562*4dc78e53SAndroid Build Coastguard Worker
563*4dc78e53SAndroid Build Coastguard Worker if (len < 0 || len > TC_QOPT_MAX_QUEUE)
564*4dc78e53SAndroid Build Coastguard Worker return -NLE_RANGE;
565*4dc78e53SAndroid Build Coastguard Worker
566*4dc78e53SAndroid Build Coastguard Worker memset(mqprio->qm_max_rate, 0, sizeof(mqprio->qm_max_rate));
567*4dc78e53SAndroid Build Coastguard Worker memcpy(mqprio->qm_max_rate, max, len * sizeof(uint64_t));
568*4dc78e53SAndroid Build Coastguard Worker mqprio->qm_mask |= SCH_MQPRIO_ATTR_MAX_RATE;
569*4dc78e53SAndroid Build Coastguard Worker
570*4dc78e53SAndroid Build Coastguard Worker return 0;
571*4dc78e53SAndroid Build Coastguard Worker }
572*4dc78e53SAndroid Build Coastguard Worker
573*4dc78e53SAndroid Build Coastguard Worker /**
574*4dc78e53SAndroid Build Coastguard Worker * Get maximum value of bandwidth rate limit for each traffic class
575*4dc78e53SAndroid Build Coastguard Worker * @arg qdisc MQPRIO qdisc.
576*4dc78e53SAndroid Build Coastguard Worker * @arg min maximum rate for each traffic class
577*4dc78e53SAndroid Build Coastguard Worker * @return 0 on success or a negative error code.
578*4dc78e53SAndroid Build Coastguard Worker */
rtnl_qdisc_mqprio_get_max_rate(struct rtnl_qdisc * qdisc,uint64_t * max)579*4dc78e53SAndroid Build Coastguard Worker int rtnl_qdisc_mqprio_get_max_rate(struct rtnl_qdisc *qdisc, uint64_t *max)
580*4dc78e53SAndroid Build Coastguard Worker {
581*4dc78e53SAndroid Build Coastguard Worker struct rtnl_mqprio *mqprio;
582*4dc78e53SAndroid Build Coastguard Worker
583*4dc78e53SAndroid Build Coastguard Worker if (!(mqprio = rtnl_tc_data_peek(TC_CAST(qdisc))))
584*4dc78e53SAndroid Build Coastguard Worker return -NLE_INVAL;
585*4dc78e53SAndroid Build Coastguard Worker
586*4dc78e53SAndroid Build Coastguard Worker if (mqprio->qm_mask & SCH_MQPRIO_ATTR_MAX_RATE) {
587*4dc78e53SAndroid Build Coastguard Worker memcpy(max, mqprio->qm_max_rate, TC_QOPT_MAX_QUEUE * sizeof(uint64_t));
588*4dc78e53SAndroid Build Coastguard Worker return 0;
589*4dc78e53SAndroid Build Coastguard Worker }
590*4dc78e53SAndroid Build Coastguard Worker
591*4dc78e53SAndroid Build Coastguard Worker return -NLE_MISSING_ATTR;
592*4dc78e53SAndroid Build Coastguard Worker }
593*4dc78e53SAndroid Build Coastguard Worker
594*4dc78e53SAndroid Build Coastguard Worker /** @} */
595*4dc78e53SAndroid Build Coastguard Worker
596*4dc78e53SAndroid Build Coastguard Worker static struct rtnl_tc_ops mqprio_ops = {
597*4dc78e53SAndroid Build Coastguard Worker .to_kind = "mqprio",
598*4dc78e53SAndroid Build Coastguard Worker .to_type = RTNL_TC_TYPE_QDISC,
599*4dc78e53SAndroid Build Coastguard Worker .to_size = sizeof(struct rtnl_mqprio),
600*4dc78e53SAndroid Build Coastguard Worker .to_msg_parser = mqprio_msg_parser,
601*4dc78e53SAndroid Build Coastguard Worker .to_dump = {
602*4dc78e53SAndroid Build Coastguard Worker [NL_DUMP_LINE] = mqprio_dump_line,
603*4dc78e53SAndroid Build Coastguard Worker [NL_DUMP_DETAILS] = mqprio_dump_details,
604*4dc78e53SAndroid Build Coastguard Worker },
605*4dc78e53SAndroid Build Coastguard Worker .to_msg_fill = mqprio_msg_fill,
606*4dc78e53SAndroid Build Coastguard Worker };
607*4dc78e53SAndroid Build Coastguard Worker
mqprio_init(void)608*4dc78e53SAndroid Build Coastguard Worker static void _nl_init mqprio_init(void)
609*4dc78e53SAndroid Build Coastguard Worker {
610*4dc78e53SAndroid Build Coastguard Worker rtnl_tc_register(&mqprio_ops);
611*4dc78e53SAndroid Build Coastguard Worker }
612*4dc78e53SAndroid Build Coastguard Worker
mqprio_exit(void)613*4dc78e53SAndroid Build Coastguard Worker static void _nl_exit mqprio_exit(void)
614*4dc78e53SAndroid Build Coastguard Worker {
615*4dc78e53SAndroid Build Coastguard Worker rtnl_tc_unregister(&mqprio_ops);
616*4dc78e53SAndroid Build Coastguard Worker }
617*4dc78e53SAndroid Build Coastguard Worker
618*4dc78e53SAndroid Build Coastguard Worker /** @} */
619