From nobody Thu Apr 9 13:27:13 2026 Received: from mail-pl1-f176.google.com (mail-pl1-f176.google.com [209.85.214.176]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3BD33279DB7 for ; Sun, 8 Mar 2026 07:10:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.176 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772953814; cv=none; b=kpGqJFhsBpY1nMABdO4+ZyEc6VJocV9RxpS+/T7IUsWTZNpDk3aSULRzu4AC+DSrMTgO7QkfhDfDEHPHpCX2Do2KW5qDTF2SgMOMBaV517BBaPaB1ktgGvKzI7rop0B08Gh301sRV84MeT5c656HyeqFtxPf87uZ4inqVIFyuSs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772953814; c=relaxed/simple; bh=0ds3TvVp9Y0y3g1MolUjIlnDaEg4EeYjjW9KPAhlBQE=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=LoEEEdlDx/hDl3f5yjUc3bNyclYJ8Y8zywc7K5HvE/KukoR6K4lkw/a8qnNnjkQb+NRIrwgxms9DuSM9HYDfCrJ3uJwPgdFeK4zIcweA8vHCe5hieV0tKxWUq/FLbvNwyMLoPZF0qiajBq+KzmReBSP6F51yx6AET3VA64WEsT4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=mr/s5HZQ; arc=none smtp.client-ip=209.85.214.176 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="mr/s5HZQ" Received: by mail-pl1-f176.google.com with SMTP id d9443c01a7336-2ab46931cf1so72599415ad.0 for ; Sat, 07 Mar 2026 23:10:13 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772953812; x=1773558612; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=IvG+tAEOxjAJfsrmxdX9V5/bQEDskvpKd6MJkmnCi6U=; b=mr/s5HZQI8pC4SK2PYYM/Sr3A+rZCjv78UQtkwInJiDp7i6BqYJXW3OOOQG9Vkwnz9 AOIsrUVOdVk9IkNGA1ZTjgP/omsbHew52vHrYpcvRj88ckCODnsFFoPmdxlKE/ceoBpg W7uWZQ2bboxis2tRJ3ufYnE3FGbU+rELqFEecefoLZNRqAcK9TTrrRj5bUUuiLcU91Ey SYcSHIDkspr2E23gSzVYCszZuke0W44PjgRSgI70IfUUzTxFQquDCE5EydSpzPEI+p1I uJYsX5aYuYWeOmqStx1+NwTdf33g1jIleQ2lAdjuwxbxPMboryNBb3OYxoimHAKtUVT8 DF/A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772953812; x=1773558612; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=IvG+tAEOxjAJfsrmxdX9V5/bQEDskvpKd6MJkmnCi6U=; b=cU5lCVSBS0+XX11bh6oOcCxG+uHndklX1GMRtgvhPbnO3lhGg3PChxGqJ8Y2bSHIqR 8VmaeCNHaeua4AkrSdnZYo7uWYnrtVFdDTxneYPcYsFc4GRJn83GbExDsbpLKnRAd1+Y pcbmmBNjdCxC3kaJjGINY2/1DDRdm81Ia2LDHFBtqIdcv4d0L8SHdMaoGIySRtqelGUT OP++bbqJgUnya5RxWLJdPTTbUi5aJ9BIZTtdonZ0/y8zlQA+9pQRtZ1oFWIZycMRlWfd /MtlWJYJxpXsPWMnQ1y2hNlZPGvhbyMePv6aTXj4Vs5yWtl7ha0+7clzfDD5fIPmNCWq MoHg== X-Forwarded-Encrypted: i=1; AJvYcCVjauvWYsw6g4iEi9aNv+ypqFzbPWhB4PbAEOzWX+7bg+YNnoDxkne1YfKBk2xLblh7DI58IlXAOIr7YeA=@vger.kernel.org X-Gm-Message-State: AOJu0YwRPt43cV6hMURIN7vge/NlEnFMER6Y/962G3JKnGyWYf3OmEYI PHiTtHw2ziKoaYCTbgZ93uU9cxndlRFJhmvjIzdCIAA4styJjK1dWDVQ X-Gm-Gg: ATEYQzxiJwbUOp5VbAAIuBFLmxDtDmIQHeXDlBGfIqsFatp4hscIlCpBLiQCjaMtnMo 8cQQZiLRaWaeC69L9bFz1t8kVjZukVC/U+sBjs5MkfMf0sjXp5aX/2vPhCAQW8US7Y/ftLQnqru iv0qNi5NFj2ol2gko7ISZKr6bTqREz3k4czj/WOOQb0e6EtJLDdHm5tSxUH/iisdGF04I1o2CC9 Shs1gcRZYMLyZ7DJXHOdqWLJ+uFt85FeYnmI2HqJOysYfGCWa1sjZ6DLycJM0MVGVVdjTsLU9Ql zd1kuc6TUfbrVRsS1aWD7T9x95JCDNvsP8bjYjre9aHpOwKC/2PkI8xeu6gIY3A0Ra2gx4uQGv8 Ipq4FnjJDIm79Oq3Uws+pbnzcgDQK478X57oUBcSCqMFxKj//fI+XrGuaATgbrFFl0THT0PllUQ se5n6KF9Q1De7idk8RX1WcB50bNOWAJG3skaU23FB7dJf7AxVnh7KXJcw7qKE= X-Received: by 2002:a17:902:d48d:b0:2ae:7f85:33d1 with SMTP id d9443c01a7336-2ae8286dc43mr72245585ad.0.1772953812451; Sat, 07 Mar 2026 23:10:12 -0800 (PST) Received: from localhost.localdomain ([2409:8929:1733:8137:18a2:98d0:7c4b:4d56]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2ae83e97924sm73472115ad.27.2026.03.07.23.10.08 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Sat, 07 Mar 2026 23:10:12 -0800 (PST) From: Chuang Wang To: Cc: Chuang Wang , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Stanislav Fomichev , Kuniyuki Iwashima , Samiullah Khawaja , Hangbin Liu , netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next] net: reduce RFS/ARFS flow updates by checking LLC affinity Date: Sun, 8 Mar 2026 15:09:16 +0800 Message-ID: <20260308070925.58939-1-nashuiliang@gmail.com> X-Mailer: git-send-email 2.50.1 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The current implementation of rps_record_sock_flow() updates the flow table every time a socket is processed on a different CPU. In high-load scenarios, especially with Accelerated RFS (ARFS), this triggers frequent flow steering updates via ndo_rx_flow_steer. For drivers like mlx5 that implement hardware flow steering, these constant updates lead to significant contention on internal driver locks (e.g., arfs_lock). This contention often becomes a performance bottleneck that outweighs the steering benefits. This patch introduces a cache-aware update strategy: the flow record is only updated if the flow migrates across Last Level Cache (LLC) boundaries. This minimizes expensive hardware reconfigurations while preserving cache locality for the application. Signed-off-by: Chuang Wang --- include/net/rps.h | 17 +-------------- net/core/dev.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 16 deletions(-) diff --git a/include/net/rps.h b/include/net/rps.h index e33c6a2fa8bb..2cd8698a79d5 100644 --- a/include/net/rps.h +++ b/include/net/rps.h @@ -55,22 +55,7 @@ struct rps_sock_flow_table { =20 #define RPS_NO_CPU 0xffff =20 -static inline void rps_record_sock_flow(rps_tag_ptr tag_ptr, u32 hash) -{ - unsigned int index =3D hash & rps_tag_to_mask(tag_ptr); - u32 val =3D hash & ~net_hotdata.rps_cpu_mask; - struct rps_sock_flow_table *table; - - /* We only give a hint, preemption can change CPU under us */ - val |=3D raw_smp_processor_id(); - - table =3D rps_tag_to_table(tag_ptr); - /* The following WRITE_ONCE() is paired with the READ_ONCE() - * here, and another one in get_rps_cpu(). - */ - if (READ_ONCE(table[index].ent) !=3D val) - WRITE_ONCE(table[index].ent, val); -} +void rps_record_sock_flow(rps_tag_ptr tag_ptr, u32 hash); =20 static inline void _sock_rps_record_flow_hash(__u32 hash) { diff --git a/net/core/dev.c b/net/core/dev.c index 203dc36aaed5..770cfb6fe06b 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -5175,6 +5175,60 @@ static int get_rps_cpu(struct net_device *dev, struc= t sk_buff *skb, return cpu; } =20 +/** + * rps_record_cond - Determine if RPS flow table should be updated + * @old_val: Previous flow record value + * @new_val: Target flow record value + * + * Returns true if the record needs an update. + */ +static inline bool rps_record_cond(u32 old_val, u32 new_val) +{ + u32 old_cpu =3D old_val & ~net_hotdata.rps_cpu_mask; + u32 new_cpu =3D new_val & ~net_hotdata.rps_cpu_mask; + + if (old_val =3D=3D new_val) + return false; + + /* Force update if the recorded CPU is invalid or has gone offline */ + if (old_cpu >=3D nr_cpu_ids || !cpu_active(old_cpu)) + return true; + + /* + * Force an update if the current task is no longer permitted + * to run on the old_cpu. + */ + if (!cpumask_test_cpu(old_cpu, current->cpus_ptr)) + return true; + + /* + * If CPUs do not share a cache, allow the update to prevent + * expensive remote memory accesses and cache misses. + */ + if (!cpus_share_cache(old_cpu, new_cpu)) + return true; + + return false; +} + +void rps_record_sock_flow(rps_tag_ptr tag_ptr, u32 hash) +{ + unsigned int index =3D hash & rps_tag_to_mask(tag_ptr); + u32 val =3D hash & ~net_hotdata.rps_cpu_mask; + struct rps_sock_flow_table *table; + + /* We only give a hint, preemption can change CPU under us */ + val |=3D raw_smp_processor_id(); + + table =3D rps_tag_to_table(tag_ptr); + /* The following WRITE_ONCE() is paired with the READ_ONCE() + * here, and another one in get_rps_cpu(). + */ + if (rps_record_cond(READ_ONCE(table[index].ent), val)) + WRITE_ONCE(table[index].ent, val); +} +EXPORT_SYMBOL(rps_record_sock_flow); + #ifdef CONFIG_RFS_ACCEL =20 /** --=20 2.47.3