Skip to content

Commit 899a59d

Browse files
ilantayariSaeed Mahameed
authored andcommitted
net/mlx5e: IPSec, Add Innova IPSec offload RX data path
In RX data path, the hardware prepends a special metadata ethertype which indicates that the packet underwent decryption, and the result of the authentication check. Communicate this to the stack in skb->sp. Make wqe_size large enough to account for the injected metadata. Support only Linked-list RQ type. IPSec offload RX packets may have useful CHECKSUM_COMPLETE information, which the stack may not be able to use yet. Signed-off-by: Ilan Tayari <[email protected]> Signed-off-by: Yossi Kuperman <[email protected]> Signed-off-by: Yevgeny Kliteynik <[email protected]> Signed-off-by: Boris Pismenny <[email protected]> Signed-off-by: Saeed Mahameed <[email protected]>
1 parent 547eede commit 899a59d

File tree

7 files changed

+269
-3
lines changed

7 files changed

+269
-3
lines changed

drivers/net/ethernet/mellanox/mlx5/core/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,4 @@ mlx5_core-$(CONFIG_MLX5_CORE_EN_DCB) += en_dcbnl.o
2020

2121
mlx5_core-$(CONFIG_MLX5_CORE_IPOIB) += ipoib/ipoib.o ipoib/ethtool.o
2222

23-
mlx5_core-$(CONFIG_MLX5_EN_IPSEC) += en_accel/ipsec.o
23+
mlx5_core-$(CONFIG_MLX5_EN_IPSEC) += en_accel/ipsec.o en_accel/ipsec_rxtx.o

drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include "en.h"
4141
#include "accel/ipsec.h"
4242
#include "en_accel/ipsec.h"
43+
#include "en_accel/ipsec_rxtx.h"
4344

4445
struct mlx5e_ipsec_sa_entry {
4546
struct hlist_node hlist; /* Item in SADB_RX hashtable */
@@ -49,6 +50,24 @@ struct mlx5e_ipsec_sa_entry {
4950
void *context;
5051
};
5152

53+
struct xfrm_state *mlx5e_ipsec_sadb_rx_lookup(struct mlx5e_ipsec *ipsec,
54+
unsigned int handle)
55+
{
56+
struct mlx5e_ipsec_sa_entry *sa_entry;
57+
struct xfrm_state *ret = NULL;
58+
59+
rcu_read_lock();
60+
hash_for_each_possible_rcu(ipsec->sadb_rx, sa_entry, hlist, handle)
61+
if (sa_entry->handle == handle) {
62+
ret = sa_entry->x;
63+
xfrm_state_hold(ret);
64+
break;
65+
}
66+
rcu_read_unlock();
67+
68+
return ret;
69+
}
70+
5271
static int mlx5e_ipsec_sadb_rx_add(struct mlx5e_ipsec_sa_entry *sa_entry)
5372
{
5473
struct mlx5e_ipsec *ipsec = sa_entry->ipsec;

drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,23 @@
4141
#include <linux/idr.h>
4242

4343
#define MLX5E_IPSEC_SADB_RX_BITS 10
44+
#define MLX5E_METADATA_ETHER_TYPE (0x8CE4)
45+
#define MLX5E_METADATA_ETHER_LEN 8
4446

4547
struct mlx5e_priv;
4648

49+
struct mlx5e_ipsec_sw_stats {
50+
atomic64_t ipsec_rx_drop_sp_alloc;
51+
atomic64_t ipsec_rx_drop_sadb_miss;
52+
atomic64_t ipsec_rx_drop_syndrome;
53+
};
54+
4755
struct mlx5e_ipsec {
4856
struct mlx5e_priv *en_priv;
4957
DECLARE_HASHTABLE(sadb_rx, MLX5E_IPSEC_SADB_RX_BITS);
5058
spinlock_t sadb_rx_lock; /* Protects sadb_rx and halloc */
5159
struct ida halloc;
60+
struct mlx5e_ipsec_sw_stats sw_stats;
5261
};
5362

5463
int mlx5e_ipsec_init(struct mlx5e_priv *priv);
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
/*
2+
* Copyright (c) 2017 Mellanox Technologies. All rights reserved.
3+
*
4+
* This software is available to you under a choice of one of two
5+
* licenses. You may choose to be licensed under the terms of the GNU
6+
* General Public License (GPL) Version 2, available from the file
7+
* COPYING in the main directory of this source tree, or the
8+
* OpenIB.org BSD license below:
9+
*
10+
* Redistribution and use in source and binary forms, with or
11+
* without modification, are permitted provided that the following
12+
* conditions are met:
13+
*
14+
* - Redistributions of source code must retain the above
15+
* copyright notice, this list of conditions and the following
16+
* disclaimer.
17+
*
18+
* - Redistributions in binary form must reproduce the above
19+
* copyright notice, this list of conditions and the following
20+
* disclaimer in the documentation and/or other materials
21+
* provided with the distribution.
22+
*
23+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27+
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28+
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29+
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30+
* SOFTWARE.
31+
*
32+
*/
33+
34+
#include <crypto/aead.h>
35+
#include <net/xfrm.h>
36+
37+
#include "en_accel/ipsec_rxtx.h"
38+
#include "en_accel/ipsec.h"
39+
#include "en.h"
40+
41+
enum {
42+
MLX5E_IPSEC_RX_SYNDROME_DECRYPTED = 0x11,
43+
MLX5E_IPSEC_RX_SYNDROME_AUTH_FAILED = 0x12,
44+
};
45+
46+
struct mlx5e_ipsec_rx_metadata {
47+
unsigned char reserved;
48+
__be32 sa_handle;
49+
} __packed;
50+
51+
struct mlx5e_ipsec_metadata {
52+
unsigned char syndrome;
53+
union {
54+
unsigned char raw[5];
55+
/* from FPGA to host, on successful decrypt */
56+
struct mlx5e_ipsec_rx_metadata rx;
57+
} __packed content;
58+
/* packet type ID field */
59+
__be16 ethertype;
60+
} __packed;
61+
62+
static inline struct xfrm_state *
63+
mlx5e_ipsec_build_sp(struct net_device *netdev, struct sk_buff *skb,
64+
struct mlx5e_ipsec_metadata *mdata)
65+
{
66+
struct mlx5e_priv *priv = netdev_priv(netdev);
67+
struct xfrm_offload *xo;
68+
struct xfrm_state *xs;
69+
u32 sa_handle;
70+
71+
skb->sp = secpath_dup(skb->sp);
72+
if (unlikely(!skb->sp)) {
73+
atomic64_inc(&priv->ipsec->sw_stats.ipsec_rx_drop_sp_alloc);
74+
return NULL;
75+
}
76+
77+
sa_handle = be32_to_cpu(mdata->content.rx.sa_handle);
78+
xs = mlx5e_ipsec_sadb_rx_lookup(priv->ipsec, sa_handle);
79+
if (unlikely(!xs)) {
80+
atomic64_inc(&priv->ipsec->sw_stats.ipsec_rx_drop_sadb_miss);
81+
return NULL;
82+
}
83+
84+
skb->sp->xvec[skb->sp->len++] = xs;
85+
skb->sp->olen++;
86+
87+
xo = xfrm_offload(skb);
88+
xo->flags = CRYPTO_DONE;
89+
switch (mdata->syndrome) {
90+
case MLX5E_IPSEC_RX_SYNDROME_DECRYPTED:
91+
xo->status = CRYPTO_SUCCESS;
92+
break;
93+
case MLX5E_IPSEC_RX_SYNDROME_AUTH_FAILED:
94+
xo->status = CRYPTO_TUNNEL_ESP_AUTH_FAILED;
95+
break;
96+
default:
97+
atomic64_inc(&priv->ipsec->sw_stats.ipsec_rx_drop_syndrome);
98+
return NULL;
99+
}
100+
return xs;
101+
}
102+
103+
struct sk_buff *mlx5e_ipsec_handle_rx_skb(struct net_device *netdev,
104+
struct sk_buff *skb)
105+
{
106+
struct mlx5e_ipsec_metadata *mdata;
107+
struct ethhdr *old_eth;
108+
struct ethhdr *new_eth;
109+
struct xfrm_state *xs;
110+
__be16 *ethtype;
111+
112+
/* Detect inline metadata */
113+
if (skb->len < ETH_HLEN + MLX5E_METADATA_ETHER_LEN)
114+
return skb;
115+
ethtype = (__be16 *)(skb->data + ETH_ALEN * 2);
116+
if (*ethtype != cpu_to_be16(MLX5E_METADATA_ETHER_TYPE))
117+
return skb;
118+
119+
/* Use the metadata */
120+
mdata = (struct mlx5e_ipsec_metadata *)(skb->data + ETH_HLEN);
121+
xs = mlx5e_ipsec_build_sp(netdev, skb, mdata);
122+
if (unlikely(!xs)) {
123+
kfree_skb(skb);
124+
return NULL;
125+
}
126+
127+
/* Remove the metadata from the buffer */
128+
old_eth = (struct ethhdr *)skb->data;
129+
new_eth = (struct ethhdr *)(skb->data + MLX5E_METADATA_ETHER_LEN);
130+
memmove(new_eth, old_eth, 2 * ETH_ALEN);
131+
/* Ethertype is already in its new place */
132+
skb_pull_inline(skb, MLX5E_METADATA_ETHER_LEN);
133+
134+
return skb;
135+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Copyright (c) 2017 Mellanox Technologies. All rights reserved.
3+
*
4+
* This software is available to you under a choice of one of two
5+
* licenses. You may choose to be licensed under the terms of the GNU
6+
* General Public License (GPL) Version 2, available from the file
7+
* COPYING in the main directory of this source tree, or the
8+
* OpenIB.org BSD license below:
9+
*
10+
* Redistribution and use in source and binary forms, with or
11+
* without modification, are permitted provided that the following
12+
* conditions are met:
13+
*
14+
* - Redistributions of source code must retain the above
15+
* copyright notice, this list of conditions and the following
16+
* disclaimer.
17+
*
18+
* - Redistributions in binary form must reproduce the above
19+
* copyright notice, this list of conditions and the following
20+
* disclaimer in the documentation and/or other materials
21+
* provided with the distribution.
22+
*
23+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27+
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28+
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29+
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30+
* SOFTWARE.
31+
*
32+
*/
33+
34+
#ifndef __MLX5E_IPSEC_RXTX_H__
35+
#define __MLX5E_IPSEC_RXTX_H__
36+
37+
#include <linux/skbuff.h>
38+
#include "en.h"
39+
40+
struct sk_buff *mlx5e_ipsec_handle_rx_skb(struct net_device *netdev,
41+
struct sk_buff *skb);
42+
void mlx5e_ipsec_handle_rx_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe);
43+
44+
#endif /* __MLX5E_IPSEC_RXTX_H__ */

drivers/net/ethernet/mellanox/mlx5/core/en_main.c

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040
#include "en_tc.h"
4141
#include "en_rep.h"
4242
#include "en_accel/ipsec.h"
43+
#include "en_accel/ipsec_rxtx.h"
44+
#include "accel/ipsec.h"
4345
#include "vxlan.h"
4446

4547
struct mlx5e_rq_param {
@@ -116,7 +118,7 @@ void mlx5e_set_rq_type_params(struct mlx5_core_dev *mdev,
116118
static void mlx5e_set_rq_params(struct mlx5_core_dev *mdev, struct mlx5e_params *params)
117119
{
118120
u8 rq_type = mlx5e_check_fragmented_striding_rq_cap(mdev) &&
119-
!params->xdp_prog ?
121+
!params->xdp_prog && !MLX5_IPSEC_DEV(mdev) ?
120122
MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ :
121123
MLX5_WQ_TYPE_LINKED_LIST;
122124
mlx5e_set_rq_type_params(mdev, params, rq_type);
@@ -593,6 +595,13 @@ static int mlx5e_alloc_rq(struct mlx5e_channel *c,
593595
rq->dealloc_wqe = mlx5e_dealloc_rx_mpwqe;
594596

595597
rq->handle_rx_cqe = c->priv->profile->rx_handlers.handle_rx_cqe_mpwqe;
598+
#ifdef CONFIG_MLX5_EN_IPSEC
599+
if (MLX5_IPSEC_DEV(mdev)) {
600+
err = -EINVAL;
601+
netdev_err(c->netdev, "MPWQE RQ with IPSec offload not supported\n");
602+
goto err_rq_wq_destroy;
603+
}
604+
#endif
596605
if (!rq->handle_rx_cqe) {
597606
err = -EINVAL;
598607
netdev_err(c->netdev, "RX handler of MPWQE RQ is not set, err %d\n", err);
@@ -625,7 +634,12 @@ static int mlx5e_alloc_rq(struct mlx5e_channel *c,
625634
rq->alloc_wqe = mlx5e_alloc_rx_wqe;
626635
rq->dealloc_wqe = mlx5e_dealloc_rx_wqe;
627636

628-
rq->handle_rx_cqe = c->priv->profile->rx_handlers.handle_rx_cqe;
637+
#ifdef CONFIG_MLX5_EN_IPSEC
638+
if (c->priv->ipsec)
639+
rq->handle_rx_cqe = mlx5e_ipsec_handle_rx_cqe;
640+
else
641+
#endif
642+
rq->handle_rx_cqe = c->priv->profile->rx_handlers.handle_rx_cqe;
629643
if (!rq->handle_rx_cqe) {
630644
kfree(rq->wqe.frag_info);
631645
err = -EINVAL;
@@ -636,6 +650,10 @@ static int mlx5e_alloc_rq(struct mlx5e_channel *c,
636650
rq->buff.wqe_sz = params->lro_en ?
637651
params->lro_wqe_sz :
638652
MLX5E_SW2HW_MTU(c->priv, c->netdev->mtu);
653+
#ifdef CONFIG_MLX5_EN_IPSEC
654+
if (MLX5_IPSEC_DEV(mdev))
655+
rq->buff.wqe_sz += MLX5E_METADATA_ETHER_LEN;
656+
#endif
639657
rq->wqe.page_reuse = !params->xdp_prog && !params->lro_en;
640658
byte_count = rq->buff.wqe_sz;
641659

drivers/net/ethernet/mellanox/mlx5/core/en_rx.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include "eswitch.h"
4242
#include "en_rep.h"
4343
#include "ipoib/ipoib.h"
44+
#include "en_accel/ipsec_rxtx.h"
4445

4546
static inline bool mlx5e_rx_hw_stamp(struct mlx5e_tstamp *tstamp)
4647
{
@@ -1183,3 +1184,43 @@ void mlx5i_handle_rx_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe)
11831184
}
11841185

11851186
#endif /* CONFIG_MLX5_CORE_IPOIB */
1187+
1188+
#ifdef CONFIG_MLX5_EN_IPSEC
1189+
1190+
void mlx5e_ipsec_handle_rx_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe)
1191+
{
1192+
struct mlx5e_wqe_frag_info *wi;
1193+
struct mlx5e_rx_wqe *wqe;
1194+
__be16 wqe_counter_be;
1195+
struct sk_buff *skb;
1196+
u16 wqe_counter;
1197+
u32 cqe_bcnt;
1198+
1199+
wqe_counter_be = cqe->wqe_counter;
1200+
wqe_counter = be16_to_cpu(wqe_counter_be);
1201+
wqe = mlx5_wq_ll_get_wqe(&rq->wq, wqe_counter);
1202+
wi = &rq->wqe.frag_info[wqe_counter];
1203+
cqe_bcnt = be32_to_cpu(cqe->byte_cnt);
1204+
1205+
skb = skb_from_cqe(rq, cqe, wi, cqe_bcnt);
1206+
if (unlikely(!skb)) {
1207+
/* a DROP, save the page-reuse checks */
1208+
mlx5e_free_rx_wqe(rq, wi);
1209+
goto wq_ll_pop;
1210+
}
1211+
skb = mlx5e_ipsec_handle_rx_skb(rq->netdev, skb);
1212+
if (unlikely(!skb)) {
1213+
mlx5e_free_rx_wqe(rq, wi);
1214+
goto wq_ll_pop;
1215+
}
1216+
1217+
mlx5e_complete_rx_cqe(rq, cqe, cqe_bcnt, skb);
1218+
napi_gro_receive(rq->cq.napi, skb);
1219+
1220+
mlx5e_free_rx_wqe_reuse(rq, wi);
1221+
wq_ll_pop:
1222+
mlx5_wq_ll_pop(&rq->wq, wqe_counter_be,
1223+
&wqe->next.next_wqe_index);
1224+
}
1225+
1226+
#endif /* CONFIG_MLX5_EN_IPSEC */

0 commit comments

Comments
 (0)