libnl  3.2.25
u32.c
1 /*
2  * lib/route/cls/u32.c u32 classifier
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-2013 Thomas Graf <tgraf@suug.ch>
10  * Copyright (c) 2005-2006 Petr Gotthard <petr.gotthard@siemens.com>
11  * Copyright (c) 2005-2006 Siemens AG Oesterreich
12  */
13 
14 /**
15  * @ingroup cls
16  * @defgroup cls_u32 Universal 32-bit Classifier
17  *
18  * @{
19  */
20 
21 #include <netlink-private/netlink.h>
22 #include <netlink-private/tc.h>
23 #include <netlink/netlink.h>
24 #include <netlink/attr.h>
25 #include <netlink/utils.h>
26 #include <netlink-private/route/tc-api.h>
27 #include <netlink/route/classifier.h>
28 #include <netlink/route/cls/u32.h>
29 #include <netlink/route/action.h>
30 
31 /** @cond SKIP */
32 #define U32_ATTR_DIVISOR 0x001
33 #define U32_ATTR_HASH 0x002
34 #define U32_ATTR_CLASSID 0x004
35 #define U32_ATTR_LINK 0x008
36 #define U32_ATTR_PCNT 0x010
37 #define U32_ATTR_SELECTOR 0x020
38 #define U32_ATTR_ACTION 0x040
39 #define U32_ATTR_POLICE 0x080
40 #define U32_ATTR_INDEV 0x100
41 /** @endcond */
42 
43 static inline struct tc_u32_sel *u32_selector(struct rtnl_u32 *u)
44 {
45  return (struct tc_u32_sel *) u->cu_selector->d_data;
46 }
47 
48 static inline struct tc_u32_sel *u32_selector_alloc(struct rtnl_u32 *u)
49 {
50  if (!u->cu_selector)
51  u->cu_selector = nl_data_alloc(NULL, sizeof(struct tc_u32_sel));
52 
53  return u32_selector(u);
54 }
55 
56 static struct nla_policy u32_policy[TCA_U32_MAX+1] = {
57  [TCA_U32_DIVISOR] = { .type = NLA_U32 },
58  [TCA_U32_HASH] = { .type = NLA_U32 },
59  [TCA_U32_CLASSID] = { .type = NLA_U32 },
60  [TCA_U32_LINK] = { .type = NLA_U32 },
61  [TCA_U32_INDEV] = { .type = NLA_STRING,
62  .maxlen = IFNAMSIZ },
63  [TCA_U32_SEL] = { .minlen = sizeof(struct tc_u32_sel) },
64  [TCA_U32_PCNT] = { .minlen = sizeof(struct tc_u32_pcnt) },
65 };
66 
67 static int u32_msg_parser(struct rtnl_tc *tc, void *data)
68 {
69  struct rtnl_u32 *u = data;
70  struct nlattr *tb[TCA_U32_MAX + 1];
71  int err;
72 
73  err = tca_parse(tb, TCA_U32_MAX, tc, u32_policy);
74  if (err < 0)
75  return err;
76 
77  if (tb[TCA_U32_DIVISOR]) {
78  u->cu_divisor = nla_get_u32(tb[TCA_U32_DIVISOR]);
79  u->cu_mask |= U32_ATTR_DIVISOR;
80  }
81 
82  if (tb[TCA_U32_SEL]) {
83  u->cu_selector = nl_data_alloc_attr(tb[TCA_U32_SEL]);
84  if (!u->cu_selector)
85  goto errout_nomem;
86  u->cu_mask |= U32_ATTR_SELECTOR;
87  }
88 
89  if (tb[TCA_U32_HASH]) {
90  u->cu_hash = nla_get_u32(tb[TCA_U32_HASH]);
91  u->cu_mask |= U32_ATTR_HASH;
92  }
93 
94  if (tb[TCA_U32_CLASSID]) {
95  u->cu_classid = nla_get_u32(tb[TCA_U32_CLASSID]);
96  u->cu_mask |= U32_ATTR_CLASSID;
97  }
98 
99  if (tb[TCA_U32_LINK]) {
100  u->cu_link = nla_get_u32(tb[TCA_U32_LINK]);
101  u->cu_mask |= U32_ATTR_LINK;
102  }
103 
104  if (tb[TCA_U32_ACT]) {
105  u->cu_mask |= U32_ATTR_ACTION;
106  err = rtnl_act_parse(&u->cu_act, tb[TCA_U32_ACT]);
107  if (err)
108  return err;
109  }
110 
111  if (tb[TCA_U32_POLICE]) {
112  u->cu_police = nl_data_alloc_attr(tb[TCA_U32_POLICE]);
113  if (!u->cu_police)
114  goto errout_nomem;
115  u->cu_mask |= U32_ATTR_POLICE;
116  }
117 
118  if (tb[TCA_U32_PCNT]) {
119  struct tc_u32_sel *sel;
120  size_t pcnt_size;
121 
122  if (!tb[TCA_U32_SEL]) {
123  err = -NLE_MISSING_ATTR;
124  goto errout;
125  }
126 
127  sel = u->cu_selector->d_data;
128  pcnt_size = sizeof(struct tc_u32_pcnt) +
129  (sel->nkeys * sizeof(uint64_t));
130  if (nla_len(tb[TCA_U32_PCNT]) < pcnt_size) {
131  err = -NLE_INVAL;
132  goto errout;
133  }
134 
135  u->cu_pcnt = nl_data_alloc_attr(tb[TCA_U32_PCNT]);
136  if (!u->cu_pcnt)
137  goto errout_nomem;
138  u->cu_mask |= U32_ATTR_PCNT;
139  }
140 
141  if (tb[TCA_U32_INDEV]) {
142  nla_strlcpy(u->cu_indev, tb[TCA_U32_INDEV], IFNAMSIZ);
143  u->cu_mask |= U32_ATTR_INDEV;
144  }
145 
146  return 0;
147 
148 errout_nomem:
149  err = -NLE_NOMEM;
150 errout:
151  return err;
152 }
153 
154 static void u32_free_data(struct rtnl_tc *tc, void *data)
155 {
156  struct rtnl_u32 *u = data;
157 
158  if (u->cu_act)
159  rtnl_act_put_all(&u->cu_act);
160  nl_data_free(u->cu_selector);
161  nl_data_free(u->cu_police);
162  nl_data_free(u->cu_pcnt);
163 }
164 
165 static int u32_clone(void *_dst, void *_src)
166 {
167  struct rtnl_u32 *dst = _dst, *src = _src;
168 
169  if (src->cu_selector &&
170  !(dst->cu_selector = nl_data_clone(src->cu_selector)))
171  return -NLE_NOMEM;
172 
173  if (src->cu_act) {
174  if (!(dst->cu_act = rtnl_act_alloc()))
175  return -NLE_NOMEM;
176 
177  memcpy(dst->cu_act, src->cu_act, sizeof(struct rtnl_act));
178  }
179 
180  if (src->cu_police && !(dst->cu_police = nl_data_clone(src->cu_police)))
181  return -NLE_NOMEM;
182 
183  if (src->cu_pcnt && !(dst->cu_pcnt = nl_data_clone(src->cu_pcnt)))
184  return -NLE_NOMEM;
185 
186  return 0;
187 }
188 
189 static void u32_dump_line(struct rtnl_tc *tc, void *data,
190  struct nl_dump_params *p)
191 {
192  struct rtnl_u32 *u = data;
193  char buf[32];
194 
195  if (!u)
196  return;
197 
198  if (u->cu_mask & U32_ATTR_DIVISOR)
199  nl_dump(p, " divisor %u", u->cu_divisor);
200  else if (u->cu_mask & U32_ATTR_CLASSID)
201  nl_dump(p, " target %s",
202  rtnl_tc_handle2str(u->cu_classid, buf, sizeof(buf)));
203 }
204 
205 static void print_selector(struct nl_dump_params *p, struct tc_u32_sel *sel,
206  struct rtnl_u32 *u)
207 {
208  int i;
209  struct tc_u32_key *key;
210 
211  if (sel->hmask || sel->hoff) {
212  /* I guess this will never be used since the kernel only
213  * exports the selector if no divisor is set but hash offset
214  * and hash mask make only sense in hash filters with divisor
215  * set */
216  nl_dump(p, " hash at %u & 0x%x", sel->hoff, sel->hmask);
217  }
218 
219  if (sel->flags & (TC_U32_OFFSET | TC_U32_VAROFFSET)) {
220  nl_dump(p, " offset at %u", sel->off);
221 
222  if (sel->flags & TC_U32_VAROFFSET)
223  nl_dump(p, " variable (at %u & 0x%x) >> %u",
224  sel->offoff, ntohs(sel->offmask), sel->offshift);
225  }
226 
227  if (sel->flags) {
228  int flags = sel->flags;
229  nl_dump(p, " <");
230 
231 #define PRINT_FLAG(f) if (flags & TC_U32_##f) { \
232  flags &= ~TC_U32_##f; nl_dump(p, #f "%s", flags ? "," : ""); }
233 
234  PRINT_FLAG(TERMINAL);
235  PRINT_FLAG(OFFSET);
236  PRINT_FLAG(VAROFFSET);
237  PRINT_FLAG(EAT);
238 #undef PRINT_FLAG
239 
240  nl_dump(p, ">");
241  }
242 
243 
244  for (i = 0; i < sel->nkeys; i++) {
245  key = (struct tc_u32_key *) ((char *) sel + sizeof(*sel)) + i;
246 
247  nl_dump(p, "\n");
248  nl_dump_line(p, " match key at %s%u ",
249  key->offmask ? "nexthdr+" : "", key->off);
250 
251  if (key->offmask)
252  nl_dump(p, "[0x%u] ", key->offmask);
253 
254  nl_dump(p, "& 0x%08x == 0x%08x", ntohl(key->mask), ntohl(key->val));
255 
256  if (p->dp_type == NL_DUMP_STATS &&
257  (u->cu_mask & U32_ATTR_PCNT)) {
258  struct tc_u32_pcnt *pcnt = u->cu_pcnt->d_data;
259  nl_dump(p, " successful %" PRIu64, pcnt->kcnts[i]);
260  }
261  }
262 }
263 
264 static void u32_dump_details(struct rtnl_tc *tc, void *data,
265  struct nl_dump_params *p)
266 {
267  struct rtnl_u32 *u = data;
268  struct tc_u32_sel *s;
269 
270  if (!u)
271  return;
272 
273  if (!(u->cu_mask & U32_ATTR_SELECTOR)) {
274  nl_dump(p, "no-selector\n");
275  return;
276  }
277 
278  s = u->cu_selector->d_data;
279 
280  nl_dump(p, "nkeys %u ", s->nkeys);
281 
282  if (u->cu_mask & U32_ATTR_HASH)
283  nl_dump(p, "ht key 0x%x hash 0x%u",
284  TC_U32_USERHTID(u->cu_hash), TC_U32_HASH(u->cu_hash));
285 
286  if (u->cu_mask & U32_ATTR_LINK)
287  nl_dump(p, "link %u ", u->cu_link);
288 
289  if (u->cu_mask & U32_ATTR_INDEV)
290  nl_dump(p, "indev %s ", u->cu_indev);
291 
292  print_selector(p, s, u);
293  nl_dump(p, "\n");
294 }
295 
296 static void u32_dump_stats(struct rtnl_tc *tc, void *data,
297  struct nl_dump_params *p)
298 {
299  struct rtnl_u32 *u = data;
300 
301  if (!u)
302  return;
303 
304  if (u->cu_mask & U32_ATTR_PCNT) {
305  struct tc_u32_pcnt *pc = u->cu_pcnt->d_data;
306  nl_dump(p, "\n");
307  nl_dump_line(p, " hit %8" PRIu64 " count %8" PRIu64 "\n",
308  pc->rhit, pc->rcnt);
309  }
310 }
311 
312 static int u32_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
313 {
314  struct rtnl_u32 *u = data;
315 
316  if (!u)
317  return 0;
318 
319  if (u->cu_mask & U32_ATTR_DIVISOR)
320  NLA_PUT_U32(msg, TCA_U32_DIVISOR, u->cu_divisor);
321 
322  if (u->cu_mask & U32_ATTR_HASH)
323  NLA_PUT_U32(msg, TCA_U32_HASH, u->cu_hash);
324 
325  if (u->cu_mask & U32_ATTR_CLASSID)
326  NLA_PUT_U32(msg, TCA_U32_CLASSID, u->cu_classid);
327 
328  if (u->cu_mask & U32_ATTR_LINK)
329  NLA_PUT_U32(msg, TCA_U32_LINK, u->cu_link);
330 
331  if (u->cu_mask & U32_ATTR_SELECTOR)
332  NLA_PUT_DATA(msg, TCA_U32_SEL, u->cu_selector);
333 
334  if (u->cu_mask & U32_ATTR_ACTION) {
335  int err;
336 
337  err = rtnl_act_fill(msg, TCA_U32_ACT, u->cu_act);
338  if (err)
339  return err;
340  }
341 
342  if (u->cu_mask & U32_ATTR_POLICE)
343  NLA_PUT_DATA(msg, TCA_U32_POLICE, u->cu_police);
344 
345  if (u->cu_mask & U32_ATTR_INDEV)
346  NLA_PUT_STRING(msg, TCA_U32_INDEV, u->cu_indev);
347 
348  return 0;
349 
350 nla_put_failure:
351  return -NLE_NOMEM;
352 }
353 
354 /**
355  * @name Attribute Modifications
356  * @{
357  */
358 
359 void rtnl_u32_set_handle(struct rtnl_cls *cls, int htid, int hash,
360  int nodeid)
361 {
362  uint32_t handle = (htid << 20) | (hash << 12) | nodeid;
363 
364  rtnl_tc_set_handle((struct rtnl_tc *) cls, handle );
365 }
366 
367 int rtnl_u32_set_classid(struct rtnl_cls *cls, uint32_t classid)
368 {
369  struct rtnl_u32 *u;
370 
371  if (!(u = rtnl_tc_data(TC_CAST(cls))))
372  return -NLE_NOMEM;
373 
374  u->cu_classid = classid;
375  u->cu_mask |= U32_ATTR_CLASSID;
376 
377  return 0;
378 }
379 
380 int rtnl_u32_set_divisor(struct rtnl_cls *cls, uint32_t divisor)
381 {
382  struct rtnl_u32 *u;
383 
384  if (!(u = (struct rtnl_u32 *) rtnl_tc_data(TC_CAST(cls))))
385  return -NLE_NOMEM;
386 
387  u->cu_divisor = divisor;
388  u->cu_mask |= U32_ATTR_DIVISOR;
389  return 0;
390 }
391 
392 int rtnl_u32_set_link(struct rtnl_cls *cls, uint32_t link)
393 {
394  struct rtnl_u32 *u;
395 
396  if (!(u = (struct rtnl_u32 *) rtnl_tc_data(TC_CAST(cls))))
397  return -NLE_NOMEM;
398 
399  u->cu_link = link;
400  u->cu_mask |= U32_ATTR_LINK;
401  return 0;
402 }
403 
404 int rtnl_u32_set_hashtable(struct rtnl_cls *cls, uint32_t ht)
405 {
406  struct rtnl_u32 *u;
407 
408  if (!(u = (struct rtnl_u32 *) rtnl_tc_data(TC_CAST(cls))))
409  return -NLE_NOMEM;
410 
411  u->cu_hash = ht;
412  u->cu_mask |= U32_ATTR_HASH;
413  return 0;
414 }
415 
416 int rtnl_u32_set_hashmask(struct rtnl_cls *cls, uint32_t hashmask, uint32_t offset)
417 {
418  struct rtnl_u32 *u;
419  struct tc_u32_sel *sel;
420  int err;
421 
422  hashmask = htonl(hashmask);
423 
424  if (!(u = (struct rtnl_u32 *) rtnl_tc_data(TC_CAST(cls))))
425  return -NLE_NOMEM;
426 
427  sel = u32_selector_alloc(u);
428  if (!sel)
429  return -NLE_NOMEM;
430 
431  err = nl_data_append(u->cu_selector, NULL, sizeof(struct tc_u32_key));
432  if(err < 0)
433  return err;
434 
435  sel = u32_selector(u);
436 
437  sel->hmask = hashmask;
438  sel->hoff = offset;
439  return 0;
440 }
441 
442 int rtnl_u32_set_cls_terminal(struct rtnl_cls *cls)
443 {
444  struct rtnl_u32 *u;
445  struct tc_u32_sel *sel;
446  int err;
447 
448  if (!(u = (struct rtnl_u32 *) rtnl_tc_data(TC_CAST(cls))))
449  return -NLE_NOMEM;
450 
451  sel = u32_selector_alloc(u);
452  if (!sel)
453  return -NLE_NOMEM;
454 
455  err = nl_data_append(u->cu_selector, NULL, sizeof(struct tc_u32_key));
456  if(err < 0)
457  return err;
458 
459  sel = u32_selector(u);
460 
461  sel->flags |= TC_U32_TERMINAL;
462  return 0;
463 }
464 
465 int rtnl_u32_add_action(struct rtnl_cls *cls, struct rtnl_act *act)
466 {
467  struct rtnl_u32 *u;
468 
469  if (!act)
470  return 0;
471 
472  if (!(u = rtnl_tc_data(TC_CAST(cls))))
473  return -NLE_NOMEM;
474 
475  u->cu_mask |= U32_ATTR_ACTION;
476  /* In case user frees it */
477  rtnl_act_get(act);
478  return rtnl_act_append(&u->cu_act, act);
479 }
480 
481 int rtnl_u32_del_action(struct rtnl_cls *cls, struct rtnl_act *act)
482 {
483  struct rtnl_u32 *u;
484  int ret;
485 
486  if (!act)
487  return 0;
488 
489  if (!(u = rtnl_tc_data(TC_CAST(cls))))
490  return -NLE_NOMEM;
491 
492  if (!(u->cu_mask & U32_ATTR_ACTION))
493  return -NLE_INVAL;
494 
495  ret = rtnl_act_remove(&u->cu_act, act);
496  if (ret)
497  return ret;
498 
499  if (!u->cu_act)
500  u->cu_mask &= ~U32_ATTR_ACTION;
501  rtnl_act_put(act);
502  return 0;
503 }
504 /** @} */
505 
506 /**
507  * @name Selector Modifications
508  * @{
509  */
510 
511 int rtnl_u32_set_flags(struct rtnl_cls *cls, int flags)
512 {
513  struct tc_u32_sel *sel;
514  struct rtnl_u32 *u;
515 
516  if (!(u = rtnl_tc_data(TC_CAST(cls))))
517  return -NLE_NOMEM;
518 
519  sel = u32_selector_alloc(u);
520  if (!sel)
521  return -NLE_NOMEM;
522 
523  sel->flags |= flags;
524  u->cu_mask |= U32_ATTR_SELECTOR;
525 
526  return 0;
527 }
528 
529 /**
530  * Append new 32-bit key to the selector
531  *
532  * @arg cls classifier to be modifier
533  * @arg val value to be matched (network byte-order)
534  * @arg mask mask to be applied before matching (network byte-order)
535  * @arg off offset, in bytes, to start matching
536  * @arg offmask offset mask
537  *
538  * General selectors define the pattern, mask and offset the pattern will be
539  * matched to the packet contents. Using the general selectors you can match
540  * virtually any single bit in the IP (or upper layer) header.
541  *
542 */
543 int rtnl_u32_add_key(struct rtnl_cls *cls, uint32_t val, uint32_t mask,
544  int off, int offmask)
545 {
546  struct tc_u32_sel *sel;
547  struct rtnl_u32 *u;
548  int err;
549 
550  if (!(u = rtnl_tc_data(TC_CAST(cls))))
551  return -NLE_NOMEM;
552 
553  sel = u32_selector_alloc(u);
554  if (!sel)
555  return -NLE_NOMEM;
556 
557  err = nl_data_append(u->cu_selector, NULL, sizeof(struct tc_u32_key));
558  if (err < 0)
559  return err;
560 
561  /* the selector might have been moved by realloc */
562  sel = u32_selector(u);
563 
564  sel->keys[sel->nkeys].mask = mask;
565  sel->keys[sel->nkeys].val = val & mask;
566  sel->keys[sel->nkeys].off = off;
567  sel->keys[sel->nkeys].offmask = offmask;
568  sel->nkeys++;
569  u->cu_mask |= U32_ATTR_SELECTOR;
570 
571  return 0;
572 }
573 
574 /**
575  * Get the 32-bit key from the selector
576  *
577  * @arg cls classifier to be retrieve
578  * @arg index the index of the array of keys, start with 0
579  * @arg val pointer to store value after masked (network byte-order)
580  * @arg mask pointer to store the mask (network byte-order)
581  * @arg off pointer to store the offset
582  * @arg offmask pointer to store offset mask
583  *
584 */
585 int rtnl_u32_get_key(struct rtnl_cls *cls, uint8_t index,
586  uint32_t *val, uint32_t *mask, int *off, int *offmask)
587 {
588  struct tc_u32_sel *sel;
589  struct rtnl_u32 *u;
590 
591  if (!(u = rtnl_tc_data(TC_CAST(cls))))
592  return -NLE_NOMEM;
593 
594  if (!(u->cu_mask & U32_ATTR_SELECTOR))
595  return -NLE_INVAL;
596 
597  /* the selector might have been moved by realloc */
598  sel = u32_selector(u);
599  if (index >= sel->nkeys)
600  return -NLE_RANGE;
601 
602  *mask = sel->keys[index].mask;
603  *val = sel->keys[index].val;
604  *off = sel->keys[index].off;
605  *offmask = sel->keys[index].offmask;
606  return 0;
607 }
608 
609 
610 int rtnl_u32_add_key_uint8(struct rtnl_cls *cls, uint8_t val, uint8_t mask,
611  int off, int offmask)
612 {
613  int shift = 24 - 8 * (off & 3);
614 
615  return rtnl_u32_add_key(cls, htonl((uint32_t)val << shift),
616  htonl((uint32_t)mask << shift),
617  off & ~3, offmask);
618 }
619 
620 /**
621  * Append new selector key to match a 16-bit number
622  *
623  * @arg cls classifier to be modified
624  * @arg val value to be matched (host byte-order)
625  * @arg mask mask to be applied before matching (host byte-order)
626  * @arg off offset, in bytes, to start matching
627  * @arg offmask offset mask
628 */
629 int rtnl_u32_add_key_uint16(struct rtnl_cls *cls, uint16_t val, uint16_t mask,
630  int off, int offmask)
631 {
632  int shift = ((off & 3) == 0 ? 16 : 0);
633  if (off % 2)
634  return -NLE_INVAL;
635 
636  return rtnl_u32_add_key(cls, htonl((uint32_t)val << shift),
637  htonl((uint32_t)mask << shift),
638  off & ~3, offmask);
639 }
640 
641 /**
642  * Append new selector key to match a 32-bit number
643  *
644  * @arg cls classifier to be modified
645  * @arg val value to be matched (host byte-order)
646  * @arg mask mask to be applied before matching (host byte-order)
647  * @arg off offset, in bytes, to start matching
648  * @arg offmask offset mask
649 */
650 int rtnl_u32_add_key_uint32(struct rtnl_cls *cls, uint32_t val, uint32_t mask,
651  int off, int offmask)
652 {
653  return rtnl_u32_add_key(cls, htonl(val), htonl(mask),
654  off & ~3, offmask);
655 }
656 
657 int rtnl_u32_add_key_in_addr(struct rtnl_cls *cls, const struct in_addr *addr,
658  uint8_t bitmask, int off, int offmask)
659 {
660  uint32_t mask = 0xFFFFFFFF << (32 - bitmask);
661  return rtnl_u32_add_key(cls, addr->s_addr, htonl(mask), off, offmask);
662 }
663 
664 int rtnl_u32_add_key_in6_addr(struct rtnl_cls *cls, const struct in6_addr *addr,
665  uint8_t bitmask, int off, int offmask)
666 {
667  int i, err;
668 
669  for (i = 1; i <= 4; i++) {
670  if (32 * i - bitmask <= 0) {
671  if ((err = rtnl_u32_add_key(cls, addr->s6_addr32[i-1],
672  0xFFFFFFFF, off+4*(i-1), offmask)) < 0)
673  return err;
674  }
675  else if (32 * i - bitmask < 32) {
676  uint32_t mask = 0xFFFFFFFF << (32 * i - bitmask);
677  if ((err = rtnl_u32_add_key(cls, addr->s6_addr32[i-1],
678  htonl(mask), off+4*(i-1), offmask)) < 0)
679  return err;
680  }
681  /* otherwise, if (32*i - bitmask >= 32) no key is generated */
682  }
683 
684  return 0;
685 }
686 
687 /** @} */
688 
689 static struct rtnl_tc_ops u32_ops = {
690  .to_kind = "u32",
691  .to_type = RTNL_TC_TYPE_CLS,
692  .to_size = sizeof(struct rtnl_u32),
693  .to_msg_parser = u32_msg_parser,
694  .to_free_data = u32_free_data,
695  .to_clone = u32_clone,
696  .to_msg_fill = u32_msg_fill,
697  .to_dump = {
698  [NL_DUMP_LINE] = u32_dump_line,
699  [NL_DUMP_DETAILS] = u32_dump_details,
700  [NL_DUMP_STATS] = u32_dump_stats,
701  },
702 };
703 
704 static void __init u32_init(void)
705 {
706  rtnl_tc_register(&u32_ops);
707 }
708 
709 static void __exit u32_exit(void)
710 {
711  rtnl_tc_unregister(&u32_ops);
712 }
713 
714 /** @} */
Dump object briefly on one line.
Definition: types.h:22
int rtnl_tc_register(struct rtnl_tc_ops *ops)
Register a traffic control module.
Definition: tc.c:958
struct nl_data * nl_data_alloc_attr(struct nlattr *nla)
Allocate abstract data object based on netlink attribute.
Definition: data.c:84
struct nl_data * nl_data_clone(struct nl_data *src)
Clone an abstract data object.
Definition: data.c:95
Attribute validation policy.
Definition: attr.h:60
#define NLA_PUT_DATA(msg, attrtype, data)
Add abstract data attribute to netlink message.
Definition: attr.h:243
enum nl_dump_type dp_type
Specifies the type of dump that is requested.
Definition: types.h:38
int rtnl_u32_add_key_uint32(struct rtnl_cls *cls, uint32_t val, uint32_t mask, int off, int offmask)
Append new selector key to match a 32-bit number.
Definition: u32.c:650
int rtnl_u32_add_key(struct rtnl_cls *cls, uint32_t val, uint32_t mask, int off, int offmask)
Append new 32-bit key to the selector.
Definition: u32.c:543
int nl_data_append(struct nl_data *data, void *buf, size_t size)
Append data to an abstract data object.
Definition: data.c:111
NUL terminated character string.
Definition: attr.h:43
Dump all attributes but no statistics.
Definition: types.h:23
void rtnl_tc_unregister(struct rtnl_tc_ops *ops)
Unregister a traffic control module.
Definition: tc.c:992
int rtnl_u32_get_key(struct rtnl_cls *cls, uint8_t index, uint32_t *val, uint32_t *mask, int *off, int *offmask)
Get the 32-bit key from the selector.
Definition: u32.c:585
#define TC_CAST(ptr)
Macro to cast qdisc/class/classifier to tc object.
Definition: tc.h:56
int rtnl_u32_add_key_uint16(struct rtnl_cls *cls, uint16_t val, uint16_t mask, int off, int offmask)
Append new selector key to match a 16-bit number.
Definition: u32.c:629
#define NLA_PUT_U32(msg, attrtype, value)
Add 32 bit integer attribute to netlink message.
Definition: attr.h:189
int nla_len(const struct nlattr *nla)
Return length of the payload .
Definition: attr.c:131
void rtnl_tc_set_handle(struct rtnl_tc *tc, uint32_t id)
Set identifier of traffic control object.
Definition: tc.c:473
struct nl_data * nl_data_alloc(void *buf, size_t size)
Allocate a new abstract data object.
Definition: data.c:50
void * rtnl_tc_data(struct rtnl_tc *tc)
Return pointer to private data of traffic control object.
Definition: tc.c:1006
#define NLA_PUT_STRING(msg, attrtype, value)
Add string attribute to netlink message.
Definition: attr.h:207
uint16_t type
Type of attribute or NLA_UNSPEC.
Definition: attr.h:62
32 bit integer
Definition: attr.h:41
char * rtnl_tc_handle2str(uint32_t handle, char *buf, size_t len)
Convert a traffic control handle to a character string (Reentrant).
Definition: classid.c:109
Dumping parameters.
Definition: types.h:33
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Definition: utils.c:915
uint32_t nla_get_u32(struct nlattr *nla)
Return payload of 32 bit integer attribute.
Definition: attr.c:624
Dump all attributes including statistics.
Definition: types.h:24
size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize)
Copy string attribute payload to a buffer.
Definition: attr.c:378
void nl_data_free(struct nl_data *data)
Free an abstract data object.
Definition: data.c:133