--- /home/sagil/libnl-3.2.25-original/lib/route/cls/u32.c 2014-07-01 13:32:53.000000000 +0300 +++ u32.c 2014-11-04 12:37:50.802733000 +0200 @@ -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 @@ 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 @@ .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 @@ 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 @@ 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 @@ !(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; @@ -266,18 +293,28 @@ { struct rtnl_u32 *u = data; struct tc_u32_sel *s; + 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] ", m->val); + nl_dump(p, "[0x%u] ", 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 +326,9 @@ 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 +369,9 @@ 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; @@ -570,6 +612,26 @@ 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; +} /** * Get the 32-bit key from the selector +++ types.h 2014-11-04 13:57:17.854790237 +0200 @@ -528,6 +528,7 @@ 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];