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 <[email protected]>
Signed-off-by: Joe Stringer <[email protected]>
Signed-off-by: Greg Rose <[email protected]>
---
 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

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to