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 == -EBADF); 809 810 /* Test spdk_sock_flush when sock is not NULL */ 811 rc = spdk_sock_flush(client_sock); 812 CU_ASSERT(rc == 0); 813 814 /* Poll the socket so the writev_async's send. The first one's 815 * callback will close the socket. */ 816 spdk_sock_group_poll(group); 817 if (ctx.called == false) { 818 /* Sometimes the zerocopy completion isn't posted immediately. Delay slightly 819 * and poll one more time. */ 820 usleep(1000); 821 spdk_sock_group_poll(group); 822 } 823 CU_ASSERT(ctx.called == true); 824 CU_ASSERT(cb_arg2 == true); 825 826 rc = spdk_sock_group_close(&group); 827 CU_ASSERT(group == NULL); 828 CU_ASSERT(rc == 0); 829 830 rc = spdk_sock_close(&client_sock); 831 CU_ASSERT(client_sock == NULL); 832 CU_ASSERT(rc == 0); 833 834 rc = spdk_sock_close(&listen_sock); 835 CU_ASSERT(listen_sock == NULL); 836 CU_ASSERT(rc == 0); 837 838 free(req1); 839 free(req2); 840 } 841 842 static void 843 _posix_sock_close(void) 844 { 845 _sock_close("127.0.0.1", UT_PORT, "posix"); 846 } 847 848 static void 849 sock_get_default_opts(void) 850 { 851 struct spdk_sock_opts opts; 852 853 /* opts_size is 0 */ 854 opts.opts_size = 0; 855 opts.priority = 3; 856 spdk_sock_get_default_opts(&opts); 857 CU_ASSERT(opts.priority == 3); 858 CU_ASSERT(opts.opts_size == 0); 859 860 /* opts_size is less than sizeof(opts) */ 861 opts.opts_size = 4; 862 opts.priority = 3; 863 spdk_sock_get_default_opts(&opts); 864 CU_ASSERT(opts.priority == 3); 865 CU_ASSERT(opts.opts_size == 4); 866 867 /* opts_size is equal to sizeof(opts) */ 868 opts.opts_size = sizeof(opts); 869 opts.priority = 3; 870 spdk_sock_get_default_opts(&opts); 871 CU_ASSERT(opts.priority == SPDK_SOCK_DEFAULT_PRIORITY); 872 CU_ASSERT(opts.opts_size == sizeof(opts)); 873 874 /* opts_size is larger then sizeof(opts) */ 875 opts.opts_size = sizeof(opts) + 1; 876 opts.priority = 3; 877 spdk_sock_get_default_opts(&opts); 878 CU_ASSERT(opts.priority == SPDK_SOCK_DEFAULT_PRIORITY); 879 CU_ASSERT(opts.opts_size == (sizeof(opts) + 1)); 880 } 881 882 static void 883 ut_sock_impl_get_set_opts(void) 884 { 885 int rc; 886 size_t len = 0; 887 /* Use any pointer value for opts. It is never dereferenced in this test */ 888 struct spdk_sock_impl_opts *opts = (struct spdk_sock_impl_opts *)0x123456789; 889 890 rc = spdk_sock_impl_get_opts("ut", NULL, &len); 891 CU_ASSERT(rc == -1); 892 CU_ASSERT(errno == EINVAL); 893 rc = spdk_sock_impl_get_opts("ut", opts, NULL); 894 CU_ASSERT(rc == -1); 895 CU_ASSERT(errno == EINVAL); 896 rc = spdk_sock_impl_get_opts("ut", opts, &len); 897 CU_ASSERT(rc == -1); 898 CU_ASSERT(errno == ENOTSUP); 899 900 rc = spdk_sock_impl_set_opts("ut", NULL, len); 901 CU_ASSERT(rc == -1); 902 CU_ASSERT(errno == EINVAL); 903 rc = spdk_sock_impl_set_opts("ut", opts, len); 904 CU_ASSERT(rc == -1); 905 CU_ASSERT(errno == ENOTSUP); 906 } 907 908 static void 909 posix_sock_impl_get_set_opts(void) 910 { 911 int rc; 912 size_t len = 0; 913 struct spdk_sock_impl_opts opts = {}; 914 915 rc = spdk_sock_impl_get_opts("posix", NULL, &len); 916 CU_ASSERT(rc == -1); 917 CU_ASSERT(errno == EINVAL); 918 rc = spdk_sock_impl_get_opts("posix", &opts, NULL); 919 CU_ASSERT(rc == -1); 920 CU_ASSERT(errno == EINVAL); 921 922 /* Check default opts */ 923 len = sizeof(opts); 924 rc = spdk_sock_impl_get_opts("posix", &opts, &len); 925 CU_ASSERT(rc == 0); 926 CU_ASSERT(len == sizeof(opts)); 927 CU_ASSERT(opts.recv_buf_size == MIN_SO_RCVBUF_SIZE); 928 CU_ASSERT(opts.send_buf_size == MIN_SO_SNDBUF_SIZE); 929 930 /* Try to request zero opts */ 931 len = 0; 932 rc = spdk_sock_impl_get_opts("posix", &opts, &len); 933 CU_ASSERT(rc == 0); 934 CU_ASSERT(len == 0); 935 936 rc = spdk_sock_impl_set_opts("posix", NULL, len); 937 CU_ASSERT(rc == -1); 938 CU_ASSERT(errno == EINVAL); 939 940 opts.recv_buf_size = 16; 941 opts.send_buf_size = 4; 942 rc = spdk_sock_impl_set_opts("posix", &opts, sizeof(opts)); 943 CU_ASSERT(rc == 0); 944 len = sizeof(opts); 945 memset(&opts, 0, sizeof(opts)); 946 rc = spdk_sock_impl_get_opts("posix", &opts, &len); 947 CU_ASSERT(rc == 0); 948 CU_ASSERT(opts.recv_buf_size == 16); 949 CU_ASSERT(opts.send_buf_size == 4); 950 951 /* Try to set less opts. Opts in the end should be untouched */ 952 opts.recv_buf_size = 5; 953 opts.send_buf_size = 10; 954 rc = spdk_sock_impl_set_opts("posix", &opts, sizeof(opts.recv_buf_size)); 955 CU_ASSERT(rc == 0); 956 len = sizeof(opts); 957 memset(&opts, 0, sizeof(opts)); 958 rc = spdk_sock_impl_get_opts("posix", &opts, &len); 959 CU_ASSERT(rc == 0); 960 CU_ASSERT(opts.recv_buf_size == 5); 961 CU_ASSERT(opts.send_buf_size == 4); 962 963 /* Try to set partial option. It should not be changed */ 964 opts.recv_buf_size = 1000; 965 rc = spdk_sock_impl_set_opts("posix", &opts, 1); 966 CU_ASSERT(rc == 0); 967 len = sizeof(opts); 968 memset(&opts, 0, sizeof(opts)); 969 rc = spdk_sock_impl_get_opts("posix", &opts, &len); 970 CU_ASSERT(rc == 0); 971 CU_ASSERT(opts.recv_buf_size == 5); 972 } 973 974 static void 975 ut_sock_map(void) 976 { 977 struct spdk_sock_map map = { 978 .entries = STAILQ_HEAD_INITIALIZER(map.entries), 979 .mtx = PTHREAD_MUTEX_INITIALIZER 980 }; 981 struct spdk_sock_group_impl *group_1, *group_2, *test_group; 982 int rc; 983 int test_id; 984 985 group_1 = spdk_ut_sock_group_impl_create(); 986 group_2 = spdk_ut_sock_group_impl_create(); 987 988 /* Test 1 989 * Sanity check when sock_map is empty */ 990 test_id = spdk_sock_map_find_free(&map); 991 CU_ASSERT(test_id == -1); 992 993 test_group = NULL; 994 rc = spdk_sock_map_lookup(&map, 1, &test_group, NULL); 995 CU_ASSERT(rc == -EINVAL); 996 CU_ASSERT(test_group == NULL); 997 998 /* Test 2 999 * Insert single entry */ 1000 rc = spdk_sock_map_insert(&map, 1, group_1); 1001 CU_ASSERT(rc == 0); 1002 1003 test_group = NULL; 1004 rc = spdk_sock_map_lookup(&map, 1, &test_group, NULL); 1005 CU_ASSERT(rc == 0); 1006 CU_ASSERT(test_group == group_1); 1007 1008 /* There is single entry allocated, but it is not free */ 1009 test_id = spdk_sock_map_find_free(&map); 1010 CU_ASSERT(test_id == -1); 1011 1012 /* Free the entry and verify */ 1013 spdk_sock_map_release(&map, 1); 1014 test_id = spdk_sock_map_find_free(&map); 1015 CU_ASSERT(test_id == 1); 1016 1017 spdk_sock_map_cleanup(&map); 1018 1019 /* Test 3 1020 * Insert sock_group into placement_id multiple times */ 1021 rc = spdk_sock_map_insert(&map, 1, group_1); 1022 CU_ASSERT(rc == 0); 1023 CU_ASSERT(STAILQ_FIRST(&map.entries)->ref == 1); 1024 rc = spdk_sock_map_insert(&map, 1, group_1); 1025 CU_ASSERT(rc == 0); 1026 CU_ASSERT(STAILQ_FIRST(&map.entries)->ref == 2); 1027 1028 /* Release entry once and see that it still exists. */ 1029 spdk_sock_map_release(&map, 1); 1030 test_group = NULL; 1031 rc = spdk_sock_map_lookup(&map, 1, &test_group, NULL); 1032 CU_ASSERT(rc == 0); 1033 CU_ASSERT(test_group == group_1); 1034 1035 /* Release entry second and final time. */ 1036 spdk_sock_map_release(&map, 1); 1037 test_group = NULL; 1038 rc = spdk_sock_map_lookup(&map, 1, &test_group, NULL); 1039 CU_ASSERT(rc == -EINVAL); 1040 CU_ASSERT(test_group == NULL); 1041 1042 spdk_sock_map_cleanup(&map); 1043 1044 /* Test 4 1045 * Test multiple entries */ 1046 rc = spdk_sock_map_insert(&map, 1, group_1); 1047 CU_ASSERT(rc == 0); 1048 1049 test_group = NULL; 1050 rc = spdk_sock_map_lookup(&map, 1, &test_group, NULL); 1051 CU_ASSERT(rc == 0); 1052 CU_ASSERT(test_group == group_1); 1053 1054 rc = spdk_sock_map_insert(&map, 2, group_2); 1055 CU_ASSERT(rc == 0); 1056 1057 test_group = NULL; 1058 rc = spdk_sock_map_lookup(&map, 2, &test_group, NULL); 1059 CU_ASSERT(rc == 0); 1060 CU_ASSERT(test_group == group_2); 1061 1062 spdk_sock_map_cleanup(&map); 1063 1064 /* Test 5 1065 * Attempt inserting multiple entries into single placement_id */ 1066 rc = spdk_sock_map_insert(&map, 1, group_1); 1067 CU_ASSERT(rc == 0); 1068 1069 test_group = NULL; 1070 rc = spdk_sock_map_lookup(&map, 1, &test_group, NULL); 1071 CU_ASSERT(rc == 0); 1072 CU_ASSERT(test_group == group_1); 1073 1074 rc = spdk_sock_map_insert(&map, 1, group_2); 1075 CU_ASSERT(rc == -EINVAL); 1076 1077 test_group = NULL; 1078 rc = spdk_sock_map_lookup(&map, 1, &test_group, NULL); 1079 CU_ASSERT(rc == 0); 1080 CU_ASSERT(test_group == group_1); 1081 1082 spdk_sock_map_cleanup(&map); 1083 1084 /* Test 6 1085 * Insert single entry without a sock_group */ 1086 rc = spdk_sock_map_insert(&map, 1, NULL); 1087 CU_ASSERT(rc == 0); 1088 1089 test_group = NULL; 1090 rc = spdk_sock_map_lookup(&map, 1, &test_group, NULL); 1091 CU_ASSERT(rc == -EINVAL); 1092 CU_ASSERT(test_group == NULL); 1093 1094 test_id = spdk_sock_map_find_free(&map); 1095 CU_ASSERT(test_id == 1); 1096 1097 rc = spdk_sock_map_insert(&map, test_id, group_1); 1098 CU_ASSERT(rc == 0); 1099 1100 test_group = NULL; 1101 rc = spdk_sock_map_lookup(&map, test_id, &test_group, NULL); 1102 CU_ASSERT(rc == 0); 1103 CU_ASSERT(test_group == group_1); 1104 1105 spdk_sock_map_cleanup(&map); 1106 1107 /* Test 6 1108 * Use hint sock_group for for placement_id */ 1109 test_group = NULL; 1110 rc = spdk_sock_map_lookup(&map, 1, &test_group, group_1); 1111 CU_ASSERT(rc == 0); 1112 CU_ASSERT(test_group == NULL); 1113 1114 test_group = NULL; 1115 rc = spdk_sock_map_lookup(&map, 1, &test_group, NULL); 1116 CU_ASSERT(rc == 0); 1117 CU_ASSERT(test_group == group_1); 1118 1119 test_id = spdk_sock_map_find_free(&map); 1120 CU_ASSERT(test_id == -1); 1121 1122 rc = spdk_sock_map_insert(&map, 1, group_2); 1123 CU_ASSERT(rc == -EINVAL); 1124 1125 rc = spdk_sock_map_insert(&map, 1, group_1); 1126 CU_ASSERT(rc == 0); 1127 1128 spdk_sock_map_cleanup(&map); 1129 1130 spdk_ut_sock_group_impl_close(group_2); 1131 spdk_ut_sock_group_impl_close(group_1); 1132 } 1133 1134 static void 1135 override_impl_opts(void) 1136 { 1137 struct spdk_sock *lsock, *csock, *asock; 1138 struct spdk_sock_opts opts; 1139 struct spdk_sock_impl_opts impl_opts; 1140 uint32_t send_buf_size; 1141 size_t opts_size; 1142 int rc; 1143 1144 opts_size = sizeof(impl_opts); 1145 rc = spdk_sock_impl_get_opts("posix", &impl_opts, &opts_size); 1146 CU_ASSERT_EQUAL(rc, 0); 1147 opts.opts_size = sizeof(opts); 1148 spdk_sock_get_default_opts(&opts); 1149 opts.impl_opts = &impl_opts; 1150 opts.impl_opts_size = sizeof(impl_opts); 1151 1152 /* Use send_buf_size to verify that impl_opts get overriden */ 1153 send_buf_size = impl_opts.send_buf_size; 1154 impl_opts.send_buf_size = send_buf_size + 1; 1155 1156 lsock = spdk_sock_listen_ext("127.0.0.1", UT_PORT, "posix", &opts); 1157 SPDK_CU_ASSERT_FATAL(lsock != NULL); 1158 CU_ASSERT_EQUAL(lsock->impl_opts.send_buf_size, send_buf_size + 1); 1159 1160 /* Check the same for connect() */ 1161 opts_size = sizeof(impl_opts); 1162 rc = spdk_sock_impl_get_opts("posix", &impl_opts, &opts_size); 1163 CU_ASSERT_EQUAL(rc, 0); 1164 opts.opts_size = sizeof(opts); 1165 spdk_sock_get_default_opts(&opts); 1166 opts.impl_opts = &impl_opts; 1167 opts.impl_opts_size = sizeof(impl_opts); 1168 1169 impl_opts.send_buf_size = send_buf_size + 2; 1170 1171 csock = spdk_sock_connect_ext("127.0.0.1", UT_PORT, "posix", &opts); 1172 SPDK_CU_ASSERT_FATAL(csock != NULL); 1173 CU_ASSERT_EQUAL(csock->impl_opts.send_buf_size, send_buf_size + 2); 1174 1175 /* Check that accept() inherits impl_opts from listen socket */ 1176 asock = spdk_sock_accept(lsock); 1177 SPDK_CU_ASSERT_FATAL(asock != NULL); 1178 CU_ASSERT_EQUAL(asock->impl_opts.send_buf_size, send_buf_size + 1); 1179 1180 spdk_sock_close(&asock); 1181 spdk_sock_close(&csock); 1182 spdk_sock_close(&lsock); 1183 1184 /* Check that impl_opts_size is verified by setting it to the offset of send_buf_size */ 1185 opts_size = sizeof(impl_opts); 1186 rc = spdk_sock_impl_get_opts("posix", &impl_opts, &opts_size); 1187 CU_ASSERT_EQUAL(rc, 0); 1188 opts.opts_size = sizeof(opts); 1189 spdk_sock_get_default_opts(&opts); 1190 opts.impl_opts = &impl_opts; 1191 opts.impl_opts_size = offsetof(struct spdk_sock_impl_opts, send_buf_size); 1192 1193 send_buf_size = impl_opts.send_buf_size; 1194 impl_opts.send_buf_size = send_buf_size + 1; 1195 1196 lsock = spdk_sock_listen_ext("127.0.0.1", UT_PORT, "posix", &opts); 1197 SPDK_CU_ASSERT_FATAL(lsock != NULL); 1198 CU_ASSERT_EQUAL(lsock->impl_opts.send_buf_size, send_buf_size); 1199 1200 /* Check the same for connect() */ 1201 opts_size = sizeof(impl_opts); 1202 rc = spdk_sock_impl_get_opts("posix", &impl_opts, &opts_size); 1203 CU_ASSERT_EQUAL(rc, 0); 1204 opts.opts_size = sizeof(opts); 1205 spdk_sock_get_default_opts(&opts); 1206 opts.impl_opts = &impl_opts; 1207 opts.impl_opts_size = offsetof(struct spdk_sock_impl_opts, send_buf_size); 1208 1209 impl_opts.send_buf_size = send_buf_size + 2; 1210 1211 csock = spdk_sock_connect_ext("127.0.0.1", UT_PORT, "posix", &opts); 1212 SPDK_CU_ASSERT_FATAL(csock != NULL); 1213 CU_ASSERT_EQUAL(csock->impl_opts.send_buf_size, send_buf_size); 1214 1215 spdk_sock_close(&lsock); 1216 spdk_sock_close(&csock); 1217 } 1218 1219 int 1220 main(int argc, char **argv) 1221 { 1222 CU_pSuite suite = NULL; 1223 unsigned int num_failures; 1224 1225 CU_set_error_action(CUEA_ABORT); 1226 CU_initialize_registry(); 1227 1228 suite = CU_add_suite("sock", NULL, NULL); 1229 1230 CU_ADD_TEST(suite, posix_sock); 1231 CU_ADD_TEST(suite, ut_sock); 1232 CU_ADD_TEST(suite, posix_sock_group); 1233 CU_ADD_TEST(suite, ut_sock_group); 1234 CU_ADD_TEST(suite, posix_sock_group_fairness); 1235 CU_ADD_TEST(suite, _posix_sock_close); 1236 CU_ADD_TEST(suite, sock_get_default_opts); 1237 CU_ADD_TEST(suite, ut_sock_impl_get_set_opts); 1238 CU_ADD_TEST(suite, posix_sock_impl_get_set_opts); 1239 CU_ADD_TEST(suite, ut_sock_map); 1240 CU_ADD_TEST(suite, override_impl_opts); 1241 1242 CU_basic_set_mode(CU_BRM_VERBOSE); 1243 1244 CU_basic_run_tests(); 1245 1246 num_failures = CU_get_number_of_failures(); 1247 CU_cleanup_registry(); 1248 1249 return num_failures; 1250 } 1251