+
+ /* Waits on the earliest next wakeup time. */
+ if (!heap_is_empty(&monitor_heap)) {
+ long long int next_timeout, next_mport_wakeup;
+
+ next_timeout = time_msec() + MONITOR_INTERVAL_MSEC;
+ next_mport_wakeup = PRIO_TO_MSEC(heap_max(&monitor_heap)->priority);
+ poll_timer_wait_until(MIN(next_timeout, next_mport_wakeup));
+ }
+ ovs_mutex_unlock(&monitor_mutex);
+ ofpbuf_uninit(&packet);
+}
+\f
+
+/* Creates the mport in monitor module if either bfd or cfm
+ * is configured. Otherwise, deletes the mport.
+ * Also checks whether the monitor thread should be started
+ * or terminated. */
+void
+ofproto_dpif_monitor_port_update(const struct ofport_dpif *ofport,
+ struct bfd *bfd, struct cfm *cfm,
+ uint8_t hw_addr[ETH_ADDR_LEN])
+{
+ ovs_mutex_lock(&monitor_mutex);
+ if (!cfm && !bfd) {
+ mport_unregister(ofport);
+ } else {
+ mport_register(ofport, bfd, cfm, hw_addr);
+ }
+ ovs_mutex_unlock(&monitor_mutex);
+
+ /* If the monitor thread is not running and the hmap
+ * is not empty, starts it. If it is and the hmap is empty,
+ * terminates it. */
+ if (!monitor_running && !hmap_is_empty(&monitor_hmap)) {
+ latch_init(&monitor_exit_latch);
+ monitor_tid = ovs_thread_create("monitor", monitor_main, NULL);
+ monitor_running = true;
+ } else if (monitor_running && hmap_is_empty(&monitor_hmap)) {
+ latch_set(&monitor_exit_latch);
+ xpthread_join(monitor_tid, NULL);
+ latch_destroy(&monitor_exit_latch);
+ 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_mutex_lock(&monitor_mutex);
+ ofproto_dpif_monitor_port_send_soon(ofport);
+ ovs_mutex_unlock(&monitor_mutex);