+
+/* Checks the 'send_soon' list for any mport that needs to send cfm/bfd
+ * control packet immediately, and calls monitor_mport_run(). */
+static void
+monitor_check_send_soon(struct ofpbuf *packet)
+ OVS_REQUIRES(monitor_mutex)
+{
+ while (!guarded_list_is_empty(&send_soon)) {
+ struct send_soon_entry *entry;
+ struct mport *mport;
+
+ entry = CONTAINER_OF(guarded_list_pop_front(&send_soon),
+ struct send_soon_entry, list_node);
+ mport = mport_find(entry->ofport);
+ if (mport) {
+ monitor_mport_run(mport, packet);
+ }
+ free(entry);
+ }
+}
+
+/* Checks the sending of control packet on 'mport'. Sends the control
+ * packet if needed. Executes bfd and cfm periodic functions (run, wait)
+ * on 'mport'. And changes the location of 'mport' in heap based on next
+ * timeout. */
+static void
+monitor_mport_run(struct mport *mport, struct ofpbuf *packet)
+ OVS_REQUIRES(monitor_mutex)
+{
+ long long int next_wake_time;
+
+ if (mport->cfm && cfm_should_send_ccm(mport->cfm)) {
+ ofpbuf_clear(packet);
+ cfm_compose_ccm(mport->cfm, packet, mport->hw_addr);
+ ofproto_dpif_send_packet(mport->ofport, packet);
+ }
+ if (mport->bfd && bfd_should_send_packet(mport->bfd)) {
+ ofpbuf_clear(packet);
+ bfd_put_packet(mport->bfd, packet, mport->hw_addr);
+ ofproto_dpif_send_packet(mport->ofport, packet);
+ }
+ if (mport->cfm) {
+ cfm_run(mport->cfm);
+ cfm_wait(mport->cfm);
+ }
+ if (mport->bfd) {
+ bfd_run(mport->bfd);
+ 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, &mport->heap_node,
+ MSEC_TO_PRIO(next_wake_time));
+}