+ ovs_mutex_unlock(&monitor_mutex);
+ dp_packet_uninit(&packet);
+}
+
+/* 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 dp_packet *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 dp_packet *packet)
+ OVS_REQUIRES(monitor_mutex)
+{
+ long long int next_wake_time;
+ long long int bfd_wake_time = LLONG_MAX;
+ long long int cfm_wake_time = LLONG_MAX;
+ long long int lldp_wake_time = LLONG_MAX;
+
+ if (mport->cfm && cfm_should_send_ccm(mport->cfm)) {
+ dp_packet_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)) {
+ dp_packet_clear(packet);
+ bfd_put_packet(mport->bfd, packet, mport->hw_addr);
+ ofproto_dpif_send_packet(mport->ofport, packet);
+ }
+ if (mport->lldp && lldp_should_send_packet(mport->lldp)) {
+ dp_packet_clear(packet);
+ lldp_put_packet(mport->lldp, packet, mport->hw_addr);
+ ofproto_dpif_send_packet(mport->ofport, packet);
+ }
+
+ if (mport->cfm) {
+ cfm_run(mport->cfm);
+ cfm_wake_time = cfm_wait(mport->cfm);
+ }
+ if (mport->bfd) {
+ bfd_run(mport->bfd);
+ bfd_wake_time = bfd_wait(mport->bfd);
+ }
+ if (mport->lldp) {
+ lldp_wake_time = lldp_wait(mport->lldp);
+ }
+ /* Computes the next wakeup time for this mport. */
+ next_wake_time = MIN(bfd_wake_time,
+ cfm_wake_time);
+ next_wake_time = MIN(next_wake_time, lldp_wake_time);
+ heap_change(&monitor_heap, &mport->heap_node,
+ MSEC_TO_PRIO(next_wake_time));