Previously we just assumed that if a LR had multiple LRPs bound to the local chassis that all routes where valid for all of these LRPs. This commit handles a previous option in ovn-nb that allowes the user to specify the interface name that a route needs to use to be acceptable for a given LRP. The users can then have a 1:1 relationship between LRPs and interfaces to allow ovn-controller to determine which route belongs to which LRP.
Signed-off-by: Felix Huettner <[email protected]> --- v3: newly introduced controller/route-exchange-netlink.c | 1 + controller/route-exchange-netlink.h | 2 ++ controller/route-exchange.c | 23 ++++++++++++++++------- controller/route.c | 12 +++++++++--- controller/route.h | 6 ++++-- tests/system-ovn.at | 11 +++++++++++ 6 files changed, 43 insertions(+), 12 deletions(-) diff --git a/controller/route-exchange-netlink.c b/controller/route-exchange-netlink.c index eb2adb6d6..a30ecaeba 100644 --- a/controller/route-exchange-netlink.c +++ b/controller/route-exchange-netlink.c @@ -221,6 +221,7 @@ handle_route_msg_delete_routes(const struct route_table_msg *msg, void *data) rr->addr = rd->rta_dst; rr->plen = rd->plen; rr->nexthop = rd->nexthops[i].rta_gw; + memcpy(rr->ifname, rd->nexthops[i].ifname, IFNAMSIZ); } return; } diff --git a/controller/route-exchange-netlink.h b/controller/route-exchange-netlink.h index 566b38fde..fca2429e6 100644 --- a/controller/route-exchange-netlink.h +++ b/controller/route-exchange-netlink.h @@ -18,6 +18,7 @@ #include <stdint.h> #include "openvswitch/hmap.h" #include <netinet/in.h> +#include <net/if.h> /* This value is arbitrary but currently unused. * See https://github.com/iproute2/iproute2/blob/main/etc/iproute2/rt_protos */ @@ -31,6 +32,7 @@ struct re_nl_received_route_node { struct in6_addr addr; unsigned int plen; struct in6_addr nexthop; + char ifname[IFNAMSIZ]; }; int re_nl_create_vrf(const char *ifname, uint32_t table_id); diff --git a/controller/route-exchange.c b/controller/route-exchange.c index 4929cccb1..cc4a1af03 100644 --- a/controller/route-exchange.c +++ b/controller/route-exchange.c @@ -27,6 +27,7 @@ #include "route.h" #include "route-exchange.h" #include "route-exchange-netlink.h" +#include "simap.h" VLOG_DEFINE_THIS_MODULE(route_exchange); @@ -102,7 +103,7 @@ route_erase_entry(struct route_entry *route_e) static void sb_sync_learned_routes(const struct sbrec_datapath_binding *datapath, const struct hmap *learned_routes, - const struct sset *bound_ports, + const struct smap *bound_ports, struct ovsdb_idl_txn *ovnsb_idl_txn, struct ovsdb_idl_index *sbrec_route_by_datapath) { @@ -118,8 +119,9 @@ sb_sync_learned_routes(const struct sbrec_datapath_binding *datapath, continue; } /* If the port is not local we don't care about it. - * Some other ovn-controller will handle it. */ - if (!sset_contains(bound_ports, sb_route->logical_port)) { + * Some other ovn-controller will handle it. + * We may not use smap_get since the value might be validly NULL. */ + if (!smap_get_node(bound_ports, sb_route->logical_port)) { continue; } route_e = route_alloc_entry(&sync_routes, @@ -138,16 +140,23 @@ sb_sync_learned_routes(const struct sbrec_datapath_binding *datapath, learned_route->plen); char *nexthop = normalize_v46(&learned_route->nexthop); - const char *logical_port; - SSET_FOR_EACH (logical_port, bound_ports) { + struct smap_node *port_node; + SMAP_FOR_EACH (port_node, bound_ports) { + /* The user specified an ifname, but we learned it on a different + * port. */ + if (port_node->value && strcmp(port_node->value, + learned_route->ifname)) { + continue; + } route_e = route_lookup_or_add(&sync_routes, datapath, - logical_port, ip_prefix, nexthop); + port_node->key, ip_prefix, nexthop); route_e->stale = false; if (!route_e->sb_route) { sb_route = sbrec_route_insert(ovnsb_idl_txn); sbrec_route_set_datapath(sb_route, datapath); - sbrec_route_set_logical_port(sb_route, logical_port); + sbrec_route_set_logical_port(sb_route, + port_node->key); sbrec_route_set_ip_prefix(sb_route, ip_prefix); sbrec_route_set_nexthop(sb_route, nexthop); sbrec_route_set_type(sb_route, "receive"); diff --git a/controller/route.c b/controller/route.c index 98618e46a..ad4e49eb1 100644 --- a/controller/route.c +++ b/controller/route.c @@ -75,7 +75,7 @@ advertise_datapath_cleanup(struct advertise_datapath_entry *ad) free(ar); } hmap_destroy(&ad->routes); - sset_destroy(&ad->bound_ports); + smap_destroy(&ad->bound_ports); free(ad); } @@ -83,6 +83,8 @@ void route_run(struct route_ctx_in *r_ctx_in, struct route_ctx_out *r_ctx_out) { + tracked_datapaths_destroy(r_ctx_out->tracked_re_datapaths); + const struct local_datapath *ld; HMAP_FOR_EACH (ld, hmap_node, r_ctx_in->local_datapaths) { if (!ld->n_peer_ports || ld->is_switch) { @@ -94,7 +96,7 @@ route_run(struct route_ctx_in *r_ctx_in, ad->key = ld->datapath->tunnel_key; ad->db = ld->datapath; hmap_init(&ad->routes); - sset_init(&ad->bound_ports); + smap_init(&ad->bound_ports); /* This is a LR datapath, find LRPs with route exchange options * that are bound locally. */ @@ -114,8 +116,12 @@ route_run(struct route_ctx_in *r_ctx_in, "maintain-vrf", false); ad->use_netns |= smap_get_bool(&sb_crp->options, "use-netns", false); + char *ifname = nullable_xstrdup( + smap_get(&sb_crp->options, + "dynamic-routing-ifname")); relevant_datapath = true; - sset_add(&ad->bound_ports, local_peer->logical_port); + smap_add_nocopy(&ad->bound_ports, + xstrdup(local_peer->logical_port), ifname); } if (!relevant_datapath) { diff --git a/controller/route.h b/controller/route.h index ca309c7be..74dd55543 100644 --- a/controller/route.h +++ b/controller/route.h @@ -19,6 +19,7 @@ #include <netinet/in.h> #include "openvswitch/hmap.h" #include "sset.h" +#include "smap.h" struct hmap; struct ovsdb_idl_index; @@ -51,8 +52,9 @@ struct advertise_datapath_entry { bool use_netns; struct hmap routes; /* the name of the port bindings locally bound for this datapath and - * running route exchange logic. */ - struct sset bound_ports; + * running route exchange logic. + * The key is the port name and the value is the ifname if set. */ + struct smap bound_ports; }; struct advertise_route_entry { diff --git a/tests/system-ovn.at b/tests/system-ovn.at index 1ad4248ce..9656e412b 100644 --- a/tests/system-ovn.at +++ b/tests/system-ovn.at @@ -14351,6 +14351,17 @@ AT_CHECK([ovn-sbctl --columns ip_prefix,nexthop,logical_port --bare find Route t internet-phys ]) +# by setting a learning interface filter we will now forget about this route +check ovn-nbctl --wait=hv set Logical_Router_Port internet-phys \ + options:dynamic-routing-ifname=thisdoesnotexist +check_row_count Route 0 type=receive + +# chaning it to "lo" will allow us to learn the route again +check ovn-nbctl --wait=hv set Logical_Router_Port internet-phys \ + options:dynamic-routing-ifname=lo +check_row_count Route 1 type=receive + + OVS_APP_EXIT_AND_WAIT([ovn-controller]) as ovn-sb -- 2.47.0 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
