It's highly unlikely that two flows will hash to the same UID. However,
we could handle multiple upcalls from the same flow. If the flow keys
are the same as a previous flow, then the current upcalls belongs to a
flow that already has a datapath flow installed. If the keys are
different, then we have generated the same UID hash for two different
flows, and we should log a warning.

Signed-off-by: Joe Stringer <joestrin...@nicira.com>
---
v5: Compare flow keys rather than hashes of flow keys.
v4: Initial post.
---
 ofproto/ofproto-dpif-upcall.c |   38 ++++++++++++++++++++++++++++----------
 1 file changed, 28 insertions(+), 10 deletions(-)

diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c
index dea3304..45c22a5 100644
--- a/ofproto/ofproto-dpif-upcall.c
+++ b/ofproto/ofproto-dpif-upcall.c
@@ -46,7 +46,7 @@
 
 VLOG_DEFINE_THIS_MODULE(ofproto_dpif_upcall);
 
-COVERAGE_DEFINE(handler_install_conflict);
+COVERAGE_DEFINE(handler_duplicate_upcall);
 COVERAGE_DEFINE(upcall_ukey_contention);
 COVERAGE_DEFINE(dumped_duplicate_flow);
 COVERAGE_DEFINE(dumped_new_flow);
@@ -1286,23 +1286,41 @@ ukey_new(struct upcall *upcall)
  * On success, returns true, installs the ukey and returns it in a locked
  * state. Otherwise, returns false. */
 static bool
-ukey_install_start(struct udpif *udpif, struct udpif_key *ukey)
-    OVS_TRY_LOCK(true, ukey->mutex)
+ukey_install_start(struct udpif *udpif, struct udpif_key *new_ukey)
+    OVS_TRY_LOCK(true, new_ukey->mutex)
 {
     struct umap *umap;
+    struct udpif_key *old_ukey;
     uint32_t idx;
     bool locked = false;
 
-    idx = ukey->hash % N_UMAPS;
+    idx = new_ukey->hash % N_UMAPS;
     umap = &udpif->ukeys[idx];
     ovs_mutex_lock(&umap->mutex);
-    if (!ukey_lookup(udpif, &ukey->uid)) {
-        ovs_mutex_lock(&ukey->mutex);
-        cmap_insert(&umap->cmap, &ukey->cmap_node, ukey->hash);
-        locked = true;
+    old_ukey = ukey_lookup(udpif, &new_ukey->uid);
+    if (old_ukey) {
+        /* Uncommon case: A ukey is already installed with the same UID. */
+        if (old_ukey->key_len == new_ukey->key_len
+            && !memcmp(old_ukey->key, new_ukey->key, new_ukey->key_len)) {
+            COVERAGE_INC(handler_duplicate_upcall);
+        } else {
+            struct ds ds = DS_EMPTY_INITIALIZER;
+
+            odp_format_uid(&old_ukey->uid, &ds);
+            ds_put_cstr(&ds, " ");
+            odp_flow_key_format(old_ukey->key, old_ukey->key_len, &ds);
+            ds_put_cstr(&ds, "\n");
+            odp_format_uid(&new_ukey->uid, &ds);
+            ds_put_cstr(&ds, " ");
+            odp_flow_key_format(new_ukey->key, new_ukey->key_len, &ds);
+
+            VLOG_WARN("Conflicting ukey for flows:\n%s", ds_cstr(&ds));
+            ds_destroy(&ds);
+        }
     } else {
-        COVERAGE_INC(handler_install_conflict);
-        VLOG_DBG("Failed to ukey_install_start(): 0x%"PRIx32, ukey->hash);
+        ovs_mutex_lock(&new_ukey->mutex);
+        cmap_insert(&umap->cmap, &new_ukey->cmap_node, new_ukey->hash);
+        locked = true;
     }
     ovs_mutex_unlock(&umap->mutex);
 
-- 
1.7.10.4

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to