From d6d5bbc9e43f5b6ce28d1d8c0df06b7cc3cb6db9 Mon Sep 17 00:00:00 2001 From: Ethan Jackson Date: Tue, 3 Sep 2013 17:34:00 -0700 Subject: [PATCH] ofproto-dpif-xlate: Fix mac learning deadlock. 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 Acked-by: Justin Pettit --- 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 2901fbeb4..ef254d9d6 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 -- 2.39.5