diff --git a/SOURCES/openvswitch-2.17.0.patch b/SOURCES/openvswitch-2.17.0.patch
index 8cd41b8..0dd25e2 100644
--- a/SOURCES/openvswitch-2.17.0.patch
+++ b/SOURCES/openvswitch-2.17.0.patch
@@ -61173,7 +61173,7 @@ index 114aff8ea3..0fc6d2ea60 100644
      enum xc_type type;
      union {
 diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
-index 578cbfe581..b91b5757fd 100644
+index 578cbfe581..c0d1cfa94b 100644
 --- a/ofproto/ofproto-dpif-xlate.c
 +++ b/ofproto/ofproto-dpif-xlate.c
 @@ -66,6 +66,7 @@
@@ -61337,7 +61337,7 @@ index 578cbfe581..b91b5757fd 100644
      free(xbundle->name);
      free(xbundle);
  }
-@@ -1515,7 +1598,7 @@ xlate_lookup_ofproto_(const struct dpif_backer *backer,
+@@ -1515,13 +1598,14 @@ xlate_lookup_ofproto_(const struct dpif_backer *backer,
          if (OVS_UNLIKELY(!recirc_id_node)) {
              if (errorp) {
                  *errorp = xasprintf("no recirculation data for recirc_id "
@@ -61346,7 +61346,43 @@ index 578cbfe581..b91b5757fd 100644
              }
              return NULL;
          }
-@@ -1556,8 +1639,8 @@ xlate_lookup_ofproto_(const struct dpif_backer *backer,
+ 
+         ofp_port_t in_port = recirc_id_node->state.metadata.in_port;
+-        if (in_port != OFPP_NONE && in_port != OFPP_CONTROLLER) {
++        if (in_port != OFPP_NONE && in_port != OFPP_CONTROLLER &&
++            !uuid_is_zero(&recirc_id_node->state.xport_uuid)) {
+             struct uuid xport_uuid = recirc_id_node->state.xport_uuid;
+             xport = xport_lookup_by_uuid(xcfg, &xport_uuid);
+             if (xport && xport->xbridge && xport->xbridge->ofproto) {
+@@ -1532,11 +1616,19 @@ xlate_lookup_ofproto_(const struct dpif_backer *backer,
+              * that the packet originated from the controller via an OpenFlow
+              * "packet-out".  The right thing to do is to find just the
+              * ofproto.  There is no xport, which is OK.
++             * Also a zeroed xport_uuid with a valid in_port, means that
++             * the packet originated from OFPP_CONTROLLER passed
++             * through a patch port.
+              *
+              * OFPP_NONE can also indicate that a bond caused recirculation. */
+             struct uuid uuid = recirc_id_node->state.ofproto_uuid;
+             const struct xbridge *bridge = xbridge_lookup_by_uuid(xcfg, &uuid);
++
+             if (bridge && bridge->ofproto) {
++                if (in_port != OFPP_CONTROLLER && in_port != OFPP_NONE &&
++                    !get_ofp_port(bridge, in_port)) {
++                    goto xport_lookup;
++                }
+                 if (errorp) {
+                     *errorp = NULL;
+                 }
+@@ -1549,6 +1641,7 @@ xlate_lookup_ofproto_(const struct dpif_backer *backer,
+         }
+     }
+ 
++xport_lookup:
+     xport = xport_lookup(xcfg, tnl_port_should_receive(flow)
+                          ? tnl_port_receive(flow)
+                          : odp_port_to_ofport(backer, flow->in_port.odp_port));
+@@ -1556,8 +1649,8 @@ xlate_lookup_ofproto_(const struct dpif_backer *backer,
          if (errorp) {
              *errorp = (tnl_port_should_receive(flow)
                         ? xstrdup("no OpenFlow tunnel port for this packet")
@@ -61357,7 +61393,7 @@ index 578cbfe581..b91b5757fd 100644
          }
          return NULL;
      }
-@@ -1639,7 +1722,7 @@ xbridge_lookup(struct xlate_cfg *xcfg, const struct ofproto_dpif *ofproto)
+@@ -1639,7 +1732,7 @@ xbridge_lookup(struct xlate_cfg *xcfg, const struct ofproto_dpif *ofproto)
  
      xbridges = &xcfg->xbridges;
  
@@ -61366,7 +61402,7 @@ index 578cbfe581..b91b5757fd 100644
                               xbridges) {
          if (xbridge->ofproto == ofproto) {
              return xbridge;
-@@ -1661,6 +1744,23 @@ xbridge_lookup_by_uuid(struct xlate_cfg *xcfg, const struct uuid *uuid)
+@@ -1661,6 +1754,23 @@ xbridge_lookup_by_uuid(struct xlate_cfg *xcfg, const struct uuid *uuid)
      return NULL;
  }
  
@@ -61390,7 +61426,7 @@ index 578cbfe581..b91b5757fd 100644
  static struct xbundle *
  xbundle_lookup(struct xlate_cfg *xcfg, const struct ofbundle *ofbundle)
  {
-@@ -1894,8 +1994,8 @@ group_is_alive(const struct xlate_ctx *ctx, uint32_t group_id, int depth)
+@@ -1894,8 +2004,8 @@ group_is_alive(const struct xlate_ctx *ctx, uint32_t group_id, int depth)
  #define MAX_LIVENESS_RECURSION 128 /* Arbitrary limit */
  
  static bool
@@ -61401,7 +61437,7 @@ index 578cbfe581..b91b5757fd 100644
  {
      if (depth >= MAX_LIVENESS_RECURSION) {
          xlate_report_error(ctx, "bucket chaining exceeded %d links",
-@@ -1903,6 +2003,12 @@ bucket_is_alive(const struct xlate_ctx *ctx,
+@@ -1903,6 +2013,12 @@ bucket_is_alive(const struct xlate_ctx *ctx,
          return false;
      }
  
@@ -61414,7 +61450,7 @@ index 578cbfe581..b91b5757fd 100644
      return (!ofputil_bucket_has_liveness(bucket)
              || (bucket->watch_port != OFPP_ANY
                 && bucket->watch_port != OFPP_CONTROLLER
-@@ -1943,7 +2049,7 @@ group_first_live_bucket(const struct xlate_ctx *ctx,
+@@ -1943,7 +2059,7 @@ group_first_live_bucket(const struct xlate_ctx *ctx,
  {
      struct ofputil_bucket *bucket;
      LIST_FOR_EACH (bucket, list_node, &group->up.buckets) {
@@ -61423,7 +61459,7 @@ index 578cbfe581..b91b5757fd 100644
              return bucket;
          }
          xlate_report_bucket_not_live(ctx, bucket);
-@@ -1962,7 +2068,7 @@ group_best_live_bucket(const struct xlate_ctx *ctx,
+@@ -1962,7 +2078,7 @@ group_best_live_bucket(const struct xlate_ctx *ctx,
  
      struct ofputil_bucket *bucket;
      LIST_FOR_EACH (bucket, list_node, &group->up.buckets) {
@@ -61432,7 +61468,7 @@ index 578cbfe581..b91b5757fd 100644
              uint32_t score =
                  (hash_int(bucket->bucket_id, basis) & 0xffff) * bucket->weight;
              if (score >= best_score) {
-@@ -2125,9 +2231,14 @@ mirror_packet(struct xlate_ctx *ctx, struct xbundle *xbundle,
+@@ -2125,9 +2241,14 @@ mirror_packet(struct xlate_ctx *ctx, struct xbundle *xbundle,
          int snaplen;
  
          /* Get the details of the mirror represented by the rightmost 1-bit. */
@@ -61450,7 +61486,7 @@ index 578cbfe581..b91b5757fd 100644
  
  
          /* If this mirror selects on the basis of VLAN, and it does not select
-@@ -2444,9 +2555,18 @@ output_normal(struct xlate_ctx *ctx, const struct xbundle *out_xbundle,
+@@ -2444,9 +2565,18 @@ output_normal(struct xlate_ctx *ctx, const struct xbundle *out_xbundle,
              /* In case recirculation is not actually in use, 'xr.recirc_id'
               * will be set to '0', since a valid 'recirc_id' can
               * not be zero.  */
@@ -61472,7 +61508,7 @@ index 578cbfe581..b91b5757fd 100644
              if (xr.recirc_id) {
                  /* Use recirculation instead of output. */
                  use_recirc = true;
-@@ -3015,7 +3135,7 @@ xlate_normal(struct xlate_ctx *ctx)
+@@ -3015,7 +3145,7 @@ xlate_normal(struct xlate_ctx *ctx)
      bool is_grat_arp = is_gratuitous_arp(flow, wc);
      if (ctx->xin->allow_side_effects
          && flow->packet_type == htonl(PT_ETH)
@@ -61481,7 +61517,7 @@ index 578cbfe581..b91b5757fd 100644
      ) {
          update_learning_table(ctx, in_xbundle, flow->dl_src, vlan,
                                is_grat_arp);
-@@ -3024,12 +3144,14 @@ xlate_normal(struct xlate_ctx *ctx)
+@@ -3024,12 +3154,14 @@ xlate_normal(struct xlate_ctx *ctx)
          struct xc_entry *entry;
  
          /* Save just enough info to update mac learning table later. */
@@ -61502,7 +61538,7 @@ index 578cbfe581..b91b5757fd 100644
      }
  
      /* Determine output bundle. */
-@@ -3048,7 +3170,6 @@ xlate_normal(struct xlate_ctx *ctx)
+@@ -3048,7 +3180,6 @@ xlate_normal(struct xlate_ctx *ctx)
               */
              ctx->xout->slow |= SLOW_ACTION;
  
@@ -61510,7 +61546,7 @@ index 578cbfe581..b91b5757fd 100644
              if (mcast_snooping_is_membership(flow->tp_src) ||
                  mcast_snooping_is_query(flow->tp_src)) {
                  if (ctx->xin->allow_side_effects && ctx->xin->packet) {
-@@ -3523,6 +3644,9 @@ propagate_tunnel_data_to_flow__(struct flow *dst_flow,
+@@ -3523,6 +3654,9 @@ propagate_tunnel_data_to_flow__(struct flow *dst_flow,
      dst_flow->dl_dst = dmac;
      dst_flow->dl_src = smac;
  
@@ -61520,7 +61556,7 @@ index 578cbfe581..b91b5757fd 100644
      dst_flow->packet_type = htonl(PT_ETH);
      dst_flow->nw_dst = src_flow->tunnel.ip_dst;
      dst_flow->nw_src = src_flow->tunnel.ip_src;
-@@ -3654,14 +3778,27 @@ native_tunnel_output(struct xlate_ctx *ctx, const struct xport *xport,
+@@ -3654,14 +3788,27 @@ native_tunnel_output(struct xlate_ctx *ctx, const struct xport *xport,
  
      err = tnl_neigh_lookup(out_dev->xbridge->name, &d_ip6, &dmac);
      if (err) {
@@ -61550,7 +61586,7 @@ index 578cbfe581..b91b5757fd 100644
          }
          return err;
      }
-@@ -3827,20 +3964,17 @@ static void
+@@ -3827,20 +3974,17 @@ static void
  patch_port_output(struct xlate_ctx *ctx, const struct xport *in_dev,
                    struct xport *out_dev, bool is_last_action)
  {
@@ -61578,7 +61614,7 @@ index 578cbfe581..b91b5757fd 100644
      flow->in_port.ofp_port = out_dev->ofp_port;
      flow->metadata = htonll(0);
      memset(&flow->tunnel, 0, sizeof flow->tunnel);
-@@ -3879,14 +4013,15 @@ patch_port_output(struct xlate_ctx *ctx, const struct xport *in_dev,
+@@ -3879,14 +4023,15 @@ patch_port_output(struct xlate_ctx *ctx, const struct xport *in_dev,
          } else {
              /* Forwarding is disabled by STP and RSTP.  Let OFPP_NORMAL and
               * the learning action look at the packet, then drop it. */
@@ -61596,7 +61632,7 @@ index 578cbfe581..b91b5757fd 100644
              ctx->odp_actions->size = old_size;
  
              /* Undo changes that may have been done for freezing. */
-@@ -3898,18 +4033,15 @@ patch_port_output(struct xlate_ctx *ctx, const struct xport *in_dev,
+@@ -3898,18 +4043,15 @@ patch_port_output(struct xlate_ctx *ctx, const struct xport *in_dev,
      if (independent_mirrors) {
          ctx->mirrors = old_mirrors;
      }
@@ -61619,7 +61655,7 @@ index 578cbfe581..b91b5757fd 100644
  
      /* The out bridge popping MPLS should have no effect on the original
       * bridge. */
-@@ -4099,6 +4231,16 @@ xport_has_ip(const struct xport *xport)
+@@ -4099,6 +4241,16 @@ xport_has_ip(const struct xport *xport)
      return n_in6 ? true : false;
  }
  
@@ -61636,7 +61672,7 @@ index 578cbfe581..b91b5757fd 100644
  static bool
  terminate_native_tunnel(struct xlate_ctx *ctx, const struct xport *xport,
                          struct flow *flow, struct flow_wildcards *wc,
-@@ -4119,9 +4261,7 @@ terminate_native_tunnel(struct xlate_ctx *ctx, const struct xport *xport,
+@@ -4119,9 +4271,7 @@ terminate_native_tunnel(struct xlate_ctx *ctx, const struct xport *xport,
          /* If no tunnel port was found and it's about an ARP or ICMPv6 packet,
           * do tunnel neighbor snooping. */
          if (*tnl_port == ODPP_NONE &&
@@ -61647,7 +61683,7 @@ index 578cbfe581..b91b5757fd 100644
              tnl_neigh_snoop(flow, wc, ctx->xbridge->name,
                              ctx->xin->allow_side_effects);
          } else if (*tnl_port != ODPP_NONE &&
-@@ -4151,7 +4291,7 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port,
+@@ -4151,7 +4301,7 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port,
      const struct xport *xport = get_ofp_port(ctx->xbridge, ofp_port);
      struct flow_wildcards *wc = ctx->wc;
      struct flow *flow = &ctx->xin->flow;
@@ -61656,7 +61692,7 @@ index 578cbfe581..b91b5757fd 100644
      union flow_vlan_hdr flow_vlans[FLOW_MAX_VLAN_HEADERS];
      uint8_t flow_nw_tos;
      odp_port_t out_port, odp_port, odp_tnl_port;
-@@ -4165,7 +4305,6 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port,
+@@ -4165,7 +4315,6 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port,
      /* If 'struct flow' gets additional metadata, we'll need to zero it out
       * before traversing a patch port. */
      BUILD_ASSERT_DECL(FLOW_WC_SEQ == 42);
@@ -61664,7 +61700,7 @@ index 578cbfe581..b91b5757fd 100644
  
      if (!check_output_prerequisites(ctx, xport, flow, check_stp)) {
          return;
-@@ -4176,6 +4315,10 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port,
+@@ -4176,6 +4325,10 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port,
          if (xport->pt_mode == NETDEV_PT_LEGACY_L3) {
              flow->packet_type = PACKET_TYPE_BE(OFPHTN_ETHERTYPE,
                                                 ntohs(flow->dl_type));
@@ -61675,7 +61711,7 @@ index 578cbfe581..b91b5757fd 100644
          }
      }
  
-@@ -4205,7 +4348,7 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port,
+@@ -4205,7 +4358,7 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port,
            * the Logical (tunnel) Port are not visible for any further
            * matches, while explicit set actions on tunnel metadata are.
            */
@@ -61684,7 +61720,7 @@ index 578cbfe581..b91b5757fd 100644
          odp_port = tnl_port_send(xport->ofport, flow, ctx->wc);
          if (odp_port == ODPP_NONE) {
              xlate_report(ctx, OFT_WARN, "Tunneling decided against output");
-@@ -4236,7 +4379,7 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port,
+@@ -4236,7 +4389,7 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port,
              tnl_type = tnl_port_get_type(xport->ofport);
              commit_odp_tunnel_action(flow, &ctx->base_flow,
                                       ctx->odp_actions, tnl_type);
@@ -61693,7 +61729,7 @@ index 578cbfe581..b91b5757fd 100644
          }
      } else {
          odp_port = xport->odp_port;
-@@ -4280,7 +4423,8 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port,
+@@ -4280,7 +4433,8 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port,
              /* Output to native tunnel port. */
              native_tunnel_output(ctx, xport, flow, odp_port, truncate,
                                   is_last_action);
@@ -61703,7 +61739,7 @@ index 578cbfe581..b91b5757fd 100644
  
          } else if (terminate_native_tunnel(ctx, xport, flow, wc,
                                             &odp_tnl_port)) {
-@@ -4323,7 +4467,7 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port,
+@@ -4323,7 +4477,7 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port,
                                           xport->xbundle));
      }
  
@@ -61712,7 +61748,7 @@ index 578cbfe581..b91b5757fd 100644
      /* Restore flow */
      memcpy(flow->vlans, flow_vlans, sizeof flow->vlans);
      flow->nw_tos = flow_nw_tos;
-@@ -4331,6 +4475,7 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port,
+@@ -4331,6 +4485,7 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port,
      flow->dl_src = flow_dl_src;
      flow->packet_type = flow_packet_type;
      flow->dl_type = flow_dl_type;
@@ -61720,7 +61756,7 @@ index 578cbfe581..b91b5757fd 100644
  }
  
  static void
-@@ -4678,7 +4823,7 @@ pick_dp_hash_select_group(struct xlate_ctx *ctx, struct group_dpif *group)
+@@ -4678,7 +4833,7 @@ pick_dp_hash_select_group(struct xlate_ctx *ctx, struct group_dpif *group)
          for (int i = 0; i <= hash_mask; i++) {
              struct ofputil_bucket *b =
                      group->hash_map[(dp_hash + i) & hash_mask];
@@ -61729,7 +61765,7 @@ index 578cbfe581..b91b5757fd 100644
                  return b;
              }
          }
-@@ -5120,6 +5265,7 @@ compose_dec_ttl(struct xlate_ctx *ctx, struct ofpact_cnt_ids *ids)
+@@ -5120,6 +5275,7 @@ compose_dec_ttl(struct xlate_ctx *ctx, struct ofpact_cnt_ids *ids)
      }
  
      ctx->wc->masks.nw_ttl = 0xff;
@@ -61737,15 +61773,15 @@ index 578cbfe581..b91b5757fd 100644
      if (flow->nw_ttl > 1) {
          flow->nw_ttl--;
          return false;
-@@ -5308,15 +5454,15 @@ xlate_output_reg_action(struct xlate_ctx *ctx,
+@@ -5308,15 +5464,15 @@ xlate_output_reg_action(struct xlate_ctx *ctx,
  {
      uint64_t port = mf_get_subfield(&or->src, &ctx->xin->flow);
      if (port <= UINT16_MAX) {
 -        xlate_report(ctx, OFT_DETAIL, "output port is %"PRIu64, port);
+-
+-        union mf_subvalue value;
 +        union mf_subvalue *value = xmalloc(sizeof *value);
  
--        union mf_subvalue value;
--
 -        memset(&value, 0xff, sizeof value);
 -        mf_write_subfield_flow(&or->src, &value, &ctx->wc->masks);
 +        xlate_report(ctx, OFT_DETAIL, "output port is %"PRIu64, port);
@@ -61758,7 +61794,7 @@ index 578cbfe581..b91b5757fd 100644
      } else {
          xlate_report(ctx, OFT_WARN, "output port %"PRIu64" is out of range",
                       port);
-@@ -5525,8 +5671,16 @@ xlate_learn_action(struct xlate_ctx *ctx, const struct ofpact_learn *learn)
+@@ -5525,8 +5681,16 @@ xlate_learn_action(struct xlate_ctx *ctx, const struct ofpact_learn *learn)
          if (!error) {
              bool success = true;
              if (ctx->xin->allow_side_effects) {
@@ -61776,7 +61812,7 @@ index 578cbfe581..b91b5757fd 100644
              } else if (learn->limit) {
                  if (!ofm->temp_rule
                      || ofm->temp_rule->state != RULE_INSERTED) {
-@@ -5622,7 +5776,8 @@ xlate_sample_action(struct xlate_ctx *ctx,
+@@ -5622,7 +5786,8 @@ xlate_sample_action(struct xlate_ctx *ctx,
  
      /* Scale the probability from 16-bit to 32-bit while representing
       * the same percentage. */
@@ -61786,7 +61822,7 @@ index 578cbfe581..b91b5757fd 100644
  
      /* If ofp_port in flow sample action is equel to ofp_port,
       * this sample action is a input port action. */
-@@ -5656,13 +5811,15 @@ xlate_sample_action(struct xlate_ctx *ctx,
+@@ -5656,13 +5821,15 @@ xlate_sample_action(struct xlate_ctx *ctx,
              struct flow *flow = &ctx->xin->flow;
              tnl_port_send(xport->ofport, flow, ctx->wc);
              if (!ovs_native_tunneling_is_on(ctx->xbridge->ofproto)) {
@@ -61804,7 +61840,7 @@ index 578cbfe581..b91b5757fd 100644
              }
          } else {
              xlate_report_error(ctx,
-@@ -5772,21 +5929,12 @@ clone_xlate_actions(const struct ofpact *actions, size_t actions_len,
+@@ -5772,21 +5939,12 @@ clone_xlate_actions(const struct ofpact *actions, size_t actions_len,
                      struct xlate_ctx *ctx, bool is_last_action,
                      bool group_bucket_action OVS_UNUSED)
  {
@@ -61829,7 +61865,7 @@ index 578cbfe581..b91b5757fd 100644
          do_xlate_actions(actions, actions_len, ctx, is_last_action, false);
          if (!ctx->freezing) {
              xlate_action_set(ctx);
-@@ -5801,7 +5949,8 @@ clone_xlate_actions(const struct ofpact *actions, size_t actions_len,
+@@ -5801,7 +5959,8 @@ clone_xlate_actions(const struct ofpact *actions, size_t actions_len,
       * avoid emitting those actions twice. Once inside
       * the clone, another time for the action after clone.  */
      xlate_commit_actions(ctx);
@@ -61839,7 +61875,7 @@ index 578cbfe581..b91b5757fd 100644
      bool old_was_mpls = ctx->was_mpls;
      bool old_conntracked = ctx->conntracked;
  
-@@ -5858,14 +6007,10 @@ dp_clone_done:
+@@ -5858,14 +6017,10 @@ dp_clone_done:
      ctx->was_mpls = old_was_mpls;
  
      /* Restore the 'base_flow' for the next action.  */
@@ -61856,7 +61892,7 @@ index 578cbfe581..b91b5757fd 100644
  }
  
  static void
-@@ -6241,8 +6386,8 @@ compose_conntrack_action(struct xlate_ctx *ctx, struct ofpact_conntrack *ofc,
+@@ -6241,8 +6396,8 @@ compose_conntrack_action(struct xlate_ctx *ctx, struct ofpact_conntrack *ofc,
  {
      uint16_t zone;
      if (ofc->zone_src.field) {
@@ -61867,7 +61903,7 @@ index 578cbfe581..b91b5757fd 100644
  
          zone = mf_get_subfield(&ofc->zone_src, &ctx->xin->flow);
          if (ctx->xin->frozen_state) {
-@@ -6252,12 +6397,13 @@ compose_conntrack_action(struct xlate_ctx *ctx, struct ofpact_conntrack *ofc,
+@@ -6252,12 +6407,13 @@ compose_conntrack_action(struct xlate_ctx *ctx, struct ofpact_conntrack *ofc,
               * which will invalidate the megaflow with old the recirc_id.
               */
              if (!mf_is_frozen_metadata(ofc->zone_src.field)) {
@@ -61883,7 +61919,7 @@ index 578cbfe581..b91b5757fd 100644
      } else {
          zone = ofc->zone_imm;
      }
-@@ -6347,16 +6493,16 @@ xlate_check_pkt_larger(struct xlate_ctx *ctx,
+@@ -6347,16 +6503,16 @@ xlate_check_pkt_larger(struct xlate_ctx *ctx,
                         const struct ofpact *remaining_acts,
                         size_t remaining_acts_len)
  {
@@ -61904,7 +61940,7 @@ index 578cbfe581..b91b5757fd 100644
                                 &ctx->xin->flow);
          /* If datapath doesn't support check_pkt_len action, then set the
           * SLOW_ACTION flag. If we don't set SLOW_ACTION, we
-@@ -6366,22 +6512,17 @@ xlate_check_pkt_larger(struct xlate_ctx *ctx,
+@@ -6366,22 +6522,17 @@ xlate_check_pkt_larger(struct xlate_ctx *ctx,
           * the packet length. This results in wrong actions being applied.
           */
          ctx->xout->slow |= SLOW_ACTION;
@@ -61932,7 +61968,7 @@ index 578cbfe581..b91b5757fd 100644
      bool old_was_mpls = ctx->was_mpls;
      bool old_conntracked = ctx->conntracked;
  
-@@ -6391,8 +6532,8 @@ xlate_check_pkt_larger(struct xlate_ctx *ctx,
+@@ -6391,8 +6542,8 @@ xlate_check_pkt_larger(struct xlate_ctx *ctx,
                     check_pkt_larger->pkt_len);
      size_t offset_attr = nl_msg_start_nested(
          ctx->odp_actions, OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_GREATER);
@@ -61943,7 +61979,7 @@ index 578cbfe581..b91b5757fd 100644
      do_xlate_actions(remaining_acts, remaining_acts_len, ctx, true, false);
      if (!ctx->freezing) {
          xlate_action_set(ctx);
-@@ -6402,10 +6543,10 @@ xlate_check_pkt_larger(struct xlate_ctx *ctx,
+@@ -6402,10 +6553,10 @@ xlate_check_pkt_larger(struct xlate_ctx *ctx,
      }
      nl_msg_end_nested(ctx->odp_actions, offset_attr);
  
@@ -61956,7 +61992,7 @@ index 578cbfe581..b91b5757fd 100644
  
      /* If the flow translation for the IF_GREATER case requires freezing,
       * then ctx->exit would be true. Reset to false so that we can
-@@ -6416,8 +6557,8 @@ xlate_check_pkt_larger(struct xlate_ctx *ctx,
+@@ -6416,8 +6567,8 @@ xlate_check_pkt_larger(struct xlate_ctx *ctx,
  
      offset_attr = nl_msg_start_nested(
          ctx->odp_actions, OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_LESS_EQUAL);
@@ -61967,7 +62003,7 @@ index 578cbfe581..b91b5757fd 100644
      do_xlate_actions(remaining_acts, remaining_acts_len, ctx, true, false);
      if (!ctx->freezing) {
          xlate_action_set(ctx);
-@@ -6428,15 +6569,12 @@ xlate_check_pkt_larger(struct xlate_ctx *ctx,
+@@ -6428,15 +6579,12 @@ xlate_check_pkt_larger(struct xlate_ctx *ctx,
      nl_msg_end_nested(ctx->odp_actions, offset_attr);
      nl_msg_end_nested(ctx->odp_actions, offset);
  
@@ -61986,7 +62022,7 @@ index 578cbfe581..b91b5757fd 100644
  }
  
  static void
-@@ -6887,6 +7025,107 @@ xlate_ofpact_unroll_xlate(struct xlate_ctx *ctx,
+@@ -6887,6 +7035,107 @@ xlate_ofpact_unroll_xlate(struct xlate_ctx *ctx,
                   "cookie=%#"PRIx64, a->rule_table_id, a->rule_cookie);
  }
  
@@ -62094,7 +62130,7 @@ index 578cbfe581..b91b5757fd 100644
  static void
  do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
                   struct xlate_ctx *ctx, bool is_last_action,
-@@ -6928,6 +7167,8 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
+@@ -6928,6 +7177,8 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
              break;
          }
  
@@ -62103,7 +62139,7 @@ index 578cbfe581..b91b5757fd 100644
          if (OVS_UNLIKELY(ctx->xin->trace)) {
              struct ds s = DS_EMPTY_INITIALIZER;
              struct ofpact_format_params fp = { .s = &s };
-@@ -7027,6 +7268,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
+@@ -7027,6 +7278,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
          case OFPACT_SET_IPV4_SRC:
              if (flow->dl_type == htons(ETH_TYPE_IP)) {
                  memset(&wc->masks.nw_src, 0xff, sizeof wc->masks.nw_src);
@@ -62111,7 +62147,7 @@ index 578cbfe581..b91b5757fd 100644
                  flow->nw_src = ofpact_get_SET_IPV4_SRC(a)->ipv4;
              }
              break;
-@@ -7034,12 +7276,14 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
+@@ -7034,12 +7286,14 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
          case OFPACT_SET_IPV4_DST:
              if (flow->dl_type == htons(ETH_TYPE_IP)) {
                  memset(&wc->masks.nw_dst, 0xff, sizeof wc->masks.nw_dst);
@@ -62126,7 +62162,7 @@ index 578cbfe581..b91b5757fd 100644
                  wc->masks.nw_tos |= IP_DSCP_MASK;
                  flow->nw_tos &= ~IP_DSCP_MASK;
                  flow->nw_tos |= ofpact_get_SET_IP_DSCP(a)->dscp;
-@@ -7048,6 +7292,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
+@@ -7048,6 +7302,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
  
          case OFPACT_SET_IP_ECN:
              if (is_ip_any(flow)) {
@@ -62134,7 +62170,7 @@ index 578cbfe581..b91b5757fd 100644
                  wc->masks.nw_tos |= IP_ECN_MASK;
                  flow->nw_tos &= ~IP_ECN_MASK;
                  flow->nw_tos |= ofpact_get_SET_IP_ECN(a)->ecn;
-@@ -7056,6 +7301,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
+@@ -7056,6 +7311,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
  
          case OFPACT_SET_IP_TTL:
              if (is_ip_any(flow)) {
@@ -62142,7 +62178,7 @@ index 578cbfe581..b91b5757fd 100644
                  wc->masks.nw_ttl = 0xff;
                  flow->nw_ttl = ofpact_get_SET_IP_TTL(a)->ttl;
              }
-@@ -7123,6 +7369,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
+@@ -7123,6 +7379,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
  
              /* Set the field only if the packet actually has it. */
              if (mf_are_prereqs_ok(mf, flow, wc)) {
@@ -62150,7 +62186,7 @@ index 578cbfe581..b91b5757fd 100644
                  mf_mask_field_masked(mf, ofpact_set_field_mask(set_field), wc);
                  mf_set_flow_value_masked(mf, set_field->value,
                                           ofpact_set_field_mask(set_field),
-@@ -7179,6 +7426,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
+@@ -7179,6 +7436,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
  
          case OFPACT_DEC_TTL:
              wc->masks.nw_ttl = 0xff;
@@ -62158,7 +62194,7 @@ index 578cbfe581..b91b5757fd 100644
              if (compose_dec_ttl(ctx, ofpact_get_DEC_TTL(a))) {
                  return;
              }
-@@ -7609,6 +7857,43 @@ xlate_wc_finish(struct xlate_ctx *ctx)
+@@ -7609,6 +7867,43 @@ xlate_wc_finish(struct xlate_ctx *ctx)
              ctx->wc->masks.vlans[i].tci = 0;
          }
      }
@@ -62202,7 +62238,7 @@ index 578cbfe581..b91b5757fd 100644
  }
  
  /* Translates the flow, actions, or rule in 'xin' into datapath actions in
-@@ -7784,6 +8069,12 @@ xlate_actions(struct xlate_in *xin, struct xlate_out *xout)
+@@ -7784,6 +8079,12 @@ xlate_actions(struct xlate_in *xin, struct xlate_out *xout)
          goto exit;
      }
  
@@ -62215,7 +62251,7 @@ index 578cbfe581..b91b5757fd 100644
      /* Tunnel metadata in udpif format must be normalized before translation. */
      if (flow->tunnel.flags & FLOW_TNL_F_UDPIF) {
          const struct tun_table *tun_tab = ofproto_get_tun_tab(
-@@ -8030,6 +8321,10 @@ exit:
+@@ -8030,6 +8331,10 @@ exit:
          if (xin->odp_actions) {
              ofpbuf_clear(xin->odp_actions);
          }
@@ -67241,7 +67277,7 @@ index 2c7e163bd6..7be6628c34 100644
  AT_CLEANUP
  
 diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
-index 7c2edeb9d4..fc125eac32 100644
+index 7c2edeb9d4..16c8af67ed 100644
 --- a/tests/ofproto-dpif.at
 +++ b/tests/ofproto-dpif.at
 @@ -29,6 +29,58 @@ AT_CHECK([ovs-appctl revalidator/wait])
@@ -68546,7 +68582,7 @@ index 7c2edeb9d4..fc125eac32 100644
  ])
  
  OVS_VSWITCHD_STOP
-@@ -5573,7 +5691,36 @@ check_flows () {
+@@ -5573,7 +5691,70 @@ check_flows () {
      echo "n_packets=$n"
      test "$n" = 1
  }
@@ -68581,10 +68617,44 @@ index 7c2edeb9d4..fc125eac32 100644
 +    test "$n" = 2
 +}
 +OVS_WAIT_UNTIL([check_flows], [ovs-ofctl dump-flows br0])
++
++OVS_VSWITCHD_STOP
++AT_CLEANUP
++
++dnl Checks for regression against a bug in which OVS dropped packets
++dnl originating from a controller passing through a patch port.
++AT_SETUP([ofproto-dpif - packet-out recirculation OFPP_CONTROLLER and patch port])
++OVS_VSWITCHD_START(
++    [add-port br0 patch-br1 -- \
++     set interface patch-br1 type=patch options:peer=patch-br0 -- \
++     add-br br1 -- set bridge br1 datapath-type=dummy fail-mode=secure -- \
++     add-port br1 patch-br0 -- set interface patch-br0 type=patch options:peer=patch-br1
++])
++
++add_of_ports --pcap br1 1
++
++AT_DATA([flows-br0.txt], [dnl
++table=0 icmp actions=output:patch-br1
++])
++AT_CHECK([ovs-ofctl add-flows br0 flows-br0.txt])
++
++AT_DATA([flows-br1.txt], [dnl
++table=0, icmp actions=ct(table=1,zone=1)
++table=1, ct_state=+trk, icmp actions=p1
++])
++AT_CHECK([ovs-ofctl add-flows br1 flows-br1.txt])
++
++packet=50540000000750540000000508004500005c000000008001b94dc0a80001c0a80002080013fc00000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f
++AT_CHECK([ovs-ofctl packet-out br0 "in_port=CONTROLLER packet=$packet actions=table"])
++
++OVS_WAIT_UNTIL_EQUAL([ovs-ofctl dump-flows -m br1 | grep "ct_state" | ofctl_strip], [dnl
++ table=1, n_packets=1, n_bytes=106, ct_state=+trk,icmp actions=output:2])
++
++OVS_WAIT_UNTIL([ovs-pcap p1-tx.pcap | grep -q "$packet"])
  
  OVS_VSWITCHD_STOP
  AT_CLEANUP
-@@ -6202,6 +6349,20 @@ AT_CHECK([tail -2 stderr], [0], [dnl
+@@ -6202,6 +6383,20 @@ AT_CHECK([tail -2 stderr], [0], [dnl
  ovs-appctl: ovs-vswitchd: server returned an error
  ])
  
@@ -68605,7 +68675,7 @@ index 7c2edeb9d4..fc125eac32 100644
  OVS_VSWITCHD_STOP
  AT_CLEANUP
  
-@@ -7004,6 +7165,29 @@ AT_CHECK([ovs-appctl coverage/read-counter mac_learning_static_none_move], [0],
+@@ -7004,6 +7199,29 @@ AT_CHECK([ovs-appctl coverage/read-counter mac_learning_static_none_move], [0],
  OVS_VSWITCHD_STOP
  AT_CLEANUP
  
@@ -68635,7 +68705,7 @@ index 7c2edeb9d4..fc125eac32 100644
  AT_SETUP([ofproto-dpif - basic truncate action])
  OVS_VSWITCHD_START
  add_of_ports br0 1 2 3 4 5
-@@ -7031,7 +7215,7 @@ dnl An 170 byte packet
+@@ -7031,7 +7249,7 @@ dnl An 170 byte packet
  AT_CHECK([ovs-appctl netdev-dummy/receive p1 '000c29c8a0a4005056c0000808004500009cb4a6000040019003c0a8da01c0a8da640800cb5fa762000556f431ad0009388e08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f'])
  
  AT_CHECK([ovs-ofctl parse-pcap p1.pcap], [0], [dnl
@@ -68644,7 +68714,7 @@ index 7c2edeb9d4..fc125eac32 100644
  ])
  
  AT_CHECK([ovs-appctl revalidator/purge], [0])
-@@ -7600,13 +7784,28 @@ dnl configure bridge IPFIX and ensure that sample action generation works at the
+@@ -7600,13 +7818,28 @@ dnl configure bridge IPFIX and ensure that sample action generation works at the
  dnl datapath level.
  AT_SETUP([ofproto-dpif - Bridge IPFIX sanity check])
  OVS_VSWITCHD_START
@@ -68674,7 +68744,7 @@ index 7c2edeb9d4..fc125eac32 100644
  dnl Send some packets that should be sampled.
  for i in `seq 1 3`; do
      AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800)'])
-@@ -8666,7 +8865,7 @@ recirc_id(0),in_port(100),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(src=192.1
+@@ -8666,7 +8899,7 @@ recirc_id(0),in_port(100),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(src=192.1
  ])
  
  AT_CHECK([grep -e '|ofproto_dpif_xlate|WARN|' ovs-vswitchd.log | sed "s/^.*|WARN|//"], [0], [dnl
@@ -68683,7 +68753,7 @@ index 7c2edeb9d4..fc125eac32 100644
  ])
  
  OVS_VSWITCHD_STOP(["/stack underflow/d"])
-@@ -8717,6 +8916,40 @@ AT_CHECK([tail -1 stdout], [0],
+@@ -8717,6 +8950,40 @@ AT_CHECK([tail -1 stdout], [0],
  OVS_VSWITCHD_STOP
  AT_CLEANUP
  
@@ -68724,7 +68794,7 @@ index 7c2edeb9d4..fc125eac32 100644
  dnl ----------------------------------------------------------------------
  AT_BANNER([ofproto-dpif -- megaflows])
  
-@@ -9855,7 +10088,7 @@ OVS_APP_EXIT_AND_WAIT([ovs-ofctl])
+@@ -9855,7 +10122,7 @@ OVS_APP_EXIT_AND_WAIT([ovs-ofctl])
  
  AT_CHECK([cat ofctl_monitor.log], [0], [dnl
  NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=86 in_port=1 (via no_match) data_len=86 (unbuffered)
@@ -68733,7 +68803,7 @@ index 7c2edeb9d4..fc125eac32 100644
  ])
  
  OVS_VSWITCHD_STOP
-@@ -9906,7 +10139,7 @@ OVS_APP_EXIT_AND_WAIT([ovs-ofctl])
+@@ -9906,7 +10173,7 @@ OVS_APP_EXIT_AND_WAIT([ovs-ofctl])
  
  AT_CHECK([cat ofctl_monitor.log], [0], [dnl
  NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=86 in_port=1 (via action) data_len=86 (unbuffered)
@@ -68742,7 +68812,7 @@ index 7c2edeb9d4..fc125eac32 100644
  ])
  
  OVS_VSWITCHD_STOP
-@@ -10166,10 +10399,10 @@ OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
+@@ -10166,10 +10433,10 @@ OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
  dnl Check this output. We only see the latter two packets, not the first.
  AT_CHECK([cat ofctl_monitor.log], [0], [dnl
  NXT_PACKET_IN (xid=0x0): table_id=6 cookie=0x0 total_len=106 reg0=0x1,reg1=0x4d2,reg2=0x1,reg3=0x1,reg4=0x1,in_port=1 (via action) data_len=106 (unbuffered)
@@ -68755,7 +68825,7 @@ index 7c2edeb9d4..fc125eac32 100644
  ])
  
  AT_CHECK([ovs-ofctl monitor br0 65534 invalid_ttl -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])
-@@ -10187,10 +10420,10 @@ OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
+@@ -10187,10 +10454,10 @@ OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
  dnl Check this output. We should see both packets
  AT_CHECK([cat ofctl_monitor.log], [0], [dnl
  NXT_PACKET_IN (xid=0x0): table_id=6 cookie=0x0 total_len=106 reg0=0x1,reg1=0x4d2,reg2=0x1,reg3=0x1,reg4=0x1,in_port=1 (via action) data_len=106 (unbuffered)
@@ -68768,7 +68838,7 @@ index 7c2edeb9d4..fc125eac32 100644
  ])
  
  OVS_VSWITCHD_STOP
-@@ -10239,10 +10472,10 @@ dnl Note that the first packet doesn't have the ct_state bits set. This
+@@ -10239,10 +10506,10 @@ dnl Note that the first packet doesn't have the ct_state bits set. This
  dnl happens because the ct_state field is available only after recirc.
  AT_CHECK([cat ofctl_monitor.log], [0], [dnl
  NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=106 in_port=1 (via action) data_len=106 (unbuffered)
@@ -68781,7 +68851,7 @@ index 7c2edeb9d4..fc125eac32 100644
  ])
  
  AT_CHECK([ovs-ofctl monitor br0 65534 invalid_ttl -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])
-@@ -10261,10 +10494,10 @@ dnl Note that the first packet doesn't have the ct_state bits set. This
+@@ -10261,10 +10528,10 @@ dnl Note that the first packet doesn't have the ct_state bits set. This
  dnl happens because the ct_state field is available only after recirc.
  AT_CHECK([cat ofctl_monitor.log], [0], [dnl
  NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=106 in_port=1 (via action) data_len=106 (unbuffered)
@@ -68794,7 +68864,7 @@ index 7c2edeb9d4..fc125eac32 100644
  ])
  
  dnl
-@@ -10320,9 +10553,9 @@ dnl Note that the first packet doesn't have the ct_state bits set. This
+@@ -10320,9 +10587,9 @@ dnl Note that the first packet doesn't have the ct_state bits set. This
  dnl happens because the ct_state field is available only after recirc.
  AT_CHECK([cat ofctl_monitor.log], [0], [dnl
  NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=126 in_port=1 (via action) data_len=126 (unbuffered)
@@ -68806,7 +68876,7 @@ index 7c2edeb9d4..fc125eac32 100644
  ])
  
  OVS_VSWITCHD_STOP
-@@ -10433,7 +10666,7 @@ OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
+@@ -10433,7 +10700,7 @@ OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
  dnl Check this output. Only one reply must be there
  AT_CHECK([cat ofctl_monitor.log], [0], [dnl
  NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x0 total_len=106 ct_state=est|rpl|trk,ct_nw_src=10.1.1.1,ct_nw_dst=10.1.1.2,ct_nw_proto=17,ct_tp_src=1,ct_tp_dst=2,ip,in_port=2 (via action) data_len=106 (unbuffered)
@@ -68815,7 +68885,7 @@ index 7c2edeb9d4..fc125eac32 100644
  dnl
  OFPT_ECHO_REQUEST (xid=0x0): 0 bytes of payload
  ])
-@@ -10467,7 +10700,7 @@ OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
+@@ -10467,7 +10734,7 @@ OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
  
  AT_CHECK([cat ofctl_monitor.log], [0], [dnl
  NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=86 ct_state=inv|trk,ipv6,in_port=2 (via action) data_len=86 (unbuffered)
@@ -68824,7 +68894,7 @@ index 7c2edeb9d4..fc125eac32 100644
  ])
  
  OVS_VSWITCHD_STOP
-@@ -10523,16 +10756,16 @@ OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
+@@ -10523,16 +10790,16 @@ OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
  dnl Check this output. We only see the latter two packets (for each zone), not the first.
  AT_CHECK([cat ofctl_monitor.log], [0], [dnl
  NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=106 in_port=1 (via action) data_len=106 (unbuffered)
@@ -68845,7 +68915,7 @@ index 7c2edeb9d4..fc125eac32 100644
  ])
  
  OVS_VSWITCHD_STOP
-@@ -10579,10 +10812,10 @@ OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
+@@ -10579,10 +10846,10 @@ OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
  dnl Check this output. We only see the latter two packets, not the first.
  AT_CHECK([cat ofctl_monitor.log], [0], [dnl
  NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x0 total_len=106 in_port=1 (via action) data_len=106 (unbuffered)
@@ -68858,7 +68928,7 @@ index 7c2edeb9d4..fc125eac32 100644
  ])
  
  OVS_VSWITCHD_STOP
-@@ -10629,10 +10862,10 @@ OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
+@@ -10629,10 +10896,10 @@ OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
  dnl Check this output. We only see the first and the last packet
  AT_CHECK([cat ofctl_monitor.log], [0], [dnl
  NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x0 total_len=47 ct_state=new|trk,ct_nw_src=172.16.0.1,ct_nw_dst=172.16.0.2,ct_nw_proto=17,ct_tp_src=41614,ct_tp_dst=5555,ip,in_port=1 (via action) data_len=47 (unbuffered)
@@ -68871,7 +68941,7 @@ index 7c2edeb9d4..fc125eac32 100644
  ])
  
  OVS_VSWITCHD_STOP
-@@ -10681,19 +10914,19 @@ OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
+@@ -10681,19 +10948,19 @@ OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
  dnl Check this output.
  AT_CHECK([cat ofctl_monitor.log], [0], [dnl
  NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=106 in_port=1 (via action) data_len=106 (unbuffered)
@@ -68896,7 +68966,7 @@ index 7c2edeb9d4..fc125eac32 100644
  ])
  
  OVS_VSWITCHD_STOP
-@@ -10738,10 +10971,10 @@ OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
+@@ -10738,10 +11005,10 @@ OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
  dnl Check this output.
  AT_CHECK([cat ofctl_monitor.log], [0], [dnl
  NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x0 total_len=106 ct_state=est|rpl|trk,ct_label=0x1,ct_nw_src=10.1.1.1,ct_nw_dst=10.1.1.2,ct_nw_proto=17,ct_tp_src=1,ct_tp_dst=2,ip,in_port=2 (via action) data_len=106 (unbuffered)
@@ -68909,7 +68979,7 @@ index 7c2edeb9d4..fc125eac32 100644
  ])
  
  OVS_VSWITCHD_STOP
-@@ -11152,16 +11385,16 @@ dnl Note that the first packet doesn't have the ct_state bits set. This
+@@ -11152,16 +11419,16 @@ dnl Note that the first packet doesn't have the ct_state bits set. This
  dnl happens because the ct_state field is available only after recirc.
  AT_CHECK([cat ofctl_monitor.log], [0], [dnl
  NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=106 in_port=1 (via action) data_len=106 (unbuffered)
@@ -68930,7 +69000,7 @@ index 7c2edeb9d4..fc125eac32 100644
  ])
  
  dnl The next test verifies that ct_clear at the datapath only gets executed
-@@ -11235,13 +11468,13 @@ OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
+@@ -11235,13 +11502,13 @@ OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
  dnl Check this output.
  AT_CHECK([cat ofctl_monitor.log], [0], [dnl
  NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x0 total_len=106 ct_state=est|rpl|trk,ct_nw_src=10.1.2.100,ct_nw_dst=10.1.2.200,ct_nw_proto=17,ct_tp_src=6,ct_tp_dst=6,ip,in_port=2 (via action) data_len=106 (unbuffered)
@@ -68947,7 +69017,7 @@ index 7c2edeb9d4..fc125eac32 100644
  ])
  
  OVS_VSWITCHD_STOP
-@@ -11504,7 +11737,7 @@ ovs-ofctl dump-flows br0
+@@ -11504,7 +11771,7 @@ ovs-ofctl dump-flows br0
  
  AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.10.10.2,dst=10.10.10.1,proto=1,tos=1,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout])
  AT_CHECK([tail -3 stdout], [0], [dnl
diff --git a/SPECS/openvswitch2.17.spec b/SPECS/openvswitch2.17.spec
index d37d2a7..ea0211d 100644
--- a/SPECS/openvswitch2.17.spec
+++ b/SPECS/openvswitch2.17.spec
@@ -57,7 +57,7 @@ Summary: Open vSwitch
 Group: System Environment/Daemons daemon/database/utilities
 URL: http://www.openvswitch.org/
 Version: 2.17.0
-Release: 107%{?dist}
+Release: 108%{?dist}
 
 # Nearly all of openvswitch is ASL 2.0.  The bugtool is LGPLv2+, and the
 # lib/sflow*.[ch] files are SISSL
@@ -751,6 +751,12 @@ exit 0
 %endif
 
 %changelog
+* Thu Sep 07 2023 Open vSwitch CI <ovs-ci@redhat.com> - 2.17.0-108
+- Merging upstream branch-2.17 [RH git: 2636d56cb6]
+    Commit list:
+    a6207b2bce ofproto-dpif-xlate: Fix recirculation with patch port and controller. (#2170920)
+
+
 * Wed Sep 06 2023 Open vSwitch CI <ovs-ci@redhat.com> - 2.17.0-107
 - Merging upstream branch-2.17 [RH git: 9ed4710854]
     Commit list: