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