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]>
---
 controller/route-exchange-netlink.c |  1 +
 controller/route-exchange-netlink.h |  2 ++
 controller/route-exchange.c         | 21 +++++++++++++++------
 controller/route.c                  | 12 +++++++++---
 controller/route.h                  |  6 ++++--
 tests/system-ovn.at                 | 11 +++++++++++
 6 files changed, 42 insertions(+), 11 deletions(-)

diff --git a/controller/route-exchange-netlink.c 
b/controller/route-exchange-netlink.c
index e373060d8..7619c1ec9 100644
--- a/controller/route-exchange-netlink.c
+++ b/controller/route-exchange-netlink.c
@@ -227,6 +227,7 @@ handle_route_msg_delete_routes(const struct route_table_msg 
*msg, void *data)
             rr->addr = rd->rta_dst;
             rr->plen = plen;
             rr->nexthop = nexthop->addr;
+            memcpy(rr->ifname, nexthop->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 50b4709c0..b3968b442 100644
--- a/controller/route-exchange.c
+++ b/controller/route-exchange.c
@@ -101,7 +101,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_learned_route_by_datapath,
                        struct ovsdb_idl_index *sbrec_port_binding_by_name)
@@ -116,8 +116,9 @@ sb_sync_learned_routes(const struct sbrec_datapath_binding 
*datapath,
     SBREC_LEARNED_ROUTE_FOR_EACH_EQUAL (sb_route, filter,
                                         sbrec_learned_route_by_datapath) {
         /* If the port is not local we don't care about it.
-         * Some other ovn-controller will handle it. */
-        if (!sset_contains(bound_ports,
+         * 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->logical_port)) {
             continue;
         }
@@ -137,14 +138,22 @@ sb_sync_learned_routes(const struct 
sbrec_datapath_binding *datapath,
                                                learned_route->plen);
         char *nexthop = normalize_v46(&learned_route->nexthop);
 
-        const char *logical_port_name;
-        SSET_FOR_EACH (logical_port_name, 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;
+            }
+
             const struct sbrec_port_binding *logical_port =
                 lport_lookup_by_name(sbrec_port_binding_by_name,
-                                     logical_port_name);
+                                     port_node->key);
             if (!logical_port) {
                 continue;
             }
+
             route_e = route_lookup_or_add(&sync_routes,
                 datapath,
                 logical_port, ip_prefix, nexthop);
diff --git a/controller/route.c b/controller/route.c
index fdff7573a..ceebe56d1 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 2a54cf3e3..4b71fa88a 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 3efd9a78d..2dd699de8 100644
--- a/tests/system-ovn.at
+++ b/tests/system-ovn.at
@@ -14592,6 +14592,17 @@ AT_CHECK_UNQUOTED([ovn-sbctl --columns 
ip_prefix,nexthop,logical_port --bare fin
 $lp
 ])
 
+# 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 Learned_Route 0
+
+# 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 Learned_Route 1
+
+
 OVS_APP_EXIT_AND_WAIT([ovn-controller])
 
 as ovn-sb
-- 
2.47.1


_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to