12#include <netlink-private/netlink.h>
13#include <netlink-private/tc.h>
14#include <netlink/netlink.h>
15#include <netlink-private/route/tc-api.h>
16#include <netlink/route/class.h>
17#include <netlink/route/qdisc.h>
18#include <netlink/route/classifier.h>
19#include <netlink/utils.h>
21static struct nl_cache_ops rtnl_class_ops;
22static struct nl_object_ops class_obj_ops;
24static void class_dump_details(
struct rtnl_tc *tc,
struct nl_dump_params *p)
26 struct rtnl_class *
class = (struct rtnl_class *) tc;
35static int class_msg_parser(
struct nl_cache_ops *ops,
struct sockaddr_nl *who,
36 struct nlmsghdr *nlh,
struct nl_parser_param *pp)
38 struct rtnl_class *
class;
41 if (!(
class = rtnl_class_alloc()))
44 if ((err = rtnl_tc_msg_parse(nlh,
TC_CAST(
class))) < 0)
47 err = pp->pp_cb(OBJ_CAST(
class), pp);
49 rtnl_class_put(
class);
54static int class_request_update(
struct nl_cache *cache,
struct nl_sock *sk)
56 struct tcmsg tchdr = {
57 .tcm_family = AF_UNSPEC,
58 .tcm_ifindex = cache->c_iarg1,
70struct rtnl_class *rtnl_class_alloc(
void)
76 tc->tc_type = RTNL_TC_TYPE_CLASS;
78 return (
struct rtnl_class *) tc;
81void rtnl_class_put(
struct rtnl_class *
class)
94static int class_build(
struct rtnl_class *
class,
int type,
int flags,
95 struct nl_msg **result)
97 uint32_t needed = TCA_ATTR_PARENT | TCA_ATTR_HANDLE;
99 if ((class->ce_mask & needed) == needed &&
100 TC_H_MAJ(class->c_parent) && TC_H_MAJ(class->c_handle) &&
101 TC_H_MAJ(class->c_parent) != TC_H_MAJ(class->c_handle)) {
102 APPBUG(
"TC_H_MAJ(parent) must match TC_H_MAJ(handle)");
106 return rtnl_tc_msg_build(
TC_CAST(
class), type, flags, result);
124 struct nl_msg **result)
126 return class_build(
class, RTM_NEWTCLASS, flags, result);
193 uint32_t required = TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE;
195 if ((class->ce_mask & required) != required) {
196 APPBUG(
"ifindex and handle must be specified");
197 return -NLE_MISSING_ATTR;
203 memset(&tchdr, 0,
sizeof(tchdr));
204 tchdr.tcm_family = AF_UNSPEC;
205 tchdr.tcm_ifindex =
class->c_ifindex;
206 tchdr.tcm_handle =
class->c_handle;
208 if (class->ce_mask & TCA_ATTR_PARENT)
209 tchdr.tcm_parent =
class->c_parent;
211 if (
nlmsg_append(msg, &tchdr,
sizeof(tchdr), NLMSG_ALIGNTO) < 0) {
272 struct nl_cache *cache)
274 struct rtnl_qdisc *leaf;
281 if (!leaf || leaf->q_handle != class->c_info)
307 struct nl_cache **result)
309 struct nl_cache * cache;
313 APPBUG(
"ifindex must be specified");
320 cache->c_iarg1 = ifindex;
350 struct rtnl_class *
class;
352 if (cache->c_ops != &rtnl_class_ops)
355 nl_list_for_each_entry(
class, &cache->c_items, ce_list) {
356 if (class->c_handle == handle && class->c_ifindex == ifindex) {
381 struct rtnl_class *
class;
383 if (cache->c_ops != &rtnl_class_ops)
386 nl_list_for_each_entry(
class, &cache->c_items, ce_list) {
387 if (class->c_parent == parent && class->c_ifindex == ifindex) {
410 void (*cb)(
struct nl_object *,
void *),
void *arg)
412 struct rtnl_class *filter;
414 filter = rtnl_class_alloc();
423 rtnl_class_put(filter);
433 void (*cb)(
struct nl_object *,
void *),
void *arg)
435 struct rtnl_cls *filter;
437 filter = rtnl_cls_alloc();
445 rtnl_cls_put(filter);
450static struct rtnl_tc_type_ops class_ops = {
451 .tt_type = RTNL_TC_TYPE_CLASS,
452 .tt_dump_prefix =
"class",
458static struct nl_object_ops class_obj_ops = {
459 .oo_name =
"route/class",
460 .oo_size =
sizeof(
struct rtnl_class),
461 .oo_free_data = rtnl_tc_free_data,
462 .oo_clone = rtnl_tc_clone,
468 .oo_compare = rtnl_tc_compare,
469 .oo_id_attrs = (TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE),
472static struct nl_cache_ops rtnl_class_ops = {
473 .co_name =
"route/class",
474 .co_hdrsize =
sizeof(
struct tcmsg),
476 { RTM_NEWTCLASS, NL_ACT_NEW,
"new" },
477 { RTM_DELTCLASS, NL_ACT_DEL,
"del" },
478 { RTM_GETTCLASS, NL_ACT_GET,
"get" },
479 END_OF_MSGTYPES_LIST,
481 .co_protocol = NETLINK_ROUTE,
482 .co_groups = tc_groups,
483 .co_request_update = &class_request_update,
484 .co_msg_parser = &class_msg_parser,
485 .co_obj_ops = &class_obj_ops,
488static void __init class_init(
void)
490 rtnl_tc_type_register(&class_ops);
494static void __exit class_exit(
void)
497 rtnl_tc_type_unregister(&class_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.
void nl_cache_foreach_filter(struct nl_cache *cache, struct nl_object *filter, void(*cb)(struct nl_object *, void *), void *arg)
Call a callback on each element of the cache (filtered).
struct nl_cache * nl_cache_alloc(struct nl_cache_ops *ops)
Allocate new cache.
struct rtnl_qdisc * rtnl_class_leaf_qdisc(struct rtnl_class *class, struct nl_cache *cache)
Lookup the leaf qdisc of a traffic class.
int rtnl_class_add(struct nl_sock *sk, struct rtnl_class *class, int flags)
Add/Update traffic class.
int rtnl_class_build_delete_request(struct rtnl_class *class, struct nl_msg **result)
Build netlink message requesting the deletion of a traffic class.
struct rtnl_class * rtnl_class_get_by_parent(struct nl_cache *cache, int ifindex, uint32_t parent)
Search class by interface index and parent.
int rtnl_class_build_add_request(struct rtnl_class *class, int flags, struct nl_msg **result)
Build a netlink message requesting the addition of a traffic class.
struct rtnl_class * rtnl_class_get(struct nl_cache *cache, int ifindex, uint32_t handle)
Search traffic class by interface index and handle.
void rtnl_class_foreach_cls(struct rtnl_class *class, struct nl_cache *cache, void(*cb)(struct nl_object *, void *), void *arg)
Call a callback for each classifier attached to the class.
int rtnl_class_delete(struct nl_sock *sk, struct rtnl_class *class)
Delete traffic class.
int rtnl_class_alloc_cache(struct nl_sock *sk, int ifindex, struct nl_cache **result)
Allocate a cache and fill it with all configured traffic classes.
void rtnl_class_foreach_child(struct rtnl_class *class, struct nl_cache *cache, void(*cb)(struct nl_object *, void *), void *arg)
Call a callback for each child of a class.
char * rtnl_tc_handle2str(uint32_t handle, char *buf, size_t len)
Convert a traffic control handle to a character string (Reentrant).
struct nl_msg * nlmsg_alloc_simple(int nlmsgtype, int flags)
Allocate a new netlink message.
void nlmsg_free(struct nl_msg *msg)
Release a reference from an netlink message.
int nlmsg_append(struct nl_msg *n, void *data, size_t len, int pad)
Append data to tail of a netlink message.
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.
struct rtnl_qdisc * rtnl_qdisc_get_by_parent(struct nl_cache *cache, int ifindex, uint32_t parent)
Search qdisc by interface index and parent.
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.
int rtnl_tc_set_kind(struct rtnl_tc *tc, const char *kind)
Define the type of traffic control object.
void rtnl_tc_set_ifindex(struct rtnl_tc *tc, int ifindex)
Set interface index of traffic control object.
#define TC_CAST(ptr)
Macro to cast qdisc/class/classifier to tc object.
void rtnl_tc_set_parent(struct rtnl_tc *tc, uint32_t parent)
Set the parent identifier of a traffic control 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.