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