diff --git a/SOURCES/openvswitch-2.17.0.patch b/SOURCES/openvswitch-2.17.0.patch
index b95502d..75d0471 100644
--- a/SOURCES/openvswitch-2.17.0.patch
+++ b/SOURCES/openvswitch-2.17.0.patch
@@ -52198,7 +52198,7 @@ index 66016eb099..7425dd44e7 100644
      /* Statistics. */
      struct dp_netdev_flow_stats stats;
 diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
-index 9f35713ef5..0b543cf222 100644
+index 9f35713ef5..5b0047f5c7 100644
 --- a/lib/dpif-netdev.c
 +++ b/lib/dpif-netdev.c
 @@ -93,7 +93,8 @@ VLOG_DEFINE_THIS_MODULE(dpif_netdev);
@@ -52299,7 +52299,60 @@ index 9f35713ef5..0b543cf222 100644
      log_netdev_flow_change(flow, match, NULL, actions, actions_len);
  
      return flow;
-@@ -4171,7 +4194,7 @@ flow_put_on_pmd(struct dp_netdev_pmd_thread *pmd,
+@@ -4143,7 +4166,7 @@ flow_put_on_pmd(struct dp_netdev_pmd_thread *pmd,
+                 const struct dpif_flow_put *put,
+                 struct dpif_flow_stats *stats)
+ {
+-    struct dp_netdev_flow *netdev_flow;
++    struct dp_netdev_flow *netdev_flow = NULL;
+     int error = 0;
+ 
+     if (stats) {
+@@ -4151,16 +4174,35 @@ flow_put_on_pmd(struct dp_netdev_pmd_thread *pmd,
+     }
+ 
+     ovs_mutex_lock(&pmd->flow_mutex);
+-    netdev_flow = dp_netdev_pmd_lookup_flow(pmd, key, NULL);
+-    if (!netdev_flow) {
+-        if (put->flags & DPIF_FP_CREATE) {
+-            dp_netdev_flow_add(pmd, match, ufid, put->actions,
+-                               put->actions_len, ODPP_NONE);
++    if (put->ufid) {
++        netdev_flow = dp_netdev_pmd_find_flow(pmd, put->ufid,
++                                              put->key, put->key_len);
++    } else {
++        /* Use key instead of the locally generated ufid
++         * to search netdev_flow. */
++        netdev_flow = dp_netdev_pmd_lookup_flow(pmd, key, NULL);
++    }
++
++    if (put->flags & DPIF_FP_CREATE) {
++        if (!netdev_flow) {
++            dp_netdev_flow_add(pmd, match, ufid,
++                               put->actions, put->actions_len, ODPP_NONE);
+         } else {
+-            error = ENOENT;
++            error = EEXIST;
+         }
+-    } else {
+-        if (put->flags & DPIF_FP_MODIFY) {
++        goto exit;
++    }
++
++    if (put->flags & DPIF_FP_MODIFY) {
++        if (!netdev_flow) {
++            error = ENOENT;
++        } else {
++            if (!put->ufid && !flow_equal(&match->flow, &netdev_flow->flow)) {
++                /* Overlapping flow. */
++                error = EINVAL;
++                goto exit;
++            }
++
+             struct dp_netdev_actions *new_actions;
+             struct dp_netdev_actions *old_actions;
+ 
+@@ -4171,7 +4213,7 @@ flow_put_on_pmd(struct dp_netdev_pmd_thread *pmd,
              ovsrcu_set(&netdev_flow->actions, new_actions);
  
              queue_netdev_flow_put(pmd, netdev_flow, match,
@@ -52308,7 +52361,25 @@ index 9f35713ef5..0b543cf222 100644
                                    DP_NETDEV_FLOW_OFFLOAD_OP_MOD);
              log_netdev_flow_change(netdev_flow, match, old_actions,
                                     put->actions, put->actions_len);
-@@ -4208,7 +4231,7 @@ static int
+@@ -4191,15 +4233,11 @@ flow_put_on_pmd(struct dp_netdev_pmd_thread *pmd,
+                  *   counter, and subtracting it before outputting the stats */
+                 error = EOPNOTSUPP;
+             }
+-
+             ovsrcu_postpone(dp_netdev_actions_free, old_actions);
+-        } else if (put->flags & DPIF_FP_CREATE) {
+-            error = EEXIST;
+-        } else {
+-            /* Overlapping flow. */
+-            error = EINVAL;
+         }
+     }
++
++exit:
+     ovs_mutex_unlock(&pmd->flow_mutex);
+     return error;
+ }
+@@ -4208,7 +4246,7 @@ static int
  dpif_netdev_flow_put(struct dpif *dpif, const struct dpif_flow_put *put)
  {
      struct dp_netdev *dp = get_dp_netdev(dpif);
@@ -52317,7 +52388,7 @@ index 9f35713ef5..0b543cf222 100644
      struct dp_netdev_pmd_thread *pmd;
      struct match match;
      ovs_u128 ufid;
-@@ -4257,9 +4280,12 @@ dpif_netdev_flow_put(struct dpif *dpif, const struct dpif_flow_put *put)
+@@ -4257,9 +4295,12 @@ dpif_netdev_flow_put(struct dpif *dpif, const struct dpif_flow_put *put)
  
      /* Must produce a netdev_flow_key for lookup.
       * Use the same method as employed to create the key when adding
@@ -52333,7 +52404,7 @@ index 9f35713ef5..0b543cf222 100644
  
      if (put->pmd_id == PMD_ID_NULL) {
          if (cmap_count(&dp->poll_threads) == 0) {
-@@ -4778,8 +4804,8 @@ dpif_netdev_set_config(struct dpif *dpif, const struct smap *other_config)
+@@ -4778,8 +4819,8 @@ dpif_netdev_set_config(struct dpif *dpif, const struct smap *other_config)
      uint32_t insert_min, cur_min;
      uint32_t tx_flush_interval, cur_tx_flush_interval;
      uint64_t rebalance_intvl;
@@ -52344,7 +52415,7 @@ index 9f35713ef5..0b543cf222 100644
      bool log_autolb = false;
      enum sched_assignment_type pmd_rxq_assign_type;
  
-@@ -4880,8 +4906,12 @@ dpif_netdev_set_config(struct dpif *dpif, const struct smap *other_config)
+@@ -4880,8 +4921,12 @@ dpif_netdev_set_config(struct dpif *dpif, const struct smap *other_config)
  
      struct pmd_auto_lb *pmd_alb = &dp->pmd_alb;
  
@@ -52359,7 +52430,7 @@ index 9f35713ef5..0b543cf222 100644
  
      /* Input is in min, convert it to msec. */
      rebalance_intvl =
-@@ -4894,21 +4924,21 @@ dpif_netdev_set_config(struct dpif *dpif, const struct smap *other_config)
+@@ -4894,21 +4939,21 @@ dpif_netdev_set_config(struct dpif *dpif, const struct smap *other_config)
          log_autolb = true;
      }
  
@@ -52387,7 +52458,7 @@ index 9f35713ef5..0b543cf222 100644
      if (rebalance_load > 100) {
          rebalance_load = ALB_LOAD_THRESHOLD;
      }
-@@ -4916,7 +4946,7 @@ dpif_netdev_set_config(struct dpif *dpif, const struct smap *other_config)
+@@ -4916,7 +4961,7 @@ dpif_netdev_set_config(struct dpif *dpif, const struct smap *other_config)
      if (rebalance_load != cur_rebalance_load) {
          atomic_store_relaxed(&pmd_alb->rebalance_load_thresh,
                               rebalance_load);
@@ -52396,7 +52467,7 @@ index 9f35713ef5..0b543cf222 100644
                    rebalance_load);
          log_autolb = true;
      }
-@@ -5425,7 +5455,6 @@ port_reconfigure(struct dp_netdev_port *port)
+@@ -5425,7 +5470,6 @@ port_reconfigure(struct dp_netdev_port *port)
  
          port->rxqs[i].port = port;
          port->rxqs[i].is_vhost = !strncmp(port->type, "dpdkvhost", 9);
@@ -52404,7 +52475,7 @@ index 9f35713ef5..0b543cf222 100644
  
          err = netdev_rxq_open(netdev, &port->rxqs[i].rx, i);
          if (err) {
-@@ -5684,23 +5713,28 @@ sched_numa_list_put_in_place(struct sched_numa_list *numa_list)
+@@ -5684,23 +5728,28 @@ sched_numa_list_put_in_place(struct sched_numa_list *numa_list)
      }
  }
  
@@ -52438,7 +52509,7 @@ index 9f35713ef5..0b543cf222 100644
                      rxq->pmd->numa_id !=
                          netdev_get_numa_id(rxq->port->netdev)) {
                      return true;
-@@ -6000,10 +6034,10 @@ sched_numa_list_schedule(struct sched_numa_list *numa_list,
+@@ -6000,10 +6049,10 @@ sched_numa_list_schedule(struct sched_numa_list *numa_list,
              /* Find any numa with available PMDs. */
              for (int j = 0; j < n_numa; j++) {
                  numa = sched_numa_list_next(numa_list, last_cross_numa);
@@ -52450,7 +52521,7 @@ index 9f35713ef5..0b543cf222 100644
                  numa = NULL;
              }
          }
-@@ -6111,7 +6145,7 @@ sched_numa_list_variance(struct sched_numa_list *numa_list)
+@@ -6111,7 +6160,7 @@ sched_numa_list_variance(struct sched_numa_list *numa_list)
   * pmd_rebalance_dry_run() can be avoided when it is not needed.
   */
  static bool
@@ -52459,7 +52530,7 @@ index 9f35713ef5..0b543cf222 100644
      OVS_REQ_RDLOCK(dp->port_rwlock)
  {
      struct dp_netdev_pmd_thread *pmd;
-@@ -6342,11 +6376,11 @@ pmd_remove_stale_ports(struct dp_netdev *dp,
+@@ -6342,11 +6391,11 @@ pmd_remove_stale_ports(struct dp_netdev *dp,
      OVS_EXCLUDED(pmd->port_mutex)
      OVS_REQ_RDLOCK(dp->port_rwlock)
  {
@@ -52474,7 +52545,7 @@ index 9f35713ef5..0b543cf222 100644
          struct dp_netdev_port *port = poll->rxq->port;
  
          if (port->need_reconfigure
-@@ -6354,7 +6388,7 @@ pmd_remove_stale_ports(struct dp_netdev *dp,
+@@ -6354,7 +6403,7 @@ pmd_remove_stale_ports(struct dp_netdev *dp,
              dp_netdev_del_rxq_from_pmd(pmd, poll);
          }
      }
@@ -52483,7 +52554,7 @@ index 9f35713ef5..0b543cf222 100644
          struct dp_netdev_port *port = tx->port;
  
          if (port->need_reconfigure
-@@ -6430,8 +6464,7 @@ reconfigure_datapath(struct dp_netdev *dp)
+@@ -6430,8 +6479,7 @@ reconfigure_datapath(struct dp_netdev *dp)
      /* We only reconfigure the ports that we determined above, because they're
       * not being used by any pmd thread at the moment.  If a port fails to
       * reconfigure we remove it from the datapath. */
@@ -52493,7 +52564,7 @@ index 9f35713ef5..0b543cf222 100644
          int err;
  
          if (!port->need_reconfigure) {
-@@ -6487,10 +6520,10 @@ reconfigure_datapath(struct dp_netdev *dp)
+@@ -6487,10 +6535,10 @@ reconfigure_datapath(struct dp_netdev *dp)
      }
  
      CMAP_FOR_EACH (pmd, node, &dp->poll_threads) {
@@ -52506,7 +52577,7 @@ index 9f35713ef5..0b543cf222 100644
              if (poll->rxq->pmd != pmd) {
                  dp_netdev_del_rxq_from_pmd(pmd, poll);
  
-@@ -6682,7 +6715,7 @@ dpif_netdev_run(struct dpif *dpif)
+@@ -6682,7 +6730,7 @@ dpif_netdev_run(struct dpif *dpif)
              if (pmd_rebalance &&
                  !dp_netdev_is_reconf_required(dp) &&
                  !ports_require_restart(dp) &&
@@ -52515,7 +52586,7 @@ index 9f35713ef5..0b543cf222 100644
                  pmd_rebalance_dry_run(dp)) {
                  VLOG_INFO("PMD auto load balance dry run. "
                            "Requesting datapath reconfigure.");
-@@ -7364,15 +7397,15 @@ static struct dp_netdev_pmd_thread *
+@@ -7364,15 +7412,15 @@ static struct dp_netdev_pmd_thread *
  dp_netdev_get_pmd(struct dp_netdev *dp, unsigned core_id)
  {
      struct dp_netdev_pmd_thread *pmd;
@@ -52537,7 +52608,7 @@ index 9f35713ef5..0b543cf222 100644
  }
  
  /* Sets the 'struct dp_netdev_pmd_thread' for non-pmd threads. */
-@@ -7505,6 +7538,7 @@ dp_netdev_destroy_pmd(struct dp_netdev_pmd_thread *pmd)
+@@ -7505,6 +7553,7 @@ dp_netdev_destroy_pmd(struct dp_netdev_pmd_thread *pmd)
      seq_destroy(pmd->reload_seq);
      ovs_mutex_destroy(&pmd->port_mutex);
      ovs_mutex_destroy(&pmd->bond_mutex);
@@ -52545,7 +52616,7 @@ index 9f35713ef5..0b543cf222 100644
      free(pmd);
  }
  
-@@ -8020,17 +8054,15 @@ dp_netdev_hw_flow(const struct dp_netdev_pmd_thread *pmd,
+@@ -8020,17 +8069,15 @@ dp_netdev_hw_flow(const struct dp_netdev_pmd_thread *pmd,
  #ifdef ALLOW_EXPERIMENTAL_API /* Packet restoration API required. */
      /* Restore the packet if HW processing was terminated before completion. */
      struct dp_netdev_rxq *rxq = pmd->ctx.last_rxq;
@@ -52570,7 +52641,7 @@ index 9f35713ef5..0b543cf222 100644
          }
      }
  #endif
-@@ -9495,6 +9527,7 @@ dpif_netdev_bond_stats_get(struct dpif *dpif, uint32_t bond_id,
+@@ -9495,6 +9542,7 @@ dpif_netdev_bond_stats_get(struct dpif *dpif, uint32_t bond_id,
  const struct dpif_class dpif_netdev_class = {
      "netdev",
      true,                       /* cleanup_required */
@@ -69922,7 +69993,7 @@ index 054dcc9ccf..d63528e69e 100644
  
  ovs-appctl time/warp 1000
 diff --git a/tests/pmd.at b/tests/pmd.at
-index a2f9d34a2a..a2832b544c 100644
+index a2f9d34a2a..287a5df15c 100644
 --- a/tests/pmd.at
 +++ b/tests/pmd.at
 @@ -199,7 +199,7 @@ pmd thread numa_id <cleared> core_id <cleared>:
@@ -70115,6 +70186,57 @@ index a2f9d34a2a..a2832b544c 100644
  
  AT_CHECK([ovs-appctl dpif-netdev/subtable-lookup-prio-set autovalidator 3], [0], [dnl
  Lookup priority change affected 0 dpcls ports and 0 subtables.
+@@ -1162,3 +1193,50 @@ ovs-appctl: ovs-vswitchd: server returned an error
+ 
+ OVS_VSWITCHD_STOP
+ AT_CLEANUP
++
++AT_SETUP([PMD - revalidator modify overlapping flows])
++
++OVS_VSWITCHD_START(
++[add-port br0 p1 \
++   -- set bridge br0 datapath-type=dummy \
++   -- set interface p1 type=dummy-pmd \
++   -- add-port br0 p2 \
++   -- set interface p2 type=dummy-pmd
++], [], [], [DUMMY_NUMA])
++
++dnl Add one OpenFlow rule and generate a megaflow.
++AT_CHECK([ovs-ofctl add-flow br0 'table=0,in_port=p1,ip,nw_dst=10.1.2.0/24,actions=p2'])
++AT_CHECK([ovs-appctl netdev-dummy/receive p1 'ipv4(src=10.0.0.1,dst=10.1.2.2,proto=6),tcp(src=1,dst=2)'])
++
++OVS_WAIT_UNTIL_EQUAL([ovs-appctl dpctl/dump-flows | sed 's/.*core: [[0-9]]*//'], [
++recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(dst=10.1.2.2/255.255.255.0,frag=no), packets:0, bytes:0, used:never, actions:2])
++
++AT_CHECK([ovs-appctl netdev-dummy/receive p1 'ipv4(src=10.0.0.1,dst=10.1.2.2,proto=6),tcp(src=1,dst=2)'])
++dnl Replace OpenFlow rules, trigger the revalidation.
++AT_CHECK([echo 'table=0,in_port=p1,ip,nw_dst=10.1.0.0/16 actions=ct(commit)' | dnl
++          ovs-ofctl --bundle replace-flows br0 -])
++AT_CHECK([ovs-appctl revalidator/wait])
++
++AT_CHECK([ovs-appctl netdev-dummy/receive p1 'ipv4(src=10.0.0.1,dst=10.1.0.2,proto=6),tcp(src=1,dst=2)'])
++OVS_WAIT_UNTIL_EQUAL([ovs-appctl dpctl/dump-flows | sed 's/.*core: [[0-9]]*//' | strip_xout_keep_actions], [
++recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(dst=10.1.0.2/255.255.0.0,frag=no), packets:0, bytes:0, used:never, actions:ct(commit)
++recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(dst=10.1.2.2/255.255.255.0,frag=no), packets:0, bytes:0, used:0.0s, actions:ct(commit)])
++
++dnl Hold the prefix 10.1.2.2/24 by another 10s.
++AT_CHECK([ovs-appctl netdev-dummy/receive p1 'ipv4(src=10.0.0.1,dst=10.1.2.2,proto=6),tcp(src=1,dst=2)'])
++dnl Send more 10.1.0.2 to make 10.1.0.0/16 tuple prepend 10.1.2.0/24 tuple in the pvector of subtables.
++for i in $(seq 0 256); do
++  AT_CHECK([ovs-appctl netdev-dummy/receive p1 'ipv4(src=10.0.0.1,dst=10.1.0.2,proto=6),tcp(src=1,dst=2)'])
++done
++
++AT_CHECK([echo 'table=0,in_port=p1,ip,nw_dst=10.1.0.0/16 actions=p2' | dnl
++          ovs-ofctl --bundle replace-flows br0 -])
++
++AT_CHECK([ovs-appctl revalidator/wait])
++AT_CHECK([ovs-appctl dpctl/dump-flows | sed 's/.*core: [[0-9]]*//' | strip_xout_keep_actions], [0], [
++recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(dst=10.1.0.2/255.255.0.0,frag=no), packets:0, bytes:0, used:0.0s, actions:2
++recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(dst=10.1.2.2/255.255.255.0,frag=no), packets:0, bytes:0, used:0.0s, actions:2
++])
++
++OVS_VSWITCHD_STOP
++AT_CLEANUP
 diff --git a/tests/reconnect.at b/tests/reconnect.at
 index 0f74709f5a..5bca84351c 100644
 --- a/tests/reconnect.at
diff --git a/SPECS/openvswitch2.17.spec b/SPECS/openvswitch2.17.spec
index f48020b..856f348 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: 100%{?dist}
+Release: 101%{?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
+* Mon Aug 14 2023 Open vSwitch CI <ovs-ci@redhat.com> - 2.17.0-101
+- Merging upstream branch-2.17 [RH git: 163447f9d5]
+    Commit list:
+    a74b7dfb96 dpif-netdev: Fix dpif_netdev_flow_put.
+
+
 * Wed Aug 09 2023 Open vSwitch CI <ovs-ci@redhat.com> - 2.17.0-100
 - Merging upstream branch-2.17 [RH git: 23753e82f9]
     Commit list: