On 2/26/25 1:24 PM, martin.kal...@canonical.com wrote: > On Tue, 2025-02-25 at 16:54 +0100, Dumitru Ceara wrote: >> Change the en_dynamic_routes I-P node to compute a map of 'advertised >> routes' (struct ar_entry) instead of parsed routes. Like that we can >> avoid having to re-parse NAT/LB IPs when advertising them. >> >> Fixes: cd4ad2f56179 ("northd: Redistribution of NAT/LB routes.") >> Signed-off-by: Dumitru Ceara <dce...@redhat.com> > > Hi Dumitru,
Hi Martin, Felix, Thanks for the reviews! > thanks for the update. Overall you can add acked-by me. I noticed few > points in code where function was renamed (to not include > "parsed_route" in name), but the related comment above function still > mentions "parsed route". Those comments should probably be updated too. Ah, good catch. I had indeed done a search and replace of "parsed_route". :) > I left comments below where I noticed this discrepancy. Awesome, that helps! > IMO, it doesn't require v3, since they are just comments, they can be > fixed on merge. Cool, I fixed them up then added your ack and applied the patch to main and 25.03. Regards, Dumitru > > Thanks, > Martin. > >> --- >> V2: >> - Addressed Felix's review comments: >> - added OVS_NOT_REACHED() for cases that shouldn't happen. >> - split the functionality of should_advertise_route() to make it >> more >> clear >> - Addressed Martin's review comments: >> - removed stale TODO item >> - renamed build_lb_nat_parsed_route_*() functions because they don't >> build parsed_route structs anymore. >> --- >> TODO.rst | 7 - >> northd/en-advertised-route-sync.c | 492 +++++++++++++++++----------- >> -- >> northd/northd.h | 3 +- >> 3 files changed, 282 insertions(+), 220 deletions(-) >> >> diff --git a/TODO.rst b/TODO.rst >> index 593b9a580f..6c2b0aa931 100644 >> --- a/TODO.rst >> +++ b/TODO.rst >> @@ -159,10 +159,3 @@ OVN To-do List >> monitoring conditions to update before we actually try to learn >> routes. >> Otherwise we could try to add duplicated Learned_Routes and the >> ovnsb >> commit would fail. >> - >> - * Consider splitting parsed_route structure. When creating parsed >> routes >> - with tracked_port explicitly set, other members of this >> structure are >> - usually unused/default. A new structure dedicated to routes with >> - explicitly defined tracked_port would be more efficient. >> - More details in >> - >> https://mail.openvswitch.org/pipermail/ovs-dev/2025-February/420985.html >> diff --git a/northd/en-advertised-route-sync.c b/northd/en- >> advertised-route-sync.c >> index 486bcc2fd2..913f58bfa6 100644 >> --- a/northd/en-advertised-route-sync.c >> +++ b/northd/en-advertised-route-sync.c >> @@ -27,6 +27,102 @@ >> #include "openvswitch/hmap.h" >> #include "ovn-util.h" >> >> +struct ar_entry { >> + struct hmap_node hmap_node; >> + >> + const struct ovn_datapath *od; /* Datapath the route is >> + * advertised on. */ >> + const struct ovn_port *op; /* Port the route is >> advertised >> + * on. */ >> + char *ip_prefix; >> + const struct ovn_port *tracked_port; /* If set, the port whose >> chassis >> + * advertises this route >> with a >> + * higher priority. */ >> + enum route_source source; >> +}; >> + >> +/* Add a new entries to the to-be-advertised routes. >> + * Takes ownership of ip_prefix. */ >> +static struct ar_entry * >> +ar_entry_add_nocopy(struct hmap *routes, const struct ovn_datapath >> *od, >> + const struct ovn_port *op, char *ip_prefix, >> + const struct ovn_port *tracked_port, >> + enum route_source source) >> +{ >> + struct ar_entry *route_e = xzalloc(sizeof *route_e); >> + >> + route_e->od = od; >> + route_e->op = op; >> + route_e->ip_prefix = ip_prefix; >> + route_e->tracked_port = tracked_port; >> + route_e->source = source; >> + uint32_t hash = uuid_hash(&od->sb->header_.uuid); >> + hash = hash_string(op->sb->logical_port, hash); >> + hash = hash_string(ip_prefix, hash); >> + hmap_insert(routes, &route_e->hmap_node, hash); >> + >> + return route_e; >> +} >> + >> +/* Add a new entries to the to-be-advertised routes. >> + * Makes a copy of ip_prefix. */ >> +static struct ar_entry * >> +ar_entry_add(struct hmap *routes, const struct ovn_datapath *od, >> + const struct ovn_port *op, const char *ip_prefix, >> + const struct ovn_port *tracked_port, >> + enum route_source source) >> +{ >> + return ar_entry_add_nocopy(routes, od, op, xstrdup(ip_prefix), >> + tracked_port, source); >> +} >> + >> +static struct ar_entry * >> +ar_entry_find(struct hmap *route_map, >> + const struct sbrec_datapath_binding *sb_db, >> + const struct sbrec_port_binding *logical_port, >> + const char *ip_prefix, >> + const struct sbrec_port_binding *tracked_port) >> +{ >> + struct ar_entry *route_e; >> + uint32_t hash; >> + >> + hash = uuid_hash(&sb_db->header_.uuid); >> + hash = hash_string(logical_port->logical_port, hash); >> + hash = hash_string(ip_prefix, hash); >> + >> + HMAP_FOR_EACH_WITH_HASH (route_e, hmap_node, hash, route_map) { >> + if (!uuid_equals(&sb_db->header_.uuid, >> + &route_e->od->sb->header_.uuid)) { >> + continue; >> + } >> + if (!uuid_equals(&logical_port->header_.uuid, >> + &route_e->op->sb->header_.uuid)) { >> + continue; >> + } >> + if (strcmp(ip_prefix, route_e->ip_prefix)) { >> + continue; >> + } >> + >> + if (tracked_port) { >> + if (!route_e->tracked_port || >> + tracked_port != route_e->tracked_port->sb) { >> + continue; >> + } >> + } >> + >> + return route_e; >> + } >> + >> + return NULL; >> +} >> + >> +static void >> +ar_entry_free(struct ar_entry *route_e) >> +{ >> + free(route_e->ip_prefix); >> + free(route_e); >> +} >> + >> static void >> advertised_route_table_sync( >> struct ovsdb_idl_txn *ovnsb_txn, >> @@ -158,7 +254,7 @@ en_advertised_route_sync_run(struct engine_node >> *node, void *data OVS_UNUSED) >> sbrec_advertised_route_table, >> &lr_stateful_data->table, >> &routes_data->parsed_routes, >> - &dynamic_routes_data->parsed_routes, >> + &dynamic_routes_data->routes, >> routes_sync_data); >> >> stopwatch_stop(ADVERTISED_ROUTE_SYNC_RUN_STOPWATCH_NAME, >> time_msec()); >> @@ -171,10 +267,10 @@ en_advertised_route_sync_run(struct engine_node >> *node, void *data OVS_UNUSED) >> * DGP (for example if it's set on gateway router), no tracked port >> will >> * be set.*/ > > It's not seen in this diff, but the comment above this function still > mentions "parsed route". > >> static void >> -build_nat_parsed_route_for_port(const struct ovn_port >> *advertising_op, >> - const struct lr_nat_record *lr_nat, >> - const struct hmap *ls_ports, >> - struct hmap *routes) >> +build_nat_route_for_port(const struct ovn_port *advertising_op, >> + const struct lr_nat_record *lr_nat, >> + const struct hmap *ls_ports, >> + struct hmap *routes) >> { >> const struct ovn_datapath *advertising_od = advertising_op->od; >> >> @@ -184,28 +280,28 @@ build_nat_parsed_route_for_port(const struct >> ovn_port *advertising_op, >> continue; >> } >> >> - int plen = nat_entry_is_v6(nat) ? 128 : 32; >> - struct in6_addr prefix; >> - ip46_parse(nat->nb->external_ip, &prefix); >> - >> const struct ovn_port *tracked_port = >> nat->is_distributed >> ? ovn_port_find(ls_ports, nat->nb->logical_port) >> : nat->l3dgw_port; >> - parsed_route_add(advertising_od, NULL, &prefix, plen, false, >> - nat->nb->external_ip, advertising_op, 0, >> false, >> - false, NULL, ROUTE_SOURCE_NAT, &nat->nb- >>> header_, >> - tracked_port, routes); >> + >> + if (!ar_entry_find(routes, advertising_od->sb, >> advertising_op->sb, >> + nat->nb->external_ip, >> + tracked_port ? tracked_port->sb : NULL)) >> { >> + ar_entry_add(routes, advertising_od, advertising_op, >> + nat->nb->external_ip, tracked_port, >> + ROUTE_SOURCE_NAT); >> + } >> } >> } >> >> /* Generate parsed routes for NAT external IPs in lr_nat, for each >> ovn port > > Comment still references "parsed routes". > >> * in "od" that has enabled redistribution of NAT adresses.*/ >> static void >> -build_nat_parsed_routes(const struct ovn_datapath *od, >> - const struct lr_nat_record *lr_nat, >> - const struct hmap *ls_ports, >> - struct hmap *routes) >> +build_nat_routes(const struct ovn_datapath *od, >> + const struct lr_nat_record *lr_nat, >> + const struct hmap *ls_ports, >> + struct hmap *routes) >> { >> const struct ovn_port *op; >> HMAP_FOR_EACH (op, dp_node, &od->ports) { >> @@ -213,17 +309,17 @@ build_nat_parsed_routes(const struct >> ovn_datapath *od, >> continue; >> } >> >> - build_nat_parsed_route_for_port(op, lr_nat, ls_ports, >> routes); >> + build_nat_route_for_port(op, lr_nat, ls_ports, routes); >> } >> } >> >> -/* Similar to build_nat_parsed_routes, this function generates >> parsed routes >> +/* Similar to build_nat_routes, this function generates parsed >> routes > > Comment still references "parsed routes". > >> * for nat records in neighboring routers. For each ovn port in "od" >> that has >> * enabled redistribution of NAT adresses, look up their neighbors >> (either >> * directly routers, or routers connected through common LS) and >> advertise >> * thier external NAT IPs too.*/ >> static void >> -build_nat_connected_parsed_routes( >> +build_nat_connected_routes( >> const struct ovn_datapath *od, >> const struct lr_stateful_table *lr_stateful_table, >> const struct hmap *ls_ports, >> @@ -255,8 +351,8 @@ build_nat_connected_parsed_routes( >> } >> >> /* Advertise peer's NAT routes via the local port too. >> */ >> - build_nat_parsed_route_for_port(op, peer_lr_stateful- >>> lrnat_rec, >> - ls_ports, routes); >> + build_nat_route_for_port(op, peer_lr_stateful- >>> lrnat_rec, >> + ls_ports, routes); >> return; >> } >> >> @@ -277,50 +373,41 @@ build_nat_connected_parsed_routes( >> } >> >> /* Advertise peer's NAT routes via the local port too. >> */ >> - build_nat_parsed_route_for_port(op, peer_lr_stateful- >>> lrnat_rec, >> - ls_ports, routes); >> + build_nat_route_for_port(op, peer_lr_stateful- >>> lrnat_rec, >> + ls_ports, routes); >> } >> } >> } >> >> /* This function adds new parsed route for each IP in lb_ips to >> "routes".*/ > > Comment still references "parsed routes". > >> static void >> -build_lb_parsed_route_for_port(const struct ovn_port >> *advertising_op, >> - const struct ovn_port *tracked_port, >> - const struct ovn_lb_ip_set *lb_ips, >> - struct hmap *routes) >> +build_lb_route_for_port(const struct ovn_port *advertising_op, >> + const struct ovn_port *tracked_port, >> + const struct ovn_lb_ip_set *lb_ips, >> + struct hmap *routes) >> { >> const struct ovn_datapath *advertising_od = advertising_op->od; >> >> const char *ip_address; >> SSET_FOR_EACH (ip_address, &lb_ips->ips_v4) { >> - struct in6_addr prefix; >> - ip46_parse(ip_address, &prefix); >> - parsed_route_add(advertising_od, NULL, &prefix, 32, false, >> - ip_address, advertising_op, 0, false, >> false, >> - NULL, ROUTE_SOURCE_LB, &advertising_op- >>> nbrp->header_, >> - tracked_port, routes); >> + ar_entry_add(routes, advertising_od, advertising_op, >> + ip_address, tracked_port, ROUTE_SOURCE_LB); >> } >> SSET_FOR_EACH (ip_address, &lb_ips->ips_v6) { >> - struct in6_addr prefix; >> - ip46_parse(ip_address, &prefix); >> - parsed_route_add(advertising_od, NULL, &prefix, 128, false, >> - ip_address, advertising_op, 0, false, >> false, >> - NULL, ROUTE_SOURCE_LB, &advertising_op- >>> nbrp->header_, >> - tracked_port, routes); >> + ar_entry_add(routes, advertising_od, advertising_op, >> + ip_address, tracked_port, ROUTE_SOURCE_LB); >> } >> } >> >> -/* Similar to build_lb_parsed_routes, this function generates parsed >> routes > > Comment still references "parsed routes". > >> +/* Similar to build_lb_routes, this function generates parsed routes >> * for LB VIPs of neighboring routers. For each ovn port in "od" >> that has >> * enabled redistribution of LB VIPs, look up their neighbors >> (either >> * directly routers, or routers connected through common LS) and >> advertise >> * thier LB VIPs too.*/ >> static void >> -build_lb_connected_parsed_routes( >> - const struct ovn_datapath *od, >> - const struct lr_stateful_table *lr_stateful_table, >> - struct hmap *routes) >> +build_lb_connected_routes(const struct ovn_datapath *od, >> + const struct lr_stateful_table >> *lr_stateful_table, >> + struct hmap *routes) >> { >> const struct ovn_port *op; >> HMAP_FOR_EACH (op, dp_node, &od->ports) { >> @@ -342,8 +429,8 @@ build_lb_connected_parsed_routes( >> lr_stateful_rec = lr_stateful_table_find_by_index( >> lr_stateful_table, peer_od->index); >> peer_port = op->peer; >> - build_lb_parsed_route_for_port(op, peer_port, >> - lr_stateful_rec->lb_ips, >> routes); >> + build_lb_route_for_port(op, peer_port, lr_stateful_rec- >>> lb_ips, >> + routes); >> return; >> } >> >> @@ -359,16 +446,16 @@ build_lb_connected_parsed_routes( >> lr_stateful_rec = lr_stateful_table_find_by_index( >> lr_stateful_table, peer_port->od->index); >> >> - build_lb_parsed_route_for_port(op, peer_port, >> - lr_stateful_rec->lb_ips, >> routes); >> + build_lb_route_for_port(op, peer_port, lr_stateful_rec- >>> lb_ips, >> + routes); >> } >> } >> } >> >> static void >> -build_lb_parsed_routes(const struct ovn_datapath *od, >> - const struct ovn_lb_ip_set *lb_ips, >> - struct hmap *routes) >> +build_lb_routes(const struct ovn_datapath *od, >> + const struct ovn_lb_ip_set *lb_ips, >> + struct hmap *routes) >> { >> const struct ovn_port *op; >> HMAP_FOR_EACH (op, dp_node, &od->ports) { >> @@ -390,8 +477,7 @@ build_lb_parsed_routes(const struct ovn_datapath >> *od, >> : &op_; >> >> for (size_t i = 0; i < n_tracked_ports; i++) { >> - build_lb_parsed_route_for_port(op, tracked_ports[i], >> lb_ips, >> - routes); >> + build_lb_route_for_port(op, tracked_ports[i], lb_ips, >> routes); >> } >> } >> } >> @@ -402,7 +488,7 @@ en_dynamic_routes_init(struct engine_node *node >> OVS_UNUSED, >> { >> struct dynamic_routes_data *data = xmalloc(sizeof *data); >> *data = (struct dynamic_routes_data) { >> - .parsed_routes = HMAP_INITIALIZER(&data->parsed_routes), >> + .routes = HMAP_INITIALIZER(&data->routes), >> }; >> >> return data; >> @@ -411,9 +497,9 @@ en_dynamic_routes_init(struct engine_node *node >> OVS_UNUSED, >> static void >> en_dynamic_routes_clear(struct dynamic_routes_data *data) >> { >> - struct parsed_route *r; >> - HMAP_FOR_EACH_POP (r, key_node, &data->parsed_routes) { >> - parsed_route_free(r); >> + struct ar_entry *ar; >> + HMAP_FOR_EACH_POP (ar, hmap_node, &data->routes) { >> + ar_entry_free(ar); >> } >> } >> void >> @@ -422,7 +508,7 @@ en_dynamic_routes_cleanup(void *data_) >> struct dynamic_routes_data *data = data_; >> >> en_dynamic_routes_clear(data); >> - hmap_destroy(&data->parsed_routes); >> + hmap_destroy(&data->routes); >> } >> >> void >> @@ -445,102 +531,22 @@ en_dynamic_routes_run(struct engine_node >> *node, void *data) >> if (!od->dynamic_routing) { >> continue; >> } >> - build_nat_parsed_routes(od, lr_stateful_rec->lrnat_rec, >> - &northd_data->ls_ports, >> - &dynamic_routes_data- >>> parsed_routes); >> - build_nat_connected_parsed_routes(od, &lr_stateful_data- >>> table, >> - &northd_data->ls_ports, >> - &dynamic_routes_data- >>> parsed_routes); >> - >> - build_lb_parsed_routes(od, lr_stateful_rec->lb_ips, >> - &dynamic_routes_data->parsed_routes); >> - build_lb_connected_parsed_routes(od, &lr_stateful_data- >>> table, >> - &dynamic_routes_data- >>> parsed_routes); >> + build_nat_routes(od, lr_stateful_rec->lrnat_rec, >> + &northd_data->ls_ports, >> + &dynamic_routes_data->routes); >> + build_nat_connected_routes(od, &lr_stateful_data->table, >> + &northd_data->ls_ports, >> + &dynamic_routes_data->routes); >> + >> + build_lb_routes(od, lr_stateful_rec->lb_ips, >> + &dynamic_routes_data->routes); >> + build_lb_connected_routes(od, &lr_stateful_data->table, >> + &dynamic_routes_data->routes); >> } >> stopwatch_stop(DYNAMIC_ROUTES_RUN_STOPWATCH_NAME, time_msec()); >> engine_set_node_state(node, EN_UPDATED); >> } >> >> -struct ar_entry { >> - struct hmap_node hmap_node; >> - >> - const struct ovn_datapath *od; /* Datapath the route is >> - * advertised on. */ >> - const struct ovn_port *op; /* Port the route is >> advertised >> - * on. */ >> - char *ip_prefix; >> - const struct ovn_port *tracked_port; /* If set, the port whose >> chassis >> - * advertises this route >> with a >> - * higher priority. */ >> -}; >> - >> -/* Add a new entries to the to-be-advertised routes. >> - * Takes ownership of ip_prefix. */ >> -static struct ar_entry * >> -ar_entry_add(struct hmap *routes, const struct ovn_datapath *od, >> - const struct ovn_port *op, char *ip_prefix, >> - const struct ovn_port *tracked_port) >> -{ >> - struct ar_entry *route_e = xzalloc(sizeof *route_e); >> - >> - route_e->od = od; >> - route_e->op = op; >> - route_e->ip_prefix = ip_prefix; >> - route_e->tracked_port = tracked_port; >> - uint32_t hash = uuid_hash(&od->sb->header_.uuid); >> - hash = hash_string(op->sb->logical_port, hash); >> - hash = hash_string(ip_prefix, hash); >> - hmap_insert(routes, &route_e->hmap_node, hash); >> - >> - return route_e; >> -} >> - >> -static struct ar_entry * >> -ar_entry_find(struct hmap *route_map, >> - const struct sbrec_datapath_binding *sb_db, >> - const struct sbrec_port_binding *logical_port, >> - const char *ip_prefix, >> - const struct sbrec_port_binding *tracked_port) >> -{ >> - struct ar_entry *route_e; >> - uint32_t hash; >> - >> - hash = uuid_hash(&sb_db->header_.uuid); >> - hash = hash_string(logical_port->logical_port, hash); >> - hash = hash_string(ip_prefix, hash); >> - >> - HMAP_FOR_EACH_WITH_HASH (route_e, hmap_node, hash, route_map) { >> - if (!uuid_equals(&sb_db->header_.uuid, >> - &route_e->od->sb->header_.uuid)) { >> - continue; >> - } >> - if (!uuid_equals(&logical_port->header_.uuid, >> - &route_e->op->sb->header_.uuid)) { >> - continue; >> - } >> - if (strcmp(ip_prefix, route_e->ip_prefix)) { >> - continue; >> - } >> - >> - if (tracked_port) { >> - if (!route_e->tracked_port || >> - tracked_port != route_e->tracked_port->sb) { >> - continue; >> - } >> - } >> - return route_e; >> - } >> - >> - return NULL; >> -} >> - >> -static void >> -ar_entry_free(struct ar_entry *route_e) >> -{ >> - free(route_e->ip_prefix); >> - free(route_e); >> -} >> - >> static void >> publish_lport_addresses(struct hmap *sync_routes, >> const struct ovn_datapath *od, >> @@ -550,16 +556,16 @@ publish_lport_addresses(struct hmap >> *sync_routes, >> { >> for (size_t i = 0; i < addresses->n_ipv4_addrs; i++) { >> const struct ipv4_netaddr *addr = &addresses->ipv4_addrs[i]; >> - ar_entry_add(sync_routes, od, logical_port, xstrdup(addr- >>> addr_s), >> - tracking_port); >> + ar_entry_add(sync_routes, od, logical_port, addr->addr_s, >> + tracking_port, ROUTE_SOURCE_CONNECTED); >> } >> for (size_t i = 0; i < addresses->n_ipv6_addrs; i++) { >> if (in6_is_lla(&addresses->ipv6_addrs[i].network)) { >> continue; >> } >> const struct ipv6_netaddr *addr = &addresses->ipv6_addrs[i]; >> - ar_entry_add(sync_routes, od, logical_port, xstrdup(addr- >>> addr_s), >> - tracking_port); >> + ar_entry_add(sync_routes, od, logical_port, addr->addr_s, >> + tracking_port, ROUTE_SOURCE_CONNECTED); >> } >> } >> >> @@ -640,78 +646,107 @@ publish_host_routes(struct hmap *sync_routes, >> } >> } >> >> -static void >> -advertised_route_table_sync_route_add( >> - const struct lr_stateful_table *lr_stateful_table, >> - struct advertised_route_sync_data *data, >> - struct uuidset *host_route_lrps, >> - struct hmap *sync_routes, >> - const struct parsed_route *route) >> +static bool >> +should_advertise_route(const struct uuidset *host_route_lrps, >> + const struct ovn_datapath *advertising_od, >> + const struct ovn_port *advertising_op, >> + enum route_source source) >> { >> - if (route->is_discard_route) { >> - return; >> - } >> - if (prefix_is_link_local(&route->prefix, route->plen)) { >> - return; >> - } >> - if (!route->od->dynamic_routing) { >> - return; >> + if (!advertising_od->dynamic_routing) { >> + return false; >> } >> >> enum dynamic_routing_redistribute_mode drr = >> - route->out_port->dynamic_routing_redistribute; >> - if (route->source == ROUTE_SOURCE_CONNECTED) { >> + advertising_op->dynamic_routing_redistribute; >> + >> + switch (source) { >> + case ROUTE_SOURCE_CONNECTED: >> if (!drr_mode_CONNECTED_is_set(drr)) { >> - return; >> + return false; >> } >> + >> /* If we advertise host routes, we only need to do so once >> per >> * LRP. */ >> - const struct uuid *lrp_uuid = &route->out_port->nbrp- >>> header_.uuid; >> + const struct uuid *lrp_uuid = &advertising_op->nbrp- >>> header_.uuid; >> if (drr_mode_CONNECTED_AS_HOST_is_set(drr) && >> - !uuidset_contains(host_route_lrps, lrp_uuid)) { >> + uuidset_contains(host_route_lrps, lrp_uuid)) { >> + return false; >> + } >> + return true; >> + case ROUTE_SOURCE_STATIC: >> + return drr_mode_STATIC_is_set(drr); >> + case ROUTE_SOURCE_NAT: >> + return drr_mode_NAT_is_set(drr); >> + case ROUTE_SOURCE_LB: >> + return drr_mode_LB_is_set(drr); >> + case ROUTE_SOURCE_LEARNED: >> + OVS_NOT_REACHED(); >> + default: >> + OVS_NOT_REACHED(); >> + } >> +} >> + >> +/* Returns true if the route has already been fully processed for >> + * advertising (e.g., for connected routes when connected-as-host is >> set). >> + * Returns false otherwise, in which case the a new 'ar_entry' needs >> to >> + * be created for this route. >> + */ >> +static bool >> +process_prereqs_advertise_route( >> + const struct lr_stateful_table *lr_stateful_table, >> + struct advertised_route_sync_data *data, >> + struct uuidset *host_route_lrps, >> + struct hmap *sync_routes, >> + const struct ovn_datapath *advertising_od, >> + const struct ovn_port *advertising_op, >> + const struct ovn_port *tracked_op, >> + enum route_source source) >> +{ >> + enum dynamic_routing_redistribute_mode drr = >> + advertising_op->dynamic_routing_redistribute; >> + >> + switch (source) { >> + case ROUTE_SOURCE_CONNECTED: >> + if (drr_mode_CONNECTED_AS_HOST_is_set(drr)) { >> + const struct uuid *lrp_uuid = &advertising_op->nbrp- >>> header_.uuid; >> uuidset_insert(host_route_lrps, lrp_uuid); >> publish_host_routes(sync_routes, lr_stateful_table, >> - route->od, route->out_port, >> + advertising_od, advertising_op, >> �� data); >> - return; >> - } >> - } >> - if (route->source == ROUTE_SOURCE_STATIC && >> !drr_mode_STATIC_is_set(drr)) { >> - return; >> - } >> - if (route->source == ROUTE_SOURCE_NAT) { >> - if (!drr_mode_NAT_is_set(drr)) { >> - return; >> + return true; >> } >> + break; >> + case ROUTE_SOURCE_STATIC: >> + break; >> + case ROUTE_SOURCE_NAT: >> /* If NAT route tracks port on a different DP than the one >> that >> * advertises the route, we need to watch for changes on >> that DP as >> * well. */ >> - if (route->tracked_port && route->tracked_port->od != route- >>> od) { >> - if (route->tracked_port->od->nbr) { >> + if (tracked_op && tracked_op->od != advertising_od) { >> + if (tracked_op->od->nbr) { >> uuidset_insert(&data->nb_lr, >> - &route->tracked_port->od->nbr- >>> header_.uuid); >> - } else if (route->tracked_port->od->nbs) { >> + &tracked_op->od->nbr->header_.uuid); >> + } else if (tracked_op->od->nbs) { >> uuidset_insert(&data->nb_ls, >> - &route->tracked_port->od->nbs- >>> header_.uuid); >> + &tracked_op->od->nbs->header_.uuid); >> } >> } >> - } >> - if (route->source == ROUTE_SOURCE_LB) { >> - if (!drr_mode_LB_is_set(drr)) { >> - return; >> - } >> + break; >> + case ROUTE_SOURCE_LB: >> /* If LB route tracks port on a different DP than the one >> that >> * advertises the route, we need to watch for changes on >> that DP as >> * well. */ >> - if (route->tracked_port && route->tracked_port->od != route- >>> od) { >> + if (tracked_op && tracked_op->od != advertising_od) { >> uuidset_insert(&data->nb_lr, >> - &route->tracked_port->od->nbr- >>> header_.uuid); >> + &tracked_op->od->nbr->header_.uuid); >> } >> + break; >> + case ROUTE_SOURCE_LEARNED: >> + OVS_NOT_REACHED(); >> + default: >> + OVS_NOT_REACHED(); >> } >> - >> - char *ip_prefix = normalize_v46_prefix(&route->prefix, route- >>> plen); >> - ar_entry_add(sync_routes, route->od, route->out_port, ip_prefix, >> - route->tracked_port); >> + return false; >> } >> >> static void >> @@ -725,23 +760,56 @@ advertised_route_table_sync( >> { >> struct hmap sync_routes = HMAP_INITIALIZER(&sync_routes); >> struct uuidset host_route_lrps = >> UUIDSET_INITIALIZER(&host_route_lrps); >> - const struct parsed_route *route; >> - >> - struct ar_entry *route_e; >> >> /* First build the set of non-dynamic routes that need sync-ing. >> */ >> + const struct parsed_route *route; >> HMAP_FOR_EACH (route, key_node, routes) { >> - advertised_route_table_sync_route_add(lr_stateful_table, >> - data, >> &host_route_lrps, >> - &sync_routes, >> - route); >> + if (route->is_discard_route) { >> + continue; >> + } >> + >> + if (prefix_is_link_local(&route->prefix, route->plen)) { >> + continue; >> + } >> + >> + if (!should_advertise_route(&host_route_lrps, route->od, >> + route->out_port, route->source)) >> { >> + continue; >> + } >> + >> + if (process_prereqs_advertise_route(lr_stateful_table, data, >> + &host_route_lrps, >> &sync_routes, >> + route->od, route- >>> out_port, >> + route->tracked_port, >> + route->source)) { >> + continue; >> + } >> + >> + ar_entry_add_nocopy(&sync_routes, route->od, route- >>> out_port, >> + normalize_v46_prefix(&route->prefix, >> route->plen), >> + route->tracked_port, >> + route->source); >> } >> + >> /* Then add the set of dynamic routes that need sync-ing. */ >> - HMAP_FOR_EACH (route, key_node, dynamic_routes) { >> - advertised_route_table_sync_route_add(lr_stateful_table, >> - data, >> &host_route_lrps, >> - &sync_routes, >> - route); >> + struct ar_entry *route_e; >> + HMAP_FOR_EACH (route_e, hmap_node, dynamic_routes) { >> + if (!should_advertise_route(&host_route_lrps, route_e->od, >> route_e->op, >> + route_e->source)) { >> + continue; >> + } >> + >> + if (process_prereqs_advertise_route(lr_stateful_table, data, >> + &host_route_lrps, >> &sync_routes, >> + route_e->od, route_e- >>> op, >> + route_e->tracked_port, >> + route_e->source)) { >> + continue; >> + } >> + >> + ar_entry_add(&sync_routes, route_e->od, route_e->op, >> + route_e->ip_prefix, route_e->tracked_port, >> + route_e->source); >> } >> uuidset_destroy(&host_route_lrps); >> >> diff --git a/northd/northd.h b/northd/northd.h >> index 12fccd7751..c221365e62 100644 >> --- a/northd/northd.h >> +++ b/northd/northd.h >> @@ -192,7 +192,8 @@ struct routes_data { >> }; >> >> struct dynamic_routes_data { >> - struct hmap parsed_routes; /* Stores struct parsed_route. */ >> + struct hmap routes; /* Stores struct ar_entry, one for each >> + * dynamic route. */ >> }; >> >> struct route_policies_data { > _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev