On Tue, Feb 25, 2025 at 04:54:34PM +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>

Acked-by: Felix Huettner <felix.huettner@stackit.cloud>

> ---
> 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.*/
>  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
>   * 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
>   * 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".*/
>  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
> +/* 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 {
> -- 
> 2.48.1
> 
_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to