When dynamic-routing-redistribute option is set to connected-as-host for
logical_router_port where dynamic-routing is enabled, virtual port ips
are advertise without taking into account if the port is bound locally.
Fix the issue setting the advertised route tracked_port to the virtual
parent port in order to allow the CMS to mange the host route priority
or to not advertised the host route if the port is not local.

Reported-at: https://issues.redhat.com/browse/FDP-1940
Signed-off-by: Lorenzo Bianconi <[email protected]>
---
Changes since v1:
- Remove dynamic-routing-redistribute-local-only check in ovn-northd.
- Improve commit message.
---
 northd/en-advertised-route-sync.c | 44 +++++++++++++++++++--
 tests/system-ovn.at               | 66 +++++++++++++++++++++++++++++++
 2 files changed, 106 insertions(+), 4 deletions(-)

diff --git a/northd/en-advertised-route-sync.c 
b/northd/en-advertised-route-sync.c
index c737376ae..b5ce0c291 100644
--- a/northd/en-advertised-route-sync.c
+++ b/northd/en-advertised-route-sync.c
@@ -129,6 +129,7 @@ advertised_route_table_sync(
     const struct sbrec_advertised_route_table *sbrec_advertised_route_table,
     const struct hmap *routes,
     const struct hmap *dynamic_routes,
+    const struct hmap *ls_ports,
     struct advertised_route_sync_data *data);
 
 enum engine_input_handler_result
@@ -241,6 +242,7 @@ en_advertised_route_sync_run(struct engine_node *node, void 
*data OVS_UNUSED)
         = engine_get_input_data("routes", node);
     struct dynamic_routes_data *dynamic_routes_data
         = engine_get_input_data("dynamic_routes", node);
+    struct northd_data *northd_data = engine_get_input_data("northd", node);
     const struct engine_context *eng_ctx = engine_get_context();
     const struct sbrec_advertised_route_table *sbrec_advertised_route_table =
         EN_OVSDB_GET(engine_get_input("SB_advertised_route", node));
@@ -251,7 +253,7 @@ en_advertised_route_sync_run(struct engine_node *node, void 
*data OVS_UNUSED)
                                 sbrec_advertised_route_table,
                                 &routes_data->parsed_routes,
                                 &dynamic_routes_data->routes,
-                                routes_sync_data);
+                                &northd_data->ls_ports, routes_sync_data);
 
     stopwatch_stop(ADVERTISED_ROUTE_SYNC_RUN_STOPWATCH_NAME, time_msec());
     return EN_UPDATED;
@@ -561,10 +563,37 @@ publish_lport_addresses(struct hmap *sync_routes,
     }
 }
 
+static void
+publish_host_routes_for_virtual_ports(
+        struct ovn_port *port,
+        const struct hmap *ls_ports,
+        const struct ovn_datapath *advertising_od,
+        const struct ovn_port *advertising_op,
+        struct hmap *sync_routes)
+{
+    ovs_assert(port->sb);
+
+    const char *virtual_parent = port->sb->virtual_parent;
+    if (!virtual_parent) {
+        return;
+    }
+
+    struct ovn_port *vp = ovn_port_find(ls_ports, virtual_parent);
+    if (!vp) {
+        return;
+    }
+
+    for (size_t i = 0; i < port->n_lsp_addrs; i++) {
+        publish_lport_addresses(sync_routes, advertising_od, advertising_op,
+                                &port->lsp_addrs[i], vp);
+    }
+}
+
 /* Collect all IP addresses connected to the out_port of a route.
  * This traverses all LSPs on the LS connected to the out_port. */
 static void
 publish_host_routes(struct hmap *sync_routes,
+                    const struct hmap *ls_ports,
                     const struct ovn_datapath *advertising_od,
                     const struct ovn_port *advertising_op,
                     struct advertised_route_sync_data *data)
@@ -597,6 +626,10 @@ publish_host_routes(struct hmap *sync_routes,
             const struct ovn_port *lrp = port->peer;
             publish_lport_addresses(sync_routes, advertising_od,
                                     advertising_op, &lrp->lrp_networks, lrp);
+        } else if (port->nbsp && !strcmp(port->nbsp->type, "virtual")) {
+            publish_host_routes_for_virtual_ports(port, ls_ports,
+                                                  advertising_od,
+                                                  advertising_op, sync_routes);
         } else {
             /* This is just a plain LSP */
             for (size_t i = 0; i < port->n_lsp_addrs; i++) {
@@ -657,6 +690,7 @@ advertise_routes_as_host_prefix(
     struct advertised_route_sync_data *data,
     struct uuidset *host_route_lrps,
     struct hmap *sync_routes,
+    const struct hmap *ls_ports,
     const struct ovn_datapath *advertising_od,
     const struct ovn_port *advertising_op,
     enum route_source source
@@ -673,7 +707,8 @@ advertise_routes_as_host_prefix(
     }
 
     uuidset_insert(host_route_lrps, &advertising_op->nbrp->header_.uuid);
-    publish_host_routes(sync_routes, advertising_od, advertising_op, data);
+    publish_host_routes(sync_routes, ls_ports, advertising_od,
+                        advertising_op, data);
     return true;
 }
 
@@ -726,6 +761,7 @@ advertised_route_table_sync(
     const struct sbrec_advertised_route_table *sbrec_advertised_route_table,
     const struct hmap *routes,
     const struct hmap *dynamic_routes,
+    const struct hmap *ls_ports,
     struct advertised_route_sync_data *data)
 {
     struct hmap sync_routes = HMAP_INITIALIZER(&sync_routes);
@@ -744,8 +780,8 @@ advertised_route_table_sync(
         }
 
         if (advertise_routes_as_host_prefix(data, &host_route_lrps,
-                                            &sync_routes, route->od,
-                                            route->out_port,
+                                            &sync_routes, ls_ports,
+                                            route->od, route->out_port,
                                             route->source)) {
             continue;
         }
diff --git a/tests/system-ovn.at b/tests/system-ovn.at
index 373a87657..941e1fb87 100644
--- a/tests/system-ovn.at
+++ b/tests/system-ovn.at
@@ -15754,6 +15754,7 @@ AT_CLEANUP
 
 OVN_FOR_EACH_NORTHD([
 AT_SETUP([dynamic-routing - DGP])
+AT_SKIP_IF([test "$HAVE_ARPING" = no])
 
 VRF_RESERVE([1337])
 VRF_RESERVE([1338])
@@ -16090,7 +16091,72 @@ blackhole 198.51.100.0/24 proto ovn metric 1000
 # When we now stop the ovn-controller it will remove the VRF.
 start_daemon ovn-controller
 OVS_WAIT_UNTIL([test "$(ovn-appctl -t ovn-controller debug/status)" == 
"running"])
+
+# Create a virutal port "vip" with parent set to "vif4".
+check ovn-nbctl lsp-add public vif4 \
+    -- lsp-set-addresses vif4 "00:00:ff:ff:ff:04 192.0.2.21"
+ADD_NAMESPACES(vif4)
+ADD_VETH(vif4, vif4, br-int, "192.0.2.30/24", "00:00:ff:ff:ff:04", 
"192.0.2.21")
+check ovn-nbctl lsp-add public vip \
+    -- lsp-set-addresses vip "00:00:00:00:01:88 192.0.2.30" \
+    -- lsp-set-type vip virtual \
+    -- set logical_switch_port vip options:virtual-ip=192.0.2.30 \
+    -- set logical_switch_port vip options:virtual-parents=vif4 \
+    -- set logical_router_port internet-public 
options:dynamic-routing-redistribute-local-only=true
 check ovn-nbctl --wait=hv sync
+
+OVN_ROUTE_EQUAL([ovnvrf1338], [dnl
+blackhole 192.0.2.2 proto ovn metric 100
+blackhole 192.0.2.3 proto ovn metric 100
+blackhole 192.0.2.10 proto ovn metric 100
+blackhole 192.0.2.20 proto ovn metric 100
+blackhole 192.0.2.21 proto ovn metric 100
+blackhole 198.51.100.0/24 proto ovn metric 1000
+233.252.0.0/24 via 192.168.10.10 dev lo onlink
+233.253.0.0/24 via 192.168.20.20 dev hv1-mll onlink])
+
+# Bind "vip" port locally and check the virtual IP is added in the VRF.
+NS_EXEC([vif4], [arping -U -c 1 -w 2 -I vif4 192.0.2.30])
+wait_column "vif4" Port_Binding virtual_parent logical_port=vip
+wait_for_ports_up vip
+OVN_ROUTE_EQUAL([ovnvrf1338], [dnl
+blackhole 192.0.2.2 proto ovn metric 100
+blackhole 192.0.2.3 proto ovn metric 100
+blackhole 192.0.2.10 proto ovn metric 100
+blackhole 192.0.2.20 proto ovn metric 100
+blackhole 192.0.2.21 proto ovn metric 100
+blackhole 192.0.2.30 proto ovn metric 100
+blackhole 198.51.100.0/24 proto ovn metric 1000
+233.252.0.0/24 via 192.168.10.10 dev lo onlink
+233.253.0.0/24 via 192.168.20.20 dev hv1-mll onlink])
+
+check ovn-sbctl clear Port_Binding vip virtual-parent
+wait_column "" Port_Binding virtual_parent logical_port=vip
+OVN_ROUTE_EQUAL([ovnvrf1338], [dnl
+blackhole 192.0.2.2 proto ovn metric 100
+blackhole 192.0.2.3 proto ovn metric 100
+blackhole 192.0.2.10 proto ovn metric 100
+blackhole 192.0.2.20 proto ovn metric 100
+blackhole 192.0.2.21 proto ovn metric 100
+blackhole 198.51.100.0/24 proto ovn metric 1000
+233.252.0.0/24 via 192.168.10.10 dev lo onlink
+233.253.0.0/24 via 192.168.20.20 dev hv1-mll onlink])
+
+# Rebind "vip" locally.
+NS_EXEC([vif4], [arping -U -c 1 -w 2 -I vif4 192.0.2.30])
+wait_column "vif4" Port_Binding virtual_parent logical_port=vip
+wait_for_ports_up vip
+OVN_ROUTE_EQUAL([ovnvrf1338], [dnl
+blackhole 192.0.2.2 proto ovn metric 100
+blackhole 192.0.2.3 proto ovn metric 100
+blackhole 192.0.2.10 proto ovn metric 100
+blackhole 192.0.2.20 proto ovn metric 100
+blackhole 192.0.2.21 proto ovn metric 100
+blackhole 192.0.2.30 proto ovn metric 100
+blackhole 198.51.100.0/24 proto ovn metric 1000
+233.252.0.0/24 via 192.168.10.10 dev lo onlink
+233.253.0.0/24 via 192.168.20.20 dev hv1-mll onlink])
+
 OVN_CLEANUP_CONTROLLER([hv1])
 AT_CHECK([ip vrf | grep -q ovnvrf1338], [1], [])
 
-- 
2.51.1

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

Reply via email to