en_route_policies was mostly defined in en-northd.h and en-northd.c. It calls out to functions and uses structures that are defined in northd.h and northd.c. In many cases, these functions were one-off uses that did not need to be exported in a header file.
To reduce the annoyingness factor, this commit moves en-route-policies to its own file. Along with it, this commit moves certain functions out of northd and into en-route-policies.c as static functions. There are no functionality changes in this commit. This only moves functions around so they are better organized. Signed-off-by: Mark Michelson <[email protected]> --- northd/automake.mk | 2 + northd/en-lflow.c | 1 + northd/en-northd.c | 117 +---------- northd/en-northd.h | 11 - northd/en-route-policies.c | 408 +++++++++++++++++++++++++++++++++++++ northd/en-route-policies.h | 56 +++++ northd/inc-proc-northd.c | 1 + northd/northd.c | 313 +--------------------------- northd/northd.h | 48 +++-- 9 files changed, 515 insertions(+), 442 deletions(-) create mode 100644 northd/en-route-policies.c create mode 100644 northd/en-route-policies.h diff --git a/northd/automake.mk b/northd/automake.mk index 1d3044930..06c35276f 100644 --- a/northd/automake.mk +++ b/northd/automake.mk @@ -34,6 +34,8 @@ northd_ovn_northd_SOURCES = \ northd/en-northd-output.h \ northd/en-port-group.c \ northd/en-port-group.h \ + northd/en-route-policies.c \ + northd/en-route-policies.h \ northd/en-sync-sb.c \ northd/en-sync-sb.h \ northd/en-sync-from-sb.c \ diff --git a/northd/en-lflow.c b/northd/en-lflow.c index f2ae40ec8..aa1cab3df 100644 --- a/northd/en-lflow.c +++ b/northd/en-lflow.c @@ -29,6 +29,7 @@ #include "en-sampling-app.h" #include "en-group-ecmp-route.h" #include "en-datapath-sync.h" +#include "en-route-policies.h" #include "lflow-mgr.h" #include "lib/inc-proc-eng.h" diff --git a/northd/en-northd.c b/northd/en-northd.c index 5286dbbb2..db0d4e413 100644 --- a/northd/en-northd.c +++ b/northd/en-northd.c @@ -1,4 +1,4 @@ - /* +/* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -32,6 +32,7 @@ #include "lib/util.h" #include "openvswitch/vlog.h" #include "en-datapath-logical-router.h" +#include "en-route-policies.h" VLOG_DEFINE_THIS_MODULE(en_northd); COVERAGE_DEFINE(northd_run); @@ -278,94 +279,6 @@ northd_nb_port_group_handler(struct engine_node *node, void *data) return EN_HANDLED_UNCHANGED; } -enum engine_input_handler_result -route_policies_northd_change_handler(struct engine_node *node, - void *data OVS_UNUSED) -{ - struct northd_data *northd_data = engine_get_input_data("northd", node); - if (!northd_has_tracked_data(&northd_data->trk_data)) { - return EN_UNHANDLED; - } - - /* This node uses the below data from the en_northd engine node. - * See (lr_stateful_get_input_data()) - * 1. northd_data->lr_datapaths - * This data gets updated when a logical router or logical router port - * is created or deleted. - * Northd engine node presently falls back to full recompute when - * this happens and so does this node. - * - */ - - return EN_HANDLED_UNCHANGED; -} - -enum engine_input_handler_result -route_policies_datapath_synced_logical_router_handler(struct engine_node *node, - void *data OVS_UNUSED) -{ - const struct ovn_synced_logical_router_map *synced_lrs = - engine_get_input_data("datapath_synced_logical_router", node); - - if (hmapx_is_empty(&synced_lrs->new) && - hmapx_is_empty(&synced_lrs->updated) && - hmapx_is_empty(&synced_lrs->deleted)) { - return EN_UNHANDLED; - } - - struct hmapx_node *lr_node; - HMAPX_FOR_EACH (lr_node, &synced_lrs->deleted) { - const struct ovn_synced_logical_router *lr = lr_node->data; - if (lr->nb->n_policies > 0) { - return EN_UNHANDLED; - } - } - - HMAPX_FOR_EACH (lr_node, &synced_lrs->new) { - const struct ovn_synced_logical_router *lr = lr_node->data; - if (lr->nb->n_policies > 0) { - return EN_UNHANDLED; - } - } - - HMAPX_FOR_EACH (lr_node, &synced_lrs->updated) { - const struct ovn_synced_logical_router *lr = lr_node->data; - if (nbrec_logical_router_is_updated( - lr->nb, NBREC_LOGICAL_ROUTER_COL_POLICIES)) { - return EN_UNHANDLED; - } - for (size_t i = 0; i < lr->nb->n_policies; i++) { - if (nbrec_logical_router_policy_row_get_seqno(lr->nb->policies[i], - OVSDB_IDL_CHANGE_MODIFY) > 0) { - return EN_UNHANDLED; - } - } - } - - return EN_HANDLED_UNCHANGED; -} - -enum engine_node_state -en_route_policies_run(struct engine_node *node, void *data) -{ - struct northd_data *northd_data = engine_get_input_data("northd", node); - struct bfd_data *bfd_data = engine_get_input_data("bfd", node); - struct route_policies_data *route_policies_data = data; - - route_policies_destroy(data); - route_policies_init(data); - - struct ovn_datapath *od; - HMAP_FOR_EACH (od, key_node, &northd_data->lr_datapaths.datapaths) { - build_route_policies(od, &bfd_data->bfd_connections, - &route_policies_data->route_policies, - &route_policies_data->bfd_active_connections, - &route_policies_data->chain_ids); - } - - return EN_UPDATED; -} - enum engine_input_handler_result routes_northd_change_handler(struct engine_node *node, void *data OVS_UNUSED) @@ -553,6 +466,12 @@ en_routes_run(struct engine_node *node, void *data) return EN_UPDATED; } +static void +destroy_bfd_data(struct bfd_data *data) +{ + bfd_destroy(&data->bfd_connections); +} + enum engine_node_state en_bfd_run(struct engine_node *node, void *data) { @@ -562,7 +481,7 @@ en_bfd_run(struct engine_node *node, void *data) const struct sbrec_bfd_table *sbrec_bfd_table = EN_OVSDB_GET(engine_get_input("SB_bfd", node)); - bfd_destroy(data); + destroy_bfd_data(data); bfd_init(data); build_bfd_map(nbrec_bfd_table, sbrec_bfd_table, &bfd_data->bfd_connections); @@ -661,16 +580,6 @@ void return data; } -void -*en_route_policies_init(struct engine_node *node OVS_UNUSED, - struct engine_arg *arg OVS_UNUSED) -{ - struct route_policies_data *data = xzalloc(sizeof *data); - - route_policies_init(data); - return data; -} - void *en_routes_init(struct engine_node *node OVS_UNUSED, struct engine_arg *arg OVS_UNUSED) @@ -758,12 +667,6 @@ northd_sb_fdb_change_handler(struct engine_node *node, void *data) return EN_HANDLED_UNCHANGED; } -void -en_route_policies_cleanup(void *data) -{ - route_policies_destroy(data); -} - void en_routes_cleanup(void *data) { @@ -779,7 +682,7 @@ en_routes_clear_tracked_data(void *data) void en_bfd_cleanup(void *data) { - bfd_destroy(data); + destroy_bfd_data(data); } void diff --git a/northd/en-northd.h b/northd/en-northd.h index 706b49e45..6fbf36749 100644 --- a/northd/en-northd.h +++ b/northd/en-northd.h @@ -31,17 +31,6 @@ enum engine_input_handler_result northd_sb_fdb_change_handler(struct engine_node *node, void *data); void *en_routes_init(struct engine_node *node OVS_UNUSED, struct engine_arg *arg OVS_UNUSED); -void en_route_policies_cleanup(void *data); -enum engine_input_handler_result -route_policies_northd_change_handler(struct engine_node *node, - void *data OVS_UNUSED); -enum engine_input_handler_result -route_policies_datapath_synced_logical_router_handler(struct engine_node *node, - void *data OVS_UNUSED); -enum engine_node_state en_route_policies_run(struct engine_node *node, - void *data); -void *en_route_policies_init(struct engine_node *node OVS_UNUSED, - struct engine_arg *arg OVS_UNUSED); void en_routes_clear_tracked_data(void *data); void en_routes_cleanup(void *data); enum engine_input_handler_result diff --git a/northd/en-route-policies.c b/northd/en-route-policies.c new file mode 100644 index 000000000..dd6d182e8 --- /dev/null +++ b/northd/en-route-policies.c @@ -0,0 +1,408 @@ +/* + * Copyright (c) 2026, Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include <config.h> + +#include "en-datapath-logical-router.h" +#include "en-route-policies.h" +#include "northd.h" +#include "ovn-nb-idl.h" + +#include "openvswitch/vlog.h" + +VLOG_DEFINE_THIS_MODULE(en_route_policies); + +static struct route_policy * +route_policies_lookup(struct hmap *route_policies, size_t hash, + struct route_policy *new_rp) +{ + struct route_policy *rp; + HMAP_FOR_EACH_WITH_HASH (rp, key_node, hash, route_policies) { + if (rp->rule != new_rp->rule) { + continue; + } + + if (rp->chain_id != new_rp->chain_id) { + continue; + } + + if (rp->jump_chain_id != new_rp->jump_chain_id) { + continue; + } + + if (rp->n_valid_nexthops != new_rp->n_valid_nexthops) { + continue; + } + + size_t i; + for (i = 0; i < new_rp->n_valid_nexthops; i++) { + size_t j; + + for (j = 0; j < rp->n_valid_nexthops; j++) { + if (!strcmp(new_rp->valid_nexthops[i], + rp->valid_nexthops[j])) { + break; + } + } + + if (j == rp->n_valid_nexthops) { + break; + } + } + + if (i == new_rp->n_valid_nexthops) { + return rp; + } + } + + return NULL; +} + +static bool +policy_chain_id(struct simap *chain_ids, const char *chain_name, uint32_t *id) +{ + if (chain_name && *chain_name) { + *id = simap_get(chain_ids, chain_name); + return true; + } + + return false; +} + +static void +policy_chain_add(struct simap *chain_ids, const char *chain_name) +{ + uint32_t id = simap_count(chain_ids) + 1; + + if (id == UINT16_MAX) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); + VLOG_WARN_RL(&rl, "Too many policy chains for Logical Router."); + return; + } + + if (!simap_put(chain_ids, chain_name, id)) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); + VLOG_WARN_RL(&rl, "Policy chain id unexpectedly appeared"); + } +} + +static bool +check_bfd_state(const struct nbrec_logical_router_policy *rule, + struct ovn_port *out_port, const char *nexthop, + const struct hmap *bfd_connections, + struct hmap *bfd_active_connections) +{ + struct in6_addr nexthop_v6; + bool is_nexthop_v6 = ipv6_parse(nexthop, &nexthop_v6); + + for (size_t i = 0; i < rule->n_bfd_sessions; i++) { + /* Check if there is a BFD session associated to the reroute + * policy. */ + const struct nbrec_bfd *nb_bt = rule->bfd_sessions[i]; + struct in6_addr dst_ipv6; + bool is_dst_v6 = ipv6_parse(nb_bt->dst_ip, &dst_ipv6); + + if (is_nexthop_v6 ^ is_dst_v6) { + continue; + } + + if ((is_nexthop_v6 && !ipv6_addr_equals(&nexthop_v6, &dst_ipv6)) || + strcmp(nb_bt->dst_ip, nexthop)) { + continue; + } + + if (strcmp(nb_bt->logical_port, out_port->key)) { + continue; + } + + struct bfd_entry *bfd_e = bfd_port_lookup(bfd_connections, + nb_bt->logical_port, + nb_bt->dst_ip); + if (!bfd_e) { + continue; + } + + /* This route policy is linked to an active bfd session. */ + struct bfd_entry *bfd_rp = bfd_port_lookup(bfd_active_connections, + nb_bt->logical_port, + nb_bt->dst_ip); + if (!bfd_rp) { + bfd_rp = bfd_alloc_entry(bfd_active_connections, + nb_bt->logical_port, nb_bt->dst_ip, + bfd_e->status); + } + + if (!strcmp(bfd_e->status, "admin_down")) { + bfd_set_status(bfd_rp, "down"); + } + + return strcmp(bfd_rp->status, "down"); + } + + return true; +} + +static void +build_route_policies(struct ovn_datapath *od, + const struct hmap *bfd_connections, + struct hmap *route_policies, + struct hmap *bfd_active_connections, + struct simap *chain_ids) +{ + struct route_policy *rp; + + /* Create chain numeric ids for policies with chain name set */ + for (int i = 0; i < od->nbr->n_policies; i++) { + const struct nbrec_logical_router_policy *rule = od->nbr->policies[i]; + uint32_t id; + + if (policy_chain_id(chain_ids, rule->chain, &id) && id == 0) { + policy_chain_add(chain_ids, rule->chain); + } + } + + for (int i = 0; i < od->nbr->n_policies; i++) { + const struct nbrec_logical_router_policy *rule = od->nbr->policies[i]; + + if (rule->nexthop && rule->nexthop[0]) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); + VLOG_WARN_RL(&rl, "Logical router: %s, policy uses deprecated" + " column \"nexthop\", this column is ignored. Please" + "use \"nexthops\" column instead.", od->nbr->name); + continue; + } + + size_t n_valid_nexthops = 0; + char **valid_nexthops = NULL; + uint32_t chain_id = 0; + uint32_t jump_chain_id = 0; + + /* Skip policy if chain name is set but id was not created above */ + if (policy_chain_id(chain_ids, rule->chain, &chain_id) + && chain_id == 0) { + continue; + } + + if (!strcmp(rule->action, "jump")) { + /* Skip policy if action is 'jump' but no target chain is set */ + if (!policy_chain_id(chain_ids, rule->jump_chain, + &jump_chain_id)) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); + VLOG_WARN_RL(&rl, + "Logical router: %s, policy action 'jump'" + " has empty target", + od->nbr->name); + continue; + } + + /* Skip policy if action is 'jump' but target chain name + is not resolved to numeric id */ + if (jump_chain_id == 0) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); + VLOG_WARN_RL(&rl, + "Logical router: %s, policy action 'jump'" + " follows to non-existent chain %s", + od->nbr->name, rule->jump_chain); + continue; + } + } + + if (simap_is_empty(chain_ids)) { + chain_id = -1; + } + + if (!strcmp(rule->action, "reroute")) { + if (rule->output_port && rule->n_nexthops != 1) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); + VLOG_WARN_RL(&rl, + "Logical router: %s, policy " + "(chain: '%s', match: '%s', priority %"PRId64"): " + "output_port only supported on non-ECMP " + "reroute policies", + od->nbr->name, + rule->chain ? rule->chain : "<Default>", + rule->match, rule->priority); + continue; + } + + valid_nexthops = xcalloc(rule->n_nexthops, sizeof *valid_nexthops); + for (size_t j = 0; j < rule->n_nexthops; j++) { + char *nexthop = rule->nexthops[j]; + if (!nexthop || !nexthop[0]) { + continue; + } + + struct ovn_port *out_port = NULL; + bool is_ipv4 = strchr(nexthop, '.') ? true : false; + + if (!find_policy_outport(od, rule, nexthop, is_ipv4, NULL, + &out_port)) { + continue; + } + if (!check_bfd_state(rule, out_port, nexthop, + bfd_connections, + bfd_active_connections)) { + continue; + } + valid_nexthops[n_valid_nexthops++] = nexthop; + } + + if (!n_valid_nexthops) { + free(valid_nexthops); + continue; + } + } + + struct route_policy *new_rp = xzalloc(sizeof *new_rp); + new_rp->rule = rule; + new_rp->n_valid_nexthops = n_valid_nexthops; + new_rp->valid_nexthops = valid_nexthops; + new_rp->chain_id = chain_id; + new_rp->jump_chain_id = jump_chain_id; + + size_t hash = uuid_hash(&od->key); + rp = route_policies_lookup(route_policies, hash, new_rp); + if (!rp) { + hmap_insert(route_policies, &new_rp->key_node, hash); + } else { + free(valid_nexthops); + free(new_rp); + } + } +} + +static void +route_policies_init(struct route_policies_data *data) +{ + hmap_init(&data->route_policies); + hmap_init(&data->bfd_active_connections); + simap_init(&data->chain_ids); +} + +static void +route_policies_destroy(struct route_policies_data *data) +{ + struct route_policy *rp; + HMAP_FOR_EACH_POP (rp, key_node, &data->route_policies) { + free(rp->valid_nexthops); + free(rp); + }; + hmap_destroy(&data->route_policies); + bfd_destroy(&data->bfd_active_connections); + simap_destroy(&data->chain_ids); +} + +enum engine_node_state +en_route_policies_run(struct engine_node *node, void *data) +{ + struct northd_data *northd_data = engine_get_input_data("northd", node); + struct bfd_data *bfd_data = engine_get_input_data("bfd", node); + struct route_policies_data *route_policies_data = data; + + route_policies_destroy(data); + route_policies_init(data); + + struct ovn_datapath *od; + HMAP_FOR_EACH (od, key_node, &northd_data->lr_datapaths.datapaths) { + build_route_policies(od, &bfd_data->bfd_connections, + &route_policies_data->route_policies, + &route_policies_data->bfd_active_connections, + &route_policies_data->chain_ids); + } + + return EN_UPDATED; +} + +void +*en_route_policies_init(struct engine_node *node OVS_UNUSED, + struct engine_arg *arg OVS_UNUSED) +{ + struct route_policies_data *data = xzalloc(sizeof *data); + + route_policies_init(data); + return data; +} + +void +en_route_policies_cleanup(void *data) +{ + route_policies_destroy(data); +} + +enum engine_input_handler_result +route_policies_northd_change_handler(struct engine_node *node, + void *data OVS_UNUSED) +{ + struct northd_data *northd_data = engine_get_input_data("northd", node); + if (!northd_has_tracked_data(&northd_data->trk_data)) { + return EN_UNHANDLED; + } + + /* This node uses the below data from the en_northd engine node. + * See (lr_stateful_get_input_data()) + * 1. northd_data->lr_datapaths + * This data gets updated when a logical router or logical router port + * is created or deleted. + * Northd engine node presently falls back to full recompute when + * this happens and so does this node. + */ + + return EN_HANDLED_UNCHANGED; +} + +enum engine_input_handler_result +route_policies_datapath_synced_logical_router_handler(struct engine_node *node, + void *data OVS_UNUSED) +{ + const struct ovn_synced_logical_router_map *synced_lrs = + engine_get_input_data("datapath_synced_logical_router", node); + + if (hmapx_is_empty(&synced_lrs->new) && + hmapx_is_empty(&synced_lrs->updated) && + hmapx_is_empty(&synced_lrs->deleted)) { + return EN_UNHANDLED; + } + + struct hmapx_node *lr_node; + HMAPX_FOR_EACH (lr_node, &synced_lrs->deleted) { + const struct ovn_synced_logical_router *lr = lr_node->data; + if (lr->nb->n_policies > 0) { + return EN_UNHANDLED; + } + } + + HMAPX_FOR_EACH (lr_node, &synced_lrs->new) { + const struct ovn_synced_logical_router *lr = lr_node->data; + if (lr->nb->n_policies > 0) { + return EN_UNHANDLED; + } + } + + HMAPX_FOR_EACH (lr_node, &synced_lrs->updated) { + const struct ovn_synced_logical_router *lr = lr_node->data; + if (nbrec_logical_router_is_updated( + lr->nb, NBREC_LOGICAL_ROUTER_COL_POLICIES)) { + return EN_UNHANDLED; + } + for (size_t i = 0; i < lr->nb->n_policies; i++) { + if (nbrec_logical_router_policy_row_get_seqno(lr->nb->policies[i], + OVSDB_IDL_CHANGE_MODIFY) > 0) { + return EN_UNHANDLED; + } + } + } + + return EN_HANDLED_UNCHANGED; +} diff --git a/northd/en-route-policies.h b/northd/en-route-policies.h new file mode 100644 index 000000000..1d2288e46 --- /dev/null +++ b/northd/en-route-policies.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2026, Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef EN_ROUTE_POLICIES_H +#define EN_ROUTE_POLICIES_H + +#include "inc-proc-eng.h" + +#include "lib/simap.h" +#include "openvswitch/hmap.h" + +/* Represents the data associated with an instance of a northbound + * Logical Router Policy for a particular Logical Router. + */ +struct route_policy { + struct hmap_node key_node; + const struct nbrec_logical_router_policy *rule; + size_t n_valid_nexthops; + char **valid_nexthops; + uint32_t chain_id; + uint32_t jump_chain_id; +}; + +/* Global route policy data exported by en-route-policies. */ +struct route_policies_data { + struct hmap route_policies; + struct hmap bfd_active_connections; + struct simap chain_ids; +}; + +void en_route_policies_cleanup(void *data); +enum engine_input_handler_result +route_policies_northd_change_handler(struct engine_node *node, + void *data OVS_UNUSED); +enum engine_input_handler_result +route_policies_datapath_synced_logical_router_handler(struct engine_node *node, + void *data OVS_UNUSED); +enum engine_node_state en_route_policies_run(struct engine_node *node, + void *data); +void *en_route_policies_init(struct engine_node *node OVS_UNUSED, + struct engine_arg *arg OVS_UNUSED); + +#endif /* EN_ROUTE_POLICIES_H */ diff --git a/northd/inc-proc-northd.c b/northd/inc-proc-northd.c index e28cd9d97..84c40fdd2 100644 --- a/northd/inc-proc-northd.c +++ b/northd/inc-proc-northd.c @@ -51,6 +51,7 @@ #include "en-datapath-logical-router.h" #include "en-datapath-logical-switch.h" #include "en-datapath-sync.h" +#include "en-route-policies.h" #include "unixctl.h" #include "util.h" diff --git a/northd/northd.c b/northd/northd.c index 5aaf320d1..c23b4ffc1 100644 --- a/northd/northd.c +++ b/northd/northd.c @@ -54,6 +54,7 @@ #include "en-sampling-app.h" #include "en-datapath-logical-switch.h" #include "en-datapath-logical-router.h" +#include "en-route-policies.h" #include "lib/ovn-parallel-hmap.h" #include "ovn/actions.h" #include "ovn/features.h" @@ -11880,19 +11881,7 @@ build_lswitch_ip_unicast_lookup_for_nats( } } -struct bfd_entry { - struct hmap_node hmap_node; - - const struct nbrec_bfd *nb_bt; - const struct sbrec_bfd *sb_bt; - - char *logical_port; - char *dst_ip; - char *status; - bool stale; -}; - -static struct bfd_entry * +struct bfd_entry * bfd_alloc_entry(struct hmap *bfd_connections, const char *logical_port, const char *dst_ip, const char *status) @@ -11908,7 +11897,7 @@ bfd_alloc_entry(struct hmap *bfd_connections, return bfd_e; } -static void +void bfd_erase_entry(struct bfd_entry *bfd_e) { free(bfd_e->logical_port); @@ -11917,14 +11906,14 @@ bfd_erase_entry(struct bfd_entry *bfd_e) free(bfd_e); } -static void +void bfd_set_status(struct bfd_entry *bfd_e, const char *status) { free(bfd_e->status); bfd_e->status = xstrdup(status); } -static struct bfd_entry * +struct bfd_entry * bfd_port_lookup(const struct hmap *bfd_map, const char *logical_port, const char *dst_ip) { @@ -12205,7 +12194,7 @@ lrp_find_member_ip(const struct ovn_port *op, const char *ip_s) * this policy could be determined. Stores a pointer to the output port * in 'p_output_port' and a pointer to the router IP address to be used for * this policy, in 'p_lrp_addr_s'. */ -static bool +bool find_policy_outport(struct ovn_datapath *od, const struct nbrec_logical_router_policy *policy, const char *nexthop, bool is_ipv4, @@ -12256,61 +12245,6 @@ find_policy_outport(struct ovn_datapath *od, return true; } -static bool check_bfd_state(const struct nbrec_logical_router_policy *rule, - struct ovn_port *out_port, const char *nexthop, - const struct hmap *bfd_connections, - struct hmap *bfd_active_connections) -{ - struct in6_addr nexthop_v6; - bool is_nexthop_v6 = ipv6_parse(nexthop, &nexthop_v6); - - for (size_t i = 0; i < rule->n_bfd_sessions; i++) { - /* Check if there is a BFD session associated to the reroute - * policy. */ - const struct nbrec_bfd *nb_bt = rule->bfd_sessions[i]; - struct in6_addr dst_ipv6; - bool is_dst_v6 = ipv6_parse(nb_bt->dst_ip, &dst_ipv6); - - if (is_nexthop_v6 ^ is_dst_v6) { - continue; - } - - if ((is_nexthop_v6 && !ipv6_addr_equals(&nexthop_v6, &dst_ipv6)) || - strcmp(nb_bt->dst_ip, nexthop)) { - continue; - } - - if (strcmp(nb_bt->logical_port, out_port->key)) { - continue; - } - - struct bfd_entry *bfd_e = bfd_port_lookup(bfd_connections, - nb_bt->logical_port, - nb_bt->dst_ip); - if (!bfd_e) { - continue; - } - - /* This route policy is linked to an active bfd session. */ - struct bfd_entry *bfd_rp = bfd_port_lookup(bfd_active_connections, - nb_bt->logical_port, - nb_bt->dst_ip); - if (!bfd_rp) { - bfd_rp = bfd_alloc_entry(bfd_active_connections, - nb_bt->logical_port, nb_bt->dst_ip, - bfd_e->status); - } - - if (!strcmp(bfd_e->status, "admin_down")) { - bfd_set_status(bfd_rp, "down"); - } - - return strcmp(bfd_rp->status, "down"); - } - - return true; -} - static void build_routing_policy_flow(struct lflow_table *lflows, struct ovn_datapath *od, struct route_policy *rp, @@ -15796,208 +15730,6 @@ build_mcast_lookup_flows_for_lrouter(struct ovn_datapath *od, } } -static struct route_policy * -route_policies_lookup(struct hmap *route_policies, size_t hash, - struct route_policy *new_rp) -{ - struct route_policy *rp; - HMAP_FOR_EACH_WITH_HASH (rp, key_node, hash, route_policies) { - if (rp->rule != new_rp->rule) { - continue; - } - - if (rp->chain_id != new_rp->chain_id) { - continue; - } - - if (rp->jump_chain_id != new_rp->jump_chain_id) { - continue; - } - - if (rp->n_valid_nexthops != new_rp->n_valid_nexthops) { - continue; - } - - size_t i; - for (i = 0; i < new_rp->n_valid_nexthops; i++) { - size_t j; - - for (j = 0; j < rp->n_valid_nexthops; j++) { - if (!strcmp(new_rp->valid_nexthops[i], - rp->valid_nexthops[j])) { - break; - } - } - - if (j == rp->n_valid_nexthops) { - break; - } - } - - if (i == new_rp->n_valid_nexthops) { - return rp; - } - } - - return NULL; -} - -static bool -policy_chain_id(struct simap *chain_ids, const char *chain_name, uint32_t *id) -{ - if (chain_name && *chain_name) { - *id = simap_get(chain_ids, chain_name); - return true; - } - - return false; -} - -static void -policy_chain_add(struct simap *chain_ids, const char *chain_name) -{ - uint32_t id = simap_count(chain_ids) + 1; - - if (id == UINT16_MAX) { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); - VLOG_WARN_RL(&rl, "Too many policy chains for Logical Router."); - return; - } - - if (!simap_put(chain_ids, chain_name, id)) { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); - VLOG_WARN_RL(&rl, "Policy chain id unexpectedly appeared"); - } -} - -void -build_route_policies(struct ovn_datapath *od, - const struct hmap *bfd_connections, - struct hmap *route_policies, - struct hmap *bfd_active_connections, - struct simap *chain_ids) -{ - struct route_policy *rp; - - /* Create chain numeric ids for policies with chain name set */ - for (int i = 0; i < od->nbr->n_policies; i++) { - const struct nbrec_logical_router_policy *rule = od->nbr->policies[i]; - uint32_t id; - - if (policy_chain_id(chain_ids, rule->chain, &id) && id == 0) { - policy_chain_add(chain_ids, rule->chain); - } - } - - for (int i = 0; i < od->nbr->n_policies; i++) { - const struct nbrec_logical_router_policy *rule = od->nbr->policies[i]; - - if (rule->nexthop && rule->nexthop[0]) { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); - VLOG_WARN_RL(&rl, "Logical router: %s, policy uses deprecated" - " column \"nexthop\", this column is ignored. Please" - "use \"nexthops\" column instead.", od->nbr->name); - continue; - } - - size_t n_valid_nexthops = 0; - char **valid_nexthops = NULL; - uint32_t chain_id = 0; - uint32_t jump_chain_id = 0; - - /* Skip policy if chain name is set but id was not created above */ - if (policy_chain_id(chain_ids, rule->chain, &chain_id) - && chain_id == 0) { - continue; - } - - if (!strcmp(rule->action, "jump")) { - /* Skip policy if action is 'jump' but no target chain is set */ - if (!policy_chain_id(chain_ids, rule->jump_chain, - &jump_chain_id)) { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); - VLOG_WARN_RL(&rl, - "Logical router: %s, policy action 'jump'" - " has empty target", - od->nbr->name); - continue; - } - - /* Skip policy if action is 'jump' but target chain name - is not resolved to numeric id */ - if (jump_chain_id == 0) { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); - VLOG_WARN_RL(&rl, - "Logical router: %s, policy action 'jump'" - " follows to non-existent chain %s", - od->nbr->name, rule->jump_chain); - continue; - } - } - - if (simap_is_empty(chain_ids)) { - chain_id = -1; - } - - if (!strcmp(rule->action, "reroute")) { - if (rule->output_port && rule->n_nexthops != 1) { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); - VLOG_WARN_RL(&rl, - "Logical router: %s, policy " - "(chain: '%s', match: '%s', priority %"PRId64"): " - "output_port only supported on non-ECMP " - "reroute policies", - od->nbr->name, - rule->chain ? rule->chain : "<Default>", - rule->match, rule->priority); - continue; - } - - valid_nexthops = xcalloc(rule->n_nexthops, sizeof *valid_nexthops); - for (size_t j = 0; j < rule->n_nexthops; j++) { - char *nexthop = rule->nexthops[j]; - if (!nexthop || !nexthop[0]) { - continue; - } - - struct ovn_port *out_port = NULL; - bool is_ipv4 = strchr(nexthop, '.') ? true : false; - - if (!find_policy_outport(od, rule, nexthop, is_ipv4, NULL, - &out_port)) { - continue; - } - if (!check_bfd_state(rule, out_port, nexthop, - bfd_connections, - bfd_active_connections)) { - continue; - } - valid_nexthops[n_valid_nexthops++] = nexthop; - } - - if (!n_valid_nexthops) { - free(valid_nexthops); - continue; - } - } - - struct route_policy *new_rp = xzalloc(sizeof *new_rp); - new_rp->rule = rule; - new_rp->n_valid_nexthops = n_valid_nexthops; - new_rp->valid_nexthops = valid_nexthops; - new_rp->chain_id = chain_id; - new_rp->jump_chain_id = jump_chain_id; - - size_t hash = uuid_hash(&od->key); - rp = route_policies_lookup(route_policies, hash, new_rp); - if (!rp) { - hmap_insert(route_policies, &new_rp->key_node, hash); - } else { - free(valid_nexthops); - free(new_rp); - } - } -} /* Logical router ingress table POLICY: Policy. * @@ -21823,14 +21555,6 @@ northd_init(struct northd_data *data) init_northd_tracked_data(data); } -void -route_policies_init(struct route_policies_data *data) -{ - hmap_init(&data->route_policies); - hmap_init(&data->bfd_active_connections); - simap_init(&data->chain_ids); -} - void routes_init(struct routes_data *data) { @@ -21912,8 +21636,8 @@ northd_destroy(struct northd_data *data) destroy_northd_tracked_data(data); } -static void -__bfd_destroy(struct hmap *bfd_connections) +void +bfd_destroy(struct hmap *bfd_connections) { struct bfd_entry *bfd_e; @@ -21923,12 +21647,6 @@ __bfd_destroy(struct hmap *bfd_connections) hmap_destroy(bfd_connections); } -void -bfd_destroy(struct bfd_data *data) -{ - __bfd_destroy(&data->bfd_connections); -} - static void __ic_learned_svcs_cleanup(struct hmap *ic_learned_svc_monitors_map) { @@ -21946,19 +21664,6 @@ ic_learned_svc_monitors_cleanup(struct ic_learned_svc_monitors_data *data) lflow_ref_destroy(data->lflow_ref); } -void -route_policies_destroy(struct route_policies_data *data) -{ - struct route_policy *rp; - HMAP_FOR_EACH_POP (rp, key_node, &data->route_policies) { - free(rp->valid_nexthops); - free(rp); - }; - hmap_destroy(&data->route_policies); - __bfd_destroy(&data->bfd_active_connections); - simap_destroy(&data->chain_ids); -} - void routes_destroy(struct routes_data *data) { @@ -21969,7 +21674,7 @@ routes_destroy(struct routes_data *data) hmap_destroy(&data->parsed_routes); simap_destroy(&data->route_tables); - __bfd_destroy(&data->bfd_active_connections); + bfd_destroy(&data->bfd_active_connections); hmapx_destroy(&data->trk_data.trk_crupdated_parsed_route); hmapx_destroy(&data->trk_data.trk_deleted_parsed_route); } diff --git a/northd/northd.h b/northd/northd.h index c4bfae177..81ebbf0f6 100644 --- a/northd/northd.h +++ b/northd/northd.h @@ -210,15 +210,6 @@ struct northd_data { struct northd_tracked_data trk_data; }; -struct route_policy { - struct hmap_node key_node; - const struct nbrec_logical_router_policy *rule; - size_t n_valid_nexthops; - char **valid_nexthops; - uint32_t chain_id; - uint32_t jump_chain_id; -}; - struct route_tracked_data { struct hmapx trk_crupdated_parsed_route; struct hmapx trk_deleted_parsed_route; @@ -232,12 +223,6 @@ struct routes_data { bool tracked; }; -struct route_policies_data { - struct hmap route_policies; - struct hmap bfd_active_connections; - struct simap chain_ids; -}; - struct bfd_data { struct hmap bfd_connections; }; @@ -949,8 +934,6 @@ void northd_init(struct northd_data *data); void northd_indices_create(struct northd_data *data, struct ovsdb_idl *ovnsb_idl); -void route_policies_init(struct route_policies_data *); -void route_policies_destroy(struct route_policies_data *); void build_parsed_routes(const struct ovn_datapath *, const struct hmap *, struct hmap *, struct simap *, struct hmap *); uint32_t get_route_table_id(struct simap *, const char *); @@ -958,8 +941,29 @@ void routes_init(struct routes_data *); void routes_destroy(struct routes_data *); void routes_clear_tracked(struct routes_data *); +struct bfd_entry { + struct hmap_node hmap_node; + + const struct nbrec_bfd *nb_bt; + const struct sbrec_bfd *sb_bt; + + char *logical_port; + char *dst_ip; + char *status; + bool stale; +}; + +struct bfd_entry *bfd_alloc_entry(struct hmap *bfd_connections, + const char *logical_port, const char *dst_ip, + const char *status); +void bfd_erase_entry(struct bfd_entry *bfd_e); +void bfd_set_status(struct bfd_entry *bfd_e, const char *status); +struct bfd_entry *bfd_port_lookup(const struct hmap *bfd_map, + const char *logical_port, + const char *dst_ip); +void bfd_destroy(struct hmap *bfd_connections); + void bfd_init(struct bfd_data *); -void bfd_destroy(struct bfd_data *); void bfd_sync_init(struct bfd_sync_data *); void bfd_sync_swap(struct bfd_sync_data *, struct sset *bfd_ports); @@ -1016,8 +1020,12 @@ bool northd_handle_lb_data_changes(struct tracked_lb_data *, const struct hmap *lr_lb_map, struct northd_tracked_data *); -void build_route_policies(struct ovn_datapath *, const struct hmap *, - struct hmap *, struct hmap *, struct simap *); +bool find_policy_outport(struct ovn_datapath *od, + const struct nbrec_logical_router_policy *policy, + const char *nexthop, bool is_ipv4, + const char **p_lrp_addr_s, + struct ovn_port **p_out_port); + void bfd_table_sync(struct ovsdb_idl_txn *, const struct nbrec_bfd_table *, const struct hmap *, const struct hmap *, const struct hmap *, const struct hmap *, -- 2.55.0 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
