12#include <netlink-private/netlink.h>
13#include <netlink-private/tc.h>
14#include <netlink/netlink.h>
15#include <netlink/utils.h>
16#include <netlink-private/route/tc-api.h>
17#include <netlink/route/classifier.h>
18#include <netlink/route/link.h>
21#define CLS_ATTR_PRIO (TCA_ATTR_MAX << 1)
22#define CLS_ATTR_PROTOCOL (TCA_ATTR_MAX << 2)
25static struct nl_object_ops cls_obj_ops;
26static struct nl_cache_ops rtnl_cls_ops;
29static int cls_build(
struct rtnl_cls *cls,
int type,
int flags,
30 struct nl_msg **result)
34 uint32_t required = TCA_ATTR_IFINDEX;
36 if ((cls->ce_mask & required) != required) {
37 APPBUG(
"ifindex must be specified");
38 return -NLE_MISSING_ATTR;
41 err = rtnl_tc_msg_build(
TC_CAST(cls), type, flags, result);
46 prio = rtnl_cls_get_prio(cls);
47 proto = rtnl_cls_get_protocol(cls);
48 tchdr->tcm_info = TC_H_MAKE(prio << 16, htons(proto));
58struct rtnl_cls *rtnl_cls_alloc(
void)
64 tc->tc_type = RTNL_TC_TYPE_CLS;
66 return (
struct rtnl_cls *) tc;
69void rtnl_cls_put(
struct rtnl_cls *cls)
81void rtnl_cls_set_prio(
struct rtnl_cls *cls, uint16_t prio)
84 cls->ce_mask |= CLS_ATTR_PRIO;
87uint16_t rtnl_cls_get_prio(
struct rtnl_cls *cls)
89 if (cls->ce_mask & CLS_ATTR_PRIO)
95void rtnl_cls_set_protocol(
struct rtnl_cls *cls, uint16_t protocol)
97 cls->c_protocol = protocol;
98 cls->ce_mask |= CLS_ATTR_PROTOCOL;
101uint16_t rtnl_cls_get_protocol(
struct rtnl_cls *cls)
103 if (cls->ce_mask & CLS_ATTR_PROTOCOL)
104 return cls->c_protocol;
132 struct nl_msg **result)
134 if (!(flags & NLM_F_CREATE) && !(cls->ce_mask & CLS_ATTR_PRIO)) {
135 APPBUG(
"prio must be specified if not a new classifier");
136 return -NLE_MISSING_ATTR;
139 return cls_build(cls, RTM_NEWTFILTER, flags, result);
203 struct nl_msg **result)
205 return cls_build(cls, RTM_NEWTFILTER, NLM_F_REPLACE | flags, result);
246 struct nl_msg **result)
248 uint32_t required = CLS_ATTR_PRIO;
250 if ((cls->ce_mask & required) != required) {
251 APPBUG(
"prio must be specified");
252 return -NLE_MISSING_ATTR;
255 return cls_build(cls, RTM_DELTFILTER, flags, result);
322 struct nl_cache **result)
324 struct nl_cache * cache;
330 cache->c_iarg1 = ifindex;
331 cache->c_iarg2 = parent;
354 int ifindex, uint32_t parent)
356 cache->c_iarg1 = ifindex;
357 cache->c_iarg2 = parent;
379 struct rtnl_cls *cls;
381 if (cache->c_ops != &rtnl_cls_ops)
384 nl_list_for_each_entry(cls, &cache->c_items, ce_list) {
385 if ((cls->c_parent == parent) &&
386 (cls->c_ifindex == ifindex)&&
387 (cls->c_handle == handle)) {
413 uint32_t parent, uint16_t prio)
415 struct rtnl_cls *cls;
417 if (cache->c_ops != &rtnl_cls_ops)
420 nl_list_for_each_entry(cls, &cache->c_items, ce_list) {
421 if ((cls->c_parent == parent) &&
422 (cls->c_ifindex == ifindex) &&
423 (cls->c_prio == prio)) {
434static void cls_dump_line(
struct rtnl_tc *tc,
struct nl_dump_params *p)
436 struct rtnl_cls *cls = (
struct rtnl_cls *) tc;
439 nl_dump(p,
" prio %u protocol %s", cls->c_prio,
440 nl_ether_proto2str(cls->c_protocol, buf,
sizeof(buf)));
443static int cls_msg_parser(
struct nl_cache_ops *ops,
struct sockaddr_nl *who,
444 struct nlmsghdr *nlh,
struct nl_parser_param *pp)
446 struct rtnl_cls *cls;
449 if (!(cls = rtnl_cls_alloc()))
452 if ((err = rtnl_tc_msg_parse(nlh,
TC_CAST(cls))) < 0)
455 cls->c_prio = TC_H_MAJ(cls->c_info) >> 16;
457 cls->ce_mask |= CLS_ATTR_PRIO;
458 cls->c_protocol = ntohs(TC_H_MIN(cls->c_info));
460 cls->ce_mask |= CLS_ATTR_PROTOCOL;
462 err = pp->pp_cb(OBJ_CAST(cls), pp);
469static int cls_request_update(
struct nl_cache *cache,
struct nl_sock *sk)
471 struct tcmsg tchdr = {
472 .tcm_family = AF_UNSPEC,
473 .tcm_ifindex = cache->c_iarg1,
474 .tcm_parent = cache->c_iarg2,
481static struct rtnl_tc_type_ops cls_ops = {
482 .tt_type = RTNL_TC_TYPE_CLS,
483 .tt_dump_prefix =
"cls",
489static struct nl_cache_ops rtnl_cls_ops = {
490 .co_name =
"route/cls",
491 .co_hdrsize =
sizeof(
struct tcmsg),
493 { RTM_NEWTFILTER, NL_ACT_NEW,
"new" },
494 { RTM_DELTFILTER, NL_ACT_DEL,
"del" },
495 { RTM_GETTFILTER, NL_ACT_GET,
"get" },
496 END_OF_MSGTYPES_LIST,
498 .co_protocol = NETLINK_ROUTE,
499 .co_groups = tc_groups,
500 .co_request_update = cls_request_update,
501 .co_msg_parser = cls_msg_parser,
502 .co_obj_ops = &cls_obj_ops,
505static struct nl_object_ops cls_obj_ops = {
506 .oo_name =
"route/cls",
507 .oo_size =
sizeof(
struct rtnl_cls),
508 .oo_free_data = rtnl_tc_free_data,
509 .oo_clone = rtnl_tc_clone,
515 .oo_compare = rtnl_tc_compare,
516 .oo_id_attrs = (TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE),
519static void __init cls_init(
void)
521 rtnl_tc_type_register(&cls_ops);
525static void __exit cls_exit(
void)
528 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.