From nobody Sun Jun 14 01:35:34 2026 Received: from mail-qk1-f175.google.com (mail-qk1-f175.google.com [209.85.222.175]) (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 CB7EC288C0E for ; Tue, 5 May 2026 00:27:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.175 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777940882; cv=none; b=L+Mu8Y2lRG+YuDaQzY53cHYWkGRPvax6hG35maNYD6rBkJb+5B19K3XXgiSuYlGCjGdvnirTkAvmF4OToEYly/fpZLNvPzh810Q8V0n09eLCkBDBGucWXyLL1FF74CvbvA5P8vatu+wtoLj2jRxKie3Bf9aXtHBZuSS/that8W0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777940882; c=relaxed/simple; bh=Kkf0AyrAiAu8KXaMTqsQTVqF0XMvHUSH4oj+GyiNFY4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=B95jPo5YeD4flOxytORPEufuM6XdQzGYpRtPTuAiTFIEo4n2tx5HWXjCgKcwOxbk4rdkIlptrE4tUZXzEAlIUvcUh2yn9ac3y2pHpn7+ut6lBDEpyIZQyFXT7/tia8BbeQ1a+B669GyE0sR3Vr6ayS8aAHaqAMs78HLYftIWeUY= 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=N6G+M6Lm; arc=none smtp.client-ip=209.85.222.175 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="N6G+M6Lm" Received: by mail-qk1-f175.google.com with SMTP id af79cd13be357-8f15e900586so227958885a.1 for ; Mon, 04 May 2026 17:27:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777940879; x=1778545679; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=MWJwbEllN4ZJKVX+XZselB2Kwac+OZX7uznK7jh7ztA=; b=N6G+M6Lmzy8wx3P4xSH/bnBmuYrJqA3jDRgXnZFZC7PcmAi8uzGo6fgodVCFrzqEbs HDuxOvt+nAtvRegeqPwB6fRwzeAvAt0YONiTI+UrvYG44dPlQDfPknCxtxhun4oaKe5l Tbh73f2oU6u98lZp+Dydzs8hQ8eKMKOtciZi8jP5YKwGXsIau6s6nWXKZoy8kHlUqVl6 E2AD+sB2bqOVv1ghPJHLZEaoglYL9wkPKRj2y0fTT3Zr/0TMp1lr2keRWYtk0zuCVsU5 Pekp/IlLtlyel0gs/6sgNcTVC7nwgzVb1tZs9eRVBmMirFN17a0kCaqy8XL8G3LagQmN 2i8A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777940879; x=1778545679; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=MWJwbEllN4ZJKVX+XZselB2Kwac+OZX7uznK7jh7ztA=; b=f583NQ7lPqGgCaBNauvw4HqnVU0aln3x3xiNTDgusVvtGpYVhJMJQlotK/7Di9uqj3 keCOKYUow94u1DRo0vgOJaPCPPIViZT+/oTtUoBaPuux+8tR3zYCkwR3UXa1EF7jr20R zhZM0qEUn6anEAHvjtj9SyCKw3GCgldnFz0JWa4r/Eqa287DsUNUvwp2JNCxJMSrTgtW 8U6B8ewyaprTrkYSumUafobOZ/g1HX1q5/ZBZxv/4W1+mFyyBGw+7JY4heTeCwAWPgA1 tglGjhtTzfHKekcDwMRATYq6l83d2LKxzf8pTJc6oLGdg0Up5wqmF3GzxoX5PGul7lLn DtGg== X-Forwarded-Encrypted: i=1; AFNElJ9sBeXsHHo8uCYX9q+QJlucQ5UI6ulQNVVwv65b6ygpeHBK15/tJxLjUP2SsXHisrw1QY/2CKarZEZmuMk=@vger.kernel.org X-Gm-Message-State: AOJu0YynkiDYsggw6N2b+ZbXBGvCEXXai6J4VVaa9SdrbNDso2Aa1QH2 SJAqXrLUKwH9GBLFMjIJSgZQQy9TFXaSX23ddjycKoMTQ0BIPfPrEaQG X-Gm-Gg: AeBDietksrAOQTGjeBn4SE0/0XP/LmHpxe4h4nCeLw7D+fhd4yeKxwVJcG9rW/3Vvbz vCZSgUfIFdHGI+LyXlwtoFNHrX8YVnye61tPoZtHYD9GEme8U2Y8XgWG6zG5M3bg288pWyKjcJs qLjvvjN0TvPnCZFltllCOVDKsKEGGAPQI3alJ9fw95OMZSJEI41FyRkf5onlLYM0WrcXrcL3PVX ZFW+Q8U/6m3QKsbUnjiGBm+y1xUuWzTxe8HVoFi047KTTm1YFjJpx4RSGdkMBqk4vq2cloBb6ue od32aVrosfzFeCS1kHIv+ONHaDpHBFYsyGGNmFyJmahpZQgodasjh0hCxJxg7JkZPx4vWYapTFx PFOr4xTNu5BsarCfGEWg8qhRpCA0aYXZgS70ejfdxwXDXKEBogp3M3Mot3nbY+Y/an5OUvZRvXn +1Nj2wF7JHYwXqzP7JrLG5TTOtO7y591LG X-Received: by 2002:a05:620a:3188:b0:8d8:ba4a:596c with SMTP id af79cd13be357-8fd1864a0famr1905610985a.51.1777940878605; Mon, 04 May 2026 17:27:58 -0700 (PDT) Received: from localhost ([2a03:2880:f804:1f::]) by smtp.gmail.com with ESMTPSA id af79cd13be357-8fc293816e8sm1158075985a.8.2026.05.04.17.27.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 04 May 2026 17:27:58 -0700 (PDT) From: Bobby Eshleman Date: Mon, 04 May 2026 17:27:48 -0700 Subject: [PATCH net-next v2 1/6] net: add netmem_tx modes that indicate dma capability 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 Message-Id: <20260504-tcp-dm-netkit-v2-1-56d52ac72fd4@meta.com> References: <20260504-tcp-dm-netkit-v2-0-56d52ac72fd4@meta.com> In-Reply-To: <20260504-tcp-dm-netkit-v2-0-56d52ac72fd4@meta.com> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Jonathan Corbet , Shuah Khan , Alex Shi , Yanteng Si , Dongliang Mu , Michael Chan , Pavan Chebbi , Joshua Washington , Harshitha Ramamurthy , Saeed Mahameed , Tariq Toukan , Mark Bloch , Leon Romanovsky , Alexander Duyck , kernel-team@meta.com, Daniel Borkmann , Nikolay Aleksandrov , Shuah Khan Cc: netdev@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-rdma@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org, Stanislav Fomichev , Mina Almasry , Bobby Eshleman X-Mailer: b4 0.14.3 From: Bobby Eshleman Devices that support netmem TX previously set dev->netmem_tx =3D true. This was checked in validate_xmit_unreadable_skb() to drop unreadable skbs (skbs with dmabuf-backed frags) before they reach drivers that would mishandle them or devices that would not have the iommu mappings for them. Some virtual devices like netkit (or ifb) never DMA and never touch frag contents, as they essentially just forward the skb to another device. They are unable to forward unreadable skbs, however, because they fail to pass TX validation checks on dev->netmem_tx. This single bit flag doesn't give the TX validator enough information to differentiate devices that will attempt DMA on the unreadable skb and those that will simply route it untouched. This patch fixes this issue by adding an additional bit to netmem_tx, so that drivers can indicate 1) if they have netmem support, and 2) if they do, are they DMA-capable or not? Replace the boolean with a 2-bit enum: NETMEM_TX_NONE - no netmem TX support (drop unreadable skbs) NETMEM_TX_DMA - full support, device does DMA NETMEM_TX_NO_DMA - pass-through, device never DMAs Update drivers to reflect these definitions. NIC drivers use NETMEM_TX_DMA, and netkit uses NETMEM_TX_NO_DMA. Signed-off-by: Bobby Eshleman Acked-by: Harshitha Ramamurthy --- Changes in v2: - Squash driver conversion patches (2-5) into patch 1 (Jakub) --- Documentation/networking/net_cachelines/net_device.rst | 2 +- Documentation/networking/netmem.rst | 8 +++++++- Documentation/translations/zh_CN/networking/netmem.rst | 7 ++++++- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 2 +- drivers/net/ethernet/google/gve/gve_main.c | 2 +- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 2 +- drivers/net/ethernet/meta/fbnic/fbnic_netdev.c | 2 +- drivers/net/netkit.c | 1 + include/linux/netdevice.h | 11 +++++++++-- 9 files changed, 28 insertions(+), 9 deletions(-) diff --git a/Documentation/networking/net_cachelines/net_device.rst b/Docum= entation/networking/net_cachelines/net_device.rst index 1c19bb7705df..c85784259544 100644 --- a/Documentation/networking/net_cachelines/net_device.rst +++ b/Documentation/networking/net_cachelines/net_device.rst @@ -10,7 +10,7 @@ Type Name = fastpath_tx_acce =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D unsigned_long:32 priv_flags read_mostl= y __dev_queue_xmit(tx) unsigned_long:1 lltx read_mostl= y HARD_TX_LOCK,HARD_TX_TRYLOCK,HARD_TX_UNLOCK(t= x) -unsigned long:1 netmem_tx:1; read_mostly +unsigned long:2 netmem_tx:2; read_mostly char name[16] struct netdev_name_node* name_node struct dev_ifalias* ifalias diff --git a/Documentation/networking/netmem.rst b/Documentation/networking= /netmem.rst index b63aded46337..217869d1108d 100644 --- a/Documentation/networking/netmem.rst +++ b/Documentation/networking/netmem.rst @@ -95,4 +95,10 @@ Driver TX Requirements netdev@, or reach out to the maintainers and/or almasrymina@google.com = for help adding the netmem API. =20 -2. Driver should declare support by setting `netdev->netmem_tx =3D true` +2. Driver should declare support by setting `netdev->netmem_tx` to the + appropriate mode: + + - `NETMEM_TX_DMA`: for physical devices that perform DMA. + + - `NETMEM_TX_NO_DMA`: for virtual or passthrough devices that do + not DMA, but still support handling of netmem-backed skbs. diff --git a/Documentation/translations/zh_CN/networking/netmem.rst b/Docum= entation/translations/zh_CN/networking/netmem.rst index fe351a240f02..320f3eacf51b 100644 --- a/Documentation/translations/zh_CN/networking/netmem.rst +++ b/Documentation/translations/zh_CN/networking/netmem.rst @@ -89,4 +89,9 @@ dma-mapping API =E5=8E=BB=E5=A4=84=E7=90=86=E3=80=82 =E4=BD=BF=E7=94=A8=E6=9F=90=E4=B8=AA=E8=BF=98=E4=B8=8D=E5=AD=98=E5=9C=A8= =E7=9A=84 netmem API=EF=BC=8C=E4=BD=A0=E5=8F=AF=E4=BB=A5=E8=87=AA=E8=A1=8C= =E6=B7=BB=E5=8A=A0=E5=B9=B6=E6=8F=90=E4=BA=A4=E5=88=B0 netdev@=EF=BC=8C=E4= =B9=9F=E5=8F=AF=E4=BB=A5=E8=81=94=E7=B3=BB=E7=BB=B4=E6=8A=A4 =E4=BA=BA=E5=91=98=E6=88=96=E8=80=85=E5=8F=91=E9=80=81=E9=82=AE=E4=BB=B6= =E8=87=B3 almasrymina@google.com =E5=AF=BB=E6=B1=82=E5=B8=AE=E5=8A=A9=E3=80= =82 =20 -2. =E9=A9=B1=E5=8A=A8=E7=A8=8B=E5=BA=8F=E5=BA=94=E9=80=9A=E8=BF=87=E8=AE= =BE=E7=BD=AE netdev->netmem_tx =3D true =E6=9D=A5=E8=A1=A8=E6=98=8E=E8=87= =AA=E8=BA=AB=E6=94=AF=E6=8C=81 netmem =E5=8A=9F=E8=83=BD=E3=80=82 +2. =E9=A9=B1=E5=8A=A8=E7=A8=8B=E5=BA=8F=E5=BA=94=E5=B0=86 `netdev->netmem_= tx` =E8=AE=BE=E7=BD=AE=E4=B8=BA=E9=80=82=E5=BD=93=E7=9A=84=E6=A8=A1=E5=BC= =8F=EF=BC=9A + + - `NETMEM_TX_DMA`=EF=BC=9A=E9=80=82=E7=94=A8=E4=BA=8E=E6=89=A7=E8=A1=8C= DMA =E7=9A=84=E7=89=A9=E7=90=86=E8=AE=BE=E5=A4=87=E3=80=82 + + - `NETMEM_TX_NO_DMA`=EF=BC=9A=E9=80=82=E7=94=A8=E4=BA=8E=E4=B8=8D=E6=89= =A7=E8=A1=8C DMA =E7=9A=84=E8=99=9A=E6=8B=9F=E6=88=96=E9=80=8F=E4=BC=A0=E8= =AE=BE=E5=A4=87=EF=BC=8C=E4=BD=86=E4=BB=8D=E6=94=AF=E6=8C=81 + =E5=A4=84=E7=90=86 netmem =E6=94=AF=E6=8C=81=E7=9A=84 skb=E3=80=82 diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethern= et/broadcom/bnxt/bnxt.c index 8c55874f44ca..ed9c22dc4a5a 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -17120,7 +17120,7 @@ static int bnxt_init_one(struct pci_dev *pdev, cons= t struct pci_device_id *ent) dev->queue_mgmt_ops =3D &bnxt_queue_mgmt_ops_unsupp; if (BNXT_SUPPORTS_QUEUE_API(bp)) dev->queue_mgmt_ops =3D &bnxt_queue_mgmt_ops; - dev->netmem_tx =3D true; + dev->netmem_tx =3D NETMEM_TX_DMA; =20 rc =3D register_netdev(dev); if (rc) diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ether= net/google/gve/gve_main.c index 424d973c97f2..dd2b8f087163 100644 --- a/drivers/net/ethernet/google/gve/gve_main.c +++ b/drivers/net/ethernet/google/gve/gve_main.c @@ -2894,7 +2894,7 @@ static int gve_probe(struct pci_dev *pdev, const stru= ct pci_device_id *ent) goto abort_with_wq; =20 if (!gve_is_gqi(priv) && !gve_is_qpl(priv)) - dev->netmem_tx =3D true; + dev->netmem_tx =3D NETMEM_TX_DMA; =20 err =3D register_netdev(dev); if (err) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/ne= t/ethernet/mellanox/mlx5/core/en_main.c index 5a46870c4b74..fc49aae38807 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -5924,7 +5924,7 @@ static void mlx5e_build_nic_netdev(struct net_device = *netdev) =20 netdev->priv_flags |=3D IFF_UNICAST_FLT; =20 - netdev->netmem_tx =3D true; + netdev->netmem_tx =3D NETMEM_TX_DMA; =20 netif_set_tso_max_size(netdev, GSO_MAX_SIZE); mlx5e_set_xdp_feature(priv); diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c b/drivers/net/e= thernet/meta/fbnic/fbnic_netdev.c index c406a3b56b37..138e522ef9b9 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c @@ -752,7 +752,7 @@ struct net_device *fbnic_netdev_alloc(struct fbnic_dev = *fbd) netdev->netdev_ops =3D &fbnic_netdev_ops; netdev->stat_ops =3D &fbnic_stat_ops; netdev->queue_mgmt_ops =3D &fbnic_queue_mgmt_ops; - netdev->netmem_tx =3D true; + netdev->netmem_tx =3D NETMEM_TX_DMA; =20 fbnic_set_ethtool_ops(netdev); =20 diff --git a/drivers/net/netkit.c b/drivers/net/netkit.c index 5e2eecc3165d..0ad6a806d7d5 100644 --- a/drivers/net/netkit.c +++ b/drivers/net/netkit.c @@ -466,6 +466,7 @@ static void netkit_setup(struct net_device *dev) dev->priv_flags |=3D IFF_NO_QUEUE; dev->priv_flags |=3D IFF_DISABLE_NETPOLL; dev->lltx =3D true; + dev->netmem_tx =3D NETMEM_TX_NO_DMA; =20 dev->netdev_ops =3D &netkit_netdev_ops; dev->ethtool_ops =3D &netkit_ethtool_ops; diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 0e1e581efc5a..11d68e75eb4f 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1788,6 +1788,12 @@ enum netdev_stat_type { NETDEV_PCPU_STAT_DSTATS, /* struct pcpu_dstats */ }; =20 +enum netmem_tx_mode { + NETMEM_TX_NONE, /* no netmem TX support */ + NETMEM_TX_DMA, /* DMA-capable netmem TX (real HW) */ + NETMEM_TX_NO_DMA, /* no DMA, e.g. passthrough for virtual devs */ +}; + enum netdev_reg_state { NETREG_UNINITIALIZED =3D 0, NETREG_REGISTERED, /* completed register_netdevice */ @@ -1809,7 +1815,8 @@ enum netdev_reg_state { * @lltx: device supports lockless Tx. Deprecated for real HW * drivers. Mainly used by logical interfaces, such as * bonding and tunnels - * @netmem_tx: device support netmem_tx. + * @netmem_tx: device netmem TX mode (NETMEM_TX_NONE, NETMEM_TX_DMA, + * or NETMEM_TX_NO_DMA). * * @name: This is the first field of the "visible" part of this structure * (i.e. as seen by users in the "Space.c" file). It is the name @@ -2132,7 +2139,7 @@ struct net_device { struct_group(priv_flags_fast, unsigned long priv_flags:32; unsigned long lltx:1; - unsigned long netmem_tx:1; + unsigned long netmem_tx:2; ); const struct net_device_ops *netdev_ops; const struct header_ops *header_ops; --=20 2.52.0 From nobody Sun Jun 14 01:35:34 2026 Received: from mail-qk1-f177.google.com (mail-qk1-f177.google.com [209.85.222.177]) (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 9ADA2282F33 for ; Tue, 5 May 2026 00:28:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.177 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777940884; cv=none; b=eroSX7/1sJnwwKLZ522jfifgqYElC0yaWvRTyHQaEBMZnbCkhykYAwtIEfHIfWDCvbo4l0Ib74nUfHlom2XmrWFM/N/NnKZf3HcoGpeWhmoUpw21HB2ektCV1Q4YCP9RVQ1M4vegrorpM7D3jJyFw0pcA7kR0Jdw5Iikn1WjztE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777940884; c=relaxed/simple; bh=wYDT0PJRMb31ZP24JWbTT5WalVrfTU+LMPYR3Vi4pjE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=PgwLQPF+a604XgDj7/NEeOop8buKhmVMcHrSTT+dO0UFgxv9jVNgunNiR6qgrEcwKHS7dHp6r5O5mKDzA81dOa3A2y18gUuWlz6Lf6pjToJJIbzvrO7aJO7vIVvsVhuMOcJEnDmrkR/+aV74dL2xa6Ed+XL1G/a+NrkEJ0vhK2g= 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=QSEHvFsH; arc=none smtp.client-ip=209.85.222.177 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="QSEHvFsH" Received: by mail-qk1-f177.google.com with SMTP id af79cd13be357-8cb40149037so462980685a.2 for ; Mon, 04 May 2026 17:28:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777940881; x=1778545681; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=m9ipZOgYycgUpmB4or1YqF/hBfNlU6IbZyyWfKcKJlQ=; b=QSEHvFsH4fGK4QO2chcgiHWNVyXkDjnoVbH0rZBsHm4qbkUODXDIlL5ZupAhl0dfPt VVNwNHSTsej/UokzDsJKI668k0eJ3YsxpeI70FWDWCWp/K6ZBD5TP+shEKGgmYHDUQNi wAi+qaMPf7IvEBk5yXzvPaxNj0+IZes0q9XG7upcYaJkkTqVaTZM0kXUlRqh41Etx03k qW84+QqI6psspkL7YKhKQ7QFVcWHvZozYsFujO7Fx0aiEzuK7HVQZ4NuSIAa9ImW/wo4 411AxWVt5sPmm+aNab0qQRUldEzLBJrEPSkcoyt1xZ3rCjd2/5TZzaUqGdrOixLVOQbi qArA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777940881; x=1778545681; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=m9ipZOgYycgUpmB4or1YqF/hBfNlU6IbZyyWfKcKJlQ=; b=GQu/OsvS0gBIqszviuK2h4YBqIVrVRLKkZwPVRW5Bt4QssZixPx5HPbDl0Fk5KsUWt paM6hN+z0G0j+PLmhFTkHeMNwWSs/+dhIbfbvndJBHhWQKMhYYhahTvTW0KX5MSe0MVk KYGgCqmLm1/dOlEL7Y1j66+2DV8ebeUWk58TIPf7pVk1yKEPs1eM3gqSRk2/Yp+JDIN9 Ixvf5353Dlh0VcZCEgIaJwudikNN1+ZCuJXx8gTxykFBUhe7tMXC+nWoJU1tQL/+dwNG XClf+IqGiR+p4jD4UFHQXGspjqdJ5RZB4jEtQMkT1HLVY6/0JO0Z7sEs+QXX09GaZ34K Cl4A== X-Forwarded-Encrypted: i=1; AFNElJ9FC4fz24xAW5hx2zCAsSarDBXypSncNzvr3pvM3DslLnrp+G2GYnfWqEShlnpT70ttXQ3MRpgKbuGrEf8=@vger.kernel.org X-Gm-Message-State: AOJu0YzSouxzVvBJou/Y8vtzRG/jzvjPD4tTGu+SgBoYngHJqCDnqwtQ UF0HI4WXbqw3FkwQ8M6FKFtsRpGAcW2Uz8I0bpx0UnN9MGuLXE1UjPrq X-Gm-Gg: AeBDievlX9e+eBtwQxjgp43JaiDFLL5iftZBinLoCWVf/TYKDCf2+B30SD51TGieyA/ 9BPOr0sjXi0fSZHMAvA/VQ5VxBTJuw64wy97YWMRLVln6DMb6a0vJ0w9CLqHC6b1yfG55aKk++H PvL3xarxuYHrd1o5SJ8PCi5Ib+JbBeWbFLxtAKF1nN+Q1AsJrp3iJxapK4X3p8PTwqIkODjKd3n YA6DyF3UWwTzQeCalw2K4h3A8U5VbYJ6Ynety5G9TMUmBODyqK6jWq3iJDfquwo531OsW9mEstE YTjqk86g4gyv1zPG34mzkeiIDJ23fH9JcqEP7+ITLe0wZdsL68EKDbhV4xDFo/A0hZSf/fN37DT FJblB8OvENiud/uQpV/Q6lg/rfHTEmHsQ72s0VPHLdUuaiGOnrJ3bKsy3p8iRi3T/ZwI/ghrhqX Ki0HWDkiRrCfeYijPSL7Yy+YYlRzIh+PoI X-Received: by 2002:a05:620a:4694:b0:8ec:c4a7:f8e5 with SMTP id af79cd13be357-8fd17b547c6mr1945417685a.31.1777940880547; Mon, 04 May 2026 17:28:00 -0700 (PDT) Received: from localhost ([2a03:2880:f800:13::]) by smtp.gmail.com with ESMTPSA id af79cd13be357-8fc2c91b976sm1219584885a.39.2026.05.04.17.28.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 04 May 2026 17:28:00 -0700 (PDT) From: Bobby Eshleman Date: Mon, 04 May 2026 17:27:49 -0700 Subject: [PATCH net-next v2 2/6] net: devmem: support TX over NETMEM_TX_NO_DMA devices 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 Message-Id: <20260504-tcp-dm-netkit-v2-2-56d52ac72fd4@meta.com> References: <20260504-tcp-dm-netkit-v2-0-56d52ac72fd4@meta.com> In-Reply-To: <20260504-tcp-dm-netkit-v2-0-56d52ac72fd4@meta.com> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Jonathan Corbet , Shuah Khan , Alex Shi , Yanteng Si , Dongliang Mu , Michael Chan , Pavan Chebbi , Joshua Washington , Harshitha Ramamurthy , Saeed Mahameed , Tariq Toukan , Mark Bloch , Leon Romanovsky , Alexander Duyck , kernel-team@meta.com, Daniel Borkmann , Nikolay Aleksandrov , Shuah Khan Cc: netdev@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-rdma@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org, Stanislav Fomichev , Mina Almasry , Bobby Eshleman X-Mailer: b4 0.14.3 From: Bobby Eshleman When a netkit virtual device leases queues from a physical NIC, devmem TX bindings created on the netkit device must still result in the dmabuf being mapped for dma by the physical device. This patch accomplishes this by teaching the bind handler to search for the underlying DMA-capable device by looking it up via leased rx queues. The function netdev_find_netmem_tx_dev(), used for finding the underlying DMA-capable device, can be extended to support other non-netkit NETMEM_TX_NO_DMA devices in the future if needed. Additionally, this patch extends validate_xmit_unreadable_skb() to support the netkit case, where the skb is validated twice: once on the netkit guest device and again on the physical NIC after BPF redirect or ip forwarding. Signed-off-by: Bobby Eshleman --- Changes in v2: - In validate_xmit_unreadable_skb() to check netmem_tx mode before inspecting frags (Jakub) - Lock bind_dev around netdev_queue_get_dma_dev() when bind_dev !=3D netdev to fix lockdep (Sashiko) --- net/core/dev.c | 21 ++++++++++++------- net/core/devmem.c | 6 ++++-- net/core/devmem.h | 9 ++++++-- net/core/netdev-genl.c | 57 +++++++++++++++++++++++++++++++++++++++++++++-= ---- 4 files changed, 77 insertions(+), 16 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index 06c195906231..74eb4eb170cd 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3990,23 +3990,30 @@ static struct sk_buff *sk_validate_xmit_skb(struct = sk_buff *skb, static struct sk_buff *validate_xmit_unreadable_skb(struct sk_buff *skb, struct net_device *dev) { + struct net_devmem_dmabuf_binding *binding; struct skb_shared_info *shinfo; struct net_iov *niov; =20 if (likely(skb_frags_readable(skb))) goto out; =20 - if (!dev->netmem_tx) + if (dev->netmem_tx =3D=3D NETMEM_TX_NONE) goto out_free; =20 + if (dev->netmem_tx =3D=3D NETMEM_TX_NO_DMA) + goto out; + shinfo =3D skb_shinfo(skb); + if (shinfo->nr_frags =3D=3D 0) + goto out; =20 - if (shinfo->nr_frags > 0) { - niov =3D netmem_to_net_iov(skb_frag_netmem(&shinfo->frags[0])); - if (net_is_devmem_iov(niov) && - READ_ONCE(net_devmem_iov_binding(niov)->dev) !=3D dev) - goto out_free; - } + niov =3D netmem_to_net_iov(skb_frag_netmem(&shinfo->frags[0])); + if (!net_is_devmem_iov(niov)) + goto out_free; + + binding =3D net_devmem_iov_binding(niov); + if (READ_ONCE(binding->dev) !=3D dev) + goto out_free; =20 out: return skb; diff --git a/net/core/devmem.c b/net/core/devmem.c index cde4c89bc146..644c286b778f 100644 --- a/net/core/devmem.c +++ b/net/core/devmem.c @@ -181,7 +181,7 @@ int net_devmem_bind_dmabuf_to_queue(struct net_device *= dev, u32 rxq_idx, } =20 struct net_devmem_dmabuf_binding * -net_devmem_bind_dmabuf(struct net_device *dev, +net_devmem_bind_dmabuf(struct net_device *dev, struct net_device *vdev, struct device *dma_dev, enum dma_data_direction direction, unsigned int dmabuf_fd, struct netdev_nl_sock *priv, @@ -212,6 +212,7 @@ net_devmem_bind_dmabuf(struct net_device *dev, } =20 binding->dev =3D dev; + binding->vdev =3D vdev; xa_init_flags(&binding->bound_rxqs, XA_FLAGS_ALLOC); =20 err =3D percpu_ref_init(&binding->ref, @@ -397,7 +398,8 @@ struct net_devmem_dmabuf_binding *net_devmem_get_bindin= g(struct sock *sk, */ dst_dev =3D dst_dev_rcu(dst); if (unlikely(!dst_dev) || - unlikely(dst_dev !=3D READ_ONCE(binding->dev))) { + unlikely(dst_dev !=3D READ_ONCE(binding->dev) && + dst_dev !=3D READ_ONCE(binding->vdev))) { err =3D -ENODEV; goto out_unlock; } diff --git a/net/core/devmem.h b/net/core/devmem.h index 1c5c18581fcb..f399632b3c4b 100644 --- a/net/core/devmem.h +++ b/net/core/devmem.h @@ -19,7 +19,12 @@ struct net_devmem_dmabuf_binding { struct dma_buf *dmabuf; struct dma_buf_attachment *attachment; struct sg_table *sgt; + /* Physical NIC that does the actual DMA for this binding. */ struct net_device *dev; + /* Virtual device (e.g. netkit) the user called bind-tx on. Must be + * NETMEM_TX_NO_DMA. + */ + struct net_device *vdev; struct gen_pool *chunk_pool; /* Protect dev */ struct mutex lock; @@ -84,7 +89,7 @@ struct dmabuf_genpool_chunk_owner { =20 void __net_devmem_dmabuf_binding_free(struct work_struct *wq); struct net_devmem_dmabuf_binding * -net_devmem_bind_dmabuf(struct net_device *dev, +net_devmem_bind_dmabuf(struct net_device *dev, struct net_device *vdev, struct device *dma_dev, enum dma_data_direction direction, unsigned int dmabuf_fd, struct netdev_nl_sock *priv, @@ -165,7 +170,7 @@ static inline void net_devmem_put_net_iov(struct net_io= v *niov) } =20 static inline struct net_devmem_dmabuf_binding * -net_devmem_bind_dmabuf(struct net_device *dev, +net_devmem_bind_dmabuf(struct net_device *dev, struct net_device *vdev, struct device *dma_dev, enum dma_data_direction direction, unsigned int dmabuf_fd, diff --git a/net/core/netdev-genl.c b/net/core/netdev-genl.c index b8f6076d8007..0e296c3bb677 100644 --- a/net/core/netdev-genl.c +++ b/net/core/netdev-genl.c @@ -1077,7 +1077,7 @@ int netdev_nl_bind_rx_doit(struct sk_buff *skb, struc= t genl_info *info) goto err_rxq_bitmap; } =20 - binding =3D net_devmem_bind_dmabuf(netdev, dma_dev, DMA_FROM_DEVICE, + binding =3D net_devmem_bind_dmabuf(netdev, NULL, dma_dev, DMA_FROM_DEVICE, dmabuf_fd, priv, info->extack); if (IS_ERR(binding)) { err =3D PTR_ERR(binding); @@ -1119,9 +1119,42 @@ int netdev_nl_bind_rx_doit(struct sk_buff *skb, stru= ct genl_info *info) return err; } =20 +/* Find the DMA-capable device for netmem TX binding. + * For NETMEM_TX_DMA devices, returns the device itself. + * For NETMEM_TX_NO_DMA devices (e.g. netkit), walks leased queues + * to find the underlying physical device. + * Returns NULL if no suitable device is found. + */ +static struct net_device *netdev_find_netmem_tx_dev(struct net_device *dev) +{ + struct netdev_rx_queue *lease_rxq; + struct net_device *phys_dev; + int i; + + if (dev->netmem_tx =3D=3D NETMEM_TX_DMA) + return dev; + + if (dev->netmem_tx !=3D NETMEM_TX_NO_DMA) + return NULL; + + for (i =3D 0; i < dev->real_num_rx_queues; i++) { + lease_rxq =3D READ_ONCE(__netif_get_rx_queue(dev, i)->lease); + if (!lease_rxq) + continue; + + phys_dev =3D lease_rxq->dev; + if (netif_device_present(phys_dev) && + phys_dev->netmem_tx =3D=3D NETMEM_TX_DMA) + return phys_dev; + } + + return NULL; +} + int netdev_nl_bind_tx_doit(struct sk_buff *skb, struct genl_info *info) { struct net_devmem_dmabuf_binding *binding; + struct net_device *bind_dev; struct netdev_nl_sock *priv; struct net_device *netdev; struct device *dma_dev; @@ -1164,16 +1197,30 @@ int netdev_nl_bind_tx_doit(struct sk_buff *skb, str= uct genl_info *info) goto err_unlock_netdev; } =20 - if (!netdev->netmem_tx) { + if (netdev->netmem_tx =3D=3D NETMEM_TX_NONE) { err =3D -EOPNOTSUPP; NL_SET_ERR_MSG(info->extack, "Driver does not support netmem TX"); goto err_unlock_netdev; } =20 - dma_dev =3D netdev_queue_get_dma_dev(netdev, 0, NETDEV_QUEUE_TYPE_TX); - binding =3D net_devmem_bind_dmabuf(netdev, dma_dev, DMA_TO_DEVICE, - dmabuf_fd, priv, info->extack); + bind_dev =3D netdev_find_netmem_tx_dev(netdev); + if (!bind_dev) { + err =3D -EOPNOTSUPP; + NL_SET_ERR_MSG(info->extack, + "No DMA-capable device found for netmem TX"); + goto err_unlock_netdev; + } + + if (bind_dev !=3D netdev) + netdev_lock(bind_dev); + dma_dev =3D netdev_queue_get_dma_dev(bind_dev, 0, NETDEV_QUEUE_TYPE_TX); + if (bind_dev !=3D netdev) + netdev_unlock(bind_dev); + binding =3D net_devmem_bind_dmabuf(bind_dev, + bind_dev !=3D netdev ? netdev : NULL, + dma_dev, DMA_TO_DEVICE, dmabuf_fd, + priv, info->extack); if (IS_ERR(binding)) { err =3D PTR_ERR(binding); goto err_unlock_netdev; --=20 2.52.0 From nobody Sun Jun 14 01:35:34 2026 Received: from mail-qt1-f173.google.com (mail-qt1-f173.google.com [209.85.160.173]) (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 7E7552DCC05 for ; Tue, 5 May 2026 00:28:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777940885; cv=none; b=lKrZz596J4dpZgIQ4cuuLDfxCvT7DdPZMX0rL7C8UQJJ8QKWpVt0drFyvHXx2CO+tPoN6Ff7FfzTnLvExapnGWXZPeQ8Pvu/zKYpdlvOuMRijGXbWbW0WFdTswXaFEopd/G5UcsK+0syqJmEmysIUkmNpGKXcq9iwLjrkAd5vvY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777940885; c=relaxed/simple; bh=PfZ9xMHw6YVTqz7Mn9CLexmMOq9qX3qQOU0tAn/sFjU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=kU5gVPqjgqq/UGK8J3ZL5jadPYEyDq681AWOswuTiokrBL9IYDaQkAd52bUoGKAydKJl6k4P1G07DtYqJcIF6m/GOcCG+aucY79YA7fObhHHLwfNnHk2jDzrpZCNykZLw7896/RLoOi+gpGHnaXoL+NM7bVH37h3hz77UVKwAfQ= 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=FfnTRsEC; arc=none smtp.client-ip=209.85.160.173 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="FfnTRsEC" Received: by mail-qt1-f173.google.com with SMTP id d75a77b69052e-50fb1ad3734so51010471cf.1 for ; Mon, 04 May 2026 17:28:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777940882; x=1778545682; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=iic/TyuRCm/AuLebHAyrx4jlilsGhca+q3E++rpbwwU=; b=FfnTRsECXQsZjqTDJe2PyPDXAzWa8Ktvhv0FACbeXjfKUNGhvFaxm7FS90gObR614J +Bd0WXKF0p9jzn6UADs3iNsGt5l8X4OBHVrMBuVsuvPo/rgHv1Bsjl9W2i6vbOleooSl fJWuS79i6dziv2u6+3nJo8DRHrsxSpd9ENpxG3sy8lBFWuIug2bdtx/JH92uZuBc68Pg VGj5/vjHbxDA3jZP5r1punyrsIrcZUACm9l7c4Kxo/HUhM19zUI0WSaeIT76GxNTn6Gz uvb3Yt5b18Pagz0glQvfqKCUBjWZD66ZMlvyoOzZh24sTHKpB/pj9G9ygw9MBuqCWUaz 8ZrA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777940882; x=1778545682; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=iic/TyuRCm/AuLebHAyrx4jlilsGhca+q3E++rpbwwU=; b=D2NPA/peM62m5gCuGIzRe1m7MkNcrmKexvPeGk0WO/IFZTmP9RpRq++d90n3VzGUUC 9IbOrnXN0Z0i3AagNALnTW/LtY1tMAEkn7RZHNx3k5xgm8ahsUcEHqJDEYXPI1/oZOM7 JrBc1cfzCigtDAhfYVvpTizCSZr0gHQKFDBOU3UNAF0kQxdjrvhxNEA3WkJ2ozV9tgGe HZyWLz+WL+kNNkjy6HWURPqU05SMeYAGZeT2QKkLZd2Wnhqgvtbu5ibYXuTb99eSUH5U +/FBoIUwNVuGXNY1Nt0sc44pUzuNkQGfJYcwneorB6tJr8eQqj9v7yQ0H7VREgAET0wv YyIw== X-Forwarded-Encrypted: i=1; AFNElJ8W5CtVfUUAejTah0YyOjg7SCfy5NjKxIBEzvuDSgKFSJ6m4b60i7dusd1Xy+MeTAc5gmvM3LMtQs5v8Co=@vger.kernel.org X-Gm-Message-State: AOJu0YwO3vjoO9sPzV+m73GwiVPmbNauIBafTx15Imkmn2hBK+73eH5X CkTcoEAHq4Fbk4AyhddER1JynfLp0LjTLBldwZN0dAVjTHPftFZjIELk X-Gm-Gg: AeBDiet4jR5EGzmpPIkoHVZ1qqm60qdJTy/+iKdTQ9ispr379OtbiFd+ht/tGTbxNAK ii1nOk7sUaKxlVH5qTsRyKj+SfHLlBeeI8nRiFXBnkZOjZVKNMRKxWAn/mgl1JyP+wLh5rKTFnw H9vMAwtdRnuU2A+GCdFQpV40T1jjZryEHwqO02nwGA1QHJW0Il0oynouSWU28+vedgumHyU+hg+ 6U0xwpGlZmwgL35OEeyEQifIeSN3fFXq+wW/RZNZ2xtPhEs0GFJ9TJyJEaR7SHgP19aM/M9wlRX 6dD7LCmw2ke9SjS1CCUOX3cLhHKoERJn0BXueGyKu18DyDbTTjb8JR+AxMrvaETUWrmajTyG6U5 1HnbtAZxm8ts6yQzmZaBgSp38emy9vP3P88U9P3MnErIg7byu8xei+1J990w4NnTr1L1YzWOq4q W3v3ftTgvQF1B1PCv/LfZhtELRqLTp1HKA X-Received: by 2002:ac8:5ac3:0:b0:50f:340f:ff35 with SMTP id d75a77b69052e-51305357ffdmr24064071cf.26.1777940882452; Mon, 04 May 2026 17:28:02 -0700 (PDT) Received: from localhost ([2a03:2880:f800:1f::]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-51040ba8967sm107237721cf.29.2026.05.04.17.28.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 04 May 2026 17:28:02 -0700 (PDT) From: Bobby Eshleman Date: Mon, 04 May 2026 17:27:50 -0700 Subject: [PATCH net-next v2 3/6] selftests: drv-net: ncdevmem: add -n flag to skip NIC configuration 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 Message-Id: <20260504-tcp-dm-netkit-v2-3-56d52ac72fd4@meta.com> References: <20260504-tcp-dm-netkit-v2-0-56d52ac72fd4@meta.com> In-Reply-To: <20260504-tcp-dm-netkit-v2-0-56d52ac72fd4@meta.com> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Jonathan Corbet , Shuah Khan , Alex Shi , Yanteng Si , Dongliang Mu , Michael Chan , Pavan Chebbi , Joshua Washington , Harshitha Ramamurthy , Saeed Mahameed , Tariq Toukan , Mark Bloch , Leon Romanovsky , Alexander Duyck , kernel-team@meta.com, Daniel Borkmann , Nikolay Aleksandrov , Shuah Khan Cc: netdev@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-rdma@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org, Stanislav Fomichev , Mina Almasry , Bobby Eshleman X-Mailer: b4 0.14.3 From: Bobby Eshleman Add a -n (skip_config) flag that causes ncdevmem to skip NIC configuration when operating as an RX server. When -n is passed, ncdevmem skips configuring header split, RSS, and flow steering, as well as their teardown on exit. This allows ksft tests to pre-configure the NIC in the host namespace before launching ncdevmem in the guest namespace. This is needed for netkit devmem tests where the test harness namespace has direct access to the NIC and the ncdevmem namespace does not. Signed-off-by: Bobby Eshleman --- tools/testing/selftests/drivers/net/hw/ncdevmem.c | 58 +++++++++++++------= ---- 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/tools/testing/selftests/drivers/net/hw/ncdevmem.c b/tools/test= ing/selftests/drivers/net/hw/ncdevmem.c index e098d6534c3c..d96e8a3b5a65 100644 --- a/tools/testing/selftests/drivers/net/hw/ncdevmem.c +++ b/tools/testing/selftests/drivers/net/hw/ncdevmem.c @@ -93,6 +93,7 @@ static char *port; static size_t do_validation; static int start_queue =3D -1; static int num_queues =3D -1; +static int skip_config; static char *ifname; static unsigned int ifindex; static unsigned int dmabuf_id; @@ -828,7 +829,7 @@ static struct netdev_queue_id *create_queues(void) =20 static int do_server(struct memory_buffer *mem) { - struct ethtool_rings_get_rsp *ring_config; + struct ethtool_rings_get_rsp *ring_config =3D NULL; char ctrl_data[sizeof(int) * 20000]; size_t non_page_aligned_frags =3D 0; struct sockaddr_in6 client_addr; @@ -851,27 +852,29 @@ static int do_server(struct memory_buffer *mem) return -1; } =20 - ring_config =3D get_ring_config(); - if (!ring_config) { - pr_err("Failed to get current ring configuration"); - return -1; - } + if (!skip_config) { + ring_config =3D get_ring_config(); + if (!ring_config) { + pr_err("Failed to get current ring configuration"); + return -1; + } =20 - if (configure_headersplit(ring_config, 1)) { - pr_err("Failed to enable TCP header split"); - goto err_free_ring_config; - } + if (configure_headersplit(ring_config, 1)) { + pr_err("Failed to enable TCP header split"); + goto err_free_ring_config; + } =20 - /* Configure RSS to divert all traffic from our devmem queues */ - if (configure_rss()) { - pr_err("Failed to configure rss"); - goto err_reset_headersplit; - } + /* Configure RSS to divert all traffic from our devmem queues */ + if (configure_rss()) { + pr_err("Failed to configure rss"); + goto err_reset_headersplit; + } =20 - /* Flow steer our devmem flows to start_queue */ - if (configure_flow_steering(&server_sin)) { - pr_err("Failed to configure flow steering"); - goto err_reset_rss; + /* Flow steer our devmem flows to start_queue */ + if (configure_flow_steering(&server_sin)) { + pr_err("Failed to configure flow steering"); + goto err_reset_rss; + } } =20 if (bind_rx_queue(ifindex, mem->fd, create_queues(), num_queues, &ys)) { @@ -1052,13 +1055,17 @@ static int do_server(struct memory_buffer *mem) err_unbind: ynl_sock_destroy(ys); err_reset_flow_steering: - reset_flow_steering(); + if (!skip_config) + reset_flow_steering(); err_reset_rss: - reset_rss(); + if (!skip_config) + reset_rss(); err_reset_headersplit: - restore_ring_config(ring_config); + if (!skip_config) + restore_ring_config(ring_config); err_free_ring_config: - ethtool_rings_get_rsp_free(ring_config); + if (!skip_config) + ethtool_rings_get_rsp_free(ring_config); return err; } =20 @@ -1404,7 +1411,7 @@ int main(int argc, char *argv[]) int is_server =3D 0, opt; int ret, err =3D 1; =20 - while ((opt =3D getopt(argc, argv, "Lls:c:p:v:q:t:f:z:")) !=3D -1) { + while ((opt =3D getopt(argc, argv, "Lls:c:p:v:q:t:f:z:n")) !=3D -1) { switch (opt) { case 'L': fail_on_linear =3D true; @@ -1436,6 +1443,9 @@ int main(int argc, char *argv[]) case 'z': max_chunk =3D atoi(optarg); break; + case 'n': + skip_config =3D 1; + break; case '?': fprintf(stderr, "unknown option: %c\n", optopt); break; --=20 2.52.0 From nobody Sun Jun 14 01:35:34 2026 Received: from mail-qk1-f175.google.com (mail-qk1-f175.google.com [209.85.222.175]) (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 D0E2423183C for ; Tue, 5 May 2026 00:28:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.175 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777940889; cv=none; b=urdWarFm+lr5eTnDBIbjIzFMHv2xLFRsUWIJOMG2glXqXckwXvgPyKD9uejZ7mgz6H0QulVSiPVEAPmUOQXuYPh6wbefHQgrJwi/r+pa8I7Cj35yMOSqcICWay4Ilw+MejehdGZ5S3jkHaxnWBkO1vrjCo3G1RJya1RsCCiuIIk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777940889; c=relaxed/simple; bh=Qa3qVnasFjeKcLXQGuewmxcuQRVtnPk652qg+JZlmVk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=VV6wIihlNCz+h9YSqo+MzNrOjyE0cgCnhXem6756gLK0krRKI/kcsEtr5bIFTstxZrxfFusNk6C7uTOmVsWlQwD2cgFZ4EoKf0eNbfsrq/gQEZ959RTXukiJF9sikqnfK/iN1uf//UC7O7b+Gt+bwXdmep5PwlYA/SopChx1odg= 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=YreCqpYl; arc=none smtp.client-ip=209.85.222.175 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="YreCqpYl" Received: by mail-qk1-f175.google.com with SMTP id af79cd13be357-8d4f78fc9f6so512167685a.3 for ; Mon, 04 May 2026 17:28:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777940885; x=1778545685; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=uKo0X1zLy79YbJbsw8fyk970YAWWmEL6K2YwtNFNBfc=; b=YreCqpYlAMqim2AuMSaAkWfdZekd3oeuX/xVg1OR8ndHDulJrVaU/rZ4zmz8ED6HnR FjFRgQrbxqkOxnwbQZSUDGvWfa9vYhOFjdDcAz3cs1CRdB/B6HtM3atQw4SO+2h/2dOl hihuRDLbm8pycePtGr5yBu0iB0B2bx0kfXjX4XNsX4FzX7JPlN5S8Xw9+wCuaAnYLvqj oTLlbqNbb+6AfhJ82teP7w8L+n5WJb8NehPGuXmYbG5/PLakmo1JYLIoXY5SWejJoY7i mxZHOBRiYwfsM/P7Qojt71Wv3/P8GAqQbynXm3aU2tzzye9jYf1dzAgRQnCDLqSTTnMa 7mgQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777940885; x=1778545685; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=uKo0X1zLy79YbJbsw8fyk970YAWWmEL6K2YwtNFNBfc=; b=NN71smXnknyBbdGAdM0WK8woCtwKCptw2tWiswO83wLep3KEfqbAoLpDpvsACVnP3q /pAdfsJItxOIihpDYtIGqRwsSrB2/0CjAAEkTPoUa9IlgQxIlj0WxIE+INaNbSqoUDmK XmN3PnXjfFTbiAJuqfBkmyayJlyp+In7NmiSeei+qOnom826nFVWxk2AH9/JNaOXIv7y 0OVPVnCGhAkb91Jw0AzpC+zNnLDxvuk/+mfFDXFlX0i6S3e4Yu3STiyEabF3a5MQqoO5 5DfL4ceE+ZKvUcejTL3HG1j1oTpHrnL+eyL5JW0h9uzW35sOnbsw6XIQ/vjgAL7O7m/7 RXxw== X-Forwarded-Encrypted: i=1; AFNElJ/Ni3q3K8YUztlQxjxnxH2+Gpz3UFbesQYxOy/N2y1zRQi+o2Z2r7HRsUYCw/tx5xs2X778JCJP0CbdroI=@vger.kernel.org X-Gm-Message-State: AOJu0YwvHXPMtymhCRFAqFdHqoLviMMlvcG5KpkMmitw8idGWAAWo5qd 8LQYS6tlR4ueFuhk9iA7+BAfEcmgWIK/fx3tdpt8UwwNaOKe2VnS48VD X-Gm-Gg: AeBDietMYFX47HkX08GbquVT2GomUeqUebFtkDTjR728rgqu5Cc4izJ9NvNrhjrfhKH DmctefIWfUdoT7BI47AVDQ/fPnN1ThKuLI92j+JFe2XO9iB8Twq/GdkKJKa7z1Icv5UqxWMACTT qZm7maxpBwRozV+wmOJvUXU1ACqxGazKZH88a47IN8/OEXf9qFzRL91kpSZjN7mq8/iYmxJpRAV lL1j2IQ/gzKGdxBqOY6RQZnewfX7kx40lmBatYEVUrPGCO8iQA1206cDeggqbULsQLbSPfrVag1 B0mdaNTh6M1ThyxuzK0VKv+WOlWkDoZzmQV2ysAyzarCV99igtmHRCzXsWh1MB4msTvijtteELb iGvLMAYqeMkdKl6UFFv7qBEshyGxkpAUgdSUOwDD/b+kuK2eRE70yO19287OF3NIo/kP8Wcw6IH RY6M0AA6Kclj1hUkxDIdInsuRRw7jcpdgG9X1Yinf+c6gZzgmelTyO+A== X-Received: by 2002:a05:620a:4722:b0:8cd:8f04:50ec with SMTP id af79cd13be357-902e49b6e22mr192973685a.2.1777940884520; Mon, 04 May 2026 17:28:04 -0700 (PDT) Received: from localhost ([2a03:2880:f800:29::]) by smtp.gmail.com with ESMTPSA id af79cd13be357-8fc29a7f4dbsm1210668885a.16.2026.05.04.17.28.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 04 May 2026 17:28:04 -0700 (PDT) From: Bobby Eshleman Date: Mon, 04 May 2026 17:27:51 -0700 Subject: [PATCH net-next v2 4/6] selftests: drv-net: refactor devmem command builders into lib module 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 Message-Id: <20260504-tcp-dm-netkit-v2-4-56d52ac72fd4@meta.com> References: <20260504-tcp-dm-netkit-v2-0-56d52ac72fd4@meta.com> In-Reply-To: <20260504-tcp-dm-netkit-v2-0-56d52ac72fd4@meta.com> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Jonathan Corbet , Shuah Khan , Alex Shi , Yanteng Si , Dongliang Mu , Michael Chan , Pavan Chebbi , Joshua Washington , Harshitha Ramamurthy , Saeed Mahameed , Tariq Toukan , Mark Bloch , Leon Romanovsky , Alexander Duyck , kernel-team@meta.com, Daniel Borkmann , Nikolay Aleksandrov , Shuah Khan Cc: netdev@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-rdma@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org, Stanislav Fomichev , Mina Almasry , Bobby Eshleman X-Mailer: b4 0.14.3 From: Bobby Eshleman Adding netkit-based devmem tests is a straight-forward copy of devmem test commands plus some args for the nk cases, so this patch breaks out these command builders into helpers used by both. Though we tried to avoid libraries to avoid increasing the barrier of entry/complexity (see selftests/drivers/net/README.md, section "Avoid libraries and frameworks"), factoring out these functions seemed like the lesser of two evils in this case of using the same commands, just with slightly different args per environment. I experimented with just having all of the tests in the same file to avoid having helpers in a library file, but because ksft_run() is limited to a single call per file, and the new tests will require different environments (NetDrvContEnv/NetDrvEpEnv), it would have been necessary to have each test set up its own environment instead of sharing one for the entire ksft_run() run. This came at the cost of ballooning the test time (from under 5s to 30s on my test system), so to strike a balance these tests were placed in separate files so they could keep a shared environment across a single ksft_run() run shared across all tests using the same env type (introduced in subsequent patches). The helpers work transparently with both plain and netkit environments by inspecting cfg for netkit-specific attributes (netns, nk_queue, etc...). Signed-off-by: Bobby Eshleman --- Changes in v2: - Move require_devmem() into individual test functions so KsftSkipEx goes u= p to ksft_run() (Sashiko) - in ncdevmem_rx(), move -v 7 to take effect for both netns and non-netns when verify=3DTrue --- tools/testing/selftests/drivers/net/hw/devmem.py | 73 +------ .../selftests/drivers/net/hw/lib/py/devmem.py | 222 +++++++++++++++++= ++++ 2 files changed, 231 insertions(+), 64 deletions(-) diff --git a/tools/testing/selftests/drivers/net/hw/devmem.py b/tools/testi= ng/selftests/drivers/net/hw/devmem.py index ee863e90d1e0..33648e39577a 100755 --- a/tools/testing/selftests/drivers/net/hw/devmem.py +++ b/tools/testing/selftests/drivers/net/hw/devmem.py @@ -1,92 +1,37 @@ #!/usr/bin/env python3 # SPDX-License-Identifier: GPL-2.0 +"""Test devmem TCP.""" =20 from os import path -from lib.py import ksft_run, ksft_exit -from lib.py import ksft_eq, KsftSkipEx +from lib.py import ksft_run, ksft_exit, ksft_disruptive from lib.py import NetDrvEpEnv -from lib.py import bkg, cmd, rand_port, wait_port_listen -from lib.py import ksft_disruptive - - -def require_devmem(cfg): - if not hasattr(cfg, "_devmem_probed"): - probe_command =3D f"{cfg.bin_local} -f {cfg.ifname}" - cfg._devmem_supported =3D cmd(probe_command, fail=3DFalse, shell= =3DTrue).ret =3D=3D 0 - cfg._devmem_probed =3D True - - if not cfg._devmem_supported: - raise KsftSkipEx("Test requires devmem support") +from lib.py.devmem import setup_test, run_rx, run_tx, run_tx_chunks, run_r= x_hds =20 =20 @ksft_disruptive def check_rx(cfg) -> None: - require_devmem(cfg) - - port =3D rand_port() - socat =3D f"socat -u - TCP{cfg.addr_ipver}:{cfg.baddr}:{port},bind=3D{= cfg.remote_baddr}:{port}" - listen_cmd =3D f"{cfg.bin_local} -l -f {cfg.ifname} -s {cfg.addr} -p {= port} -c {cfg.remote_addr} -v 7" - - with bkg(listen_cmd, exit_wait=3DTrue) as ncdevmem: - wait_port_listen(port) - cmd(f"yes $(echo -e \x01\x02\x03\x04\x05\x06) | \ - head -c 1K | {socat}", host=3Dcfg.remote, shell=3DTrue) - - ksft_eq(ncdevmem.ret, 0) + run_rx(cfg) =20 =20 @ksft_disruptive def check_tx(cfg) -> None: - require_devmem(cfg) - - port =3D rand_port() - listen_cmd =3D f"socat -U - TCP{cfg.addr_ipver}-LISTEN:{port}" - - with bkg(listen_cmd, host=3Dcfg.remote, exit_wait=3DTrue) as socat: - wait_port_listen(port, host=3Dcfg.remote) - cmd(f"echo -e \"hello\\nworld\"| {cfg.bin_local} -f {cfg.ifname} -= s {cfg.remote_addr} -p {port}", shell=3DTrue) - - ksft_eq(socat.stdout.strip(), "hello\nworld") + run_tx(cfg) =20 =20 @ksft_disruptive def check_tx_chunks(cfg) -> None: - require_devmem(cfg) - - port =3D rand_port() - listen_cmd =3D f"socat -U - TCP{cfg.addr_ipver}-LISTEN:{port}" - - with bkg(listen_cmd, host=3Dcfg.remote, exit_wait=3DTrue) as socat: - wait_port_listen(port, host=3Dcfg.remote) - cmd(f"echo -e \"hello\\nworld\"| {cfg.bin_local} -f {cfg.ifname} -= s {cfg.remote_addr} -p {port} -z 3", shell=3DTrue) - - ksft_eq(socat.stdout.strip(), "hello\nworld") + run_tx_chunks(cfg) =20 =20 def check_rx_hds(cfg) -> None: - """Test HDS splitting across payload sizes.""" - require_devmem(cfg) - - for size in [1, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192]: - port =3D rand_port() - listen_cmd =3D f"{cfg.bin_local} -L -l -f {cfg.ifname} -s {cfg.add= r} -p {port}" - - with bkg(listen_cmd, exit_wait=3DTrue) as ncdevmem: - wait_port_listen(port) - cmd(f"dd if=3D/dev/zero bs=3D{size} count=3D1 2>/dev/null | " + - f"socat -b {size} -u - TCP{cfg.addr_ipver}:{cfg.baddr}:{po= rt},nodelay", - host=3Dcfg.remote, shell=3DTrue) - - ksft_eq(ncdevmem.ret, 0, f"HDS failed for payload size {size}") + run_rx_hds(cfg) =20 =20 def main() -> None: with NetDrvEpEnv(__file__) as cfg: - cfg.bin_local =3D path.abspath(path.dirname(__file__) + "/ncdevmem= ") - cfg.bin_remote =3D cfg.remote.deploy(cfg.bin_local) - + setup_test(cfg, path.abspath(path.dirname(__file__) + "/ncdevmem")) ksft_run([check_rx, check_tx, check_tx_chunks, check_rx_hds], - args=3D(cfg, )) + args=3D(cfg,)) ksft_exit() =20 =20 diff --git a/tools/testing/selftests/drivers/net/hw/lib/py/devmem.py b/tool= s/testing/selftests/drivers/net/hw/lib/py/devmem.py new file mode 100644 index 000000000000..6f8a3f5aae14 --- /dev/null +++ b/tools/testing/selftests/drivers/net/hw/lib/py/devmem.py @@ -0,0 +1,222 @@ +# SPDX-License-Identifier: GPL-2.0 +"""Shared helpers for devmem TCP selftests.""" + +import re + +from net.lib.py import (bkg, cmd, defer, ethtool, rand_port, wait_port_lis= ten, + ksft_eq, KsftSkipEx, NetNSEnter, EthtoolFamily, + NetdevFamily) + + +def require_devmem(cfg): + if not hasattr(cfg, "_devmem_probed"): + probe_command =3D f"{cfg.bin_local} -f {cfg.ifname}" + cfg._devmem_supported =3D cmd(probe_command, fail=3DFalse, shell= =3DTrue).ret =3D=3D 0 + cfg._devmem_probed =3D True + + if not cfg._devmem_supported: + raise KsftSkipEx("Test requires devmem support") + + +def configure_nic(cfg): + """Channels, rings, RSS, queue lease for netkit devmem. + + Rings and RSS are re-applied each call because per-test defers restore + them after every test case. The queue lease is created only once. + """ + cfg.require_ipver('6') + ethnl =3D EthtoolFamily() + + channels =3D ethnl.channels_get({'header': {'dev-index': cfg.ifindex}}) + channels =3D channels['combined-count'] + if channels < 2: + raise KsftSkipEx( + 'Test requires NETIF with at least 2 combined channels' + ) + + rings =3D ethnl.rings_get({'header': {'dev-index': cfg.ifindex}}) + rx_rings =3D rings['rx'] + hds_thresh =3D rings.get('hds-thresh', 0) + orig_data_split =3D rings.get('tcp-data-split', 'unknown') + + ethnl.rings_set({'header': {'dev-index': cfg.ifindex}, + 'tcp-data-split': 'enabled', + 'hds-thresh': 0, + 'rx': min(64, rx_rings)}) + defer(ethnl.rings_set, {'header': {'dev-index': cfg.ifindex}, + 'tcp-data-split': orig_data_split, + 'hds-thresh': hds_thresh, + 'rx': rx_rings}) + + cfg.src_queue =3D channels - 1 + ethtool(f"-X {cfg.ifname} equal {cfg.src_queue}") + defer(ethtool, f"-X {cfg.ifname} default") + + if not hasattr(cfg, 'nk_queue'): + with NetNSEnter(str(cfg.netns)): + netdevnl =3D NetdevFamily() + lease_result =3D netdevnl.queue_create({ + "ifindex": cfg.nk_guest_ifindex, + "type": "rx", + "lease": { + "ifindex": cfg.ifindex, + "queue": {"id": cfg.src_queue, "type": "rx"}, + "netns-id": 0, + }, + }) + cfg.nk_queue =3D lease_result['id'] + + +def set_flow_rule(cfg, port): + output =3D ethtool( + f"-N {cfg.ifname} flow-type tcp6 dst-port {port}" + f" action {cfg.src_queue}" + ).stdout + return int(re.search(r'ID (\d+)', output).group(1)) + + +def ncdevmem_rx(cfg, port, verify=3DTrue, fail_on_linear=3DFalse, flow_ste= er=3DFalse): + if hasattr(cfg, 'netns'): + flow_rule_id =3D set_flow_rule(cfg, port) + defer(ethtool, f"-N {cfg.ifname} delete {flow_rule_id}") + + ifname =3D cfg._nk_guest_ifname + addr =3D cfg.nk_guest_ipv6 + extras =3D f" -t {cfg.nk_queue} -q 1 -n" + else: + ifname =3D cfg.ifname + addr =3D cfg.addr + + extras =3D "" + if flow_steer: + extras +=3D f"-c {cfg.remote_addr}" + + if verify: + extras +=3D " -v 7" + + if fail_on_linear: + extras +=3D " -L" + + return f"{cfg.bin_local} -l -f {ifname} -s {addr} -p {port} {extras}" + + +def ncdevmem_tx(cfg, port, chunk_size=3D0): + """ncdevmem TX send command (without stdin pipe).""" + if hasattr(cfg, 'netns'): + ifname =3D cfg._nk_guest_ifname + addr =3D cfg.remote_addr_v['6'] + nk_args =3D "-t 0 -q 1 -n" + else: + ifname =3D cfg.ifname + addr =3D cfg.remote_addr + nk_args =3D "" + + chunk =3D f"-z {chunk_size}" if chunk_size else "" + + return (f"{cfg.bin_local} -f {ifname} -s {addr} -p {port}" + f" {nk_args} {chunk}").rstrip() + + +def socat_send(cfg, port, buf_size=3D0, nodelay=3DFalse, bind=3DFalse): + """Socat command for sending to the devmem listener.""" + proto =3D f"TCP{cfg.addr_ipver}" + + if hasattr(cfg, 'netns'): + addr =3D f"[{cfg.nk_guest_ipv6}]" + else: + addr =3D cfg.baddr + + buf =3D f"-b {buf_size} " if buf_size else "" + + suffix =3D "" + if nodelay: + suffix +=3D ",nodelay" + # Match the 5-tuple flow rule ncdevmem installs when given -c. + if bind: + suffix +=3D f",bind=3D{cfg.remote_baddr}:{port}" + + return f"socat {buf}-u - {proto}:{addr}:{port}{suffix}" + + +def socat_listen(cfg, port): + """Socat listen command for TX tests.""" + proto =3D f"TCP{cfg.addr_ipver}" + + if hasattr(cfg, 'netns'): + opts =3D ",reuseaddr" + else: + opts =3D "" + + return f"socat -U - {proto}-LISTEN:{port}{opts}" + + +def setup_test(cfg, bin_local): + cfg.bin_local =3D bin_local + cfg.bin_remote =3D cfg.remote.deploy(cfg.bin_local) + cfg.listen_ns =3D getattr(cfg, 'netns', None) + + +def run_rx(cfg): + require_devmem(cfg) + if hasattr(cfg, 'netns'): + configure_nic(cfg) + port =3D rand_port() + socat =3D socat_send(cfg, port) + data_pipe =3D (f"yes $(echo -e \x01\x02\x03\x04\x05\x06) | head -c 1K" + f" | {socat}") + ns =3D getattr(cfg, "netns", None) + + listen_cmd =3D ncdevmem_rx(cfg, port) + with bkg(listen_cmd, exit_wait=3DTrue, ns=3Dns) as ncdevmem: + wait_port_listen(port, proto=3D"tcp", ns=3Dns) + cmd(data_pipe, host=3Dcfg.remote, shell=3DTrue) + ksft_eq(ncdevmem.ret, 0) + + +def run_tx(cfg): + require_devmem(cfg) + if hasattr(cfg, 'netns'): + configure_nic(cfg) + ns =3D getattr(cfg, "netns", None) + port =3D rand_port() + tx =3D ncdevmem_tx(cfg, port) + listen_cmd =3D socat_listen(cfg, port) + + with bkg(listen_cmd, host=3Dcfg.remote, exit_wait=3DTrue) as socat: + wait_port_listen(port, host=3Dcfg.remote) + cmd(f"bash -c 'echo -e \"hello\\nworld\" | {tx}'", ns=3Dns, shell= =3DTrue) + ksft_eq(socat.stdout.strip(), "hello\nworld") + + +def run_tx_chunks(cfg): + require_devmem(cfg) + if hasattr(cfg, 'netns'): + configure_nic(cfg) + ns =3D getattr(cfg, "netns", None) + port =3D rand_port() + tx =3D ncdevmem_tx(cfg, port, chunk_size=3D3) + listen_cmd =3D socat_listen(cfg, port) + + with bkg(listen_cmd, host=3Dcfg.remote, exit_wait=3DTrue) as socat: + wait_port_listen(port, host=3Dcfg.remote) + cmd(f"bash -c 'echo -e \"hello\\nworld\" | {tx}'", ns=3Dns, shell= =3DTrue) + ksft_eq(socat.stdout.strip(), "hello\nworld") + + +def run_rx_hds(cfg): + require_devmem(cfg) + if hasattr(cfg, 'netns'): + configure_nic(cfg) + ns =3D getattr(cfg, "netns", None) + + for size in [1, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192]: + port =3D rand_port() + + listen_cmd =3D ncdevmem_rx(cfg, port, verify=3DFalse, fail_on_line= ar=3DTrue) + socat =3D socat_send(cfg, port, buf_size=3Dsize, nodelay=3DTrue) + + with bkg(listen_cmd, exit_wait=3DTrue, ns=3Dns) as ncdevmem: + wait_port_listen(port, proto=3D"tcp", ns=3Dns) + cmd(f"dd if=3D/dev/zero bs=3D{size} count=3D1 2>/dev/null | " + f"{socat}", host=3Dcfg.remote, shell=3DTrue) + ksft_eq(ncdevmem.ret, 0, f"HDS failed for payload size {size}") --=20 2.52.0 From nobody Sun Jun 14 01:35:34 2026 Received: from mail-qt1-f171.google.com (mail-qt1-f171.google.com [209.85.160.171]) (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 5CE33314B93 for ; Tue, 5 May 2026 00:28:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777940892; cv=none; b=cfQt3EK70SejUYr7ochwMFH7cXyhOLaEvook7RXoXS/Ukpo0GNxVgL8t5PbAlgcUKa0YW3vUcBPcpSwj/35Iah9OjgPRFIS5R85CzNs2LcdbbreFznLr5E0CO7WCnMGYZiKx8qJn/fZVXO945Drwx9eAD6us88ybVEd8ExPIoko= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777940892; c=relaxed/simple; bh=pZx1YkARmGowE47Fjinw6aGk/1Z/1eqLPS3aBUwU4zo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=HdBepzPMSC0xNKR8Yzxd2j2SuZe2BR5bhZqXQ7HeFsicGo3UOIFh2aHyUWFg240x2xqgVr11XQeyU+c7W5elqx3Y1lHp20XNHCifQEGu9jQ0aLNvHay4r5aP7OwQ+nw8uO5rD8zO7qdt+gii551gO+G5yXil9UpFLilNAEcatoU= 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=lIZkiPnu; arc=none smtp.client-ip=209.85.160.171 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="lIZkiPnu" Received: by mail-qt1-f171.google.com with SMTP id d75a77b69052e-51306c9f2e1so2160841cf.0 for ; Mon, 04 May 2026 17:28:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777940887; x=1778545687; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=7WIazItlhuwSwfo6on4yEwmRZQUGTlMWmE/koiDnhNI=; b=lIZkiPnupTpPzOuzkDC4Yw1Cu1BgO3sOdLFuMCHCBhJA9cLhjmz1Bc/scN5fYqaFQ0 GFp1cMHeEotCuoGPs+fzIkih7NtQvdM+iZxVoJ22X/RrjN3QT5/6wekz3JcYQ+rv6GYO /A4iFcfXDCpOKdtjwVXjiHzg+BKYZ3Qzpn/fJCY9YoF95NCCJvO2OO+Nni2MxNBea7H1 zkewXblbuO3Zo++1gUKEAaqGE9l7KGzIqrypEo5QkcJ24Bepd/hmJ0nlK2mhMSjyeU2I wCt3FOM+UssBy6AzGxlBmLYUvrzyRspkzoTm2h8Uf8q0uCVowKqoSnihQZ/vifxhDsPL CCAA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777940887; x=1778545687; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=7WIazItlhuwSwfo6on4yEwmRZQUGTlMWmE/koiDnhNI=; b=T7Cjipqd29Uy4wcB9NLLchQsCIBqAU8iUSgjTiSfC6S5W3P9hWT48uuE8vFbcILVQR ufa02ifVQsmmDQ4+VdnSYp8sZS9H3CGihZQnoCDrz+t/YOg0UPnLeS/L3c366PCQCY4h zlp6ca8Ay+TOvPXa4YS59qhpc6Ozx3tgOlJTZuSovdGWeuWDkxO1RxyDsFBqXipRYzdD hnfcJnlZ+rKqk7jltA7Vg6obXHDCAby6tAVf3S6U1yl7V4cvgVRBkf/VkUSRLGr9YJo1 eX2aUNubiAUQ68TzYgdGYUGq7g+nleS8ssS3CRc6wUaqjPRwtYVRy7I8EqxKvtkLUx9Z 0nDA== X-Forwarded-Encrypted: i=1; AFNElJ+mZXStgFoK2hWK5iOk5p8NbUJdKVfOhWJRf7rNaxtJtAK1FF1bXXDi2FgBmgeep0t94YqwecDE0F8Tdds=@vger.kernel.org X-Gm-Message-State: AOJu0YwrQkwK+unLMHcLb2O7NfAZbHd1sGsiygWFaEyUvDNz4tHd1TQ6 sN3iVQpvSMymePBsmGZ8svZ1JG0faxKI2jDXXfsq7efSFstcFFljQKWO X-Gm-Gg: AeBDiesEPy/o6P9/rt8sJ1AJ8VHRFU2wdBjHaoU1OyIziGxUppDwX7pUJqkzvpVTgdk OJiy4YpV6JarIEybRmKpf18hTMsWtmOoSG148N/9E7UeDLPcSCk2CSkYoMr1cIQaHInsLdhPYKc sgoi1DCeOkeoE8GFXIzPmOzHNui+LlPE1Lhsp0/Obx8J1OITaA2xaFU/VeqeoTJ9xQOcLmVPell xUNm0BRvg9cp3ldoZsM06zRXRSi4I37rGW3vyi+NPWV7eL+3mfoY4q24CCACMq48XrLSt7nv6wv GksaX1NGFmfEp1Sx+YxEu1bjknqzAsjlkIIqcDWBoFYCHTwbRZxXA63zx+OMEUvXrmjgQWMrmt/ sUmLnayT0k3j5RNzSD9UOaeQhhaoaFum0JxNs+t4JY098xQWfem5slkkcnMbxk3LYzDEXPwNGQv 9WwGnVpqv5vsDD+VrFBwHdzleqcLHfCDErifo0m011DKI= X-Received: by 2002:a05:622a:509:b0:50f:9c33:af18 with SMTP id d75a77b69052e-5104bf964f0mr168578611cf.51.1777940886765; Mon, 04 May 2026 17:28:06 -0700 (PDT) Received: from localhost ([2a03:2880:f804:2e::]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-51040ba8967sm107239171cf.29.2026.05.04.17.28.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 04 May 2026 17:28:06 -0700 (PDT) From: Bobby Eshleman Date: Mon, 04 May 2026 17:27:52 -0700 Subject: [PATCH net-next v2 5/6] selftests: drv-net: add primary_rx_redirect support to NetDrvContEnv 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 Message-Id: <20260504-tcp-dm-netkit-v2-5-56d52ac72fd4@meta.com> References: <20260504-tcp-dm-netkit-v2-0-56d52ac72fd4@meta.com> In-Reply-To: <20260504-tcp-dm-netkit-v2-0-56d52ac72fd4@meta.com> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Jonathan Corbet , Shuah Khan , Alex Shi , Yanteng Si , Dongliang Mu , Michael Chan , Pavan Chebbi , Joshua Washington , Harshitha Ramamurthy , Saeed Mahameed , Tariq Toukan , Mark Bloch , Leon Romanovsky , Alexander Duyck , kernel-team@meta.com, Daniel Borkmann , Nikolay Aleksandrov , Shuah Khan Cc: netdev@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-rdma@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org, Stanislav Fomichev , Mina Almasry , Bobby Eshleman X-Mailer: b4 0.14.3 From: Bobby Eshleman When sending from a namespace that has access to a netkit device with a leased queue, the nk primary in the host namespace needs to redirect its RX to the physical device. This patch adds that redirection bpf program and teaches the harness to install it. Add primary_rx_redirect=3DFalse parameter to NetDrvContEnv.__init__(). When enabled, _attach_primary_rx_redirect_bpf() attaches a new BPF TC program (nk_primary_rx_redirect.bpf.c) to the primary (host-side) netkit interface. The program redirects non-ICMPv6 IPv6 packets to the physical NIC via bpf_redirect_neigh(), with the physical ifindex configured via the .bss map. Extract _find_bss_map_id() from _attach_bpf() into a reusable helper so other BPF attachment methods can use it. Also add an IPv6 host route on the remote endpoint for the netkit guest IP via the physical NIC address, so the remote can send packets that traverse the redirect path to the guest. Signed-off-by: Bobby Eshleman --- .../drivers/net/hw/nk_primary_rx_redirect.bpf.c | 41 +++++++++++++ tools/testing/selftests/drivers/net/lib/py/env.py | 67 ++++++++++++++++++= ---- 2 files changed, 96 insertions(+), 12 deletions(-) diff --git a/tools/testing/selftests/drivers/net/hw/nk_primary_rx_redirect.= bpf.c b/tools/testing/selftests/drivers/net/hw/nk_primary_rx_redirect.bpf.c new file mode 100644 index 000000000000..fe3c127a4fd0 --- /dev/null +++ b/tools/testing/selftests/drivers/net/hw/nk_primary_rx_redirect.bpf.c @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include + +#define TC_ACT_OK 0 +#define ETH_P_IPV6 0x86DD +#define IPPROTO_ICMPV6 58 + +#define ctx_ptr(field) ((void *)(long)(field)) + +volatile __u32 phys_ifindex; + +SEC("tc/ingress") +int nk_primary_rx_redirect(struct __sk_buff *skb) +{ + void *data_end =3D ctx_ptr(skb->data_end); + void *data =3D ctx_ptr(skb->data); + struct ethhdr *eth; + struct ipv6hdr *ip6h; + + eth =3D data; + if ((void *)(eth + 1) > data_end) + return TC_ACT_OK; + + if (eth->h_proto !=3D bpf_htons(ETH_P_IPV6)) + return TC_ACT_OK; + + ip6h =3D data + sizeof(struct ethhdr); + if ((void *)(ip6h + 1) > data_end) + return TC_ACT_OK; + + if (ip6h->nexthdr =3D=3D IPPROTO_ICMPV6) + return TC_ACT_OK; + + return bpf_redirect_neigh(phys_ifindex, NULL, 0, 0); +} + +char __license[] SEC("license") =3D "GPL"; diff --git a/tools/testing/selftests/drivers/net/lib/py/env.py b/tools/test= ing/selftests/drivers/net/lib/py/env.py index 24ce122abd9c..d569d01ef791 100644 --- a/tools/testing/selftests/drivers/net/lib/py/env.py +++ b/tools/testing/selftests/drivers/net/lib/py/env.py @@ -336,15 +336,17 @@ class NetDrvContEnv(NetDrvEpEnv): +---------------+ """ =20 - def __init__(self, src_path, rxqueues=3D1, **kwargs): + def __init__(self, src_path, rxqueues=3D1, primary_rx_redirect=3DFalse= , **kwargs): self.netns =3D None self._nk_host_ifname =3D None self._nk_guest_ifname =3D None self._tc_clsact_added =3D False self._tc_attached =3D False + self._primary_rx_redirect_attached =3D False self._bpf_prog_pref =3D None self._bpf_prog_id =3D None self._init_ns_attached =3D False + self._remote_route_added =3D False self._old_fwd =3D None self._old_accept_ra =3D None =20 @@ -396,8 +398,14 @@ class NetDrvContEnv(NetDrvEpEnv): =20 self._setup_ns() self._attach_bpf() + if primary_rx_redirect: + self._attach_primary_rx_redirect_bpf() =20 def __del__(self): + if self._primary_rx_redirect_attached: + cmd(f"tc qdisc del dev {self._nk_host_ifname} clsact", fail=3D= False) + self._primary_rx_redirect_attached =3D False + if self._tc_attached: cmd(f"tc filter del dev {self.ifname} ingress pref {self._bpf_= prog_pref}") self._tc_attached =3D False @@ -406,6 +414,11 @@ class NetDrvContEnv(NetDrvEpEnv): cmd(f"tc qdisc del dev {self.ifname} clsact") self._tc_clsact_added =3D False =20 + if self._remote_route_added: + cmd(f"ip -6 route del {self.nk_guest_ipv6}/128", + host=3Dself.remote, fail=3DFalse) + self._remote_route_added =3D False + if self._nk_host_ifname: cmd(f"ip link del dev {self._nk_host_ifname}") self._nk_host_ifname =3D None @@ -459,6 +472,9 @@ class NetDrvContEnv(NetDrvEpEnv): ip(f"-6 addr add {self.nk_guest_ipv6}/64 dev {self._nk_guest_ifnam= e} nodad", ns=3Dself.netns) ip(f"-6 route add default via fe80::1 dev {self._nk_guest_ifname}"= , ns=3Dself.netns) =20 + ip(f"-6 route add {self.nk_guest_ipv6}/128 via {self.addr_v['6']}"= , host=3Dself.remote) + self._remote_route_added =3D True + def _tc_ensure_clsact(self): qdisc =3D json.loads(cmd(f"tc -j qdisc show dev {self.ifname}").st= dout) for q in qdisc: @@ -476,6 +492,15 @@ class NetDrvContEnv(NetDrvEpEnv): return (bpf['pref'], bpf['options']['prog']['id']) raise Exception("Failed to get BPF prog ID") =20 + def _find_bss_map_id(self, prog_id): + """Find the .bss map ID for a loaded BPF program.""" + prog_info =3D bpftool(f"prog show id {prog_id}", json=3DTrue) + for map_id in prog_info.get("map_ids", []): + map_info =3D bpftool(f"map show id {map_id}", json=3DTrue) + if map_info.get("name", "").endswith("bss"): + return map_id + raise Exception(f"Failed to find .bss map for prog {prog_id}") + def _attach_bpf(self): bpf_obj =3D self.test_dir / "nk_forward.bpf.o" if not bpf_obj.exists(): @@ -487,17 +512,7 @@ class NetDrvContEnv(NetDrvEpEnv): self._tc_attached =3D True =20 (self._bpf_prog_pref, self._bpf_prog_id) =3D self._get_bpf_prog_id= s() - prog_info =3D bpftool(f"prog show id {self._bpf_prog_id}", json=3D= True) - map_ids =3D prog_info.get("map_ids", []) - - bss_map_id =3D None - for map_id in map_ids: - map_info =3D bpftool(f"map show id {map_id}", json=3DTrue) - if map_info.get("name").endswith("bss"): - bss_map_id =3D map_id - - if bss_map_id is None: - raise Exception("Failed to find .bss map") + bss_map_id =3D self._find_bss_map_id(self._bpf_prog_id) =20 ipv6_addr =3D ipaddress.IPv6Address(self.ipv6_prefix) ipv6_bytes =3D ipv6_addr.packed @@ -505,3 +520,31 @@ class NetDrvContEnv(NetDrvEpEnv): value =3D ipv6_bytes + ifindex_bytes value_hex =3D ' '.join(f'{b:02x}' for b in value) bpftool(f"map update id {bss_map_id} key hex 00 00 00 00 value hex= {value_hex}") + + def _attach_primary_rx_redirect_bpf(self): + """Attach BPF redirect program on the primary netkit ingress.""" + bpf_obj =3D self.test_dir / "nk_primary_rx_redirect.bpf.o" + if not bpf_obj.exists(): + raise KsftSkipEx("Primary RX redirect BPF prog not found") + + cmd(f"tc qdisc add dev {self._nk_host_ifname} clsact") + cmd(f"tc filter add dev {self._nk_host_ifname} ingress" + f" bpf obj {bpf_obj} sec tc/ingress direct-action") + self._primary_rx_redirect_attached =3D True + + filters =3D json.loads( + cmd(f"tc -j filter show dev {self._nk_host_ifname} ingress").s= tdout) + redirect_prog_id =3D None + for bpf in filters: + if 'options' not in bpf: + continue + if bpf['options']['bpf_name'].startswith('nk_primary_rx_redire= ct'): + redirect_prog_id =3D bpf['options']['prog']['id'] + break + if redirect_prog_id is None: + raise Exception("Failed to get primary RX redirect BPF prog ID= ") + + bss_map_id =3D self._find_bss_map_id(redirect_prog_id) + phys_ifindex_bytes =3D self.ifindex.to_bytes(4, byteorder=3D'littl= e') + value_hex =3D ' '.join(f'{b:02x}' for b in phys_ifindex_bytes) + bpftool(f"map update id {bss_map_id} key hex 00 00 00 00 value hex= {value_hex}") --=20 2.52.0 From nobody Sun Jun 14 01:35:34 2026 Received: from mail-yx1-f45.google.com (mail-yx1-f45.google.com [74.125.224.45]) (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 E2F45318ED2 for ; Tue, 5 May 2026 00:28:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.224.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777940892; cv=none; b=HCu//gozGO/Z+sY7CsvHOw6Moa2YnZ47zUhl+gYIadOsdLtesOP/iBF21XtR00rRSD/5Vt2C3BDZR0svRicimjVYbteWiL8nvRRBk5xnTQHeyMQpdFsgI3Y0T/N7gRfij6k70+6WJjEZ1g8L8ZgdQWGhUvvdBjdXFVspKPaK5DI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777940892; c=relaxed/simple; bh=rz0GaQVWFC5Ldv7XCxhQcnrPcxM3OWUNdbw0/XWxahY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=PTwmfPf9eiHhUb/0ADEWhMOrdIaUNctc19H2uuZYSmLsRDjJjuJ9ToXvpN3Ir8jO3nmKjMX6W+VrnM7je7TZ7IBrb3l8gh9xrF2Xt3ogjGZ2r/DqiakW5TelHiD0aYyHi5ncUmVHdFvXRO2QWQ0XxTjFPrb++ybo9StQK/g7cVY= 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=MDa2Dl2c; arc=none smtp.client-ip=74.125.224.45 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="MDa2Dl2c" Received: by mail-yx1-f45.google.com with SMTP id 956f58d0204a3-6530287803cso4668162d50.1 for ; Mon, 04 May 2026 17:28:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777940889; x=1778545689; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=TSp2GUXkgxtGrFcBtn8vEntUxKtdvA3MvOWwc4dLMzU=; b=MDa2Dl2ca6GUYsU2a7xMr0ZWI0GwSUsx99y85UMGJrdr/6fezJxNDssw/37zR49cHV ORLgcwD0xL+9lxuvRmGoGXCAnAer/y8Tu2Fjf51Scpgp5RIBuhTn+Ou/Q8F0pwShjJ6z UnaHXDe9T2eSnyfO1KIHX26/+3VfeZfA8i7MCiJY+lPRrUhsagBE3cNCKSlhJ7jzlIS1 guFPRzm+p18+GD5+ZkB+OzXCk/yy6IkBlDM4tieLvfG0HatfEolLYlQlo6P0DvgtRZvq cnux6lda/RdvmEtsoiBbYh3V++0EEVcc3WHwRFAJlKZRah5IbSNVmXPbAhIqGJyF7OAV eMgg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777940889; x=1778545689; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=TSp2GUXkgxtGrFcBtn8vEntUxKtdvA3MvOWwc4dLMzU=; b=OBkyo/aOkbdMaE5FuEyRqMA7wPDnAxwpQSCKXZmeGyQtoAkcCU3JpPimN3O6emtAos BRh+C3Q28Dh4mnvK6vgg9sCPN2hqB7wFdzOr0i0EbnLjlPPD18hsCUqScOQBfll4iKa9 kE6sv4vDJ5wnnMgN9+mcL/yBU379t99g/IfPCqsYg/7aEn8bONhbMYAnH/53spZydQu5 /GS2D9If59IJIAdYxTnzcDHVaks+cNT7ujRU8IeyRVHoGOqSJ9UMpZuFgrLZfphiKyn1 RtzoSYxdD80Kix8mrJ/ctE23ps58l1AdQmeUyFtkXC96KFp/3Ag/fdyd9MQDSOhjYLUH N0sA== X-Forwarded-Encrypted: i=1; AFNElJ9j7BpPg1vsE1TsdXCoAGu2ldIa/wmEWCLkaa/XgtvURfoPCuKFjBuaYV82WPi5SMacBL0PXFyPQ4Ll/H8=@vger.kernel.org X-Gm-Message-State: AOJu0YwwdyGSjnnetMWGOdNxtq0VAlHLNxGA4lJsmUnw/eUixtPXFJry Pww1vQY/5JbO3CJ1I1N2FY7Ml0pog0qfxu/HKh+0eM60l7h+eXTG4Vzd X-Gm-Gg: AeBDieunz0Cl7l6/cBkZhPop3ENTNjlETyQPwFUsPjhjLOZoSy82CVh5EJ+K1ZMTF5D RVzIVykmuAodZVR34Lu5JmMgj6j8AAJNy2r90a79kaZHyrnK1PveIZrYdl89V9xL/eg4r1ue5PF mjer+zyQEK/tumkxyL1Y8+SmwD5CDVa3c8Y2VZmJqKEDa9bifTZ6iRuajtkJhjlfztJQ7y9is93 d0N0pISbGbFV8ZajjppNGk4efAnqRnhIvjoVdWmcgRBPe3Y8av1H19z3QtnClon2UW/HCF48VY2 TAFdNHbUto9WUIxQDHY6FjH8KN7/AaQAcA1pQ7CR/Ul0OsC+uyEScbP2r89TndkrO2mcyH8JaE7 cx0yuWt/h2x3dwqZvWQUzSLjcp7kLmf2LK1DSa1zAQFubDm+5tDIyB06YvQHrKFiT1FyN2ixHRH zg6Xj1r1DKrXfQA10G+7cYu5NW/TiflUy6/57wHXry X-Received: by 2002:a05:690e:1c08:b0:64e:e896:a86 with SMTP id 956f58d0204a3-65c3db39b1dmr12329280d50.36.1777940888641; Mon, 04 May 2026 17:28:08 -0700 (PDT) Received: from localhost ([2a03:2880:ff:73::]) by smtp.gmail.com with ESMTPSA id 956f58d0204a3-65c2e8ae9c7sm6268726d50.19.2026.05.04.17.28.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 04 May 2026 17:28:08 -0700 (PDT) From: Bobby Eshleman Date: Mon, 04 May 2026 17:27:53 -0700 Subject: [PATCH net-next v2 6/6] selftests: drv-net: add netkit devmem tests 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 Message-Id: <20260504-tcp-dm-netkit-v2-6-56d52ac72fd4@meta.com> References: <20260504-tcp-dm-netkit-v2-0-56d52ac72fd4@meta.com> In-Reply-To: <20260504-tcp-dm-netkit-v2-0-56d52ac72fd4@meta.com> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Jonathan Corbet , Shuah Khan , Alex Shi , Yanteng Si , Dongliang Mu , Michael Chan , Pavan Chebbi , Joshua Washington , Harshitha Ramamurthy , Saeed Mahameed , Tariq Toukan , Mark Bloch , Leon Romanovsky , Alexander Duyck , kernel-team@meta.com, Daniel Borkmann , Nikolay Aleksandrov , Shuah Khan Cc: netdev@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-rdma@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org, Stanislav Fomichev , Mina Almasry , Bobby Eshleman X-Mailer: b4 0.14.3 From: Bobby Eshleman Add nk_devmem.py with four tests for TCP devmem through a netkit device: These tests are just duplicates of the original devmem tests, with some adjusted parameters such as telling ncdevmem to avoid device setup (since it only has access to netkit, not a phys device). Each test uses NetDrvContEnv with primary_rx_redirect=3DTrue to set up the BPF redirect program on the primary netkit interface. Signed-off-by: Bobby Eshleman --- Changes in v2: - Add nk_devmem.py to TEST_PROGS in Makefile (Sashiko) --- tools/testing/selftests/drivers/net/hw/Makefile | 1 + .../testing/selftests/drivers/net/hw/nk_devmem.py | 40 ++++++++++++++++++= ++++ 2 files changed, 41 insertions(+) diff --git a/tools/testing/selftests/drivers/net/hw/Makefile b/tools/testin= g/selftests/drivers/net/hw/Makefile index 85ca4d1ecf9e..2f78c6aec397 100644 --- a/tools/testing/selftests/drivers/net/hw/Makefile +++ b/tools/testing/selftests/drivers/net/hw/Makefile @@ -34,6 +34,7 @@ TEST_PROGS =3D \ irq.py \ loopback.sh \ nic_timestamp.py \ + nk_devmem.py \ nk_netns.py \ nk_qlease.py \ ntuple.py \ diff --git a/tools/testing/selftests/drivers/net/hw/nk_devmem.py b/tools/te= sting/selftests/drivers/net/hw/nk_devmem.py new file mode 100755 index 000000000000..c069d525798b --- /dev/null +++ b/tools/testing/selftests/drivers/net/hw/nk_devmem.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0 +"""Test devmem TCP with netkit.""" + +from os import path +from lib.py import ksft_run, ksft_exit, ksft_disruptive +from lib.py import NetDrvContEnv +from lib.py.devmem import setup_test, run_rx, run_tx, run_tx_chunks, run_r= x_hds + + +@ksft_disruptive +def check_nk_rx(cfg) -> None: + run_rx(cfg) + + +@ksft_disruptive +def check_nk_tx(cfg) -> None: + run_tx(cfg) + + +@ksft_disruptive +def check_nk_tx_chunks(cfg) -> None: + run_tx_chunks(cfg) + + +@ksft_disruptive +def check_nk_rx_hds(cfg) -> None: + run_rx_hds(cfg) + + +def main() -> None: + with NetDrvContEnv(__file__, rxqueues=3D2, primary_rx_redirect=3DTrue)= as cfg: + setup_test(cfg, path.abspath(path.dirname(__file__) + "/ncdevmem")) + ksft_run([check_nk_rx, check_nk_tx, check_nk_tx_chunks, check_nk_r= x_hds], + args=3D(cfg,)) + ksft_exit() + + +if __name__ =3D=3D "__main__": + main() --=20 2.52.0