diff --git a/lib/dpctl.c b/lib/dpctl.c
index 33202813b..d907eddb4 100644
--- a/lib/dpctl.c
+++ b/lib/dpctl.c
@@ -1146,6 +1146,12 @@ dpctl_put_flow(int argc, const char *argv[], enum dpif_flow_put_flags flags,
         ufid_present = true;
     }
 
+    if (ufid_present && dpctl_p->consistent) {
+        dpctl_error(dpctl_p, -1,
+                    "ufid and consistent are enabled at same time.");
+        return -1;
+    }
+
     simap_init(&port_names);
     DPIF_PORT_FOR_EACH (&dpif_port, &port_dump, dpif) {
         simap_put(&port_names, dpif_port.name, odp_to_u32(dpif_port.port_no));
@@ -1169,6 +1175,11 @@ dpctl_put_flow(int argc, const char *argv[], enum dpif_flow_put_flags flags,
         goto out_freeactions;
     }
 
+    if (dpctl_p->consistent) {
+        odp_flow_key_hash_local(key.data, key.size, &ufid);
+        ufid_present = true;
+    }
+
     if (!ufid_present && dpctl_p->is_appctl) {
         /* Generating UFID for this flow so it could be offloaded to HW.  We're
          * not doing that if invoked from ovs-dpctl utility because
@@ -1326,6 +1337,17 @@ dpctl_del_flow(int argc, const char *argv[], struct dpctl_params *dpctl_p)
         goto out;
     }
 
+    if (ufid_present && dpctl_p->consistent) {
+        dpctl_error(dpctl_p, -1,
+                    "ufid and consistent are enabled at same time.");
+        goto out;
+    }
+
+    if (dpctl_p->consistent) {
+        odp_flow_key_hash_local(key.data, key.size, &ufid);
+        ufid_present = ufid_generated = true;
+    }
+
     if (!ufid_present && dpctl_p->is_appctl) {
         /* While adding flow via appctl we're generating UFID to make HW
          * offloading possible.  Generating UFID here to be sure that such
@@ -2670,6 +2692,8 @@ dpctl_unixctl_handler(struct unixctl_conn *conn, int argc, const char *argv[],
             } else if (!strcmp(arg, "--no-names")) {
                 dpctl_p.names = false;
                 set_names = true;
+            } else if (!strcmp(arg, "--consistent")) {
+                dpctl_p.consistent = true;
             } else {
                 ds_put_format(&ds, "Unrecognized option %s", argv[1]);
                 error = true;
diff --git a/lib/dpctl.h b/lib/dpctl.h
index 9d0052152..b042663cc 100644
--- a/lib/dpctl.h
+++ b/lib/dpctl.h
@@ -42,6 +42,9 @@ struct dpctl_params {
     /* --names: Use port names in output? */
     bool names;
 
+    /* --consistent: Install consistent flow. */
+    bool consistent;
+
     /* Callback for printing.  This function is called from dpctl_run_command()
      * to output data.  The 'aux' parameter is set to the 'aux'
      * member.  The 'error' parameter is true if 'string' is an error
diff --git a/lib/odp-util.c b/lib/odp-util.c
index 252a91bfa..ddf30077c 100644
--- a/lib/odp-util.c
+++ b/lib/odp-util.c
@@ -6592,6 +6592,17 @@ odp_flow_key_hash(const void *key, size_t key_len, ovs_u128 *hash)
     }
     hash_bytes128(key, key_len, secret, hash);
     uuid_set_bits_v4((struct uuid *)hash);
+
+    /* Clean up the first bit. */
+    hash->u32[0] &= ~0x1;
+}
+
+void
+odp_flow_key_hash_local(const void *key, size_t key_len, ovs_u128 *hash)
+{
+    odp_flow_key_hash(key, key_len, hash);
+    /* If setting 1, it means flows are consistent. */
+    hash->u32[0] |= 0x1;
 }
 
 static void
diff --git a/lib/odp-util.h b/lib/odp-util.h
index 623a66aa2..dc0ad2332 100644
--- a/lib/odp-util.h
+++ b/lib/odp-util.h
@@ -244,6 +244,7 @@ void odp_flow_key_from_flow(const struct odp_flow_key_parms *, struct ofpbuf *);
 void odp_flow_key_from_mask(const struct odp_flow_key_parms *, struct ofpbuf *);
 
 void odp_flow_key_hash(const void *key, size_t key_len, ovs_u128 *hash);
+void odp_flow_key_hash_local(const void *key, size_t key_len, ovs_u128 *hash);
 
 /* Estimated space needed for metadata. */
 enum { ODP_KEY_METADATA_SIZE = 9 * 8 };
diff --git a/lib/uuid.h b/lib/uuid.h
index fa49354f6..1aab3231e 100644
--- a/lib/uuid.h
+++ b/lib/uuid.h
@@ -42,6 +42,9 @@ extern "C" {
     ((unsigned int) ((UUID)->parts[2] & 0xffff)),   \
     ((unsigned int) ((UUID)->parts[3]))
 
+#define UUID_LOCAL(ufid) \
+    (((ufid)->u32[0] & 0x1) == 0x1)
+
 /* Returns a hash value for 'uuid'.  This hash value is the same regardless of
  * whether we are running on a 32-bit or 64-bit or big-endian or little-endian
  * architecture. */
diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c
index 19b92dfe0..c8ea16c18 100644
--- a/ofproto/ofproto-dpif-upcall.c
+++ b/ofproto/ofproto-dpif-upcall.c
@@ -2685,6 +2685,10 @@ revalidate(struct revalidator *revalidator)
             bool already_dumped;
             int error;
 
+            if (f->ufid_present && UUID_LOCAL(&(f)->ufid)) {
+                continue;
+            }
+
             if (ukey_acquire(udpif, f, &ukey, &error)) {
                 if (error == EBUSY) {
                     /* Another thread is processing this flow, so don't bother
@@ -2794,6 +2798,9 @@ revalidator_sweep__(struct revalidator *revalidator, bool purge)
         CMAP_FOR_EACH(ukey, cmap_node, &umap->cmap) {
             enum ukey_state ukey_state;
 
+            if (ukey->ufid_present && UUID_LOCAL(&(ukey)->ufid)) {
+                continue;
+            }
             /* Handler threads could be holding a ukey lock while it installs a
              * new flow, so don't hang around waiting for access to it. */
             if (ovs_mutex_trylock(&ukey->mutex)) {
