}
 
 #if IS_ENABLED(CONFIG_NF_NAT)
+static void ovs_nat_update_key(struct sw_flow_key *key,
+                              const struct sk_buff *skb,
+                              enum nf_nat_manip_type maniptype)
+{
+       if (maniptype == NF_NAT_MANIP_SRC) {
+               __be16 src;
+
+               key->ct_state |= OVS_CS_F_SRC_NAT;
+               if (key->eth.type == htons(ETH_P_IP))
+                       key->ipv4.addr.src = ip_hdr(skb)->saddr;
+               else if (key->eth.type == htons(ETH_P_IPV6))
+                       memcpy(&key->ipv6.addr.src, &ipv6_hdr(skb)->saddr,
+                              sizeof(key->ipv6.addr.src));
+               else
+                       return;
+
+               if (key->ip.proto == IPPROTO_UDP)
+                       src = udp_hdr(skb)->source;
+               else if (key->ip.proto == IPPROTO_TCP)
+                       src = tcp_hdr(skb)->source;
+               else if (key->ip.proto == IPPROTO_SCTP)
+                       src = sctp_hdr(skb)->source;
+               else
+                       return;
+
+               key->tp.src = src;
+       } else {
+               __be16 dst;
+
+               key->ct_state |= OVS_CS_F_DST_NAT;
+               if (key->eth.type == htons(ETH_P_IP))
+                       key->ipv4.addr.dst = ip_hdr(skb)->daddr;
+               else if (key->eth.type == htons(ETH_P_IPV6))
+                       memcpy(&key->ipv6.addr.dst, &ipv6_hdr(skb)->daddr,
+                              sizeof(key->ipv6.addr.dst));
+               else
+                       return;
+
+               if (key->ip.proto == IPPROTO_UDP)
+                       dst = udp_hdr(skb)->dest;
+               else if (key->ip.proto == IPPROTO_TCP)
+                       dst = tcp_hdr(skb)->dest;
+               else if (key->ip.proto == IPPROTO_SCTP)
+                       dst = sctp_hdr(skb)->dest;
+               else
+                       return;
+
+               key->tp.dst = dst;
+       }
+}
+
 /* Modelled after nf_nat_ipv[46]_fn().
  * range is only used for new, uninitialized NAT state.
  * Returns either NF_ACCEPT or NF_DROP.
 static int ovs_ct_nat_execute(struct sk_buff *skb, struct nf_conn *ct,
                              enum ip_conntrack_info ctinfo,
                              const struct nf_nat_range2 *range,
-                             enum nf_nat_manip_type maniptype)
+                             enum nf_nat_manip_type maniptype, struct sw_flow_key *key)
 {
        int hooknum, nh_off, err = NF_ACCEPT;
 
 push:
        skb_push_rcsum(skb, nh_off);
 
-       return err;
-}
-
-static void ovs_nat_update_key(struct sw_flow_key *key,
-                              const struct sk_buff *skb,
-                              enum nf_nat_manip_type maniptype)
-{
-       if (maniptype == NF_NAT_MANIP_SRC) {
-               __be16 src;
-
-               key->ct_state |= OVS_CS_F_SRC_NAT;
-               if (key->eth.type == htons(ETH_P_IP))
-                       key->ipv4.addr.src = ip_hdr(skb)->saddr;
-               else if (key->eth.type == htons(ETH_P_IPV6))
-                       memcpy(&key->ipv6.addr.src, &ipv6_hdr(skb)->saddr,
-                              sizeof(key->ipv6.addr.src));
-               else
-                       return;
-
-               if (key->ip.proto == IPPROTO_UDP)
-                       src = udp_hdr(skb)->source;
-               else if (key->ip.proto == IPPROTO_TCP)
-                       src = tcp_hdr(skb)->source;
-               else if (key->ip.proto == IPPROTO_SCTP)
-                       src = sctp_hdr(skb)->source;
-               else
-                       return;
-
-               key->tp.src = src;
-       } else {
-               __be16 dst;
-
-               key->ct_state |= OVS_CS_F_DST_NAT;
-               if (key->eth.type == htons(ETH_P_IP))
-                       key->ipv4.addr.dst = ip_hdr(skb)->daddr;
-               else if (key->eth.type == htons(ETH_P_IPV6))
-                       memcpy(&key->ipv6.addr.dst, &ipv6_hdr(skb)->daddr,
-                              sizeof(key->ipv6.addr.dst));
-               else
-                       return;
-
-               if (key->ip.proto == IPPROTO_UDP)
-                       dst = udp_hdr(skb)->dest;
-               else if (key->ip.proto == IPPROTO_TCP)
-                       dst = tcp_hdr(skb)->dest;
-               else if (key->ip.proto == IPPROTO_SCTP)
-                       dst = sctp_hdr(skb)->dest;
-               else
-                       return;
+       /* Update the flow key if NAT successful. */
+       if (err == NF_ACCEPT)
+               ovs_nat_update_key(key, skb, maniptype);
 
-               key->tp.dst = dst;
-       }
+       return err;
 }
 
 /* Returns NF_DROP if the packet should be dropped, NF_ACCEPT otherwise. */
        } else {
                return NF_ACCEPT; /* Connection is not NATed. */
        }
-       err = ovs_ct_nat_execute(skb, ct, ctinfo, &info->range, maniptype);
+       err = ovs_ct_nat_execute(skb, ct, ctinfo, &info->range, maniptype, key);
 
        if (err == NF_ACCEPT && ct->status & IPS_DST_NAT) {
                if (ct->status & IPS_SRC_NAT) {
                                maniptype = NF_NAT_MANIP_SRC;
 
                        err = ovs_ct_nat_execute(skb, ct, ctinfo, &info->range,
-                                                maniptype);
+                                                maniptype, key);
                } else if (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL) {
                        err = ovs_ct_nat_execute(skb, ct, ctinfo, NULL,
-                                                NF_NAT_MANIP_SRC);
+                                                NF_NAT_MANIP_SRC, key);
                }
        }
 
-       /* Mark NAT done if successful and update the flow key. */
-       if (err == NF_ACCEPT)
-               ovs_nat_update_key(key, skb, maniptype);
-
        return err;
 }
 #else /* !CONFIG_NF_NAT */