When ovn-controller returns DNS responses with multiple IP addresses, clients typically use the first IP in the list. Without randomization, all clients direct traffic to the same backend, leading to uneven load distribution.
This patch implements Fisher-Yates shuffle on IPv4 and IPv6 address arrays before building DNS answers, ensuring each query returns IPs in a randomized order for better traffic distribution across backends. v2: - Fixed test to accept either IP ordering due to round-robin shuffling Signed-off-by: Mehrdad Moradi <[email protected]> --- controller/pinctrl.c | 40 ++++++++++++++++++++++++++++++++++ tests/ovn.at | 52 +++++++++++++++++++++++++++++++++++++++----- 2 files changed, 86 insertions(+), 6 deletions(-) diff --git a/controller/pinctrl.c b/controller/pinctrl.c index ab8a0a37c..8f9edf7cd 100644 --- a/controller/pinctrl.c +++ b/controller/pinctrl.c @@ -3365,6 +3365,42 @@ dns_build_ptr_answer( free(encoded); } +/* On Wed, Jan 28, 2026 at 2:23 PM Mehrdad Moradi <[email protected]> wrote: > From cc6e5132aa2b299933af0f0b3565d43b320217ce Mon Sep 17 00:00:00 2001 > From: Mehrdad Moradi <[email protected]> > Date: Wed, 28 Jan 2026 14:13:12 -0800 > Subject: [PATCH ovn] pinctrl: Randomize DNS response IP order for load > balancing. > > When ovn-controller returns DNS responses with multiple IP addresses, > clients typically use the first IP in the list. Without randomization, > all clients direct traffic to the same backend, leading to uneven load > distribution. > > This patch implements Fisher-Yates shuffle on IPv4 and IPv6 address > arrays before building DNS answers, ensuring each query returns IPs > in a randomized order for better traffic distribution across backends. > > Signed-off-by: Mehrdad Moradi <[email protected]> > --- > controller/pinctrl.c | 40 ++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 40 insertions(+) > > diff --git a/controller/pinctrl.c b/controller/pinctrl.c > index ab8a0a37c..8f9edf7cd 100644 > --- a/controller/pinctrl.c > +++ b/controller/pinctrl.c > @@ -3365,6 +3365,42 @@ dns_build_ptr_answer( > free(encoded); > } > > +/* Shuffle IPv4 addresses using Fisher-Yates for DNS round-robin. */ > +static void > +dns_shuffle_ipv4_addrs(struct ipv4_netaddr *addrs, size_t n) > +{ > + if (n <= 1) { > + return; > + } > + > + for (size_t i = n - 1; i > 0; i--) { > + size_t j = random_range(i + 1); > + if (i != j) { > + struct ipv4_netaddr tmp = addrs[i]; > + addrs[i] = addrs[j]; > + addrs[j] = tmp; > + } > + } > +} > + > +/* Shuffle IPv6 addresses using Fisher-Yates for DNS round-robin. */ > +static void > +dns_shuffle_ipv6_addrs(struct ipv6_netaddr *addrs, size_t n) > +{ > + if (n <= 1) { > + return; > + } > + > + for (size_t i = n - 1; i > 0; i--) { > + size_t j = random_range(i + 1); > + if (i != j) { > + struct ipv6_netaddr tmp = addrs[i]; > + addrs[i] = addrs[j]; > + addrs[j] = tmp; > + } > + } > +} > + > #define DNS_RCODE_SERVER_REFUSE 0x5 > #define DNS_QUERY_TYPE_CLASS_LEN (2 * sizeof(ovs_be16)) > > @@ -3530,6 +3566,10 @@ pinctrl_handle_dns_lookup( > goto exit; > } > > + /* Shuffle IPs for round-robin load balancing. */ > + dns_shuffle_ipv4_addrs(ip_addrs.ipv4_addrs, > ip_addrs.n_ipv4_addrs); > + dns_shuffle_ipv6_addrs(ip_addrs.ipv6_addrs, > ip_addrs.n_ipv6_addrs); > + > if (query_type == DNS_QUERY_TYPE_A || > query_type == DNS_QUERY_TYPE_ANY) { > for (size_t i = 0; i < ip_addrs.n_ipv4_addrs; i++) { > -- > 2.52.0 > > _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
