From 3844b15d734b5017e234a4ffcc1c55c15942b6bb Mon Sep 17 00:00:00 2001 From: Sagi Lowenhardt Date: Mon, 10 Nov 2014 07:51:41 -0800 Subject: [PATCH 1/2] route/cls: support 'match mark' u32 filters Signed-off-by: Thomas Haller --- include/netlink-private/types.h | 1 + include/netlink/route/cls/u32.h | 2 + lib/route/cls/u32.c | 90 +++++++++++++++++++++++++++++++-- 3 files changed, 88 insertions(+), 5 deletions(-) diff --git a/include/netlink-private/types.h b/include/netlink-private/types.h index 6f3243b..4ba13f7 100644 --- a/include/netlink-private/types.h +++ b/include/netlink-private/types.h @@ -528,6 +528,7 @@ struct rtnl_u32 uint32_t cu_link; struct nl_data * cu_pcnt; struct nl_data * cu_selector; + struct nl_data * cu_mark; struct rtnl_act* cu_act; struct nl_data * cu_police; char cu_indev[IFNAMSIZ]; diff --git a/include/netlink/route/cls/u32.h b/include/netlink/route/cls/u32.h index f35d37a..11a812b 100644 --- a/include/netlink/route/cls/u32.h +++ b/include/netlink/route/cls/u32.h @@ -30,6 +30,8 @@ extern int rtnl_u32_set_hashmask(struct rtnl_cls *, uint32_t, uint32_t); extern int rtnl_u32_set_cls_terminal(struct rtnl_cls *); extern int rtnl_u32_set_flags(struct rtnl_cls *, int); +extern int rtnl_u32_add_mark(struct rtnl_cls *, uint32_t, uint32_t); +extern int rtnl_u32_del_mark(struct rtnl_cls *); extern int rtnl_u32_add_key(struct rtnl_cls *, uint32_t, uint32_t, int, int); extern int rtnl_u32_get_key(struct rtnl_cls *, uint8_t, uint32_t *, uint32_t *, diff --git a/lib/route/cls/u32.c b/lib/route/cls/u32.c index 0a4e83c..f194296 100644 --- a/lib/route/cls/u32.c +++ b/lib/route/cls/u32.c @@ -38,6 +38,7 @@ #define U32_ATTR_ACTION 0x040 #define U32_ATTR_POLICE 0x080 #define U32_ATTR_INDEV 0x100 +#define U32_ATTR_MARK 0x200 /** @endcond */ static inline struct tc_u32_sel *u32_selector(struct rtnl_u32 *u) @@ -53,6 +54,19 @@ static inline struct tc_u32_sel *u32_selector_alloc(struct rtnl_u32 *u) return u32_selector(u); } +static inline struct tc_u32_mark *u32_mark(struct rtnl_u32 *u) +{ + return (struct tc_u32_mark *) u->cu_mark->d_data; +} + +static inline struct tc_u32_mark *u32_mark_alloc(struct rtnl_u32 *u) +{ + if (!u->cu_mark) + u->cu_mark = nl_data_alloc(NULL, sizeof(struct tc_u32_mark)); + + return u32_mark(u); +} + static struct nla_policy u32_policy[TCA_U32_MAX+1] = { [TCA_U32_DIVISOR] = { .type = NLA_U32 }, [TCA_U32_HASH] = { .type = NLA_U32 }, @@ -62,6 +76,7 @@ static struct nla_policy u32_policy[TCA_U32_MAX+1] = { .maxlen = IFNAMSIZ }, [TCA_U32_SEL] = { .minlen = sizeof(struct tc_u32_sel) }, [TCA_U32_PCNT] = { .minlen = sizeof(struct tc_u32_pcnt) }, + [TCA_U32_MARK] = { .minlen = sizeof(struct tc_u32_mark) } }; static int u32_msg_parser(struct rtnl_tc *tc, void *data) @@ -86,6 +101,13 @@ static int u32_msg_parser(struct rtnl_tc *tc, void *data) u->cu_mask |= U32_ATTR_SELECTOR; } + if (tb[TCA_U32_MARK]) { + u->cu_mark = nl_data_alloc_attr(tb[TCA_U32_MARK]); + if (!u->cu_mark) + goto errout_nomem; + u->cu_mask |= U32_ATTR_MARK; + } + if (tb[TCA_U32_HASH]) { u->cu_hash = nla_get_u32(tb[TCA_U32_HASH]); u->cu_mask |= U32_ATTR_HASH; @@ -157,6 +179,7 @@ static void u32_free_data(struct rtnl_tc *tc, void *data) if (u->cu_act) rtnl_act_put_all(&u->cu_act); + nl_data_free(u->cu_mark); nl_data_free(u->cu_selector); nl_data_free(u->cu_police); nl_data_free(u->cu_pcnt); @@ -170,6 +193,10 @@ static int u32_clone(void *_dst, void *_src) !(dst->cu_selector = nl_data_clone(src->cu_selector))) return -NLE_NOMEM; + if (src->cu_mark && + !(dst->cu_mark = nl_data_clone(src->cu_mark))) + return -NLE_NOMEM; + if (src->cu_act) { if (!(dst->cu_act = rtnl_act_alloc())) return -NLE_NOMEM; @@ -265,19 +292,28 @@ static void u32_dump_details(struct rtnl_tc *tc, void *data, struct nl_dump_params *p) { struct rtnl_u32 *u = data; - struct tc_u32_sel *s; + struct tc_u32_sel *s = NULL; + struct tc_u32_mark *m; if (!u) return; if (!(u->cu_mask & U32_ATTR_SELECTOR)) { nl_dump(p, "no-selector\n"); - return; + } else { + s = u->cu_selector->d_data; + nl_dump(p, "nkeys %u ", s->nkeys); } - s = u->cu_selector->d_data; + if (!(u->cu_mask & U32_ATTR_MARK)) { + nl_dump(p, "no-mark\n"); + } else { + m = u->cu_mark->d_data; + nl_dump(p, "mark 0x%u 0x%u\n", m->val, m->mask); + } - nl_dump(p, "nkeys %u ", s->nkeys); + if (!(u->cu_mask & U32_ATTR_SELECTOR) && !(u->cu_mask & U32_ATTR_MARK)) + return; if (u->cu_mask & U32_ATTR_HASH) nl_dump(p, "ht key 0x%x hash 0x%u", @@ -289,7 +325,9 @@ static void u32_dump_details(struct rtnl_tc *tc, void *data, if (u->cu_mask & U32_ATTR_INDEV) nl_dump(p, "indev %s ", u->cu_indev); - print_selector(p, s, u); + if (u->cu_mask & U32_ATTR_SELECTOR) + print_selector(p, s, u); + nl_dump(p, "\n"); } @@ -330,6 +368,9 @@ static int u32_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg) if (u->cu_mask & U32_ATTR_SELECTOR) NLA_PUT_DATA(msg, TCA_U32_SEL, u->cu_selector); + + if (u->cu_mask & U32_ATTR_MARK) + NLA_PUT_DATA(msg, TCA_U32_MARK, u->cu_mark); if (u->cu_mask & U32_ATTR_ACTION) { int err; @@ -571,6 +612,45 @@ int rtnl_u32_add_key(struct rtnl_cls *cls, uint32_t val, uint32_t mask, return 0; } +int rtnl_u32_add_mark(struct rtnl_cls *cls, uint32_t val, uint32_t mask) +{ + struct tc_u32_mark *mark; + struct rtnl_u32 *u; + + if (!(u = rtnl_tc_data(TC_CAST(cls)))) + return -NLE_NOMEM; + + mark = u32_mark_alloc(u); + if (!mark) + return -NLE_NOMEM; + + mark->mask = mask; + mark->val = val; + + u->cu_mask |= U32_ATTR_MARK; + + return 0; +} + +int rtnl_u32_del_mark(struct rtnl_cls *cls) +{ + struct rtnl_u32 *u; + + if (!(u = rtnl_tc_data(TC_CAST(cls)))) + return -NLE_NOMEM; + + if (!(u->cu_mask)) + return -NLE_INVAL; + + if (!(u->cu_mask & U32_ATTR_MARK)) + return -NLE_INVAL; + + nl_data_free(u->cu_mark); + u->cu_mark = NULL; + + return 0; +} + /** * Get the 32-bit key from the selector * From 8759c20beb60a441acbd98af27e7b8f1d3e2eb95 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Sun, 23 Nov 2014 15:25:01 +0100 Subject: [PATCH 2/2] route/cls: minor fixes in for match mark filters - whitespace - fix newline and whitespace in output of u32_dump_details() - let rtnl_u32_del_mark() clear U32_ATTR_MARK Signed-off-by: Thomas Haller --- include/netlink/route/cls/u32.h | 4 +-- lib/route/cls/u32.c | 56 ++++++++++++++++----------------- 2 files changed, 29 insertions(+), 31 deletions(-) diff --git a/include/netlink/route/cls/u32.h b/include/netlink/route/cls/u32.h index 11a812b..4567e16 100644 --- a/include/netlink/route/cls/u32.h +++ b/include/netlink/route/cls/u32.h @@ -30,8 +30,8 @@ extern int rtnl_u32_set_hashmask(struct rtnl_cls *, uint32_t, uint32_t); extern int rtnl_u32_set_cls_terminal(struct rtnl_cls *); extern int rtnl_u32_set_flags(struct rtnl_cls *, int); -extern int rtnl_u32_add_mark(struct rtnl_cls *, uint32_t, uint32_t); -extern int rtnl_u32_del_mark(struct rtnl_cls *); +extern int rtnl_u32_add_mark(struct rtnl_cls *, uint32_t, uint32_t); +extern int rtnl_u32_del_mark(struct rtnl_cls *); extern int rtnl_u32_add_key(struct rtnl_cls *, uint32_t, uint32_t, int, int); extern int rtnl_u32_get_key(struct rtnl_cls *, uint8_t, uint32_t *, uint32_t *, diff --git a/lib/route/cls/u32.c b/lib/route/cls/u32.c index f194296..1912533 100644 --- a/lib/route/cls/u32.c +++ b/lib/route/cls/u32.c @@ -54,17 +54,12 @@ static inline struct tc_u32_sel *u32_selector_alloc(struct rtnl_u32 *u) return u32_selector(u); } -static inline struct tc_u32_mark *u32_mark(struct rtnl_u32 *u) -{ - return (struct tc_u32_mark *) u->cu_mark->d_data; -} - static inline struct tc_u32_mark *u32_mark_alloc(struct rtnl_u32 *u) { if (!u->cu_mark) u->cu_mark = nl_data_alloc(NULL, sizeof(struct tc_u32_mark)); - return u32_mark(u); + return (struct tc_u32_mark *) u->cu_mark->d_data; } static struct nla_policy u32_policy[TCA_U32_MAX+1] = { @@ -145,7 +140,7 @@ static int u32_msg_parser(struct rtnl_tc *tc, void *data) err = -NLE_MISSING_ATTR; goto errout; } - + sel = u->cu_selector->d_data; pcnt_size = sizeof(struct tc_u32_pcnt) + (sel->nkeys * sizeof(uint64_t)); @@ -193,7 +188,7 @@ static int u32_clone(void *_dst, void *_src) !(dst->cu_selector = nl_data_clone(src->cu_selector))) return -NLE_NOMEM; - if (src->cu_mark && + if (src->cu_mark && !(dst->cu_mark = nl_data_clone(src->cu_mark))) return -NLE_NOMEM; @@ -218,7 +213,7 @@ static void u32_dump_line(struct rtnl_tc *tc, void *data, { struct rtnl_u32 *u = data; char buf[32]; - + if (!u) return; @@ -266,8 +261,8 @@ static void print_selector(struct nl_dump_params *p, struct tc_u32_sel *sel, nl_dump(p, ">"); } - - + + for (i = 0; i < sel->nkeys; i++) { key = (struct tc_u32_key *) ((char *) sel + sizeof(*sel)) + i; @@ -298,32 +293,34 @@ static void u32_dump_details(struct rtnl_tc *tc, void *data, if (!u) return; - if (!(u->cu_mask & U32_ATTR_SELECTOR)) { - nl_dump(p, "no-selector\n"); - } else { - s = u->cu_selector->d_data; - nl_dump(p, "nkeys %u ", s->nkeys); + if (!(u->cu_mask & (U32_ATTR_SELECTOR & U32_ATTR_MARK))) { + nl_dump(p, "no-selector no-mark\n"); + return; } - + + if (!(u->cu_mask & U32_ATTR_SELECTOR)) { + nl_dump(p, "no-selector"); + } else { + s = u->cu_selector->d_data; + nl_dump(p, "nkeys %u", s->nkeys); + } + if (!(u->cu_mask & U32_ATTR_MARK)) { - nl_dump(p, "no-mark\n"); + nl_dump(p, " no-mark"); } else { m = u->cu_mark->d_data; - nl_dump(p, "mark 0x%u 0x%u\n", m->val, m->mask); + nl_dump(p, " mark 0x%u 0x%u", m->val, m->mask); } - if (!(u->cu_mask & U32_ATTR_SELECTOR) && !(u->cu_mask & U32_ATTR_MARK)) - return; - if (u->cu_mask & U32_ATTR_HASH) - nl_dump(p, "ht key 0x%x hash 0x%u", + nl_dump(p, " ht key 0x%x hash 0x%u", TC_U32_USERHTID(u->cu_hash), TC_U32_HASH(u->cu_hash)); if (u->cu_mask & U32_ATTR_LINK) - nl_dump(p, "link %u ", u->cu_link); + nl_dump(p, " link %u", u->cu_link); if (u->cu_mask & U32_ATTR_INDEV) - nl_dump(p, "indev %s ", u->cu_indev); + nl_dump(p, " indev %s", u->cu_indev); if (u->cu_mask & U32_ATTR_SELECTOR) print_selector(p, s, u); @@ -353,7 +350,7 @@ static int u32_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg) if (!u) return 0; - + if (u->cu_mask & U32_ATTR_DIVISOR) NLA_PUT_U32(msg, TCA_U32_DIVISOR, u->cu_divisor); @@ -368,7 +365,7 @@ static int u32_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg) if (u->cu_mask & U32_ATTR_SELECTOR) NLA_PUT_DATA(msg, TCA_U32_SEL, u->cu_selector); - + if (u->cu_mask & U32_ATTR_MARK) NLA_PUT_DATA(msg, TCA_U32_MARK, u->cu_mark); @@ -404,14 +401,14 @@ void rtnl_u32_set_handle(struct rtnl_cls *cls, int htid, int hash, rtnl_tc_set_handle((struct rtnl_tc *) cls, handle ); } - + int rtnl_u32_set_classid(struct rtnl_cls *cls, uint32_t classid) { struct rtnl_u32 *u; if (!(u = rtnl_tc_data(TC_CAST(cls)))) return -NLE_NOMEM; - + u->cu_classid = classid; u->cu_mask |= U32_ATTR_CLASSID; @@ -647,6 +644,7 @@ int rtnl_u32_del_mark(struct rtnl_cls *cls) nl_data_free(u->cu_mark); u->cu_mark = NULL; + u->cu_mask &= ~U32_ATTR_MARK; return 0; }