12#include "nl-default.h"
14#include <linux/ethtool.h>
16#include <netlink/netlink.h>
17#include <netlink/utils.h>
18#include <netlink/route/classifier.h>
19#include <netlink/route/link.h>
31#define CLS_ATTR_PRIO (TCA_ATTR_MAX << 1)
32#define CLS_ATTR_PROTOCOL (TCA_ATTR_MAX << 2)
35static struct nl_object_ops cls_obj_ops;
36static struct nl_cache_ops rtnl_cls_ops;
39static int cls_build(
struct rtnl_cls *cls,
int type,
int flags,
40 struct nl_msg **result)
44 uint32_t required = TCA_ATTR_IFINDEX;
46 if ((cls->ce_mask & required) != required) {
47 APPBUG(
"ifindex must be specified");
48 return -NLE_MISSING_ATTR;
51 err = rtnl_tc_msg_build(
TC_CAST(cls), type, flags, result);
56 prio = rtnl_cls_get_prio(cls);
57 proto = rtnl_cls_get_protocol(cls);
58 tchdr->tcm_info = TC_H_MAKE(prio << 16, htons(proto));
68struct rtnl_cls *rtnl_cls_alloc(
void)
74 tc->tc_type = RTNL_TC_TYPE_CLS;
76 return (
struct rtnl_cls *) tc;
79void rtnl_cls_put(
struct rtnl_cls *cls)
91void rtnl_cls_set_prio(
struct rtnl_cls *cls, uint16_t prio)
94 cls->ce_mask |= CLS_ATTR_PRIO;
97uint16_t rtnl_cls_get_prio(
struct rtnl_cls *cls)
99 if (cls->ce_mask & CLS_ATTR_PRIO)
105void rtnl_cls_set_protocol(
struct rtnl_cls *cls, uint16_t protocol)
107 cls->c_protocol = protocol;
108 cls->ce_mask |= CLS_ATTR_PROTOCOL;
111uint16_t rtnl_cls_get_protocol(
struct rtnl_cls *cls)
113 if (cls->ce_mask & CLS_ATTR_PROTOCOL)
114 return cls->c_protocol;
142 struct nl_msg **result)
144 if (!(flags & NLM_F_CREATE) && !(cls->ce_mask & CLS_ATTR_PRIO)) {
145 APPBUG(
"prio must be specified if not a new classifier");
146 return -NLE_MISSING_ATTR;
149 return cls_build(cls, RTM_NEWTFILTER, flags, result);
213 struct nl_msg **result)
215 return cls_build(cls, RTM_NEWTFILTER, NLM_F_REPLACE | flags, result);
256 struct nl_msg **result)
258 uint32_t required = CLS_ATTR_PRIO;
260 if ((cls->ce_mask & required) != required) {
261 APPBUG(
"prio must be specified");
262 return -NLE_MISSING_ATTR;
265 return cls_build(cls, RTM_DELTFILTER, flags, result);
332 struct nl_cache **result)
334 struct nl_cache * cache;
340 cache->c_iarg1 = ifindex;
341 cache->c_iarg2 = parent;
364 int ifindex, uint32_t parent)
366 cache->c_iarg1 = ifindex;
367 cache->c_iarg2 = parent;
389 struct rtnl_cls *cls;
391 if (cache->c_ops != &rtnl_cls_ops)
394 nl_list_for_each_entry(cls, &cache->c_items, ce_list) {
395 if ((cls->c_parent == parent) &&
396 (cls->c_ifindex == ifindex)&&
397 (cls->c_handle == handle)) {
423 uint32_t parent, uint16_t prio)
425 struct rtnl_cls *cls;
427 if (cache->c_ops != &rtnl_cls_ops)
430 nl_list_for_each_entry(cls, &cache->c_items, ce_list) {
431 if ((cls->c_parent == parent) &&
432 (cls->c_ifindex == ifindex) &&
433 (cls->c_prio == prio)) {
446 struct rtnl_cls *cls = (
struct rtnl_cls *) tc;
449 nl_dump(p,
" prio %u protocol %s", cls->c_prio,
450 nl_ether_proto2str(cls->c_protocol, buf,
sizeof(buf)));
453static int cls_msg_parser(
struct nl_cache_ops *ops,
struct sockaddr_nl *who,
454 struct nlmsghdr *nlh,
struct nl_parser_param *pp)
456 struct rtnl_cls *cls;
459 if (!(cls = rtnl_cls_alloc()))
462 if ((err = rtnl_tc_msg_parse(nlh,
TC_CAST(cls))) < 0)
465 cls->c_prio = TC_H_MAJ(cls->c_info) >> 16;
467 cls->ce_mask |= CLS_ATTR_PRIO;
468 cls->c_protocol = ntohs(TC_H_MIN(cls->c_info));
470 cls->ce_mask |= CLS_ATTR_PROTOCOL;
472 err = pp->pp_cb(OBJ_CAST(cls), pp);
479static int cls_request_update(
struct nl_cache *cache,
struct nl_sock *sk)
481 struct tcmsg tchdr = {
482 .tcm_family = AF_UNSPEC,
483 .tcm_ifindex = cache->c_iarg1,
484 .tcm_parent = cache->c_iarg2,
492 .tt_type = RTNL_TC_TYPE_CLS,
493 .tt_dump_prefix =
"cls",
499static struct nl_cache_ops rtnl_cls_ops = {
500 .co_name =
"route/cls",
501 .co_hdrsize =
sizeof(
struct tcmsg),
503 { RTM_NEWTFILTER, NL_ACT_NEW,
"new" },
504 { RTM_DELTFILTER, NL_ACT_DEL,
"del" },
505 { RTM_GETTFILTER, NL_ACT_GET,
"get" },
506 END_OF_MSGTYPES_LIST,
508 .co_protocol = NETLINK_ROUTE,
509 .co_groups = tc_groups,
510 .co_request_update = cls_request_update,
511 .co_msg_parser = cls_msg_parser,
512 .co_obj_ops = &cls_obj_ops,
515static struct nl_object_ops cls_obj_ops = {
516 .oo_name =
"route/cls",
517 .oo_size =
sizeof(
struct rtnl_cls),
518 .oo_free_data = rtnl_tc_free_data,
519 .oo_clone = rtnl_tc_clone,
525 .oo_compare = rtnl_tc_compare,
526 .oo_id_attrs = (TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE),
529static void _nl_init cls_init(
void)
531 rtnl_tc_type_register(&cls_ops);
535static void _nl_exit cls_exit(
void)
538 rtnl_tc_type_unregister(&cls_ops);
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.
int nl_cache_refill(struct nl_sock *sk, struct nl_cache *cache)
(Re)fill a cache with the contents in the kernel.
void nl_cache_free(struct nl_cache *cache)
Free a cache.
struct nl_cache * nl_cache_alloc(struct nl_cache_ops *ops)
Allocate new cache.
struct rtnl_cls * rtnl_cls_find_by_handle(struct nl_cache *cache, int ifindex, uint32_t parent, uint32_t handle)
Search classifier by interface index, parent and handle.
int rtnl_cls_add(struct nl_sock *sk, struct rtnl_cls *cls, int flags)
Add/Update classifier.
int rtnl_cls_build_change_request(struct rtnl_cls *cls, int flags, struct nl_msg **result)
Build a netlink message to change classifier attributes.
int rtnl_cls_change(struct nl_sock *sk, struct rtnl_cls *cls, int flags)
Change a classifier.
int rtnl_cls_delete(struct nl_sock *sk, struct rtnl_cls *cls, int flags)
Delete classifier.
struct rtnl_cls * rtnl_cls_find_by_prio(struct nl_cache *cache, int ifindex, uint32_t parent, uint16_t prio)
Search classifier by interface index, parent and priority.
int rtnl_cls_build_delete_request(struct rtnl_cls *cls, int flags, struct nl_msg **result)
Build netlink message requesting the deletion of a classifier.
int rtnl_cls_alloc_cache(struct nl_sock *sk, int ifindex, uint32_t parent, struct nl_cache **result)
Allocate a cache and fill it with all configured classifiers.
int rtnl_cls_build_add_request(struct rtnl_cls *cls, int flags, struct nl_msg **result)
Build a netlink message requesting the addition of a classifier.
void rtnl_cls_cache_set_tc_params(struct nl_cache *cache, int ifindex, uint32_t parent)
Set interface index and parent handle for classifier cache.
struct nlmsghdr * nlmsg_hdr(struct nl_msg *n)
Return actual netlink message.
void * nlmsg_data(const struct nlmsghdr *nlh)
Return pointer to message payload.
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.
#define TC_CAST(ptr)
Macro to cast qdisc/class/classifier to tc object.
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
@ 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.