Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net/mlx5: Accel, Add IPSec acceleration interface

Add routines for manipulating the hardware IPSec SA database (SADB).

In Innova IPSec, a Security Association (SA) is added or deleted
via a command message over the SBU connection.
The HW then sends a response message over the same connection.

Add implementation for Innova IPSec (FPGA-based) hardware.

These routines will be used by the IPSec offload support in a later patch
However they may also be used by others such as RDMA and RoCE IPSec.

mlx5/accel is a middle acceleration layer to allow mlx5e and other ULPs
to work directly with mlx5_core rather than Innova FPGA or other mlx5
acceleration providers.

In this patchset we add Innova IPSec support and mlx5/accel delegates
IPSec offloads to Innova routines.

In the future, when IPSec/TLS or any other acceleration gets integrated
into ConnectX chip, mlx5/accel layer will provide the integrated
acceleration, rather than the Innova one.

Signed-off-by: Ilan Tayari <ilant@mellanox.com>
Signed-off-by: Boris Pismenny <borisp@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>

authored by

Ilan Tayari and committed by
Saeed Mahameed
bebb23e6 a9956d35

+772 -1
+4
drivers/net/ethernet/mellanox/mlx5/core/Kconfig
··· 11 11 Core driver for low level functionality of the ConnectX-4 and 12 12 Connect-IB cards by Mellanox Technologies. 13 13 14 + config MLX5_ACCEL 15 + bool 16 + 14 17 config MLX5_FPGA 15 18 bool "Mellanox Technologies Innova support" 16 19 depends on MLX5_CORE 20 + select MLX5_ACCEL 17 21 ---help--- 18 22 Build support for the Innova family of network cards by Mellanox 19 23 Technologies. Innova network cards are comprised of a ConnectX chip
+4 -1
drivers/net/ethernet/mellanox/mlx5/core/Makefile
··· 6 6 mad.o transobj.o vport.o sriov.o fs_cmd.o fs_core.o \ 7 7 fs_counters.o rl.o lag.o dev.o lib/gid.o 8 8 9 - mlx5_core-$(CONFIG_MLX5_FPGA) += fpga/cmd.o fpga/core.o fpga/conn.o fpga/sdk.o 9 + mlx5_core-$(CONFIG_MLX5_ACCEL) += accel/ipsec.o 10 + 11 + mlx5_core-$(CONFIG_MLX5_FPGA) += fpga/cmd.o fpga/core.o fpga/conn.o fpga/sdk.o \ 12 + fpga/ipsec.o 10 13 11 14 mlx5_core-$(CONFIG_MLX5_CORE_EN) += wq.o eswitch.o eswitch_offloads.o \ 12 15 en_main.o en_common.o en_fs.o en_ethtool.o en_tx.o \
+78
drivers/net/ethernet/mellanox/mlx5/core/accel/ipsec.c
··· 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 <linux/mlx5/device.h> 35 + 36 + #include "accel/ipsec.h" 37 + #include "mlx5_core.h" 38 + #include "fpga/ipsec.h" 39 + 40 + void *mlx5_accel_ipsec_sa_cmd_exec(struct mlx5_core_dev *mdev, 41 + struct mlx5_accel_ipsec_sa *cmd) 42 + { 43 + if (!MLX5_IPSEC_DEV(mdev)) 44 + return ERR_PTR(-EOPNOTSUPP); 45 + 46 + return mlx5_fpga_ipsec_sa_cmd_exec(mdev, cmd); 47 + } 48 + 49 + int mlx5_accel_ipsec_sa_cmd_wait(void *ctx) 50 + { 51 + return mlx5_fpga_ipsec_sa_cmd_wait(ctx); 52 + } 53 + 54 + u32 mlx5_accel_ipsec_device_caps(struct mlx5_core_dev *mdev) 55 + { 56 + return mlx5_fpga_ipsec_device_caps(mdev); 57 + } 58 + 59 + unsigned int mlx5_accel_ipsec_counters_count(struct mlx5_core_dev *mdev) 60 + { 61 + return mlx5_fpga_ipsec_counters_count(mdev); 62 + } 63 + 64 + int mlx5_accel_ipsec_counters_read(struct mlx5_core_dev *mdev, u64 *counters, 65 + unsigned int count) 66 + { 67 + return mlx5_fpga_ipsec_counters_read(mdev, counters, count); 68 + } 69 + 70 + int mlx5_accel_ipsec_init(struct mlx5_core_dev *mdev) 71 + { 72 + return mlx5_fpga_ipsec_init(mdev); 73 + } 74 + 75 + void mlx5_accel_ipsec_cleanup(struct mlx5_core_dev *mdev) 76 + { 77 + mlx5_fpga_ipsec_cleanup(mdev); 78 + }
+138
drivers/net/ethernet/mellanox/mlx5/core/accel/ipsec.h
··· 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 __MLX5_ACCEL_IPSEC_H__ 35 + #define __MLX5_ACCEL_IPSEC_H__ 36 + 37 + #ifdef CONFIG_MLX5_ACCEL 38 + 39 + #include <linux/mlx5/driver.h> 40 + 41 + enum { 42 + MLX5_ACCEL_IPSEC_DEVICE = BIT(1), 43 + MLX5_ACCEL_IPSEC_IPV6 = BIT(2), 44 + MLX5_ACCEL_IPSEC_ESP = BIT(3), 45 + MLX5_ACCEL_IPSEC_LSO = BIT(4), 46 + }; 47 + 48 + #define MLX5_IPSEC_SADB_IP_AH BIT(7) 49 + #define MLX5_IPSEC_SADB_IP_ESP BIT(6) 50 + #define MLX5_IPSEC_SADB_SA_VALID BIT(5) 51 + #define MLX5_IPSEC_SADB_SPI_EN BIT(4) 52 + #define MLX5_IPSEC_SADB_DIR_SX BIT(3) 53 + #define MLX5_IPSEC_SADB_IPV6 BIT(2) 54 + 55 + enum { 56 + MLX5_IPSEC_CMD_ADD_SA = 0, 57 + MLX5_IPSEC_CMD_DEL_SA = 1, 58 + }; 59 + 60 + enum mlx5_accel_ipsec_enc_mode { 61 + MLX5_IPSEC_SADB_MODE_NONE = 0, 62 + MLX5_IPSEC_SADB_MODE_AES_GCM_128_AUTH_128 = 1, 63 + MLX5_IPSEC_SADB_MODE_AES_GCM_256_AUTH_128 = 3, 64 + }; 65 + 66 + #define MLX5_IPSEC_DEV(mdev) (mlx5_accel_ipsec_device_caps(mdev) & \ 67 + MLX5_ACCEL_IPSEC_DEVICE) 68 + 69 + struct mlx5_accel_ipsec_sa { 70 + __be32 cmd; 71 + u8 key_enc[32]; 72 + u8 key_auth[32]; 73 + __be32 sip[4]; 74 + __be32 dip[4]; 75 + union { 76 + struct { 77 + __be32 reserved; 78 + u8 salt_iv[8]; 79 + __be32 salt; 80 + } __packed gcm; 81 + struct { 82 + u8 salt[16]; 83 + } __packed cbc; 84 + }; 85 + __be32 spi; 86 + __be32 sw_sa_handle; 87 + __be16 tfclen; 88 + u8 enc_mode; 89 + u8 sip_masklen; 90 + u8 dip_masklen; 91 + u8 flags; 92 + u8 reserved[2]; 93 + } __packed; 94 + 95 + /** 96 + * mlx5_accel_ipsec_sa_cmd_exec - Execute an IPSec SADB command 97 + * @mdev: mlx5 device 98 + * @cmd: command to execute 99 + * May be called from atomic context. Returns context pointer, or error 100 + * Caller must eventually call mlx5_accel_ipsec_sa_cmd_wait from non-atomic 101 + * context, to cleanup the context pointer 102 + */ 103 + void *mlx5_accel_ipsec_sa_cmd_exec(struct mlx5_core_dev *mdev, 104 + struct mlx5_accel_ipsec_sa *cmd); 105 + 106 + /** 107 + * mlx5_accel_ipsec_sa_cmd_wait - Wait for command execution completion 108 + * @context: Context pointer returned from call to mlx5_accel_ipsec_sa_cmd_exec 109 + * Sleeps (killable) until command execution is complete. 110 + * Returns the command result, or -EINTR if killed 111 + */ 112 + int mlx5_accel_ipsec_sa_cmd_wait(void *context); 113 + 114 + u32 mlx5_accel_ipsec_device_caps(struct mlx5_core_dev *mdev); 115 + 116 + unsigned int mlx5_accel_ipsec_counters_count(struct mlx5_core_dev *mdev); 117 + int mlx5_accel_ipsec_counters_read(struct mlx5_core_dev *mdev, u64 *counters, 118 + unsigned int count); 119 + 120 + int mlx5_accel_ipsec_init(struct mlx5_core_dev *mdev); 121 + void mlx5_accel_ipsec_cleanup(struct mlx5_core_dev *mdev); 122 + 123 + #else 124 + 125 + #define MLX5_IPSEC_DEV(mdev) false 126 + 127 + static inline int mlx5_accel_ipsec_init(struct mlx5_core_dev *mdev) 128 + { 129 + return 0; 130 + } 131 + 132 + static inline void mlx5_accel_ipsec_cleanup(struct mlx5_core_dev *mdev) 133 + { 134 + } 135 + 136 + #endif 137 + 138 + #endif /* __MLX5_ACCEL_IPSEC_H__ */
+2
drivers/net/ethernet/mellanox/mlx5/core/fpga/core.h
··· 51 51 struct mlx5_core_mkey mkey; 52 52 struct mlx5_uars_page *uar; 53 53 } conn_res; 54 + 55 + struct mlx5_fpga_ipsec *ipsec; 54 56 }; 55 57 56 58 #define mlx5_fpga_dbg(__adev, format, ...) \
+376
drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.c
··· 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 <linux/mlx5/driver.h> 35 + 36 + #include "mlx5_core.h" 37 + #include "fpga/ipsec.h" 38 + #include "fpga/sdk.h" 39 + #include "fpga/core.h" 40 + 41 + #define SBU_QP_QUEUE_SIZE 8 42 + 43 + enum mlx5_ipsec_response_syndrome { 44 + MLX5_IPSEC_RESPONSE_SUCCESS = 0, 45 + MLX5_IPSEC_RESPONSE_ILLEGAL_REQUEST = 1, 46 + MLX5_IPSEC_RESPONSE_SADB_ISSUE = 2, 47 + MLX5_IPSEC_RESPONSE_WRITE_RESPONSE_ISSUE = 3, 48 + }; 49 + 50 + enum mlx5_fpga_ipsec_sacmd_status { 51 + MLX5_FPGA_IPSEC_SACMD_PENDING, 52 + MLX5_FPGA_IPSEC_SACMD_SEND_FAIL, 53 + MLX5_FPGA_IPSEC_SACMD_COMPLETE, 54 + }; 55 + 56 + struct mlx5_ipsec_command_context { 57 + struct mlx5_fpga_dma_buf buf; 58 + struct mlx5_accel_ipsec_sa sa; 59 + enum mlx5_fpga_ipsec_sacmd_status status; 60 + int status_code; 61 + struct completion complete; 62 + struct mlx5_fpga_device *dev; 63 + struct list_head list; /* Item in pending_cmds */ 64 + }; 65 + 66 + struct mlx5_ipsec_sadb_resp { 67 + __be32 syndrome; 68 + __be32 sw_sa_handle; 69 + u8 reserved[24]; 70 + } __packed; 71 + 72 + struct mlx5_fpga_ipsec { 73 + struct list_head pending_cmds; 74 + spinlock_t pending_cmds_lock; /* Protects pending_cmds */ 75 + u32 caps[MLX5_ST_SZ_DW(ipsec_extended_cap)]; 76 + struct mlx5_fpga_conn *conn; 77 + }; 78 + 79 + static bool mlx5_fpga_is_ipsec_device(struct mlx5_core_dev *mdev) 80 + { 81 + if (!mdev->fpga || !MLX5_CAP_GEN(mdev, fpga)) 82 + return false; 83 + 84 + if (MLX5_CAP_FPGA(mdev, ieee_vendor_id) != 85 + MLX5_FPGA_CAP_SANDBOX_VENDOR_ID_MLNX) 86 + return false; 87 + 88 + if (MLX5_CAP_FPGA(mdev, sandbox_product_id) != 89 + MLX5_FPGA_CAP_SANDBOX_PRODUCT_ID_IPSEC) 90 + return false; 91 + 92 + return true; 93 + } 94 + 95 + static void mlx5_fpga_ipsec_send_complete(struct mlx5_fpga_conn *conn, 96 + struct mlx5_fpga_device *fdev, 97 + struct mlx5_fpga_dma_buf *buf, 98 + u8 status) 99 + { 100 + struct mlx5_ipsec_command_context *context; 101 + 102 + if (status) { 103 + context = container_of(buf, struct mlx5_ipsec_command_context, 104 + buf); 105 + mlx5_fpga_warn(fdev, "IPSec command send failed with status %u\n", 106 + status); 107 + context->status = MLX5_FPGA_IPSEC_SACMD_SEND_FAIL; 108 + complete(&context->complete); 109 + } 110 + } 111 + 112 + static inline int syndrome_to_errno(enum mlx5_ipsec_response_syndrome syndrome) 113 + { 114 + switch (syndrome) { 115 + case MLX5_IPSEC_RESPONSE_SUCCESS: 116 + return 0; 117 + case MLX5_IPSEC_RESPONSE_SADB_ISSUE: 118 + return -EEXIST; 119 + case MLX5_IPSEC_RESPONSE_ILLEGAL_REQUEST: 120 + return -EINVAL; 121 + case MLX5_IPSEC_RESPONSE_WRITE_RESPONSE_ISSUE: 122 + return -EIO; 123 + } 124 + return -EIO; 125 + } 126 + 127 + static void mlx5_fpga_ipsec_recv(void *cb_arg, struct mlx5_fpga_dma_buf *buf) 128 + { 129 + struct mlx5_ipsec_sadb_resp *resp = buf->sg[0].data; 130 + struct mlx5_ipsec_command_context *context; 131 + enum mlx5_ipsec_response_syndrome syndrome; 132 + struct mlx5_fpga_device *fdev = cb_arg; 133 + unsigned long flags; 134 + 135 + if (buf->sg[0].size < sizeof(*resp)) { 136 + mlx5_fpga_warn(fdev, "Short receive from FPGA IPSec: %u < %zu bytes\n", 137 + buf->sg[0].size, sizeof(*resp)); 138 + return; 139 + } 140 + 141 + mlx5_fpga_dbg(fdev, "mlx5_ipsec recv_cb syndrome %08x sa_id %x\n", 142 + ntohl(resp->syndrome), ntohl(resp->sw_sa_handle)); 143 + 144 + spin_lock_irqsave(&fdev->ipsec->pending_cmds_lock, flags); 145 + context = list_first_entry_or_null(&fdev->ipsec->pending_cmds, 146 + struct mlx5_ipsec_command_context, 147 + list); 148 + if (context) 149 + list_del(&context->list); 150 + spin_unlock_irqrestore(&fdev->ipsec->pending_cmds_lock, flags); 151 + 152 + if (!context) { 153 + mlx5_fpga_warn(fdev, "Received IPSec offload response without pending command request\n"); 154 + return; 155 + } 156 + mlx5_fpga_dbg(fdev, "Handling response for %p\n", context); 157 + 158 + if (context->sa.sw_sa_handle != resp->sw_sa_handle) { 159 + mlx5_fpga_err(fdev, "mismatch SA handle. cmd 0x%08x vs resp 0x%08x\n", 160 + ntohl(context->sa.sw_sa_handle), 161 + ntohl(resp->sw_sa_handle)); 162 + return; 163 + } 164 + 165 + syndrome = ntohl(resp->syndrome); 166 + context->status_code = syndrome_to_errno(syndrome); 167 + context->status = MLX5_FPGA_IPSEC_SACMD_COMPLETE; 168 + 169 + if (context->status_code) 170 + mlx5_fpga_warn(fdev, "IPSec SADB command failed with syndrome %08x\n", 171 + syndrome); 172 + complete(&context->complete); 173 + } 174 + 175 + void *mlx5_fpga_ipsec_sa_cmd_exec(struct mlx5_core_dev *mdev, 176 + struct mlx5_accel_ipsec_sa *cmd) 177 + { 178 + struct mlx5_ipsec_command_context *context; 179 + struct mlx5_fpga_device *fdev = mdev->fpga; 180 + unsigned long flags; 181 + int res = 0; 182 + 183 + BUILD_BUG_ON((sizeof(struct mlx5_accel_ipsec_sa) & 3) != 0); 184 + if (!fdev || !fdev->ipsec) 185 + return ERR_PTR(-EOPNOTSUPP); 186 + 187 + context = kzalloc(sizeof(*context), GFP_ATOMIC); 188 + if (!context) 189 + return ERR_PTR(-ENOMEM); 190 + 191 + memcpy(&context->sa, cmd, sizeof(*cmd)); 192 + context->buf.complete = mlx5_fpga_ipsec_send_complete; 193 + context->buf.sg[0].size = sizeof(context->sa); 194 + context->buf.sg[0].data = &context->sa; 195 + init_completion(&context->complete); 196 + context->dev = fdev; 197 + spin_lock_irqsave(&fdev->ipsec->pending_cmds_lock, flags); 198 + list_add_tail(&context->list, &fdev->ipsec->pending_cmds); 199 + spin_unlock_irqrestore(&fdev->ipsec->pending_cmds_lock, flags); 200 + 201 + context->status = MLX5_FPGA_IPSEC_SACMD_PENDING; 202 + 203 + res = mlx5_fpga_sbu_conn_sendmsg(fdev->ipsec->conn, &context->buf); 204 + if (res) { 205 + mlx5_fpga_warn(fdev, "Failure sending IPSec command: %d\n", 206 + res); 207 + spin_lock_irqsave(&fdev->ipsec->pending_cmds_lock, flags); 208 + list_del(&context->list); 209 + spin_unlock_irqrestore(&fdev->ipsec->pending_cmds_lock, flags); 210 + kfree(context); 211 + return ERR_PTR(res); 212 + } 213 + /* Context will be freed by wait func after completion */ 214 + return context; 215 + } 216 + 217 + int mlx5_fpga_ipsec_sa_cmd_wait(void *ctx) 218 + { 219 + struct mlx5_ipsec_command_context *context = ctx; 220 + int res; 221 + 222 + res = wait_for_completion_killable(&context->complete); 223 + if (res) { 224 + mlx5_fpga_warn(context->dev, "Failure waiting for IPSec command response\n"); 225 + return -EINTR; 226 + } 227 + 228 + if (context->status == MLX5_FPGA_IPSEC_SACMD_COMPLETE) 229 + res = context->status_code; 230 + else 231 + res = -EIO; 232 + 233 + kfree(context); 234 + return res; 235 + } 236 + 237 + u32 mlx5_fpga_ipsec_device_caps(struct mlx5_core_dev *mdev) 238 + { 239 + struct mlx5_fpga_device *fdev = mdev->fpga; 240 + u32 ret = 0; 241 + 242 + if (mlx5_fpga_is_ipsec_device(mdev)) 243 + ret |= MLX5_ACCEL_IPSEC_DEVICE; 244 + else 245 + return ret; 246 + 247 + if (!fdev->ipsec) 248 + return ret; 249 + 250 + if (MLX5_GET(ipsec_extended_cap, fdev->ipsec->caps, esp)) 251 + ret |= MLX5_ACCEL_IPSEC_ESP; 252 + 253 + if (MLX5_GET(ipsec_extended_cap, fdev->ipsec->caps, ipv6)) 254 + ret |= MLX5_ACCEL_IPSEC_IPV6; 255 + 256 + if (MLX5_GET(ipsec_extended_cap, fdev->ipsec->caps, lso)) 257 + ret |= MLX5_ACCEL_IPSEC_LSO; 258 + 259 + return ret; 260 + } 261 + 262 + unsigned int mlx5_fpga_ipsec_counters_count(struct mlx5_core_dev *mdev) 263 + { 264 + struct mlx5_fpga_device *fdev = mdev->fpga; 265 + 266 + if (!fdev || !fdev->ipsec) 267 + return 0; 268 + 269 + return MLX5_GET(ipsec_extended_cap, fdev->ipsec->caps, 270 + number_of_ipsec_counters); 271 + } 272 + 273 + int mlx5_fpga_ipsec_counters_read(struct mlx5_core_dev *mdev, u64 *counters, 274 + unsigned int counters_count) 275 + { 276 + struct mlx5_fpga_device *fdev = mdev->fpga; 277 + unsigned int i; 278 + u32 *data; 279 + u32 count; 280 + u64 addr; 281 + int ret; 282 + 283 + if (!fdev || !fdev->ipsec) 284 + return 0; 285 + 286 + addr = (u64)MLX5_GET(ipsec_extended_cap, fdev->ipsec->caps, 287 + ipsec_counters_addr_low) + 288 + ((u64)MLX5_GET(ipsec_extended_cap, fdev->ipsec->caps, 289 + ipsec_counters_addr_high) << 32); 290 + 291 + count = mlx5_fpga_ipsec_counters_count(mdev); 292 + 293 + data = kzalloc(sizeof(u32) * count * 2, GFP_KERNEL); 294 + if (!data) { 295 + ret = -ENOMEM; 296 + goto out; 297 + } 298 + 299 + ret = mlx5_fpga_mem_read(fdev, count * sizeof(u64), addr, data, 300 + MLX5_FPGA_ACCESS_TYPE_DONTCARE); 301 + if (ret < 0) { 302 + mlx5_fpga_err(fdev, "Failed to read IPSec counters from HW: %d\n", 303 + ret); 304 + goto out; 305 + } 306 + ret = 0; 307 + 308 + if (count > counters_count) 309 + count = counters_count; 310 + 311 + /* Each counter is low word, then high. But each word is big-endian */ 312 + for (i = 0; i < count; i++) 313 + counters[i] = (u64)ntohl(data[i * 2]) | 314 + ((u64)ntohl(data[i * 2 + 1]) << 32); 315 + 316 + out: 317 + kfree(data); 318 + return ret; 319 + } 320 + 321 + int mlx5_fpga_ipsec_init(struct mlx5_core_dev *mdev) 322 + { 323 + struct mlx5_fpga_conn_attr init_attr = {0}; 324 + struct mlx5_fpga_device *fdev = mdev->fpga; 325 + struct mlx5_fpga_conn *conn; 326 + int err; 327 + 328 + if (!mlx5_fpga_is_ipsec_device(mdev)) 329 + return 0; 330 + 331 + fdev->ipsec = kzalloc(sizeof(*fdev->ipsec), GFP_KERNEL); 332 + if (!fdev->ipsec) 333 + return -ENOMEM; 334 + 335 + err = mlx5_fpga_get_sbu_caps(fdev, sizeof(fdev->ipsec->caps), 336 + fdev->ipsec->caps); 337 + if (err) { 338 + mlx5_fpga_err(fdev, "Failed to retrieve IPSec extended capabilities: %d\n", 339 + err); 340 + goto error; 341 + } 342 + 343 + INIT_LIST_HEAD(&fdev->ipsec->pending_cmds); 344 + spin_lock_init(&fdev->ipsec->pending_cmds_lock); 345 + 346 + init_attr.rx_size = SBU_QP_QUEUE_SIZE; 347 + init_attr.tx_size = SBU_QP_QUEUE_SIZE; 348 + init_attr.recv_cb = mlx5_fpga_ipsec_recv; 349 + init_attr.cb_arg = fdev; 350 + conn = mlx5_fpga_sbu_conn_create(fdev, &init_attr); 351 + if (IS_ERR(conn)) { 352 + err = PTR_ERR(conn); 353 + mlx5_fpga_err(fdev, "Error creating IPSec command connection %d\n", 354 + err); 355 + goto error; 356 + } 357 + fdev->ipsec->conn = conn; 358 + return 0; 359 + 360 + error: 361 + kfree(fdev->ipsec); 362 + fdev->ipsec = NULL; 363 + return err; 364 + } 365 + 366 + void mlx5_fpga_ipsec_cleanup(struct mlx5_core_dev *mdev) 367 + { 368 + struct mlx5_fpga_device *fdev = mdev->fpga; 369 + 370 + if (!mlx5_fpga_is_ipsec_device(mdev)) 371 + return; 372 + 373 + mlx5_fpga_sbu_conn_destroy(fdev->ipsec->conn); 374 + kfree(fdev->ipsec); 375 + fdev->ipsec = NULL; 376 + }
+94
drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.h
··· 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 __MLX5_FPGA_IPSEC_H__ 35 + #define __MLX5_FPGA_IPSEC_H__ 36 + 37 + #include "accel/ipsec.h" 38 + 39 + #ifdef CONFIG_MLX5_FPGA 40 + 41 + void *mlx5_fpga_ipsec_sa_cmd_exec(struct mlx5_core_dev *mdev, 42 + struct mlx5_accel_ipsec_sa *cmd); 43 + int mlx5_fpga_ipsec_sa_cmd_wait(void *context); 44 + 45 + u32 mlx5_fpga_ipsec_device_caps(struct mlx5_core_dev *mdev); 46 + unsigned int mlx5_fpga_ipsec_counters_count(struct mlx5_core_dev *mdev); 47 + int mlx5_fpga_ipsec_counters_read(struct mlx5_core_dev *mdev, u64 *counters, 48 + unsigned int counters_count); 49 + 50 + int mlx5_fpga_ipsec_init(struct mlx5_core_dev *mdev); 51 + void mlx5_fpga_ipsec_cleanup(struct mlx5_core_dev *mdev); 52 + 53 + #else 54 + 55 + static inline void *mlx5_fpga_ipsec_sa_cmd_exec(struct mlx5_core_dev *mdev, 56 + struct mlx5_accel_ipsec_sa *cmd) 57 + { 58 + return ERR_PTR(-EOPNOTSUPP); 59 + } 60 + 61 + static inline int mlx5_fpga_ipsec_sa_cmd_wait(void *context) 62 + { 63 + return -EOPNOTSUPP; 64 + } 65 + 66 + static inline u32 mlx5_fpga_ipsec_device_caps(struct mlx5_core_dev *mdev) 67 + { 68 + return 0; 69 + } 70 + 71 + static inline unsigned int 72 + mlx5_fpga_ipsec_counters_count(struct mlx5_core_dev *mdev) 73 + { 74 + return 0; 75 + } 76 + 77 + static inline int mlx5_fpga_ipsec_counters_read(struct mlx5_core_dev *mdev, 78 + u64 *counters) 79 + { 80 + return 0; 81 + } 82 + 83 + static inline int mlx5_fpga_ipsec_init(struct mlx5_core_dev *mdev) 84 + { 85 + return 0; 86 + } 87 + 88 + static inline void mlx5_fpga_ipsec_cleanup(struct mlx5_core_dev *mdev) 89 + { 90 + } 91 + 92 + #endif /* CONFIG_MLX5_FPGA */ 93 + 94 + #endif /* __MLX5_FPGA_SADB_H__ */
+9
drivers/net/ethernet/mellanox/mlx5/core/main.c
··· 58 58 #endif 59 59 #include "lib/mlx5.h" 60 60 #include "fpga/core.h" 61 + #include "accel/ipsec.h" 61 62 62 63 MODULE_AUTHOR("Eli Cohen <eli@mellanox.com>"); 63 64 MODULE_DESCRIPTION("Mellanox Connect-IB, ConnectX-4 core driver"); ··· 1170 1169 dev_err(&pdev->dev, "fpga device start failed %d\n", err); 1171 1170 goto err_fpga_start; 1172 1171 } 1172 + err = mlx5_accel_ipsec_init(dev); 1173 + if (err) { 1174 + dev_err(&pdev->dev, "IPSec device start failed %d\n", err); 1175 + goto err_ipsec_start; 1176 + } 1173 1177 1174 1178 if (mlx5_device_registered(dev)) { 1175 1179 mlx5_attach_device(dev); ··· 1194 1188 return 0; 1195 1189 1196 1190 err_reg_dev: 1191 + mlx5_accel_ipsec_cleanup(dev); 1192 + err_ipsec_start: 1197 1193 mlx5_fpga_device_stop(dev); 1198 1194 1199 1195 err_fpga_start: ··· 1275 1267 if (mlx5_device_registered(dev)) 1276 1268 mlx5_detach_device(dev); 1277 1269 1270 + mlx5_accel_ipsec_cleanup(dev); 1278 1271 mlx5_fpga_device_stop(dev); 1279 1272 1280 1273 mlx5_sriov_detach(dev);
+67
include/linux/mlx5/mlx5_ifc_fpga.h
··· 32 32 #ifndef MLX5_IFC_FPGA_H 33 33 #define MLX5_IFC_FPGA_H 34 34 35 + enum { 36 + MLX5_FPGA_CAP_SANDBOX_VENDOR_ID_MLNX = 0x2c9, 37 + }; 38 + 39 + enum { 40 + MLX5_FPGA_CAP_SANDBOX_PRODUCT_ID_IPSEC = 0x2, 41 + }; 42 + 35 43 struct mlx5_ifc_fpga_shell_caps_bits { 36 44 u8 max_num_qps[0x10]; 37 45 u8 reserved_at_10[0x8]; ··· 368 360 u8 syndrome[0x20]; 369 361 370 362 u8 reserved_at_40[0x40]; 363 + }; 364 + 365 + struct mlx5_ifc_ipsec_extended_cap_bits { 366 + u8 encapsulation[0x20]; 367 + 368 + u8 reserved_0[0x15]; 369 + u8 ipv4_fragment[0x1]; 370 + u8 ipv6[0x1]; 371 + u8 esn[0x1]; 372 + u8 lso[0x1]; 373 + u8 transport_and_tunnel_mode[0x1]; 374 + u8 tunnel_mode[0x1]; 375 + u8 transport_mode[0x1]; 376 + u8 ah_esp[0x1]; 377 + u8 esp[0x1]; 378 + u8 ah[0x1]; 379 + u8 ipv4_options[0x1]; 380 + 381 + u8 auth_alg[0x20]; 382 + 383 + u8 enc_alg[0x20]; 384 + 385 + u8 sa_cap[0x20]; 386 + 387 + u8 reserved_1[0x10]; 388 + u8 number_of_ipsec_counters[0x10]; 389 + 390 + u8 ipsec_counters_addr_low[0x20]; 391 + u8 ipsec_counters_addr_high[0x20]; 392 + }; 393 + 394 + struct mlx5_ifc_ipsec_counters_bits { 395 + u8 dec_in_packets[0x40]; 396 + 397 + u8 dec_out_packets[0x40]; 398 + 399 + u8 dec_bypass_packets[0x40]; 400 + 401 + u8 enc_in_packets[0x40]; 402 + 403 + u8 enc_out_packets[0x40]; 404 + 405 + u8 enc_bypass_packets[0x40]; 406 + 407 + u8 drop_dec_packets[0x40]; 408 + 409 + u8 failed_auth_dec_packets[0x40]; 410 + 411 + u8 drop_enc_packets[0x40]; 412 + 413 + u8 success_add_sa[0x40]; 414 + 415 + u8 fail_add_sa[0x40]; 416 + 417 + u8 success_delete_sa[0x40]; 418 + 419 + u8 fail_delete_sa[0x40]; 420 + 421 + u8 dropped_cmd[0x40]; 371 422 }; 372 423 373 424 #endif /* MLX5_IFC_FPGA_H */