libnl  3.2.24-rc1
dsmark.c
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 
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 
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 
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 
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 
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 
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 
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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 
401 static void __init dsmark_init(void)
402 {
403  rtnl_tc_register(&dsmark_qdisc_ops);
404  rtnl_tc_register(&dsmark_class_ops);
405 }
406 
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 /** @} */