[ovs-dev] [PATCH] ofproto-dpif-xlate: Fix mac learning deadlock.

Ethan Jackson ethan at nicira.com
Wed Sep 4 00:40:15 UTC 2013


xlate_normal() held the mac_learning lock while calling
output_normal().  When running with patch ports, this could cause
xlate_actions() to be called again, possibly attempting to take a
write lock on the same learning table causing a deadlock.  This patch
solves the problem by holding the lock for a very brief period of
time.

Bug #19423.
Signed-off-by: Ethan Jackson <ethan at nicira.com>
---
 ofproto/ofproto-dpif-xlate.c |    9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
index 2901fbe..ef254d9 100644
--- a/ofproto/ofproto-dpif-xlate.c
+++ b/ofproto/ofproto-dpif-xlate.c
@@ -1224,6 +1224,7 @@ xlate_normal(struct xlate_ctx *ctx)
     struct xbundle *in_xbundle;
     struct xport *in_port;
     struct mac_entry *mac;
+    void *mac_port;
     uint16_t vlan;
     uint16_t vid;
 
@@ -1286,8 +1287,11 @@ xlate_normal(struct xlate_ctx *ctx)
     /* Determine output bundle. */
     ovs_rwlock_rdlock(&ctx->xbridge->ml->rwlock);
     mac = mac_learning_lookup(ctx->xbridge->ml, flow->dl_dst, vlan);
-    if (mac) {
-        struct xbundle *mac_xbundle = xbundle_lookup(mac->port.p);
+    mac_port = mac ? mac->port.p : NULL;
+    ovs_rwlock_unlock(&ctx->xbridge->ml->rwlock);
+
+    if (mac_port) {
+        struct xbundle *mac_xbundle = xbundle_lookup(mac_port);
         if (mac_xbundle && mac_xbundle != in_xbundle) {
             xlate_report(ctx, "forwarding to learned port");
             output_normal(ctx, mac_xbundle, vlan);
@@ -1310,7 +1314,6 @@ xlate_normal(struct xlate_ctx *ctx)
         }
         ctx->xout->nf_output_iface = NF_OUT_FLOOD;
     }
-    ovs_rwlock_unlock(&ctx->xbridge->ml->rwlock);
 }
 
 /* Compose SAMPLE action for sFlow or IPFIX.  The given probability is
-- 
1.7.9.5




More information about the dev mailing list