Previously we always recomputed lflows on any kind of route changes. With these changes we can now incrementally handle these changes. However because of limitations of the group_ecmp_route engine node we can currently only handle learned routes incrementally.
Signed-off-by: Felix Huettner <[email protected]> --- northd/en-lflow.c | 66 +++++++++++++++++++++++++++++++++++++++- northd/en-lflow.h | 1 + northd/inc-proc-northd.c | 3 +- northd/northd.c | 49 +++++++++++++++++++---------- northd/northd.h | 5 +++ tests/ovn-northd.at | 4 +-- 6 files changed, 108 insertions(+), 20 deletions(-) diff --git a/northd/en-lflow.c b/northd/en-lflow.c index f0117d078..fe79d083c 100644 --- a/northd/en-lflow.c +++ b/northd/en-lflow.c @@ -27,7 +27,7 @@ #include "en-northd.h" #include "en-meters.h" #include "en-sampling-app.h" -#include "en-learned-route-sync.h" +#include "en-group-ecmp-route.h" #include "lflow-mgr.h" #include "lib/inc-proc-eng.h" @@ -268,6 +268,70 @@ lflow_multicast_igmp_handler(struct engine_node *node, void *data) return true; } +bool +lflow_group_ecmp_route_handler(struct engine_node *node, void *data OVS_UNUSED) +{ + struct group_ecmp_route_data *group_ecmp_route_data = + engine_get_input_data("group_ecmp_route", node); + + /* If we do not have tracked data we need to recompute. */ + if (!group_ecmp_route_data->tracked) { + return false; + } + + const struct engine_context *eng_ctx = engine_get_context(); + struct lflow_data *lflow_data = data; + + struct lflow_input lflow_input; + lflow_get_input_data(node, &lflow_input); + + struct group_ecmp_route_node *route_node; + struct hmapx_node *hmapx_node; + + /* We need to handle deletions before additions as they could potentially + * overlap. */ + HMAPX_FOR_EACH (hmapx_node, + &group_ecmp_route_data->trk_data.deleted_routes) { + route_node = hmapx_node->data; + lflow_ref_unlink_lflows(route_node->lflow_ref); + + bool handled = lflow_ref_sync_lflows( + route_node->lflow_ref, lflow_data->lflow_table, + eng_ctx->ovnsb_idl_txn, lflow_input.ls_datapaths, + lflow_input.lr_datapaths, + lflow_input.ovn_internal_version_changed, + lflow_input.sbrec_logical_flow_table, + lflow_input.sbrec_logical_dp_group_table); + if (!handled) { + return false; + } + } + + /* Now we handle created or updated route nodes. */ + HMAPX_FOR_EACH (hmapx_node, + &group_ecmp_route_data->trk_data.crupdated_routes) { + route_node = hmapx_node->data; + lflow_ref_unlink_lflows(route_node->lflow_ref); + build_route_data_flows_for_lrouter( + route_node->od, lflow_data->lflow_table, + route_node, lflow_input.bfd_ports); + + bool handled = lflow_ref_sync_lflows( + route_node->lflow_ref, lflow_data->lflow_table, + eng_ctx->ovnsb_idl_txn, lflow_input.ls_datapaths, + lflow_input.lr_datapaths, + lflow_input.ovn_internal_version_changed, + lflow_input.sbrec_logical_flow_table, + lflow_input.sbrec_logical_dp_group_table); + if (!handled) { + return false; + } + } + + engine_set_node_state(node, EN_UPDATED); + return true; +} + void *en_lflow_init(struct engine_node *node OVS_UNUSED, struct engine_arg *arg OVS_UNUSED) { diff --git a/northd/en-lflow.h b/northd/en-lflow.h index f90f5c61c..2d9b0a540 100644 --- a/northd/en-lflow.h +++ b/northd/en-lflow.h @@ -23,5 +23,6 @@ bool lflow_port_group_handler(struct engine_node *, void *data); bool lflow_lr_stateful_handler(struct engine_node *, void *data); bool lflow_ls_stateful_handler(struct engine_node *node, void *data); bool lflow_multicast_igmp_handler(struct engine_node *node, void *data); +bool lflow_group_ecmp_route_handler(struct engine_node *node, void *data); #endif /* EN_LFLOW_H */ diff --git a/northd/inc-proc-northd.c b/northd/inc-proc-northd.c index 147f54da0..656b56df9 100644 --- a/northd/inc-proc-northd.c +++ b/northd/inc-proc-northd.c @@ -338,7 +338,8 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb, /* XXX: This causes a full lflow recompute on each change to any route. * At least for learned routes we should add incremental processing here. * */ - engine_add_input(&en_lflow, &en_group_ecmp_route, NULL); + engine_add_input(&en_lflow, &en_group_ecmp_route, + lflow_group_ecmp_route_handler); engine_add_input(&en_lflow, &en_global_config, node_global_config_handler); diff --git a/northd/northd.c b/northd/northd.c index 45e43ce37..27149a526 100644 --- a/northd/northd.c +++ b/northd/northd.c @@ -11693,7 +11693,7 @@ find_static_route_outport(const struct ovn_datapath *od, static void add_ecmp_symmetric_reply_flows(struct lflow_table *lflows, - struct ovn_datapath *od, + const struct ovn_datapath *od, const char *port_ip, const struct ovn_port *out_port, const struct parsed_route *route, @@ -11790,7 +11790,8 @@ add_ecmp_symmetric_reply_flows(struct lflow_table *lflows, } static void -build_ecmp_route_flow(struct lflow_table *lflows, struct ovn_datapath *od, +build_ecmp_route_flow(struct lflow_table *lflows, + const struct ovn_datapath *od, struct ecmp_groups_node *eg, struct lflow_ref *lflow_ref, const char *protocol) @@ -11909,7 +11910,7 @@ build_ecmp_route_flow(struct lflow_table *lflows, struct ovn_datapath *od, } static void -add_route(struct lflow_table *lflows, struct ovn_datapath *od, +add_route(struct lflow_table *lflows, const struct ovn_datapath *od, const struct ovn_port *op, const char *lrp_addr_s, const char *network_s, int plen, const struct in6_addr *gateway, bool is_src_route, const uint32_t rtb_id, @@ -11983,10 +11984,9 @@ add_route(struct lflow_table *lflows, struct ovn_datapath *od, } static void -build_route_flow(struct lflow_table *lflows, struct ovn_datapath *od, - const struct parsed_route *route, - const struct sset *bfd_ports, - struct lflow_ref *lflow_ref) +build_route_flow(struct lflow_table *lflows, const struct ovn_datapath *od, + const struct parsed_route *route, + const struct sset *bfd_ports, struct lflow_ref *lflow_ref) { bool is_ipv4_prefix = IN6_IS_ADDR_V4MAPPED(&route->prefix); bool is_ipv4_nexthop = route->nexthop @@ -13820,12 +13820,10 @@ build_ip_routing_pre_flows_for_lrouter(struct ovn_datapath *od, } static void -build_route_flows_for_lrouter( +build_default_route_flows_for_lrouter( struct ovn_datapath *od, struct lflow_table *lflows, - const struct group_ecmp_route_data *route_data, - struct simap *route_tables, const struct sset *bfd_ports) + struct simap *route_tables) { - ovs_assert(od->nbr); ovn_lflow_add_default_drop(lflows, od, S_ROUTER_IN_IP_ROUTING_ECMP, NULL); ovn_lflow_add_default_drop(lflows, od, S_ROUTER_IN_IP_ROUTING, @@ -13839,12 +13837,14 @@ build_route_flows_for_lrouter( route_tables, NULL); } - const struct group_ecmp_route_node *route_node = - group_ecmp_route_lookup(route_data, od); - if (!route_node) { - return; - } +} +void +build_route_data_flows_for_lrouter( + const struct ovn_datapath *od, struct lflow_table *lflows, + const struct group_ecmp_route_node *route_node, + const struct sset *bfd_ports) +{ struct ecmp_groups_node *group; HMAP_FOR_EACH (group, hmap_node, &route_node->ecmp_groups) { /* add a flow in IP_ROUTING, and one flow for each member in @@ -13870,6 +13870,23 @@ build_route_flows_for_lrouter( } } +static void +build_route_flows_for_lrouter( + struct ovn_datapath *od, struct lflow_table *lflows, + const struct group_ecmp_route_data *route_data, + struct simap *route_tables, const struct sset *bfd_ports) +{ + ovs_assert(od->nbr); + build_default_route_flows_for_lrouter(od, lflows, route_tables); + + const struct group_ecmp_route_node *route_node = + group_ecmp_route_lookup(route_data, od); + if (!route_node) { + return; + } + build_route_data_flows_for_lrouter(od, lflows, route_node, bfd_ports); +} + static void build_lrouter_ip_mcast_igmp_mld(struct ovn_igmp_group *igmp_group, struct lflow_table *lflows, diff --git a/northd/northd.h b/northd/northd.h index b83efdb63..949589939 100644 --- a/northd/northd.h +++ b/northd/northd.h @@ -859,11 +859,16 @@ void bfd_sync_destroy(struct bfd_sync_data *); struct lflow_table; struct lr_stateful_tracked_data; struct ls_stateful_tracked_data; +struct group_ecmp_route_node; void build_lflows(struct ovsdb_idl_txn *ovnsb_txn, struct lflow_input *input_data, struct lflow_table *); void lflow_reset_northd_refs(struct lflow_input *); +void build_route_data_flows_for_lrouter( + const struct ovn_datapath *, struct lflow_table *, + const struct group_ecmp_route_node *, const struct sset *); + bool lflow_handle_northd_port_changes(struct ovsdb_idl_txn *ovnsb_txn, struct tracked_ovn_ports *, diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at index b70deade3..71b7ed944 100644 --- a/tests/ovn-northd.at +++ b/tests/ovn-northd.at @@ -15643,7 +15643,7 @@ check_engine_compute routes unchanged check_engine_compute advertised_route_sync unchanged check_engine_compute learned_route_sync incremental check_engine_compute group_ecmp_route incremental -check_engine_compute lflow recompute +check_engine_compute lflow incremental CHECK_NO_CHANGE_AFTER_RECOMPUTE check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats @@ -15654,7 +15654,7 @@ check_engine_compute routes unchanged check_engine_compute advertised_route_sync unchanged check_engine_compute learned_route_sync incremental check_engine_compute group_ecmp_route incremental -check_engine_compute lflow recompute +check_engine_compute lflow incremental CHECK_NO_CHANGE_AFTER_RECOMPUTE check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats -- 2.48.1 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
