On Wed, Dec 11, 2024 at 04:06:55PM +0100, Dumitru Ceara wrote:
> On 12/10/24 3:12 PM, Felix Huettner via dev wrote:
> > previously connected routes (so routes based on the networks of the
> > LRPs) where handled separately from static routes.
> > 
> > In order to later announce routes from ovn to the fabric we need to have
> > a central overview over all routes we want to announce. This includes
> > routes based on Logical_Router_Static_Routes as well as the networks on
> > Logical_Router_Port.
> > 
> > With this change the "routes" engine node will output a complete list of
> > all routes in the system. This also serves as a future integration point
> > to integrate routes learned from outside of OVN.
> > 
> > Signed-off-by: Felix Huettner <felix.huettner@stackit.cloud>
> > ---
> 
> Hi Felix,
> 
> I didn't dig into it too much but this patch introduces a crash in
> northd.  E.g. on the ovsrobot runs:

Hi Dumitru,

i found the issue and it is caused by a double free.
Once i have time i will send a new version.

The fix will be part of "northd: Store outport of parsed_route." since
it fitted there best.

Thanks a lot
Felix

> 
> https://github.com/ovsrobot/ovn/actions/runs/12258207439/job/34197883591
> 
> SIGSEGV detected, backtrace:
> 0x555e06149990   <fatal_signal_handler+0x29>
> 0x7f4735664320   <__sigaction+0x50>
> 0x555e061b4cd2   <hmap_next+0x14>
> 0x555e061b53aa   <sset_clear+0x86>
> 0x555e061b4eac   <sset_destroy+0x23>
> 0x555e0606dc67   <parsed_route_free+0x43>
> 0x555e06087521   <routes_destroy+0x4d>
> 0x555e0608d3db   <en_routes_run+0x5c>
> 0x555e060af86b   <engine_recompute+0x1b3>
> 0x555e060afb59   <engine_compute+0x1b3>
> 0x555e060afcf2   <engine_run_node+0x14f>
> 0x555e060afd88   <engine_run+0x5f>
> 0x555e0609d962   <inc_proc_northd_run+0xae>
> 0x555e0608ab33   <main+0xe1c>
> 0x7f47356491ca   <__libc_init_first+0x8a>
> 0x7f473564928b   <__libc_start_main+0x8b>
> 0x555e060497c5   <_start+0x25>
> 
> I'll look at the first 5 patches of this series as we might be able to
> accept some already.
> 
> Regards,
> Dumitru
> 
> > Changed to original patchset:
> > * rebased
> > 
> >  northd/northd.c | 278 ++++++++++++++++++++++++++++++------------------
> >  northd/northd.h |   9 ++
> >  2 files changed, 183 insertions(+), 104 deletions(-)
> > 
> > diff --git a/northd/northd.c b/northd/northd.c
> > index 9487cae0c..ba2594c35 100644
> > --- a/northd/northd.c
> > +++ b/northd/northd.c
> > @@ -11119,6 +11119,19 @@ parsed_route_lookup(struct hmap *routes, size_t 
> > hash,
> >              continue;
> >          }
> >  
> > +        if (pr->source != new_pr->source) {
> > +            continue;
> > +        }
> > +
> > +        /* Check if both parsed_route have nexthop set to NULL or 
> > non-NULL. */
> > +        if (!pr->nexthop != !new_pr->nexthop) {
> > +            continue;
> > +        }
> > +
> > +        if (pr->nexthop && ipv6_addr_equals(pr->nexthop, new_pr->nexthop)) 
> > {
> > +            continue;
> > +        }
> > +
> >          if (memcmp(&pr->prefix, &new_pr->prefix, sizeof(struct in6_addr))) 
> > {
> >              continue;
> >          }
> > @@ -11161,35 +11174,89 @@ parsed_route_lookup(struct hmap *routes, size_t 
> > hash,
> >  static void
> >  parsed_route_free(struct parsed_route *pr) {
> >      free(pr->lrp_addr_s);
> > +    free(pr->nexthop);
> > +    sset_destroy(&pr->ecmp_selection_fields);
> >      free(pr);
> >  }
> >  
> >  static void
> > -parsed_routes_add(struct ovn_datapath *od, const struct hmap *lr_ports,
> > +parsed_route_add(const struct ovn_datapath *od,
> > +                 struct in6_addr *nexthop,
> > +                 const struct in6_addr prefix,
> > +                 unsigned int plen,
> > +                 bool is_discard_route,
> > +                 const char *lrp_addr_s,
> > +                 const struct ovn_port *out_port,
> > +                 const struct nbrec_logical_router_static_route *route,
> > +                 uint32_t route_table_id,
> > +                 bool is_src_route,
> > +                 bool ecmp_symmetric_reply,
> > +                 const struct sset *ecmp_selection_fields,
> > +                 enum route_source source,
> > +                 struct hmap *routes)
> > +{
> > +
> > +    struct parsed_route *new_pr = xzalloc(sizeof *new_pr);
> > +    new_pr->prefix = prefix;
> > +    new_pr->plen = plen;
> > +    new_pr->nexthop = nexthop;
> > +    new_pr->route_table_id = route_table_id;
> > +    new_pr->is_src_route = is_src_route;
> > +    new_pr->hash = route_hash(new_pr);
> > +    new_pr->nbr = od->nbr;
> > +    new_pr->ecmp_symmetric_reply = ecmp_symmetric_reply;
> > +    new_pr->is_discard_route = is_discard_route;
> > +    if (!is_discard_route) {
> > +        new_pr->lrp_addr_s = xstrdup(lrp_addr_s);
> > +    }
> > +    new_pr->out_port = out_port;
> > +    new_pr->source = source;
> > +    new_pr->route = route;
> > +    if (ecmp_selection_fields) {
> > +        sset_clone(&new_pr->ecmp_selection_fields, ecmp_selection_fields);
> > +    } else {
> > +        sset_init(&new_pr->ecmp_selection_fields);
> > +    }
> > +
> > +    size_t hash = uuid_hash(&od->key);
> > +    struct parsed_route *pr = parsed_route_lookup(routes, hash, new_pr);
> > +    if (!pr) {
> > +        hmap_insert(routes, &new_pr->key_node, hash);
> > +    } else {
> > +        pr->stale = false;
> > +        parsed_route_free(new_pr);
> > +    }
> > +}
> > +
> > +static void
> > +parsed_routes_add_static(struct ovn_datapath *od, const struct hmap 
> > *lr_ports,
> >                    const struct nbrec_logical_router_static_route *route,
> >                    const struct hmap *bfd_connections,
> >                    struct hmap *routes, struct simap *route_tables,
> >                    struct hmap *bfd_active_connections)
> >  {
> >      /* Verify that the next hop is an IP address with an all-ones mask. */
> > -    struct in6_addr nexthop;
> > +    struct in6_addr *nexthop = NULL;
> >      unsigned int plen;
> >      bool is_discard_route = !strcmp(route->nexthop, "discard");
> >      bool valid_nexthop = route->nexthop[0] && !is_discard_route;
> >      if (valid_nexthop) {
> > -        if (!ip46_parse_cidr(route->nexthop, &nexthop, &plen)) {
> > +        nexthop = xmalloc(sizeof(*nexthop));
> > +        if (!ip46_parse_cidr(route->nexthop, nexthop, &plen)) {
> >              static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
> >              VLOG_WARN_RL(&rl, "bad 'nexthop' %s in static route "
> >                           UUID_FMT, route->nexthop,
> >                           UUID_ARGS(&route->header_.uuid));
> > +            free(nexthop);
> >              return;
> >          }
> > -        if ((IN6_IS_ADDR_V4MAPPED(&nexthop) && plen != 32) ||
> > -            (!IN6_IS_ADDR_V4MAPPED(&nexthop) && plen != 128)) {
> > +        if ((IN6_IS_ADDR_V4MAPPED(nexthop) && plen != 32) ||
> > +            (!IN6_IS_ADDR_V4MAPPED(nexthop) && plen != 128)) {
> >              static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
> >              VLOG_WARN_RL(&rl, "bad next hop mask %s in static route "
> >                           UUID_FMT, route->nexthop,
> >                           UUID_ARGS(&route->header_.uuid));
> > +            free(nexthop);
> >              return;
> >          }
> >      }
> > @@ -11201,17 +11268,19 @@ parsed_routes_add(struct ovn_datapath *od, const 
> > struct hmap *lr_ports,
> >          VLOG_WARN_RL(&rl, "bad 'ip_prefix' %s in static route "
> >                       UUID_FMT, route->ip_prefix,
> >                       UUID_ARGS(&route->header_.uuid));
> > +        free(nexthop);
> >          return;
> >      }
> >  
> >      /* Verify that ip_prefix and nexthop have same address familiy. */
> >      if (valid_nexthop) {
> > -        if (IN6_IS_ADDR_V4MAPPED(&prefix) != 
> > IN6_IS_ADDR_V4MAPPED(&nexthop)) {
> > +        if (IN6_IS_ADDR_V4MAPPED(&prefix) != 
> > IN6_IS_ADDR_V4MAPPED(nexthop)) {
> >              static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
> >              VLOG_WARN_RL(&rl, "Address family doesn't match between 
> > 'ip_prefix'"
> >                           " %s and 'nexthop' %s in static route "UUID_FMT,
> >                           route->ip_prefix, route->nexthop,
> >                           UUID_ARGS(&route->header_.uuid));
> > +            free(nexthop);
> >              return;
> >          }
> >      }
> > @@ -11223,6 +11292,7 @@ parsed_routes_add(struct ovn_datapath *od, const 
> > struct hmap *lr_ports,
> >          !find_static_route_outport(od, lr_ports, route,
> >                                     IN6_IS_ADDR_V4MAPPED(&prefix),
> >                                     &lrp_addr_s, &out_port)) {
> > +        free(nexthop);
> >          return;
> >      }
> >  
> > @@ -11232,6 +11302,7 @@ parsed_routes_add(struct ovn_datapath *od, const 
> > struct hmap *lr_ports,
> >                                                    nb_bt->logical_port,
> >                                                    nb_bt->dst_ip);
> >          if (!bfd_e) {
> > +            free(nexthop);
> >              return;
> >          }
> >  
> > @@ -11251,25 +11322,12 @@ parsed_routes_add(struct ovn_datapath *od, const 
> > struct hmap *lr_ports,
> >  
> >  
> >          if (!strcmp(bfd_sr->status, "down")) {
> > +            free(nexthop);
> >              return;
> >          }
> >      }
> >  
> > -    struct parsed_route *new_pr = xzalloc(sizeof *new_pr);
> > -    new_pr->prefix = prefix;
> > -    new_pr->plen = plen;
> > -    new_pr->route_table_id = get_route_table_id(route_tables,
> > -                                                route->route_table);
> > -    new_pr->is_src_route = (route->policy &&
> > -                            !strcmp(route->policy, "src-ip"));
> > -    new_pr->hash = route_hash(new_pr);
> > -    new_pr->route = route;
> > -    new_pr->nbr = od->nbr;
> > -    new_pr->ecmp_symmetric_reply = smap_get_bool(&route->options,
> > -                                                 "ecmp_symmetric_reply",
> > -                                                 false);
> > -    new_pr->is_discard_route = is_discard_route;
> > -    sset_init(&new_pr->ecmp_selection_fields);
> > +    struct sset ecmp_selection_fields = 
> > SSET_INITIALIZER(&ecmp_selection_fields);
> >  
> >      /* If tp_src or tp_dst is included in the selection_fields, implicitly
> >       * include match on ip_proto. */
> > @@ -11282,23 +11340,58 @@ parsed_routes_add(struct ovn_datapath *od, const 
> > struct hmap *lr_ports,
> >              }
> >              sset_add(&field_set, field);
> >          }
> > -        sset_clone(&new_pr->ecmp_selection_fields, &field_set);
> > +        sset_clone(&ecmp_selection_fields, &field_set);
> >          sset_destroy(&field_set);
> >      }
> >  
> > -    if (!is_discard_route) {
> > -        new_pr->lrp_addr_s = xstrdup(lrp_addr_s);
> > -    }
> > -    new_pr->out_port = out_port;
> > +    uint32_t route_table_id = get_route_table_id(route_tables,
> > +                                        route->route_table);
> > +    bool is_src_route = (route->policy && !strcmp(route->policy, 
> > "src-ip"));
> > +    bool ecmp_symmetric_reply = smap_get_bool(&route->options,
> > +                                         "ecmp_symmetric_reply",
> > +                                         false);
> >  
> > -    size_t hash = uuid_hash(&od->key);
> > -    struct parsed_route *pr = parsed_route_lookup(routes, hash, new_pr);
> > -    if (!pr) {
> > -        hmap_insert(routes, &new_pr->key_node, hash);
> > +    enum route_source source;
> > +    if (!strcmp(smap_get_def(&route->options, "origin", ""),
> > +                                 ROUTE_ORIGIN_CONNECTED)) {
> > +        source = ROUTE_SOURCE_CONNECTED;
> >      } else {
> > -        pr->stale = false;
> > -        sset_destroy(&new_pr->ecmp_selection_fields);
> > -        parsed_route_free(new_pr);
> > +        source = ROUTE_SOURCE_STATIC;
> > +    }
> > +
> > +    parsed_route_add(od, nexthop, prefix, plen, is_discard_route, 
> > lrp_addr_s,
> > +                     out_port, route, route_table_id, is_src_route,
> > +                     ecmp_symmetric_reply, &ecmp_selection_fields, source,
> > +                     routes);
> > +    sset_destroy(&ecmp_selection_fields);
> > +}
> > +
> > +static void
> > +parsed_routes_add_connected(struct ovn_datapath *od, const struct ovn_port 
> > *op,
> > +                            struct hmap *routes)
> > +{
> > +    for (int i = 0; i < op->lrp_networks.n_ipv4_addrs; i++) {
> > +        const struct ipv4_netaddr *addr = &op->lrp_networks.ipv4_addrs[i];
> > +        struct in6_addr prefix;
> > +        ip46_parse(addr->network_s, &prefix);
> > +
> > +        parsed_route_add(od, NULL, prefix, addr->plen,
> > +                          false, addr->addr_s, op,
> > +                          NULL, 0, false,
> > +                          false, NULL, ROUTE_SOURCE_CONNECTED,
> > +                          routes);
> > +    }
> > +
> > +    for (int i = 0; i < op->lrp_networks.n_ipv6_addrs; i++) {
> > +        const struct ipv6_netaddr *addr = &op->lrp_networks.ipv6_addrs[i];
> > +        struct in6_addr prefix;
> > +        ip46_parse(addr->network_s, &prefix);
> > +
> > +        parsed_route_add(od, NULL, prefix, addr->plen,
> > +                          false, addr->addr_s, op,
> > +                          NULL, 0, false,
> > +                          false, NULL, ROUTE_SOURCE_CONNECTED,
> > +                          routes);
> >      }
> >  }
> >  
> > @@ -11316,9 +11409,14 @@ build_parsed_routes(struct ovn_datapath *od, const 
> > struct hmap *lr_ports,
> >      }
> >  
> >      for (int i = 0; i < od->nbr->n_static_routes; i++) {
> > -        parsed_routes_add(od, lr_ports, od->nbr->static_routes[i],
> > -                          bfd_connections, routes, route_tables,
> > -                          bfd_active_connections);
> > +        parsed_routes_add_static(od, lr_ports, od->nbr->static_routes[i],
> > +                                 bfd_connections, routes, route_tables,
> > +                                 bfd_active_connections);
> > +    }
> > +
> > +    const struct ovn_port *op;
> > +    HMAP_FOR_EACH (op, dp_node, &od->ports) {
> > +        parsed_routes_add_connected(od, op, routes);
> >      }
> >  
> >      HMAP_FOR_EACH_SAFE (pr, key_node, routes) {
> > @@ -11343,7 +11441,7 @@ struct ecmp_groups_node {
> >      struct in6_addr prefix;
> >      unsigned int plen;
> >      bool is_src_route;
> > -    const char *origin;
> > +    enum route_source source;
> >      uint32_t route_table_id;
> >      uint16_t route_count;
> >      struct ovs_list route_list; /* Contains ecmp_route_list_node */
> > @@ -11391,7 +11489,7 @@ ecmp_groups_add(struct hmap *ecmp_groups,
> >      eg->prefix = route->prefix;
> >      eg->plen = route->plen;
> >      eg->is_src_route = route->is_src_route;
> > -    eg->origin = smap_get_def(&route->route->options, "origin", "");
> > +    eg->source = route->source;
> >      eg->route_table_id = route->route_table_id;
> >      sset_init(&eg->selection_fields);
> >      ovs_list_init(&eg->route_list);
> > @@ -11457,6 +11555,7 @@ unique_routes_remove(struct hmap *unique_routes,
> >          if (ipv6_addr_equals(&route->prefix, &ur->route->prefix) &&
> >              route->plen == ur->route->plen &&
> >              route->is_src_route == ur->route->is_src_route &&
> > +            route->source == ur->route->source &&
> >              route->route_table_id == ur->route->route_table_id) {
> >              hmap_remove(unique_routes, &ur->hmap_node);
> >              const struct parsed_route *existed_route = ur->route;
> > @@ -11689,6 +11788,19 @@ add_ecmp_symmetric_reply_flows(struct lflow_table 
> > *lflows,
> >      ds_destroy(&ecmp_reply);
> >  }
> >  
> > +static int
> > +route_source_to_offset(enum route_source source)
> > +{
> > +    switch (source) {
> > +        case ROUTE_SOURCE_CONNECTED:
> > +            return ROUTE_PRIO_OFFSET_CONNECTED;
> > +        case ROUTE_SOURCE_STATIC:
> > +            return ROUTE_PRIO_OFFSET_STATIC;
> > +        default:
> > +            OVS_NOT_REACHED();
> > +    }
> > +}
> > +
> >  static void
> >  build_ecmp_route_flow(struct lflow_table *lflows, struct ovn_datapath *od,
> >                        struct ecmp_groups_node *eg, struct lflow_ref 
> > *lflow_ref,
> > @@ -11701,8 +11813,7 @@ build_ecmp_route_flow(struct lflow_table *lflows, 
> > struct ovn_datapath *od,
> >      struct ds route_match = DS_EMPTY_INITIALIZER;
> >  
> >      char *prefix_s = build_route_prefix_s(&eg->prefix, eg->plen);
> > -    int ofs = !strcmp(eg->origin, ROUTE_ORIGIN_CONNECTED) ?
> > -        ROUTE_PRIO_OFFSET_CONNECTED: ROUTE_PRIO_OFFSET_STATIC;
> > +    int ofs = route_source_to_offset(eg->source);
> >      build_route_match(NULL, eg->route_table_id, prefix_s, eg->plen,
> >                        eg->is_src_route, is_ipv4, &route_match, &priority, 
> > ofs,
> >                        protocol != NULL);
> > @@ -11785,13 +11896,14 @@ build_ecmp_route_flow(struct lflow_table *lflows, 
> > struct ovn_datapath *od,
> >                        REG_ECMP_MEMBER_ID" == %"PRIu16,
> >                        eg->id, er->id);
> >          ds_clear(&actions);
> > -        ds_put_format(&actions, "%s = %s; "
> > +        ds_put_format(&actions, "%s = ",
> > +                      is_ipv4 ? REG_NEXT_HOP_IPV4 : REG_NEXT_HOP_IPV6);
> > +        ipv6_format_mapped(route_->nexthop, &actions);
> > +        ds_put_format(&actions, "; "
> >                        "%s = %s; "
> >                        "eth.src = %s; "
> >                        "outport = %s; "
> >                        "next;",
> > -                      is_ipv4 ? REG_NEXT_HOP_IPV4 : REG_NEXT_HOP_IPV6,
> > -                      route->nexthop,
> >                        is_ipv4 ? REG_SRC_IPV4 : REG_SRC_IPV6,
> >                        route_->lrp_addr_s,
> >                        route_->out_port->lrp_networks.ea_s,
> > @@ -11809,17 +11921,19 @@ build_ecmp_route_flow(struct lflow_table *lflows, 
> > struct ovn_datapath *od,
> >  static void
> >  add_route(struct lflow_table *lflows, struct ovn_datapath *od,
> >            const struct ovn_port *op, const char *lrp_addr_s,
> > -          const char *network_s, int plen, const char *gateway,
> > +          const char *network_s, int plen, const struct in6_addr *gateway,
> >            bool is_src_route, const uint32_t rtb_id,
> >            const struct sset *bfd_ports,
> >            const struct ovsdb_idl_row *stage_hint, bool is_discard_route,
> > -          int ofs, struct lflow_ref *lflow_ref)
> > +          enum route_source source, struct lflow_ref *lflow_ref)
> >  {
> >      bool is_ipv4 = strchr(network_s, '.') ? true : false;
> >      struct ds match = DS_EMPTY_INITIALIZER;
> >      uint16_t priority;
> >      const struct ovn_port *op_inport = NULL;
> >  
> > +    int ofs = route_source_to_offset(source);
> > +
> >      /* IPv6 link-local addresses must be scoped to the local router port. 
> > */
> >      if (!is_ipv4) {
> >          struct in6_addr network;
> > @@ -11838,8 +11952,8 @@ add_route(struct lflow_table *lflows, struct 
> > ovn_datapath *od,
> >      } else {
> >          ds_put_format(&common_actions, REG_ECMP_GROUP_ID" = 0; %s = ",
> >                        is_ipv4 ? REG_NEXT_HOP_IPV4 : REG_NEXT_HOP_IPV6);
> > -        if (gateway && gateway[0]) {
> > -            ds_put_cstr(&common_actions, gateway);
> > +        if (gateway) {
> > +            ipv6_format_mapped(gateway, &common_actions);
> >          } else {
> >              ds_put_format(&common_actions, "ip%s.dst", is_ipv4 ? "4" : 
> > "6");
> >          }
> > @@ -11874,23 +11988,20 @@ add_route(struct lflow_table *lflows, struct 
> > ovn_datapath *od,
> >  }
> >  
> >  static void
> > -build_static_route_flow(struct lflow_table *lflows, struct ovn_datapath 
> > *od,
> > +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)
> >  {
> >      const struct nbrec_logical_router_static_route *route = route_->route;
> >  
> > -    int ofs = !strcmp(smap_get_def(&route->options, "origin", ""),
> > -                      ROUTE_ORIGIN_CONNECTED) ? ROUTE_PRIO_OFFSET_CONNECTED
> > -                                              : ROUTE_PRIO_OFFSET_STATIC;
> > -
> >      char *prefix_s = build_route_prefix_s(&route_->prefix, route_->plen);
> >      add_route(lflows, route_->is_discard_route ? od : route_->out_port->od,
> >                route_->out_port, route_->lrp_addr_s, prefix_s,
> > -              route_->plen, route->nexthop, route_->is_src_route,
> > -              route_->route_table_id, bfd_ports, &route->header_,
> > -              route_->is_discard_route, ofs, lflow_ref);
> > +              route_->plen, route_->nexthop, route_->is_src_route,
> > +              route_->route_table_id, bfd_ports,
> > +              route ? &route->header_ : &route_->out_port->nbrp->header_,
> > +              route_->is_discard_route, route_->source, lflow_ref);
> >  
> >      free(prefix_s);
> >  }
> > @@ -13707,51 +13818,8 @@ build_ip_routing_pre_flows_for_lrouter(struct 
> > ovn_datapath *od,
> >                    REG_ROUTE_TABLE_ID" = 0; next;", lflow_ref);
> >  }
> >  
> > -/* Logical router ingress table IP_ROUTING : IP Routing.
> > - *
> > - * A packet that arrives at this table is an IP packet that should be
> > - * routed to the address in 'ip[46].dst'.
> > - *
> > - * For regular routes without ECMP, table IP_ROUTING sets outport to the
> > - * correct output port, eth.src to the output port's MAC address, and
> > - * REG_NEXT_HOP_IPV4/REG_NEXT_HOP_IPV6 to the next-hop IP address
> > - * (leaving 'ip[46].dst', the packet’s final destination, unchanged), and
> > - * advances to the next table.
> > - *
> > - * For ECMP routes, i.e. multiple routes with same policy and prefix, table
> > - * IP_ROUTING remembers ECMP group id and selects a member id, and advances
> > - * to table IP_ROUTING_ECMP, which sets outport, eth.src and
> > - * REG_NEXT_HOP_IPV4/REG_NEXT_HOP_IPV6 for the selected ECMP member.
> > - *
> > - * This function adds routes for directly connected subnets configured on 
> > the
> > - * LRP 'op'.
> > - */
> >  static void
> > -build_ip_routing_flows_for_lrp(struct ovn_port *op,
> > -                               const struct sset *bfd_ports,
> > -                               struct lflow_table *lflows,
> > -                               struct lflow_ref *lflow_ref)
> > -{
> > -    ovs_assert(op->nbrp);
> > -    for (int i = 0; i < op->lrp_networks.n_ipv4_addrs; i++) {
> > -        add_route(lflows, op->od, op, 
> > op->lrp_networks.ipv4_addrs[i].addr_s,
> > -                  op->lrp_networks.ipv4_addrs[i].network_s,
> > -                  op->lrp_networks.ipv4_addrs[i].plen, NULL, false, 0,
> > -                  bfd_ports, &op->nbrp->header_, false,
> > -                  ROUTE_PRIO_OFFSET_CONNECTED, lflow_ref);
> > -    }
> > -
> > -    for (int i = 0; i < op->lrp_networks.n_ipv6_addrs; i++) {
> > -        add_route(lflows, op->od, op, 
> > op->lrp_networks.ipv6_addrs[i].addr_s,
> > -                  op->lrp_networks.ipv6_addrs[i].network_s,
> > -                  op->lrp_networks.ipv6_addrs[i].plen, NULL, false, 0,
> > -                  bfd_ports, &op->nbrp->header_, false,
> > -                  ROUTE_PRIO_OFFSET_CONNECTED, lflow_ref);
> > -    }
> > -}
> > -
> > -static void
> > -build_static_route_flows_for_lrouter(
> > +build_route_flows_for_lrouter(
> >          struct ovn_datapath *od, struct lflow_table *lflows,
> >          struct hmap *parsed_routes,
> >          struct simap *route_tables, const struct sset *bfd_ports,
> > @@ -13778,6 +13846,10 @@ build_static_route_flows_for_lrouter(
> >      struct parsed_route *route;
> >      HMAP_FOR_EACH_WITH_HASH (route, key_node, uuid_hash(&od->key),
> >                               parsed_routes) {
> > +        if (route->source == ROUTE_SOURCE_CONNECTED) {
> > +            unique_routes_add(&unique_routes, route);
> > +            continue;
> > +        }
> >          group = ecmp_groups_find(&ecmp_groups, route);
> >          if (group) {
> >              ecmp_groups_add_route(group, route);
> > @@ -13815,7 +13887,7 @@ build_static_route_flows_for_lrouter(
> >      }
> >      const struct unique_routes_node *ur;
> >      HMAP_FOR_EACH (ur, hmap_node, &unique_routes) {
> > -        build_static_route_flow(lflows, od, ur->route,
> > +        build_route_flow(lflows, od, ur->route,
> >                                  bfd_ports, lflow_ref);
> >      }
> >      ecmp_groups_destroy(&ecmp_groups);
> > @@ -17059,7 +17131,7 @@ build_routable_flows_for_router_port(
> >                                laddrs->ipv4_addrs[k].network_s,
> >                                laddrs->ipv4_addrs[k].plen, NULL, false, 0,
> >                                bfd_ports, &router_port->nbrp->header_,
> > -                              false, ROUTE_PRIO_OFFSET_CONNECTED,
> > +                              false, ROUTE_SOURCE_CONNECTED,
> >                                lrp->stateful_lflow_ref);
> >                  }
> >              }
> > @@ -17301,7 +17373,7 @@ build_lswitch_and_lrouter_iterate_by_lr(struct 
> > ovn_datapath *od,
> >                                             lsi->meter_groups, NULL);
> >      build_ND_RA_flows_for_lrouter(od, lsi->lflows, NULL);
> >      build_ip_routing_pre_flows_for_lrouter(od, lsi->lflows, NULL);
> > -    build_static_route_flows_for_lrouter(od, lsi->lflows,
> > +    build_route_flows_for_lrouter(od, lsi->lflows,
> >                                           lsi->parsed_routes, 
> > lsi->route_tables,
> >                                           lsi->bfd_ports, NULL);
> >      build_mcast_lookup_flows_for_lrouter(od, lsi->lflows, &lsi->match,
> > @@ -17374,8 +17446,6 @@ build_lswitch_and_lrouter_iterate_by_lrp(struct 
> > ovn_port *op,
> >                                            &lsi->actions, op->lflow_ref);
> >      build_neigh_learning_flows_for_lrouter_port(op, lsi->lflows, 
> > &lsi->match,
> >                                                  &lsi->actions, 
> > op->lflow_ref);
> > -    build_ip_routing_flows_for_lrp(op, lsi->bfd_ports,
> > -                                   lsi->lflows, op->lflow_ref);
> >      build_ND_RA_flows_for_lrouter_port(op, lsi->lflows, &lsi->match,
> >                                         &lsi->actions, lsi->meter_groups,
> >                                         op->lflow_ref);
> > diff --git a/northd/northd.h b/northd/northd.h
> > index 1d00f0499..dc452794e 100644
> > --- a/northd/northd.h
> > +++ b/northd/northd.h
> > @@ -696,10 +696,18 @@ struct ovn_port {
> >      struct lflow_ref *stateful_lflow_ref;
> >  };
> >  
> > +enum route_source {
> > +    /* the route is directly connected to the logical router */
> > +    ROUTE_SOURCE_CONNECTED,
> > +    /* the route is derived from a northbound static route entry */
> > +    ROUTE_SOURCE_STATIC,
> > +};
> > +
> >  struct parsed_route {
> >      struct hmap_node key_node;
> >      struct in6_addr prefix;
> >      unsigned int plen;
> > +    struct in6_addr *nexthop; /* NULL for ROUTE_SOURCE_CONNECTED */
> >      bool is_src_route;
> >      uint32_t route_table_id;
> >      uint32_t hash;
> > @@ -709,6 +717,7 @@ struct parsed_route {
> >      const struct nbrec_logical_router *nbr;
> >      bool stale;
> >      struct sset ecmp_selection_fields;
> > +    enum route_source source;
> >      char *lrp_addr_s;
> >      const struct ovn_port *out_port;
> >  };
> 
_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to