[ovs-dev,v3] ofproto-dpif: do not block on uninitialized pause barriers
diff mbox

Message ID 1443206560-24345-1-git-send-email-zoltan.kiss@linaro.org
State Accepted
Headers show

Commit Message

Zoltan Kiss Sept. 25, 2015, 6:42 p.m. UTC
e4e74c3a "dpif-netdev: Purge all ukeys when reconfigure pmd." introduced a new
dp_purge_cb function, which calls udpif_pause_revalidators() and that tries to
block on pause_barrier.
But if OVS was started with flow-restore-wait="true" (e.g. through ovs-ctl),
type_run() will have backer->recv_set_enable == false, and udpif_set_threads
won't initialize the barrier, which leads to a segfault like this:

#0  seq_read (seq=0x0) at lib/seq.c:121
#1  0x00000000004f33a2 in ovs_barrier_block (barrier=barrier@entry=0x9304a0) at lib/ovs-thread.c:291
#2  0x0000000000445a01 in udpif_pause_revalidators (udpif=0x930410) at ofproto/ofproto-dpif-upcall.c:526
#3  dp_purge_cb (aux=0x930410, pmd_id=4294967295) at ofproto/ofproto-dpif-upcall.c:2271
#4  0x0000000000471552 in dp_netdev_del_pmd (pmd=pmd@entry=0x961f10, dp=<optimised out>, dp=<optimised out>) at lib/dpif-netdev.c:2891
#5  0x00000000004716d9 in dp_netdev_destroy_all_pmds (dp=0x948550) at lib/dpif-netdev.c:2904
#6  dpif_netdev_pmd_set (dpif=<optimised out>, n_rxqs=1, cmask=0x946250 "2") at lib/dpif-netdev.c:2385
#7  0x000000000047873a in dpif_poll_threads_set (dpif=0x95ed10, n_rxqs=<optimised out>, cmask=<optimised out>) at lib/dpif.c:1411
#8  0x000000000043897f in type_run (type=<optimised out>) at ofproto/ofproto-dpif.c:558
#9  0x000000000042b195 in ofproto_type_run (datapath_type=<optimised out>, datapath_type@entry=0xcf23e0 "netdev") at ofproto/ofproto.c:1655
#10 0x000000000040f395 in bridge_run__ () at vswitchd/bridge.c:2875
#11 0x00000000004155b3 in bridge_reconfigure (ovs_cfg=ovs_cfg@entry=0x961db0) at vswitchd/bridge.c:700
#12 0x0000000000418439 in bridge_run () at vswitchd/bridge.c:2984
#13 0x000000000040d025 in main (argc=11, argv=0x7fffffffe9a8) at vswitchd/ovs-vswitchd.c:120

This patch introduces ofproto_dpif_backer_enabled(), which checks
recv_set_enable before touching the latch and blocking on pause_barrier.

Signed-off-by: Zoltan Kiss <zoltan.kiss@linaro.org>
---
v2:
- ofproto_dpif_backer_enabled() to check recv_set_enable
- do not touch the latch

v3:
- rebase to latest master
- don't touch control chars

Comments

Joe Stringer Sept. 25, 2015, 10:29 p.m. UTC | #1
On 25 September 2015 at 11:42, Zoltan Kiss <zoltan.kiss@linaro.org> wrote:
> e4e74c3a "dpif-netdev: Purge all ukeys when reconfigure pmd." introduced a new
> dp_purge_cb function, which calls udpif_pause_revalidators() and that tries to
> block on pause_barrier.
> But if OVS was started with flow-restore-wait="true" (e.g. through ovs-ctl),
> type_run() will have backer->recv_set_enable == false, and udpif_set_threads
> won't initialize the barrier, which leads to a segfault like this:
>
> #0  seq_read (seq=0x0) at lib/seq.c:121
> #1  0x00000000004f33a2 in ovs_barrier_block (barrier=barrier@entry=0x9304a0) at lib/ovs-thread.c:291
> #2  0x0000000000445a01 in udpif_pause_revalidators (udpif=0x930410) at ofproto/ofproto-dpif-upcall.c:526
> #3  dp_purge_cb (aux=0x930410, pmd_id=4294967295) at ofproto/ofproto-dpif-upcall.c:2271
> #4  0x0000000000471552 in dp_netdev_del_pmd (pmd=pmd@entry=0x961f10, dp=<optimised out>, dp=<optimised out>) at lib/dpif-netdev.c:2891
> #5  0x00000000004716d9 in dp_netdev_destroy_all_pmds (dp=0x948550) at lib/dpif-netdev.c:2904
> #6  dpif_netdev_pmd_set (dpif=<optimised out>, n_rxqs=1, cmask=0x946250 "2") at lib/dpif-netdev.c:2385
> #7  0x000000000047873a in dpif_poll_threads_set (dpif=0x95ed10, n_rxqs=<optimised out>, cmask=<optimised out>) at lib/dpif.c:1411
> #8  0x000000000043897f in type_run (type=<optimised out>) at ofproto/ofproto-dpif.c:558
> #9  0x000000000042b195 in ofproto_type_run (datapath_type=<optimised out>, datapath_type@entry=0xcf23e0 "netdev") at ofproto/ofproto.c:1655
> #10 0x000000000040f395 in bridge_run__ () at vswitchd/bridge.c:2875
> #11 0x00000000004155b3 in bridge_reconfigure (ovs_cfg=ovs_cfg@entry=0x961db0) at vswitchd/bridge.c:700
> #12 0x0000000000418439 in bridge_run () at vswitchd/bridge.c:2984
> #13 0x000000000040d025 in main (argc=11, argv=0x7fffffffe9a8) at vswitchd/ovs-vswitchd.c:120
>
> This patch introduces ofproto_dpif_backer_enabled(), which checks
> recv_set_enable before touching the latch and blocking on pause_barrier.
>
> Signed-off-by: Zoltan Kiss <zoltan.kiss@linaro.org>

Thanks, applied to master.

Patch
diff mbox

diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c
index 8a43bbf..3b897e0 100644
--- a/ofproto/ofproto-dpif-upcall.c
+++ b/ofproto/ofproto-dpif-upcall.c
@@ -522,8 +522,10 @@  udpif_start_threads(struct udpif *udpif, size_t n_handlers,
 static void
 udpif_pause_revalidators(struct udpif *udpif)
 {
-    latch_set(&udpif->pause_latch);
-    ovs_barrier_block(&udpif->pause_barrier);
+    if (ofproto_dpif_backer_enabled(udpif->backer)) {
+        latch_set(&udpif->pause_latch);
+        ovs_barrier_block(&udpif->pause_barrier);
+    }
 }
 
 /* Resumes the pausing of revalidators.  Should only be called by the
@@ -531,8 +533,10 @@  udpif_pause_revalidators(struct udpif *udpif)
 static void
 udpif_resume_revalidators(struct udpif *udpif)
 {
-    latch_poll(&udpif->pause_latch);
-    ovs_barrier_block(&udpif->pause_barrier);
+    if (ofproto_dpif_backer_enabled(udpif->backer)) {
+        latch_poll(&udpif->pause_latch);
+        ovs_barrier_block(&udpif->pause_barrier);
+    }
 }
 
 /* Tells 'udpif' how many threads it should use to handle upcalls.
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index cffedb9..ef1ad18 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -515,6 +515,12 @@  lookup_ofproto_dpif_by_port_name(const char *name)
     return NULL;
 }
 
+bool
+ofproto_dpif_backer_enabled(struct dpif_backer* backer)
+{
+    return backer->recv_set_enable;
+}
+
 static int
 type_run(const char *type)
 {
diff --git a/ofproto/ofproto-dpif.h b/ofproto/ofproto-dpif.h
index 2397fb4..dab422a 100644
--- a/ofproto/ofproto-dpif.h
+++ b/ofproto/ofproto-dpif.h
@@ -169,6 +169,8 @@  struct ofport_dpif *odp_port_to_ofport(const struct dpif_backer *, odp_port_t);
 struct ofport_dpif *ofp_port_to_ofport(const struct ofproto_dpif *,
                                        ofp_port_t);
 
+bool ofproto_dpif_backer_enabled(struct dpif_backer* backer);
+
 int ofproto_dpif_add_internal_flow(struct ofproto_dpif *,
                                    const struct match *, int priority,
                                    uint16_t idle_timeout,