libnl 3.7.0
prio.c
1/* SPDX-License-Identifier: LGPL-2.1-only */
2/*
3 * Copyright (c) 2003-2011 Thomas Graf <tgraf@suug.ch>
4 */
5
6/**
7 * @ingroup qdisc
8 * @defgroup qdisc_prio (Fast) Prio
9 * @brief
10 *
11 * @par 1) Typical PRIO configuration
12 * @code
13 * // Specify the maximal number of bands to be used for this PRIO qdisc.
14 * rtnl_qdisc_prio_set_bands(qdisc, QDISC_PRIO_DEFAULT_BANDS);
15 *
16 * // Provide a map assigning each priority to a band number.
17 * uint8_t map[] = QDISC_PRIO_DEFAULT_PRIOMAP;
18 * rtnl_qdisc_prio_set_priomap(qdisc, map, sizeof(map));
19 * @endcode
20 * @{
21 */
22
23#include <netlink-private/netlink.h>
24#include <netlink-private/tc.h>
25#include <netlink/netlink.h>
26#include <netlink/utils.h>
27#include <netlink-private/route/tc-api.h>
28#include <netlink/route/qdisc.h>
29#include <netlink/route/qdisc/prio.h>
30
31/** @cond SKIP */
32#define SCH_PRIO_ATTR_BANDS 1
33#define SCH_PRIO_ATTR_PRIOMAP 2
34/** @endcond */
35
36static int prio_msg_parser(struct rtnl_tc *tc, void *data)
37{
38 struct rtnl_prio *prio = data;
39 struct tc_prio_qopt *opt;
40
41 if (tc->tc_opts->d_size < sizeof(*opt))
42 return -NLE_INVAL;
43
44 opt = (struct tc_prio_qopt *) tc->tc_opts->d_data;
45 prio->qp_bands = opt->bands;
46 memcpy(prio->qp_priomap, opt->priomap, sizeof(prio->qp_priomap));
47 prio->qp_mask = (SCH_PRIO_ATTR_BANDS | SCH_PRIO_ATTR_PRIOMAP);
48
49 return 0;
50}
51
52static void prio_dump_line(struct rtnl_tc *tc, void *data,
53 struct nl_dump_params *p)
54{
55 struct rtnl_prio *prio = data;
56
57 if (prio)
58 nl_dump(p, " bands %u", prio->qp_bands);
59}
60
61static void prio_dump_details(struct rtnl_tc *tc, void *data,
62 struct nl_dump_params *p)
63{
64 struct rtnl_prio *prio = data;
65 int i, hp;
66
67 if (!prio)
68 return;
69
70 nl_dump(p, "priomap [");
71
72 for (i = 0; i <= TC_PRIO_MAX; i++)
73 nl_dump(p, "%u%s", prio->qp_priomap[i],
74 i < TC_PRIO_MAX ? " " : "");
75
76 nl_dump(p, "]\n");
77 nl_new_line(p);
78
79 hp = (((TC_PRIO_MAX/2) + 1) & ~1);
80
81 for (i = 0; i < hp; i++) {
82 char a[32];
83 nl_dump(p, " %18s => %u",
84 rtnl_prio2str(i, a, sizeof(a)),
85 prio->qp_priomap[i]);
86 if (hp+i <= TC_PRIO_MAX) {
87 nl_dump(p, " %18s => %u",
88 rtnl_prio2str(hp+i, a, sizeof(a)),
89 prio->qp_priomap[hp+i]);
90 if (i < (hp - 1)) {
91 nl_dump(p, "\n");
92 nl_new_line(p);
93 }
94 }
95 }
96}
97
98static int prio_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
99{
100 struct rtnl_prio *prio = data;
101 struct tc_prio_qopt opts;
102
103 if (!prio || !(prio->qp_mask & SCH_PRIO_ATTR_PRIOMAP))
104 BUG();
105
106 opts.bands = prio->qp_bands;
107 memcpy(opts.priomap, prio->qp_priomap, sizeof(opts.priomap));
108
109 return nlmsg_append(msg, &opts, sizeof(opts), NL_DONTPAD);
110}
111
112/**
113 * @name Attribute Modification
114 * @{
115 */
116
117/**
118 * Set number of bands of PRIO qdisc.
119 * @arg qdisc PRIO qdisc to be modified.
120 * @arg bands New number of bands.
121 * @return 0 on success or a negative error code.
122 */
123void rtnl_qdisc_prio_set_bands(struct rtnl_qdisc *qdisc, int bands)
124{
125 struct rtnl_prio *prio;
126
127 if (!(prio = rtnl_tc_data(TC_CAST(qdisc))))
128 BUG();
129
130 prio->qp_bands = bands;
131 prio->qp_mask |= SCH_PRIO_ATTR_BANDS;
132}
133
134/**
135 * Get number of bands of PRIO qdisc.
136 * @arg qdisc PRIO qdisc.
137 * @return Number of bands or a negative error code.
138 */
139int rtnl_qdisc_prio_get_bands(struct rtnl_qdisc *qdisc)
140{
141 struct rtnl_prio *prio;
142
143 if (!(prio = rtnl_tc_data(TC_CAST(qdisc))))
144 BUG();
145
146 if (prio->qp_mask & SCH_PRIO_ATTR_BANDS)
147 return prio->qp_bands;
148 else
149 return -NLE_NOMEM;
150}
151
152/**
153 * Set priomap of the PRIO qdisc.
154 * @arg qdisc PRIO qdisc to be modified.
155 * @arg priomap New priority mapping.
156 * @arg len Length of priomap (# of elements).
157 * @return 0 on success or a negative error code.
158 */
159int rtnl_qdisc_prio_set_priomap(struct rtnl_qdisc *qdisc, uint8_t priomap[],
160 int len)
161{
162 struct rtnl_prio *prio;
163 int i;
164
165 if (!(prio = rtnl_tc_data(TC_CAST(qdisc))))
166 BUG();
167
168 if (!(prio->qp_mask & SCH_PRIO_ATTR_BANDS))
169 return -NLE_MISSING_ATTR;
170
171 if ((len / sizeof(uint8_t)) > (TC_PRIO_MAX+1))
172 return -NLE_RANGE;
173
174 for (i = 0; i <= TC_PRIO_MAX; i++) {
175 if (priomap[i] > prio->qp_bands)
176 return -NLE_RANGE;
177 }
178
179 memcpy(prio->qp_priomap, priomap, len);
180 prio->qp_mask |= SCH_PRIO_ATTR_PRIOMAP;
181
182 return 0;
183}
184
185/**
186 * Get priomap of a PRIO qdisc.
187 * @arg qdisc PRIO qdisc.
188 * @return Priority mapping as array of size TC_PRIO_MAX+1
189 * or NULL if an error occured.
190 */
191uint8_t *rtnl_qdisc_prio_get_priomap(struct rtnl_qdisc *qdisc)
192{
193 struct rtnl_prio *prio;
194
195 if (!(prio = rtnl_tc_data(TC_CAST(qdisc))))
196 BUG();
197
198 if (prio->qp_mask & SCH_PRIO_ATTR_PRIOMAP)
199 return prio->qp_priomap;
200 else
201 return NULL;
202}
203
204/** @} */
205
206/**
207 * @name Priority Band Translations
208 * @{
209 */
210
211static const struct trans_tbl prios[] = {
212 __ADD(TC_PRIO_BESTEFFORT,besteffort),
213 __ADD(TC_PRIO_FILLER,filler),
214 __ADD(TC_PRIO_BULK,bulk),
215 __ADD(TC_PRIO_INTERACTIVE_BULK,interactive_bulk),
216 __ADD(TC_PRIO_INTERACTIVE,interactive),
217 __ADD(TC_PRIO_CONTROL,control),
218};
219
220/**
221 * Convert priority to character string.
222 * @arg prio Priority.
223 * @arg buf Destination buffer
224 * @arg size Size of destination buffer.
225 *
226 * Converts a priority to a character string and stores the result in
227 * the specified destination buffer.
228 *
229 * @return Name of priority as character string.
230 */
231char * rtnl_prio2str(int prio, char *buf, size_t size)
232{
233 return __type2str(prio, buf, size, prios, ARRAY_SIZE(prios));
234}
235
236/**
237 * Convert character string to priority.
238 * @arg name Name of priority.
239 *
240 * Converts the provided character string specifying a priority
241 * to the corresponding numeric value.
242 *
243 * @return Numeric priority or a negative value if no match was found.
244 */
245int rtnl_str2prio(const char *name)
246{
247 return __str2type(name, prios, ARRAY_SIZE(prios));
248}
249
250/** @} */
251
252static struct rtnl_tc_ops prio_ops = {
253 .to_kind = "prio",
254 .to_type = RTNL_TC_TYPE_QDISC,
255 .to_size = sizeof(struct rtnl_prio),
256 .to_msg_parser = prio_msg_parser,
257 .to_dump = {
258 [NL_DUMP_LINE] = prio_dump_line,
259 [NL_DUMP_DETAILS] = prio_dump_details,
260 },
261 .to_msg_fill = prio_msg_fill,
262};
263
264static struct rtnl_tc_ops pfifo_fast_ops = {
265 .to_kind = "pfifo_fast",
266 .to_type = RTNL_TC_TYPE_QDISC,
267 .to_size = sizeof(struct rtnl_prio),
268 .to_msg_parser = prio_msg_parser,
269 .to_dump = {
270 [NL_DUMP_LINE] = prio_dump_line,
271 [NL_DUMP_DETAILS] = prio_dump_details,
272 },
273 .to_msg_fill = prio_msg_fill,
274};
275
276static void __init prio_init(void)
277{
278 rtnl_tc_register(&prio_ops);
279 rtnl_tc_register(&pfifo_fast_ops);
280}
281
282static void __exit prio_exit(void)
283{
284 rtnl_tc_unregister(&prio_ops);
285 rtnl_tc_unregister(&pfifo_fast_ops);
286}
287
288/** @} */
int nlmsg_append(struct nl_msg *n, void *data, size_t len, int pad)
Append data to tail of a netlink message.
Definition: msg.c:442
int rtnl_qdisc_prio_get_bands(struct rtnl_qdisc *qdisc)
Get number of bands of PRIO qdisc.
Definition: prio.c:139
int rtnl_str2prio(const char *name)
Convert character string to priority.
Definition: prio.c:245
int rtnl_qdisc_prio_set_priomap(struct rtnl_qdisc *qdisc, uint8_t priomap[], int len)
Set priomap of the PRIO qdisc.
Definition: prio.c:159
uint8_t * rtnl_qdisc_prio_get_priomap(struct rtnl_qdisc *qdisc)
Get priomap of a PRIO qdisc.
Definition: prio.c:191
char * rtnl_prio2str(int prio, char *buf, size_t size)
Convert priority to character string.
Definition: prio.c:231
void rtnl_qdisc_prio_set_bands(struct rtnl_qdisc *qdisc, int bands)
Set number of bands of PRIO qdisc.
Definition: prio.c:123
#define TC_CAST(ptr)
Macro to cast qdisc/class/classifier to tc object.
Definition: tc.h:50
void * rtnl_tc_data(struct rtnl_tc *tc)
Return pointer to private data of traffic control object.
Definition: tc.c:1076
int rtnl_tc_register(struct rtnl_tc_ops *ops)
Register a traffic control module.
Definition: tc.c:1015
void rtnl_tc_unregister(struct rtnl_tc_ops *ops)
Unregister a traffic control module.
Definition: tc.c:1049
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Definition: utils.c:955
void nl_new_line(struct nl_dump_params *params)
Handle a new line while dumping.
Definition: utils.c:906
@ NL_DUMP_LINE
Dump object briefly on one line.
Definition: types.h:16
@ NL_DUMP_DETAILS
Dump all attributes but no statistics.
Definition: types.h:17
Dumping parameters.
Definition: types.h:28