@@ -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;
@@ -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
@@ -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
@@ -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 };
@@ -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. */
@@ -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)) {