All of lore.kernel.org
 help / color / mirror / Atom feed
From: Hangbin Liu <hangbin.liu@linux.dev>
To: Jay Vosburgh <jv@jvosburgh.net>
Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
	Hangbin Liu <liuhangbin@gmail.com>,
	Hangbin Liu <liuhangbin@kylinos.cn>,
	Andrew Lunn <andrew+netdev@lunn.ch>,
	"David S. Miller" <davem@davemloft.net>,
	Eric Dumazet <edumazet@google.com>,
	Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
	Simon Horman <horms@kernel.org>
Subject: Re: [PATCH net v2] bonding: fix u32 overflow in compute_gap()
Date: Mon, 17 Aug 2026 14:56:39 +0800	[thread overview]
Message-ID: <aoKwp6gTtSrnzR2n@fedora> (raw)
In-Reply-To: <20260814-bond_overflow-v2-1-d3fe588ad167@kylinos.cn>

Hi Jay,
On Fri, Aug 14, 2026 at 01:39:23PM +0800, Hangbin Liu wrote:
> From: Hangbin Liu <liuhangbin@kylinos.cn>
> 
> The TLB fields tx_bytes, load_history, load, and unbalanced_load are
> all u32, which can overflow when sustained throughput exceeds ~3.2
> Gbit/s over the 10-second rebalance interval. On modern high-speed
> NICs under heavy load this is easily reached, causing the gap
> calculation in compute_gap() to wrap and produce incorrect slave
> selection.
> 
> Widen these fields to s64 so the load arithmetic stays correct.
> This also lets compute_gap() naturally return negative values when a
> slave is oversubscribed, which the existing max-gap selection already
> handles.
> 
> Additionally, the NIC speed is left-shifted before being cast to s64.
> For speeds >= 4 Gbit/s (slave->speed >= 4096), the u32 shift
> (4096 << 20 = 0x100000000) overflows before the cast takes effect.
> Cast slave->speed to s64 before shifting so the arithmetic is
> performed in 64 bits throughout.
> 
> Also cast SPEED_UNKNOWN to 0; otherwise, it would be the largest speed
> after the shift.
> 
> Detected by AI code review.
> 
> Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
> Signed-off-by: Hangbin Liu <liuhangbin@kylinos.cn>
> ---
> Changes in v2:
> - update comment description, including AI-detected info.
> - fix tx_bytes/load type detected by sashiko
> - cast SPEED_UNKNOWN to 0 before shift, detected by sashiko
> - Link to v1: https://lore.kernel.org/r/20260810-bond_overflow-v1-1-c9ff29d76770@kylinos.cn
> ---
>  drivers/net/bonding/bond_alb.c | 12 ++++++++++--
>  include/net/bond_alb.h         |  8 ++++----
>  2 files changed, 14 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
> index 839f7482dc18..052ab6beb661 100644
> --- a/drivers/net/bonding/bond_alb.c
> +++ b/drivers/net/bonding/bond_alb.c
> @@ -6,6 +6,7 @@
>  #include <linux/skbuff.h>
>  #include <linux/netdevice.h>
>  #include <linux/etherdevice.h>
> +#include <linux/ethtool.h>
>  #include <linux/pkt_sched.h>
>  #include <linux/spinlock.h>
>  #include <linux/slab.h>
> @@ -160,8 +161,15 @@ static void tlb_deinitialize(struct bonding *bond)
>  
>  static long long compute_gap(struct slave *slave)
>  {
> -	return (s64) (slave->speed << 20) - /* Convert to Megabit per sec */
> -	       (s64) (SLAVE_TLB_INFO(slave).load << 3); /* Bytes to bits */
> +	s64 speed;
> +
> +	if (slave->speed == SPEED_UNKNOWN)
> +		speed = 0;
> +	else
> +		speed = (s64)slave->speed;
> +
> +	return (speed << 20) - /* Mbit/s -> bit/s */
> +	       (SLAVE_TLB_INFO(slave).load << 3); /* Byte/s -> bit/s */
>  }
>  
>  static struct slave *tlb_get_least_loaded_slave(struct bonding *bond)
> diff --git a/include/net/bond_alb.h b/include/net/bond_alb.h
> index e5945427f38d..4933a855a438 100644
> --- a/include/net/bond_alb.h
> +++ b/include/net/bond_alb.h
> @@ -57,12 +57,12 @@ struct tlb_client_info {
>  				 * packets to a Client that the Hash function
>  				 * gave this entry index.
>  				 */
> -	u32 tx_bytes;		/* Each Client accumulates the BytesTx that
> +	s64 tx_bytes;		/* Each Client accumulates the BytesTx that
>  				 * were transmitted to it, and after each
>  				 * CallBack the LoadHistory is divided
>  				 * by the balance interval
>  				 */
> -	u32 load_history;	/* This field contains the amount of Bytes
> +	s64 load_history;	/* This field contains the amount of Bytes
>  				 * that were transmitted to this client by
>  				 * the server on the previous balance
>  				 * interval in Bps.
> @@ -118,14 +118,14 @@ struct tlb_slave_info {
>  			 * are the entries that were assigned to use this
>  			 * slave for transmit.
>  			 */
> -	u32 load;	/* Each slave sums the loadHistory of all clients
> +	s64 load;	/* Each slave sums the loadHistory of all clients
>  			 * assigned to it
>  			 */
>  };
>  
>  struct alb_bond_info {
>  	struct tlb_client_info	*tx_hashtbl; /* Dynamically allocated */
> -	u32			unbalanced_load;
> +	s64			unbalanced_load;
>  	atomic_t		tx_rebalance_counter;
>  	int			lp_counter;
>  	/* -------- rlb parameters -------- */

Sashiko reported that on a 32-bit system, these s64 numbers' read/write
operations and division will tear. We need to use div_s64() for divisions
and may also need to convert the number to atomic64_t for read/write operations.

Do you know how bonding support works on a 32-bit system? Should we handle it?

Thanks
Hangbin

      reply	other threads:[~2026-08-17  6:57 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-14  5:39 [PATCH net v2] bonding: fix u32 overflow in compute_gap() Hangbin Liu
2026-08-17  6:56 ` Hangbin Liu [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=aoKwp6gTtSrnzR2n@fedora \
    --to=hangbin.liu@linux.dev \
    --cc=andrew+netdev@lunn.ch \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=horms@kernel.org \
    --cc=jv@jvosburgh.net \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=liuhangbin@gmail.com \
    --cc=liuhangbin@kylinos.cn \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.