12#include "nl-default.h"
14#include <linux/gen_stats.h>
16#include <netlink/netlink.h>
17#include <netlink/utils.h>
18#include <netlink/route/link.h>
19#include <netlink/route/action.h>
23#include "nl-priv-dynamic-core/object-api.h"
24#include "nl-priv-dynamic-core/cache-api.h"
25#include "nl-aux-route/nl-route.h"
27static struct nl_object_ops act_obj_ops;
28static struct nl_cache_ops rtnl_act_ops;
50 while (p_act->a_next) {
52 p_act = p_act->a_next;
55 if (count > TCA_ACT_MAX_PRIO)
66 for (ap = head; (a = *ap) != NULL; ap = &a->a_next)
75 return -NLE_OBJ_NOTFOUND;
78static int rtnl_act_fill_one(
struct nl_msg *msg,
struct rtnl_act *act,
int order)
81 struct rtnl_tc_ops *ops;
89 if (tc->ce_mask & TCA_ATTR_KIND)
92 ops = rtnl_tc_get_ops(tc);
93 if (ops && (ops->to_msg_fill || ops->to_msg_fill_raw)) {
97 if (ops->to_msg_fill) {
101 if ((err = ops->to_msg_fill(tc, data, msg)) < 0)
102 goto nla_put_failure;
105 }
else if ((err = ops->to_msg_fill_raw(tc, data, msg)) < 0)
106 goto nla_put_failure;
115int rtnl_act_fill(
struct nl_msg *msg,
int attrtype,
struct rtnl_act *act)
126 err = rtnl_act_fill_one(msg, p_act, ++order);
129 p_act = p_act->a_next;
136static int rtnl_act_msg_build(
struct rtnl_act *act,
int type,
int flags,
137 struct nl_msg **result)
140 struct tcamsg tcahdr = {
141 .tca_family = AF_UNSPEC,
143 int err = -NLE_MSGSIZE;
149 if (
nlmsg_append(msg, &tcahdr,
sizeof(tcahdr), NLMSG_ALIGNTO) < 0)
150 goto nla_put_failure;
152 err = rtnl_act_fill(msg, TCA_ACT_TAB, act);
154 goto nla_put_failure;
164static int act_build(
struct rtnl_act *act,
int type,
int flags,
165 struct nl_msg **result)
169 err = rtnl_act_msg_build(act, type, flags, result);
180struct rtnl_act *rtnl_act_alloc(
void)
186 tc->tc_type = RTNL_TC_TYPE_ACT;
191void rtnl_act_get(
struct rtnl_act *act)
196void rtnl_act_put(
struct rtnl_act *act)
223 struct nl_msg **result)
225 return act_build(act, RTM_NEWACTION, flags, result);
286 struct nl_msg **result)
288 return act_build(act, RTM_NEWACTION, NLM_F_REPLACE | flags, result);
329 struct nl_msg **result)
331 return act_build(act, RTM_DELACTION, flags, result);
382void rtnl_act_put_all(
struct rtnl_act **head)
397 [TCA_STATS_QUEUE] = { .minlen =
sizeof(
struct gnet_stats_queue) },
398 [TCA_STATS_RATE_EST] = { .minlen =
sizeof(
struct gnet_stats_rate_est) },
399 [TCA_STATS_RATE_EST64] = { .minlen =
sizeof(
struct gnet_stats_rate_est64) },
402int rtnl_act_parse(
struct rtnl_act **head,
struct nlattr *tb)
404 _nl_auto_rtnl_act_all
struct rtnl_act *tmp_head = NULL;
405 struct rtnl_tc_ops *ops;
406 struct nlattr *tb2[TCA_ACT_MAX + 1];
407 struct nlattr *nla[TCA_ACT_MAX_PRIO + 1];
408 char kind[TCKINDSIZ];
412 NLMSG_ALIGN(
nla_len(tb)), NULL);
416 for (i = 0; i < TCA_ACT_MAX_PRIO; i++) {
417 _nl_auto_rtnl_act
struct rtnl_act *act = NULL;
423 act = rtnl_act_alloc();
433 if (tb2[TCA_ACT_KIND] == NULL)
434 return -NLE_MISSING_ATTR;
436 nla_strlcpy(kind, tb2[TCA_ACT_KIND],
sizeof(kind));
439 if (tb2[TCA_ACT_OPTIONS]) {
443 tc->ce_mask |= TCA_ATTR_OPTS;
446 if (tb2[TCA_ACT_STATS]) {
447 struct nlattr *tb3[TCA_STATS_MAX + 1];
450 tc_act_stats_policy);
454 if (tb3[TCA_STATS_BASIC]) {
455 struct gnet_stats_basic bs;
457 memcpy(&bs,
nla_data(tb3[TCA_STATS_BASIC]),
462 if (tb3[TCA_STATS_RATE_EST64]) {
463 struct gnet_stats_rate_est64 re;
465 memcpy(&re,
nla_data(tb3[TCA_STATS_RATE_EST64]),
469 }
else if (tb3[TCA_STATS_RATE_EST]) {
470 struct gnet_stats_rate_est *re;
472 re =
nla_data(tb3[TCA_STATS_RATE_EST]);
476 if (tb3[TCA_STATS_QUEUE]) {
477 struct gnet_stats_queue *q;
485 ops = rtnl_tc_get_ops(tc);
486 if (ops && ops->to_msg_parser) {
492 err = ops->to_msg_parser(tc, data);
496 err = _rtnl_act_append_take(&tmp_head, _nl_steal_pointer(&act));
501 *head = _nl_steal_pointer(&tmp_head);
505static int rtnl_act_msg_parse(
struct nlmsghdr *n,
struct rtnl_act **act)
508 struct nl_cache *link_cache;
509 struct nlattr *tb[TCAA_MAX + 1];
513 tc->ce_msgtype = n->nlmsg_type;
515 err =
nlmsg_parse(n,
sizeof(*tm), tb, TCAA_MAX, NULL);
520 tc->tc_family = tm->tca_family;
522 if (tb[TCA_ACT_TAB] == NULL)
523 return -NLE_MISSING_ATTR;
525 err = rtnl_act_parse(act, tb[TCA_ACT_TAB]);
529 if ((link_cache = __nl_cache_mngt_require(
"route/link"))) {
542static int act_msg_parser(
struct nl_cache_ops *ops,
struct sockaddr_nl *who,
543 struct nlmsghdr *nlh,
struct nl_parser_param *pp)
548 if (!(act = rtnl_act_alloc()))
551 if ((err = rtnl_act_msg_parse(nlh, &act)) < 0)
556 err = pp->pp_cb(OBJ_CAST(act), pp);
559 _nl_assert_not_reached();
564 p_act = p_act->a_next;
572static int act_request_update(
struct nl_cache *cache,
struct nl_sock *sk)
574 struct tcamsg tcahdr = {
575 .tca_family = AF_UNSPEC,
583 .tt_type = RTNL_TC_TYPE_ACT,
584 .tt_dump_prefix =
"act",
590static struct nl_cache_ops rtnl_act_ops = {
591 .co_name =
"route/act",
592 .co_hdrsize =
sizeof(
struct tcmsg),
594 { RTM_NEWACTION, NL_ACT_NEW,
"new" },
595 { RTM_DELACTION, NL_ACT_DEL,
"del" },
596 { RTM_GETACTION, NL_ACT_GET,
"get" },
597 END_OF_MSGTYPES_LIST,
599 .co_protocol = NETLINK_ROUTE,
600 .co_request_update = act_request_update,
601 .co_msg_parser = act_msg_parser,
602 .co_obj_ops = &act_obj_ops,
605static struct nl_object_ops act_obj_ops = {
606 .oo_name =
"route/act",
608 .oo_free_data = rtnl_tc_free_data,
609 .oo_clone = rtnl_tc_clone,
615 .oo_compare = rtnl_tc_compare,
616 .oo_id_attrs = (TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE),
619static void _nl_init act_init(
void)
621 rtnl_tc_type_register(&act_ops);
625static void _nl_exit act_exit(
void)
628 rtnl_tc_type_unregister(&act_ops);
int rtnl_act_change(struct nl_sock *sk, struct rtnl_act *act, int flags)
Change an action.
int rtnl_act_build_delete_request(struct rtnl_act *act, int flags, struct nl_msg **result)
Build netlink message requesting the deletion of an action.
int rtnl_act_build_add_request(struct rtnl_act *act, int flags, struct nl_msg **result)
Build a netlink message requesting the addition of an action.
int rtnl_act_delete(struct nl_sock *sk, struct rtnl_act *act, int flags)
Delete action.
int rtnl_act_add(struct nl_sock *sk, struct rtnl_act *act, int flags)
Add/Update action.
int rtnl_act_build_change_request(struct rtnl_act *act, int flags, struct nl_msg **result)
Build a netlink message to change action attributes.
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.
void * nla_data(const struct nlattr *nla)
Return pointer to the payload section.
struct nlattr * nla_nest_start(struct nl_msg *msg, int attrtype)
Start a new level of nested attributes.
size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize)
Copy string attribute payload to a buffer.
int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, const struct nla_policy *policy)
Create attribute index based on nested attribute.
int nla_len(const struct nlattr *nla)
Return length of the payload .
#define NLA_PUT_STRING(msg, attrtype, value)
Add string attribute to netlink message.
int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
Finalize nesting of attributes.
int nl_cache_mngt_unregister(struct nl_cache_ops *ops)
Unregister a set of cache operations.
int nl_cache_mngt_register(struct nl_cache_ops *ops)
Register a set of cache operations.
struct nl_data * nl_data_alloc_attr(const struct nlattr *nla)
Allocate abstract data object based on netlink attribute.
struct rtnl_link * rtnl_link_get(struct nl_cache *cache, int ifindex)
Lookup link in cache by interface index.
void rtnl_link_put(struct rtnl_link *link)
Release a link object reference.
struct nl_msg * nlmsg_alloc_simple(int nlmsgtype, int flags)
Allocate a new netlink message.
void * nlmsg_data(const struct nlmsghdr *nlh)
Return pointer to message payload.
void nlmsg_free(struct nl_msg *msg)
Release a reference from an netlink message.
int nlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], int maxtype, const struct nla_policy *policy)
parse attributes of a netlink message
int nlmsg_append(struct nl_msg *n, void *data, size_t len, int pad)
Append data to tail of a netlink message.
void nl_object_put(struct nl_object *obj)
Release a reference from an object.
void nl_object_get(struct nl_object *obj)
Acquire a reference on a object.
struct nl_object * nl_object_alloc(struct nl_object_ops *ops)
Allocate a new object of kind specified by the operations handle.
int nl_send_sync(struct nl_sock *sk, struct nl_msg *msg)
Finalize and transmit Netlink message and wait for ACK or error message.
int nl_send_simple(struct nl_sock *sk, int type, int flags, void *buf, size_t size)
Construct and transmit a Netlink message.
int rtnl_tc_set_kind(struct rtnl_tc *tc, const char *kind)
Define the type of traffic control object.
void rtnl_tc_set_link(struct rtnl_tc *tc, struct rtnl_link *link)
Set link of traffic control object.
#define TC_CAST(ptr)
Macro to cast qdisc/class/classifier to tc object.
void * rtnl_tc_data(struct rtnl_tc *)
Return pointer to private data of traffic control object.
@ RTNL_TC_PACKETS
Number of packets seen.
@ RTNL_TC_BYTES
Total bytes seen.
@ RTNL_TC_OVERLIMITS
Total number of overlimits.
@ RTNL_TC_DROPS
Total number of packets dropped.
@ RTNL_TC_RATE_PPS
Current packet/s (rate estimator)
@ RTNL_TC_RATE_BPS
Current bits/s (rate estimator)
@ NL_DUMP_STATS
Dump all attributes including statistics.
@ NL_DUMP_LINE
Dump object briefly on one line.
@ NL_DUMP_DETAILS
Dump all attributes but no statistics.
Attribute validation policy.
uint16_t minlen
Minimal length of payload required.
uint16_t type
Type of attribute or NLA_UNSPEC.