diff mbox series

[ovs-dev,v2,24/32] controller: Prioritize host routes.

Message ID 8c7a994a1de7c308a3acc1236f99c35536777f6d.1730713432.git.felix.huettner@stackit.cloud
State Superseded
Headers show
Series OVN Fabric integration | expand

Checks

Context Check Description
ovsrobot/apply-robot success apply and check: success

Commit Message

Felix Huettner Nov. 4, 2024, 11:04 a.m. UTC
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(-)
diff mbox series

Patch

diff --git a/controller/route-exchange-netlink.c b/controller/route-exchange-netlink.c
index ee33d08d2..1d6e1a58e 100644
--- a/controller/route-exchange-netlink.c
+++ b/controller/route-exchange-netlink.c
@@ -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 "
diff --git a/controller/route-exchange-netlink.h b/controller/route-exchange-netlink.h
index 566b38fde..4c0f37a98 100644
--- a/controller/route-exchange-netlink.h
+++ b/controller/route-exchange-netlink.h
@@ -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);
 
diff --git a/controller/route.c b/controller/route.c
index 6aaabe576..3af7b8859 100644
--- a/controller/route.c
+++ b/controller/route.c
@@ -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);
 
diff --git a/controller/route.h b/controller/route.h
index ca309c7be..b5aab50cb 100644
--- a/controller/route.h
+++ b/controller/route.h
@@ -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;