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