19 #include <netlink-local.h>
20 #include <netlink-tc.h>
21 #include <netlink/netlink.h>
22 #include <netlink/utils.h>
23 #include <netlink/route/rtnl.h>
24 #include <netlink/route/link.h>
25 #include <netlink/route/tc.h>
29 static struct nla_policy tc_policy[TCA_MAX+1] = {
31 .maxlen = TCKINDSIZ },
32 [TCA_STATS] = { .minlen =
sizeof(
struct tc_stats) },
36 int tca_parse(
struct nlattr **tb,
int maxattr,
struct rtnl_tca *g,
40 if (g->ce_mask & TCA_ATTR_OPTS)
42 (
struct nlattr *) g->tc_opts->d_data,
43 g->tc_opts->d_size, policy);
47 memset(tb, 0,
sizeof(
struct nlattr *) * (maxattr + 1));
52 static struct nla_policy tc_stats2_policy[TCA_STATS_MAX+1] = {
53 [TCA_STATS_BASIC] = { .
minlen =
sizeof(
struct gnet_stats_basic) },
54 [TCA_STATS_RATE_EST] = { .minlen =
sizeof(
struct gnet_stats_rate_est) },
55 [TCA_STATS_QUEUE] = { .minlen =
sizeof(
struct gnet_stats_queue) },
58 int tca_msg_parser(
struct nlmsghdr *n,
struct rtnl_tca *g)
60 struct nlattr *tb[TCA_MAX + 1];
64 err =
nlmsg_parse(n,
sizeof(*tm), tb, TCA_MAX, tc_policy);
68 if (tb[TCA_KIND] == NULL)
69 return nl_error(EINVAL,
"Missing tca kind TLV");
74 g->tc_family = tm->tcm_family;
75 g->tc_ifindex = tm->tcm_ifindex;
76 g->tc_handle = tm->tcm_handle;
77 g->tc_parent = tm->tcm_parent;
78 g->tc_info = tm->tcm_info;
80 g->ce_mask = (TCA_ATTR_FAMILY | TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE |
81 TCA_ATTR_PARENT | TCA_ATTR_INFO | TCA_ATTR_KIND);
83 if (tb[TCA_OPTIONS]) {
86 return nl_errno(ENOMEM);
87 g->ce_mask |= TCA_ATTR_OPTS;
92 struct nlattr *tbs[TCA_STATS_MAX + 1];
99 if (tbs[TCA_STATS_BASIC]) {
100 struct gnet_stats_basic *bs;
102 bs =
nla_data(tbs[TCA_STATS_BASIC]);
107 if (tbs[TCA_STATS_RATE_EST]) {
108 struct gnet_stats_rate_est *re;
110 re =
nla_data(tbs[TCA_STATS_RATE_EST]);
115 if (tbs[TCA_STATS_QUEUE]) {
116 struct gnet_stats_queue *q;
126 g->ce_mask |= TCA_ATTR_STATS;
128 if (tbs[TCA_STATS_APP]) {
130 if (g->tc_xstats == NULL)
136 struct tc_stats *st =
nla_data(tb[TCA_STATS]);
147 g->ce_mask |= TCA_ATTR_STATS;
151 if (tb[TCA_XSTATS]) {
153 if (g->tc_xstats == NULL)
155 g->ce_mask |= TCA_ATTR_XSTATS;
163 void tca_free_data(
struct rtnl_tca *tca)
169 int tca_clone(
struct rtnl_tca *dst,
struct rtnl_tca *src)
177 if (src->tc_xstats) {
185 return nl_get_errno();
188 int tca_dump_brief(
struct rtnl_tca *g,
const char *type,
191 char handle[32], parent[32];
192 struct nl_cache *link_cache;
196 dp_dump(p,
"%s %s ", g->tc_kind, type);
200 dp_dump(p,
"dev %s ",
204 dp_dump(p,
"dev %u ", g->tc_ifindex);
206 dp_dump(p,
"handle %s parent %s",
213 int tca_dump_full(
struct rtnl_tca *g,
struct nl_dump_params *p,
int line)
215 dp_dump_line(p, line++,
" ");
219 int tca_dump_stats(
struct rtnl_tca *g,
struct nl_dump_params *p,
int line)
223 strcpy(fmt,
" %7.2f %s %10u %10u %10u %10u %10u\n");
225 dp_dump_line(p, line++,
226 " Stats: bytes packets drops overlimits" \
233 dp_dump_line(p, line++, fmt, res, unit,
242 strcpy(fmt,
" %7.2f %s/s%9u pps");
252 int tca_compare(
struct nl_object *_a,
struct nl_object *_b,
253 uint32_t attrs,
int flags)
255 struct rtnl_tca *a = (
struct rtnl_tca *) _a;
256 struct rtnl_tca *b = (
struct rtnl_tca *) _b;
259 #define TC_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, TCA_ATTR_##ATTR, a, b, EXPR)
261 diff |= TC_DIFF(HANDLE, a->tc_handle != b->tc_handle);
262 diff |= TC_DIFF(PARENT, a->tc_parent != b->tc_parent);
263 diff |= TC_DIFF(IFINDEX, a->tc_ifindex != b->tc_ifindex);
264 diff |= TC_DIFF(KIND, strcmp(a->tc_kind, b->tc_kind));
271 void tca_set_ifindex(
struct rtnl_tca *t,
int ifindex)
273 t->tc_ifindex = ifindex;
274 t->ce_mask |= TCA_ATTR_IFINDEX;
277 int tca_get_ifindex(
struct rtnl_tca *t)
279 if (t->ce_mask & TCA_ATTR_IFINDEX)
280 return t->tc_ifindex;
285 void tca_set_handle(
struct rtnl_tca *t, uint32_t handle)
287 t->tc_handle = handle;
288 t->ce_mask |= TCA_ATTR_HANDLE;
291 uint32_t tca_get_handle(
struct rtnl_tca *t)
293 if (t->ce_mask & TCA_ATTR_HANDLE)
299 void tca_set_parent(
struct rtnl_tca *t, uint32_t parent)
301 t->tc_parent = parent;
302 t->ce_mask |= TCA_ATTR_PARENT;
305 uint32_t tca_get_parent(
struct rtnl_tca *t)
307 if (t->ce_mask & TCA_ATTR_PARENT)
313 void tca_set_kind(
struct rtnl_tca *t,
const char *kind)
315 strncpy(t->tc_kind, kind,
sizeof(t->tc_kind) - 1);
316 t->ce_mask |= TCA_ATTR_KIND;
319 char *tca_get_kind(
struct rtnl_tca *t)
321 if (t->ce_mask & TCA_ATTR_KIND)
327 uint64_t tca_get_stat(
struct rtnl_tca *t,
int id)
329 if (id < 0 || id > RTNL_TC_STATS_MAX)
332 return t->tc_stats[id];
335 struct nl_msg *tca_build_msg(
struct rtnl_tca *tca,
int type,
int flags)
338 struct tcmsg tchdr = {
339 .tcm_family = AF_UNSPEC,
340 .tcm_ifindex = tca->tc_ifindex,
341 .tcm_handle = tca->tc_handle,
342 .tcm_parent = tca->tc_parent,
347 goto nla_put_failure;
349 if (
nlmsg_append(msg, &tchdr,
sizeof(tchdr), NLMSG_ALIGNTO) < 0)
350 goto nla_put_failure;
352 if (tca->ce_mask & TCA_ATTR_KIND)
387 tx_time_secs = (double) bufsize / (
double) rate;
389 return tx_time_secs * 1000000.;
410 bufsize = (double) txtime * (
double) rate;
412 return bufsize / 1000000.;
424 for (i = 0; i < 32; i++)
425 if ((1 << i) == cell_size)
428 return nl_errno(EINVAL);
457 int i, size, cell_log;
464 size = (i << cell_log) + overhead;
495 if (TC_H_ROOT == handle)
496 snprintf(buf, len,
"root");
497 else if (TC_H_UNSPEC == handle)
498 snprintf(buf, len,
"none");
499 else if (0 == TC_H_MAJ(handle))
500 snprintf(buf, len,
":%02x", TC_H_MIN(handle));
501 else if (0 == TC_H_MIN(handle))
502 snprintf(buf, len,
"%02x:", TC_H_MAJ(handle) >> 16);
504 snprintf(buf, len,
"%02x:%02x",
505 TC_H_MAJ(handle) >> 16, TC_H_MIN(handle));
533 if (!strcasecmp(name,
"root")) {
538 if (!strcasecmp(name,
"none")) {
543 h = strtoul(name, &colon, 16);
558 if (
'\0' == colon[1]) {
563 uint32_t l = strtoul(colon+1, &end, 16);
574 }
else if (
'\0' == *colon) {
#define RTNL_LINK_NOT_FOUND
Special interface index stating the link was not found.
int rtnl_tc_calc_txtime(int bufsize, int rate)
Calculate time required to transmit buffer at a specific rate.
void * nlmsg_data(const struct nlmsghdr *nlh)
head of message payload
#define RTNL_TC_RTABLE_SIZE
Number of entries in a transmission time lookup table.
int rtnl_tc_calc_cell_log(int cell_size)
Calculate the binary logarithm for a specific cell size.
struct nl_data * nl_data_clone(struct nl_data *src)
Clone an abstract data object.
Current packet/s (rate estimator)
attribute validation policy
void nlmsg_free(struct nl_msg *n)
Free a netlink message.
int nlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], int maxtype, struct nla_policy *policy)
parse attributes of a netlink message
#define NLA_PUT_STRING(n, attrtype, value)
Add a character string netlink attribute to a netlink message.
Current bits/s (rate estimator)
char * rtnl_tc_handle2str(uint32_t handle, char *buf, size_t len)
Convert a traffic control handle to a character string (Reentrant).
int rtnl_tc_calc_bufsize(int txtime, int rate)
Calculate buffer size able to transmit in a specific time and rate.
double nl_cancel_down_bytes(unsigned long long l, char **unit)
Cancel down a byte counter.
int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, struct nla_policy *policy)
parse nested attributes
struct nl_cache * nl_cache_mngt_require(const char *name)
Demand the use of a global cache.
void * nla_data(const struct nlattr *nla)
head of payload
int nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len, struct nla_policy *policy)
Parse a stream of attributes into a tb buffer.
uint16_t minlen
Minimal length of payload required to be available.
int nlmsg_append(struct nl_msg *n, void *data, size_t len, int pad)
Append data to tail of a netlink message.
uint16_t type
Type of attribute or NLA_UNSPEC.
struct nl_msg * nlmsg_alloc_simple(int nlmsgtype, int flags)
Allocate a new netlink message.
char * rtnl_link_i2name(struct nl_cache *cache, int ifindex, char *dst, size_t len)
Translate an interface index to the corresponding link name.
struct nl_data * nla_get_data(struct nlattr *nla)
Return payload of abstract data attribute.
int rtnl_tc_build_rate_table(uint32_t *dst, uint8_t mpu, uint8_t overhead, int cell, int rate)
Compute a transmission time lookup table.
int rtnl_tc_str2handle(const char *name, uint32_t *res)
Convert a charactering strint to a traffic control handle.
size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize)
Copy string attribute payload into a sized buffer.
void nl_data_free(struct nl_data *data)
Free an abstract data object.