libnl: /data/src/libnl/lib/route/qdisc/prio.c Source File

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