bridge: Reconfigure when system interfaces change.
authorThadeu Lima de Souza Cascardo <cascardo@redhat.com>
Fri, 31 Jul 2015 17:35:02 +0000 (14:35 -0300)
committerBen Pfaff <blp@nicira.com>
Sun, 2 Aug 2015 19:04:06 +0000 (12:04 -0700)
Whenever system interfaces are removed, added or change state, reconfigure
bridge. This allows late interfaces to be added to the datapath when they are
added to the system after ovs-vswitchd is started.

Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@redhat.com>
Signed-off-by: Ben Pfaff <blp@nicira.com>
lib/automake.mk
lib/if-notifier-bsd.c [new file with mode: 0644]
lib/if-notifier-stub.c [new file with mode: 0644]
lib/if-notifier.c [new file with mode: 0644]
lib/if-notifier.h [new file with mode: 0644]
vswitchd/bridge.c

index faca968..a7e7b9b 100644 (file)
@@ -292,6 +292,7 @@ lib_libopenvswitch_la_SOURCES += \
        lib/getrusage-windows.c \
        lib/latch-windows.c \
        lib/route-table-stub.c \
+       lib/if-notifier-stub.c \
        lib/strsep.c
 else
 lib_libopenvswitch_la_SOURCES += \
@@ -338,6 +339,8 @@ if LINUX
 lib_libopenvswitch_la_SOURCES += \
        lib/dpif-netlink.c \
        lib/dpif-netlink.h \
+       lib/if-notifier.c \
+       lib/if-notifier.h \
        lib/netdev-linux.c \
        lib/netdev-linux.h \
        lib/netlink-notifier.c \
@@ -379,11 +382,13 @@ endif
 
 if ESX
 lib_libopenvswitch_la_SOURCES += \
-        lib/route-table-stub.c
+       lib/route-table-stub.c \
+       lib/if-notifier-stub.c
 endif
 
 if HAVE_IF_DL
 lib_libopenvswitch_la_SOURCES += \
+       lib/if-notifier-bsd.c \
        lib/netdev-bsd.c \
        lib/rtbsd.c \
        lib/rtbsd.h \
diff --git a/lib/if-notifier-bsd.c b/lib/if-notifier-bsd.c
new file mode 100644 (file)
index 0000000..b57b4b1
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2015 Red Hat, 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 "if-notifier.h"
+#include "rtbsd.h"
+#include "util.h"
+
+struct if_notifier {
+    struct rtbsd_notifier notifier;
+    if_notify_func *cb;
+    void *aux;
+};
+
+static void
+if_notifier_cb(const struct rtbsd_change *change OVS_UNUSED, void *aux)
+{
+    struct if_notifier *notifier;
+    notifier = aux;
+    notifier->cb(notifier->aux);
+}
+
+struct if_notifier *
+if_notifier_create(if_notify_func *cb, void *aux)
+{
+    struct if_notifier *notifier;
+    int ret;
+    notifier = xzalloc(sizeof *notifier);
+    notifier->cb = cb;
+    notifier->aux = aux;
+    ret = rtbsd_notifier_register(&notifier->notifier, if_notifier_cb,
+                                  notifier);
+    if (ret) {
+        free(notifier);
+        return NULL;
+    }
+    return notifier;
+}
+
+void
+if_notifier_destroy(struct if_notifier *notifier)
+{
+    if (notifier) {
+        rtbsd_notifier_unregister(&notifier->notifier);
+        free(notifier);
+    }
+}
+
+void
+if_notifier_run(void)
+{
+    rtbsd_notifier_run();
+}
+
+void
+if_notifier_wait(void)
+{
+    rtbsd_notifier_wait();
+}
diff --git a/lib/if-notifier-stub.c b/lib/if-notifier-stub.c
new file mode 100644 (file)
index 0000000..a5b529a
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015 Red Hat, 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 "if-notifier.h"
+#include <stddef.h>
+#include "compiler.h"
+
+struct if_notifier *
+if_notifier_create(if_notify_func *cb OVS_UNUSED, void *aux OVS_UNUSED)
+{
+    return NULL;
+}
+
+void
+if_notifier_destroy(struct if_notifier *notifier OVS_UNUSED)
+{
+}
+
+void
+if_notifier_run(void)
+{
+}
+
+void
+if_notifier_wait(void)
+{
+}
diff --git a/lib/if-notifier.c b/lib/if-notifier.c
new file mode 100644 (file)
index 0000000..9a64f9b
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2015 Red Hat, 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 "if-notifier.h"
+#include "rtnetlink.h"
+#include "util.h"
+
+struct if_notifier {
+    struct nln_notifier *notifier;
+    if_notify_func *cb;
+    void *aux;
+};
+
+static void
+if_notifier_cb(const struct rtnetlink_change *change OVS_UNUSED, void *aux)
+{
+    struct if_notifier *notifier;
+    notifier = aux;
+    notifier->cb(notifier->aux);
+}
+
+struct if_notifier *
+if_notifier_create(if_notify_func *cb, void *aux)
+{
+    struct if_notifier *notifier;
+    notifier = xmalloc(sizeof *notifier);
+    notifier->cb = cb;
+    notifier->aux = aux;
+    notifier->notifier = rtnetlink_notifier_create(if_notifier_cb, notifier);
+    return notifier;
+}
+
+void
+if_notifier_destroy(struct if_notifier *notifier)
+{
+    if (notifier) {
+        rtnetlink_notifier_destroy(notifier->notifier);
+        free(notifier);
+    }
+}
+
+void
+if_notifier_run(void)
+{
+    rtnetlink_run();
+}
+
+void
+if_notifier_wait(void)
+{
+    rtnetlink_wait();
+}
diff --git a/lib/if-notifier.h b/lib/if-notifier.h
new file mode 100644 (file)
index 0000000..259138f
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2015 Red Hat, 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 IF_NOTIFIER_H
+#define IF_NOTIFIER_H 1
+
+struct if_notifier;
+
+typedef void if_notify_func(void *aux);
+
+struct if_notifier *if_notifier_create(if_notify_func *, void *aux);
+void if_notifier_destroy(struct if_notifier *);
+
+void if_notifier_run(void);
+void if_notifier_wait(void);
+
+#endif  /* if-notifier.h */
index 39d4cb3..f021360 100644 (file)
@@ -48,6 +48,7 @@
 #include "ofproto/ofproto.h"
 #include "ovs-numa.h"
 #include "poll-loop.h"
+#include "if-notifier.h"
 #include "seq.h"
 #include "sha1.h"
 #include "shash.h"
@@ -217,6 +218,12 @@ static long long int stats_timer = LLONG_MIN;
 #define AA_REFRESH_INTERVAL (1000) /* In milliseconds. */
 static long long int aa_refresh_timer = LLONG_MIN;
 
+/* Whenever system interfaces are added, removed or change state, the bridge
+ * will be reconfigured.
+ */
+static struct if_notifier *ifnotifier;
+static bool ifaces_changed = false;
+
 static void add_del_bridges(const struct ovsrec_open_vswitch *);
 static void bridge_run__(void);
 static void bridge_create(const struct ovsrec_bridge *);
@@ -375,6 +382,12 @@ bridge_init_ofproto(const struct ovsrec_open_vswitch *cfg)
     shash_destroy_free_data(&iface_hints);
     initialized = true;
 }
+
+static void
+if_change_cb(void *aux OVS_UNUSED)
+{
+    ifaces_changed = true;
+}
 \f
 /* Public functions. */
 
@@ -478,6 +491,7 @@ bridge_init(const char *remote)
     stp_init();
     lldp_init();
     rstp_init();
+    ifnotifier = if_notifier_create(if_change_cb, NULL);
 }
 
 void
@@ -485,6 +499,7 @@ bridge_exit(void)
 {
     struct bridge *br, *next_br;
 
+    if_notifier_destroy(ifnotifier);
     HMAP_FOR_EACH_SAFE (br, next_br, node, &all_bridges) {
         bridge_destroy(br);
     }
@@ -2877,6 +2892,8 @@ bridge_run(void)
 
     ovsdb_idl_run(idl);
 
+    if_notifier_run();
+
     if (ovsdb_idl_is_lock_contended(idl)) {
         static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
         struct bridge *br, *next_br;
@@ -2943,9 +2960,12 @@ bridge_run(void)
         }
     }
 
-    if (ovsdb_idl_get_seqno(idl) != idl_seqno || vlan_splinters_changed) {
+    if (ovsdb_idl_get_seqno(idl) != idl_seqno || vlan_splinters_changed
+        || ifaces_changed) {
         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);
@@ -3002,6 +3022,11 @@ bridge_wait(void)
         ovsdb_idl_txn_wait(daemonize_txn);
     }
 
+    if_notifier_wait();
+    if (ifaces_changed) {
+        poll_immediate_wake();
+    }
+
     sset_init(&types);
     ofproto_enumerate_types(&types);
     SSET_FOR_EACH (type, &types) {