[ovs-dev,RFC,8/8] ovn-controller: port-binding incremental processing for physical flows

Message ID 1519153484-11253-9-git-send-email-hzhou8@ebay.com
State RFC
Headers show
Series
  • Untitled series #29585
Related show

Commit Message

Han Zhou Feb. 20, 2018, 7:04 p.m.
This patch implements change handler for port-binding in flow_output
for physical flows computing, so that physical flow computing will
be incremental.

This patch together with previous incremental processing engine
related changes supports incremental processing for lflow changes
and port-binding changes of lports on other HVs, which are the most
common scenarios in a cloud where workloads come up and down.

The CPU time of ovn-controller in ovn-scale-test for 500 lports
creating and binding decreased 90% comparing with master without
incremental processing engine related changes.

(TODO: test case 2337 failed)

Signed-off-by: Han Zhou <hzhou8@ebay.com>
---
 ovn/controller/ovn-controller.c | 36 ++++++++++++++++++++++++++++++++++-
 ovn/controller/physical.c       | 42 ++++++++++++++++++++++++++++++++++-------
 ovn/controller/physical.h       |  6 ++++++
 3 files changed, 76 insertions(+), 8 deletions(-)

Patch

diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c
index 31f78f1..b92dcf5 100644
--- a/ovn/controller/ovn-controller.c
+++ b/ovn/controller/ovn-controller.c
@@ -780,6 +780,40 @@  flow_output_sb_logical_flow_handler(struct engine_node *node)
     return true;
 }
 
+static bool
+flow_output_sb_port_binding_handler(struct engine_node *node)
+{
+    struct controller_ctx *ctx = (struct controller_ctx *)node->context;
+    struct ed_type_runtime_data *data =
+        (struct ed_type_runtime_data *)engine_get_input(
+                "runtime_data", node)->data;
+    struct hmap *local_datapaths = data->local_datapaths;
+    struct sset *active_tunnels = data->active_tunnels;
+    struct chassis_index *chassis_index = data->chassis_index;
+    const struct ovsrec_bridge *br_int = get_br_int(ctx);
+
+    const char *chassis_id = get_chassis_id(ctx->ovs_idl);
+
+
+    const struct sbrec_chassis *chassis = NULL;
+    if (chassis_id) {
+        chassis = get_chassis(ctx->ovnsb_idl, chassis_id);
+    }
+
+    ovs_assert(br_int && chassis);
+
+    // TODO: handle port-binding for lflow processing
+
+    enum mf_field_id mff_ovn_geneve = ofctrl_get_mf_field_id();
+    physical_handle_port_binding_changes(ctx, mff_ovn_geneve,
+                 chassis, ctx->ct_zones,
+                 local_datapaths,
+                 chassis_index, active_tunnels);
+
+    node->changed = true;
+    return true;
+}
+
 int
 main(int argc, char *argv[])
 {
@@ -911,7 +945,7 @@  main(int argc, char *argv[])
     engine_add_input(&en_flow_output, &en_sb_address_set, NULL);
     engine_add_input(&en_flow_output, &en_sb_multicast_group, NULL);
     engine_add_input(&en_flow_output, &en_sb_datapath_binding, NULL);
-    engine_add_input(&en_flow_output, &en_sb_port_binding, NULL);
+    engine_add_input(&en_flow_output, &en_sb_port_binding, flow_output_sb_port_binding_handler);
     engine_add_input(&en_flow_output, &en_sb_mac_binding, NULL);
     engine_add_input(&en_flow_output, &en_sb_logical_flow, flow_output_sb_logical_flow_handler);
     engine_add_input(&en_flow_output, &en_sb_dhcp_options, NULL);
diff --git a/ovn/controller/physical.c b/ovn/controller/physical.c
index 41ea9fe..b14051b 100644
--- a/ovn/controller/physical.c
+++ b/ovn/controller/physical.c
@@ -358,7 +358,7 @@  consider_port_binding(struct controller_ctx *ctx,
         ofpact_finish_CLONE(ofpacts_p, &clone);
 
         ofctrl_add_flow(OFTABLE_LOG_TO_PHY, 100, 0,
-                        &match, ofpacts_p, hc_uuid);
+                        &match, ofpacts_p, &binding->header_.uuid);
         return;
     }
 
@@ -426,7 +426,7 @@  consider_port_binding(struct controller_ctx *ctx,
         }
 
         ofctrl_add_flow(OFTABLE_LOCAL_OUTPUT, 100, 0,
-                        &match, ofpacts_p, hc_uuid);
+                        &match, ofpacts_p, &binding->header_.uuid);
 
         goto out;
     }
@@ -558,7 +558,7 @@  consider_port_binding(struct controller_ctx *ctx,
         /* Resubmit to first logical ingress pipeline table. */
         put_resubmit(OFTABLE_LOG_INGRESS_PIPELINE, ofpacts_p);
         ofctrl_add_flow(OFTABLE_PHY_TO_LOG,
-                        tag ? 150 : 100, 0, &match, ofpacts_p, hc_uuid);
+                        tag ? 150 : 100, 0, &match, ofpacts_p, &binding->header_.uuid);
 
         if (!tag && (!strcmp(binding->type, "localnet")
                      || !strcmp(binding->type, "l2gateway"))) {
@@ -568,7 +568,7 @@  consider_port_binding(struct controller_ctx *ctx,
              * action. */
             ofpbuf_pull(ofpacts_p, ofpacts_orig_size);
             match_set_dl_tci_masked(&match, 0, htons(VLAN_CFI));
-            ofctrl_add_flow(0, 100, 0, &match, ofpacts_p, hc_uuid);
+            ofctrl_add_flow(0, 100, 0, &match, ofpacts_p, &binding->header_.uuid);
         }
 
         /* Table 65, Priority 100.
@@ -596,7 +596,7 @@  consider_port_binding(struct controller_ctx *ctx,
             ofpact_put_STRIP_VLAN(ofpacts_p);
         }
         ofctrl_add_flow(OFTABLE_LOG_TO_PHY, 100, 0,
-                        &match, ofpacts_p, hc_uuid);
+                        &match, ofpacts_p, &binding->header_.uuid);
     } else if (!tun && !is_ha_remote) {
         /* Remote port connected by localnet port */
         /* Table 33, priority 100.
@@ -619,7 +619,7 @@  consider_port_binding(struct controller_ctx *ctx,
         /* Resubmit to table 33. */
         put_resubmit(OFTABLE_LOCAL_OUTPUT, ofpacts_p);
         ofctrl_add_flow(OFTABLE_LOCAL_OUTPUT, 100, 0,
-                        &match, ofpacts_p, hc_uuid);
+                        &match, ofpacts_p, &binding->header_.uuid);
     } else {
         /* Remote port connected by tunnel */
 
@@ -710,7 +710,7 @@  consider_port_binding(struct controller_ctx *ctx,
             ofpact_finish_BUNDLE(ofpacts_p, &bundle);
         }
         ofctrl_add_flow(OFTABLE_REMOTE_OUTPUT, 100, 0,
-                        &match, ofpacts_p, hc_uuid);
+                        &match, ofpacts_p, &binding->header_.uuid);
     }
 out:
     if (gateway_chassis) {
@@ -857,6 +857,33 @@  update_ofports(struct simap *old, struct simap *new)
 }
 
 void
+physical_handle_port_binding_changes(struct controller_ctx *ctx, enum mf_field_id mff_ovn_geneve,
+             const struct sbrec_chassis *chassis,
+             const struct simap *ct_zones,
+             struct hmap *local_datapaths,
+             struct chassis_index *chassis_index,
+             struct sset *active_tunnels)
+{
+    const struct sbrec_port_binding *binding;
+    struct ofpbuf ofpacts;
+    ofpbuf_init(&ofpacts, 0);
+    SBREC_PORT_BINDING_FOR_EACH_TRACKED (binding, ctx->ovnsb_idl) {
+        if (sbrec_port_binding_is_deleted(binding)) {
+            ofctrl_remove_flows(&binding->header_.uuid);
+        } else {
+            if (!sbrec_port_binding_is_new(binding)) {
+                ofctrl_remove_flows(&binding->header_.uuid);
+            }
+        consider_port_binding(ctx, mff_ovn_geneve, ct_zones,
+                              chassis_index, active_tunnels,
+                              local_datapaths, binding, chassis,
+                              &ofpacts);
+        }
+    }
+
+}
+
+void
 physical_run(struct controller_ctx *ctx, enum mf_field_id mff_ovn_geneve,
              const struct ovsrec_bridge *br_int,
              const struct sbrec_chassis *chassis,
@@ -978,6 +1005,7 @@  physical_run(struct controller_ctx *ctx, enum mf_field_id mff_ovn_geneve,
     /* Capture changed or removed openflow ports. */
     physical_map_changed |= update_ofports(&localvif_to_ofport,
                                            &new_localvif_to_ofport);
+    // TODO: maybe this is not needed any more?
     if (physical_map_changed) {
         /* Reprocess logical flow table immediately. */
         poll_immediate_wake();
diff --git a/ovn/controller/physical.h b/ovn/controller/physical.h
index 4aeec04..e0b31a4 100644
--- a/ovn/controller/physical.h
+++ b/ovn/controller/physical.h
@@ -51,5 +51,11 @@  void physical_run(struct controller_ctx *, enum mf_field_id mff_ovn_geneve,
                   const struct sset *local_lports,
                   struct chassis_index *chassis_index,
                   struct sset *active_tunnels);
+void physical_handle_port_binding_changes(struct controller_ctx *ctx, enum mf_field_id mff_ovn_geneve,
+             const struct sbrec_chassis *chassis,
+             const struct simap *ct_zones,
+             struct hmap *local_datapaths,
+             struct chassis_index *chassis_index,
+             struct sset *active_tunnels);
 
 #endif /* ovn/physical.h */