[ovs-dev] [PATCH] conntrack: Fix for force/commit bug

Greg Rose gvrose8192 at gmail.com
Wed Jul 12 18:05:20 UTC 2017


When the direction is being forced key->ct_state may not have been
set.  Check for this condition and take action to set the state
correctly so that the force direction occurs.

Co-authored-by: Joe Stringer <joe at ovn.org>
Signed-off-by: Joe Stringer <joe at ovn.org>
Signed-off-by: Greg Rose <gvrose8192 at gmail.com>
---
 datapath/conntrack.c | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/datapath/conntrack.c b/datapath/conntrack.c
index bf28fc0..2da0321 100644
--- a/datapath/conntrack.c
+++ b/datapath/conntrack.c
@@ -665,7 +665,7 @@ ovs_ct_find_existing(struct net *net, const struct nf_conntrack_zone *zone,
 
 /* Determine whether skb->_nfct is equal to the result of conntrack lookup. */
 static bool skb_nfct_cached(struct net *net,
-			    const struct sw_flow_key *key,
+			    struct sw_flow_key *key,
 			    const struct ovs_conntrack_info *info,
 			    struct sk_buff *skb)
 {
@@ -675,12 +675,22 @@ static bool skb_nfct_cached(struct net *net,
 	ct = nf_ct_get(skb, &ctinfo);
 	/* If no ct, check if we have evidence that an existing conntrack entry
 	 * might be found for this skb.  This happens when we lose a skb->_nfct
-	 * due to an upcall.  If the connection was not confirmed, it is not
-	 * cached and needs to be run through conntrack again.
+	 * due to an upcall, or if the direction is being forced.  If the
+	 * connection was not confirmed, it is not cached and needs to be run
+	 * through conntrack again.
 	 */
-	if (!ct && key->ct_state & OVS_CS_F_TRACKED &&
+	if ((!ct && (key->ct_state & OVS_CS_F_TRACKED &&
 	    !(key->ct_state & OVS_CS_F_INVALID) &&
-	    key->ct_zone == info->zone.id) {
+	    key->ct_zone == info->zone.id)) ||
+	    (!key->ct_state && info->force)) {
+		if (!key->ct_state && info->force && !info->ct) {
+			int result = nf_conntrack_in(net, info->family,
+						     NF_INET_PRE_ROUTING, skb);
+			if (result != NF_ACCEPT)
+				return false;
+			/* Update the key, but keep the NAT flags. */
+			ovs_ct_update_key(skb, info, key, true, true);
+		}
 		ct = ovs_ct_find_existing(net, &info->zone, info->family, skb,
 					  !!(key->ct_state
 					     & OVS_CS_F_NAT_MASK));
-- 
1.8.3.1



More information about the dev mailing list