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