net: openvswitch: Be liberal in tcp conntrack.
authorNuman Siddique <nusiddiq@redhat.com>
Mon, 16 Nov 2020 13:01:26 +0000 (18:31 +0530)
committerJakub Kicinski <kuba@kernel.org>
Fri, 20 Nov 2020 17:53:48 +0000 (09:53 -0800)
There is no easy way to distinguish if a conntracked tcp packet is
marked invalid because of tcp_in_window() check error or because
it doesn't belong to an existing connection. With this patch,
openvswitch sets liberal tcp flag for the established sessions so
that out of window packets are not marked invalid.

A helper function - nf_ct_set_tcp_be_liberal(nf_conn) is added which
sets this flag for both the directions of the nf_conn.

Suggested-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Numan Siddique <nusiddiq@redhat.com>
Acked-by: Florian Westphal <fw@strlen.de>
Link: https://lore.kernel.org/r/20201116130126.3065077-1-nusiddiq@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
include/net/netfilter/nf_conntrack_l4proto.h
net/netfilter/nf_conntrack_proto_tcp.c
net/openvswitch/conntrack.c

index 88186b95b3c2c9d81f50faa3691ed4171356ed34..9be7320b994fa333429016f9c78f4a228be7d86c 100644 (file)
@@ -203,6 +203,20 @@ static inline struct nf_icmp_net *nf_icmpv6_pernet(struct net *net)
 {
        return &net->ct.nf_ct_proto.icmpv6;
 }
+
+/* Caller must check nf_ct_protonum(ct) is IPPROTO_TCP before calling. */
+static inline void nf_ct_set_tcp_be_liberal(struct nf_conn *ct)
+{
+       ct->proto.tcp.seen[0].flags |= IP_CT_TCP_FLAG_BE_LIBERAL;
+       ct->proto.tcp.seen[1].flags |= IP_CT_TCP_FLAG_BE_LIBERAL;
+}
+
+/* Caller must check nf_ct_protonum(ct) is IPPROTO_TCP before calling. */
+static inline bool nf_conntrack_tcp_established(const struct nf_conn *ct)
+{
+       return ct->proto.tcp.state == TCP_CONNTRACK_ESTABLISHED &&
+              test_bit(IPS_ASSURED_BIT, &ct->status);
+}
 #endif
 
 #ifdef CONFIG_NF_CT_PROTO_DCCP
index c8fb2187ad4b2df200273acdbdf2163c831de09b..811c6c9b59e171daf0497959955740f77f75a0d3 100644 (file)
@@ -834,12 +834,6 @@ static noinline bool tcp_new(struct nf_conn *ct, const struct sk_buff *skb,
        return true;
 }
 
-static bool nf_conntrack_tcp_established(const struct nf_conn *ct)
-{
-       return ct->proto.tcp.state == TCP_CONNTRACK_ESTABLISHED &&
-              test_bit(IPS_ASSURED_BIT, &ct->status);
-}
-
 /* Returns verdict for packet, or -1 for invalid. */
 int nf_conntrack_tcp_packet(struct nf_conn *ct,
                            struct sk_buff *skb,
index 4beb96139d7763dbe0784e54aa76daf8dc337bd4..6a88daab019082f56a6f8f956779b1b60f066fec 100644 (file)
@@ -1037,6 +1037,14 @@ static int __ovs_ct_lookup(struct net *net, struct sw_flow_key *key,
                    ovs_ct_helper(skb, info->family) != NF_ACCEPT) {
                        return -EINVAL;
                }
+
+               if (nf_ct_protonum(ct) == IPPROTO_TCP &&
+                   nf_ct_is_confirmed(ct) && nf_conntrack_tcp_established(ct)) {
+                       /* Be liberal for tcp packets so that out-of-window
+                        * packets are not marked invalid.
+                        */
+                       nf_ct_set_tcp_be_liberal(ct);
+               }
        }
 
        return 0;