summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVolodymyr Bendiuga <volodymyr.bendiuga@westermo.se>2017-10-24 16:40:00 +0200
committerThomas Haller <thaller@redhat.com>2018-04-11 12:22:16 +0200
commit5893c3f18e29e2fa964397cf3db261583f93abdd (patch)
tree518ebdbbb203b28f11f21c4c9539f04e09ef99be
parent50918a9a50b56b8bccf15e54b355686e626710bd (diff)
downloadlibnl-5893c3f18e29e2fa964397cf3db261583f93abdd.tar.gz
route:cls: add matchall classifier
This simple classifier allows any traffic pass through. Useful as an example for port mirroring. Signed-off-by: Volodymyr Bendiuga <volodymyr.bendiuga@westermo.se>
-rw-r--r--Makefile.am4
-rw-r--r--include/netlink-private/types.h8
-rw-r--r--include/netlink/route/cls/matchall.h36
-rw-r--r--lib/route/cls/mall.c301
-rw-r--r--libnl-route-3.sym7
5 files changed, 355 insertions, 1 deletions
diff --git a/Makefile.am b/Makefile.am
index 1f511242..98b0c5e4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -121,7 +121,8 @@ libnlinclude_netlink_route_cls_HEADERS = \
include/netlink/route/cls/ematch.h \
include/netlink/route/cls/fw.h \
include/netlink/route/cls/police.h \
- include/netlink/route/cls/u32.h
+ include/netlink/route/cls/u32.h \
+ include/netlink/route/cls/matchall.h
libnlinclude_netlink_route_cls_ematchdir = $(libnlincludedir)/netlink/route/cls/ematch
libnlinclude_netlink_route_cls_ematch_HEADERS = \
include/netlink/route/cls/ematch/cmp.h \
@@ -364,6 +365,7 @@ lib_libnl_route_3_la_SOURCES = \
lib/route/cls/fw.c \
lib/route/cls/police.c \
lib/route/cls/u32.c \
+ lib/route/cls/mall.c \
lib/route/link/api.c \
lib/route/link/bonding.c \
lib/route/link/bridge.c \
diff --git a/include/netlink-private/types.h b/include/netlink-private/types.h
index db03192d..de93bd9e 100644
--- a/include/netlink-private/types.h
+++ b/include/netlink-private/types.h
@@ -605,6 +605,14 @@ struct rtnl_u32
int cu_mask;
};
+struct rtnl_mall
+{
+ uint32_t m_classid;
+ uint32_t m_flags;
+ struct rtnl_act *m_act;
+ int m_mask;
+};
+
struct rtnl_cgroup
{
struct rtnl_ematch_tree *cg_ematch;
diff --git a/include/netlink/route/cls/matchall.h b/include/netlink/route/cls/matchall.h
new file mode 100644
index 00000000..19556943
--- /dev/null
+++ b/include/netlink/route/cls/matchall.h
@@ -0,0 +1,36 @@
+/*
+ * netlink/route/cls/matchall.h matchall classifier
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2017 Volodymyr Bendiuga <volodymyr.bendiuga@gmail.com>
+ */
+
+#ifndef NETLINK_MATCHALL_H_
+#define NETLINK_MATCHALL_H_
+
+#include <netlink/netlink.h>
+#include <netlink/cache.h>
+#include <netlink/route/classifier.h>
+#include <netlink/route/action.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int rtnl_mall_set_classid(struct rtnl_cls *, uint32_t);
+extern int rtnl_mall_get_classid(struct rtnl_cls *, uint32_t *);
+extern int rtnl_mall_set_flags(struct rtnl_cls *, uint32_t);
+extern int rtnl_mall_get_flags(struct rtnl_cls *, uint32_t *);
+extern int rtnl_mall_append_action(struct rtnl_cls *, struct rtnl_act *);
+extern struct rtnl_act *rtnl_mall_get_first_action(struct rtnl_cls *);
+extern int rtnl_mall_del_action(struct rtnl_cls *, struct rtnl_act *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/route/cls/mall.c b/lib/route/cls/mall.c
new file mode 100644
index 00000000..d1588f65
--- /dev/null
+++ b/lib/route/cls/mall.c
@@ -0,0 +1,301 @@
+/*
+ * lib/route/cls/mall.c match-all classifier
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2017 Volodymyr Bendiuga <volodymyr.bendiuga@gmail.com>
+ */
+
+/**
+ * @ingroup cls
+ * @defgroup cls_mall Match-all Classifier
+ *
+ * @{
+ */
+
+#include <netlink-private/netlink.h>
+#include <netlink-private/tc.h>
+#include <netlink/netlink.h>
+#include <netlink/attr.h>
+#include <netlink/utils.h>
+#include <netlink-private/route/tc-api.h>
+#include <netlink/route/classifier.h>
+#include <netlink/route/cls/matchall.h>
+#include <netlink/route/action.h>
+
+
+#define MALL_ATTR_CLASSID 0x01
+#define MALL_ATTR_FLAGS 0x02
+#define MALL_ATTR_ACTION 0x03
+
+
+static struct nla_policy mall_policy[TCA_MATCHALL_MAX + 1] = {
+ [TCA_MATCHALL_CLASSID] = { .type = NLA_U32 },
+ [TCA_MATCHALL_FLAGS] = { .type = NLA_U32 },
+};
+
+/**
+ * @name Attribute Modifications
+ * @{
+ */
+
+int rtnl_mall_set_classid(struct rtnl_cls *cls, uint32_t classid)
+{
+ struct rtnl_mall *mall;
+ if (!(mall = rtnl_tc_data(TC_CAST(cls))))
+ return -NLE_NOMEM;
+
+ mall->m_classid = classid;
+ mall->m_mask |= MALL_ATTR_CLASSID;
+
+ return 0;
+}
+
+int rtnl_mall_get_classid(struct rtnl_cls *cls, uint32_t *classid)
+{
+ struct rtnl_mall *mall;
+
+ if (!(mall = rtnl_tc_data_peek(TC_CAST(cls))))
+ return -NLE_INVAL;
+
+ if (!(mall->m_mask & MALL_ATTR_CLASSID))
+ return -NLE_INVAL;
+
+ *classid = mall->m_classid;
+ return 0;
+}
+
+int rtnl_mall_set_flags(struct rtnl_cls *cls, uint32_t flags)
+{
+ struct rtnl_mall *mall;
+
+ if (!(mall = rtnl_tc_data(TC_CAST(cls))))
+ return -NLE_NOMEM;
+
+ mall->m_flags = flags;
+ mall->m_mask |= MALL_ATTR_FLAGS;
+
+ return 0;
+}
+
+int rtnl_mall_get_flags(struct rtnl_cls *cls, uint32_t *flags)
+{
+ struct rtnl_mall *mall;
+
+ if (!(mall = rtnl_tc_data_peek(TC_CAST(cls))))
+ return -NLE_INVAL;
+
+ if (!(mall->m_mask & MALL_ATTR_FLAGS))
+ return -NLE_INVAL;
+
+ *flags = mall->m_flags;
+ return 0;
+}
+
+int rtnl_mall_append_action(struct rtnl_cls *cls, struct rtnl_act *act)
+{
+ struct rtnl_mall *mall;
+ int err;
+
+ if (!act)
+ return 0;
+
+ if (!(mall = rtnl_tc_data(TC_CAST(cls))))
+ return -NLE_NOMEM;
+
+ mall->m_mask |= MALL_ATTR_ACTION;
+ err = rtnl_act_append(&mall->m_act, act);
+ if (err)
+ return err;
+
+ rtnl_act_get(act);
+ return 0;
+}
+
+struct rtnl_act *rtnl_mall_get_first_action(struct rtnl_cls *cls)
+{
+ struct rtnl_mall *mall;
+ struct rtnl_act *act;
+
+ if (!(mall = rtnl_tc_data(TC_CAST(cls))))
+ return NULL;
+
+ if (!(mall->m_mask & MALL_ATTR_ACTION))
+ return NULL;
+
+ act = mall->m_act;
+ rtnl_act_get(act);
+
+ return act;
+}
+
+int rtnl_mall_del_action(struct rtnl_cls *cls, struct rtnl_act *act)
+{
+ struct rtnl_mall *mall;
+ int ret;
+
+ if (!act)
+ return 0;
+
+ if (!(mall = rtnl_tc_data(TC_CAST(cls))))
+ return -NLE_NOMEM;
+
+ if (!(mall->m_mask & MALL_ATTR_ACTION))
+ return -NLE_INVAL;
+
+ ret = rtnl_act_remove(&mall->m_act, act);
+ if (ret < 0)
+ return ret;
+
+ rtnl_act_put(act);
+
+ return 0;
+}
+
+/** @} */
+
+static void mall_free_data(struct rtnl_tc *tc, void *data)
+{
+ struct rtnl_mall *mall = data;
+
+ if (mall->m_act)
+ rtnl_act_put_all(&mall->m_act);
+}
+
+static int mall_msg_parser(struct rtnl_tc *tc, void *data)
+{
+ struct rtnl_mall *mall = data;
+ struct nlattr *tb[TCA_MATCHALL_MAX + 1];
+ int err;
+
+ err = tca_parse(tb, TCA_MATCHALL_MAX, tc, mall_policy);
+ if (err < 0)
+ return err;
+
+ if (tb[TCA_MATCHALL_CLASSID]) {
+ mall->m_classid = nla_get_u32(tb[TCA_MATCHALL_CLASSID]);
+ mall->m_mask |= MALL_ATTR_CLASSID;
+ }
+
+ if (tb[TCA_MATCHALL_FLAGS]) {
+ mall->m_flags = nla_get_u32(tb[TCA_MATCHALL_FLAGS]);
+ mall->m_mask |= MALL_ATTR_FLAGS;
+ }
+
+ if (tb[TCA_MATCHALL_ACT]) {
+ mall->m_mask |= MALL_ATTR_ACTION;
+ err = rtnl_act_parse(&mall->m_act, tb[TCA_MATCHALL_ACT]);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+static int mall_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
+{
+ struct rtnl_mall *mall = data;
+
+ if (!mall)
+ return 0;
+
+ if (mall->m_mask & MALL_ATTR_CLASSID)
+ NLA_PUT_U32(msg, TCA_MATCHALL_CLASSID, mall->m_classid);
+
+ if (mall->m_mask & MALL_ATTR_FLAGS)
+ NLA_PUT_U32(msg, TCA_MATCHALL_FLAGS, mall->m_flags);
+
+ if (mall->m_mask & MALL_ATTR_ACTION) {
+ int err;
+
+ err = rtnl_act_fill(msg, TCA_MATCHALL_ACT, mall->m_act);
+ if (err)
+ return err;
+ }
+
+ return 0;
+
+ nla_put_failure:
+ return -NLE_NOMEM;
+}
+
+static int mall_clone(void *_dst, void *_src)
+{
+ struct rtnl_mall *dst = _dst, *src = _src;
+ struct rtnl_act *next;
+ int err;
+
+ if (src->m_act) {
+ if (!(dst->m_act = rtnl_act_alloc()))
+ return -NLE_NOMEM;
+
+ memcpy(dst->m_act, src->m_act, sizeof(struct rtnl_act));
+ next = rtnl_act_next(src->m_act);
+ while (next) {
+ err = rtnl_act_append(&dst->m_act, next);
+ if (err < 0)
+ return err;
+
+ next = rtnl_act_next(next);
+ }
+
+ /* action nl list next and prev pointers must be updated */
+ nl_init_list_head(&dst->m_act->ce_list);
+ }
+
+ return 0;
+}
+
+static void mall_dump_line(struct rtnl_tc *tc, void *data,
+ struct nl_dump_params *p)
+{
+ struct rtnl_mall *mall = data;
+ char buf[32];
+
+ if (!mall)
+ return;
+
+ if (mall->m_mask & MALL_ATTR_CLASSID)
+ nl_dump(p, " target %s",
+ rtnl_tc_handle2str(mall->m_classid, buf, sizeof(buf)));
+}
+
+static void mall_dump_details(struct rtnl_tc *tc, void *data,
+ struct nl_dump_params *p)
+{
+ struct rtnl_mall *mall = data;
+
+ if (!mall)
+ return;
+
+ nl_dump(p, "no details for match-all");
+}
+
+static struct rtnl_tc_ops mall_ops = {
+ .to_kind = "matchall",
+ .to_type = RTNL_TC_TYPE_CLS,
+ .to_size = sizeof(struct rtnl_mall),
+ .to_msg_parser = mall_msg_parser,
+ .to_free_data = mall_free_data,
+ .to_clone = mall_clone,
+ .to_msg_fill = mall_msg_fill,
+ .to_dump = {
+ [NL_DUMP_LINE] = mall_dump_line,
+ [NL_DUMP_DETAILS] = mall_dump_details,
+ },
+};
+
+static void __init mall_init(void)
+{
+ rtnl_tc_register(&mall_ops);
+}
+
+static void __exit mall_exit(void)
+{
+ rtnl_tc_unregister(&mall_ops);
+}
+
+/** @} */
diff --git a/libnl-route-3.sym b/libnl-route-3.sym
index efb42069..dc1d9ede 100644
--- a/libnl-route-3.sym
+++ b/libnl-route-3.sym
@@ -1098,4 +1098,11 @@ global:
rtnl_rule_set_dport;
rtnl_rule_set_dport_range;
rtnl_rule_get_dport;
+ rtnl_mall_set_classid;
+ rtnl_mall_get_classid;
+ rtnl_mall_set_flags;
+ rtnl_mall_get_flags;
+ rtnl_mall_append_action;
+ rtnl_mall_get_first_action;
+ rtnl_mall_del_action;
} libnl_3_4;