1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2 /* Copyright (C) 2018 Netronome Systems, Inc */
3 /* Copyright (C) 2021 Corigine, Inc */
4 
5 #include <linux/module.h>
6 #include <linux/kernel.h>
7 #include <linux/init.h>
8 #include <linux/netdevice.h>
9 #include <asm/unaligned.h>
10 #include <linux/ktime.h>
11 #include <net/xfrm.h>
12 
13 #include "../nfp_net_ctrl.h"
14 #include "../nfp_net.h"
15 #include "crypto.h"
16 
17 #define NFP_NET_IPSEC_MAX_SA_CNT  (16 * 1024) /* Firmware support a maximum of 16K SA offload */
18 
19 static int nfp_net_xfrm_add_state(struct xfrm_state *x)
20 {
21 	return -EOPNOTSUPP;
22 }
23 
24 static void nfp_net_xfrm_del_state(struct xfrm_state *x)
25 {
26 }
27 
28 static bool nfp_net_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *x)
29 {
30 	return false;
31 }
32 
33 static const struct xfrmdev_ops nfp_net_ipsec_xfrmdev_ops = {
34 	.xdo_dev_state_add = nfp_net_xfrm_add_state,
35 	.xdo_dev_state_delete = nfp_net_xfrm_del_state,
36 	.xdo_dev_offload_ok = nfp_net_ipsec_offload_ok,
37 };
38 
39 void nfp_net_ipsec_init(struct nfp_net *nn)
40 {
41 	if (!(nn->cap_w1 & NFP_NET_CFG_CTRL_IPSEC))
42 		return;
43 
44 	xa_init_flags(&nn->xa_ipsec, XA_FLAGS_ALLOC);
45 	nn->dp.netdev->xfrmdev_ops = &nfp_net_ipsec_xfrmdev_ops;
46 }
47 
48 void nfp_net_ipsec_clean(struct nfp_net *nn)
49 {
50 	if (!(nn->cap_w1 & NFP_NET_CFG_CTRL_IPSEC))
51 		return;
52 
53 	WARN_ON(!xa_empty(&nn->xa_ipsec));
54 	xa_destroy(&nn->xa_ipsec);
55 }
56 
57 bool nfp_net_ipsec_tx_prep(struct nfp_net_dp *dp, struct sk_buff *skb,
58 			   struct nfp_ipsec_offload *offload_info)
59 {
60 	struct xfrm_offload *xo = xfrm_offload(skb);
61 	struct xfrm_state *x;
62 
63 	x = xfrm_input_state(skb);
64 	if (!x)
65 		return false;
66 
67 	offload_info->seq_hi = xo->seq.hi;
68 	offload_info->seq_low = xo->seq.low;
69 	offload_info->handle = x->xso.offload_handle;
70 
71 	return true;
72 }
73 
74 int nfp_net_ipsec_rx(struct nfp_meta_parsed *meta, struct sk_buff *skb)
75 {
76 	struct net_device *netdev = skb->dev;
77 	struct xfrm_offload *xo;
78 	struct xfrm_state *x;
79 	struct sec_path *sp;
80 	struct nfp_net *nn;
81 	u32 saidx;
82 
83 	nn = netdev_priv(netdev);
84 
85 	saidx = meta->ipsec_saidx - 1;
86 	if (saidx >= NFP_NET_IPSEC_MAX_SA_CNT)
87 		return -EINVAL;
88 
89 	sp = secpath_set(skb);
90 	if (unlikely(!sp))
91 		return -ENOMEM;
92 
93 	xa_lock(&nn->xa_ipsec);
94 	x = xa_load(&nn->xa_ipsec, saidx);
95 	xa_unlock(&nn->xa_ipsec);
96 	if (!x)
97 		return -EINVAL;
98 
99 	xfrm_state_hold(x);
100 	sp->xvec[sp->len++] = x;
101 	sp->olen++;
102 	xo = xfrm_offload(skb);
103 	xo->flags = CRYPTO_DONE;
104 	xo->status = CRYPTO_SUCCESS;
105 
106 	return 0;
107 }
108