Skip to content

Commit

Permalink
net/mlx5e: Add kTLS TX HW offload support
Browse files Browse the repository at this point in the history
Add support for transmit side kernel-TLS acceleration.
Offload the crypto encryption to HW.

Per TLS connection:
- Use a separate TIS to maintain the HW context.
- Use a separate encryption key.
- Maintain static and progress HW contexts by posting the proper
  WQEs at creation time, or upon resync.
- Use a special DUMP opcode to replay the previous frags and sync
  the HW context.

To make sure the SQ is able to serve an xmit request, increase
SQ stop room to cover:
- static params WQE,
- progress params WQE, and
- resync DUMP per frag.

Currently supporting TLS 1.2, and key size 128bit.

Tested over SimX simulator.

Signed-off-by: Tariq Toukan <tariqt@mellanox.com>
Signed-off-by: Eran Ben Elisha <eranbe@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Tariq Toukan authored and davem330 committed Jul 5, 2019
1 parent 37badd1 commit d2ead1f
Show file tree
Hide file tree
Showing 14 changed files with 748 additions and 7 deletions.
3 changes: 2 additions & 1 deletion drivers/net/ethernet/mellanox/mlx5/core/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,5 @@ mlx5_core-$(CONFIG_MLX5_FPGA) += fpga/cmd.o fpga/core.o fpga/conn.o fpga/sdk.o
mlx5_core-$(CONFIG_MLX5_EN_IPSEC) += en_accel/ipsec.o en_accel/ipsec_rxtx.o \
en_accel/ipsec_stats.o

mlx5_core-$(CONFIG_MLX5_EN_TLS) += en_accel/tls.o en_accel/tls_rxtx.o en_accel/tls_stats.o
mlx5_core-$(CONFIG_MLX5_EN_TLS) += en_accel/tls.o en_accel/tls_rxtx.o en_accel/tls_stats.o \
en_accel/ktls.o en_accel/ktls_tx.o
8 changes: 7 additions & 1 deletion drivers/net/ethernet/mellanox/mlx5/core/en.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,10 @@ struct mlx5e_umr_wqe {
struct mlx5_wqe_ctrl_seg ctrl;
struct mlx5_wqe_umr_ctrl_seg uctrl;
struct mlx5_mkey_seg mkc;
struct mlx5_mtt inline_mtts[0];
union {
struct mlx5_mtt inline_mtts[0];
u8 tls_static_params_ctx[0];
};
};

extern const char mlx5e_self_tests[][ETH_GSTRING_LEN];
Expand Down Expand Up @@ -333,6 +336,9 @@ struct mlx5e_tx_wqe_info {
u32 num_bytes;
u8 num_wqebbs;
u8 num_dma;
#ifdef CONFIG_MLX5_EN_TLS
skb_frag_t *resync_dump_frag;
#endif
};

enum mlx5e_dma_map_type {
Expand Down
8 changes: 7 additions & 1 deletion drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,15 @@
#else
/* TLS offload requires additional stop_room for:
* - a resync SKB.
* kTLS offload requires additional stop_room for:
* - static params WQE,
* - progress params WQE, and
* - resync DUMP per frag.
*/
#define MLX5E_SQ_TLS_ROOM \
(MLX5_SEND_WQE_MAX_WQEBBS)
(MLX5_SEND_WQE_MAX_WQEBBS + \
MLX5E_KTLS_STATIC_WQEBBS + MLX5E_KTLS_PROGRESS_WQEBBS + \
MAX_SKB_FRAGS * MLX5E_KTLS_MAX_DUMP_WQEBBS)
#endif

#define INL_HDR_START_SZ (sizeof(((struct mlx5_wqe_eth_seg *)NULL)->inline_hdr.start))
Expand Down
93 changes: 93 additions & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
// Copyright (c) 2019 Mellanox Technologies.

#include "en.h"
#include "en_accel/ktls.h"

static int mlx5e_ktls_create_tis(struct mlx5_core_dev *mdev, u32 *tisn)
{
u32 in[MLX5_ST_SZ_DW(create_tis_in)] = {};
void *tisc;

tisc = MLX5_ADDR_OF(create_tis_in, in, ctx);

MLX5_SET(tisc, tisc, tls_en, 1);

return mlx5e_create_tis(mdev, in, tisn);
}

static int mlx5e_ktls_add(struct net_device *netdev, struct sock *sk,
enum tls_offload_ctx_dir direction,
struct tls_crypto_info *crypto_info,
u32 start_offload_tcp_sn)
{
struct mlx5e_priv *priv = netdev_priv(netdev);
struct mlx5e_ktls_offload_context_tx *tx_priv;
struct tls_context *tls_ctx = tls_get_ctx(sk);
struct mlx5_core_dev *mdev = priv->mdev;
int err;

if (WARN_ON(direction != TLS_OFFLOAD_CTX_DIR_TX))
return -EINVAL;

if (WARN_ON(!mlx5e_ktls_type_check(mdev, crypto_info)))
return -EOPNOTSUPP;

tx_priv = kvzalloc(sizeof(*tx_priv), GFP_KERNEL);
if (!tx_priv)
return -ENOMEM;

tx_priv->expected_seq = start_offload_tcp_sn;
tx_priv->crypto_info = crypto_info;
mlx5e_set_ktls_tx_priv_ctx(tls_ctx, tx_priv);

/* tc and underlay_qpn values are not in use for tls tis */
err = mlx5e_ktls_create_tis(mdev, &tx_priv->tisn);
if (err)
goto create_tis_fail;

err = mlx5_ktls_create_key(mdev, crypto_info, &tx_priv->key_id);
if (err)
goto encryption_key_create_fail;

mlx5e_ktls_tx_offload_set_pending(tx_priv);

return 0;

encryption_key_create_fail:
mlx5e_destroy_tis(priv->mdev, tx_priv->tisn);
create_tis_fail:
kvfree(tx_priv);
return err;
}

static void mlx5e_ktls_del(struct net_device *netdev,
struct tls_context *tls_ctx,
enum tls_offload_ctx_dir direction)
{
struct mlx5e_priv *priv = netdev_priv(netdev);
struct mlx5e_ktls_offload_context_tx *tx_priv =
mlx5e_get_ktls_tx_priv_ctx(tls_ctx);

mlx5_ktls_destroy_key(priv->mdev, tx_priv->key_id);
mlx5e_destroy_tis(priv->mdev, tx_priv->tisn);
kvfree(tx_priv);
}

static const struct tlsdev_ops mlx5e_ktls_ops = {
.tls_dev_add = mlx5e_ktls_add,
.tls_dev_del = mlx5e_ktls_del,
};

void mlx5e_ktls_build_netdev(struct mlx5e_priv *priv)
{
struct net_device *netdev = priv->netdev;

if (!mlx5_accel_is_ktls_device(priv->mdev))
return;

netdev->hw_features |= NETIF_F_HW_TLS_TX;
netdev->features |= NETIF_F_HW_TLS_TX;

netdev->tlsdev_ops = &mlx5e_ktls_ops;
}
97 changes: 97 additions & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
/* Copyright (c) 2019 Mellanox Technologies. */

#ifndef __MLX5E_KTLS_H__
#define __MLX5E_KTLS_H__

#include "en.h"

#ifdef CONFIG_MLX5_EN_TLS
#include <net/tls.h>
#include "accel/tls.h"

#define MLX5E_KTLS_STATIC_UMR_WQE_SZ \
(sizeof(struct mlx5e_umr_wqe) + MLX5_ST_SZ_BYTES(tls_static_params))
#define MLX5E_KTLS_STATIC_WQEBBS \
(DIV_ROUND_UP(MLX5E_KTLS_STATIC_UMR_WQE_SZ, MLX5_SEND_WQE_BB))

#define MLX5E_KTLS_PROGRESS_WQE_SZ \
(sizeof(struct mlx5e_tx_wqe) + MLX5_ST_SZ_BYTES(tls_progress_params))
#define MLX5E_KTLS_PROGRESS_WQEBBS \
(DIV_ROUND_UP(MLX5E_KTLS_PROGRESS_WQE_SZ, MLX5_SEND_WQE_BB))
#define MLX5E_KTLS_MAX_DUMP_WQEBBS 2

enum {
MLX5E_TLS_PROGRESS_PARAMS_AUTH_STATE_NO_OFFLOAD = 0,
MLX5E_TLS_PROGRESS_PARAMS_AUTH_STATE_OFFLOAD = 1,
MLX5E_TLS_PROGRESS_PARAMS_AUTH_STATE_AUTHENTICATION = 2,
};

enum {
MLX5E_TLS_PROGRESS_PARAMS_RECORD_TRACKER_STATE_START = 0,
MLX5E_TLS_PROGRESS_PARAMS_RECORD_TRACKER_STATE_SEARCHING = 1,
MLX5E_TLS_PROGRESS_PARAMS_RECORD_TRACKER_STATE_TRACKING = 2,
};

struct mlx5e_ktls_offload_context_tx {
struct tls_offload_context_tx *tx_ctx;
struct tls_crypto_info *crypto_info;
u32 expected_seq;
u32 tisn;
u32 key_id;
bool ctx_post_pending;
};

struct mlx5e_ktls_offload_context_tx_shadow {
struct tls_offload_context_tx tx_ctx;
struct mlx5e_ktls_offload_context_tx *priv_tx;
};

static inline void
mlx5e_set_ktls_tx_priv_ctx(struct tls_context *tls_ctx,
struct mlx5e_ktls_offload_context_tx *priv_tx)
{
struct tls_offload_context_tx *tx_ctx = tls_offload_ctx_tx(tls_ctx);
struct mlx5e_ktls_offload_context_tx_shadow *shadow;

BUILD_BUG_ON(sizeof(*shadow) > TLS_OFFLOAD_CONTEXT_SIZE_TX);

shadow = (struct mlx5e_ktls_offload_context_tx_shadow *)tx_ctx;

shadow->priv_tx = priv_tx;
priv_tx->tx_ctx = tx_ctx;
}

static inline struct mlx5e_ktls_offload_context_tx *
mlx5e_get_ktls_tx_priv_ctx(struct tls_context *tls_ctx)
{
struct tls_offload_context_tx *tx_ctx = tls_offload_ctx_tx(tls_ctx);
struct mlx5e_ktls_offload_context_tx_shadow *shadow;

BUILD_BUG_ON(sizeof(*shadow) > TLS_OFFLOAD_CONTEXT_SIZE_TX);

shadow = (struct mlx5e_ktls_offload_context_tx_shadow *)tx_ctx;

return shadow->priv_tx;
}

void mlx5e_ktls_build_netdev(struct mlx5e_priv *priv);
void mlx5e_ktls_tx_offload_set_pending(struct mlx5e_ktls_offload_context_tx *priv_tx);

struct sk_buff *mlx5e_ktls_handle_tx_skb(struct net_device *netdev,
struct mlx5e_txqsq *sq,
struct sk_buff *skb,
struct mlx5e_tx_wqe **wqe, u16 *pi);
void mlx5e_ktls_tx_handle_resync_dump_comp(struct mlx5e_txqsq *sq,
struct mlx5e_tx_wqe_info *wi,
struct mlx5e_sq_dma *dma);

#else

static inline void mlx5e_ktls_build_netdev(struct mlx5e_priv *priv)
{
}

#endif

#endif /* __MLX5E_TLS_H__ */
Loading

0 comments on commit d2ead1f

Please sign in to comment.