Skip to content

Commit 436396f

Browse files
wanghuanhuan12kuba-moo
authored andcommitted
nfp: support IPsec offloading for NFP3800
Add IPsec offloading support for NFP3800. Include data plane and control plane. Data plane: add IPsec packet process flow in NFP3800 datapath (NFDk). Control plane: add an algorithm support distinction flow in xfrm hook function xdo_dev_state_add(), as NFP3800 has a different set of IPsec algorithm support. This matches existing support for the NFP6000/NFP4000 and their NFD3 datapath. In addition, fixup the md_bytes calculation for NFD3 datapath to make sure the two datapahts are keept in sync. Signed-off-by: Huanhuan Wang <huanhuan.wang@corigine.com> Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com> Signed-off-by: Simon Horman <simon.horman@corigine.com> Reviewed-by: Leon Romanovsky <leonro@nvidia.com> Link: https://lore.kernel.org/r/20230208091000.4139974-1-simon.horman@corigine.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent 2894d35 commit 436396f

File tree

6 files changed

+83
-13
lines changed

6 files changed

+83
-13
lines changed

drivers/net/ethernet/netronome/nfp/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ nfp-objs += \
8080
abm/main.o
8181
endif
8282

83-
nfp-$(CONFIG_NFP_NET_IPSEC) += crypto/ipsec.o nfd3/ipsec.o
83+
nfp-$(CONFIG_NFP_NET_IPSEC) += crypto/ipsec.o nfd3/ipsec.o nfdk/ipsec.o
8484

8585
nfp-$(CONFIG_NFP_DEBUG) += nfp_net_debugfs.o
8686

drivers/net/ethernet/netronome/nfp/crypto/ipsec.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <linux/ktime.h>
1111
#include <net/xfrm.h>
1212

13+
#include "../nfpcore/nfp_dev.h"
1314
#include "../nfp_net_ctrl.h"
1415
#include "../nfp_net.h"
1516
#include "crypto.h"
@@ -330,6 +331,10 @@ static int nfp_net_xfrm_add_state(struct xfrm_state *x,
330331
trunc_len = -1;
331332
break;
332333
case SADB_AALG_MD5HMAC:
334+
if (nn->pdev->device == PCI_DEVICE_ID_NFP3800) {
335+
NL_SET_ERR_MSG_MOD(extack, "Unsupported authentication algorithm");
336+
return -EINVAL;
337+
}
333338
set_md5hmac(cfg, &trunc_len);
334339
break;
335340
case SADB_AALG_SHA1HMAC:
@@ -373,6 +378,10 @@ static int nfp_net_xfrm_add_state(struct xfrm_state *x,
373378
cfg->ctrl_word.cipher = NFP_IPSEC_CIPHER_NULL;
374379
break;
375380
case SADB_EALG_3DESCBC:
381+
if (nn->pdev->device == PCI_DEVICE_ID_NFP3800) {
382+
NL_SET_ERR_MSG_MOD(extack, "Unsupported encryption algorithm for offload");
383+
return -EINVAL;
384+
}
376385
cfg->ctrl_word.cimode = NFP_IPSEC_CIMODE_CBC;
377386
cfg->ctrl_word.cipher = NFP_IPSEC_CIPHER_3DES;
378387
break;

drivers/net/ethernet/netronome/nfp/nfd3/dp.c

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -192,10 +192,10 @@ static int nfp_nfd3_prep_tx_meta(struct nfp_net_dp *dp, struct sk_buff *skb,
192192
return 0;
193193

194194
md_bytes = sizeof(meta_id) +
195-
!!md_dst * NFP_NET_META_PORTID_SIZE +
196-
!!tls_handle * NFP_NET_META_CONN_HANDLE_SIZE +
197-
vlan_insert * NFP_NET_META_VLAN_SIZE +
198-
*ipsec * NFP_NET_META_IPSEC_FIELD_SIZE; /* IPsec has 12 bytes of metadata */
195+
(!!md_dst ? NFP_NET_META_PORTID_SIZE : 0) +
196+
(!!tls_handle ? NFP_NET_META_CONN_HANDLE_SIZE : 0) +
197+
(vlan_insert ? NFP_NET_META_VLAN_SIZE : 0) +
198+
(*ipsec ? NFP_NET_META_IPSEC_FIELD_SIZE : 0);
199199

200200
if (unlikely(skb_cow_head(skb, md_bytes)))
201201
return -ENOMEM;
@@ -226,9 +226,6 @@ static int nfp_nfd3_prep_tx_meta(struct nfp_net_dp *dp, struct sk_buff *skb,
226226
meta_id |= NFP_NET_META_VLAN;
227227
}
228228
if (*ipsec) {
229-
/* IPsec has three consecutive 4-bit IPsec metadata types,
230-
* so in total IPsec has three 4 bytes of metadata.
231-
*/
232229
data -= NFP_NET_META_IPSEC_SIZE;
233230
put_unaligned_be32(offload_info.seq_hi, data);
234231
data -= NFP_NET_META_IPSEC_SIZE;

drivers/net/ethernet/netronome/nfp/nfdk/dp.c

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <linux/overflow.h>
77
#include <linux/sizes.h>
88
#include <linux/bitfield.h>
9+
#include <net/xfrm.h>
910

1011
#include "../nfp_app.h"
1112
#include "../nfp_net.h"
@@ -172,25 +173,32 @@ nfp_nfdk_tx_maybe_close_block(struct nfp_net_tx_ring *tx_ring,
172173

173174
static int
174175
nfp_nfdk_prep_tx_meta(struct nfp_net_dp *dp, struct nfp_app *app,
175-
struct sk_buff *skb)
176+
struct sk_buff *skb, bool *ipsec)
176177
{
177178
struct metadata_dst *md_dst = skb_metadata_dst(skb);
179+
struct nfp_ipsec_offload offload_info;
178180
unsigned char *data;
179181
bool vlan_insert;
180182
u32 meta_id = 0;
181183
int md_bytes;
182184

185+
#ifdef CONFIG_NFP_NET_IPSEC
186+
if (xfrm_offload(skb))
187+
*ipsec = nfp_net_ipsec_tx_prep(dp, skb, &offload_info);
188+
#endif
189+
183190
if (unlikely(md_dst && md_dst->type != METADATA_HW_PORT_MUX))
184191
md_dst = NULL;
185192

186193
vlan_insert = skb_vlan_tag_present(skb) && (dp->ctrl & NFP_NET_CFG_CTRL_TXVLAN_V2);
187194

188-
if (!(md_dst || vlan_insert))
195+
if (!(md_dst || vlan_insert || *ipsec))
189196
return 0;
190197

191198
md_bytes = sizeof(meta_id) +
192-
!!md_dst * NFP_NET_META_PORTID_SIZE +
193-
vlan_insert * NFP_NET_META_VLAN_SIZE;
199+
(!!md_dst ? NFP_NET_META_PORTID_SIZE : 0) +
200+
(vlan_insert ? NFP_NET_META_VLAN_SIZE : 0) +
201+
(*ipsec ? NFP_NET_META_IPSEC_FIELD_SIZE : 0);
194202

195203
if (unlikely(skb_cow_head(skb, md_bytes)))
196204
return -ENOMEM;
@@ -212,6 +220,17 @@ nfp_nfdk_prep_tx_meta(struct nfp_net_dp *dp, struct nfp_app *app,
212220
meta_id |= NFP_NET_META_VLAN;
213221
}
214222

223+
if (*ipsec) {
224+
data -= NFP_NET_META_IPSEC_SIZE;
225+
put_unaligned_be32(offload_info.seq_hi, data);
226+
data -= NFP_NET_META_IPSEC_SIZE;
227+
put_unaligned_be32(offload_info.seq_low, data);
228+
data -= NFP_NET_META_IPSEC_SIZE;
229+
put_unaligned_be32(offload_info.handle - 1, data);
230+
meta_id <<= NFP_NET_META_IPSEC_FIELD_SIZE;
231+
meta_id |= NFP_NET_META_IPSEC << 8 | NFP_NET_META_IPSEC << 4 | NFP_NET_META_IPSEC;
232+
}
233+
215234
meta_id = FIELD_PREP(NFDK_META_LEN, md_bytes) |
216235
FIELD_PREP(NFDK_META_FIELDS, meta_id);
217236

@@ -243,6 +262,7 @@ netdev_tx_t nfp_nfdk_tx(struct sk_buff *skb, struct net_device *netdev)
243262
struct nfp_net_dp *dp;
244263
int nr_frags, wr_idx;
245264
dma_addr_t dma_addr;
265+
bool ipsec = false;
246266
u64 metadata;
247267

248268
dp = &nn->dp;
@@ -263,7 +283,7 @@ netdev_tx_t nfp_nfdk_tx(struct sk_buff *skb, struct net_device *netdev)
263283
return NETDEV_TX_BUSY;
264284
}
265285

266-
metadata = nfp_nfdk_prep_tx_meta(dp, nn->app, skb);
286+
metadata = nfp_nfdk_prep_tx_meta(dp, nn->app, skb, &ipsec);
267287
if (unlikely((int)metadata < 0))
268288
goto err_flush;
269289

@@ -361,6 +381,9 @@ netdev_tx_t nfp_nfdk_tx(struct sk_buff *skb, struct net_device *netdev)
361381

362382
(txd - 1)->dma_len_type = cpu_to_le16(dlen_type | NFDK_DESC_TX_EOP);
363383

384+
if (ipsec)
385+
metadata = nfp_nfdk_ipsec_tx(metadata, skb);
386+
364387
if (!skb_is_gso(skb)) {
365388
real_len = skb->len;
366389
/* Metadata desc */
@@ -760,6 +783,15 @@ nfp_nfdk_parse_meta(struct net_device *netdev, struct nfp_meta_parsed *meta,
760783
return false;
761784
data += sizeof(struct nfp_net_tls_resync_req);
762785
break;
786+
#ifdef CONFIG_NFP_NET_IPSEC
787+
case NFP_NET_META_IPSEC:
788+
/* Note: IPsec packet could have zero saidx, so need add 1
789+
* to indicate packet is IPsec packet within driver.
790+
*/
791+
meta->ipsec_saidx = get_unaligned_be32(data) + 1;
792+
data += 4;
793+
break;
794+
#endif
763795
default:
764796
return true;
765797
}
@@ -1186,6 +1218,13 @@ static int nfp_nfdk_rx(struct nfp_net_rx_ring *rx_ring, int budget)
11861218
continue;
11871219
}
11881220

1221+
#ifdef CONFIG_NFP_NET_IPSEC
1222+
if (meta.ipsec_saidx != 0 && unlikely(nfp_net_ipsec_rx(&meta, skb))) {
1223+
nfp_nfdk_rx_drop(dp, r_vec, rx_ring, NULL, skb);
1224+
continue;
1225+
}
1226+
#endif
1227+
11891228
if (meta_len_xdp)
11901229
skb_metadata_set(skb, meta_len_xdp);
11911230

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2+
/* Copyright (C) 2023 Corigine, Inc */
3+
4+
#include <net/xfrm.h>
5+
6+
#include "../nfp_net.h"
7+
#include "nfdk.h"
8+
9+
u64 nfp_nfdk_ipsec_tx(u64 flags, struct sk_buff *skb)
10+
{
11+
struct xfrm_state *x = xfrm_input_state(skb);
12+
13+
if (x->xso.dev && (x->xso.dev->features & NETIF_F_HW_ESP_TX_CSUM))
14+
flags |= NFDK_DESC_TX_L3_CSUM | NFDK_DESC_TX_L4_CSUM;
15+
16+
return flags;
17+
}

drivers/net/ethernet/netronome/nfp/nfdk/nfdk.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,4 +125,12 @@ nfp_nfdk_ctrl_tx_one(struct nfp_net *nn, struct nfp_net_r_vector *r_vec,
125125
void nfp_nfdk_ctrl_poll(struct tasklet_struct *t);
126126
void nfp_nfdk_rx_ring_fill_freelist(struct nfp_net_dp *dp,
127127
struct nfp_net_rx_ring *rx_ring);
128+
#ifndef CONFIG_NFP_NET_IPSEC
129+
static inline u64 nfp_nfdk_ipsec_tx(u64 flags, struct sk_buff *skb)
130+
{
131+
return flags;
132+
}
133+
#else
134+
u64 nfp_nfdk_ipsec_tx(u64 flags, struct sk_buff *skb);
135+
#endif
128136
#endif

0 commit comments

Comments
 (0)