summaryrefslogtreecommitdiff
path: root/lib/route/cls.c
diff options
context:
space:
mode:
authorThomas Graf <tgraf@suug.ch>2011-03-21 15:51:52 +0100
committerThomas Graf <tgraf@suug.ch>2011-03-21 15:51:52 +0100
commit8eb5b5532eae985a5f0911dccf2db8cb4e0a5de4 (patch)
tree0fec48d114edbb535bd234f2684acccf81447d13 /lib/route/cls.c
parent5dc897d5de9f54078221b241e0122713207f5e0c (diff)
downloadlibnl-8eb5b5532eae985a5f0911dccf2db8cb4e0a5de4.tar.gz
Unified TC API
Finally got rid of all the qdisc/class/cls code duplication in the tc module API. The API takes care of allocation/freeing the tc object specific data. I hope I got it right this time.
Diffstat (limited to 'lib/route/cls.c')
-rw-r--r--lib/route/cls.c194
1 files changed, 131 insertions, 63 deletions
diff --git a/lib/route/cls.c b/lib/route/cls.c
index 093b030..a041baa 100644
--- a/lib/route/cls.c
+++ b/lib/route/cls.c
@@ -28,66 +28,26 @@
#include <netlink-tc.h>
#include <netlink/netlink.h>
#include <netlink/utils.h>
-#include <netlink/route/tc.h>
+#include <netlink/route/tc-api.h>
#include <netlink/route/classifier.h>
-#include <netlink/route/classifier-modules.h>
#include <netlink/route/link.h>
-static struct nl_cache_ops rtnl_cls_ops;
-
-static int cls_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
- struct nlmsghdr *nlh, struct nl_parser_param *pp)
-{
- struct rtnl_cls_ops *cops;
- struct rtnl_cls *cls;
- int err;
+/** @cond SKIP */
+#define CLS_ATTR_PRIO (TCA_ATTR_MAX << 1)
+#define CLS_ATTR_PROTOCOL (TCA_ATTR_MAX << 2)
+/** @endcond */
- cls = rtnl_cls_alloc();
- if (!cls) {
- err = -NLE_NOMEM;
- goto errout;
- }
- cls->ce_msgtype = nlh->nlmsg_type;
-
- err = tca_msg_parser(nlh, (struct rtnl_tc *) cls);
- if (err < 0)
- goto errout_free;
-
- cls->c_prio = TC_H_MAJ(cls->c_info) >> 16;
- cls->c_protocol = ntohs(TC_H_MIN(cls->c_info));
-
- cops = rtnl_cls_lookup_ops(cls);
- if (cops && cops->co_msg_parser && (err = cops->co_msg_parser(cls)) < 0)
- goto errout_free;
-
- err = pp->pp_cb((struct nl_object *) cls, pp);
-errout_free:
- rtnl_cls_put(cls);
-errout:
- return err;
-}
-
-static int cls_request_update(struct nl_cache *cache, struct nl_sock *sk)
-{
- struct tcmsg tchdr = {
- .tcm_family = AF_UNSPEC,
- .tcm_ifindex = cache->c_iarg1,
- .tcm_parent = cache->c_iarg2,
- };
-
- return nl_send_simple(sk, RTM_GETTFILTER, NLM_F_DUMP, &tchdr,
- sizeof(tchdr));
-}
+static struct nl_object_ops cls_obj_ops;
+static struct nl_cache_ops rtnl_cls_ops;
static int cls_build(struct rtnl_cls *cls, int type, int flags,
struct nl_msg **result)
{
- struct rtnl_cls_ops *cops;
int err, prio, proto;
struct tcmsg *tchdr;
- err = tca_build_msg((struct rtnl_tc *) cls, type, flags, result);
+ err = rtnl_tc_msg_build(TC_CAST(cls), type, flags, result);
if (err < 0)
return err;
@@ -96,27 +56,68 @@ static int cls_build(struct rtnl_cls *cls, int type, int flags,
proto = rtnl_cls_get_protocol(cls);
tchdr->tcm_info = TC_H_MAKE(prio << 16, htons(proto));
- cops = rtnl_cls_lookup_ops(cls);
- if (cops && cops->co_get_opts) {
- struct nlattr *opts;
+ return 0;
+}
- if (!(opts = nla_nest_start(*result, TCA_OPTIONS))) {
- err = -NLE_NOMEM;
- goto errout;
- }
+/**
+ * @name Allocation/Freeing
+ * @{
+ */
- if ((err = cops->co_get_opts(cls, *result)) < 0)
- goto errout;
+struct rtnl_cls *rtnl_cls_alloc(void)
+{
+ struct rtnl_tc *tc;
- nla_nest_end(*result, opts);
- }
+ tc = TC_CAST(nl_object_alloc(&cls_obj_ops));
+ if (tc)
+ tc->tc_type = RTNL_TC_TYPE_CLS;
- return 0;
-errout:
- nlmsg_free(*result);
- return err;
+ return (struct rtnl_cls *) tc;
+}
+
+void rtnl_cls_put(struct rtnl_cls *cls)
+{
+ nl_object_put((struct nl_object *) cls);
+}
+
+/** @} */
+
+/**
+ * @name Attributes
+ * @{
+ */
+
+void rtnl_cls_set_prio(struct rtnl_cls *cls, uint16_t prio)
+{
+ cls->c_prio = prio;
+ cls->ce_mask |= CLS_ATTR_PRIO;
+}
+
+uint16_t rtnl_cls_get_prio(struct rtnl_cls *cls)
+{
+ if (cls->ce_mask & CLS_ATTR_PRIO)
+ return cls->c_prio;
+ else
+ return 0;
+}
+
+void rtnl_cls_set_protocol(struct rtnl_cls *cls, uint16_t protocol)
+{
+ cls->c_protocol = protocol;
+ cls->ce_mask |= CLS_ATTR_PROTOCOL;
+}
+
+uint16_t rtnl_cls_get_protocol(struct rtnl_cls *cls)
+{
+ if (cls->ce_mask & CLS_ATTR_PROTOCOL)
+ return cls->c_protocol;
+ else
+ return ETH_P_ALL;
}
+/** @} */
+
+
/**
* @name Classifier Addition/Modification/Deletion
* @{
@@ -311,6 +312,57 @@ int rtnl_cls_alloc_cache(struct nl_sock *sk, int ifindex, uint32_t parent, st
/** @} */
+static void cls_dump_line(struct rtnl_tc *tc, struct nl_dump_params *p)
+{
+ struct rtnl_cls *cls = (struct rtnl_cls *) tc;
+ char buf[32];
+
+ nl_dump(p, " prio %u protocol %s", cls->c_prio,
+ nl_ether_proto2str(cls->c_protocol, buf, sizeof(buf)));
+}
+
+static int cls_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
+ struct nlmsghdr *nlh, struct nl_parser_param *pp)
+{
+ struct rtnl_cls *cls;
+ int err;
+
+ if (!(cls = rtnl_cls_alloc()))
+ return -NLE_NOMEM;
+
+ if ((err = rtnl_tc_msg_parse(nlh, TC_CAST(cls))) < 0)
+ goto errout;
+
+ cls->c_prio = TC_H_MAJ(cls->c_info) >> 16;
+ cls->c_protocol = ntohs(TC_H_MIN(cls->c_info));
+
+ err = pp->pp_cb(OBJ_CAST(cls), pp);
+errout:
+ rtnl_cls_put(cls);
+
+ return err;
+}
+
+static int cls_request_update(struct nl_cache *cache, struct nl_sock *sk)
+{
+ struct tcmsg tchdr = {
+ .tcm_family = AF_UNSPEC,
+ .tcm_ifindex = cache->c_iarg1,
+ .tcm_parent = cache->c_iarg2,
+ };
+
+ return nl_send_simple(sk, RTM_GETTFILTER, NLM_F_DUMP, &tchdr,
+ sizeof(tchdr));
+}
+
+static struct rtnl_tc_type_ops cls_ops = {
+ .tt_type = RTNL_TC_TYPE_CLS,
+ .tt_dump_prefix = "cls",
+ .tt_dump = {
+ [NL_DUMP_LINE] = cls_dump_line,
+ },
+};
+
static struct nl_cache_ops rtnl_cls_ops = {
.co_name = "route/cls",
.co_hdrsize = sizeof(struct tcmsg),
@@ -326,14 +378,30 @@ static struct nl_cache_ops rtnl_cls_ops = {
.co_obj_ops = &cls_obj_ops,
};
+static struct nl_object_ops cls_obj_ops = {
+ .oo_name = "route/cls",
+ .oo_size = sizeof(struct rtnl_cls),
+ .oo_free_data = rtnl_tc_free_data,
+ .oo_clone = rtnl_tc_clone,
+ .oo_dump = {
+ [NL_DUMP_LINE] = rtnl_tc_dump_line,
+ [NL_DUMP_DETAILS] = rtnl_tc_dump_details,
+ [NL_DUMP_STATS] = rtnl_tc_dump_stats,
+ },
+ .oo_compare = rtnl_tc_compare,
+ .oo_id_attrs = (TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE),
+};
+
static void __init cls_init(void)
{
+ rtnl_tc_type_register(&cls_ops);
nl_cache_mngt_register(&rtnl_cls_ops);
}
static void __exit cls_exit(void)
{
nl_cache_mngt_unregister(&rtnl_cls_ops);
+ rtnl_tc_type_unregister(&cls_ops);
}
/** @} */