xref: /aosp_15_r20/external/libnl/lib/route/qdisc/dsmark.c (revision 4dc78e53d49367fa8e61b07018507c90983a077d)
1 /* SPDX-License-Identifier: LGPL-2.1-only */
2 /*
3  * Copyright (c) 2003-2011 Thomas Graf <[email protected]>
4  */
5 
6 /**
7  * @ingroup qdisc
8  * @ingroup class
9  * @defgroup qdisc_dsmark Differentiated Services Marker (DSMARK)
10  * @{
11  */
12 
13 #include "nl-default.h"
14 
15 #include <netlink/netlink.h>
16 #include <netlink/utils.h>
17 #include <netlink/route/qdisc.h>
18 #include <netlink/route/class.h>
19 #include <netlink/route/qdisc/dsmark.h>
20 
21 #include "tc-api.h"
22 
23 /** @cond SKIP */
24 struct rtnl_dsmark_qdisc {
25 	uint16_t qdm_indices;
26 	uint16_t qdm_default_index;
27 	uint32_t qdm_set_tc_index;
28 	uint32_t qdm_mask;
29 };
30 
31 struct rtnl_dsmark_class {
32 	uint8_t cdm_bmask;
33 	uint8_t cdm_value;
34 	uint32_t cdm_mask;
35 };
36 
37 #define SCH_DSMARK_ATTR_INDICES		0x1
38 #define SCH_DSMARK_ATTR_DEFAULT_INDEX	0x2
39 #define SCH_DSMARK_ATTR_SET_TC_INDEX	0x4
40 
41 #define SCH_DSMARK_ATTR_MASK		0x1
42 #define SCH_DSMARK_ATTR_VALUE		0x2
43 /** @endcond */
44 
45 static struct nla_policy dsmark_policy[TCA_DSMARK_MAX+1] = {
46 	[TCA_DSMARK_INDICES]		= { .type = NLA_U16 },
47 	[TCA_DSMARK_DEFAULT_INDEX]	= { .type = NLA_U16 },
48 	[TCA_DSMARK_SET_TC_INDEX]	= { .type = NLA_FLAG },
49 	[TCA_DSMARK_VALUE]		= { .type = NLA_U8 },
50 	[TCA_DSMARK_MASK]		= { .type = NLA_U8 },
51 };
52 
dsmark_qdisc_msg_parser(struct rtnl_tc * tc,void * data)53 static int dsmark_qdisc_msg_parser(struct rtnl_tc *tc, void *data)
54 {
55 	struct rtnl_dsmark_qdisc *dsmark = data;
56 	struct nlattr *tb[TCA_DSMARK_MAX + 1];
57 	int err;
58 
59 	err = tca_parse(tb, TCA_DSMARK_MAX, tc, dsmark_policy);
60 	if (err < 0)
61 		return err;
62 
63 	if (tb[TCA_DSMARK_INDICES]) {
64 		dsmark->qdm_indices = nla_get_u16(tb[TCA_DSMARK_INDICES]);
65 		dsmark->qdm_mask |= SCH_DSMARK_ATTR_INDICES;
66 	}
67 
68 	if (tb[TCA_DSMARK_DEFAULT_INDEX]) {
69 		dsmark->qdm_default_index =
70 				nla_get_u16(tb[TCA_DSMARK_DEFAULT_INDEX]);
71 		dsmark->qdm_mask |= SCH_DSMARK_ATTR_DEFAULT_INDEX;
72 	}
73 
74 	if (tb[TCA_DSMARK_SET_TC_INDEX]) {
75 		dsmark->qdm_set_tc_index = 1;
76 		dsmark->qdm_mask |= SCH_DSMARK_ATTR_SET_TC_INDEX;
77 	}
78 
79 	return 0;
80 }
81 
dsmark_class_msg_parser(struct rtnl_tc * tc,void * data)82 static int dsmark_class_msg_parser(struct rtnl_tc *tc, void *data)
83 {
84 	struct rtnl_dsmark_class *dsmark = data;
85 	struct nlattr *tb[TCA_DSMARK_MAX + 1];
86 	int err;
87 
88 	err = tca_parse(tb, TCA_DSMARK_MAX, tc, dsmark_policy);
89 	if (err < 0)
90 		return err;
91 
92 	if (tb[TCA_DSMARK_MASK]) {
93 		dsmark->cdm_bmask = nla_get_u8(tb[TCA_DSMARK_MASK]);
94 		dsmark->cdm_mask |= SCH_DSMARK_ATTR_MASK;
95 	}
96 
97 	if (tb[TCA_DSMARK_VALUE]) {
98 		dsmark->cdm_value = nla_get_u8(tb[TCA_DSMARK_VALUE]);
99 		dsmark->cdm_mask |= SCH_DSMARK_ATTR_VALUE;
100 	}
101 
102 	return 0;
103 }
104 
dsmark_qdisc_dump_line(struct rtnl_tc * tc,void * data,struct nl_dump_params * p)105 static void dsmark_qdisc_dump_line(struct rtnl_tc *tc, void *data,
106 				   struct nl_dump_params *p)
107 {
108 	struct rtnl_dsmark_qdisc *dsmark = data;
109 
110 	if (dsmark && (dsmark->qdm_mask & SCH_DSMARK_ATTR_INDICES))
111 		nl_dump(p, " indices 0x%04x", dsmark->qdm_indices);
112 }
113 
dsmark_qdisc_dump_details(struct rtnl_tc * tc,void * data,struct nl_dump_params * p)114 static void dsmark_qdisc_dump_details(struct rtnl_tc *tc, void *data,
115 				      struct nl_dump_params *p)
116 {
117 	struct rtnl_dsmark_qdisc *dsmark = data;
118 
119 	if (!dsmark)
120 		return;
121 
122 	if (dsmark->qdm_mask & SCH_DSMARK_ATTR_DEFAULT_INDEX)
123 		nl_dump(p, " default index 0x%04x", dsmark->qdm_default_index);
124 
125 	if (dsmark->qdm_mask & SCH_DSMARK_ATTR_SET_TC_INDEX)
126 		nl_dump(p, " set-tc-index");
127 }
128 
dsmark_class_dump_line(struct rtnl_tc * tc,void * data,struct nl_dump_params * p)129 static void dsmark_class_dump_line(struct rtnl_tc *tc, void *data,
130 				   struct nl_dump_params *p)
131 {
132 	struct rtnl_dsmark_class *dsmark = data;
133 
134 	if (!dsmark)
135 		return;
136 
137 	if (dsmark->cdm_mask & SCH_DSMARK_ATTR_VALUE)
138 		nl_dump(p, " value 0x%02x", dsmark->cdm_value);
139 
140 	if (dsmark->cdm_mask & SCH_DSMARK_ATTR_MASK)
141 		nl_dump(p, " mask 0x%02x", dsmark->cdm_bmask);
142 }
143 
dsmark_qdisc_msg_fill(struct rtnl_tc * tc,void * data,struct nl_msg * msg)144 static int dsmark_qdisc_msg_fill(struct rtnl_tc *tc, void *data,
145 				 struct nl_msg *msg)
146 {
147 	struct rtnl_dsmark_qdisc *dsmark = data;
148 
149 	if (!dsmark)
150 		return 0;
151 
152 	if (dsmark->qdm_mask & SCH_DSMARK_ATTR_INDICES)
153 		NLA_PUT_U16(msg, TCA_DSMARK_INDICES, dsmark->qdm_indices);
154 
155 	if (dsmark->qdm_mask & SCH_DSMARK_ATTR_DEFAULT_INDEX)
156 		NLA_PUT_U16(msg, TCA_DSMARK_DEFAULT_INDEX,
157 			    dsmark->qdm_default_index);
158 
159 	if (dsmark->qdm_mask & SCH_DSMARK_ATTR_SET_TC_INDEX)
160 		NLA_PUT_FLAG(msg, TCA_DSMARK_SET_TC_INDEX);
161 
162 	return 0;
163 
164 nla_put_failure:
165 	return -NLE_MSGSIZE;
166 }
167 
dsmark_class_msg_fill(struct rtnl_tc * tc,void * data,struct nl_msg * msg)168 static int dsmark_class_msg_fill(struct rtnl_tc *tc, void *data,
169 				 struct nl_msg *msg)
170 {
171 	struct rtnl_dsmark_class *dsmark = data;
172 
173 	if (!dsmark)
174 		return 0;
175 
176 	if (dsmark->cdm_mask & SCH_DSMARK_ATTR_MASK)
177 		NLA_PUT_U8(msg, TCA_DSMARK_MASK, dsmark->cdm_bmask);
178 
179 	if (dsmark->cdm_mask & SCH_DSMARK_ATTR_VALUE)
180 		NLA_PUT_U8(msg, TCA_DSMARK_VALUE, dsmark->cdm_value);
181 
182 	return 0;
183 
184 nla_put_failure:
185 	return -NLE_MSGSIZE;
186 }
187 
188 /**
189  * @name Class Attribute Access
190  * @{
191  */
192 
193 /**
194  * Set bitmask of DSMARK class.
195  * @arg class		DSMARK class to be modified.
196  * @arg mask		New bitmask.
197  * @return 0 on success or a negative error code.
198  */
rtnl_class_dsmark_set_bitmask(struct rtnl_class * class,uint8_t mask)199 int rtnl_class_dsmark_set_bitmask(struct rtnl_class *class, uint8_t mask)
200 {
201 	struct rtnl_dsmark_class *dsmark;
202 
203 	if (!(dsmark = rtnl_tc_data(TC_CAST(class))))
204 		return -NLE_NOMEM;
205 
206 	dsmark->cdm_bmask = mask;
207 	dsmark->cdm_mask |= SCH_DSMARK_ATTR_MASK;
208 
209 	return 0;
210 }
211 
212 /**
213  * Get bitmask of DSMARK class.
214  * @arg class		DSMARK class.
215  * @return Bitmask or a negative error code.
216  */
rtnl_class_dsmark_get_bitmask(struct rtnl_class * class)217 int rtnl_class_dsmark_get_bitmask(struct rtnl_class *class)
218 {
219 	struct rtnl_dsmark_class *dsmark;
220 
221 	if (!(dsmark = rtnl_tc_data(TC_CAST(class))))
222 		return -NLE_NOMEM;
223 
224 	if (dsmark->cdm_mask & SCH_DSMARK_ATTR_MASK)
225 		return dsmark->cdm_bmask;
226 	else
227 		return -NLE_NOATTR;
228 }
229 
230 /**
231  * Set value of DSMARK class.
232  * @arg class		DSMARK class to be modified.
233  * @arg value		New value.
234  * @return 0 on success or a negative errror code.
235  */
rtnl_class_dsmark_set_value(struct rtnl_class * class,uint8_t value)236 int rtnl_class_dsmark_set_value(struct rtnl_class *class, uint8_t value)
237 {
238 	struct rtnl_dsmark_class *dsmark;
239 
240 	if (!(dsmark = rtnl_tc_data(TC_CAST(class))))
241 		return -NLE_NOMEM;
242 
243 	dsmark->cdm_value = value;
244 	dsmark->cdm_mask |= SCH_DSMARK_ATTR_VALUE;
245 
246 	return 0;
247 }
248 
249 /**
250  * Get value of DSMARK class.
251  * @arg class		DSMARK class.
252  * @return Value or a negative error code.
253  */
rtnl_class_dsmark_get_value(struct rtnl_class * class)254 int rtnl_class_dsmark_get_value(struct rtnl_class *class)
255 {
256 	struct rtnl_dsmark_class *dsmark;
257 
258 	if (!(dsmark = rtnl_tc_data(TC_CAST(class))))
259 		return -NLE_NOMEM;
260 
261 	if (dsmark->cdm_mask & SCH_DSMARK_ATTR_VALUE)
262 		return dsmark->cdm_value;
263 	else
264 		return -NLE_NOATTR;
265 }
266 
267 /** @} */
268 
269 /**
270  * @name Qdisc Attribute Access
271  * @{
272  */
273 
274 /**
275  * Set indices of DSMARK qdisc.
276  * @arg qdisc		DSMARK qdisc to be modified.
277  * @arg indices		New indices.
278  */
rtnl_qdisc_dsmark_set_indices(struct rtnl_qdisc * qdisc,uint16_t indices)279 int rtnl_qdisc_dsmark_set_indices(struct rtnl_qdisc *qdisc, uint16_t indices)
280 {
281 	struct rtnl_dsmark_qdisc *dsmark;
282 
283 	if (!(dsmark = rtnl_tc_data(TC_CAST(qdisc))))
284 		return -NLE_NOMEM;
285 
286 	dsmark->qdm_indices = indices;
287 	dsmark->qdm_mask |= SCH_DSMARK_ATTR_INDICES;
288 
289 	return 0;
290 }
291 
292 /**
293  * Get indices of DSMARK qdisc.
294  * @arg qdisc		DSMARK qdisc.
295  * @return Indices or a negative error code.
296  */
rtnl_qdisc_dsmark_get_indices(struct rtnl_qdisc * qdisc)297 int rtnl_qdisc_dsmark_get_indices(struct rtnl_qdisc *qdisc)
298 {
299 	struct rtnl_dsmark_qdisc *dsmark;
300 
301 	if (!(dsmark = rtnl_tc_data(TC_CAST(qdisc))))
302 		return -NLE_NOMEM;
303 
304 	if (dsmark->qdm_mask & SCH_DSMARK_ATTR_INDICES)
305 		return dsmark->qdm_indices;
306 	else
307 		return -NLE_NOATTR;
308 }
309 
310 /**
311  * Set default index of DSMARK qdisc.
312  * @arg qdisc		DSMARK qdisc to be modified.
313  * @arg default_index	New default index.
314  * @return 0 on success or a negative error code.
315  */
rtnl_qdisc_dsmark_set_default_index(struct rtnl_qdisc * qdisc,uint16_t default_index)316 int rtnl_qdisc_dsmark_set_default_index(struct rtnl_qdisc *qdisc,
317 					uint16_t default_index)
318 {
319 	struct rtnl_dsmark_qdisc *dsmark;
320 
321 	if (!(dsmark = rtnl_tc_data(TC_CAST(qdisc))))
322 		return -NLE_NOMEM;
323 
324 	dsmark->qdm_default_index = default_index;
325 	dsmark->qdm_mask |= SCH_DSMARK_ATTR_DEFAULT_INDEX;
326 
327 	return 0;
328 }
329 
330 /**
331  * Get default index of DSMARK qdisc.
332  * @arg qdisc		DSMARK qdisc.
333  * @return Default index or a negative error code.
334  */
rtnl_qdisc_dsmark_get_default_index(struct rtnl_qdisc * qdisc)335 int rtnl_qdisc_dsmark_get_default_index(struct rtnl_qdisc *qdisc)
336 {
337 	struct rtnl_dsmark_qdisc *dsmark;
338 
339 	if (!(dsmark = rtnl_tc_data(TC_CAST(qdisc))))
340 		return -NLE_NOMEM;
341 
342 	if (dsmark->qdm_mask & SCH_DSMARK_ATTR_DEFAULT_INDEX)
343 		return dsmark->qdm_default_index;
344 	else
345 		return -NLE_NOATTR;
346 }
347 
348 /**
349  * Set set-tc-index flag of DSMARK qdisc.
350  * @arg qdisc		DSMARK qdisc to be modified.
351  * @arg flag		Flag indicating whether to enable or disable.
352  * @return 0 on success or a negative error code.
353  */
rtnl_qdisc_dsmark_set_set_tc_index(struct rtnl_qdisc * qdisc,int flag)354 int rtnl_qdisc_dsmark_set_set_tc_index(struct rtnl_qdisc *qdisc, int flag)
355 {
356 	struct rtnl_dsmark_qdisc *dsmark;
357 
358 	if (!(dsmark = rtnl_tc_data(TC_CAST(qdisc))))
359 		return -NLE_NOMEM;
360 
361 	dsmark->qdm_set_tc_index = !!flag;
362 	dsmark->qdm_mask |= SCH_DSMARK_ATTR_SET_TC_INDEX;
363 
364 	return 0;
365 }
366 
367 /**
368  * Get set-tc-index flag of DSMARK qdisc.
369  * @arg qdisc		DSMARK qdisc to be modified.
370  * @return 1 or 0 to indicate wehther the flag is enabled or a negative
371  *         error code.
372  */
rtnl_qdisc_dsmark_get_set_tc_index(struct rtnl_qdisc * qdisc)373 int rtnl_qdisc_dsmark_get_set_tc_index(struct rtnl_qdisc *qdisc)
374 {
375 	struct rtnl_dsmark_qdisc *dsmark;
376 
377 	if (!(dsmark = rtnl_tc_data(TC_CAST(qdisc))))
378 		return -NLE_NOMEM;
379 
380 	if (dsmark->qdm_mask & SCH_DSMARK_ATTR_SET_TC_INDEX)
381 		return dsmark->qdm_set_tc_index;
382 	else
383 		return -NLE_NOATTR;
384 }
385 
386 /** @} */
387 
388 static struct rtnl_tc_ops dsmark_qdisc_ops = {
389 	.to_kind		= "dsmark",
390 	.to_type		= RTNL_TC_TYPE_QDISC,
391 	.to_size		= sizeof(struct rtnl_dsmark_qdisc),
392 	.to_msg_parser		= dsmark_qdisc_msg_parser,
393 	.to_dump = {
394 	    [NL_DUMP_LINE]	= dsmark_qdisc_dump_line,
395 	    [NL_DUMP_DETAILS]	= dsmark_qdisc_dump_details,
396 	},
397 	.to_msg_fill		= dsmark_qdisc_msg_fill,
398 };
399 
400 static struct rtnl_tc_ops dsmark_class_ops = {
401 	.to_kind		= "dsmark",
402 	.to_type		= RTNL_TC_TYPE_CLASS,
403 	.to_size		= sizeof(struct rtnl_dsmark_class),
404 	.to_msg_parser		= dsmark_class_msg_parser,
405 	.to_dump[NL_DUMP_LINE]	= dsmark_class_dump_line,
406 	.to_msg_fill		= dsmark_class_msg_fill,
407 };
408 
dsmark_init(void)409 static void _nl_init dsmark_init(void)
410 {
411 	rtnl_tc_register(&dsmark_qdisc_ops);
412 	rtnl_tc_register(&dsmark_class_ops);
413 }
414 
dsmark_exit(void)415 static void _nl_exit dsmark_exit(void)
416 {
417 	rtnl_tc_unregister(&dsmark_qdisc_ops);
418 	rtnl_tc_unregister(&dsmark_class_ops);
419 }
420 
421 /** @} */
422