ofproto: Lock for vlan splinters only if have them.
authorJarno Rajahalme <jrajahalme@nicira.com>
Fri, 7 Feb 2014 19:34:01 +0000 (11:34 -0800)
committerJarno Rajahalme <jrajahalme@nicira.com>
Wed, 12 Feb 2014 21:58:47 +0000 (13:58 -0800)
Reading the hmap count for determining if it is empty or not is thread
safe, so avoid locking when not necessary.

Signed-off-by: Jarno Rajahalme <jrajahalme@nicira.com>
Signed-off-by: Ben Pfaff <blp@nicira.com>
lib/hmap.h
ofproto/ofproto-dpif-xlate.c
ofproto/ofproto-dpif.c

index 76a73ac..445e74f 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <stdbool.h>
 #include <stdlib.h>
+#include "ovs-atomic.h"
 #include "util.h"
 
 #ifdef  __cplusplus
@@ -189,10 +190,13 @@ hmap_capacity(const struct hmap *hmap)
 }
 
 /* Returns true if 'hmap' currently contains no nodes,
- * false otherwise. */
+ * false otherwise.
+ * Note: While hmap in general is not thread-safe without additional locking,
+ * hmap_is_empty() is. */
 static inline bool
 hmap_is_empty(const struct hmap *hmap)
 {
+    atomic_thread_fence(memory_order_acquire);
     return hmap->n == 0;
 }
 
index ffcfdf9..ccf0b75 100644 (file)
@@ -1780,19 +1780,18 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port,
                                  &ctx->xout->odp_actions);
         flow->tunnel = flow_tnl; /* Restore tunnel metadata */
     } else {
-        ofp_port_t vlandev_port;
-
         odp_port = xport->odp_port;
+        out_port = odp_port;
         if (ofproto_has_vlan_splinters(ctx->xbridge->ofproto)) {
+            ofp_port_t vlandev_port;
+
             wc->masks.vlan_tci |= htons(VLAN_VID_MASK | VLAN_CFI);
-        }
-        vlandev_port = vsp_realdev_to_vlandev(ctx->xbridge->ofproto, ofp_port,
-                                              flow->vlan_tci);
-        if (vlandev_port == ofp_port) {
-            out_port = odp_port;
-        } else {
-            out_port = ofp_port_to_odp_port(ctx->xbridge, vlandev_port);
-            flow->vlan_tci = htons(0);
+            vlandev_port = vsp_realdev_to_vlandev(ctx->xbridge->ofproto,
+                                                  ofp_port, flow->vlan_tci);
+            if (vlandev_port != ofp_port) {
+                out_port = ofp_port_to_odp_port(ctx->xbridge, vlandev_port);
+                flow->vlan_tci = htons(0);
+            }
         }
     }
 
index 7b3e1eb..f2ae600 100644 (file)
@@ -4250,12 +4250,8 @@ bool
 ofproto_has_vlan_splinters(const struct ofproto_dpif *ofproto)
     OVS_EXCLUDED(ofproto->vsp_mutex)
 {
-    bool ret;
-
-    ovs_mutex_lock(&ofproto->vsp_mutex);
-    ret = !hmap_is_empty(&ofproto->realdev_vid_map);
-    ovs_mutex_unlock(&ofproto->vsp_mutex);
-    return ret;
+    /* hmap_is_empty is thread safe. */
+    return !hmap_is_empty(&ofproto->realdev_vid_map);
 }
 
 static ofp_port_t
@@ -4293,6 +4289,10 @@ vsp_realdev_to_vlandev(const struct ofproto_dpif *ofproto,
 {
     ofp_port_t ret;
 
+    /* hmap_is_empty is thread safe, see if we can return immediately. */
+    if (hmap_is_empty(&ofproto->realdev_vid_map)) {
+        return realdev_ofp_port;
+    }
     ovs_mutex_lock(&ofproto->vsp_mutex);
     ret = vsp_realdev_to_vlandev__(ofproto, realdev_ofp_port, vlan_tci);
     ovs_mutex_unlock(&ofproto->vsp_mutex);
@@ -4356,6 +4356,11 @@ vsp_adjust_flow(const struct ofproto_dpif *ofproto, struct flow *flow)
     ofp_port_t realdev;
     int vid;
 
+    /* hmap_is_empty is thread safe. */
+    if (hmap_is_empty(&ofproto->vlandev_map)) {
+        return false;
+    }
+
     ovs_mutex_lock(&ofproto->vsp_mutex);
     realdev = vsp_vlandev_to_realdev(ofproto, flow->in_port.ofp_port, &vid);
     ovs_mutex_unlock(&ofproto->vsp_mutex);