From nobody Fri Jul 24 20:51:03 2026 Received: from mail-wm1-f54.google.com (mail-wm1-f54.google.com [209.85.128.54]) (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 ABBBC3B47E0 for ; Fri, 24 Jul 2026 16:13:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784909585; cv=none; b=APngShn5vhbNoct4G5TCdy5Ol096Ftf5FIYFHP4+ijyc9piyr48VAjy5S1eGC/ADsX9QKTpdcY+Cj3JkxW8UeCS+HmY54T8/mnEtwznJOcvglvp4ORIXaxO9gGbYeuidSCk5wxV6Y8GkyXHH1TdmuitLPMG/0pbDl2ZSAm8T5To= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784909585; c=relaxed/simple; bh=LKbFUDhj3VWhwQaESnH2NVyncH+CR8IBlzH7bYjPfDQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=tIMu9PGC2Bxgw14AStIFSvUa+07g1Z7gmGfLl2uRo5QymlajNoYPa8ecFhEFW5DuX57v5TDy8iQtTsEUebZ4UUnx1hQSBY80OOe4RmdJPdslEpLDz5cBkoVlzPRi0eShXhc/OLYvZ/47XxJtGP0oEEIqgkabkMi1oRhS6AGT2Ew= 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=sgx2Y+bE; arc=none smtp.client-ip=209.85.128.54 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="sgx2Y+bE" Received: by mail-wm1-f54.google.com with SMTP id 5b1f17b1804b1-4954a2dba6cso639035e9.1 for ; Fri, 24 Jul 2026 09:12:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1784909577; x=1785514377; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=g5QCk+t6gnqXj6DEKChexCyjlhSd215AVJ6Z8sL7eXs=; b=sgx2Y+bETIngYbB+KU9LklzffUhbsct07z/XF3f/xANDZQCdTxDRC9BOFhIDdjqIHK OPj0SfWwW8jgQYIN9aS43y+OZMwmV/HjibOICRkzOxFXvV80ot46bdyLLy5/79L2DeeS Edxn4G2zKcTp88DNABmGweRJNo6CSGwP2n2curwbP9tjaiqj0+L+slzJn7l/S1RAHtzJ Jp1ZHhGMCiqr8R+mP08g0ymDyzN8b2YTiS8fWdbdrgbE/U7C8dm7u74SoKayJ0kFP3bo GWhMi/GM23JG1cAEjgtc+KK4Oz00ntFfFZHl2EDDNDEDfsstaidgz/KUPXOaZPQEQPK1 6XDQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1784909577; x=1785514377; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=g5QCk+t6gnqXj6DEKChexCyjlhSd215AVJ6Z8sL7eXs=; b=rTIPYAyqX63t4UASurOhCWza2bDOSWoQntFp7WIhVtz2iilkIpS1IlsHccIt5h886M sRnFCTDlP7E/tCfHW+troK/DR8TSSNR/JfdC/tAa9hGcDl5fFKrKOfGQohHApjlldqaF hC1HBH96IGacI5g22JooRjAgaaPYCzfvlqfZXbVOueI6XHkuUn8h45RqT+pujzKEmIOB PKjAm8z7wE67BwV7Ju9GHltQfZN3mJ21x+yf9ZZ5IYvIWY8ayBt7aRjSXHHvxqn6NqnV zxQP4fSo+YkaCbR92ZTLmktDpiEfzn1NBgl1IoGJHIUR5JObJfu/ZOKOlq8TeCiLSIrh dEVg== X-Forwarded-Encrypted: i=1; AHgh+Ro436PLubkIT/Sdh6xDrK4w70MMGg3qY99V75PZgk22XyQyn9eUjsIFHp0nEeDUkx9vEpAiH/c6605Hd+c=@vger.kernel.org X-Gm-Message-State: AOJu0YwgQHy80Znh7nK+WeBFOoEWm3BcmX1kHeiJdVsVc7ZGB15zdj9g 0Z/aAKKYKd2Md32EDrZ+AdrXfxruYasDOsVgf87W97IsGjHX5J931z5O X-Gm-Gg: AR+sD13wyl0orKviOHWf3x9wwKtN720Nmsi8CjZG+7mu31g1vvZpJ2eSae/B9u4Ow/O CCVViLDVHPiVsHJJ15zzzrkhKxb9GyoSXYebtSE8bd6ucrH+QBzyb8jpF5hg426lrvuKCWTuHxK Q778iyx1ATrUMKmifuZKSIk5lEGDxJta251wyKQGc474yGYWhtk098Ebf84X4Yru1ELHaaelJC/ H49IvBugRJZz3wn4mn/SqPxRPN/3r/5sI/TPmbpHOQqqP7w1LocG3wgLVCS8mQ85eeEQtOOsIyr BrcyYE7hHnq8fbDN3gYIP+bLGJmPJ5IjX+mHdRPHuPFK++LTdfnV4i2XgDWxxQN6v/Xo6ONk0wo A7dQHTFLFFicOZpGVRRfKodDBozKkpKJbOrD6Pv6FJFVYeP+qCE4Kosv6pPQ+1ehq5lWBK0jFK8 CFlXdoDoBjuhiaHRUDvfAJxw91lDQuxzUiMwsmer4yJqZwSM8x8Kp8RbxtdOnEX+34rFk2rl5gU KSY0D8ejmK53NRpjzMP2BQEHoa6UX+ZbqoezIw= X-Received: by 2002:a05:600c:190b:b0:495:4840:c6b with SMTP id 5b1f17b1804b1-4957a7e9131mr33384715e9.1.1784909576912; Fri, 24 Jul 2026 09:12:56 -0700 (PDT) Received: from L-022584.energy.envision.com (dynamic-077-181-161-038.77.181.pool.telefonica.de. [77.181.161.38]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4957f9928fdsm40969655e9.1.2026.07.24.09.12.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 24 Jul 2026 09:12:56 -0700 (PDT) From: Xin Xie To: netdev@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org Cc: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, andrew+netdev@lunn.ch, shuah@kernel.org, kees@kernel.org, petr.wozniak@gmail.com, qingfang.deng@linux.dev, fmaurer@redhat.com, luka.gejak@linux.dev, bigeasy@linutronix.de, xiaoliang.yang_1@nxp.com, skhawaja@google.com, Xin Xie , stable@vger.kernel.org Subject: [PATCH net v2 1/4] net: hsr: fix packet drops caused by GRO superpackets Date: Fri, 24 Jul 2026 18:12:50 +0200 Message-ID: <20260724161253.79-2-xiexinet@gmail.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260724161253.79-1-xiexinet@gmail.com> References: <20260724161253.79-1-xiexinet@gmail.com> 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" HSR/PRP append a 6-byte tag/RCT to every forwarded frame and process each frame individually (sequence numbering, duplicate discard). When a lower device aggregates received frames into a GRO super-packet -- in software, or in hardware on GRO_HW-capable NICs -- the HSR receive/forward path mishandles it: frames are dropped and, on memory-constrained devices, processing super-skbs in softirq context can also pressure atomic memory allocation. The HSR/PRP stack already disables LRO on enslaved devices for the same reason. Extend that treatment to GRO: add netif_disable_gro() and dev_disable_gro() mirroring netif_disable_lro()/dev_disable_lro(), and call dev_disable_gro() from hsr_portdev_setup() so enslavement to an HSR/PRP master automatically strips NETIF_F_GRO and NETIF_F_GRO_HW on the lower device (recursively on its own lowers, as with LRO). Fixes: f421436a591d ("net/hsr: Add support for the High-availability Seamle= ss Redundancy protocol (HSRv0)") Cc: stable@vger.kernel.org Signed-off-by: Xin Xie --- include/linux/netdevice.h | 2 ++ net/core/dev.c | 18 ++++++++++++++++++ net/core/dev_api.c | 16 ++++++++++++++++ net/hsr/hsr_slave.c | 1 + 4 files changed, 37 insertions(+) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 9981d637f8b..eba2c26a49b 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -3434,6 +3434,8 @@ void dev_close(struct net_device *dev); void netif_close_many(struct list_head *head, bool unlink); void netif_disable_lro(struct net_device *dev); void dev_disable_lro(struct net_device *dev); +void netif_disable_gro(struct net_device *dev); +void dev_disable_gro(struct net_device *dev); int dev_loopback_xmit(struct net *net, struct sock *sk, struct sk_buff *ne= wskb); u16 dev_pick_tx_zero(struct net_device *dev, struct sk_buff *skb, struct net_device *sb_dev); diff --git a/net/core/dev.c b/net/core/dev.c index 5933c5dab09..a6cf2adc862 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1840,6 +1840,24 @@ void netif_disable_lro(struct net_device *dev) } } =20 +void netif_disable_gro(struct net_device *dev) +{ + struct net_device *lower_dev; + struct list_head *iter; + + dev->wanted_features &=3D ~(NETIF_F_GRO | NETIF_F_GRO_HW); + netdev_update_features(dev); + + if (unlikely(dev->features & (NETIF_F_GRO | NETIF_F_GRO_HW))) + netdev_WARN(dev, "failed to disable GRO!\n"); + + netdev_for_each_lower_dev(dev, lower_dev, iter) { + netdev_lock_ops(lower_dev); + netif_disable_gro(lower_dev); + netdev_unlock_ops(lower_dev); + } +} + /** * dev_disable_gro_hw - disable HW Generic Receive Offload on a device * @dev: device diff --git a/net/core/dev_api.c b/net/core/dev_api.c index 437947dd08e..02fb2162951 100644 --- a/net/core/dev_api.c +++ b/net/core/dev_api.c @@ -269,6 +269,22 @@ void dev_disable_lro(struct net_device *dev) } EXPORT_SYMBOL(dev_disable_lro); =20 +/** + * dev_disable_gro() - disable Generic Receive Offload on a device + * @dev: device + * + * Disable Generic Receive Offload (GRO) on a net device. Must be + * called under RTNL. This is needed if received packets may be + * forwarded to another interface. + */ +void dev_disable_gro(struct net_device *dev) +{ + netdev_lock_ops(dev); + netif_disable_gro(dev); + netdev_unlock_ops(dev); +} +EXPORT_SYMBOL(dev_disable_gro); + /** * dev_set_promiscuity() - update promiscuity count on a device * @dev: device diff --git a/net/hsr/hsr_slave.c b/net/hsr/hsr_slave.c index d9af9e65f72..cefbbfbd5ef 100644 --- a/net/hsr/hsr_slave.c +++ b/net/hsr/hsr_slave.c @@ -170,6 +170,7 @@ static int hsr_portdev_setup(struct hsr_priv *hsr, stru= ct net_device *dev, if (res) goto fail_rx_handler; dev_disable_lro(dev); + dev_disable_gro(dev); =20 return 0; =20 --=20 2.43.0 From nobody Fri Jul 24 20:51:03 2026 Received: from mail-wm1-f47.google.com (mail-wm1-f47.google.com [209.85.128.47]) (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 13355175A95 for ; Fri, 24 Jul 2026 16:13:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784909608; cv=none; b=o2RNwl0ZLoGO3WAgutIss7E4NnlklzvgTAbYEJiBZFo43wyuifdl2tQ8f+O2hHEUHu3uKwcyv7lHOFUhh24koCiCMazdaTotshKL1x3tMNZchj/R3+OF4j3CbIHKmj1p1l9dN6uT4QkYWdS09xw5Imse6jlY7S/U61DOl3+68GE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784909608; c=relaxed/simple; bh=DrZn5Cm0c6AMnJiWXRIPou1SyGN6W4LA+hiWm/G6shI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=huvS0hvJtWMyy0Ej7i1Lj73pu/m/9+VwR2tfa88hANzkhVDLZd2D68tOJBHkZjANvxKDTTknz1TiutvDeDBOZ8MKNkNU95SEc10Jg7/P8vjkkKo5akk64tZDN0QIbEbEFJysL/bx12jC00pdnXp5uu9Q2b+rck17cOeIuqf/0i8= 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=s2pP9vRy; arc=none smtp.client-ip=209.85.128.47 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="s2pP9vRy" Received: by mail-wm1-f47.google.com with SMTP id 5b1f17b1804b1-494049206c6so882675e9.2 for ; Fri, 24 Jul 2026 09:13:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1784909579; x=1785514379; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=GQEhlL0dKHAvltrTCYueCiy8so7kE3jHnbdeiA1S1sw=; b=s2pP9vRyukVzKD7Q9AvYuYAwwRysqh9Kg3dZ3eywusHi8kQQqRg3+9rjh30MuWo1cr edcIoz9i0y9u+NAx/KzhfVCYhTYCplaNFFQDTWmlBb/ZHl9rOeT3LreSAF/hEJDzZiGn 1Soc+q+ycIvtSAantCLhYXgtizWMWUnVj0tD5zfX6O/ZgkfZy1c6qcpfo/YqaqC8qsLH KeY9TvRU+SXW2BzmdBcZLakjy3/InZhZ/bw6/TjOV3jojs8ZoO5LLQzjurWmoEF/UiG9 NHVTtTOsYVJp2vkkiQ+owoNoyDkaq7LOYdlJt0ApKti9wf3Ew1dlkxmlb6JI9xOHVAVt 10KA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1784909579; x=1785514379; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=GQEhlL0dKHAvltrTCYueCiy8so7kE3jHnbdeiA1S1sw=; b=JbyL0jbT9lgVBVbhi8VL7qMf50d5MsbXylBWF4I2sksZEofe9ln5QEm79QAtGHV1uj pU9+q1Apg1IecrugJzX2wdkHe+DUBNRJcTzJPUF9/uVCuiLUxYS9blib1DR8Q2z20aS+ QFVI9utaKziqPVbwkxOlE0oKVKfXqPT9G4xPEDY3jdRITTmB2R+HPYhrrBHyi6mT5tlP c6lej/PPS7BTRSYkIvfrx4WbRVrJPX3C1st+HX2ZfLnh8DM9c+UXXx4HqPkKGjPGWNbO wm6oREJPL2Y6sZrW4a48OORO3cfDewi3BcN7/7DlbrCtDMaxCyaWIlCNURk3a6qj3Sr5 Qxhg== X-Forwarded-Encrypted: i=1; AHgh+Rp8l8N6flhveDwD8pww02MBRdQMBjVbDJ5sfctCvVuB1SAWnacWblRHr3TltpkTr26Of0e5+PNNLssMUn0=@vger.kernel.org X-Gm-Message-State: AOJu0Yy6JiVm9wNgSr2KIRF27fk0pZddyfHy1Ggad4hSwWnyO9BFt8+k wjkTuAm2GahR2V3v2Eu63IhzbjJIIjfblxoTE6b5dPexw7CZORFNncAw X-Gm-Gg: AR+sD12TD7WTy4paVioqbCC5wGDJ0wCbTISPm8A/7jVw1Mxhak4Y85dL3Bs2FTGn5Rg vYr3dCDGa1HyERWJDu9SiCFmcPdcnYirephxu/U4FxmueVaxCzGLm807YwmKmr8Od0xW5jdv5UK vlQhbTelwkne4qrfQTZaw5cau/XDjjfd686Xw4sx+iXaULxXRbMSDRujX8yhSr+3FcAycJm8zgu ZTn0hGldpP7p2xtkr72hswlmnWM0U6n1fc6nX1snYdROrRMpz/KPmSpzRZhplSE4rm7I8JIGDhC RT8muWJs+FGxVw3HFknELP+4LCM05oF0bTWlVRd2uoFPRujUxaH5o2+9tr274fJnodIrnm7sdtC ZJqjpa2vqZy/Hq4SjXDorBzg/UnC8shbGCEsDM4t5hqgKTFJ1IV1KvX4GeuLy0su+PZpLLtwvgL dQZqlNzcRYDoIogh3n+cKj4e7O+3EcW+xbA46e9u1lARcgfwkzwW2eII/6IkyFokoDVikrtOFFR SVe9QVBN7BFK56GLieMVIGUzj9i6r3o2f0pDwM= X-Received: by 2002:a05:600c:3508:b0:492:1e4d:d44b with SMTP id 5b1f17b1804b1-4957ae14d36mr34322885e9.8.1784909578225; Fri, 24 Jul 2026 09:12:58 -0700 (PDT) Received: from L-022584.energy.envision.com (dynamic-077-181-161-038.77.181.pool.telefonica.de. [77.181.161.38]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4957f9928fdsm40969655e9.1.2026.07.24.09.12.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 24 Jul 2026 09:12:57 -0700 (PDT) From: Xin Xie To: netdev@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org Cc: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, andrew+netdev@lunn.ch, shuah@kernel.org, kees@kernel.org, petr.wozniak@gmail.com, qingfang.deng@linux.dev, fmaurer@redhat.com, luka.gejak@linux.dev, bigeasy@linutronix.de, xiaoliang.yang_1@nxp.com, skhawaja@google.com, Xin Xie , stable@vger.kernel.org Subject: [PATCH net v2 2/4] net: hsr: shrink seqnr_lock to sequence counter updates Date: Fri, 24 Jul 2026 18:12:51 +0200 Message-ID: <20260724161253.79-3-xiexinet@gmail.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260724161253.79-1-xiexinet@gmail.com> References: <20260724161253.79-1-xiexinet@gmail.com> 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" hsr->seqnr_lock is currently held across entire hsr_forward_skb() calls: master TX (hsr_dev_xmit()), interlink RX (hsr_handle_frame()), and both supervision frame builders hold it while frames are built, classified, duplicated and forwarded on every port. The only state that actually needs the lock is the sequence counters themselves (hsr->sequence_nr / hsr->sup_sequence_nr). Shrink the locking to the individual counter updates: handle_std_frame() now takes the lock around its sequence number allocation (replacing the lockdep assertion), the master TX and interlink RX paths drop their outer lock, and the supervision builders release the lock right after updating their counter instead of holding it across frame construction and forwarding. Sequence numbers remain unique and monotonically allocated per counter; concurrent inputs may now interleave allocations, which is fine as the output paths were already concurrent. This is a prerequisite for unfolding GSO super-packets at the forward entry: the expensive segmentation work should not extend the global sequence lock's critical section. The locking being narrowed here was introduced by commit 06afd2c31d33 ("hsr: Synchronize sending frames to have always incremented outgoing seq nr."), briefly removed by commit b3c9e65eb227 ("net: hsr: remove seqnr_lock") and reinstated for the interlink RX path after a syzbot lockdep report by commit 430d67bdcb04 ("net: hsr: Use the seqnr lock for frames received via interlink port."). All sequence counter updates remain protected; only the forwarding work moves out of the critical section. Cc: stable@vger.kernel.org Signed-off-by: Xin Xie --- net/hsr/hsr_device.c | 15 ++++----------- net/hsr/hsr_forward.c | 3 ++- net/hsr/hsr_slave.c | 11 +---------- 3 files changed, 7 insertions(+), 22 deletions(-) diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c index 5555b71ab19..3fd1762d891 100644 --- a/net/hsr/hsr_device.c +++ b/net/hsr/hsr_device.c @@ -232,9 +232,7 @@ static netdev_tx_t hsr_dev_xmit(struct sk_buff *skb, st= ruct net_device *dev) skb->dev =3D master->dev; skb_reset_mac_header(skb); skb_reset_mac_len(skb); - spin_lock_bh(&hsr->seqnr_lock); hsr_forward_skb(skb, master); - spin_unlock_bh(&hsr->seqnr_lock); } else { dev_core_stats_tx_dropped_inc(dev); dev_kfree_skb_any(skb); @@ -335,6 +333,7 @@ static void send_hsr_supervision_frame(struct hsr_port = *port, hsr_stag->sequence_nr =3D htons(hsr->sequence_nr); hsr->sequence_nr++; } + spin_unlock_bh(&hsr->seqnr_lock); =20 hsr_stag->tlv.HSR_TLV_type =3D type; /* HSRv0 has 6 unused bytes after the MAC */ @@ -356,14 +355,10 @@ static void send_hsr_supervision_frame(struct hsr_por= t *port, ether_addr_copy(hsr_sp->macaddress_A, hsr->macaddress_redbox); } =20 - if (skb_put_padto(skb, ETH_ZLEN)) { - spin_unlock_bh(&hsr->seqnr_lock); + if (skb_put_padto(skb, ETH_ZLEN)) return; - } =20 hsr_forward_skb(skb, port); - spin_unlock_bh(&hsr->seqnr_lock); - return; } =20 static void send_prp_supervision_frame(struct hsr_port *master, @@ -390,6 +385,7 @@ static void send_prp_supervision_frame(struct hsr_port = *master, spin_lock_bh(&hsr->seqnr_lock); hsr_stag->sequence_nr =3D htons(hsr->sup_sequence_nr); hsr->sup_sequence_nr++; + spin_unlock_bh(&hsr->seqnr_lock); hsr_stag->tlv.HSR_TLV_type =3D PRP_TLV_LIFE_CHECK_DD; hsr_stag->tlv.HSR_TLV_length =3D sizeof(struct hsr_sup_payload); =20 @@ -397,13 +393,10 @@ static void send_prp_supervision_frame(struct hsr_por= t *master, hsr_sp =3D skb_put(skb, sizeof(struct hsr_sup_payload)); ether_addr_copy(hsr_sp->macaddress_A, master->dev->dev_addr); =20 - if (skb_put_padto(skb, ETH_ZLEN)) { - spin_unlock_bh(&hsr->seqnr_lock); + if (skb_put_padto(skb, ETH_ZLEN)) return; - } =20 hsr_forward_skb(skb, master); - spin_unlock_bh(&hsr->seqnr_lock); } =20 /* Announce (supervision frame) timer function diff --git a/net/hsr/hsr_forward.c b/net/hsr/hsr_forward.c index 0774981a65c..8e4158a9b57 100644 --- a/net/hsr/hsr_forward.c +++ b/net/hsr/hsr_forward.c @@ -621,9 +621,10 @@ static void handle_std_frame(struct sk_buff *skb, if (port->type =3D=3D HSR_PT_MASTER || port->type =3D=3D HSR_PT_INTERLINK) { /* Sequence nr for the master/interlink node */ - lockdep_assert_held(&hsr->seqnr_lock); + spin_lock_bh(&hsr->seqnr_lock); frame->sequence_nr =3D hsr->sequence_nr; hsr->sequence_nr++; + spin_unlock_bh(&hsr->seqnr_lock); } } =20 diff --git a/net/hsr/hsr_slave.c b/net/hsr/hsr_slave.c index cefbbfbd5ef..c7fd021f03b 100644 --- a/net/hsr/hsr_slave.c +++ b/net/hsr/hsr_slave.c @@ -73,16 +73,7 @@ static rx_handler_result_t hsr_handle_frame(struct sk_bu= ff **pskb) } skb_reset_mac_len(skb); =20 - /* Only the frames received over the interlink port will assign a - * sequence number and require synchronisation vs other sender. - */ - if (port->type =3D=3D HSR_PT_INTERLINK) { - spin_lock_bh(&hsr->seqnr_lock); - hsr_forward_skb(skb, port); - spin_unlock_bh(&hsr->seqnr_lock); - } else { - hsr_forward_skb(skb, port); - } + hsr_forward_skb(skb, port); =20 finish_consume: return RX_HANDLER_CONSUMED; --=20 2.43.0 From nobody Fri Jul 24 20:51:03 2026 Received: from mail-wm1-f51.google.com (mail-wm1-f51.google.com [209.85.128.51]) (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 E04B6443E50 for ; Fri, 24 Jul 2026 16:13:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784909589; cv=none; b=VoQ7M57JGgvLqKYvc+OyoPiPBFYfi6AbVzA0lHNsNBeSFa9xcISk3SIvC3fgG8ZH7Zm6twBpcDsVxhCd65U/bKSE6SLvdLOlMdelTOkgH5m0EUYVSspi5N8W56i404Jo+sRjz4F7mE3FTm8NrHvEfFi9T/Fa2z4ljhiieDzSZGg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784909589; c=relaxed/simple; bh=dAukikgscD/sy37SrCR+NUuKcEPuwimIfzZixY9SKkQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=h7uF6XOYBN28QAwJzze7sycNqBtrpz9wVMo0jhMYR65+pavGEJGU/LM6wHCxYpApVdtZQY7aPojv+tcNkuX7D0iDGokfyBYirSG6YifSmUFJWQoRfgZzPTsldztxH3bJK/6/oUlzBAvw5guraafhFte07qz/+pGm3cYDcSJ8QHU= 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=WZAORtwr; arc=none smtp.client-ip=209.85.128.51 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="WZAORtwr" Received: by mail-wm1-f51.google.com with SMTP id 5b1f17b1804b1-4954b3c5cbeso818255e9.1 for ; Fri, 24 Jul 2026 09:13:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1784909580; x=1785514380; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=OFxEw60vauemVEtCp0jQT47c7pb4PO17HGhXnCKMNEc=; b=WZAORtwrJFEGaA4SoodBrdr7jysg8NqStvzsuuecPN1zcg0fH3xutiCWdax1+6ay03 pdDd6wXW5UmUCUEbrKkSZqRHedA0DI+r2eA1yLJlh8OLcgDAj5rosuP1jgEpAPpUiKfo RoXXD5aZSmdCmUpyvbmomksFvA/0/imqu7t9jNrQJw6PZ9Ka0TdfR6mp820eOwQ6om7C Ob5YvtqexJ+Axy0Hd0QzdXitQ6XJ85YubNrRg8yvPltJt9/UnEjZFA1iLwxh0UzsgfPJ g9nKrfIJMusiYCu9A4XaQlk5j9Hp20zQ9YrAHaiU9A2f0TgaOGsf5JSqlhu1nBIxhfUm Dvvg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1784909580; x=1785514380; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=OFxEw60vauemVEtCp0jQT47c7pb4PO17HGhXnCKMNEc=; b=cx0tIIzMfO2LnW0QcFRS5Kd9lR3H012KMN/Uc7DymP49fxkrbJuIZr4utmd6RNAz3U MPLNV1YotZ7FGlm2IY47wOzLf5PvnmHq5cU2fhamw+YDwfLYO6FBcBzM6MVngAHvgR+3 IOeq9rO7bzxhQJ/VbwNd9ynD4TBuyPucBn5JtnAS3k42Y0Y11hVgn7ExCXZb4ay1yzTY kv+D0Xo/L4tzBWZX3MTWrs6PZrNo4PAIqSayJz46LOplhLDpXizDYlRLQY660bPRRoGk TbK896KBqcuc02SDvknOAmRMCn3muVCAYvZJKSHFbjeQIdnY70CI2m8pu4BeRs9waPji YB7w== X-Forwarded-Encrypted: i=1; AHgh+RryDkowjcguYqNvOzSM8zSjjqpAfYhlAKAWkJjibFIUQe+Re/IirY1LMWZwLnYZWW3SGvb8Nr+Kqa/Jec4=@vger.kernel.org X-Gm-Message-State: AOJu0YxHqByt7bMUUqIO/vtoo/qnA9J6a6XfGwF0DYXKPCqeIYL6W4y/ JZAunLZkDsiiPa+gZM1ZGlw46aRp7BPfF4xBtDUFdTeEhjjprdzEeplH X-Gm-Gg: AR+sD10+ITLIhQC37q9JEBWa90JirmgZqlrMjwDStpF0qdZcycE8ERGgPnT2yjUPcMn lKzTqGgnJpFpUOLGVwsXqzzCbiLj6TkDZUuPOridKzP6X133nzCtcrhvZlneWAKvwbLFoL4RthD kRZhyhEvYbEzAN3F51rfxoy3houA2Y46uSx07pu1CNPLLKLX76eoqRDPoyVvC4Qy2RmSRy/BJei OKA0z6YtwDjNlt/qeo18KaXIc+imd4TJJ7tyaFz1b1AD1qL0BvEv6+iphpTsq95YiB7Fwg5Zoy3 y2jpczvG6S5y5ha1f990X6Mp4KOb679LAOj1njp4wy1MCBZ5Jp4RK6U0lq3k0/MR3exubqmVKEV 8IQKI4no9derd5ApLwwubDqLGgSc/0rzfNgSKHzUrT4rCh8xCQWZez/oXoZhGwOxZPreWIQH8lL 2vvaYOm1FoA0ws3LI/PGrC0KGuBW+CrRTFk9j+T6iz5wM7qNAaIKMV5FcxJIQdPyRvCbcs5sCWP cUYtdHUYx5/h1kKbOsjf1yCohV3Aq+FGd/FyRXQ2Un2i6dRww== X-Received: by 2002:a05:600c:4685:b0:493:f42e:1b3f with SMTP id 5b1f17b1804b1-4957ac0c193mr37717825e9.3.1784909579525; Fri, 24 Jul 2026 09:12:59 -0700 (PDT) Received: from L-022584.energy.envision.com (dynamic-077-181-161-038.77.181.pool.telefonica.de. [77.181.161.38]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4957f9928fdsm40969655e9.1.2026.07.24.09.12.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 24 Jul 2026 09:12:59 -0700 (PDT) From: Xin Xie To: netdev@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org Cc: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, andrew+netdev@lunn.ch, shuah@kernel.org, kees@kernel.org, petr.wozniak@gmail.com, qingfang.deng@linux.dev, fmaurer@redhat.com, luka.gejak@linux.dev, bigeasy@linutronix.de, xiaoliang.yang_1@nxp.com, skhawaja@google.com, Xin Xie , stable@vger.kernel.org Subject: [PATCH net v2 3/4] net: hsr: unfold GSO super-packets at the forward entry Date: Fri, 24 Jul 2026 18:12:52 +0200 Message-ID: <20260724161253.79-4-xiexinet@gmail.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260724161253.79-1-xiexinet@gmail.com> References: <20260724161253.79-1-xiexinet@gmail.com> 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" HSR/PRP forward frames one by one: each wire frame gets its own tag and sequence number, and duplicate discard is per frame. A GSO super-packet reaching hsr_forward_skb() breaks that per-frame semantics: it would be tagged and forwarded as a single frame. Unfold such super-packets at the forward entry with the top-level GSO dispatch: __skb_gso_segment() initializes SKB_GSO_CB() and performs the L2->L3->L4 protocol dispatch (calling the low-level skb_segment() helper directly is not allowed here -- it reads SKB_GSO_CB(skb) state that only __skb_gso_segment() sets up). features =3D 0 requests full software segmentation; tx_path is selected by ingress port (master =3D locally generated TX, interlink =3D RX) to get the right checksum semantics. Each segment then runs through the existing per-frame path, which is split out as hsr_forward_skb_one() so that no GSO skb can reach it. Segmentation is only offered for the ingress roles whose frames are known to be plain Ethernet: the master (locally generated) and the interlink (SAN side, untagged). A super-packet received from a LAN slave may carry per-frame HSR tags or PRP RCT trailers that software segmentation cannot recover, and an already-tagged HSR/PRP super-packet violates per-frame wire semantics; both are rejected by ingress-port policy. (ETH_P_PRP identifies supervision traffic only; a PRP data frame keeps its payload EtherType, so RCT carriage cannot be tested by protocol.) Also drop NETIF_F_GSO_MASK from the HSR master's hw_features so locally generated traffic is segmented before reaching the forward path whenever possible. Fixes: f421436a591d ("net/hsr: Add support for the High-availability Seamle= ss Redundancy protocol (HSRv0)") Cc: stable@vger.kernel.org Signed-off-by: Xin Xie --- net/hsr/hsr_device.c | 2 +- net/hsr/hsr_forward.c | 50 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c index 3fd1762d891..248cbb142e2 100644 --- a/net/hsr/hsr_device.c +++ b/net/hsr/hsr_device.c @@ -652,7 +652,7 @@ void hsr_dev_setup(struct net_device *dev) dev->needs_free_netdev =3D true; =20 dev->hw_features =3D NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | - NETIF_F_GSO_MASK | NETIF_F_HW_CSUM | + NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_FILTER; =20 diff --git a/net/hsr/hsr_forward.c b/net/hsr/hsr_forward.c index 8e4158a9b57..3fcdbac49c5 100644 --- a/net/hsr/hsr_forward.c +++ b/net/hsr/hsr_forward.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "hsr_main.h" #include "hsr_framereg.h" =20 @@ -732,7 +733,7 @@ static int fill_frame_info(struct hsr_frame_info *frame, } =20 /* Must be called holding rcu read lock (because of the port parameter) */ -void hsr_forward_skb(struct sk_buff *skb, struct hsr_port *port) +static void hsr_forward_skb_one(struct sk_buff *skb, struct hsr_port *port) { struct hsr_frame_info frame; =20 @@ -761,3 +762,50 @@ void hsr_forward_skb(struct sk_buff *skb, struct hsr_p= ort *port) port->dev->stats.tx_dropped++; kfree_skb(skb); } + +/* GSO fan-out funnel: unfold super-packets before per-frame processing so + * each wire frame gets its own HSR/PRP tag and sequence number. + */ +void hsr_forward_skb(struct sk_buff *skb, struct hsr_port *port) +{ + struct sk_buff *segs, *next; + + if (likely(!skb_is_gso(skb))) { + hsr_forward_skb_one(skb, port); + return; + } + + /* Unfold only plain-Ethernet GSO super-packets: locally generated + * on the master, or arriving untagged from the SAN side on the + * interlink. A super-packet from a LAN slave may carry per-frame + * HSR tags / PRP RCT trailers that software segmentation cannot + * recover; an already-tagged HSR/PRP super-packet violates + * per-frame wire semantics. Drop both. + */ + if (port->type !=3D HSR_PT_MASTER && port->type !=3D HSR_PT_INTERLINK) + goto drop_gso; + if (skb->protocol =3D=3D htons(ETH_P_HSR) || + skb->protocol =3D=3D htons(ETH_P_PRP)) + goto drop_gso; + + /* features =3D 0: request full software segmentation. tx_path is true + * only for locally generated traffic on the master; ingress from + * the interlink follows RX checksum semantics. + */ + segs =3D __skb_gso_segment(skb, 0, port->type =3D=3D HSR_PT_MASTER); + if (IS_ERR(segs) || unlikely(!segs)) + goto drop_gso; + + consume_skb(skb); + while (segs) { + next =3D segs->next; + segs->next =3D NULL; + hsr_forward_skb_one(segs, port); + segs =3D next; + } + return; + +drop_gso: + port->dev->stats.tx_dropped++; + kfree_skb(skb); +} --=20 2.43.0 From nobody Fri Jul 24 20:51:03 2026 Received: from mail-wm1-f51.google.com (mail-wm1-f51.google.com [209.85.128.51]) (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 A5A7F4457D8 for ; Fri, 24 Jul 2026 16:13:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784909594; cv=none; b=bceoAHGUyH1hXFcdx+/7cyrKWvkCl+cJUBdZCFysl9FRYJgRQOarZj3dwK+/mmyDUdK+iqD8WiOoGJQgff1Cif/MWmHEEq68m13HtIj2lM4MRsDpYHW5vf9ap1l2gmVckecMzGC/DhiavcYy81REuqzZs/RdKhhH1fV8OWRB0/w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784909594; c=relaxed/simple; bh=YhffjiTwHNnsDaIV0MpIXslfWw13P8PP5NtdMFnhPJQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=d1wpkdZwvmOOZ6hOZxF1Vrey2DFCAKHaeGmBAoyJo+pyM2fALk8tDnVfEnFksDyKcMKvlIwawnBVit8hgrbExaClmlqTLRTyYvU6MnWq69VI0VgjSuqeasZlU0Xzt/FpwsLvfsXlied2777on+RBwt6u3ttXmPwMWhiys5w0LQE= 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=h5ykbDd7; arc=none smtp.client-ip=209.85.128.51 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="h5ykbDd7" Received: by mail-wm1-f51.google.com with SMTP id 5b1f17b1804b1-494049206c6so882755e9.2 for ; Fri, 24 Jul 2026 09:13:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1784909581; x=1785514381; darn=vger.kernel.org; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:from:to:cc:subject :date:message-id:reply-to:content-type; bh=yqLAYmpkh+P1dlY0H6sXFdrX0pxDVL4N33QHbpBIrEk=; b=h5ykbDd70yNH17FxKEDzGFbT50Q1nytqv3TVH5hSnW/m/qW5PH7qZGm0lPhmh3aho1 /3w1xgWamCswuS16W4oZWNtkiVtpYvZSNUDiWM0w4+HZsyBrINi3eUTinKVMd9WVliEB 10ptenxzK9Kf9oJcli1EvSD/jjwSrTB0gbLU1LYJckWdPSmn1PMH2xQ81w1n1rrGHrL2 f3ymQFf9OWbos17naO/+sU725a3whGN/XFrDuy00jk35pmx/ARlaOk3SQ43SbmzuYuXY zTazqKeua4mIvJY3iOanbM+Xy1tiMa9YrjtIRJU/VD2dh5F8bGQzVyyPx7yHIVVyJmoq GSWA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1784909581; x=1785514381; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=yqLAYmpkh+P1dlY0H6sXFdrX0pxDVL4N33QHbpBIrEk=; b=Pfkj+o4bjvjng7KshQDewJoRyKHBYnWTQ3pIVKwGqk14EJ70R/J+fncXvSb1RT0gI8 VgYEOAqHue4N0K36NHgmy7NZc7a4aVjEwjPufYi9M1UBm97eW5EYObhBJu9wfUEAF4Bv rGTdnwVhJTM07YmKh4vYOPMD7rasvQzHTBvH/gkyJ9jQ94bBpAs0U9CIOzuQ9aLZYptr 5t39PBa/rPMYXEpvfzyiZkCEyth+LTLKSMOoaZpaIW+OMxrX67npX67ONJoNR0GwDuua beorUAkM3uDhTvXcra156FU2/OxJzPh/qH6Vubz+Xy9tvEGyfoO1g+DyQEKuyx1jqJzL va1Q== X-Forwarded-Encrypted: i=1; AHgh+Rq4UUyXEfFc3IEb49Zi0RRi9sOlUPhHSrG3/KF0aeWFM/m0p4lyhmWPn2oVuJMBo/xJP46GpItsfav55Mw=@vger.kernel.org X-Gm-Message-State: AOJu0Yxi3hGN3uBmvpVRcl/yxsrwKiCmAeF3gye2R3lFihw0IuR80Cg6 rGarCAUAwlw0brokNTuhqPDLW+wZiR0IH4IGtj6SbsMCc3QJD2X5NFLGAlSblQKI4dM= X-Gm-Gg: AR+sD13jMcDm9yRWLyn7m7DsSCDdsIyymhMnriJ3lHInImdiMwtWW9EJtGy/LtDVM/N 9EYQ4Zg8/RZvVg0xDDAa6n2zJY3D/uuCkJjtSjta+g2EMM98JRQcWY3ME4HuKpXtPhkKYQ+95fC lgiHhiEcYK+aCNaanvEgVwjHsbhZiMiZ9ycbNHc+gBll/UArgrrXmJDQTz/xJyH6B+0h7Jd8Vzo lo/AY6EDs3NTJIz9HHUS+ii+A2g4lqZZsMXxmMU1frJ538ufjoNuwrnWmoWNsZljk3mFfb6zRSR kwkrCrXQ6Ctjt4bxtOWfDsghKRMN+90sAAlTekMLmZGv2pNHt/wdslwSxZr18LlxKmjfOdUG0nA sn05m6m7+Yw2Lc4er1MSJZyCYZk4otb+DAeUUcQoB1aV/Thw4/bEvuLp2zxL77iXDXM2jpa9xYy zuS8xx3FlutVulPAnmzgoJP2C++EsjJzk0+9QoKRiB5jxk7ujo/vOqgpJsQ2/xLdjTxhqp0sEpN ensewowLjVqTBeGcgiiK0R8l6IOBjsxlx8rWk4= X-Received: by 2002:a05:600c:2e56:b0:495:6274:56bd with SMTP id 5b1f17b1804b1-4957ac0ed8amr19094855e9.4.1784909580824; Fri, 24 Jul 2026 09:13:00 -0700 (PDT) Received: from L-022584.energy.envision.com (dynamic-077-181-161-038.77.181.pool.telefonica.de. [77.181.161.38]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4957f9928fdsm40969655e9.1.2026.07.24.09.12.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 24 Jul 2026 09:13:00 -0700 (PDT) From: Xin Xie To: netdev@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org Cc: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, andrew+netdev@lunn.ch, shuah@kernel.org, kees@kernel.org, petr.wozniak@gmail.com, qingfang.deng@linux.dev, fmaurer@redhat.com, luka.gejak@linux.dev, bigeasy@linutronix.de, xiaoliang.yang_1@nxp.com, skhawaja@google.com, Xin Xie Subject: [PATCH net v2 4/4] selftests: net: hsr: add GRO super-packet forwarding test Date: Fri, 24 Jul 2026 18:12:53 +0200 Message-ID: <20260724161253.79-5-xiexinet@gmail.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260724161253.79-1-xiexinet@gmail.com> References: <20260724161253.79-1-xiexinet@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Add a test exercising the HSR forward path with GSO super-packets: a TSO-enabled SAN behind the interlink streams TCP through an HSR DUT to a peer node. The test verifies that: * enslaved devices have GRO and HW-GRO disabled automatically, * the HSR master does not advertise GSO/TSO features (including tx-tcp6/udp/gso-list, to catch future hw_features leaks), * super-packets really leave the SAN (TX average frame size above a fixed threshold) while bulk output on the DUT's LAN legs stays at per-frame size =E2=80=94 aggregate counter evidence that GSO enters the forward path and is unfolded at the forward entry. Zero TCP retransmits is reported as a secondary health signal. The one-shot iperf3 server lives in a private mktemp -d workdir (mode 0700): its exact PID is retained only after numeric, alive, comm=3D=3Diperf3 and netns-membership checks, its real exit status is propagated through an rc file, and cleanup kills by exact PID with a bounded wrapper reap plus a namespace-scoped iperf3 sweep. Server startup failure, client failure and a never-published PID are all bounded exits with no process or directory leaks. Environments whose iproute2 lacks the HSR interlink syntax are skipped with ksft_skip. Without this series the feature checks fail, and on drivers that hand GRO super-packets to the HSR receive path the stream degrades or stalls. Signed-off-by: Xin Xie --- tools/testing/selftests/net/hsr/Makefile | 1 + .../selftests/net/hsr/hsr_gro_superpacket.sh | 437 ++++++++++++++++++ 2 files changed, 438 insertions(+) create mode 100755 tools/testing/selftests/net/hsr/hsr_gro_superpacket.sh diff --git a/tools/testing/selftests/net/hsr/Makefile b/tools/testing/selft= ests/net/hsr/Makefile index 31fb9326cf5..0d105476e7c 100644 --- a/tools/testing/selftests/net/hsr/Makefile +++ b/tools/testing/selftests/net/hsr/Makefile @@ -3,6 +3,7 @@ top_srcdir =3D ../../../../.. =20 TEST_PROGS :=3D \ + hsr_gro_superpacket.sh \ hsr_ping.sh \ hsr_redbox.sh \ link_faults.sh \ diff --git a/tools/testing/selftests/net/hsr/hsr_gro_superpacket.sh b/tools= /testing/selftests/net/hsr/hsr_gro_superpacket.sh new file mode 100755 index 00000000000..4ca2a7f395e --- /dev/null +++ b/tools/testing/selftests/net/hsr/hsr_gro_superpacket.sh @@ -0,0 +1,437 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# +# Test HSR handling of GRO/GSO super-packets: +# +# 1. Enslaving a device to an HSR master disables GRO on it +# (dev_disable_gro()). +# 2. The HSR master does not advertise GSO/TSO features. +# 3. A TCP stream from a TSO-enabled SAN (which therefore emits GSO +# super-packets) is unfolded at the HSR forward entry. Evidence: +# interface-counter deltas show super-packet-sized frames leaving +# the SAN and per-frame-sized traffic leaving the DUT's LAN ports. +# +# Topology (100.64.0.0/24): +# +# ns_san ns_dut ns_peer +# +-----------+ interlink +---------------+ LAN A/B +-----------+ +# | s0 [0.1] |-------------| d_il hsr0 |-----------| hsr1 [0.3]| +# +-----------+ | d_a / d_b | | p_a / p_b | +# +---------------+ +-----------+ +# +# SAN traffic reaches ns_peer only through hsr0's forward path +# (interlink RX -> LAN A/B TX), so every SAN frame is tagged and +# forwarded by the DUT. + +source ./hsr_common.sh + +ns_dut=3D"hsr-gro-dut" +ns_san=3D"hsr-gro-san" +ns_peer=3D"hsr-gro-peer" +san_ip=3D"100.64.0.1" +peer_ip=3D"100.64.0.3" + +# Aggregate counter thresholds for the stream test (bytes/packets): +# SAN_AVG_MIN proves GSO super-packets left the SAN; LAN_AVG_MAX is a +# guard with margin, not the protocol maximum (see do_tso_stream_test). +SAN_AVG_MIN=3D2048 +LAN_AVG_MAX=3D1514 + +iperf_pid=3D"" +server_wrapper=3D"" +workdir=3D"" +pidfile=3D"" +rcfile=3D"" + +cleanup() +{ + # exact-PID kill only after RE-validating identity (guards against + # PID reuse between publication and cleanup) + if [ -n "${iperf_pid}" ] && valid_server_pid "${iperf_pid}"; then + kill "${iperf_pid}" 2>/dev/null + fi + iperf_pid=3D"" + if [ -n "${server_wrapper}" ]; then + # the wrapper waits on the server; reap it with a 5s bound so a + # live-but-unpublished server can never hang cleanup + for _ in $(seq 1 50); do + kill -0 "${server_wrapper}" 2>/dev/null || break + sleep 0.1 + done + kill "${server_wrapper}" 2>/dev/null + wait "${server_wrapper}" 2>/dev/null + server_wrapper=3D"" + fi + # last resort, namespace-scoped only: TERM the iperf3 processes that + # actually live in the peer netns, poll for bounded exit, then + # SIGKILL any survivor before touching the namespace name. A blind + # pkill would scan the host PID space and hit unrelated tests. + local _p _still + for _p in $(ip netns pids "$ns_peer" 2>/dev/null); do + if [ "$(cat /proc/"$_p"/comm 2>/dev/null)" =3D "iperf3" ]; then + kill "$_p" 2>/dev/null + fi + done + for _ in $(seq 1 50); do + _still=3D0 + for _p in $(ip netns pids "$ns_peer" 2>/dev/null); do + if [ "$(cat /proc/"$_p"/comm 2>/dev/null)" =3D "iperf3" ]; then + _still=3D1 + break + fi + done + [ "$_still" -eq 0 ] && break + sleep 0.1 + done + for _p in $(ip netns pids "$ns_peer" 2>/dev/null); do + if [ "$(cat /proc/"$_p"/comm 2>/dev/null)" =3D "iperf3" ]; then + kill -9 "$_p" 2>/dev/null + fi + done + # remove only the known non-empty private directory + if [ -n "${workdir}" ] && [ -d "${workdir}" ]; then + rm -rf "${workdir}" + fi + workdir=3D"" + pidfile=3D"" + rcfile=3D"" + ip netns del "$ns_dut" 2>/dev/null + ip netns del "$ns_san" 2>/dev/null + ip netns del "$ns_peer" 2>/dev/null +} + +trap cleanup EXIT + +check_tool() +{ + if ! command -v "$1" > /dev/null 2>&1; then + echo "SKIP: Could not run test without $1" + exit $ksft_skip + fi +} + +nsx() +{ + ip netns exec "$1" bash -c "$2" +} + +setup_topo() +{ + local ns + + cleanup + for ns in "$ns_dut" "$ns_san" "$ns_peer"; do + ip netns add "$ns" + done + + ip link add d_a netns "$ns_dut" type veth peer name p_a netns "$ns_peer" + ip link add d_b netns "$ns_dut" type veth peer name p_b netns "$ns_peer" + ip link add d_il netns "$ns_dut" type veth peer name s0 netns "$ns_san" + + # HSR tags add 6 bytes per frame; give the LAN legs headroom. + for iface in d_a d_b; do + nsx "$ns_dut" "ip link set $iface mtu 1600; ip link set $iface up" + done + for iface in p_a p_b; do + nsx "$ns_peer" "ip link set $iface mtu 1600; ip link set $iface up" + done + + nsx "$ns_dut" "ip link set d_il up" + nsx "$ns_san" "ip link set s0 up; ip addr add $san_ip/24 dev s0" + + nsx "$ns_dut" "ip link add hsr0 type hsr \ + slave1 d_a slave2 d_b interlink d_il proto 0; \ + ip link set hsr0 up" + nsx "$ns_peer" "ip link add hsr1 type hsr \ + slave1 p_a slave2 p_b proto 0; \ + ip link set hsr1 up; ip addr add $peer_ip/24 dev hsr1" + + # Let the nodes see each other's supervision frames. + sleep 2 +} + +check_feature() +{ + local ns=3D"$1" + local iface=3D"$2" + local feature=3D"$3" + local want=3D"$4" + + if nsx "$ns" "ethtool -k $iface" | grep -q "^$feature: $want"; then + echo "INFO: $ns/$iface $feature is $want [ OK ]" + else + echo "FAIL: $ns/$iface $feature is not $want" 1>&2 + ret=3D1 + fi +} + +# Off-or-absent variant: fails only when the feature is present AND on, +# so devices that simply do not list the feature do not fail it. +check_feature_not_on() +{ + local ns=3D"$1" + local iface=3D"$2" + local feature=3D"$3" + + if nsx "$ns" "ethtool -k $iface" | grep -q "^$feature: on"; then + echo "FAIL: $ns/$iface $feature is on" 1>&2 + ret=3D1 + else + echo "INFO: $ns/$iface $feature not on [ OK ]" + fi +} + +do_gro_feature_checks() +{ + echo "INFO: Checking that enslavement disabled GRO." + check_feature "$ns_dut" d_a generic-receive-offload off + check_feature "$ns_dut" d_b generic-receive-offload off + check_feature "$ns_dut" d_il generic-receive-offload off + stop_if_error "GRO not disabled on enslaved devices." + + echo "INFO: Checking that enslavement disabled HW-GRO." + check_feature "$ns_dut" d_a rx-gro-hw off + check_feature "$ns_dut" d_b rx-gro-hw off + check_feature "$ns_dut" d_il rx-gro-hw off + stop_if_error "HW-GRO not disabled on enslaved devices." + + echo "INFO: Checking that the HSR master does not advertise GSO/TSO." + check_feature "$ns_dut" hsr0 generic-segmentation-offload off + check_feature "$ns_dut" hsr0 tcp-segmentation-offload off + check_feature_not_on "$ns_dut" hsr0 tx-tcp6-segmentation + check_feature_not_on "$ns_dut" hsr0 tx-udp-segmentation + check_feature_not_on "$ns_dut" hsr0 tx-gso-list + stop_if_error "HSR master still advertises GSO-family features." +} + +alloc_workdir() +{ + # Allocated only here, long after the initial topology cleanup, so + # cleanup() at setup_topo() time can never remove it. mktemp failure + # is a hard test failure. + workdir=3D$(mktemp -d /tmp/hsr_gro_test.XXXXXX) || { + echo "FAIL: mktemp -d failed" 1>&2 + exit 1 + } + chmod 700 "${workdir}" + pidfile=3D"${workdir}/iperf.pid" + rcfile=3D"${workdir}/iperf.rc" +} + +# Numeric, alive, comm =3D=3D iperf3, and really owned by the peer netns. +valid_server_pid() +{ + local p=3D"$1" + + [[ "$p" =3D~ ^[0-9]+$ ]] || return 1 + kill -0 "$p" 2>/dev/null || return 1 + [ "$(cat /proc/"$p"/comm 2>/dev/null)" =3D "iperf3" ] || return 1 + ip netns pids "$ns_peer" 2>/dev/null | grep -qx "$p" +} + +start_iperf_server() +{ + local candidate_pid + + # One-shot server, no -D: the wrapper records its exact PID and its + # real exit status (netns shares the PID namespace and the host fs). + alloc_workdir + ( nsx "$ns_peer" "iperf3 -s -1 > /dev/null 2>&1 & \ + echo \$! > ${pidfile}; \ + wait \$!; \ + echo \$? > ${rcfile}" ) & + server_wrapper=3D$! + # the wrapper writes the pidfile asynchronously; wait for it to + # appear instead of racing the read + for _ in $(seq 1 50); do + [ -s "${pidfile}" ] && break + sleep 0.1 + done + if [ ! -s "${pidfile}" ]; then + echo "FAIL: iperf3 server did not publish a pid (no pidfile)" 1>&2 + ret=3D1 + return 1 + fi + candidate_pid=3D$(<"${pidfile}") + if ! valid_server_pid "${candidate_pid}"; then + echo "FAIL: iperf3 server pid '${candidate_pid}' failed validation" 1>&2 + ret=3D1 + return 1 + fi + # publish only after full validation + iperf_pid=3D"${candidate_pid}" + sleep 1 + return 0 +} + +# Print " " for exactly one TX record of ns/dev; anything +# else (missing, duplicated, non-numeric) is a hard FAIL. +read_tx_counters() +{ + local ns=3D"$1" dev=3D"$2" + local out cnt + + out=3D$(nsx "$ns" "ip -s link show $dev" | \ + awk '/^ +TX:/{getline; print $1, $2}') + cnt=3D$(echo "$out" | grep -c '^[0-9]* [0-9]*$') + if [ "$cnt" -ne 1 ]; then + echo "FAIL: cannot parse TX counters of $ns/$dev (records=3D$cnt)" 1>&2 + ret=3D1 + return 1 + fi + echo "$out" + return 0 +} + +eval_counter_delta() +{ + local name=3D"$1" b0=3D"$2" p0=3D"$3" b1=3D"$4" p1=3D"$5" op=3D"$6" limit= =3D"$7" + local bd pd + + if ! [[ "$b0" =3D~ ^[0-9]+$ && "$b1" =3D~ ^[0-9]+$ && \ + "$p0" =3D~ ^[0-9]+$ && "$p1" =3D~ ^[0-9]+$ ]]; then + echo "FAIL: non-numeric counter input for $name" 1>&2 + ret=3D1 + return 1 + fi + bd=3D$((b1 - b0)) + pd=3D$((p1 - p0)) + if [ "$bd" -lt 0 ] || [ "$pd" -le 0 ]; then + echo "FAIL: counter delta invalid for $name (bytes=3D$bd pkts=3D$pd)" 1>= &2 + ret=3D1 + return 1 + fi + if [ "$op" =3D "gt" ]; then + if [ "$bd" -le $((pd * limit)) ]; then + echo "FAIL: $name bytes/packets $bd/$pd <=3D $limit" 1>&2 + ret=3D1 + return 1 + fi + else + if [ "$bd" -gt $((pd * limit)) ]; then + echo "FAIL: $name bytes/packets $bd/$pd > $limit" 1>&2 + ret=3D1 + return 1 + fi + fi + echo "INFO: $name counter delta bytes=3D$bd packets=3D$pd" \ + "(op $op limit $limit) [ OK ]" + return 0 +} + +do_tso_stream_test() +{ + local out sender_retr server_rc + local san_b0 san_p0 san_b1 san_p1 + local a_b0 a_p0 a_b1 a_p1 b_b0 b_p0 b_b1 b_p1 + + echo "INFO: Enabling TSO/GSO on the SAN interface." + nsx "$ns_san" "ethtool -K s0 tso on gso on" + check_feature "$ns_san" s0 tcp-segmentation-offload on + stop_if_error "Could not enable TSO on the SAN interface." + + echo "INFO: Running 10s TCP stream SAN -> peer through the HSR DUT." + start_iperf_server || return + + # Counter snapshots around the stream window. The SAN-side average + # must exceed SAN_AVG_MIN (aggregate proof that GSO super-packets + # really left the SAN); each DUT LAN leg must stay under LAN_AVG_MAX + # (aggregate proof that bulk output was segmented per-frame). These + # are aggregate discriminators, not a per-frame maximum proof. + san_b0=3D0; san_p0=3D0; a_b0=3D0; a_p0=3D0; b_b0=3D0; b_p0=3D0 + read -r san_b0 san_p0 <&1); then + echo "FAIL: iperf3 client failed:" 1>&2 + echo "$out" 1>&2 + ret=3D1 + return + fi + + read -r san_b1 san_p1 <&2 + ret=3D1 + return + fi + server_rc=3D$(cat "${rcfile}") + if ! [[ "$server_rc" =3D~ ^[0-9]+$ ]] || [ "$server_rc" -ne 0 ]; then + echo "FAIL: iperf3 server exited with rc=3D'${server_rc}'" 1>&2 + ret=3D1 + return + fi + iperf_pid=3D"" + + # secondary health signal only: anchored, single-match, numeric =E2=80=94 + # any parse anomaly is a loud FAIL, but the value itself no longer + # gates (the counter inequalities above are the primary evidence). + sender_retr=3D$(echo "$out" | awk '/sec .* sender$/ {print $(NF-1)}') + if [ "$(echo "$sender_retr" | grep -Ec '^[0-9]+$')" -ne 1 ]; then + echo "FAIL: cannot parse sender retransmits reliably" 1>&2 + echo "$out" 1>&2 + ret=3D1 + return + fi + echo "INFO: TCP stream done;" \ + "sender retransmits=3D$sender_retr (secondary signal)" + echo "$out" | grep -E "sender|receiver" +} + +check_prerequisites +check_tool ethtool +check_tool iperf3 +check_tool timeout + +# iproute2 must know the HSR interlink syntax. +if ! ip link help hsr 2>&1 | grep -qi interlink; then + echo "SKIP: iproute2 has no HSR interlink support" + exit $ksft_skip +fi + +setup_topo + +echo "INFO: Initial validation ping (SAN -> peer through the DUT)." +do_ping "$ns_san" "$peer_ip" +stop_if_error "Initial validation failed." + +do_gro_feature_checks +do_tso_stream_test +stop_if_error "GSO super-packet stream test failed." + +echo "INFO: All good." +exit $ret --=20 2.43.0