libnl 3.8.0
act.c
1/* SPDX-License-Identifier: LGPL-2.1-only */
2/*
3 * Copyright (c) 2013 Cong Wang <xiyou.wangcong@gmail.com>
4 */
5
6/**
7 * @ingroup tc
8 * @defgroup act Action
9 * @{
10 */
11
12#include "nl-default.h"
13
14#include <linux/gen_stats.h>
15
16#include <netlink/netlink.h>
17#include <netlink/utils.h>
18#include <netlink/route/link.h>
19#include <netlink/route/action.h>
20
21#include "nl-route.h"
22#include "tc-api.h"
23#include "nl-priv-dynamic-core/object-api.h"
24#include "nl-priv-dynamic-core/cache-api.h"
25
26static struct nl_object_ops act_obj_ops;
27static struct nl_cache_ops rtnl_act_ops;
28
29struct rtnl_act * rtnl_act_next(struct rtnl_act *act)
30{
31 if (act == NULL) {
32 return NULL;
33 }
34
35 return act->a_next;
36}
37
38int rtnl_act_append(struct rtnl_act **head, struct rtnl_act *new)
39{
40 struct rtnl_act *p_act;
41 int count = 1;
42
43 if (*head == NULL) {
44 *head = new;
45 return 0;
46 }
47
48 p_act = *head;
49 while (p_act->a_next) {
50 ++count;
51 p_act = p_act->a_next;
52 }
53
54 if (count > TCA_ACT_MAX_PRIO)
55 return -NLE_RANGE;
56
57 p_act->a_next = new;
58 return 0;
59}
60
61int rtnl_act_remove(struct rtnl_act **head, struct rtnl_act *act)
62{
63 struct rtnl_act *a, **ap;
64
65 for (ap = head; (a = *ap) != NULL; ap = &a->a_next)
66 if (a == act)
67 break;
68 if (a) {
69 *ap = a->a_next;
70 a->a_next = NULL;
71 return 0;
72 }
73
74 return -NLE_OBJ_NOTFOUND;
75}
76
77static int rtnl_act_fill_one(struct nl_msg *msg, struct rtnl_act *act, int order)
78{
79 struct rtnl_tc *tc = TC_CAST(act);
80 struct rtnl_tc_ops *ops;
81 struct nlattr *nest;
82 int err = -NLE_NOMEM;
83
84 nest = nla_nest_start(msg, order);
85 if (!nest)
86 goto nla_put_failure;
87
88 if (tc->ce_mask & TCA_ATTR_KIND)
89 NLA_PUT_STRING(msg, TCA_ACT_KIND, tc->tc_kind);
90
91 ops = rtnl_tc_get_ops(tc);
92 if (ops && (ops->to_msg_fill || ops->to_msg_fill_raw)) {
93 struct nlattr *opts;
94 void *data = rtnl_tc_data(tc);
95
96 if (ops->to_msg_fill) {
97 if (!(opts = nla_nest_start(msg, TCA_ACT_OPTIONS)))
98 goto nla_put_failure;
99
100 if ((err = ops->to_msg_fill(tc, data, msg)) < 0)
101 goto nla_put_failure;
102
103 nla_nest_end(msg, opts);
104 } else if ((err = ops->to_msg_fill_raw(tc, data, msg)) < 0)
105 goto nla_put_failure;
106 }
107 nla_nest_end(msg, nest);
108 return 0;
109
110nla_put_failure:
111 return err;
112}
113
114int rtnl_act_fill(struct nl_msg *msg, int attrtype, struct rtnl_act *act)
115{
116 struct rtnl_act *p_act = act;
117 struct nlattr *nest;
118 int err, order = 0;
119
120 nest = nla_nest_start(msg, attrtype);
121 if (!nest)
122 return -NLE_MSGSIZE;
123
124 while (p_act) {
125 err = rtnl_act_fill_one(msg, p_act, ++order);
126 if (err < 0)
127 return err;
128 p_act = p_act->a_next;
129 }
130
131 nla_nest_end(msg, nest);
132 return 0;
133}
134
135static int rtnl_act_msg_build(struct rtnl_act *act, int type, int flags,
136 struct nl_msg **result)
137{
138 struct nl_msg *msg;
139 struct tcamsg tcahdr = {
140 .tca_family = AF_UNSPEC,
141 };
142 int err = -NLE_MSGSIZE;
143
144 msg = nlmsg_alloc_simple(type, flags);
145 if (!msg)
146 return -NLE_NOMEM;
147
148 if (nlmsg_append(msg, &tcahdr, sizeof(tcahdr), NLMSG_ALIGNTO) < 0)
149 goto nla_put_failure;
150
151 err = rtnl_act_fill(msg, TCA_ACT_TAB, act);
152 if (err < 0)
153 goto nla_put_failure;
154
155 *result = msg;
156 return 0;
157
158nla_put_failure:
159 nlmsg_free(msg);
160 return err;
161}
162
163static int act_build(struct rtnl_act *act, int type, int flags,
164 struct nl_msg **result)
165{
166 int err;
167
168 err = rtnl_act_msg_build(act, type, flags, result);
169 if (err < 0)
170 return err;
171 return 0;
172}
173
174/**
175 * @name Allocation/Freeing
176 * @{
177 */
178
179struct rtnl_act *rtnl_act_alloc(void)
180{
181 struct rtnl_tc *tc;
182
183 tc = TC_CAST(nl_object_alloc(&act_obj_ops));
184 if (tc)
185 tc->tc_type = RTNL_TC_TYPE_ACT;
186
187 return (struct rtnl_act *) tc;
188}
189
190void rtnl_act_get(struct rtnl_act *act)
191{
192 nl_object_get(OBJ_CAST(act));
193}
194
195void rtnl_act_put(struct rtnl_act *act)
196{
197 nl_object_put((struct nl_object *) act);
198}
199
200/** @} */
201
202/**
203 * @name Addition/Modification/Deletion
204 * @{
205 */
206
207/**
208 * Build a netlink message requesting the addition of an action
209 * @arg act Action to add
210 * @arg flags Additional netlink message flags
211 * @arg result Pointer to store resulting netlink message
212 *
213 * The behaviour of this function is identical to rtnl_act_add() with
214 * the exception that it will not send the message but return it int the
215 * provided return pointer instead.
216 *
217 * @see rtnl_act_add()
218 *
219 * @return 0 on success or a negative error code.
220 */
221int rtnl_act_build_add_request(struct rtnl_act *act, int flags,
222 struct nl_msg **result)
223{
224 return act_build(act, RTM_NEWACTION, flags, result);
225}
226
227/**
228 * Add/Update action
229 * @arg sk Netlink socket
230 * @arg act Action to add/update
231 * @arg flags Additional netlink message flags
232 *
233 * Builds a \c RTM_NEWACTION netlink message requesting the addition
234 * of a new action and sends the message to the kernel. The
235 * configuration of the action is derived from the attributes of
236 * the specified traffic class.
237 *
238 * The following flags may be specified:
239 * - \c NLM_F_CREATE: Create action if it does not exist,
240 * otherwise -NLE_OBJ_NOTFOUND is returned.
241 * - \c NLM_F_EXCL: Return -NLE_EXISTS if an action with
242 * matching handle exists already.
243 *
244 * Existing actions with matching handles will be updated, unless
245 * the flag \c NLM_F_EXCL is specified. If no matching action
246 * exists, it will be created if the flag \c NLM_F_CREATE is set,
247 * otherwise the error -NLE_OBJ_NOTFOUND is returned.
248 *
249 * After sending, the function will wait for the ACK or an eventual
250 * error message to be received and will therefore block until the
251 * operation has been completed.
252 *
253 * @note Disabling auto-ack (nl_socket_disable_auto_ack()) will cause
254 * this function to return immediately after sending. In this case,
255 * it is the responsibility of the caller to handle any error
256 * messages returned.
257 *
258 * @return 0 on success or a negative error code.
259 */
260int rtnl_act_add(struct nl_sock *sk, struct rtnl_act *act, int flags)
261{
262 struct nl_msg *msg;
263 int err;
264
265 if ((err = rtnl_act_build_add_request(act, flags, &msg)) < 0)
266 return err;
267
268 return nl_send_sync(sk, msg);
269}
270
271/**
272 * Build a netlink message to change action attributes
273 * @arg act Action to change
274 * @arg flags additional netlink message flags
275 * @arg result Pointer to store resulting message.
276 *
277 * Builds a new netlink message requesting a change of a neigh
278 * attributes. The netlink message header isn't fully equipped with
279 * all relevant fields and must thus be sent out via nl_send_auto_complete()
280 * or supplemented as needed.
281 *
282 * @return 0 on success or a negative error code.
283 */
284int rtnl_act_build_change_request(struct rtnl_act *act, int flags,
285 struct nl_msg **result)
286{
287 return act_build(act, RTM_NEWACTION, NLM_F_REPLACE | flags, result);
288}
289
290/**
291 * Change an action
292 * @arg sk Netlink socket.
293 * @arg act action to change
294 * @arg flags additional netlink message flags
295 *
296 * Builds a netlink message by calling rtnl_act_build_change_request(),
297 * sends the request to the kernel and waits for the next ACK to be
298 * received and thus blocks until the request has been processed.
299 *
300 * @return 0 on success or a negative error if an error occured.
301 */
302int rtnl_act_change(struct nl_sock *sk, struct rtnl_act *act, int flags)
303{
304 struct nl_msg *msg;
305 int err;
306
307 if ((err = rtnl_act_build_change_request(act, flags, &msg)) < 0)
308 return err;
309
310 return nl_send_sync(sk, msg);
311}
312
313/**
314 * Build netlink message requesting the deletion of an action
315 * @arg act Action to delete
316 * @arg flags Additional netlink message flags
317 * @arg result Pointer to store resulting netlink message
318 *
319 * The behaviour of this function is identical to rtnl_act_delete() with
320 * the exception that it will not send the message but return it in the
321 * provided return pointer instead.
322 *
323 * @see rtnl_act_delete()
324 *
325 * @return 0 on success or a negative error code.
326 */
327int rtnl_act_build_delete_request(struct rtnl_act *act, int flags,
328 struct nl_msg **result)
329{
330 return act_build(act, RTM_DELACTION, flags, result);
331}
332
333/**
334 * Delete action
335 * @arg sk Netlink socket
336 * @arg act Action to delete
337 * @arg flags Additional netlink message flags
338 *
339 * Builds a \c RTM_DELACTION netlink message requesting the deletion
340 * of an action and sends the message to the kernel.
341 *
342 * The message is constructed out of the following attributes:
343 * - \c ifindex (required)
344 * - \c prio (required)
345 * - \c protocol (required)
346 * - \c handle (required)
347 * - \c parent (optional, if not specified parent equals root-qdisc)
348 * - \c kind (optional, must match if provided)
349 *
350 * All other action attributes including all class type specific
351 * attributes are ignored.
352 *
353 * After sending, the function will wait for the ACK or an eventual
354 * error message to be received and will therefore block until the
355 * operation has been completed.
356 *
357 * @note Disabling auto-ack (nl_socket_disable_auto_ack()) will cause
358 * this function to return immediately after sending. In this case,
359 * it is the responsibility of the caller to handle any error
360 * messages returned.
361 *
362 * @return 0 on success or a negative error code.
363 */
364int rtnl_act_delete(struct nl_sock *sk, struct rtnl_act *act, int flags)
365{
366 struct nl_msg *msg;
367 int err;
368
369 if ((err = rtnl_act_build_delete_request(act, flags, &msg)) < 0)
370 return err;
371
372 return nl_send_sync(sk, msg);
373}
374
375/** @} */
376
377static void act_dump_line(struct rtnl_tc *tc, struct nl_dump_params *p)
378{
379}
380
381void rtnl_act_put_all(struct rtnl_act **head)
382{
383 struct rtnl_act *curr, *next;
384
385 curr = *head;
386 while (curr) {
387 next = curr->a_next;
388 rtnl_act_put(curr);
389 curr = next;
390 }
391 *head = NULL;
392}
393
394static struct nla_policy tc_act_stats_policy[TCA_STATS_MAX+1] = {
395 [TCA_STATS_BASIC] = { .minlen = sizeof(struct gnet_stats_basic) },
396 [TCA_STATS_QUEUE] = { .minlen = sizeof(struct gnet_stats_queue) },
397 [TCA_STATS_RATE_EST] = { .minlen = sizeof(struct gnet_stats_rate_est) },
398 [TCA_STATS_RATE_EST64] = { .minlen = sizeof(struct gnet_stats_rate_est64) },
399};
400
401int rtnl_act_parse(struct rtnl_act **head, struct nlattr *tb)
402{
403 struct rtnl_act *act;
404 struct rtnl_tc_ops *ops;
405 struct nlattr *tb2[TCA_ACT_MAX + 1];
406 struct nlattr *nla[TCA_ACT_MAX_PRIO + 1];
407 char kind[TCKINDSIZ];
408 int err, i;
409
410 err = nla_parse(nla, TCA_ACT_MAX_PRIO, nla_data(tb),
411 NLMSG_ALIGN(nla_len(tb)), NULL);
412 if (err < 0)
413 return err;
414
415 for (i = 0; i < TCA_ACT_MAX_PRIO; i++) {
416 struct rtnl_tc *tc;
417
418 if (nla[i] == NULL)
419 continue;
420
421 act = rtnl_act_alloc();
422 if (!act) {
423 err = -NLE_NOMEM;
424 goto err_free;
425 }
426 tc = TC_CAST(act);
427 err = nla_parse(tb2, TCA_ACT_MAX, nla_data(nla[i]),
428 nla_len(nla[i]), NULL);
429 if (err < 0)
430 goto err_free;
431
432 if (tb2[TCA_ACT_KIND] == NULL) {
433 err = -NLE_MISSING_ATTR;
434 goto err_free;
435 }
436
437 nla_strlcpy(kind, tb2[TCA_ACT_KIND], sizeof(kind));
438 rtnl_tc_set_kind(tc, kind);
439
440 if (tb2[TCA_ACT_OPTIONS]) {
441 tc->tc_opts = nl_data_alloc_attr(tb2[TCA_ACT_OPTIONS]);
442 if (!tc->tc_opts) {
443 err = -NLE_NOMEM;
444 goto err_free;
445 }
446 tc->ce_mask |= TCA_ATTR_OPTS;
447 }
448
449 if (tb2[TCA_ACT_STATS]) {
450 struct nlattr *tb3[TCA_STATS_MAX + 1];
451
452 err = nla_parse_nested(tb3, TCA_STATS_MAX, tb2[TCA_ACT_STATS],
453 tc_act_stats_policy);
454 if (err < 0)
455 return err;
456
457 if (tb3[TCA_STATS_BASIC]) {
458 struct gnet_stats_basic bs;
459
460 memcpy(&bs, nla_data(tb3[TCA_STATS_BASIC]),
461 sizeof(bs));
462 tc->tc_stats[RTNL_TC_BYTES] = bs.bytes;
463 tc->tc_stats[RTNL_TC_PACKETS] = bs.packets;
464 }
465 if (tb3[TCA_STATS_RATE_EST64]) {
466 struct gnet_stats_rate_est64 re;
467
468 memcpy(&re, nla_data(tb3[TCA_STATS_RATE_EST64]),
469 sizeof(re));
470 tc->tc_stats[RTNL_TC_RATE_BPS] = re.bps;
471 tc->tc_stats[RTNL_TC_RATE_PPS] = re.pps;
472 } else if (tb3[TCA_STATS_RATE_EST]) {
473 struct gnet_stats_rate_est *re;
474
475 re = nla_data(tb3[TCA_STATS_RATE_EST]);
476 tc->tc_stats[RTNL_TC_RATE_BPS] = re->bps;
477 tc->tc_stats[RTNL_TC_RATE_PPS] = re->pps;
478 }
479 if (tb3[TCA_STATS_QUEUE]) {
480 struct gnet_stats_queue *q;
481
482 q = nla_data(tb3[TCA_STATS_QUEUE]);
483 tc->tc_stats[RTNL_TC_DROPS] = q->drops;
484 tc->tc_stats[RTNL_TC_OVERLIMITS] = q->overlimits;
485 }
486 }
487
488 ops = rtnl_tc_get_ops(tc);
489 if (ops && ops->to_msg_parser) {
490 void *data = rtnl_tc_data(tc);
491
492 if (!data) {
493 err = -NLE_NOMEM;
494 goto err_free;
495 }
496
497 err = ops->to_msg_parser(tc, data);
498 if (err < 0)
499 goto err_free;
500 }
501 err = rtnl_act_append(head, act);
502 if (err < 0)
503 goto err_free;
504 }
505 return 0;
506
507err_free:
508 rtnl_act_put (act);
509 rtnl_act_put_all(head);
510
511 return err;
512}
513
514static int rtnl_act_msg_parse(struct nlmsghdr *n, struct rtnl_act **act)
515{
516 struct rtnl_tc *tc = TC_CAST(*act);
517 struct nl_cache *link_cache;
518 struct nlattr *tb[TCAA_MAX + 1];
519 struct tcamsg *tm;
520 int err;
521
522 tc->ce_msgtype = n->nlmsg_type;
523
524 err = nlmsg_parse(n, sizeof(*tm), tb, TCAA_MAX, NULL);
525 if (err < 0)
526 return err;
527
528 tm = nlmsg_data(n);
529 tc->tc_family = tm->tca_family;
530
531 if (tb[TCA_ACT_TAB] == NULL)
532 return -NLE_MISSING_ATTR;
533
534 err = rtnl_act_parse(act, tb[TCA_ACT_TAB]);
535 if (err < 0)
536 return err;
537
538 if ((link_cache = __nl_cache_mngt_require("route/link"))) {
539 struct rtnl_link *link;
540
541 if ((link = rtnl_link_get(link_cache, tc->tc_ifindex))) {
542 rtnl_tc_set_link(tc, link);
543
544 /* rtnl_tc_set_link incs refcnt */
545 rtnl_link_put(link);
546 }
547 }
548
549 return 0;
550}
551static int act_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
552 struct nlmsghdr *nlh, struct nl_parser_param *pp)
553{
554 struct rtnl_act *act, *p_act;
555 int err;
556
557 if (!(act = rtnl_act_alloc()))
558 return -NLE_NOMEM;
559
560 if ((err = rtnl_act_msg_parse(nlh, &act)) < 0)
561 goto errout;
562
563 p_act = act;
564 while(p_act) {
565 err = pp->pp_cb(OBJ_CAST(act), pp);
566 if (err) {
567 if (err > 0) {
568 _nl_assert_not_reached();
569 err = -NLE_FAILURE;
570 }
571 break;
572 }
573 p_act = p_act->a_next;
574 }
575errout:
576 rtnl_act_put(act);
577
578 return err;
579}
580
581static int act_request_update(struct nl_cache *cache, struct nl_sock *sk)
582{
583 struct tcamsg tcahdr = {
584 .tca_family = AF_UNSPEC,
585 };
586
587 return nl_send_simple(sk, RTM_GETACTION, NLM_F_DUMP, &tcahdr,
588 sizeof(tcahdr));
589}
590
591static struct rtnl_tc_type_ops act_ops = {
592 .tt_type = RTNL_TC_TYPE_ACT,
593 .tt_dump_prefix = "act",
594 .tt_dump = {
595 [NL_DUMP_LINE] = act_dump_line,
596 },
597};
598
599static struct nl_cache_ops rtnl_act_ops = {
600 .co_name = "route/act",
601 .co_hdrsize = sizeof(struct tcmsg),
602 .co_msgtypes = {
603 { RTM_NEWACTION, NL_ACT_NEW, "new" },
604 { RTM_DELACTION, NL_ACT_DEL, "del" },
605 { RTM_GETACTION, NL_ACT_GET, "get" },
606 END_OF_MSGTYPES_LIST,
607 },
608 .co_protocol = NETLINK_ROUTE,
609 .co_request_update = act_request_update,
610 .co_msg_parser = act_msg_parser,
611 .co_obj_ops = &act_obj_ops,
612};
613
614static struct nl_object_ops act_obj_ops = {
615 .oo_name = "route/act",
616 .oo_size = sizeof(struct rtnl_act),
617 .oo_free_data = rtnl_tc_free_data,
618 .oo_clone = rtnl_tc_clone,
619 .oo_dump = {
620 [NL_DUMP_LINE] = rtnl_tc_dump_line,
621 [NL_DUMP_DETAILS] = rtnl_tc_dump_details,
622 [NL_DUMP_STATS] = rtnl_tc_dump_stats,
623 },
624 .oo_compare = rtnl_tc_compare,
625 .oo_id_attrs = (TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE),
626};
627
628static void _nl_init act_init(void)
629{
630 rtnl_tc_type_register(&act_ops);
631 nl_cache_mngt_register(&rtnl_act_ops);
632}
633
634static void _nl_exit act_exit(void)
635{
636 nl_cache_mngt_unregister(&rtnl_act_ops);
637 rtnl_tc_type_unregister(&act_ops);
638}
639
640/** @} */
int rtnl_act_change(struct nl_sock *sk, struct rtnl_act *act, int flags)
Change an action.
Definition: act.c:302
int rtnl_act_build_delete_request(struct rtnl_act *act, int flags, struct nl_msg **result)
Build netlink message requesting the deletion of an action.
Definition: act.c:327
int rtnl_act_build_add_request(struct rtnl_act *act, int flags, struct nl_msg **result)
Build a netlink message requesting the addition of an action.
Definition: act.c:221
int rtnl_act_delete(struct nl_sock *sk, struct rtnl_act *act, int flags)
Delete action.
Definition: act.c:364
int rtnl_act_add(struct nl_sock *sk, struct rtnl_act *act, int flags)
Add/Update action.
Definition: act.c:260
int rtnl_act_build_change_request(struct rtnl_act *act, int flags, struct nl_msg **result)
Build a netlink message to change action attributes.
Definition: act.c:284
int nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len, const struct nla_policy *policy)
Create attribute index based on a stream of attributes.
Definition: attr.c:241
void * nla_data(const struct nlattr *nla)
Return pointer to the payload section.
Definition: attr.c:119
struct nlattr * nla_nest_start(struct nl_msg *msg, int attrtype)
Start a new level of nested attributes.
Definition: attr.c:906
size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize)
Copy string attribute payload to a buffer.
Definition: attr.c:379
int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, const struct nla_policy *policy)
Create attribute index based on nested attribute.
Definition: attr.c:1033
int nla_len(const struct nlattr *nla)
Return length of the payload .
Definition: attr.c:130
#define NLA_PUT_STRING(msg, attrtype, value)
Add string attribute to netlink message.
Definition: attr.h:257
int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
Finalize nesting of attributes.
Definition: attr.c:969
int nl_cache_mngt_unregister(struct nl_cache_ops *ops)
Unregister a set of cache operations.
Definition: cache_mngt.c:287
int nl_cache_mngt_register(struct nl_cache_ops *ops)
Register a set of cache operations.
Definition: cache_mngt.c:252
struct nl_data * nl_data_alloc_attr(const struct nlattr *nla)
Allocate abstract data object based on netlink attribute.
Definition: data.c:84
struct nl_msg * nlmsg_alloc_simple(int nlmsgtype, int flags)
Allocate a new netlink message.
Definition: msg.c:349
void * nlmsg_data(const struct nlmsghdr *nlh)
Return pointer to message payload.
Definition: msg.c:108
void nlmsg_free(struct nl_msg *msg)
Release a reference from an netlink message.
Definition: msg.c:566
int nlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], int maxtype, const struct nla_policy *policy)
parse attributes of a netlink message
Definition: msg.c:216
int nlmsg_append(struct nl_msg *n, void *data, size_t len, int pad)
Append data to tail of a netlink message.
Definition: msg.c:450
void nl_object_put(struct nl_object *obj)
Release a reference from an object.
Definition: object.c:221
void nl_object_get(struct nl_object *obj)
Acquire a reference on a object.
Definition: object.c:210
struct nl_object * nl_object_alloc(struct nl_object_ops *ops)
Allocate a new object of kind specified by the operations handle.
Definition: object.c:55
int nl_send_sync(struct nl_sock *sk, struct nl_msg *msg)
Finalize and transmit Netlink message and wait for ACK or error message.
Definition: nl.c:547
int nl_send_simple(struct nl_sock *sk, int type, int flags, void *buf, size_t size)
Construct and transmit a Netlink message.
Definition: nl.c:579
int rtnl_tc_set_kind(struct rtnl_tc *tc, const char *kind)
Define the type of traffic control object.
Definition: tc.c:528
void rtnl_tc_set_link(struct rtnl_tc *tc, struct rtnl_link *link)
Set link of traffic control object.
Definition: tc.c:309
#define TC_CAST(ptr)
Macro to cast qdisc/class/classifier to tc object.
Definition: tc.h:50
void * rtnl_tc_data(struct rtnl_tc *)
Return pointer to private data of traffic control object.
Definition: tc.c:1079
@ RTNL_TC_PACKETS
Number of packets seen.
Definition: tc.h:61
@ RTNL_TC_BYTES
Total bytes seen.
Definition: tc.h:62
@ RTNL_TC_OVERLIMITS
Total number of overlimits.
Definition: tc.h:69
@ RTNL_TC_DROPS
Total number of packets dropped.
Definition: tc.h:67
@ RTNL_TC_RATE_PPS
Current packet/s (rate estimator)
Definition: tc.h:64
@ RTNL_TC_RATE_BPS
Current bits/s (rate estimator)
Definition: tc.h:63
@ NL_DUMP_STATS
Dump all attributes including statistics.
Definition: types.h:22
@ NL_DUMP_LINE
Dump object briefly on one line.
Definition: types.h:20
@ NL_DUMP_DETAILS
Dump all attributes but no statistics.
Definition: types.h:21
Dumping parameters.
Definition: types.h:32
Attribute validation policy.
Definition: attr.h:63
uint16_t minlen
Minimal length of payload required.
Definition: attr.h:68