diff --git a/SOURCES/openvswitch-2.17.0.patch b/SOURCES/openvswitch-2.17.0.patch
index 6baf51c..35adced 100644
--- a/SOURCES/openvswitch-2.17.0.patch
+++ b/SOURCES/openvswitch-2.17.0.patch
@@ -59855,7 +59855,7 @@ index fcaddf10ad..71039e24f1 100644
  
  /* Attempts to guess the content type of a stream whose first few bytes were
 diff --git a/lib/tc.c b/lib/tc.c
-index adb2d3182a..bbadb6972a 100644
+index adb2d3182a..c4ae6d355a 100644
 --- a/lib/tc.c
 +++ b/lib/tc.c
 @@ -36,6 +36,7 @@
@@ -60545,7 +60545,7 @@ index adb2d3182a..bbadb6972a 100644
      if (host_eth_type == ETH_P_IP) {
              FLOWER_PUT_MASKED_VALUE(ipv4.ipv4_src, TCA_FLOWER_KEY_IPV4_SRC);
              FLOWER_PUT_MASKED_VALUE(ipv4.ipv4_dst, TCA_FLOWER_KEY_IPV4_DST);
-@@ -2993,12 +3152,79 @@ nl_msg_put_flower_options(struct ofpbuf *request, struct tc_flower *flower)
+@@ -2993,12 +3152,78 @@ nl_msg_put_flower_options(struct ofpbuf *request, struct tc_flower *flower)
      return 0;
  }
  
@@ -60586,15 +60586,13 @@ index adb2d3182a..bbadb6972a 100644
 +
 +        ds_put_cstr(&s, "\nExpected Actions:\n");
 +        for (i = 0, action = a->actions; i < a->action_count; i++, action++) {
-+            ds_put_cstr(&s, " - ");
-+            ds_put_hex(&s, action, sizeof *action);
-+            ds_put_cstr(&s, "\n");
++            ds_put_format(&s, " - %d -\n", i);
++            ds_put_sparse_hex_dump(&s, action, sizeof *action, 0, false);
 +        }
-+        ds_put_cstr(&s, "Received Actions:\n");
++        ds_put_cstr(&s, "\nReceived Actions:\n");
 +        for (i = 0, action = b->actions; i < b->action_count; i++, action++) {
-+            ds_put_cstr(&s, " - ");
-+            ds_put_hex(&s, action, sizeof *action);
-+            ds_put_cstr(&s, "\n");
++            ds_put_format(&s, " - %d -\n", i);
++            ds_put_sparse_hex_dump(&s, action, sizeof *action, 0, false);
 +        }
 +    } else {
 +        /* Only dump the delta in actions. */
@@ -60603,12 +60601,13 @@ index adb2d3182a..bbadb6972a 100644
 +
 +        for (int i = 0; i < a->action_count; i++, action_a++, action_b++) {
 +            if (memcmp(action_a, action_b, sizeof *action_a)) {
-+                ds_put_format(&s,
-+                              "\nAction %d mismatch:\n - Expected Action: ",
-+                              i);
-+                ds_put_hex(&s, action_a, sizeof *action_a);
-+                ds_put_cstr(&s, "\n - Received Action: ");
-+                ds_put_hex(&s, action_b, sizeof *action_b);
++                ds_put_format(&s, "\nAction %d mismatch:\n"
++                                  " - Expected Action:\n", i);
++                ds_put_sparse_hex_dump(&s, action_a, sizeof *action_a,
++                                       0, false);
++                ds_put_cstr(&s, " - Received Action:\n");
++                ds_put_sparse_hex_dump(&s, action_b, sizeof *action_b,
++                                       0, false);
 +            }
 +        }
 +    }
@@ -60626,7 +60625,7 @@ index adb2d3182a..bbadb6972a 100644
          return false;
      }
  
-@@ -3011,8 +3237,8 @@ cmp_tc_flower_match_action(const struct tc_flower *a,
+@@ -3011,8 +3236,8 @@ cmp_tc_flower_match_action(const struct tc_flower *a,
          uint8_t key_b = ((uint8_t *)&b->key)[i] & mask;
  
          if (key_a != key_b) {
@@ -60637,7 +60636,7 @@ index adb2d3182a..bbadb6972a 100644
              return false;
          }
      }
-@@ -3022,14 +3248,15 @@ cmp_tc_flower_match_action(const struct tc_flower *a,
+@@ -3022,14 +3247,15 @@ cmp_tc_flower_match_action(const struct tc_flower *a,
      const struct tc_action *action_b = b->actions;
  
      if (a->action_count != b->action_count) {
@@ -60656,7 +60655,7 @@ index adb2d3182a..bbadb6972a 100644
              return false;
          }
      }
-@@ -3063,8 +3290,15 @@ tc_replace_flower(struct tcf_id *id, struct tc_flower *flower)
+@@ -3063,8 +3289,15 @@ tc_replace_flower(struct tcf_id *id, struct tc_flower *flower)
  
      error = tc_transact(&request, &reply);
      if (!error) {
@@ -61893,7 +61892,7 @@ index 78a54c715d..109940ad2a 100644
              oftrace_node_destroy(node);
          }
 diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c
-index 57f94df544..53b47073ad 100644
+index 57f94df544..4629406b3f 100644
 --- a/ofproto/ofproto-dpif-upcall.c
 +++ b/ofproto/ofproto-dpif-upcall.c
 @@ -47,17 +47,20 @@
@@ -61967,7 +61966,33 @@ index 57f94df544..53b47073ad 100644
          atomic_store_relaxed(&udpif->n_flows, flow_count);
          ovs_mutex_unlock(&udpif->n_flows_mutex);
      } else {
-@@ -1746,6 +1769,7 @@ ukey_create__(const struct nlattr *key, size_t key_len,
+@@ -959,7 +982,7 @@ udpif_revalidator(void *arg)
+             udpif->reval_exit = latch_is_set(&udpif->exit_latch);
+ 
+             start_time = time_msec();
+-            if (!udpif->reval_exit) {
++            if (!udpif->reval_exit && !udpif->pause) {
+                 bool terse_dump;
+ 
+                 terse_dump = udpif_use_ufid(udpif);
+@@ -968,10 +991,15 @@ udpif_revalidator(void *arg)
+             }
+         }
+ 
+-        /* Wait for the leader to start the flow dump. */
++        /* Wait for the leader to reach this point. */
+         ovs_barrier_block(&udpif->reval_barrier);
+         if (udpif->pause) {
+             revalidator_pause(revalidator);
++            if (!udpif->reval_exit) {
++                /* The main thread resumed all validators, but the leader
++                 * didn't start the dump, go to next iteration. */
++                continue;
++            }
+         }
+ 
+         if (udpif->reval_exit) {
+@@ -1746,6 +1774,7 @@ ukey_create__(const struct nlattr *key, size_t key_len,
      ukey->created = ukey->flow_time = time_msec();
      memset(&ukey->stats, 0, sizeof ukey->stats);
      ukey->stats.used = used;
@@ -61975,7 +62000,7 @@ index 57f94df544..53b47073ad 100644
      ukey->xcache = NULL;
  
      ukey->offloaded = false;
-@@ -1868,6 +1892,7 @@ try_ukey_replace(struct umap *umap, struct udpif_key *old_ukey,
+@@ -1868,6 +1897,7 @@ try_ukey_replace(struct umap *umap, struct udpif_key *old_ukey,
              ovs_mutex_lock(&new_ukey->mutex);
              cmap_replace(&umap->cmap, &old_ukey->cmap_node,
                           &new_ukey->cmap_node, new_ukey->hash);
@@ -61983,7 +62008,7 @@ index 57f94df544..53b47073ad 100644
              ovsrcu_postpone(ukey_delete__, old_ukey);
              transition_ukey(old_ukey, UKEY_DELETED);
              transition_ukey(new_ukey, UKEY_VISIBLE);
-@@ -2074,10 +2099,12 @@ ukey_delete(struct umap *umap, struct udpif_key *ukey)
+@@ -2074,10 +2104,12 @@ ukey_delete(struct umap *umap, struct udpif_key *ukey)
  }
  
  static bool
@@ -61998,7 +62023,7 @@ index 57f94df544..53b47073ad 100644
  
      if (!used) {
          /* Always revalidate the first time a flow is dumped. */
-@@ -2104,8 +2131,12 @@ should_revalidate(const struct udpif *udpif, uint64_t packets,
+@@ -2104,8 +2136,12 @@ should_revalidate(const struct udpif *udpif, uint64_t packets,
      duration = now - used;
      metric = duration / packets;
  
@@ -62013,7 +62038,7 @@ index 57f94df544..53b47073ad 100644
          return true;
      }
      return false;
-@@ -2303,7 +2334,7 @@ static enum reval_result
+@@ -2303,7 +2339,7 @@ static enum reval_result
  revalidate_ukey(struct udpif *udpif, struct udpif_key *ukey,
                  const struct dpif_flow_stats *stats,
                  struct ofpbuf *odp_actions, uint64_t reval_seq,
@@ -62022,7 +62047,7 @@ index 57f94df544..53b47073ad 100644
      OVS_REQUIRES(ukey->mutex)
  {
      bool need_revalidate = ukey->reval_seq != reval_seq;
-@@ -2321,8 +2352,15 @@ revalidate_ukey(struct udpif *udpif, struct udpif_key *ukey,
+@@ -2321,8 +2357,15 @@ revalidate_ukey(struct udpif *udpif, struct udpif_key *ukey,
                      ? stats->n_bytes - ukey->stats.n_bytes
                      : 0);
  
@@ -62039,7 +62064,7 @@ index 57f94df544..53b47073ad 100644
              if (!ukey->xcache) {
                  ukey->xcache = xlate_cache_new();
              } else {
-@@ -2338,7 +2376,7 @@ revalidate_ukey(struct udpif *udpif, struct udpif_key *ukey,
+@@ -2338,7 +2381,7 @@ revalidate_ukey(struct udpif *udpif, struct udpif_key *ukey,
  
      /* Stats for deleted flows will be attributed upon flow deletion. Skip. */
      if (result != UKEY_DELETE) {
@@ -62048,7 +62073,7 @@ index 57f94df544..53b47073ad 100644
          ukey->stats = *stats;
          ukey->reval_seq = reval_seq;
      }
-@@ -2434,6 +2472,15 @@ push_dp_ops(struct udpif *udpif, struct ukey_op *ops, size_t n_ops)
+@@ -2434,6 +2477,15 @@ push_dp_ops(struct udpif *udpif, struct ukey_op *ops, size_t n_ops)
              push->tcp_flags = stats->tcp_flags | op->ukey->stats.tcp_flags;
              push->n_packets = stats->n_packets - op->ukey->stats.n_packets;
              push->n_bytes = stats->n_bytes - op->ukey->stats.n_bytes;
@@ -62064,7 +62089,7 @@ index 57f94df544..53b47073ad 100644
              ovs_mutex_unlock(&op->ukey->mutex);
          } else {
              push = stats;
-@@ -2738,6 +2785,22 @@ revalidate(struct revalidator *revalidator)
+@@ -2738,6 +2790,22 @@ revalidate(struct revalidator *revalidator)
                  continue;
              }
  
@@ -62087,7 +62112,7 @@ index 57f94df544..53b47073ad 100644
              already_dumped = ukey->dump_seq == dump_seq;
              if (already_dumped) {
                  /* The flow has already been handled during this flow dump
-@@ -2769,8 +2832,7 @@ revalidate(struct revalidator *revalidator)
+@@ -2769,8 +2837,7 @@ revalidate(struct revalidator *revalidator)
                  result = UKEY_DELETE;
              } else {
                  result = revalidate_ukey(udpif, ukey, &stats, &odp_actions,
@@ -62097,7 +62122,7 @@ index 57f94df544..53b47073ad 100644
              }
              ukey->dump_seq = dump_seq;
  
-@@ -2853,9 +2915,9 @@ revalidator_sweep__(struct revalidator *revalidator, bool purge)
+@@ -2853,9 +2920,9 @@ revalidator_sweep__(struct revalidator *revalidator, bool purge)
                  } else {
                      struct dpif_flow_stats stats;
                      COVERAGE_INC(revalidate_missed_dp_flow);
@@ -62109,10 +62134,27 @@ index 57f94df544..53b47073ad 100644
                  }
                  if (result != UKEY_KEEP) {
                      /* Clears 'recircs' if filled by revalidate_ukey(). */
-@@ -3099,6 +3161,31 @@ upcall_unixctl_purge(struct unixctl_conn *conn, int argc OVS_UNUSED,
-     unixctl_command_reply(conn, "");
- }
+@@ -3090,15 +3157,48 @@ upcall_unixctl_purge(struct unixctl_conn *conn, int argc OVS_UNUSED,
+     struct udpif *udpif;
  
+     LIST_FOR_EACH (udpif, list_node, &all_udpifs) {
++        bool wake_up = false;
+         int n;
+ 
++        if (!latch_is_set(&udpif->pause_latch)) {
++            udpif_pause_revalidators(udpif);
++            wake_up = true;
++        }
+         for (n = 0; n < udpif->n_revalidators; n++) {
+             revalidator_purge(&udpif->revalidators[n]);
+         }
++        if (wake_up) {
++            udpif_resume_revalidators(udpif);
++        }
++    }
++    unixctl_command_reply(conn, "");
++}
++
 +static void
 +upcall_unixctl_pause(struct unixctl_conn *conn, int argc OVS_UNUSED,
 +                     const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
@@ -62121,10 +62163,10 @@ index 57f94df544..53b47073ad 100644
 +
 +    LIST_FOR_EACH (udpif, list_node, &all_udpifs) {
 +        udpif_pause_revalidators(udpif);
-+    }
-+    unixctl_command_reply(conn, "");
-+}
-+
+     }
+     unixctl_command_reply(conn, "");
+ }
+ 
 +static void
 +upcall_unixctl_resume(struct unixctl_conn *conn, int argc OVS_UNUSED,
 +                      const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
@@ -72503,7 +72545,7 @@ index d21fd777dd..81123f7309 100644
  ADD_NAMESPACES(at_ns0, at_ns1)
  
 diff --git a/tests/system-offloads-traffic.at b/tests/system-offloads-traffic.at
-index 80bc1dd5c3..bf60e4cb27 100644
+index 80bc1dd5c3..c302f198fe 100644
 --- a/tests/system-offloads-traffic.at
 +++ b/tests/system-offloads-traffic.at
 @@ -90,7 +90,7 @@ AT_CHECK([tc -o -s -d filter show dev ovs-p0 ingress |
@@ -72524,7 +72566,7 @@ index 80bc1dd5c3..bf60e4cb27 100644
  OVS_TRAFFIC_VSWITCHD_STOP
  AT_CLEANUP
  
-@@ -168,3 +168,186 @@ matchall
+@@ -168,3 +168,184 @@ matchall
  ])
  OVS_TRAFFIC_VSWITCHD_STOP
  AT_CLEANUP
@@ -72705,8 +72747,6 @@ index 80bc1dd5c3..bf60e4cb27 100644
 +
 +OVS_TRAFFIC_VSWITCHD_STOP(["/could not open network device ovs-p0/d
 +/on nonexistent port/d
-+/failed to flow_get/d
-+/Failed to acquire udpif_key/d
 +/No such device/d
 +/failed to offload flow/d
 +"])
diff --git a/SPECS/openvswitch2.17.spec b/SPECS/openvswitch2.17.spec
index 33430ad..5dead06 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: 115%{?dist}
+Release: 116%{?dist}
 
 # Nearly all of openvswitch is ASL 2.0.  The bugtool is LGPLv2+, and the
 # lib/sflow*.[ch] files are SISSL
@@ -751,6 +751,13 @@ exit 0
 %endif
 
 %changelog
+* Fri Oct 20 2023 Open vSwitch CI <ovs-ci@redhat.com> - 2.17.0-116
+- Merging upstream branch-2.17 [RH git: 258fc7a88a]
+    Commit list:
+    bce17b0bb5 tc: Improve logging of mismatched actions.
+    af934924f8 ofproto-dpif-upcall: Pause revalidators when purging.
+
+
 * Wed Oct 18 2023 Open vSwitch CI <ovs-ci@redhat.com> - 2.17.0-115
 - Merging upstream branch-2.17 [RH git: 0717965172]
     Commit list: