aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Pfaff <blp@nicira.com>2015-10-01 09:37:53 -0700
committerBen Pfaff <blp@nicira.com>2015-10-16 20:15:08 -0700
commita1d210a64f2b5a2661256aa50c200bf6ac1f3373 (patch)
tree8dc6e066e203f9944a9cbcdbf47390a7b2939399
parent69a832cfc033338101db192c6db0aa07397acaaf (diff)
ovn-controller: Factor patch port management into new "patch" module.
Upcoming patches will introduce new extensive use of patch ports and it seems reasonable to put it into its own file. This is mostly code motion. Code changes are limited to those necessary to make the separated code compile, except for renaming init_bridge_mappings() to patch_run(). Signed-off-by: Ben Pfaff <blp@nicira.com> Acked-by: Justin Pettit <jpettit@nicira.com>
-rw-r--r--ovn/controller/automake.mk2
-rw-r--r--ovn/controller/ovn-controller.c213
-rw-r--r--ovn/controller/ovn-controller.h3
-rw-r--r--ovn/controller/patch.c232
-rw-r--r--ovn/controller/patch.h30
5 files changed, 270 insertions, 210 deletions
diff --git a/ovn/controller/automake.mk b/ovn/controller/automake.mk
index 9c9142008..fec9bf17b 100644
--- a/ovn/controller/automake.mk
+++ b/ovn/controller/automake.mk
@@ -10,6 +10,8 @@ ovn_controller_ovn_controller_SOURCES = \
ovn/controller/lflow.h \
ovn/controller/ofctrl.c \
ovn/controller/ofctrl.h \
+ ovn/controller/patch.c \
+ ovn/controller/patch.h \
ovn/controller/ovn-controller.c \
ovn/controller/ovn-controller.h \
ovn/controller/physical.c \
diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c
index 3bd072aa3..3f29b257f 100644
--- a/ovn/controller/ovn-controller.c
+++ b/ovn/controller/ovn-controller.c
@@ -44,6 +44,7 @@
#include "binding.h"
#include "chassis.h"
#include "encaps.h"
+#include "patch.h"
#include "physical.h"
#include "lflow.h"
@@ -87,7 +88,7 @@ get_tunnel_type(const char *name)
return 0;
}
-static const struct ovsrec_bridge *
+const struct ovsrec_bridge *
get_bridge(struct ovsdb_idl *ovs_idl, const char *br_name)
{
const struct ovsrec_bridge *br;
@@ -169,214 +170,6 @@ get_chassis_id(const struct ovsdb_idl *ovs_idl)
return cfg ? smap_get(&cfg->external_ids, "system-id") : NULL;
}
-static char *
-patch_port_name(const struct ovsrec_bridge *b1, const struct ovsrec_bridge *b2)
-{
- return xasprintf("patch-%s-to-%s", b1->name, b2->name);
-}
-
-/*
- * Return true if the port is a patch port from b1 to b2
- */
-static bool
-match_patch_port(const struct ovsrec_port *port,
- const struct ovsrec_bridge *b1,
- const struct ovsrec_bridge *b2)
-{
- struct ovsrec_interface *iface;
- size_t i;
- char *peer_port_name;
- bool res = false;
-
- peer_port_name = patch_port_name(b2, b1);
-
- for (i = 0; i < port->n_interfaces; i++) {
- iface = port->interfaces[i];
- if (strcmp(iface->type, "patch")) {
- continue;
- }
- const char *peer;
- peer = smap_get(&iface->options, "peer");
- if (peer && !strcmp(peer, peer_port_name)) {
- res = true;
- break;
- }
- }
-
- free(peer_port_name);
-
- return res;
-}
-
-static void
-create_patch_port(struct controller_ctx *ctx,
- const char *network,
- const struct ovsrec_bridge *b1,
- const struct ovsrec_bridge *b2)
-{
- if (!ctx->ovs_idl_txn) {
- return;
- }
-
- char *port_name = patch_port_name(b1, b2);
- char *peer_port_name = patch_port_name(b2, b1);
-
- ovsdb_idl_txn_add_comment(ctx->ovs_idl_txn,
- "ovn-controller: creating patch port '%s' from '%s' to '%s'",
- port_name, b1->name, b2->name);
-
- struct ovsrec_interface *iface;
- iface = ovsrec_interface_insert(ctx->ovs_idl_txn);
- ovsrec_interface_set_name(iface, port_name);
- ovsrec_interface_set_type(iface, "patch");
- const struct smap options = SMAP_CONST1(&options, "peer", peer_port_name);
- ovsrec_interface_set_options(iface, &options);
-
- struct ovsrec_port *port;
- port = ovsrec_port_insert(ctx->ovs_idl_txn);
- ovsrec_port_set_name(port, port_name);
- ovsrec_port_set_interfaces(port, &iface, 1);
- const struct smap ids = SMAP_CONST1(&ids, "ovn-patch-port", network);
- ovsrec_port_set_external_ids(port, &ids);
-
- struct ovsrec_port **ports;
- ports = xmalloc(sizeof *ports * (b1->n_ports + 1));
- memcpy(ports, b1->ports, sizeof *ports * b1->n_ports);
- ports[b1->n_ports] = port;
- ovsrec_bridge_verify_ports(b1);
- ovsrec_bridge_set_ports(b1, ports, b1->n_ports + 1);
-
- free(ports);
- free(port_name);
- free(peer_port_name);
-}
-
-static void
-create_patch_ports(struct controller_ctx *ctx,
- const char *network,
- struct shash *existing_ports,
- const struct ovsrec_bridge *b1,
- const struct ovsrec_bridge *b2)
-{
- size_t i;
-
- for (i = 0; i < b1->n_ports; i++) {
- if (match_patch_port(b1->ports[i], b1, b2)) {
- /* Patch port already exists on b1 */
- shash_find_and_delete(existing_ports, b1->ports[i]->name);
- break;
- }
- }
- if (i == b1->n_ports) {
- create_patch_port(ctx, network, b1, b2);
- }
-}
-
-static void
-init_existing_ports(struct controller_ctx *ctx,
- struct shash *existing_ports)
-{
- const struct ovsrec_port *port;
-
- OVSREC_PORT_FOR_EACH (port, ctx->ovs_idl) {
- if (smap_get(&port->external_ids, "ovn-patch-port")) {
- shash_add(existing_ports, port->name, port);
- }
- }
-}
-
-static void
-remove_port(struct controller_ctx *ctx,
- const struct ovsrec_port *port)
-{
- const struct ovsrec_bridge *bridge;
-
- /* We know the port we want to delete, but we have to find the bridge its on
- * to do so. Note this only runs on a config change that should be pretty
- * rare. */
- OVSREC_BRIDGE_FOR_EACH (bridge, ctx->ovs_idl) {
- size_t i;
- for (i = 0; i < bridge->n_ports; i++) {
- if (bridge->ports[i] != port) {
- continue;
- }
- struct ovsrec_port **new_ports;
- new_ports = xmemdup(bridge->ports,
- sizeof *new_ports * (bridge->n_ports - 1));
- if (i != bridge->n_ports - 1) {
- /* Removed port was not last */
- new_ports[i] = bridge->ports[bridge->n_ports - 1];
- }
- ovsrec_bridge_verify_ports(bridge);
- ovsrec_bridge_set_ports(bridge, new_ports, bridge->n_ports - 1);
- free(new_ports);
- ovsrec_port_delete(port);
- return;
- }
- }
-}
-
-static void
-parse_bridge_mappings(struct controller_ctx *ctx,
- const struct ovsrec_bridge *br_int,
- const char *mappings_cfg)
-{
- struct shash existing_ports = SHASH_INITIALIZER(&existing_ports);
- init_existing_ports(ctx, &existing_ports);
-
- char *cur, *next, *start;
- next = start = xstrdup(mappings_cfg);
- while ((cur = strsep(&next, ",")) && *cur) {
- char *network, *bridge = cur;
- const struct ovsrec_bridge *ovs_bridge;
-
- network = strsep(&bridge, ":");
- if (!bridge || !*network || !*bridge) {
- VLOG_ERR("Invalid ovn-bridge-mappings configuration: '%s'",
- mappings_cfg);
- break;
- }
-
- ovs_bridge = get_bridge(ctx->ovs_idl, bridge);
- if (!ovs_bridge) {
- VLOG_WARN("Bridge '%s' not found for network '%s'",
- bridge, network);
- continue;
- }
-
- create_patch_ports(ctx, network, &existing_ports, br_int, ovs_bridge);
- create_patch_ports(ctx, network, &existing_ports, ovs_bridge, br_int);
- }
- free(start);
-
- /* Any ports left in existing_ports are related to configuration that has
- * been removed, so we should delete the ports now. */
- struct shash_node *port_node, *port_next_node;
- SHASH_FOR_EACH_SAFE (port_node, port_next_node, &existing_ports) {
- struct ovsrec_port *port = port_node->data;
- shash_delete(&existing_ports, port_node);
- remove_port(ctx, port);
- }
- shash_destroy(&existing_ports);
-}
-
-static void
-init_bridge_mappings(struct controller_ctx *ctx,
- const struct ovsrec_bridge *br_int)
-{
- const char *mappings_cfg = "";
- const struct ovsrec_open_vswitch *cfg;
-
- cfg = ovsrec_open_vswitch_first(ctx->ovs_idl);
- if (cfg) {
- mappings_cfg = smap_get(&cfg->external_ids, "ovn-bridge-mappings");
- if (!mappings_cfg) {
- mappings_cfg = "";
- }
- }
- parse_bridge_mappings(ctx, br_int, mappings_cfg);
-}
-
/* Retrieves the OVN Southbound remote location from the
* "external-ids:ovn-remote" key in 'ovs_idl' and returns a copy of it.
*
@@ -487,7 +280,7 @@ main(int argc, char *argv[])
/* Map bridges to local nets from ovn-bridge-mappings */
if (br_int) {
- init_bridge_mappings(&ctx, br_int);
+ patch_run(&ctx, br_int);
}
if (chassis_id) {
diff --git a/ovn/controller/ovn-controller.h b/ovn/controller/ovn-controller.h
index ded7fce95..8c437a729 100644
--- a/ovn/controller/ovn-controller.h
+++ b/ovn/controller/ovn-controller.h
@@ -31,6 +31,9 @@ struct controller_ctx {
struct ovsdb_idl_txn *ovs_idl_txn;
};
+const struct ovsrec_bridge *get_bridge(struct ovsdb_idl *,
+ const char *br_name);
+
const struct sbrec_chassis *get_chassis(struct ovsdb_idl *,
const char *chassis_id);
diff --git a/ovn/controller/patch.c b/ovn/controller/patch.c
new file mode 100644
index 000000000..0d192fa89
--- /dev/null
+++ b/ovn/controller/patch.c
@@ -0,0 +1,232 @@
+/* Copyright (c) 2015 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 "patch.h"
+
+#include "hash.h"
+#include "lib/vswitch-idl.h"
+#include "openvswitch/vlog.h"
+#include "ovn-controller.h"
+
+VLOG_DEFINE_THIS_MODULE(patch);
+
+static char *
+patch_port_name(const struct ovsrec_bridge *b1, const struct ovsrec_bridge *b2)
+{
+ return xasprintf("patch-%s-to-%s", b1->name, b2->name);
+}
+
+/*
+ * Return true if the port is a patch port from b1 to b2
+ */
+static bool
+match_patch_port(const struct ovsrec_port *port,
+ const struct ovsrec_bridge *b1,
+ const struct ovsrec_bridge *b2)
+{
+ struct ovsrec_interface *iface;
+ size_t i;
+ char *peer_port_name;
+ bool res = false;
+
+ peer_port_name = patch_port_name(b2, b1);
+
+ for (i = 0; i < port->n_interfaces; i++) {
+ iface = port->interfaces[i];
+ if (strcmp(iface->type, "patch")) {
+ continue;
+ }
+ const char *peer;
+ peer = smap_get(&iface->options, "peer");
+ if (peer && !strcmp(peer, peer_port_name)) {
+ res = true;
+ break;
+ }
+ }
+
+ free(peer_port_name);
+
+ return res;
+}
+
+static void
+create_patch_port(struct controller_ctx *ctx,
+ const char *network,
+ const struct ovsrec_bridge *b1,
+ const struct ovsrec_bridge *b2)
+{
+ if (!ctx->ovs_idl_txn) {
+ return;
+ }
+
+ char *port_name = patch_port_name(b1, b2);
+ char *peer_port_name = patch_port_name(b2, b1);
+
+ ovsdb_idl_txn_add_comment(ctx->ovs_idl_txn,
+ "ovn-controller: creating patch port '%s' from '%s' to '%s'",
+ port_name, b1->name, b2->name);
+
+ struct ovsrec_interface *iface;
+ iface = ovsrec_interface_insert(ctx->ovs_idl_txn);
+ ovsrec_interface_set_name(iface, port_name);
+ ovsrec_interface_set_type(iface, "patch");
+ const struct smap options = SMAP_CONST1(&options, "peer", peer_port_name);
+ ovsrec_interface_set_options(iface, &options);
+
+ struct ovsrec_port *port;
+ port = ovsrec_port_insert(ctx->ovs_idl_txn);
+ ovsrec_port_set_name(port, port_name);
+ ovsrec_port_set_interfaces(port, &iface, 1);
+ const struct smap ids = SMAP_CONST1(&ids, "ovn-patch-port", network);
+ ovsrec_port_set_external_ids(port, &ids);
+
+ struct ovsrec_port **ports;
+ ports = xmalloc(sizeof *ports * (b1->n_ports + 1));
+ memcpy(ports, b1->ports, sizeof *ports * b1->n_ports);
+ ports[b1->n_ports] = port;
+ ovsrec_bridge_verify_ports(b1);
+ ovsrec_bridge_set_ports(b1, ports, b1->n_ports + 1);
+
+ free(ports);
+ free(port_name);
+ free(peer_port_name);
+}
+
+static void
+create_patch_ports(struct controller_ctx *ctx,
+ const char *network,
+ struct shash *existing_ports,
+ const struct ovsrec_bridge *b1,
+ const struct ovsrec_bridge *b2)
+{
+ size_t i;
+
+ for (i = 0; i < b1->n_ports; i++) {
+ if (match_patch_port(b1->ports[i], b1, b2)) {
+ /* Patch port already exists on b1 */
+ shash_find_and_delete(existing_ports, b1->ports[i]->name);
+ break;
+ }
+ }
+ if (i == b1->n_ports) {
+ create_patch_port(ctx, network, b1, b2);
+ }
+}
+
+static void
+init_existing_ports(struct controller_ctx *ctx,
+ struct shash *existing_ports)
+{
+ const struct ovsrec_port *port;
+
+ OVSREC_PORT_FOR_EACH (port, ctx->ovs_idl) {
+ if (smap_get(&port->external_ids, "ovn-patch-port")) {
+ shash_add(existing_ports, port->name, port);
+ }
+ }
+}
+
+static void
+remove_port(struct controller_ctx *ctx,
+ const struct ovsrec_port *port)
+{
+ const struct ovsrec_bridge *bridge;
+
+ /* We know the port we want to delete, but we have to find the bridge its
+ * on to do so. Note this only runs on a config change that should be
+ * pretty rare. */
+ OVSREC_BRIDGE_FOR_EACH (bridge, ctx->ovs_idl) {
+ size_t i;
+ for (i = 0; i < bridge->n_ports; i++) {
+ if (bridge->ports[i] != port) {
+ continue;
+ }
+ struct ovsrec_port **new_ports;
+ new_ports = xmemdup(bridge->ports,
+ sizeof *new_ports * (bridge->n_ports - 1));
+ if (i != bridge->n_ports - 1) {
+ /* Removed port was not last */
+ new_ports[i] = bridge->ports[bridge->n_ports - 1];
+ }
+ ovsrec_bridge_verify_ports(bridge);
+ ovsrec_bridge_set_ports(bridge, new_ports, bridge->n_ports - 1);
+ free(new_ports);
+ ovsrec_port_delete(port);
+ return;
+ }
+ }
+}
+
+static void
+parse_bridge_mappings(struct controller_ctx *ctx,
+ const struct ovsrec_bridge *br_int,
+ const char *mappings_cfg)
+{
+ struct shash existing_ports = SHASH_INITIALIZER(&existing_ports);
+ init_existing_ports(ctx, &existing_ports);
+
+ char *cur, *next, *start;
+ next = start = xstrdup(mappings_cfg);
+ while ((cur = strsep(&next, ",")) && *cur) {
+ char *network, *bridge = cur;
+ const struct ovsrec_bridge *ovs_bridge;
+
+ network = strsep(&bridge, ":");
+ if (!bridge || !*network || !*bridge) {
+ VLOG_ERR("Invalid ovn-bridge-mappings configuration: '%s'",
+ mappings_cfg);
+ break;
+ }
+
+ ovs_bridge = get_bridge(ctx->ovs_idl, bridge);
+ if (!ovs_bridge) {
+ VLOG_WARN("Bridge '%s' not found for network '%s'",
+ bridge, network);
+ continue;
+ }
+
+ create_patch_ports(ctx, network, &existing_ports, br_int, ovs_bridge);
+ create_patch_ports(ctx, network, &existing_ports, ovs_bridge, br_int);
+ }
+ free(start);
+
+ /* Any ports left in existing_ports are related to configuration that has
+ * been removed, so we should delete the ports now. */
+ struct shash_node *port_node, *port_next_node;
+ SHASH_FOR_EACH_SAFE (port_node, port_next_node, &existing_ports) {
+ struct ovsrec_port *port = port_node->data;
+ shash_delete(&existing_ports, port_node);
+ remove_port(ctx, port);
+ }
+ shash_destroy(&existing_ports);
+}
+
+void
+patch_run(struct controller_ctx *ctx, const struct ovsrec_bridge *br_int)
+{
+ const char *mappings_cfg = "";
+ const struct ovsrec_open_vswitch *cfg;
+
+ cfg = ovsrec_open_vswitch_first(ctx->ovs_idl);
+ if (cfg) {
+ mappings_cfg = smap_get(&cfg->external_ids, "ovn-bridge-mappings");
+ if (!mappings_cfg) {
+ mappings_cfg = "";
+ }
+ }
+ parse_bridge_mappings(ctx, br_int, mappings_cfg);
+}
diff --git a/ovn/controller/patch.h b/ovn/controller/patch.h
new file mode 100644
index 000000000..f7db2fc11
--- /dev/null
+++ b/ovn/controller/patch.h
@@ -0,0 +1,30 @@
+/* Copyright (c) 2015 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 OVN_PATCH_H
+#define OVN_PATCH_H 1
+
+/* Patch Ports
+ * ===========
+ *
+ * This module adds and removes patch ports between the integration bridge and
+ * physical bridges, as directed by other-config:ovn-bridge-mappings. */
+
+struct controller_ctx;
+struct ovsrec_bridge;
+
+void patch_run(struct controller_ctx *, const struct ovsrec_bridge *br_int);
+
+#endif /* ovn/patch.h */