diff mbox series

[ovs-dev,v6,05/17] ovn-controller: runtime_data changehandler for SB port-binding

Message ID 1558123002-4905-6-git-send-email-hzhou8@ebay.com
State Accepted
Headers show
Series ovn-controller incremental processing | expand

Commit Message

Han Zhou May 17, 2019, 7:56 p.m. UTC
From: Han Zhou <hzhou8@ebay.com>

Evaluates change for SB port-binding in runtime_data node.
If the port-binding change has no impact for the runtime_data it will
not trigger runtime_data change.

Signed-off-by: Han Zhou <hzhou8@ebay.com>
---
 ovn/controller/binding.c        | 100 ++++++++++++++++++++++++++++++++--------
 ovn/controller/binding.h        |   6 +++
 ovn/controller/ovn-controller.c |  41 +++++++++++++++-
 3 files changed, 126 insertions(+), 21 deletions(-)

Comments

0-day Robot May 17, 2019, 9:10 p.m. UTC | #1
Bleep bloop.  Greetings Han Zhou, I am a robot and I have tried out your patch.
Thanks for your contribution.

I encountered some error that I wasn't expecting.  See the details below.


checkpatch:
WARNING: Comment with 'xxx' marker
#149 FILE: ovn/controller/binding.c:706:
        /* XXX: currently OVSDB change tracking doesn't support getting old

Lines checked: 250, Warnings: 1, Errors: 0


Please check this out.  If you feel there has been an error, please email aconole@bytheb.org

Thanks,
0-day Robot
diff mbox series

Patch

diff --git a/ovn/controller/binding.c b/ovn/controller/binding.c
index c8e737a..b62b3da 100644
--- a/ovn/controller/binding.c
+++ b/ovn/controller/binding.c
@@ -427,6 +427,41 @@  sbrec_get_port_encap(const struct sbrec_chassis *chassis_rec,
     return best_encap;
 }
 
+static bool
+is_our_chassis(const struct sbrec_chassis *chassis_rec,
+               const struct sbrec_port_binding *binding_rec,
+               const struct sset *active_tunnels,
+               const struct shash *lport_to_iface,
+               const struct sset *local_lports)
+{
+    const struct ovsrec_interface *iface_rec
+        = shash_find_data(lport_to_iface, binding_rec->logical_port);
+
+    bool our_chassis = false;
+    if (iface_rec
+        || (binding_rec->parent_port && binding_rec->parent_port[0] &&
+            sset_contains(local_lports, binding_rec->parent_port))) {
+        /* This port is in our chassis unless it is a localport. */
+        our_chassis = strcmp(binding_rec->type, "localport");
+    } else if (!strcmp(binding_rec->type, "l2gateway")) {
+        const char *chassis_id = smap_get(&binding_rec->options,
+                                          "l2gateway-chassis");
+        our_chassis = chassis_id && !strcmp(chassis_id, chassis_rec->name);
+    } else if (!strcmp(binding_rec->type, "chassisredirect") ||
+               !strcmp(binding_rec->type, "external")) {
+        our_chassis = ha_chassis_group_contains(binding_rec->ha_chassis_group,
+                                                chassis_rec) &&
+                      ha_chassis_group_is_active(binding_rec->ha_chassis_group,
+                                                 active_tunnels, chassis_rec);
+    } else if (!strcmp(binding_rec->type, "l3gateway")) {
+        const char *chassis_id = smap_get(&binding_rec->options,
+                                          "l3gateway-chassis");
+        our_chassis = chassis_id && !strcmp(chassis_id, chassis_rec->name);
+    }
+
+    return our_chassis;
+}
+
 static void
 consider_local_datapath(struct ovsdb_idl_txn *ovnsb_idl_txn,
                         struct ovsdb_idl_txn *ovs_idl_txn,
@@ -445,7 +480,8 @@  consider_local_datapath(struct ovsdb_idl_txn *ovnsb_idl_txn,
     const struct ovsrec_interface *iface_rec
         = shash_find_data(lport_to_iface, binding_rec->logical_port);
 
-    bool our_chassis = false;
+    bool our_chassis = is_our_chassis(chassis_rec, binding_rec, active_tunnels,
+                                      lport_to_iface, local_lports);
     if (iface_rec
         || (binding_rec->parent_port && binding_rec->parent_port[0] &&
             sset_contains(local_lports, binding_rec->parent_port))) {
@@ -460,14 +496,7 @@  consider_local_datapath(struct ovsdb_idl_txn *ovnsb_idl_txn,
         if (iface_rec && qos_map && ovs_idl_txn) {
             get_qos_params(binding_rec, qos_map);
         }
-        /* This port is in our chassis unless it is a localport. */
-        if (strcmp(binding_rec->type, "localport")) {
-            our_chassis = true;
-        }
     } else if (!strcmp(binding_rec->type, "l2gateway")) {
-        const char *chassis_id = smap_get(&binding_rec->options,
-                                          "l2gateway-chassis");
-        our_chassis = chassis_id && !strcmp(chassis_id, chassis_rec->name);
         if (our_chassis) {
             sset_add(local_lports, binding_rec->logical_port);
             add_local_datapath(sbrec_datapath_binding_by_key,
@@ -478,19 +507,12 @@  consider_local_datapath(struct ovsdb_idl_txn *ovnsb_idl_txn,
     } else if (!strcmp(binding_rec->type, "chassisredirect")) {
         if (ha_chassis_group_contains(binding_rec->ha_chassis_group,
                                       chassis_rec)) {
-            our_chassis = ha_chassis_group_is_active(
-                binding_rec->ha_chassis_group,
-                active_tunnels, chassis_rec);
-
             add_local_datapath(sbrec_datapath_binding_by_key,
                                sbrec_port_binding_by_datapath,
                                sbrec_port_binding_by_name,
                                binding_rec->datapath, false, local_datapaths);
         }
     } else if (!strcmp(binding_rec->type, "l3gateway")) {
-        const char *chassis_id = smap_get(&binding_rec->options,
-                                          "l3gateway-chassis");
-        our_chassis = chassis_id && !strcmp(chassis_id, chassis_rec->name);
         if (our_chassis) {
             add_local_datapath(sbrec_datapath_binding_by_key,
                                sbrec_port_binding_by_datapath,
@@ -501,14 +523,9 @@  consider_local_datapath(struct ovsdb_idl_txn *ovnsb_idl_txn,
         /* Add all localnet ports to local_lports so that we allocate ct zones
          * for them. */
         sset_add(local_lports, binding_rec->logical_port);
-        our_chassis = false;
     } else if (!strcmp(binding_rec->type, "external")) {
         if (ha_chassis_group_contains(binding_rec->ha_chassis_group,
                                       chassis_rec)) {
-            our_chassis = ha_chassis_group_is_active(
-                binding_rec->ha_chassis_group,
-                active_tunnels, chassis_rec);
-
             add_local_datapath(sbrec_datapath_binding_by_key,
                                sbrec_port_binding_by_datapath,
                                sbrec_port_binding_by_name,
@@ -664,6 +681,49 @@  binding_run(struct ovsdb_idl_txn *ovnsb_idl_txn,
     hmap_destroy(&qos_map);
 }
 
+/* Returns true if port-binding changes potentially require flow changes on
+ * the current chassis. Returns false if we are sure there is no impact. */
+bool
+binding_evaluate_port_binding_changes(
+        const struct sbrec_port_binding_table *pb_table,
+        const struct ovsrec_bridge *br_int,
+        const struct sbrec_chassis *chassis_rec,
+        struct sset *active_tunnels,
+        struct sset *local_lports)
+{
+    if (!chassis_rec) {
+        return true;
+    }
+
+    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);
+    if (br_int) {
+        get_local_iface_ids(br_int, &lport_to_iface, local_lports,
+                            &egress_ifaces);
+    }
+    SBREC_PORT_BINDING_TABLE_FOR_EACH_TRACKED (binding_rec, pb_table) {
+        /* XXX: currently OVSDB change tracking doesn't support getting old
+         * data when the operation is update, so if a port-binding moved from
+         * this chassis to another, there is no easy way to find out the
+         * change. To workaround this problem, we just makes sure if
+         * any port *related to* this chassis has any change, then trigger
+         * recompute.
+         *
+         * - If a regular VIF is unbound from this chassis, the local ovsdb
+         *   interface table will be updated, which will trigger recompute.
+         *
+         * - If the port is not a regular VIF, always trigger recompute. */
+        if (binding_rec->chassis == chassis_rec
+            || is_our_chassis(chassis_rec, binding_rec,
+                              active_tunnels, &lport_to_iface, local_lports)
+            || strcmp(binding_rec->type, "")) {
+            return true;
+        }
+    }
+    return false;
+}
+
 /* Returns true if the database is all cleaned up, false if more work is
  * required. */
 bool
diff --git a/ovn/controller/binding.h b/ovn/controller/binding.h
index 0f24a0e..8d94926 100644
--- a/ovn/controller/binding.h
+++ b/ovn/controller/binding.h
@@ -47,5 +47,11 @@  void binding_run(struct ovsdb_idl_txn *ovnsb_idl_txn,
 bool binding_cleanup(struct ovsdb_idl_txn *ovnsb_idl_txn,
                      const struct sbrec_port_binding_table *,
                      const struct sbrec_chassis *);
+bool binding_evaluate_port_binding_changes(
+        const struct sbrec_port_binding_table *,
+        const struct ovsrec_bridge *br_int,
+        const struct sbrec_chassis *,
+        struct sset *active_tunnels,
+        struct sset *local_lports);
 
 #endif /* ovn/binding.h */
diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c
index 881e9d9..57bd5ed 100644
--- a/ovn/controller/ovn-controller.c
+++ b/ovn/controller/ovn-controller.c
@@ -848,6 +848,44 @@  en_runtime_data_run(struct engine_node *node)
     node->changed = true;
 }
 
+static bool
+runtime_data_sb_port_binding_handler(struct engine_node *node)
+{
+    struct ed_type_runtime_data *data =
+        (struct ed_type_runtime_data *)node->data;
+    struct sset *local_lports = &data->local_lports;
+    struct sset *active_tunnels = &data->active_tunnels;
+
+    struct ovsrec_open_vswitch_table *ovs_table =
+        (struct ovsrec_open_vswitch_table *)EN_OVSDB_GET(
+            engine_get_input("OVS_open_vswitch", node));
+    struct ovsrec_bridge_table *bridge_table =
+        (struct ovsrec_bridge_table *)EN_OVSDB_GET(
+            engine_get_input("OVS_bridge", node));
+    const char *chassis_id = get_chassis_id(ovs_table);
+    const struct ovsrec_bridge *br_int = get_br_int(bridge_table, ovs_table);
+
+    ovs_assert(br_int && chassis_id);
+
+    struct ovsdb_idl_index *sbrec_chassis_by_name =
+        engine_ovsdb_node_get_index(
+                engine_get_input("SB_chassis", node),
+                "name");
+
+    const struct sbrec_chassis *chassis
+        = chassis_lookup_by_name(sbrec_chassis_by_name, chassis_id);
+    ovs_assert(chassis);
+
+    struct sbrec_port_binding_table *pb_table =
+        (struct sbrec_port_binding_table *)EN_OVSDB_GET(
+            engine_get_input("SB_port_binding", node));
+
+    bool changed = binding_evaluate_port_binding_changes(
+        pb_table, br_int, chassis, active_tunnels, local_lports);
+
+    return !changed;
+}
+
 struct ed_type_mff_ovn_geneve {
     enum mf_field_id mff_ovn_geneve;
 };
@@ -1234,7 +1272,8 @@  main(int argc, char *argv[])
     engine_add_input(&en_runtime_data, &en_sb_address_set, NULL);
     engine_add_input(&en_runtime_data, &en_sb_port_group, NULL);
     engine_add_input(&en_runtime_data, &en_sb_datapath_binding, NULL);
-    engine_add_input(&en_runtime_data, &en_sb_port_binding, NULL);
+    engine_add_input(&en_runtime_data, &en_sb_port_binding,
+                     runtime_data_sb_port_binding_handler);
 
     engine_init(&en_flow_output);