[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1490707592-1430-11-git-send-email-aviadye@mellanox.com>
Date: Tue, 28 Mar 2017 16:26:27 +0300
From: Aviad Yehezkel <aviadye@...lanox.com>
To: davem@...emloft.net, aviadye@...lanox.com, ilyal@...lanox.com,
borisp@...lanox.com, davejwatson@...com, netdev@...r.kernel.org
Cc: matanb@...lanox.com, liranl@...lanox.com, haggaie@...lanox.com,
tom@...bertland.com, herbert@...dor.apana.org.au, nmav@...lts.org,
fridolin.pokorny@...il.com, ilant@...lanox.com,
kliteyn@...lanox.com, linux-crypto@...r.kernel.org,
saeedm@...lanox.com, aviadye@....mellanox.co.il
Subject: [RFC TLS Offload Support 10/15] mlx/tls: Add mlx_accel offload driver for TLS
From: Ilya Lesokhin <ilyal@...lanox.com>
Implement the transmit and receive callbacks as well as the netdev
operations for adding and removing sockets.
Signed-off-by: Guy Shapiro <guysh@...lanox.com>
Signed-off-by: Ilya Lesokhin <ilyal@...lanox.com>
Signed-off-by: Matan Barak <matanb@...lanox.com>
Signed-off-by: Haggai Eran <haggaie@...lanox.com>
Signed-off-by: Aviad Yehezkel <aviadye@...lanox.com>
---
.../net/ethernet/mellanox/accelerator/tls/tls.c | 652 +++++++++++++++++++++
.../net/ethernet/mellanox/accelerator/tls/tls.h | 100 ++++
2 files changed, 752 insertions(+)
create mode 100644 drivers/net/ethernet/mellanox/accelerator/tls/tls.c
create mode 100644 drivers/net/ethernet/mellanox/accelerator/tls/tls.h
diff --git a/drivers/net/ethernet/mellanox/accelerator/tls/tls.c b/drivers/net/ethernet/mellanox/accelerator/tls/tls.c
new file mode 100644
index 0000000..07a4b67
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/accelerator/tls/tls.c
@@ -0,0 +1,652 @@
+/*
+ * Copyright (c) 2015-2017 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 "tls.h"
+#include "tls_sysfs.h"
+#include "tls_hw.h"
+#include "tls_cmds.h"
+#include <linux/mlx5/driver.h>
+#include <linux/netdevice.h>
+
+static LIST_HEAD(mlx_tls_devs);
+static DEFINE_MUTEX(mlx_tls_mutex);
+
+/* Start of context identifiers range (inclusive) */
+#define SWID_START 5
+/* End of context identifiers range (exclusive) */
+#define SWID_END BIT(24)
+
+static netdev_features_t mlx_tls_feature_chk(struct sk_buff *skb,
+ struct net_device *netdev,
+ netdev_features_t features,
+ bool *done)
+{
+ return features;
+}
+
+int mlx_tls_get_count(struct net_device *netdev)
+{
+ return 0;
+}
+
+int mlx_tls_get_strings(struct net_device *netdev, uint8_t *data)
+{
+ return 0;
+}
+
+int mlx_tls_get_stats(struct net_device *netdev, u64 *data)
+{
+ return 0;
+}
+
+/* must hold mlx_tls_mutex to call this function */
+static struct mlx_tls_dev *find_mlx_tls_dev_by_netdev(
+ struct net_device *netdev)
+{
+ struct mlx_tls_dev *dev;
+
+ list_for_each_entry(dev, &mlx_tls_devs, accel_dev_list) {
+ if (dev->netdev == netdev)
+ return dev;
+ }
+
+ return NULL;
+}
+
+struct mlx_tls_offload_context *get_tls_context(struct sock *sk)
+{
+ struct tls_context *tls_ctx = tls_get_ctx(sk);
+
+ return container_of(tls_offload_ctx(tls_ctx),
+ struct mlx_tls_offload_context,
+ context);
+}
+
+static int mlx_tls_add(struct net_device *netdev,
+ struct sock *sk,
+ enum tls_offload_ctx_dir direction,
+ struct tls_crypto_info *crypto_info,
+ struct tls_offload_context **ctx)
+{
+ struct tls_crypto_info_aes_gcm_128 *crypto_info_aes_gcm_128;
+ struct mlx_tls_offload_context *context;
+ struct mlx_tls_dev *dev;
+ int swid;
+ int ret;
+
+ pr_info("mlx_tls_add called\n");
+
+ if (direction == TLS_OFFLOAD_CTX_DIR_RX) {
+ pr_err("mlx_tls_add(): do not support recv\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (!crypto_info ||
+ crypto_info->cipher_type != TLS_CIPHER_AES_GCM_128) {
+ pr_err("mlx_tls_add(): support only aes_gcm_128\n");
+ ret = -EINVAL;
+ goto out;
+ }
+ crypto_info_aes_gcm_128 =
+ (struct tls_crypto_info_aes_gcm_128 *)crypto_info;
+
+ dev = mlx_tls_find_dev_by_netdev(netdev);
+ if (!dev) {
+ pr_err("mlx_tls_add(): tls dev not found\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ swid = ida_simple_get(&dev->swid_ida, SWID_START, SWID_END,
+ GFP_KERNEL);
+ if (swid < 0) {
+ pr_err("mlx_tls_add(): Failed to allocate swid\n");
+ ret = swid;
+ goto out;
+ }
+
+ context = kzalloc(sizeof(*context), GFP_KERNEL);
+ if (!context) {
+ ret = -ENOMEM;
+ goto release_swid;
+ }
+
+ context->swid = htonl(swid);
+ context->context.expectedSN = tcp_sk(sk)->write_seq;
+
+ ret = mlx_tls_hw_start_cmd(dev,
+ sk,
+ crypto_info_aes_gcm_128,
+ context);
+ if (ret)
+ goto relese_context;
+
+ try_module_get(THIS_MODULE);
+ *ctx = &context->context;
+out:
+ return ret;
+
+relese_context:
+ kfree(context);
+release_swid:
+ ida_simple_remove(&dev->swid_ida, swid);
+ return ret;
+}
+
+static void mlx_tls_del(struct net_device *netdev,
+ struct sock *sk,
+ enum tls_offload_ctx_dir direction)
+{
+ struct mlx_tls_offload_context *context = NULL;
+
+ if (direction == TLS_OFFLOAD_CTX_DIR_RX) {
+ pr_err("mlx_tls_del(): do not support recv\n");
+ return;
+ }
+
+ context = get_tls_context(sk);
+ if (context)
+ mlx_tls_hw_stop_cmd(netdev, context);
+ else
+ pr_err("delete non-offloaded context\n");
+}
+
+static const struct tlsdev_ops mlx_tls_ops = {
+ .tls_dev_add = mlx_tls_add,
+ .tls_dev_del = mlx_tls_del,
+};
+
+struct mlx_tls_dev *mlx_tls_find_dev_by_netdev(struct net_device *netdev)
+{
+ struct mlx_tls_dev *dev;
+
+ mutex_lock(&mlx_tls_mutex);
+ dev = find_mlx_tls_dev_by_netdev(netdev);
+ mutex_unlock(&mlx_tls_mutex);
+ return dev;
+}
+
+#define SYNDROME_OFFLOAD_REQUIRED 32
+#define SYNDROME_SYNC 33.
+#define SYNDROME_BYPASS 34
+
+#define MIN_BYPASS_RECORD_SIZE 29
+#define BYPASS_RECORD_PADDING_SIZE \
+ (MIN_BYPASS_RECORD_SIZE - TLS_HEADER_SIZE)
+
+#define MAX_BYPASS_SIZE ((1 << 15) - BYPASS_RECORD_PADDING_SIZE - 1)
+
+static void create_bypass_record(u8 *buf, u16 len)
+{
+ len += BYPASS_RECORD_PADDING_SIZE;
+ buf[0] = TLS_RECORD_TYPE_DATA;
+ buf[1] = TLS_1_2_VERSION_MAJOR;
+ buf[2] = TLS_1_2_VERSION_MINOR;
+ buf[3] = len >> 8;
+ buf[4] = len & 0xFF;
+ memset(buf + TLS_HEADER_SIZE, 0, BYPASS_RECORD_PADDING_SIZE);
+}
+
+struct sync_info {
+ s32 sync_len;
+ int nr_frags;
+ skb_frag_t frags[MAX_SKB_FRAGS];
+};
+
+static int get_sync_data(struct mlx_tls_offload_context *context,
+ u32 tcp_seq, struct sync_info *info)
+{
+ struct tls_record_info *record;
+ unsigned long flags;
+ int remaining;
+ s32 sync_size;
+ int ret = -EINVAL;
+ int i = 0;
+
+ spin_lock_irqsave(&context->context.lock, flags);
+ record = tls_get_record(&context->context, tcp_seq);
+
+ if (unlikely(!record)) {
+ pr_err("record not found for seq %u\n", tcp_seq);
+ goto out;
+ }
+
+ sync_size = tcp_seq - (record->end_seq - record->len);
+ info->sync_len = sync_size;
+ if (unlikely(sync_size < 0)) {
+ if (record->len != 0) {
+ pr_err("Invalid record for seq %u\n", tcp_seq);
+ goto out;
+ }
+ goto done;
+ }
+
+ remaining = sync_size;
+ while (remaining > 0) {
+ info->frags[i] = record->frags[i];
+ __skb_frag_ref(&info->frags[i]);
+ remaining -= skb_frag_size(&info->frags[i]);
+
+ if (remaining < 0) {
+ skb_frag_size_add(
+ &info->frags[i],
+ remaining);
+ }
+
+ i++;
+ }
+ info->nr_frags = i;
+done:
+ ret = 0;
+out:
+ spin_unlock_irqrestore(&context->context.lock, flags);
+ return ret;
+}
+
+static struct sk_buff *complete_sync_skb(
+ struct sk_buff *skb,
+ struct sk_buff *nskb,
+ u32 tcp_seq,
+ int headln,
+ unsigned char syndrome
+ )
+{
+ struct iphdr *iph;
+ struct tcphdr *th;
+ int mss;
+ struct pet *pet;
+ __be16 tcp_seq_low;
+
+ nskb->dev = skb->dev;
+ skb_reset_mac_header(nskb);
+ skb_set_network_header(nskb, skb_network_offset(skb));
+ skb_set_transport_header(nskb, skb_transport_offset(skb));
+ memcpy(nskb->data, skb->data, headln);
+
+ iph = ip_hdr(nskb);
+ iph->tot_len = htons(nskb->len - skb_network_offset(nskb));
+ th = tcp_hdr(nskb);
+ tcp_seq -= nskb->data_len;
+ th->seq = htonl(tcp_seq);
+ tcp_seq_low = htons(tcp_seq);
+
+ mss = nskb->dev->mtu - (headln - skb_network_offset(nskb));
+ skb_shinfo(nskb)->gso_size = 0;
+ if (nskb->data_len > mss) {
+ skb_shinfo(nskb)->gso_size = mss;
+ skb_shinfo(nskb)->gso_segs = DIV_ROUND_UP(nskb->data_len, mss);
+ }
+ skb_shinfo(nskb)->gso_type = skb_shinfo(skb)->gso_type;
+
+ nskb->queue_mapping = skb->queue_mapping;
+
+ pet = (struct pet *)(nskb->data + sizeof(struct ethhdr));
+ pet->syndrome = syndrome;
+ memcpy(pet->content.raw, &tcp_seq_low, sizeof(tcp_seq_low));
+
+ nskb->ip_summed = CHECKSUM_PARTIAL;
+ __skb_pull(nskb, skb_transport_offset(skb));
+ inet_csk(skb->sk)->icsk_af_ops->send_check(skb->sk, nskb);
+ __skb_push(nskb, skb_transport_offset(skb));
+
+ nskb->next = skb;
+ nskb->xmit_more = 1;
+ return nskb;
+}
+
+static void strip_pet(struct sk_buff *skb)
+{
+ struct ethhdr *old_eth;
+ struct ethhdr *new_eth;
+
+ old_eth = (struct ethhdr *)((skb->data) - sizeof(struct ethhdr));
+ new_eth = (struct ethhdr *)((skb_pull_inline(skb, sizeof(struct pet)))
+ - sizeof(struct ethhdr));
+ skb->mac_header += sizeof(struct pet);
+
+ memmove(new_eth, old_eth, 2 * ETH_ALEN);
+ /* Ethertype is already in its new place */
+}
+
+static struct sk_buff *handle_ooo(struct mlx_tls_offload_context *context,
+ struct sk_buff *skb)
+{
+ struct sync_info info;
+ u32 tcp_seq = ntohl(tcp_hdr(skb)->seq);
+ struct sk_buff *nskb;
+ int linear_len = 0;
+ int headln;
+ unsigned char syndrome = SYNDROME_SYNC;
+
+ if (get_sync_data(context, tcp_seq, &info)) {
+ dev_kfree_skb_any(skb);
+ return NULL;
+ }
+
+ headln = skb_transport_offset(skb) + tcp_hdrlen(skb);
+
+ if (unlikely(info.sync_len < 0)) {
+ if (-info.sync_len > MAX_BYPASS_SIZE) {
+ if (skb->len - headln > -info.sync_len) {
+ pr_err("Required bypass record is too big\n");
+ /* can fragment into two large SKBs in SW */
+ return NULL;
+ }
+ skb_push(skb, sizeof(struct ethhdr));
+ strip_pet(skb);
+ skb_pull(skb, sizeof(struct ethhdr));
+ return skb;
+ }
+
+ linear_len = MIN_BYPASS_RECORD_SIZE;
+ }
+
+ linear_len += headln;
+ nskb = alloc_skb(linear_len, GFP_ATOMIC);
+ if (unlikely(!nskb)) {
+ dev_kfree_skb_any(skb);
+ return NULL;
+ }
+
+ skb_put(nskb, linear_len);
+ syndrome = SYNDROME_SYNC;
+ if (likely(info.sync_len >= 0)) {
+ int i;
+
+ for (i = 0; i < info.nr_frags; i++)
+ skb_shinfo(nskb)->frags[i] = info.frags[i];
+
+ skb_shinfo(nskb)->nr_frags = info.nr_frags;
+ nskb->data_len = info.sync_len;
+ nskb->len += info.sync_len;
+ } else {
+ create_bypass_record(nskb->data + headln, -info.sync_len);
+ tcp_seq -= MIN_BYPASS_RECORD_SIZE;
+ syndrome = SYNDROME_BYPASS;
+ }
+
+ return complete_sync_skb(skb, nskb, tcp_seq, headln, syndrome);
+}
+
+static int insert_pet(struct sk_buff *skb)
+{
+ struct ethhdr *eth;
+ struct pet *pet;
+ struct mlx_tls_offload_context *context;
+
+ pr_debug("insert_pet started\n");
+ if (skb_cow_head(skb, sizeof(struct pet)))
+ return -ENOMEM;
+
+ eth = (struct ethhdr *)skb_push(skb, sizeof(struct pet));
+ skb->mac_header -= sizeof(struct pet);
+ pet = (struct pet *)(eth + 1);
+
+ memmove(skb->data, skb->data + sizeof(struct pet), 2 * ETH_ALEN);
+
+ eth->h_proto = cpu_to_be16(MLX5_METADATA_ETHER_TYPE);
+ pet->syndrome = SYNDROME_OFFLOAD_REQUIRED;
+
+ memset(pet->content.raw, 0, sizeof(pet->content.raw));
+ context = get_tls_context(skb->sk);
+ memcpy(pet->content.send.sid, &context->swid,
+ sizeof(pet->content.send.sid));
+
+ return 0;
+}
+
+static struct sk_buff *mlx_tls_tx_handler(struct sk_buff *skb,
+ struct mlx5_swp_info *swp_info)
+{
+ struct mlx_tls_offload_context *context;
+ int datalen;
+ u32 skb_seq;
+
+ pr_debug("mlx_tls_tx_handler started\n");
+
+ if (!skb->sk || !tls_is_sk_tx_device_offloaded(skb->sk))
+ goto out;
+
+ datalen = skb->len - (skb_transport_offset(skb) + tcp_hdrlen(skb));
+ if (!datalen)
+ goto out;
+
+ skb_seq = ntohl(tcp_hdr(skb)->seq);
+
+ context = get_tls_context(skb->sk);
+ pr_debug("mlx_tls_tx_handler: mapping: %u cpu %u size %u with swid %u expectedSN: %u actualSN: %u\n",
+ skb->queue_mapping, smp_processor_id(), skb->len,
+ ntohl(context->swid), context->context.expectedSN, skb_seq);
+
+ insert_pet(skb);
+
+ if (unlikely(context->context.expectedSN != skb_seq)) {
+ skb = handle_ooo(context, skb);
+ if (!skb)
+ goto out;
+
+ pr_info("Sending sync packet\n");
+
+ if (!skb->next)
+ goto out;
+ }
+ context->context.expectedSN = skb_seq + datalen;
+
+out:
+ return skb;
+}
+
+static struct sk_buff *mlx_tls_rx_handler(struct sk_buff *skb, u8 *rawpet,
+ u8 petlen)
+{
+ struct pet *pet = (struct pet *)rawpet;
+
+ if (petlen != sizeof(*pet))
+ goto out;
+
+ dev_dbg(&skb->dev->dev, ">> rx_handler %u bytes\n", skb->len);
+ dev_dbg(&skb->dev->dev, " RX PET: size %lu, etherType %04X, syndrome %02x\n",
+ sizeof(*pet), be16_to_cpu(pet->ethertype), pet->syndrome);
+
+ if (pet->syndrome != 48) {
+ dev_dbg(&skb->dev->dev, "unexpected pet syndrome %d\n",
+ pet->syndrome);
+ goto out;
+ }
+
+out:
+ return skb;
+}
+
+/* Must hold mlx_tls_mutex to call this function.
+ * Assumes that dev->core_ctx is destroyed be the caller
+ */
+static void mlx_tls_free(struct mlx_tls_dev *dev)
+{
+ list_del(&dev->accel_dev_list);
+#ifdef MLX_TLS_SADB_RDMA
+ kobject_put(&dev->kobj);
+#endif
+ dev_put(dev->netdev);
+ kfree(dev);
+}
+
+int mlx_tls_netdev_event(struct notifier_block *this, unsigned long event,
+ void *ptr)
+{
+ struct net_device *netdev = netdev_notifier_info_to_dev(ptr);
+ struct mlx_tls_dev *accel_dev = NULL;
+
+ if (!netdev)
+ goto out;
+
+ pr_debug("mlx_tls_netdev_event: %lu\n", event);
+
+ /* We are interested only in net devices going down */
+ if (event != NETDEV_UNREGISTER)
+ goto out;
+
+ /* Take down all connections using a netdev that is going down */
+ mutex_lock(&mlx_tls_mutex);
+ accel_dev = find_mlx_tls_dev_by_netdev(netdev);
+ if (!accel_dev) {
+ pr_debug("mlx_tls_netdev_event: Failed to find tls device for net device\n");
+ goto unlock;
+ }
+ mlx_tls_free(accel_dev);
+
+unlock:
+ mutex_unlock(&mlx_tls_mutex);
+out:
+ return NOTIFY_DONE;
+}
+
+static struct mlx5_accel_ops mlx_tls_client_ops = {
+ .rx_handler = mlx_tls_rx_handler,
+ .tx_handler = mlx_tls_tx_handler,
+ .feature_chk = mlx_tls_feature_chk,
+ .get_count = mlx_tls_get_count,
+ .get_strings = mlx_tls_get_strings,
+ .get_stats = mlx_tls_get_stats,
+ .mtu_extra = sizeof(struct pet),
+ .features = 0,
+};
+
+int mlx_tls_add_one(struct mlx_accel_core_device *accel_device)
+{
+ int ret = 0;
+ struct mlx_tls_dev *dev = NULL;
+ struct net_device *netdev = NULL;
+#ifdef MLX_TLS_SADB_RDMA
+ struct mlx_accel_core_conn_init_attr init_attr = {0};
+#endif
+ pr_debug("mlx_tls_add_one called for %s\n", accel_device->name);
+
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ INIT_LIST_HEAD(&dev->accel_dev_list);
+ dev->accel_device = accel_device;
+ ida_init(&dev->swid_ida);
+
+#ifdef MLX_TLS_SADB_RDMA
+ init_attr.rx_size = 128;
+ init_attr.tx_size = 32;
+ init_attr.recv_cb = mlx_tls_hw_qp_recv_cb;
+ init_attr.cb_arg = dev;
+ dev->conn = mlx_accel_core_conn_create(accel_device, &init_attr);
+ if (IS_ERR(dev->conn)) {
+ ret = PTR_ERR(dev->conn);
+ pr_err("mlx_tls_add_one(): Got error while creating connection %d\n",
+ ret);
+ goto err_dev;
+ }
+#endif
+ netdev = accel_device->ib_dev->get_netdev(accel_device->ib_dev,
+ accel_device->port);
+ if (!netdev) {
+ pr_err("mlx_tls_add_one(): Failed to retrieve net device from ib device\n");
+ ret = -EINVAL;
+ goto err_conn;
+ }
+ dev->netdev = netdev;
+
+ ret = mlx_accel_core_client_ops_register(accel_device,
+ &mlx_tls_client_ops);
+ if (ret) {
+ pr_err("mlx_tls_add_one(): Failed to register client ops %d\n",
+ ret);
+ goto err_netdev;
+ }
+
+#ifdef MLX_TLS_SADB_RDMA
+ ret = tls_sysfs_init_and_add(&dev->kobj,
+ mlx_accel_core_kobj(dev->accel_device),
+ "%s",
+ "accel_dev");
+ if (ret) {
+ pr_err("mlx_tls_add_one(): Got error from kobject_init_and_add %d\n",
+ ret);
+ goto err_ops_register;
+ }
+#endif
+
+ mutex_lock(&mlx_tls_mutex);
+ list_add(&dev->accel_dev_list, &mlx_tls_devs);
+ mutex_unlock(&mlx_tls_mutex);
+
+ dev->netdev->tlsdev_ops = &mlx_tls_ops;
+ goto out;
+
+#ifdef MLX_TLS_SADB_RDMA
+err_ops_register:
+ mlx_accel_core_client_ops_unregister(accel_device);
+#endif
+err_netdev:
+ dev_put(netdev);
+err_conn:
+ mlx_accel_core_conn_destroy(dev->conn);
+#ifdef MLX_TLS_SADB_RDMA
+err_dev:
+#endif
+ kfree(dev);
+out:
+ return ret;
+}
+
+void mlx_tls_remove_one(struct mlx_accel_core_device *accel_device)
+{
+ struct mlx_tls_dev *dev;
+ struct net_device *netdev = NULL;
+
+ pr_debug("mlx_tls_remove_one called for %s\n", accel_device->name);
+
+ mutex_lock(&mlx_tls_mutex);
+
+ list_for_each_entry(dev, &mlx_tls_devs, accel_dev_list) {
+ if (dev->accel_device == accel_device) {
+ netdev = dev->netdev;
+ netdev->tlsdev_ops = NULL;
+ mlx_accel_core_client_ops_unregister(accel_device);
+#ifdef MLX_TLS_SADB_RDMA
+ mlx_accel_core_conn_destroy(dev->conn);
+#endif
+ mlx_tls_free(dev);
+ break;
+ }
+ }
+ mutex_unlock(&mlx_tls_mutex);
+}
diff --git a/drivers/net/ethernet/mellanox/accelerator/tls/tls.h b/drivers/net/ethernet/mellanox/accelerator/tls/tls.h
new file mode 100644
index 0000000..7c7539a
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/accelerator/tls/tls.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2015-2017 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 __TLS_H__
+#define __TLS_H__
+
+#include <linux/types.h>
+#include <linux/kobject.h>
+#include <linux/kfifo.h>
+#include <linux/list.h>
+#include <linux/skbuff.h>
+#include <linux/hashtable.h>
+#include <net/sock.h>
+#include <net/inet_common.h>
+#include <net/tls.h>
+#include <linux/mlx5/accel_sdk.h>
+
+#include "tls_cmds.h"
+
+#define DRIVER_NAME "mlx_tls"
+#define DRIVER_VERSION "0.1"
+#define DRIVER_RELDATE "January 2016"
+
+#define MLX_TLS_DEVICE_NAME "mlx_tls"
+/* TODO: Consider moving this to include/uapi/linux/if_ether.h */
+
+struct send_pet_content {
+ /* The next field is meaningful only for sync packets with LSO
+ * enabled (by the syndrome field))
+ */
+ __be16 first_seq; /* LSBs of the first TCP seq in the packet */
+ unsigned char sid[3];
+} __packed;
+
+/*TODO: move this to HW/cmds header files when added*/
+struct pet {
+ unsigned char syndrome;
+ union {
+ unsigned char raw[5];
+ /* from host to FPGA */
+ struct send_pet_content send;
+ } __packed content;
+ /* packet type ID field */
+ __be16 ethertype;
+} __packed;
+
+struct mlx_tls_dev {
+ struct kobject kobj;
+ struct list_head accel_dev_list;
+ struct mlx_accel_core_device *accel_device;
+ struct mlx_accel_core_conn *conn;
+ struct net_device *netdev;
+ struct ida swid_ida;
+};
+
+struct mlx_tls_offload_context {
+ struct tls_offload_context context;
+ struct list_head tls_del_list;
+ struct net_device *netdev;
+ __be32 swid;
+};
+
+int mlx_tls_netdev_event(struct notifier_block *this,
+ unsigned long event, void *ptr);
+
+int mlx_tls_add_one(struct mlx_accel_core_device *accel_device);
+void mlx_tls_remove_one(struct mlx_accel_core_device *accel_device);
+
+struct mlx_tls_dev *mlx_tls_find_dev_by_netdev(struct net_device *netdev);
+
+#endif /* __TLS_H__ */
--
2.7.4
Powered by blists - more mailing lists