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_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_flush(struct spdk_sock *sock) 205 { 206 return -1; 207 } 208 209 static int 210 spdk_ut_sock_set_recvlowat(struct spdk_sock *_sock, int nbytes) 211 { 212 return 0; 213 } 214 215 static int 216 spdk_ut_sock_set_recvbuf(struct spdk_sock *_sock, int sz) 217 { 218 return 0; 219 } 220 221 static int 222 spdk_ut_sock_set_sendbuf(struct spdk_sock *_sock, int sz) 223 { 224 return 0; 225 } 226 227 static bool 228 spdk_ut_sock_is_ipv6(struct spdk_sock *_sock) 229 { 230 return false; 231 } 232 233 static bool 234 spdk_ut_sock_is_ipv4(struct spdk_sock *_sock) 235 { 236 return true; 237 } 238 239 static bool 240 spdk_ut_sock_is_connected(struct spdk_sock *_sock) 241 { 242 struct spdk_ut_sock *sock = __ut_sock(_sock); 243 244 return (sock->peer != NULL); 245 } 246 247 static struct spdk_sock_group_impl * 248 spdk_ut_sock_group_impl_get_optimal(struct spdk_sock *_sock, struct spdk_sock_group_impl *hint) 249 { 250 return NULL; 251 } 252 253 static struct spdk_sock_group_impl * 254 spdk_ut_sock_group_impl_create(void) 255 { 256 struct spdk_ut_sock_group_impl *group_impl; 257 258 group_impl = calloc(1, sizeof(*group_impl)); 259 SPDK_CU_ASSERT_FATAL(group_impl != NULL); 260 261 return &group_impl->base; 262 } 263 264 static int 265 spdk_ut_sock_group_impl_add_sock(struct spdk_sock_group_impl *_group, struct spdk_sock *_sock) 266 { 267 struct spdk_ut_sock_group_impl *group = __ut_group(_group); 268 struct spdk_ut_sock *sock = __ut_sock(_sock); 269 270 group->sock = sock; 271 272 return 0; 273 } 274 275 static int 276 spdk_ut_sock_group_impl_remove_sock(struct spdk_sock_group_impl *_group, struct spdk_sock *_sock) 277 { 278 struct spdk_ut_sock_group_impl *group = __ut_group(_group); 279 struct spdk_ut_sock *sock = __ut_sock(_sock); 280 281 CU_ASSERT(group->sock == sock); 282 group->sock = NULL; 283 284 return 0; 285 } 286 287 static int 288 spdk_ut_sock_group_impl_poll(struct spdk_sock_group_impl *_group, int max_events, 289 struct spdk_sock **socks) 290 { 291 struct spdk_ut_sock_group_impl *group = __ut_group(_group); 292 293 if (group->sock != NULL && group->sock->bytes_avail > 0) { 294 socks[0] = &group->sock->base; 295 return 1; 296 } 297 298 return 0; 299 } 300 301 static int 302 spdk_ut_sock_group_impl_close(struct spdk_sock_group_impl *_group) 303 { 304 struct spdk_ut_sock_group_impl *group = __ut_group(_group); 305 306 CU_ASSERT(group->sock == NULL); 307 free(_group); 308 309 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 SPDK_NET_IMPL_REGISTER(ut, &g_ut_net_impl, DEFAULT_SOCK_PRIORITY + 2); 338 339 static void 340 _sock(const char *ip, int port, char *impl_name) 341 { 342 struct spdk_sock *listen_sock; 343 struct spdk_sock *server_sock; 344 struct spdk_sock *client_sock; 345 char *test_string = "abcdef"; 346 char buffer[64]; 347 ssize_t bytes_read, bytes_written; 348 struct iovec iov; 349 int nbytes; 350 int rc; 351 352 listen_sock = spdk_sock_listen(ip, port, impl_name); 353 SPDK_CU_ASSERT_FATAL(listen_sock != NULL); 354 355 server_sock = spdk_sock_accept(listen_sock); 356 CU_ASSERT(server_sock == NULL); 357 CU_ASSERT(errno == EAGAIN || errno == EWOULDBLOCK); 358 359 client_sock = spdk_sock_connect(ip, port, impl_name); 360 SPDK_CU_ASSERT_FATAL(client_sock != NULL); 361 362 /* 363 * Delay a bit here before checking if server socket is 364 * ready. 365 */ 366 usleep(1000); 367 368 server_sock = spdk_sock_accept(listen_sock); 369 SPDK_CU_ASSERT_FATAL(server_sock != NULL); 370 CU_ASSERT(spdk_sock_is_connected(client_sock) == true); 371 CU_ASSERT(spdk_sock_is_connected(server_sock) == true); 372 373 /* Test spdk_sock_set_default_impl */ 374 rc = spdk_sock_set_default_impl(impl_name); 375 CU_ASSERT(rc == 0); 376 CU_ASSERT(g_default_impl != NULL); 377 378 /* Test spdk_sock_set_default_impl when name is NULL */ 379 rc = spdk_sock_set_default_impl(NULL); 380 CU_ASSERT(rc == -1); 381 CU_ASSERT(errno == EINVAL); 382 383 /* Test spdk_sock_is _ipv6 */ 384 CU_ASSERT(!spdk_sock_is_ipv6(client_sock)); 385 386 /* Test spdk_sock_is _ipv4 */ 387 CU_ASSERT(spdk_sock_is_ipv4(client_sock)); 388 389 nbytes = 2048; 390 391 /* Test spdk_sock_set_recvlowat */ 392 rc = spdk_sock_set_recvlowat(client_sock, nbytes); 393 CU_ASSERT(rc == 0); 394 395 /* Test spdk_sock_set_recvbuf */ 396 rc = spdk_sock_set_recvbuf(client_sock, nbytes); 397 CU_ASSERT(rc == 0); 398 399 /* Test spdk_sock_set_sendbuf */ 400 rc = spdk_sock_set_sendbuf(client_sock, nbytes); 401 CU_ASSERT(rc == 0); 402 403 /* Test spdk_sock_recv */ 404 iov.iov_base = test_string; 405 iov.iov_len = 7; 406 bytes_written = spdk_sock_writev(client_sock, &iov, 1); 407 CU_ASSERT(bytes_written == 7); 408 409 usleep(1000); 410 411 bytes_read = spdk_sock_recv(server_sock, buffer, 2); 412 CU_ASSERT(bytes_read == 2); 413 414 usleep(1000); 415 416 bytes_read += spdk_sock_recv(server_sock, buffer + 2, 5); 417 CU_ASSERT(bytes_read == 7); 418 419 CU_ASSERT(strncmp(test_string, buffer, 7) == 0); 420 421 /* Test spdk_sock_readv */ 422 iov.iov_base = test_string; 423 iov.iov_len = 7; 424 bytes_written = spdk_sock_writev(client_sock, &iov, 1); 425 CU_ASSERT(bytes_written == 7); 426 427 usleep(1000); 428 429 iov.iov_base = buffer; 430 iov.iov_len = 2; 431 bytes_read = spdk_sock_readv(server_sock, &iov, 1); 432 CU_ASSERT(bytes_read == 2); 433 434 usleep(1000); 435 436 iov.iov_base = buffer + 2; 437 iov.iov_len = 5; 438 bytes_read += spdk_sock_readv(server_sock, &iov, 1); 439 CU_ASSERT(bytes_read == 7); 440 441 usleep(1000); 442 443 CU_ASSERT(strncmp(test_string, buffer, 7) == 0); 444 445 rc = spdk_sock_close(&client_sock); 446 CU_ASSERT(client_sock == NULL); 447 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 CU_ASSERT(spdk_sock_is_connected(server_sock) == false); 455 456 rc = spdk_sock_close(&server_sock); 457 CU_ASSERT(server_sock == NULL); 458 CU_ASSERT(rc == 0); 459 460 rc = spdk_sock_close(&listen_sock); 461 CU_ASSERT(listen_sock == NULL); 462 CU_ASSERT(rc == 0); 463 } 464 465 static void 466 posix_sock(void) 467 { 468 _sock("127.0.0.1", UT_PORT, "posix"); 469 } 470 471 static void 472 ut_sock(void) 473 { 474 _sock(UT_IP, UT_PORT, "ut"); 475 } 476 477 static void 478 read_data(void *cb_arg, struct spdk_sock_group *group, struct spdk_sock *sock) 479 { 480 struct spdk_sock *server_sock = cb_arg; 481 482 CU_ASSERT(server_sock == sock); 483 484 g_read_data_called = true; 485 g_bytes_read += spdk_sock_recv(server_sock, g_buf + g_bytes_read, sizeof(g_buf) - g_bytes_read); 486 } 487 488 static void 489 _sock_group(const char *ip, int port, char *impl_name) 490 { 491 struct spdk_sock_group *group; 492 struct spdk_sock_group *hint; 493 struct spdk_sock *listen_sock; 494 struct spdk_sock *server_sock; 495 struct spdk_sock *client_sock; 496 char *test_string = "abcdef"; 497 ssize_t bytes_written; 498 struct iovec iov; 499 int rc; 500 501 listen_sock = spdk_sock_listen(ip, port, impl_name); 502 SPDK_CU_ASSERT_FATAL(listen_sock != NULL); 503 504 server_sock = spdk_sock_accept(listen_sock); 505 CU_ASSERT(server_sock == NULL); 506 CU_ASSERT(errno == EAGAIN || errno == EWOULDBLOCK); 507 508 client_sock = spdk_sock_connect(ip, port, impl_name); 509 SPDK_CU_ASSERT_FATAL(client_sock != NULL); 510 511 usleep(1000); 512 513 server_sock = spdk_sock_accept(listen_sock); 514 SPDK_CU_ASSERT_FATAL(server_sock != NULL); 515 516 group = spdk_sock_group_create(NULL); 517 SPDK_CU_ASSERT_FATAL(group != NULL); 518 519 hint = spdk_sock_group_create(NULL); 520 SPDK_CU_ASSERT_FATAL(hint != NULL); 521 522 /* pass null cb_fn */ 523 rc = spdk_sock_group_add_sock(group, server_sock, NULL, NULL); 524 CU_ASSERT(rc == -1); 525 CU_ASSERT(errno == EINVAL); 526 527 rc = spdk_sock_group_add_sock(group, server_sock, read_data, server_sock); 528 CU_ASSERT(rc == 0); 529 530 /* try adding sock a second time */ 531 rc = spdk_sock_group_add_sock(group, server_sock, read_data, server_sock); 532 CU_ASSERT(rc == -1); 533 CU_ASSERT(errno == EINVAL); 534 535 g_read_data_called = false; 536 g_bytes_read = 0; 537 rc = spdk_sock_group_poll(group); 538 539 CU_ASSERT(rc == 0); 540 CU_ASSERT(g_read_data_called == false); 541 542 iov.iov_base = test_string; 543 iov.iov_len = 7; 544 bytes_written = spdk_sock_writev(client_sock, &iov, 1); 545 CU_ASSERT(bytes_written == 7); 546 547 usleep(1000); 548 549 g_read_data_called = false; 550 g_bytes_read = 0; 551 rc = spdk_sock_group_poll(group); 552 553 CU_ASSERT(rc == 1); 554 CU_ASSERT(g_read_data_called == true); 555 CU_ASSERT(g_bytes_read == 7); 556 557 CU_ASSERT(strncmp(test_string, g_buf, 7) == 0); 558 559 rc = spdk_sock_close(&client_sock); 560 CU_ASSERT(client_sock == NULL); 561 CU_ASSERT(rc == 0); 562 563 /* Test get_optimal_sock_group */ 564 rc = spdk_sock_get_optimal_sock_group(server_sock, &group, hint); 565 CU_ASSERT(rc == 0); 566 567 /* Try to close sock_group while it still has sockets. */ 568 rc = spdk_sock_group_close(&group); 569 CU_ASSERT(rc == -1); 570 CU_ASSERT(errno == EBUSY); 571 572 /* Try to close sock while it is still part of a sock_group. */ 573 rc = spdk_sock_close(&server_sock); 574 CU_ASSERT(rc == -1); 575 CU_ASSERT(errno == EBUSY); 576 577 rc = spdk_sock_group_remove_sock(group, server_sock); 578 CU_ASSERT(rc == 0); 579 580 rc = spdk_sock_group_close(&group); 581 CU_ASSERT(group == NULL); 582 CU_ASSERT(rc == 0); 583 584 rc = spdk_sock_group_close(&hint); 585 CU_ASSERT(hint == NULL); 586 CU_ASSERT(rc == 0); 587 588 rc = spdk_sock_close(&server_sock); 589 CU_ASSERT(server_sock == NULL); 590 CU_ASSERT(rc == 0); 591 592 rc = spdk_sock_close(&listen_sock); 593 CU_ASSERT(listen_sock == NULL); 594 CU_ASSERT(rc == 0); 595 } 596 597 static void 598 posix_sock_group(void) 599 { 600 _sock_group("127.0.0.1", UT_PORT, "posix"); 601 } 602 603 static void 604 ut_sock_group(void) 605 { 606 _sock_group(UT_IP, UT_PORT, "ut"); 607 } 608 609 static void 610 read_data_fairness(void *cb_arg, struct spdk_sock_group *group, struct spdk_sock *sock) 611 { 612 struct spdk_sock *server_sock = cb_arg; 613 ssize_t bytes_read; 614 char buf[1]; 615 616 CU_ASSERT(g_server_sock_read == NULL); 617 CU_ASSERT(server_sock == sock); 618 619 g_server_sock_read = server_sock; 620 bytes_read = spdk_sock_recv(server_sock, buf, 1); 621 CU_ASSERT(bytes_read == 1); 622 } 623 624 static void 625 posix_sock_group_fairness(void) 626 { 627 struct spdk_sock_group *group; 628 struct spdk_sock *listen_sock; 629 struct spdk_sock *server_sock[3]; 630 struct spdk_sock *client_sock[3]; 631 char test_char = 'a'; 632 ssize_t bytes_written; 633 struct iovec iov; 634 int i, rc; 635 636 listen_sock = spdk_sock_listen("127.0.0.1", UT_PORT, "posix"); 637 SPDK_CU_ASSERT_FATAL(listen_sock != NULL); 638 639 group = spdk_sock_group_create(NULL); 640 SPDK_CU_ASSERT_FATAL(group != NULL); 641 642 for (i = 0; i < 3; i++) { 643 client_sock[i] = spdk_sock_connect("127.0.0.1", UT_PORT, "posix"); 644 SPDK_CU_ASSERT_FATAL(client_sock[i] != NULL); 645 646 usleep(1000); 647 648 server_sock[i] = spdk_sock_accept(listen_sock); 649 SPDK_CU_ASSERT_FATAL(server_sock[i] != NULL); 650 651 rc = spdk_sock_group_add_sock(group, server_sock[i], 652 read_data_fairness, server_sock[i]); 653 CU_ASSERT(rc == 0); 654 } 655 656 iov.iov_base = &test_char; 657 iov.iov_len = 1; 658 659 for (i = 0; i < 3; i++) { 660 bytes_written = spdk_sock_writev(client_sock[i], &iov, 1); 661 CU_ASSERT(bytes_written == 1); 662 } 663 664 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 g_server_sock_read = NULL; 671 rc = spdk_sock_group_poll_count(group, 1); 672 CU_ASSERT(rc == 1); 673 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 bytes_written = spdk_sock_writev(client_sock[0], &iov, 1); 681 CU_ASSERT(bytes_written == 1); 682 683 usleep(1000); 684 685 g_server_sock_read = NULL; 686 rc = spdk_sock_group_poll_count(group, 1); 687 CU_ASSERT(rc == 1); 688 CU_ASSERT(g_server_sock_read == server_sock[1]); 689 690 g_server_sock_read = NULL; 691 rc = spdk_sock_group_poll_count(group, 1); 692 CU_ASSERT(rc == 1); 693 CU_ASSERT(g_server_sock_read == server_sock[2]); 694 695 g_server_sock_read = NULL; 696 rc = spdk_sock_group_poll_count(group, 1); 697 CU_ASSERT(rc == 1); 698 CU_ASSERT(g_server_sock_read == server_sock[0]); 699 700 for (i = 0; i < 3; i++) { 701 rc = spdk_sock_group_remove_sock(group, server_sock[i]); 702 CU_ASSERT(rc == 0); 703 704 rc = spdk_sock_close(&client_sock[i]); 705 CU_ASSERT(client_sock[i] == NULL); 706 CU_ASSERT(rc == 0); 707 708 rc = spdk_sock_close(&server_sock[i]); 709 CU_ASSERT(server_sock[i] == NULL); 710 CU_ASSERT(rc == 0); 711 } 712 713 rc = spdk_sock_group_close(&group); 714 CU_ASSERT(group == NULL); 715 CU_ASSERT(rc == 0); 716 717 rc = spdk_sock_close(&listen_sock); 718 CU_ASSERT(listen_sock == NULL); 719 CU_ASSERT(rc == 0); 720 } 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 _first_close_cb(void *cb_arg, int err) 730 { 731 struct close_ctx *ctx = cb_arg; 732 int rc; 733 734 ctx->called = true; 735 736 /* Always close the socket here */ 737 rc = spdk_sock_group_remove_sock(ctx->group, ctx->sock); 738 CU_ASSERT(rc == 0); 739 spdk_sock_close(&ctx->sock); 740 741 CU_ASSERT(err == 0); 742 } 743 744 static void 745 _second_close_cb(void *cb_arg, int err) 746 { 747 *(bool *)cb_arg = true; 748 CU_ASSERT(err == -ECANCELED); 749 } 750 751 static void 752 _sock_close(const char *ip, int port, char *impl_name) 753 { 754 struct spdk_sock_group *group; 755 struct spdk_sock *listen_sock; 756 struct spdk_sock *server_sock; 757 struct spdk_sock *client_sock; 758 uint8_t data_buf[64] = {}; 759 struct spdk_sock_request *req1, *req2; 760 struct close_ctx ctx = {}; 761 bool cb_arg2 = false; 762 int rc; 763 764 listen_sock = spdk_sock_listen(ip, port, impl_name); 765 SPDK_CU_ASSERT_FATAL(listen_sock != NULL); 766 767 client_sock = spdk_sock_connect(ip, port, impl_name); 768 SPDK_CU_ASSERT_FATAL(client_sock != NULL); 769 770 usleep(1000); 771 772 server_sock = spdk_sock_accept(listen_sock); 773 SPDK_CU_ASSERT_FATAL(server_sock != NULL); 774 775 group = spdk_sock_group_create(NULL); 776 SPDK_CU_ASSERT_FATAL(group != NULL); 777 778 rc = spdk_sock_group_add_sock(group, server_sock, read_data, server_sock); 779 CU_ASSERT(rc == 0); 780 781 /* Submit multiple async writevs on the server sock */ 782 783 req1 = calloc(1, sizeof(struct spdk_sock_request) + sizeof(struct iovec)); 784 SPDK_CU_ASSERT_FATAL(req1 != NULL); 785 SPDK_SOCK_REQUEST_IOV(req1, 0)->iov_base = data_buf; 786 SPDK_SOCK_REQUEST_IOV(req1, 0)->iov_len = 64; 787 ctx.group = group; 788 ctx.sock = server_sock; 789 ctx.called = false; 790 req1->iovcnt = 1; 791 req1->cb_fn = _first_close_cb; 792 req1->cb_arg = &ctx; 793 spdk_sock_writev_async(server_sock, req1); 794 CU_ASSERT(ctx.called == false); 795 796 req2 = calloc(1, sizeof(struct spdk_sock_request) + sizeof(struct iovec)); 797 SPDK_CU_ASSERT_FATAL(req2 != NULL); 798 SPDK_SOCK_REQUEST_IOV(req2, 0)->iov_base = data_buf; 799 SPDK_SOCK_REQUEST_IOV(req2, 0)->iov_len = 64; 800 req2->iovcnt = 1; 801 req2->cb_fn = _second_close_cb; 802 req2->cb_arg = &cb_arg2; 803 spdk_sock_writev_async(server_sock, req2); 804 CU_ASSERT(cb_arg2 == false); 805 806 /* Test spdk_sock_flush when sock is NULL */ 807 rc = spdk_sock_flush(NULL); 808 CU_ASSERT(rc == -1); 809 CU_ASSERT(errno == EBADF); 810 811 /* Test spdk_sock_flush when sock is not NULL */ 812 rc = spdk_sock_flush(client_sock); 813 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 spdk_sock_group_poll(group); 818 if (ctx.called == false) { 819 /* Sometimes the zerocopy completion isn't posted immediately. Delay slightly 820 * and poll one more time. */ 821 usleep(1000); 822 spdk_sock_group_poll(group); 823 } 824 CU_ASSERT(ctx.called == true); 825 CU_ASSERT(cb_arg2 == true); 826 827 rc = spdk_sock_group_close(&group); 828 CU_ASSERT(group == NULL); 829 CU_ASSERT(rc == 0); 830 831 rc = spdk_sock_close(&client_sock); 832 CU_ASSERT(client_sock == NULL); 833 CU_ASSERT(rc == 0); 834 835 rc = spdk_sock_close(&listen_sock); 836 CU_ASSERT(listen_sock == NULL); 837 CU_ASSERT(rc == 0); 838 839 free(req1); 840 free(req2); 841 } 842 843 static void 844 _posix_sock_close(void) 845 { 846 _sock_close("127.0.0.1", UT_PORT, "posix"); 847 } 848 849 static void 850 sock_get_default_opts(void) 851 { 852 struct spdk_sock_opts opts; 853 854 /* opts_size is 0 */ 855 opts.opts_size = 0; 856 opts.priority = 3; 857 spdk_sock_get_default_opts(&opts); 858 CU_ASSERT(opts.priority == 3); 859 CU_ASSERT(opts.opts_size == 0); 860 861 /* opts_size is less than sizeof(opts) */ 862 opts.opts_size = 4; 863 opts.priority = 3; 864 spdk_sock_get_default_opts(&opts); 865 CU_ASSERT(opts.priority == 3); 866 CU_ASSERT(opts.opts_size == 4); 867 868 /* opts_size is equal to sizeof(opts) */ 869 opts.opts_size = sizeof(opts); 870 opts.priority = 3; 871 spdk_sock_get_default_opts(&opts); 872 CU_ASSERT(opts.priority == SPDK_SOCK_DEFAULT_PRIORITY); 873 CU_ASSERT(opts.opts_size == sizeof(opts)); 874 875 /* opts_size is larger then sizeof(opts) */ 876 opts.opts_size = sizeof(opts) + 1; 877 opts.priority = 3; 878 spdk_sock_get_default_opts(&opts); 879 CU_ASSERT(opts.priority == SPDK_SOCK_DEFAULT_PRIORITY); 880 CU_ASSERT(opts.opts_size == (sizeof(opts) + 1)); 881 } 882 883 static void 884 ut_sock_impl_get_set_opts(void) 885 { 886 int rc; 887 size_t len = 0; 888 /* Use any pointer value for opts. It is never dereferenced in this test */ 889 struct spdk_sock_impl_opts *opts = (struct spdk_sock_impl_opts *)0x123456789; 890 891 rc = spdk_sock_impl_get_opts("ut", NULL, &len); 892 CU_ASSERT(rc == -1); 893 CU_ASSERT(errno == EINVAL); 894 rc = spdk_sock_impl_get_opts("ut", opts, NULL); 895 CU_ASSERT(rc == -1); 896 CU_ASSERT(errno == EINVAL); 897 rc = spdk_sock_impl_get_opts("ut", opts, &len); 898 CU_ASSERT(rc == -1); 899 CU_ASSERT(errno == ENOTSUP); 900 901 rc = spdk_sock_impl_set_opts("ut", NULL, len); 902 CU_ASSERT(rc == -1); 903 CU_ASSERT(errno == EINVAL); 904 rc = spdk_sock_impl_set_opts("ut", opts, len); 905 CU_ASSERT(rc == -1); 906 CU_ASSERT(errno == ENOTSUP); 907 } 908 909 static void 910 posix_sock_impl_get_set_opts(void) 911 { 912 int rc; 913 size_t len = 0; 914 struct spdk_sock_impl_opts opts = {}; 915 916 rc = spdk_sock_impl_get_opts("posix", NULL, &len); 917 CU_ASSERT(rc == -1); 918 CU_ASSERT(errno == EINVAL); 919 rc = spdk_sock_impl_get_opts("posix", &opts, NULL); 920 CU_ASSERT(rc == -1); 921 CU_ASSERT(errno == EINVAL); 922 923 /* Check default opts */ 924 len = sizeof(opts); 925 rc = spdk_sock_impl_get_opts("posix", &opts, &len); 926 CU_ASSERT(rc == 0); 927 CU_ASSERT(len == sizeof(opts)); 928 CU_ASSERT(opts.recv_buf_size == MIN_SO_RCVBUF_SIZE); 929 CU_ASSERT(opts.send_buf_size == MIN_SO_SNDBUF_SIZE); 930 931 /* Try to request zero opts */ 932 len = 0; 933 rc = spdk_sock_impl_get_opts("posix", &opts, &len); 934 CU_ASSERT(rc == 0); 935 CU_ASSERT(len == 0); 936 937 rc = spdk_sock_impl_set_opts("posix", NULL, len); 938 CU_ASSERT(rc == -1); 939 CU_ASSERT(errno == EINVAL); 940 941 opts.recv_buf_size = 16; 942 opts.send_buf_size = 4; 943 rc = spdk_sock_impl_set_opts("posix", &opts, sizeof(opts)); 944 CU_ASSERT(rc == 0); 945 len = sizeof(opts); 946 memset(&opts, 0, sizeof(opts)); 947 rc = spdk_sock_impl_get_opts("posix", &opts, &len); 948 CU_ASSERT(rc == 0); 949 CU_ASSERT(opts.recv_buf_size == 16); 950 CU_ASSERT(opts.send_buf_size == 4); 951 952 /* Try to set less opts. Opts in the end should be untouched */ 953 opts.recv_buf_size = 5; 954 opts.send_buf_size = 10; 955 rc = spdk_sock_impl_set_opts("posix", &opts, sizeof(opts.recv_buf_size)); 956 CU_ASSERT(rc == 0); 957 len = sizeof(opts); 958 memset(&opts, 0, sizeof(opts)); 959 rc = spdk_sock_impl_get_opts("posix", &opts, &len); 960 CU_ASSERT(rc == 0); 961 CU_ASSERT(opts.recv_buf_size == 5); 962 CU_ASSERT(opts.send_buf_size == 4); 963 964 /* Try to set partial option. It should not be changed */ 965 opts.recv_buf_size = 1000; 966 rc = spdk_sock_impl_set_opts("posix", &opts, 1); 967 CU_ASSERT(rc == 0); 968 len = sizeof(opts); 969 memset(&opts, 0, sizeof(opts)); 970 rc = spdk_sock_impl_get_opts("posix", &opts, &len); 971 CU_ASSERT(rc == 0); 972 CU_ASSERT(opts.recv_buf_size == 5); 973 } 974 975 static void 976 ut_sock_map(void) 977 { 978 struct spdk_sock_map map = { 979 .entries = STAILQ_HEAD_INITIALIZER(map.entries), 980 .mtx = PTHREAD_MUTEX_INITIALIZER 981 }; 982 struct spdk_sock_group_impl *group_1, *group_2, *test_group; 983 int rc; 984 int test_id; 985 986 group_1 = spdk_ut_sock_group_impl_create(); 987 group_2 = spdk_ut_sock_group_impl_create(); 988 989 /* Test 1 990 * Sanity check when sock_map is empty */ 991 test_id = spdk_sock_map_find_free(&map); 992 CU_ASSERT(test_id == -1); 993 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 /* Test 2 1000 * Insert single entry */ 1001 rc = spdk_sock_map_insert(&map, 1, group_1); 1002 CU_ASSERT(rc == 0); 1003 1004 test_group = NULL; 1005 rc = spdk_sock_map_lookup(&map, 1, &test_group, NULL); 1006 CU_ASSERT(rc == 0); 1007 CU_ASSERT(test_group == group_1); 1008 1009 /* There is single entry allocated, but it is not free */ 1010 test_id = spdk_sock_map_find_free(&map); 1011 CU_ASSERT(test_id == -1); 1012 1013 /* Free the entry and verify */ 1014 spdk_sock_map_release(&map, 1); 1015 test_id = spdk_sock_map_find_free(&map); 1016 CU_ASSERT(test_id == 1); 1017 1018 spdk_sock_map_cleanup(&map); 1019 1020 /* Test 3 1021 * Insert sock_group into placement_id multiple times */ 1022 rc = spdk_sock_map_insert(&map, 1, group_1); 1023 CU_ASSERT(rc == 0); 1024 CU_ASSERT(STAILQ_FIRST(&map.entries)->ref == 1); 1025 rc = spdk_sock_map_insert(&map, 1, group_1); 1026 CU_ASSERT(rc == 0); 1027 CU_ASSERT(STAILQ_FIRST(&map.entries)->ref == 2); 1028 1029 /* Release entry once and see that it still exists. */ 1030 spdk_sock_map_release(&map, 1); 1031 test_group = NULL; 1032 rc = spdk_sock_map_lookup(&map, 1, &test_group, NULL); 1033 CU_ASSERT(rc == 0); 1034 CU_ASSERT(test_group == group_1); 1035 1036 /* Release entry second and final time. */ 1037 spdk_sock_map_release(&map, 1); 1038 test_group = NULL; 1039 rc = spdk_sock_map_lookup(&map, 1, &test_group, NULL); 1040 CU_ASSERT(rc == -EINVAL); 1041 CU_ASSERT(test_group == NULL); 1042 1043 spdk_sock_map_cleanup(&map); 1044 1045 /* Test 4 1046 * Test multiple entries */ 1047 rc = spdk_sock_map_insert(&map, 1, group_1); 1048 CU_ASSERT(rc == 0); 1049 1050 test_group = NULL; 1051 rc = spdk_sock_map_lookup(&map, 1, &test_group, NULL); 1052 CU_ASSERT(rc == 0); 1053 CU_ASSERT(test_group == group_1); 1054 1055 rc = spdk_sock_map_insert(&map, 2, group_2); 1056 CU_ASSERT(rc == 0); 1057 1058 test_group = NULL; 1059 rc = spdk_sock_map_lookup(&map, 2, &test_group, NULL); 1060 CU_ASSERT(rc == 0); 1061 CU_ASSERT(test_group == group_2); 1062 1063 spdk_sock_map_cleanup(&map); 1064 1065 /* Test 5 1066 * Attempt inserting multiple entries into single placement_id */ 1067 rc = spdk_sock_map_insert(&map, 1, group_1); 1068 CU_ASSERT(rc == 0); 1069 1070 test_group = NULL; 1071 rc = spdk_sock_map_lookup(&map, 1, &test_group, NULL); 1072 CU_ASSERT(rc == 0); 1073 CU_ASSERT(test_group == group_1); 1074 1075 rc = spdk_sock_map_insert(&map, 1, group_2); 1076 CU_ASSERT(rc == -EINVAL); 1077 1078 test_group = NULL; 1079 rc = spdk_sock_map_lookup(&map, 1, &test_group, NULL); 1080 CU_ASSERT(rc == 0); 1081 CU_ASSERT(test_group == group_1); 1082 1083 spdk_sock_map_cleanup(&map); 1084 1085 /* Test 6 1086 * Insert single entry without a sock_group */ 1087 rc = spdk_sock_map_insert(&map, 1, NULL); 1088 CU_ASSERT(rc == 0); 1089 1090 test_group = NULL; 1091 rc = spdk_sock_map_lookup(&map, 1, &test_group, NULL); 1092 CU_ASSERT(rc == -EINVAL); 1093 CU_ASSERT(test_group == NULL); 1094 1095 test_id = spdk_sock_map_find_free(&map); 1096 CU_ASSERT(test_id == 1); 1097 1098 rc = spdk_sock_map_insert(&map, test_id, group_1); 1099 CU_ASSERT(rc == 0); 1100 1101 test_group = NULL; 1102 rc = spdk_sock_map_lookup(&map, test_id, &test_group, NULL); 1103 CU_ASSERT(rc == 0); 1104 CU_ASSERT(test_group == group_1); 1105 1106 spdk_sock_map_cleanup(&map); 1107 1108 /* Test 6 1109 * Use hint sock_group for for placement_id */ 1110 test_group = NULL; 1111 rc = spdk_sock_map_lookup(&map, 1, &test_group, group_1); 1112 CU_ASSERT(rc == 0); 1113 CU_ASSERT(test_group == NULL); 1114 1115 test_group = NULL; 1116 rc = spdk_sock_map_lookup(&map, 1, &test_group, NULL); 1117 CU_ASSERT(rc == 0); 1118 CU_ASSERT(test_group == group_1); 1119 1120 test_id = spdk_sock_map_find_free(&map); 1121 CU_ASSERT(test_id == -1); 1122 1123 rc = spdk_sock_map_insert(&map, 1, group_2); 1124 CU_ASSERT(rc == -EINVAL); 1125 1126 rc = spdk_sock_map_insert(&map, 1, group_1); 1127 CU_ASSERT(rc == 0); 1128 1129 spdk_sock_map_cleanup(&map); 1130 1131 spdk_ut_sock_group_impl_close(group_2); 1132 spdk_ut_sock_group_impl_close(group_1); 1133 } 1134 1135 static void 1136 override_impl_opts(void) 1137 { 1138 struct spdk_sock *lsock, *csock, *asock; 1139 struct spdk_sock_opts opts; 1140 struct spdk_sock_impl_opts impl_opts; 1141 uint32_t send_buf_size; 1142 size_t opts_size; 1143 int rc; 1144 1145 opts_size = sizeof(impl_opts); 1146 rc = spdk_sock_impl_get_opts("posix", &impl_opts, &opts_size); 1147 CU_ASSERT_EQUAL(rc, 0); 1148 opts.opts_size = sizeof(opts); 1149 spdk_sock_get_default_opts(&opts); 1150 opts.impl_opts = &impl_opts; 1151 opts.impl_opts_size = sizeof(impl_opts); 1152 1153 /* Use send_buf_size to verify that impl_opts get overridden */ 1154 send_buf_size = impl_opts.send_buf_size; 1155 impl_opts.send_buf_size = send_buf_size + 1; 1156 1157 lsock = spdk_sock_listen_ext("127.0.0.1", UT_PORT, "posix", &opts); 1158 SPDK_CU_ASSERT_FATAL(lsock != NULL); 1159 CU_ASSERT_EQUAL(lsock->impl_opts.send_buf_size, send_buf_size + 1); 1160 1161 /* Check the same for connect() */ 1162 opts_size = sizeof(impl_opts); 1163 rc = spdk_sock_impl_get_opts("posix", &impl_opts, &opts_size); 1164 CU_ASSERT_EQUAL(rc, 0); 1165 opts.opts_size = sizeof(opts); 1166 spdk_sock_get_default_opts(&opts); 1167 opts.impl_opts = &impl_opts; 1168 opts.impl_opts_size = sizeof(impl_opts); 1169 1170 impl_opts.send_buf_size = send_buf_size + 2; 1171 1172 csock = spdk_sock_connect_ext("127.0.0.1", UT_PORT, "posix", &opts); 1173 SPDK_CU_ASSERT_FATAL(csock != NULL); 1174 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 asock = spdk_sock_accept(lsock); 1178 SPDK_CU_ASSERT_FATAL(asock != NULL); 1179 CU_ASSERT_EQUAL(asock->impl_opts.send_buf_size, send_buf_size + 1); 1180 1181 spdk_sock_close(&asock); 1182 spdk_sock_close(&csock); 1183 spdk_sock_close(&lsock); 1184 1185 /* Check that impl_opts_size is verified by setting it to the offset of send_buf_size */ 1186 opts_size = sizeof(impl_opts); 1187 rc = spdk_sock_impl_get_opts("posix", &impl_opts, &opts_size); 1188 CU_ASSERT_EQUAL(rc, 0); 1189 opts.opts_size = sizeof(opts); 1190 spdk_sock_get_default_opts(&opts); 1191 opts.impl_opts = &impl_opts; 1192 opts.impl_opts_size = offsetof(struct spdk_sock_impl_opts, send_buf_size); 1193 1194 send_buf_size = impl_opts.send_buf_size; 1195 impl_opts.send_buf_size = send_buf_size + 1; 1196 1197 lsock = spdk_sock_listen_ext("127.0.0.1", UT_PORT, "posix", &opts); 1198 SPDK_CU_ASSERT_FATAL(lsock != NULL); 1199 CU_ASSERT_EQUAL(lsock->impl_opts.send_buf_size, send_buf_size); 1200 1201 /* Check the same for connect() */ 1202 opts_size = sizeof(impl_opts); 1203 rc = spdk_sock_impl_get_opts("posix", &impl_opts, &opts_size); 1204 CU_ASSERT_EQUAL(rc, 0); 1205 opts.opts_size = sizeof(opts); 1206 spdk_sock_get_default_opts(&opts); 1207 opts.impl_opts = &impl_opts; 1208 opts.impl_opts_size = offsetof(struct spdk_sock_impl_opts, send_buf_size); 1209 1210 impl_opts.send_buf_size = send_buf_size + 2; 1211 1212 csock = spdk_sock_connect_ext("127.0.0.1", UT_PORT, "posix", &opts); 1213 SPDK_CU_ASSERT_FATAL(csock != NULL); 1214 CU_ASSERT_EQUAL(csock->impl_opts.send_buf_size, send_buf_size); 1215 1216 spdk_sock_close(&lsock); 1217 spdk_sock_close(&csock); 1218 } 1219 1220 static void 1221 ut_sock_group_get_ctx(void) 1222 { 1223 void *test_ctx = (void *)0xff0000000; 1224 void *test_ctx1 = (void *)0xfff000000; 1225 void *test_ctx2 = (void *)0xffff00000; 1226 struct spdk_sock_group group; 1227 1228 /* The return should be NULL */ 1229 test_ctx = spdk_sock_group_get_ctx(NULL); 1230 CU_ASSERT(test_ctx == NULL); 1231 1232 /* The group.ctx should be changed */ 1233 group.ctx = test_ctx1; 1234 test_ctx2 = spdk_sock_group_get_ctx(&group); 1235 1236 CU_ASSERT(test_ctx1 == test_ctx2); 1237 } 1238 1239 int 1240 main(int argc, char **argv) 1241 { 1242 CU_pSuite suite = NULL; 1243 unsigned int num_failures; 1244 1245 CU_set_error_action(CUEA_ABORT); 1246 CU_initialize_registry(); 1247 1248 suite = CU_add_suite("sock", NULL, NULL); 1249 1250 CU_ADD_TEST(suite, posix_sock); 1251 CU_ADD_TEST(suite, ut_sock); 1252 CU_ADD_TEST(suite, posix_sock_group); 1253 CU_ADD_TEST(suite, ut_sock_group); 1254 CU_ADD_TEST(suite, posix_sock_group_fairness); 1255 CU_ADD_TEST(suite, _posix_sock_close); 1256 CU_ADD_TEST(suite, sock_get_default_opts); 1257 CU_ADD_TEST(suite, ut_sock_impl_get_set_opts); 1258 CU_ADD_TEST(suite, posix_sock_impl_get_set_opts); 1259 CU_ADD_TEST(suite, ut_sock_map); 1260 CU_ADD_TEST(suite, override_impl_opts); 1261 CU_ADD_TEST(suite, ut_sock_group_get_ctx); 1262 1263 CU_basic_set_mode(CU_BRM_VERBOSE); 1264 1265 CU_basic_run_tests(); 1266 1267 num_failures = CU_get_number_of_failures(); 1268 CU_cleanup_registry(); 1269 1270 return num_failures; 1271 } 1272