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 <al...@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 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev