[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