[PATCH net-next v5.0 17/19] psp: provide decapsulation and receive helper for drivers
From: Daniel Zahka <daniel.zahka@gmail.com>
Date: 2025-07-23 20:35:41
Subsystem:
networking [general], psp security protocol, the rest · Maintainers:
"David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Daniel Zahka, Willem de Bruijn, Linus Torvalds
From: Raed Salem <redacted>
Create psp_rcv(), which drivers can call to psp decapsulate and attach
a psp_skb_ext to an skb.
psp_rcv() only supports what the PSP architecture specification refers
to as "transport mode" packets, where the L3 header is IPv6. psp_rcv()
also assumes that a psp trailer is present and should be pulled from
the skb.
Signed-off-by: Raed Salem <redacted>
Signed-off-by: Rahul Rameshbabu <rrameshbabu@nvidia.com>
Signed-off-by: Cosmin Ratiu <redacted>
Signed-off-by: Daniel Zahka <daniel.zahka@gmail.com>
---
Notes:
v4:
- rename psp_rcv() to psp_dev_rcv()
- add strip_icv param psp_dev_rcv() to make trailer stripping optional
v3:
- patch introduced
include/net/psp/functions.h | 1 +
net/psp/psp_main.c | 53 +++++++++++++++++++++++++++++++++++++
2 files changed, 54 insertions(+)
diff --git a/include/net/psp/functions.h b/include/net/psp/functions.h
index 460af903a35a..3afb48e23f47 100644
--- a/include/net/psp/functions.h
+++ b/include/net/psp/functions.h@@ -18,6 +18,7 @@ psp_dev_create(struct net_device *netdev, struct psp_dev_ops *psd_ops, void psp_dev_unregister(struct psp_dev *psd); bool psp_dev_encapsulate(struct net *net, struct sk_buff *skb, __be32 spi, u8 ver, __be16 sport); +int psp_dev_rcv(struct sk_buff *skb, u16 dev_id, u8 generation, bool strip_icv); /* Kernel-facing API */ void psp_assoc_put(struct psp_assoc *pas);
diff --git a/net/psp/psp_main.c b/net/psp/psp_main.c
index 434ff6dac18f..437cd3c7f9eb 100644
--- a/net/psp/psp_main.c
+++ b/net/psp/psp_main.c@@ -210,6 +210,59 @@ bool psp_dev_encapsulate(struct net *net, struct sk_buff *skb, } EXPORT_SYMBOL(psp_dev_encapsulate); +/* Receive handler for PSP packets. + * + * Presently it accepts only already-authenticated packets and does not + * support optional fields, such as virtualization cookies. + */ +int psp_dev_rcv(struct sk_buff *skb, u16 dev_id, u8 generation, bool strip_icv) +{ + const struct psphdr *psph; + int depth = 0, end_depth; + struct psp_skb_ext *pse; + struct ipv6hdr *ipv6h; + struct ethhdr *eth; + int encap_bytes; + __be16 proto; + + eth = (struct ethhdr *)(skb->data); + proto = __vlan_get_protocol(skb, eth->h_proto, &depth); + if (proto != htons(ETH_P_IPV6)) + return -EINVAL; + + ipv6h = (struct ipv6hdr *)(skb->data + depth); + depth += sizeof(*ipv6h); + end_depth = depth + sizeof(struct udphdr) + sizeof(struct psphdr); + + if (unlikely(end_depth > skb_headlen(skb))) + return -EINVAL; + + pse = skb_ext_add(skb, SKB_EXT_PSP); + if (!pse) + return -EINVAL; + + psph = (const struct psphdr *)(skb->data + depth + sizeof(struct udphdr)); + pse->spi = psph->spi; + pse->dev_id = dev_id; + pse->generation = generation; + pse->version = FIELD_GET(PSPHDR_VERFL_VERSION, psph->verfl); + + ipv6h->nexthdr = psph->nexthdr; + + encap_bytes = PSP_ENCAP_HLEN; + encap_bytes += strip_icv ? PSP_TRL_SIZE : 0; + ipv6h->payload_len = htons(ntohs(ipv6h->payload_len) - encap_bytes); + + memmove(skb->data + PSP_ENCAP_HLEN, skb->data, depth); + skb_pull(skb, PSP_ENCAP_HLEN); + + if (strip_icv) + pskb_trim(skb, skb->len - PSP_TRL_SIZE); + + return 0; +} +EXPORT_SYMBOL(psp_dev_rcv); + static int __init psp_init(void) { mutex_init(&psp_devs_lock);
--
2.47.1