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