]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - net/openvswitch/conntrack.c
Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[linux.git] / net / openvswitch / conntrack.c
index 42a95919df094ba0f21cf4e4c1ade6c570f10284..bf602e33c40af4896240c9cc0566fa10126cf662 100644 (file)
@@ -516,10 +516,38 @@ ovs_ct_expect_find(struct net *net, const struct nf_conntrack_zone *zone,
                   u16 proto, const struct sk_buff *skb)
 {
        struct nf_conntrack_tuple tuple;
+       struct nf_conntrack_expect *exp;
 
        if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb), proto, net, &tuple))
                return NULL;
-       return __nf_ct_expect_find(net, zone, &tuple);
+
+       exp = __nf_ct_expect_find(net, zone, &tuple);
+       if (exp) {
+               struct nf_conntrack_tuple_hash *h;
+
+               /* Delete existing conntrack entry, if it clashes with the
+                * expectation.  This can happen since conntrack ALGs do not
+                * check for clashes between (new) expectations and existing
+                * conntrack entries.  nf_conntrack_in() will check the
+                * expectations only if a conntrack entry can not be found,
+                * which can lead to OVS finding the expectation (here) in the
+                * init direction, but which will not be removed by the
+                * nf_conntrack_in() call, if a matching conntrack entry is
+                * found instead.  In this case all init direction packets
+                * would be reported as new related packets, while reply
+                * direction packets would be reported as un-related
+                * established packets.
+                */
+               h = nf_conntrack_find_get(net, zone, &tuple);
+               if (h) {
+                       struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h);
+
+                       nf_ct_delete(ct, 0, 0);
+                       nf_conntrack_put(&ct->ct_general);
+               }
+       }
+
+       return exp;
 }
 
 /* This replicates logic from nf_conntrack_core.c that is not exported. */