Re: [PATCH net v5 2/2] bonding: fix u32 overflow in compute_gap()
From: Paolo Abeni
Date: Thu Aug 27 2026 - 09:52:55 EST
On 8/25/26 3:01 AM, Hangbin Liu wrote:
> From: Hangbin Liu <liuhangbin@xxxxxxxxxx>
>
> The TLB load-tracking fields tx_bytes, load_history, load, and
> unbalanced_load are all u32. At sustained throughput above ~3.2 Gbit/s
> over the 10-second rebalance interval the byte counters wrap, causing
> compute_gap() to produce incorrect gap values and mis-select slaves.
> Such speeds are common on modern NICs under heavy traffic.
>
> Widen these fields to u64. Use u64_stats_sync to protect the per-cpu
> unbalanced_load_stats against tearing on 32-bit architectures, and
> div_u64() for the 64-bit divisions. The tx_bytes and load_history
> are protected in spin_lock. Also protect the slave load writing in
> bond_alb_monitor() with spin_lock in case of tear on 32-bit.
>
> Rework compute_gap() to use s64 arithmetic throughout. Return LLONG_MIN
> when the speed is unknown.
>
> Detected by AI code review.
>
> Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
> Signed-off-by: Hangbin Liu <liuhangbin@xxxxxxxxxx>
> ---
> drivers/net/bonding/bond_alb.c | 52 ++++++++++++++++++++++++++++++------------
> include/net/bond_alb.h | 11 +++++----
> 2 files changed, 44 insertions(+), 19 deletions(-)
>
> diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
> index 0afed2c39231..9a43a1f47893 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>
> @@ -74,8 +75,8 @@ static inline u8 _simple_hash(const u8 *hash_start, int hash_size)
> static inline void tlb_init_table_entry(struct tlb_client_info *entry, int save_load)
> {
> if (save_load) {
> - entry->load_history = 1 + entry->tx_bytes /
> - BOND_TLB_REBALANCE_INTERVAL;
> + entry->load_history = 1 + div_u64(entry->tx_bytes,
> + BOND_TLB_REBALANCE_INTERVAL);
> entry->tx_bytes = 0;
> }
>
> @@ -133,7 +134,7 @@ static int tlb_initialize(struct bonding *bond)
> if (!new_hashtbl)
> return -ENOMEM;
>
> - bond_info->unbalanced_load = alloc_percpu(struct unbalanced_load_stats);
> + bond_info->unbalanced_load = netdev_alloc_pcpu_stats(struct unbalanced_load_stats);
> if (!bond_info->unbalanced_load)
> goto out;
>
> @@ -170,8 +171,14 @@ 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 */
> + u32 raw_speed = READ_ONCE(slave->speed);
> +
> + /* It's meaningless to compare gap on unknown speed NIC */
> + if (raw_speed == (u32)SPEED_UNKNOWN)
> + return LLONG_MIN;
Sashiko noted the above could entirely disable:
https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260825-bond_overflow-v5-0-7a800de133f1%40kylinos.cn
I think the v2 code for the above should be fine.
All other comments look noise to me.
/P