18 #include <netlink-private/netlink.h> 19 #include <netlink-private/tc.h> 20 #include <netlink/netlink.h> 21 #include <netlink/utils.h> 22 #include <netlink-private/route/tc-api.h> 23 #include <netlink/route/classifier.h> 24 #include <netlink/route/link.h> 27 #define CLS_ATTR_PRIO (TCA_ATTR_MAX << 1) 28 #define CLS_ATTR_PROTOCOL (TCA_ATTR_MAX << 2) 31 static struct nl_object_ops cls_obj_ops;
32 static struct nl_cache_ops rtnl_cls_ops;
35 static int cls_build(
struct rtnl_cls *cls,
int type,
int flags,
36 struct nl_msg **result)
40 uint32_t required = TCA_ATTR_IFINDEX;
42 if ((cls->ce_mask & required) != required) {
43 APPBUG(
"ifindex must be specified");
44 return -NLE_MISSING_ATTR;
47 err = rtnl_tc_msg_build(
TC_CAST(cls), type, flags, result);
52 prio = rtnl_cls_get_prio(cls);
53 proto = rtnl_cls_get_protocol(cls);
54 tchdr->tcm_info = TC_H_MAKE(prio << 16, htons(proto));
64 struct rtnl_cls *rtnl_cls_alloc(
void)
70 tc->tc_type = RTNL_TC_TYPE_CLS;
72 return (
struct rtnl_cls *) tc;
75 void rtnl_cls_put(
struct rtnl_cls *cls)
87 void rtnl_cls_set_prio(
struct rtnl_cls *cls, uint16_t prio)
90 cls->ce_mask |= CLS_ATTR_PRIO;
93 uint16_t rtnl_cls_get_prio(
struct rtnl_cls *cls)
95 if (cls->ce_mask & CLS_ATTR_PRIO)
101 void rtnl_cls_set_protocol(
struct rtnl_cls *cls, uint16_t protocol)
103 cls->c_protocol = protocol;
104 cls->ce_mask |= CLS_ATTR_PROTOCOL;
107 uint16_t rtnl_cls_get_protocol(
struct rtnl_cls *cls)
109 if (cls->ce_mask & CLS_ATTR_PROTOCOL)
110 return cls->c_protocol;
138 struct nl_msg **result)
140 if (!(flags & NLM_F_CREATE) && !(cls->ce_mask & CLS_ATTR_PRIO)) {
141 APPBUG(
"prio must be specified if not a new classifier");
142 return -NLE_MISSING_ATTR;
145 return cls_build(cls, RTM_NEWTFILTER, flags, result);
209 struct nl_msg **result)
211 return cls_build(cls, RTM_NEWTFILTER, NLM_F_REPLACE | flags, result);
252 struct nl_msg **result)
254 uint32_t required = CLS_ATTR_PRIO;
256 if ((cls->ce_mask & required) != required) {
257 APPBUG(
"prio must be specified");
258 return -NLE_MISSING_ATTR;
261 return cls_build(cls, RTM_DELTFILTER, flags, result);
329 struct nl_cache * cache;
335 cache->c_iarg1 = ifindex;
336 cache->c_iarg2 = parent;
349 static void cls_dump_line(
struct rtnl_tc *tc,
struct nl_dump_params *p)
351 struct rtnl_cls *cls = (
struct rtnl_cls *) tc;
354 nl_dump(p,
" prio %u protocol %s", cls->c_prio,
355 nl_ether_proto2str(cls->c_protocol, buf,
sizeof(buf)));
358 static int cls_msg_parser(
struct nl_cache_ops *ops,
struct sockaddr_nl *who,
359 struct nlmsghdr *nlh,
struct nl_parser_param *pp)
361 struct rtnl_cls *cls;
364 if (!(cls = rtnl_cls_alloc()))
367 if ((err = rtnl_tc_msg_parse(nlh,
TC_CAST(cls))) < 0)
370 cls->c_prio = TC_H_MAJ(cls->c_info) >> 16;
372 cls->ce_mask |= CLS_ATTR_PRIO;
373 cls->c_protocol = ntohs(TC_H_MIN(cls->c_info));
375 cls->ce_mask |= CLS_ATTR_PROTOCOL;
377 err = pp->pp_cb(OBJ_CAST(cls), pp);
384 static int cls_request_update(
struct nl_cache *cache,
struct nl_sock *sk)
386 struct tcmsg tchdr = {
387 .tcm_family = AF_UNSPEC,
388 .tcm_ifindex = cache->c_iarg1,
389 .tcm_parent = cache->c_iarg2,
396 static struct rtnl_tc_type_ops cls_ops = {
397 .tt_type = RTNL_TC_TYPE_CLS,
398 .tt_dump_prefix =
"cls",
404 static struct nl_cache_ops rtnl_cls_ops = {
405 .co_name =
"route/cls",
406 .co_hdrsize =
sizeof(
struct tcmsg),
408 { RTM_NEWTFILTER, NL_ACT_NEW,
"new" },
409 { RTM_DELTFILTER, NL_ACT_DEL,
"del" },
410 { RTM_GETTFILTER, NL_ACT_GET,
"get" },
411 END_OF_MSGTYPES_LIST,
413 .co_protocol = NETLINK_ROUTE,
414 .co_groups = tc_groups,
415 .co_request_update = cls_request_update,
416 .co_msg_parser = cls_msg_parser,
417 .co_obj_ops = &cls_obj_ops,
420 static struct nl_object_ops cls_obj_ops = {
421 .oo_name =
"route/cls",
422 .oo_size =
sizeof(
struct rtnl_cls),
423 .oo_free_data = rtnl_tc_free_data,
424 .oo_clone = rtnl_tc_clone,
430 .oo_compare = rtnl_tc_compare,
431 .oo_id_attrs = (TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE),
434 static void __init cls_init(
void)
436 rtnl_tc_type_register(&cls_ops);
440 static void __exit cls_exit(
void)
443 rtnl_tc_type_unregister(&cls_ops);
int rtnl_cls_change(struct nl_sock *sk, struct rtnl_cls *cls, int flags)
Change a classifier.
Dump object briefly on one line.
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.
void * nlmsg_data(const struct nlmsghdr *nlh)
Return pointer to message payload.
struct nl_object * nl_object_alloc(struct nl_object_ops *ops)
Allocate a new object of kind specified by the operations handle.
int nl_cache_mngt_unregister(struct nl_cache_ops *ops)
Unregister a set of cache operations.
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 rtnl_cls_add(struct nl_sock *sk, struct rtnl_cls *cls, int flags)
Add/Update classifier.
int rtnl_cls_delete(struct nl_sock *sk, struct rtnl_cls *cls, int flags)
Delete classifier.
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.
Dump all attributes but no statistics.
void nl_cache_free(struct nl_cache *cache)
Free a cache.
int nl_cache_mngt_register(struct nl_cache_ops *ops)
Register a set of cache operations.
#define TC_CAST(ptr)
Macro to cast qdisc/class/classifier to tc object.
struct nlmsghdr * nlmsg_hdr(struct nl_msg *n)
Return actual netlink message.
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 nl_send_simple(struct nl_sock *sk, int type, int flags, void *buf, size_t size)
Construct and transmit a Netlink message.
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 nl_cache_refill(struct nl_sock *sk, struct nl_cache *cache)
(Re)fill a cache with the contents in the kernel.
void nl_object_put(struct nl_object *obj)
Release a reference from an object.
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Dump all attributes including statistics.
struct nl_cache * nl_cache_alloc(struct nl_cache_ops *ops)
Allocate new cache.