[ovs-dev] [PATCH v14 2/6] Change encaps_run to work incrementally
Ryan Moats
rmoats at us.ibm.com
Wed Apr 13 13:38:31 UTC 2016
As a side effect, tunnel context is persisted.
Signed-off-by: Ryan Moats <rmoats at us.ibm.com>
---
ovn/controller/encaps.c | 162 ++++++++++++++++++++++++++++------------
ovn/controller/ovn-controller.c | 5 ++
2 files changed, 120 insertions(+), 47 deletions(-)
diff --git a/ovn/controller/encaps.c b/ovn/controller/encaps.c
index dfb11c0..4c2bb84 100644
--- a/ovn/controller/encaps.c
+++ b/ovn/controller/encaps.c
@@ -15,6 +15,7 @@
#include <config.h>
#include "encaps.h"
+#include "lflow.h"
#include "lib/hash.h"
#include "lib/sset.h"
@@ -49,6 +50,7 @@ struct tunnel_ctx {
* generated we remove them. After generating all the rows, any
* remaining in 'tunnel_hmap' must be deleted from the database. */
struct hmap tunnel_hmap;
+ struct hmap tunnel_hmap_by_uuid;
/* Names of all ports in the bridge, to allow checking uniqueness when
* adding a new tunnel. */
@@ -58,8 +60,18 @@ struct tunnel_ctx {
const struct ovsrec_bridge *br_int;
};
+struct tunnel_ctx tc = {
+ .tunnel_hmap = HMAP_INITIALIZER(&tc.tunnel_hmap),
+ .tunnel_hmap_by_uuid = HMAP_INITIALIZER(&tc.tunnel_hmap_by_uuid),
+ .port_names = SSET_INITIALIZER(&tc.port_names),
+};
+
+bool process_full_encaps = false;
+
struct port_hash_node {
struct hmap_node node;
+ struct hmap_node uuid_node;
+ const struct uuid *uuid;
const struct ovsrec_port *port;
const struct ovsrec_bridge *bridge;
};
@@ -92,7 +104,7 @@ port_hash_rec(const struct ovsrec_port *port)
}
static char *
-tunnel_create_name(struct tunnel_ctx *tc, const char *chassis_id)
+tunnel_create_name(const char *chassis_id)
{
int i;
@@ -100,7 +112,7 @@ tunnel_create_name(struct tunnel_ctx *tc, const char *chassis_id)
char *port_name;
port_name = xasprintf("ovn-%.6s-%x", chassis_id, i);
- if (!sset_contains(&tc->port_names, port_name)) {
+ if (!sset_contains(&tc.port_names, port_name)) {
return port_name;
}
@@ -110,19 +122,32 @@ tunnel_create_name(struct tunnel_ctx *tc, const char *chassis_id)
return NULL;
}
+static struct port_hash_node *
+port_lookup_by_uuid(const struct uuid *uuid)
+{
+ struct hmap_node *node = hmap_first_with_hash(&tc.tunnel_hmap_by_uuid,
+ uuid_hash(uuid));
+ if (node) {
+ return CONTAINER_OF(node, struct port_hash_node, uuid_node);
+ }
+ return NULL;
+}
static void
-tunnel_add(struct tunnel_ctx *tc, const char *new_chassis_id,
+tunnel_add(const struct sbrec_chassis *chassis_rec,
const struct sbrec_encap *encap)
{
struct port_hash_node *hash_node;
+ const char *new_chassis_id = chassis_rec->name;
+
+ /* Check whether such a row already exists in OVS. If so, update
+ * the uuid field and insert into the by uuid hashmap. If not,
+ * create the tunnel */
- /* Check whether such a row already exists in OVS. If so, remove it
- * from 'tc->tunnel_hmap' and we're done. */
HMAP_FOR_EACH_WITH_HASH (hash_node, node,
port_hash(new_chassis_id,
encap->type, encap->ip),
- &tc->tunnel_hmap) {
+ &tc.tunnel_hmap) {
const struct ovsrec_port *port = hash_node->port;
const char *chassis_id = smap_get(&port->external_ids,
"ovn-chassis-id");
@@ -142,8 +167,12 @@ tunnel_add(struct tunnel_ctx *tc, const char *new_chassis_id,
if (!strcmp(new_chassis_id, chassis_id)
&& !strcmp(encap->type, iface->type)
&& !strcmp(encap->ip, ip)) {
- hmap_remove(&tc->tunnel_hmap, &hash_node->node);
- free(hash_node);
+
+ hash_node->uuid = &chassis_rec->header_.uuid;
+ if (!port_lookup_by_uuid(hash_node->uuid)) {
+ hmap_insert(&tc.tunnel_hmap_by_uuid, &hash_node->uuid_node,
+ uuid_hash(hash_node->uuid));
+ }
return;
}
}
@@ -155,14 +184,14 @@ tunnel_add(struct tunnel_ctx *tc, const char *new_chassis_id,
char *port_name;
size_t i;
- port_name = tunnel_create_name(tc, new_chassis_id);
+ port_name = tunnel_create_name(new_chassis_id);
if (!port_name) {
VLOG_WARN("Unable to allocate unique name for '%s' tunnel",
new_chassis_id);
return;
}
- iface = ovsrec_interface_insert(tc->ovs_txn);
+ iface = ovsrec_interface_insert(tc.ovs_txn);
ovsrec_interface_set_name(iface, port_name);
ovsrec_interface_set_type(iface, encap->type);
smap_add(&options, "remote_ip", encap->ip);
@@ -170,23 +199,25 @@ tunnel_add(struct tunnel_ctx *tc, const char *new_chassis_id,
ovsrec_interface_set_options(iface, &options);
smap_destroy(&options);
- port = ovsrec_port_insert(tc->ovs_txn);
+ port = ovsrec_port_insert(tc.ovs_txn);
ovsrec_port_set_name(port, port_name);
ovsrec_port_set_interfaces(port, &iface, 1);
const struct smap id = SMAP_CONST1(&id, "ovn-chassis-id", new_chassis_id);
ovsrec_port_set_external_ids(port, &id);
- ports = xmalloc(sizeof *tc->br_int->ports * (tc->br_int->n_ports + 1));
- for (i = 0; i < tc->br_int->n_ports; i++) {
- ports[i] = tc->br_int->ports[i];
+ ports = xmalloc(sizeof *tc.br_int->ports * (tc.br_int->n_ports + 1));
+ for (i = 0; i < tc.br_int->n_ports; i++) {
+ ports[i] = tc.br_int->ports[i];
}
- ports[tc->br_int->n_ports] = port;
- ovsrec_bridge_verify_ports(tc->br_int);
- ovsrec_bridge_set_ports(tc->br_int, ports, tc->br_int->n_ports + 1);
+ ports[tc.br_int->n_ports] = port;
+ ovsrec_bridge_verify_ports(tc.br_int);
+ ovsrec_bridge_set_ports(tc.br_int, ports, tc.br_int->n_ports + 1);
- sset_add(&tc->port_names, port_name);
+ sset_add(&tc.port_names, port_name);
free(port_name);
free(ports);
+ // reset_flow_processing();
+ process_full_encaps = true;
}
static void
@@ -224,6 +255,24 @@ preferred_encap(const struct sbrec_chassis *chassis_rec)
return best_encap;
}
+<<<<<<< HEAD
+=======
+static void
+check_and_add_tunnel(const struct sbrec_chassis *chassis_rec,
+ const char *chassis_id)
+{
+ if (strcmp(chassis_rec->name, chassis_id)) {
+ /* Create tunnels to the other chassis. */
+ const struct sbrec_encap *encap = preferred_encap(chassis_rec);
+ if (!encap) {
+ VLOG_INFO("No supported encaps for '%s'", chassis_rec->name);
+ return;
+ }
+ tunnel_add(chassis_rec, encap);
+ }
+}
+
+>>>>>>> Change encaps_run to work incrementally
void
encaps_run(struct controller_ctx *ctx, const struct ovsrec_bridge *br_int,
const char *chassis_id)
@@ -235,12 +284,7 @@ encaps_run(struct controller_ctx *ctx, const struct ovsrec_bridge *br_int,
const struct sbrec_chassis *chassis_rec;
const struct ovsrec_bridge *br;
- struct tunnel_ctx tc = {
- .tunnel_hmap = HMAP_INITIALIZER(&tc.tunnel_hmap),
- .port_names = SSET_INITIALIZER(&tc.port_names),
- .br_int = br_int
- };
-
+ tc.br_int = br_int;
tc.ovs_txn = ctx->ovs_idl_txn;
ovsdb_idl_txn_add_comment(tc.ovs_txn,
"ovn-controller: modifying OVS tunnels '%s'",
@@ -257,37 +301,61 @@ encaps_run(struct controller_ctx *ctx, const struct ovsrec_bridge *br_int,
sset_add(&tc.port_names, port->name);
- if (smap_get(&port->external_ids, "ovn-chassis-id")) {
- struct port_hash_node *hash_node = xzalloc(sizeof *hash_node);
- hash_node->bridge = br;
- hash_node->port = port;
- hmap_insert(&tc.tunnel_hmap, &hash_node->node,
- port_hash_rec(port));
+ const char *old_chassis_id = smap_get(&port->external_ids,
+ "ovn-chassis-id");
+ if (old_chassis_id) {
+ if (!hmap_first_with_hash(&tc.tunnel_hmap,
+ port_hash_rec(port))) {
+ struct port_hash_node *hash_node =
+ xzalloc(sizeof *hash_node);
+ hash_node->bridge = br;
+ hash_node->port = port;
+ hmap_insert(&tc.tunnel_hmap, &hash_node->node,
+ port_hash_rec(port));
+ process_full_encaps = true;
+ }
}
}
}
- SBREC_CHASSIS_FOR_EACH(chassis_rec, ctx->ovnsb_idl) {
- if (strcmp(chassis_rec->name, chassis_id)) {
- /* Create tunnels to the other chassis. */
- const struct sbrec_encap *encap = preferred_encap(chassis_rec);
- if (!encap) {
- VLOG_INFO("No supported encaps for '%s'", chassis_rec->name);
+ if (process_full_encaps) {
+ SBREC_CHASSIS_FOR_EACH (chassis_rec, ctx->ovnsb_idl) {
+ check_and_add_tunnel(chassis_rec, chassis_id);
+ }
+ process_full_encaps = false;
+ } else {
+ SBREC_CHASSIS_FOR_EACH_TRACKED (chassis_rec, ctx->ovnsb_idl) {
+ bool is_deleted = sbrec_chassis_row_get_seqno(chassis_rec,
+ OVSDB_IDL_CHANGE_DELETE) > 0;
+ bool is_new = sbrec_chassis_row_get_seqno(chassis_rec,
+ OVSDB_IDL_CHANGE_MODIFY) == 0;
+
+ if (is_deleted) {
+ /* lookup the tunnel by row uuid and remove it */
+ struct port_hash_node *port_hash =
+ port_lookup_by_uuid(&chassis_rec->header_.uuid);
+ if (port_hash) {
+ bridge_delete_port(port_hash->bridge, port_hash->port);
+ sset_find_and_delete(&tc.port_names,
+ port_hash->port->name);
+ hmap_remove(&tc.tunnel_hmap, &port_hash->node);
+ hmap_remove(&tc.tunnel_hmap_by_uuid,
+ &port_hash->uuid_node);
+ free(port_hash);
+ }
continue;
}
- tunnel_add(&tc, chassis_rec->name, encap);
+ if (!is_new) {
+ if (strcmp(chassis_rec->name, chassis_id)) {
+ /* TODO: find the tunnel by looking it up based on its
+ * uuid and then change it. */
+ ;
+ }
+ } else {
+ check_and_add_tunnel(chassis_rec, chassis_id);
+ }
}
}
-
- /* Delete any existing OVN tunnels that were not still around. */
- struct port_hash_node *hash_node, *next_hash_node;
- HMAP_FOR_EACH_SAFE (hash_node, next_hash_node, node, &tc.tunnel_hmap) {
- hmap_remove(&tc.tunnel_hmap, &hash_node->node);
- bridge_delete_port(hash_node->bridge, hash_node->port);
- free(hash_node);
- }
- hmap_destroy(&tc.tunnel_hmap);
- sset_destroy(&tc.port_names);
}
/* Returns true if the database is all cleaned up, false if more work is
diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c
index 7c68c9d..16731a4 100644
--- a/ovn/controller/ovn-controller.c
+++ b/ovn/controller/ovn-controller.c
@@ -304,6 +304,10 @@ main(int argc, char *argv[])
char *ovnsb_remote = get_ovnsb_remote(ovs_idl_loop.idl);
struct ovsdb_idl_loop ovnsb_idl_loop = OVSDB_IDL_LOOP_INITIALIZER(
ovsdb_idl_create(ovnsb_remote, &sbrec_idl_class, true, true));
+
+ /* track the southbound idl */
+ ovsdb_idl_track_add_all(ovnsb_idl_loop.idl);
+
ovsdb_idl_get_initial_snapshot(ovnsb_idl_loop.idl);
int probe_interval = 0;
@@ -398,6 +402,7 @@ main(int argc, char *argv[])
}
ovsdb_idl_loop_commit_and_wait(&ovnsb_idl_loop);
ovsdb_idl_loop_commit_and_wait(&ovs_idl_loop);
+ ovsdb_idl_track_clear(ovnsb_idl_loop.idl);
poll_block();
if (should_service_stop()) {
exiting = true;
--
1.9.1
More information about the dev
mailing list