diff mbox

[ovs-dev,v1,3/4] ovn: l3ha make is_chassis_active aware of redirect-chassis

Message ID 1496406704-15393-4-git-send-email-majopela@redhat.com
State Superseded
Headers show

Commit Message

Miguel Angel Ajo June 2, 2017, 12:31 p.m. UTC
From: Miguel Angel Ajo <majopela@redhat.com>

is_chassis_active now is only true for redirect-chassis ports
in the case of the specific lport being active on the
local chassis.

This will naturally make the ARP responder / redirection openflow
rules automatically inserted/removed when a router goes active/backup.

Signed-off-by: Miguel Angel Ajo <majopela@redhat.com>
---
 ovn/controller/binding.c        | 21 +++++---------------
 ovn/controller/binding.h        |  2 +-
 ovn/controller/lflow.c          | 38 ++++++++++++++++++++++++++----------
 ovn/controller/lflow.h          |  4 +++-
 ovn/controller/lport.c          | 43 ++++++++++++++++++++++++++++++++++++++++-
 ovn/controller/lport.h          |  7 ++++++-
 ovn/controller/ovn-controller.c |  6 ++++--
 7 files changed, 89 insertions(+), 32 deletions(-)
diff mbox

Patch

diff --git a/ovn/controller/binding.c b/ovn/controller/binding.c
index 431b61e..b733229 100644
--- a/ovn/controller/binding.c
+++ b/ovn/controller/binding.c
@@ -430,17 +430,8 @@  consider_local_datapath(struct controller_ctx *ctx,
 
         if (redirect_chassis &&
            redirect_chassis_contains(redirect_chassis, chassis_rec)) {
-            struct redirect_chassis *rc;
-            LIST_FOR_EACH (rc, node, redirect_chassis) {
-                if (!strcmp(rc->chassis_id, chassis_rec->name)) {
-                    /* sb_rec_port_binding->chassis should reflect master */
-                    our_chassis = true;
-                    break;
-                }
-                if (sset_contains(active_tunnels, rc->chassis_id)) {
-                    break;
-                }
-            }
+            our_chassis = redirect_chassis_is_active(
+                    redirect_chassis, chassis_rec, active_tunnels);
             add_local_datapath(ldatapaths, lports, binding_rec->datapath,
                                false, local_datapaths, our_chassis);
         }
@@ -491,7 +482,7 @@  binding_run(struct controller_ctx *ctx, const struct ovsrec_bridge *br_int,
             const struct sbrec_chassis *chassis_rec,
             const struct ldatapath_index *ldatapaths,
             const struct lport_index *lports, struct hmap *local_datapaths,
-            struct sset *local_lports)
+            struct sset *local_lports, struct sset *active_tunnels)
 {
     if (!chassis_rec) {
         return;
@@ -500,13 +491,12 @@  binding_run(struct controller_ctx *ctx, const struct ovsrec_bridge *br_int,
     const struct sbrec_port_binding *binding_rec;
     struct shash lport_to_iface = SHASH_INITIALIZER(&lport_to_iface);
     struct sset egress_ifaces = SSET_INITIALIZER(&egress_ifaces);
-    struct sset active_tunnels = SSET_INITIALIZER(&active_tunnels);
     struct hmap qos_map;
 
     hmap_init(&qos_map);
     if (br_int) {
         get_local_iface_ids(br_int, &lport_to_iface, local_lports,
-                            &egress_ifaces, &active_tunnels);
+                            &egress_ifaces, active_tunnels);
     }
 
     /* Run through each binding record to see if it is resident on this
@@ -517,7 +507,7 @@  binding_run(struct controller_ctx *ctx, const struct ovsrec_bridge *br_int,
                                 chassis_rec, binding_rec,
                                 sset_is_empty(&egress_ifaces) ? NULL :
                                 &qos_map, local_datapaths, &lport_to_iface,
-                                local_lports, &active_tunnels);
+                                local_lports, active_tunnels);
 
     }
     if (!sset_is_empty(&egress_ifaces)
@@ -530,7 +520,6 @@  binding_run(struct controller_ctx *ctx, const struct ovsrec_bridge *br_int,
 
     shash_destroy(&lport_to_iface);
     sset_destroy(&egress_ifaces);
-    sset_destroy(&active_tunnels);
     hmap_destroy(&qos_map);
 }
 
diff --git a/ovn/controller/binding.h b/ovn/controller/binding.h
index 2b88ec5..99c5225 100644
--- a/ovn/controller/binding.h
+++ b/ovn/controller/binding.h
@@ -32,7 +32,7 @@  void binding_register_ovs_idl(struct ovsdb_idl *);
 void binding_run(struct controller_ctx *, const struct ovsrec_bridge *br_int,
                  const struct sbrec_chassis *, const struct ldatapath_index *,
                  const struct lport_index *, struct hmap *local_datapaths,
-                 struct sset *all_lports);
+                 struct sset *all_lports, struct sset *active_tunnels);
 void bfd_run(struct controller_ctx *ctx, const struct ovsrec_bridge *br_int,
              const struct sbrec_chassis *chassis_rec,
              struct hmap *local_datapaths);
diff --git a/ovn/controller/lflow.c b/ovn/controller/lflow.c
index b7d1bcb..f901bea 100644
--- a/ovn/controller/lflow.c
+++ b/ovn/controller/lflow.c
@@ -53,6 +53,7 @@  struct lookup_port_aux {
 struct condition_aux {
     const struct lport_index *lports;
     const struct sbrec_chassis *chassis;
+    const struct sset *active_tunnels;
 };
 
 static void consider_logical_flow(const struct lport_index *lports,
@@ -65,7 +66,8 @@  static void consider_logical_flow(const struct lport_index *lports,
                                   struct hmap *dhcpv6_opts,
                                   uint32_t *conj_id_ofs,
                                   const struct shash *addr_sets,
-                                  struct hmap *flow_table);
+                                  struct hmap *flow_table,
+                                  struct sset *active_tunnels);
 
 static bool
 lookup_port_cb(const void *aux_, const char *port_name, unsigned int *portp)
@@ -96,10 +98,23 @@  is_chassis_resident_cb(const void *c_aux_, const char *port_name)
 
     const struct sbrec_port_binding *pb
         = lport_lookup_by_name(c_aux->lports, port_name);
-    if (pb && pb->chassis && pb->chassis == c_aux->chassis) {
-        return true;
+    if (!pb) {
+        return false;
+    }
+    if (strcmp(pb->type, "chassisredirect")) {
+        /* for non-chassisredirect ports */
+        return pb->chassis && pb->chassis == c_aux->chassis;
     } else {
-        return pb_redirect_chassis_contains(pb, c_aux->chassis);
+        struct ovs_list *redirect_chassis;
+        redirect_chassis = parse_redirect_chassis(pb);
+        if (redirect_chassis) {
+            bool active = redirect_chassis_is_active(redirect_chassis,
+                                                     c_aux->chassis,
+                                                     c_aux->active_tunnels);
+            redirect_chassis_destroy(redirect_chassis);
+            return active;
+        }
+        return false;
     }
 }
 
@@ -127,7 +142,8 @@  add_logical_flows(struct controller_ctx *ctx, const struct lport_index *lports,
                   struct group_table *group_table,
                   const struct sbrec_chassis *chassis,
                   const struct shash *addr_sets,
-                  struct hmap *flow_table)
+                  struct hmap *flow_table,
+                  struct sset *active_tunnels)
 {
     uint32_t conj_id_ofs = 1;
     const struct sbrec_logical_flow *lflow;
@@ -151,7 +167,7 @@  add_logical_flows(struct controller_ctx *ctx, const struct lport_index *lports,
         consider_logical_flow(lports, mcgroups, lflow, local_datapaths,
                               group_table, chassis,
                               &dhcp_opts, &dhcpv6_opts, &conj_id_ofs,
-                              addr_sets, flow_table);
+                              addr_sets, flow_table, active_tunnels);
     }
 
     dhcp_opts_destroy(&dhcp_opts);
@@ -169,7 +185,8 @@  consider_logical_flow(const struct lport_index *lports,
                       struct hmap *dhcpv6_opts,
                       uint32_t *conj_id_ofs,
                       const struct shash *addr_sets,
-                      struct hmap *flow_table)
+                      struct hmap *flow_table,
+                      struct sset *active_tunnels)
 {
     /* Determine translation of logical table IDs to physical table IDs. */
     bool ingress = !strcmp(lflow->pipeline, "ingress");
@@ -266,7 +283,7 @@  consider_logical_flow(const struct lport_index *lports,
         return;
     }
 
-    struct condition_aux cond_aux = { lports, chassis };
+    struct condition_aux cond_aux = { lports, chassis, active_tunnels};
     expr = expr_simplify(expr, is_chassis_resident_cb, &cond_aux);
     expr = expr_normalize(expr);
     uint32_t n_conjs = expr_to_matches(expr, lookup_port_cb, &aux,
@@ -395,10 +412,11 @@  lflow_run(struct controller_ctx *ctx,
           const struct hmap *local_datapaths,
           struct group_table *group_table,
           const struct shash *addr_sets,
-          struct hmap *flow_table)
+          struct hmap *flow_table,
+          struct sset *active_tunnels)
 {
     add_logical_flows(ctx, lports, mcgroups, local_datapaths, group_table,
-                      chassis, addr_sets, flow_table);
+                      chassis, addr_sets, flow_table, active_tunnels);
     add_neighbor_flows(ctx, lports, flow_table);
 }
 
diff --git a/ovn/controller/lflow.h b/ovn/controller/lflow.h
index a23cde0..6c02216 100644
--- a/ovn/controller/lflow.h
+++ b/ovn/controller/lflow.h
@@ -42,6 +42,7 @@  struct lport_index;
 struct mcgroup_index;
 struct sbrec_chassis;
 struct simap;
+struct sset;
 struct uuid;
 
 /* OpenFlow table numbers.
@@ -69,7 +70,8 @@  void lflow_run(struct controller_ctx *,
                const struct hmap *local_datapaths,
                struct group_table *group_table,
                const struct shash *addr_sets,
-               struct hmap *flow_table);
+               struct hmap *flow_table,
+               struct sset *active_tunnels);
 void lflow_destroy(void);
 
 #endif /* ovn/lflow.h */
diff --git a/ovn/controller/lport.c b/ovn/controller/lport.c
index 52608a1..a0c403a 100644
--- a/ovn/controller/lport.c
+++ b/ovn/controller/lport.c
@@ -15,11 +15,11 @@ 
 
 #include <config.h>
 
+#include "lib/sset.h"
 #include "lport.h"
 #include "hash.h"
 #include "openvswitch/vlog.h"
 #include "ovn/lib/ovn-sb-idl.h"
-
 VLOG_DEFINE_THIS_MODULE(lport);
 
 static struct ldatapath *ldatapath_lookup_by_key__(
@@ -356,3 +356,44 @@  pb_redirect_chassis_contains(const struct sbrec_port_binding *binding,
     redirect_chassis_destroy(redirect_chassis);
     return contained;
 }
+
+bool
+redirect_chassis_is_active(const struct ovs_list *redirect_chassis,
+                           const struct sbrec_chassis *local_chassis,
+                           const struct sset *active_tunnels)
+{
+    struct redirect_chassis *rc;
+
+    if (!redirect_chassis) {
+        return false;
+    }
+    /* if there's only one chassis, and local chassis is on the list
+     * it's not HA and it's the equivalent of being active */
+    if (ovs_list_is_short(redirect_chassis) &&
+       redirect_chassis_contains(redirect_chassis, local_chassis)) {
+        return true;
+    }
+
+    /* if there are no other tunnels active, we assume that the
+     * connection providing tunneling is down, hence we're down */
+    if (sset_is_empty(active_tunnels)) {
+        return false;
+    }
+
+    /* redirect_chassis is an ordered list, by priority, of chassis
+     * hosting the redirect of the port */
+    LIST_FOR_EACH (rc, node, redirect_chassis) {
+        /* if we found the chassis on the list, and we didn't exit before
+         * on the active_tunnels check for other higher priority chassis
+         * being active, then this chassis is master. */
+        if (!strcmp(rc->chassis_id, local_chassis->name)) {
+            return true;
+        }
+        /* if we find this specific chassis on the list to have an active
+         * tunnel, then 'local_chassis' is not master */
+        if (sset_contains(active_tunnels, rc->chassis_id)) {
+            return false;
+        }
+    }
+    return false;
+}
diff --git a/ovn/controller/lport.h b/ovn/controller/lport.h
index 329a71f..e7abae4 100644
--- a/ovn/controller/lport.h
+++ b/ovn/controller/lport.h
@@ -25,6 +25,8 @@  struct ovsdb_idl;
 struct sbrec_chassis;
 struct sbrec_datapath_binding;
 struct sbrec_port_binding;
+struct sset;
+
 
 /* Database indexes.
  * =================
@@ -120,5 +122,8 @@  void redirect_chassis_destroy(struct ovs_list *list);
 bool pb_redirect_chassis_contains(
         const struct sbrec_port_binding *binding,
         const struct sbrec_chassis *chassis);
-
+bool redirect_chassis_is_active(
+        const struct ovs_list *redirect_chassis,
+        const struct sbrec_chassis *local_chassis,
+        const struct sset *active_tunnels);
 #endif /* ovn/lport.h */
diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c
index 7930b6e..10dfdfe 100644
--- a/ovn/controller/ovn-controller.c
+++ b/ovn/controller/ovn-controller.c
@@ -613,6 +613,7 @@  main(int argc, char *argv[])
          * l2gateway ports for which options:l2gateway-chassis designates the
          * local hypervisor, and localnet ports. */
         struct sset local_lports = SSET_INITIALIZER(&local_lports);
+        struct sset active_tunnels = SSET_INITIALIZER(&active_tunnels);
 
         const struct ovsrec_bridge *br_int = get_br_int(&ctx);
         const char *chassis_id = get_chassis_id(ctx.ovs_idl);
@@ -629,7 +630,7 @@  main(int argc, char *argv[])
             chassis = chassis_run(&ctx, chassis_id, br_int);
             encaps_run(&ctx, br_int, chassis_id);
             binding_run(&ctx, br_int, chassis, &ldatapaths, &lports,
-                        &local_datapaths, &local_lports);
+                        &local_datapaths, &local_lports, &active_tunnels);
         }
 
         if (br_int && chassis) {
@@ -651,7 +652,7 @@  main(int argc, char *argv[])
                     struct hmap flow_table = HMAP_INITIALIZER(&flow_table);
                     lflow_run(&ctx, chassis, &lports, &mcgroups,
                               &local_datapaths, &group_table,
-                              &addr_sets, &flow_table);
+                              &addr_sets, &flow_table, &active_tunnels);
 
                     bfd_run(&ctx, br_int, chassis, &local_datapaths);
                     physical_run(&ctx, mff_ovn_geneve,
@@ -705,6 +706,7 @@  main(int argc, char *argv[])
         ldatapath_index_destroy(&ldatapaths);
 
         sset_destroy(&local_lports);
+        sset_destroy(&active_tunnels);
 
         struct local_datapath *cur_node, *next_node;
         HMAP_FOR_EACH_SAFE (cur_node, next_node, hmap_node, &local_datapaths) {