On 1/19/26 8:39 PM, Lucas Vargas Dias via dev wrote:
> FIN or FIN-ACK packets from client was dropping because the client
> side was using conntrack. Connection is in SYN_SENT state because the
> response from backends bypass the conntrack, when client sends a FIN
> or FIN-ACK, the conntrack is invalid and packet is dropped.
> To fix it, remove the client side from conntrack, calculating the hash
> from packet to choice the backend.
> REG_IDX_LB_STATELESS is used to store the index from backend.
>
> Signed-off-by: Lucas Vargas Dias <[email protected]>
> ---
Hi Lucas,
Thanks for the backport!
> northd/lb.c | 3 +
> northd/lb.h | 2 +
> northd/northd.c | 281 +++++++++++++++++++++++++++++++-------------
> tests/multinode.at | 99 ++++++++++------
> tests/ovn-northd.at | 217 ++++++++++++++++++++++++++++++++--
> 5 files changed, 473 insertions(+), 129 deletions(-)
>
> diff --git a/northd/lb.c b/northd/lb.c
> index af0c92954..ef92249ce 100644
> --- a/northd/lb.c
> +++ b/northd/lb.c
> @@ -296,6 +296,9 @@ ovn_northd_lb_init(struct ovn_northd_lb *lb,
> }
> lb->affinity_timeout = affinity_timeout;
>
> + lb->use_stateless_nat = smap_get_bool(&nbrec_lb->options,
> + "use_stateless_nat", false);
> +
> sset_init(&lb->ips_v4);
> sset_init(&lb->ips_v6);
> struct smap_node *node;
> diff --git a/northd/lb.h b/northd/lb.h
> index aa6616af4..4696b4d98 100644
> --- a/northd/lb.h
> +++ b/northd/lb.h
> @@ -72,6 +72,8 @@ struct ovn_northd_lb {
>
> /* Indicates if the load balancer has health checks configured. */
> bool health_checks;
> +
> + bool use_stateless_nat;
> };
>
> /* ovn-northd specific backend information. */
> diff --git a/northd/northd.c b/northd/northd.c
> index f6559c240..5c78f322e 100644
> --- a/northd/northd.c
> +++ b/northd/northd.c
> @@ -149,6 +149,7 @@ static bool vxlan_ic_mode;
> #define REG_LB_IPV4 "reg4"
> #define REG_LB_IPV6 "xxreg1"
> #define REG_LB_PORT "reg2[0..15]"
> +#define REG_IDX_LB_STATELESS "reg1[0..15]"
>
> /* Registers for ACL evaluation */
> #define REGBIT_ACL_VERDICT_ALLOW "reg8[16]"
> @@ -12021,6 +12022,154 @@ lrouter_use_common_zone(const struct ovn_datapath
> *od)
> return !od->is_gw_router && use_common_zone;
> }
>
> +static void
> +build_lrouter_flows_for_lb_stateless(struct lrouter_nat_lb_flows_ctx *ctx,
> + struct ovn_datapath *od,
> + struct lflow_ref *lflow_ref,
> + struct ovn_port *dgp,
> + const char *meter)
> +{
> + /* (NOTE) dnat_action: Add a new rule lr_in_dnat with backend IP
> + * and port action to skip conntrack completely. It is based on
> + * REG_IDX_LB_STATELESS which was calculated in lr_in_defrag.
> + * So, if the packet has VIP IP destination and port
> + * (if port was configured), it selects a backend based on
> + * REG_IDX_LB_STATELESS. It works to multi-chassis and avoid to
> + * sync conntrack between them.
> + */
> + struct ds new_action_stateless_nat = DS_EMPTY_INITIALIZER;
> + struct ds new_match_stateless_nat = DS_EMPTY_INITIALIZER;
> + if (ctx->lb_vip->n_backends ||
> + !ctx->lb_vip->empty_backend_rej) {
> + ds_put_format(&new_match_stateless_nat, "is_chassis_resident(%s)",
> + dgp->cr_port->json_key);
> + }
> +
> + bool ipv4 = ctx->lb_vip->address_family == AF_INET;
> + const char *ip_match = ipv4 ? "ip4" : "ip6";
> + ds_put_format(&new_match_stateless_nat, " && %s && %s.dst == %s",
> + ip_match, ip_match, ctx->lb_vip->vip_str);
> + if (ctx->lb_vip->port_str) {
> + ds_put_format(&new_match_stateless_nat,
> + " && %s && %s.dst == %s",
> + ctx->lb->proto, ctx->lb->proto,
> + ctx->lb_vip->port_str);
> + }
> +
> + const struct ovn_lb_backend *backend;
> + if (ctx->lb_vip->n_backends == 1) {
> + backend = &ctx->lb_vip->backends[0];
> + ds_put_format(&new_action_stateless_nat, "%s.dst = %s; ",
> + ip_match, backend->ip_str);
> + if (ctx->lb_vip->port_str) {
> + ds_put_format(&new_action_stateless_nat, "%s.dst = %s; ",
> + ctx->lb->proto, backend->port_str);
> + }
> + ds_put_format(&new_action_stateless_nat, "next;");
> + ovn_lflow_add_with_hint__(ctx->lflows, od, S_ROUTER_IN_DNAT,
> + ctx->prio,
> + ds_cstr(&new_match_stateless_nat),
> + ds_cstr(&new_action_stateless_nat),
> + NULL, meter, &ctx->lb->nlb->header_,
> + lflow_ref);
> + }
> + size_t match_len = new_match_stateless_nat.length;
> +
> + size_t i = 0;
> + for (; i < ctx->lb_vip->n_backends; i++) {
Nit: 'size_t i = 0' can be moved inside the 'for'.
I took care of this and applied the patch to 25.03.
Regards,
Dumitru
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev