diff --git a/include/uapi/linux/pkt_cls.h b/include/uapi/linux/pkt_cls.h index 8fd715f806a27f327051d48a8e6b4ab8656c9703..cf45c4468caa51037e2bd5edbeed7266b7108745 100644 --- a/include/uapi/linux/pkt_cls.h +++ b/include/uapi/linux/pkt_cls.h @@ -182,6 +182,7 @@ enum { TCA_U32_MARK, TCA_U32_FLAGS, TCA_U32_PAD, + TCA_U32_EXTMARK, __TCA_U32_MAX }; diff --git a/net/sched/Kconfig b/net/sched/Kconfig index 87956a768d1b7f829876ea64614d3a2ab8efe6ea..a970e65ebb6e620b218db8c3047ec43d63cc84ea 100644 --- a/net/sched/Kconfig +++ b/net/sched/Kconfig @@ -423,6 +423,12 @@ config CLS_U32_MARK ---help--- Say Y here to be able to use netfilter marks as u32 key. +config CLS_U32_EXTMARK + bool "Netfilter extended marks support" + depends on NET_CLS_U32 + ---help--- + Say Y here to be able to use netfilter marks as u32 key. + config NET_CLS_RSVP tristate "IPv4 Resource Reservation Protocol (RSVP)" select NET_CLS diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index ae83c3aec3082d3c4a1714c909f817835925a546..f1b770d2fba4d0e1a5750f23815a3b5d99caa5ac 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c @@ -64,6 +64,9 @@ struct tc_u_knode { u32 val; u32 mask; u32 __percpu *pcpu_success; +#endif +#ifdef CONFIG_CLS_U32_EXTMARK + struct tc_u32_mark extmark; #endif struct tcf_proto *tp; struct rcu_head rcu; @@ -148,6 +151,14 @@ next_knode: __this_cpu_inc(*n->pcpu_success); } #endif +#ifdef CONFIG_CLS_U32_EXTMARK + if ((skb->extmark & n->extmark.mask) != n->extmark.val) { + n = n->next; + goto next_knode; + } else { + n->extmark.success++; + } +#endif for (i = n->sel.nkeys; i > 0; i--, key++) { int toff = off + key->off + (off2 & key->offmask); @@ -697,6 +708,9 @@ static const struct nla_policy u32_policy[TCA_U32_MAX + 1] = { [TCA_U32_SEL] = { .len = sizeof(struct tc_u32_sel) }, [TCA_U32_INDEV] = { .type = NLA_STRING, .len = IFNAMSIZ }, [TCA_U32_MARK] = { .len = sizeof(struct tc_u32_mark) }, +#ifdef CONFIG_CLS_U32_EXTMARK + [TCA_U32_EXTMARK] = { .len = sizeof(struct tc_u32_mark) }, +#endif [TCA_U32_FLAGS] = { .type = NLA_U32 }, }; @@ -1005,6 +1019,15 @@ static int u32_change(struct net *net, struct sk_buff *in_skb, n->mask = mark->mask; } #endif +#ifdef CONFIG_CLS_U32_EXTMARK + if (tb[TCA_U32_EXTMARK]) { + struct tc_u32_mark *extmark; + + extmark = nla_data(tb[TCA_U32_EXTMARK]); + memcpy(&n->extmark, extmark, sizeof(struct tc_u32_mark)); + n->extmark.success = 0; + } +#endif err = u32_set_parms(net, tp, base, ht, n, tb, tca[TCA_RATE], ovr); if (err == 0) { @@ -1149,6 +1172,12 @@ static int u32_dump(struct net *net, struct tcf_proto *tp, unsigned long fh, goto nla_put_failure; } #endif +#ifdef CONFIG_CLS_U32_EXTMARK + if ((n->extmark.val || n->extmark.mask) && + nla_put(skb, TCA_U32_EXTMARK, + sizeof(n->extmark), &n->extmark)) + goto nla_put_failure; +#endif if (tcf_exts_dump(skb, &n->exts) < 0) goto nla_put_failure;