[ovs-dev] [PATCH v5 08/20] ovn-controller: Incremental logical flow processing

Han Zhou zhouhan at gmail.com
Mon Aug 13 17:48:07 UTC 2018


Implements change handler of flow_output for SB lflow changes.

Signed-off-by: Han Zhou <hzhou8 at ebay.com>
---
 ovn/controller/lflow.c          | 84 +++++++++++++++++++++++++++++++++++++++++
 ovn/controller/lflow.h          | 18 +++++++++
 ovn/controller/ovn-controller.c | 76 ++++++++++++++++++++++++++++++++++++-
 3 files changed, 177 insertions(+), 1 deletion(-)

diff --git a/ovn/controller/lflow.c b/ovn/controller/lflow.c
index 72b1ec7..f7cb6d4 100644
--- a/ovn/controller/lflow.c
+++ b/ovn/controller/lflow.c
@@ -200,6 +200,90 @@ add_logical_flows(
     nd_ra_opts_destroy(&nd_ra_opts);
 }
 
+bool
+lflow_handle_changed_flows(
+    struct ovsdb_idl_index *sbrec_chassis_by_name,
+    struct ovsdb_idl_index *sbrec_multicast_group_by_name_datapath,
+    struct ovsdb_idl_index *sbrec_port_binding_by_name,
+    const struct sbrec_dhcp_options_table *dhcp_options_table,
+    const struct sbrec_dhcpv6_options_table *dhcpv6_options_table,
+    const struct sbrec_logical_flow_table *logical_flow_table,
+    const struct hmap *local_datapaths,
+    const struct sbrec_chassis *chassis,
+    const struct shash *addr_sets,
+    const struct shash *port_groups,
+    const struct sset *active_tunnels,
+    const struct sset *local_lport_ids,
+    struct ovn_desired_flow_table *flow_table,
+    struct ovn_extend_table *group_table,
+    struct ovn_extend_table *meter_table,
+    uint32_t *conj_id_ofs)
+{
+    bool ret = true;
+    const struct sbrec_logical_flow *lflow;
+
+    struct hmap dhcp_opts = HMAP_INITIALIZER(&dhcp_opts);
+    struct hmap dhcpv6_opts = HMAP_INITIALIZER(&dhcpv6_opts);
+    const struct sbrec_dhcp_options *dhcp_opt_row;
+    SBREC_DHCP_OPTIONS_TABLE_FOR_EACH (dhcp_opt_row, dhcp_options_table) {
+        dhcp_opt_add(&dhcp_opts, dhcp_opt_row->name, dhcp_opt_row->code,
+                     dhcp_opt_row->type);
+    }
+
+
+    const struct sbrec_dhcpv6_options *dhcpv6_opt_row;
+    SBREC_DHCPV6_OPTIONS_TABLE_FOR_EACH (dhcpv6_opt_row,
+                                         dhcpv6_options_table) {
+       dhcp_opt_add(&dhcpv6_opts, dhcpv6_opt_row->name, dhcpv6_opt_row->code,
+                    dhcpv6_opt_row->type);
+    }
+
+    struct hmap nd_ra_opts = HMAP_INITIALIZER(&nd_ra_opts);
+    nd_ra_opts_init(&nd_ra_opts);
+
+    /* Handle removed flows first, and then other flows, so that when
+     * the flows being added and removed have same match conditions
+     * can be processed in the proper order */
+    SBREC_LOGICAL_FLOW_TABLE_FOR_EACH_TRACKED (lflow, logical_flow_table) {
+        /* Remove any flows that should be removed. */
+        if (sbrec_logical_flow_is_deleted(lflow)) {
+            VLOG_DBG("handle deleted lflow "UUID_FMT,
+                     UUID_ARGS(&lflow->header_.uuid));
+            ofctrl_remove_flows(flow_table, &lflow->header_.uuid);
+        }
+    }
+    SBREC_LOGICAL_FLOW_TABLE_FOR_EACH_TRACKED (lflow, logical_flow_table) {
+        if (!sbrec_logical_flow_is_deleted(lflow)) {
+            /* Now, add/modify existing flows. If the logical
+             * flow is a modification, just remove the flows
+             * for this row, and then add new flows. */
+            if (!sbrec_logical_flow_is_new(lflow)) {
+                VLOG_DBG("handle updated lflow "UUID_FMT,
+                         UUID_ARGS(&lflow->header_.uuid));
+                ofctrl_remove_flows(flow_table, &lflow->header_.uuid);
+            }
+            VLOG_DBG("handle new lflow "UUID_FMT,
+                     UUID_ARGS(&lflow->header_.uuid));
+            if (!consider_logical_flow(sbrec_chassis_by_name,
+                                       sbrec_multicast_group_by_name_datapath,
+                                       sbrec_port_binding_by_name,
+                                       lflow, local_datapaths,
+                                       chassis, &dhcp_opts, &dhcpv6_opts,
+                                       &nd_ra_opts, addr_sets, port_groups,
+                                       active_tunnels, local_lport_ids,
+                                       flow_table, group_table, meter_table,
+                                       conj_id_ofs)) {
+                ret = false;
+                break;
+            }
+        }
+    }
+    dhcp_opts_destroy(&dhcp_opts);
+    dhcp_opts_destroy(&dhcpv6_opts);
+    nd_ra_opts_destroy(&nd_ra_opts);
+    return ret;
+}
+
 static bool
 update_conj_id_ofs(uint32_t *conj_id_ofs, uint32_t n_conjs)
 {
diff --git a/ovn/controller/lflow.h b/ovn/controller/lflow.h
index b4120d0..31e34e2 100644
--- a/ovn/controller/lflow.h
+++ b/ovn/controller/lflow.h
@@ -84,6 +84,24 @@ void lflow_run(struct ovsdb_idl_index *sbrec_chassis_by_name,
                struct ovn_extend_table *meter_table,
                uint32_t *conj_id_ofs);
 
+bool lflow_handle_changed_flows(
+    struct ovsdb_idl_index *sbrec_chassis_by_name,
+    struct ovsdb_idl_index *sbrec_multicast_group_by_name_datapath,
+    struct ovsdb_idl_index *sbrec_port_binding_by_name,
+    const struct sbrec_dhcp_options_table *,
+    const struct sbrec_dhcpv6_options_table *,
+    const struct sbrec_logical_flow_table *,
+    const struct hmap *local_datapaths,
+    const struct sbrec_chassis *,
+    const struct shash *addr_sets,
+    const struct shash *port_groups,
+    const struct sset *active_tunnels,
+    const struct sset *local_lport_ids,
+    struct ovn_desired_flow_table *,
+    struct ovn_extend_table *group_table,
+    struct ovn_extend_table *meter_table,
+    uint32_t *conj_id_ofs);
+
 void lflow_destroy(void);
 
 #endif /* ovn/lflow.h */
diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c
index bfe99dd..5c24cba 100644
--- a/ovn/controller/ovn-controller.c
+++ b/ovn/controller/ovn-controller.c
@@ -973,6 +973,80 @@ en_flow_output_run(struct engine_node *node)
     node->changed = true;
 }
 
+static bool
+flow_output_sb_logical_flow_handler(struct engine_node *node)
+{
+    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 *local_lport_ids = &data->local_lport_ids;
+    struct sset *active_tunnels = &data->active_tunnels;
+    struct shash *addr_sets = &data->addr_sets;
+    struct shash *port_groups = &data->port_groups;
+
+    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 struct ovsrec_bridge *br_int = get_br_int(bridge_table, ovs_table);
+    const char *chassis_id = get_chassis_id(ovs_table);
+
+    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 = NULL;
+    if (chassis_id) {
+        chassis = chassis_lookup_by_name(sbrec_chassis_by_name, chassis_id);
+    }
+
+    ovs_assert(br_int && chassis);
+
+    struct ed_type_flow_output *fo =
+        (struct ed_type_flow_output *)node->data;
+    struct ovn_desired_flow_table *flow_table = &fo->flow_table;
+    struct ovn_extend_table *group_table = &fo->group_table;
+    struct ovn_extend_table *meter_table = &fo->meter_table;
+    uint32_t *conj_id_ofs = &fo->conj_id_ofs;
+
+    struct ovsdb_idl_index *sbrec_multicast_group_by_name_datapath =
+        engine_ovsdb_node_get_index(
+                engine_get_input("SB_multicast_group", node),
+                "name_datapath");
+
+    struct ovsdb_idl_index *sbrec_port_binding_by_name =
+        engine_ovsdb_node_get_index(
+                engine_get_input("SB_port_binding", node),
+                "name");
+
+    struct sbrec_dhcp_options_table *dhcp_table =
+        (struct sbrec_dhcp_options_table *)EN_OVSDB_GET(
+            engine_get_input("SB_dhcp_options", node));
+
+    struct sbrec_dhcpv6_options_table *dhcpv6_table =
+        (struct sbrec_dhcpv6_options_table *)EN_OVSDB_GET(
+            engine_get_input("SB_dhcpv6_options", node));
+
+    struct sbrec_logical_flow_table *logical_flow_table =
+        (struct sbrec_logical_flow_table *)EN_OVSDB_GET(
+            engine_get_input("SB_logical_flow", node));
+
+    bool handled = lflow_handle_changed_flows(sbrec_chassis_by_name,
+              sbrec_multicast_group_by_name_datapath,
+              sbrec_port_binding_by_name,
+              dhcp_table, dhcpv6_table,
+              logical_flow_table,
+              local_datapaths, chassis, addr_sets,
+              port_groups, active_tunnels, local_lport_ids,
+              flow_table, group_table, meter_table, conj_id_ofs);
+
+    node->changed = true;
+    return handled;
+}
+
 struct ovn_controller_exit_args {
     bool *exiting;
     bool *restart;
@@ -1092,7 +1166,7 @@ main(int argc, char *argv[])
     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_mac_binding, NULL);
-    engine_add_input(&en_flow_output, &en_sb_logical_flow, 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);
     engine_add_input(&en_flow_output, &en_sb_dhcpv6_options, NULL);
     engine_add_input(&en_flow_output, &en_sb_dns, NULL);
-- 
2.1.0



More information about the dev mailing list