libnl 3.11.0
tc.c
1/* SPDX-License-Identifier: LGPL-2.1-only */
2/*
3 * Copyright (c) 2003-2011 Thomas Graf <tgraf@suug.ch>
4 */
5
6/**
7 * @ingroup rtnl
8 * @defgroup tc Traffic Control
9 * @{
10 */
11
12#include "nl-default.h"
13
14#include <linux/if_arp.h>
15#include <linux/gen_stats.h>
16
17#include <linux/atm.h>
18
19#include <netlink/netlink.h>
20#include <netlink/utils.h>
21#include <netlink/route/rtnl.h>
22#include <netlink/route/link.h>
23#include <netlink/route/tc.h>
24
25#include "tc-api.h"
26
27/** @cond SKIP */
28
29static struct nl_list_head tc_ops_list[__RTNL_TC_TYPE_MAX];
30static struct rtnl_tc_type_ops *tc_type_ops[__RTNL_TC_TYPE_MAX];
31
32static struct nla_policy tc_policy[TCA_MAX+1] = {
33 [TCA_KIND] = { .type = NLA_STRING,
34 .maxlen = TCKINDSIZ },
35 [TCA_CHAIN] = { .type = NLA_U32 },
36 [TCA_STATS] = { .minlen = sizeof(struct tc_stats) },
37 [TCA_STATS2] = { .type = NLA_NESTED },
38};
39
40int tca_parse(struct nlattr **tb, int maxattr, struct rtnl_tc *g,
41 const struct nla_policy *policy)
42{
43
44 if (g->ce_mask & TCA_ATTR_OPTS)
45 return nla_parse(tb, maxattr,
46 (struct nlattr *) g->tc_opts->d_data,
47 g->tc_opts->d_size, policy);
48 else {
49 /* Ugly but tb[] must be in a defined state even if no
50 * attributes can be found. */
51 memset(tb, 0, sizeof(struct nlattr *) * (maxattr + 1));
52 return 0;
53 }
54}
55
56static struct nla_policy tc_stats2_policy[TCA_STATS_MAX+1] = {
57 [TCA_STATS_BASIC] = { .minlen = sizeof(struct gnet_stats_basic) },
58 [TCA_STATS_RATE_EST] = { .minlen = sizeof(struct gnet_stats_rate_est) },
59 [TCA_STATS_QUEUE] = { .minlen = sizeof(struct gnet_stats_queue) },
60};
61
62int rtnl_tc_msg_parse(struct nlmsghdr *n, struct rtnl_tc *tc)
63{
64 struct nl_cache *link_cache;
65 struct rtnl_tc_ops *ops;
66 struct nlattr *tb[TCA_MAX + 1];
67 char kind[TCKINDSIZ];
68 struct tcmsg *tm;
69 int err;
70
71 tc->ce_msgtype = n->nlmsg_type;
72
73 err = nlmsg_parse(n, sizeof(*tm), tb, TCA_MAX, tc_policy);
74 if (err < 0)
75 return err;
76
77 if (tb[TCA_KIND] == NULL)
78 return -NLE_MISSING_ATTR;
79
80 nla_strlcpy(kind, tb[TCA_KIND], sizeof(kind));
81 rtnl_tc_set_kind(tc, kind);
82
83 if (tb[TCA_CHAIN])
84 rtnl_tc_set_chain(tc, nla_get_u32(tb[TCA_CHAIN]));
85
86 tm = nlmsg_data(n);
87 tc->tc_family = tm->tcm_family;
88 tc->tc_ifindex = tm->tcm_ifindex;
89 tc->tc_handle = tm->tcm_handle;
90 tc->tc_parent = tm->tcm_parent;
91 tc->tc_info = tm->tcm_info;
92
93 tc->ce_mask |= (TCA_ATTR_FAMILY | TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE|
94 TCA_ATTR_PARENT | TCA_ATTR_INFO);
95
96 if (tb[TCA_OPTIONS]) {
97 tc->tc_opts = nl_data_alloc_attr(tb[TCA_OPTIONS]);
98 if (!tc->tc_opts)
99 return -NLE_NOMEM;
100 tc->ce_mask |= TCA_ATTR_OPTS;
101 }
102
103 if (tb[TCA_STATS2]) {
104 struct nlattr *tbs[TCA_STATS_MAX + 1];
105
106 err = nla_parse_nested(tbs, TCA_STATS_MAX, tb[TCA_STATS2],
107 tc_stats2_policy);
108 if (err < 0)
109 return err;
110
111 if (tbs[TCA_STATS_BASIC]) {
112 struct gnet_stats_basic bs;
113
114 memcpy(&bs, nla_data(tbs[TCA_STATS_BASIC]), sizeof(bs));
115 tc->tc_stats[RTNL_TC_BYTES] = bs.bytes;
116 tc->tc_stats[RTNL_TC_PACKETS] = bs.packets;
117 }
118
119 if (tbs[TCA_STATS_RATE_EST]) {
120 struct gnet_stats_rate_est *re;
121
122 re = nla_data(tbs[TCA_STATS_RATE_EST]);
123 tc->tc_stats[RTNL_TC_RATE_BPS] = re->bps;
124 tc->tc_stats[RTNL_TC_RATE_PPS] = re->pps;
125 }
126
127 if (tbs[TCA_STATS_QUEUE]) {
128 struct gnet_stats_queue *q;
129
130 q = nla_data(tbs[TCA_STATS_QUEUE]);
131 tc->tc_stats[RTNL_TC_QLEN] = q->qlen;
132 tc->tc_stats[RTNL_TC_BACKLOG] = q->backlog;
133 tc->tc_stats[RTNL_TC_DROPS] = q->drops;
134 tc->tc_stats[RTNL_TC_REQUEUES] = q->requeues;
135 tc->tc_stats[RTNL_TC_OVERLIMITS] = q->overlimits;
136 }
137
138 tc->ce_mask |= TCA_ATTR_STATS;
139
140 if (tbs[TCA_STATS_APP]) {
141 tc->tc_xstats = nl_data_alloc_attr(tbs[TCA_STATS_APP]);
142 if (tc->tc_xstats == NULL)
143 return -NLE_NOMEM;
144 tc->ce_mask |= TCA_ATTR_XSTATS;
145 } else
146 goto compat_xstats;
147 } else {
148 if (tb[TCA_STATS]) {
149 struct tc_stats st;
150
151 memcpy(&st, nla_data(tb[TCA_STATS]), sizeof(st));
152 tc->tc_stats[RTNL_TC_BYTES] = st.bytes;
153 tc->tc_stats[RTNL_TC_PACKETS] = st.packets;
154 tc->tc_stats[RTNL_TC_RATE_BPS] = st.bps;
155 tc->tc_stats[RTNL_TC_RATE_PPS] = st.pps;
156 tc->tc_stats[RTNL_TC_QLEN] = st.qlen;
157 tc->tc_stats[RTNL_TC_BACKLOG] = st.backlog;
158 tc->tc_stats[RTNL_TC_DROPS] = st.drops;
159 tc->tc_stats[RTNL_TC_OVERLIMITS]= st.overlimits;
160
161 tc->ce_mask |= TCA_ATTR_STATS;
162 }
163
164compat_xstats:
165 if (tb[TCA_XSTATS]) {
166 tc->tc_xstats = nl_data_alloc_attr(tb[TCA_XSTATS]);
167 if (tc->tc_xstats == NULL)
168 return -NLE_NOMEM;
169 tc->ce_mask |= TCA_ATTR_XSTATS;
170 }
171 }
172
173 ops = rtnl_tc_get_ops(tc);
174 if (ops && ops->to_msg_parser) {
175 void *data = rtnl_tc_data(tc);
176
177 if (!data)
178 return -NLE_NOMEM;
179
180 err = ops->to_msg_parser(tc, data);
181 if (err < 0)
182 return err;
183 }
184
185 if ((link_cache = __nl_cache_mngt_require("route/link"))) {
186 struct rtnl_link *link;
187
188 if ((link = rtnl_link_get(link_cache, tc->tc_ifindex))) {
189 rtnl_tc_set_link(tc, link);
190
191 /* rtnl_tc_set_link incs refcnt */
192 rtnl_link_put(link);
193 }
194 }
195
196 return 0;
197}
198
199int rtnl_tc_msg_build(struct rtnl_tc *tc, int type, int flags,
200 struct nl_msg **result)
201{
202 struct nl_msg *msg;
203 struct rtnl_tc_ops *ops;
204 struct tcmsg tchdr = {
205 .tcm_family = AF_UNSPEC,
206 .tcm_ifindex = tc->tc_ifindex,
207 .tcm_handle = tc->tc_handle,
208 .tcm_parent = tc->tc_parent,
209 };
210 int err;
211
212 msg = nlmsg_alloc_simple(type, flags);
213 if (!msg)
214 return -NLE_NOMEM;
215
216 if (nlmsg_append(msg, &tchdr, sizeof(tchdr), NLMSG_ALIGNTO) < 0) {
217 err = -NLE_MSGSIZE;
218 goto out_err;
219 }
220
221 if (tc->ce_mask & TCA_ATTR_KIND)
222 NLA_PUT_STRING(msg, TCA_KIND, tc->tc_kind);
223
224 if (tc->ce_mask & TCA_ATTR_CHAIN)
225 NLA_PUT_U32(msg, TCA_CHAIN, tc->tc_chain);
226
227 ops = rtnl_tc_get_ops(tc);
228 if (ops && (ops->to_msg_fill || ops->to_msg_fill_raw)) {
229 struct nlattr *opts;
230 void *data = rtnl_tc_data(tc);
231
232 if (ops->to_msg_fill) {
233 if (!(opts = nla_nest_start(msg, TCA_OPTIONS))) {
234 err = -NLE_NOMEM;
235 goto out_err;
236 }
237
238 if ((err = ops->to_msg_fill(tc, data, msg)) < 0)
239 goto out_err;
240
241 if (strcmp("cgroup", tc->tc_kind))
242 nla_nest_end(msg, opts);
243 else
244 nla_nest_end_keep_empty(msg, opts);
245 } else if ((err = ops->to_msg_fill_raw(tc, data, msg)) < 0)
246 goto out_err;
247 }
248
249 *result = msg;
250 return 0;
251
252nla_put_failure:
253 err = -NLE_NOMEM;
254out_err:
255 nlmsg_free(msg);
256 return err;
257}
258
259
260/** @endcond */
261
262/**
263 * @name Attributes
264 * @{
265 */
266
267/**
268 * Set interface index of traffic control object
269 * @arg tc traffic control object
270 * @arg ifindex interface index.
271 *
272 * Sets the interface index of a traffic control object. The interface
273 * index defines the network device which this tc object is attached to.
274 * This function will overwrite any network device assigned with previous
275 * calls to rtnl_tc_set_ifindex() or rtnl_tc_set_link().
276 */
277void rtnl_tc_set_ifindex(struct rtnl_tc *tc, int ifindex)
278{
279 /* Obsolete possible old link reference */
280 rtnl_link_put(tc->tc_link);
281 tc->tc_link = NULL;
282 tc->ce_mask &= ~TCA_ATTR_LINK;
283
284 tc->tc_ifindex = ifindex;
285 tc->ce_mask |= TCA_ATTR_IFINDEX;
286}
287
288/**
289 * Return interface index of traffic control object
290 * @arg tc traffic control object
291 */
293{
294 return tc->tc_ifindex;
295}
296
297/**
298 * Set link of traffic control object
299 * @arg tc traffic control object
300 * @arg link link object
301 *
302 * Sets the link of a traffic control object. This function serves
303 * the same purpose as rtnl_tc_set_ifindex() but due to the continued
304 * allowed access to the link object it gives it the possibility to
305 * retrieve sane default values for the the MTU and the linktype.
306 * Always prefer this function over rtnl_tc_set_ifindex() if you can
307 * spare to have an additional link object around.
308 */
309void rtnl_tc_set_link(struct rtnl_tc *tc, struct rtnl_link *link)
310{
311 rtnl_link_put(tc->tc_link);
312
313 if (!link)
314 return;
315 if (!link->l_index)
316 BUG();
317
318 nl_object_get(OBJ_CAST(link));
319 tc->tc_link = link;
320 tc->tc_ifindex = link->l_index;
321 tc->ce_mask |= TCA_ATTR_LINK | TCA_ATTR_IFINDEX;
322}
323
324/**
325 * Get link of traffic control object
326 * @arg tc traffic control object
327 *
328 * Returns the link of a traffic control object. The link is only
329 * returned if it has been set before via rtnl_tc_set_link() or
330 * if a link cache was available while parsing the tc object. This
331 * function may still return NULL even if an ifindex is assigned to
332 * the tc object. It will _not_ look up the link by itself.
333 *
334 * @note The returned link will have its reference counter incremented.
335 * It is in the responsibility of the caller to return the
336 * reference.
337 *
338 * @return link object or NULL if not set.
339 */
341{
342 if (tc->tc_link) {
343 nl_object_get(OBJ_CAST(tc->tc_link));
344 return tc->tc_link;
345 }
346
347 return NULL;
348}
349
350/**
351 * Set the Maximum Transmission Unit (MTU) of traffic control object
352 * @arg tc traffic control object
353 * @arg mtu largest packet size expected
354 *
355 * Sets the MTU of a traffic control object. Not all traffic control
356 * objects will make use of this but it helps while calculating rate
357 * tables. This value is typically derived directly from the link
358 * the tc object is attached to if the link has been assigned via
359 * rtnl_tc_set_link(). It is usually not necessary to set the MTU
360 * manually, this function is provided to allow overwriting the derived
361 * value.
362 */
363void rtnl_tc_set_mtu(struct rtnl_tc *tc, uint32_t mtu)
364{
365 tc->tc_mtu = mtu;
366 tc->ce_mask |= TCA_ATTR_MTU;
367}
368
369/**
370 * Return the MTU of traffic control object
371 * @arg tc traffic control object
372 *
373 * Returns the MTU of a traffic control object which has been set via:
374 * -# User specified value set via rtnl_tc_set_mtu()
375 * -# Dervied from link set via rtnl_tc_set_link()
376 * -# Fall back to default: ethernet = 1500
377 */
378uint32_t rtnl_tc_get_mtu(struct rtnl_tc *tc)
379{
380 if (tc->ce_mask & TCA_ATTR_MTU)
381 return tc->tc_mtu;
382 else if (tc->ce_mask & TCA_ATTR_LINK)
383 return tc->tc_link->l_mtu;
384 else
385 return 1500; /* default to ethernet */
386}
387
388/**
389 * Set the Minimum Packet Unit (MPU) of a traffic control object
390 * @arg tc traffic control object
391 * @arg mpu minimum packet size expected
392 *
393 * Sets the MPU of a traffic contorl object. It specifies the minimum
394 * packet size to ever hit this traffic control object. Not all traffic
395 * control objects will make use of this but it helps while calculating
396 * rate tables.
397 */
398void rtnl_tc_set_mpu(struct rtnl_tc *tc, uint32_t mpu)
399{
400 tc->tc_mpu = mpu;
401 tc->ce_mask |= TCA_ATTR_MPU;
402}
403
404/**
405 * Return the Minimum Packet Unit (MPU) of a traffic control object
406 * @arg tc traffic control object
407 *
408 * @return The MPU previously set via rtnl_tc_set_mpu() or 0.
409 */
410uint32_t rtnl_tc_get_mpu(struct rtnl_tc *tc)
411{
412 return tc->tc_mpu;
413}
414
415/**
416 * Set per packet overhead of a traffic control object
417 * @arg tc traffic control object
418 * @arg overhead overhead per packet in bytes
419 *
420 * Sets the per packet overhead in bytes occuring on the link not seen
421 * by the kernel. This value can be used to correct size calculations
422 * if the packet size on the wire does not match the packet sizes seen
423 * in the network stack. Not all traffic control objects will make use
424 * this but it helps while calculating accurate packet sizes in the
425 * kernel.
426 */
427void rtnl_tc_set_overhead(struct rtnl_tc *tc, uint32_t overhead)
428{
429 tc->tc_overhead = overhead;
430 tc->ce_mask |= TCA_ATTR_OVERHEAD;
431}
432
433/**
434 * Return per packet overhead of a traffic control object
435 * @arg tc traffic control object
436 *
437 * @return The overhead previously set by rtnl_tc_set_overhead() or 0.
438 */
439uint32_t rtnl_tc_get_overhead(struct rtnl_tc *tc)
440{
441 return tc->tc_overhead;
442}
443
444/**
445 * Set the linktype of a traffic control object
446 * @arg tc traffic control object
447 * @arg type type of link (e.g. ARPHRD_ATM, ARPHRD_ETHER)
448 *
449 * Overwrites the type of link this traffic control object is attached to.
450 * This value is typically derived from the link this tc object is attached
451 * if the link has been assigned via rtnl_tc_set_link(). It is usually not
452 * necessary to set the linktype manually. This function is provided to
453 * allow overwriting the linktype.
454 */
455void rtnl_tc_set_linktype(struct rtnl_tc *tc, uint32_t type)
456{
457 tc->tc_linktype = type;
458 tc->ce_mask |= TCA_ATTR_LINKTYPE;
459}
460
461/**
462 * Return the linktype of a traffic control object
463 * @arg tc traffic control object
464 *
465 * Returns the linktype of the link the traffic control object is attached to:
466 * -# User specified value via rtnl_tc_set_linktype()
467 * -# Value derived from link set via rtnl_tc_set_link()
468 * -# Default fall-back: ARPHRD_ETHER
469 */
470uint32_t rtnl_tc_get_linktype(struct rtnl_tc *tc)
471{
472 if (tc->ce_mask & TCA_ATTR_LINKTYPE)
473 return tc->tc_linktype;
474 else if (tc->ce_mask & TCA_ATTR_LINK)
475 return tc->tc_link->l_arptype;
476 else
477 return ARPHRD_ETHER; /* default to ethernet */
478}
479
480/**
481 * Set identifier of traffic control object
482 * @arg tc traffic control object
483 * @arg id unique identifier
484 */
485void rtnl_tc_set_handle(struct rtnl_tc *tc, uint32_t id)
486{
487 tc->tc_handle = id;
488 tc->ce_mask |= TCA_ATTR_HANDLE;
489}
490
491/**
492 * Return identifier of a traffic control object
493 * @arg tc traffic control object
494 */
495uint32_t rtnl_tc_get_handle(struct rtnl_tc *tc)
496{
497 return tc->tc_handle;
498}
499
500/**
501 * Set the parent identifier of a traffic control object
502 * @arg tc traffic control object
503 * @arg parent identifier of parent traffif control object
504 *
505 */
506void rtnl_tc_set_parent(struct rtnl_tc *tc, uint32_t parent)
507{
508 tc->tc_parent = parent;
509 tc->ce_mask |= TCA_ATTR_PARENT;
510}
511
512/**
513 * Return parent identifier of a traffic control object
514 * @arg tc traffic control object
515 */
516uint32_t rtnl_tc_get_parent(struct rtnl_tc *tc)
517{
518 return tc->tc_parent;
519}
520
521/**
522 * Define the type of traffic control object
523 * @arg tc traffic control object
524 * @arg kind name of the tc object type
525 *
526 * @return 0 on success or a negative error code
527 */
528int rtnl_tc_set_kind(struct rtnl_tc *tc, const char *kind)
529{
530 if (tc->ce_mask & TCA_ATTR_KIND)
531 return -NLE_EXIST;
532
533 if ( !kind
534 || strlen (kind) >= sizeof (tc->tc_kind))
535 return -NLE_INVAL;
536
537 _nl_strncpy_assert(tc->tc_kind, kind, sizeof(tc->tc_kind));
538
539 tc->ce_mask |= TCA_ATTR_KIND;
540
541 /* Force allocation of data */
542 rtnl_tc_data(tc);
543
544 return 0;
545}
546
547/**
548 * Return kind of traffic control object
549 * @arg tc traffic control object
550 *
551 * @return Kind of traffic control object or NULL if not set.
552 */
553char *rtnl_tc_get_kind(struct rtnl_tc *tc)
554{
555 if (tc->ce_mask & TCA_ATTR_KIND)
556 return tc->tc_kind;
557 else
558 return NULL;
559}
560
561/**
562 * Return value of a statistical counter of a traffic control object
563 * @arg tc traffic control object
564 * @arg id identifier of statistical counter
565 *
566 * @return Value of requested statistic counter or 0.
567 */
568uint64_t rtnl_tc_get_stat(struct rtnl_tc *tc, enum rtnl_tc_stat id)
569{
570 if ((unsigned int) id > RTNL_TC_STATS_MAX)
571 return 0;
572
573 return tc->tc_stats[id];
574}
575
576/**
577 * Set the chain index of a traffic control object
578 * @arg tc traffic control object
579 * @arg chain chain index of traffic control object
580 *
581 */
582void rtnl_tc_set_chain(struct rtnl_tc *tc, uint32_t chain)
583{
584 tc->tc_chain = chain;
585 tc->ce_mask |= TCA_ATTR_CHAIN;
586}
587
588/**
589 * Return chain index of traffic control object
590 * @arg tc traffic control object
591 * @arg out_value output argument.
592 *
593 * @return 0 of the output value was successfully returned, or a negative
594 * error code on failure.
595 */
596int rtnl_tc_get_chain(struct rtnl_tc *tc, uint32_t *out_value)
597{
598 if (!(tc->ce_mask & TCA_ATTR_CHAIN))
599 return -NLE_MISSING_ATTR;
600 *out_value = tc->tc_chain;
601 return 0;
602}
603
604/** @} */
605
606/**
607 * @name Utilities
608 * @{
609 */
610
611static const struct trans_tbl tc_stats[] = {
612 __ADD(RTNL_TC_PACKETS, packets),
613 __ADD(RTNL_TC_BYTES, bytes),
614 __ADD(RTNL_TC_RATE_BPS, rate_bps),
615 __ADD(RTNL_TC_RATE_PPS, rate_pps),
616 __ADD(RTNL_TC_QLEN, qlen),
617 __ADD(RTNL_TC_BACKLOG, backlog),
618 __ADD(RTNL_TC_DROPS, drops),
619 __ADD(RTNL_TC_REQUEUES, requeues),
620 __ADD(RTNL_TC_OVERLIMITS, overlimits),
621};
622
623char *rtnl_tc_stat2str(enum rtnl_tc_stat st, char *buf, size_t len)
624{
625 return __type2str(st, buf, len, tc_stats, ARRAY_SIZE(tc_stats));
626}
627
628int rtnl_tc_str2stat(const char *name)
629{
630 return __str2type(name, tc_stats, ARRAY_SIZE(tc_stats));
631}
632
633/**
634 * Calculate time required to transmit buffer at a specific rate
635 * @arg bufsize Size of buffer to be transmited in bytes.
636 * @arg rate Transmit rate in bytes per second.
637 *
638 * Calculates the number of micro seconds required to transmit a
639 * specific buffer at a specific transmit rate.
640 *
641 * @f[
642 * txtime=\frac{bufsize}{rate}10^6
643 * @f]
644 *
645 * @return Required transmit time in micro seconds.
646 */
647int rtnl_tc_calc_txtime(int bufsize, int rate)
648{
649 return ((double) bufsize / (double) rate) * 1000000.0;
650}
651
652/**
653 * Calculate buffer size able to transmit in a specific time and rate.
654 * @arg txtime Available transmit time in micro seconds.
655 * @arg rate Transmit rate in bytes per second.
656 *
657 * Calculates the size of the buffer that can be transmitted in a
658 * specific time period at a specific transmit rate.
659 *
660 * @f[
661 * bufsize=\frac{{txtime} \times {rate}}{10^6}
662 * @f]
663 *
664 * @return Size of buffer in bytes.
665 */
666int rtnl_tc_calc_bufsize(int txtime, int rate)
667{
668 return ((double) txtime * (double) rate) / 1000000.0;
669}
670
671/**
672 * Calculate the binary logarithm for a specific cell size
673 * @arg cell_size Size of cell, must be a power of two.
674 * @return Binary logarithm of cell size or a negative error code.
675 */
676int rtnl_tc_calc_cell_log(int cell_size)
677{
678 int i;
679
680 for (i = 0; i < 32; i++)
681 if ((((uint32_t)1u) << i) == ((uint32_t)cell_size))
682 return i;
683
684 return -NLE_INVAL;
685}
686
687
688/** @} */
689
690/**
691 * @name Rate Tables
692 * @{
693 */
694
695/*
696 * COPYRIGHT NOTE:
697 * align_to_atm() and adjust_size() derived/coped from iproute2 source.
698 */
699
700/*
701 * The align to ATM cells is used for determining the (ATM) SAR
702 * alignment overhead at the ATM layer. (SAR = Segmentation And
703 * Reassembly). This is for example needed when scheduling packet on
704 * an ADSL connection. Note that the extra ATM-AAL overhead is _not_
705 * included in this calculation. This overhead is added in the kernel
706 * before doing the rate table lookup, as this gives better precision
707 * (as the table will always be aligned for 48 bytes).
708 * --Hawk, d.7/11-2004. <hawk@diku.dk>
709 */
710static unsigned int align_to_atm(unsigned int size)
711{
712 int linksize, cells;
713 cells = size / ATM_CELL_PAYLOAD;
714 if ((size % ATM_CELL_PAYLOAD) > 0)
715 cells++;
716
717 linksize = cells * ATM_CELL_SIZE; /* Use full cell size to add ATM tax */
718 return linksize;
719}
720
721static unsigned int adjust_size(unsigned int size, unsigned int mpu,
722 uint32_t linktype)
723{
724 if (size < mpu)
725 size = mpu;
726
727 switch (linktype) {
728 case ARPHRD_ATM:
729 return align_to_atm(size);
730
731 case ARPHRD_ETHER:
732 default:
733 return size;
734 }
735}
736
737/**
738 * Compute a transmission time lookup table
739 * @arg tc traffic control object
740 * @arg spec Rate specification
741 * @arg dst Destination buffer of RTNL_TC_RTABLE_SIZE uint32_t[].
742 *
743 * Computes a table of RTNL_TC_RTABLE_SIZE entries specyfing the
744 * transmission times for various packet sizes, e.g. the transmission
745 * time for a packet of size \c pktsize could be looked up:
746 * @code
747 * txtime = table[pktsize >> log2(mtu)];
748 * @endcode
749 */
750int rtnl_tc_build_rate_table(struct rtnl_tc *tc, struct rtnl_ratespec *spec,
751 uint32_t *dst)
752{
753 uint32_t mtu = rtnl_tc_get_mtu(tc);
754 uint32_t linktype = rtnl_tc_get_linktype(tc);
755 uint8_t cell_log = spec->rs_cell_log;
756 unsigned int size, i;
757
758 spec->rs_mpu = rtnl_tc_get_mpu(tc);
759 spec->rs_overhead = rtnl_tc_get_overhead(tc);
760
761 if (mtu == 0)
762 mtu = 2047;
763
764 if (cell_log == UINT8_MAX) {
765 /*
766 * cell_log not specified, calculate it. It has to specify the
767 * minimum number of rshifts required to break the MTU to below
768 * RTNL_TC_RTABLE_SIZE.
769 */
770 cell_log = 0;
771 while ((mtu >> cell_log) >= RTNL_TC_RTABLE_SIZE)
772 cell_log++;
773 }
774
775 for (i = 0; i < RTNL_TC_RTABLE_SIZE; i++) {
776 size = adjust_size((i + 1) << cell_log, spec->rs_mpu, linktype);
777 dst[i] = nl_us2ticks(rtnl_tc_calc_txtime64(size, spec->rs_rate64));
778 }
779
780 spec->rs_cell_align = -1;
781 spec->rs_cell_log = cell_log;
782
783 return 0;
784}
785
786/** @} */
787
788/**
789 * @name TC implementation of cache functions
790 */
791
792void rtnl_tc_free_data(struct nl_object *obj)
793{
794 struct rtnl_tc *tc = TC_CAST(obj);
795 struct rtnl_tc_ops *ops;
796
797 rtnl_link_put(tc->tc_link);
798 nl_data_free(tc->tc_opts);
799 nl_data_free(tc->tc_xstats);
800
801 if (tc->tc_subdata) {
802 ops = rtnl_tc_get_ops(tc);
803 if (ops && ops->to_free_data)
804 ops->to_free_data(tc, nl_data_get(tc->tc_subdata));
805
806 nl_data_free(tc->tc_subdata);
807 }
808}
809
810int rtnl_tc_clone(struct nl_object *dstobj, struct nl_object *srcobj)
811{
812 struct rtnl_tc *dst = TC_CAST(dstobj);
813 struct rtnl_tc *src = TC_CAST(srcobj);
814 struct rtnl_tc_ops *ops;
815
816 dst->tc_opts = NULL;
817 dst->tc_xstats = NULL;
818 dst->tc_subdata = NULL;
819 dst->tc_link = NULL;
820 dst->tc_ops = NULL;
821
822 if (src->tc_link) {
823 nl_object_get(OBJ_CAST(src->tc_link));
824 dst->tc_link = src->tc_link;
825 }
826
827 dst->ce_mask &= ~(TCA_ATTR_OPTS |
828 TCA_ATTR_XSTATS);
829
830 if (src->tc_opts) {
831 dst->tc_opts = nl_data_clone(src->tc_opts);
832 if (!dst->tc_opts)
833 return -NLE_NOMEM;
834 dst->ce_mask |= TCA_ATTR_OPTS;
835 }
836
837 if (src->tc_xstats) {
838 dst->tc_xstats = nl_data_clone(src->tc_xstats);
839 if (!dst->tc_xstats)
840 return -NLE_NOMEM;
841 dst->ce_mask |= TCA_ATTR_XSTATS;
842 }
843
844 if (src->tc_subdata) {
845 if (!(dst->tc_subdata = nl_data_clone(src->tc_subdata))) {
846 return -NLE_NOMEM;
847 }
848
849 /* Warning: if the data contains pointer, then at this point, dst->tc_subdata
850 * will alias those pointers.
851 *
852 * ops->to_clone() MUST fix that.
853 *
854 * If the type is actually "struct rtnl_act", then to_clone() must also
855 * fix dangling "a_next" pointer. */
856
857 ops = rtnl_tc_get_ops(src);
858 if (ops && ops->to_clone) {
859 return ops->to_clone(rtnl_tc_data(dst), rtnl_tc_data(src));
860 }
861 }
862
863 return 0;
864}
865
866static int tc_dump(struct rtnl_tc *tc, enum nl_dump_type type,
867 struct nl_dump_params *p)
868{
869 struct rtnl_tc_type_ops *type_ops;
870 struct rtnl_tc_ops *ops;
871 void *data = rtnl_tc_data(tc);
872
873 type_ops = tc_type_ops[tc->tc_type];
874 if (type_ops && type_ops->tt_dump[type])
875 type_ops->tt_dump[type](tc, p);
876
877 ops = rtnl_tc_get_ops(tc);
878 if (ops && ops->to_dump[type]) {
879 ops->to_dump[type](tc, data, p);
880 return 1;
881 }
882
883 return 0;
884}
885
886void rtnl_tc_dump_line(struct nl_object *obj, struct nl_dump_params *p)
887{
888 struct rtnl_tc_type_ops *type_ops;
889 struct rtnl_tc *tc = TC_CAST(obj);
890 struct nl_cache *link_cache;
891 char buf[32];
892
893 nl_new_line(p);
894
895 type_ops = tc_type_ops[tc->tc_type];
896 if (type_ops && type_ops->tt_dump_prefix)
897 nl_dump(p, "%s ", type_ops->tt_dump_prefix);
898
899 nl_dump(p, "%s ", tc->tc_kind);
900
901 if ((link_cache = nl_cache_mngt_require_safe("route/link"))) {
902 nl_dump(p, "dev %s ",
903 rtnl_link_i2name(link_cache, tc->tc_ifindex,
904 buf, sizeof(buf)));
905 } else
906 nl_dump(p, "dev %u ", tc->tc_ifindex);
907
908 nl_dump(p, "id %s ",
909 rtnl_tc_handle2str(tc->tc_handle, buf, sizeof(buf)));
910
911 nl_dump(p, "parent %s",
912 rtnl_tc_handle2str(tc->tc_parent, buf, sizeof(buf)));
913
914 tc_dump(tc, NL_DUMP_LINE, p);
915 nl_dump(p, "\n");
916
917 if (link_cache)
918 nl_cache_put(link_cache);
919}
920
921void rtnl_tc_dump_details(struct nl_object *obj, struct nl_dump_params *p)
922{
923 struct rtnl_tc *tc = TC_CAST(obj);
924
925 rtnl_tc_dump_line(OBJ_CAST(tc), p);
926
927 nl_dump_line(p, " ");
928
929 if (tc->ce_mask & TCA_ATTR_MTU)
930 nl_dump(p, " mtu %u", tc->tc_mtu);
931
932 if (tc->ce_mask & TCA_ATTR_MPU)
933 nl_dump(p, " mpu %u", tc->tc_mpu);
934
935 if (tc->ce_mask & TCA_ATTR_OVERHEAD)
936 nl_dump(p, " overhead %u", tc->tc_overhead);
937
938 if (!tc_dump(tc, NL_DUMP_DETAILS, p))
939 nl_dump(p, "no options");
940 nl_dump(p, "\n");
941}
942
943void rtnl_tc_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
944{
945 struct rtnl_tc *tc = TC_CAST(obj);
946 char *unit;
947 float res;
948
949 rtnl_tc_dump_details(OBJ_CAST(tc), p);
950
951 nl_dump_line(p,
952 " stats: %-14s %-10s %-10s %-10s %-10s %-10s\n",
953 "bytes", "packets", "drops", "overlimits", "qlen", "backlog");
954
955 res = nl_cancel_down_bytes(tc->tc_stats[RTNL_TC_BYTES], &unit);
956
957 nl_dump_line(
958 p,
959 " %10.2f %3s %10llu %-10llu %-10llu %-10llu %-10llu\n",
960 res, unit, (long long unsigned)tc->tc_stats[RTNL_TC_PACKETS],
961 (long long unsigned)tc->tc_stats[RTNL_TC_DROPS],
962 (long long unsigned)tc->tc_stats[RTNL_TC_OVERLIMITS],
963 (long long unsigned)tc->tc_stats[RTNL_TC_QLEN],
964 (long long unsigned)tc->tc_stats[RTNL_TC_BACKLOG]);
965
966 res = nl_cancel_down_bytes(tc->tc_stats[RTNL_TC_RATE_BPS], &unit);
967
968 nl_dump_line(p, " %10.2f %3s/s %10llu/s\n", res, unit,
969 (long long unsigned)tc->tc_stats[RTNL_TC_RATE_PPS]);
970}
971
972uint64_t rtnl_tc_compare(struct nl_object *aobj, struct nl_object *bobj,
973 uint64_t attrs, int flags)
974{
975 struct rtnl_tc *a = TC_CAST(aobj);
976 struct rtnl_tc *b = TC_CAST(bobj);
977 uint64_t diff = 0;
978
979#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
980 diff |= _DIFF(TCA_ATTR_HANDLE, a->tc_handle != b->tc_handle);
981 diff |= _DIFF(TCA_ATTR_PARENT, a->tc_parent != b->tc_parent);
982 diff |= _DIFF(TCA_ATTR_IFINDEX, a->tc_ifindex != b->tc_ifindex);
983 diff |= _DIFF(TCA_ATTR_KIND, strcmp(a->tc_kind, b->tc_kind));
984#undef _DIFF
985
986 return diff;
987}
988
989/** @} */
990
991/**
992 * @name Modules API
993 */
994
995struct rtnl_tc_ops *rtnl_tc_lookup_ops(enum rtnl_tc_type type, const char *kind)
996{
997 struct rtnl_tc_ops *ops;
998
999 nl_list_for_each_entry(ops, &tc_ops_list[type], to_list)
1000 if (!strcmp(kind, ops->to_kind))
1001 return ops;
1002
1003 return NULL;
1004}
1005
1006struct rtnl_tc_ops *rtnl_tc_get_ops(struct rtnl_tc *tc)
1007{
1008 if (!tc->tc_ops)
1009 tc->tc_ops = rtnl_tc_lookup_ops(tc->tc_type, tc->tc_kind);
1010
1011 return tc->tc_ops;
1012}
1013
1014/**
1015 * Register a traffic control module
1016 * @arg ops traffic control module operations
1017 */
1018int rtnl_tc_register(struct rtnl_tc_ops *ops)
1019{
1020 static int init = 0;
1021
1022 /*
1023 * Initialiation hack, make sure list is initialized when
1024 * the first tc module registers. Putting this in a
1025 * separate _nl_init would required correct ordering of init
1026 * functions
1027 */
1028 if (!init) {
1029 int i;
1030
1031 for (i = 0; i < __RTNL_TC_TYPE_MAX; i++)
1032 nl_init_list_head(&tc_ops_list[i]);
1033
1034 init = 1;
1035 }
1036
1037 if (!ops->to_kind || ops->to_type > RTNL_TC_TYPE_MAX)
1038 BUG();
1039
1040 if (rtnl_tc_lookup_ops(ops->to_type, ops->to_kind))
1041 return -NLE_EXIST;
1042
1043 nl_list_add_tail(&ops->to_list, &tc_ops_list[ops->to_type]);
1044
1045 return 0;
1046}
1047
1048/**
1049 * Unregister a traffic control module
1050 * @arg ops traffic control module operations
1051 */
1052void rtnl_tc_unregister(struct rtnl_tc_ops *ops)
1053{
1054 nl_list_del(&ops->to_list);
1055}
1056
1057/**
1058 * Returns the private data of the traffic control object.
1059 * Contrary to rtnl_tc_data(), this returns NULL if the data is
1060 * not yet allocated
1061 * @arg tc traffic control object
1062 *
1063 * @return pointer to the private data or NULL if not allocated.
1064 */
1066{
1067 return tc->tc_subdata ? nl_data_get(tc->tc_subdata) : NULL;
1068}
1069
1070/**
1071 * Return pointer to private data of traffic control object
1072 * @arg tc traffic control object
1073 *
1074 * Allocates the private traffic control object data section
1075 * as necessary and returns it.
1076 *
1077 * @return Pointer to private tc data or NULL if allocation failed.
1078 */
1079void *rtnl_tc_data(struct rtnl_tc *tc)
1080{
1081 if (!tc->tc_subdata) {
1082 size_t size;
1083
1084 if (!tc->tc_ops) {
1085 if (!rtnl_tc_get_ops(tc))
1086 return NULL;
1087 }
1088
1089 if (!(size = tc->tc_ops->to_size))
1090 BUG();
1091
1092 if (!(tc->tc_subdata = nl_data_alloc(NULL, size)))
1093 return NULL;
1094 }
1095
1096 return nl_data_get(tc->tc_subdata);
1097}
1098
1099/**
1100 * Check traffic control object type and return private data section
1101 * @arg tc traffic control object
1102 * @arg ops expected traffic control object operations
1103 * @arg err the place where saves the error code if fails
1104 *
1105 * Checks whether the traffic control object matches the type
1106 * specified with the traffic control object operations. If the
1107 * type matches, the private tc object data is returned. If type
1108 * mismatches, APPBUG() will print a application bug warning.
1109 *
1110 * @see rtnl_tc_data()
1111 *
1112 * @return Pointer to private tc data or NULL if type mismatches.
1113 */
1114void *rtnl_tc_data_check(struct rtnl_tc *tc, struct rtnl_tc_ops *ops, int *err)
1115{
1116 void *ret;
1117
1118 if (tc->tc_ops != ops) {
1119 char buf[64];
1120
1121 snprintf(buf, sizeof(buf),
1122 "tc object %p used in %s context but is of type %s",
1123 tc, ops->to_kind, tc->tc_ops->to_kind);
1124 APPBUG(buf);
1125
1126 if (err)
1127 *err = -NLE_OPNOTSUPP;
1128 return NULL;
1129 }
1130
1131 ret = rtnl_tc_data(tc);
1132 if (ret == NULL) {
1133 if (err)
1134 *err = -NLE_NOMEM;
1135 }
1136
1137 return ret;
1138}
1139
1140struct nl_af_group tc_groups[] = {
1141 { AF_UNSPEC, RTNLGRP_TC },
1142 { END_OF_GROUP_LIST },
1143};
1144
1145
1146void rtnl_tc_type_register(struct rtnl_tc_type_ops *ops)
1147{
1148 if (ops->tt_type > RTNL_TC_TYPE_MAX)
1149 BUG();
1150
1151 tc_type_ops[ops->tt_type] = ops;
1152}
1153
1154void rtnl_tc_type_unregister(struct rtnl_tc_type_ops *ops)
1155{
1156 if (ops->tt_type > RTNL_TC_TYPE_MAX)
1157 BUG();
1158
1159 tc_type_ops[ops->tt_type] = NULL;
1160}
1161
1162/** @} */
1163
1164/** @} */
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
Definition attr.c:714
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:245
void * nla_data(const struct nlattr *nla)
Return pointer to the payload section.
Definition attr.c:119
#define NLA_PUT_U32(msg, attrtype, value)
Add 32 bit integer attribute to netlink message.
Definition attr.h:237
struct nlattr * nla_nest_start(struct nl_msg *msg, int attrtype)
Start a new level of nested attributes.
Definition attr.c:974
size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize)
Copy string attribute payload to a buffer.
Definition attr.c:383
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:1101
#define NLA_PUT_STRING(msg, attrtype, value)
Add string attribute to netlink message.
Definition attr.h:264
int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
Finalize nesting of attributes.
Definition attr.c:1037
int nla_nest_end_keep_empty(struct nl_msg *msg, struct nlattr *start)
Finalize nesting of attributes without stripping off empty attributes.
Definition attr.c:1052
@ NLA_STRING
NUL terminated character string.
Definition attr.h:39
@ NLA_NESTED
Nested attributes.
Definition attr.h:42
@ NLA_U32
32 bit integer
Definition attr.h:37
struct nl_cache * nl_cache_mngt_require_safe(const char *name)
Return cache previously provided via nl_cache_mngt_provide()
Definition cache_mngt.c:430
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
struct nl_data * nl_data_clone(const struct nl_data *src)
Clone an abstract data object.
Definition data.c:95
void nl_data_free(struct nl_data *data)
Free an abstract data object.
Definition data.c:134
struct nl_data * nl_data_alloc(const void *buf, size_t size)
Allocate a new abstract data object.
Definition data.c:50
struct nl_data * nl_data_alloc_attr(const struct nlattr *nla)
Allocate abstract data object based on netlink attribute.
Definition data.c:84
void * nl_data_get(const struct nl_data *data)
Get data buffer of abstract data object.
Definition data.c:154
struct nl_msg * nlmsg_alloc_simple(int nlmsgtype, int flags)
Allocate a new netlink message.
Definition msg.c:352
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:572
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:219
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:456
void nl_object_get(struct nl_object *obj)
Acquire a reference on a object.
Definition object.c:210
void rtnl_tc_set_mpu(struct rtnl_tc *tc, uint32_t mpu)
Set the Minimum Packet Unit (MPU) of a traffic control object.
Definition tc.c:398
uint32_t rtnl_tc_get_parent(struct rtnl_tc *tc)
Return parent identifier of a traffic control object.
Definition tc.c:516
void rtnl_tc_set_linktype(struct rtnl_tc *tc, uint32_t type)
Set the linktype of a traffic control object.
Definition tc.c:455
void * rtnl_tc_data_check(struct rtnl_tc *tc, struct rtnl_tc_ops *ops, int *err)
Check traffic control object type and return private data section.
Definition tc.c:1114
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_data_peek(struct rtnl_tc *tc)
Returns the private data of the traffic control object.
Definition tc.c:1065
int rtnl_tc_calc_cell_log(int cell_size)
Calculate the binary logarithm for a specific cell size.
Definition tc.c:676
int rtnl_tc_get_chain(struct rtnl_tc *tc, uint32_t *out_value)
Return chain index of traffic control object.
Definition tc.c:596
char * rtnl_tc_get_kind(struct rtnl_tc *tc)
Return kind of traffic control object.
Definition tc.c:553
void rtnl_tc_set_ifindex(struct rtnl_tc *tc, int ifindex)
Set interface index of traffic control object.
Definition tc.c:277
int rtnl_tc_build_rate_table(struct rtnl_tc *tc, struct rtnl_ratespec *spec, uint32_t *dst)
Compute a transmission time lookup table.
Definition tc.c:750
void rtnl_tc_set_overhead(struct rtnl_tc *tc, uint32_t overhead)
Set per packet overhead of a traffic control object.
Definition tc.c:427
int rtnl_tc_calc_bufsize(int txtime, int rate)
Calculate buffer size able to transmit in a specific time and rate.
Definition tc.c:666
uint32_t rtnl_tc_get_mtu(struct rtnl_tc *tc)
Return the MTU of traffic control object.
Definition tc.c:378
int rtnl_tc_get_ifindex(struct rtnl_tc *tc)
Return interface index of traffic control object.
Definition tc.c:292
void rtnl_tc_set_link(struct rtnl_tc *tc, struct rtnl_link *link)
Set link of traffic control object.
Definition tc.c:309
uint32_t rtnl_tc_get_handle(struct rtnl_tc *tc)
Return identifier of a traffic control object.
Definition tc.c:495
#define TC_CAST(ptr)
Macro to cast qdisc/class/classifier to tc object.
Definition tc.h:50
uint32_t rtnl_tc_get_overhead(struct rtnl_tc *tc)
Return per packet overhead of a traffic control object.
Definition tc.c:439
void rtnl_tc_set_handle(struct rtnl_tc *tc, uint32_t id)
Set identifier of traffic control object.
Definition tc.c:485
void rtnl_tc_set_parent(struct rtnl_tc *tc, uint32_t parent)
Set the parent identifier of a traffic control object.
Definition tc.c:506
void * rtnl_tc_data(struct rtnl_tc *tc)
Return pointer to private data of traffic control object.
Definition tc.c:1079
int rtnl_tc_register(struct rtnl_tc_ops *ops)
Register a traffic control module.
Definition tc.c:1018
void rtnl_tc_unregister(struct rtnl_tc_ops *ops)
Unregister a traffic control module.
Definition tc.c:1052
void rtnl_tc_set_mtu(struct rtnl_tc *tc, uint32_t mtu)
Set the Maximum Transmission Unit (MTU) of traffic control object.
Definition tc.c:363
void rtnl_tc_set_chain(struct rtnl_tc *tc, uint32_t chain)
Set the chain index of a traffic control object.
Definition tc.c:582
uint64_t rtnl_tc_get_stat(struct rtnl_tc *tc, enum rtnl_tc_stat id)
Return value of a statistical counter of a traffic control object.
Definition tc.c:568
rtnl_tc_stat
Traffic control statistical identifier.
Definition tc.h:60
struct rtnl_link * rtnl_tc_get_link(struct rtnl_tc *tc)
Get link of traffic control object.
Definition tc.c:340
uint32_t rtnl_tc_get_linktype(struct rtnl_tc *tc)
Return the linktype of a traffic control object.
Definition tc.c:470
uint32_t rtnl_tc_get_mpu(struct rtnl_tc *tc)
Return the Minimum Packet Unit (MPU) of a traffic control object.
Definition tc.c:410
int rtnl_tc_calc_txtime(int bufsize, int rate)
Calculate time required to transmit buffer at a specific rate.
Definition tc.c:647
@ RTNL_TC_PACKETS
Number of packets seen.
Definition tc.h:61
@ RTNL_TC_BYTES
Total bytes seen.
Definition tc.h:62
@ RTNL_TC_QLEN
Current queue length.
Definition tc.h:65
@ 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_REQUEUES
Total number of requeues.
Definition tc.h:68
@ RTNL_TC_BACKLOG
Current backlog length.
Definition tc.h:66
@ RTNL_TC_RATE_BPS
Current bits/s (rate estimator)
Definition tc.h:63
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Definition utils.c:1015
double nl_cancel_down_bytes(unsigned long long l, char **unit)
Cancel down a byte counter.
Definition utils.c:223
void nl_new_line(struct nl_dump_params *params)
Handle a new line while dumping.
Definition utils.c:966
nl_dump_type
Enumeration of dumping variations (dp_type)
Definition types.h:19
uint32_t nl_us2ticks(uint32_t us)
Convert micro seconds to ticks.
Definition utils.c:582
@ 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:66
uint16_t minlen
Minimal length of payload required.
Definition attr.h:71
uint16_t type
Type of attribute or NLA_UNSPEC.
Definition attr.h:68
void(* tt_dump[NL_DUMP_MAX+1])(struct rtnl_tc *, struct nl_dump_params *)
Dump callbacks.
Definition tc-api.h:60