summaryrefslogtreecommitdiff
path: root/ovn
diff options
context:
space:
mode:
authorGao Zhenyu <sysugaozhenyu@gmail.com>2017-08-20 14:37:31 +0000
committerRussell Bryant <russell@ovn.org>2017-08-24 15:05:41 -0400
commit75f9e007e7f7eb91461e238f882d1c539c56bb8d (patch)
tree92b23edbe052e1b367c107bf35e50fde0f0cdeb2 /ovn
parent40e28d1323fdbc4dcaf71cc1ac96af921646e40d (diff)
downloadopenvswitch-75f9e007e7f7eb91461e238f882d1c539c56bb8d.tar.gz
ovn: Fix BFD error config on gateway
The bfd_calculate_chassis function calculates gateway's peer datapaths to figure out which tunnel's BFD should be enabled to from the current chassis. Existing algorithm only calculats peer datapaths at one hop, but multiple logical switches and E/W routers could be in the path, making several hops which were not considered on the calculation. It may disable BFD on some gw's tunnel ports. Then a port on a remote ovs cannot send packet out because it believes all remote gateways are down. This patch will go through whole graph and visit all datapath's port which has connection with gateways. Signed-off-by: Zhenyu Gao <sysugaozhenyu@gmail.com> Acked-by: Venkata Anil Kommaddi <vkommadi@redhat.com> Tested-by: Venkata Anil Kommaddi <vkommadi@redhat.com> Signed-off-by: Russell Bryant <russell@ovn.org>
Diffstat (limited to 'ovn')
-rw-r--r--ovn/controller/bfd.c102
1 files changed, 84 insertions, 18 deletions
diff --git a/ovn/controller/bfd.c b/ovn/controller/bfd.c
index d1448b13f..efc1482ec 100644
--- a/ovn/controller/bfd.c
+++ b/ovn/controller/bfd.c
@@ -100,6 +100,88 @@ bfd_calculate_active_tunnels(const struct ovsrec_bridge *br_int,
}
}
+struct local_datapath_node {
+ struct ovs_list node;
+ struct local_datapath *dp;
+};
+
+static void
+bfd_travel_gw_related_chassis(struct local_datapath *dp,
+ const struct hmap *local_datapaths,
+ struct ovsdb_idl_index_cursor *cursor,
+ struct sbrec_port_binding *lpval,
+ struct sset *bfd_chassis)
+{
+ struct ovs_list dp_list;
+ const struct sbrec_port_binding *pb;
+ struct sset visited_dp = SSET_INITIALIZER(&visited_dp);
+ const char *dp_key;
+ struct local_datapath_node *dp_binding;
+
+ if (!(dp_key = smap_get(&dp->datapath->external_ids, "logical-router")) &&
+ !(dp_key = smap_get(&dp->datapath->external_ids, "logical-switch"))) {
+ VLOG_INFO("datapath has no uuid, cannot travel graph");
+ return;
+ }
+
+ sset_add(&visited_dp, dp_key);
+
+ ovs_list_init(&dp_list);
+ dp_binding = xmalloc(sizeof *dp_binding);
+ dp_binding->dp = dp;
+ ovs_list_push_back(&dp_list, &dp_binding->node);
+
+ /*
+ * Go through whole graph to figure out all chassis which may deliver
+ * packets to gateway. */
+ do {
+ dp_binding = CONTAINER_OF(ovs_list_pop_front(&dp_list),
+ struct local_datapath_node, node);
+ dp = dp_binding->dp;
+ free(dp_binding);
+ for (size_t i = 0; i < dp->n_peer_dps; i++) {
+ const struct sbrec_datapath_binding *pdp = dp->peer_dps[i];
+ if (!pdp) {
+ continue;
+ }
+
+ if (!(dp_key = smap_get(&pdp->external_ids, "logical-router")) &&
+ !(dp_key = smap_get(&pdp->external_ids, "logical-switch"))) {
+ continue;
+ }
+
+ if (sset_contains(&visited_dp, dp_key)) {
+ continue;
+ }
+
+ sset_add(&visited_dp, dp_key);
+
+ struct hmap_node *node = hmap_first_with_hash(local_datapaths,
+ pdp->tunnel_key);
+ if (!node) {
+ continue;
+ }
+
+ dp_binding = xmalloc(sizeof *dp_binding);
+ dp_binding->dp = CONTAINER_OF(node, struct local_datapath,
+ hmap_node);
+ ovs_list_push_back(&dp_list, &dp_binding->node);
+
+ sbrec_port_binding_index_set_datapath(lpval, pdp);
+ SBREC_PORT_BINDING_FOR_EACH_EQUAL (pb, cursor, lpval) {
+ if (pb->chassis) {
+ const char *chassis_name = pb->chassis->name;
+ if (chassis_name) {
+ sset_add(bfd_chassis, chassis_name);
+ }
+ }
+ }
+ }
+ } while (!ovs_list_is_empty(&dp_list));
+
+ sset_destroy(&visited_dp);
+}
+
static void
bfd_calculate_chassis(struct controller_ctx *ctx,
const struct sbrec_chassis *our_chassis,
@@ -155,24 +237,8 @@ bfd_calculate_chassis(struct controller_ctx *ctx,
}
}
if (our_chassis_is_gw_for_dp) {
- for (size_t i = 0; i < dp->n_peer_dps; i++) {
- const struct sbrec_datapath_binding *pdp = dp->peer_dps[i];
- if (!pdp) {
- continue;
- }
-
- sbrec_port_binding_index_set_datapath(lpval, pdp);
- SBREC_PORT_BINDING_FOR_EACH_EQUAL (pb, &cursor, lpval) {
- if (pb->chassis) {
- /* Gateway node has to enable bfd to all nodes hosting
- * connected network ports */
- const char *chassis_name = pb->chassis->name;
- if (chassis_name) {
- sset_add(bfd_chassis, chassis_name);
- }
- }
- }
- }
+ bfd_travel_gw_related_chassis(dp, local_datapaths, &cursor,
+ lpval, bfd_chassis);
}
}
sbrec_port_binding_index_destroy_row(lpval);