]> granicus.if.org Git - ipset/commitdiff
net: sched: fix skb->protocol use in case of accelerated vlan path
authorJiri Pirko <jiri@resnulli.us>
Tue, 11 Oct 2016 20:09:08 +0000 (22:09 +0200)
committerJozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Tue, 11 Oct 2016 20:09:08 +0000 (22:09 +0200)
tc code implicitly considers skb->protocol even in case of accelerated
vlan paths and expects vlan protocol type here. However, on rx path,
if the vlan header was already stripped, skb->protocol contains value
of next header. Similar situation is on tx path.

So for skbs that use skb->vlan_tci for tagging, use skb->vlan_proto instead.

Reported-by: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: Jiri Pirko <jiri@resnulli.us>
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
configure.ac
kernel/include/linux/netfilter/ipset/ip_set_compat.h.in
kernel/net/sched/em_ipset.c

index b73b3cc7e706e330ff5c7476b8f768745efaf8ec..f046e8bb76f7ceecb02c4efe77ff799b13e5cfc8 100644 (file)
@@ -487,6 +487,16 @@ else
        AC_SUBST(HAVE_EXPORT_SYMBOL_GPL_IN_MODULE_H, undef)
 fi
 
+AC_MSG_CHECKING([kernel source for tc_skb_protocol in pkt_sched.h])
+if test -f $ksourcedir/include/net/pkt_sched.h && \
+   $GREP -q 'tc_skb_protocol' $ksourcedir/include/net/pkt_sched.h; then
+       AC_MSG_RESULT(yes)
+       AC_SUBST(HAVE_TC_SKB_PROTOCOL, define)
+else
+       AC_MSG_RESULT(no)
+       AC_SUBST(HAVE_TC_SKB_PROTOCOL, undef)
+fi
+
 AC_MSG_CHECKING([kernel source for struct net_generic])
 if test -f $ksourcedir/include/net/netns/generic.h && \
    $GREP -q 'struct net_generic' $ksourcedir/include/net/netns/generic.h; then
index fe24255843fac4bb08c2f425885c9a57a868dac1..062becbc4d2be4e7a32134a1a9846a830903ee91 100644 (file)
@@ -33,6 +33,7 @@
 #@HAVE_NLA_PUT_IN_ADDR@ HAVE_NLA_PUT_IN_ADDR
 #@HAVE_NET_IN_NFNL_CALLBACK_FN@ HAVE_NET_IN_NFNL_CALLBACK_FN
 #@HAVE_EXPORT_SYMBOL_GPL_IN_MODULE_H@ HAVE_EXPORT_SYMBOL_GPL_IN_MODULE_H
+#@HAVE_TC_SKB_PROTOCOL@ HAVE_TC_SKB_PROTOCOL
 
 #ifdef HAVE_EXPORT_SYMBOL_GPL_IN_MODULE_H
 #include <linux/module.h>
@@ -273,6 +274,16 @@ static inline int nla_put_in6_addr(struct sk_buff *skb, int attrtype,
 #define IPSET_SOCK_NET(net, ctnl)              sock_net(ctnl)
 #endif
 
+#ifndef HAVE_TC_SKB_PROTOCOL
+#include <linux/if_vlan.h>
+static inline __be16 tc_skb_protocol(const struct sk_buff *skb)
+{
+       if (vlan_tx_tag_present(skb))
+               return skb->vlan_proto;
+       return skb->protocol;
+}
+#endif
+
 #ifndef smp_mb__before_atomic
 #define smp_mb__before_atomic()        smp_mb()
 #define smp_mb__after_atomic() smp_mb()
index bc1a2f1b7128060b679caec23ca4216f1919fbb2..87b84191e5542b2362c3fccf76b175e54dc4f613 100644 (file)
@@ -77,7 +77,7 @@ static int em_ipset_match(struct sk_buff *skb, struct tcf_ematch *em,
        struct net_device *dev, *indev = NULL;
        int ret, network_offset;
 
-       switch (skb->protocol) {
+       switch (tc_skb_protocol(skb)) {
        case htons(ETH_P_IP):
                acpar.family = NFPROTO_IPV4;
                if (!pskb_network_may_pull(skb, sizeof(struct iphdr)))