Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2022 Intel Corporation.
3 : : * Copyright (c) 2022, 2023 NVIDIA CORPORATION & AFFILIATES
4 : : * All rights reserved.
5 : : */
6 : :
7 : : #include "spdk/stdinc.h"
8 : :
9 : : #include "spdk/accel_module.h"
10 : : #include "accel_internal.h"
11 : :
12 : : #include "spdk/env.h"
13 : : #include "spdk/likely.h"
14 : : #include "spdk/log.h"
15 : : #include "spdk/thread.h"
16 : : #include "spdk/json.h"
17 : : #include "spdk/crc32.h"
18 : : #include "spdk/util.h"
19 : : #include "spdk/xor.h"
20 : : #include "spdk/dif.h"
21 : :
22 : : #ifdef SPDK_CONFIG_HAVE_LZ4
23 : : #include <lz4.h>
24 : : #endif
25 : :
26 : : #ifdef SPDK_CONFIG_ISAL
27 : : #include "../isa-l/include/igzip_lib.h"
28 : : #ifdef SPDK_CONFIG_ISAL_CRYPTO
29 : : #include "../isa-l-crypto/include/aes_xts.h"
30 : : #include "../isa-l-crypto/include/isal_crypto_api.h"
31 : : #endif
32 : : #endif
33 : :
34 : : /* Per the AES-XTS spec, the size of data unit cannot be bigger than 2^20 blocks, 128b each block */
35 : : #define ACCEL_AES_XTS_MAX_BLOCK_SIZE (1 << 24)
36 : :
37 : : #ifdef SPDK_CONFIG_ISAL
38 : : #define COMP_DEFLATE_MIN_LEVEL ISAL_DEF_MIN_LEVEL
39 : : #define COMP_DEFLATE_MAX_LEVEL ISAL_DEF_MAX_LEVEL
40 : : #else
41 : : #define COMP_DEFLATE_MIN_LEVEL 0
42 : : #define COMP_DEFLATE_MAX_LEVEL 0
43 : : #endif
44 : :
45 : : #define COMP_DEFLATE_LEVEL_NUM (COMP_DEFLATE_MAX_LEVEL + 1)
46 : :
47 : : struct comp_deflate_level_buf {
48 : : uint32_t size;
49 : : uint8_t *buf;
50 : : };
51 : :
52 : : struct sw_accel_io_channel {
53 : : /* for ISAL */
54 : : #ifdef SPDK_CONFIG_ISAL
55 : : struct isal_zstream stream;
56 : : struct inflate_state state;
57 : : /* The array index corresponds to the algorithm level */
58 : : struct comp_deflate_level_buf deflate_level_bufs[COMP_DEFLATE_LEVEL_NUM];
59 : : uint8_t level_buf_mem[ISAL_DEF_LVL0_DEFAULT + ISAL_DEF_LVL1_DEFAULT +
60 : : ISAL_DEF_LVL2_DEFAULT + ISAL_DEF_LVL3_DEFAULT];
61 : : #endif
62 : : #ifdef SPDK_CONFIG_HAVE_LZ4
63 : : /* for lz4 */
64 : : LZ4_stream_t *lz4_stream;
65 : : LZ4_streamDecode_t *lz4_stream_decode;
66 : : #endif
67 : : struct spdk_poller *completion_poller;
68 : : STAILQ_HEAD(, spdk_accel_task) tasks_to_complete;
69 : : };
70 : :
71 : : typedef int (*sw_accel_crypto_op)(const uint8_t *k2, const uint8_t *k1,
72 : : const uint8_t *initial_tweak, const uint64_t len_bytes,
73 : : const void *in, void *out);
74 : :
75 : : struct sw_accel_crypto_key_data {
76 : : sw_accel_crypto_op encrypt;
77 : : sw_accel_crypto_op decrypt;
78 : : };
79 : :
80 : : static struct spdk_accel_module_if g_sw_module;
81 : :
82 : : static void sw_accel_crypto_key_deinit(struct spdk_accel_crypto_key *_key);
83 : : static int sw_accel_crypto_key_init(struct spdk_accel_crypto_key *key);
84 : : static bool sw_accel_crypto_supports_tweak_mode(enum spdk_accel_crypto_tweak_mode tweak_mode);
85 : : static bool sw_accel_crypto_supports_cipher(enum spdk_accel_cipher cipher, size_t key_size);
86 : :
87 : : /* Post SW completions to a list; processed by ->completion_poller. */
88 : : inline static void
89 : 122910996 : _add_to_comp_list(struct sw_accel_io_channel *sw_ch, struct spdk_accel_task *accel_task, int status)
90 : : {
91 [ + - + - ]: 122910996 : accel_task->status = status;
92 [ + - + - : 122910996 : STAILQ_INSERT_TAIL(&sw_ch->tasks_to_complete, accel_task, link);
+ - + - +
- + - + -
+ - + - +
- + - +
- ]
93 : 122910996 : }
94 : :
95 : : static bool
96 : 34648 : sw_accel_supports_opcode(enum spdk_accel_opcode opc)
97 : : {
98 [ + + ]: 34648 : switch (opc) {
99 : 33016 : case SPDK_ACCEL_OPC_COPY:
100 : : case SPDK_ACCEL_OPC_FILL:
101 : : case SPDK_ACCEL_OPC_DUALCAST:
102 : : case SPDK_ACCEL_OPC_COMPARE:
103 : : case SPDK_ACCEL_OPC_CRC32C:
104 : : case SPDK_ACCEL_OPC_COPY_CRC32C:
105 : : case SPDK_ACCEL_OPC_COMPRESS:
106 : : case SPDK_ACCEL_OPC_DECOMPRESS:
107 : : case SPDK_ACCEL_OPC_ENCRYPT:
108 : : case SPDK_ACCEL_OPC_DECRYPT:
109 : : case SPDK_ACCEL_OPC_XOR:
110 : : case SPDK_ACCEL_OPC_DIF_VERIFY:
111 : : case SPDK_ACCEL_OPC_DIF_GENERATE:
112 : : case SPDK_ACCEL_OPC_DIF_GENERATE_COPY:
113 : : case SPDK_ACCEL_OPC_DIF_VERIFY_COPY:
114 : : case SPDK_ACCEL_OPC_DIX_GENERATE:
115 : : case SPDK_ACCEL_OPC_DIX_VERIFY:
116 : 34648 : return true;
117 : 0 : default:
118 : 0 : return false;
119 : : }
120 : 1632 : }
121 : :
122 : : static int
123 : 819972 : _sw_accel_dualcast_iovs(struct iovec *dst_iovs, uint32_t dst_iovcnt,
124 : : struct iovec *dst2_iovs, uint32_t dst2_iovcnt,
125 : : struct iovec *src_iovs, uint32_t src_iovcnt)
126 : : {
127 [ + - - + : 819972 : if (spdk_unlikely(dst_iovcnt != 1 || dst2_iovcnt != 1 || src_iovcnt != 1)) {
+ + - + ]
128 : 0 : return -EINVAL;
129 : : }
130 : :
131 [ + + + + : 819972 : if (spdk_unlikely(dst_iovs[0].iov_len != src_iovs[0].iov_len ||
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
132 : : dst_iovs[0].iov_len != dst2_iovs[0].iov_len)) {
133 : 0 : return -EINVAL;
134 : : }
135 : :
136 [ - + - + : 819972 : memcpy(dst_iovs[0].iov_base, src_iovs[0].iov_base, dst_iovs[0].iov_len);
# # # # #
# # # # #
# # # # #
# # # ]
137 [ - + - + : 819972 : memcpy(dst2_iovs[0].iov_base, src_iovs[0].iov_base, dst_iovs[0].iov_len);
# # # # #
# # # # #
# # # # #
# # # ]
138 : :
139 : 819972 : return 0;
140 : 1 : }
141 : :
142 : : static void
143 : 96399188 : _sw_accel_copy_iovs(struct iovec *dst_iovs, uint32_t dst_iovcnt,
144 : : struct iovec *src_iovs, uint32_t src_iovcnt)
145 : : {
146 : 37479362 : struct spdk_ioviter iter;
147 : 37479362 : void *src, *dst;
148 : : size_t len;
149 : :
150 [ + + ]: 152207219 : for (len = spdk_ioviter_first(&iter, src_iovs, src_iovcnt,
151 : 27588741 : dst_iovs, dst_iovcnt, &src, &dst);
152 [ + + ]: 201162417 : len != 0;
153 : 104763229 : len = spdk_ioviter_next(&iter, &src, &dst)) {
154 [ - + - + ]: 104763229 : memcpy(dst, src, len);
155 : 28219290 : }
156 : 96399188 : }
157 : :
158 : : static int
159 : 1056196 : _sw_accel_compare(struct iovec *src_iovs, uint32_t src_iovcnt,
160 : : struct iovec *src2_iovs, uint32_t src2_iovcnt)
161 : : {
162 [ + + - + ]: 1056196 : if (spdk_unlikely(src_iovcnt != 1 || src2_iovcnt != 1)) {
163 : 0 : return -EINVAL;
164 : : }
165 : :
166 [ + + # # : 1056196 : if (spdk_unlikely(src_iovs[0].iov_len != src2_iovs[0].iov_len)) {
# # # # #
# # # #
# ]
167 : 0 : return -EINVAL;
168 : : }
169 : :
170 [ - + - + : 1056196 : return memcmp(src_iovs[0].iov_base, src2_iovs[0].iov_base, src_iovs[0].iov_len);
# # # # #
# # # # #
# # # # #
# # # ]
171 : 1 : }
172 : :
173 : : static int
174 : 13381675 : _sw_accel_fill(struct iovec *iovs, uint32_t iovcnt, uint8_t fill)
175 : : {
176 : : void *dst;
177 : : size_t nbytes;
178 : :
179 [ - + ]: 13381675 : if (spdk_unlikely(iovcnt != 1)) {
180 : 0 : return -EINVAL;
181 : : }
182 : :
183 [ # # # # : 13381675 : dst = iovs[0].iov_base;
# # ]
184 [ # # # # : 13381675 : nbytes = iovs[0].iov_len;
# # ]
185 : :
186 [ - + ]: 13381675 : memset(dst, fill, nbytes);
187 : :
188 : 13381675 : return 0;
189 : 2590078 : }
190 : :
191 : : static void
192 : 4977758 : _sw_accel_crc32cv(uint32_t *crc_dst, struct iovec *iov, uint32_t iovcnt, uint32_t seed)
193 : : {
194 [ # # ]: 4977758 : *crc_dst = spdk_crc32c_iov_update(iov, iovcnt, ~seed);
195 : 4977758 : }
196 : :
197 : : static int
198 : 0 : _sw_accel_compress_lz4(struct sw_accel_io_channel *sw_ch, struct spdk_accel_task *accel_task)
199 : : {
200 : : #ifdef SPDK_CONFIG_HAVE_LZ4
201 : 0 : LZ4_stream_t *stream = sw_ch->lz4_stream;
202 : 0 : struct iovec *siov = accel_task->s.iovs;
203 : 0 : struct iovec *diov = accel_task->d.iovs;
204 : 0 : size_t dst_segoffset = 0;
205 : 0 : int32_t comp_size = 0;
206 : 0 : uint32_t output_size = 0;
207 : 0 : uint32_t i, d = 0;
208 : 0 : int rc = 0;
209 : :
210 : 0 : LZ4_resetStream(stream);
211 [ # # ]: 0 : for (i = 0; i < accel_task->s.iovcnt; i++) {
212 [ # # ]: 0 : if ((diov[d].iov_len - dst_segoffset) == 0) {
213 [ # # ]: 0 : if (++d < accel_task->d.iovcnt) {
214 : 0 : dst_segoffset = 0;
215 : 0 : } else {
216 : 0 : SPDK_ERRLOG("Not enough destination buffer provided.\n");
217 : 0 : rc = -ENOMEM;
218 : 0 : break;
219 : : }
220 : 0 : }
221 : :
222 : 0 : comp_size = LZ4_compress_fast_continue(stream, siov[i].iov_base, diov[d].iov_base + dst_segoffset,
223 : 0 : siov[i].iov_len, diov[d].iov_len - dst_segoffset,
224 : 0 : accel_task->comp.level);
225 [ # # ]: 0 : if (comp_size <= 0) {
226 : 0 : SPDK_ERRLOG("LZ4_compress_fast_continue was incorrectly executed.\n");
227 : 0 : rc = -EIO;
228 : 0 : break;
229 : : }
230 : :
231 : 0 : dst_segoffset += comp_size;
232 : 0 : output_size += comp_size;
233 : 0 : }
234 : :
235 : : /* Get our total output size */
236 [ # # ]: 0 : if (accel_task->output_size != NULL) {
237 : 0 : *accel_task->output_size = output_size;
238 : 0 : }
239 : :
240 : 0 : return rc;
241 : : #else
242 : 0 : SPDK_ERRLOG("LZ4 library is required to use software compression.\n");
243 : 0 : return -EINVAL;
244 : : #endif
245 : : }
246 : :
247 : : static int
248 : 0 : _sw_accel_decompress_lz4(struct sw_accel_io_channel *sw_ch, struct spdk_accel_task *accel_task)
249 : : {
250 : : #ifdef SPDK_CONFIG_HAVE_LZ4
251 : 0 : LZ4_streamDecode_t *stream = sw_ch->lz4_stream_decode;
252 : 0 : struct iovec *siov = accel_task->s.iovs;
253 : 0 : struct iovec *diov = accel_task->d.iovs;
254 : 0 : size_t dst_segoffset = 0;
255 : 0 : int32_t decomp_size = 0;
256 : 0 : uint32_t output_size = 0;
257 : 0 : uint32_t i, d = 0;
258 : 0 : int rc = 0;
259 : :
260 : 0 : LZ4_setStreamDecode(stream, NULL, 0);
261 [ # # ]: 0 : for (i = 0; i < accel_task->s.iovcnt; ++i) {
262 [ # # ]: 0 : if ((diov[d].iov_len - dst_segoffset) == 0) {
263 [ # # ]: 0 : if (++d < accel_task->d.iovcnt) {
264 : 0 : dst_segoffset = 0;
265 : 0 : } else {
266 : 0 : SPDK_ERRLOG("Not enough destination buffer provided.\n");
267 : 0 : rc = -ENOMEM;
268 : 0 : break;
269 : : }
270 : 0 : }
271 : 0 : decomp_size = LZ4_decompress_safe_continue(stream, siov[i].iov_base,
272 : 0 : diov[d].iov_base + dst_segoffset, siov[i].iov_len,
273 : 0 : diov[d].iov_len - dst_segoffset);
274 [ # # ]: 0 : if (decomp_size < 0) {
275 : 0 : SPDK_ERRLOG("LZ4_compress_fast_continue was incorrectly executed.\n");
276 : 0 : rc = -EIO;
277 : 0 : break;
278 : : }
279 : 0 : dst_segoffset += decomp_size;
280 : 0 : output_size += decomp_size;
281 : 0 : }
282 : :
283 : : /* Get our total output size */
284 [ # # ]: 0 : if (accel_task->output_size != NULL) {
285 : 0 : *accel_task->output_size = output_size;
286 : 0 : }
287 : :
288 : 0 : return rc;
289 : : #else
290 : 0 : SPDK_ERRLOG("LZ4 library is required to use software compression.\n");
291 : 0 : return -EINVAL;
292 : : #endif
293 : : }
294 : :
295 : : static int
296 : 318985 : _sw_accel_compress_deflate(struct sw_accel_io_channel *sw_ch, struct spdk_accel_task *accel_task)
297 : : {
298 : : #ifdef SPDK_CONFIG_ISAL
299 [ # # # # : 318985 : size_t last_seglen = accel_task->s.iovs[accel_task->s.iovcnt - 1].iov_len;
# # # # #
# # # # #
# # # # #
# # # ]
300 [ # # # # : 318985 : struct iovec *siov = accel_task->s.iovs;
# # # # ]
301 [ # # # # : 318985 : struct iovec *diov = accel_task->d.iovs;
# # # # ]
302 : : size_t remaining;
303 : 318985 : uint32_t i, s = 0, d = 0;
304 : 318985 : int rc = 0;
305 : :
306 [ - + # # : 318985 : if (accel_task->comp.level > COMP_DEFLATE_MAX_LEVEL) {
# # # # #
# ]
307 [ # # # # : 0 : SPDK_ERRLOG("isal_deflate doesn't support this algorithm level(%u)\n", accel_task->comp.level);
# # # # ]
308 : 0 : return -EINVAL;
309 : : }
310 : :
311 : 318985 : remaining = 0;
312 [ + + # # : 637970 : for (i = 0; i < accel_task->s.iovcnt; ++i) {
# # # # #
# ]
313 [ # # # # : 318985 : remaining += accel_task->s.iovs[i].iov_len;
# # # # #
# # # #
# ]
314 : 2 : }
315 : :
316 [ # # ]: 318985 : isal_deflate_reset(&sw_ch->stream);
317 [ # # # # : 318985 : sw_ch->stream.end_of_stream = 0;
# # ]
318 [ # # # # : 318985 : sw_ch->stream.next_out = diov[d].iov_base;
# # # # #
# # # ]
319 [ # # # # : 318985 : sw_ch->stream.avail_out = diov[d].iov_len;
# # # # #
# # # ]
320 [ # # # # : 318985 : sw_ch->stream.next_in = siov[s].iov_base;
# # # # #
# # # ]
321 [ # # # # : 318985 : sw_ch->stream.avail_in = siov[s].iov_len;
# # # # #
# # # ]
322 [ # # # # : 318985 : sw_ch->stream.level = accel_task->comp.level;
# # # # #
# # # #
# ]
323 [ # # # # : 318985 : sw_ch->stream.level_buf = sw_ch->deflate_level_bufs[accel_task->comp.level].buf;
# # # # #
# # # # #
# # # # #
# # # #
# ]
324 [ # # # # : 318985 : sw_ch->stream.level_buf_size = sw_ch->deflate_level_bufs[accel_task->comp.level].size;
# # # # #
# # # # #
# # # # #
# # # #
# ]
325 : :
326 : 2 : do {
327 : : /* if isal has exhausted the current dst iovec, move to the next
328 : : * one if there is one */
329 [ + + # # : 318985 : if (sw_ch->stream.avail_out == 0) {
# # # # ]
330 [ # # # # : 0 : if (++d < accel_task->d.iovcnt) {
# # # # #
# ]
331 [ # # # # : 0 : sw_ch->stream.next_out = diov[d].iov_base;
# # # # #
# # # ]
332 [ # # # # : 0 : sw_ch->stream.avail_out = diov[d].iov_len;
# # # # #
# # # ]
333 [ # # # # : 0 : assert(sw_ch->stream.avail_out > 0);
# # # # #
# ]
334 : 0 : } else {
335 : : /* we have no avail_out but also no more iovecs left so this is
336 : : * the case where either the output buffer was a perfect fit
337 : : * or not enough was provided. Check the ISAL state to determine
338 : : * which. */
339 [ # # # # : 0 : if (sw_ch->stream.internal_state.state != ZSTATE_END) {
# # # # #
# ]
340 : 0 : SPDK_ERRLOG("Not enough destination buffer provided.\n");
341 : 0 : rc = -ENOMEM;
342 : 0 : }
343 : 0 : break;
344 : : }
345 : 0 : }
346 : :
347 : : /* if isal has exhausted the current src iovec, move to the next
348 : : * one if there is one */
349 [ - + - - : 318985 : if (sw_ch->stream.avail_in == 0 && ((s + 1) < accel_task->s.iovcnt)) {
# # # # #
# # # # #
# # # # ]
350 : 0 : s++;
351 [ # # # # : 0 : sw_ch->stream.next_in = siov[s].iov_base;
# # # # #
# # # ]
352 [ # # # # : 0 : sw_ch->stream.avail_in = siov[s].iov_len;
# # # # #
# # # ]
353 [ # # # # : 0 : assert(sw_ch->stream.avail_in > 0);
# # # # #
# ]
354 : 0 : }
355 : :
356 [ + + ]: 318985 : if (remaining <= last_seglen) {
357 : : /* Need to set end of stream on last block */
358 [ # # # # : 318985 : sw_ch->stream.end_of_stream = 1;
# # ]
359 : 2 : }
360 : :
361 [ # # ]: 318985 : rc = isal_deflate(&sw_ch->stream);
362 [ + + ]: 318985 : if (rc) {
363 : 0 : SPDK_ERRLOG("isal_deflate returned error %d.\n", rc);
364 : 0 : }
365 : :
366 [ + + ]: 318985 : if (remaining > 0) {
367 [ + + # # : 318985 : assert(siov[s].iov_len > sw_ch->stream.avail_in);
# # # # #
# # # # #
# # ]
368 [ # # # # : 318985 : remaining -= (siov[s].iov_len - sw_ch->stream.avail_in);
# # # # #
# # # ]
369 : 2 : }
370 : :
371 [ - + - + : 318985 : } while (remaining > 0 || sw_ch->stream.avail_out == 0);
# # # # #
# ]
372 [ + + # # : 318985 : assert(sw_ch->stream.avail_in == 0);
# # # # #
# ]
373 : :
374 : : /* Get our total output size */
375 [ + + # # : 318985 : if (accel_task->output_size != NULL) {
# # # # ]
376 [ + + # # : 318985 : assert(sw_ch->stream.total_out > 0);
# # # # #
# ]
377 [ # # # # : 318985 : *accel_task->output_size = sw_ch->stream.total_out;
# # # # #
# # # #
# ]
378 : 2 : }
379 : :
380 : 318985 : return rc;
381 : : #else
382 : : SPDK_ERRLOG("ISAL option is required to use software compression.\n");
383 : : return -EINVAL;
384 : : #endif
385 : 2 : }
386 : :
387 : : static int
388 : 1028020 : _sw_accel_decompress_deflate(struct sw_accel_io_channel *sw_ch, struct spdk_accel_task *accel_task)
389 : : {
390 : : #ifdef SPDK_CONFIG_ISAL
391 [ # # # # : 1028020 : struct iovec *siov = accel_task->s.iovs;
# # # # ]
392 [ # # # # : 1028020 : struct iovec *diov = accel_task->d.iovs;
# # # # ]
393 : 1028020 : uint32_t s = 0, d = 0;
394 : 1028020 : int rc = 0;
395 : :
396 [ # # ]: 1028020 : isal_inflate_reset(&sw_ch->state);
397 [ # # # # : 1028020 : sw_ch->state.next_out = diov[d].iov_base;
# # # # #
# # # ]
398 [ # # # # : 1028020 : sw_ch->state.avail_out = diov[d].iov_len;
# # # # #
# # # ]
399 [ # # # # : 1028020 : sw_ch->state.next_in = siov[s].iov_base;
# # # # #
# # # ]
400 [ # # # # : 1028020 : sw_ch->state.avail_in = siov[s].iov_len;
# # # # #
# # # ]
401 : :
402 : 7 : do {
403 : : /* if isal has exhausted the current dst iovec, move to the next
404 : : * one if there is one */
405 [ - + - - : 1028020 : if (sw_ch->state.avail_out == 0 && ((d + 1) < accel_task->d.iovcnt)) {
# # # # #
# # # # #
# # # # ]
406 : 0 : d++;
407 [ # # # # : 0 : sw_ch->state.next_out = diov[d].iov_base;
# # # # #
# # # ]
408 [ # # # # : 0 : sw_ch->state.avail_out = diov[d].iov_len;
# # # # #
# # # ]
409 [ # # # # : 0 : assert(sw_ch->state.avail_out > 0);
# # # # #
# ]
410 : 0 : }
411 : :
412 : : /* if isal has exhausted the current src iovec, move to the next
413 : : * one if there is one */
414 [ - + - - : 1028020 : if (sw_ch->state.avail_in == 0 && ((s + 1) < accel_task->s.iovcnt)) {
# # # # #
# # # # #
# # # # ]
415 : 0 : s++;
416 [ # # # # : 0 : sw_ch->state.next_in = siov[s].iov_base;
# # # # #
# # # ]
417 [ # # # # : 0 : sw_ch->state.avail_in = siov[s].iov_len;
# # # # #
# # # ]
418 [ # # # # : 0 : assert(sw_ch->state.avail_in > 0);
# # # # #
# ]
419 : 0 : }
420 : :
421 [ # # ]: 1028020 : rc = isal_inflate(&sw_ch->state);
422 [ - + ]: 1028020 : if (rc) {
423 : 0 : SPDK_ERRLOG("isal_inflate returned error %d.\n", rc);
424 : 0 : }
425 : :
426 [ - + # # : 1028020 : } while (sw_ch->state.block_state < ISAL_BLOCK_FINISH);
# # # # ]
427 [ + + # # : 1028020 : assert(sw_ch->state.avail_in == 0);
# # # # #
# ]
428 : :
429 : : /* Get our total output size */
430 [ + + # # : 1028020 : if (accel_task->output_size != NULL) {
# # # # ]
431 [ - + # # : 248632 : assert(sw_ch->state.total_out > 0);
# # # # #
# ]
432 [ # # # # : 248632 : *accel_task->output_size = sw_ch->state.total_out;
# # # # #
# # # #
# ]
433 : 0 : }
434 : :
435 : 1028020 : return rc;
436 : : #else
437 : : SPDK_ERRLOG("ISAL option is required to use software decompression.\n");
438 : : return -EINVAL;
439 : : #endif
440 : : }
441 : :
442 : : static int
443 : 318985 : _sw_accel_compress(struct sw_accel_io_channel *sw_ch, struct spdk_accel_task *accel_task)
444 : : {
445 [ + - + # : 318985 : switch (accel_task->comp.algo) {
# # # # #
# # ]
446 : 318983 : case SPDK_ACCEL_COMP_ALGO_DEFLATE:
447 : 318985 : return _sw_accel_compress_deflate(sw_ch, accel_task);
448 : 0 : case SPDK_ACCEL_COMP_ALGO_LZ4:
449 : 0 : return _sw_accel_compress_lz4(sw_ch, accel_task);
450 : 0 : default:
451 [ # # ]: 0 : assert(0);
452 : : return -EINVAL;
453 : : }
454 : 2 : }
455 : :
456 : : static int
457 : 1028020 : _sw_accel_decompress(struct sw_accel_io_channel *sw_ch, struct spdk_accel_task *accel_task)
458 : : {
459 [ + - + # : 1028020 : switch (accel_task->comp.algo) {
# # # # #
# # ]
460 : 1028013 : case SPDK_ACCEL_COMP_ALGO_DEFLATE:
461 : 1028020 : return _sw_accel_decompress_deflate(sw_ch, accel_task);
462 : 0 : case SPDK_ACCEL_COMP_ALGO_LZ4:
463 : 0 : return _sw_accel_decompress_lz4(sw_ch, accel_task);
464 : 0 : default:
465 [ # # ]: 0 : assert(0);
466 : : return -EINVAL;
467 : : }
468 : 7 : }
469 : :
470 : : static int
471 : 3200870 : _sw_accel_crypto_operation(struct spdk_accel_task *accel_task, struct spdk_accel_crypto_key *key,
472 : : sw_accel_crypto_op op)
473 : : {
474 : : #ifdef SPDK_CONFIG_ISAL_CRYPTO
475 : 15 : uint64_t iv[2];
476 : : size_t remaining_len, dst_len;
477 : 3200870 : uint64_t src_offset = 0, dst_offset = 0;
478 : 3200870 : uint32_t src_iovpos = 0, dst_iovpos = 0, src_iovcnt, dst_iovcnt;
479 : 3200870 : uint32_t i, block_size, crypto_len, crypto_accum_len = 0;
480 : : struct iovec *src_iov, *dst_iov;
481 : : uint8_t *src, *dst;
482 : : int rc;
483 : :
484 : : /* iv is 128 bits, since we are using logical block address (64 bits) as iv, fill first 8 bytes with zeroes */
485 [ # # # # ]: 3200870 : iv[0] = 0;
486 [ # # # # : 3200870 : iv[1] = accel_task->iv;
# # # # #
# ]
487 [ # # # # : 3200870 : src_iov = accel_task->s.iovs;
# # # # ]
488 [ # # # # : 3200870 : src_iovcnt = accel_task->s.iovcnt;
# # # # ]
489 [ + - # # : 3200870 : if (accel_task->d.iovcnt) {
# # # # #
# ]
490 [ # # # # : 3200870 : dst_iov = accel_task->d.iovs;
# # # # ]
491 [ # # # # : 3200870 : dst_iovcnt = accel_task->d.iovcnt;
# # # # ]
492 : 5 : } else {
493 : : /* inplace operation */
494 [ # # # # : 0 : dst_iov = accel_task->s.iovs;
# # # # ]
495 [ # # # # : 0 : dst_iovcnt = accel_task->s.iovcnt;
# # # # ]
496 : : }
497 [ # # # # : 3200870 : block_size = accel_task->block_size;
# # ]
498 : :
499 [ + - + - : 3200870 : if (!src_iovcnt || !dst_iovcnt || !block_size || !op) {
+ - - + ]
500 : 0 : SPDK_ERRLOG("src_iovcnt %d, dst_iovcnt %d, block_size %d, op %p\n", src_iovcnt, dst_iovcnt,
501 : : block_size, op);
502 : 0 : return -EINVAL;
503 : : }
504 : :
505 : 3200870 : remaining_len = 0;
506 [ + + ]: 6401845 : for (i = 0; i < src_iovcnt; i++) {
507 [ # # # # : 3200975 : remaining_len += src_iov[i].iov_len;
# # ]
508 : 5 : }
509 : 3200870 : dst_len = 0;
510 [ + + ]: 6401868 : for (i = 0; i < dst_iovcnt; i++) {
511 [ # # # # : 3200998 : dst_len += dst_iov[i].iov_len;
# # ]
512 : 5 : }
513 : :
514 [ + + - + ]: 3200870 : if (spdk_unlikely(remaining_len != dst_len || !remaining_len)) {
515 : 0 : return -ERANGE;
516 : : }
517 [ - + - + : 3200870 : if (spdk_unlikely(remaining_len % accel_task->block_size != 0)) {
# # # # #
# ]
518 : 0 : return -EINVAL;
519 : : }
520 : :
521 [ + + ]: 13882115 : while (remaining_len) {
522 [ - + # # : 13882115 : crypto_len = spdk_min(block_size - crypto_accum_len, src_iov->iov_len - src_offset);
# # # # #
# ]
523 [ - + # # : 13882115 : crypto_len = spdk_min(crypto_len, dst_iov->iov_len - dst_offset);
# # # # #
# ]
524 [ # # # # : 13882115 : src = (uint8_t *)src_iov->iov_base + src_offset;
# # ]
525 [ # # # # : 13882115 : dst = (uint8_t *)dst_iov->iov_base + dst_offset;
# # ]
526 : :
527 [ # # # # : 13882115 : rc = op((uint8_t *)key->key2, (uint8_t *)key->key, (uint8_t *)iv, crypto_len, src, dst);
# # # # #
# # # ]
528 [ + + ]: 13882115 : if (rc != ISAL_CRYPTO_ERR_NONE) {
529 : 0 : break;
530 : : }
531 : :
532 : 13882115 : src_offset += crypto_len;
533 : 13882115 : dst_offset += crypto_len;
534 : 13882115 : crypto_accum_len += crypto_len;
535 : 13882115 : remaining_len -= crypto_len;
536 : :
537 [ + + ]: 13882115 : if (crypto_accum_len == block_size) {
538 : : /* we can process part of logical block. Once the whole block is processed, increment iv */
539 : 13882115 : crypto_accum_len = 0;
540 [ # # # # ]: 13882115 : iv[1]++;
541 : 5 : }
542 [ + + # # : 13882115 : if (src_offset == src_iov->iov_len) {
# # ]
543 [ # # ]: 3200975 : src_iov++;
544 : 3200975 : src_iovpos++;
545 : 3200975 : src_offset = 0;
546 : 5 : }
547 [ + + ]: 13882115 : if (src_iovpos == src_iovcnt) {
548 : 3200870 : break;
549 : : }
550 [ + + # # : 10681245 : if (dst_offset == dst_iov->iov_len) {
# # ]
551 [ # # ]: 128 : dst_iov++;
552 : 128 : dst_iovpos++;
553 : 128 : dst_offset = 0;
554 : 0 : }
555 [ - + ]: 10681245 : if (dst_iovpos == dst_iovcnt) {
556 : 0 : break;
557 : : }
558 : : }
559 : :
560 [ - + ]: 3200870 : if (remaining_len) {
561 : 0 : SPDK_ERRLOG("remaining len %zu\n", remaining_len);
562 : 0 : return -EINVAL;
563 : : }
564 : :
565 : 3200870 : return 0;
566 : : #else
567 : : return -ENOTSUP;
568 : : #endif
569 : 5 : }
570 : :
571 : : static int
572 : 2199713 : _sw_accel_encrypt(struct sw_accel_io_channel *sw_ch, struct spdk_accel_task *accel_task)
573 : : {
574 : : struct spdk_accel_crypto_key *key;
575 : : struct sw_accel_crypto_key_data *key_data;
576 : :
577 [ # # # # : 2199713 : key = accel_task->crypto_key;
# # ]
578 [ + + - + : 2199713 : if (spdk_unlikely(key->module_if != &g_sw_module || !key->priv)) {
# # # # #
# # # ]
579 : 0 : return -EINVAL;
580 : : }
581 [ + + # # : 2199713 : if (spdk_unlikely(accel_task->block_size > ACCEL_AES_XTS_MAX_BLOCK_SIZE)) {
# # # # #
# # # ]
582 [ # # # # : 0 : SPDK_WARNLOG("Max block size for AES_XTS is limited to %u, current size %u\n",
# # # # #
# ]
583 : : ACCEL_AES_XTS_MAX_BLOCK_SIZE, accel_task->block_size);
584 : 0 : return -ERANGE;
585 : : }
586 [ # # # # ]: 2199713 : key_data = key->priv;
587 [ # # # # ]: 2199713 : return _sw_accel_crypto_operation(accel_task, key, key_data->encrypt);
588 : 3 : }
589 : :
590 : : static int
591 : 1001157 : _sw_accel_decrypt(struct sw_accel_io_channel *sw_ch, struct spdk_accel_task *accel_task)
592 : : {
593 : : struct spdk_accel_crypto_key *key;
594 : : struct sw_accel_crypto_key_data *key_data;
595 : :
596 [ # # # # : 1001157 : key = accel_task->crypto_key;
# # ]
597 [ + + - + : 1001157 : if (spdk_unlikely(key->module_if != &g_sw_module || !key->priv)) {
# # # # #
# # # ]
598 : 0 : return -EINVAL;
599 : : }
600 [ + + # # : 1001157 : if (spdk_unlikely(accel_task->block_size > ACCEL_AES_XTS_MAX_BLOCK_SIZE)) {
# # # # #
# # # ]
601 [ # # # # : 0 : SPDK_WARNLOG("Max block size for AES_XTS is limited to %u, current size %u\n",
# # # # #
# ]
602 : : ACCEL_AES_XTS_MAX_BLOCK_SIZE, accel_task->block_size);
603 : 0 : return -ERANGE;
604 : : }
605 [ # # # # ]: 1001157 : key_data = key->priv;
606 [ # # # # ]: 1001157 : return _sw_accel_crypto_operation(accel_task, key, key_data->decrypt);
607 : 2 : }
608 : :
609 : : static int
610 : 1841696 : _sw_accel_xor(struct sw_accel_io_channel *sw_ch, struct spdk_accel_task *accel_task)
611 : : {
612 [ # # # # : 1841698 : return spdk_xor_gen(accel_task->d.iovs[0].iov_base,
# # # # #
# # # #
# ]
613 [ # # # # : 1 : accel_task->nsrcs.srcs,
# # # # ]
614 [ # # # # : 1 : accel_task->nsrcs.cnt,
# # # # ]
615 [ # # # # : 1841696 : accel_task->d.iovs[0].iov_len);
# # # # #
# # # #
# ]
616 : : }
617 : :
618 : : static int
619 : 227480 : _sw_accel_dif_verify(struct sw_accel_io_channel *sw_ch, struct spdk_accel_task *accel_task)
620 : : {
621 [ # # # # : 454960 : return spdk_dif_verify(accel_task->s.iovs,
# # # # ]
622 [ # # # # : 227480 : accel_task->s.iovcnt,
# # # # ]
623 [ # # # # : 0 : accel_task->dif.num_blocks,
# # # # ]
624 [ # # # # : 0 : accel_task->dif.ctx,
# # # # ]
625 [ # # # # : 0 : accel_task->dif.err);
# # # # ]
626 : : }
627 : :
628 : : static int
629 : 18 : _sw_accel_dif_verify_copy(struct sw_accel_io_channel *sw_ch, struct spdk_accel_task *accel_task)
630 : : {
631 [ # # # # : 54 : return spdk_dif_verify_copy(accel_task->d.iovs,
# # # # ]
632 [ # # # # : 18 : accel_task->d.iovcnt,
# # # # ]
633 [ # # # # : 0 : accel_task->s.iovs,
# # # # ]
634 [ # # # # : 18 : accel_task->s.iovcnt,
# # # # ]
635 [ # # # # : 0 : accel_task->dif.num_blocks,
# # # # ]
636 [ # # # # : 0 : accel_task->dif.ctx,
# # # # ]
637 [ # # # # : 0 : accel_task->dif.err);
# # # # ]
638 : : }
639 : :
640 : : static int
641 : 571712 : _sw_accel_dif_generate(struct sw_accel_io_channel *sw_ch, struct spdk_accel_task *accel_task)
642 : : {
643 [ # # # # : 1143424 : return spdk_dif_generate(accel_task->s.iovs,
# # # # ]
644 [ # # # # : 571712 : accel_task->s.iovcnt,
# # # # ]
645 [ # # # # : 0 : accel_task->dif.num_blocks,
# # # # ]
646 [ # # # # : 0 : accel_task->dif.ctx);
# # # # ]
647 : : }
648 : :
649 : : static int
650 : 201430 : _sw_accel_dif_generate_copy(struct sw_accel_io_channel *sw_ch, struct spdk_accel_task *accel_task)
651 : : {
652 [ # # # # : 604290 : return spdk_dif_generate_copy(accel_task->s.iovs,
# # # # ]
653 [ # # # # : 201430 : accel_task->s.iovcnt,
# # # # ]
654 [ # # # # : 0 : accel_task->d.iovs,
# # # # ]
655 [ # # # # : 201430 : accel_task->d.iovcnt,
# # # # ]
656 [ # # # # : 0 : accel_task->dif.num_blocks,
# # # # ]
657 [ # # # # : 0 : accel_task->dif.ctx);
# # # # ]
658 : : }
659 : :
660 : : static int
661 : 18 : _sw_accel_dix_generate(struct sw_accel_io_channel *sw_ch, struct spdk_accel_task *accel_task)
662 : : {
663 [ # # # # : 36 : return spdk_dix_generate(accel_task->s.iovs,
# # # # ]
664 [ # # # # : 18 : accel_task->s.iovcnt,
# # # # ]
665 [ # # # # : 3 : accel_task->d.iovs,
# # # # ]
666 [ # # # # : 3 : accel_task->dif.num_blocks,
# # # # ]
667 [ # # # # : 3 : accel_task->dif.ctx);
# # # # ]
668 : : }
669 : :
670 : : static int
671 : 180750 : _sw_accel_dix_verify(struct sw_accel_io_channel *sw_ch, struct spdk_accel_task *accel_task)
672 : : {
673 [ # # # # : 361500 : return spdk_dix_verify(accel_task->s.iovs,
# # # # ]
674 [ # # # # : 180750 : accel_task->s.iovcnt,
# # # # ]
675 [ # # # # : 3 : accel_task->d.iovs,
# # # # ]
676 [ # # # # : 3 : accel_task->dif.num_blocks,
# # # # ]
677 [ # # # # : 3 : accel_task->dif.ctx,
# # # # ]
678 [ # # # # : 3 : accel_task->dif.err);
# # # # ]
679 : : }
680 : :
681 : : static int
682 : 757564944 : accel_comp_poll(void *arg)
683 : : {
684 : 757564944 : struct sw_accel_io_channel *sw_ch = arg;
685 : 273598927 : STAILQ_HEAD(, spdk_accel_task) tasks_to_complete;
686 : : struct spdk_accel_task *accel_task;
687 : :
688 [ + + + - : 757564944 : if (STAILQ_EMPTY(&sw_ch->tasks_to_complete)) {
+ - + + ]
689 : 743894377 : return SPDK_POLLER_IDLE;
690 : : }
691 : :
692 [ + - ]: 13670567 : STAILQ_INIT(&tasks_to_complete);
693 [ + + + + : 13670567 : STAILQ_SWAP(&tasks_to_complete, &sw_ch->tasks_to_complete, spdk_accel_task);
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - -
+ # # + -
+ - + - +
- + - + -
+ - + - +
- ]
694 : :
695 [ + + ]: 135930476 : while ((accel_task = STAILQ_FIRST(&tasks_to_complete))) {
696 [ + + + - : 122384615 : STAILQ_REMOVE_HEAD(&tasks_to_complete, link);
+ - + + +
- ]
697 [ + - + - ]: 122384615 : spdk_accel_task_complete(accel_task, accel_task->status);
698 : : }
699 : :
700 : 13545861 : return SPDK_POLLER_BUSY;
701 : 41233109 : }
702 : :
703 : : static int
704 : 122901654 : sw_accel_submit_tasks(struct spdk_io_channel *ch, struct spdk_accel_task *accel_task)
705 : : {
706 : 122901654 : struct sw_accel_io_channel *sw_ch = spdk_io_channel_get_ctx(ch);
707 : : struct spdk_accel_task *tmp;
708 : 122901654 : int rc = 0;
709 : :
710 : : /*
711 : : * Lazily initialize our completion poller. We don't want to complete
712 : : * them inline as they'll likely submit another.
713 : : */
714 [ + + + - : 122901654 : if (spdk_unlikely(sw_ch->completion_poller == NULL)) {
+ + ]
715 [ + - + - ]: 3700 : sw_ch->completion_poller = SPDK_POLLER_REGISTER(accel_comp_poll, sw_ch, 0);
716 : 313 : }
717 : :
718 : 29815860 : do {
719 [ + + + + : 123326451 : switch (accel_task->op_code) {
+ + + + +
+ + + + +
+ + + + -
- - - ]
720 : 67869324 : case SPDK_ACCEL_OPC_COPY:
721 [ + - + - : 123136540 : _sw_accel_copy_iovs(accel_task->d.iovs, accel_task->d.iovcnt,
+ - + - +
- + - + -
+ - ]
722 [ + - + - : 27633608 : accel_task->s.iovs, accel_task->s.iovcnt);
+ - + - +
- + - + -
+ - ]
723 : 95502932 : break;
724 : 10791597 : case SPDK_ACCEL_OPC_FILL:
725 [ # # # # : 16005631 : rc = _sw_accel_fill(accel_task->d.iovs, accel_task->d.iovcnt,
# # # # #
# # # # #
# # ]
726 [ # # # # : 13398614 : accel_task->fill_pattern);
# # ]
727 : 13398614 : break;
728 : 819971 : case SPDK_ACCEL_OPC_DUALCAST:
729 [ # # # # : 819973 : rc = _sw_accel_dualcast_iovs(accel_task->d.iovs, accel_task->d.iovcnt,
# # # # #
# # # # #
# # ]
730 [ # # # # : 1 : accel_task->d2.iovs, accel_task->d2.iovcnt,
# # # # #
# # # # #
# # ]
731 [ # # # # : 1 : accel_task->s.iovs, accel_task->s.iovcnt);
# # # # #
# # # # #
# # ]
732 : 819972 : break;
733 : 1056195 : case SPDK_ACCEL_OPC_COMPARE:
734 [ # # # # : 1056197 : rc = _sw_accel_compare(accel_task->s.iovs, accel_task->s.iovcnt,
# # # # #
# # # # #
# # ]
735 [ # # # # : 1 : accel_task->s2.iovs, accel_task->s2.iovcnt);
# # # # #
# # # # #
# # ]
736 : 1056196 : break;
737 : 4036626 : case SPDK_ACCEL_OPC_CRC32C:
738 [ # # # # : 4036634 : _sw_accel_crc32cv(accel_task->crc_dst, accel_task->s.iovs, accel_task->s.iovcnt, accel_task->seed);
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
739 : 4036634 : break;
740 : 941123 : case SPDK_ACCEL_OPC_COPY_CRC32C:
741 [ # # # # : 941125 : _sw_accel_copy_iovs(accel_task->d.iovs, accel_task->d.iovcnt,
# # # # #
# # # # #
# # ]
742 [ # # # # : 1 : accel_task->s.iovs, accel_task->s.iovcnt);
# # # # #
# # # # #
# # ]
743 [ # # # # : 941125 : _sw_accel_crc32cv(accel_task->crc_dst, accel_task->s.iovs,
# # # # #
# # # #
# ]
744 [ # # # # : 1 : accel_task->s.iovcnt, accel_task->seed);
# # # # #
# # # #
# ]
745 : 941124 : break;
746 : 318983 : case SPDK_ACCEL_OPC_COMPRESS:
747 : 318985 : rc = _sw_accel_compress(sw_ch, accel_task);
748 : 318985 : break;
749 : 1028013 : case SPDK_ACCEL_OPC_DECOMPRESS:
750 : 1028020 : rc = _sw_accel_decompress(sw_ch, accel_task);
751 : 1028020 : break;
752 : 1841695 : case SPDK_ACCEL_OPC_XOR:
753 : 1841696 : rc = _sw_accel_xor(sw_ch, accel_task);
754 : 1841696 : break;
755 : 2199710 : case SPDK_ACCEL_OPC_ENCRYPT:
756 : 2199713 : rc = _sw_accel_encrypt(sw_ch, accel_task);
757 : 2199713 : break;
758 : 1001155 : case SPDK_ACCEL_OPC_DECRYPT:
759 : 1001157 : rc = _sw_accel_decrypt(sw_ch, accel_task);
760 : 1001157 : break;
761 : 227480 : case SPDK_ACCEL_OPC_DIF_VERIFY:
762 : 227480 : rc = _sw_accel_dif_verify(sw_ch, accel_task);
763 : 227480 : break;
764 : 18 : case SPDK_ACCEL_OPC_DIF_VERIFY_COPY:
765 : 18 : rc = _sw_accel_dif_verify_copy(sw_ch, accel_task);
766 : 18 : break;
767 : 571712 : case SPDK_ACCEL_OPC_DIF_GENERATE:
768 : 571712 : rc = _sw_accel_dif_generate(sw_ch, accel_task);
769 : 571712 : break;
770 : 201430 : case SPDK_ACCEL_OPC_DIF_GENERATE_COPY:
771 : 201430 : rc = _sw_accel_dif_generate_copy(sw_ch, accel_task);
772 : 201430 : break;
773 : 15 : case SPDK_ACCEL_OPC_DIX_GENERATE:
774 : 18 : rc = _sw_accel_dix_generate(sw_ch, accel_task);
775 : 18 : break;
776 : 180747 : case SPDK_ACCEL_OPC_DIX_VERIFY:
777 : 180750 : rc = _sw_accel_dix_verify(sw_ch, accel_task);
778 : 180750 : break;
779 : 0 : default:
780 [ # # ]: 0 : assert(false);
781 : : break;
782 : : }
783 : :
784 [ + - + - : 123326451 : tmp = STAILQ_NEXT(accel_task, link);
+ - ]
785 : :
786 : 123326451 : _add_to_comp_list(sw_ch, accel_task, rc);
787 : :
788 : 123326451 : accel_task = tmp;
789 [ + + ]: 123326451 : } while (accel_task);
790 : :
791 : 122901654 : return 0;
792 : : }
793 : :
794 : : static int
795 : 8929 : sw_accel_create_cb(void *io_device, void *ctx_buf)
796 : : {
797 : 8929 : struct sw_accel_io_channel *sw_ch = ctx_buf;
798 : : #ifdef SPDK_CONFIG_ISAL
799 : : struct comp_deflate_level_buf *deflate_level_bufs;
800 : : int i;
801 : : #endif
802 : :
803 [ + - + - : 8929 : STAILQ_INIT(&sw_ch->tasks_to_complete);
+ - + - +
- + - + -
+ - ]
804 [ + - + - ]: 8929 : sw_ch->completion_poller = NULL;
805 : :
806 : : #ifdef SPDK_CONFIG_HAVE_LZ4
807 : 294 : sw_ch->lz4_stream = LZ4_createStream();
808 [ + - ]: 294 : if (sw_ch->lz4_stream == NULL) {
809 : 0 : SPDK_ERRLOG("Failed to create the lz4 stream for compression\n");
810 : 0 : return -ENOMEM;
811 : : }
812 : 294 : sw_ch->lz4_stream_decode = LZ4_createStreamDecode();
813 [ + - ]: 294 : if (sw_ch->lz4_stream_decode == NULL) {
814 : 0 : SPDK_ERRLOG("Failed to create the lz4 stream for decompression\n");
815 : 0 : LZ4_freeStream(sw_ch->lz4_stream);
816 : 0 : return -ENOMEM;
817 : : }
818 : : #endif
819 : : #ifdef SPDK_CONFIG_ISAL
820 [ + - + - : 8929 : sw_ch->deflate_level_bufs[0].buf = sw_ch->level_buf_mem;
+ - + - +
- + - ]
821 [ + - ]: 8929 : deflate_level_bufs = sw_ch->deflate_level_bufs;
822 [ + - + - : 8929 : deflate_level_bufs[0].size = ISAL_DEF_LVL0_DEFAULT;
+ - ]
823 [ + + + - ]: 35716 : for (i = 1; i < COMP_DEFLATE_LEVEL_NUM; i++) {
824 [ + - + - : 51933 : deflate_level_bufs[i].buf = deflate_level_bufs[i - 1].buf +
+ - + - +
- + - + -
+ - ]
825 [ + - + - : 26787 : deflate_level_bufs[i - 1].size;
+ - + - ]
826 [ + + + + ]: 26787 : switch (i) {
827 : 8551 : case 1:
828 [ + - + - : 8929 : deflate_level_bufs[i].size = ISAL_DEF_LVL1_DEFAULT;
+ - ]
829 : 8929 : break;
830 : 8551 : case 2:
831 [ + - + - : 8929 : deflate_level_bufs[i].size = ISAL_DEF_LVL2_DEFAULT;
+ - ]
832 : 8929 : break;
833 : 8551 : case 3:
834 [ + - + - : 8929 : deflate_level_bufs[i].size = ISAL_DEF_LVL3_DEFAULT;
+ - ]
835 : 8929 : break;
836 : 0 : default:
837 [ # # ]: 0 : assert(false);
838 : : }
839 : 1134 : }
840 : :
841 [ + - ]: 8929 : isal_deflate_init(&sw_ch->stream);
842 [ + - + - : 8929 : sw_ch->stream.flush = NO_FLUSH;
+ - ]
843 [ + - ]: 8929 : isal_inflate_init(&sw_ch->state);
844 : : #endif
845 : :
846 : 8929 : return 0;
847 : 294 : }
848 : :
849 : : static void
850 : 8929 : sw_accel_destroy_cb(void *io_device, void *ctx_buf)
851 : : {
852 : 8929 : struct sw_accel_io_channel *sw_ch = ctx_buf;
853 : :
854 : : #ifdef SPDK_CONFIG_HAVE_LZ4
855 : 294 : LZ4_freeStream(sw_ch->lz4_stream);
856 : 294 : LZ4_freeStreamDecode(sw_ch->lz4_stream_decode);
857 : : #endif
858 [ + - ]: 8929 : spdk_poller_unregister(&sw_ch->completion_poller);
859 : 8929 : }
860 : :
861 : : static struct spdk_io_channel *
862 : 151320 : sw_accel_get_io_channel(void)
863 : : {
864 : 151320 : return spdk_get_io_channel(&g_sw_module);
865 : : }
866 : :
867 : : static size_t
868 : 4076 : sw_accel_module_get_ctx_size(void)
869 : : {
870 : 4076 : return sizeof(struct spdk_accel_task);
871 : : }
872 : :
873 : : static int
874 : 2038 : sw_accel_module_init(void)
875 : : {
876 : 2038 : spdk_io_device_register(&g_sw_module, sw_accel_create_cb, sw_accel_destroy_cb,
877 : : sizeof(struct sw_accel_io_channel), "sw_accel_module");
878 : :
879 : 2038 : return 0;
880 : : }
881 : :
882 : : static void
883 : 2038 : sw_accel_module_fini(void *ctxt)
884 : : {
885 : 2038 : spdk_io_device_unregister(&g_sw_module, NULL);
886 : 2038 : spdk_accel_module_finish();
887 : 2038 : }
888 : :
889 : : static int
890 : 44 : sw_accel_create_aes_xts(struct spdk_accel_crypto_key *key)
891 : : {
892 : : #ifdef SPDK_CONFIG_ISAL_CRYPTO
893 : : struct sw_accel_crypto_key_data *key_data;
894 : :
895 : 44 : key_data = calloc(1, sizeof(*key_data));
896 [ + + ]: 44 : if (!key_data) {
897 : 0 : return -ENOMEM;
898 : : }
899 : :
900 [ + + - # : 44 : switch (key->key_size) {
# # # ]
901 : 42 : case SPDK_ACCEL_AES_XTS_128_KEY_SIZE:
902 [ # # # # ]: 44 : key_data->encrypt = isal_aes_xts_enc_128;
903 [ # # # # ]: 44 : key_data->decrypt = isal_aes_xts_dec_128;
904 : 44 : break;
905 : 0 : case SPDK_ACCEL_AES_XTS_256_KEY_SIZE:
906 [ # # # # ]: 0 : key_data->encrypt = isal_aes_xts_enc_256;
907 [ # # # # ]: 0 : key_data->decrypt = isal_aes_xts_dec_256;
908 : 0 : break;
909 : 0 : default:
910 [ # # ]: 0 : assert(0);
911 : : free(key_data);
912 : : return -EINVAL;
913 : : }
914 : :
915 [ # # # # ]: 44 : key->priv = key_data;
916 : :
917 : 44 : return 0;
918 : : #else
919 : : return -ENOTSUP;
920 : : #endif
921 : 2 : }
922 : :
923 : : static int
924 : 44 : sw_accel_crypto_key_init(struct spdk_accel_crypto_key *key)
925 : : {
926 : 44 : return sw_accel_create_aes_xts(key);
927 : : }
928 : :
929 : : static void
930 : 44 : sw_accel_crypto_key_deinit(struct spdk_accel_crypto_key *key)
931 : : {
932 [ + - + - : 44 : if (!key || key->module_if != &g_sw_module || !key->priv) {
+ + # # #
# # # #
# ]
933 : 0 : return;
934 : : }
935 : :
936 [ # # # # ]: 44 : free(key->priv);
937 : 2 : }
938 : :
939 : : static bool
940 : 44 : sw_accel_crypto_supports_tweak_mode(enum spdk_accel_crypto_tweak_mode tweak_mode)
941 : : {
942 : 44 : return tweak_mode == SPDK_ACCEL_CRYPTO_TWEAK_MODE_SIMPLE_LBA;
943 : : }
944 : :
945 : : static bool
946 : 44 : sw_accel_crypto_supports_cipher(enum spdk_accel_cipher cipher, size_t key_size)
947 : : {
948 [ + - ]: 44 : switch (cipher) {
949 : 42 : case SPDK_ACCEL_CIPHER_AES_XTS:
950 [ + + - - ]: 44 : return key_size == SPDK_ACCEL_AES_XTS_128_KEY_SIZE || key_size == SPDK_ACCEL_AES_XTS_256_KEY_SIZE;
951 : 0 : default:
952 : 0 : return false;
953 : : }
954 : 2 : }
955 : :
956 : : static bool
957 : 1347013 : sw_accel_compress_supports_algo(enum spdk_accel_comp_algo algo)
958 : : {
959 [ + + ]: 1347013 : switch (algo) {
960 : 1347002 : case SPDK_ACCEL_COMP_ALGO_DEFLATE:
961 : : #ifdef SPDK_CONFIG_HAVE_LZ4
962 : : case SPDK_ACCEL_COMP_ALGO_LZ4:
963 : : #endif
964 : 1347013 : return true;
965 : 0 : default:
966 : 0 : return false;
967 : : }
968 : 11 : }
969 : :
970 : : static int
971 : 10 : sw_accel_get_compress_level_range(enum spdk_accel_comp_algo algo,
972 : : uint32_t *min_level, uint32_t *max_level)
973 : : {
974 [ + - - ]: 10 : switch (algo) {
975 : 10 : case SPDK_ACCEL_COMP_ALGO_DEFLATE:
976 : : #ifdef SPDK_CONFIG_ISAL
977 [ # # ]: 10 : *min_level = COMP_DEFLATE_MIN_LEVEL;
978 [ # # ]: 10 : *max_level = COMP_DEFLATE_MAX_LEVEL;
979 : 10 : return 0;
980 : : #else
981 : : SPDK_ERRLOG("ISAL option is required to use software compression.\n");
982 : : return -EINVAL;
983 : : #endif
984 : 0 : case SPDK_ACCEL_COMP_ALGO_LZ4:
985 : : #ifdef SPDK_CONFIG_HAVE_LZ4
986 : 0 : *min_level = 1;
987 : 0 : *max_level = 65537;
988 : 0 : return 0;
989 : : #else
990 : 0 : SPDK_ERRLOG("LZ4 library is required to use software compression.\n");
991 : 0 : return -EINVAL;
992 : : #endif
993 : 0 : default:
994 : 0 : return -EINVAL;
995 : : }
996 : 0 : }
997 : :
998 : : static int
999 : 216 : sw_accel_get_operation_info(enum spdk_accel_opcode opcode,
1000 : : const struct spdk_accel_operation_exec_ctx *ctx,
1001 : : struct spdk_accel_opcode_info *info)
1002 : : {
1003 [ # # # # ]: 216 : info->required_alignment = 0;
1004 : :
1005 : 216 : return 0;
1006 : : }
1007 : :
1008 : : static struct spdk_accel_module_if g_sw_module = {
1009 : : .module_init = sw_accel_module_init,
1010 : : .module_fini = sw_accel_module_fini,
1011 : : .write_config_json = NULL,
1012 : : .get_ctx_size = sw_accel_module_get_ctx_size,
1013 : : .name = "software",
1014 : : .priority = SPDK_ACCEL_SW_PRIORITY,
1015 : : .supports_opcode = sw_accel_supports_opcode,
1016 : : .get_io_channel = sw_accel_get_io_channel,
1017 : : .submit_tasks = sw_accel_submit_tasks,
1018 : : .crypto_key_init = sw_accel_crypto_key_init,
1019 : : .crypto_key_deinit = sw_accel_crypto_key_deinit,
1020 : : .crypto_supports_tweak_mode = sw_accel_crypto_supports_tweak_mode,
1021 : : .crypto_supports_cipher = sw_accel_crypto_supports_cipher,
1022 : : .compress_supports_algo = sw_accel_compress_supports_algo,
1023 : : .get_compress_level_range = sw_accel_get_compress_level_range,
1024 : : .get_operation_info = sw_accel_get_operation_info,
1025 : : };
1026 : :
1027 : 2163 : SPDK_ACCEL_MODULE_REGISTER(sw, &g_sw_module)
|