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