bfd: Send FINAL immediately after receiving POLL.
[sliver-openvswitch.git] / ofproto / ofproto-dpif-monitor.c
index 2a833bb..f67f036 100644 (file)
@@ -197,7 +197,7 @@ monitor_run(void)
     struct ofpbuf packet;
 
     ofpbuf_use_stub(&packet, stub, sizeof stub);
-    ovs_rwlock_rdlock(&monitor_rwlock);
+    ovs_rwlock_wrlock(&monitor_rwlock);
     prio_now = MSEC_TO_PRIO(time_msec());
     /* Peeks the top of heap and checks if we should run this mport. */
     while (!heap_is_empty(&monitor_heap)
@@ -225,8 +225,9 @@ monitor_run(void)
             bfd_wait(mport->bfd);
         }
         /* Computes the next wakeup time for this mport. */
-        next_wake_time = MIN(bfd_wake_time(mport->bfd), cfm_wake_time(mport->cfm));
-        heap_change(&monitor_heap, heap_max(&monitor_heap),
+        next_wake_time = MIN(bfd_wake_time(mport->bfd),
+                             cfm_wake_time(mport->cfm));
+        heap_change(&monitor_heap, &mport->heap_node,
                     MSEC_TO_PRIO(next_wake_time));
     }
 
@@ -275,3 +276,27 @@ ofproto_dpif_monitor_port_update(const struct ofport_dpif *ofport,
         monitor_running = false;
     }
 }
+
+/* Moves the mport on top of the heap.  This is necessary when
+ * for example, bfd POLL is received and the mport should
+ * immediately send FINAL back. */
+void
+ofproto_dpif_monitor_port_send_soon_safe(const struct ofport_dpif *ofport)
+{
+    ovs_rwlock_wrlock(&monitor_rwlock);
+    ofproto_dpif_monitor_port_send_soon(ofport);
+    ovs_rwlock_unlock(&monitor_rwlock);
+}
+
+void
+ofproto_dpif_monitor_port_send_soon(const struct ofport_dpif *ofport)
+    OVS_REQ_WRLOCK(monitor_rwlock)
+{
+    struct mport *mport;
+
+    monitor_init();
+    mport = mport_find(ofport);
+    if (mport) {
+        heap_change(&monitor_heap, &mport->heap_node, LLONG_MAX);
+    }
+}