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