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