[ovs-dev] [RFC 4/4] monitor: Add generic monitor library.

Alex Wang alexw at nicira.com
Mon Mar 17 17:42:25 UTC 2014


This commit abstracts the tunnel monitoring logic in 'ofproto-dpif-monitor'
into a generic 'monitor' library.  The 'monitor' library is designed to
allow user monitor using multiple protocols (e.g. bfd/cfm) together.  Also,
it employs heap to order the sessions for efficiency.  The code in the
'ofproto-dpif-monitor' module is updated to use this library.

Note, monitor library module still uses current heap, hash and hmap module
in Open Vswitch project.

Signed-off-by: Alex Wang <alexw at nicira.com>
---
 lib/automake.mk                |    2 +
 lib/monitor.c                  |  150 +++++++++++++++++++++++++
 lib/monitor.h                  |   29 +++++
 ofproto/ofproto-dpif-monitor.c |  236 +++++++++++-----------------------------
 ofproto/ofproto-dpif-monitor.h |    7 +-
 ofproto/ofproto-dpif.c         |   35 ++++--
 ofproto/ofproto-dpif.h         |    9 ++
 ofproto/ofproto.c              |    4 +
 8 files changed, 288 insertions(+), 184 deletions(-)
 create mode 100644 lib/monitor.c
 create mode 100644 lib/monitor.h

diff --git a/lib/automake.mk b/lib/automake.mk
index 9b315ee..55bd745 100644
--- a/lib/automake.mk
+++ b/lib/automake.mk
@@ -105,6 +105,8 @@ lib_libopenvswitch_la_SOURCES = \
 	lib/memory.h \
 	lib/meta-flow.c \
 	lib/meta-flow.h \
+	lib/monitor.c \
+	lib/monitor.h \
 	lib/multipath.c \
 	lib/multipath.h \
 	lib/netdev-dummy.c \
diff --git a/lib/monitor.c b/lib/monitor.c
new file mode 100644
index 0000000..e7a3acf
--- /dev/null
+++ b/lib/monitor.c
@@ -0,0 +1,150 @@
+/* Copyright (c) 2014 Nicira, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License. */
+
+#include <config.h>
+#include "monitor.h"
+
+#include "hash.h"
+#include "heap.h"
+#include "hmap.h"
+#include "util.h"
+
+/* Converts the time in millisecond to heap priority. */
+#define MSEC_TO_PRIO(TIME) (LLONG_MAX - (TIME))
+/* Converts the heap priority to time in millisecond. */
+#define PRIO_TO_MSEC(PRIO) (LLONG_MAX - (PRIO))
+
+/* Heap for ordering 'struct mport's based on session wakeup time. */
+static struct heap monitor_heap;
+
+/* Hmap that contains all "struct mport"s. */
+static struct hmap monitor_hmap = HMAP_INITIALIZER(&monitor_hmap);
+
+/* Monitored port/interface. */
+struct mport {
+    struct hmap_node hmap_node;       /* In monitor_hmap. */
+    struct heap_node heap_node;       /* In monitor_heap. */
+
+    /* Anything that user can use to identify the interface owning the
+     * monitored session.  For example, 'iface' can be the pointer to the
+     * actual monitored 'struct iface' which contains reference to bfd/cfm
+     * object. */
+    const void *iface;
+};
+
+
+/* Tries finding and returning the 'mport' from the monitor_hmap by using
+ * the hash value of 'iface'.  If there is no such 'mport', returns NULL. */
+static struct mport *
+mport_find(const void *iface)
+{
+    struct mport *node;
+
+    HMAP_FOR_EACH_WITH_HASH (node, hmap_node, hash_pointer(iface, 0),
+                             &monitor_hmap) {
+        if (node->iface == iface) {
+            return node;
+        }
+    }
+    return NULL;
+}
+
+
+/* Returns true if the 'monitor_hmap' is not empty. */
+bool
+monitor_has_session(void)
+{
+    return !hmap_is_empty(&monitor_hmap);
+}
+
+/* Creates a 'struct mport' and registers the mport to the 'monitor_heap'
+ * and 'monitor_hmap'. */
+void
+monitor_register_session(const void *iface)
+{
+    struct mport *mport = mport_find(iface);
+
+    if (!mport) {
+        mport = xzalloc(sizeof *mport);
+        mport->iface = iface;
+        heap_insert(&monitor_heap, &mport->heap_node, 0);
+        hmap_insert(&monitor_hmap, &mport->hmap_node, hash_pointer(iface, 0));
+    }
+}
+
+/* Unregisters the 'struct mport' that contains the 'iface' from
+ * 'monitor_heap' and 'monitor_hmap', and deletes the 'struct mport'. */
+void
+monitor_unregister_session(const void *iface)
+{
+    struct mport *mport = mport_find(iface);
+
+    if (mport) {
+        heap_remove(&monitor_heap, &mport->heap_node);
+        hmap_remove(&monitor_hmap, &mport->hmap_node);
+        free(mport);
+    }
+}
+
+/* Returns true if the top-of-heap session has timed out. */
+bool
+monitor_has_timedout_session(long long int now)
+{
+    long long int prio_now = MSEC_TO_PRIO(now);
+
+    if (!heap_is_empty(&monitor_heap)
+        && heap_max(&monitor_heap)->priority >= prio_now) {
+        return true;
+    }
+
+    return false;
+}
+
+/* Returns the 'iface' of the 'mport' of the top-of-heap session. */
+const void *
+monitor_get_timedout_session(void)
+{
+    struct mport *mport;
+
+    if (heap_is_empty(&monitor_heap)) {
+        return NULL;
+    }
+    mport = OBJECT_CONTAINING(heap_max(&monitor_heap), mport, heap_node);
+
+    return mport->iface;
+}
+
+/* Updates the priority of the heap node of the 'struct mport' which contains
+ * 'iface' based on the next wakeup time 'next'. */
+int
+monitor_update_session_timeout(const void *iface, long long int next)
+{
+    struct mport *mport = mport_find(iface);
+
+    heap_change(&monitor_heap, &mport->heap_node, MSEC_TO_PRIO(next));
+
+    return 0;
+}
+
+/* Returns the timeout in milliseconds of the session of top-of-heap
+ * mport. */
+long long int
+monitor_next_timeout(void)
+{
+    if (heap_is_empty(&monitor_heap)) {
+        return LLONG_MAX;
+    } else {
+        return PRIO_TO_MSEC(heap_max(&monitor_heap)->priority);
+    }
+}
diff --git a/lib/monitor.h b/lib/monitor.h
new file mode 100644
index 0000000..08020bd
--- /dev/null
+++ b/lib/monitor.h
@@ -0,0 +1,29 @@
+/* Copyright (c) 2014 Nicira, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License. */
+
+#ifndef MONITOR_H
+#define MONITOR_H 1
+
+#include <stdbool.h>
+
+bool monitor_has_session(void);
+void monitor_register_session(const void *iface);
+void monitor_unregister_session(const void *iface);
+
+bool monitor_has_timedout_session(long long int now);
+const void * monitor_get_timedout_session(void);
+int monitor_update_session_timeout(const void *iface, long long int next);
+long long int monitor_next_timeout(void);
+
+#endif /* monitor.h */
diff --git a/ofproto/ofproto-dpif-monitor.c b/ofproto/ofproto-dpif-monitor.c
index e66ebf0..5bce87b 100644
--- a/ofproto/ofproto-dpif-monitor.c
+++ b/ofproto/ofproto-dpif-monitor.c
@@ -21,10 +21,8 @@
 
 #include "bfd-ovs.h"
 #include "cfm.h"
-#include "hash.h"
-#include "heap.h"
-#include "hmap.h"
 #include "latch.h"
+#include "monitor.h"
 #include "ofpbuf.h"
 #include "ofproto-dpif.h"
 #include "ovs-thread.h"
@@ -36,27 +34,7 @@
 
 VLOG_DEFINE_THIS_MODULE(ofproto_dpif_monitor);
 
-/* Converts the time in millisecond to heap priority. */
-#define MSEC_TO_PRIO(TIME) (LLONG_MAX - (TIME))
-/* Converts the heap priority to time in millisecond. */
-#define PRIO_TO_MSEC(PRIO) (LLONG_MAX - (PRIO))
-
-/* Monitored port.  It owns references to ofport, bfd, cfm structs. */
-struct mport {
-    struct hmap_node hmap_node;       /* In monitor_hmap. */
-    struct heap_node heap_node;       /* In monitor_heap. */
-    const struct ofport_dpif *ofport; /* The corresponding ofport. */
-
-    struct cfm *cfm;                  /* Reference to cfm. */
-    struct bfd *bfd;                  /* Reference to bfd. */
-    uint8_t hw_addr[OFP_ETH_ALEN];    /* Hardware address. */
-};
-
-/* hmap that contains "struct mport"s. */
-static struct hmap monitor_hmap = HMAP_INITIALIZER(&monitor_hmap);
-
-/* heap for ordering mport based on bfd/cfm wakeup time. */
-static struct heap monitor_heap;
+struct ovs_mutex monitor_mutex = OVS_MUTEX_INITIALIZER;
 
 /* The monitor thread id. */
 static pthread_t monitor_tid;
@@ -64,104 +42,19 @@ static pthread_t monitor_tid;
 static bool monitor_running;
 
 static struct latch monitor_exit_latch;
-static struct ovs_mutex monitor_mutex = OVS_MUTEX_INITIALIZER;
-
-static void *monitor_main(void *);
-static void monitor_run(void);
-
-static void mport_register(const struct ofport_dpif *, struct bfd *,
-                           struct cfm *, uint8_t[ETH_ADDR_LEN])
-    OVS_REQUIRES(monitor_mutex);
-static void mport_unregister(const struct ofport_dpif *)
-    OVS_REQUIRES(monitor_mutex);
-static void mport_update(struct mport *, struct bfd *, struct cfm *,
-                         uint8_t[ETH_ADDR_LEN]) OVS_REQUIRES(monitor_mutex);
-static struct mport *mport_find(const struct ofport_dpif *)
-    OVS_REQUIRES(monitor_mutex);
-
-/* Tries finding and returning the 'mport' from the monitor_hmap.
- * If there is no such 'mport', returns NULL. */
-static struct mport *
-mport_find(const struct ofport_dpif *ofport) OVS_REQUIRES(monitor_mutex)
-{
-    struct mport *node;
-
-    HMAP_FOR_EACH_WITH_HASH (node, hmap_node, hash_pointer(ofport, 0),
-                             &monitor_hmap) {
-        if (node->ofport == ofport) {
-            return node;
-        }
-    }
-    return NULL;
-}
-
-/* Creates a new mport and inserts it into monitor_hmap and monitor_heap,
- * if it doesn't exist.  Otherwise, just updates its fields. */
-static void
-mport_register(const struct ofport_dpif *ofport, struct bfd *bfd,
-               struct cfm *cfm, uint8_t *hw_addr)
-    OVS_REQUIRES(monitor_mutex)
-{
-    struct mport *mport = mport_find(ofport);
-
-    if (!mport) {
-        mport = xzalloc(sizeof *mport);
-        mport->ofport = ofport;
-        hmap_insert(&monitor_hmap, &mport->hmap_node, hash_pointer(ofport, 0));
-        heap_insert(&monitor_heap, &mport->heap_node, 0);
-    }
-    mport_update(mport, bfd, cfm, hw_addr);
-}
-
-/* Removes mport from monitor_hmap and monitor_heap and frees it. */
-static void
-mport_unregister(const struct ofport_dpif *ofport)
-    OVS_REQUIRES(monitor_mutex)
-{
-    struct mport *mport = mport_find(ofport);
 
-    if (mport) {
-        mport_update(mport, NULL, NULL, NULL);
-        hmap_remove(&monitor_hmap, &mport->hmap_node);
-        heap_remove(&monitor_heap, &mport->heap_node);
-        free(mport);
-    }
-}
-
-/* Updates the fields of an existing mport struct. */
-static void
-mport_update(struct mport *mport, struct bfd *bfd, struct cfm *cfm,
-             uint8_t hw_addr[ETH_ADDR_LEN]) OVS_REQUIRES(monitor_mutex)
-{
-    ovs_assert(mport);
+static void *ofproto_dpif_monitor_main(void *);
+static void ofproto_dpif_monitor_run(void);
 
-    if (mport->cfm != cfm) {
-        cfm_unref(mport->cfm);
-        mport->cfm = cfm_ref(cfm);
-    }
-    if (mport->bfd != bfd) {
-        bfd_ovs_unref(mport->bfd);
-        mport->bfd = bfd_ovs_ref(bfd);
-    }
-    if (hw_addr && memcmp(mport->hw_addr, hw_addr, ETH_ADDR_LEN)) {
-        memcpy(mport->hw_addr, hw_addr, ETH_ADDR_LEN);
-    }
-    /* If bfd/cfm is added or reconfigured, move the mport on top of the heap
-     * so that the monitor thread can run the mport next time it wakes up. */
-    if (mport->bfd || mport->cfm) {
-        heap_change(&monitor_heap, &mport->heap_node, LLONG_MAX);
-    }
-}
 
-
 /* The 'main' function for the monitor thread. */
 static void *
-monitor_main(void * args OVS_UNUSED)
+ofproto_dpif_monitor_main(void * args OVS_UNUSED)
 {
     set_subprogram_name("monitor");
     VLOG_INFO("monitor thread created");
     while (!latch_is_set(&monitor_exit_latch)) {
-        monitor_run();
+        ofproto_dpif_monitor_run();
         latch_wait(&monitor_exit_latch);
         poll_block();
     }
@@ -177,85 +70,87 @@ monitor_main(void * args OVS_UNUSED)
  * Sends the control packets if needed.  Executes bfd and cfm periodic
  * functions (run, wait) on those mports. */
 static void
-monitor_run(void)
+ofproto_dpif_monitor_run(void)
 {
     uint32_t stub[512 / 4];
-    long long int prio_now;
     struct ofpbuf packet;
+    long long int next_timeout;
 
     ofpbuf_use_stub(&packet, stub, sizeof stub);
     ovs_mutex_lock(&monitor_mutex);
-    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)
-           && heap_max(&monitor_heap)->priority >= prio_now) {
-        long long int next_wake_time;
-        struct mport *mport;
-
-        mport = CONTAINER_OF(heap_max(&monitor_heap), struct mport, heap_node);
-        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);
+    while (monitor_has_timedout_session(time_msec())) {
+        const struct ofport_dpif *port;
+        struct bfd *bfd;
+        struct cfm *cfm;
+        uint8_t hw_addr[OFP_ETH_ALEN];
+        long long int next_session_wakeup;
+
+        port = monitor_get_timedout_session();
+        ofport_get_hwaddr(port, hw_addr);
+        bfd = ofport_get_bfd(port);
+        if (bfd) {
+            if (bfd_ovs_should_send_packet(bfd)) {
+                ofpbuf_clear(&packet);
+                bfd_ovs_put_packet(bfd, &packet, hw_addr);
+                ofproto_dpif_send_packet(port, &packet);
+            }
+            bfd_ovs_run(bfd);
+            bfd_ovs_wait(bfd);
         }
-        if (mport->bfd && bfd_ovs_should_send_packet(mport->bfd)) {
-            ofpbuf_clear(&packet);
-            bfd_ovs_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_ovs_run(mport->bfd);
-            bfd_ovs_wait(mport->bfd);
+
+        cfm = ofport_get_cfm(port);
+        if (cfm) {
+            if (cfm && cfm_should_send_ccm(cfm)) {
+                ofpbuf_clear(&packet);
+                cfm_compose_ccm(cfm, &packet, hw_addr);
+                ofproto_dpif_send_packet(port, &packet);
+            }
+            cfm_run(cfm);
+            cfm_wait(cfm);
         }
+
         /* Computes the next wakeup time for this mport. */
-        next_wake_time = MIN(bfd_ovs_wake_time(mport->bfd),
-                             cfm_wake_time(mport->cfm));
-        heap_change(&monitor_heap, &mport->heap_node,
-                    MSEC_TO_PRIO(next_wake_time));
+        next_session_wakeup = MIN(bfd_ovs_wake_time(bfd),
+                                  cfm_wake_time(cfm));
+        monitor_update_session_timeout(port, next_session_wakeup);
     }
 
     /* 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;
+    poll_timer_wait_until(MIN(next_timeout, monitor_next_timeout()));
 
-        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);
 }
 
 
-/* Creates the mport in monitor module if either bfd or cfm
- * is configured.  Otherwise, deletes the mport.
+/* Registers the 'ofport' in monitor module if either bfd or cfm
+ * is configured.  Otherwise, unregisters the 'ofport'.
+ *
  * 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])
+ofproto_dpif_monitor_port_update(const struct ofport_dpif *ofport)
+    OVS_REQUIRES(monitor_mutex)
 {
-    ovs_mutex_lock(&monitor_mutex);
+    struct bfd *bfd = ofport_get_bfd(ofport);
+    struct cfm *cfm = ofport_get_cfm(ofport);
+
     if (!cfm && !bfd) {
-        mport_unregister(ofport);
+        monitor_unregister_session(ofport);
     } else {
-        mport_register(ofport, bfd, cfm, hw_addr);
+        monitor_register_session(ofport);
+        monitor_update_session_timeout(ofport, 0);
     }
-    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))  {
+    /* If the monitor thread is not running and the monitor module
+     * has sessions, starts the thread.  If it is running and the
+     * monitor module do not have session, terminates the thread. */
+    if (!monitor_running && monitor_has_session())  {
         latch_init(&monitor_exit_latch);
-        xpthread_create(&monitor_tid, NULL, monitor_main, NULL);
+        xpthread_create(&monitor_tid, NULL, ofproto_dpif_monitor_main, NULL);
         monitor_running = true;
-    } else if (monitor_running && hmap_is_empty(&monitor_hmap))  {
+    } else if (monitor_running && !monitor_has_session())  {
         latch_set(&monitor_exit_latch);
         xpthread_join(monitor_tid, NULL);
         latch_destroy(&monitor_exit_latch);
@@ -263,9 +158,9 @@ ofproto_dpif_monitor_port_update(const struct ofport_dpif *ofport,
     }
 }
 
-/* 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. */
+/* Schedule the session for 'ofport' to send soon.  This is
+ * necessary when for example, bfd POLL is received and the
+ * session should immediately send FINAL back. */
 void
 ofproto_dpif_monitor_port_send_soon_safe(const struct ofport_dpif *ofport)
 {
@@ -278,10 +173,5 @@ void
 ofproto_dpif_monitor_port_send_soon(const struct ofport_dpif *ofport)
     OVS_REQUIRES(monitor_mutex)
 {
-    struct mport *mport;
-
-    mport = mport_find(ofport);
-    if (mport) {
-        heap_change(&monitor_heap, &mport->heap_node, LLONG_MAX);
-    }
+    monitor_update_session_timeout(ofport, 0);
 }
diff --git a/ofproto/ofproto-dpif-monitor.h b/ofproto/ofproto-dpif-monitor.h
index 1f6be5c..b18bcb1 100644
--- a/ofproto/ofproto-dpif-monitor.h
+++ b/ofproto/ofproto-dpif-monitor.h
@@ -23,11 +23,12 @@ struct bfd;
 struct cfm;
 struct ofport_dpif;
 
+extern struct ovs_mutex monitor_mutex;
+
 void ofproto_dpif_monitor_port_send_soon(const struct ofport_dpif *);
 void ofproto_dpif_monitor_port_send_soon_safe(const struct ofport_dpif *);
 
-void ofproto_dpif_monitor_port_update(const struct ofport_dpif *,
-                                      struct bfd *, struct cfm *,
-                                      uint8_t[OFP_ETH_ALEN]);
+void ofproto_dpif_monitor_port_update(const struct ofport_dpif *)
+    OVS_REQUIRES(monitor_mutex);
 
 #endif /* ofproto-dpif-monitor.h */
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index 61f133f..9735589 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -1577,10 +1577,6 @@ port_modified(struct ofport *port_)
         cfm_set_netdev(port->cfm, port->up.netdev);
     }
 
-
-    ofproto_dpif_monitor_port_update(port, port->bfd, port->cfm,
-                                     port->up.pp.hw_addr);
-
     if (port->is_tunnel && tnl_port_reconfigure(port, port->up.netdev,
                                                 port->odp_port)) {
         ofproto_dpif_cast(port->up.ofproto)->backer->need_revalidate =
@@ -1673,6 +1669,7 @@ set_cfm(struct ofport *ofport_, const struct cfm_settings *s)
     struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
     int error = 0;
 
+    ovs_mutex_lock(&monitor_mutex);
     if (s) {
         if (!ofport->cfm) {
             struct ofproto_dpif *ofproto;
@@ -1692,11 +1689,18 @@ set_cfm(struct ofport *ofport_, const struct cfm_settings *s)
     cfm_unref(ofport->cfm);
     ofport->cfm = NULL;
 out:
-    ofproto_dpif_monitor_port_update(ofport, ofport->bfd, ofport->cfm,
-                                     ofport->up.pp.hw_addr);
+    ofproto_dpif_monitor_port_update(ofport);
+    ovs_mutex_unlock(&monitor_mutex);
+
     return error;
 }
 
+struct cfm *
+ofport_get_cfm(const struct ofport_dpif *ofport) OVS_REQUIRES(monitor_mutex)
+{
+   return ofport->cfm;
+}
+
 static bool
 get_cfm_status(const struct ofport *ofport_,
                struct ofproto_cfm_status *status)
@@ -1722,17 +1726,25 @@ set_bfd(struct ofport *ofport_, const struct smap *cfg)
     struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
     struct bfd *old;
 
+    ovs_mutex_lock(&monitor_mutex);
     old = ofport->bfd;
     ofport->bfd = bfd_ovs_configure(old, netdev_get_name(ofport->up.netdev),
                                    cfg);
     if (ofport->bfd != old) {
         ofproto->backer->need_revalidate = REV_RECONFIGURE;
     }
-    ofproto_dpif_monitor_port_update(ofport, ofport->bfd, ofport->cfm,
-                                     ofport->up.pp.hw_addr);
+    ofproto_dpif_monitor_port_update(ofport);
+    ovs_mutex_unlock(&monitor_mutex);
+
     return 0;
 }
 
+struct bfd *
+ofport_get_bfd(const struct ofport_dpif *ofport) OVS_REQUIRES(monitor_mutex)
+{
+    return ofport->bfd;
+}
+
 static int
 get_bfd_status(struct ofport *ofport_, struct smap *smap)
 {
@@ -1740,6 +1752,13 @@ get_bfd_status(struct ofport *ofport_, struct smap *smap)
 
     return bfd_ovs_get_status(ofport->bfd, smap);
 }
+
+void
+ofport_get_hwaddr(const struct ofport_dpif *ofport, uint8_t hw_addr[8])
+{
+    memcpy(hw_addr, ofport->up.pp.hw_addr, ETH_ADDR_LEN);
+}
+
 
 /* Spanning Tree. */
 
diff --git a/ofproto/ofproto-dpif.h b/ofproto/ofproto-dpif.h
index d09e285..77f4476 100644
--- a/ofproto/ofproto-dpif.h
+++ b/ofproto/ofproto-dpif.h
@@ -36,6 +36,7 @@ struct OVS_LOCKABLE group_dpif;
 
 /* For lock annotation below only. */
 extern struct ovs_rwlock xlate_rwlock;
+extern struct ovs_mutex monitor_mutex;
 
 /* Ofproto-dpif -- DPIF based ofproto implementation.
  *
@@ -121,4 +122,12 @@ void ofproto_dpif_flow_mod(struct ofproto_dpif *, struct ofputil_flow_mod *);
 
 struct ofport_dpif *odp_port_to_ofport(const struct dpif_backer *, odp_port_t);
 
+/* Used by ofproto-dpif-monitor */
+struct bfd * ofport_get_bfd(const struct ofport_dpif *)
+    OVS_REQUIRES(monitor_mutex);
+struct cfm * ofport_get_cfm(const struct ofport_dpif *)
+    OVS_REQUIRES(monitor_mutex);
+void ofport_get_hwaddr(const struct ofport_dpif *, uint8_t hw_addr[8])
+    OVS_REQUIRES(monitor_mutex);
+
 #endif /* ofproto-dpif.h */
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index 884e63e..51cfa26 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -2239,6 +2239,8 @@ ofport_remove_with_name(struct ofproto *ofproto, const char *name)
     }
 }
 
+extern struct ovs_mutex monitor_mutex;
+
 /* Updates 'port' with new 'pp' description.
  *
  * Does not handle a name or port number change.  The caller must implement
@@ -2246,7 +2248,9 @@ ofport_remove_with_name(struct ofproto *ofproto, const char *name)
 static void
 ofport_modified(struct ofport *port, struct ofputil_phy_port *pp)
 {
+    ovs_mutex_lock(&monitor_mutex);
     memcpy(port->pp.hw_addr, pp->hw_addr, ETH_ADDR_LEN);
+    ovs_mutex_unlock(&monitor_mutex);
     port->pp.config = ((port->pp.config & ~OFPUTIL_PC_PORT_DOWN)
                         | (pp->config & OFPUTIL_PC_PORT_DOWN));
     port->pp.state = ((port->pp.state & ~OFPUTIL_PS_LINK_DOWN)
-- 
1.7.9.5




More information about the dev mailing list