net/mlx5e: TLS, Add Innova TLS TX support
authorIlya Lesokhin <ilyal@mellanox.com>
Mon, 30 Apr 2018 07:16:19 +0000 (10:16 +0300)
committerDavid S. Miller <davem@davemloft.net>
Tue, 1 May 2018 13:42:47 +0000 (09:42 -0400)
Add NETIF_F_HW_TLS_TX capability and expose tlsdev_ops to work with the
TLS generic NIC offload infrastructure.
The NETIF_F_HW_TLS_TX capability will be added in the next patch.

Signed-off-by: Ilya Lesokhin <ilyal@mellanox.com>
Signed-off-by: Boris Pismenny <borisp@mellanox.com>
Acked-by: Saeed Mahameed <saeedm@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlx5/core/Kconfig
drivers/net/ethernet/mellanox/mlx5/core/Makefile
drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.c [new file with mode: 0644]
drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.h [new file with mode: 0644]
drivers/net/ethernet/mellanox/mlx5/core/en_main.c

index 12257034131eca50701733fc4e33e3673a788392..ee6684779d112478ee4061960f1cf24fd918560f 100644 (file)
@@ -86,3 +86,14 @@ config MLX5_EN_IPSEC
          Build support for IPsec cryptography-offload accelaration in the NIC.
          Note: Support for hardware with this capability needs to be selected
          for this option to become available.
+
+config MLX5_EN_TLS
+       bool "TLS cryptography-offload accelaration"
+       depends on MLX5_CORE_EN
+       depends on TLS_DEVICE
+       depends on MLX5_ACCEL
+       default n
+       ---help---
+         Build support for TLS cryptography-offload accelaration in the NIC.
+         Note: Support for hardware with this capability needs to be selected
+         for this option to become available.
index 9989e5265a4551c531763200cc294d87f4c96bb5..50872ed30c0b641ae133b221f755161b28d3b2c3 100644 (file)
@@ -28,4 +28,6 @@ mlx5_core-$(CONFIG_MLX5_CORE_IPOIB) += ipoib/ipoib.o ipoib/ethtool.o ipoib/ipoib
 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
+
 CFLAGS_tracepoint.o := -I$(src)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.c
new file mode 100644 (file)
index 0000000..38d8810
--- /dev/null
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2018 Mellanox Technologies. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#include <linux/netdevice.h>
+#include <net/ipv6.h>
+#include "en_accel/tls.h"
+#include "accel/tls.h"
+
+static void mlx5e_tls_set_ipv4_flow(void *flow, struct sock *sk)
+{
+       struct inet_sock *inet = inet_sk(sk);
+
+       MLX5_SET(tls_flow, flow, ipv6, 0);
+       memcpy(MLX5_ADDR_OF(tls_flow, flow, dst_ipv4_dst_ipv6.ipv4_layout.ipv4),
+              &inet->inet_daddr, MLX5_FLD_SZ_BYTES(ipv4_layout, ipv4));
+       memcpy(MLX5_ADDR_OF(tls_flow, flow, src_ipv4_src_ipv6.ipv4_layout.ipv4),
+              &inet->inet_rcv_saddr, MLX5_FLD_SZ_BYTES(ipv4_layout, ipv4));
+}
+
+#if IS_ENABLED(CONFIG_IPV6)
+static void mlx5e_tls_set_ipv6_flow(void *flow, struct sock *sk)
+{
+       struct ipv6_pinfo *np = inet6_sk(sk);
+
+       MLX5_SET(tls_flow, flow, ipv6, 1);
+       memcpy(MLX5_ADDR_OF(tls_flow, flow, dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
+              &sk->sk_v6_daddr, MLX5_FLD_SZ_BYTES(ipv6_layout, ipv6));
+       memcpy(MLX5_ADDR_OF(tls_flow, flow, src_ipv4_src_ipv6.ipv6_layout.ipv6),
+              &np->saddr, MLX5_FLD_SZ_BYTES(ipv6_layout, ipv6));
+}
+#endif
+
+static void mlx5e_tls_set_flow_tcp_ports(void *flow, struct sock *sk)
+{
+       struct inet_sock *inet = inet_sk(sk);
+
+       memcpy(MLX5_ADDR_OF(tls_flow, flow, src_port), &inet->inet_sport,
+              MLX5_FLD_SZ_BYTES(tls_flow, src_port));
+       memcpy(MLX5_ADDR_OF(tls_flow, flow, dst_port), &inet->inet_dport,
+              MLX5_FLD_SZ_BYTES(tls_flow, dst_port));
+}
+
+static int mlx5e_tls_set_flow(void *flow, struct sock *sk, u32 caps)
+{
+       switch (sk->sk_family) {
+       case AF_INET:
+               mlx5e_tls_set_ipv4_flow(flow, sk);
+               break;
+#if IS_ENABLED(CONFIG_IPV6)
+       case AF_INET6:
+               if (!sk->sk_ipv6only &&
+                   ipv6_addr_type(&sk->sk_v6_daddr) == IPV6_ADDR_MAPPED) {
+                       mlx5e_tls_set_ipv4_flow(flow, sk);
+                       break;
+               }
+               if (!(caps & MLX5_ACCEL_TLS_IPV6))
+                       goto error_out;
+
+               mlx5e_tls_set_ipv6_flow(flow, sk);
+               break;
+#endif
+       default:
+               goto error_out;
+       }
+
+       mlx5e_tls_set_flow_tcp_ports(flow, sk);
+       return 0;
+error_out:
+       return -EINVAL;
+}
+
+static int mlx5e_tls_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 tls_context *tls_ctx = tls_get_ctx(sk);
+       struct mlx5_core_dev *mdev = priv->mdev;
+       u32 caps = mlx5_accel_tls_device_caps(mdev);
+       int ret = -ENOMEM;
+       void *flow;
+
+       if (direction != TLS_OFFLOAD_CTX_DIR_TX)
+               return -EINVAL;
+
+       flow = kzalloc(MLX5_ST_SZ_BYTES(tls_flow), GFP_KERNEL);
+       if (!flow)
+               return ret;
+
+       ret = mlx5e_tls_set_flow(flow, sk, caps);
+       if (ret)
+               goto free_flow;
+
+       if (direction == TLS_OFFLOAD_CTX_DIR_TX) {
+               struct mlx5e_tls_offload_context *tx_ctx =
+                   mlx5e_get_tls_tx_context(tls_ctx);
+               u32 swid;
+
+               ret = mlx5_accel_tls_add_tx_flow(mdev, flow, crypto_info,
+                                                start_offload_tcp_sn, &swid);
+               if (ret < 0)
+                       goto free_flow;
+
+               tx_ctx->swid = htonl(swid);
+               tx_ctx->expected_seq = start_offload_tcp_sn;
+       }
+
+       return 0;
+free_flow:
+       kfree(flow);
+       return ret;
+}
+
+static void mlx5e_tls_del(struct net_device *netdev,
+                         struct tls_context *tls_ctx,
+                         enum tls_offload_ctx_dir direction)
+{
+       struct mlx5e_priv *priv = netdev_priv(netdev);
+
+       if (direction == TLS_OFFLOAD_CTX_DIR_TX) {
+               u32 swid = ntohl(mlx5e_get_tls_tx_context(tls_ctx)->swid);
+
+               mlx5_accel_tls_del_tx_flow(priv->mdev, swid);
+       } else {
+               netdev_err(netdev, "unsupported direction %d\n", direction);
+       }
+}
+
+static const struct tlsdev_ops mlx5e_tls_ops = {
+       .tls_dev_add = mlx5e_tls_add,
+       .tls_dev_del = mlx5e_tls_del,
+};
+
+void mlx5e_tls_build_netdev(struct mlx5e_priv *priv)
+{
+       struct net_device *netdev = priv->netdev;
+
+       if (!mlx5_accel_is_tls_device(priv->mdev))
+               return;
+
+       netdev->tlsdev_ops = &mlx5e_tls_ops;
+}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.h
new file mode 100644 (file)
index 0000000..f7216b9
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2018 Mellanox Technologies. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+#ifndef __MLX5E_TLS_H__
+#define __MLX5E_TLS_H__
+
+#ifdef CONFIG_MLX5_EN_TLS
+
+#include <net/tls.h>
+#include "en.h"
+
+struct mlx5e_tls_offload_context {
+       struct tls_offload_context base;
+       u32 expected_seq;
+       __be32 swid;
+};
+
+static inline struct mlx5e_tls_offload_context *
+mlx5e_get_tls_tx_context(struct tls_context *tls_ctx)
+{
+       BUILD_BUG_ON(sizeof(struct mlx5e_tls_offload_context) >
+                    TLS_OFFLOAD_CONTEXT_SIZE);
+       return container_of(tls_offload_ctx(tls_ctx),
+                           struct mlx5e_tls_offload_context,
+                           base);
+}
+
+void mlx5e_tls_build_netdev(struct mlx5e_priv *priv);
+
+#else
+
+static inline void mlx5e_tls_build_netdev(struct mlx5e_priv *priv) { }
+
+#endif
+
+#endif /* __MLX5E_TLS_H__ */
index f1fe490ed7944bae01adbb81bbaefe56da60af37..0450c8c9b44721ac3cfc7d296ee4e6a94e1d6fa6 100644 (file)
@@ -42,7 +42,9 @@
 #include "en_rep.h"
 #include "en_accel/ipsec.h"
 #include "en_accel/ipsec_rxtx.h"
+#include "en_accel/tls.h"
 #include "accel/ipsec.h"
+#include "accel/tls.h"
 #include "vxlan.h"
 
 struct mlx5e_rq_param {
@@ -4376,6 +4378,7 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
 #endif
 
        mlx5e_ipsec_build_netdev(priv);
+       mlx5e_tls_build_netdev(priv);
 }
 
 static void mlx5e_create_q_counters(struct mlx5e_priv *priv)