On Wed, May 13, 2026 at 11:15 AM Dumitru Ceara via dev <
[email protected]> wrote:
> The pflow_output SB_port_binding handler triggers a full
> recompute when the type column is updated on a port binding.
> However, for newly created port bindings, the OVSDB IDL
> marks all non-default columns as "updated", even though no
> actual update occurred. This caused every new port binding
> with a non-default type (e.g., remote, patch, localnet,
> router) to unnecessarily trigger a full pflow_output
> recompute, severely impacting ovn-controller performance
> at scale.
>
> This is particularly problematic in deployments that use
> remote LSPs, such as ovn-kubernetes with L2 UDNs, where
> frequent creation of remote port bindings leads to
> continuous full recomputes and high CPU usage.
>
> Guard the type-update check with sbrec_port_binding_is_new()
> and sbrec_port_binding_is_deleted() so that only genuine
> type changes on existing port bindings trigger a recompute.
> This matches the pattern already used in binding.c for the
> tunnel_key column.
>
> Also fix a typo in the test name ("path" -> "patch").
>
> Fixes: 73a10345a29c ("controller: Update physical flows for peer port when
> the patch port is removed.")
> Reported-at: https://redhat.atlassian.net/browse/FDP-3819
> Reported-by: Patryk Diak <[email protected]>
> Assisted-by: Claude Opus 4.6, Claude Code
> Signed-off-by: Dumitru Ceara <[email protected]>
> ---
> controller/ovn-controller.c | 6 ++++--
> tests/ovn-controller.at | 14 +++++++++++++-
> tests/ovn-performance.at | 7 +++++++
> 3 files changed, 24 insertions(+), 3 deletions(-)
>
> diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
> index 3024399f36..b26ccfbd96 100644
> --- a/controller/ovn-controller.c
> +++ b/controller/ovn-controller.c
> @@ -5081,12 +5081,14 @@ pflow_output_sb_port_binding_handler(struct
> engine_node *node,
> */
> const struct sbrec_port_binding *pb;
> SBREC_PORT_BINDING_TABLE_FOR_EACH_TRACKED (pb,
> p_ctx.port_binding_table) {
> + bool removed = sbrec_port_binding_is_deleted(pb);
> +
> /* Trigger a full recompute if type column is updated. */
> - if (sbrec_port_binding_is_updated(pb,
> SBREC_PORT_BINDING_COL_TYPE)) {
> + if (!removed && !sbrec_port_binding_is_new(pb) &&
> + sbrec_port_binding_is_updated(pb,
> SBREC_PORT_BINDING_COL_TYPE)) {
> destroy_physical_ctx(&p_ctx);
> return EN_UNHANDLED;
> }
> - bool removed = sbrec_port_binding_is_deleted(pb);
> if (!physical_handle_flows_for_lport(pb, removed, &p_ctx,
> &pfo->flow_table)) {
> destroy_physical_ctx(&p_ctx);
> diff --git a/tests/ovn-controller.at b/tests/ovn-controller.at
> index b1814dfb74..f9f64d691c 100644
> --- a/tests/ovn-controller.at
> +++ b/tests/ovn-controller.at
> @@ -962,7 +962,7 @@ AT_CLEANUP
> ])
>
> OVN_FOR_EACH_NORTHD([
> -AT_SETUP([ovn-controller - ovn IP check path ports])
> +AT_SETUP([ovn-controller - ovn IP check patch ports])
> AT_KEYWORDS([ovn-ip-patch-ports])
>
> ovn_start
> @@ -1003,6 +1003,18 @@ check as hv1 ovn-appctl -t ovn-controller
> inc-engine/clear-stats
> check ovn-nbctl --wait=hv lsp-set-type ls0-rp localnet
> check_controller_engine_stats hv1 pflow_output recompute nocompute
>
> +# Check that adding a new port with a non-default type does not trigger
> +# a pflow_output recompute.
> +check as hv1 ovn-appctl -t ovn-controller inc-engine/clear-stats
> +check ovn-nbctl --wait=hv lsp-add ls0 lsp-remote -- lsp-set-type
> lsp-remote remote
> +check_controller_engine_stats hv1 pflow_output norecompute compute
> +
> +# Check that deleting a port with a non-default type does not trigger
> +# a pflow_output recompute.
> +check as hv1 ovn-appctl -t ovn-controller inc-engine/clear-stats
> +check ovn-nbctl --wait=hv lsp-del lsp-remote
> +check_controller_engine_stats hv1 pflow_output norecompute compute
> +
> OVN_CLEANUP([hv1])
> AT_CLEANUP
> ])
> diff --git a/tests/ovn-performance.at b/tests/ovn-performance.at
> index 2bccbb06dd..114917832b 100644
> --- a/tests/ovn-performance.at
> +++ b/tests/ovn-performance.at
> @@ -386,6 +386,13 @@ for i in 1 2; do
> done
> done
>
> +# Check that adding a new port with a non-default type does not trigger
> +# a physical_run.
> +OVN_CONTROLLER_EXPECT_NO_HIT(
> + [hv1 hv2], [physical_run],
> + [ovn-nbctl --wait=hv lsp-add ls1 lsp-remote -- lsp-set-type
> lsp-remote remote]
> +)
> +
> for i in 1 2; do
> j=$((i%2 + 1))
> as=as$i
> --
> 2.54.0
>
> _______________________________________________
> dev mailing list
> [email protected]
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
>
Thank you Dumitru,
applied to main and backported down to 25.09.
Regards,
Ales
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev