diff options
author | Volodymyr Bendiuga <volodymyr.bendiuga@westermo.se> | 2017-10-24 16:40:00 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2018-04-11 12:22:16 +0200 |
commit | 5893c3f18e29e2fa964397cf3db261583f93abdd (patch) | |
tree | 518ebdbbb203b28f11f21c4c9539f04e09ef99be | |
parent | 50918a9a50b56b8bccf15e54b355686e626710bd (diff) | |
download | libnl-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.am | 4 | ||||
-rw-r--r-- | include/netlink-private/types.h | 8 | ||||
-rw-r--r-- | include/netlink/route/cls/matchall.h | 36 | ||||
-rw-r--r-- | lib/route/cls/mall.c | 301 | ||||
-rw-r--r-- | libnl-route-3.sym | 7 |
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; |