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