summaryrefslogtreecommitdiff
path: root/vswitchd
diff options
context:
space:
mode:
authorThadeu Lima de Souza Cascardo <cascardo@redhat.com>2016-10-25 15:44:43 -0200
committerBen Pfaff <blp@ovn.org>2016-10-31 11:11:06 -0700
commit0612d7393fc6e04ecb976c2b999624aad607f8f3 (patch)
treee94cec63f6a936fb9724f10ef4e0916d158c49b7 /vswitchd
parent01dee7de6661bb2cd5ff20085dbfb7c1d8084d01 (diff)
downloadopenvswitch-0612d7393fc6e04ecb976c2b999624aad607f8f3.tar.gz
ifnotifier: do not wake up when there is no db connection
When bridge uses the interface notifier, it wakes up until a reconfiguration takes place. However, if there is no connection or a lock contention to the database, the check for reconfiguration will not take place. This uses a seq and only seq_wait when checking for the interfaces change. This is easily reproduced by starting ovs-vswitchd without starting ovsdb-server, and then creating a new system interface, like using 'ip link add type veth'. ovs-vswitchd will then consume 100% CPU. Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@redhat.com> Signed-off-by: Ben Pfaff <blp@ovn.org>
Diffstat (limited to 'vswitchd')
-rw-r--r--vswitchd/bridge.c30
1 files changed, 22 insertions, 8 deletions
diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
index ff5d86fe5..d78c48e18 100644
--- a/vswitchd/bridge.c
+++ b/vswitchd/bridge.c
@@ -223,7 +223,8 @@ static long long int aa_refresh_timer = LLONG_MIN;
* will be reconfigured.
*/
static struct if_notifier *ifnotifier;
-static bool ifaces_changed = false;
+static struct seq *ifaces_changed;
+static uint64_t last_ifaces_changed;
static void add_del_bridges(const struct ovsrec_open_vswitch *);
static void bridge_run__(void);
@@ -368,7 +369,21 @@ bridge_init_ofproto(const struct ovsrec_open_vswitch *cfg)
static void
if_change_cb(void *aux OVS_UNUSED)
{
- ifaces_changed = true;
+ seq_change(ifaces_changed);
+}
+
+static bool
+if_notifier_changed(struct if_notifier *notifier OVS_UNUSED)
+{
+ uint64_t new_seq;
+ bool changed = false;
+ new_seq = seq_read(ifaces_changed);
+ if (new_seq != last_ifaces_changed) {
+ changed = true;
+ last_ifaces_changed = new_seq;
+ }
+ seq_wait(ifaces_changed, last_ifaces_changed);
+ return changed;
}
/* Public functions. */
@@ -475,6 +490,8 @@ bridge_init(const char *remote)
stp_init();
lldp_init();
rstp_init();
+ ifaces_changed = seq_create();
+ last_ifaces_changed = seq_read(ifaces_changed);
ifnotifier = if_notifier_create(if_change_cb, NULL);
}
@@ -484,6 +501,7 @@ bridge_exit(void)
struct bridge *br, *next_br;
if_notifier_destroy(ifnotifier);
+ seq_destroy(ifaces_changed);
HMAP_FOR_EACH_SAFE (br, next_br, node, &all_bridges) {
bridge_destroy(br, false);
}
@@ -2929,11 +2947,10 @@ bridge_run(void)
stream_ssl_set_ca_cert_file(ssl->ca_cert, ssl->bootstrap_ca_cert);
}
- if (ovsdb_idl_get_seqno(idl) != idl_seqno || ifaces_changed) {
+ if (ovsdb_idl_get_seqno(idl) != idl_seqno ||
+ if_notifier_changed(ifnotifier)) {
struct ovsdb_idl_txn *txn;
- ifaces_changed = false;
-
idl_seqno = ovsdb_idl_get_seqno(idl);
txn = ovsdb_idl_txn_create(idl);
bridge_reconfigure(cfg ? cfg : &null_cfg);
@@ -2991,9 +3008,6 @@ bridge_wait(void)
}
if_notifier_wait();
- if (ifaces_changed) {
- poll_immediate_wake();
- }
sset_init(&types);
ofproto_enumerate_types(&types);