diff --git a/SOURCES/openvswitch-2.13.0.patch b/SOURCES/openvswitch-2.13.0.patch
index b2dffa5..1d46d02 100644
--- a/SOURCES/openvswitch-2.13.0.patch
+++ b/SOURCES/openvswitch-2.13.0.patch
@@ -79976,6 +79976,18 @@ index 5289a70f6e..cf009f8264 100644
  #define OVS_LOCKABLE __attribute__((lockable))
  #define OVS_REQ_RDLOCK(...) __attribute__((shared_locks_required(__VA_ARGS__)))
  #define OVS_ACQ_RDLOCK(...) __attribute__((shared_lock_function(__VA_ARGS__)))
+diff --git a/include/openvswitch/meta-flow.h b/include/openvswitch/meta-flow.h
+index 1f81d830e7..4b9893388b 100644
+--- a/include/openvswitch/meta-flow.h
++++ b/include/openvswitch/meta-flow.h
+@@ -2277,6 +2277,7 @@ void mf_set_flow_value_masked(const struct mf_field *,
+                               const union mf_value *mask,
+                               struct flow *);
+ bool mf_is_tun_metadata(const struct mf_field *);
++bool mf_is_frozen_metadata(const struct mf_field *);
+ bool mf_is_pipeline_field(const struct mf_field *);
+ bool mf_is_set(const struct mf_field *, const struct flow *);
+ void mf_mask_field(const struct mf_field *, struct flow_wildcards *);
 diff --git a/ipsec/ovs-monitor-ipsec.in b/ipsec/ovs-monitor-ipsec.in
 index 37e3703245..668507fd37 100755
 --- a/ipsec/ovs-monitor-ipsec.in
@@ -82235,10 +82247,30 @@ index 19e9305266..34738535db 100644
              }
              chassis->c_protocol = port->p_protocol = cfg->g_protocols[i].mode;
 diff --git a/lib/meta-flow.c b/lib/meta-flow.c
-index 8b62e6d968..80063b933d 100644
+index 8b62e6d968..8a48a41197 100644
 --- a/lib/meta-flow.c
 +++ b/lib/meta-flow.c
-@@ -2296,12 +2296,6 @@ mf_set(const struct mf_field *mf,
+@@ -1764,6 +1764,19 @@ mf_is_tun_metadata(const struct mf_field *mf)
+            mf->id < MFF_TUN_METADATA0 + TUN_METADATA_NUM_OPTS;
+ }
+ 
++bool
++mf_is_frozen_metadata(const struct mf_field *mf)
++{
++    if (mf->id >= MFF_TUN_ID && mf->id <= MFF_IN_PORT_OXM) {
++        return true;
++    }
++
++    if (mf->id >= MFF_REG0 && mf->id < MFF_ETH_SRC) {
++        return true;
++    }
++    return false;
++}
++
+ bool
+ mf_is_pipeline_field(const struct mf_field *mf)
+ {
+@@ -2296,12 +2309,6 @@ mf_set(const struct mf_field *mf,
      switch (mf->id) {
      case MFF_CT_ZONE:
      case MFF_CT_NW_PROTO:
@@ -82251,7 +82283,7 @@ index 8b62e6d968..80063b933d 100644
      case MFF_RECIRC_ID:
      case MFF_PACKET_TYPE:
      case MFF_CONJ_ID:
-@@ -2419,6 +2413,30 @@ mf_set(const struct mf_field *mf,
+@@ -2419,6 +2426,30 @@ mf_set(const struct mf_field *mf,
                                    ntoh128(mask->be128));
          break;
  
@@ -85297,7 +85329,7 @@ index 409286ab15..cb197e9010 100644
  
              ofproto_dpif_send_async_msg(upcall->ofproto, am);
 diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
-index 4407f9c97a..04a75e12d3 100644
+index 4407f9c97a..72c0a0efce 100644
 --- a/ofproto/ofproto-dpif-xlate.c
 +++ b/ofproto/ofproto-dpif-xlate.c
 @@ -1516,15 +1516,32 @@ xlate_lookup_ofproto_(const struct dpif_backer *backer,
@@ -85372,7 +85404,55 @@ index 4407f9c97a..04a75e12d3 100644
  }
  
  static void
-@@ -7519,7 +7536,8 @@ xlate_actions(struct xlate_in *xin, struct xlate_out *xout)
+@@ -6123,11 +6140,32 @@ static void
+ compose_conntrack_action(struct xlate_ctx *ctx, struct ofpact_conntrack *ofc,
+                          bool is_last_action)
+ {
+-    ovs_u128 old_ct_label_mask = ctx->wc->masks.ct_label;
+-    uint32_t old_ct_mark_mask = ctx->wc->masks.ct_mark;
+-    size_t ct_offset;
+     uint16_t zone;
++    if (ofc->zone_src.field) {
++        union mf_subvalue value;
++        memset(&value, 0xff, sizeof(value));
++
++        zone = mf_get_subfield(&ofc->zone_src, &ctx->xin->flow);
++        if (ctx->xin->frozen_state) {
++            /* If the upcall is a resume of a recirculation, we only need to
++             * unwildcard the fields that are not in the frozen_metadata, as
++             * when the rules update, OVS will generate a new recirc_id,
++             * which will invalidate the megaflow with old the recirc_id.
++             */
++            if (!mf_is_frozen_metadata(ofc->zone_src.field)) {
++                mf_write_subfield_flow(&ofc->zone_src, &value,
++                                       &ctx->wc->masks);
++            }
++        } else {
++            mf_write_subfield_flow(&ofc->zone_src, &value, &ctx->wc->masks);
++        }
++    } else {
++        zone = ofc->zone_imm;
++    }
+ 
++    size_t ct_offset;
++    ovs_u128 old_ct_label_mask = ctx->wc->masks.ct_label;
++    uint32_t old_ct_mark_mask = ctx->wc->masks.ct_mark;
+     /* Ensure that any prior actions are applied before composing the new
+      * conntrack action. */
+     xlate_commit_actions(ctx);
+@@ -6139,11 +6177,6 @@ compose_conntrack_action(struct xlate_ctx *ctx, struct ofpact_conntrack *ofc,
+     do_xlate_actions(ofc->actions, ofpact_ct_get_action_len(ofc), ctx,
+                      is_last_action, false);
+ 
+-    if (ofc->zone_src.field) {
+-        zone = mf_get_subfield(&ofc->zone_src, &ctx->xin->flow);
+-    } else {
+-        zone = ofc->zone_imm;
+-    }
+ 
+     ct_offset = nl_msg_start_nested(ctx->odp_actions, OVS_ACTION_ATTR_CT);
+     if (ofc->flags & NX_CT_F_COMMIT) {
+@@ -7519,7 +7552,8 @@ xlate_actions(struct xlate_in *xin, struct xlate_out *xout)
  
          /* Restore pipeline metadata. May change flow's in_port and other
           * metadata to the values that existed when freezing was triggered. */
@@ -85382,7 +85462,7 @@ index 4407f9c97a..04a75e12d3 100644
  
          /* Restore stack, if any. */
          if (state->stack) {
-@@ -7571,14 +7589,10 @@ xlate_actions(struct xlate_in *xin, struct xlate_out *xout)
+@@ -7571,14 +7605,10 @@ xlate_actions(struct xlate_in *xin, struct xlate_out *xout)
              ctx.error = XLATE_INVALID_TUNNEL_METADATA;
              goto exit;
          }
@@ -89748,7 +89828,7 @@ index 0000000000..1714273e35
 +OVS_TRAFFIC_VSWITCHD_STOP
 +AT_CLEANUP
 diff --git a/tests/system-traffic.at b/tests/system-traffic.at
-index 4a39c929c2..620cd2512f 100644
+index 4a39c929c2..b5097f2ac3 100644
 --- a/tests/system-traffic.at
 +++ b/tests/system-traffic.at
 @@ -574,6 +574,60 @@ NS_CHECK_EXEC([at_ns0], [ping -s 3200 -q -c 3 -i 0.3 -w 2 10.1.1.100 | FORMAT_PI
@@ -89829,7 +89909,119 @@ index 4a39c929c2..620cd2512f 100644
  OVS_APP_EXIT_AND_WAIT([ovs-ofctl])
  OVS_TRAFFIC_VSWITCHD_STOP
  AT_CLEANUP
-@@ -2331,6 +2395,35 @@ NXST_FLOW reply:
+@@ -1925,6 +1989,111 @@ tcp,orig=(src=10.1.1.3,dst=10.1.1.4,sport=<cleared>,dport=<cleared>),reply=(src=
+ OVS_TRAFFIC_VSWITCHD_STOP
+ AT_CLEANUP
+ 
++AT_SETUP([conntrack - zones from other field])
++CHECK_CONNTRACK()
++OVS_TRAFFIC_VSWITCHD_START()
++
++ADD_NAMESPACES(at_ns0, at_ns1)
++
++ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24")
++ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24")
++
++dnl Allow any traffic from ns0->ns1. Only allow nd, return traffic from ns1->ns0.
++AT_DATA([flows.txt], [dnl
++priority=1,action=drop
++priority=10,arp,action=normal
++priority=10,icmp,action=normal
++priority=100,in_port=1,tcp,ct_state=-trk,action=ct(zone=5,table=0)
++priority=100,in_port=1,tcp,ct_state=+trk,action=ct(commit,zone=NXM_NX_CT_ZONE[]),2
++priority=100,in_port=2,ct_state=-trk,tcp,action=ct(table=0,zone=5)
++priority=100,in_port=2,ct_state=+trk,ct_zone=5,tcp,action=1
++])
++
++AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt])
++
++OVS_START_L7([at_ns1], [http])
++
++dnl HTTP requests from p0->p1 should work fine.
++NS_CHECK_EXEC([at_ns0], [wget 10.1.1.2 -t 3 -T 1 --retry-connrefused -v -o wget0.log])
++
++AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1.2)], [0], [dnl
++tcp,dnl
++orig=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),dnl
++reply=(src=10.1.1.2,dst=10.1.1.1,sport=<cleared>,dport=<cleared>),dnl
++zone=5,protoinfo=(state=<cleared>)
++])
++
++dnl This is to test when the zoneid is set by a field variable like
++dnl NXM_NX_CT_ZONE, the OVS xlate should generate a megaflow with a form of
++dnl "ct_zone(5), ...  actions: ct(commit, zone=5)".  The match "ct_zone(5)"
++dnl is needed as if we changes the zoneid into 15 in the following, the old
++dnl "ct_zone(5), ... actions: ct(commit, zone=5)" megaflow will not get hit,
++dnl and OVS will generate a new megaflow with the match "ct_zone(0xf)".
++dnl This will make sure that the new packets are committing to zoneid 15
++dnl rather than old 5.
++AT_CHECK([ovs-appctl dpctl/dump-flows --names filter=in_port=ovs-p0 dnl
++              | grep "+trk" | grep -q "ct_zone(0x5)" ], [0], [])
++
++AT_CHECK([ovs-ofctl mod-flows br0 dnl
++            'priority=100,ct_state=-trk,tcp,in_port="ovs-p0" actions=ct(table=0,zone=15)'])
++
++NS_CHECK_EXEC([at_ns0], [wget 10.1.1.2 -t 3 -T 1 --retry-connrefused -v -o wget0.log])
++
++AT_CHECK([ovs-appctl dpctl/dump-flows --names filter=in_port=ovs-p0 dnl
++              | grep "+trk" | grep -q "ct_zone(0xf)" ], [0], [])
++
++OVS_TRAFFIC_VSWITCHD_STOP
++AT_CLEANUP
++
++AT_SETUP([conntrack - zones from other field, more tests])
++CHECK_CONNTRACK()
++OVS_TRAFFIC_VSWITCHD_START()
++
++ADD_NAMESPACES(at_ns0, at_ns1)
++
++ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24")
++ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24")
++
++dnl Allow any traffic from ns0->ns1. Only allow nd, return traffic from ns1->ns0.
++AT_DATA([flows.txt], [dnl
++priority=1,action=drop
++priority=10,arp,action=normal
++priority=10,icmp,action=normal
++priority=100,in_port=1,tcp,ct_state=-trk,action=ct(zone=5,table=0,commit,exec(load:0xffff0005->NXM_NX_CT_LABEL[[0..31]]))
++priority=100,in_port=1,tcp,ct_state=+trk,action=ct(commit,zone=NXM_NX_CT_LABEL[[0..15]]),2
++priority=100,in_port=2,ct_state=-trk,tcp,action=ct(table=0,zone=5)
++priority=100,in_port=2,ct_state=+trk,ct_zone=5,tcp,action=1
++])
++
++AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt])
++
++OVS_START_L7([at_ns1], [http])
++
++dnl HTTP requests from p0->p1 should work fine.
++NS_CHECK_EXEC([at_ns0], [wget 10.1.1.2 -t 3 -T 1 --retry-connrefused -v -o wget0.log])
++
++AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1.2)], [0], [dnl
++tcp,dnl
++orig=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),dnl
++reply=(src=10.1.1.2,dst=10.1.1.1,sport=<cleared>,dport=<cleared>),dnl
++zone=5,labels=0xffff0005,protoinfo=(state=<cleared>)
++])
++
++AT_CHECK([ovs-appctl dpctl/dump-flows --names filter=in_port=ovs-p0 dnl
++              | grep "+trk" | sed 's/0xffff0005\/0xffff/0x5\/0xffff/' dnl
++              | grep -q "ct_label(0x5/0xffff)" ], [0], [])
++
++AT_CHECK([ovs-ofctl mod-flows br0 'priority=100,ct_state=-trk,tcp,in_port="ovs-p0" actions=ct(table=0,zone=15,commit,exec(load:0xffff000f->NXM_NX_CT_LABEL[[0..31]]))'])
++
++NS_CHECK_EXEC([at_ns0], [wget 10.1.1.2 -t 3 -T 1 --retry-connrefused -v -o wget0.log])
++
++AT_CHECK([ovs-appctl dpctl/dump-flows --names filter=in_port=ovs-p0 dnl
++              | grep "+trk" | sed 's/0xffff000f\/0xffff/0xf\/0xffff/' dnl
++              | grep -q "ct_label(0xf/0xffff)" ], [0], [])
++
++OVS_TRAFFIC_VSWITCHD_STOP
++AT_CLEANUP
++
+ AT_SETUP([conntrack - multiple bridges])
+ CHECK_CONNTRACK()
+ OVS_TRAFFIC_VSWITCHD_START(
+@@ -2331,6 +2500,35 @@ NXST_FLOW reply:
  OVS_TRAFFIC_VSWITCHD_STOP
  AT_CLEANUP
  
@@ -89865,7 +90057,7 @@ index 4a39c929c2..620cd2512f 100644
  AT_SETUP([conntrack - ICMP related])
  AT_SKIP_IF([test $HAVE_NC = no])
  CHECK_CONNTRACK()
-@@ -3220,6 +3313,46 @@ NS_CHECK_EXEC([at_ns0], [ping6 -s 3200 -q -c 3 -i 0.3 -w 2 fc00::2 | FORMAT_PING
+@@ -3220,6 +3418,46 @@ NS_CHECK_EXEC([at_ns0], [ping6 -s 3200 -q -c 3 -i 0.3 -w 2 fc00::2 | FORMAT_PING
  OVS_TRAFFIC_VSWITCHD_STOP
  AT_CLEANUP
  
@@ -89912,7 +90104,7 @@ index 4a39c929c2..620cd2512f 100644
  AT_SETUP([conntrack - resubmit to ct multiple times])
  CHECK_CONNTRACK()
  
-@@ -4379,6 +4512,52 @@ tcp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),reply=(src=
+@@ -4379,6 +4617,52 @@ tcp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),reply=(src=
  OVS_TRAFFIC_VSWITCHD_STOP
  AT_CLEANUP
  
@@ -89965,7 +90157,7 @@ index 4a39c929c2..620cd2512f 100644
  AT_SETUP([conntrack - simple DNAT])
  CHECK_CONNTRACK()
  CHECK_CONNTRACK_NAT()
-@@ -4434,6 +4613,41 @@ tcp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),reply=(src=
+@@ -4434,6 +4718,41 @@ tcp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),reply=(src=
  OVS_TRAFFIC_VSWITCHD_STOP
  AT_CLEANUP
  
@@ -90007,7 +90199,7 @@ index 4a39c929c2..620cd2512f 100644
  AT_SETUP([conntrack - more complex DNAT])
  CHECK_CONNTRACK()
  CHECK_CONNTRACK_NAT()
-@@ -5873,6 +6087,50 @@ ovs-appctl dpif/dump-flows br0
+@@ -5873,6 +6192,50 @@ ovs-appctl dpif/dump-flows br0
  OVS_TRAFFIC_VSWITCHD_STOP
  AT_CLEANUP
  
diff --git a/SPECS/openvswitch2.13.spec b/SPECS/openvswitch2.13.spec
index b1fad2f..3d2f647 100644
--- a/SPECS/openvswitch2.13.spec
+++ b/SPECS/openvswitch2.13.spec
@@ -59,7 +59,7 @@ Summary: Open vSwitch
 Group: System Environment/Daemons daemon/database/utilities
 URL: http://www.openvswitch.org/
 Version: 2.13.0
-Release: 130%{?commit0:.%{date}git%{shortcommit0}}%{?commit1:dpdk%{shortcommit1}}%{?dist}
+Release: 131%{?commit0:.%{date}git%{shortcommit0}}%{?commit1:dpdk%{shortcommit1}}%{?dist}
 
 # Nearly all of openvswitch is ASL 2.0.  The bugtool is LGPLv2+, and the
 # lib/sflow*.[ch] files are SISSL
@@ -712,6 +712,12 @@ exit 0
 %endif
 
 %changelog
+* Thu Oct 14 2021 Open vSwitch CI <ovs-ci@redhat.com> - 2.13.0-131
+- Merging upstream branch-2.13 [RH git: 31c65d3e94]
+    Commit list:
+    6e2e180851 ofproto-dpif-xlate: Fix zone set from non-frozen-metadata fields.
+
+
 * Wed Oct 13 2021 Open vSwitch CI <ovs-ci@redhat.com> - 2.13.0-130
 - Merging upstream branch-2.13 [RH git: beb8cdaec6]
     Commit list: