18 #include <netlink-private/netlink.h>
19 #include <netlink-private/tc.h>
20 #include <netlink/netlink.h>
21 #include <netlink-private/route/tc-api.h>
22 #include <netlink/route/class.h>
23 #include <netlink/route/qdisc.h>
24 #include <netlink/route/classifier.h>
25 #include <netlink/utils.h>
27 static struct nl_cache_ops rtnl_class_ops;
28 static struct nl_object_ops class_obj_ops;
30 static void class_dump_details(
struct rtnl_tc *tc,
struct nl_dump_params *p)
32 struct rtnl_class *
class = (struct rtnl_class *) tc;
41 static int class_msg_parser(
struct nl_cache_ops *ops,
struct sockaddr_nl *who,
42 struct nlmsghdr *nlh,
struct nl_parser_param *pp)
44 struct rtnl_class *
class;
47 if (!(
class = rtnl_class_alloc()))
50 if ((err = rtnl_tc_msg_parse(nlh,
TC_CAST(
class))) < 0)
53 err = pp->pp_cb(OBJ_CAST(
class), pp);
55 rtnl_class_put(
class);
60 static int class_request_update(
struct nl_cache *cache,
struct nl_sock *sk)
62 struct tcmsg tchdr = {
63 .tcm_family = AF_UNSPEC,
64 .tcm_ifindex = cache->c_iarg1,
76 struct rtnl_class *rtnl_class_alloc(
void)
82 tc->tc_type = RTNL_TC_TYPE_CLASS;
84 return (
struct rtnl_class *) tc;
87 void rtnl_class_put(
struct rtnl_class *
class)
100 static int class_build(
struct rtnl_class *
class,
int type,
int flags,
101 struct nl_msg **result)
103 uint32_t needed = TCA_ATTR_PARENT | TCA_ATTR_HANDLE;
105 if ((class->ce_mask & needed) == needed &&
106 TC_H_MAJ(class->c_parent) && TC_H_MAJ(class->c_handle) &&
107 TC_H_MAJ(class->c_parent) != TC_H_MAJ(class->c_handle)) {
108 APPBUG(
"TC_H_MAJ(parent) must match TC_H_MAJ(handle)");
112 return rtnl_tc_msg_build(
TC_CAST(
class), type, flags, result);
130 struct nl_msg **result)
132 return class_build(
class, RTM_NEWTCLASS, flags, result);
199 uint32_t required = TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE;
201 if ((class->ce_mask & required) != required) {
202 APPBUG(
"ifindex and handle must be specified");
203 return -NLE_MISSING_ATTR;
209 memset(&tchdr, 0,
sizeof(tchdr));
210 tchdr.tcm_family = AF_UNSPEC;
211 tchdr.tcm_ifindex =
class->c_ifindex;
212 tchdr.tcm_handle =
class->c_handle;
214 if (class->ce_mask & TCA_ATTR_PARENT)
215 tchdr.tcm_parent =
class->c_parent;
217 if (
nlmsg_append(msg, &tchdr,
sizeof(tchdr), NLMSG_ALIGNTO) < 0) {
278 struct nl_cache *cache)
280 struct rtnl_qdisc *leaf;
287 if (!leaf || leaf->q_handle != class->c_info)
313 struct nl_cache **result)
315 struct nl_cache * cache;
319 APPBUG(
"ifindex must be specified");
326 cache->c_iarg1 = ifindex;
356 struct rtnl_class *
class;
358 if (cache->c_ops != &rtnl_class_ops)
361 nl_list_for_each_entry(
class, &cache->c_items, ce_list) {
362 if (class->c_handle == handle && class->c_ifindex == ifindex) {
384 void (*cb)(
struct nl_object *,
void *),
void *arg)
386 struct rtnl_class *filter;
388 filter = rtnl_class_alloc();
397 rtnl_class_put(filter);
407 void (*cb)(
struct nl_object *,
void *),
void *arg)
409 struct rtnl_cls *filter;
411 filter = rtnl_cls_alloc();
419 rtnl_cls_put(filter);
424 static struct rtnl_tc_type_ops class_ops = {
425 .tt_type = RTNL_TC_TYPE_CLASS,
426 .tt_dump_prefix =
"class",
432 static struct nl_object_ops class_obj_ops = {
433 .oo_name =
"route/class",
434 .oo_size =
sizeof(
struct rtnl_class),
435 .oo_free_data = rtnl_tc_free_data,
436 .oo_clone = rtnl_tc_clone,
442 .oo_compare = rtnl_tc_compare,
443 .oo_id_attrs = (TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE),
446 static struct nl_cache_ops rtnl_class_ops = {
447 .co_name =
"route/class",
448 .co_hdrsize =
sizeof(
struct tcmsg),
450 { RTM_NEWTCLASS, NL_ACT_NEW,
"new" },
451 { RTM_DELTCLASS, NL_ACT_DEL,
"del" },
452 { RTM_GETTCLASS, NL_ACT_GET,
"get" },
453 END_OF_MSGTYPES_LIST,
455 .co_protocol = NETLINK_ROUTE,
456 .co_request_update = &class_request_update,
457 .co_msg_parser = &class_msg_parser,
458 .co_obj_ops = &class_obj_ops,
461 static void __init class_init(
void)
463 rtnl_tc_type_register(&class_ops);
467 static void __exit class_exit(
void)
470 rtnl_tc_type_unregister(&class_ops);