@@ -102,7 +102,8 @@ re_nl_delete_vrf(const char *ifname)
static int
modify_route(uint32_t type, uint32_t flags_arg, uint32_t table_id,
- const struct in6_addr *dst, unsigned int plen)
+ const struct in6_addr *dst, unsigned int plen,
+ unsigned int priority)
{
uint32_t flags = NLM_F_REQUEST | NLM_F_ACK;
bool is_ipv4 = IN6_IS_ADDR_V4MAPPED(dst);
@@ -128,6 +129,7 @@ modify_route(uint32_t type, uint32_t flags_arg, uint32_t table_id,
rt->rtm_dst_len = plen;
nl_msg_put_u32(&request, RTA_TABLE, table_id);
+ nl_msg_put_u32(&request, RTA_PRIORITY, priority);
if (is_ipv4) {
nl_msg_put_be32(&request, RTA_DST, in6_addr_get_mapped_ipv4(dst));
@@ -143,7 +145,7 @@ modify_route(uint32_t type, uint32_t flags_arg, uint32_t table_id,
int
re_nl_add_route(uint32_t table_id, const struct in6_addr *dst,
- unsigned int plen)
+ unsigned int plen, unsigned int priority)
{
uint32_t flags = NLM_F_CREATE | NLM_F_EXCL;
uint32_t type = RTM_NEWROUTE;
@@ -155,12 +157,12 @@ re_nl_add_route(uint32_t table_id, const struct in6_addr *dst,
return EINVAL;
}
- return modify_route(type, flags, table_id, dst, plen);
+ return modify_route(type, flags, table_id, dst, plen, priority);
}
int
re_nl_delete_route(uint32_t table_id, const struct in6_addr *dst,
- unsigned int plen)
+ unsigned int plen, unsigned int priority)
{
if (!TABLE_ID_VALID(table_id)) {
VLOG_WARN_RL(&rl,
@@ -169,7 +171,7 @@ re_nl_delete_route(uint32_t table_id, const struct in6_addr *dst,
return EINVAL;
}
- return modify_route(RTM_DELROUTE, 0, table_id, dst, plen);
+ return modify_route(RTM_DELROUTE, 0, table_id, dst, plen, priority);
}
static uint32_t
@@ -228,13 +230,14 @@ handle_route_msg_delete_routes(const struct route_table_msg *msg, void *data)
uint32_t arhash = advertise_route_hash(&rd->rta_dst, rd->plen);
HMAP_FOR_EACH_WITH_HASH (ar, node, arhash, routes) {
if (ipv6_addr_equals(&ar->addr, &rd->rta_dst)
- && ar->plen == rd->plen) {
+ && ar->plen == rd->plen && ar->priority == rd->rta_priority) {
ar->installed = true;
return;
}
}
+
err = re_nl_delete_route(rd->rta_table_id, &rd->rta_dst,
- rd->plen);
+ rd->plen, rd->rta_priority);
if (err) {
char addr_s[INET6_ADDRSTRLEN + 1];
VLOG_WARN_RL(&rl, "Delete route table_id=%"PRIu32" dst=%s plen=%d: %s",
@@ -271,7 +274,8 @@ re_nl_sync_routes(uint32_t table_id,
if (ar->installed) {
continue;
}
- int err = re_nl_add_route(table_id, &ar->addr, ar->plen);
+ int err = re_nl_add_route(table_id, &ar->addr, ar->plen,
+ ar->priority);
if (err) {
char addr_s[INET6_ADDRSTRLEN + 1];
VLOG_WARN_RL(&rl, "Add route table_id=%"PRIu32" dst=%s "
@@ -37,9 +37,9 @@ int re_nl_create_vrf(const char *ifname, uint32_t table_id);
int re_nl_delete_vrf(const char *ifname);
int re_nl_add_route(uint32_t table_id, const struct in6_addr *dst,
- unsigned int plen);
+ unsigned int plen, unsigned int priority);
int re_nl_delete_route(uint32_t table_id, const struct in6_addr *dst,
- unsigned int plen);
+ unsigned int plen, unsigned int priority);
void re_nl_dump(uint32_t table_id);
@@ -33,6 +33,9 @@ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20);
* in the corresponding VRF interface name. */
#define MAX_TABLE_ID 1000000000
+#define PRIORITY_DEFAULT 1000
+#define PRIORITY_LOCAL_BOUND 100
+
bool
route_exchange_relevant_port(const struct sbrec_port_binding *pb)
{
@@ -66,6 +69,19 @@ find_local_crp(struct ovsdb_idl_index *sbrec_port_binding_by_name,
return lport_lookup_by_name(sbrec_port_binding_by_name, crp);
}
+static const struct sbrec_port_binding*
+find_local_crp_by_name(struct ovsdb_idl_index *sbrec_port_binding_by_name,
+ const struct sbrec_chassis *chassis,
+ const struct sset *active_tunnels,
+ const char *port_name)
+{
+ const struct sbrec_port_binding *pb = lport_lookup_by_name(
+ sbrec_port_binding_by_name, port_name);
+
+ return find_local_crp(sbrec_port_binding_by_name, chassis, active_tunnels,
+ pb);
+}
+
static void
advertise_datapath_cleanup(struct advertise_datapath_entry *ad)
{
@@ -162,11 +178,24 @@ route_run(struct route_ctx_in *r_ctx_in,
continue;
}
+ unsigned int priority = PRIORITY_DEFAULT;
+
+ if (route->tracked_port) {
+ if (find_local_crp_by_name(
+ r_ctx_in->sbrec_port_binding_by_name,
+ r_ctx_in->chassis,
+ r_ctx_in->active_tunnels,
+ route->tracked_port)) {
+ priority = PRIORITY_LOCAL_BOUND;
+ }
+ }
+
struct advertise_route_entry *ar = xzalloc(sizeof(*ar));
hmap_insert(&ad->routes, &ar->node,
advertise_route_hash(&prefix, plen));
ar->addr = prefix;
ar->plen = plen;
+ ar->priority = priority;
}
sbrec_route_index_destroy_row(route_filter);
@@ -59,6 +59,7 @@ struct advertise_route_entry {
struct hmap_node node;
struct in6_addr addr;
unsigned int plen;
+ unsigned int priority;
/* used by the route-exchange module to determine if the route is
* already installed */
bool installed;
northd allows us to announce host routes instead of connected routes of LRs. For the host routes we also know the LSP that host the address. We can then check if this LSP is pointing to a LRP that is also local to the current chassis, so if a LR is chained behind an LR and both use chassisredirect ports. In this case we can announce the route with a more preferable priority than otherwise. This helps in the following case: * the backend router is bound on only a single chassis * the frontend router is bound to multiple chassis (with multiple LRPs) * one of the chassis of the frontend router matches the backend router In this case it would be preferable if the network fabric sends the traffic to the chassis that hosts both the frontend and backend router. Other chassis would work as well, but then OVN would redirect the traffic from one chassis to the other. So this allows us to skip tunneling traffic in one case. Signed-off-by: Felix Huettner <felix.huettner@stackit.cloud> --- controller/route-exchange-netlink.c | 20 ++++++++++++-------- controller/route-exchange-netlink.h | 4 ++-- controller/route.c | 29 +++++++++++++++++++++++++++++ controller/route.h | 1 + 4 files changed, 44 insertions(+), 10 deletions(-)