Netdev List
 help / color / mirror / Atom feed
From: Daniel Zahka <daniel.zahka@gmail.com>
To: Jakub Kicinski <kuba@kernel.org>,
	Andrew Lunn <andrew+netdev@lunn.ch>,
	 "David S. Miller" <davem@davemloft.net>,
	Eric Dumazet <edumazet@google.com>,
	 Paolo Abeni <pabeni@redhat.com>,
	 Willem de Bruijn <willemdebruijn.kernel@gmail.com>
Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH net-next 3/6] netdevsim: psp: move rx processing into nsim_poll()
Date: Fri, 08 May 2026 07:53:46 -0700	[thread overview]
Message-ID: <20260508-nsim-psp-crypto-v1-3-4b50ed09b794@gmail.com> (raw)
In-Reply-To: <20260508-nsim-psp-crypto-v1-0-4b50ed09b794@gmail.com>

nsim_do_psp() does PSP decap and skb extension creation in the tx
path. This has the slightly undesirable property of not allowing the
psp rx code to run on PSP packets cooked up in userspace and
transmitted on a packet socket from the peer dev (e.g. packetdrill).

This commit instead triggers the psp rx path just based on parsing the
received skb. The current code relies on a bit of a hack to simulate
authentication with the proper key: the peer's psd->generation was
placed into the tx key, and during decap used to fill out the
extension the packet before being sent up the psp rx path. This commit
removes that hack, which creates a transient break in psp.py test
cases that rely on this behavior (e.g. data_send_bad_key). Subsequent
commits which introduce real aes-gcm crypto will restore the correct
behavior.

Assisted-by: Claude:claude-opus-4.6
Signed-off-by: Daniel Zahka <daniel.zahka@gmail.com>
---
 drivers/net/netdevsim/netdev.c    |  18 ++---
 drivers/net/netdevsim/netdevsim.h |  14 ++--
 drivers/net/netdevsim/psp.c       | 143 ++++++++++++++++++++++++++------------
 3 files changed, 113 insertions(+), 62 deletions(-)

diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c
index a750768912b5..9c0db7b91fd6 100644
--- a/drivers/net/netdevsim/netdev.c
+++ b/drivers/net/netdevsim/netdev.c
@@ -103,19 +103,13 @@ 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 skb_ext *psp_ext)
+			    struct nsim_rq *rq)
 {
 	int ret;
 
 	ret = __dev_forward_skb(rx_dev, skb);
-	if (ret) {
-		if (psp_ext)
-			__skb_ext_put(psp_ext);
+	if (ret)
 		return ret;
-	}
-
-	nsim_psp_handle_ext(skb, psp_ext);
 
 	return nsim_napi_rx(tx_dev, rx_dev, rq, skb);
 }
@@ -123,7 +117,6 @@ static int nsim_forward_skb(struct net_device *tx_dev,
 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;
@@ -147,7 +140,7 @@ static netdev_tx_t nsim_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		peer_dev = peer_ns->netdev;
 	}
 
-	dr = nsim_do_psp(skb, ns, peer_ns, &psp_ext);
+	dr = nsim_psp_handle_tx(skb, ns);
 	if (dr)
 		goto out_drop_free;
 
@@ -165,7 +158,7 @@ static netdev_tx_t nsim_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	skb_tx_timestamp(skb);
 	if (unlikely(nsim_forward_skb(dev, peer_dev,
-				      skb, rq, psp_ext) == NET_RX_DROP))
+				      skb, rq) == NET_RX_DROP))
 		goto out_drop_cnt;
 
 	if (!hrtimer_active(&rq->napi_timer))
@@ -379,6 +372,9 @@ static int nsim_rcv(struct nsim_rq *rq, int budget)
 
 		skb = skb_dequeue(&rq->skb_queue);
 
+		if (nsim_psp_handle_rx(ns, skb))
+			continue;
+
 		if (xdp_prog) {
 			/* skb might be freed directly by XDP, save the len */
 			skblen = skb->len;
diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h
index d909c4160ea1..dcea76429bac 100644
--- a/drivers/net/netdevsim/netdevsim.h
+++ b/drivers/net/netdevsim/netdevsim.h
@@ -451,22 +451,22 @@ static inline void nsim_macsec_teardown(struct netdevsim *ns)
 #if IS_ENABLED(CONFIG_INET_PSP)
 int nsim_psp_init(struct netdevsim *ns);
 void nsim_psp_uninit(struct netdevsim *ns);
-void nsim_psp_handle_ext(struct sk_buff *skb, struct skb_ext *psp_ext);
 enum skb_drop_reason
-nsim_do_psp(struct sk_buff *skb, struct netdevsim *ns,
-	    struct netdevsim *peer_ns, struct skb_ext **psp_ext);
+nsim_psp_handle_tx(struct sk_buff *skb, struct netdevsim *ns);
+bool nsim_psp_handle_rx(struct netdevsim *ns, struct sk_buff *skb);
 #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)
+nsim_psp_handle_tx(struct sk_buff *skb, struct netdevsim *ns)
 {
 	return 0;
 }
 
-static inline void
-nsim_psp_handle_ext(struct sk_buff *skb, struct skb_ext *psp_ext) {}
+static inline bool nsim_psp_handle_rx(struct netdevsim *ns, struct sk_buff *skb)
+{
+	return false;
+}
 #endif
 
 int nsim_setup_tc(struct net_device *dev, enum tc_setup_type type,
diff --git a/drivers/net/netdevsim/psp.c b/drivers/net/netdevsim/psp.c
index 75740e2a731f..e8831d4bf394 100644
--- a/drivers/net/netdevsim/psp.c
+++ b/drivers/net/netdevsim/psp.c
@@ -6,18 +6,10 @@
 
 #include "netdevsim.h"
 
-void nsim_psp_handle_ext(struct sk_buff *skb, struct skb_ext *psp_ext)
-{
-	if (psp_ext)
-		__skb_ext_set(skb, SKB_EXT_PSP, psp_ext);
-}
-
 enum skb_drop_reason
-nsim_do_psp(struct sk_buff *skb, struct netdevsim *ns,
-	    struct netdevsim *peer_ns, struct skb_ext **psp_ext)
+nsim_psp_handle_tx(struct sk_buff *skb, struct netdevsim *ns)
 {
 	enum skb_drop_reason rc = 0;
-	struct psp_dev *peer_psd;
 	struct psp_assoc *pas;
 	struct net *net;
 	void **ptr;
@@ -46,47 +38,110 @@ nsim_do_psp(struct sk_buff *skb, struct netdevsim *ns,
 		goto out_unlock;
 	}
 
-	/* Now pretend we just received this frame */
-	peer_psd = rcu_dereference(peer_ns->psp.dev);
-	if (peer_psd && peer_psd->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_psd->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;
-
-		u64_stats_update_begin(&ns->psp.syncp);
-		u64_stats_inc(&ns->psp.tx_packets);
-		u64_stats_inc(&ns->psp.rx_packets);
-		u64_stats_add(&ns->psp.tx_bytes,
-			      skb->len - skb_inner_transport_offset(skb));
-		u64_stats_add(&ns->psp.rx_bytes,
-			      skb->len - skb_inner_transport_offset(skb));
-		u64_stats_update_end(&ns->psp.syncp);
-	} else {
-		skb->ip_summed	= CHECKSUM_NONE;
-	}
+	skb->decrypted = 0;
 
+	u64_stats_update_begin(&ns->psp.syncp);
+	u64_stats_inc(&ns->psp.tx_packets);
+	u64_stats_add(&ns->psp.tx_bytes,
+		      skb->len - skb_inner_transport_offset(skb));
+	u64_stats_update_end(&ns->psp.syncp);
 out_unlock:
 	rcu_read_unlock();
 	return rc;
 }
 
+/* Returns true if skb was consumed, false otherwise. */
+bool nsim_psp_handle_rx(struct netdevsim *ns, struct sk_buff *skb)
+{
+	struct psp_dev *psd;
+	struct psphdr *psph;
+	struct udphdr *uh;
+	int payload_len;
+	u32 versions;
+	int psp_off;
+	bool is_udp;
+	int l3_hlen;
+	u8 version;
+	u32 psd_id;
+	int err;
+
+	if (skb->protocol == htons(ETH_P_IP)) {
+		struct iphdr *iph;
+
+		if (!pskb_may_pull(skb, sizeof(struct iphdr)))
+			return false;
+
+		iph = (struct iphdr *)skb->data;
+		if (iph->ihl < 5)
+			return false;
+
+		is_udp = iph->protocol == IPPROTO_UDP;
+		l3_hlen = iph->ihl * 4;
+	} else if (skb->protocol == htons(ETH_P_IPV6)) {
+		struct ipv6hdr *ip6h;
+
+		if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
+			return false;
+		ip6h = (struct ipv6hdr *)skb->data;
+		is_udp = ip6h->nexthdr == IPPROTO_UDP;
+		l3_hlen = sizeof(struct ipv6hdr);
+	} else {
+		return false;
+	}
+
+	if (!is_udp)
+		return false;
+
+	if (!pskb_may_pull(skb, l3_hlen + sizeof(struct udphdr) + PSP_HDR_SIZE))
+		return false;
+
+	uh = (struct udphdr *)(skb->data + l3_hlen);
+	if (uh->dest != htons(PSP_DEFAULT_UDP_PORT))
+		return false;
+
+	psph = (struct psphdr *)(uh + 1);
+	version = FIELD_GET(PSPHDR_VERFL_VERSION, psph->verfl);
+
+	rcu_read_lock();
+	psd = rcu_dereference(ns->psp.dev);
+	if (psd) {
+		versions = READ_ONCE(psd->config.versions);
+		psd_id = psd->id;
+	}
+	rcu_read_unlock();
+
+	if (!psd || !(versions & (1 << version))) {
+		skb->ip_summed = CHECKSUM_NONE;
+		return false;
+	}
+
+	psp_off = l3_hlen + sizeof(struct udphdr);
+	payload_len = skb->len - psp_off - PSP_HDR_SIZE - PSP_TRL_SIZE;
+	if (payload_len < 0)
+		goto drop;
+
+	skb_push(skb, ETH_HLEN);
+	skb->mac_len = ETH_HLEN;
+	err = psp_dev_rcv(skb, psd_id, 0, false);
+	if (err)
+		goto drop;
+
+	skb_reset_mac_header(skb);
+	skb_pull(skb, ETH_HLEN);
+	skb->decrypted = 1;
+
+	u64_stats_update_begin(&ns->psp.syncp);
+	u64_stats_inc(&ns->psp.rx_packets);
+	u64_stats_add(&ns->psp.rx_bytes, payload_len);
+	u64_stats_update_end(&ns->psp.syncp);
+
+	return false;
+
+drop:
+	kfree_skb_reason(skb, SKB_DROP_REASON_PSP_INPUT);
+	return true;
+}
+
 static int
 nsim_psp_set_config(struct psp_dev *psd, struct psp_dev_config *conf,
 		    struct netlink_ext_ack *extack)

-- 
2.52.0


  parent reply	other threads:[~2026-05-08 14:54 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-08 14:53 [PATCH net-next 0/6] netdevsim: psp: implement real crypto operations from the PSP spec Daniel Zahka
2026-05-08 14:53 ` [PATCH net-next 1/6] netdevsim: psp: reset spi on key rotation and check for exhaustion on alloc Daniel Zahka
2026-05-11 16:53   ` Willem de Bruijn
2026-05-08 14:53 ` [PATCH net-next 2/6] netdevsim: psp: remove unnecessary UDP checksum computation Daniel Zahka
2026-05-11 17:01   ` Willem de Bruijn
2026-05-11 17:46     ` Daniel Zahka
2026-05-11 19:01       ` Willem de Bruijn
2026-05-11 19:43         ` Daniel Zahka
2026-05-08 14:53 ` Daniel Zahka [this message]
2026-05-11 20:03   ` [PATCH net-next 3/6] netdevsim: psp: move rx processing into nsim_poll() Willem de Bruijn
2026-05-12  0:25     ` Daniel Zahka
2026-05-12  0:51       ` Willem de Bruijn
2026-05-08 14:53 ` [PATCH net-next 4/6] netdevsim: psp: implement kdf from psp spec Daniel Zahka
2026-05-11 19:49   ` Willem de Bruijn
2026-05-11 23:55     ` Daniel Zahka
2026-05-12  0:48       ` Willem de Bruijn
2026-05-08 14:53 ` [PATCH net-next 5/6] netdevsim: psp: add real aes-gcm encryption and decryption Daniel Zahka
2026-05-11 20:10   ` Willem de Bruijn
2026-05-08 14:53 ` [PATCH net-next 6/6] netdevsim: psp: count rx authentication and length errors Daniel Zahka
2026-05-11 20:19   ` Willem de Bruijn

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260508-nsim-psp-crypto-v1-3-4b50ed09b794@gmail.com \
    --to=daniel.zahka@gmail.com \
    --cc=andrew+netdev@lunn.ch \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=willemdebruijn.kernel@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox