* [PATCH net-next 0/9] psp: add a kselftest suite and netdevsim implementation.
@ 2025-09-24 19:49 Daniel Zahka
2025-09-24 19:49 ` [PATCH net-next 1/9] netdevsim: a basic test PSP implementation Daniel Zahka
` (8 more replies)
0 siblings, 9 replies; 19+ messages in thread
From: Daniel Zahka @ 2025-09-24 19:49 UTC (permalink / raw)
To: Jakub Kicinski, Andrew Lunn, David S. Miller, Eric Dumazet,
Paolo Abeni, Simon Horman, Shuah Khan
Cc: Willem de Bruijn, Breno Leitao, Petr Machata, Yuyang Huang,
Xiao Liang, Carolina Jubran, Donald Hunter, netdev
Add a basic test suite for drivers that support PSP. Also, add a PSP
implementation in the netdevsim driver.
The netdevsim implementation does encapsulation and decapsulation of
PSP packets, but no crypto.
The tests cover the basic usage of the uapi, and demonstrate key
exchange and connection setup. The tests and netdevsim support IPv4
and IPv6. Here is an example run on a system with a CX7 NIC.
TAP version 13
1..28
ok 1 psp.test_case # SKIP Test requires IPv4 connectivity
ok 2 psp.data_basic_send_v0_ip6
ok 3 psp.test_case # SKIP Test requires IPv4 connectivity
ok 4 psp.data_basic_send_v1_ip6
ok 5 psp.test_case # SKIP Test requires IPv4 connectivity
ok 6 psp.data_basic_send_v2_ip6 # SKIP ('PSP version not supported', 'hdr0-aes-gmac-128')
ok 7 psp.test_case # SKIP Test requires IPv4 connectivity
ok 8 psp.data_basic_send_v3_ip6 # SKIP ('PSP version not supported', 'hdr0-aes-gmac-256')
ok 9 psp.test_case # SKIP Test requires IPv4 connectivity
ok 10 psp.data_mss_adjust_ip6
ok 11 psp.dev_list_devices
ok 12 psp.dev_get_device
ok 13 psp.dev_get_device_bad
ok 14 psp.dev_rotate
ok 15 psp.dev_rotate_spi
ok 16 psp.assoc_basic
ok 17 psp.assoc_bad_dev
ok 18 psp.assoc_sk_only_conn
ok 19 psp.assoc_sk_only_mismatch
ok 20 psp.assoc_sk_only_mismatch_tx
ok 21 psp.assoc_sk_only_unconn
ok 22 psp.assoc_version_mismatch
ok 23 psp.assoc_twice
ok 24 psp.data_send_bad_key
ok 25 psp.data_send_disconnect
ok 26 psp.data_stale_key
ok 27 psp.removal_device_rx # XFAIL Test only works on netdevsim
ok 28 psp.removal_device_bi # XFAIL Test only works on netdevsim
# Totals: pass:19 fail:0 xfail:2 xpass:0 skip:7 error:0
#
# Responder logs (0):
# STDERR:
# Set PSP enable on device 1 to 0x3
# Set PSP enable on device 1 to 0x0
Daniel Zahka (1):
selftests: net: add skip all feature to ksft_run()
Jakub Kicinski (8):
netdevsim: a basic test PSP implementation
selftests: drv-net: base device access API test
selftests: drv-net: add PSP responder
selftests: drv-net: psp: add basic data transfer and key rotation
tests
selftests: drv-net: psp: add association tests
selftests: drv-net: psp: add connection breaking tests
selftests: drv-net: psp: add test for auto-adjusting TCP MSS
selftests: drv-net: psp: add tests for destroying devices
drivers/net/netdevsim/Makefile | 4 +
drivers/net/netdevsim/netdev.c | 56 +-
drivers/net/netdevsim/netdevsim.h | 38 ++
drivers/net/netdevsim/psp.c | 218 +++++++
net/core/skbuff.c | 1 +
.../testing/selftests/drivers/net/.gitignore | 1 +
tools/testing/selftests/drivers/net/Makefile | 10 +
tools/testing/selftests/drivers/net/config | 1 +
.../drivers/net/hw/lib/py/__init__.py | 4 +-
.../selftests/drivers/net/lib/py/__init__.py | 4 +-
.../selftests/drivers/net/lib/py/env.py | 5 +
tools/testing/selftests/drivers/net/psp.py | 609 ++++++++++++++++++
.../selftests/drivers/net/psp_responder.c | 481 ++++++++++++++
.../testing/selftests/net/lib/py/__init__.py | 2 +-
tools/testing/selftests/net/lib/py/ksft.py | 14 +-
tools/testing/selftests/net/lib/py/ynl.py | 5 +
16 files changed, 1439 insertions(+), 14 deletions(-)
create mode 100644 drivers/net/netdevsim/psp.c
create mode 100755 tools/testing/selftests/drivers/net/psp.py
create mode 100644 tools/testing/selftests/drivers/net/psp_responder.c
--
2.47.3
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH net-next 1/9] netdevsim: a basic test PSP implementation
2025-09-24 19:49 [PATCH net-next 0/9] psp: add a kselftest suite and netdevsim implementation Daniel Zahka
@ 2025-09-24 19:49 ` Daniel Zahka
2025-09-25 0:12 ` Jakub Kicinski
` (3 more replies)
2025-09-24 19:49 ` [PATCH net-next 2/9] selftests: net: add skip all feature to ksft_run() Daniel Zahka
` (7 subsequent siblings)
8 siblings, 4 replies; 19+ messages in thread
From: Daniel Zahka @ 2025-09-24 19:49 UTC (permalink / raw)
To: Jakub Kicinski, Andrew Lunn, David S. Miller, Eric Dumazet,
Paolo Abeni, Simon Horman, Shuah Khan
Cc: Willem de Bruijn, Breno Leitao, Petr Machata, Yuyang Huang,
Xiao Liang, Carolina Jubran, Donald Hunter, netdev
From: Jakub Kicinski <kuba@kernel.org>
Provide a PSP implementation for netdevsim.
Use psp_dev_encapsulate() and psp_dev_rcv() to do actual encapsulation
and decapsulation on skbs, but perform no encryption or decryption. In
order to make encryption with a bad key result in a drop on the peer's
rx side, we stash our psd's generation number in the first byte of each
key before handing to the peer.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Co-developed-by: Daniel Zahka <daniel.zahka@gmail.com>
Signed-off-by: Daniel Zahka <daniel.zahka@gmail.com>
---
drivers/net/netdevsim/Makefile | 4 +
drivers/net/netdevsim/netdev.c | 56 ++++++--
drivers/net/netdevsim/netdevsim.h | 38 ++++++
drivers/net/netdevsim/psp.c | 218 ++++++++++++++++++++++++++++++
net/core/skbuff.c | 1 +
5 files changed, 309 insertions(+), 8 deletions(-)
create mode 100644 drivers/net/netdevsim/psp.c
diff --git a/drivers/net/netdevsim/Makefile b/drivers/net/netdevsim/Makefile
index f8de93bc5f5b..14a553e000ec 100644
--- a/drivers/net/netdevsim/Makefile
+++ b/drivers/net/netdevsim/Makefile
@@ -18,6 +18,10 @@ ifneq ($(CONFIG_PSAMPLE),)
netdevsim-objs += psample.o
endif
+ifneq ($(CONFIG_INET_PSP),)
+netdevsim-objs += psp.o
+endif
+
ifneq ($(CONFIG_MACSEC),)
netdevsim-objs += macsec.o
endif
diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c
index 0178219f0db5..1905c95967e0 100644
--- a/drivers/net/netdevsim/netdev.c
+++ b/drivers/net/netdevsim/netdev.c
@@ -103,29 +103,46 @@ static int nsim_napi_rx(struct net_device *tx_dev, struct net_device *rx_dev,
static int nsim_forward_skb(struct net_device *tx_dev,
struct net_device *rx_dev,
struct sk_buff *skb,
- struct nsim_rq *rq)
+ struct nsim_rq *rq,
+ struct skb_ext *psp_ext)
{
- return __dev_forward_skb(rx_dev, skb) ?:
- nsim_napi_rx(tx_dev, rx_dev, rq, skb);
+ int ret;
+
+ ret = __dev_forward_skb(rx_dev, skb);
+ if (ret)
+ return ret;
+
+ if (psp_ext)
+ __skb_ext_set(skb, SKB_EXT_PSP, psp_ext);
+
+ return nsim_napi_rx(tx_dev, rx_dev, rq, skb);
}
static netdev_tx_t nsim_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct netdevsim *ns = netdev_priv(dev);
+ struct skb_ext *psp_ext = NULL;
struct net_device *peer_dev;
unsigned int len = skb->len;
struct netdevsim *peer_ns;
struct netdev_config *cfg;
struct nsim_rq *rq;
int rxq;
+ int dr;
rcu_read_lock();
if (!nsim_ipsec_tx(ns, skb))
- goto out_drop_free;
+ goto out_drop_any;
peer_ns = rcu_dereference(ns->peer);
if (!peer_ns)
- goto out_drop_free;
+ goto out_drop_any;
+
+ if (nsim_tx_skb_is_psp(skb)) {
+ dr = nsim_do_psp(skb, ns, peer_ns, &psp_ext);
+ if (dr)
+ goto out_drop_free;
+ }
peer_dev = peer_ns->netdev;
rxq = skb_get_queue_mapping(skb);
@@ -141,7 +158,8 @@ static netdev_tx_t nsim_start_xmit(struct sk_buff *skb, struct net_device *dev)
skb_linearize(skb);
skb_tx_timestamp(skb);
- if (unlikely(nsim_forward_skb(dev, peer_dev, skb, rq) == NET_RX_DROP))
+ if (unlikely(nsim_forward_skb(dev, peer_dev, skb, rq, psp_ext) ==
+ NET_RX_DROP))
goto out_drop_cnt;
if (!hrtimer_active(&rq->napi_timer))
@@ -151,8 +169,10 @@ static netdev_tx_t nsim_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev_dstats_tx_add(dev, len);
return NETDEV_TX_OK;
+out_drop_any:
+ dr = SKB_DROP_REASON_NOT_SPECIFIED;
out_drop_free:
- dev_kfree_skb(skb);
+ kfree_skb_reason(skb, dr);
out_drop_cnt:
rcu_read_unlock();
dev_dstats_tx_dropped(dev);
@@ -1002,6 +1022,7 @@ static void nsim_queue_uninit(struct netdevsim *ns)
static int nsim_init_netdevsim(struct netdevsim *ns)
{
+ struct netdevsim *peer;
struct mock_phc *phc;
int err;
@@ -1039,12 +1060,29 @@ static int nsim_init_netdevsim(struct netdevsim *ns)
if (IS_ENABLED(CONFIG_DEBUG_NET)) {
ns->nb.notifier_call = netdev_debug_event;
if (register_netdevice_notifier_dev_net(ns->netdev, &ns->nb,
- &ns->nn))
+ &ns->nn)){
ns->nb.notifier_call = NULL;
+ goto err_unregister_netdev;
+ }
}
+ err = nsim_psp_init(ns);
+ if (err)
+ goto err_unregister_notifier;
+
return 0;
+err_unregister_notifier:
+ if (ns->nb.notifier_call)
+ unregister_netdevice_notifier_dev_net(ns->netdev, &ns->nb,
+ &ns->nn);
+err_unregister_netdev:
+ rtnl_lock();
+ peer = rtnl_dereference(ns->peer);
+ if (peer)
+ RCU_INIT_POINTER(peer->peer, NULL);
+ RCU_INIT_POINTER(ns->peer, NULL);
+ unregister_netdevice(ns->netdev);
err_ipsec_teardown:
nsim_ipsec_teardown(ns);
nsim_macsec_teardown(ns);
@@ -1128,6 +1166,8 @@ void nsim_destroy(struct netdevsim *ns)
debugfs_remove(ns->qr_dfs);
debugfs_remove(ns->pp_dfs);
+ nsim_psp_uninit(ns);
+
if (ns->nb.notifier_call)
unregister_netdevice_notifier_dev_net(ns->netdev, &ns->nb,
&ns->nn);
diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h
index bddd24c1389d..60aafcf67f65 100644
--- a/drivers/net/netdevsim/netdevsim.h
+++ b/drivers/net/netdevsim/netdevsim.h
@@ -23,6 +23,7 @@
#include <linux/ptp_mock.h>
#include <linux/u64_stats_sync.h>
#include <net/devlink.h>
+#include <net/psp.h>
#include <net/udp_tunnel.h>
#include <net/xdp.h>
#include <net/macsec.h>
@@ -108,6 +109,12 @@ struct netdevsim {
int rq_reset_mode;
+ struct {
+ struct psp_dev *dev;
+ u32 spi;
+ u32 assoc_cnt;
+ } psp;
+
struct nsim_bus_dev *nsim_bus_dev;
struct bpf_prog *bpf_offloaded;
@@ -421,6 +428,37 @@ static inline void nsim_macsec_teardown(struct netdevsim *ns)
}
#endif
+#if IS_ENABLED(CONFIG_INET_PSP)
+int nsim_psp_init(struct netdevsim *ns);
+void nsim_psp_uninit(struct netdevsim *ns);
+enum skb_drop_reason
+nsim_do_psp(struct sk_buff *skb, struct netdevsim *ns,
+ struct netdevsim *peer_ns, struct skb_ext **psp_ext);
+static inline bool nsim_tx_skb_is_psp(struct sk_buff *skb)
+{
+ bool ret;
+
+ rcu_read_lock();
+ ret = !!psp_skb_get_assoc_rcu(skb);
+ rcu_read_unlock();
+ return ret;
+}
+#else
+static inline int nsim_psp_init(struct netdevsim *ns) { return 0; }
+static inline void nsim_psp_uninit(struct netdevsim *ns) {}
+static inline enum skb_drop_reason
+nsim_do_psp(struct sk_buff *skb, struct netdevsim *ns,
+ struct netdevsim *peer_ns, struct skb_ext **psp_ext)
+{
+ return 0;
+}
+
+static inline bool nsim_tx_skb_is_psp(struct sk_buff *skb)
+{
+ return false;
+}
+#endif
+
struct nsim_bus_dev {
struct device dev;
struct list_head list;
diff --git a/drivers/net/netdevsim/psp.c b/drivers/net/netdevsim/psp.c
new file mode 100644
index 000000000000..cb568f89eb3e
--- /dev/null
+++ b/drivers/net/netdevsim/psp.c
@@ -0,0 +1,218 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#include <linux/ip.h>
+#include <linux/skbuff.h>
+#include <net/ip6_checksum.h>
+#include <net/psp.h>
+#include <net/sock.h>
+
+#include "netdevsim.h"
+
+enum skb_drop_reason
+nsim_do_psp(struct sk_buff *skb, struct netdevsim *ns,
+ struct netdevsim *peer_ns, struct skb_ext **psp_ext)
+{
+ struct net *net = sock_net(skb->sk);
+ enum skb_drop_reason rc = 0;
+ struct psp_assoc *pas;
+ void **ptr;
+
+ rcu_read_lock();
+ pas = psp_skb_get_assoc_rcu(skb);
+ if (!pas) {
+ rc = SKB_DROP_REASON_PSP_OUTPUT;
+ goto out_unlock;
+ }
+
+ if (!skb_transport_header_was_set(skb)) {
+ rc = SKB_DROP_REASON_PSP_OUTPUT;
+ goto out_unlock;
+ }
+
+ ptr = psp_assoc_drv_data(pas);
+ if (*ptr != ns) {
+ rc = SKB_DROP_REASON_PSP_OUTPUT;
+ goto out_unlock;
+ }
+
+ if (!psp_dev_encapsulate(net, skb, pas->tx.spi, pas->version, 0)) {
+ rc = SKB_DROP_REASON_PSP_OUTPUT;
+ goto out_unlock;
+ }
+
+ /* Now pretend we just received this frame */
+ if (peer_ns->psp.dev->config.versions & (1 << pas->version)) {
+ bool strip_icv = false;
+ u8 generation;
+
+ /* We cheat a bit and put the generation in the key.
+ * In real life if generation was too old, then decryption would
+ * fail. Here, we just make it so a bad key causes a bad
+ * generation too, and psp_sk_rx_policy_check() will fail.
+ */
+ generation = pas->tx.key[0];
+
+ skb_ext_reset(skb);
+ skb->mac_len = ETH_HLEN;
+ if (psp_dev_rcv(skb, peer_ns->psp.dev->id, generation,
+ strip_icv)) {
+ rc = SKB_DROP_REASON_PSP_OUTPUT;
+ goto out_unlock;
+ }
+
+ *psp_ext = skb->extensions;
+ refcount_inc(&(*psp_ext)->refcnt);
+ skb->decrypted = 1;
+ } else {
+ struct ipv6hdr *ip6h;
+ struct iphdr *iph;
+ struct udphdr *uh;
+ __wsum csum;
+
+ /* Do not decapsulate. Receive the skb with the udp and psp
+ * headers still there as if this is a normal udp packet.
+ * psp_dev_encapsulate() sets udp checksum to 0, so we need to
+ * provide a valid checksum here, so the skb isn't dropped.
+ */
+ uh = udp_hdr(skb);
+ csum = skb_checksum(skb, skb_transport_offset(skb),
+ ntohs(uh->len), 0);
+
+ switch (skb->protocol) {
+ case htons(ETH_P_IP):
+ iph = ip_hdr(skb);
+ uh->check = udp_v4_check(ntohs(uh->len), iph->saddr,
+ iph->daddr, csum);
+ break;
+#if IS_ENABLED(CONFIG_IPV6)
+ case htons(ETH_P_IPV6):
+ ip6h = ipv6_hdr(skb);
+ uh->check = udp_v6_check(ntohs(uh->len), &ip6h->saddr,
+ &ip6h->daddr, csum);
+ break;
+#endif
+ }
+
+ uh->check = uh->check ?: CSUM_MANGLED_0;
+ skb->ip_summed = CHECKSUM_NONE;
+ }
+
+out_unlock:
+ rcu_read_unlock();
+ return rc;
+}
+
+static int
+nsim_psp_set_config(struct psp_dev *psd, struct psp_dev_config *conf,
+ struct netlink_ext_ack *extack)
+{
+ return 0;
+}
+
+static int
+nsim_rx_spi_alloc(struct psp_dev *psd, u32 version,
+ struct psp_key_parsed *assoc,
+ struct netlink_ext_ack *extack)
+{
+ struct netdevsim *ns = psd->drv_priv;
+ unsigned int new;
+ int i;
+
+ new = ++ns->psp.spi & PSP_SPI_KEY_ID;
+ if (psd->generation & 1)
+ new |= PSP_SPI_KEY_PHASE;
+
+ assoc->spi = cpu_to_be32(new);
+ assoc->key[0] = psd->generation;
+ for (i = 1; i < PSP_MAX_KEY; i++)
+ assoc->key[i] = ns->psp.spi + i;
+
+ return 0;
+}
+
+static int nsim_assoc_add(struct psp_dev *psd, struct psp_assoc *pas,
+ struct netlink_ext_ack *extack)
+{
+ struct netdevsim *ns = psd->drv_priv;
+ void **ptr = psp_assoc_drv_data(pas);
+
+ /* Copy drv_priv from psd to assoc */
+ *ptr = psd->drv_priv;
+ ns->psp.assoc_cnt++;
+
+ return 0;
+}
+
+static int nsim_key_rotate(struct psp_dev *psd, struct netlink_ext_ack *extack)
+{
+ return 0;
+}
+
+static void nsim_assoc_del(struct psp_dev *psd, struct psp_assoc *pas)
+{
+ struct netdevsim *ns = psd->drv_priv;
+ void **ptr = psp_assoc_drv_data(pas);
+
+ *ptr = NULL;
+ ns->psp.assoc_cnt--;
+}
+
+static struct psp_dev_ops nsim_psp_ops = {
+ .set_config = nsim_psp_set_config,
+ .rx_spi_alloc = nsim_rx_spi_alloc,
+ .tx_key_add = nsim_assoc_add,
+ .tx_key_del = nsim_assoc_del,
+ .key_rotate = nsim_key_rotate,
+};
+
+static struct psp_dev_caps nsim_psp_caps = {
+ .versions = 1 << PSP_VERSION_HDR0_AES_GCM_128 |
+ 1 << PSP_VERSION_HDR0_AES_GMAC_128 |
+ 1 << PSP_VERSION_HDR0_AES_GCM_256 |
+ 1 << PSP_VERSION_HDR0_AES_GMAC_256,
+ .assoc_drv_spc = sizeof(void *),
+};
+
+void nsim_psp_uninit(struct netdevsim *ns)
+{
+ if (!IS_ERR(ns->psp.dev))
+ psp_dev_unregister(ns->psp.dev);
+ WARN_ON(ns->psp.assoc_cnt);
+}
+
+static ssize_t
+nsim_psp_rereg_write(struct file *file, const char __user *data, size_t count,
+ loff_t *ppos)
+{
+ struct netdevsim *ns = file->private_data;
+ int err;
+
+ nsim_psp_uninit(ns);
+
+ ns->psp.dev = psp_dev_create(ns->netdev, &nsim_psp_ops,
+ &nsim_psp_caps, ns);
+ err = PTR_ERR_OR_ZERO(ns->psp.dev);
+ return err ?: count;
+}
+
+static const struct file_operations nsim_psp_rereg_fops = {
+ .open = simple_open,
+ .write = nsim_psp_rereg_write,
+ .llseek = generic_file_llseek,
+ .owner = THIS_MODULE,
+};
+
+int nsim_psp_init(struct netdevsim *ns)
+{
+ struct dentry *ddir = ns->nsim_dev_port->ddir;
+ int err;
+
+ ns->psp.dev = psp_dev_create(ns->netdev, &nsim_psp_ops,
+ &nsim_psp_caps, ns);
+ err = PTR_ERR_OR_ZERO(ns->psp.dev);
+ if (err)
+ return err;
+
+ debugfs_create_file("psp_rereg", 0200, ddir, ns, &nsim_psp_rereg_fops);
+ return 0;
+}
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index d331e607edfb..07a655056bda 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -7048,6 +7048,7 @@ void *__skb_ext_set(struct sk_buff *skb, enum skb_ext_id id,
skb->active_extensions = 1 << id;
return skb_ext_get_ptr(ext, id);
}
+EXPORT_SYMBOL_NS_GPL(__skb_ext_set, "NETDEV_INTERNAL");
/**
* skb_ext_add - allocate space for given extension, COW if needed
--
2.47.3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH net-next 2/9] selftests: net: add skip all feature to ksft_run()
2025-09-24 19:49 [PATCH net-next 0/9] psp: add a kselftest suite and netdevsim implementation Daniel Zahka
2025-09-24 19:49 ` [PATCH net-next 1/9] netdevsim: a basic test PSP implementation Daniel Zahka
@ 2025-09-24 19:49 ` Daniel Zahka
2025-09-25 16:09 ` Petr Machata
2025-09-24 19:49 ` [PATCH net-next 3/9] selftests: drv-net: base device access API test Daniel Zahka
` (6 subsequent siblings)
8 siblings, 1 reply; 19+ messages in thread
From: Daniel Zahka @ 2025-09-24 19:49 UTC (permalink / raw)
To: Jakub Kicinski, Andrew Lunn, David S. Miller, Eric Dumazet,
Paolo Abeni, Simon Horman, Shuah Khan
Cc: Willem de Bruijn, Breno Leitao, Petr Machata, Yuyang Huang,
Xiao Liang, Carolina Jubran, Donald Hunter, netdev
When there is an entire test suite where each test case depends upon
some feature, e.g., psp, it is easier to state the least common
denominator of dpendencies up front, rather than doing:
cfg.require_psp()
at the start of each test.
Signed-off-by: Daniel Zahka <daniel.zahka@gmail.com>
---
tools/testing/selftests/net/lib/py/ksft.py | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/net/lib/py/ksft.py b/tools/testing/selftests/net/lib/py/ksft.py
index 8e35ed12ed9e..375020d3edf2 100644
--- a/tools/testing/selftests/net/lib/py/ksft.py
+++ b/tools/testing/selftests/net/lib/py/ksft.py
@@ -210,7 +210,7 @@ def _ksft_intr(signum, frame):
ksft_pr(f"Ignoring SIGTERM (cnt: {term_cnt}), already exiting...")
-def ksft_run(cases=None, globs=None, case_pfx=None, args=()):
+def ksft_run(cases=None, globs=None, case_pfx=None, args=(), skip_all=None):
cases = cases or []
if globs and case_pfx:
@@ -241,6 +241,8 @@ def ksft_run(cases=None, globs=None, case_pfx=None, args=()):
cnt_key = ""
try:
+ if skip_all:
+ raise KsftSkipEx()
case(*args)
except KsftSkipEx as e:
comment = "SKIP " + str(e)
--
2.47.3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH net-next 3/9] selftests: drv-net: base device access API test
2025-09-24 19:49 [PATCH net-next 0/9] psp: add a kselftest suite and netdevsim implementation Daniel Zahka
2025-09-24 19:49 ` [PATCH net-next 1/9] netdevsim: a basic test PSP implementation Daniel Zahka
2025-09-24 19:49 ` [PATCH net-next 2/9] selftests: net: add skip all feature to ksft_run() Daniel Zahka
@ 2025-09-24 19:49 ` Daniel Zahka
2025-09-25 0:13 ` Jakub Kicinski
2025-09-24 19:49 ` [PATCH net-next 4/9] selftests: drv-net: add PSP responder Daniel Zahka
` (5 subsequent siblings)
8 siblings, 1 reply; 19+ messages in thread
From: Daniel Zahka @ 2025-09-24 19:49 UTC (permalink / raw)
To: Jakub Kicinski, Andrew Lunn, David S. Miller, Eric Dumazet,
Paolo Abeni, Simon Horman, Shuah Khan
Cc: Willem de Bruijn, Breno Leitao, Petr Machata, Yuyang Huang,
Xiao Liang, Carolina Jubran, Donald Hunter, netdev
From: Jakub Kicinski <kuba@kernel.org>
Simple PSP test to getting info about PSP devices.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Daniel Zahka <daniel.zahka@gmail.com>
---
tools/testing/selftests/drivers/net/Makefile | 1 +
tools/testing/selftests/drivers/net/config | 1 +
.../drivers/net/hw/lib/py/__init__.py | 2 +-
.../selftests/drivers/net/lib/py/__init__.py | 2 +-
tools/testing/selftests/drivers/net/psp.py | 68 +++++++++++++++++++
.../testing/selftests/net/lib/py/__init__.py | 2 +-
tools/testing/selftests/net/lib/py/ynl.py | 5 ++
7 files changed, 78 insertions(+), 3 deletions(-)
create mode 100755 tools/testing/selftests/drivers/net/psp.py
diff --git a/tools/testing/selftests/drivers/net/Makefile b/tools/testing/selftests/drivers/net/Makefile
index 984ece05f7f9..102cfb36846c 100644
--- a/tools/testing/selftests/drivers/net/Makefile
+++ b/tools/testing/selftests/drivers/net/Makefile
@@ -19,6 +19,7 @@ TEST_PROGS := \
netcons_sysdata.sh \
netpoll_basic.py \
ping.py \
+ psp.py \
queues.py \
stats.py \
shaper.py \
diff --git a/tools/testing/selftests/drivers/net/config b/tools/testing/selftests/drivers/net/config
index f27172ddee0a..ac13da8847ca 100644
--- a/tools/testing/selftests/drivers/net/config
+++ b/tools/testing/selftests/drivers/net/config
@@ -5,3 +5,4 @@ CONFIG_NETCONSOLE=m
CONFIG_NETCONSOLE_DYNAMIC=y
CONFIG_NETCONSOLE_EXTENDED_LOG=y
CONFIG_XDP_SOCKETS=y
+CONFIG_INET_PSP=y
diff --git a/tools/testing/selftests/drivers/net/hw/lib/py/__init__.py b/tools/testing/selftests/drivers/net/hw/lib/py/__init__.py
index 1462a339a74b..559c572e296a 100644
--- a/tools/testing/selftests/drivers/net/hw/lib/py/__init__.py
+++ b/tools/testing/selftests/drivers/net/hw/lib/py/__init__.py
@@ -13,7 +13,7 @@ try:
# Import one by one to avoid pylint false positives
from net.lib.py import EthtoolFamily, NetdevFamily, NetshaperFamily, \
- NlError, RtnlFamily, DevlinkFamily
+ NlError, RtnlFamily, DevlinkFamily, PSPFamily
from net.lib.py import CmdExitFailure
from net.lib.py import bkg, cmd, defer, ethtool, fd_read_timeout, ip, \
rand_port, tool, wait_port_listen
diff --git a/tools/testing/selftests/drivers/net/lib/py/__init__.py b/tools/testing/selftests/drivers/net/lib/py/__init__.py
index a07b56a75c8a..31ecc618050c 100644
--- a/tools/testing/selftests/drivers/net/lib/py/__init__.py
+++ b/tools/testing/selftests/drivers/net/lib/py/__init__.py
@@ -12,7 +12,7 @@ try:
# Import one by one to avoid pylint false positives
from net.lib.py import EthtoolFamily, NetdevFamily, NetshaperFamily, \
- NlError, RtnlFamily, DevlinkFamily
+ NlError, RtnlFamily, DevlinkFamily, PSPFamily
from net.lib.py import CmdExitFailure
from net.lib.py import bkg, cmd, bpftool, bpftrace, defer, ethtool, \
fd_read_timeout, ip, rand_port, tool, wait_port_listen, wait_file
diff --git a/tools/testing/selftests/drivers/net/psp.py b/tools/testing/selftests/drivers/net/psp.py
new file mode 100755
index 000000000000..965e456836d2
--- /dev/null
+++ b/tools/testing/selftests/drivers/net/psp.py
@@ -0,0 +1,68 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0
+
+"""Test suite for PSP capable drivers."""
+
+from lib.py import ksft_run, ksft_exit
+from lib.py import ksft_true, ksft_eq
+from lib.py import NetDrvEpEnv, PSPFamily, NlError
+
+#
+# Test cases
+#
+
+def dev_list_devices(cfg):
+ """ Dump all devices """
+ devices = cfg.pspnl.dev_get({}, dump=True)
+
+ found = False
+ for dev in devices:
+ found |= dev['id'] == cfg.psp_dev_id
+ ksft_true(found)
+
+
+def dev_get_device(cfg):
+ """ Get the device we intend to use """
+ dev = cfg.pspnl.dev_get({'id': cfg.psp_dev_id})
+ ksft_eq(dev['id'], cfg.psp_dev_id)
+
+
+def dev_get_device_bad(cfg):
+ """ Test getting device which doesn't exist """
+ raised = False
+ try:
+ cfg.pspnl.dev_get({'id': cfg.psp_dev_id + 1234567})
+ except NlError as e:
+ ksft_eq(e.nl_msg.error, -19)
+ raised = True
+ ksft_true(raised)
+
+
+def main() -> None:
+ with NetDrvEpEnv(__file__) as cfg:
+ cfg.pspnl = PSPFamily()
+
+ # Figure out which local device we are testing against
+ cfg.psp_dev_id = None
+ versions = None
+ devs = [dev for dev in cfg.pspnl.dev_get({}, dump=True) if dev["ifindex"] == cfg.ifindex]
+ if devs:
+ info = devs[0]
+ cfg.psp_dev_id = info['id']
+
+ # Enable PSP if necessary
+ if info['psp-versions-ena'] != info['psp-versions-cap']:
+ versions = info['psp-versions-ena']
+ cfg.pspnl.dev_set({"id": cfg.psp_dev_id,
+ "psp-versions-ena": info['psp-versions-cap']})
+
+ ksft_run(globs=globals(), case_pfx={"dev_"},
+ args=(cfg, ), skip_all=(cfg.psp_dev_id is None))
+
+ if versions is not None:
+ cfg.pspnl.dev_set({"id": cfg.psp_dev_id, "psp-versions-ena": versions})
+ ksft_exit()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/tools/testing/selftests/net/lib/py/__init__.py b/tools/testing/selftests/net/lib/py/__init__.py
index 02be28dcc089..997b85cc216a 100644
--- a/tools/testing/selftests/net/lib/py/__init__.py
+++ b/tools/testing/selftests/net/lib/py/__init__.py
@@ -6,4 +6,4 @@ from .netns import NetNS, NetNSEnter
from .nsim import *
from .utils import *
from .ynl import NlError, YnlFamily, EthtoolFamily, NetdevFamily, RtnlFamily, RtnlAddrFamily
-from .ynl import NetshaperFamily, DevlinkFamily
+from .ynl import NetshaperFamily, DevlinkFamily, PSPFamily
diff --git a/tools/testing/selftests/net/lib/py/ynl.py b/tools/testing/selftests/net/lib/py/ynl.py
index 2b3a61ea3bfa..32c223e93b2c 100644
--- a/tools/testing/selftests/net/lib/py/ynl.py
+++ b/tools/testing/selftests/net/lib/py/ynl.py
@@ -61,3 +61,8 @@ class DevlinkFamily(YnlFamily):
def __init__(self, recv_size=0):
super().__init__((SPEC_PATH / Path('devlink.yaml')).as_posix(),
schema='', recv_size=recv_size)
+
+class PSPFamily(YnlFamily):
+ def __init__(self, recv_size=0):
+ super().__init__((SPEC_PATH / Path('psp.yaml')).as_posix(),
+ schema='', recv_size=recv_size)
--
2.47.3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH net-next 4/9] selftests: drv-net: add PSP responder
2025-09-24 19:49 [PATCH net-next 0/9] psp: add a kselftest suite and netdevsim implementation Daniel Zahka
` (2 preceding siblings ...)
2025-09-24 19:49 ` [PATCH net-next 3/9] selftests: drv-net: base device access API test Daniel Zahka
@ 2025-09-24 19:49 ` Daniel Zahka
2025-09-24 19:49 ` [PATCH net-next 5/9] selftests: drv-net: psp: add basic data transfer and key rotation tests Daniel Zahka
` (4 subsequent siblings)
8 siblings, 0 replies; 19+ messages in thread
From: Daniel Zahka @ 2025-09-24 19:49 UTC (permalink / raw)
To: Jakub Kicinski, Andrew Lunn, David S. Miller, Eric Dumazet,
Paolo Abeni, Simon Horman, Shuah Khan
Cc: Willem de Bruijn, Breno Leitao, Petr Machata, Yuyang Huang,
Xiao Liang, Carolina Jubran, Donald Hunter, netdev
From: Jakub Kicinski <kuba@kernel.org>
PSP tests need the remote system to support PSP, and some PSP capable
application to exchange data with. Create a simple PSP responder app
which we can build and deploy to the remote host. The tests themselves
can be written in Python but for ease of deploying the responder is in C
(using C YNL).
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Daniel Zahka <daniel.zahka@gmail.com>
---
.../testing/selftests/drivers/net/.gitignore | 1 +
tools/testing/selftests/drivers/net/Makefile | 9 +
.../selftests/drivers/net/psp_responder.c | 481 ++++++++++++++++++
3 files changed, 491 insertions(+)
create mode 100644 tools/testing/selftests/drivers/net/psp_responder.c
diff --git a/tools/testing/selftests/drivers/net/.gitignore b/tools/testing/selftests/drivers/net/.gitignore
index d634d8395d90..585ecb4d5dc4 100644
--- a/tools/testing/selftests/drivers/net/.gitignore
+++ b/tools/testing/selftests/drivers/net/.gitignore
@@ -1,2 +1,3 @@
# SPDX-License-Identifier: GPL-2.0-only
napi_id_helper
+psp_responder
diff --git a/tools/testing/selftests/drivers/net/Makefile b/tools/testing/selftests/drivers/net/Makefile
index 102cfb36846c..bd3af9a34e2f 100644
--- a/tools/testing/selftests/drivers/net/Makefile
+++ b/tools/testing/selftests/drivers/net/Makefile
@@ -27,4 +27,13 @@ TEST_PROGS := \
xdp.py \
# end of TEST_PROGS
+# YNL files, must be before "include ..lib.mk"
+YNL_GEN_FILES := psp_responder
+TEST_GEN_FILES += $(YNL_GEN_FILES)
+
include ../../lib.mk
+
+# YNL build
+YNL_GENS := psp
+
+include ../../net/ynl.mk
diff --git a/tools/testing/selftests/drivers/net/psp_responder.c b/tools/testing/selftests/drivers/net/psp_responder.c
new file mode 100644
index 000000000000..e54b6fcec9a1
--- /dev/null
+++ b/tools/testing/selftests/drivers/net/psp_responder.c
@@ -0,0 +1,481 @@
+#include <stdio.h>
+#include <string.h>
+#include <sys/poll.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <unistd.h>
+
+#include <ynl.h>
+
+#include "psp-user.h"
+
+#define dbg(msg...) \
+do { \
+ if (opts->verbose) \
+ fprintf(stderr, "DEBUG: " msg); \
+} while (0)
+
+static bool should_quit;
+
+struct opts {
+ int port;
+ int devid;
+ bool verbose;
+};
+
+enum accept_cfg {
+ ACCEPT_CFG_NONE = 0,
+ ACCEPT_CFG_CLEAR,
+ ACCEPT_CFG_PSP,
+};
+
+static struct {
+ unsigned char tx;
+ unsigned char rx;
+} psp_vers;
+
+static int conn_setup_psp(struct ynl_sock *ys, struct opts *opts, int data_sock)
+{
+ struct psp_rx_assoc_rsp *rsp;
+ struct psp_rx_assoc_req *req;
+ struct psp_tx_assoc_rsp *tsp;
+ struct psp_tx_assoc_req *teq;
+ char info[300];
+ int key_len;
+ ssize_t sz;
+ __u32 spi;
+
+ dbg("create PSP connection\n");
+
+ // Rx assoc alloc
+ req = psp_rx_assoc_req_alloc();
+
+ psp_rx_assoc_req_set_sock_fd(req, data_sock);
+ psp_rx_assoc_req_set_version(req, psp_vers.rx);
+
+ rsp = psp_rx_assoc(ys, req);
+ psp_rx_assoc_req_free(req);
+
+ if (!rsp) {
+ perror("ERROR: failed to Rx assoc");
+ return -1;
+ }
+
+ // SPI exchange
+ key_len = rsp->rx_key._len.key;
+ memcpy(info, &rsp->rx_key.spi, sizeof(spi));
+ memcpy(&info[sizeof(spi)], rsp->rx_key.key, key_len);
+ sz = sizeof(spi) + key_len;
+
+ send(data_sock, info, sz, MSG_WAITALL);
+ psp_rx_assoc_rsp_free(rsp);
+
+ sz = recv(data_sock, info, sz, MSG_WAITALL);
+ if (sz < 0) {
+ perror("ERROR: failed to read PSP key from sock");
+ return -1;
+ }
+ memcpy(&spi, info, sizeof(spi));
+
+ // Setup Tx assoc
+ teq = psp_tx_assoc_req_alloc();
+
+ psp_tx_assoc_req_set_sock_fd(teq, data_sock);
+ psp_tx_assoc_req_set_version(teq, psp_vers.tx);
+ psp_tx_assoc_req_set_tx_key_spi(teq, spi);
+ psp_tx_assoc_req_set_tx_key_key(teq, &info[sizeof(spi)], key_len);
+
+ tsp = psp_tx_assoc(ys, teq);
+ psp_tx_assoc_req_free(teq);
+ if (!tsp) {
+ perror("ERROR: failed to Tx assoc");
+ return -1;
+ }
+ psp_tx_assoc_rsp_free(tsp);
+
+ return 0;
+}
+
+static void send_ack(int sock)
+{
+ send(sock, "ack", 4, MSG_WAITALL);
+}
+
+static void send_err(int sock)
+{
+ send(sock, "err", 4, MSG_WAITALL);
+}
+
+static void send_str(int sock, int value)
+{
+ char buf[128];
+ int ret;
+
+ ret = snprintf(buf, sizeof(buf), "%d", value);
+ send(sock, buf, ret + 1, MSG_WAITALL);
+}
+
+static void
+run_session(struct ynl_sock *ys, struct opts *opts,
+ int server_sock, int comm_sock)
+{
+ enum accept_cfg accept_cfg = ACCEPT_CFG_NONE;
+ struct pollfd pfds[3];
+ size_t data_read = 0;
+ int data_sock = -1;
+
+ while (true) {
+ bool race_close = false;
+ int nfds;
+
+ memset(pfds, 0, sizeof(pfds));
+
+ pfds[0].fd = server_sock;
+ pfds[0].events = POLLIN;
+
+ pfds[1].fd = comm_sock;
+ pfds[1].events = POLLIN;
+
+ nfds = 2;
+ if (data_sock >= 0) {
+ pfds[2].fd = data_sock;
+ pfds[2].events = POLLIN;
+ nfds++;
+ }
+
+ dbg(" ...\n");
+ if (poll(pfds, nfds, -1) < 0) {
+ perror("poll");
+ break;
+ }
+
+ /* data sock */
+ if (pfds[2].revents & POLLIN) {
+ char buf[8192];
+ ssize_t n;
+
+ n = recv(data_sock, buf, sizeof(buf), 0);
+ if (n <= 0) {
+ if (n < 0)
+ perror("data read");
+ close(data_sock);
+ data_sock = -1;
+ dbg("data sock closed\n");
+ } else {
+ data_read += n;
+ dbg("data read %zd\n", data_read);
+ }
+ }
+
+ /* comm sock */
+ if (pfds[1].revents & POLLIN) {
+ static char buf[4096];
+ static ssize_t off;
+ bool consumed;
+ ssize_t n;
+
+ n = recv(comm_sock, &buf[off], sizeof(buf) - off, 0);
+ if (n <= 0) {
+ if (n < 0)
+ perror("comm read");
+ return;
+ }
+
+ off += n;
+ n = off;
+
+#define __consume(sz) \
+ ({ \
+ if (n == (sz)) { \
+ off = 0; \
+ } else { \
+ off -= (sz); \
+ memmove(buf, &buf[(sz)], off); \
+ } \
+ })
+
+#define cmd(_name) \
+ ({ \
+ ssize_t sz = sizeof(_name); \
+ bool match = n >= sz && !memcmp(buf, _name, sz); \
+ \
+ if (match) { \
+ dbg("command: " _name "\n"); \
+ __consume(sz); \
+ } \
+ consumed |= match; \
+ match; \
+ })
+
+ do {
+ consumed = false;
+
+ if (cmd("read len"))
+ send_str(comm_sock, data_read);
+
+ if (cmd("data echo")) {
+ if (data_sock >= 0)
+ send(data_sock, "echo", 5,
+ MSG_WAITALL);
+ else
+ fprintf(stderr, "WARN: echo but no data sock\n");
+ send_ack(comm_sock);
+ }
+ if (cmd("data close")) {
+ if (data_sock >= 0) {
+ close(data_sock);
+ data_sock = -1;
+ send_ack(comm_sock);
+ } else {
+ race_close = true;
+ }
+ }
+ if (cmd("conn psp")) {
+ if (accept_cfg != ACCEPT_CFG_NONE)
+ fprintf(stderr, "WARN: old conn config still set!\n");
+ accept_cfg = ACCEPT_CFG_PSP;
+ send_ack(comm_sock);
+ /* next two bytes are versions */
+ if (off >= 2) {
+ memcpy(&psp_vers, buf, 2);
+ __consume(2);
+ } else {
+ fprintf(stderr, "WARN: short conn psp command!\n");
+ }
+ }
+ if (cmd("conn clr")) {
+ if (accept_cfg != ACCEPT_CFG_NONE)
+ fprintf(stderr, "WARN: old conn config still set!\n");
+ accept_cfg = ACCEPT_CFG_CLEAR;
+ send_ack(comm_sock);
+ }
+ if (cmd("exit"))
+ should_quit = true;
+#undef cmd
+
+ if (!consumed) {
+ fprintf(stderr, "WARN: unknown cmd: [%zd] %s\n",
+ off, buf);
+ }
+ } while (consumed && off);
+ }
+
+ /* server sock */
+ if (pfds[0].revents & POLLIN) {
+ if (data_sock >= 0) {
+ fprintf(stderr, "WARN: new data sock but old one still here\n");
+ close(data_sock);
+ data_sock = -1;
+ }
+ data_sock = accept(server_sock, NULL, NULL);
+ if (data_sock < 0) {
+ perror("accept");
+ continue;
+ }
+ data_read = 0;
+
+ if (accept_cfg == ACCEPT_CFG_CLEAR) {
+ dbg("new data sock: clear\n");
+ /* nothing to do */
+ } else if (accept_cfg == ACCEPT_CFG_PSP) {
+ dbg("new data sock: psp\n");
+ conn_setup_psp(ys, opts, data_sock);
+ } else {
+ fprintf(stderr, "WARN: new data sock but no config\n");
+ }
+ accept_cfg = ACCEPT_CFG_NONE;
+ }
+
+ if (race_close) {
+ if (data_sock >= 0) {
+ /* indeed, ordering problem, handle the close */
+ close(data_sock);
+ data_sock = -1;
+ send_ack(comm_sock);
+ } else {
+ fprintf(stderr, "WARN: close but no data sock\n");
+ send_err(comm_sock);
+ }
+ }
+ }
+ dbg("session ending\n");
+}
+
+static int spawn_server(struct opts *opts)
+{
+ struct sockaddr_in6 addr;
+ int fd;
+
+ fd = socket(AF_INET6, SOCK_STREAM, 0);
+ if (fd < 0) {
+ perror("can't open socket");
+ return -1;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+
+ addr.sin6_family = AF_INET6;
+ addr.sin6_addr = in6addr_any;
+ addr.sin6_port = htons(opts->port);
+
+ if (bind(fd, (struct sockaddr *)&addr, sizeof(addr))) {
+ perror("can't bind socket");
+ return -1;
+ }
+
+ if (listen(fd, 5)) {
+ perror("can't listen");
+ return -1;
+ }
+
+ return fd;
+}
+
+static int run_responder(struct ynl_sock *ys, struct opts *opts)
+{
+ int server_sock, comm;
+
+ server_sock = spawn_server(opts);
+ if (server_sock < 0)
+ return 4;
+
+ while (!should_quit) {
+ comm = accept(server_sock, NULL, NULL);
+ if (comm < 0) {
+ perror("accept failed");
+ } else {
+ run_session(ys, opts, server_sock, comm);
+ close(comm);
+ }
+ }
+
+ return 0;
+}
+
+static void usage(const char *name, const char *miss)
+{
+ if (miss)
+ fprintf(stderr, "Missing argument: %s\n", miss);
+
+ fprintf(stderr, "Usage: %s -p port [-v] [-d psp-dev-id]\n", name);
+ exit(EXIT_FAILURE);
+}
+
+static void parse_cmd_opts(int argc, char **argv, struct opts *opts)
+{
+ int opt;
+
+ while ((opt = getopt(argc, argv, "vp:d:")) != -1) {
+ switch (opt) {
+ case 'v':
+ opts->verbose = 1;
+ break;
+ case 'p':
+ opts->port = atoi(optarg);
+ break;
+ case 'd':
+ opts->devid = atoi(optarg);
+ break;
+ default:
+ usage(argv[0], NULL);
+ }
+ }
+}
+
+static int psp_dev_set_ena(struct ynl_sock *ys, __u32 dev_id, __u32 versions)
+{
+ struct psp_dev_set_req *sreq;
+ struct psp_dev_set_rsp *srsp;
+
+ fprintf(stderr, "Set PSP enable on device %d to 0x%x\n",
+ dev_id, versions);
+
+ sreq = psp_dev_set_req_alloc();
+
+ psp_dev_set_req_set_id(sreq, dev_id);
+ psp_dev_set_req_set_psp_versions_ena(sreq, versions);
+
+ srsp = psp_dev_set(ys, sreq);
+ psp_dev_set_req_free(sreq);
+ if (!srsp)
+ return 10;
+
+ psp_dev_set_rsp_free(srsp);
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ struct psp_dev_get_list *dev_list;
+ bool devid_found = false;
+ __u32 ver_ena, ver_cap;
+ struct opts opts = {};
+ struct ynl_error yerr;
+ struct ynl_sock *ys;
+ int first_id = 0;
+ int ret;
+
+ parse_cmd_opts(argc, argv, &opts);
+ if (!opts.port)
+ usage(argv[0], "port"); // exits
+
+ ys = ynl_sock_create(&ynl_psp_family, &yerr);
+ if (!ys) {
+ fprintf(stderr, "YNL: %s\n", yerr.msg);
+ return 1;
+ }
+
+ dev_list = psp_dev_get_dump(ys);
+ if (ynl_dump_empty(dev_list)) {
+ if (ys->err.code)
+ goto err_close;
+ fprintf(stderr, "No PSP devices\n");
+ goto err_close_silent;
+ }
+
+ ynl_dump_foreach(dev_list, d) {
+ if (opts.devid) {
+ devid_found = true;
+ ver_ena = d->psp_versions_ena;
+ ver_cap = d->psp_versions_cap;
+ } else if (!first_id) {
+ first_id = d->id;
+ ver_ena = d->psp_versions_ena;
+ ver_cap = d->psp_versions_cap;
+ } else {
+ fprintf(stderr, "Multiple PSP devices found\n");
+ goto err_close_silent;
+ }
+ }
+ psp_dev_get_list_free(dev_list);
+
+ if (opts.devid && !devid_found) {
+ fprintf(stderr, "PSP device %d requested on cmdline, not found\n",
+ opts.devid);
+ goto err_close_silent;
+ } else if (!opts.devid) {
+ opts.devid = first_id;
+ }
+
+ if (ver_ena != ver_cap) {
+ ret = psp_dev_set_ena(ys, opts.devid, ver_cap);
+ if (ret)
+ goto err_close;
+ }
+
+ ret = run_responder(ys, &opts);
+
+ if (ver_ena != ver_cap && psp_dev_set_ena(ys, opts.devid, ver_ena))
+ fprintf(stderr, "WARN: failed to set the PSP versions back\n");
+
+ ynl_sock_destroy(ys);
+
+ return ret;
+
+err_close:
+ fprintf(stderr, "YNL: %s\n", ys->err.msg);
+err_close_silent:
+ ynl_sock_destroy(ys);
+ return 2;
+}
--
2.47.3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH net-next 5/9] selftests: drv-net: psp: add basic data transfer and key rotation tests
2025-09-24 19:49 [PATCH net-next 0/9] psp: add a kselftest suite and netdevsim implementation Daniel Zahka
` (3 preceding siblings ...)
2025-09-24 19:49 ` [PATCH net-next 4/9] selftests: drv-net: add PSP responder Daniel Zahka
@ 2025-09-24 19:49 ` Daniel Zahka
2025-09-26 9:15 ` Petr Machata
2025-09-24 19:49 ` [PATCH net-next 6/9] selftests: drv-net: psp: add association tests Daniel Zahka
` (3 subsequent siblings)
8 siblings, 1 reply; 19+ messages in thread
From: Daniel Zahka @ 2025-09-24 19:49 UTC (permalink / raw)
To: Jakub Kicinski, Andrew Lunn, David S. Miller, Eric Dumazet,
Paolo Abeni, Simon Horman, Shuah Khan
Cc: Willem de Bruijn, Breno Leitao, Petr Machata, Yuyang Huang,
Xiao Liang, Carolina Jubran, Donald Hunter, netdev
From: Jakub Kicinski <kuba@kernel.org>
Add basic tests for sending data over PSP and making sure that key
rotation toggles the MSB of the spi.
Deploy PSP responder on the remote end. We also need a healthy dose
of common helpers for setting up the connections, assertions and
interrogating socket state on the Python side.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Daniel Zahka <daniel.zahka@gmail.com>
---
tools/testing/selftests/drivers/net/psp.py | 200 ++++++++++++++++++++-
1 file changed, 192 insertions(+), 8 deletions(-)
diff --git a/tools/testing/selftests/drivers/net/psp.py b/tools/testing/selftests/drivers/net/psp.py
index 965e456836d2..b4f8a32ccbbb 100755
--- a/tools/testing/selftests/drivers/net/psp.py
+++ b/tools/testing/selftests/drivers/net/psp.py
@@ -3,9 +3,94 @@
"""Test suite for PSP capable drivers."""
-from lib.py import ksft_run, ksft_exit
-from lib.py import ksft_true, ksft_eq
+import fcntl
+import socket
+import struct
+import termios
+import time
+
+from lib.py import ksft_run, ksft_exit, ksft_pr
+from lib.py import ksft_true, ksft_eq, ksft_ne, KsftSkipEx
from lib.py import NetDrvEpEnv, PSPFamily, NlError
+from lib.py import bkg, rand_port, wait_port_listen
+
+
+def _get_outq(s):
+ one = b'\0' * 4
+ outq = fcntl.ioctl(s.fileno(), termios.TIOCOUTQ, one)
+ return struct.unpack("I", outq)[0]
+
+
+def _send_with_ack(cfg, msg):
+ cfg.comm_sock.send(msg)
+ response = cfg.comm_sock.recv(4)
+ if response != b'ack\0':
+ raise Exception("Unexpected server response", response)
+
+
+def _remote_read_len(cfg):
+ cfg.comm_sock.send(b'read len\0')
+ return int(cfg.comm_sock.recv(1024)[:-1].decode('utf-8'))
+
+
+def _make_psp_conn(cfg, version=0, ipver=None):
+ _send_with_ack(cfg, b'conn psp\0' + struct.pack('BB', version, version))
+ remote_addr = cfg.remote_addr_v[ipver] if ipver else cfg.remote_addr
+ s = socket.create_connection((remote_addr, cfg.comm_port), )
+ return s
+
+
+def _close_conn(cfg, s):
+ _send_with_ack(cfg, b'data close\0')
+ s.close()
+
+
+def _close_psp_conn(cfg, s):
+ _close_conn(cfg, s)
+
+
+def _spi_xchg(s, rx):
+ s.send(struct.pack('I', rx['spi']) + rx['key'])
+ tx = s.recv(4 + len(rx['key']))
+ return {
+ 'spi': struct.unpack('I', tx[:4])[0],
+ 'key': tx[4:]
+ }
+
+
+def _send_careful(cfg, s, rounds):
+ data = b'0123456789' * 200
+ for i in range(rounds):
+ n = 0
+ retries = 0
+ while True:
+ try:
+ n += s.send(data[n:], socket.MSG_DONTWAIT)
+ if n == len(data):
+ break
+ except BlockingIOError:
+ time.sleep(0.05)
+
+ retries += 1
+ if retries > 10:
+ rlen = _remote_read_len(cfg)
+ outq = _get_outq(s)
+ report = f'sent: {i * len(data) + n} remote len: {rlen} outq: {outq}'
+ if retries > 10:
+ raise Exception(report)
+
+ return len(data) * rounds
+
+
+def _check_data_rx(cfg, exp_len):
+ read_len = -1
+ for _ in range(30):
+ cfg.comm_sock.send(b'read len\0')
+ read_len = int(cfg.comm_sock.recv(1024)[:-1].decode('utf-8'))
+ if read_len == exp_len:
+ break
+ time.sleep(0.01)
+ ksft_eq(read_len, exp_len)
#
# Test cases
@@ -38,6 +123,75 @@ def dev_get_device_bad(cfg):
ksft_true(raised)
+def dev_rotate(cfg):
+ """ Test key rotation """
+ rot = cfg.pspnl.key_rotate({"id": cfg.psp_dev_id})
+ ksft_eq(rot['id'], cfg.psp_dev_id)
+ rot = cfg.pspnl.key_rotate({"id": cfg.psp_dev_id})
+ ksft_eq(rot['id'], cfg.psp_dev_id)
+
+
+def dev_rotate_spi(cfg):
+ """ Test key rotation and SPI check """
+ top_a = top_b = 0
+ with socket.socket(socket.AF_INET6, socket.SOCK_STREAM) as s:
+ assoc_a = cfg.pspnl.rx_assoc({"version": 0,
+ "dev-id": cfg.psp_dev_id,
+ "sock-fd": s.fileno()})
+ top_a = assoc_a['rx-key']['spi'] >> 31
+ s.close()
+ rot = cfg.pspnl.key_rotate({"id": cfg.psp_dev_id})
+ with socket.socket(socket.AF_INET6, socket.SOCK_STREAM) as s:
+ ksft_eq(rot['id'], cfg.psp_dev_id)
+ assoc_b = cfg.pspnl.rx_assoc({"version": 0,
+ "dev-id": cfg.psp_dev_id,
+ "sock-fd": s.fileno()})
+ top_b = assoc_b['rx-key']['spi'] >> 31
+ s.close()
+ ksft_ne(top_a, top_b)
+
+
+def _data_basic_send(cfg, version, ipver):
+ """ Test basic data send """
+ # Version 0 is required by spec, don't let it skip
+ if version:
+ name = cfg.pspnl.consts["version"].entries_by_val[version].name
+ if name not in cfg.psp_supported_versions:
+ with socket.socket(socket.AF_INET6, socket.SOCK_STREAM) as s:
+ with ksft_raises(NlError) as cm:
+ cfg.pspnl.rx_assoc({"version": version,
+ "dev-id": cfg.psp_dev_id,
+ "sock-fd": s.fileno()})
+ ksft_eq(cm.exception.nl_msg.error, -95)
+ raise KsftSkipEx("PSP version not supported", name)
+
+ s = _make_psp_conn(cfg, version, ipver)
+
+ rx_assoc = cfg.pspnl.rx_assoc({"version": version,
+ "dev-id": cfg.psp_dev_id,
+ "sock-fd": s.fileno()})
+ rx = rx_assoc['rx-key']
+ tx = _spi_xchg(s, rx)
+
+ cfg.pspnl.tx_assoc({"dev-id": cfg.psp_dev_id,
+ "version": version,
+ "tx-key": tx,
+ "sock-fd": s.fileno()})
+
+ data_len = _send_careful(cfg, s, 100)
+ _check_data_rx(cfg, data_len)
+ _close_psp_conn(cfg, s)
+
+
+def psp_ip_ver_test_builder(name, test_func, psp_ver, ipver):
+ """Build test cases for each combo of PSP version and IP version"""
+ def test_case(cfg):
+ cfg.require_ipver(ipver)
+ test_case.__name__ = f"{name}_v{psp_ver}_ip{ipver}"
+ test_func(cfg, psp_ver, ipver)
+ return test_case
+
+
def main() -> None:
with NetDrvEpEnv(__file__) as cfg:
cfg.pspnl = PSPFamily()
@@ -55,12 +209,42 @@ def main() -> None:
versions = info['psp-versions-ena']
cfg.pspnl.dev_set({"id": cfg.psp_dev_id,
"psp-versions-ena": info['psp-versions-cap']})
-
- ksft_run(globs=globals(), case_pfx={"dev_"},
- args=(cfg, ), skip_all=(cfg.psp_dev_id is None))
-
- if versions is not None:
- cfg.pspnl.dev_set({"id": cfg.psp_dev_id, "psp-versions-ena": versions})
+ cfg.psp_supported_versions = info['psp-versions-cap']
+
+ # Set up responder and communication sock
+ responder = cfg.remote.deploy("psp_responder")
+
+ cfg.comm_port = rand_port()
+ try:
+ with bkg(responder + f" -p {cfg.comm_port}", host=cfg.remote, exit_wait=True) as srv:
+ wait_port_listen(cfg.comm_port, host=cfg.remote)
+
+ cfg.comm_sock = socket.create_connection((cfg.remote_addr,
+ cfg.comm_port), timeout=1)
+
+ cases = [
+ psp_ip_ver_test_builder(
+ "data_basic_send", _data_basic_send, version, ipver
+ )
+ for version in range(0, 4)
+ for ipver in ("4", "6")
+ ]
+ ksft_run(cases = cases, globs=globals(), case_pfx={"dev_", "data_"},
+ args=(cfg, ), skip_all=(cfg.psp_dev_id is None))
+ cfg.comm_sock.send(b"exit\0")
+ cfg.comm_sock.close()
+
+ if versions is not None:
+ cfg.pspnl.dev_set({"id": cfg.psp_dev_id, "psp-versions-ena": versions})
+
+ finally:
+ if srv.stdout or srv.stderr:
+ ksft_pr("")
+ ksft_pr(f"Responder logs ({srv.ret}):")
+ if srv.stdout:
+ ksft_pr("STDOUT:\n# " + srv.stdout.strip().replace("\n", "\n# "))
+ if srv.stderr:
+ ksft_pr("STDERR:\n# " + srv.stderr.strip().replace("\n", "\n# "))
ksft_exit()
--
2.47.3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH net-next 6/9] selftests: drv-net: psp: add association tests
2025-09-24 19:49 [PATCH net-next 0/9] psp: add a kselftest suite and netdevsim implementation Daniel Zahka
` (4 preceding siblings ...)
2025-09-24 19:49 ` [PATCH net-next 5/9] selftests: drv-net: psp: add basic data transfer and key rotation tests Daniel Zahka
@ 2025-09-24 19:49 ` Daniel Zahka
2025-09-24 19:49 ` [PATCH net-next 7/9] selftests: drv-net: psp: add connection breaking tests Daniel Zahka
` (2 subsequent siblings)
8 siblings, 0 replies; 19+ messages in thread
From: Daniel Zahka @ 2025-09-24 19:49 UTC (permalink / raw)
To: Jakub Kicinski, Andrew Lunn, David S. Miller, Eric Dumazet,
Paolo Abeni, Simon Horman, Shuah Khan
Cc: Willem de Bruijn, Breno Leitao, Petr Machata, Yuyang Huang,
Xiao Liang, Carolina Jubran, Donald Hunter, netdev
From: Jakub Kicinski <kuba@kernel.org>
Add tests for exercising PSP associations for TCP sockets.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Daniel Zahka <daniel.zahka@gmail.com>
---
.../drivers/net/hw/lib/py/__init__.py | 2 +-
.../selftests/drivers/net/lib/py/__init__.py | 2 +-
tools/testing/selftests/drivers/net/psp.py | 145 +++++++++++++++++-
tools/testing/selftests/net/lib/py/ksft.py | 5 +
4 files changed, 150 insertions(+), 4 deletions(-)
diff --git a/tools/testing/selftests/drivers/net/hw/lib/py/__init__.py b/tools/testing/selftests/drivers/net/hw/lib/py/__init__.py
index 559c572e296a..1c631f3c81f1 100644
--- a/tools/testing/selftests/drivers/net/hw/lib/py/__init__.py
+++ b/tools/testing/selftests/drivers/net/hw/lib/py/__init__.py
@@ -22,7 +22,7 @@ try:
from net.lib.py import ksft_disruptive, ksft_exit, ksft_pr, ksft_run, \
ksft_setup
from net.lib.py import ksft_eq, ksft_ge, ksft_in, ksft_is, ksft_lt, \
- ksft_ne, ksft_not_in, ksft_raises, ksft_true
+ ksft_ne, ksft_not_in, ksft_raises, ksft_true, ksft_gt
from net.lib.py import NetNSEnter
from drivers.net.lib.py import GenerateTraffic
from drivers.net.lib.py import NetDrvEnv, NetDrvEpEnv
diff --git a/tools/testing/selftests/drivers/net/lib/py/__init__.py b/tools/testing/selftests/drivers/net/lib/py/__init__.py
index 31ecc618050c..8a795eeb5051 100644
--- a/tools/testing/selftests/drivers/net/lib/py/__init__.py
+++ b/tools/testing/selftests/drivers/net/lib/py/__init__.py
@@ -21,7 +21,7 @@ try:
from net.lib.py import ksft_disruptive, ksft_exit, ksft_pr, ksft_run, \
ksft_setup
from net.lib.py import ksft_eq, ksft_ge, ksft_in, ksft_is, ksft_lt, \
- ksft_ne, ksft_not_in, ksft_raises, ksft_true
+ ksft_ne, ksft_not_in, ksft_raises, ksft_true, ksft_gt
except ModuleNotFoundError as e:
ksft_pr("Failed importing `net` library from kernel sources")
ksft_pr(str(e))
diff --git a/tools/testing/selftests/drivers/net/psp.py b/tools/testing/selftests/drivers/net/psp.py
index b4f8a32ccbbb..1c504975b07d 100755
--- a/tools/testing/selftests/drivers/net/psp.py
+++ b/tools/testing/selftests/drivers/net/psp.py
@@ -10,7 +10,7 @@ import termios
import time
from lib.py import ksft_run, ksft_exit, ksft_pr
-from lib.py import ksft_true, ksft_eq, ksft_ne, KsftSkipEx
+from lib.py import ksft_true, ksft_eq, ksft_ne, ksft_gt, ksft_raises, KsftSkipEx
from lib.py import NetDrvEpEnv, PSPFamily, NlError
from lib.py import bkg, rand_port, wait_port_listen
@@ -33,6 +33,13 @@ def _remote_read_len(cfg):
return int(cfg.comm_sock.recv(1024)[:-1].decode('utf-8'))
+def _make_clr_conn(cfg, ipver=None):
+ _send_with_ack(cfg, b'conn clr\0')
+ remote_addr = cfg.remote_addr_v[ipver] if ipver else cfg.remote_addr
+ s = socket.create_connection((remote_addr, cfg.comm_port), )
+ return s
+
+
def _make_psp_conn(cfg, version=0, ipver=None):
_send_with_ack(cfg, b'conn psp\0' + struct.pack('BB', version, version))
remote_addr = cfg.remote_addr_v[ipver] if ipver else cfg.remote_addr
@@ -151,6 +158,140 @@ def dev_rotate_spi(cfg):
ksft_ne(top_a, top_b)
+def assoc_basic(cfg):
+ """ Test creating associations """
+ with socket.socket(socket.AF_INET6, socket.SOCK_STREAM) as s:
+ assoc = cfg.pspnl.rx_assoc({"version": 0,
+ "dev-id": cfg.psp_dev_id,
+ "sock-fd": s.fileno()})
+ ksft_eq(assoc['dev-id'], cfg.psp_dev_id)
+ ksft_gt(assoc['rx-key']['spi'], 0)
+ ksft_eq(len(assoc['rx-key']['key']), 16)
+
+ assoc = cfg.pspnl.tx_assoc({"dev-id": cfg.psp_dev_id,
+ "version": 0,
+ "tx-key": assoc['rx-key'],
+ "sock-fd": s.fileno()})
+ ksft_eq(len(assoc), 0)
+ s.close()
+
+
+def assoc_bad_dev(cfg):
+ """ Test creating associations with bad device ID """
+ with socket.socket(socket.AF_INET6, socket.SOCK_STREAM) as s:
+ with ksft_raises(NlError) as cm:
+ cfg.pspnl.rx_assoc({"version": 0,
+ "dev-id": cfg.psp_dev_id + 1234567,
+ "sock-fd": s.fileno()})
+ ksft_eq(cm.exception.nl_msg.error, -19)
+
+
+def assoc_sk_only_conn(cfg):
+ """ Test creating associations based on socket """
+ with _make_clr_conn(cfg) as s:
+ assoc = cfg.pspnl.rx_assoc({"version": 0,
+ "sock-fd": s.fileno()})
+ ksft_eq(assoc['dev-id'], cfg.psp_dev_id)
+ cfg.pspnl.tx_assoc({"version": 0,
+ "tx-key": assoc['rx-key'],
+ "sock-fd": s.fileno()})
+ _close_conn(cfg, s)
+
+
+def assoc_sk_only_mismatch(cfg):
+ """ Test creating associations based on socket (dev mismatch) """
+ with _make_clr_conn(cfg) as s:
+ with ksft_raises(NlError) as cm:
+ cfg.pspnl.rx_assoc({"version": 0,
+ "dev-id": cfg.psp_dev_id + 1234567,
+ "sock-fd": s.fileno()})
+ the_exception = cm.exception
+ ksft_eq(the_exception.nl_msg.extack['bad-attr'], ".dev-id")
+ ksft_eq(the_exception.nl_msg.error, -22)
+
+
+def assoc_sk_only_mismatch_tx(cfg):
+ """ Test creating associations based on socket (dev mismatch) """
+ with _make_clr_conn(cfg) as s:
+ with ksft_raises(NlError) as cm:
+ assoc = cfg.pspnl.rx_assoc({"version": 0,
+ "sock-fd": s.fileno()})
+ cfg.pspnl.tx_assoc({"version": 0,
+ "tx-key": assoc['rx-key'],
+ "dev-id": cfg.psp_dev_id + 1234567,
+ "sock-fd": s.fileno()})
+ the_exception = cm.exception
+ ksft_eq(the_exception.nl_msg.extack['bad-attr'], ".dev-id")
+ ksft_eq(the_exception.nl_msg.error, -22)
+
+
+def assoc_sk_only_unconn(cfg):
+ """ Test creating associations based on socket (unconnected, should fail) """
+ with socket.socket(socket.AF_INET6, socket.SOCK_STREAM) as s:
+ with ksft_raises(NlError) as cm:
+ cfg.pspnl.rx_assoc({"version": 0,
+ "sock-fd": s.fileno()})
+ the_exception = cm.exception
+ ksft_eq(the_exception.nl_msg.extack['miss-type'], "dev-id")
+ ksft_eq(the_exception.nl_msg.error, -22)
+
+
+def assoc_version_mismatch(cfg):
+ """ Test creating associations where Rx and Tx PSP versions do not match """
+ versions = list(cfg.psp_supported_versions)
+ if len(versions) < 2:
+ raise KsftSkipEx("Not enough PSP versions supported by the device for the test")
+
+ # Translate versions to integers
+ versions = [cfg.pspnl.consts["version"].entries[v].value for v in versions]
+
+ with socket.socket(socket.AF_INET6, socket.SOCK_STREAM) as s:
+ rx = cfg.pspnl.rx_assoc({"version": versions[0],
+ "dev-id": cfg.psp_dev_id,
+ "sock-fd": s.fileno()})
+
+ for version in versions[1:]:
+ with ksft_raises(NlError) as cm:
+ cfg.pspnl.tx_assoc({"dev-id": cfg.psp_dev_id,
+ "version": version,
+ "tx-key": rx['rx-key'],
+ "sock-fd": s.fileno()})
+ the_exception = cm.exception
+ ksft_eq(the_exception.nl_msg.error, -22)
+
+
+def assoc_twice(cfg):
+ """ Test reusing Tx assoc for two sockets """
+ def rx_assoc_check(s):
+ assoc = cfg.pspnl.rx_assoc({"version": 0,
+ "dev-id": cfg.psp_dev_id,
+ "sock-fd": s.fileno()})
+ ksft_eq(assoc['dev-id'], cfg.psp_dev_id)
+ ksft_gt(assoc['rx-key']['spi'], 0)
+ ksft_eq(len(assoc['rx-key']['key']), 16)
+
+ return assoc
+
+ with socket.socket(socket.AF_INET6, socket.SOCK_STREAM) as s:
+ assoc = rx_assoc_check(s)
+ tx = cfg.pspnl.tx_assoc({"dev-id": cfg.psp_dev_id,
+ "version": 0,
+ "tx-key": assoc['rx-key'],
+ "sock-fd": s.fileno()})
+ ksft_eq(len(tx), 0)
+
+ # Use the same Tx assoc second time
+ with socket.socket(socket.AF_INET6, socket.SOCK_STREAM) as s2:
+ rx_assoc_check(s2)
+ tx = cfg.pspnl.tx_assoc({"dev-id": cfg.psp_dev_id,
+ "version": 0,
+ "tx-key": assoc['rx-key'],
+ "sock-fd": s2.fileno()})
+ ksft_eq(len(tx), 0)
+
+ s.close()
+
+
def _data_basic_send(cfg, version, ipver):
""" Test basic data send """
# Version 0 is required by spec, don't let it skip
@@ -229,7 +370,7 @@ def main() -> None:
for version in range(0, 4)
for ipver in ("4", "6")
]
- ksft_run(cases = cases, globs=globals(), case_pfx={"dev_", "data_"},
+ ksft_run(cases = cases, globs=globals(), case_pfx={"dev_", "data_", "assoc_"},
args=(cfg, ), skip_all=(cfg.psp_dev_id is None))
cfg.comm_sock.send(b"exit\0")
cfg.comm_sock.close()
diff --git a/tools/testing/selftests/net/lib/py/ksft.py b/tools/testing/selftests/net/lib/py/ksft.py
index 375020d3edf2..d65dd087c549 100644
--- a/tools/testing/selftests/net/lib/py/ksft.py
+++ b/tools/testing/selftests/net/lib/py/ksft.py
@@ -92,6 +92,11 @@ def ksft_ge(a, b, comment=""):
_fail("Check failed", a, "<", b, comment)
+def ksft_gt(a, b, comment=""):
+ if a <= b:
+ _fail("Check failed", a, "<=", b, comment)
+
+
def ksft_lt(a, b, comment=""):
if a >= b:
_fail("Check failed", a, ">=", b, comment)
--
2.47.3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH net-next 7/9] selftests: drv-net: psp: add connection breaking tests
2025-09-24 19:49 [PATCH net-next 0/9] psp: add a kselftest suite and netdevsim implementation Daniel Zahka
` (5 preceding siblings ...)
2025-09-24 19:49 ` [PATCH net-next 6/9] selftests: drv-net: psp: add association tests Daniel Zahka
@ 2025-09-24 19:49 ` Daniel Zahka
2025-09-24 19:49 ` [PATCH net-next 8/9] selftests: drv-net: psp: add test for auto-adjusting TCP MSS Daniel Zahka
2025-09-24 19:49 ` [PATCH net-next 9/9] selftests: drv-net: psp: add tests for destroying devices Daniel Zahka
8 siblings, 0 replies; 19+ messages in thread
From: Daniel Zahka @ 2025-09-24 19:49 UTC (permalink / raw)
To: Jakub Kicinski, Andrew Lunn, David S. Miller, Eric Dumazet,
Paolo Abeni, Simon Horman, Shuah Khan
Cc: Willem de Bruijn, Breno Leitao, Petr Machata, Yuyang Huang,
Xiao Liang, Carolina Jubran, Donald Hunter, netdev
From: Jakub Kicinski <kuba@kernel.org>
Add test checking conditions which lead to connections breaking.
Using bad key or connection gets stuck if device key is rotated
twice.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Daniel Zahka <daniel.zahka@gmail.com>
---
tools/testing/selftests/drivers/net/psp.py | 111 +++++++++++++++++++++
1 file changed, 111 insertions(+)
diff --git a/tools/testing/selftests/drivers/net/psp.py b/tools/testing/selftests/drivers/net/psp.py
index 1c504975b07d..46e63b85be75 100755
--- a/tools/testing/selftests/drivers/net/psp.py
+++ b/tools/testing/selftests/drivers/net/psp.py
@@ -15,6 +15,10 @@ from lib.py import NetDrvEpEnv, PSPFamily, NlError
from lib.py import bkg, rand_port, wait_port_listen
+class PSPExceptShortIO(Exception):
+ pass
+
+
def _get_outq(s):
one = b'\0' * 4
outq = fcntl.ioctl(s.fileno(), termios.TIOCOUTQ, one)
@@ -89,6 +93,18 @@ def _send_careful(cfg, s, rounds):
return len(data) * rounds
+def _recv_careful(s, target, rounds=100):
+ data = b''
+ for _ in range(rounds):
+ try:
+ data += s.recv(target - len(data), socket.MSG_DONTWAIT)
+ if len(data) == target:
+ return data
+ except BlockingIOError:
+ time.sleep(0.001)
+ raise PSPExceptShortIO(target, len(data), data)
+
+
def _check_data_rx(cfg, exp_len):
read_len = -1
for _ in range(30):
@@ -99,6 +115,27 @@ def _check_data_rx(cfg, exp_len):
time.sleep(0.01)
ksft_eq(read_len, exp_len)
+
+def _check_data_outq(s, exp_len, force_wait=False):
+ outq = 0
+ for _ in range(10):
+ outq = _get_outq(s)
+ if not force_wait and outq == exp_len:
+ break
+ time.sleep(0.01)
+ ksft_eq(outq, exp_len)
+
+
+def _req_echo(cfg, s, expect_fail=False):
+ _send_with_ack(cfg, b'data echo\0')
+ try:
+ _recv_careful(s, 5)
+ if expect_fail:
+ raise Exception("Received unexpected echo reply")
+ except PSPExceptShortIO:
+ if not expect_fail:
+ raise
+
#
# Test cases
#
@@ -324,6 +361,80 @@ def _data_basic_send(cfg, version, ipver):
_close_psp_conn(cfg, s)
+def __bad_xfer_do(cfg, s, tx, version='hdr0-aes-gcm-128'):
+ # Make sure we accept the ACK for the SPI before we seal with the bad assoc
+ _check_data_outq(s, 0)
+
+ cfg.pspnl.tx_assoc({"dev-id": cfg.psp_dev_id,
+ "version": version,
+ "tx-key": tx,
+ "sock-fd": s.fileno()})
+
+ data_len = _send_careful(cfg, s, 20)
+ _check_data_outq(s, data_len, force_wait=True)
+ _check_data_rx(cfg, 0)
+ _close_psp_conn(cfg, s)
+
+
+def data_send_bad_key(cfg):
+ """ Test send data with bad key """
+ s = _make_psp_conn(cfg)
+
+ rx_assoc = cfg.pspnl.rx_assoc({"version": 0,
+ "dev-id": cfg.psp_dev_id,
+ "sock-fd": s.fileno()})
+ rx = rx_assoc['rx-key']
+ tx = _spi_xchg(s, rx)
+ tx['key'] = (tx['key'][0] ^ 0xff).to_bytes(1, 'little') + tx['key'][1:]
+ __bad_xfer_do(cfg, s, tx)
+
+
+def data_send_disconnect(cfg):
+ """ Test socket close after sending data """
+ with _make_psp_conn(cfg) as s:
+ assoc = cfg.pspnl.rx_assoc({"version": 0,
+ "sock-fd": s.fileno()})
+ tx = _spi_xchg(s, assoc['rx-key'])
+ cfg.pspnl.tx_assoc({"version": 0,
+ "tx-key": tx,
+ "sock-fd": s.fileno()})
+
+ data_len = _send_careful(cfg, s, 100)
+ _check_data_rx(cfg, data_len)
+
+ s.shutdown(socket.SHUT_RDWR)
+ s.close()
+
+
+def data_stale_key(cfg):
+ """ Test send on a double-rotated key """
+
+ s = _make_psp_conn(cfg)
+ try:
+ rx_assoc = cfg.pspnl.rx_assoc({"version": 0,
+ "dev-id": cfg.psp_dev_id,
+ "sock-fd": s.fileno()})
+ rx = rx_assoc['rx-key']
+ tx = _spi_xchg(s, rx)
+
+ cfg.pspnl.tx_assoc({"dev-id": cfg.psp_dev_id,
+ "version": 0,
+ "tx-key": tx,
+ "sock-fd": s.fileno()})
+
+ data_len = _send_careful(cfg, s, 100)
+ _check_data_rx(cfg, data_len)
+ _check_data_outq(s, 0)
+
+ cfg.pspnl.key_rotate({"id": cfg.psp_dev_id})
+ cfg.pspnl.key_rotate({"id": cfg.psp_dev_id})
+
+ s.send(b'0123456789' * 200)
+ _check_data_outq(s, 2000, force_wait=True)
+ finally:
+ _close_psp_conn(cfg, s)
+
+
def psp_ip_ver_test_builder(name, test_func, psp_ver, ipver):
"""Build test cases for each combo of PSP version and IP version"""
def test_case(cfg):
--
2.47.3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH net-next 8/9] selftests: drv-net: psp: add test for auto-adjusting TCP MSS
2025-09-24 19:49 [PATCH net-next 0/9] psp: add a kselftest suite and netdevsim implementation Daniel Zahka
` (6 preceding siblings ...)
2025-09-24 19:49 ` [PATCH net-next 7/9] selftests: drv-net: psp: add connection breaking tests Daniel Zahka
@ 2025-09-24 19:49 ` Daniel Zahka
2025-09-24 19:49 ` [PATCH net-next 9/9] selftests: drv-net: psp: add tests for destroying devices Daniel Zahka
8 siblings, 0 replies; 19+ messages in thread
From: Daniel Zahka @ 2025-09-24 19:49 UTC (permalink / raw)
To: Jakub Kicinski, Andrew Lunn, David S. Miller, Eric Dumazet,
Paolo Abeni, Simon Horman, Shuah Khan
Cc: Willem de Bruijn, Breno Leitao, Petr Machata, Yuyang Huang,
Xiao Liang, Carolina Jubran, Donald Hunter, netdev
From: Jakub Kicinski <kuba@kernel.org>
Test TCP MSS getting auto-adjusted. PSP adds an encapsulation overhead
of 40B per packet, when used in transport mode without any
virtualization cookie or other optional PSP header fields. The kernel
should adjust the MSS for a connection after PSP tx state is reached.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Daniel Zahka <daniel.zahka@gmail.com>
---
tools/testing/selftests/drivers/net/psp.py | 50 ++++++++++++++++++++++
1 file changed, 50 insertions(+)
diff --git a/tools/testing/selftests/drivers/net/psp.py b/tools/testing/selftests/drivers/net/psp.py
index 46e63b85be75..ee103b47568c 100755
--- a/tools/testing/selftests/drivers/net/psp.py
+++ b/tools/testing/selftests/drivers/net/psp.py
@@ -406,6 +406,43 @@ def data_send_disconnect(cfg):
s.close()
+def _data_mss_adjust(cfg, ipver):
+ # First figure out what the MSS would be without any adjustments
+ s = _make_clr_conn(cfg, ipver)
+ s.send(b"0123456789abcdef" * 1024)
+ _check_data_rx(cfg, 16 * 1024)
+ mss = s.getsockopt(socket.IPPROTO_TCP, socket.TCP_MAXSEG)
+ _close_conn(cfg, s)
+
+ s = _make_psp_conn(cfg, 0, ipver)
+ try:
+ rx_assoc = cfg.pspnl.rx_assoc({"version": 0,
+ "dev-id": cfg.psp_dev_id,
+ "sock-fd": s.fileno()})
+ rx = rx_assoc['rx-key']
+ tx = _spi_xchg(s, rx)
+
+ rxmss = s.getsockopt(socket.IPPROTO_TCP, socket.TCP_MAXSEG)
+ ksft_eq(mss, rxmss)
+
+ cfg.pspnl.tx_assoc({"dev-id": cfg.psp_dev_id,
+ "version": 0,
+ "tx-key": tx,
+ "sock-fd": s.fileno()})
+
+ txmss = s.getsockopt(socket.IPPROTO_TCP, socket.TCP_MAXSEG)
+ ksft_eq(mss, txmss + 40)
+
+ data_len = _send_careful(cfg, s, 100)
+ _check_data_rx(cfg, data_len)
+ _check_data_outq(s, 0)
+
+ txmss = s.getsockopt(socket.IPPROTO_TCP, socket.TCP_MAXSEG)
+ ksft_eq(mss, txmss + 40)
+ finally:
+ _close_psp_conn(cfg, s)
+
+
def data_stale_key(cfg):
""" Test send on a double-rotated key """
@@ -444,6 +481,15 @@ def psp_ip_ver_test_builder(name, test_func, psp_ver, ipver):
return test_case
+def ipver_test_builder(name, test_func, ipver):
+ """Build test cases for each IP version"""
+ def test_case(cfg):
+ cfg.require_ipver(ipver)
+ test_case.__name__ = f"{name}_ip{ipver}"
+ test_func(cfg, ipver)
+ return test_case
+
+
def main() -> None:
with NetDrvEpEnv(__file__) as cfg:
cfg.pspnl = PSPFamily()
@@ -481,6 +527,10 @@ def main() -> None:
for version in range(0, 4)
for ipver in ("4", "6")
]
+ cases += [
+ ipver_test_builder("data_mss_adjust", _data_mss_adjust, ipver)
+ for ipver in ("4", "6")
+ ]
ksft_run(cases = cases, globs=globals(), case_pfx={"dev_", "data_", "assoc_"},
args=(cfg, ), skip_all=(cfg.psp_dev_id is None))
cfg.comm_sock.send(b"exit\0")
--
2.47.3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH net-next 9/9] selftests: drv-net: psp: add tests for destroying devices
2025-09-24 19:49 [PATCH net-next 0/9] psp: add a kselftest suite and netdevsim implementation Daniel Zahka
` (7 preceding siblings ...)
2025-09-24 19:49 ` [PATCH net-next 8/9] selftests: drv-net: psp: add test for auto-adjusting TCP MSS Daniel Zahka
@ 2025-09-24 19:49 ` Daniel Zahka
8 siblings, 0 replies; 19+ messages in thread
From: Daniel Zahka @ 2025-09-24 19:49 UTC (permalink / raw)
To: Jakub Kicinski, Andrew Lunn, David S. Miller, Eric Dumazet,
Paolo Abeni, Simon Horman, Shuah Khan
Cc: Willem de Bruijn, Breno Leitao, Petr Machata, Yuyang Huang,
Xiao Liang, Carolina Jubran, Donald Hunter, netdev
From: Jakub Kicinski <kuba@kernel.org>
Add tests for making sure device can disappear while associations
exist. This is netdevsim-only since destroying real devices is
more tricky.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Daniel Zahka <daniel.zahka@gmail.com>
---
.../drivers/net/hw/lib/py/__init__.py | 2 +-
.../selftests/drivers/net/lib/py/__init__.py | 2 +-
.../selftests/drivers/net/lib/py/env.py | 5 ++
tools/testing/selftests/drivers/net/psp.py | 59 ++++++++++++++++++-
tools/testing/selftests/net/lib/py/ksft.py | 5 ++
5 files changed, 69 insertions(+), 4 deletions(-)
diff --git a/tools/testing/selftests/drivers/net/hw/lib/py/__init__.py b/tools/testing/selftests/drivers/net/hw/lib/py/__init__.py
index 1c631f3c81f1..0ceb297e7757 100644
--- a/tools/testing/selftests/drivers/net/hw/lib/py/__init__.py
+++ b/tools/testing/selftests/drivers/net/hw/lib/py/__init__.py
@@ -22,7 +22,7 @@ try:
from net.lib.py import ksft_disruptive, ksft_exit, ksft_pr, ksft_run, \
ksft_setup
from net.lib.py import ksft_eq, ksft_ge, ksft_in, ksft_is, ksft_lt, \
- ksft_ne, ksft_not_in, ksft_raises, ksft_true, ksft_gt
+ ksft_ne, ksft_not_in, ksft_raises, ksft_true, ksft_gt, ksft_not_none
from net.lib.py import NetNSEnter
from drivers.net.lib.py import GenerateTraffic
from drivers.net.lib.py import NetDrvEnv, NetDrvEpEnv
diff --git a/tools/testing/selftests/drivers/net/lib/py/__init__.py b/tools/testing/selftests/drivers/net/lib/py/__init__.py
index 8a795eeb5051..2a645415c4ca 100644
--- a/tools/testing/selftests/drivers/net/lib/py/__init__.py
+++ b/tools/testing/selftests/drivers/net/lib/py/__init__.py
@@ -21,7 +21,7 @@ try:
from net.lib.py import ksft_disruptive, ksft_exit, ksft_pr, ksft_run, \
ksft_setup
from net.lib.py import ksft_eq, ksft_ge, ksft_in, ksft_is, ksft_lt, \
- ksft_ne, ksft_not_in, ksft_raises, ksft_true, ksft_gt
+ ksft_ne, ksft_not_in, ksft_raises, ksft_true, ksft_gt, ksft_not_none
except ModuleNotFoundError as e:
ksft_pr("Failed importing `net` library from kernel sources")
ksft_pr(str(e))
diff --git a/tools/testing/selftests/drivers/net/lib/py/env.py b/tools/testing/selftests/drivers/net/lib/py/env.py
index c1f3b608c6d8..fc12e20af880 100644
--- a/tools/testing/selftests/drivers/net/lib/py/env.py
+++ b/tools/testing/selftests/drivers/net/lib/py/env.py
@@ -7,6 +7,7 @@ from lib.py import KsftSkipEx, KsftXfailEx
from lib.py import ksft_setup, wait_file
from lib.py import cmd, ethtool, ip, CmdExitFailure
from lib.py import NetNS, NetdevSimDev
+from lib.py import KsftXfailEx
from .remote import Remote
@@ -245,6 +246,10 @@ class NetDrvEpEnv(NetDrvEnvBase):
if not self.addr_v[ipver] or not self.remote_addr_v[ipver]:
raise KsftSkipEx(f"Test requires IPv{ipver} connectivity")
+ def require_nsim(self):
+ if self._ns is None:
+ raise KsftXfailEx("Test only works on netdevsim")
+
def _require_cmd(self, comm, key, host=None):
cached = self._required_cmd.get(comm, {})
if cached.get(key) is None:
diff --git a/tools/testing/selftests/drivers/net/psp.py b/tools/testing/selftests/drivers/net/psp.py
index ee103b47568c..6a7f51801703 100755
--- a/tools/testing/selftests/drivers/net/psp.py
+++ b/tools/testing/selftests/drivers/net/psp.py
@@ -10,7 +10,7 @@ import termios
import time
from lib.py import ksft_run, ksft_exit, ksft_pr
-from lib.py import ksft_true, ksft_eq, ksft_ne, ksft_gt, ksft_raises, KsftSkipEx
+from lib.py import ksft_true, ksft_eq, ksft_ne, ksft_gt, ksft_raises, ksft_not_none, KsftSkipEx
from lib.py import NetDrvEpEnv, PSPFamily, NlError
from lib.py import bkg, rand_port, wait_port_listen
@@ -472,6 +472,61 @@ def data_stale_key(cfg):
_close_psp_conn(cfg, s)
+def __nsim_psp_rereg(cfg):
+ # The PSP dev ID will change, remember what was there before
+ before = set([x['id'] for x in cfg.pspnl.dev_get({}, dump=True)])
+
+ cfg._ns.nsims[0].dfs_write('psp_rereg', '1')
+
+ after = set([x['id'] for x in cfg.pspnl.dev_get({}, dump=True)])
+
+ new_devs = list(after - before)
+ ksft_eq(len(new_devs), 1)
+ cfg.psp_dev_id = list(after - before)[0]
+
+
+def removal_device_rx(cfg):
+ """ Test removing a netdev / PSD with active Rx assoc """
+
+ # We could technically devlink reload real devices, too
+ # but that kills the control socket. So test this on
+ # netdevsim only for now
+ cfg.require_nsim()
+
+ s = _make_clr_conn(cfg)
+ try:
+ rx_assoc = cfg.pspnl.rx_assoc({"version": 0,
+ "dev-id": cfg.psp_dev_id,
+ "sock-fd": s.fileno()})
+ ksft_not_none(rx_assoc)
+
+ __nsim_psp_rereg(cfg)
+ finally:
+ _close_conn(cfg, s)
+
+
+def removal_device_bi(cfg):
+ """ Test removing a netdev / PSD with active Rx/Tx assoc """
+
+ # We could technically devlink reload real devices, too
+ # but that kills the control socket. So test this on
+ # netdevsim only for now
+ cfg.require_nsim()
+
+ s = _make_clr_conn(cfg)
+ try:
+ rx_assoc = cfg.pspnl.rx_assoc({"version": 0,
+ "dev-id": cfg.psp_dev_id,
+ "sock-fd": s.fileno()})
+ cfg.pspnl.tx_assoc({"dev-id": cfg.psp_dev_id,
+ "version": 0,
+ "tx-key": rx_assoc['rx-key'],
+ "sock-fd": s.fileno()})
+ __nsim_psp_rereg(cfg)
+ finally:
+ _close_conn(cfg, s)
+
+
def psp_ip_ver_test_builder(name, test_func, psp_ver, ipver):
"""Build test cases for each combo of PSP version and IP version"""
def test_case(cfg):
@@ -531,7 +586,7 @@ def main() -> None:
ipver_test_builder("data_mss_adjust", _data_mss_adjust, ipver)
for ipver in ("4", "6")
]
- ksft_run(cases = cases, globs=globals(), case_pfx={"dev_", "data_", "assoc_"},
+ ksft_run(cases = cases, globs=globals(), case_pfx={"dev_", "data_", "assoc_", "removal_"},
args=(cfg, ), skip_all=(cfg.psp_dev_id is None))
cfg.comm_sock.send(b"exit\0")
cfg.comm_sock.close()
diff --git a/tools/testing/selftests/net/lib/py/ksft.py b/tools/testing/selftests/net/lib/py/ksft.py
index d65dd087c549..43b40a027f5e 100644
--- a/tools/testing/selftests/net/lib/py/ksft.py
+++ b/tools/testing/selftests/net/lib/py/ksft.py
@@ -72,6 +72,11 @@ def ksft_true(a, comment=""):
_fail("Check failed", a, "does not eval to True", comment)
+def ksft_not_none(a, comment=""):
+ if a is None:
+ _fail("Check failed", a, "is None", comment)
+
+
def ksft_in(a, b, comment=""):
if a not in b:
_fail("Check failed", a, "not in", b, comment)
--
2.47.3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH net-next 1/9] netdevsim: a basic test PSP implementation
2025-09-24 19:49 ` [PATCH net-next 1/9] netdevsim: a basic test PSP implementation Daniel Zahka
@ 2025-09-25 0:12 ` Jakub Kicinski
2025-09-25 6:48 ` kernel test robot
` (2 subsequent siblings)
3 siblings, 0 replies; 19+ messages in thread
From: Jakub Kicinski @ 2025-09-25 0:12 UTC (permalink / raw)
To: Daniel Zahka
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Paolo Abeni,
Simon Horman, Shuah Khan, Willem de Bruijn, Breno Leitao,
Petr Machata, Yuyang Huang, Xiao Liang, Carolina Jubran,
Donald Hunter, netdev
On Wed, 24 Sep 2025 12:49:47 -0700 Daniel Zahka wrote:
> + if (psp_ext)
> + __skb_ext_set(skb, SKB_EXT_PSP, psp_ext);
Oops, the extension is not defined if the CONFIG is not set:
drivers/net/netdevsim/netdev.c: In function ‘nsim_forward_skb’:
drivers/net/netdevsim/netdev.c:116:36: error: ‘SKB_EXT_PSP’ undeclared (first use in this function); did you mean ‘SKB_EXT_NUM’?
116 | __skb_ext_set(skb, SKB_EXT_PSP, psp_ext);
| ^~~~~~~~~~~
| SKB_EXT_NUM
--
pw-bot: cr
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH net-next 3/9] selftests: drv-net: base device access API test
2025-09-24 19:49 ` [PATCH net-next 3/9] selftests: drv-net: base device access API test Daniel Zahka
@ 2025-09-25 0:13 ` Jakub Kicinski
0 siblings, 0 replies; 19+ messages in thread
From: Jakub Kicinski @ 2025-09-25 0:13 UTC (permalink / raw)
To: Daniel Zahka
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Paolo Abeni,
Simon Horman, Shuah Khan, Willem de Bruijn, Breno Leitao,
Petr Machata, Yuyang Huang, Xiao Liang, Carolina Jubran,
Donald Hunter, netdev
On Wed, 24 Sep 2025 12:49:49 -0700 Daniel Zahka wrote:
> --- a/tools/testing/selftests/drivers/net/config
> +++ b/tools/testing/selftests/drivers/net/config
> @@ -5,3 +5,4 @@ CONFIG_NETCONSOLE=m
> CONFIG_NETCONSOLE_DYNAMIC=y
> CONFIG_NETCONSOLE_EXTENDED_LOG=y
> CONFIG_XDP_SOCKETS=y
> +CONFIG_INET_PSP=y
nit: when you respin could you move this up a little?
so that the config options are in (some approximation) of alphabetical
order?
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH net-next 1/9] netdevsim: a basic test PSP implementation
2025-09-24 19:49 ` [PATCH net-next 1/9] netdevsim: a basic test PSP implementation Daniel Zahka
2025-09-25 0:12 ` Jakub Kicinski
@ 2025-09-25 6:48 ` kernel test robot
2025-09-26 15:30 ` Simon Horman
2025-09-26 15:35 ` Simon Horman
3 siblings, 0 replies; 19+ messages in thread
From: kernel test robot @ 2025-09-25 6:48 UTC (permalink / raw)
To: Daniel Zahka, Jakub Kicinski, Andrew Lunn, David S. Miller,
Eric Dumazet, Paolo Abeni, Simon Horman, Shuah Khan
Cc: oe-kbuild-all, netdev, Willem de Bruijn, Breno Leitao,
Petr Machata, Yuyang Huang, Xiao Liang, Carolina Jubran,
Donald Hunter
Hi Daniel,
kernel test robot noticed the following build errors:
[auto build test ERROR on net-next/main]
url: https://github.com/intel-lab-lkp/linux/commits/Daniel-Zahka/netdevsim-a-basic-test-PSP-implementation/20250925-035305
base: net-next/main
patch link: https://lore.kernel.org/r/20250924194959.2845473-2-daniel.zahka%40gmail.com
patch subject: [PATCH net-next 1/9] netdevsim: a basic test PSP implementation
config: i386-buildonly-randconfig-003-20250925 (https://download.01.org/0day-ci/archive/20250925/202509251404.crckqEdD-lkp@intel.com/config)
compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250925/202509251404.crckqEdD-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202509251404.crckqEdD-lkp@intel.com/
All errors (new ones prefixed by >>):
drivers/net/netdevsim/netdev.c: In function 'nsim_forward_skb':
>> drivers/net/netdevsim/netdev.c:116:36: error: 'SKB_EXT_PSP' undeclared (first use in this function); did you mean 'SKB_EXT_NUM'?
116 | __skb_ext_set(skb, SKB_EXT_PSP, psp_ext);
| ^~~~~~~~~~~
| SKB_EXT_NUM
drivers/net/netdevsim/netdev.c:116:36: note: each undeclared identifier is reported only once for each function it appears in
vim +116 drivers/net/netdevsim/netdev.c
102
103 static int nsim_forward_skb(struct net_device *tx_dev,
104 struct net_device *rx_dev,
105 struct sk_buff *skb,
106 struct nsim_rq *rq,
107 struct skb_ext *psp_ext)
108 {
109 int ret;
110
111 ret = __dev_forward_skb(rx_dev, skb);
112 if (ret)
113 return ret;
114
115 if (psp_ext)
> 116 __skb_ext_set(skb, SKB_EXT_PSP, psp_ext);
117
118 return nsim_napi_rx(tx_dev, rx_dev, rq, skb);
119 }
120
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH net-next 2/9] selftests: net: add skip all feature to ksft_run()
2025-09-24 19:49 ` [PATCH net-next 2/9] selftests: net: add skip all feature to ksft_run() Daniel Zahka
@ 2025-09-25 16:09 ` Petr Machata
2025-09-25 17:04 ` Daniel Zahka
2025-09-26 2:18 ` Jakub Kicinski
0 siblings, 2 replies; 19+ messages in thread
From: Petr Machata @ 2025-09-25 16:09 UTC (permalink / raw)
To: Daniel Zahka
Cc: Jakub Kicinski, Andrew Lunn, David S. Miller, Eric Dumazet,
Paolo Abeni, Simon Horman, Shuah Khan, Willem de Bruijn,
Breno Leitao, Petr Machata, Yuyang Huang, Xiao Liang,
Carolina Jubran, Donald Hunter, netdev
Daniel Zahka <daniel.zahka@gmail.com> writes:
> When there is an entire test suite where each test case depends upon
> some feature, e.g., psp, it is easier to state the least common
> denominator of dpendencies up front, rather than doing:
>
> cfg.require_psp()
>
> at the start of each test.
>
> Signed-off-by: Daniel Zahka <daniel.zahka@gmail.com>
> ---
> tools/testing/selftests/net/lib/py/ksft.py | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/tools/testing/selftests/net/lib/py/ksft.py b/tools/testing/selftests/net/lib/py/ksft.py
> index 8e35ed12ed9e..375020d3edf2 100644
> --- a/tools/testing/selftests/net/lib/py/ksft.py
> +++ b/tools/testing/selftests/net/lib/py/ksft.py
> @@ -210,7 +210,7 @@ def _ksft_intr(signum, frame):
> ksft_pr(f"Ignoring SIGTERM (cnt: {term_cnt}), already exiting...")
>
>
> -def ksft_run(cases=None, globs=None, case_pfx=None, args=()):
> +def ksft_run(cases=None, globs=None, case_pfx=None, args=(), skip_all=None):
> cases = cases or []
>
> if globs and case_pfx:
> @@ -241,6 +241,8 @@ def ksft_run(cases=None, globs=None, case_pfx=None, args=()):
> cnt_key = ""
>
> try:
> + if skip_all:
> + raise KsftSkipEx()
> case(*args)
> except KsftSkipEx as e:
> comment = "SKIP " + str(e)
Personally I'm not very fond of this. Calling a run helper just to have
it skip all tests... eh, wouldn't it make more sense to just not call
the function at all then? If all tests have PSP as prereq, just have the
test say so and bail out early?
Topic-specific tests are pretty common, so it's not nonsense to have a
facility that supports that. But this API just seems wrong to me. Run
these tests, except don't run them, just show they are all skipped.
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH net-next 2/9] selftests: net: add skip all feature to ksft_run()
2025-09-25 16:09 ` Petr Machata
@ 2025-09-25 17:04 ` Daniel Zahka
2025-09-26 2:18 ` Jakub Kicinski
1 sibling, 0 replies; 19+ messages in thread
From: Daniel Zahka @ 2025-09-25 17:04 UTC (permalink / raw)
To: Petr Machata
Cc: Jakub Kicinski, Andrew Lunn, David S. Miller, Eric Dumazet,
Paolo Abeni, Simon Horman, Shuah Khan, Willem de Bruijn,
Breno Leitao, Yuyang Huang, Xiao Liang, Carolina Jubran,
Donald Hunter, netdev
On 9/25/25 12:09 PM, Petr Machata wrote:
> Personally I'm not very fond of this. Calling a run helper just to have
> it skip all tests... eh, wouldn't it make more sense to just not call
> the function at all then? If all tests have PSP as prereq, just have the
> test say so and bail out early?
>
> Topic-specific tests are pretty common, so it's not nonsense to have a
> facility that supports that. But this API just seems wrong to me. Run
> these tests, except don't run them, just show they are all skipped.
That's fair. I will change that for the next posting. Thanks for taking
a look.
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH net-next 2/9] selftests: net: add skip all feature to ksft_run()
2025-09-25 16:09 ` Petr Machata
2025-09-25 17:04 ` Daniel Zahka
@ 2025-09-26 2:18 ` Jakub Kicinski
1 sibling, 0 replies; 19+ messages in thread
From: Jakub Kicinski @ 2025-09-26 2:18 UTC (permalink / raw)
To: Petr Machata
Cc: Daniel Zahka, Andrew Lunn, David S. Miller, Eric Dumazet,
Paolo Abeni, Simon Horman, Shuah Khan, Willem de Bruijn,
Breno Leitao, Yuyang Huang, Xiao Liang, Carolina Jubran,
Donald Hunter, netdev
On Thu, 25 Sep 2025 18:09:33 +0200 Petr Machata wrote:
> > + if skip_all:
> > + raise KsftSkipEx()
> > case(*args)
> > except KsftSkipEx as e:
> > comment = "SKIP " + str(e)
>
> Personally I'm not very fond of this. Calling a run helper just to have
> it skip all tests... eh, wouldn't it make more sense to just not call
> the function at all then? If all tests have PSP as prereq, just have the
> test say so and bail out early?
Yes, good call. To be clear this was my bad idea, I think I wrote this
before the ksft took shape upstream. My tree says:
Date: Tue Apr 16 12:02:59 2024 -0700
on the patch from which this was factored out. So let's chalk this
lapse of reason to experimentation :)
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH net-next 5/9] selftests: drv-net: psp: add basic data transfer and key rotation tests
2025-09-24 19:49 ` [PATCH net-next 5/9] selftests: drv-net: psp: add basic data transfer and key rotation tests Daniel Zahka
@ 2025-09-26 9:15 ` Petr Machata
0 siblings, 0 replies; 19+ messages in thread
From: Petr Machata @ 2025-09-26 9:15 UTC (permalink / raw)
To: Daniel Zahka
Cc: Jakub Kicinski, Andrew Lunn, David S. Miller, Eric Dumazet,
Paolo Abeni, Simon Horman, Shuah Khan, Willem de Bruijn,
Breno Leitao, Petr Machata, Yuyang Huang, Xiao Liang,
Carolina Jubran, Donald Hunter, netdev
Daniel Zahka <daniel.zahka@gmail.com> writes:
> From: Jakub Kicinski <kuba@kernel.org>
>
> Add basic tests for sending data over PSP and making sure that key
> rotation toggles the MSB of the spi.
>
> Deploy PSP responder on the remote end. We also need a healthy dose
> of common helpers for setting up the connections, assertions and
> interrogating socket state on the Python side.
>
> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
> Signed-off-by: Daniel Zahka <daniel.zahka@gmail.com>
> ---
> tools/testing/selftests/drivers/net/psp.py | 200 ++++++++++++++++++++-
> 1 file changed, 192 insertions(+), 8 deletions(-)
>
> diff --git a/tools/testing/selftests/drivers/net/psp.py b/tools/testing/selftests/drivers/net/psp.py
> index 965e456836d2..b4f8a32ccbbb 100755
> --- a/tools/testing/selftests/drivers/net/psp.py
> +++ b/tools/testing/selftests/drivers/net/psp.py
> @@ -3,9 +3,94 @@
>
> """Test suite for PSP capable drivers."""
>
> -from lib.py import ksft_run, ksft_exit
> -from lib.py import ksft_true, ksft_eq
> +import fcntl
> +import socket
> +import struct
> +import termios
> +import time
> +
> +from lib.py import ksft_run, ksft_exit, ksft_pr
> +from lib.py import ksft_true, ksft_eq, ksft_ne, KsftSkipEx
> from lib.py import NetDrvEpEnv, PSPFamily, NlError
> +from lib.py import bkg, rand_port, wait_port_listen
> +
> +
> +def _get_outq(s):
> + one = b'\0' * 4
> + outq = fcntl.ioctl(s.fileno(), termios.TIOCOUTQ, one)
> + return struct.unpack("I", outq)[0]
> +
> +
> +def _send_with_ack(cfg, msg):
> + cfg.comm_sock.send(msg)
> + response = cfg.comm_sock.recv(4)
> + if response != b'ack\0':
> + raise Exception("Unexpected server response", response)
> +
> +
> +def _remote_read_len(cfg):
> + cfg.comm_sock.send(b'read len\0')
> + return int(cfg.comm_sock.recv(1024)[:-1].decode('utf-8'))
> +
> +
> +def _make_psp_conn(cfg, version=0, ipver=None):
> + _send_with_ack(cfg, b'conn psp\0' + struct.pack('BB', version, version))
> + remote_addr = cfg.remote_addr_v[ipver] if ipver else cfg.remote_addr
> + s = socket.create_connection((remote_addr, cfg.comm_port), )
> + return s
> +
> +
> +def _close_conn(cfg, s):
> + _send_with_ack(cfg, b'data close\0')
> + s.close()
> +
> +
> +def _close_psp_conn(cfg, s):
> + _close_conn(cfg, s)
> +
> +
> +def _spi_xchg(s, rx):
> + s.send(struct.pack('I', rx['spi']) + rx['key'])
> + tx = s.recv(4 + len(rx['key']))
> + return {
> + 'spi': struct.unpack('I', tx[:4])[0],
> + 'key': tx[4:]
> + }
> +
> +
> +def _send_careful(cfg, s, rounds):
> + data = b'0123456789' * 200
> + for i in range(rounds):
> + n = 0
> + retries = 0
> + while True:
> + try:
> + n += s.send(data[n:], socket.MSG_DONTWAIT)
> + if n == len(data):
> + break
> + except BlockingIOError:
> + time.sleep(0.05)
> +
> + retries += 1
> + if retries > 10:
> + rlen = _remote_read_len(cfg)
> + outq = _get_outq(s)
> + report = f'sent: {i * len(data) + n} remote len: {rlen} outq: {outq}'
> + if retries > 10:
This is always true at this point.
> + raise Exception(report)
> +
> + return len(data) * rounds
> +
> +
> +def _check_data_rx(cfg, exp_len):
> + read_len = -1
> + for _ in range(30):
> + cfg.comm_sock.send(b'read len\0')
> + read_len = int(cfg.comm_sock.recv(1024)[:-1].decode('utf-8'))
> + if read_len == exp_len:
> + break
> + time.sleep(0.01)
> + ksft_eq(read_len, exp_len)
>
> #
> # Test cases
> @@ -38,6 +123,75 @@ def dev_get_device_bad(cfg):
> ksft_true(raised)
>
>
> +def dev_rotate(cfg):
> + """ Test key rotation """
> + rot = cfg.pspnl.key_rotate({"id": cfg.psp_dev_id})
> + ksft_eq(rot['id'], cfg.psp_dev_id)
> + rot = cfg.pspnl.key_rotate({"id": cfg.psp_dev_id})
> + ksft_eq(rot['id'], cfg.psp_dev_id)
> +
> +
> +def dev_rotate_spi(cfg):
> + """ Test key rotation and SPI check """
> + top_a = top_b = 0
> + with socket.socket(socket.AF_INET6, socket.SOCK_STREAM) as s:
> + assoc_a = cfg.pspnl.rx_assoc({"version": 0,
> + "dev-id": cfg.psp_dev_id,
> + "sock-fd": s.fileno()})
> + top_a = assoc_a['rx-key']['spi'] >> 31
> + s.close()
> + rot = cfg.pspnl.key_rotate({"id": cfg.psp_dev_id})
> + with socket.socket(socket.AF_INET6, socket.SOCK_STREAM) as s:
> + ksft_eq(rot['id'], cfg.psp_dev_id)
> + assoc_b = cfg.pspnl.rx_assoc({"version": 0,
> + "dev-id": cfg.psp_dev_id,
> + "sock-fd": s.fileno()})
> + top_b = assoc_b['rx-key']['spi'] >> 31
> + s.close()
> + ksft_ne(top_a, top_b)
> +
> +
> +def _data_basic_send(cfg, version, ipver):
> + """ Test basic data send """
> + # Version 0 is required by spec, don't let it skip
> + if version:
> + name = cfg.pspnl.consts["version"].entries_by_val[version].name
> + if name not in cfg.psp_supported_versions:
> + with socket.socket(socket.AF_INET6, socket.SOCK_STREAM) as s:
> + with ksft_raises(NlError) as cm:
> + cfg.pspnl.rx_assoc({"version": version,
> + "dev-id": cfg.psp_dev_id,
> + "sock-fd": s.fileno()})
> + ksft_eq(cm.exception.nl_msg.error, -95)
> + raise KsftSkipEx("PSP version not supported", name)
> +
> + s = _make_psp_conn(cfg, version, ipver)
> +
> + rx_assoc = cfg.pspnl.rx_assoc({"version": version,
> + "dev-id": cfg.psp_dev_id,
> + "sock-fd": s.fileno()})
> + rx = rx_assoc['rx-key']
> + tx = _spi_xchg(s, rx)
> +
> + cfg.pspnl.tx_assoc({"dev-id": cfg.psp_dev_id,
> + "version": version,
> + "tx-key": tx,
> + "sock-fd": s.fileno()})
> +
> + data_len = _send_careful(cfg, s, 100)
> + _check_data_rx(cfg, data_len)
> + _close_psp_conn(cfg, s)
> +
> +
> +def psp_ip_ver_test_builder(name, test_func, psp_ver, ipver):
> + """Build test cases for each combo of PSP version and IP version"""
> + def test_case(cfg):
> + cfg.require_ipver(ipver)
> + test_case.__name__ = f"{name}_v{psp_ver}_ip{ipver}"
> + test_func(cfg, psp_ver, ipver)
> + return test_case
> +
> +
> def main() -> None:
> with NetDrvEpEnv(__file__) as cfg:
> cfg.pspnl = PSPFamily()
> @@ -55,12 +209,42 @@ def main() -> None:
> versions = info['psp-versions-ena']
> cfg.pspnl.dev_set({"id": cfg.psp_dev_id,
> "psp-versions-ena": info['psp-versions-cap']})
> -
> - ksft_run(globs=globals(), case_pfx={"dev_"},
> - args=(cfg, ), skip_all=(cfg.psp_dev_id is None))
> -
> - if versions is not None:
> - cfg.pspnl.dev_set({"id": cfg.psp_dev_id, "psp-versions-ena": versions})
> + cfg.psp_supported_versions = info['psp-versions-cap']
> +
> + # Set up responder and communication sock
> + responder = cfg.remote.deploy("psp_responder")
> +
> + cfg.comm_port = rand_port()
> + try:
> + with bkg(responder + f" -p {cfg.comm_port}", host=cfg.remote, exit_wait=True) as srv:
> + wait_port_listen(cfg.comm_port, host=cfg.remote)
> +
> + cfg.comm_sock = socket.create_connection((cfg.remote_addr,
> + cfg.comm_port), timeout=1)
> +
> + cases = [
> + psp_ip_ver_test_builder(
> + "data_basic_send", _data_basic_send, version, ipver
> + )
> + for version in range(0, 4)
> + for ipver in ("4", "6")
> + ]
> + ksft_run(cases = cases, globs=globals(), case_pfx={"dev_", "data_"},
> + args=(cfg, ), skip_all=(cfg.psp_dev_id is None))
> + cfg.comm_sock.send(b"exit\0")
> + cfg.comm_sock.close()
> +
> + if versions is not None:
> + cfg.pspnl.dev_set({"id": cfg.psp_dev_id, "psp-versions-ena": versions})
> +
> + finally:
> + if srv.stdout or srv.stderr:
> + ksft_pr("")
> + ksft_pr(f"Responder logs ({srv.ret}):")
> + if srv.stdout:
> + ksft_pr("STDOUT:\n# " + srv.stdout.strip().replace("\n", "\n# "))
> + if srv.stderr:
> + ksft_pr("STDERR:\n# " + srv.stderr.strip().replace("\n", "\n# "))
> ksft_exit()
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH net-next 1/9] netdevsim: a basic test PSP implementation
2025-09-24 19:49 ` [PATCH net-next 1/9] netdevsim: a basic test PSP implementation Daniel Zahka
2025-09-25 0:12 ` Jakub Kicinski
2025-09-25 6:48 ` kernel test robot
@ 2025-09-26 15:30 ` Simon Horman
2025-09-26 15:35 ` Simon Horman
3 siblings, 0 replies; 19+ messages in thread
From: Simon Horman @ 2025-09-26 15:30 UTC (permalink / raw)
To: Daniel Zahka
Cc: Jakub Kicinski, Andrew Lunn, David S. Miller, Eric Dumazet,
Paolo Abeni, Shuah Khan, Willem de Bruijn, Breno Leitao,
Petr Machata, Yuyang Huang, Xiao Liang, Carolina Jubran,
Donald Hunter, netdev
On Wed, Sep 24, 2025 at 12:49:47PM -0700, Daniel Zahka wrote:
> From: Jakub Kicinski <kuba@kernel.org>
>
> Provide a PSP implementation for netdevsim.
>
> Use psp_dev_encapsulate() and psp_dev_rcv() to do actual encapsulation
> and decapsulation on skbs, but perform no encryption or decryption. In
> order to make encryption with a bad key result in a drop on the peer's
> rx side, we stash our psd's generation number in the first byte of each
> key before handing to the peer.
>
> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
> Co-developed-by: Daniel Zahka <daniel.zahka@gmail.com>
> Signed-off-by: Daniel Zahka <daniel.zahka@gmail.com>
...
> diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c
...
> @@ -1039,12 +1060,29 @@ static int nsim_init_netdevsim(struct netdevsim *ns)
> if (IS_ENABLED(CONFIG_DEBUG_NET)) {
> ns->nb.notifier_call = netdev_debug_event;
> if (register_netdevice_notifier_dev_net(ns->netdev, &ns->nb,
> - &ns->nn))
> + &ns->nn)){
> ns->nb.notifier_call = NULL;
> + goto err_unregister_netdev;
Hi Daniel, Jakub, all,
This will result in this function returning err.
But here err is set to 0, wheras it seems it
should be set to a negative error value.
Flagged by Smatch.
> + }
> }
>
> + err = nsim_psp_init(ns);
> + if (err)
> + goto err_unregister_notifier;
> +
> return 0;
>
> +err_unregister_notifier:
> + if (ns->nb.notifier_call)
> + unregister_netdevice_notifier_dev_net(ns->netdev, &ns->nb,
> + &ns->nn);
> +err_unregister_netdev:
> + rtnl_lock();
> + peer = rtnl_dereference(ns->peer);
> + if (peer)
> + RCU_INIT_POINTER(peer->peer, NULL);
> + RCU_INIT_POINTER(ns->peer, NULL);
> + unregister_netdevice(ns->netdev);
> err_ipsec_teardown:
> nsim_ipsec_teardown(ns);
> nsim_macsec_teardown(ns);
...
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH net-next 1/9] netdevsim: a basic test PSP implementation
2025-09-24 19:49 ` [PATCH net-next 1/9] netdevsim: a basic test PSP implementation Daniel Zahka
` (2 preceding siblings ...)
2025-09-26 15:30 ` Simon Horman
@ 2025-09-26 15:35 ` Simon Horman
3 siblings, 0 replies; 19+ messages in thread
From: Simon Horman @ 2025-09-26 15:35 UTC (permalink / raw)
To: Daniel Zahka
Cc: Jakub Kicinski, Andrew Lunn, David S. Miller, Eric Dumazet,
Paolo Abeni, Shuah Khan, Willem de Bruijn, Breno Leitao,
Petr Machata, Yuyang Huang, Xiao Liang, Carolina Jubran,
Donald Hunter, netdev
On Wed, Sep 24, 2025 at 12:49:47PM -0700, Daniel Zahka wrote:
> From: Jakub Kicinski <kuba@kernel.org>
>
> Provide a PSP implementation for netdevsim.
>
> Use psp_dev_encapsulate() and psp_dev_rcv() to do actual encapsulation
> and decapsulation on skbs, but perform no encryption or decryption. In
> order to make encryption with a bad key result in a drop on the peer's
> rx side, we stash our psd's generation number in the first byte of each
> key before handing to the peer.
>
> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
> Co-developed-by: Daniel Zahka <daniel.zahka@gmail.com>
> Signed-off-by: Daniel Zahka <daniel.zahka@gmail.com>
...
> diff --git a/drivers/net/netdevsim/psp.c b/drivers/net/netdevsim/psp.c
> new file mode 100644
> index 000000000000..cb568f89eb3e
> --- /dev/null
> +++ b/drivers/net/netdevsim/psp.c
> @@ -0,0 +1,218 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +
> +#include <linux/ip.h>
> +#include <linux/skbuff.h>
> +#include <net/ip6_checksum.h>
> +#include <net/psp.h>
> +#include <net/sock.h>
> +
> +#include "netdevsim.h"
> +
> +enum skb_drop_reason
> +nsim_do_psp(struct sk_buff *skb, struct netdevsim *ns,
> + struct netdevsim *peer_ns, struct skb_ext **psp_ext)
> +{
...
> + } else {
> + struct ipv6hdr *ip6h;
> + struct iphdr *iph;
> + struct udphdr *uh;
> + __wsum csum;
> +
> + /* Do not decapsulate. Receive the skb with the udp and psp
> + * headers still there as if this is a normal udp packet.
> + * psp_dev_encapsulate() sets udp checksum to 0, so we need to
> + * provide a valid checksum here, so the skb isn't dropped.
> + */
> + uh = udp_hdr(skb);
> + csum = skb_checksum(skb, skb_transport_offset(skb),
> + ntohs(uh->len), 0);
> +
> + switch (skb->protocol) {
> + case htons(ETH_P_IP):
> + iph = ip_hdr(skb);
> + uh->check = udp_v4_check(ntohs(uh->len), iph->saddr,
> + iph->daddr, csum);
> + break;
> +#if IS_ENABLED(CONFIG_IPV6)
> + case htons(ETH_P_IPV6):
> + ip6h = ipv6_hdr(skb);
ip6h is only used here. Which means that if CONFIG_IPV6 is not set then
compilers - e.g GCC 15.2.0 and Clang 21.1.1 - will warn when run with
-Wunused-variable.
Maybe no one cares. But if the scope of ip6h was reduced to here,
say by making this a block (using {}) and declaring iph6 inside it,
or using a helper, then things might be a bit cleaner.
> + uh->check = udp_v6_check(ntohs(uh->len), &ip6h->saddr,
> + &ip6h->daddr, csum);
> + break;
> +#endif
> + }
> +
> + uh->check = uh->check ?: CSUM_MANGLED_0;
> + skb->ip_summed = CHECKSUM_NONE;
> + }
> +
> +out_unlock:
> + rcu_read_unlock();
> + return rc;
> +}
...
^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2025-09-26 15:35 UTC | newest]
Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-24 19:49 [PATCH net-next 0/9] psp: add a kselftest suite and netdevsim implementation Daniel Zahka
2025-09-24 19:49 ` [PATCH net-next 1/9] netdevsim: a basic test PSP implementation Daniel Zahka
2025-09-25 0:12 ` Jakub Kicinski
2025-09-25 6:48 ` kernel test robot
2025-09-26 15:30 ` Simon Horman
2025-09-26 15:35 ` Simon Horman
2025-09-24 19:49 ` [PATCH net-next 2/9] selftests: net: add skip all feature to ksft_run() Daniel Zahka
2025-09-25 16:09 ` Petr Machata
2025-09-25 17:04 ` Daniel Zahka
2025-09-26 2:18 ` Jakub Kicinski
2025-09-24 19:49 ` [PATCH net-next 3/9] selftests: drv-net: base device access API test Daniel Zahka
2025-09-25 0:13 ` Jakub Kicinski
2025-09-24 19:49 ` [PATCH net-next 4/9] selftests: drv-net: add PSP responder Daniel Zahka
2025-09-24 19:49 ` [PATCH net-next 5/9] selftests: drv-net: psp: add basic data transfer and key rotation tests Daniel Zahka
2025-09-26 9:15 ` Petr Machata
2025-09-24 19:49 ` [PATCH net-next 6/9] selftests: drv-net: psp: add association tests Daniel Zahka
2025-09-24 19:49 ` [PATCH net-next 7/9] selftests: drv-net: psp: add connection breaking tests Daniel Zahka
2025-09-24 19:49 ` [PATCH net-next 8/9] selftests: drv-net: psp: add test for auto-adjusting TCP MSS Daniel Zahka
2025-09-24 19:49 ` [PATCH net-next 9/9] selftests: drv-net: psp: add tests for destroying devices Daniel Zahka
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).