Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2019 Intel Corporation.
3 : : * All rights reserved.
4 : : * Copyright (c) 2021,2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
5 : : */
6 : :
7 : : #include "spdk/stdinc.h"
8 : : #include "spdk/nvme.h"
9 : :
10 : : #include "spdk_internal/cunit.h"
11 : :
12 : : #include "common/lib/test_sock.c"
13 : : #include "nvme/nvme_internal.h"
14 : : #include "common/lib/nvme/common_stubs.h"
15 : :
16 : : /* nvme_transport_ctrlr_disconnect_qpair_done() stub is defined in common_stubs.h, but we need to
17 : : * override it here */
18 : : static void nvme_transport_ctrlr_disconnect_qpair_done_mocked(struct spdk_nvme_qpair *qpair);
19 : : #define nvme_transport_ctrlr_disconnect_qpair_done nvme_transport_ctrlr_disconnect_qpair_done_mocked
20 : :
21 : : #include "nvme/nvme_tcp.c"
22 : :
23 : 4 : SPDK_LOG_REGISTER_COMPONENT(nvme)
24 : :
25 : 0 : DEFINE_STUB(nvme_qpair_submit_request,
26 : : int, (struct spdk_nvme_qpair *qpair, struct nvme_request *req), 0);
27 : :
28 : 0 : DEFINE_STUB(spdk_nvme_poll_group_remove, int, (struct spdk_nvme_poll_group *group,
29 : : struct spdk_nvme_qpair *qpair), 0);
30 : 0 : DEFINE_STUB(spdk_sock_get_optimal_sock_group,
31 : : int,
32 : : (struct spdk_sock *sock, struct spdk_sock_group **group, struct spdk_sock_group *hint),
33 : : 0);
34 : :
35 : 0 : DEFINE_STUB(spdk_sock_group_get_ctx,
36 : : void *,
37 : : (struct spdk_sock_group *group),
38 : : NULL);
39 : :
40 : 0 : DEFINE_STUB(spdk_nvme_poll_group_process_completions, int64_t, (struct spdk_nvme_poll_group *group,
41 : : uint32_t completions_per_qpair, spdk_nvme_disconnected_qpair_cb disconnected_qpair_cb), 0);
42 : :
43 : 0 : DEFINE_STUB(nvme_poll_group_connect_qpair, int, (struct spdk_nvme_qpair *qpair), 0);
44 : 4 : DEFINE_STUB_V(nvme_qpair_resubmit_requests, (struct spdk_nvme_qpair *qpair, uint32_t num_requests));
45 : :
46 : 12 : DEFINE_STUB_V(spdk_nvme_qpair_print_command, (struct spdk_nvme_qpair *qpair,
47 : : struct spdk_nvme_cmd *cmd));
48 : :
49 : 12 : DEFINE_STUB_V(spdk_nvme_qpair_print_completion, (struct spdk_nvme_qpair *qpair,
50 : : struct spdk_nvme_cpl *cpl));
51 : :
52 : : static void
53 : 16 : nvme_transport_ctrlr_disconnect_qpair_done_mocked(struct spdk_nvme_qpair *qpair)
54 : : {
55 : 16 : qpair->state = NVME_QPAIR_DISCONNECTED;
56 : 16 : }
57 : :
58 : : static void
59 : 4 : test_nvme_tcp_pdu_set_data_buf(void)
60 : : {
61 : 4 : struct nvme_tcp_pdu pdu = {};
62 : 4 : struct iovec iov[NVME_TCP_MAX_SGL_DESCRIPTORS] = {};
63 : : uint32_t data_len;
64 : : uint64_t i;
65 : :
66 : : /* 1st case: input is a single SGL entry. */
67 : 4 : iov[0].iov_base = (void *)0xDEADBEEF;
68 : 4 : iov[0].iov_len = 4096;
69 : :
70 : 4 : nvme_tcp_pdu_set_data_buf(&pdu, iov, 1, 1024, 512);
71 : :
72 : 4 : CU_ASSERT(pdu.data_iovcnt == 1);
73 : 4 : CU_ASSERT((uint64_t)pdu.data_iov[0].iov_base == 0xDEADBEEF + 1024);
74 : 4 : CU_ASSERT(pdu.data_iov[0].iov_len == 512);
75 : :
76 : : /* 2nd case: simulate split on multiple SGL entries. */
77 : 4 : iov[0].iov_base = (void *)0xDEADBEEF;
78 : 4 : iov[0].iov_len = 4096;
79 : 4 : iov[1].iov_base = (void *)0xFEEDBEEF;
80 : 4 : iov[1].iov_len = 512 * 7;
81 : 4 : iov[2].iov_base = (void *)0xF00DF00D;
82 : 4 : iov[2].iov_len = 4096 * 2;
83 : :
84 : 4 : nvme_tcp_pdu_set_data_buf(&pdu, iov, 3, 0, 2048);
85 : :
86 : 4 : CU_ASSERT(pdu.data_iovcnt == 1);
87 : 4 : CU_ASSERT((uint64_t)pdu.data_iov[0].iov_base == 0xDEADBEEF);
88 : 4 : CU_ASSERT(pdu.data_iov[0].iov_len == 2048);
89 : :
90 : 4 : nvme_tcp_pdu_set_data_buf(&pdu, iov, 3, 2048, 2048 + 512 * 3);
91 : :
92 : 4 : CU_ASSERT(pdu.data_iovcnt == 2);
93 : 4 : CU_ASSERT((uint64_t)pdu.data_iov[0].iov_base == 0xDEADBEEF + 2048);
94 : 4 : CU_ASSERT(pdu.data_iov[0].iov_len == 2048);
95 : 4 : CU_ASSERT((uint64_t)pdu.data_iov[1].iov_base == 0xFEEDBEEF);
96 : 4 : CU_ASSERT(pdu.data_iov[1].iov_len == 512 * 3);
97 : :
98 : 4 : nvme_tcp_pdu_set_data_buf(&pdu, iov, 3, 4096 + 512 * 3, 512 * 4 + 4096 * 2);
99 : :
100 : 4 : CU_ASSERT(pdu.data_iovcnt == 2);
101 : 4 : CU_ASSERT((uint64_t)pdu.data_iov[0].iov_base == 0xFEEDBEEF + 512 * 3);
102 : 4 : CU_ASSERT(pdu.data_iov[0].iov_len == 512 * 4);
103 : 4 : CU_ASSERT((uint64_t)pdu.data_iov[1].iov_base == 0xF00DF00D);
104 : 4 : CU_ASSERT(pdu.data_iov[1].iov_len == 4096 * 2);
105 : :
106 : : /* 3rd case: Number of input SGL entries is equal to the number of PDU SGL
107 : : * entries.
108 : : */
109 : 4 : data_len = 0;
110 [ + + ]: 68 : for (i = 0; i < NVME_TCP_MAX_SGL_DESCRIPTORS; i++) {
111 : 64 : iov[i].iov_base = (void *)(0xDEADBEEF + i);
112 : 64 : iov[i].iov_len = 512 * (i + 1);
113 : 64 : data_len += 512 * (i + 1);
114 : : }
115 : :
116 : 4 : nvme_tcp_pdu_set_data_buf(&pdu, iov, NVME_TCP_MAX_SGL_DESCRIPTORS, 0, data_len);
117 : :
118 : 4 : CU_ASSERT(pdu.data_iovcnt == NVME_TCP_MAX_SGL_DESCRIPTORS);
119 [ + + ]: 68 : for (i = 0; i < NVME_TCP_MAX_SGL_DESCRIPTORS; i++) {
120 : 64 : CU_ASSERT((uint64_t)pdu.data_iov[i].iov_base == 0xDEADBEEF + i);
121 : 64 : CU_ASSERT(pdu.data_iov[i].iov_len == 512 * (i + 1));
122 : : }
123 : 4 : }
124 : :
125 : : static void
126 : 4 : test_nvme_tcp_build_iovs(void)
127 : : {
128 : 4 : const uintptr_t pdu_iov_len = 4096;
129 : 4 : struct nvme_tcp_pdu pdu = {};
130 : 4 : struct iovec iovs[5] = {};
131 : 4 : uint32_t mapped_length = 0;
132 : : int rc;
133 : :
134 : 4 : pdu.hdr.common.pdu_type = SPDK_NVME_TCP_PDU_TYPE_CAPSULE_CMD;
135 : 4 : pdu.hdr.common.hlen = sizeof(struct spdk_nvme_tcp_cmd);
136 : 4 : pdu.hdr.common.plen = pdu.hdr.common.hlen + SPDK_NVME_TCP_DIGEST_LEN + pdu_iov_len * 2 +
137 : : SPDK_NVME_TCP_DIGEST_LEN;
138 : 4 : pdu.data_len = pdu_iov_len * 2;
139 : 4 : pdu.padding_len = 0;
140 : :
141 : 4 : pdu.data_iov[0].iov_base = (void *)0xDEADBEEF;
142 : 4 : pdu.data_iov[0].iov_len = pdu_iov_len;
143 : 4 : pdu.data_iov[1].iov_base = (void *)(0xDEADBEEF + pdu_iov_len);
144 : 4 : pdu.data_iov[1].iov_len = pdu_iov_len;
145 : 4 : pdu.data_iovcnt = 2;
146 : :
147 : 4 : rc = nvme_tcp_build_iovs(iovs, 5, &pdu, true, true, &mapped_length);
148 : 4 : CU_ASSERT(rc == 4);
149 : 4 : CU_ASSERT(iovs[0].iov_base == (void *)&pdu.hdr.raw);
150 : 4 : CU_ASSERT(iovs[0].iov_len == sizeof(struct spdk_nvme_tcp_cmd) + SPDK_NVME_TCP_DIGEST_LEN);
151 : 4 : CU_ASSERT(iovs[1].iov_base == (void *)0xDEADBEEF);
152 : 4 : CU_ASSERT(iovs[1].iov_len == pdu_iov_len);
153 : 4 : CU_ASSERT(iovs[2].iov_base == (void *)(0xDEADBEEF + pdu_iov_len));
154 : 4 : CU_ASSERT(iovs[2].iov_len == pdu_iov_len);
155 : 4 : CU_ASSERT(iovs[3].iov_base == (void *)pdu.data_digest);
156 : 4 : CU_ASSERT(iovs[3].iov_len == SPDK_NVME_TCP_DIGEST_LEN);
157 : 4 : CU_ASSERT(mapped_length == sizeof(struct spdk_nvme_tcp_cmd) + SPDK_NVME_TCP_DIGEST_LEN +
158 : : pdu_iov_len * 2 + SPDK_NVME_TCP_DIGEST_LEN);
159 : :
160 : : /* Add a new data_iov entry, update pdu iov count and data length */
161 : 4 : pdu.data_iov[2].iov_base = (void *)(0xBAADF00D);
162 : 4 : pdu.data_iov[2].iov_len = 123;
163 : 4 : pdu.data_iovcnt = 3;
164 : 4 : pdu.data_len += 123;
165 : 4 : pdu.hdr.common.plen += 123;
166 : :
167 : 4 : rc = nvme_tcp_build_iovs(iovs, 5, &pdu, true, true, &mapped_length);
168 : 4 : CU_ASSERT(rc == 5);
169 : 4 : CU_ASSERT(iovs[0].iov_base == (void *)&pdu.hdr.raw);
170 : 4 : CU_ASSERT(iovs[0].iov_len == sizeof(struct spdk_nvme_tcp_cmd) + SPDK_NVME_TCP_DIGEST_LEN);
171 : 4 : CU_ASSERT(iovs[1].iov_base == (void *)0xDEADBEEF);
172 : 4 : CU_ASSERT(iovs[1].iov_len == pdu_iov_len);
173 : 4 : CU_ASSERT(iovs[2].iov_base == (void *)(0xDEADBEEF + pdu_iov_len));
174 : 4 : CU_ASSERT(iovs[2].iov_len == pdu_iov_len);
175 : 4 : CU_ASSERT(iovs[3].iov_base == (void *)(0xBAADF00D));
176 : 4 : CU_ASSERT(iovs[3].iov_len == 123);
177 : 4 : CU_ASSERT(iovs[4].iov_base == (void *)pdu.data_digest);
178 : 4 : CU_ASSERT(iovs[4].iov_len == SPDK_NVME_TCP_DIGEST_LEN);
179 : 4 : CU_ASSERT(mapped_length == sizeof(struct spdk_nvme_tcp_cmd) + SPDK_NVME_TCP_DIGEST_LEN +
180 : : pdu_iov_len * 2 + SPDK_NVME_TCP_DIGEST_LEN + 123);
181 : 4 : }
182 : :
183 : : struct nvme_tcp_ut_bdev_io {
184 : : struct iovec iovs[NVME_TCP_MAX_SGL_DESCRIPTORS];
185 : : int iovpos;
186 : : };
187 : :
188 : : /* essentially a simplification of bdev_nvme_next_sge and bdev_nvme_reset_sgl */
189 : : static void
190 : 24 : nvme_tcp_ut_reset_sgl(void *cb_arg, uint32_t offset)
191 : : {
192 : 24 : struct nvme_tcp_ut_bdev_io *bio = cb_arg;
193 : : struct iovec *iov;
194 : :
195 [ + - ]: 24 : for (bio->iovpos = 0; bio->iovpos < NVME_TCP_MAX_SGL_DESCRIPTORS; bio->iovpos++) {
196 : 24 : iov = &bio->iovs[bio->iovpos];
197 : : /* Offset must be aligned with the start of any SGL entry */
198 [ + - ]: 24 : if (offset == 0) {
199 : 24 : break;
200 : : }
201 : :
202 [ # # ]: 0 : SPDK_CU_ASSERT_FATAL(offset >= iov->iov_len);
203 : 0 : offset -= iov->iov_len;
204 : : }
205 : :
206 [ - + ]: 24 : SPDK_CU_ASSERT_FATAL(offset == 0);
207 [ - + ]: 24 : SPDK_CU_ASSERT_FATAL(bio->iovpos < NVME_TCP_MAX_SGL_DESCRIPTORS);
208 : 24 : }
209 : :
210 : : static int
211 : 100 : nvme_tcp_ut_next_sge(void *cb_arg, void **address, uint32_t *length)
212 : : {
213 : 100 : struct nvme_tcp_ut_bdev_io *bio = cb_arg;
214 : : struct iovec *iov;
215 : :
216 [ - + ]: 100 : SPDK_CU_ASSERT_FATAL(bio->iovpos < NVME_TCP_MAX_SGL_DESCRIPTORS);
217 : :
218 : 100 : iov = &bio->iovs[bio->iovpos];
219 : :
220 : 100 : *address = iov->iov_base;
221 : 100 : *length = iov->iov_len;
222 : 100 : bio->iovpos++;
223 : :
224 : 100 : return 0;
225 : : }
226 : :
227 : : static void
228 : 4 : test_nvme_tcp_build_sgl_request(void)
229 : : {
230 : 4 : struct nvme_tcp_qpair tqpair;
231 : 4 : struct spdk_nvme_ctrlr ctrlr = {{0}};
232 : 4 : struct nvme_tcp_req tcp_req = {0};
233 : 4 : struct nvme_request req = {{0}};
234 : 4 : struct nvme_tcp_ut_bdev_io bio;
235 : : uint64_t i;
236 : : int rc;
237 : :
238 : 4 : ctrlr.max_sges = NVME_TCP_MAX_SGL_DESCRIPTORS;
239 : 4 : tqpair.qpair.ctrlr = &ctrlr;
240 : 4 : tcp_req.req = &req;
241 : :
242 : 4 : req.payload = NVME_PAYLOAD_SGL(nvme_tcp_ut_reset_sgl, nvme_tcp_ut_next_sge, &bio, NULL);
243 : 4 : req.qpair = &tqpair.qpair;
244 : :
245 [ + + ]: 68 : for (i = 0; i < NVME_TCP_MAX_SGL_DESCRIPTORS; i++) {
246 : 64 : bio.iovs[i].iov_base = (void *)(0xFEEDB000 + i * 0x1000);
247 : 64 : bio.iovs[i].iov_len = 0;
248 : : }
249 : :
250 : : /* Test case 1: Single SGL. Expected: PASS */
251 : 4 : bio.iovpos = 0;
252 : 4 : req.payload_offset = 0;
253 : 4 : req.payload_size = 0x1000;
254 : 4 : bio.iovs[0].iov_len = 0x1000;
255 : 4 : rc = nvme_tcp_build_sgl_request(&tqpair, &tcp_req);
256 [ - + ]: 4 : SPDK_CU_ASSERT_FATAL(rc == 0);
257 : 4 : CU_ASSERT(bio.iovpos == 1);
258 : 4 : CU_ASSERT((uint64_t)tcp_req.iov[0].iov_base == (uint64_t)bio.iovs[0].iov_base);
259 : 4 : CU_ASSERT(tcp_req.iov[0].iov_len == bio.iovs[0].iov_len);
260 : 4 : CU_ASSERT(tcp_req.iovcnt == 1);
261 : :
262 : : /* Test case 2: Multiple SGL. Expected: PASS */
263 : 4 : bio.iovpos = 0;
264 : 4 : req.payload_offset = 0;
265 : 4 : req.payload_size = 0x4000;
266 [ + + ]: 20 : for (i = 0; i < 4; i++) {
267 : 16 : bio.iovs[i].iov_len = 0x1000;
268 : : }
269 : 4 : rc = nvme_tcp_build_sgl_request(&tqpair, &tcp_req);
270 [ - + ]: 4 : SPDK_CU_ASSERT_FATAL(rc == 0);
271 : 4 : CU_ASSERT(bio.iovpos == 4);
272 : 4 : CU_ASSERT(tcp_req.iovcnt == 4);
273 [ + + ]: 20 : for (i = 0; i < 4; i++) {
274 : 16 : CU_ASSERT(tcp_req.iov[i].iov_len == bio.iovs[i].iov_len);
275 : 16 : CU_ASSERT((uint64_t)tcp_req.iov[i].iov_base == (uint64_t)bio.iovs[i].iov_base);
276 : : }
277 : :
278 : : /* Test case 3: Payload is bigger than SGL. Expected: FAIL */
279 : 4 : bio.iovpos = 0;
280 : 4 : req.payload_offset = 0;
281 : 4 : req.payload_size = 0x17000;
282 [ + + ]: 68 : for (i = 0; i < NVME_TCP_MAX_SGL_DESCRIPTORS; i++) {
283 : 64 : bio.iovs[i].iov_len = 0x1000;
284 : : }
285 : 4 : rc = nvme_tcp_build_sgl_request(&tqpair, &tcp_req);
286 [ - + ]: 4 : SPDK_CU_ASSERT_FATAL(rc != 0);
287 : 4 : CU_ASSERT(bio.iovpos == NVME_TCP_MAX_SGL_DESCRIPTORS);
288 [ + + ]: 68 : for (i = 0; i < NVME_TCP_MAX_SGL_DESCRIPTORS; i++) {
289 : 64 : CU_ASSERT(tcp_req.iov[i].iov_len == bio.iovs[i].iov_len);
290 : 64 : CU_ASSERT((uint64_t)tcp_req.iov[i].iov_base == (uint64_t)bio.iovs[i].iov_base);
291 : : }
292 : 4 : }
293 : :
294 : : static void
295 : 4 : test_nvme_tcp_pdu_set_data_buf_with_md(void)
296 : : {
297 : 4 : struct nvme_tcp_pdu pdu = {};
298 : 4 : struct iovec iovs[7] = {};
299 : 4 : struct spdk_dif_ctx dif_ctx = {};
300 : : int rc;
301 : 4 : struct spdk_dif_ctx_init_ext_opts dif_opts;
302 : :
303 : 4 : pdu.dif_ctx = &dif_ctx;
304 : :
305 : 4 : dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
306 : 4 : dif_opts.dif_pi_format = SPDK_DIF_PI_FORMAT_16;
307 : 4 : rc = spdk_dif_ctx_init(&dif_ctx, 520, 8, true, false, SPDK_DIF_DISABLE, 0,
308 : : 0, 0, 0, 0, 0, &dif_opts);
309 : 4 : CU_ASSERT(rc == 0);
310 : :
311 : : /* Single iovec case */
312 : 4 : iovs[0].iov_base = (void *)0xDEADBEEF;
313 : 4 : iovs[0].iov_len = 2080;
314 : :
315 : 4 : nvme_tcp_pdu_set_data_buf(&pdu, iovs, 1, 0, 500);
316 : :
317 : 4 : CU_ASSERT(dif_ctx.data_offset == 0);
318 : 4 : CU_ASSERT(pdu.data_len == 500);
319 : 4 : CU_ASSERT(pdu.data_iovcnt == 1);
320 : 4 : CU_ASSERT(pdu.data_iov[0].iov_base == (void *)0xDEADBEEF);
321 : 4 : CU_ASSERT(pdu.data_iov[0].iov_len == 500);
322 : :
323 : 4 : nvme_tcp_pdu_set_data_buf(&pdu, iovs, 1, 500, 1000);
324 : :
325 : 4 : CU_ASSERT(dif_ctx.data_offset == 500);
326 : 4 : CU_ASSERT(pdu.data_len == 1000);
327 : 4 : CU_ASSERT(pdu.data_iovcnt == 1);
328 : 4 : CU_ASSERT(pdu.data_iov[0].iov_base == (void *)(0xDEADBEEF + 500));
329 : 4 : CU_ASSERT(pdu.data_iov[0].iov_len == 1016);
330 : :
331 : 4 : nvme_tcp_pdu_set_data_buf(&pdu, iovs, 1, 1500, 548);
332 : :
333 : 4 : CU_ASSERT(dif_ctx.data_offset == 1500);
334 : 4 : CU_ASSERT(pdu.data_len == 548);
335 : 4 : CU_ASSERT(pdu.data_iovcnt == 1);
336 : 4 : CU_ASSERT(pdu.data_iov[0].iov_base == (void *)(0xDEADBEEF + 1516));
337 : 4 : CU_ASSERT(pdu.data_iov[0].iov_len == 564);
338 : :
339 : : /* Multiple iovecs case */
340 : 4 : iovs[0].iov_base = (void *)0xDEADBEEF;
341 : 4 : iovs[0].iov_len = 256;
342 : 4 : iovs[1].iov_base = (void *)((uint8_t *)(0xDEADBEEF + 0x1000));
343 : 4 : iovs[1].iov_len = 256 + 1;
344 : 4 : iovs[2].iov_base = (void *)((uint8_t *)(0xDEADBEEF + 0x2000));
345 : 4 : iovs[2].iov_len = 4;
346 : 4 : iovs[3].iov_base = (void *)((uint8_t *)(0xDEADBEEF + 0x3000));
347 : 4 : iovs[3].iov_len = 3 + 123;
348 : 4 : iovs[4].iov_base = (void *)((uint8_t *)(0xDEADBEEF + 0x4000));
349 : 4 : iovs[4].iov_len = 389 + 6;
350 : 4 : iovs[5].iov_base = (void *)((uint8_t *)(0xDEADBEEF + 0x5000));
351 : 4 : iovs[5].iov_len = 2 + 512 + 8 + 432;
352 : 4 : iovs[6].iov_base = (void *)((uint8_t *)(0xDEADBEEF + 0x6000));
353 : 4 : iovs[6].iov_len = 80 + 8;
354 : :
355 : 4 : nvme_tcp_pdu_set_data_buf(&pdu, iovs, 7, 0, 500);
356 : :
357 : 4 : CU_ASSERT(dif_ctx.data_offset == 0);
358 : 4 : CU_ASSERT(pdu.data_len == 500);
359 : 4 : CU_ASSERT(pdu.data_iovcnt == 2);
360 : 4 : CU_ASSERT(pdu.data_iov[0].iov_base == (void *)0xDEADBEEF);
361 : 4 : CU_ASSERT(pdu.data_iov[0].iov_len == 256);
362 : 4 : CU_ASSERT(pdu.data_iov[1].iov_base == (void *)(0xDEADBEEF + 0x1000));
363 : 4 : CU_ASSERT(pdu.data_iov[1].iov_len == 244);
364 : :
365 : 4 : nvme_tcp_pdu_set_data_buf(&pdu, iovs, 7, 500, 1000);
366 : :
367 : 4 : CU_ASSERT(dif_ctx.data_offset == 500);
368 : 4 : CU_ASSERT(pdu.data_len == 1000);
369 : 4 : CU_ASSERT(pdu.data_iovcnt == 5);
370 : 4 : CU_ASSERT(pdu.data_iov[0].iov_base == (void *)(0xDEADBEEF + 0x1000 + 244));
371 : 4 : CU_ASSERT(pdu.data_iov[0].iov_len == 13);
372 : 4 : CU_ASSERT(pdu.data_iov[1].iov_base == (void *)(0xDEADBEEF + 0x2000));
373 : 4 : CU_ASSERT(pdu.data_iov[1].iov_len == 4);
374 : 4 : CU_ASSERT(pdu.data_iov[2].iov_base == (void *)(0xDEADBEEF + 0x3000));
375 : 4 : CU_ASSERT(pdu.data_iov[2].iov_len == 3 + 123);
376 : 4 : CU_ASSERT(pdu.data_iov[3].iov_base == (void *)(0xDEADBEEF + 0x4000));
377 : 4 : CU_ASSERT(pdu.data_iov[3].iov_len == 395);
378 : 4 : CU_ASSERT(pdu.data_iov[4].iov_base == (void *)(0xDEADBEEF + 0x5000));
379 : 4 : CU_ASSERT(pdu.data_iov[4].iov_len == 478);
380 : :
381 : 4 : nvme_tcp_pdu_set_data_buf(&pdu, iovs, 7, 1500, 548);
382 : :
383 : 4 : CU_ASSERT(dif_ctx.data_offset == 1500);
384 : 4 : CU_ASSERT(pdu.data_len == 548);
385 : 4 : CU_ASSERT(pdu.data_iovcnt == 2);
386 : 4 : CU_ASSERT(pdu.data_iov[0].iov_base == (void *)(0xDEADBEEF + 0x5000 + 478));
387 : 4 : CU_ASSERT(pdu.data_iov[0].iov_len == 476);
388 : 4 : CU_ASSERT(pdu.data_iov[1].iov_base == (void *)(0xDEADBEEF + 0x6000));
389 : 4 : CU_ASSERT(pdu.data_iov[1].iov_len == 88);
390 : 4 : }
391 : :
392 : : static void
393 : 4 : test_nvme_tcp_build_iovs_with_md(void)
394 : : {
395 : 4 : struct nvme_tcp_pdu pdu = {};
396 : 4 : struct iovec iovs[11] = {};
397 : 4 : struct spdk_dif_ctx dif_ctx = {};
398 : 4 : uint32_t mapped_length = 0;
399 : : int rc;
400 : 4 : struct spdk_dif_ctx_init_ext_opts dif_opts;
401 : :
402 : 4 : dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
403 : 4 : dif_opts.dif_pi_format = SPDK_DIF_PI_FORMAT_16;
404 : 4 : rc = spdk_dif_ctx_init(&dif_ctx, 520, 8, true, false, SPDK_DIF_DISABLE, 0,
405 : : 0, 0, 0, 0, 0, &dif_opts);
406 : 4 : CU_ASSERT(rc == 0);
407 : :
408 : 4 : pdu.dif_ctx = &dif_ctx;
409 : :
410 : 4 : pdu.hdr.common.pdu_type = SPDK_NVME_TCP_PDU_TYPE_CAPSULE_CMD;
411 : 4 : pdu.hdr.common.hlen = sizeof(struct spdk_nvme_tcp_cmd);
412 : 4 : pdu.hdr.common.plen = pdu.hdr.common.hlen + SPDK_NVME_TCP_DIGEST_LEN + 512 * 8 +
413 : : SPDK_NVME_TCP_DIGEST_LEN;
414 : 4 : pdu.data_len = 512 * 8;
415 : 4 : pdu.padding_len = 0;
416 : :
417 : 4 : pdu.data_iov[0].iov_base = (void *)0xDEADBEEF;
418 : 4 : pdu.data_iov[0].iov_len = (512 + 8) * 8;
419 : 4 : pdu.data_iovcnt = 1;
420 : :
421 : 4 : rc = nvme_tcp_build_iovs(iovs, 11, &pdu, true, true, &mapped_length);
422 : 4 : CU_ASSERT(rc == 10);
423 : 4 : CU_ASSERT(iovs[0].iov_base == (void *)&pdu.hdr.raw);
424 : 4 : CU_ASSERT(iovs[0].iov_len == sizeof(struct spdk_nvme_tcp_cmd) + SPDK_NVME_TCP_DIGEST_LEN);
425 : 4 : CU_ASSERT(iovs[1].iov_base == (void *)0xDEADBEEF);
426 : 4 : CU_ASSERT(iovs[1].iov_len == 512);
427 : 4 : CU_ASSERT(iovs[2].iov_base == (void *)(0xDEADBEEF + 520));
428 : 4 : CU_ASSERT(iovs[2].iov_len == 512);
429 : 4 : CU_ASSERT(iovs[3].iov_base == (void *)(0xDEADBEEF + 520 * 2));
430 : 4 : CU_ASSERT(iovs[3].iov_len == 512);
431 : 4 : CU_ASSERT(iovs[4].iov_base == (void *)(0xDEADBEEF + 520 * 3));
432 : 4 : CU_ASSERT(iovs[4].iov_len == 512);
433 : 4 : CU_ASSERT(iovs[5].iov_base == (void *)(0xDEADBEEF + 520 * 4));
434 : 4 : CU_ASSERT(iovs[5].iov_len == 512);
435 : 4 : CU_ASSERT(iovs[6].iov_base == (void *)(0xDEADBEEF + 520 * 5));
436 : 4 : CU_ASSERT(iovs[6].iov_len == 512);
437 : 4 : CU_ASSERT(iovs[7].iov_base == (void *)(0xDEADBEEF + 520 * 6));
438 : 4 : CU_ASSERT(iovs[7].iov_len == 512);
439 : 4 : CU_ASSERT(iovs[8].iov_base == (void *)(0xDEADBEEF + 520 * 7));
440 : 4 : CU_ASSERT(iovs[8].iov_len == 512);
441 : 4 : CU_ASSERT(iovs[9].iov_base == (void *)pdu.data_digest);
442 : 4 : CU_ASSERT(iovs[9].iov_len == SPDK_NVME_TCP_DIGEST_LEN);
443 : 4 : CU_ASSERT(mapped_length == sizeof(struct spdk_nvme_tcp_cmd) + SPDK_NVME_TCP_DIGEST_LEN +
444 : : 512 * 8 + SPDK_NVME_TCP_DIGEST_LEN);
445 : 4 : }
446 : :
447 : : /* Just define, nothing to do */
448 : : static void
449 : 28 : ut_nvme_complete_request(void *arg, const struct spdk_nvme_cpl *cpl)
450 : : {
451 : 28 : return;
452 : : }
453 : :
454 : : static void
455 : 4 : test_nvme_tcp_req_complete_safe(void)
456 : : {
457 : : bool rc;
458 : 4 : struct nvme_tcp_req tcp_req = {0};
459 : 4 : struct nvme_request req = {{0}};
460 : 4 : struct nvme_tcp_qpair tqpair = {{0}};
461 : :
462 : 4 : tcp_req.req = &req;
463 : 4 : tcp_req.req->qpair = &tqpair.qpair;
464 : 4 : tcp_req.req->cb_fn = ut_nvme_complete_request;
465 : 4 : tcp_req.tqpair = &tqpair;
466 : 4 : tcp_req.state = NVME_TCP_REQ_ACTIVE;
467 : 4 : TAILQ_INIT(&tcp_req.tqpair->outstanding_reqs);
468 : 4 : tqpair.qpair.num_outstanding_reqs = 1;
469 : :
470 : : /* Test case 1: send operation and transfer completed. Expect: PASS */
471 : 4 : tcp_req.state = NVME_TCP_REQ_ACTIVE;
472 : 4 : tcp_req.ordering.bits.send_ack = 1;
473 : 4 : tcp_req.ordering.bits.data_recv = 1;
474 : 4 : TAILQ_INSERT_TAIL(&tcp_req.tqpair->outstanding_reqs, &tcp_req, link);
475 : :
476 : 4 : rc = nvme_tcp_req_complete_safe(&tcp_req);
477 : 4 : CU_ASSERT(rc == true);
478 : 4 : CU_ASSERT(tqpair.qpair.num_outstanding_reqs == 0);
479 : :
480 : : /* Test case 2: send operation not completed. Expect: FAIL */
481 : 4 : tcp_req.ordering.raw = 0;
482 : 4 : tcp_req.state = NVME_TCP_REQ_ACTIVE;
483 : 4 : TAILQ_INSERT_TAIL(&tcp_req.tqpair->outstanding_reqs, &tcp_req, link);
484 : 4 : tqpair.qpair.num_outstanding_reqs = 1;
485 : :
486 : 4 : rc = nvme_tcp_req_complete_safe(&tcp_req);
487 [ - + ]: 4 : SPDK_CU_ASSERT_FATAL(rc != true);
488 : 4 : CU_ASSERT(tqpair.qpair.num_outstanding_reqs == 1);
489 [ - + ]: 4 : TAILQ_REMOVE(&tcp_req.tqpair->outstanding_reqs, &tcp_req, link);
490 : :
491 : : /* Test case 3: in completion context. Expect: PASS */
492 : 4 : tqpair.qpair.in_completion_context = 1;
493 : 4 : tqpair.async_complete = 0;
494 : 4 : tcp_req.ordering.bits.send_ack = 1;
495 : 4 : tcp_req.ordering.bits.data_recv = 1;
496 : 4 : tcp_req.state = NVME_TCP_REQ_ACTIVE;
497 : 4 : TAILQ_INSERT_TAIL(&tcp_req.tqpair->outstanding_reqs, &tcp_req, link);
498 : 4 : tqpair.qpair.num_outstanding_reqs = 1;
499 : :
500 : 4 : rc = nvme_tcp_req_complete_safe(&tcp_req);
501 : 4 : CU_ASSERT(rc == true);
502 : 4 : CU_ASSERT(tcp_req.tqpair->async_complete == 0);
503 : 4 : CU_ASSERT(tqpair.qpair.num_outstanding_reqs == 0);
504 : :
505 : : /* Test case 4: in async complete. Expect: PASS */
506 : 4 : tqpair.qpair.in_completion_context = 0;
507 : 4 : tcp_req.ordering.bits.send_ack = 1;
508 : 4 : tcp_req.ordering.bits.data_recv = 1;
509 : 4 : tcp_req.state = NVME_TCP_REQ_ACTIVE;
510 : 4 : TAILQ_INSERT_TAIL(&tcp_req.tqpair->outstanding_reqs, &tcp_req, link);
511 : 4 : tqpair.qpair.num_outstanding_reqs = 1;
512 : :
513 : 4 : rc = nvme_tcp_req_complete_safe(&tcp_req);
514 : 4 : CU_ASSERT(rc == true);
515 : 4 : CU_ASSERT(tcp_req.tqpair->async_complete);
516 : 4 : CU_ASSERT(tqpair.qpair.num_outstanding_reqs == 0);
517 : 4 : }
518 : :
519 : : static void
520 : 4 : test_nvme_tcp_req_init(void)
521 : : {
522 : 4 : struct nvme_tcp_qpair tqpair = {};
523 : 4 : struct nvme_request req = {};
524 : 4 : struct nvme_tcp_req tcp_req = {0};
525 : 4 : struct spdk_nvme_ctrlr ctrlr = {{0}};
526 : 4 : struct nvme_tcp_ut_bdev_io bio = {};
527 : : int rc;
528 : :
529 : 4 : tqpair.qpair.ctrlr = &ctrlr;
530 : 4 : req.qpair = &tqpair.qpair;
531 : :
532 : 4 : tcp_req.cid = 1;
533 : 4 : req.payload = NVME_PAYLOAD_SGL(nvme_tcp_ut_reset_sgl, nvme_tcp_ut_next_sge, &bio, NULL);
534 : 4 : req.payload_offset = 0;
535 : 4 : req.payload_size = 4096;
536 : 4 : ctrlr.max_sges = NVME_TCP_MAX_SGL_DESCRIPTORS;
537 : 4 : ctrlr.ioccsz_bytes = 1024;
538 : 4 : bio.iovpos = 0;
539 : 4 : bio.iovs[0].iov_len = 8192;
540 : 4 : bio.iovs[0].iov_base = (void *)0xDEADBEEF;
541 : :
542 : : /* Test case1: payload type SGL. Expect: PASS */
543 : 4 : req.cmd.opc = SPDK_NVME_DATA_HOST_TO_CONTROLLER;
544 : 4 : req.payload.reset_sgl_fn = nvme_tcp_ut_reset_sgl;
545 : :
546 : 4 : rc = nvme_tcp_req_init(&tqpair, &req, &tcp_req);
547 : 4 : CU_ASSERT(rc == 0);
548 : 4 : CU_ASSERT(tcp_req.req == &req);
549 [ - + ]: 4 : CU_ASSERT(tcp_req.in_capsule_data == true);
550 : 4 : CU_ASSERT(tcp_req.iovcnt == 1);
551 : 4 : CU_ASSERT(tcp_req.iov[0].iov_len == req.payload_size);
552 : 4 : CU_ASSERT(tcp_req.iov[0].iov_base == bio.iovs[0].iov_base);
553 : 4 : CU_ASSERT(req.cmd.cid == tcp_req.cid);
554 : 4 : CU_ASSERT(req.cmd.psdt == SPDK_NVME_PSDT_SGL_MPTR_CONTIG);
555 : 4 : CU_ASSERT(req.cmd.dptr.sgl1.unkeyed.type == SPDK_NVME_SGL_TYPE_DATA_BLOCK);
556 : 4 : CU_ASSERT(req.cmd.dptr.sgl1.unkeyed.subtype == SPDK_NVME_SGL_SUBTYPE_OFFSET);
557 : 4 : CU_ASSERT(req.cmd.dptr.sgl1.unkeyed.length == req.payload_size);
558 : 4 : CU_ASSERT(req.cmd.dptr.sgl1.address == 0);
559 : :
560 : : /* Test case2: payload type CONTIG. Expect: PASS */
561 [ - + ]: 4 : memset(&req.cmd, 0, sizeof(req.cmd));
562 [ - + ]: 4 : memset(&tcp_req, 0, sizeof(tcp_req));
563 : 4 : tcp_req.cid = 1;
564 : 4 : req.payload = NVME_PAYLOAD_CONTIG(&bio, NULL);
565 : 4 : req.cmd.opc = SPDK_NVME_DATA_HOST_TO_CONTROLLER;
566 : :
567 : 4 : rc = nvme_tcp_req_init(&tqpair, &req, &tcp_req);
568 : 4 : CU_ASSERT(rc == 0);
569 : 4 : CU_ASSERT(tcp_req.req == &req);
570 [ - + ]: 4 : CU_ASSERT(tcp_req.in_capsule_data == true);
571 : 4 : CU_ASSERT(tcp_req.iov[0].iov_len == req.payload_size);
572 : 4 : CU_ASSERT(tcp_req.iov[0].iov_base == &bio);
573 : 4 : CU_ASSERT(tcp_req.iovcnt == 1);
574 : 4 : CU_ASSERT(req.cmd.cid == tcp_req.cid);
575 : 4 : CU_ASSERT(req.cmd.psdt == SPDK_NVME_PSDT_SGL_MPTR_CONTIG);
576 : 4 : CU_ASSERT(req.cmd.dptr.sgl1.unkeyed.type == SPDK_NVME_SGL_TYPE_DATA_BLOCK);
577 : 4 : CU_ASSERT(req.cmd.dptr.sgl1.unkeyed.subtype == SPDK_NVME_SGL_SUBTYPE_OFFSET);
578 : 4 : CU_ASSERT(req.cmd.dptr.sgl1.unkeyed.length == req.payload_size);
579 : 4 : CU_ASSERT(req.cmd.dptr.sgl1.address == 0);
580 : :
581 : 4 : }
582 : :
583 : : static void
584 : 4 : test_nvme_tcp_req_get(void)
585 : : {
586 : 4 : struct nvme_tcp_req tcp_req = {0};
587 : 4 : struct nvme_tcp_qpair tqpair = {};
588 : 4 : struct nvme_tcp_pdu send_pdu = {};
589 : :
590 : 4 : tcp_req.pdu = &send_pdu;
591 : 4 : tcp_req.state = NVME_TCP_REQ_FREE;
592 : :
593 : 4 : TAILQ_INIT(&tqpair.free_reqs);
594 : 4 : TAILQ_INIT(&tqpair.outstanding_reqs);
595 [ - + ]: 4 : TAILQ_INSERT_HEAD(&tqpair.free_reqs, &tcp_req, link);
596 : :
597 : 4 : CU_ASSERT(nvme_tcp_req_get(&tqpair) == &tcp_req);
598 : 4 : CU_ASSERT(tcp_req.state == NVME_TCP_REQ_ACTIVE);
599 : 4 : CU_ASSERT(tcp_req.datao == 0);
600 : 4 : CU_ASSERT(tcp_req.req == NULL);
601 [ - + ]: 4 : CU_ASSERT(tcp_req.in_capsule_data == false);
602 : 4 : CU_ASSERT(tcp_req.r2tl_remain == 0);
603 : 4 : CU_ASSERT(tcp_req.iovcnt == 0);
604 : 4 : CU_ASSERT(tcp_req.ordering.raw == 0);
605 : : /* outstanding_reqs should still be empty - caller is responsible
606 : : * for putting it on the TAILQ after any other initialization is
607 : : * completed.
608 : : */
609 : 4 : CU_ASSERT(TAILQ_EMPTY(&tqpair.outstanding_reqs));
610 : 4 : CU_ASSERT(TAILQ_EMPTY(&tqpair.free_reqs));
611 : :
612 : : /* No tcp request available, expect fail */
613 [ - + ]: 4 : SPDK_CU_ASSERT_FATAL(nvme_tcp_req_get(&tqpair) == NULL);
614 : 4 : }
615 : :
616 : : static void
617 : 4 : test_nvme_tcp_qpair_capsule_cmd_send(void)
618 : : {
619 : 4 : struct nvme_tcp_qpair tqpair = {};
620 : 4 : struct spdk_nvme_tcp_stat stats = {};
621 : 4 : struct nvme_tcp_req tcp_req = {};
622 : 4 : struct nvme_tcp_pdu pdu = {};
623 : 4 : struct nvme_request req = {};
624 : 4 : char iov_base0[4096];
625 : 4 : char iov_base1[4096];
626 : : uint32_t plen;
627 : : uint8_t pdo;
628 : :
629 [ - + ]: 4 : memset(iov_base0, 0xFF, 4096);
630 [ - + ]: 4 : memset(iov_base1, 0xFF, 4096);
631 : 4 : tcp_req.req = &req;
632 : 4 : tcp_req.pdu = &pdu;
633 : 4 : TAILQ_INIT(&tqpair.send_queue);
634 : 4 : tqpair.stats = &stats;
635 : :
636 : 4 : tcp_req.iov[0].iov_base = (void *)iov_base0;
637 : 4 : tcp_req.iov[0].iov_len = 4096;
638 : 4 : tcp_req.iov[1].iov_base = (void *)iov_base1;
639 : 4 : tcp_req.iov[1].iov_len = 4096;
640 : 4 : tcp_req.iovcnt = 2;
641 : 4 : tcp_req.req->payload_size = 8192;
642 : 4 : tcp_req.in_capsule_data = true;
643 : 4 : tqpair.cpda = NVME_TCP_HPDA_DEFAULT;
644 : :
645 : : /* Test case 1: host hdgst and ddgst enable. Expect: PASS */
646 : 4 : tqpair.flags.host_hdgst_enable = 1;
647 : 4 : tqpair.flags.host_ddgst_enable = 1;
648 : 4 : pdo = plen = sizeof(struct spdk_nvme_tcp_cmd) +
649 : : SPDK_NVME_TCP_DIGEST_LEN;
650 : 4 : plen += tcp_req.req->payload_size;
651 : 4 : plen += SPDK_NVME_TCP_DIGEST_LEN;
652 : :
653 : 4 : nvme_tcp_qpair_capsule_cmd_send(&tqpair, &tcp_req);
654 [ - + ]: 4 : TAILQ_REMOVE(&tqpair.send_queue, &pdu, tailq);
655 : 4 : CU_ASSERT(pdu.hdr.capsule_cmd.common.flags
656 : : & SPDK_NVME_TCP_CH_FLAGS_HDGSTF);
657 : 4 : CU_ASSERT(pdu.hdr.capsule_cmd.common.flags
658 : : & SPDK_NVME_TCP_CH_FLAGS_DDGSTF);
659 : 4 : CU_ASSERT(pdu.hdr.capsule_cmd.common.pdu_type ==
660 : : SPDK_NVME_TCP_PDU_TYPE_CAPSULE_CMD);
661 : 4 : CU_ASSERT(pdu.hdr.capsule_cmd.common.pdo == pdo);
662 : 4 : CU_ASSERT(pdu.hdr.capsule_cmd.common.plen == plen);
663 : 4 : CU_ASSERT(pdu.data_iov[0].iov_base == tcp_req.iov[0].iov_base);
664 : 4 : CU_ASSERT(pdu.data_iov[0].iov_len == tcp_req.iov[0].iov_len);
665 : 4 : CU_ASSERT(pdu.data_iov[1].iov_base == tcp_req.iov[1].iov_base);
666 : 4 : CU_ASSERT(pdu.data_iov[1].iov_len == tcp_req.iov[0].iov_len);
667 : :
668 : : /* Test case 2: host hdgst and ddgst disable. Expect: PASS */
669 [ - + ]: 4 : memset(&pdu, 0, sizeof(pdu));
670 : 4 : tqpair.flags.host_hdgst_enable = 0;
671 : 4 : tqpair.flags.host_ddgst_enable = 0;
672 : :
673 : 4 : pdo = plen = sizeof(struct spdk_nvme_tcp_cmd);
674 : 4 : plen += tcp_req.req->payload_size;
675 : :
676 : 4 : nvme_tcp_qpair_capsule_cmd_send(&tqpair, &tcp_req);
677 [ - + ]: 4 : TAILQ_REMOVE(&tqpair.send_queue, &pdu, tailq);
678 : 4 : CU_ASSERT(pdu.hdr.capsule_cmd.common.flags == 0)
679 : 4 : CU_ASSERT(pdu.hdr.capsule_cmd.common.pdu_type ==
680 : : SPDK_NVME_TCP_PDU_TYPE_CAPSULE_CMD);
681 : 4 : CU_ASSERT(pdu.hdr.capsule_cmd.common.pdo == pdo);
682 : 4 : CU_ASSERT(pdu.hdr.capsule_cmd.common.plen == plen);
683 : 4 : CU_ASSERT(pdu.data_iov[0].iov_base == tcp_req.iov[0].iov_base);
684 : 4 : CU_ASSERT(pdu.data_iov[0].iov_len == tcp_req.iov[0].iov_len);
685 : 4 : CU_ASSERT(pdu.data_iov[1].iov_base == tcp_req.iov[1].iov_base);
686 : 4 : CU_ASSERT(pdu.data_iov[1].iov_len == tcp_req.iov[0].iov_len);
687 : :
688 : : /* Test case 3: padding available. Expect: PASS */
689 [ - + ]: 4 : memset(&pdu, 0, sizeof(pdu));
690 : 4 : tqpair.flags.host_hdgst_enable = 1;
691 : 4 : tqpair.flags.host_ddgst_enable = 1;
692 : 4 : tqpair.cpda = SPDK_NVME_TCP_CPDA_MAX;
693 : :
694 : 4 : pdo = plen = (SPDK_NVME_TCP_CPDA_MAX + 1) << 2;
695 : 4 : plen += tcp_req.req->payload_size;
696 : 4 : plen += SPDK_NVME_TCP_DIGEST_LEN;
697 : :
698 : 4 : nvme_tcp_qpair_capsule_cmd_send(&tqpair, &tcp_req);
699 [ - + ]: 4 : TAILQ_REMOVE(&tqpair.send_queue, &pdu, tailq);
700 : 4 : CU_ASSERT(pdu.hdr.capsule_cmd.common.flags
701 : : & SPDK_NVME_TCP_CH_FLAGS_HDGSTF);
702 : 4 : CU_ASSERT(pdu.hdr.capsule_cmd.common.flags
703 : : & SPDK_NVME_TCP_CH_FLAGS_DDGSTF);
704 : 4 : CU_ASSERT(pdu.hdr.capsule_cmd.common.pdu_type ==
705 : : SPDK_NVME_TCP_PDU_TYPE_CAPSULE_CMD);
706 : 4 : CU_ASSERT(pdu.hdr.capsule_cmd.common.pdo == pdo);
707 : 4 : CU_ASSERT(pdu.hdr.capsule_cmd.common.plen == plen);
708 : 4 : CU_ASSERT(pdu.data_iov[0].iov_base == tcp_req.iov[0].iov_base);
709 : 4 : CU_ASSERT(pdu.data_iov[0].iov_len == tcp_req.iov[0].iov_len);
710 : 4 : CU_ASSERT(pdu.data_iov[1].iov_base == tcp_req.iov[1].iov_base);
711 : 4 : CU_ASSERT(pdu.data_iov[1].iov_len == tcp_req.iov[0].iov_len);
712 : 4 : }
713 : :
714 : : /* Just define, nothing to do */
715 : : static void
716 : 0 : ut_nvme_tcp_qpair_xfer_complete_cb(void *cb_arg)
717 : : {
718 : 0 : return;
719 : : }
720 : :
721 : : static void
722 : 4 : test_nvme_tcp_qpair_write_pdu(void)
723 : : {
724 : 4 : struct nvme_tcp_qpair tqpair = {};
725 : 4 : struct spdk_nvme_tcp_stat stats = {};
726 : 4 : struct nvme_request req = {};
727 : 4 : struct nvme_tcp_req treq = { .req = &req };
728 : 4 : struct nvme_tcp_pdu pdu = { .req = &treq };
729 : 4 : void *cb_arg = (void *)0xDEADBEEF;
730 : 4 : char iov_base0[4096];
731 : 4 : char iov_base1[4096];
732 : :
733 [ - + ]: 4 : memset(iov_base0, 0xFF, 4096);
734 [ - + ]: 4 : memset(iov_base1, 0xFF, 4096);
735 : 4 : pdu.data_len = 4096 * 2;
736 : 4 : pdu.padding_len = 0;
737 : 4 : pdu.data_iov[0].iov_base = (void *)iov_base0;
738 : 4 : pdu.data_iov[0].iov_len = 4096;
739 : 4 : pdu.data_iov[1].iov_base = (void *)iov_base1;
740 : 4 : pdu.data_iov[1].iov_len = 4096;
741 : 4 : pdu.data_iovcnt = 2;
742 : 4 : TAILQ_INIT(&tqpair.send_queue);
743 : :
744 : : /* Test case1: host hdgst and ddgst enable Expect: PASS */
745 [ - + ]: 4 : memset(pdu.hdr.raw, 0, SPDK_NVME_TCP_TERM_REQ_PDU_MAX_SIZE);
746 [ - + ]: 4 : memset(pdu.data_digest, 0, SPDK_NVME_TCP_DIGEST_LEN);
747 : :
748 : 4 : pdu.hdr.common.pdu_type = SPDK_NVME_TCP_PDU_TYPE_CAPSULE_CMD;
749 : 4 : pdu.hdr.common.hlen = sizeof(struct spdk_nvme_tcp_cmd);
750 : 4 : pdu.hdr.common.plen = pdu.hdr.common.hlen +
751 : : SPDK_NVME_TCP_DIGEST_LEN * 2 ;
752 : 4 : pdu.hdr.common.plen += pdu.data_len;
753 : 4 : tqpair.flags.host_hdgst_enable = 1;
754 : 4 : tqpair.flags.host_ddgst_enable = 1;
755 : 4 : tqpair.stats = &stats;
756 : :
757 : 4 : nvme_tcp_qpair_write_pdu(&tqpair,
758 : : &pdu,
759 : : ut_nvme_tcp_qpair_xfer_complete_cb,
760 : : cb_arg);
761 [ - + ]: 4 : TAILQ_REMOVE(&tqpair.send_queue, &pdu, tailq);
762 : : /* Check the crc data of header digest filled into raw */
763 : 4 : CU_ASSERT(pdu.hdr.raw[pdu.hdr.common.hlen]);
764 : 4 : CU_ASSERT(pdu.data_digest[0]);
765 : 4 : CU_ASSERT(pdu.sock_req.iovcnt == 4);
766 : 4 : CU_ASSERT(pdu.iov[0].iov_base == &pdu.hdr.raw);
767 : 4 : CU_ASSERT(pdu.iov[0].iov_len == (sizeof(struct spdk_nvme_tcp_cmd) +
768 : : SPDK_NVME_TCP_DIGEST_LEN));
769 : 4 : CU_ASSERT(pdu.iov[1].iov_base == pdu.data_iov[0].iov_base);
770 : 4 : CU_ASSERT(pdu.iov[1].iov_len == pdu.data_iov[0].iov_len);
771 : 4 : CU_ASSERT(pdu.iov[2].iov_base == pdu.data_iov[1].iov_base);
772 : 4 : CU_ASSERT(pdu.iov[2].iov_len == pdu.data_iov[1].iov_len);
773 : 4 : CU_ASSERT(pdu.iov[3].iov_base == &pdu.data_digest);
774 : 4 : CU_ASSERT(pdu.iov[3].iov_len == SPDK_NVME_TCP_DIGEST_LEN);
775 : 4 : CU_ASSERT(pdu.cb_fn == ut_nvme_tcp_qpair_xfer_complete_cb);
776 : 4 : CU_ASSERT(pdu.cb_arg == cb_arg);
777 : 4 : CU_ASSERT(pdu.qpair == &tqpair);
778 : 4 : CU_ASSERT(pdu.sock_req.cb_arg == (void *)&pdu);
779 : :
780 : : /* Test case2: host hdgst and ddgst disable Expect: PASS */
781 [ - + ]: 4 : memset(pdu.hdr.raw, 0, SPDK_NVME_TCP_TERM_REQ_PDU_MAX_SIZE);
782 [ - + ]: 4 : memset(pdu.data_digest, 0, SPDK_NVME_TCP_DIGEST_LEN);
783 : :
784 : 4 : pdu.hdr.common.hlen = sizeof(struct spdk_nvme_tcp_cmd);
785 : 4 : pdu.hdr.common.plen = pdu.hdr.common.hlen + pdu.data_len;
786 : 4 : tqpair.flags.host_hdgst_enable = 0;
787 : 4 : tqpair.flags.host_ddgst_enable = 0;
788 : :
789 : 4 : nvme_tcp_qpair_write_pdu(&tqpair,
790 : : &pdu,
791 : : ut_nvme_tcp_qpair_xfer_complete_cb,
792 : : cb_arg);
793 [ - + ]: 4 : TAILQ_REMOVE(&tqpair.send_queue, &pdu, tailq);
794 : 4 : CU_ASSERT(pdu.hdr.raw[pdu.hdr.common.hlen] == 0);
795 : 4 : CU_ASSERT(pdu.data_digest[0] == 0);
796 : 4 : CU_ASSERT(pdu.sock_req.iovcnt == 3);
797 : 4 : CU_ASSERT(pdu.iov[0].iov_base == &pdu.hdr.raw);
798 : 4 : CU_ASSERT(pdu.iov[0].iov_len == sizeof(struct spdk_nvme_tcp_cmd));
799 : 4 : CU_ASSERT(pdu.iov[1].iov_base == pdu.data_iov[0].iov_base);
800 : 4 : CU_ASSERT(pdu.iov[1].iov_len == pdu.data_iov[0].iov_len);
801 : 4 : CU_ASSERT(pdu.iov[2].iov_base == pdu.data_iov[1].iov_base);
802 : 4 : CU_ASSERT(pdu.iov[2].iov_len == pdu.data_iov[1].iov_len);
803 : 4 : CU_ASSERT(pdu.cb_fn == ut_nvme_tcp_qpair_xfer_complete_cb);
804 : 4 : CU_ASSERT(pdu.cb_arg == cb_arg);
805 : 4 : CU_ASSERT(pdu.qpair == &tqpair);
806 : 4 : CU_ASSERT(pdu.sock_req.cb_arg == (void *)&pdu);
807 : 4 : }
808 : :
809 : : static void
810 : 4 : test_nvme_tcp_qpair_set_recv_state(void)
811 : : {
812 : 4 : struct nvme_tcp_qpair tqpair = {};
813 : :
814 : : /* case1: The recv state of tqpair is same with the state to be set */
815 : 4 : tqpair.recv_state = NVME_TCP_PDU_RECV_STATE_ERROR;
816 : 4 : nvme_tcp_qpair_set_recv_state(&tqpair, NVME_TCP_PDU_RECV_STATE_ERROR);
817 : 4 : CU_ASSERT(tqpair.recv_state == NVME_TCP_PDU_RECV_STATE_ERROR);
818 : :
819 : : /* Different state will be set accordingly */
820 : 4 : tqpair.recv_state = NVME_TCP_PDU_RECV_STATE_AWAIT_PDU_READY;
821 : 4 : nvme_tcp_qpair_set_recv_state(&tqpair, 0xff);
822 : 4 : CU_ASSERT(tqpair.recv_state == 0xff);
823 : 4 : }
824 : :
825 : : static void
826 : 4 : test_nvme_tcp_alloc_reqs(void)
827 : : {
828 : 4 : struct nvme_tcp_qpair tqpair = {};
829 : 4 : int rc = 0;
830 : :
831 : : /* case1: single entry. Expect: PASS */
832 : 4 : tqpair.num_entries = 1;
833 : 4 : rc = nvme_tcp_alloc_reqs(&tqpair);
834 : 4 : CU_ASSERT(rc == 0);
835 : 4 : CU_ASSERT(tqpair.tcp_reqs[0].cid == 0);
836 : 4 : CU_ASSERT(tqpair.tcp_reqs[0].tqpair == &tqpair);
837 : 4 : CU_ASSERT(tqpair.tcp_reqs[0].pdu == &tqpair.send_pdus[0]);
838 : 4 : CU_ASSERT(tqpair.send_pdu == &tqpair.send_pdus[tqpair.num_entries]);
839 : 4 : free(tqpair.tcp_reqs);
840 : 4 : spdk_free(tqpair.send_pdus);
841 : :
842 : : /* case2: multiple entries. Expect: PASS */
843 : 4 : tqpair.num_entries = 5;
844 : 4 : rc = nvme_tcp_alloc_reqs(&tqpair);
845 : 4 : CU_ASSERT(rc == 0);
846 [ + + ]: 24 : for (int i = 0; i < tqpair.num_entries; i++) {
847 : 20 : CU_ASSERT(tqpair.tcp_reqs[i].cid == i);
848 : 20 : CU_ASSERT(tqpair.tcp_reqs[i].tqpair == &tqpair);
849 : 20 : CU_ASSERT(tqpair.tcp_reqs[i].pdu == &tqpair.send_pdus[i]);
850 : : }
851 : 4 : CU_ASSERT(tqpair.send_pdu == &tqpair.send_pdus[tqpair.num_entries]);
852 : :
853 : : /* case3: Test nvme_tcp_free_reqs test. Expect: PASS */
854 : 4 : nvme_tcp_free_reqs(&tqpair);
855 : 4 : CU_ASSERT(tqpair.tcp_reqs == NULL);
856 : 4 : CU_ASSERT(tqpair.send_pdus == NULL);
857 : 4 : }
858 : :
859 : : static void
860 : 4 : test_nvme_tcp_qpair_send_h2c_term_req(void)
861 : : {
862 : 4 : struct nvme_tcp_qpair tqpair = {};
863 : 4 : struct spdk_nvme_tcp_stat stats = {};
864 : 4 : struct nvme_tcp_pdu pdu = {}, recv_pdu = {}, send_pdu = {};
865 : 4 : enum spdk_nvme_tcp_term_req_fes fes = SPDK_NVME_TCP_TERM_REQ_FES_INVALID_HEADER_FIELD;
866 : 4 : uint32_t error_offset = 1;
867 : :
868 : 4 : tqpair.send_pdu = &send_pdu;
869 : 4 : tqpair.recv_pdu = &recv_pdu;
870 : 4 : tqpair.stats = &stats;
871 : 4 : TAILQ_INIT(&tqpair.send_queue);
872 : : /* case1: hlen < SPDK_NVME_TCP_TERM_REQ_ERROR_DATA_MAX_SIZE, Expect: copy_len == hlen */
873 : 4 : pdu.hdr.common.hlen = 64;
874 : 4 : nvme_tcp_qpair_send_h2c_term_req(&tqpair, &pdu, fes, error_offset);
875 : 4 : CU_ASSERT(tqpair.recv_state == NVME_TCP_PDU_RECV_STATE_QUIESCING);
876 : 4 : CU_ASSERT(tqpair.send_pdu->hdr.term_req.common.hlen == sizeof(struct spdk_nvme_tcp_term_req_hdr));
877 : 4 : CU_ASSERT(tqpair.send_pdu->hdr.term_req.common.plen == tqpair.send_pdu->hdr.term_req.common.hlen +
878 : : pdu.hdr.common.hlen);
879 : 4 : CU_ASSERT(tqpair.send_pdu->hdr.term_req.common.pdu_type == SPDK_NVME_TCP_PDU_TYPE_H2C_TERM_REQ);
880 : :
881 : : /* case2: hlen > SPDK_NVME_TCP_TERM_REQ_ERROR_DATA_MAX_SIZE, Expect: copy_len == SPDK_NVME_TCP_TERM_REQ_ERROR_DATA_MAX_SIZE */
882 : 4 : pdu.hdr.common.hlen = 255;
883 : 4 : nvme_tcp_qpair_send_h2c_term_req(&tqpair, &pdu, fes, error_offset);
884 : 4 : CU_ASSERT(tqpair.recv_state == NVME_TCP_PDU_RECV_STATE_QUIESCING);
885 : 4 : CU_ASSERT(tqpair.send_pdu->hdr.term_req.common.hlen == sizeof(struct spdk_nvme_tcp_term_req_hdr));
886 : 4 : CU_ASSERT(tqpair.send_pdu->hdr.term_req.common.plen == (unsigned)
887 : : tqpair.send_pdu->hdr.term_req.common.hlen + SPDK_NVME_TCP_TERM_REQ_ERROR_DATA_MAX_SIZE);
888 : 4 : CU_ASSERT(tqpair.send_pdu->hdr.term_req.common.pdu_type == SPDK_NVME_TCP_PDU_TYPE_H2C_TERM_REQ);
889 : 4 : }
890 : :
891 : : static void
892 : 4 : test_nvme_tcp_pdu_ch_handle(void)
893 : : {
894 : 4 : struct nvme_tcp_qpair tqpair = {};
895 : 4 : struct spdk_nvme_tcp_stat stats = {};
896 : 4 : struct nvme_tcp_pdu send_pdu = {}, recv_pdu = {};
897 : :
898 : 4 : tqpair.send_pdu = &send_pdu;
899 : 4 : tqpair.recv_pdu = &recv_pdu;
900 : 4 : tqpair.stats = &stats;
901 : 4 : TAILQ_INIT(&tqpair.send_queue);
902 : : /* case 1: Already received IC_RESP PDU. Expect: fail */
903 : 4 : tqpair.recv_pdu->hdr.common.pdu_type = SPDK_NVME_TCP_PDU_TYPE_IC_RESP;
904 : 4 : tqpair.state = NVME_TCP_QPAIR_STATE_INITIALIZING;
905 : 4 : nvme_tcp_pdu_ch_handle(&tqpair);
906 : 4 : CU_ASSERT(tqpair.recv_state == NVME_TCP_PDU_RECV_STATE_QUIESCING);
907 : 4 : CU_ASSERT(tqpair.send_pdu->hdr.term_req.common.pdu_type == SPDK_NVME_TCP_PDU_TYPE_H2C_TERM_REQ);
908 : 4 : CU_ASSERT(tqpair.send_pdu->hdr.term_req.common.hlen == sizeof(struct spdk_nvme_tcp_term_req_hdr));
909 : 4 : CU_ASSERT(tqpair.send_pdu->hdr.term_req.common.plen == tqpair.send_pdu->hdr.term_req.common.hlen);
910 : :
911 : : /* case 2: Expected PDU header length and received are different. Expect: fail */
912 : 4 : tqpair.recv_pdu->hdr.common.pdu_type = SPDK_NVME_TCP_PDU_TYPE_IC_RESP;
913 : 4 : tqpair.state = NVME_TCP_QPAIR_STATE_INVALID;
914 : 4 : tqpair.recv_pdu->hdr.common.plen = sizeof(struct spdk_nvme_tcp_ic_resp);
915 : 4 : tqpair.recv_pdu->hdr.common.hlen = 0;
916 : 4 : nvme_tcp_pdu_ch_handle(&tqpair);
917 : 4 : CU_ASSERT(tqpair.recv_state == NVME_TCP_PDU_RECV_STATE_QUIESCING);
918 : 4 : CU_ASSERT(tqpair.send_pdu->hdr.term_req.common.pdu_type == SPDK_NVME_TCP_PDU_TYPE_H2C_TERM_REQ);
919 : 4 : CU_ASSERT(tqpair.send_pdu->hdr.term_req.common.hlen == sizeof(struct spdk_nvme_tcp_term_req_hdr));
920 : 4 : CU_ASSERT(tqpair.send_pdu->hdr.term_req.common.plen == tqpair.send_pdu->hdr.term_req.common.hlen);
921 : 4 : CU_ASSERT(tqpair.send_pdu->hdr.term_req.fei[0] == 2);
922 : :
923 : : /* case 3: The TCP/IP tqpair connection is not negotiated. Expect: fail */
924 : 4 : tqpair.recv_pdu->hdr.common.pdu_type = SPDK_NVME_TCP_PDU_TYPE_CAPSULE_RESP;
925 : 4 : tqpair.state = NVME_TCP_QPAIR_STATE_INVALID;
926 : 4 : tqpair.recv_pdu->hdr.common.plen = sizeof(struct spdk_nvme_tcp_ic_resp);
927 : 4 : tqpair.recv_pdu->hdr.common.hlen = 0;
928 : 4 : nvme_tcp_pdu_ch_handle(&tqpair);
929 : 4 : CU_ASSERT(tqpair.recv_state == NVME_TCP_PDU_RECV_STATE_QUIESCING);
930 : 4 : CU_ASSERT(tqpair.send_pdu->hdr.term_req.common.pdu_type == SPDK_NVME_TCP_PDU_TYPE_H2C_TERM_REQ);
931 : 4 : CU_ASSERT(tqpair.send_pdu->hdr.term_req.common.hlen == sizeof(struct spdk_nvme_tcp_term_req_hdr));
932 : 4 : CU_ASSERT(tqpair.send_pdu->hdr.term_req.common.plen == tqpair.send_pdu->hdr.term_req.common.hlen);
933 : :
934 : : /* case 4: Unexpected PDU type. Expect: fail */
935 : 4 : tqpair.recv_pdu->hdr.common.pdu_type = SPDK_NVME_TCP_PDU_TYPE_IC_REQ;
936 : 4 : tqpair.state = NVME_TCP_QPAIR_STATE_RUNNING;
937 : 4 : tqpair.recv_pdu->hdr.common.plen = 0;
938 : 4 : tqpair.recv_pdu->hdr.common.hlen = sizeof(struct spdk_nvme_tcp_ic_resp);
939 : 4 : nvme_tcp_pdu_ch_handle(&tqpair);
940 : 4 : CU_ASSERT(tqpair.recv_state == NVME_TCP_PDU_RECV_STATE_QUIESCING);
941 : 4 : CU_ASSERT(tqpair.send_pdu->hdr.term_req.common.pdu_type == SPDK_NVME_TCP_PDU_TYPE_H2C_TERM_REQ);
942 : 4 : CU_ASSERT(tqpair.send_pdu->hdr.term_req.common.hlen == sizeof(struct spdk_nvme_tcp_term_req_hdr));
943 : 4 : CU_ASSERT(tqpair.send_pdu->hdr.term_req.common.plen == tqpair.send_pdu->hdr.term_req.common.hlen +
944 : : (unsigned)SPDK_NVME_TCP_TERM_REQ_ERROR_DATA_MAX_SIZE);
945 : :
946 : : /* case 5: plen error. Expect: fail */
947 : 4 : tqpair.recv_pdu->hdr.common.pdu_type = SPDK_NVME_TCP_PDU_TYPE_IC_RESP;
948 : 4 : tqpair.state = NVME_TCP_QPAIR_STATE_INVALID;
949 : 4 : tqpair.recv_pdu->hdr.common.plen = 0;
950 : 4 : tqpair.recv_pdu->hdr.common.hlen = sizeof(struct spdk_nvme_tcp_ic_resp);
951 : 4 : nvme_tcp_pdu_ch_handle(&tqpair);
952 : 4 : CU_ASSERT(tqpair.recv_state == NVME_TCP_PDU_RECV_STATE_QUIESCING);
953 : 4 : CU_ASSERT(tqpair.send_pdu->hdr.term_req.common.pdu_type == SPDK_NVME_TCP_PDU_TYPE_H2C_TERM_REQ);
954 : 4 : CU_ASSERT(tqpair.send_pdu->hdr.term_req.common.hlen == sizeof(struct spdk_nvme_tcp_term_req_hdr));
955 : 4 : CU_ASSERT(tqpair.send_pdu->hdr.term_req.common.plen == tqpair.send_pdu->hdr.term_req.common.hlen +
956 : : (unsigned)SPDK_NVME_TCP_TERM_REQ_ERROR_DATA_MAX_SIZE);
957 : 4 : CU_ASSERT(tqpair.send_pdu->hdr.term_req.fei[0] == 4);
958 : :
959 : 4 : tqpair.recv_pdu->hdr.common.pdu_type = SPDK_NVME_TCP_PDU_TYPE_CAPSULE_RESP;
960 : 4 : tqpair.state = NVME_TCP_QPAIR_STATE_RUNNING;
961 : 4 : tqpair.recv_pdu->hdr.common.flags = SPDK_NVME_TCP_CH_FLAGS_HDGSTF;
962 : 4 : tqpair.recv_pdu->hdr.common.plen = 0;
963 : 4 : tqpair.recv_pdu->hdr.common.hlen = sizeof(struct spdk_nvme_tcp_rsp);
964 : 4 : nvme_tcp_pdu_ch_handle(&tqpair);
965 : 4 : CU_ASSERT(tqpair.recv_state == NVME_TCP_PDU_RECV_STATE_QUIESCING);
966 : 4 : CU_ASSERT(tqpair.send_pdu->hdr.term_req.common.pdu_type == SPDK_NVME_TCP_PDU_TYPE_H2C_TERM_REQ);
967 : 4 : CU_ASSERT(tqpair.send_pdu->hdr.term_req.common.hlen == sizeof(struct spdk_nvme_tcp_term_req_hdr));
968 : 4 : CU_ASSERT(tqpair.send_pdu->hdr.term_req.common.plen == tqpair.send_pdu->hdr.term_req.common.hlen +
969 : : (unsigned)sizeof(struct spdk_nvme_tcp_term_req_hdr));
970 : 4 : CU_ASSERT(tqpair.send_pdu->hdr.term_req.fei[0] == 4);
971 : :
972 : 4 : tqpair.recv_pdu->hdr.common.pdu_type = SPDK_NVME_TCP_PDU_TYPE_C2H_DATA;
973 : 4 : tqpair.state = NVME_TCP_QPAIR_STATE_RUNNING;
974 : 4 : tqpair.recv_pdu->hdr.common.plen = 0;
975 : 4 : tqpair.recv_pdu->hdr.common.pdo = 64;
976 : 4 : tqpair.recv_pdu->hdr.common.hlen = sizeof(struct spdk_nvme_tcp_c2h_data_hdr);
977 : 4 : nvme_tcp_pdu_ch_handle(&tqpair);
978 : 4 : CU_ASSERT(tqpair.recv_state == NVME_TCP_PDU_RECV_STATE_QUIESCING);
979 : 4 : CU_ASSERT(tqpair.send_pdu->hdr.term_req.common.pdu_type == SPDK_NVME_TCP_PDU_TYPE_H2C_TERM_REQ);
980 : 4 : CU_ASSERT(tqpair.send_pdu->hdr.term_req.common.hlen == sizeof(struct spdk_nvme_tcp_term_req_hdr));
981 : 4 : CU_ASSERT(tqpair.send_pdu->hdr.term_req.common.plen == tqpair.send_pdu->hdr.term_req.common.hlen +
982 : : (unsigned)sizeof(struct spdk_nvme_tcp_term_req_hdr));
983 : 4 : CU_ASSERT(tqpair.send_pdu->hdr.term_req.fei[0] == 4);
984 : :
985 : 4 : tqpair.recv_pdu->hdr.common.pdu_type = SPDK_NVME_TCP_PDU_TYPE_C2H_TERM_REQ;
986 : 4 : tqpair.state = NVME_TCP_QPAIR_STATE_RUNNING;
987 : 4 : tqpair.recv_pdu->hdr.common.plen = 0;
988 : 4 : tqpair.recv_pdu->hdr.common.hlen = sizeof(struct spdk_nvme_tcp_term_req_hdr);
989 : 4 : nvme_tcp_pdu_ch_handle(&tqpair);
990 : 4 : CU_ASSERT(tqpair.recv_state == NVME_TCP_PDU_RECV_STATE_QUIESCING);
991 : 4 : CU_ASSERT(tqpair.send_pdu->hdr.term_req.common.pdu_type == SPDK_NVME_TCP_PDU_TYPE_H2C_TERM_REQ);
992 : 4 : CU_ASSERT(tqpair.send_pdu->hdr.term_req.common.hlen == sizeof(struct spdk_nvme_tcp_term_req_hdr));
993 : 4 : CU_ASSERT(tqpair.send_pdu->hdr.term_req.common.plen == tqpair.send_pdu->hdr.term_req.common.hlen +
994 : : (unsigned)sizeof(struct spdk_nvme_tcp_term_req_hdr));
995 : 4 : CU_ASSERT(tqpair.send_pdu->hdr.term_req.fei[0] == 4);
996 : :
997 : 4 : tqpair.recv_pdu->hdr.common.pdu_type = SPDK_NVME_TCP_PDU_TYPE_R2T;
998 : 4 : tqpair.state = NVME_TCP_QPAIR_STATE_RUNNING;
999 : 4 : tqpair.recv_pdu->hdr.common.flags = SPDK_NVME_TCP_CH_FLAGS_HDGSTF;
1000 : 4 : tqpair.recv_pdu->hdr.common.plen = 0;
1001 : 4 : tqpair.recv_pdu->hdr.common.hlen = sizeof(struct spdk_nvme_tcp_r2t_hdr);
1002 : 4 : nvme_tcp_pdu_ch_handle(&tqpair);
1003 : 4 : CU_ASSERT(tqpair.recv_state == NVME_TCP_PDU_RECV_STATE_QUIESCING);
1004 : 4 : CU_ASSERT(tqpair.send_pdu->hdr.term_req.common.pdu_type == SPDK_NVME_TCP_PDU_TYPE_H2C_TERM_REQ);
1005 : 4 : CU_ASSERT(tqpair.send_pdu->hdr.term_req.common.hlen == sizeof(struct spdk_nvme_tcp_term_req_hdr));
1006 : 4 : CU_ASSERT(tqpair.send_pdu->hdr.term_req.common.plen == tqpair.send_pdu->hdr.term_req.common.hlen +
1007 : : (unsigned)sizeof(struct spdk_nvme_tcp_r2t_hdr));
1008 : 4 : CU_ASSERT(tqpair.send_pdu->hdr.term_req.fei[0] == 4);
1009 : :
1010 : : /* case 6: Expect: PASS */
1011 : 4 : tqpair.recv_pdu->hdr.common.pdu_type = SPDK_NVME_TCP_PDU_TYPE_IC_RESP;
1012 : 4 : tqpair.state = NVME_TCP_QPAIR_STATE_INVALID;
1013 : 4 : tqpair.recv_pdu->hdr.common.plen = sizeof(struct spdk_nvme_tcp_ic_resp);
1014 : 4 : tqpair.recv_pdu->hdr.common.hlen = sizeof(struct spdk_nvme_tcp_ic_resp);
1015 : 4 : nvme_tcp_pdu_ch_handle(&tqpair);
1016 : 4 : CU_ASSERT(tqpair.recv_state == NVME_TCP_PDU_RECV_STATE_AWAIT_PDU_PSH);
1017 : 4 : CU_ASSERT(tqpair.recv_pdu->psh_len == tqpair.recv_pdu->hdr.common.hlen - sizeof(
1018 : : struct spdk_nvme_tcp_common_pdu_hdr));
1019 : 4 : }
1020 : :
1021 : : DEFINE_RETURN_MOCK(spdk_sock_connect_ext, struct spdk_sock *);
1022 : : struct spdk_sock *
1023 : 24 : spdk_sock_connect_ext(const char *ip, int port,
1024 : : const char *_impl_name, struct spdk_sock_opts *opts)
1025 : : {
1026 [ + + + + ]: 24 : HANDLE_RETURN_MOCK(spdk_sock_connect_ext);
1027 : 12 : CU_ASSERT(port == 23);
1028 : 12 : CU_ASSERT(opts->opts_size == sizeof(*opts));
1029 : 12 : CU_ASSERT(opts->priority == 1);
1030 [ - + ]: 12 : CU_ASSERT(opts->zcopy == true);
1031 [ - + ]: 12 : CU_ASSERT(!strcmp(ip, "192.168.1.78"));
1032 : 12 : return (struct spdk_sock *)0xDDADBEEF;
1033 : : }
1034 : :
1035 : : static void
1036 : 4 : test_nvme_tcp_qpair_connect_sock(void)
1037 : : {
1038 : 4 : struct nvme_tcp_ctrlr tctrlr = {};
1039 : 4 : struct spdk_nvme_ctrlr *ctrlr = &tctrlr.ctrlr;
1040 : 4 : struct nvme_tcp_qpair tqpair = {};
1041 : : int rc;
1042 : :
1043 : 4 : tqpair.qpair.trtype = SPDK_NVME_TRANSPORT_TCP;
1044 : 4 : tqpair.qpair.id = 1;
1045 : 4 : tqpair.qpair.poll_group = (void *)0xDEADBEEF;
1046 : 4 : ctrlr->trid.priority = 1;
1047 : 4 : ctrlr->trid.adrfam = SPDK_NVMF_ADRFAM_IPV4;
1048 [ - + - + ]: 4 : memcpy(ctrlr->trid.traddr, "192.168.1.78", sizeof("192.168.1.78"));
1049 [ - + - + ]: 4 : memcpy(ctrlr->trid.trsvcid, "23", sizeof("23"));
1050 [ - + - + ]: 4 : memcpy(ctrlr->opts.src_addr, "192.168.1.77", sizeof("192.168.1.77"));
1051 [ - + - + ]: 4 : memcpy(ctrlr->opts.src_svcid, "23", sizeof("23"));
1052 : :
1053 : 4 : rc = nvme_tcp_qpair_connect_sock(ctrlr, &tqpair.qpair);
1054 : 4 : CU_ASSERT(rc == 0);
1055 : :
1056 : : /* Unsupported family of the transport address */
1057 : 4 : ctrlr->trid.adrfam = SPDK_NVMF_ADRFAM_IB;
1058 : :
1059 : 4 : rc = nvme_tcp_qpair_connect_sock(ctrlr, &tqpair.qpair);
1060 [ - + ]: 4 : SPDK_CU_ASSERT_FATAL(rc == -1);
1061 : :
1062 : : /* Invalid dst_port, INT_MAX is 2147483647 */
1063 : 4 : ctrlr->trid.adrfam = SPDK_NVMF_ADRFAM_IPV4;
1064 [ - + - + ]: 4 : memcpy(ctrlr->trid.trsvcid, "2147483647", sizeof("2147483647"));
1065 : :
1066 : 4 : rc = nvme_tcp_qpair_connect_sock(ctrlr, &tqpair.qpair);
1067 [ - + ]: 4 : SPDK_CU_ASSERT_FATAL(rc == -EINVAL);
1068 : :
1069 : : /* Parse invalid address */
1070 [ - + - + ]: 4 : memcpy(ctrlr->trid.trsvcid, "23", sizeof("23"));
1071 [ - + - + ]: 4 : memcpy(ctrlr->trid.traddr, "192.168.1.256", sizeof("192.168.1.256"));
1072 : :
1073 : 4 : rc = nvme_tcp_qpair_connect_sock(ctrlr, &tqpair.qpair);
1074 [ - + ]: 4 : SPDK_CU_ASSERT_FATAL(rc != 0);
1075 : 4 : }
1076 : :
1077 : : static void
1078 : 4 : test_nvme_tcp_qpair_icreq_send(void)
1079 : : {
1080 : 4 : struct nvme_tcp_qpair tqpair = {};
1081 : 4 : struct spdk_nvme_tcp_stat stats = {};
1082 : 4 : struct spdk_nvme_ctrlr ctrlr = {};
1083 : 4 : struct nvme_tcp_pdu pdu = {};
1084 : 4 : struct nvme_tcp_poll_group poll_group = {};
1085 : 4 : struct spdk_nvme_tcp_ic_req *ic_req = NULL;
1086 : : int rc;
1087 : :
1088 : 4 : tqpair.send_pdu = &pdu;
1089 : 4 : tqpair.qpair.ctrlr = &ctrlr;
1090 : 4 : tqpair.qpair.poll_group = &poll_group.group;
1091 : 4 : tqpair.stats = &stats;
1092 : 4 : ic_req = &pdu.hdr.ic_req;
1093 : :
1094 : 4 : tqpair.state = NVME_TCP_QPAIR_STATE_RUNNING;
1095 : 4 : tqpair.qpair.ctrlr->opts.header_digest = true;
1096 : 4 : tqpair.qpair.ctrlr->opts.data_digest = true;
1097 : 4 : TAILQ_INIT(&tqpair.send_queue);
1098 : :
1099 : 4 : rc = nvme_tcp_qpair_icreq_send(&tqpair);
1100 : 4 : CU_ASSERT(rc == 0);
1101 : 4 : CU_ASSERT(ic_req->common.hlen == sizeof(*ic_req));
1102 : 4 : CU_ASSERT(ic_req->common.plen == sizeof(*ic_req));
1103 : 4 : CU_ASSERT(ic_req->common.pdu_type == SPDK_NVME_TCP_PDU_TYPE_IC_REQ);
1104 : 4 : CU_ASSERT(ic_req->pfv == 0);
1105 : 4 : CU_ASSERT(ic_req->maxr2t == NVME_TCP_MAX_R2T_DEFAULT - 1);
1106 : 4 : CU_ASSERT(ic_req->hpda == NVME_TCP_HPDA_DEFAULT);
1107 : 4 : CU_ASSERT(ic_req->dgst.bits.hdgst_enable == true);
1108 : 4 : CU_ASSERT(ic_req->dgst.bits.ddgst_enable == true);
1109 : 4 : }
1110 : :
1111 : : static void
1112 : 4 : test_nvme_tcp_c2h_payload_handle(void)
1113 : : {
1114 : 4 : struct nvme_tcp_qpair tqpair = {};
1115 : 4 : struct spdk_nvme_tcp_stat stats = {};
1116 : 4 : struct nvme_tcp_pdu pdu = {};
1117 : 4 : struct nvme_tcp_req tcp_req = {};
1118 : 4 : struct nvme_request req = {};
1119 : 4 : struct nvme_tcp_pdu recv_pdu = {};
1120 : 4 : uint32_t reaped = 1;
1121 : :
1122 : 4 : tcp_req.req = &req;
1123 : 4 : tcp_req.req->qpair = &tqpair.qpair;
1124 : 4 : tcp_req.req->cb_fn = ut_nvme_complete_request;
1125 : 4 : tcp_req.tqpair = &tqpair;
1126 : 4 : tcp_req.cid = 1;
1127 : 4 : tqpair.stats = &stats;
1128 : :
1129 : 4 : TAILQ_INIT(&tcp_req.tqpair->outstanding_reqs);
1130 : :
1131 : 4 : pdu.req = &tcp_req;
1132 : 4 : pdu.hdr.c2h_data.common.flags = SPDK_NVME_TCP_C2H_DATA_FLAGS_SUCCESS |
1133 : : SPDK_NVME_TCP_C2H_DATA_FLAGS_LAST_PDU;
1134 : 4 : pdu.data_len = 1024;
1135 : :
1136 : 4 : tqpair.qpair.id = 1;
1137 : 4 : tqpair.recv_pdu = &recv_pdu;
1138 : :
1139 : : /* case 1: nvme_tcp_c2h_data_payload_handle: tcp_req->datao != tcp_req->req->payload_size */
1140 : 4 : tcp_req.datao = 1024;
1141 : 4 : tcp_req.req->payload_size = 2048;
1142 : 4 : tcp_req.state = NVME_TCP_REQ_ACTIVE;
1143 : 4 : tcp_req.ordering.bits.send_ack = 1;
1144 [ - + ]: 4 : memset(&tcp_req.rsp, 0, sizeof(tcp_req.rsp));
1145 : 4 : tcp_req.ordering.bits.data_recv = 0;
1146 : 4 : tqpair.recv_state = NVME_TCP_PDU_RECV_STATE_ERROR;
1147 : 4 : TAILQ_INSERT_TAIL(&tcp_req.tqpair->outstanding_reqs, &tcp_req, link);
1148 : 4 : tqpair.qpair.num_outstanding_reqs = 1;
1149 : :
1150 : 4 : nvme_tcp_c2h_data_payload_handle(&tqpair, &pdu, &reaped);
1151 : :
1152 : 4 : CU_ASSERT(tcp_req.rsp.status.p == 0);
1153 : 4 : CU_ASSERT(tcp_req.rsp.cid == tcp_req.cid);
1154 : 4 : CU_ASSERT(tcp_req.rsp.sqid == tqpair.qpair.id);
1155 : 4 : CU_ASSERT(tcp_req.ordering.bits.data_recv == 1);
1156 : 4 : CU_ASSERT(reaped == 2);
1157 : 4 : CU_ASSERT(tqpair.qpair.num_outstanding_reqs == 0);
1158 : :
1159 : : /* case 2: nvme_tcp_c2h_data_payload_handle: tcp_req->datao == tcp_req->req->payload_size */
1160 : 4 : tcp_req.datao = 1024;
1161 : 4 : tcp_req.req->payload_size = 1024;
1162 : 4 : tcp_req.state = NVME_TCP_REQ_ACTIVE;
1163 : 4 : tcp_req.ordering.bits.send_ack = 1;
1164 [ - + ]: 4 : memset(&tcp_req.rsp, 0, sizeof(tcp_req.rsp));
1165 : 4 : tcp_req.ordering.bits.data_recv = 0;
1166 : 4 : tqpair.recv_state = NVME_TCP_PDU_RECV_STATE_ERROR;
1167 : 4 : TAILQ_INSERT_TAIL(&tcp_req.tqpair->outstanding_reqs, &tcp_req, link);
1168 : 4 : tqpair.qpair.num_outstanding_reqs = 1;
1169 : :
1170 : 4 : nvme_tcp_c2h_data_payload_handle(&tqpair, &pdu, &reaped);
1171 : :
1172 : 4 : CU_ASSERT(tcp_req.rsp.status.p == 1);
1173 : 4 : CU_ASSERT(tcp_req.rsp.cid == tcp_req.cid);
1174 : 4 : CU_ASSERT(tcp_req.rsp.sqid == tqpair.qpair.id);
1175 : 4 : CU_ASSERT(tcp_req.ordering.bits.data_recv == 1);
1176 : 4 : CU_ASSERT(reaped == 3);
1177 : 4 : CU_ASSERT(tqpair.qpair.num_outstanding_reqs == 0);
1178 : :
1179 : : /* case 3: nvme_tcp_c2h_data_payload_handle: flag does not have SPDK_NVME_TCP_C2H_DATA_FLAGS_SUCCESS */
1180 : 4 : pdu.hdr.c2h_data.common.flags = SPDK_NVME_TCP_C2H_DATA_FLAGS_LAST_PDU;
1181 : 4 : tcp_req.datao = 1024;
1182 : 4 : tcp_req.req->payload_size = 1024;
1183 : 4 : tcp_req.state = NVME_TCP_REQ_ACTIVE;
1184 : 4 : tcp_req.ordering.bits.send_ack = 1;
1185 [ - + ]: 4 : memset(&tcp_req.rsp, 0, sizeof(tcp_req.rsp));
1186 : 4 : tcp_req.ordering.bits.data_recv = 0;
1187 : 4 : tqpair.recv_state = NVME_TCP_PDU_RECV_STATE_ERROR;
1188 : 4 : TAILQ_INSERT_TAIL(&tcp_req.tqpair->outstanding_reqs, &tcp_req, link);
1189 : 4 : tqpair.qpair.num_outstanding_reqs = 1;
1190 : :
1191 : 4 : nvme_tcp_c2h_data_payload_handle(&tqpair, &pdu, &reaped);
1192 : :
1193 : 4 : CU_ASSERT(reaped == 3);
1194 : 4 : CU_ASSERT(tqpair.qpair.num_outstanding_reqs == 1);
1195 : :
1196 : : /* case 4: nvme_tcp_c2h_term_req_payload_handle: recv_state is NVME_TCP_PDU_RECV_STATE_ERROR */
1197 : 4 : pdu.hdr.term_req.fes = SPDK_NVME_TCP_TERM_REQ_FES_INVALID_HEADER_FIELD;
1198 : 4 : nvme_tcp_c2h_term_req_payload_handle(&tqpair, &pdu);
1199 : :
1200 : 4 : CU_ASSERT(tqpair.recv_state == NVME_TCP_PDU_RECV_STATE_QUIESCING);
1201 : 4 : CU_ASSERT(tqpair.qpair.num_outstanding_reqs == 1);
1202 : 4 : }
1203 : :
1204 : : static void
1205 : 4 : test_nvme_tcp_icresp_handle(void)
1206 : : {
1207 : 4 : struct nvme_tcp_qpair tqpair = {};
1208 : 4 : struct spdk_nvme_tcp_stat stats = {};
1209 : 4 : struct nvme_tcp_pdu pdu = {};
1210 : 4 : struct nvme_tcp_pdu send_pdu = {};
1211 : 4 : struct nvme_tcp_pdu recv_pdu = {};
1212 : :
1213 : 4 : tqpair.send_pdu = &send_pdu;
1214 : 4 : tqpair.recv_pdu = &recv_pdu;
1215 : 4 : tqpair.stats = &stats;
1216 : 4 : TAILQ_INIT(&tqpair.send_queue);
1217 : :
1218 : : /* case 1: Expected ICResp PFV and got are different. */
1219 : 4 : pdu.hdr.ic_resp.pfv = 1;
1220 : :
1221 : 4 : nvme_tcp_icresp_handle(&tqpair, &pdu);
1222 : :
1223 : 4 : CU_ASSERT(tqpair.recv_state == NVME_TCP_PDU_RECV_STATE_QUIESCING);
1224 : :
1225 : : /* case 2: Expected ICResp maxh2cdata and got are different. */
1226 : 4 : pdu.hdr.ic_resp.pfv = 0;
1227 : 4 : pdu.hdr.ic_resp.maxh2cdata = 2048;
1228 : :
1229 : 4 : nvme_tcp_icresp_handle(&tqpair, &pdu);
1230 : :
1231 : 4 : CU_ASSERT(tqpair.recv_state == NVME_TCP_PDU_RECV_STATE_QUIESCING);
1232 : :
1233 : : /* case 3: Expected ICResp cpda and got are different. */
1234 : 4 : pdu.hdr.ic_resp.maxh2cdata = NVME_TCP_PDU_H2C_MIN_DATA_SIZE;
1235 : 4 : pdu.hdr.ic_resp.cpda = 64;
1236 : :
1237 : 4 : nvme_tcp_icresp_handle(&tqpair, &pdu);
1238 : :
1239 : 4 : CU_ASSERT(tqpair.recv_state == NVME_TCP_PDU_RECV_STATE_QUIESCING);
1240 : :
1241 : : /* case 4: waiting icreq ack. */
1242 : 4 : pdu.hdr.ic_resp.maxh2cdata = NVME_TCP_PDU_H2C_MIN_DATA_SIZE;
1243 : 4 : pdu.hdr.ic_resp.cpda = 30;
1244 : 4 : pdu.hdr.ic_resp.dgst.bits.hdgst_enable = true;
1245 : 4 : pdu.hdr.ic_resp.dgst.bits.ddgst_enable = true;
1246 : 4 : tqpair.flags.icreq_send_ack = 0;
1247 : :
1248 : 4 : nvme_tcp_icresp_handle(&tqpair, &pdu);
1249 : :
1250 : 4 : CU_ASSERT(tqpair.recv_state == NVME_TCP_PDU_RECV_STATE_AWAIT_PDU_READY);
1251 : 4 : CU_ASSERT(tqpair.state == NVME_TCP_QPAIR_STATE_INITIALIZING);
1252 : 4 : CU_ASSERT(tqpair.maxh2cdata == pdu.hdr.ic_resp.maxh2cdata);
1253 : 4 : CU_ASSERT(tqpair.cpda == pdu.hdr.ic_resp.cpda);
1254 : 4 : CU_ASSERT(tqpair.flags.host_hdgst_enable == pdu.hdr.ic_resp.dgst.bits.hdgst_enable);
1255 : 4 : CU_ASSERT(tqpair.flags.host_ddgst_enable == pdu.hdr.ic_resp.dgst.bits.ddgst_enable);
1256 : :
1257 : : /* case 5: Expect: PASS. */
1258 : 4 : tqpair.flags.icreq_send_ack = 1;
1259 : :
1260 : 4 : nvme_tcp_icresp_handle(&tqpair, &pdu);
1261 : :
1262 : 4 : CU_ASSERT(tqpair.recv_state == NVME_TCP_PDU_RECV_STATE_AWAIT_PDU_READY);
1263 : 4 : CU_ASSERT(tqpair.state == NVME_TCP_QPAIR_STATE_FABRIC_CONNECT_SEND);
1264 : 4 : CU_ASSERT(tqpair.maxh2cdata == pdu.hdr.ic_resp.maxh2cdata);
1265 : 4 : CU_ASSERT(tqpair.cpda == pdu.hdr.ic_resp.cpda);
1266 : 4 : CU_ASSERT(tqpair.flags.host_hdgst_enable == pdu.hdr.ic_resp.dgst.bits.hdgst_enable);
1267 : 4 : CU_ASSERT(tqpair.flags.host_ddgst_enable == pdu.hdr.ic_resp.dgst.bits.ddgst_enable);
1268 : 4 : }
1269 : :
1270 : : static void
1271 : 4 : test_nvme_tcp_pdu_payload_handle(void)
1272 : : {
1273 : 4 : struct nvme_tcp_qpair tqpair = {};
1274 : 4 : struct spdk_nvme_tcp_stat stats = {};
1275 : 4 : struct nvme_tcp_pdu recv_pdu = {};
1276 : 4 : struct nvme_tcp_req tcp_req = {};
1277 : 4 : struct nvme_request req = {};
1278 : 4 : uint32_t reaped = 0;
1279 : :
1280 : 4 : tqpair.recv_pdu = &recv_pdu;
1281 : 4 : tcp_req.tqpair = &tqpair;
1282 : 4 : tcp_req.req = &req;
1283 : 4 : tcp_req.req->qpair = &tqpair.qpair;
1284 : 4 : tqpair.stats = &stats;
1285 : :
1286 : 4 : tqpair.recv_state = NVME_TCP_PDU_RECV_STATE_AWAIT_PDU_PAYLOAD;
1287 : 4 : tqpair.qpair.id = 1;
1288 : 4 : recv_pdu.ddgst_enable = false;
1289 : 4 : recv_pdu.req = &tcp_req;
1290 : 4 : recv_pdu.hdr.c2h_data.common.flags = SPDK_NVME_TCP_C2H_DATA_FLAGS_SUCCESS |
1291 : : SPDK_NVME_TCP_C2H_DATA_FLAGS_LAST_PDU;
1292 : 4 : recv_pdu.data_len = 1024;
1293 : 4 : tcp_req.ordering.bits.data_recv = 0;
1294 : 4 : tcp_req.req->cb_fn = ut_nvme_complete_request;
1295 : 4 : tcp_req.cid = 1;
1296 : 4 : TAILQ_INIT(&tcp_req.tqpair->outstanding_reqs);
1297 : 4 : TAILQ_INSERT_TAIL(&tcp_req.tqpair->outstanding_reqs, &tcp_req, link);
1298 : 4 : tqpair.qpair.num_outstanding_reqs = 1;
1299 : :
1300 : : /* C2H_DATA */
1301 : 4 : recv_pdu.hdr.common.pdu_type = SPDK_NVME_TCP_PDU_TYPE_C2H_DATA;
1302 : 4 : tcp_req.datao = 1024;
1303 : 4 : tcp_req.req->payload_size = 2048;
1304 : 4 : tcp_req.state = NVME_TCP_REQ_ACTIVE;
1305 : 4 : tcp_req.ordering.bits.send_ack = 1;
1306 : :
1307 : 4 : recv_pdu.req = &tcp_req;
1308 : 4 : nvme_tcp_pdu_payload_handle(&tqpair, &reaped);
1309 : 4 : CU_ASSERT(tqpair.recv_state == NVME_TCP_PDU_RECV_STATE_AWAIT_PDU_READY);
1310 : 4 : CU_ASSERT(tcp_req.rsp.status.p == 0);
1311 : 4 : CU_ASSERT(tcp_req.rsp.cid == 1);
1312 : 4 : CU_ASSERT(tcp_req.rsp.sqid == 1);
1313 : 4 : CU_ASSERT(tcp_req.ordering.bits.data_recv == 1);
1314 : 4 : CU_ASSERT(reaped == 1);
1315 : 4 : CU_ASSERT(tqpair.qpair.num_outstanding_reqs == 0);
1316 : :
1317 : : /* TermResp */
1318 : 4 : recv_pdu.hdr.common.pdu_type = SPDK_NVME_TCP_PDU_TYPE_C2H_TERM_REQ;
1319 : 4 : recv_pdu.hdr.term_req.fes = SPDK_NVME_TCP_TERM_REQ_FES_INVALID_HEADER_FIELD;
1320 : 4 : tqpair.recv_state = NVME_TCP_PDU_RECV_STATE_AWAIT_PDU_PAYLOAD;
1321 : :
1322 : 4 : recv_pdu.req = &tcp_req;
1323 : 4 : nvme_tcp_pdu_payload_handle(&tqpair, &reaped);
1324 : 4 : CU_ASSERT(tqpair.recv_state == NVME_TCP_PDU_RECV_STATE_QUIESCING);
1325 : 4 : }
1326 : :
1327 : : static void
1328 : 4 : test_nvme_tcp_capsule_resp_hdr_handle(void)
1329 : : {
1330 : 4 : struct nvme_tcp_qpair tqpair = {};
1331 : 4 : struct spdk_nvme_ctrlr ctrlr = {};
1332 : 4 : struct spdk_nvme_tcp_stat stats = {};
1333 : 4 : struct nvme_request req = {};
1334 : 4 : struct spdk_nvme_cpl rccqe_tgt = {};
1335 : 4 : struct nvme_tcp_req *tcp_req = NULL;
1336 : 4 : uint32_t reaped = 0;
1337 : : int rc;
1338 : :
1339 : : /* Initialize requests and pdus */
1340 : 4 : tqpair.num_entries = 1;
1341 : 4 : tqpair.stats = &stats;
1342 : 4 : req.qpair = &tqpair.qpair;
1343 : 4 : req.qpair->ctrlr = &ctrlr;
1344 : 4 : req.payload = NVME_PAYLOAD_CONTIG(NULL, NULL);
1345 : :
1346 : 4 : rc = nvme_tcp_alloc_reqs(&tqpair);
1347 [ - + ]: 4 : SPDK_CU_ASSERT_FATAL(rc == 0);
1348 : 4 : tcp_req = nvme_tcp_req_get(&tqpair);
1349 [ - + ]: 4 : SPDK_CU_ASSERT_FATAL(tcp_req != NULL);
1350 : 4 : rc = nvme_tcp_req_init(&tqpair, &req, tcp_req);
1351 [ - + ]: 4 : SPDK_CU_ASSERT_FATAL(rc == 0);
1352 : 4 : tcp_req->ordering.bits.send_ack = 1;
1353 : 4 : tqpair.recv_state = NVME_TCP_PDU_RECV_STATE_AWAIT_PDU_PSH;
1354 : : /* tqpair.recv_pdu will be reseted after handling */
1355 : 4 : memset(&rccqe_tgt, 0xff, sizeof(rccqe_tgt));
1356 : 4 : rccqe_tgt.cid = 0;
1357 : 4 : memcpy(&tqpair.recv_pdu->hdr.capsule_resp.rccqe, &rccqe_tgt, sizeof(rccqe_tgt));
1358 : 4 : tqpair.qpair.num_outstanding_reqs = 1;
1359 : :
1360 : 4 : nvme_tcp_capsule_resp_hdr_handle(&tqpair, tqpair.recv_pdu, &reaped);
1361 : 4 : CU_ASSERT(tqpair.recv_state == NVME_TCP_PDU_RECV_STATE_AWAIT_PDU_READY);
1362 [ - + ]: 4 : CU_ASSERT(!memcmp(&tcp_req->rsp, &rccqe_tgt, sizeof(rccqe_tgt)));
1363 : 4 : CU_ASSERT(tcp_req->ordering.bits.data_recv == 1);
1364 : 4 : CU_ASSERT(reaped == 1);
1365 : 4 : CU_ASSERT(TAILQ_EMPTY(&tcp_req->tqpair->outstanding_reqs));
1366 : 4 : CU_ASSERT(tqpair.qpair.num_outstanding_reqs == 0);
1367 : :
1368 : : /* Get tcp request error, expect fail */
1369 : 4 : reaped = 0;
1370 : 4 : tqpair.recv_pdu->hdr.capsule_resp.rccqe.cid = 1;
1371 : 4 : tqpair.recv_state = NVME_TCP_PDU_RECV_STATE_AWAIT_PDU_PSH;
1372 : :
1373 : 4 : nvme_tcp_capsule_resp_hdr_handle(&tqpair, tqpair.recv_pdu, &reaped);
1374 : 4 : CU_ASSERT(reaped == 0);
1375 : 4 : CU_ASSERT(tqpair.recv_state == NVME_TCP_PDU_RECV_STATE_QUIESCING);
1376 : 4 : nvme_tcp_free_reqs(&tqpair);
1377 : 4 : }
1378 : :
1379 : : static void
1380 : 4 : test_nvme_tcp_ctrlr_connect_qpair(void)
1381 : : {
1382 : 4 : struct spdk_nvme_ctrlr ctrlr = {};
1383 : : struct spdk_nvme_qpair *qpair;
1384 : : struct nvme_tcp_qpair *tqpair;
1385 : 4 : struct nvme_tcp_pdu pdu = {};
1386 : 4 : struct nvme_tcp_pdu recv_pdu = {};
1387 : 4 : struct spdk_nvme_tcp_ic_req *ic_req = NULL;
1388 : : int rc;
1389 : :
1390 : 4 : tqpair = calloc(1, sizeof(*tqpair));
1391 : 4 : tqpair->qpair.trtype = SPDK_NVME_TRANSPORT_TCP;
1392 : 4 : tqpair->recv_pdu = &recv_pdu;
1393 : 4 : qpair = &tqpair->qpair;
1394 : 4 : tqpair->sock = (struct spdk_sock *)0xDEADBEEF;
1395 : 4 : tqpair->send_pdu = &pdu;
1396 : 4 : tqpair->qpair.ctrlr = &ctrlr;
1397 : 4 : tqpair->qpair.state = NVME_QPAIR_CONNECTING;
1398 : 4 : tqpair->num_entries = 128;
1399 : 4 : ic_req = &pdu.hdr.ic_req;
1400 : :
1401 : 4 : tqpair->recv_pdu->hdr.common.pdu_type = SPDK_NVME_TCP_PDU_TYPE_IC_RESP;
1402 : 4 : tqpair->recv_pdu->hdr.common.plen = sizeof(struct spdk_nvme_tcp_ic_resp);
1403 : 4 : tqpair->recv_pdu->hdr.common.hlen = sizeof(struct spdk_nvme_tcp_ic_resp);
1404 : 4 : tqpair->recv_pdu->ch_valid_bytes = sizeof(struct spdk_nvme_tcp_common_pdu_hdr) - 1;
1405 : 7 : tqpair->recv_pdu->psh_valid_bytes = tqpair->recv_pdu->hdr.common.hlen -
1406 : 4 : sizeof(struct spdk_nvme_tcp_common_pdu_hdr) - 1;
1407 : 4 : tqpair->recv_pdu->hdr.ic_resp.maxh2cdata = 4096;
1408 : 4 : tqpair->recv_pdu->hdr.ic_resp.cpda = 1;
1409 : 4 : tqpair->flags.icreq_send_ack = 1;
1410 : 4 : tqpair->qpair.ctrlr->opts.header_digest = true;
1411 : 4 : tqpair->qpair.ctrlr->opts.data_digest = true;
1412 : 4 : TAILQ_INIT(&tqpair->send_queue);
1413 : :
1414 : 4 : rc = nvme_tcp_ctrlr_connect_qpair(&ctrlr, qpair);
1415 : 4 : CU_ASSERT(rc == 0);
1416 : :
1417 : : /* skip NVME_TCP_PDU_RECV_STATE_AWAIT_PDU_READY state */
1418 : : /* assume already received the icresp */
1419 : 4 : tqpair->recv_state = NVME_TCP_PDU_RECV_STATE_AWAIT_PDU_CH;
1420 : :
1421 [ + + ]: 12 : while (nvme_qpair_get_state(qpair) == NVME_QPAIR_CONNECTING) {
1422 : 8 : rc = nvme_tcp_qpair_process_completions(qpair, 0);
1423 : 8 : CU_ASSERT(rc >= 0);
1424 : : }
1425 : :
1426 : 4 : CU_ASSERT(tqpair->maxr2t == NVME_TCP_MAX_R2T_DEFAULT);
1427 : 4 : CU_ASSERT(tqpair->state == NVME_TCP_QPAIR_STATE_RUNNING);
1428 : 4 : CU_ASSERT(tqpair->recv_state == NVME_TCP_PDU_RECV_STATE_AWAIT_PDU_CH);
1429 : 4 : CU_ASSERT(ic_req->common.hlen == sizeof(*ic_req));
1430 : 4 : CU_ASSERT(ic_req->common.plen == sizeof(*ic_req));
1431 : 4 : CU_ASSERT(ic_req->common.pdu_type == SPDK_NVME_TCP_PDU_TYPE_IC_REQ);
1432 : 4 : CU_ASSERT(ic_req->pfv == 0);
1433 : 4 : CU_ASSERT(ic_req->maxr2t == NVME_TCP_MAX_R2T_DEFAULT - 1);
1434 : 4 : CU_ASSERT(ic_req->hpda == NVME_TCP_HPDA_DEFAULT);
1435 : 4 : CU_ASSERT(ic_req->dgst.bits.hdgst_enable == true);
1436 : 4 : CU_ASSERT(ic_req->dgst.bits.ddgst_enable == true);
1437 : :
1438 : 4 : nvme_tcp_ctrlr_delete_io_qpair(&ctrlr, qpair);
1439 : 4 : }
1440 : :
1441 : : static void
1442 : 4 : ut_disconnect_qpair_req_cb(void *ctx, const struct spdk_nvme_cpl *cpl)
1443 : : {
1444 : 4 : CU_ASSERT_EQUAL(cpl->status.sc, SPDK_NVME_SC_ABORTED_SQ_DELETION);
1445 : 4 : CU_ASSERT_EQUAL(cpl->status.sct, SPDK_NVME_SCT_GENERIC);
1446 : 4 : }
1447 : :
1448 : : static void
1449 : 4 : ut_disconnect_qpair_poll_group_cb(struct spdk_nvme_qpair *qpair, void *ctx)
1450 : : {
1451 : 4 : int *disconnected = ctx;
1452 : :
1453 : 4 : (*disconnected)++;
1454 : 4 : }
1455 : :
1456 : : static void
1457 : 4 : test_nvme_tcp_ctrlr_disconnect_qpair(void)
1458 : : {
1459 : 4 : struct spdk_nvme_ctrlr ctrlr = {};
1460 : : struct spdk_nvme_qpair *qpair;
1461 : 4 : struct nvme_tcp_pdu pdu = {}, recv_pdu = {};
1462 : 4 : struct nvme_tcp_qpair tqpair = {
1463 : : .qpair = {
1464 : : .trtype = SPDK_NVME_TRANSPORT_TCP,
1465 : : .ctrlr = &ctrlr,
1466 : : .async = true,
1467 : : },
1468 : : .recv_pdu = &recv_pdu,
1469 : : };
1470 : 4 : struct spdk_nvme_poll_group group = {};
1471 : 4 : struct nvme_tcp_poll_group tgroup = { .group.group = &group };
1472 : 4 : struct nvme_request req = { .qpair = &tqpair.qpair, .cb_fn = ut_disconnect_qpair_req_cb };
1473 : 4 : struct nvme_tcp_req treq = { .req = &req, .tqpair = &tqpair };
1474 : 4 : int rc, disconnected;
1475 : :
1476 : 4 : qpair = &tqpair.qpair;
1477 : 4 : qpair->poll_group = &tgroup.group;
1478 : 4 : tqpair.sock = (struct spdk_sock *)0xDEADBEEF;
1479 : 4 : tqpair.needs_poll = true;
1480 : 4 : TAILQ_INIT(&tgroup.needs_poll);
1481 : 4 : STAILQ_INIT(&tgroup.group.disconnected_qpairs);
1482 : 4 : TAILQ_INIT(&tqpair.send_queue);
1483 : 4 : TAILQ_INIT(&tqpair.free_reqs);
1484 : 4 : TAILQ_INIT(&tqpair.outstanding_reqs);
1485 : 4 : TAILQ_INSERT_TAIL(&tgroup.needs_poll, &tqpair, link);
1486 : 4 : TAILQ_INSERT_TAIL(&tqpair.send_queue, &pdu, tailq);
1487 : :
1488 : 4 : nvme_tcp_ctrlr_disconnect_qpair(&ctrlr, qpair);
1489 : :
1490 [ - + ]: 4 : CU_ASSERT(tqpair.needs_poll == false);
1491 : 4 : CU_ASSERT(tqpair.sock == NULL);
1492 : 4 : CU_ASSERT(TAILQ_EMPTY(&tqpair.send_queue) == true);
1493 : :
1494 : : /* Check that outstanding requests are aborted */
1495 : 4 : treq.state = NVME_TCP_REQ_ACTIVE;
1496 : 4 : qpair->num_outstanding_reqs = 1;
1497 : 4 : qpair->state = NVME_QPAIR_DISCONNECTING;
1498 : 4 : TAILQ_INSERT_TAIL(&tqpair.outstanding_reqs, &treq, link);
1499 : :
1500 : 4 : nvme_tcp_ctrlr_disconnect_qpair(&ctrlr, qpair);
1501 : :
1502 : 4 : CU_ASSERT(TAILQ_EMPTY(&tqpair.outstanding_reqs));
1503 : 4 : CU_ASSERT_EQUAL(qpair->num_outstanding_reqs, 0);
1504 : 4 : CU_ASSERT_EQUAL(&treq, TAILQ_FIRST(&tqpair.free_reqs));
1505 : 4 : CU_ASSERT_EQUAL(qpair->state, NVME_QPAIR_DISCONNECTING);
1506 : :
1507 : : /* Check that a request with an accel operation in progress won't be aborted until that
1508 : : * operation is completed */
1509 : 4 : treq.state = NVME_TCP_REQ_ACTIVE;
1510 : 4 : treq.ordering.bits.in_progress_accel = 1;
1511 : 4 : qpair->poll_group = NULL;
1512 : 4 : qpair->num_outstanding_reqs = 1;
1513 : 4 : qpair->state = NVME_QPAIR_DISCONNECTING;
1514 [ - + ]: 4 : TAILQ_REMOVE(&tqpair.free_reqs, &treq, link);
1515 : 4 : TAILQ_INSERT_TAIL(&tqpair.outstanding_reqs, &treq, link);
1516 : :
1517 : 4 : nvme_tcp_ctrlr_disconnect_qpair(&ctrlr, qpair);
1518 : :
1519 : 4 : CU_ASSERT_EQUAL(&treq, TAILQ_FIRST(&tqpair.outstanding_reqs));
1520 : 4 : CU_ASSERT_EQUAL(qpair->num_outstanding_reqs, 1);
1521 : 4 : CU_ASSERT_EQUAL(qpair->state, NVME_QPAIR_DISCONNECTING);
1522 : :
1523 : : /* Check that a qpair will be transitioned to a DISCONNECTED state only once the accel
1524 : : * operation is completed */
1525 : 4 : rc = nvme_tcp_qpair_process_completions(qpair, 0);
1526 : 4 : CU_ASSERT_EQUAL(rc, 0);
1527 : 4 : CU_ASSERT_EQUAL(&treq, TAILQ_FIRST(&tqpair.outstanding_reqs));
1528 : 4 : CU_ASSERT_EQUAL(qpair->num_outstanding_reqs, 1);
1529 : 4 : CU_ASSERT_EQUAL(qpair->state, NVME_QPAIR_DISCONNECTING);
1530 : :
1531 : 4 : treq.ordering.bits.in_progress_accel = 0;
1532 : 4 : qpair->num_outstanding_reqs = 0;
1533 [ - + ]: 4 : TAILQ_REMOVE(&tqpair.outstanding_reqs, &treq, link);
1534 : :
1535 : 4 : rc = nvme_tcp_qpair_process_completions(qpair, 0);
1536 : 4 : CU_ASSERT_EQUAL(rc, -ENXIO);
1537 : 4 : CU_ASSERT_EQUAL(qpair->state, NVME_QPAIR_DISCONNECTED);
1538 : :
1539 : : /* Check the same scenario but this time with spdk_sock_flush() returning errors */
1540 : 4 : treq.state = NVME_TCP_REQ_ACTIVE;
1541 : 4 : treq.ordering.bits.in_progress_accel = 1;
1542 : 4 : qpair->num_outstanding_reqs = 1;
1543 : 4 : qpair->state = NVME_QPAIR_DISCONNECTING;
1544 : 4 : TAILQ_INSERT_TAIL(&tqpair.outstanding_reqs, &treq, link);
1545 : :
1546 : 4 : nvme_tcp_ctrlr_disconnect_qpair(&ctrlr, qpair);
1547 : :
1548 : 4 : CU_ASSERT_EQUAL(&treq, TAILQ_FIRST(&tqpair.outstanding_reqs));
1549 : 4 : CU_ASSERT_EQUAL(qpair->num_outstanding_reqs, 1);
1550 : 4 : CU_ASSERT_EQUAL(qpair->state, NVME_QPAIR_DISCONNECTING);
1551 : :
1552 : 4 : MOCK_SET(spdk_sock_flush, -ENOTCONN);
1553 : 4 : treq.ordering.bits.in_progress_accel = 0;
1554 : 4 : qpair->num_outstanding_reqs = 0;
1555 [ - + ]: 4 : TAILQ_REMOVE(&tqpair.outstanding_reqs, &treq, link);
1556 : :
1557 : 4 : rc = nvme_tcp_qpair_process_completions(qpair, 0);
1558 : 4 : CU_ASSERT_EQUAL(rc, 0);
1559 : 4 : CU_ASSERT_EQUAL(qpair->state, NVME_QPAIR_DISCONNECTED);
1560 : 4 : rc = nvme_tcp_qpair_process_completions(qpair, 0);
1561 : 4 : CU_ASSERT_EQUAL(rc, -ENXIO);
1562 : 4 : CU_ASSERT_EQUAL(qpair->state, NVME_QPAIR_DISCONNECTED);
1563 : 4 : MOCK_CLEAR(spdk_sock_flush);
1564 : :
1565 : : /* Now check the same scenario, but with a qpair that's part of a poll group */
1566 : 4 : disconnected = 0;
1567 : 4 : group.ctx = &disconnected;
1568 : 4 : treq.state = NVME_TCP_REQ_ACTIVE;
1569 : 4 : treq.ordering.bits.in_progress_accel = 1;
1570 : 4 : qpair->poll_group = &tgroup.group;
1571 : 4 : qpair->num_outstanding_reqs = 1;
1572 : 4 : qpair->state = NVME_QPAIR_DISCONNECTING;
1573 : 4 : STAILQ_INSERT_TAIL(&tgroup.group.disconnected_qpairs, qpair, poll_group_stailq);
1574 : 4 : TAILQ_INSERT_TAIL(&tqpair.outstanding_reqs, &treq, link);
1575 : :
1576 : 4 : nvme_tcp_poll_group_process_completions(&tgroup.group, 0,
1577 : : ut_disconnect_qpair_poll_group_cb);
1578 : : /* Until there's an outstanding request, disconnect_cb shouldn't be executed */
1579 : 4 : CU_ASSERT_EQUAL(disconnected, 0);
1580 : 4 : CU_ASSERT_EQUAL(qpair->num_outstanding_reqs, 1);
1581 : 4 : CU_ASSERT_EQUAL(&treq, TAILQ_FIRST(&tqpair.outstanding_reqs));
1582 : 4 : CU_ASSERT_EQUAL(qpair->state, NVME_QPAIR_DISCONNECTING);
1583 : :
1584 : 4 : treq.ordering.bits.in_progress_accel = 0;
1585 : 4 : qpair->num_outstanding_reqs = 0;
1586 [ - + ]: 4 : TAILQ_REMOVE(&tqpair.outstanding_reqs, &treq, link);
1587 : :
1588 : 4 : nvme_tcp_poll_group_process_completions(&tgroup.group, 0,
1589 : : ut_disconnect_qpair_poll_group_cb);
1590 : 4 : CU_ASSERT_EQUAL(disconnected, 1);
1591 : 4 : CU_ASSERT_EQUAL(qpair->state, NVME_QPAIR_DISCONNECTED);
1592 : :
1593 : : /* Check that a non-async qpair is marked as disconnected immediately */
1594 : 4 : qpair->poll_group = NULL;
1595 : 4 : qpair->state = NVME_QPAIR_DISCONNECTING;
1596 : 4 : qpair->async = false;
1597 : :
1598 : 4 : nvme_tcp_ctrlr_disconnect_qpair(&ctrlr, qpair);
1599 : :
1600 : 4 : CU_ASSERT_EQUAL(qpair->state, NVME_QPAIR_DISCONNECTED);
1601 : 4 : }
1602 : :
1603 : : static void
1604 : 4 : test_nvme_tcp_ctrlr_create_io_qpair(void)
1605 : : {
1606 : 4 : struct spdk_nvme_qpair *qpair = NULL;
1607 : 4 : struct nvme_tcp_ctrlr tctrlr = {};
1608 : 4 : struct spdk_nvme_ctrlr *ctrlr = &tctrlr.ctrlr;
1609 : 4 : uint16_t qid = 1;
1610 : 4 : struct spdk_nvme_io_qpair_opts opts = {
1611 : : .io_queue_size = 2,
1612 : : .qprio = SPDK_NVME_QPRIO_URGENT,
1613 : : .io_queue_requests = 1,
1614 : : };
1615 : : struct nvme_tcp_qpair *tqpair;
1616 : :
1617 : 4 : ctrlr->trid.priority = 1;
1618 : 4 : ctrlr->trid.adrfam = SPDK_NVMF_ADRFAM_IPV4;
1619 [ - + ]: 4 : memset(ctrlr->opts.psk, 0, sizeof(ctrlr->opts.psk));
1620 [ - + - + ]: 4 : memcpy(ctrlr->trid.traddr, "192.168.1.78", sizeof("192.168.1.78"));
1621 [ - + - + ]: 4 : memcpy(ctrlr->trid.trsvcid, "23", sizeof("23"));
1622 [ - + - + ]: 4 : memcpy(ctrlr->opts.src_addr, "192.168.1.77", sizeof("192.168.1.77"));
1623 [ - + - + ]: 4 : memcpy(ctrlr->opts.src_svcid, "23", sizeof("23"));
1624 : :
1625 : 4 : qpair = nvme_tcp_ctrlr_create_io_qpair(ctrlr, qid, &opts);
1626 : 4 : tqpair = nvme_tcp_qpair(qpair);
1627 : :
1628 : 4 : CU_ASSERT(qpair != NULL);
1629 : 4 : CU_ASSERT(qpair->id == 1);
1630 : 4 : CU_ASSERT(qpair->ctrlr == ctrlr);
1631 : 4 : CU_ASSERT(qpair->qprio == SPDK_NVME_QPRIO_URGENT);
1632 : 4 : CU_ASSERT(qpair->trtype == SPDK_NVME_TRANSPORT_TCP);
1633 : 4 : CU_ASSERT(qpair->poll_group == (void *)0xDEADBEEF);
1634 : 4 : CU_ASSERT(tqpair->num_entries == 1);
1635 : :
1636 : 4 : free(tqpair->tcp_reqs);
1637 : 4 : spdk_free(tqpair->send_pdus);
1638 : 4 : free(tqpair);
1639 : :
1640 : : /* Max queue size shall pass */
1641 : 4 : opts.io_queue_size = 0xffff;
1642 : 4 : qpair = nvme_tcp_ctrlr_create_io_qpair(ctrlr, qid, &opts);
1643 : 4 : tqpair = nvme_tcp_qpair(qpair);
1644 : :
1645 : 4 : CU_ASSERT(qpair != NULL);
1646 : 4 : CU_ASSERT(tqpair->num_entries == 0xfffe);
1647 : :
1648 : 4 : free(tqpair->tcp_reqs);
1649 : 4 : spdk_free(tqpair->send_pdus);
1650 : 4 : free(tqpair);
1651 : :
1652 : : /* Queue size 0 shall fail */
1653 : 4 : opts.io_queue_size = 0;
1654 : 4 : qpair = nvme_tcp_ctrlr_create_io_qpair(ctrlr, qid, &opts);
1655 : 4 : CU_ASSERT(qpair == NULL);
1656 : :
1657 : : /* Queue size 1 shall fail */
1658 : 4 : opts.io_queue_size = 1;
1659 : 4 : qpair = nvme_tcp_ctrlr_create_io_qpair(ctrlr, qid, &opts);
1660 : 4 : CU_ASSERT(qpair == NULL);
1661 : 4 : }
1662 : :
1663 : : static void
1664 : 4 : test_nvme_tcp_ctrlr_delete_io_qpair(void)
1665 : : {
1666 : 4 : struct spdk_nvme_ctrlr ctrlr = {};
1667 : : struct spdk_nvme_qpair *qpair;
1668 : : struct nvme_tcp_qpair *tqpair;
1669 : 4 : struct nvme_tcp_req tcp_req = {};
1670 : 4 : struct nvme_request req = {};
1671 : : int rc;
1672 : :
1673 : 4 : tqpair = calloc(1, sizeof(struct nvme_tcp_qpair));
1674 : 4 : tqpair->tcp_reqs = calloc(1, sizeof(struct nvme_tcp_req));
1675 : 4 : tqpair->send_pdus = calloc(1, sizeof(struct nvme_tcp_pdu));
1676 : 4 : tqpair->qpair.trtype = SPDK_NVME_TRANSPORT_TCP;
1677 : 4 : qpair = &tqpair->qpair;
1678 : 4 : qpair->ctrlr = &ctrlr;
1679 : 4 : tcp_req.req = &req;
1680 : 4 : tcp_req.req->qpair = &tqpair->qpair;
1681 : 4 : tcp_req.req->cb_fn = ut_nvme_complete_request;
1682 : 4 : tcp_req.tqpair = tqpair;
1683 : 4 : tcp_req.state = NVME_TCP_REQ_ACTIVE;
1684 : 4 : TAILQ_INIT(&tqpair->outstanding_reqs);
1685 : 4 : TAILQ_INSERT_TAIL(&tcp_req.tqpair->outstanding_reqs, &tcp_req, link);
1686 : 4 : qpair->num_outstanding_reqs = 1;
1687 : :
1688 : 4 : rc = nvme_tcp_ctrlr_delete_io_qpair(&ctrlr, qpair);
1689 : :
1690 : 4 : CU_ASSERT(rc == 0);
1691 : 4 : }
1692 : :
1693 : : static void
1694 : 4 : test_nvme_tcp_poll_group_get_stats(void)
1695 : : {
1696 : 4 : int rc = 0;
1697 : 4 : struct spdk_sock_group sgroup = {};
1698 : 4 : struct nvme_tcp_poll_group *pgroup = NULL;
1699 : 4 : struct spdk_nvme_transport_poll_group *tgroup = NULL;
1700 : 4 : struct spdk_nvme_transport_poll_group_stat *tgroup_stat = NULL;
1701 : :
1702 : 4 : MOCK_SET(spdk_sock_group_create, &sgroup);
1703 : 4 : tgroup = nvme_tcp_poll_group_create();
1704 : 4 : CU_ASSERT(tgroup != NULL);
1705 : 4 : pgroup = nvme_tcp_poll_group(tgroup);
1706 : 4 : CU_ASSERT(pgroup != NULL);
1707 : :
1708 : : /* Invalid group pointer, expect fail and return -EINVAL */
1709 : 4 : rc = nvme_tcp_poll_group_get_stats(NULL, &tgroup_stat);
1710 : 4 : CU_ASSERT(rc == -EINVAL);
1711 : 4 : CU_ASSERT(tgroup_stat == NULL);
1712 : :
1713 : : /* Invalid stats, expect fail and return -EINVAL */
1714 : 4 : rc = nvme_tcp_poll_group_get_stats(tgroup, NULL);
1715 : 4 : CU_ASSERT(rc == -EINVAL);
1716 : :
1717 : : /* Get stats success */
1718 : 4 : rc = nvme_tcp_poll_group_get_stats(tgroup, &tgroup_stat);
1719 : 4 : CU_ASSERT(rc == 0);
1720 : 4 : CU_ASSERT(tgroup_stat != NULL);
1721 : 4 : CU_ASSERT(tgroup_stat->trtype == SPDK_NVME_TRANSPORT_TCP);
1722 [ - + - + ]: 4 : CU_ASSERT(memcmp(&tgroup_stat->tcp, &pgroup->stats, sizeof(struct spdk_nvme_tcp_stat)) == 0);
1723 : :
1724 : 4 : nvme_tcp_poll_group_free_stats(tgroup, tgroup_stat);
1725 : 4 : rc = nvme_tcp_poll_group_destroy(tgroup);
1726 : 4 : CU_ASSERT(rc == 0);
1727 : :
1728 : 4 : MOCK_CLEAR(spdk_sock_group_create);
1729 : 4 : }
1730 : :
1731 : : static void
1732 : 4 : test_nvme_tcp_ctrlr_construct(void)
1733 : : {
1734 : 4 : struct nvme_tcp_qpair *tqpair = NULL;
1735 : 4 : struct nvme_tcp_ctrlr *tctrlr = NULL;
1736 : 4 : struct spdk_nvme_ctrlr *ctrlr = NULL;
1737 : 4 : struct spdk_nvme_transport_id trid = {
1738 : : .trtype = SPDK_NVME_TRANSPORT_TCP,
1739 : : .priority = 1,
1740 : : .adrfam = SPDK_NVMF_ADRFAM_IPV4,
1741 : : .traddr = "192.168.1.78",
1742 : : .trsvcid = "23",
1743 : : };
1744 : 4 : struct spdk_nvme_ctrlr_opts opts = {
1745 : : .admin_queue_size = 2,
1746 : : .src_addr = "192.168.1.77",
1747 : : .src_svcid = "23",
1748 : : };
1749 : :
1750 : : /* Transmit ACK timeout value exceeds max, expected to pass and using max */
1751 : 4 : opts.transport_ack_timeout = NVME_TCP_CTRLR_MAX_TRANSPORT_ACK_TIMEOUT + 1;
1752 : 4 : MOCK_SET(spdk_sock_connect_ext, (struct spdk_sock *)0xDEADBEEF);
1753 : 4 : ctrlr = nvme_tcp_ctrlr_construct(&trid, &opts, NULL);
1754 : 4 : tctrlr = nvme_tcp_ctrlr(ctrlr);
1755 : 4 : tqpair = nvme_tcp_qpair(tctrlr->ctrlr.adminq);
1756 : :
1757 : 4 : CU_ASSERT(ctrlr != NULL);
1758 : 4 : CU_ASSERT(tctrlr != NULL);
1759 : 4 : CU_ASSERT(tqpair != NULL);
1760 : 4 : CU_ASSERT(ctrlr->opts.transport_ack_timeout == NVME_TCP_CTRLR_MAX_TRANSPORT_ACK_TIMEOUT);
1761 [ - + ]: 4 : CU_ASSERT(memcmp(&ctrlr->trid, &trid, sizeof(struct spdk_nvme_transport_id)) == 0);
1762 : 4 : CU_ASSERT(tqpair->num_entries == 1);
1763 : 4 : CU_ASSERT(TAILQ_EMPTY(&tqpair->send_queue));
1764 : 4 : CU_ASSERT(TAILQ_EMPTY(&tqpair->outstanding_reqs));
1765 : 4 : CU_ASSERT(!TAILQ_EMPTY(&tqpair->free_reqs));
1766 : 4 : CU_ASSERT(TAILQ_FIRST(&tqpair->free_reqs) == &tqpair->tcp_reqs[0]);
1767 : 4 : CU_ASSERT(TAILQ_FIRST(&tqpair->free_reqs)->cid == 0);
1768 : 4 : CU_ASSERT(TAILQ_FIRST(&tqpair->free_reqs)->tqpair == tqpair);
1769 : 4 : CU_ASSERT(TAILQ_FIRST(&tqpair->free_reqs)->pdu == &tqpair->send_pdus[0]);
1770 : 4 : CU_ASSERT(tqpair->send_pdu == &tqpair->send_pdus[1]);
1771 : 4 : CU_ASSERT(tqpair->recv_pdu == &tqpair->send_pdus[2]);
1772 : :
1773 : 4 : free(tqpair->tcp_reqs);
1774 : 4 : spdk_free(tqpair->send_pdus);
1775 : 4 : free(tqpair);
1776 : 4 : free(tctrlr);
1777 : :
1778 : : /* The Admin queue size is less than the minimum required size, expected to create Admin qpair failed */
1779 : 4 : opts.admin_queue_size = 1;
1780 : 4 : ctrlr = nvme_tcp_ctrlr_construct(&trid, &opts, NULL);
1781 : 4 : CU_ASSERT(ctrlr == NULL);
1782 : :
1783 : : /* Unhandled ADRFAM, expected to create Admin qpair failed */
1784 : 4 : opts.admin_queue_size = 2;
1785 : 4 : trid.adrfam = SPDK_NVMF_ADRFAM_INTRA_HOST;
1786 : 4 : ctrlr = nvme_tcp_ctrlr_construct(&trid, &opts, NULL);
1787 : 4 : CU_ASSERT(ctrlr == NULL);
1788 : :
1789 : : /* Error connecting socket, expected to create Admin qpair failed */
1790 : 4 : trid.adrfam = SPDK_NVMF_ADRFAM_IPV4;
1791 : 4 : MOCK_SET(spdk_sock_connect_ext, NULL);
1792 : 4 : ctrlr = nvme_tcp_ctrlr_construct(&trid, &opts, NULL);
1793 : 4 : CU_ASSERT(ctrlr == NULL);
1794 : :
1795 : 4 : MOCK_CLEAR(spdk_sock_connect_ext);
1796 : 4 : }
1797 : :
1798 : : static void
1799 : 4 : test_nvme_tcp_qpair_submit_request(void)
1800 : : {
1801 : 4 : int rc = 0;
1802 : 4 : struct nvme_tcp_ctrlr *tctrlr = NULL;
1803 : 4 : struct nvme_tcp_qpair *tqpair = NULL;
1804 : 4 : struct spdk_nvme_ctrlr *ctrlr = NULL;
1805 : 4 : struct nvme_tcp_req *tcp_req = NULL;
1806 : 4 : struct nvme_request req = {};
1807 : 4 : struct nvme_tcp_ut_bdev_io bio = {};
1808 : 4 : struct spdk_nvme_tcp_stat stat = {};
1809 : 4 : struct spdk_nvme_transport_id trid = {
1810 : : .trtype = SPDK_NVME_TRANSPORT_TCP,
1811 : : .priority = 1,
1812 : : .adrfam = SPDK_NVMF_ADRFAM_IPV4,
1813 : : .traddr = "192.168.1.78",
1814 : : .trsvcid = "23",
1815 : : };
1816 : 4 : struct spdk_nvme_ctrlr_opts opts = {
1817 : : .admin_queue_size = 2,
1818 : : .src_addr = "192.168.1.77",
1819 : : .src_svcid = "23",
1820 : : };
1821 : :
1822 : : /* Construct TCP Controller */
1823 : 4 : opts.transport_ack_timeout = NVME_TCP_CTRLR_MAX_TRANSPORT_ACK_TIMEOUT + 1;
1824 : 4 : MOCK_SET(spdk_sock_connect_ext, (struct spdk_sock *)0xDCADBEEF);
1825 : :
1826 : 4 : ctrlr = nvme_tcp_ctrlr_construct(&trid, &opts, NULL);
1827 : 4 : CU_ASSERT(ctrlr != NULL);
1828 : 4 : tctrlr = nvme_tcp_ctrlr(ctrlr);
1829 : 4 : tqpair = nvme_tcp_qpair(tctrlr->ctrlr.adminq);
1830 : 4 : tcp_req = TAILQ_FIRST(&tqpair->free_reqs);
1831 : 4 : CU_ASSERT(tctrlr != NULL);
1832 : 4 : CU_ASSERT(tqpair != NULL);
1833 : 4 : CU_ASSERT(tcp_req->pdu != NULL);
1834 : 4 : CU_ASSERT(tqpair->num_entries == 1);
1835 : :
1836 : 4 : tqpair->stats = &stat;
1837 : 4 : req.qpair = &tqpair->qpair;
1838 : 4 : req.cmd.opc = SPDK_NVME_DATA_HOST_TO_CONTROLLER;
1839 : 4 : req.payload = NVME_PAYLOAD_SGL(nvme_tcp_ut_reset_sgl, nvme_tcp_ut_next_sge, &bio, NULL);
1840 : :
1841 : : /* Failed to construct request, because not enough max_sges */
1842 : 4 : req.qpair->ctrlr->max_sges = 1;
1843 : 4 : req.payload_size = 2048;
1844 : 4 : req.payload_offset = 0;
1845 : 4 : bio.iovpos = 0;
1846 : 4 : bio.iovs[0].iov_len = 1024;
1847 : 4 : bio.iovs[1].iov_len = 1024;
1848 : 4 : bio.iovs[0].iov_base = (void *)0xDEADBEEF;
1849 : 4 : bio.iovs[1].iov_base = (void *)0xDFADBEEF;
1850 : :
1851 : 4 : rc = nvme_tcp_qpair_submit_request(tctrlr->ctrlr.adminq, &req);
1852 : 4 : CU_ASSERT(rc == -1);
1853 : 4 : CU_ASSERT(tcp_req == TAILQ_FIRST(&tqpair->free_reqs));
1854 : 4 : CU_ASSERT(tcp_req->state == NVME_TCP_REQ_FREE);
1855 : :
1856 : : /* Multiple SGL, expected to pass */
1857 : 4 : req.qpair->ctrlr->max_sges = 2;
1858 : :
1859 : 4 : rc = nvme_tcp_qpair_submit_request(tctrlr->ctrlr.adminq, &req);
1860 : 4 : CU_ASSERT(rc == 0);
1861 : 4 : CU_ASSERT(tcp_req->state == NVME_TCP_REQ_ACTIVE);
1862 : 4 : CU_ASSERT(NULL == TAILQ_FIRST(&tqpair->free_reqs));
1863 : 4 : CU_ASSERT(tcp_req == TAILQ_FIRST(&tqpair->outstanding_reqs));
1864 : 4 : CU_ASSERT(tcp_req->expected_datao == 0);
1865 : 4 : CU_ASSERT(tcp_req->req == &req);
1866 : 4 : CU_ASSERT(tcp_req->r2tl_remain == 0);
1867 : 4 : CU_ASSERT(tcp_req->r2tl_remain_next == 0);
1868 : 4 : CU_ASSERT(tcp_req->active_r2ts == 0);
1869 : 4 : CU_ASSERT(tcp_req->iovcnt == 2);
1870 : 4 : CU_ASSERT(tcp_req->ordering.raw == 0);
1871 : 4 : CU_ASSERT(req.cmd.cid == tcp_req->cid);
1872 : 4 : CU_ASSERT(req.cmd.psdt == SPDK_NVME_PSDT_SGL_MPTR_CONTIG);
1873 : 4 : CU_ASSERT(req.cmd.dptr.sgl1.unkeyed.type == SPDK_NVME_SGL_TYPE_DATA_BLOCK);
1874 : 4 : CU_ASSERT(req.cmd.dptr.sgl1.unkeyed.subtype == SPDK_NVME_SGL_SUBTYPE_OFFSET);
1875 : 4 : CU_ASSERT(req.cmd.dptr.sgl1.unkeyed.length == req.payload_size);
1876 : 4 : CU_ASSERT(req.cmd.dptr.sgl1.address == 0);
1877 [ - + ]: 4 : CU_ASSERT(tcp_req->in_capsule_data == true);
1878 : 4 : CU_ASSERT(tcp_req->iov[0].iov_len == bio.iovs[0].iov_len);
1879 : 4 : CU_ASSERT(tcp_req->iov[1].iov_len == bio.iovs[1].iov_len);
1880 : 4 : CU_ASSERT(tcp_req->iov[0].iov_base == bio.iovs[0].iov_base);
1881 : 4 : CU_ASSERT(tcp_req->iov[1].iov_base == bio.iovs[1].iov_base);
1882 : 4 : CU_ASSERT(tcp_req->pdu->hdr.capsule_cmd.common.pdu_type == SPDK_NVME_TCP_PDU_TYPE_CAPSULE_CMD);
1883 : 4 : CU_ASSERT((tcp_req->pdu->hdr.capsule_cmd.common.flags & SPDK_NVME_TCP_CH_FLAGS_HDGSTF) == 0);
1884 : 4 : CU_ASSERT((tcp_req->pdu->hdr.capsule_cmd.common.flags & SPDK_NVME_TCP_CH_FLAGS_DDGSTF) == 0);
1885 : 4 : CU_ASSERT(tcp_req->datao == 0);
1886 : 4 : CU_ASSERT(tcp_req->pdu->data_len == req.payload_size);
1887 : 4 : CU_ASSERT(tcp_req->pdu->hdr.capsule_cmd.common.pdo == sizeof(struct spdk_nvme_tcp_cmd));
1888 : 4 : CU_ASSERT(tcp_req->pdu->hdr.capsule_cmd.common.plen == sizeof(struct spdk_nvme_tcp_cmd) +
1889 : : req.payload_size);
1890 : 4 : CU_ASSERT(tcp_req->pdu->data_iov[0].iov_base == (void *)0xDEADBEEF);
1891 : 4 : CU_ASSERT(tcp_req->pdu->data_iov[0].iov_len == 1024);
1892 : 4 : CU_ASSERT(tcp_req->pdu->data_iov[1].iov_base == (void *)0xDFADBEEF);
1893 : 4 : CU_ASSERT(tcp_req->pdu->data_iov[1].iov_len == 1024);
1894 : 4 : CU_ASSERT(tcp_req->pdu->data_iovcnt == 2);
1895 : :
1896 : : /* Request resource limit reached, expected to return -EAGAIN */
1897 [ - + ]: 4 : memset(&req, 0x00, sizeof(struct nvme_request));
1898 : 4 : CU_ASSERT(tqpair->stats->queued_requests == 0);
1899 : :
1900 : 4 : rc = nvme_tcp_qpair_submit_request(tctrlr->ctrlr.adminq, &req);
1901 : 4 : CU_ASSERT(rc == -EAGAIN);
1902 : 4 : CU_ASSERT(tqpair->stats->queued_requests == 1);
1903 : :
1904 : 4 : MOCK_CLEAR(spdk_sock_connect_ext);
1905 : 4 : free(tqpair->tcp_reqs);
1906 : 4 : spdk_free(tqpair->send_pdus);
1907 : 4 : free(tqpair);
1908 : 4 : free(tctrlr);
1909 : 4 : }
1910 : :
1911 : : int
1912 : 4 : main(int argc, char **argv)
1913 : : {
1914 : 4 : CU_pSuite suite = NULL;
1915 : : unsigned int num_failures;
1916 : :
1917 : 4 : CU_initialize_registry();
1918 : :
1919 : 4 : suite = CU_add_suite("nvme_tcp", NULL, NULL);
1920 : 4 : CU_ADD_TEST(suite, test_nvme_tcp_pdu_set_data_buf);
1921 : 4 : CU_ADD_TEST(suite, test_nvme_tcp_build_iovs);
1922 : 4 : CU_ADD_TEST(suite, test_nvme_tcp_build_sgl_request);
1923 : 4 : CU_ADD_TEST(suite, test_nvme_tcp_pdu_set_data_buf_with_md);
1924 : 4 : CU_ADD_TEST(suite, test_nvme_tcp_build_iovs_with_md);
1925 : 4 : CU_ADD_TEST(suite, test_nvme_tcp_req_complete_safe);
1926 : 4 : CU_ADD_TEST(suite, test_nvme_tcp_req_get);
1927 : 4 : CU_ADD_TEST(suite, test_nvme_tcp_req_init);
1928 : 4 : CU_ADD_TEST(suite, test_nvme_tcp_qpair_capsule_cmd_send);
1929 : 4 : CU_ADD_TEST(suite, test_nvme_tcp_qpair_write_pdu);
1930 : 4 : CU_ADD_TEST(suite, test_nvme_tcp_qpair_set_recv_state);
1931 : 4 : CU_ADD_TEST(suite, test_nvme_tcp_alloc_reqs);
1932 : 4 : CU_ADD_TEST(suite, test_nvme_tcp_qpair_send_h2c_term_req);
1933 : 4 : CU_ADD_TEST(suite, test_nvme_tcp_pdu_ch_handle);
1934 : 4 : CU_ADD_TEST(suite, test_nvme_tcp_qpair_connect_sock);
1935 : 4 : CU_ADD_TEST(suite, test_nvme_tcp_qpair_icreq_send);
1936 : 4 : CU_ADD_TEST(suite, test_nvme_tcp_c2h_payload_handle);
1937 : 4 : CU_ADD_TEST(suite, test_nvme_tcp_icresp_handle);
1938 : 4 : CU_ADD_TEST(suite, test_nvme_tcp_pdu_payload_handle);
1939 : 4 : CU_ADD_TEST(suite, test_nvme_tcp_capsule_resp_hdr_handle);
1940 : 4 : CU_ADD_TEST(suite, test_nvme_tcp_ctrlr_connect_qpair);
1941 : 4 : CU_ADD_TEST(suite, test_nvme_tcp_ctrlr_disconnect_qpair);
1942 : 4 : CU_ADD_TEST(suite, test_nvme_tcp_ctrlr_create_io_qpair);
1943 : 4 : CU_ADD_TEST(suite, test_nvme_tcp_ctrlr_delete_io_qpair);
1944 : 4 : CU_ADD_TEST(suite, test_nvme_tcp_poll_group_get_stats);
1945 : 4 : CU_ADD_TEST(suite, test_nvme_tcp_ctrlr_construct);
1946 : 4 : CU_ADD_TEST(suite, test_nvme_tcp_qpair_submit_request);
1947 : :
1948 : 4 : num_failures = spdk_ut_run_tests(argc, argv, NULL);
1949 : 4 : CU_cleanup_registry();
1950 : 4 : return num_failures;
1951 : : }
|