]> git.ipfire.org Git - thirdparty/libnl.git/commitdiff
route/cls: support 'match mark' u32 filters
authorSagi Lowenhardt <sagil@infinidat.com>
Mon, 10 Nov 2014 15:51:41 +0000 (07:51 -0800)
committerThomas Haller <thaller@redhat.com>
Sun, 23 Nov 2014 14:28:55 +0000 (15:28 +0100)
Signed-off-by: Thomas Haller <thaller@redhat.com>
include/netlink-private/types.h
include/netlink/route/cls/u32.h
lib/route/cls/u32.c

index 6f3243b6b25dc24c40651eb6fa4f1e44bc9e96a3..4ba13f745ab50b0bb087c49a24b985b681b44f24 100644 (file)
@@ -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];
index f35d37a4fc53074662d7a9a2ef033679b4e2e5c8..11a812b4b4c2894b564fa078793dc70c8ac57d67 100644 (file)
@@ -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 *,
index 0a4e83cf30834af2649b0f7855c7d70da0c0c522..f194296fb70560b8bc7186b957327346096318f6 100644 (file)
@@ -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
  *