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;
371 cls->c_protocol = ntohs(TC_H_MIN(cls->c_info));
373 err = pp->pp_cb(OBJ_CAST(cls), pp);
380 static int cls_request_update(
struct nl_cache *cache,
struct nl_sock *sk)
382 struct tcmsg tchdr = {
383 .tcm_family = AF_UNSPEC,
384 .tcm_ifindex = cache->c_iarg1,
385 .tcm_parent = cache->c_iarg2,
392 static struct rtnl_tc_type_ops cls_ops = {
393 .tt_type = RTNL_TC_TYPE_CLS,
394 .tt_dump_prefix =
"cls",
400 static struct nl_cache_ops rtnl_cls_ops = {
401 .co_name =
"route/cls",
402 .co_hdrsize =
sizeof(
struct tcmsg),
404 { RTM_NEWTFILTER, NL_ACT_NEW,
"new" },
405 { RTM_DELTFILTER, NL_ACT_DEL,
"del" },
406 { RTM_GETTFILTER, NL_ACT_GET,
"get" },
407 END_OF_MSGTYPES_LIST,
409 .co_protocol = NETLINK_ROUTE,
410 .co_request_update = cls_request_update,
411 .co_msg_parser = cls_msg_parser,
412 .co_obj_ops = &cls_obj_ops,
415 static struct nl_object_ops cls_obj_ops = {
416 .oo_name =
"route/cls",
417 .oo_size =
sizeof(
struct rtnl_cls),
418 .oo_free_data = rtnl_tc_free_data,
419 .oo_clone = rtnl_tc_clone,
425 .oo_compare = rtnl_tc_compare,
426 .oo_id_attrs = (TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE),
429 static void __init cls_init(
void)
431 rtnl_tc_type_register(&cls_ops);
435 static void __exit cls_exit(
void)
438 rtnl_tc_type_unregister(&cls_ops);