summaryrefslogtreecommitdiffstats
path: root/lib/route/cls/u32.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/route/cls/u32.c')
-rw-r--r--lib/route/cls/u32.c90
1 files changed, 85 insertions, 5 deletions
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
*