Skip to content

Commit 2c0592b

Browse files
author
Paolo Abeni
committed
Merge branch 'psp-add-a-kselftest-suite-and-netdevsim-implementation'
Jakub Kicinski says: ==================== psp: add a kselftest suite and netdevsim implementation 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.data_basic_send_v0_ip4 ok 2 psp.data_basic_send_v0_ip6 ok 3 psp.data_basic_send_v1_ip4 ok 4 psp.data_basic_send_v1_ip6 ok 5 psp.data_basic_send_v2_ip4 # SKIP ('PSP version not supported', 'hdr0-aes-gmac-128') ok 6 psp.data_basic_send_v2_ip6 # SKIP ('PSP version not supported', 'hdr0-aes-gmac-128') ok 7 psp.data_basic_send_v3_ip4 # SKIP ('PSP version not supported', 'hdr0-aes-gmac-256') ok 8 psp.data_basic_send_v3_ip6 # SKIP ('PSP version not supported', 'hdr0-aes-gmac-256') ok 9 psp.data_mss_adjust_ip4 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:22 fail:0 xfail:2 xpass:0 skip:4 error:0 # # Responder logs (0): # STDERR: # Set PSP enable on device 1 to 0x3 # Set PSP enable on device 1 to 0x0 v2: https://lore.kernel.org/[email protected] v1: https://lore.kernel.org/[email protected] ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Paolo Abeni <[email protected]>
2 parents 9ebef94 + b3820e0 commit 2c0592b

File tree

16 files changed

+1440
-11
lines changed

16 files changed

+1440
-11
lines changed

drivers/net/netdevsim/Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ ifneq ($(CONFIG_PSAMPLE),)
1818
netdevsim-objs += psample.o
1919
endif
2020

21+
ifneq ($(CONFIG_INET_PSP),)
22+
netdevsim-objs += psp.o
23+
endif
24+
2125
ifneq ($(CONFIG_MACSEC),)
2226
netdevsim-objs += macsec.o
2327
endif

drivers/net/netdevsim/netdev.c

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -103,28 +103,42 @@ static int nsim_napi_rx(struct net_device *tx_dev, struct net_device *rx_dev,
103103
static int nsim_forward_skb(struct net_device *tx_dev,
104104
struct net_device *rx_dev,
105105
struct sk_buff *skb,
106-
struct nsim_rq *rq)
106+
struct nsim_rq *rq,
107+
struct skb_ext *psp_ext)
107108
{
108-
return __dev_forward_skb(rx_dev, skb) ?:
109-
nsim_napi_rx(tx_dev, rx_dev, rq, skb);
109+
int ret;
110+
111+
ret = __dev_forward_skb(rx_dev, skb);
112+
if (ret)
113+
return ret;
114+
115+
nsim_psp_handle_ext(skb, psp_ext);
116+
117+
return nsim_napi_rx(tx_dev, rx_dev, rq, skb);
110118
}
111119

112120
static netdev_tx_t nsim_start_xmit(struct sk_buff *skb, struct net_device *dev)
113121
{
114122
struct netdevsim *ns = netdev_priv(dev);
123+
struct skb_ext *psp_ext = NULL;
115124
struct net_device *peer_dev;
116125
unsigned int len = skb->len;
117126
struct netdevsim *peer_ns;
118127
struct netdev_config *cfg;
119128
struct nsim_rq *rq;
120129
int rxq;
130+
int dr;
121131

122132
rcu_read_lock();
123133
if (!nsim_ipsec_tx(ns, skb))
124-
goto out_drop_free;
134+
goto out_drop_any;
125135

126136
peer_ns = rcu_dereference(ns->peer);
127137
if (!peer_ns)
138+
goto out_drop_any;
139+
140+
dr = nsim_do_psp(skb, ns, peer_ns, &psp_ext);
141+
if (dr)
128142
goto out_drop_free;
129143

130144
peer_dev = peer_ns->netdev;
@@ -141,7 +155,8 @@ static netdev_tx_t nsim_start_xmit(struct sk_buff *skb, struct net_device *dev)
141155
skb_linearize(skb);
142156

143157
skb_tx_timestamp(skb);
144-
if (unlikely(nsim_forward_skb(dev, peer_dev, skb, rq) == NET_RX_DROP))
158+
if (unlikely(nsim_forward_skb(dev, peer_dev,
159+
skb, rq, psp_ext) == NET_RX_DROP))
145160
goto out_drop_cnt;
146161

147162
if (!hrtimer_active(&rq->napi_timer))
@@ -151,8 +166,10 @@ static netdev_tx_t nsim_start_xmit(struct sk_buff *skb, struct net_device *dev)
151166
dev_dstats_tx_add(dev, len);
152167
return NETDEV_TX_OK;
153168

169+
out_drop_any:
170+
dr = SKB_DROP_REASON_NOT_SPECIFIED;
154171
out_drop_free:
155-
dev_kfree_skb(skb);
172+
kfree_skb_reason(skb, dr);
156173
out_drop_cnt:
157174
rcu_read_unlock();
158175
dev_dstats_tx_dropped(dev);
@@ -1002,6 +1019,7 @@ static void nsim_queue_uninit(struct netdevsim *ns)
10021019

10031020
static int nsim_init_netdevsim(struct netdevsim *ns)
10041021
{
1022+
struct netdevsim *peer;
10051023
struct mock_phc *phc;
10061024
int err;
10071025

@@ -1036,6 +1054,10 @@ static int nsim_init_netdevsim(struct netdevsim *ns)
10361054
goto err_ipsec_teardown;
10371055
rtnl_unlock();
10381056

1057+
err = nsim_psp_init(ns);
1058+
if (err)
1059+
goto err_unregister_netdev;
1060+
10391061
if (IS_ENABLED(CONFIG_DEBUG_NET)) {
10401062
ns->nb.notifier_call = netdev_debug_event;
10411063
if (register_netdevice_notifier_dev_net(ns->netdev, &ns->nb,
@@ -1045,6 +1067,13 @@ static int nsim_init_netdevsim(struct netdevsim *ns)
10451067

10461068
return 0;
10471069

1070+
err_unregister_netdev:
1071+
rtnl_lock();
1072+
peer = rtnl_dereference(ns->peer);
1073+
if (peer)
1074+
RCU_INIT_POINTER(peer->peer, NULL);
1075+
RCU_INIT_POINTER(ns->peer, NULL);
1076+
unregister_netdevice(ns->netdev);
10481077
err_ipsec_teardown:
10491078
nsim_ipsec_teardown(ns);
10501079
nsim_macsec_teardown(ns);
@@ -1132,6 +1161,8 @@ void nsim_destroy(struct netdevsim *ns)
11321161
unregister_netdevice_notifier_dev_net(ns->netdev, &ns->nb,
11331162
&ns->nn);
11341163

1164+
nsim_psp_uninit(ns);
1165+
11351166
rtnl_lock();
11361167
peer = rtnl_dereference(ns->peer);
11371168
if (peer)

drivers/net/netdevsim/netdevsim.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,12 @@ struct netdevsim {
108108

109109
int rq_reset_mode;
110110

111+
struct {
112+
struct psp_dev *dev;
113+
u32 spi;
114+
u32 assoc_cnt;
115+
} psp;
116+
111117
struct nsim_bus_dev *nsim_bus_dev;
112118

113119
struct bpf_prog *bpf_offloaded;
@@ -421,6 +427,27 @@ static inline void nsim_macsec_teardown(struct netdevsim *ns)
421427
}
422428
#endif
423429

430+
#if IS_ENABLED(CONFIG_INET_PSP)
431+
int nsim_psp_init(struct netdevsim *ns);
432+
void nsim_psp_uninit(struct netdevsim *ns);
433+
void nsim_psp_handle_ext(struct sk_buff *skb, struct skb_ext *psp_ext);
434+
enum skb_drop_reason
435+
nsim_do_psp(struct sk_buff *skb, struct netdevsim *ns,
436+
struct netdevsim *peer_ns, struct skb_ext **psp_ext);
437+
#else
438+
static inline int nsim_psp_init(struct netdevsim *ns) { return 0; }
439+
static inline void nsim_psp_uninit(struct netdevsim *ns) {}
440+
static inline enum skb_drop_reason
441+
nsim_do_psp(struct sk_buff *skb, struct netdevsim *ns,
442+
struct netdevsim *peer_ns, struct skb_ext **psp_ext)
443+
{
444+
return 0;
445+
}
446+
447+
static inline void
448+
nsim_psp_handle_ext(struct sk_buff *skb, struct skb_ext *psp_ext) {}
449+
#endif
450+
424451
struct nsim_bus_dev {
425452
struct device dev;
426453
struct list_head list;

drivers/net/netdevsim/psp.c

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
#include <linux/ip.h>
4+
#include <linux/skbuff.h>
5+
#include <net/ip6_checksum.h>
6+
#include <net/psp.h>
7+
#include <net/sock.h>
8+
9+
#include "netdevsim.h"
10+
11+
void nsim_psp_handle_ext(struct sk_buff *skb, struct skb_ext *psp_ext)
12+
{
13+
if (psp_ext)
14+
__skb_ext_set(skb, SKB_EXT_PSP, psp_ext);
15+
}
16+
17+
enum skb_drop_reason
18+
nsim_do_psp(struct sk_buff *skb, struct netdevsim *ns,
19+
struct netdevsim *peer_ns, struct skb_ext **psp_ext)
20+
{
21+
enum skb_drop_reason rc = 0;
22+
struct psp_assoc *pas;
23+
struct net *net;
24+
void **ptr;
25+
26+
rcu_read_lock();
27+
pas = psp_skb_get_assoc_rcu(skb);
28+
if (!pas) {
29+
rc = SKB_NOT_DROPPED_YET;
30+
goto out_unlock;
31+
}
32+
33+
if (!skb_transport_header_was_set(skb)) {
34+
rc = SKB_DROP_REASON_PSP_OUTPUT;
35+
goto out_unlock;
36+
}
37+
38+
ptr = psp_assoc_drv_data(pas);
39+
if (*ptr != ns) {
40+
rc = SKB_DROP_REASON_PSP_OUTPUT;
41+
goto out_unlock;
42+
}
43+
44+
net = sock_net(skb->sk);
45+
if (!psp_dev_encapsulate(net, skb, pas->tx.spi, pas->version, 0)) {
46+
rc = SKB_DROP_REASON_PSP_OUTPUT;
47+
goto out_unlock;
48+
}
49+
50+
/* Now pretend we just received this frame */
51+
if (peer_ns->psp.dev->config.versions & (1 << pas->version)) {
52+
bool strip_icv = false;
53+
u8 generation;
54+
55+
/* We cheat a bit and put the generation in the key.
56+
* In real life if generation was too old, then decryption would
57+
* fail. Here, we just make it so a bad key causes a bad
58+
* generation too, and psp_sk_rx_policy_check() will fail.
59+
*/
60+
generation = pas->tx.key[0];
61+
62+
skb_ext_reset(skb);
63+
skb->mac_len = ETH_HLEN;
64+
if (psp_dev_rcv(skb, peer_ns->psp.dev->id, generation,
65+
strip_icv)) {
66+
rc = SKB_DROP_REASON_PSP_OUTPUT;
67+
goto out_unlock;
68+
}
69+
70+
*psp_ext = skb->extensions;
71+
refcount_inc(&(*psp_ext)->refcnt);
72+
skb->decrypted = 1;
73+
} else {
74+
struct ipv6hdr *ip6h __maybe_unused;
75+
struct iphdr *iph;
76+
struct udphdr *uh;
77+
__wsum csum;
78+
79+
/* Do not decapsulate. Receive the skb with the udp and psp
80+
* headers still there as if this is a normal udp packet.
81+
* psp_dev_encapsulate() sets udp checksum to 0, so we need to
82+
* provide a valid checksum here, so the skb isn't dropped.
83+
*/
84+
uh = udp_hdr(skb);
85+
csum = skb_checksum(skb, skb_transport_offset(skb),
86+
ntohs(uh->len), 0);
87+
88+
switch (skb->protocol) {
89+
case htons(ETH_P_IP):
90+
iph = ip_hdr(skb);
91+
uh->check = udp_v4_check(ntohs(uh->len), iph->saddr,
92+
iph->daddr, csum);
93+
break;
94+
#if IS_ENABLED(CONFIG_IPV6)
95+
case htons(ETH_P_IPV6):
96+
ip6h = ipv6_hdr(skb);
97+
uh->check = udp_v6_check(ntohs(uh->len), &ip6h->saddr,
98+
&ip6h->daddr, csum);
99+
break;
100+
#endif
101+
}
102+
103+
uh->check = uh->check ?: CSUM_MANGLED_0;
104+
skb->ip_summed = CHECKSUM_NONE;
105+
}
106+
107+
out_unlock:
108+
rcu_read_unlock();
109+
return rc;
110+
}
111+
112+
static int
113+
nsim_psp_set_config(struct psp_dev *psd, struct psp_dev_config *conf,
114+
struct netlink_ext_ack *extack)
115+
{
116+
return 0;
117+
}
118+
119+
static int
120+
nsim_rx_spi_alloc(struct psp_dev *psd, u32 version,
121+
struct psp_key_parsed *assoc,
122+
struct netlink_ext_ack *extack)
123+
{
124+
struct netdevsim *ns = psd->drv_priv;
125+
unsigned int new;
126+
int i;
127+
128+
new = ++ns->psp.spi & PSP_SPI_KEY_ID;
129+
if (psd->generation & 1)
130+
new |= PSP_SPI_KEY_PHASE;
131+
132+
assoc->spi = cpu_to_be32(new);
133+
assoc->key[0] = psd->generation;
134+
for (i = 1; i < PSP_MAX_KEY; i++)
135+
assoc->key[i] = ns->psp.spi + i;
136+
137+
return 0;
138+
}
139+
140+
static int nsim_assoc_add(struct psp_dev *psd, struct psp_assoc *pas,
141+
struct netlink_ext_ack *extack)
142+
{
143+
struct netdevsim *ns = psd->drv_priv;
144+
void **ptr = psp_assoc_drv_data(pas);
145+
146+
/* Copy drv_priv from psd to assoc */
147+
*ptr = psd->drv_priv;
148+
ns->psp.assoc_cnt++;
149+
150+
return 0;
151+
}
152+
153+
static int nsim_key_rotate(struct psp_dev *psd, struct netlink_ext_ack *extack)
154+
{
155+
return 0;
156+
}
157+
158+
static void nsim_assoc_del(struct psp_dev *psd, struct psp_assoc *pas)
159+
{
160+
struct netdevsim *ns = psd->drv_priv;
161+
void **ptr = psp_assoc_drv_data(pas);
162+
163+
*ptr = NULL;
164+
ns->psp.assoc_cnt--;
165+
}
166+
167+
static struct psp_dev_ops nsim_psp_ops = {
168+
.set_config = nsim_psp_set_config,
169+
.rx_spi_alloc = nsim_rx_spi_alloc,
170+
.tx_key_add = nsim_assoc_add,
171+
.tx_key_del = nsim_assoc_del,
172+
.key_rotate = nsim_key_rotate,
173+
};
174+
175+
static struct psp_dev_caps nsim_psp_caps = {
176+
.versions = 1 << PSP_VERSION_HDR0_AES_GCM_128 |
177+
1 << PSP_VERSION_HDR0_AES_GMAC_128 |
178+
1 << PSP_VERSION_HDR0_AES_GCM_256 |
179+
1 << PSP_VERSION_HDR0_AES_GMAC_256,
180+
.assoc_drv_spc = sizeof(void *),
181+
};
182+
183+
void nsim_psp_uninit(struct netdevsim *ns)
184+
{
185+
if (!IS_ERR(ns->psp.dev))
186+
psp_dev_unregister(ns->psp.dev);
187+
WARN_ON(ns->psp.assoc_cnt);
188+
}
189+
190+
static ssize_t
191+
nsim_psp_rereg_write(struct file *file, const char __user *data, size_t count,
192+
loff_t *ppos)
193+
{
194+
struct netdevsim *ns = file->private_data;
195+
int err;
196+
197+
nsim_psp_uninit(ns);
198+
199+
ns->psp.dev = psp_dev_create(ns->netdev, &nsim_psp_ops,
200+
&nsim_psp_caps, ns);
201+
err = PTR_ERR_OR_ZERO(ns->psp.dev);
202+
return err ?: count;
203+
}
204+
205+
static const struct file_operations nsim_psp_rereg_fops = {
206+
.open = simple_open,
207+
.write = nsim_psp_rereg_write,
208+
.llseek = generic_file_llseek,
209+
.owner = THIS_MODULE,
210+
};
211+
212+
int nsim_psp_init(struct netdevsim *ns)
213+
{
214+
struct dentry *ddir = ns->nsim_dev_port->ddir;
215+
int err;
216+
217+
ns->psp.dev = psp_dev_create(ns->netdev, &nsim_psp_ops,
218+
&nsim_psp_caps, ns);
219+
err = PTR_ERR_OR_ZERO(ns->psp.dev);
220+
if (err)
221+
return err;
222+
223+
debugfs_create_file("psp_rereg", 0200, ddir, ns, &nsim_psp_rereg_fops);
224+
return 0;
225+
}

net/core/skbuff.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7048,6 +7048,7 @@ void *__skb_ext_set(struct sk_buff *skb, enum skb_ext_id id,
70487048
skb->active_extensions = 1 << id;
70497049
return skb_ext_get_ptr(ext, id);
70507050
}
7051+
EXPORT_SYMBOL_NS_GPL(__skb_ext_set, "NETDEV_INTERNAL");
70517052

70527053
/**
70537054
* skb_ext_add - allocate space for given extension, COW if needed

0 commit comments

Comments
 (0)