Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2018 Intel Corporation. All rights reserved.
3 : : * Copyright (c) 2020 Mellanox Technologies LTD. All rights reserved.
4 : : * Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
5 : : */
6 : :
7 : : #include "spdk/stdinc.h"
8 : : #include "spdk/util.h"
9 : :
10 : : #include "spdk_internal/cunit.h"
11 : :
12 : : #include "spdk_internal/sock.h"
13 : :
14 : : #include "sock/sock.c"
15 : : #include "sock/posix/posix.c"
16 : :
17 : : #include "spdk_internal/mock.h"
18 : : #include "common/lib/test_env.c"
19 : :
20 : : #include "unit/lib/json_mock.c"
21 : :
22 : : #define UT_IP "test_ip"
23 : : #define UT_PORT 1234
24 : :
25 : : bool g_read_data_called;
26 : : ssize_t g_bytes_read;
27 : : char g_buf[256];
28 : : struct spdk_sock *g_server_sock_read;
29 : : int g_ut_accept_count;
30 : : struct spdk_ut_sock *g_ut_listen_sock;
31 : : struct spdk_ut_sock *g_ut_client_sock;
32 : :
33 : : struct spdk_ut_sock {
34 : : struct spdk_sock base;
35 : : struct spdk_ut_sock *peer;
36 : : size_t bytes_avail;
37 : : char buf[256];
38 : : };
39 : :
40 : : struct spdk_ut_sock_group_impl {
41 : : struct spdk_sock_group_impl base;
42 : : struct spdk_ut_sock *sock;
43 : : };
44 : :
45 : : #define __ut_sock(sock) (struct spdk_ut_sock *)sock
46 : : #define __ut_group(group) (struct spdk_ut_sock_group_impl *)group
47 : :
48 : : static int
49 : 0 : spdk_ut_sock_getaddr(struct spdk_sock *_sock, char *saddr, int slen, uint16_t *sport,
50 : : char *caddr, int clen, uint16_t *cport)
51 : : {
52 : 0 : return 0;
53 : : }
54 : :
55 : : static struct spdk_sock *
56 : 12 : spdk_ut_sock_listen(const char *ip, int port, struct spdk_sock_opts *opts)
57 : : {
58 : : struct spdk_ut_sock *sock;
59 : :
60 [ + + + + : 12 : if (strcmp(ip, UT_IP) || port != UT_PORT) {
- + ]
61 : 0 : return NULL;
62 : : }
63 : :
64 : 12 : CU_ASSERT(g_ut_listen_sock == NULL);
65 : :
66 : 12 : sock = calloc(1, sizeof(*sock));
67 [ - + ]: 12 : SPDK_CU_ASSERT_FATAL(sock != NULL);
68 : 12 : g_ut_listen_sock = sock;
69 : :
70 : 12 : return &sock->base;
71 : : }
72 : :
73 : : static struct spdk_sock *
74 : 12 : spdk_ut_sock_connect(const char *ip, int port, struct spdk_sock_opts *opts)
75 : : {
76 : : struct spdk_ut_sock *sock;
77 : :
78 [ + + + + : 12 : if (strcmp(ip, UT_IP) || port != UT_PORT) {
- + ]
79 : 0 : return NULL;
80 : : }
81 : :
82 : 12 : sock = calloc(1, sizeof(*sock));
83 [ - + ]: 12 : SPDK_CU_ASSERT_FATAL(sock != NULL);
84 : 12 : g_ut_accept_count++;
85 : 12 : CU_ASSERT(g_ut_client_sock == NULL);
86 : 12 : g_ut_client_sock = sock;
87 : :
88 : 12 : return &sock->base;
89 : : }
90 : :
91 : : static struct spdk_sock *
92 : 24 : spdk_ut_sock_accept(struct spdk_sock *_sock)
93 : : {
94 : 24 : struct spdk_ut_sock *sock = __ut_sock(_sock);
95 : : struct spdk_ut_sock *new_sock;
96 : :
97 : 24 : CU_ASSERT(sock == g_ut_listen_sock);
98 : :
99 [ + + ]: 24 : if (g_ut_accept_count == 0) {
100 : 12 : errno = EAGAIN;
101 : 12 : return NULL;
102 : : }
103 : :
104 : 12 : g_ut_accept_count--;
105 : 12 : new_sock = calloc(1, sizeof(*sock));
106 [ - + ]: 12 : if (new_sock == NULL) {
107 : 0 : SPDK_ERRLOG("sock allocation failed\n");
108 : 0 : return NULL;
109 : : }
110 : :
111 [ - + ]: 12 : SPDK_CU_ASSERT_FATAL(g_ut_client_sock != NULL);
112 : 12 : g_ut_client_sock->peer = new_sock;
113 : 12 : new_sock->peer = g_ut_client_sock;
114 : :
115 : 12 : return &new_sock->base;
116 : : }
117 : :
118 : : static int
119 : 36 : spdk_ut_sock_close(struct spdk_sock *_sock)
120 : : {
121 : 36 : struct spdk_ut_sock *sock = __ut_sock(_sock);
122 : :
123 [ + + ]: 36 : if (sock == g_ut_listen_sock) {
124 : 12 : g_ut_listen_sock = NULL;
125 : : }
126 [ + + ]: 36 : if (sock == g_ut_client_sock) {
127 : 12 : g_ut_client_sock = NULL;
128 : : }
129 : :
130 [ + + ]: 36 : if (sock->peer != NULL) {
131 : 12 : sock->peer->peer = NULL;
132 : : }
133 : :
134 : 36 : free(_sock);
135 : :
136 : 36 : return 0;
137 : : }
138 : :
139 : : static ssize_t
140 : 18 : spdk_ut_sock_recv(struct spdk_sock *_sock, void *buf, size_t len)
141 : : {
142 : 18 : struct spdk_ut_sock *sock = __ut_sock(_sock);
143 : 15 : char tmp[256];
144 : :
145 : 18 : len = spdk_min(len, sock->bytes_avail);
146 : :
147 [ - + ]: 18 : if (len == 0) {
148 : 0 : errno = EAGAIN;
149 : 0 : return -1;
150 : : }
151 : :
152 [ - + - + ]: 18 : memcpy(buf, sock->buf, len);
153 [ - + ]: 18 : memcpy(tmp, &sock->buf[len], sock->bytes_avail - len);
154 [ - + ]: 18 : memcpy(sock->buf, tmp, sock->bytes_avail - len);
155 : 18 : sock->bytes_avail -= len;
156 : :
157 : 18 : return len;
158 : : }
159 : :
160 : : static ssize_t
161 : 12 : spdk_ut_sock_readv(struct spdk_sock *_sock, struct iovec *iov, int iovcnt)
162 : : {
163 : 12 : struct spdk_ut_sock *sock = __ut_sock(_sock);
164 : : size_t len;
165 : 10 : char tmp[256];
166 : :
167 : : /* Test implementation only supports single iov for now. */
168 : 12 : CU_ASSERT(iovcnt == 1);
169 : :
170 : 12 : len = spdk_min(iov[0].iov_len, sock->bytes_avail);
171 : :
172 [ - + ]: 12 : if (len == 0) {
173 : 0 : errno = EAGAIN;
174 : 0 : return -1;
175 : : }
176 : :
177 [ - + - + ]: 12 : memcpy(iov[0].iov_base, sock->buf, len);
178 [ - + ]: 12 : memcpy(tmp, &sock->buf[len], sock->bytes_avail - len);
179 [ - + ]: 12 : memcpy(sock->buf, tmp, sock->bytes_avail - len);
180 : 12 : sock->bytes_avail -= len;
181 : :
182 : 12 : return len;
183 : : }
184 : :
185 : : static ssize_t
186 : 18 : spdk_ut_sock_writev(struct spdk_sock *_sock, struct iovec *iov, int iovcnt)
187 : : {
188 : 18 : struct spdk_ut_sock *sock = __ut_sock(_sock);
189 : : struct spdk_ut_sock *peer;
190 : :
191 [ - + ]: 18 : SPDK_CU_ASSERT_FATAL(sock->peer != NULL);
192 : 18 : peer = sock->peer;
193 : :
194 : : /* Test implementation only supports single iov for now. */
195 : 18 : CU_ASSERT(iovcnt == 1);
196 : :
197 [ - + - + ]: 18 : memcpy(&peer->buf[peer->bytes_avail], iov[0].iov_base, iov[0].iov_len);
198 : 18 : peer->bytes_avail += iov[0].iov_len;
199 : :
200 : 18 : return iov[0].iov_len;
201 : : }
202 : :
203 : : static int
204 : 0 : spdk_ut_sock_flush(struct spdk_sock *sock)
205 : : {
206 : 0 : return -1;
207 : : }
208 : :
209 : : static int
210 : 6 : spdk_ut_sock_set_recvlowat(struct spdk_sock *_sock, int nbytes)
211 : : {
212 : 6 : return 0;
213 : : }
214 : :
215 : : static int
216 : 6 : spdk_ut_sock_set_recvbuf(struct spdk_sock *_sock, int sz)
217 : : {
218 : 6 : return 0;
219 : : }
220 : :
221 : : static int
222 : 6 : spdk_ut_sock_set_sendbuf(struct spdk_sock *_sock, int sz)
223 : : {
224 : 6 : return 0;
225 : : }
226 : :
227 : : static bool
228 : 6 : spdk_ut_sock_is_ipv6(struct spdk_sock *_sock)
229 : : {
230 : 6 : return false;
231 : : }
232 : :
233 : : static bool
234 : 6 : spdk_ut_sock_is_ipv4(struct spdk_sock *_sock)
235 : : {
236 : 6 : return true;
237 : : }
238 : :
239 : : static bool
240 : 18 : spdk_ut_sock_is_connected(struct spdk_sock *_sock)
241 : : {
242 : 18 : struct spdk_ut_sock *sock = __ut_sock(_sock);
243 : :
244 : 18 : return (sock->peer != NULL);
245 : : }
246 : :
247 : : static struct spdk_sock_group_impl *
248 : 6 : spdk_ut_sock_group_impl_get_optimal(struct spdk_sock *_sock, struct spdk_sock_group_impl *hint)
249 : : {
250 : 6 : return NULL;
251 : : }
252 : :
253 : : static struct spdk_sock_group_impl *
254 : 48 : spdk_ut_sock_group_impl_create(void)
255 : : {
256 : : struct spdk_ut_sock_group_impl *group_impl;
257 : :
258 : 48 : group_impl = calloc(1, sizeof(*group_impl));
259 [ - + ]: 48 : SPDK_CU_ASSERT_FATAL(group_impl != NULL);
260 : :
261 : 48 : return &group_impl->base;
262 : : }
263 : :
264 : : static int
265 : 6 : spdk_ut_sock_group_impl_add_sock(struct spdk_sock_group_impl *_group, struct spdk_sock *_sock)
266 : : {
267 : 6 : struct spdk_ut_sock_group_impl *group = __ut_group(_group);
268 : 6 : struct spdk_ut_sock *sock = __ut_sock(_sock);
269 : :
270 : 6 : group->sock = sock;
271 : :
272 : 6 : return 0;
273 : : }
274 : :
275 : : static int
276 : 6 : spdk_ut_sock_group_impl_remove_sock(struct spdk_sock_group_impl *_group, struct spdk_sock *_sock)
277 : : {
278 : 6 : struct spdk_ut_sock_group_impl *group = __ut_group(_group);
279 : 6 : struct spdk_ut_sock *sock = __ut_sock(_sock);
280 : :
281 : 6 : CU_ASSERT(group->sock == sock);
282 : 6 : group->sock = NULL;
283 : :
284 : 6 : return 0;
285 : : }
286 : :
287 : : static int
288 : 12 : spdk_ut_sock_group_impl_poll(struct spdk_sock_group_impl *_group, int max_events,
289 : : struct spdk_sock **socks)
290 : : {
291 : 12 : struct spdk_ut_sock_group_impl *group = __ut_group(_group);
292 : :
293 [ + - + + ]: 12 : if (group->sock != NULL && group->sock->bytes_avail > 0) {
294 : 6 : socks[0] = &group->sock->base;
295 : 6 : return 1;
296 : : }
297 : :
298 : 6 : return 0;
299 : : }
300 : :
301 : : static int
302 : 48 : spdk_ut_sock_group_impl_close(struct spdk_sock_group_impl *_group)
303 : : {
304 : 48 : struct spdk_ut_sock_group_impl *group = __ut_group(_group);
305 : :
306 : 48 : CU_ASSERT(group->sock == NULL);
307 : 48 : free(_group);
308 : :
309 : 48 : return 0;
310 : : }
311 : :
312 : : static struct spdk_net_impl g_ut_net_impl = {
313 : : .name = "ut",
314 : : .getaddr = spdk_ut_sock_getaddr,
315 : : .connect = spdk_ut_sock_connect,
316 : : .listen = spdk_ut_sock_listen,
317 : : .accept = spdk_ut_sock_accept,
318 : : .close = spdk_ut_sock_close,
319 : : .recv = spdk_ut_sock_recv,
320 : : .readv = spdk_ut_sock_readv,
321 : : .writev = spdk_ut_sock_writev,
322 : : .flush = spdk_ut_sock_flush,
323 : : .set_recvlowat = spdk_ut_sock_set_recvlowat,
324 : : .set_recvbuf = spdk_ut_sock_set_recvbuf,
325 : : .set_sendbuf = spdk_ut_sock_set_sendbuf,
326 : : .is_ipv6 = spdk_ut_sock_is_ipv6,
327 : : .is_ipv4 = spdk_ut_sock_is_ipv4,
328 : : .is_connected = spdk_ut_sock_is_connected,
329 : : .group_impl_get_optimal = spdk_ut_sock_group_impl_get_optimal,
330 : : .group_impl_create = spdk_ut_sock_group_impl_create,
331 : : .group_impl_add_sock = spdk_ut_sock_group_impl_add_sock,
332 : : .group_impl_remove_sock = spdk_ut_sock_group_impl_remove_sock,
333 : : .group_impl_poll = spdk_ut_sock_group_impl_poll,
334 : : .group_impl_close = spdk_ut_sock_group_impl_close,
335 : : };
336 : :
337 : 6 : SPDK_NET_IMPL_REGISTER(ut, &g_ut_net_impl, DEFAULT_SOCK_PRIORITY + 2);
338 : :
339 : : static void
340 : 12 : _sock(const char *ip, int port, char *impl_name)
341 : : {
342 : 10 : struct spdk_sock *listen_sock;
343 : 10 : struct spdk_sock *server_sock;
344 : 10 : struct spdk_sock *client_sock;
345 : 12 : char *test_string = "abcdef";
346 : 10 : char buffer[64];
347 : : ssize_t bytes_read, bytes_written;
348 : 10 : struct iovec iov;
349 : : int nbytes;
350 : : int rc;
351 : :
352 : 12 : listen_sock = spdk_sock_listen(ip, port, impl_name);
353 [ - + ]: 12 : SPDK_CU_ASSERT_FATAL(listen_sock != NULL);
354 : :
355 : 12 : server_sock = spdk_sock_accept(listen_sock);
356 : 12 : CU_ASSERT(server_sock == NULL);
357 [ - + - - ]: 12 : CU_ASSERT(errno == EAGAIN || errno == EWOULDBLOCK);
358 : :
359 : 12 : client_sock = spdk_sock_connect(ip, port, impl_name);
360 [ - + ]: 12 : SPDK_CU_ASSERT_FATAL(client_sock != NULL);
361 : :
362 : : /*
363 : : * Delay a bit here before checking if server socket is
364 : : * ready.
365 : : */
366 : 12 : usleep(1000);
367 : :
368 : 12 : server_sock = spdk_sock_accept(listen_sock);
369 [ - + ]: 12 : SPDK_CU_ASSERT_FATAL(server_sock != NULL);
370 : 12 : CU_ASSERT(spdk_sock_is_connected(client_sock) == true);
371 : 12 : CU_ASSERT(spdk_sock_is_connected(server_sock) == true);
372 : :
373 : : /* Test spdk_sock_set_default_impl */
374 : 12 : rc = spdk_sock_set_default_impl(impl_name);
375 : 12 : CU_ASSERT(rc == 0);
376 : 12 : CU_ASSERT(g_default_impl != NULL);
377 : :
378 : : /* Test spdk_sock_set_default_impl when name is NULL */
379 : 12 : rc = spdk_sock_set_default_impl(NULL);
380 : 12 : CU_ASSERT(rc == -1);
381 : 12 : CU_ASSERT(errno == EINVAL);
382 : :
383 : : /* Test spdk_sock_is _ipv6 */
384 : 12 : CU_ASSERT(!spdk_sock_is_ipv6(client_sock));
385 : :
386 : : /* Test spdk_sock_is _ipv4 */
387 : 12 : CU_ASSERT(spdk_sock_is_ipv4(client_sock));
388 : :
389 : 12 : nbytes = 2048;
390 : :
391 : : /* Test spdk_sock_set_recvlowat */
392 : 12 : rc = spdk_sock_set_recvlowat(client_sock, nbytes);
393 : 12 : CU_ASSERT(rc == 0);
394 : :
395 : : /* Test spdk_sock_set_recvbuf */
396 : 12 : rc = spdk_sock_set_recvbuf(client_sock, nbytes);
397 : 12 : CU_ASSERT(rc == 0);
398 : :
399 : : /* Test spdk_sock_set_sendbuf */
400 : 12 : rc = spdk_sock_set_sendbuf(client_sock, nbytes);
401 : 12 : CU_ASSERT(rc == 0);
402 : :
403 : : /* Test spdk_sock_recv */
404 : 12 : iov.iov_base = test_string;
405 : 12 : iov.iov_len = 7;
406 : 12 : bytes_written = spdk_sock_writev(client_sock, &iov, 1);
407 : 12 : CU_ASSERT(bytes_written == 7);
408 : :
409 : 12 : usleep(1000);
410 : :
411 : 12 : bytes_read = spdk_sock_recv(server_sock, buffer, 2);
412 : 12 : CU_ASSERT(bytes_read == 2);
413 : :
414 : 12 : usleep(1000);
415 : :
416 : 12 : bytes_read += spdk_sock_recv(server_sock, buffer + 2, 5);
417 : 12 : CU_ASSERT(bytes_read == 7);
418 : :
419 [ - + ]: 12 : CU_ASSERT(strncmp(test_string, buffer, 7) == 0);
420 : :
421 : : /* Test spdk_sock_readv */
422 : 12 : iov.iov_base = test_string;
423 : 12 : iov.iov_len = 7;
424 : 12 : bytes_written = spdk_sock_writev(client_sock, &iov, 1);
425 : 12 : CU_ASSERT(bytes_written == 7);
426 : :
427 : 12 : usleep(1000);
428 : :
429 : 12 : iov.iov_base = buffer;
430 : 12 : iov.iov_len = 2;
431 : 12 : bytes_read = spdk_sock_readv(server_sock, &iov, 1);
432 : 12 : CU_ASSERT(bytes_read == 2);
433 : :
434 : 12 : usleep(1000);
435 : :
436 : 12 : iov.iov_base = buffer + 2;
437 : 12 : iov.iov_len = 5;
438 : 12 : bytes_read += spdk_sock_readv(server_sock, &iov, 1);
439 : 12 : CU_ASSERT(bytes_read == 7);
440 : :
441 : 12 : usleep(1000);
442 : :
443 [ - + ]: 12 : CU_ASSERT(strncmp(test_string, buffer, 7) == 0);
444 : :
445 : 12 : rc = spdk_sock_close(&client_sock);
446 : 12 : CU_ASSERT(client_sock == NULL);
447 : 12 : CU_ASSERT(rc == 0);
448 : :
449 : : #if defined(__FreeBSD__)
450 : : /* On FreeBSD, it takes a small amount of time for a close to propagate to the
451 : : * other side, even in loopback. Introduce a small sleep. */
452 : : sleep(1);
453 : : #endif
454 : 12 : CU_ASSERT(spdk_sock_is_connected(server_sock) == false);
455 : :
456 : 12 : rc = spdk_sock_close(&server_sock);
457 : 12 : CU_ASSERT(server_sock == NULL);
458 : 12 : CU_ASSERT(rc == 0);
459 : :
460 : 12 : rc = spdk_sock_close(&listen_sock);
461 : 12 : CU_ASSERT(listen_sock == NULL);
462 : 12 : CU_ASSERT(rc == 0);
463 : 12 : }
464 : :
465 : : static void
466 : 6 : posix_sock(void)
467 : : {
468 : 6 : _sock("127.0.0.1", UT_PORT, "posix");
469 : 6 : }
470 : :
471 : : static void
472 : 6 : ut_sock(void)
473 : : {
474 : 6 : _sock(UT_IP, UT_PORT, "ut");
475 : 6 : }
476 : :
477 : : static void
478 : 12 : read_data(void *cb_arg, struct spdk_sock_group *group, struct spdk_sock *sock)
479 : : {
480 : 12 : struct spdk_sock *server_sock = cb_arg;
481 : :
482 : 12 : CU_ASSERT(server_sock == sock);
483 : :
484 : 12 : g_read_data_called = true;
485 : 12 : g_bytes_read += spdk_sock_recv(server_sock, g_buf + g_bytes_read, sizeof(g_buf) - g_bytes_read);
486 : 12 : }
487 : :
488 : : static void
489 : 12 : _sock_group(const char *ip, int port, char *impl_name)
490 : : {
491 : 10 : struct spdk_sock_group *group;
492 : 10 : struct spdk_sock_group *hint;
493 : 10 : struct spdk_sock *listen_sock;
494 : 10 : struct spdk_sock *server_sock;
495 : 10 : struct spdk_sock *client_sock;
496 : 12 : char *test_string = "abcdef";
497 : : ssize_t bytes_written;
498 : 10 : struct iovec iov;
499 : : int rc;
500 : :
501 : 12 : listen_sock = spdk_sock_listen(ip, port, impl_name);
502 [ - + ]: 12 : SPDK_CU_ASSERT_FATAL(listen_sock != NULL);
503 : :
504 : 12 : server_sock = spdk_sock_accept(listen_sock);
505 : 12 : CU_ASSERT(server_sock == NULL);
506 [ - + - - ]: 12 : CU_ASSERT(errno == EAGAIN || errno == EWOULDBLOCK);
507 : :
508 : 12 : client_sock = spdk_sock_connect(ip, port, impl_name);
509 [ - + ]: 12 : SPDK_CU_ASSERT_FATAL(client_sock != NULL);
510 : :
511 : 12 : usleep(1000);
512 : :
513 : 12 : server_sock = spdk_sock_accept(listen_sock);
514 [ - + ]: 12 : SPDK_CU_ASSERT_FATAL(server_sock != NULL);
515 : :
516 : 12 : group = spdk_sock_group_create(NULL);
517 [ - + ]: 12 : SPDK_CU_ASSERT_FATAL(group != NULL);
518 : :
519 : 12 : hint = spdk_sock_group_create(NULL);
520 [ - + ]: 12 : SPDK_CU_ASSERT_FATAL(hint != NULL);
521 : :
522 : : /* pass null cb_fn */
523 : 12 : rc = spdk_sock_group_add_sock(group, server_sock, NULL, NULL);
524 : 12 : CU_ASSERT(rc == -1);
525 : 12 : CU_ASSERT(errno == EINVAL);
526 : :
527 : 12 : rc = spdk_sock_group_add_sock(group, server_sock, read_data, server_sock);
528 : 12 : CU_ASSERT(rc == 0);
529 : :
530 : : /* try adding sock a second time */
531 : 12 : rc = spdk_sock_group_add_sock(group, server_sock, read_data, server_sock);
532 : 12 : CU_ASSERT(rc == -1);
533 : 12 : CU_ASSERT(errno == EINVAL);
534 : :
535 : 12 : g_read_data_called = false;
536 : 12 : g_bytes_read = 0;
537 : 12 : rc = spdk_sock_group_poll(group);
538 : :
539 : 12 : CU_ASSERT(rc == 0);
540 [ - + ]: 12 : CU_ASSERT(g_read_data_called == false);
541 : :
542 : 12 : iov.iov_base = test_string;
543 : 12 : iov.iov_len = 7;
544 : 12 : bytes_written = spdk_sock_writev(client_sock, &iov, 1);
545 : 12 : CU_ASSERT(bytes_written == 7);
546 : :
547 : 12 : usleep(1000);
548 : :
549 : 12 : g_read_data_called = false;
550 : 12 : g_bytes_read = 0;
551 : 12 : rc = spdk_sock_group_poll(group);
552 : :
553 : 12 : CU_ASSERT(rc == 1);
554 [ - + ]: 12 : CU_ASSERT(g_read_data_called == true);
555 : 12 : CU_ASSERT(g_bytes_read == 7);
556 : :
557 [ - + ]: 12 : CU_ASSERT(strncmp(test_string, g_buf, 7) == 0);
558 : :
559 : 12 : rc = spdk_sock_close(&client_sock);
560 : 12 : CU_ASSERT(client_sock == NULL);
561 : 12 : CU_ASSERT(rc == 0);
562 : :
563 : : /* Test get_optimal_sock_group */
564 : 12 : rc = spdk_sock_get_optimal_sock_group(server_sock, &group, hint);
565 : 12 : CU_ASSERT(rc == 0);
566 : :
567 : : /* Try to close sock_group while it still has sockets. */
568 : 12 : rc = spdk_sock_group_close(&group);
569 : 12 : CU_ASSERT(rc == -1);
570 : 12 : CU_ASSERT(errno == EBUSY);
571 : :
572 : : /* Try to close sock while it is still part of a sock_group. */
573 : 12 : rc = spdk_sock_close(&server_sock);
574 : 12 : CU_ASSERT(rc == -1);
575 : 12 : CU_ASSERT(errno == EBUSY);
576 : :
577 : 12 : rc = spdk_sock_group_remove_sock(group, server_sock);
578 : 12 : CU_ASSERT(rc == 0);
579 : :
580 : 12 : rc = spdk_sock_group_close(&group);
581 : 12 : CU_ASSERT(group == NULL);
582 : 12 : CU_ASSERT(rc == 0);
583 : :
584 : 12 : rc = spdk_sock_group_close(&hint);
585 : 12 : CU_ASSERT(hint == NULL);
586 : 12 : CU_ASSERT(rc == 0);
587 : :
588 : 12 : rc = spdk_sock_close(&server_sock);
589 : 12 : CU_ASSERT(server_sock == NULL);
590 : 12 : CU_ASSERT(rc == 0);
591 : :
592 : 12 : rc = spdk_sock_close(&listen_sock);
593 : 12 : CU_ASSERT(listen_sock == NULL);
594 : 12 : CU_ASSERT(rc == 0);
595 : 12 : }
596 : :
597 : : static void
598 : 6 : posix_sock_group(void)
599 : : {
600 : 6 : _sock_group("127.0.0.1", UT_PORT, "posix");
601 : 6 : }
602 : :
603 : : static void
604 : 6 : ut_sock_group(void)
605 : : {
606 : 6 : _sock_group(UT_IP, UT_PORT, "ut");
607 : 6 : }
608 : :
609 : : static void
610 : 24 : read_data_fairness(void *cb_arg, struct spdk_sock_group *group, struct spdk_sock *sock)
611 : : {
612 : 24 : struct spdk_sock *server_sock = cb_arg;
613 : : ssize_t bytes_read;
614 : 20 : char buf[1];
615 : :
616 : 24 : CU_ASSERT(g_server_sock_read == NULL);
617 : 24 : CU_ASSERT(server_sock == sock);
618 : :
619 : 24 : g_server_sock_read = server_sock;
620 : 24 : bytes_read = spdk_sock_recv(server_sock, buf, 1);
621 : 24 : CU_ASSERT(bytes_read == 1);
622 : 24 : }
623 : :
624 : : static void
625 : 6 : posix_sock_group_fairness(void)
626 : : {
627 : 5 : struct spdk_sock_group *group;
628 : 5 : struct spdk_sock *listen_sock;
629 : 5 : struct spdk_sock *server_sock[3];
630 : 5 : struct spdk_sock *client_sock[3];
631 : 6 : char test_char = 'a';
632 : : ssize_t bytes_written;
633 : 5 : struct iovec iov;
634 : : int i, rc;
635 : :
636 : 6 : listen_sock = spdk_sock_listen("127.0.0.1", UT_PORT, "posix");
637 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(listen_sock != NULL);
638 : :
639 : 6 : group = spdk_sock_group_create(NULL);
640 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(group != NULL);
641 : :
642 [ + + ]: 24 : for (i = 0; i < 3; i++) {
643 : 18 : client_sock[i] = spdk_sock_connect("127.0.0.1", UT_PORT, "posix");
644 [ - + ]: 18 : SPDK_CU_ASSERT_FATAL(client_sock[i] != NULL);
645 : :
646 : 18 : usleep(1000);
647 : :
648 : 18 : server_sock[i] = spdk_sock_accept(listen_sock);
649 [ - + ]: 18 : SPDK_CU_ASSERT_FATAL(server_sock[i] != NULL);
650 : :
651 : 18 : rc = spdk_sock_group_add_sock(group, server_sock[i],
652 : 18 : read_data_fairness, server_sock[i]);
653 : 18 : CU_ASSERT(rc == 0);
654 : : }
655 : :
656 : 6 : iov.iov_base = &test_char;
657 : 6 : iov.iov_len = 1;
658 : :
659 [ + + ]: 24 : for (i = 0; i < 3; i++) {
660 : 18 : bytes_written = spdk_sock_writev(client_sock[i], &iov, 1);
661 : 18 : CU_ASSERT(bytes_written == 1);
662 : : }
663 : :
664 : 6 : usleep(1000);
665 : :
666 : : /*
667 : : * Poll for just one event - this should be server sock 0, since that
668 : : * is the peer of the first client sock that we wrote to.
669 : : */
670 : 6 : g_server_sock_read = NULL;
671 : 6 : rc = spdk_sock_group_poll_count(group, 1);
672 : 6 : CU_ASSERT(rc == 1);
673 : 6 : CU_ASSERT(g_server_sock_read == server_sock[0]);
674 : :
675 : : /*
676 : : * Now write another byte to client sock 0. We want to ensure that
677 : : * the sock group does not unfairly process the event for this sock
678 : : * before the socks that were written to earlier.
679 : : */
680 : 6 : bytes_written = spdk_sock_writev(client_sock[0], &iov, 1);
681 : 6 : CU_ASSERT(bytes_written == 1);
682 : :
683 : 6 : usleep(1000);
684 : :
685 : 6 : g_server_sock_read = NULL;
686 : 6 : rc = spdk_sock_group_poll_count(group, 1);
687 : 6 : CU_ASSERT(rc == 1);
688 : 6 : CU_ASSERT(g_server_sock_read == server_sock[1]);
689 : :
690 : 6 : g_server_sock_read = NULL;
691 : 6 : rc = spdk_sock_group_poll_count(group, 1);
692 : 6 : CU_ASSERT(rc == 1);
693 : 6 : CU_ASSERT(g_server_sock_read == server_sock[2]);
694 : :
695 : 6 : g_server_sock_read = NULL;
696 : 6 : rc = spdk_sock_group_poll_count(group, 1);
697 : 6 : CU_ASSERT(rc == 1);
698 : 6 : CU_ASSERT(g_server_sock_read == server_sock[0]);
699 : :
700 [ + + ]: 24 : for (i = 0; i < 3; i++) {
701 : 18 : rc = spdk_sock_group_remove_sock(group, server_sock[i]);
702 : 18 : CU_ASSERT(rc == 0);
703 : :
704 : 18 : rc = spdk_sock_close(&client_sock[i]);
705 : 18 : CU_ASSERT(client_sock[i] == NULL);
706 : 18 : CU_ASSERT(rc == 0);
707 : :
708 : 18 : rc = spdk_sock_close(&server_sock[i]);
709 : 18 : CU_ASSERT(server_sock[i] == NULL);
710 : 18 : CU_ASSERT(rc == 0);
711 : : }
712 : :
713 : 6 : rc = spdk_sock_group_close(&group);
714 : 6 : CU_ASSERT(group == NULL);
715 : 6 : CU_ASSERT(rc == 0);
716 : :
717 : 6 : rc = spdk_sock_close(&listen_sock);
718 : 6 : CU_ASSERT(listen_sock == NULL);
719 : 6 : CU_ASSERT(rc == 0);
720 : 6 : }
721 : :
722 : : struct close_ctx {
723 : : struct spdk_sock_group *group;
724 : : struct spdk_sock *sock;
725 : : bool called;
726 : : };
727 : :
728 : : static void
729 : 6 : _first_close_cb(void *cb_arg, int err)
730 : : {
731 : 6 : struct close_ctx *ctx = cb_arg;
732 : : int rc;
733 : :
734 : 6 : ctx->called = true;
735 : :
736 : : /* Always close the socket here */
737 : 6 : rc = spdk_sock_group_remove_sock(ctx->group, ctx->sock);
738 : 6 : CU_ASSERT(rc == 0);
739 : 6 : spdk_sock_close(&ctx->sock);
740 : :
741 : 6 : CU_ASSERT(err == 0);
742 : 6 : }
743 : :
744 : : static void
745 : 6 : _second_close_cb(void *cb_arg, int err)
746 : : {
747 : 6 : *(bool *)cb_arg = true;
748 : 6 : CU_ASSERT(err == -ECANCELED);
749 : 6 : }
750 : :
751 : : static void
752 : 6 : _sock_close(const char *ip, int port, char *impl_name)
753 : : {
754 : 5 : struct spdk_sock_group *group;
755 : 5 : struct spdk_sock *listen_sock;
756 : : struct spdk_sock *server_sock;
757 : 5 : struct spdk_sock *client_sock;
758 : 6 : uint8_t data_buf[64] = {};
759 : : struct spdk_sock_request *req1, *req2;
760 : 6 : struct close_ctx ctx = {};
761 : 6 : bool cb_arg2 = false;
762 : : int rc;
763 : :
764 : 6 : listen_sock = spdk_sock_listen(ip, port, impl_name);
765 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(listen_sock != NULL);
766 : :
767 : 6 : client_sock = spdk_sock_connect(ip, port, impl_name);
768 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(client_sock != NULL);
769 : :
770 : 6 : usleep(1000);
771 : :
772 : 6 : server_sock = spdk_sock_accept(listen_sock);
773 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(server_sock != NULL);
774 : :
775 : 6 : group = spdk_sock_group_create(NULL);
776 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(group != NULL);
777 : :
778 : 6 : rc = spdk_sock_group_add_sock(group, server_sock, read_data, server_sock);
779 : 6 : CU_ASSERT(rc == 0);
780 : :
781 : : /* Submit multiple async writevs on the server sock */
782 : :
783 : 6 : req1 = calloc(1, sizeof(struct spdk_sock_request) + sizeof(struct iovec));
784 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(req1 != NULL);
785 : 6 : SPDK_SOCK_REQUEST_IOV(req1, 0)->iov_base = data_buf;
786 : 6 : SPDK_SOCK_REQUEST_IOV(req1, 0)->iov_len = 64;
787 : 6 : ctx.group = group;
788 : 6 : ctx.sock = server_sock;
789 : 6 : ctx.called = false;
790 : 6 : req1->iovcnt = 1;
791 : 6 : req1->cb_fn = _first_close_cb;
792 : 6 : req1->cb_arg = &ctx;
793 : 6 : spdk_sock_writev_async(server_sock, req1);
794 [ - + ]: 6 : CU_ASSERT(ctx.called == false);
795 : :
796 : 6 : req2 = calloc(1, sizeof(struct spdk_sock_request) + sizeof(struct iovec));
797 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(req2 != NULL);
798 : 6 : SPDK_SOCK_REQUEST_IOV(req2, 0)->iov_base = data_buf;
799 : 6 : SPDK_SOCK_REQUEST_IOV(req2, 0)->iov_len = 64;
800 : 6 : req2->iovcnt = 1;
801 : 6 : req2->cb_fn = _second_close_cb;
802 : 6 : req2->cb_arg = &cb_arg2;
803 : 6 : spdk_sock_writev_async(server_sock, req2);
804 [ - + ]: 6 : CU_ASSERT(cb_arg2 == false);
805 : :
806 : : /* Test spdk_sock_flush when sock is NULL */
807 : 6 : rc = spdk_sock_flush(NULL);
808 : 6 : CU_ASSERT(rc == -1);
809 : 6 : CU_ASSERT(errno == EBADF);
810 : :
811 : : /* Test spdk_sock_flush when sock is not NULL */
812 : 6 : rc = spdk_sock_flush(client_sock);
813 : 6 : CU_ASSERT(rc == 0);
814 : :
815 : : /* Poll the socket so the writev_async's send. The first one's
816 : : * callback will close the socket. */
817 : 6 : spdk_sock_group_poll(group);
818 [ - + - + ]: 6 : if (ctx.called == false) {
819 : : /* Sometimes the zerocopy completion isn't posted immediately. Delay slightly
820 : : * and poll one more time. */
821 : 0 : usleep(1000);
822 : 0 : spdk_sock_group_poll(group);
823 : : }
824 [ - + ]: 6 : CU_ASSERT(ctx.called == true);
825 [ - + ]: 6 : CU_ASSERT(cb_arg2 == true);
826 : :
827 : 6 : rc = spdk_sock_group_close(&group);
828 : 6 : CU_ASSERT(group == NULL);
829 : 6 : CU_ASSERT(rc == 0);
830 : :
831 : 6 : rc = spdk_sock_close(&client_sock);
832 : 6 : CU_ASSERT(client_sock == NULL);
833 : 6 : CU_ASSERT(rc == 0);
834 : :
835 : 6 : rc = spdk_sock_close(&listen_sock);
836 : 6 : CU_ASSERT(listen_sock == NULL);
837 : 6 : CU_ASSERT(rc == 0);
838 : :
839 : 6 : free(req1);
840 : 6 : free(req2);
841 : 6 : }
842 : :
843 : : static void
844 : 6 : _posix_sock_close(void)
845 : : {
846 : 6 : _sock_close("127.0.0.1", UT_PORT, "posix");
847 : 6 : }
848 : :
849 : : static void
850 : 6 : sock_get_default_opts(void)
851 : : {
852 : 5 : struct spdk_sock_opts opts;
853 : :
854 : : /* opts_size is 0 */
855 : 6 : opts.opts_size = 0;
856 : 6 : opts.priority = 3;
857 : 6 : spdk_sock_get_default_opts(&opts);
858 : 6 : CU_ASSERT(opts.priority == 3);
859 : 6 : CU_ASSERT(opts.opts_size == 0);
860 : :
861 : : /* opts_size is less than sizeof(opts) */
862 : 6 : opts.opts_size = 4;
863 : 6 : opts.priority = 3;
864 : 6 : spdk_sock_get_default_opts(&opts);
865 : 6 : CU_ASSERT(opts.priority == 3);
866 : 6 : CU_ASSERT(opts.opts_size == 4);
867 : :
868 : : /* opts_size is equal to sizeof(opts) */
869 : 6 : opts.opts_size = sizeof(opts);
870 : 6 : opts.priority = 3;
871 : 6 : spdk_sock_get_default_opts(&opts);
872 : 6 : CU_ASSERT(opts.priority == SPDK_SOCK_DEFAULT_PRIORITY);
873 : 6 : CU_ASSERT(opts.opts_size == sizeof(opts));
874 : :
875 : : /* opts_size is larger then sizeof(opts) */
876 : 6 : opts.opts_size = sizeof(opts) + 1;
877 : 6 : opts.priority = 3;
878 : 6 : spdk_sock_get_default_opts(&opts);
879 : 6 : CU_ASSERT(opts.priority == SPDK_SOCK_DEFAULT_PRIORITY);
880 : 6 : CU_ASSERT(opts.opts_size == (sizeof(opts) + 1));
881 : 6 : }
882 : :
883 : : static void
884 : 6 : ut_sock_impl_get_set_opts(void)
885 : : {
886 : : int rc;
887 : 6 : size_t len = 0;
888 : : /* Use any pointer value for opts. It is never dereferenced in this test */
889 : 6 : struct spdk_sock_impl_opts *opts = (struct spdk_sock_impl_opts *)0x123456789;
890 : :
891 : 6 : rc = spdk_sock_impl_get_opts("ut", NULL, &len);
892 : 6 : CU_ASSERT(rc == -1);
893 : 6 : CU_ASSERT(errno == EINVAL);
894 : 6 : rc = spdk_sock_impl_get_opts("ut", opts, NULL);
895 : 6 : CU_ASSERT(rc == -1);
896 : 6 : CU_ASSERT(errno == EINVAL);
897 : 6 : rc = spdk_sock_impl_get_opts("ut", opts, &len);
898 : 6 : CU_ASSERT(rc == -1);
899 : 6 : CU_ASSERT(errno == ENOTSUP);
900 : :
901 : 6 : rc = spdk_sock_impl_set_opts("ut", NULL, len);
902 : 6 : CU_ASSERT(rc == -1);
903 : 6 : CU_ASSERT(errno == EINVAL);
904 : 6 : rc = spdk_sock_impl_set_opts("ut", opts, len);
905 : 6 : CU_ASSERT(rc == -1);
906 : 6 : CU_ASSERT(errno == ENOTSUP);
907 : 6 : }
908 : :
909 : : static void
910 : 6 : posix_sock_impl_get_set_opts(void)
911 : : {
912 : : int rc;
913 : 6 : size_t len = 0;
914 : 6 : struct spdk_sock_impl_opts opts = {};
915 : :
916 : 6 : rc = spdk_sock_impl_get_opts("posix", NULL, &len);
917 : 6 : CU_ASSERT(rc == -1);
918 : 6 : CU_ASSERT(errno == EINVAL);
919 : 6 : rc = spdk_sock_impl_get_opts("posix", &opts, NULL);
920 : 6 : CU_ASSERT(rc == -1);
921 : 6 : CU_ASSERT(errno == EINVAL);
922 : :
923 : : /* Check default opts */
924 : 6 : len = sizeof(opts);
925 : 6 : rc = spdk_sock_impl_get_opts("posix", &opts, &len);
926 : 6 : CU_ASSERT(rc == 0);
927 : 6 : CU_ASSERT(len == sizeof(opts));
928 : 6 : CU_ASSERT(opts.recv_buf_size == DEFAULT_SO_RCVBUF_SIZE);
929 : 6 : CU_ASSERT(opts.send_buf_size == DEFAULT_SO_SNDBUF_SIZE);
930 : :
931 : : /* Try to request zero opts */
932 : 6 : len = 0;
933 : 6 : rc = spdk_sock_impl_get_opts("posix", &opts, &len);
934 : 6 : CU_ASSERT(rc == 0);
935 : 6 : CU_ASSERT(len == 0);
936 : :
937 : 6 : rc = spdk_sock_impl_set_opts("posix", NULL, len);
938 : 6 : CU_ASSERT(rc == -1);
939 : 6 : CU_ASSERT(errno == EINVAL);
940 : :
941 : 6 : opts.recv_buf_size = 16;
942 : 6 : opts.send_buf_size = 4;
943 : 6 : rc = spdk_sock_impl_set_opts("posix", &opts, sizeof(opts));
944 : 6 : CU_ASSERT(rc == 0);
945 : 6 : len = sizeof(opts);
946 : 6 : memset(&opts, 0, sizeof(opts));
947 : 6 : rc = spdk_sock_impl_get_opts("posix", &opts, &len);
948 : 6 : CU_ASSERT(rc == 0);
949 : 6 : CU_ASSERT(opts.recv_buf_size == 16);
950 : 6 : CU_ASSERT(opts.send_buf_size == 4);
951 : :
952 : : /* Try to set less opts. Opts in the end should be untouched */
953 : 6 : opts.recv_buf_size = 5;
954 : 6 : opts.send_buf_size = 10;
955 : 6 : rc = spdk_sock_impl_set_opts("posix", &opts, sizeof(opts.recv_buf_size));
956 : 6 : CU_ASSERT(rc == 0);
957 : 6 : len = sizeof(opts);
958 : 6 : memset(&opts, 0, sizeof(opts));
959 : 6 : rc = spdk_sock_impl_get_opts("posix", &opts, &len);
960 : 6 : CU_ASSERT(rc == 0);
961 : 6 : CU_ASSERT(opts.recv_buf_size == 5);
962 : 6 : CU_ASSERT(opts.send_buf_size == 4);
963 : :
964 : : /* Try to set partial option. It should not be changed */
965 : 6 : opts.recv_buf_size = 1000;
966 : 6 : rc = spdk_sock_impl_set_opts("posix", &opts, 1);
967 : 6 : CU_ASSERT(rc == 0);
968 : 6 : len = sizeof(opts);
969 : 6 : memset(&opts, 0, sizeof(opts));
970 : 6 : rc = spdk_sock_impl_get_opts("posix", &opts, &len);
971 : 6 : CU_ASSERT(rc == 0);
972 : 6 : CU_ASSERT(opts.recv_buf_size == 5);
973 : 6 : }
974 : :
975 : : static void
976 : 6 : ut_sock_map(void)
977 : : {
978 : 6 : struct spdk_sock_map map = {
979 : : .entries = STAILQ_HEAD_INITIALIZER(map.entries),
980 : : .mtx = PTHREAD_MUTEX_INITIALIZER
981 : : };
982 : 5 : struct spdk_sock_group_impl *group_1, *group_2, *test_group;
983 : : int rc;
984 : : int test_id;
985 : :
986 : 6 : group_1 = spdk_ut_sock_group_impl_create();
987 : 6 : group_2 = spdk_ut_sock_group_impl_create();
988 : :
989 : : /* Test 1
990 : : * Sanity check when sock_map is empty */
991 : 6 : test_id = spdk_sock_map_find_free(&map);
992 : 6 : CU_ASSERT(test_id == -1);
993 : :
994 : 6 : test_group = NULL;
995 : 6 : rc = spdk_sock_map_lookup(&map, 1, &test_group, NULL);
996 : 6 : CU_ASSERT(rc == -EINVAL);
997 : 6 : CU_ASSERT(test_group == NULL);
998 : :
999 : : /* Test 2
1000 : : * Insert single entry */
1001 : 6 : rc = spdk_sock_map_insert(&map, 1, group_1);
1002 : 6 : CU_ASSERT(rc == 0);
1003 : :
1004 : 6 : test_group = NULL;
1005 : 6 : rc = spdk_sock_map_lookup(&map, 1, &test_group, NULL);
1006 : 6 : CU_ASSERT(rc == 0);
1007 : 6 : CU_ASSERT(test_group == group_1);
1008 : :
1009 : : /* There is single entry allocated, but it is not free */
1010 : 6 : test_id = spdk_sock_map_find_free(&map);
1011 : 6 : CU_ASSERT(test_id == -1);
1012 : :
1013 : : /* Free the entry and verify */
1014 : 6 : spdk_sock_map_release(&map, 1);
1015 : 6 : test_id = spdk_sock_map_find_free(&map);
1016 : 6 : CU_ASSERT(test_id == 1);
1017 : :
1018 : 6 : spdk_sock_map_cleanup(&map);
1019 : :
1020 : : /* Test 3
1021 : : * Insert sock_group into placement_id multiple times */
1022 : 6 : rc = spdk_sock_map_insert(&map, 1, group_1);
1023 : 6 : CU_ASSERT(rc == 0);
1024 : 6 : CU_ASSERT(STAILQ_FIRST(&map.entries)->ref == 1);
1025 : 6 : rc = spdk_sock_map_insert(&map, 1, group_1);
1026 : 6 : CU_ASSERT(rc == 0);
1027 : 6 : CU_ASSERT(STAILQ_FIRST(&map.entries)->ref == 2);
1028 : :
1029 : : /* Release entry once and see that it still exists. */
1030 : 6 : spdk_sock_map_release(&map, 1);
1031 : 6 : test_group = NULL;
1032 : 6 : rc = spdk_sock_map_lookup(&map, 1, &test_group, NULL);
1033 : 6 : CU_ASSERT(rc == 0);
1034 : 6 : CU_ASSERT(test_group == group_1);
1035 : :
1036 : : /* Release entry second and final time. */
1037 : 6 : spdk_sock_map_release(&map, 1);
1038 : 6 : test_group = NULL;
1039 : 6 : rc = spdk_sock_map_lookup(&map, 1, &test_group, NULL);
1040 : 6 : CU_ASSERT(rc == -EINVAL);
1041 : 6 : CU_ASSERT(test_group == NULL);
1042 : :
1043 : 6 : spdk_sock_map_cleanup(&map);
1044 : :
1045 : : /* Test 4
1046 : : * Test multiple entries */
1047 : 6 : rc = spdk_sock_map_insert(&map, 1, group_1);
1048 : 6 : CU_ASSERT(rc == 0);
1049 : :
1050 : 6 : test_group = NULL;
1051 : 6 : rc = spdk_sock_map_lookup(&map, 1, &test_group, NULL);
1052 : 6 : CU_ASSERT(rc == 0);
1053 : 6 : CU_ASSERT(test_group == group_1);
1054 : :
1055 : 6 : rc = spdk_sock_map_insert(&map, 2, group_2);
1056 : 6 : CU_ASSERT(rc == 0);
1057 : :
1058 : 6 : test_group = NULL;
1059 : 6 : rc = spdk_sock_map_lookup(&map, 2, &test_group, NULL);
1060 : 6 : CU_ASSERT(rc == 0);
1061 : 6 : CU_ASSERT(test_group == group_2);
1062 : :
1063 : 6 : spdk_sock_map_cleanup(&map);
1064 : :
1065 : : /* Test 5
1066 : : * Attempt inserting multiple entries into single placement_id */
1067 : 6 : rc = spdk_sock_map_insert(&map, 1, group_1);
1068 : 6 : CU_ASSERT(rc == 0);
1069 : :
1070 : 6 : test_group = NULL;
1071 : 6 : rc = spdk_sock_map_lookup(&map, 1, &test_group, NULL);
1072 : 6 : CU_ASSERT(rc == 0);
1073 : 6 : CU_ASSERT(test_group == group_1);
1074 : :
1075 : 6 : rc = spdk_sock_map_insert(&map, 1, group_2);
1076 : 6 : CU_ASSERT(rc == -EINVAL);
1077 : :
1078 : 6 : test_group = NULL;
1079 : 6 : rc = spdk_sock_map_lookup(&map, 1, &test_group, NULL);
1080 : 6 : CU_ASSERT(rc == 0);
1081 : 6 : CU_ASSERT(test_group == group_1);
1082 : :
1083 : 6 : spdk_sock_map_cleanup(&map);
1084 : :
1085 : : /* Test 6
1086 : : * Insert single entry without a sock_group */
1087 : 6 : rc = spdk_sock_map_insert(&map, 1, NULL);
1088 : 6 : CU_ASSERT(rc == 0);
1089 : :
1090 : 6 : test_group = NULL;
1091 : 6 : rc = spdk_sock_map_lookup(&map, 1, &test_group, NULL);
1092 : 6 : CU_ASSERT(rc == -EINVAL);
1093 : 6 : CU_ASSERT(test_group == NULL);
1094 : :
1095 : 6 : test_id = spdk_sock_map_find_free(&map);
1096 : 6 : CU_ASSERT(test_id == 1);
1097 : :
1098 : 6 : rc = spdk_sock_map_insert(&map, test_id, group_1);
1099 : 6 : CU_ASSERT(rc == 0);
1100 : :
1101 : 6 : test_group = NULL;
1102 : 6 : rc = spdk_sock_map_lookup(&map, test_id, &test_group, NULL);
1103 : 6 : CU_ASSERT(rc == 0);
1104 : 6 : CU_ASSERT(test_group == group_1);
1105 : :
1106 : 6 : spdk_sock_map_cleanup(&map);
1107 : :
1108 : : /* Test 6
1109 : : * Use hint sock_group for for placement_id */
1110 : 6 : test_group = NULL;
1111 : 6 : rc = spdk_sock_map_lookup(&map, 1, &test_group, group_1);
1112 : 6 : CU_ASSERT(rc == 0);
1113 : 6 : CU_ASSERT(test_group == NULL);
1114 : :
1115 : 6 : test_group = NULL;
1116 : 6 : rc = spdk_sock_map_lookup(&map, 1, &test_group, NULL);
1117 : 6 : CU_ASSERT(rc == 0);
1118 : 6 : CU_ASSERT(test_group == group_1);
1119 : :
1120 : 6 : test_id = spdk_sock_map_find_free(&map);
1121 : 6 : CU_ASSERT(test_id == -1);
1122 : :
1123 : 6 : rc = spdk_sock_map_insert(&map, 1, group_2);
1124 : 6 : CU_ASSERT(rc == -EINVAL);
1125 : :
1126 : 6 : rc = spdk_sock_map_insert(&map, 1, group_1);
1127 : 6 : CU_ASSERT(rc == 0);
1128 : :
1129 : 6 : spdk_sock_map_cleanup(&map);
1130 : :
1131 : 6 : spdk_ut_sock_group_impl_close(group_2);
1132 : 6 : spdk_ut_sock_group_impl_close(group_1);
1133 : 6 : }
1134 : :
1135 : : static void
1136 : 6 : override_impl_opts(void)
1137 : : {
1138 : 5 : struct spdk_sock *lsock, *csock, *asock;
1139 : 5 : struct spdk_sock_opts opts;
1140 : 5 : struct spdk_sock_impl_opts impl_opts;
1141 : : uint32_t send_buf_size;
1142 : 5 : size_t opts_size;
1143 : : int rc;
1144 : :
1145 : 6 : opts_size = sizeof(impl_opts);
1146 : 6 : rc = spdk_sock_impl_get_opts("posix", &impl_opts, &opts_size);
1147 : 6 : CU_ASSERT_EQUAL(rc, 0);
1148 : 6 : opts.opts_size = sizeof(opts);
1149 : 6 : spdk_sock_get_default_opts(&opts);
1150 : 6 : opts.impl_opts = &impl_opts;
1151 : 6 : opts.impl_opts_size = sizeof(impl_opts);
1152 : :
1153 : : /* Use send_buf_size to verify that impl_opts get overridden */
1154 : 6 : send_buf_size = impl_opts.send_buf_size;
1155 : 6 : impl_opts.send_buf_size = send_buf_size + 1;
1156 : :
1157 : 6 : lsock = spdk_sock_listen_ext("127.0.0.1", UT_PORT, "posix", &opts);
1158 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(lsock != NULL);
1159 : 6 : CU_ASSERT_EQUAL(lsock->impl_opts.send_buf_size, send_buf_size + 1);
1160 : :
1161 : : /* Check the same for connect() */
1162 : 6 : opts_size = sizeof(impl_opts);
1163 : 6 : rc = spdk_sock_impl_get_opts("posix", &impl_opts, &opts_size);
1164 : 6 : CU_ASSERT_EQUAL(rc, 0);
1165 : 6 : opts.opts_size = sizeof(opts);
1166 : 6 : spdk_sock_get_default_opts(&opts);
1167 : 6 : opts.impl_opts = &impl_opts;
1168 : 6 : opts.impl_opts_size = sizeof(impl_opts);
1169 : :
1170 : 6 : impl_opts.send_buf_size = send_buf_size + 2;
1171 : :
1172 : 6 : csock = spdk_sock_connect_ext("127.0.0.1", UT_PORT, "posix", &opts);
1173 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(csock != NULL);
1174 : 6 : CU_ASSERT_EQUAL(csock->impl_opts.send_buf_size, send_buf_size + 2);
1175 : :
1176 : : /* Check that accept() inherits impl_opts from listen socket */
1177 : 6 : asock = spdk_sock_accept(lsock);
1178 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(asock != NULL);
1179 : 6 : CU_ASSERT_EQUAL(asock->impl_opts.send_buf_size, send_buf_size + 1);
1180 : :
1181 : 6 : spdk_sock_close(&asock);
1182 : 6 : spdk_sock_close(&csock);
1183 : 6 : spdk_sock_close(&lsock);
1184 : :
1185 : : /* Check that impl_opts_size is verified by setting it to the offset of send_buf_size */
1186 : 6 : opts_size = sizeof(impl_opts);
1187 : 6 : rc = spdk_sock_impl_get_opts("posix", &impl_opts, &opts_size);
1188 : 6 : CU_ASSERT_EQUAL(rc, 0);
1189 : 6 : opts.opts_size = sizeof(opts);
1190 : 6 : spdk_sock_get_default_opts(&opts);
1191 : 6 : opts.impl_opts = &impl_opts;
1192 : 6 : opts.impl_opts_size = offsetof(struct spdk_sock_impl_opts, send_buf_size);
1193 : :
1194 : 6 : send_buf_size = impl_opts.send_buf_size;
1195 : 6 : impl_opts.send_buf_size = send_buf_size + 1;
1196 : :
1197 : 6 : lsock = spdk_sock_listen_ext("127.0.0.1", UT_PORT, "posix", &opts);
1198 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(lsock != NULL);
1199 : 6 : CU_ASSERT_EQUAL(lsock->impl_opts.send_buf_size, send_buf_size);
1200 : :
1201 : : /* Check the same for connect() */
1202 : 6 : opts_size = sizeof(impl_opts);
1203 : 6 : rc = spdk_sock_impl_get_opts("posix", &impl_opts, &opts_size);
1204 : 6 : CU_ASSERT_EQUAL(rc, 0);
1205 : 6 : opts.opts_size = sizeof(opts);
1206 : 6 : spdk_sock_get_default_opts(&opts);
1207 : 6 : opts.impl_opts = &impl_opts;
1208 : 6 : opts.impl_opts_size = offsetof(struct spdk_sock_impl_opts, send_buf_size);
1209 : :
1210 : 6 : impl_opts.send_buf_size = send_buf_size + 2;
1211 : :
1212 : 6 : csock = spdk_sock_connect_ext("127.0.0.1", UT_PORT, "posix", &opts);
1213 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(csock != NULL);
1214 : 6 : CU_ASSERT_EQUAL(csock->impl_opts.send_buf_size, send_buf_size);
1215 : :
1216 : 6 : spdk_sock_close(&lsock);
1217 : 6 : spdk_sock_close(&csock);
1218 : 6 : }
1219 : :
1220 : : static void
1221 : 6 : ut_sock_group_get_ctx(void)
1222 : : {
1223 : 6 : void *test_ctx = (void *)0xff0000000;
1224 : 6 : void *test_ctx1 = (void *)0xfff000000;
1225 : 6 : void *test_ctx2 = (void *)0xffff00000;
1226 : 5 : struct spdk_sock_group group;
1227 : :
1228 : : /* The return should be NULL */
1229 : 6 : test_ctx = spdk_sock_group_get_ctx(NULL);
1230 : 6 : CU_ASSERT(test_ctx == NULL);
1231 : :
1232 : : /* The group.ctx should be changed */
1233 : 6 : group.ctx = test_ctx1;
1234 : 6 : test_ctx2 = spdk_sock_group_get_ctx(&group);
1235 : :
1236 : 6 : CU_ASSERT(test_ctx1 == test_ctx2);
1237 : 6 : }
1238 : :
1239 : : int
1240 : 6 : main(int argc, char **argv)
1241 : : {
1242 : 6 : CU_pSuite suite = NULL;
1243 : : unsigned int num_failures;
1244 : :
1245 : 6 : CU_initialize_registry();
1246 : :
1247 : 6 : suite = CU_add_suite("sock", NULL, NULL);
1248 : :
1249 : 6 : CU_ADD_TEST(suite, posix_sock);
1250 : 6 : CU_ADD_TEST(suite, ut_sock);
1251 : 6 : CU_ADD_TEST(suite, posix_sock_group);
1252 : 6 : CU_ADD_TEST(suite, ut_sock_group);
1253 : 6 : CU_ADD_TEST(suite, posix_sock_group_fairness);
1254 : 6 : CU_ADD_TEST(suite, _posix_sock_close);
1255 : 6 : CU_ADD_TEST(suite, sock_get_default_opts);
1256 : 6 : CU_ADD_TEST(suite, ut_sock_impl_get_set_opts);
1257 : 6 : CU_ADD_TEST(suite, posix_sock_impl_get_set_opts);
1258 : 6 : CU_ADD_TEST(suite, ut_sock_map);
1259 : 6 : CU_ADD_TEST(suite, override_impl_opts);
1260 : 6 : CU_ADD_TEST(suite, ut_sock_group_get_ctx);
1261 : :
1262 : :
1263 : 6 : num_failures = spdk_ut_run_tests(argc, argv, NULL);
1264 : :
1265 : 6 : CU_cleanup_registry();
1266 : :
1267 : 6 : return num_failures;
1268 : : }
|