tc.c revision b4fbe1d34d6f54045b5c6236d86aacd4340ec83d
144d362409d5469aed47d19e7908d19bd194493aThomas Graf/* 244d362409d5469aed47d19e7908d19bd194493aThomas Graf * lib/route/tc.c Traffic Control 344d362409d5469aed47d19e7908d19bd194493aThomas Graf * 444d362409d5469aed47d19e7908d19bd194493aThomas Graf * This library is free software; you can redistribute it and/or 544d362409d5469aed47d19e7908d19bd194493aThomas Graf * modify it under the terms of the GNU Lesser General Public 644d362409d5469aed47d19e7908d19bd194493aThomas Graf * License as published by the Free Software Foundation version 2.1 744d362409d5469aed47d19e7908d19bd194493aThomas Graf * of the License. 844d362409d5469aed47d19e7908d19bd194493aThomas Graf * 98a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch> 1044d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 1144d362409d5469aed47d19e7908d19bd194493aThomas Graf 1244d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 1344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @ingroup rtnl 1444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @defgroup tc Traffic Control 1544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @brief 1644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 1744d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 1844d362409d5469aed47d19e7908d19bd194493aThomas Graf 1944d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink-local.h> 2044d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink-tc.h> 2144d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/netlink.h> 2244d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/utils.h> 2344d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/route/rtnl.h> 2444d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/route/link.h> 2544d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/route/tc.h> 2644d362409d5469aed47d19e7908d19bd194493aThomas Graf 2744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @cond SKIP */ 2844d362409d5469aed47d19e7908d19bd194493aThomas Graf 2944d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nla_policy tc_policy[TCA_MAX+1] = { 3044d362409d5469aed47d19e7908d19bd194493aThomas Graf [TCA_KIND] = { .type = NLA_STRING, 3144d362409d5469aed47d19e7908d19bd194493aThomas Graf .maxlen = TCKINDSIZ }, 3244d362409d5469aed47d19e7908d19bd194493aThomas Graf [TCA_STATS] = { .minlen = sizeof(struct tc_stats) }, 3344d362409d5469aed47d19e7908d19bd194493aThomas Graf [TCA_STATS2] = { .type = NLA_NESTED }, 3444d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 3544d362409d5469aed47d19e7908d19bd194493aThomas Graf 3644d362409d5469aed47d19e7908d19bd194493aThomas Grafint tca_parse(struct nlattr **tb, int maxattr, struct rtnl_tca *g, 3744d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nla_policy *policy) 3844d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 3944d362409d5469aed47d19e7908d19bd194493aThomas Graf 4044d362409d5469aed47d19e7908d19bd194493aThomas Graf if (g->ce_mask & TCA_ATTR_OPTS) 4144d362409d5469aed47d19e7908d19bd194493aThomas Graf return nla_parse(tb, maxattr, 4244d362409d5469aed47d19e7908d19bd194493aThomas Graf (struct nlattr *) g->tc_opts->d_data, 4344d362409d5469aed47d19e7908d19bd194493aThomas Graf g->tc_opts->d_size, policy); 4444d362409d5469aed47d19e7908d19bd194493aThomas Graf else { 4544d362409d5469aed47d19e7908d19bd194493aThomas Graf /* Ugly but tb[] must be in a defined state even if no 4644d362409d5469aed47d19e7908d19bd194493aThomas Graf * attributes can be found. */ 4744d362409d5469aed47d19e7908d19bd194493aThomas Graf memset(tb, 0, sizeof(struct nlattr *) * (maxattr + 1)); 4844d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 4944d362409d5469aed47d19e7908d19bd194493aThomas Graf } 5044d362409d5469aed47d19e7908d19bd194493aThomas Graf} 5144d362409d5469aed47d19e7908d19bd194493aThomas Graf 5244d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nla_policy tc_stats2_policy[TCA_STATS_MAX+1] = { 5344d362409d5469aed47d19e7908d19bd194493aThomas Graf [TCA_STATS_BASIC] = { .minlen = sizeof(struct gnet_stats_basic) }, 5444d362409d5469aed47d19e7908d19bd194493aThomas Graf [TCA_STATS_RATE_EST] = { .minlen = sizeof(struct gnet_stats_rate_est) }, 5544d362409d5469aed47d19e7908d19bd194493aThomas Graf [TCA_STATS_QUEUE] = { .minlen = sizeof(struct gnet_stats_queue) }, 5644d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 5744d362409d5469aed47d19e7908d19bd194493aThomas Graf 5844d362409d5469aed47d19e7908d19bd194493aThomas Grafint tca_msg_parser(struct nlmsghdr *n, struct rtnl_tca *g) 5944d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 6044d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nlattr *tb[TCA_MAX + 1]; 6144d362409d5469aed47d19e7908d19bd194493aThomas Graf struct tcmsg *tm; 6244d362409d5469aed47d19e7908d19bd194493aThomas Graf int err; 6344d362409d5469aed47d19e7908d19bd194493aThomas Graf 6444d362409d5469aed47d19e7908d19bd194493aThomas Graf err = nlmsg_parse(n, sizeof(*tm), tb, TCA_MAX, tc_policy); 6544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (err < 0) 6644d362409d5469aed47d19e7908d19bd194493aThomas Graf return err; 6744d362409d5469aed47d19e7908d19bd194493aThomas Graf 6844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[TCA_KIND] == NULL) 698a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_MISSING_ATTR; 7044d362409d5469aed47d19e7908d19bd194493aThomas Graf 7144d362409d5469aed47d19e7908d19bd194493aThomas Graf nla_strlcpy(g->tc_kind, tb[TCA_KIND], TCKINDSIZ); 7244d362409d5469aed47d19e7908d19bd194493aThomas Graf 7344d362409d5469aed47d19e7908d19bd194493aThomas Graf tm = nlmsg_data(n); 7444d362409d5469aed47d19e7908d19bd194493aThomas Graf g->tc_family = tm->tcm_family; 7544d362409d5469aed47d19e7908d19bd194493aThomas Graf g->tc_ifindex = tm->tcm_ifindex; 7644d362409d5469aed47d19e7908d19bd194493aThomas Graf g->tc_handle = tm->tcm_handle; 7744d362409d5469aed47d19e7908d19bd194493aThomas Graf g->tc_parent = tm->tcm_parent; 7844d362409d5469aed47d19e7908d19bd194493aThomas Graf g->tc_info = tm->tcm_info; 7944d362409d5469aed47d19e7908d19bd194493aThomas Graf 8044d362409d5469aed47d19e7908d19bd194493aThomas Graf g->ce_mask = (TCA_ATTR_FAMILY | TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE | 8144d362409d5469aed47d19e7908d19bd194493aThomas Graf TCA_ATTR_PARENT | TCA_ATTR_INFO | TCA_ATTR_KIND); 8244d362409d5469aed47d19e7908d19bd194493aThomas Graf 8344d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[TCA_OPTIONS]) { 84eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf g->tc_opts = nl_data_alloc_attr(tb[TCA_OPTIONS]); 8544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!g->tc_opts) 868a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_NOMEM; 8744d362409d5469aed47d19e7908d19bd194493aThomas Graf g->ce_mask |= TCA_ATTR_OPTS; 8844d362409d5469aed47d19e7908d19bd194493aThomas Graf } 8944d362409d5469aed47d19e7908d19bd194493aThomas Graf 9044d362409d5469aed47d19e7908d19bd194493aThomas Graf 9144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[TCA_STATS2]) { 9244d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nlattr *tbs[TCA_STATS_MAX + 1]; 9344d362409d5469aed47d19e7908d19bd194493aThomas Graf 9444d362409d5469aed47d19e7908d19bd194493aThomas Graf err = nla_parse_nested(tbs, TCA_STATS_MAX, tb[TCA_STATS2], 9544d362409d5469aed47d19e7908d19bd194493aThomas Graf tc_stats2_policy); 9644d362409d5469aed47d19e7908d19bd194493aThomas Graf if (err < 0) 9744d362409d5469aed47d19e7908d19bd194493aThomas Graf return err; 9844d362409d5469aed47d19e7908d19bd194493aThomas Graf 9944d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tbs[TCA_STATS_BASIC]) { 10044d362409d5469aed47d19e7908d19bd194493aThomas Graf struct gnet_stats_basic *bs; 10144d362409d5469aed47d19e7908d19bd194493aThomas Graf 10244d362409d5469aed47d19e7908d19bd194493aThomas Graf bs = nla_data(tbs[TCA_STATS_BASIC]); 10344d362409d5469aed47d19e7908d19bd194493aThomas Graf g->tc_stats[RTNL_TC_BYTES] = bs->bytes; 10444d362409d5469aed47d19e7908d19bd194493aThomas Graf g->tc_stats[RTNL_TC_PACKETS] = bs->packets; 10544d362409d5469aed47d19e7908d19bd194493aThomas Graf } 10644d362409d5469aed47d19e7908d19bd194493aThomas Graf 10744d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tbs[TCA_STATS_RATE_EST]) { 10844d362409d5469aed47d19e7908d19bd194493aThomas Graf struct gnet_stats_rate_est *re; 10944d362409d5469aed47d19e7908d19bd194493aThomas Graf 11044d362409d5469aed47d19e7908d19bd194493aThomas Graf re = nla_data(tbs[TCA_STATS_RATE_EST]); 11144d362409d5469aed47d19e7908d19bd194493aThomas Graf g->tc_stats[RTNL_TC_RATE_BPS] = re->bps; 11244d362409d5469aed47d19e7908d19bd194493aThomas Graf g->tc_stats[RTNL_TC_RATE_PPS] = re->pps; 11344d362409d5469aed47d19e7908d19bd194493aThomas Graf } 11444d362409d5469aed47d19e7908d19bd194493aThomas Graf 11544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tbs[TCA_STATS_QUEUE]) { 11644d362409d5469aed47d19e7908d19bd194493aThomas Graf struct gnet_stats_queue *q; 11744d362409d5469aed47d19e7908d19bd194493aThomas Graf 11844d362409d5469aed47d19e7908d19bd194493aThomas Graf q = nla_data(tbs[TCA_STATS_QUEUE]); 11944d362409d5469aed47d19e7908d19bd194493aThomas Graf g->tc_stats[RTNL_TC_QLEN] = q->qlen; 12044d362409d5469aed47d19e7908d19bd194493aThomas Graf g->tc_stats[RTNL_TC_BACKLOG] = q->backlog; 12144d362409d5469aed47d19e7908d19bd194493aThomas Graf g->tc_stats[RTNL_TC_DROPS] = q->drops; 12244d362409d5469aed47d19e7908d19bd194493aThomas Graf g->tc_stats[RTNL_TC_REQUEUES] = q->requeues; 12344d362409d5469aed47d19e7908d19bd194493aThomas Graf g->tc_stats[RTNL_TC_OVERLIMITS] = q->overlimits; 12444d362409d5469aed47d19e7908d19bd194493aThomas Graf } 12544d362409d5469aed47d19e7908d19bd194493aThomas Graf 12644d362409d5469aed47d19e7908d19bd194493aThomas Graf g->ce_mask |= TCA_ATTR_STATS; 12744d362409d5469aed47d19e7908d19bd194493aThomas Graf 12844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tbs[TCA_STATS_APP]) { 129eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf g->tc_xstats = nl_data_alloc_attr(tbs[TCA_STATS_APP]); 13044d362409d5469aed47d19e7908d19bd194493aThomas Graf if (g->tc_xstats == NULL) 1318a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_NOMEM; 13244d362409d5469aed47d19e7908d19bd194493aThomas Graf } else 13344d362409d5469aed47d19e7908d19bd194493aThomas Graf goto compat_xstats; 13444d362409d5469aed47d19e7908d19bd194493aThomas Graf } else { 13544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[TCA_STATS]) { 13644d362409d5469aed47d19e7908d19bd194493aThomas Graf struct tc_stats *st = nla_data(tb[TCA_STATS]); 13744d362409d5469aed47d19e7908d19bd194493aThomas Graf 13844d362409d5469aed47d19e7908d19bd194493aThomas Graf g->tc_stats[RTNL_TC_BYTES] = st->bytes; 13944d362409d5469aed47d19e7908d19bd194493aThomas Graf g->tc_stats[RTNL_TC_PACKETS] = st->packets; 14044d362409d5469aed47d19e7908d19bd194493aThomas Graf g->tc_stats[RTNL_TC_RATE_BPS] = st->bps; 14144d362409d5469aed47d19e7908d19bd194493aThomas Graf g->tc_stats[RTNL_TC_RATE_PPS] = st->pps; 14244d362409d5469aed47d19e7908d19bd194493aThomas Graf g->tc_stats[RTNL_TC_QLEN] = st->qlen; 14344d362409d5469aed47d19e7908d19bd194493aThomas Graf g->tc_stats[RTNL_TC_BACKLOG] = st->backlog; 14444d362409d5469aed47d19e7908d19bd194493aThomas Graf g->tc_stats[RTNL_TC_DROPS] = st->drops; 14544d362409d5469aed47d19e7908d19bd194493aThomas Graf g->tc_stats[RTNL_TC_OVERLIMITS] = st->overlimits; 14644d362409d5469aed47d19e7908d19bd194493aThomas Graf 14744d362409d5469aed47d19e7908d19bd194493aThomas Graf g->ce_mask |= TCA_ATTR_STATS; 14844d362409d5469aed47d19e7908d19bd194493aThomas Graf } 14944d362409d5469aed47d19e7908d19bd194493aThomas Graf 15044d362409d5469aed47d19e7908d19bd194493aThomas Grafcompat_xstats: 15144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tb[TCA_XSTATS]) { 152eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf g->tc_xstats = nl_data_alloc_attr(tb[TCA_XSTATS]); 15344d362409d5469aed47d19e7908d19bd194493aThomas Graf if (g->tc_xstats == NULL) 1548a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_NOMEM; 15544d362409d5469aed47d19e7908d19bd194493aThomas Graf g->ce_mask |= TCA_ATTR_XSTATS; 15644d362409d5469aed47d19e7908d19bd194493aThomas Graf } 15744d362409d5469aed47d19e7908d19bd194493aThomas Graf } 15844d362409d5469aed47d19e7908d19bd194493aThomas Graf 15944d362409d5469aed47d19e7908d19bd194493aThomas Graf 16044d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 16144d362409d5469aed47d19e7908d19bd194493aThomas Graf} 16244d362409d5469aed47d19e7908d19bd194493aThomas Graf 16344d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid tca_free_data(struct rtnl_tca *tca) 16444d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 16544d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_data_free(tca->tc_opts); 16644d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_data_free(tca->tc_xstats); 16744d362409d5469aed47d19e7908d19bd194493aThomas Graf} 16844d362409d5469aed47d19e7908d19bd194493aThomas Graf 16944d362409d5469aed47d19e7908d19bd194493aThomas Grafint tca_clone(struct rtnl_tca *dst, struct rtnl_tca *src) 17044d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 17144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (src->tc_opts) { 17244d362409d5469aed47d19e7908d19bd194493aThomas Graf dst->tc_opts = nl_data_clone(src->tc_opts); 17344d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!dst->tc_opts) 1748a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_NOMEM; 17544d362409d5469aed47d19e7908d19bd194493aThomas Graf } 17644d362409d5469aed47d19e7908d19bd194493aThomas Graf 17744d362409d5469aed47d19e7908d19bd194493aThomas Graf if (src->tc_xstats) { 17844d362409d5469aed47d19e7908d19bd194493aThomas Graf dst->tc_xstats = nl_data_clone(src->tc_xstats); 17944d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!dst->tc_xstats) 1808a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_NOMEM; 18144d362409d5469aed47d19e7908d19bd194493aThomas Graf } 18244d362409d5469aed47d19e7908d19bd194493aThomas Graf 18344d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 18444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 18544d362409d5469aed47d19e7908d19bd194493aThomas Graf 18644d362409d5469aed47d19e7908d19bd194493aThomas Grafint tca_dump_brief(struct rtnl_tca *g, const char *type, 18744d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_dump_params *p, int line) 18844d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 18944d362409d5469aed47d19e7908d19bd194493aThomas Graf char handle[32], parent[32]; 19044d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_cache *link_cache; 19144d362409d5469aed47d19e7908d19bd194493aThomas Graf 19244d362409d5469aed47d19e7908d19bd194493aThomas Graf link_cache = nl_cache_mngt_require("route/link"); 19344d362409d5469aed47d19e7908d19bd194493aThomas Graf 19444d362409d5469aed47d19e7908d19bd194493aThomas Graf dp_dump(p, "%s %s ", g->tc_kind, type); 19544d362409d5469aed47d19e7908d19bd194493aThomas Graf 19644d362409d5469aed47d19e7908d19bd194493aThomas Graf if (link_cache) { 19744d362409d5469aed47d19e7908d19bd194493aThomas Graf char buf[32]; 19844d362409d5469aed47d19e7908d19bd194493aThomas Graf dp_dump(p, "dev %s ", 19944d362409d5469aed47d19e7908d19bd194493aThomas Graf rtnl_link_i2name(link_cache, g->tc_ifindex, 20044d362409d5469aed47d19e7908d19bd194493aThomas Graf buf, sizeof(buf))); 20144d362409d5469aed47d19e7908d19bd194493aThomas Graf } else 20244d362409d5469aed47d19e7908d19bd194493aThomas Graf dp_dump(p, "dev %u ", g->tc_ifindex); 20344d362409d5469aed47d19e7908d19bd194493aThomas Graf 20444d362409d5469aed47d19e7908d19bd194493aThomas Graf dp_dump(p, "handle %s parent %s", 20544d362409d5469aed47d19e7908d19bd194493aThomas Graf rtnl_tc_handle2str(g->tc_handle, handle, sizeof(handle)), 20644d362409d5469aed47d19e7908d19bd194493aThomas Graf rtnl_tc_handle2str(g->tc_parent, parent, sizeof(parent))); 20744d362409d5469aed47d19e7908d19bd194493aThomas Graf 20844d362409d5469aed47d19e7908d19bd194493aThomas Graf return 1; 20944d362409d5469aed47d19e7908d19bd194493aThomas Graf} 21044d362409d5469aed47d19e7908d19bd194493aThomas Graf 21144d362409d5469aed47d19e7908d19bd194493aThomas Grafint tca_dump_full(struct rtnl_tca *g, struct nl_dump_params *p, int line) 21244d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 21344d362409d5469aed47d19e7908d19bd194493aThomas Graf dp_dump_line(p, line++, " "); 21444d362409d5469aed47d19e7908d19bd194493aThomas Graf return line; 21544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 21644d362409d5469aed47d19e7908d19bd194493aThomas Graf 21744d362409d5469aed47d19e7908d19bd194493aThomas Grafint tca_dump_stats(struct rtnl_tca *g, struct nl_dump_params *p, int line) 21844d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 21944d362409d5469aed47d19e7908d19bd194493aThomas Graf char *unit, fmt[64]; 22044d362409d5469aed47d19e7908d19bd194493aThomas Graf float res; 22144d362409d5469aed47d19e7908d19bd194493aThomas Graf strcpy(fmt, " %7.2f %s %10u %10u %10u %10u %10u\n"); 22244d362409d5469aed47d19e7908d19bd194493aThomas Graf 22344d362409d5469aed47d19e7908d19bd194493aThomas Graf dp_dump_line(p, line++, 22444d362409d5469aed47d19e7908d19bd194493aThomas Graf " Stats: bytes packets drops overlimits" \ 22544d362409d5469aed47d19e7908d19bd194493aThomas Graf " qlen backlog\n"); 22644d362409d5469aed47d19e7908d19bd194493aThomas Graf 22744d362409d5469aed47d19e7908d19bd194493aThomas Graf res = nl_cancel_down_bytes(g->tc_stats[RTNL_TC_BYTES], &unit); 22844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (*unit == 'B') 22944d362409d5469aed47d19e7908d19bd194493aThomas Graf fmt[11] = '9'; 23044d362409d5469aed47d19e7908d19bd194493aThomas Graf 23144d362409d5469aed47d19e7908d19bd194493aThomas Graf dp_dump_line(p, line++, fmt, res, unit, 23244d362409d5469aed47d19e7908d19bd194493aThomas Graf g->tc_stats[RTNL_TC_PACKETS], 23344d362409d5469aed47d19e7908d19bd194493aThomas Graf g->tc_stats[RTNL_TC_DROPS], 23444d362409d5469aed47d19e7908d19bd194493aThomas Graf g->tc_stats[RTNL_TC_OVERLIMITS], 23544d362409d5469aed47d19e7908d19bd194493aThomas Graf g->tc_stats[RTNL_TC_QLEN], 23644d362409d5469aed47d19e7908d19bd194493aThomas Graf g->tc_stats[RTNL_TC_BACKLOG]); 23744d362409d5469aed47d19e7908d19bd194493aThomas Graf 23844d362409d5469aed47d19e7908d19bd194493aThomas Graf res = nl_cancel_down_bytes(g->tc_stats[RTNL_TC_RATE_BPS], &unit); 23944d362409d5469aed47d19e7908d19bd194493aThomas Graf 24044d362409d5469aed47d19e7908d19bd194493aThomas Graf strcpy(fmt, " %7.2f %s/s%9u pps"); 24144d362409d5469aed47d19e7908d19bd194493aThomas Graf 24244d362409d5469aed47d19e7908d19bd194493aThomas Graf if (*unit == 'B') 24344d362409d5469aed47d19e7908d19bd194493aThomas Graf fmt[11] = '9'; 24444d362409d5469aed47d19e7908d19bd194493aThomas Graf 24544d362409d5469aed47d19e7908d19bd194493aThomas Graf dp_dump_line(p, line++, fmt, res, unit, g->tc_stats[RTNL_TC_RATE_PPS]); 24644d362409d5469aed47d19e7908d19bd194493aThomas Graf 24744d362409d5469aed47d19e7908d19bd194493aThomas Graf return line; 24844d362409d5469aed47d19e7908d19bd194493aThomas Graf} 24944d362409d5469aed47d19e7908d19bd194493aThomas Graf 25044d362409d5469aed47d19e7908d19bd194493aThomas Grafint tca_compare(struct nl_object *_a, struct nl_object *_b, 25144d362409d5469aed47d19e7908d19bd194493aThomas Graf uint32_t attrs, int flags) 25244d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 25344d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_tca *a = (struct rtnl_tca *) _a; 25444d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_tca *b = (struct rtnl_tca *) _b; 25544d362409d5469aed47d19e7908d19bd194493aThomas Graf int diff = 0; 25644d362409d5469aed47d19e7908d19bd194493aThomas Graf 25744d362409d5469aed47d19e7908d19bd194493aThomas Graf#define TC_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, TCA_ATTR_##ATTR, a, b, EXPR) 25844d362409d5469aed47d19e7908d19bd194493aThomas Graf 25944d362409d5469aed47d19e7908d19bd194493aThomas Graf diff |= TC_DIFF(HANDLE, a->tc_handle != b->tc_handle); 26044d362409d5469aed47d19e7908d19bd194493aThomas Graf diff |= TC_DIFF(PARENT, a->tc_parent != b->tc_parent); 26144d362409d5469aed47d19e7908d19bd194493aThomas Graf diff |= TC_DIFF(IFINDEX, a->tc_ifindex != b->tc_ifindex); 26244d362409d5469aed47d19e7908d19bd194493aThomas Graf diff |= TC_DIFF(KIND, strcmp(a->tc_kind, b->tc_kind)); 26344d362409d5469aed47d19e7908d19bd194493aThomas Graf 26444d362409d5469aed47d19e7908d19bd194493aThomas Graf#undef TC_DIFF 26544d362409d5469aed47d19e7908d19bd194493aThomas Graf 26644d362409d5469aed47d19e7908d19bd194493aThomas Graf return diff; 26744d362409d5469aed47d19e7908d19bd194493aThomas Graf} 26844d362409d5469aed47d19e7908d19bd194493aThomas Graf 26944d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid tca_set_ifindex(struct rtnl_tca *t, int ifindex) 27044d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 27144d362409d5469aed47d19e7908d19bd194493aThomas Graf t->tc_ifindex = ifindex; 27244d362409d5469aed47d19e7908d19bd194493aThomas Graf t->ce_mask |= TCA_ATTR_IFINDEX; 27344d362409d5469aed47d19e7908d19bd194493aThomas Graf} 27444d362409d5469aed47d19e7908d19bd194493aThomas Graf 27544d362409d5469aed47d19e7908d19bd194493aThomas Grafint tca_get_ifindex(struct rtnl_tca *t) 27644d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 277b4fbe1d34d6f54045b5c6236d86aacd4340ec83dThomas Graf return t->tc_ifindex; 27844d362409d5469aed47d19e7908d19bd194493aThomas Graf} 27944d362409d5469aed47d19e7908d19bd194493aThomas Graf 28044d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid tca_set_handle(struct rtnl_tca *t, uint32_t handle) 28144d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 28244d362409d5469aed47d19e7908d19bd194493aThomas Graf t->tc_handle = handle; 28344d362409d5469aed47d19e7908d19bd194493aThomas Graf t->ce_mask |= TCA_ATTR_HANDLE; 28444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 28544d362409d5469aed47d19e7908d19bd194493aThomas Graf 28644d362409d5469aed47d19e7908d19bd194493aThomas Grafuint32_t tca_get_handle(struct rtnl_tca *t) 28744d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 28844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (t->ce_mask & TCA_ATTR_HANDLE) 28944d362409d5469aed47d19e7908d19bd194493aThomas Graf return t->tc_handle; 29044d362409d5469aed47d19e7908d19bd194493aThomas Graf else 29144d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 29244d362409d5469aed47d19e7908d19bd194493aThomas Graf} 29344d362409d5469aed47d19e7908d19bd194493aThomas Graf 29444d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid tca_set_parent(struct rtnl_tca *t, uint32_t parent) 29544d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 29644d362409d5469aed47d19e7908d19bd194493aThomas Graf t->tc_parent = parent; 29744d362409d5469aed47d19e7908d19bd194493aThomas Graf t->ce_mask |= TCA_ATTR_PARENT; 29844d362409d5469aed47d19e7908d19bd194493aThomas Graf} 29944d362409d5469aed47d19e7908d19bd194493aThomas Graf 30044d362409d5469aed47d19e7908d19bd194493aThomas Grafuint32_t tca_get_parent(struct rtnl_tca *t) 30144d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 30244d362409d5469aed47d19e7908d19bd194493aThomas Graf if (t->ce_mask & TCA_ATTR_PARENT) 30344d362409d5469aed47d19e7908d19bd194493aThomas Graf return t->tc_parent; 30444d362409d5469aed47d19e7908d19bd194493aThomas Graf else 30544d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 30644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 30744d362409d5469aed47d19e7908d19bd194493aThomas Graf 30844d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid tca_set_kind(struct rtnl_tca *t, const char *kind) 30944d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 31044d362409d5469aed47d19e7908d19bd194493aThomas Graf strncpy(t->tc_kind, kind, sizeof(t->tc_kind) - 1); 31144d362409d5469aed47d19e7908d19bd194493aThomas Graf t->ce_mask |= TCA_ATTR_KIND; 31244d362409d5469aed47d19e7908d19bd194493aThomas Graf} 31344d362409d5469aed47d19e7908d19bd194493aThomas Graf 31444d362409d5469aed47d19e7908d19bd194493aThomas Grafchar *tca_get_kind(struct rtnl_tca *t) 31544d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 31644d362409d5469aed47d19e7908d19bd194493aThomas Graf if (t->ce_mask & TCA_ATTR_KIND) 31744d362409d5469aed47d19e7908d19bd194493aThomas Graf return t->tc_kind; 31844d362409d5469aed47d19e7908d19bd194493aThomas Graf else 31944d362409d5469aed47d19e7908d19bd194493aThomas Graf return NULL; 32044d362409d5469aed47d19e7908d19bd194493aThomas Graf} 32144d362409d5469aed47d19e7908d19bd194493aThomas Graf 32244d362409d5469aed47d19e7908d19bd194493aThomas Grafuint64_t tca_get_stat(struct rtnl_tca *t, int id) 32344d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 32444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (id < 0 || id > RTNL_TC_STATS_MAX) 32544d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 32644d362409d5469aed47d19e7908d19bd194493aThomas Graf 32744d362409d5469aed47d19e7908d19bd194493aThomas Graf return t->tc_stats[id]; 32844d362409d5469aed47d19e7908d19bd194493aThomas Graf} 32944d362409d5469aed47d19e7908d19bd194493aThomas Graf 3308a3efffa5b3fde252675239914118664d36a2c24Thomas Grafint tca_build_msg(struct rtnl_tca *tca, int type, int flags, 3318a3efffa5b3fde252675239914118664d36a2c24Thomas Graf struct nl_msg **result) 33244d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 33344d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_msg *msg; 33444d362409d5469aed47d19e7908d19bd194493aThomas Graf struct tcmsg tchdr = { 33544d362409d5469aed47d19e7908d19bd194493aThomas Graf .tcm_family = AF_UNSPEC, 33644d362409d5469aed47d19e7908d19bd194493aThomas Graf .tcm_ifindex = tca->tc_ifindex, 33744d362409d5469aed47d19e7908d19bd194493aThomas Graf .tcm_handle = tca->tc_handle, 33844d362409d5469aed47d19e7908d19bd194493aThomas Graf .tcm_parent = tca->tc_parent, 33944d362409d5469aed47d19e7908d19bd194493aThomas Graf }; 34044d362409d5469aed47d19e7908d19bd194493aThomas Graf 34144d362409d5469aed47d19e7908d19bd194493aThomas Graf msg = nlmsg_alloc_simple(type, flags); 34244d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!msg) 3438a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_NOMEM; 34444d362409d5469aed47d19e7908d19bd194493aThomas Graf 34544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (nlmsg_append(msg, &tchdr, sizeof(tchdr), NLMSG_ALIGNTO) < 0) 34644d362409d5469aed47d19e7908d19bd194493aThomas Graf goto nla_put_failure; 34744d362409d5469aed47d19e7908d19bd194493aThomas Graf 34844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (tca->ce_mask & TCA_ATTR_KIND) 34944d362409d5469aed47d19e7908d19bd194493aThomas Graf NLA_PUT_STRING(msg, TCA_KIND, tca->tc_kind); 35044d362409d5469aed47d19e7908d19bd194493aThomas Graf 3518a3efffa5b3fde252675239914118664d36a2c24Thomas Graf *result = msg; 3528a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return 0; 35344d362409d5469aed47d19e7908d19bd194493aThomas Graf 35444d362409d5469aed47d19e7908d19bd194493aThomas Grafnla_put_failure: 35544d362409d5469aed47d19e7908d19bd194493aThomas Graf nlmsg_free(msg); 3568a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_MSGSIZE; 35744d362409d5469aed47d19e7908d19bd194493aThomas Graf} 35844d362409d5469aed47d19e7908d19bd194493aThomas Graf 35944d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @endcond */ 36044d362409d5469aed47d19e7908d19bd194493aThomas Graf 36144d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 36244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Utilities 36344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 36444d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 36544d362409d5469aed47d19e7908d19bd194493aThomas Graf 36644d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 36744d362409d5469aed47d19e7908d19bd194493aThomas Graf * Calculate time required to transmit buffer at a specific rate 36844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg bufsize Size of buffer to be transmited in bytes. 36944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg rate Transmit rate in bytes per second. 37044d362409d5469aed47d19e7908d19bd194493aThomas Graf * 37144d362409d5469aed47d19e7908d19bd194493aThomas Graf * Calculates the number of micro seconds required to transmit a 37244d362409d5469aed47d19e7908d19bd194493aThomas Graf * specific buffer at a specific transmit rate. 37344d362409d5469aed47d19e7908d19bd194493aThomas Graf * 37444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @f[ 37544d362409d5469aed47d19e7908d19bd194493aThomas Graf * txtime=\frac{bufsize}{rate}10^6 37644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @f] 37744d362409d5469aed47d19e7908d19bd194493aThomas Graf * 37844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return Required transmit time in micro seconds. 37944d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 38044d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_tc_calc_txtime(int bufsize, int rate) 38144d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 38244d362409d5469aed47d19e7908d19bd194493aThomas Graf double tx_time_secs; 38344d362409d5469aed47d19e7908d19bd194493aThomas Graf 38444d362409d5469aed47d19e7908d19bd194493aThomas Graf tx_time_secs = (double) bufsize / (double) rate; 38544d362409d5469aed47d19e7908d19bd194493aThomas Graf 38644d362409d5469aed47d19e7908d19bd194493aThomas Graf return tx_time_secs * 1000000.; 38744d362409d5469aed47d19e7908d19bd194493aThomas Graf} 38844d362409d5469aed47d19e7908d19bd194493aThomas Graf 38944d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 39044d362409d5469aed47d19e7908d19bd194493aThomas Graf * Calculate buffer size able to transmit in a specific time and rate. 39144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg txtime Available transmit time in micro seconds. 39244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg rate Transmit rate in bytes per second. 39344d362409d5469aed47d19e7908d19bd194493aThomas Graf * 39444d362409d5469aed47d19e7908d19bd194493aThomas Graf * Calculates the size of the buffer that can be transmitted in a 39544d362409d5469aed47d19e7908d19bd194493aThomas Graf * specific time period at a specific transmit rate. 39644d362409d5469aed47d19e7908d19bd194493aThomas Graf * 39744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @f[ 39844d362409d5469aed47d19e7908d19bd194493aThomas Graf * bufsize=\frac{{txtime} \times {rate}}{10^6} 39944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @f] 40044d362409d5469aed47d19e7908d19bd194493aThomas Graf * 40144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return Size of buffer in bytes. 40244d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 40344d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_tc_calc_bufsize(int txtime, int rate) 40444d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 40544d362409d5469aed47d19e7908d19bd194493aThomas Graf double bufsize; 40644d362409d5469aed47d19e7908d19bd194493aThomas Graf 40744d362409d5469aed47d19e7908d19bd194493aThomas Graf bufsize = (double) txtime * (double) rate; 40844d362409d5469aed47d19e7908d19bd194493aThomas Graf 40944d362409d5469aed47d19e7908d19bd194493aThomas Graf return bufsize / 1000000.; 41044d362409d5469aed47d19e7908d19bd194493aThomas Graf} 41144d362409d5469aed47d19e7908d19bd194493aThomas Graf 41244d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 41344d362409d5469aed47d19e7908d19bd194493aThomas Graf * Calculate the binary logarithm for a specific cell size 41444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg cell_size Size of cell, must be a power of two. 41544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return Binary logirhtm of cell size or a negative error code. 41644d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 41744d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_tc_calc_cell_log(int cell_size) 41844d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 41944d362409d5469aed47d19e7908d19bd194493aThomas Graf int i; 42044d362409d5469aed47d19e7908d19bd194493aThomas Graf 42144d362409d5469aed47d19e7908d19bd194493aThomas Graf for (i = 0; i < 32; i++) 42244d362409d5469aed47d19e7908d19bd194493aThomas Graf if ((1 << i) == cell_size) 42344d362409d5469aed47d19e7908d19bd194493aThomas Graf return i; 42444d362409d5469aed47d19e7908d19bd194493aThomas Graf 4258a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_INVAL; 42644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 42744d362409d5469aed47d19e7908d19bd194493aThomas Graf 42844d362409d5469aed47d19e7908d19bd194493aThomas Graf 42944d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 43044d362409d5469aed47d19e7908d19bd194493aThomas Graf 43144d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 43244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Rate Tables 43344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 43444d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 43544d362409d5469aed47d19e7908d19bd194493aThomas Graf 43644d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 43744d362409d5469aed47d19e7908d19bd194493aThomas Graf * Compute a transmission time lookup table 43844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg dst Destination buffer of RTNL_TC_RTABLE_SIZE uint32_t[]. 43944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg mpu Minimal size of a packet at all times. 44044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg overhead Overhead to be added to each packet. 44144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg cell Size of cell, i.e. size of step between entries in bytes. 44244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg rate Rate in bytes per second. 44344d362409d5469aed47d19e7908d19bd194493aThomas Graf * 44444d362409d5469aed47d19e7908d19bd194493aThomas Graf * Computes a table of RTNL_TC_RTABLE_SIZE entries specyfing the 44544d362409d5469aed47d19e7908d19bd194493aThomas Graf * transmission times for various packet sizes, e.g. the transmission 44644d362409d5469aed47d19e7908d19bd194493aThomas Graf * time for a packet of size \c pktsize could be looked up: 44744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @code 44844d362409d5469aed47d19e7908d19bd194493aThomas Graf * txtime = table[pktsize >> log2(cell)]; 44944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @endcode 45044d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 45144d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_tc_build_rate_table(uint32_t *dst, uint8_t mpu, uint8_t overhead, 45244d362409d5469aed47d19e7908d19bd194493aThomas Graf int cell, int rate) 45344d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 45444d362409d5469aed47d19e7908d19bd194493aThomas Graf int i, size, cell_log; 45544d362409d5469aed47d19e7908d19bd194493aThomas Graf 45644d362409d5469aed47d19e7908d19bd194493aThomas Graf cell_log = rtnl_tc_calc_cell_log(cell); 45744d362409d5469aed47d19e7908d19bd194493aThomas Graf if (cell_log < 0) 45844d362409d5469aed47d19e7908d19bd194493aThomas Graf return cell_log; 45944d362409d5469aed47d19e7908d19bd194493aThomas Graf 46044d362409d5469aed47d19e7908d19bd194493aThomas Graf for (i = 0; i < RTNL_TC_RTABLE_SIZE; i++) { 46144d362409d5469aed47d19e7908d19bd194493aThomas Graf size = (i << cell_log) + overhead; 46244d362409d5469aed47d19e7908d19bd194493aThomas Graf if (size < mpu) 46344d362409d5469aed47d19e7908d19bd194493aThomas Graf size = mpu; 46444d362409d5469aed47d19e7908d19bd194493aThomas Graf 46544d362409d5469aed47d19e7908d19bd194493aThomas Graf dst[i] = rtnl_tc_calc_txtime(size, rate); 46644d362409d5469aed47d19e7908d19bd194493aThomas Graf } 46744d362409d5469aed47d19e7908d19bd194493aThomas Graf 46844d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 46944d362409d5469aed47d19e7908d19bd194493aThomas Graf} 47044d362409d5469aed47d19e7908d19bd194493aThomas Graf 47144d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 47244d362409d5469aed47d19e7908d19bd194493aThomas Graf 47344d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 47444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Traffic Control Handle Translations 47544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 47644d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 47744d362409d5469aed47d19e7908d19bd194493aThomas Graf 47844d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 47944d362409d5469aed47d19e7908d19bd194493aThomas Graf * Convert a traffic control handle to a character string (Reentrant). 48044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg handle traffic control handle 48144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg buf destination buffer 48244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg len buffer length 48344d362409d5469aed47d19e7908d19bd194493aThomas Graf * 48444d362409d5469aed47d19e7908d19bd194493aThomas Graf * Converts a tarffic control handle to a character string in the 48544d362409d5469aed47d19e7908d19bd194493aThomas Graf * form of \c MAJ:MIN and stores it in the specified destination buffer. 48644d362409d5469aed47d19e7908d19bd194493aThomas Graf * 48744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return The destination buffer or the type encoded in hexidecimal 48844d362409d5469aed47d19e7908d19bd194493aThomas Graf * form if no match was found. 48944d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 49044d362409d5469aed47d19e7908d19bd194493aThomas Grafchar * rtnl_tc_handle2str(uint32_t handle, char *buf, size_t len) 49144d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 49244d362409d5469aed47d19e7908d19bd194493aThomas Graf if (TC_H_ROOT == handle) 49344d362409d5469aed47d19e7908d19bd194493aThomas Graf snprintf(buf, len, "root"); 49444d362409d5469aed47d19e7908d19bd194493aThomas Graf else if (TC_H_UNSPEC == handle) 49544d362409d5469aed47d19e7908d19bd194493aThomas Graf snprintf(buf, len, "none"); 49644d362409d5469aed47d19e7908d19bd194493aThomas Graf else if (0 == TC_H_MAJ(handle)) 49744d362409d5469aed47d19e7908d19bd194493aThomas Graf snprintf(buf, len, ":%02x", TC_H_MIN(handle)); 49844d362409d5469aed47d19e7908d19bd194493aThomas Graf else if (0 == TC_H_MIN(handle)) 49944d362409d5469aed47d19e7908d19bd194493aThomas Graf snprintf(buf, len, "%02x:", TC_H_MAJ(handle) >> 16); 50044d362409d5469aed47d19e7908d19bd194493aThomas Graf else 50144d362409d5469aed47d19e7908d19bd194493aThomas Graf snprintf(buf, len, "%02x:%02x", 50244d362409d5469aed47d19e7908d19bd194493aThomas Graf TC_H_MAJ(handle) >> 16, TC_H_MIN(handle)); 50344d362409d5469aed47d19e7908d19bd194493aThomas Graf 50444d362409d5469aed47d19e7908d19bd194493aThomas Graf return buf; 50544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 50644d362409d5469aed47d19e7908d19bd194493aThomas Graf 50744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 50844d362409d5469aed47d19e7908d19bd194493aThomas Graf * Convert a charactering strint to a traffic control handle 50944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg name traffic control handle as character string 51044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg res destination buffer 51144d362409d5469aed47d19e7908d19bd194493aThomas Graf * 51244d362409d5469aed47d19e7908d19bd194493aThomas Graf * Converts the provided character string specifying a traffic 51344d362409d5469aed47d19e7908d19bd194493aThomas Graf * control handle to the corresponding numeric value. 51444d362409d5469aed47d19e7908d19bd194493aThomas Graf * 51544d362409d5469aed47d19e7908d19bd194493aThomas Graf * The handle must be provided in one of the following formats: 51644d362409d5469aed47d19e7908d19bd194493aThomas Graf * - root 51744d362409d5469aed47d19e7908d19bd194493aThomas Graf * - none 51844d362409d5469aed47d19e7908d19bd194493aThomas Graf * - XXXX: 51944d362409d5469aed47d19e7908d19bd194493aThomas Graf * - :YYYY 52044d362409d5469aed47d19e7908d19bd194493aThomas Graf * - XXXX:YYYY 52144d362409d5469aed47d19e7908d19bd194493aThomas Graf * - XXXXYYYY 52244d362409d5469aed47d19e7908d19bd194493aThomas Graf * 52344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return 0 on success or a negative error code 52444d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 52544d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_tc_str2handle(const char *name, uint32_t *res) 52644d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 52744d362409d5469aed47d19e7908d19bd194493aThomas Graf char *colon, *end; 52844d362409d5469aed47d19e7908d19bd194493aThomas Graf uint32_t h; 52944d362409d5469aed47d19e7908d19bd194493aThomas Graf 53044d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!strcasecmp(name, "root")) { 53144d362409d5469aed47d19e7908d19bd194493aThomas Graf *res = TC_H_ROOT; 53244d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 53344d362409d5469aed47d19e7908d19bd194493aThomas Graf } 53444d362409d5469aed47d19e7908d19bd194493aThomas Graf 53544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!strcasecmp(name, "none")) { 53644d362409d5469aed47d19e7908d19bd194493aThomas Graf *res = TC_H_UNSPEC; 53744d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 53844d362409d5469aed47d19e7908d19bd194493aThomas Graf } 53944d362409d5469aed47d19e7908d19bd194493aThomas Graf 54044d362409d5469aed47d19e7908d19bd194493aThomas Graf h = strtoul(name, &colon, 16); 54144d362409d5469aed47d19e7908d19bd194493aThomas Graf 54244d362409d5469aed47d19e7908d19bd194493aThomas Graf if (colon == name) { 54344d362409d5469aed47d19e7908d19bd194493aThomas Graf /* :YYYY */ 54444d362409d5469aed47d19e7908d19bd194493aThomas Graf h = 0; 54544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (':' != *colon) 5468a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_INVAL; 54744d362409d5469aed47d19e7908d19bd194493aThomas Graf } 54844d362409d5469aed47d19e7908d19bd194493aThomas Graf 54944d362409d5469aed47d19e7908d19bd194493aThomas Graf if (':' == *colon) { 55044d362409d5469aed47d19e7908d19bd194493aThomas Graf /* check if we would lose bits */ 55144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (TC_H_MAJ(h)) 5528a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_RANGE; 55344d362409d5469aed47d19e7908d19bd194493aThomas Graf h <<= 16; 55444d362409d5469aed47d19e7908d19bd194493aThomas Graf 55544d362409d5469aed47d19e7908d19bd194493aThomas Graf if ('\0' == colon[1]) { 55644d362409d5469aed47d19e7908d19bd194493aThomas Graf /* XXXX: */ 55744d362409d5469aed47d19e7908d19bd194493aThomas Graf *res = h; 55844d362409d5469aed47d19e7908d19bd194493aThomas Graf } else { 55944d362409d5469aed47d19e7908d19bd194493aThomas Graf /* XXXX:YYYY */ 56044d362409d5469aed47d19e7908d19bd194493aThomas Graf uint32_t l = strtoul(colon+1, &end, 16); 56144d362409d5469aed47d19e7908d19bd194493aThomas Graf 56244d362409d5469aed47d19e7908d19bd194493aThomas Graf /* check if we overlap with major part */ 56344d362409d5469aed47d19e7908d19bd194493aThomas Graf if (TC_H_MAJ(l)) 5648a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_RANGE; 56544d362409d5469aed47d19e7908d19bd194493aThomas Graf 56644d362409d5469aed47d19e7908d19bd194493aThomas Graf if ('\0' != *end) 5678a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_INVAL; 56844d362409d5469aed47d19e7908d19bd194493aThomas Graf 56944d362409d5469aed47d19e7908d19bd194493aThomas Graf *res = (h | l); 57044d362409d5469aed47d19e7908d19bd194493aThomas Graf } 57144d362409d5469aed47d19e7908d19bd194493aThomas Graf } else if ('\0' == *colon) { 57244d362409d5469aed47d19e7908d19bd194493aThomas Graf /* XXXXYYYY */ 57344d362409d5469aed47d19e7908d19bd194493aThomas Graf *res = h; 57444d362409d5469aed47d19e7908d19bd194493aThomas Graf } else 5758a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_INVAL; 57644d362409d5469aed47d19e7908d19bd194493aThomas Graf 57744d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 57844d362409d5469aed47d19e7908d19bd194493aThomas Graf} 57944d362409d5469aed47d19e7908d19bd194493aThomas Graf 58044d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 58144d362409d5469aed47d19e7908d19bd194493aThomas Graf 58244d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 583