On Mon, Jan 19, 2026 at 5:35 PM Xavier Simonart via dev <
[email protected]> wrote:

> When using lb with allow-stateless and enable-stateless-acl-with-lb
> enabled, there was an issue with hairpin traffic.
> SYN and SYN/ACK were properly handled (DNATted and SNATted). However next
> ACK,
> or PACKET, were not properly SNATted, resulting in the TCP connection
> remaining in SYN-RECV/FIN-WAIT-1.
> ACK was then retransmitted, potentially causing a new conntrack entry.
>
> This caused test "enable-stateless-acl-with-lb usage" to randomly fail
> due to this issue.
>
> This patch properly sets REG_LB_IPV4/6 and REG_LB_PORT registers.
> It also modifies the test so that it would also fail w/o the flow
> modification.
>
> Signed-off-by: Xavier Simonart <[email protected]>
> ---
>  northd/northd.c     |  9 +++++++++
>  tests/ovn-northd.at |  4 ++--
>  tests/system-ovn.at | 13 ++++++++++++-
>  3 files changed, 23 insertions(+), 3 deletions(-)
>
> diff --git a/northd/northd.c b/northd/northd.c
> index bb3844c7f..d79fe40c9 100644
> --- a/northd/northd.c
> +++ b/northd/northd.c
> @@ -8063,6 +8063,15 @@ build_lb_rules_pre_stateful(struct lflow_table
> *lflows,
>                                lb_vip->port_str);
>              }
>
> +            if (lb->vips[i].address_family == AF_INET) {
> +                ds_put_format(action, REG_LB_IPV4 " = %s; ",
> lb_vip->vip_str);
> +            } else {
> +                ds_put_format(action, REG_LB_IPV6 " = %s; ",
> lb_vip->vip_str);
> +            }
> +            if (lb_vip->port_str) {
> +                ds_put_format(action, REG_LB_PORT " = %s; ",
> lb_vip->port_str);
> +            }
> +
>              ds_put_cstr(action, "ct_lb_mark;");
>
>              ovn_lflow_add(lflows, od, S_SWITCH_IN_PRE_STATEFUL, 150,
> diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
> index 25655c456..3acd99183 100644
> --- a/tests/ovn-northd.at
> +++ b/tests/ovn-northd.at
> @@ -17919,7 +17919,7 @@ AT_CHECK([grep -E 'ls_in_pre_stateful' sw0flows |
> ovn_strip_lflows], [0], [dnl
>    table=??(ls_in_pre_stateful ), priority=110  , match=(reg0[[2]] == 1),
> action=(ct_lb_mark;)
>    table=??(ls_in_pre_stateful ), priority=115  , match=(reg0[[2]] == 1 &&
> ip.is_frag), action=(reg0[[19]] = 1; ct_lb_mark;)
>    table=??(ls_in_pre_stateful ), priority=120  , match=(reg0[[2]] == 1 &&
> ip4.dst == 10.0.0.5), action=(reg4 = 10.0.0.5; ct_lb_mark;)
> -  table=??(ls_in_pre_stateful ), priority=150  , match=(ip4.dst ==
> 10.0.0.5), action=(ct_lb_mark;)
> +  table=??(ls_in_pre_stateful ), priority=150  , match=(ip4.dst ==
> 10.0.0.5), action=(reg4 = 10.0.0.5; ct_lb_mark;)
>  ])
>
>  AS_BOX([Set hairpin_snat_ip to Load Balancer without port.])
> @@ -17933,7 +17933,7 @@ AT_CHECK([grep -E 'ls_in_pre_stateful' sw0flows |
> ovn_strip_lflows], [0], [dnl
>    table=??(ls_in_pre_stateful ), priority=110  , match=(reg0[[2]] == 1),
> action=(ct_lb_mark;)
>    table=??(ls_in_pre_stateful ), priority=115  , match=(reg0[[2]] == 1 &&
> ip.is_frag), action=(reg0[[19]] = 1; ct_lb_mark;)
>    table=??(ls_in_pre_stateful ), priority=120  , match=(reg0[[2]] == 1 &&
> ip4.dst == 10.0.0.5), action=(reg4 = 10.0.0.5; ct_lb_mark;)
> -  table=??(ls_in_pre_stateful ), priority=150  , match=(ip4.dst ==
> 10.0.0.5), action=(ct_lb_mark;)
> +  table=??(ls_in_pre_stateful ), priority=150  , match=(ip4.dst ==
> 10.0.0.5), action=(reg4 = 10.0.0.5; ct_lb_mark;)
>  ])
>
>  AS_BOX([Create one more logical switch with load balancer.])
> diff --git a/tests/system-ovn.at b/tests/system-ovn.at
> index fc601dd1b..5b3dc47fd 100644
> --- a/tests/system-ovn.at
> +++ b/tests/system-ovn.at
> @@ -4907,7 +4907,6 @@ AT_CLEANUP
>  OVN_FOR_EACH_NORTHD([
>  AT_SETUP([enable-stateless-acl-with-lb usage])
>  AT_SKIP_IF([test $HAVE_NC = no])
> -TAG_UNSTABLE
>
>  CHECK_CONNTRACK()
>  ovn_start
> @@ -5018,6 +5017,7 @@ NETNS_DAEMONIZE([lsp1], [nc -u -l 192.168.0.101
> 4042], [lsp1_udp.pid])
>  NETNS_DAEMONIZE([lsp1], [nc -l -k 192.168.0.101 4043], [lsp1_non_lb.pid])
>
>  # Send the packet to VIP from private network.
> +NETNS_START_TCPDUMP([lsp1], [-nnnei lsp1], [lsp1])
>  NS_CHECK_EXEC([lsp1], [nc -z 192.168.0.1 8080], [0], [ignore], [ignore])
>
>  # Udp connections
> @@ -5033,6 +5033,17 @@
> udp,orig=(src=192.168.0.101,dst=192.168.0.1,sport=<cleared>,dport=<cleared>),rep
>
>  AT_CHECK([ovs-appctl dpctl/flush-conntrack])
>
> +# Do the same sending a packet.
> +NS_CHECK_EXEC([lsp1], [echo a | nc 192.168.0.1 8080], [0], [ignore],
> [ignore])
> +
> +# Check conntrack zone of lsp1 has tcp entry for lb
> +AT_CHECK([ovs-appctl dpctl/dump-conntrack zone=$zone_lsp1_id | \
> +FORMAT_CT(192.168.0.1) | \
> +sed -e 's/zone=[[0-9]]*/zone=<cleared>/'], [0], [dnl
>
> +tcp,orig=(src=192.168.0.101,dst=192.168.0.1,sport=<cleared>,dport=<cleared>),reply=(src=192.168.0.101,dst=192.168.0.101,sport=<cleared>,dport=<cleared>),zone=<cleared>,mark=2,protoinfo=(state=<cleared>)
> +])
> +AT_CHECK([ovs-appctl dpctl/flush-conntrack])
> +
>  # Check that internal traffic not related to lb doesn't create conntrack
> records
>  NS_CHECK_EXEC([external], [nc -z 192.168.0.101 4043], [0], [])
>
> --
> 2.47.1
>
> _______________________________________________
> dev mailing list
> [email protected]
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
>
Thank you Xavier,

I have added the missing Fixes tag, went ahead and merged this into main
and 25.09.

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

Reply via email to