On Wed, Nov 5, 2025 at 1:42 PM Dumitru Ceara <[email protected]> wrote:
> This patch covers a few scenarios that were missed by the
> dynamic-routing route advertisement support:
> - "pure" patch ports (between routers and switches) are fully
> distributed hence always local (if the switch/router is a local
> datapath)
> - when installing advertised routes do that only for records whose
> 'logical_port' is local to the hypervisor (it's not enough to check if
> the 'tracked_port' is local)
> - due to the fact that a pure patch port can change to a
> chassis-redirect port (when the associated LRP becomes a DGP) it's
> possible that the route_runtime_data_handler() is not called (no local
> datapath change). However, the route_sb_port_binding_data_handler()
> does run and it can detect if changes happened to chassis-redirect
> ports for distributed ports that are relevant to routing
>
> The patch also adds a system test to ensure the behavior in the above
> scenarios is correct.
>
> Fixes: a3f72e44ddde ("controller: Make sure we will update routes on
> tracked port change.")
> Fixes: ccb0b6b9109c ("controller: Introduce route node.")
> Fixes: 712fca55b3b1 ("controller: Prioritize host routes.")
> Signed-off-by: Dumitru Ceara <[email protected]>
> ---
> controller/lport.c | 5 ++
> controller/ovn-controller.c | 14 ++++
> controller/route.c | 10 +++
> tests/system-ovn.at | 128 ++++++++++++++++++++++++++++++++----
> 4 files changed, 145 insertions(+), 12 deletions(-)
>
> diff --git a/controller/lport.c b/controller/lport.c
> index 077e66acff..b30bcd398e 100644
> --- a/controller/lport.c
> +++ b/controller/lport.c
> @@ -107,6 +107,11 @@ lport_is_local(struct ovsdb_idl_index
> *sbrec_port_binding_by_name,
> const struct sbrec_port_binding *cr_pb =
> lport_get_cr_port(sbrec_port_binding_by_name, pb, NULL);
>
> + /* Patch ports that are not redirect ports are always local. */
> + if (!cr_pb && get_lport_type(pb) == LP_PATCH) {
> + return true;
> + }
> +
> return lport_pb_is_chassis_resident(chassis, cr_pb);
> }
>
> diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
> index c2dab41c11..5699e29d95 100644
> --- a/controller/ovn-controller.c
> +++ b/controller/ovn-controller.c
> @@ -5390,6 +5390,20 @@ route_sb_port_binding_data_handler(struct
> engine_node *node, void *data)
> * request recompute. */
> return EN_UNHANDLED;
> }
> +
> + const char *dp_name = smap_get(&sbrec_pb->options,
> "distributed-port");
> + if (dp_name && sset_contains(&re_data->tracked_ports_local,
> + dp_name)) {
> + /* XXX: Until we get I-P support for route exchange we need to
> + * request recompute. */
> + return EN_UNHANDLED;
> + }
> + if (dp_name && sset_contains(&re_data->tracked_ports_remote,
> + dp_name)) {
> + /* XXX: Until we get I-P support for route exchange we need to
> + * request recompute. */
> + return EN_UNHANDLED;
> + }
> }
>
> return EN_HANDLED_UNCHANGED;
> diff --git a/controller/route.c b/controller/route.c
> index dded03d352..093306c5b3 100644
> --- a/controller/route.c
> +++ b/controller/route.c
> @@ -284,6 +284,16 @@ route_run(struct route_ctx_in *r_ctx_in,
> continue;
> }
>
> + if (!lport_is_local(r_ctx_in->sbrec_port_binding_by_name,
> + r_ctx_in->chassis,
> + route->logical_port->logical_port)) {
> + sset_add(r_ctx_out->tracked_ports_remote,
> + route->logical_port->logical_port);
> + continue;
> + }
> + sset_add(r_ctx_out->tracked_ports_local,
> + route->logical_port->logical_port);
> +
> unsigned int priority = PRIORITY_DEFAULT;
> if (route->tracked_port) {
> bool redistribute_local_bound_only =
> diff --git a/tests/system-ovn.at b/tests/system-ovn.at
> index cc672d43a0..8abfb6dfac 100644
> --- a/tests/system-ovn.at
> +++ b/tests/system-ovn.at
> @@ -15932,13 +15932,14 @@ blackhole 198.51.100.0/24 proto ovn metric
> 1000])
> # * 192.0.2.3/32
> # * 192.0.2.10/32
> # * 192.0.2.20/32
> -# The last 3 of them are local to the current chassis so we expect a
> better
> -# prio.
> +# All of them are local to the current chassis (the first one is a patch
> port
> +# and the last two are chassis redirect ports bound to the current
> chassis)
> +# so we expect a better prio for all of them.
> check ovn-nbctl --wait=hv set Logical_Router_Port internet-public \
> options:dynamic-routing-redistribute="connected-as-host,static,nat"
>
> OVN_ROUTE_EQUAL([ovnvrf1337], [dnl
> -blackhole 192.0.2.1 proto ovn metric 1000
> +blackhole 192.0.2.1 proto ovn metric 100
> 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
> @@ -15951,7 +15952,7 @@ blackhole 198.51.100.0/24 proto ovn metric 1000])
> check ovn-nbctl lrp-del-gateway-chassis pr1-public hv1
> check ovn-nbctl --wait=hv lrp-set-gateway-chassis pr1-public hv123
> OVN_ROUTE_EQUAL([ovnvrf1337], [dnl
> -blackhole 192.0.2.1 proto ovn metric 1000
> +blackhole 192.0.2.1 proto ovn metric 100
> blackhole 192.0.2.2 proto ovn metric 1000
> blackhole 192.0.2.3 proto ovn metric 100
> blackhole 192.0.2.10 proto ovn metric 1000
> @@ -15962,7 +15963,7 @@ blackhole 198.51.100.0/24 proto ovn metric 1000])
> check ovn-nbctl lrp-del-gateway-chassis pr1-public hv123
> check ovn-nbctl --wait=hv lrp-set-gateway-chassis pr1-public hv1
> OVN_ROUTE_EQUAL([ovnvrf1337], [dnl
> -blackhole 192.0.2.1 proto ovn metric 1000
> +blackhole 192.0.2.1 proto ovn metric 100
> 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
> @@ -15972,7 +15973,7 @@ blackhole 198.51.100.0/24 proto ovn metric 1000])
> # Moving vif3 away from hv1 will change the route metric to default.
> check ovn-nbctl --wait=hv set Logical_Switch_Port vif3
> options:requested-chassis=thisdoesnotexist
> OVN_ROUTE_EQUAL([ovnvrf1337], [dnl
> -blackhole 192.0.2.1 proto ovn metric 1000
> +blackhole 192.0.2.1 proto ovn metric 100
> 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
> @@ -15982,7 +15983,7 @@ blackhole 198.51.100.0/24 proto ovn metric 1000])
> # Bringing vif3 back will change the route metric to local again.
> check ovn-nbctl --wait=hv set Logical_Switch_Port vif3
> options:requested-chassis=hv1
> OVN_ROUTE_EQUAL([ovnvrf1337], [dnl
> -blackhole 192.0.2.1 proto ovn metric 1000
> +blackhole 192.0.2.1 proto ovn metric 100
> 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
> @@ -16050,7 +16051,7 @@ OVN_ROUTE_EQUAL([ovnvrf1337], [dnl
> start_daemon ovn-controller
> OVS_WAIT_UNTIL([test "$(ovn-appctl -t ovn-controller debug/status)" ==
> "running"])
> OVN_ROUTE_EQUAL([ovnvrf1337], [dnl
> -blackhole 192.0.2.1 proto ovn metric 1000
> +blackhole 192.0.2.1 proto ovn metric 100
> 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
> @@ -16067,7 +16068,7 @@ check ovn-nbctl --wait=hv set Logical_Router
> internet \
> options:dynamic-routing-vrf-name=ovnvrf1338
> AT_CHECK([ip vrf | grep -q ovnvrf1337], [1], [])
> OVN_ROUTE_EQUAL([ovnvrf1338], [dnl
> -blackhole 192.0.2.1 proto ovn metric 1000
> +blackhole 192.0.2.1 proto ovn metric 100
> 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
> @@ -16079,7 +16080,7 @@ blackhole 198.51.100.0/24 proto ovn metric 1000
> # Stopping with --restart will not touch the routes.
> OVN_CONTROLLER_EXIT([],[--restart])
> OVN_ROUTE_EQUAL([ovnvrf1338], [dnl
> -blackhole 192.0.2.1 proto ovn metric 1000
> +blackhole 192.0.2.1 proto ovn metric 100
> 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
> @@ -16109,6 +16110,7 @@ check ovn-nbctl lsp-add public vip \
> check ovn-nbctl --wait=hv sync
>
> OVN_ROUTE_EQUAL([ovnvrf1338], [dnl
> +blackhole 192.0.2.1 proto ovn metric 100
> 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
> @@ -16123,6 +16125,7 @@ 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.1 proto ovn metric 100
> 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
> @@ -16135,6 +16138,7 @@ blackhole 198.51.100.0/24 proto ovn metric 1000
>
> check ovn-sbctl clear Port_Binding vip virtual-parent
> OVN_ROUTE_EQUAL([ovnvrf1338], [dnl
> +blackhole 192.0.2.1 proto ovn metric 100
> 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
> @@ -16149,6 +16153,7 @@ 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.1 proto ovn metric 100
> 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
> @@ -16164,6 +16169,7 @@ check ovn-sbctl clear Port_Binding vip
> virtual-parent
> wait_column "" Port_Binding chassis logical_port=vip
> check ovn-sbctl set Port_Binding vip virtual_parent=vif5
> OVN_ROUTE_EQUAL([ovnvrf1338], [dnl
> +blackhole 192.0.2.1 proto ovn metric 100
> 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
> @@ -16177,7 +16183,7 @@ blackhole 198.51.100.0/24 proto ovn metric 1000
> check ovn-nbctl --wait=hv set logical_router_port internet-public \
> options:dynamic-routing-redistribute-local-only=false
> OVN_ROUTE_EQUAL([ovnvrf1338], [dnl
> -blackhole 192.0.2.1 proto ovn metric 1000
> +blackhole 192.0.2.1 proto ovn metric 100
> 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
> @@ -16194,7 +16200,7 @@ 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.1 proto ovn metric 1000
> +blackhole 192.0.2.1 proto ovn metric 100
> 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
> @@ -17601,6 +17607,104 @@ OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query
> port patch-.*/d
> AT_CLEANUP
> ])
>
> +OVN_FOR_EACH_NORTHD([
> +AT_SETUP([dynamic-routing - multiple DGP])
> +
> +VRF_RESERVE([1337])
> +
> +ovn_start
> +OVS_TRAFFIC_VSWITCHD_START()
> +
> +ADD_BR([br-int])
> +check ovs-vsctl
> \
> + -- set Open_vSwitch . external-ids:system-id=hv1
> \
> + -- set Open_vSwitch .
> external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \
> + -- set Open_vSwitch . external-ids:ovn-encap-type=geneve
> \
> + -- set Open_vSwitch . external-ids:ovn-encap-ip=169.0.0.1
> \
> + -- set bridge br-int fail-mode=secure
> other-config:disable-in-band=true
> +
> +start_daemon ovn-controller
> +check ovn-nbctl
> \
> + -- lr-add lr
> \
> + -- set logical_router lr options:dynamic-routing=true
> \
> + options:dynamic-routing-vrf-id=1337
> \
> + -- lrp-add lr lr-gw1 00:00:00:01:00:10 42.10.10.12/24
> \
> + -- lrp-set-gateway-chassis lr-gw1 hv1 10
> \
> + -- lrp-set-options lr-gw1 dynamic-routing-redistribute=nat,lb
> \
> + dynamic-routing-maintain-vrf=true
> \
> + -- lrp-add lr lr-gw2 00:00:00:02:00:10 42.20.10.22/24
> \
> + -- lrp-set-gateway-chassis lr-gw2 hv2 10
> \
> + -- lrp-set-options lr-gw2 dynamic-routing-redistribute=nat,lb
> \
> + dynamic-routing-maintain-vrf=true
> \
> + -- lrp-add lr lr-int1 00:00:00:00:01:02 30.0.1.1/24
> \
> + -- lrp-set-options lr-int1
> dynamic-routing-redistribute=connected \
> + -- lrp-add lr lr-int2 00:00:00:00:01:02 30.0.2.1/24
> \
> + -- lrp-set-options lr-int2
> dynamic-routing-redistribute=connected \
> + -- ls-add ls
> \
> + -- lsp-add-router-port ls ls-lr-gw1 lr-gw1
> \
> + -- lsp-add-router-port ls ls-lr-gw2 lr-gw2
> \
> + -- ls-add ls-int1
> \
> + -- lsp-add-router-port ls-int1 ls-int1-lr lr-int1
> \
> + -- lsp-add ls-int1 w1
> \
> + -- lsp-set-addresses w1 "00:00:00:00:00:01 30.0.1.11"
> \
> + -- ls-add ls-int2
> \
> + -- lsp-add-router-port ls-int2 ls-int2-lr lr-int2
> \
> + -- lsp-add ls-int2 w2
> \
> + -- lsp-set-addresses w2 "00:00:00:00:00:02 30.0.2.11"
> \
> + -- lr-nat-add lr dnat_and_snat 42.10.10.23 30.0.1.11 w1
> 00:00:00:00:01:11 \
> + -- lb-add lb1 42.10.10.14 30.0.1.11
> \
> + -- lr-lb-add lr lb1
> \
> + -- lr-nat-add lr dnat_and_snat 42.20.10.23 30.0.2.11 w2
> 00:00:00:00:02:11 \
> + -- lb-add lb2 42.20.10.24 30.0.2.11
> \
> + -- lr-lb-add lr lb2
> +
> +check ovs-vsctl add-port br-int w1 \
> + -- set interface w1 type=internal external_ids:iface-id=w1
> +check ovs-vsctl add-port br-int w2 \
> + -- set interface w2 type=internal external_ids:iface-id=w2
> +check ovn-nbctl --wait=hv sync
> +wait_for_ports_up w1 w2
> +
> +lrp1=$(fetch_column port_binding _uuid logical_port="lrp1")
> +lrp2=$(fetch_column port_binding _uuid logical_port="lrp2")
> +
> +AT_CHECK([ip vrf show ovnvrf1337], [0], [dnl
> +ovnvrf1337 1337
> +])
> +
> +OVN_ROUTE_EQUAL([ovnvrf1337], [dnl
> +blackhole 30.0.1.0/24 proto ovn metric 1000
> +blackhole 30.0.2.0/24 proto ovn metric 1000
> +blackhole 42.10.10.14 proto ovn metric 100
> +blackhole 42.10.10.14 proto ovn metric 1000
> +blackhole 42.10.10.23 proto ovn metric 100
> +blackhole 42.20.10.23 proto ovn metric 100
> +blackhole 42.20.10.24 proto ovn metric 100
> +blackhole 42.20.10.24 proto ovn metric 1000])
> +
> +check ovn-nbctl --wait=hv ls-del ls-int1
> +check ovn-nbctl --wait=hv ls-del ls-int2
> +check ovn-nbctl --wait=hv ls-del ls
> +check ovn-nbctl --wait=hv lr-del lr
> +
> +OVN_CLEANUP_CONTROLLER([hv1])
> +
> +as ovn-sb
> +OVS_APP_EXIT_AND_WAIT([ovsdb-server])
> +
> +as ovn-nb
> +OVS_APP_EXIT_AND_WAIT([ovsdb-server])
> +
> +as northd
> +OVS_APP_EXIT_AND_WAIT([ovn-northd])
> +
> +as
> +OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d
> +/connection dropped.*/d"])
> +
> +AT_CLEANUP
> +])
> +
> OVN_FOR_EACH_NORTHD([
> AT_SETUP([Mac binding aging - Probing])
> AT_KEYWORDS([mac_binding_probing])
> --
> 2.51.0
>
>
Thank you Dumitru,
I went ahead, applied this to main and backported to 25.09 and 25.03.
Regards,
Ales
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev