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