@@ -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;
}
@@ -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);
@@ -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");
@@ -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) {
@@ -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 {
@@ -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
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 <felix.huettner@stackit.cloud> --- 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(-)