1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. 5 * 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 "sock/sock.c" 40 #include "sock/posix/posix.c" 41 42 #define UT_IP "test_ip" 43 #define UT_PORT 1234 44 45 bool g_read_data_called; 46 ssize_t g_bytes_read; 47 char g_buf[256]; 48 struct spdk_sock *g_server_sock_read; 49 int g_ut_accept_count; 50 struct spdk_ut_sock *g_ut_listen_sock; 51 struct spdk_ut_sock *g_ut_client_sock; 52 53 struct spdk_ut_sock { 54 struct spdk_sock base; 55 struct spdk_ut_sock *peer; 56 size_t bytes_avail; 57 char buf[256]; 58 }; 59 60 struct spdk_ut_sock_group_impl { 61 struct spdk_sock_group_impl base; 62 struct spdk_ut_sock *sock; 63 }; 64 65 #define __ut_sock(sock) (struct spdk_ut_sock *)sock 66 #define __ut_group(group) (struct spdk_ut_sock_group_impl *)group 67 68 static int 69 spdk_ut_sock_getaddr(struct spdk_sock *_sock, char *saddr, int slen, uint16_t *sport, 70 char *caddr, int clen, uint16_t *cport) 71 { 72 return 0; 73 } 74 75 static struct spdk_sock * 76 spdk_ut_sock_listen(const char *ip, int port) 77 { 78 struct spdk_ut_sock *sock; 79 80 if (strcmp(ip, UT_IP) || port != UT_PORT) { 81 return NULL; 82 } 83 84 CU_ASSERT(g_ut_listen_sock == NULL); 85 86 sock = calloc(1, sizeof(*sock)); 87 SPDK_CU_ASSERT_FATAL(sock != NULL); 88 g_ut_listen_sock = sock; 89 90 return &sock->base; 91 } 92 93 static struct spdk_sock * 94 spdk_ut_sock_connect(const char *ip, int port) 95 { 96 struct spdk_ut_sock *sock; 97 98 if (strcmp(ip, UT_IP) || port != UT_PORT) { 99 return NULL; 100 } 101 102 sock = calloc(1, sizeof(*sock)); 103 SPDK_CU_ASSERT_FATAL(sock != NULL); 104 g_ut_accept_count++; 105 CU_ASSERT(g_ut_client_sock == NULL); 106 g_ut_client_sock = sock; 107 108 return &sock->base; 109 } 110 111 static struct spdk_sock * 112 spdk_ut_sock_accept(struct spdk_sock *_sock) 113 { 114 struct spdk_ut_sock *sock = __ut_sock(_sock); 115 struct spdk_ut_sock *new_sock; 116 117 CU_ASSERT(sock == g_ut_listen_sock); 118 119 if (g_ut_accept_count == 0) { 120 errno = EAGAIN; 121 return NULL; 122 } 123 124 g_ut_accept_count--; 125 new_sock = calloc(1, sizeof(*sock)); 126 if (new_sock == NULL) { 127 SPDK_ERRLOG("sock allocation failed\n"); 128 return NULL; 129 } 130 131 SPDK_CU_ASSERT_FATAL(g_ut_client_sock != NULL); 132 g_ut_client_sock->peer = new_sock; 133 134 return &new_sock->base; 135 } 136 137 static int 138 spdk_ut_sock_close(struct spdk_sock *_sock) 139 { 140 struct spdk_ut_sock *sock = __ut_sock(_sock); 141 142 if (sock == g_ut_listen_sock) { 143 g_ut_listen_sock = NULL; 144 } 145 if (sock == g_ut_client_sock) { 146 g_ut_client_sock = NULL; 147 } 148 free(_sock); 149 150 return 0; 151 } 152 153 static ssize_t 154 spdk_ut_sock_recv(struct spdk_sock *_sock, void *buf, size_t len) 155 { 156 struct spdk_ut_sock *sock = __ut_sock(_sock); 157 char tmp[256]; 158 159 len = spdk_min(len, sock->bytes_avail); 160 161 if (len == 0) { 162 errno = EAGAIN; 163 return -1; 164 } 165 166 memcpy(buf, sock->buf, len); 167 memcpy(tmp, &sock->buf[len], sock->bytes_avail - len); 168 memcpy(sock->buf, tmp, sock->bytes_avail - len); 169 sock->bytes_avail -= len; 170 171 return len; 172 } 173 174 static ssize_t 175 spdk_ut_sock_readv(struct spdk_sock *_sock, struct iovec *iov, int iovcnt) 176 { 177 struct spdk_ut_sock *sock = __ut_sock(_sock); 178 size_t len; 179 char tmp[256]; 180 181 /* Test implementation only supports single iov for now. */ 182 CU_ASSERT(iovcnt == 1); 183 184 len = spdk_min(iov[0].iov_len, sock->bytes_avail); 185 186 if (len == 0) { 187 errno = EAGAIN; 188 return -1; 189 } 190 191 memcpy(iov[0].iov_base, sock->buf, len); 192 memcpy(tmp, &sock->buf[len], sock->bytes_avail - len); 193 memcpy(sock->buf, tmp, sock->bytes_avail - len); 194 sock->bytes_avail -= len; 195 196 return len; 197 } 198 199 static ssize_t 200 spdk_ut_sock_writev(struct spdk_sock *_sock, struct iovec *iov, int iovcnt) 201 { 202 struct spdk_ut_sock *sock = __ut_sock(_sock); 203 struct spdk_ut_sock *peer; 204 205 SPDK_CU_ASSERT_FATAL(sock->peer != NULL); 206 peer = sock->peer; 207 208 /* Test implementation only supports single iov for now. */ 209 CU_ASSERT(iovcnt == 1); 210 211 memcpy(&peer->buf[peer->bytes_avail], iov[0].iov_base, iov[0].iov_len); 212 peer->bytes_avail += iov[0].iov_len; 213 214 return iov[0].iov_len; 215 } 216 217 static int 218 spdk_ut_sock_set_recvlowat(struct spdk_sock *_sock, int nbytes) 219 { 220 return 0; 221 } 222 223 static int 224 spdk_ut_sock_set_recvbuf(struct spdk_sock *_sock, int sz) 225 { 226 return 0; 227 } 228 229 static int 230 spdk_ut_sock_set_sendbuf(struct spdk_sock *_sock, int sz) 231 { 232 return 0; 233 } 234 235 static bool 236 spdk_ut_sock_is_ipv6(struct spdk_sock *_sock) 237 { 238 return false; 239 } 240 241 static bool 242 spdk_ut_sock_is_ipv4(struct spdk_sock *_sock) 243 { 244 return true; 245 } 246 247 static struct spdk_sock_group_impl * 248 spdk_ut_sock_group_impl_create(void) 249 { 250 struct spdk_ut_sock_group_impl *group_impl; 251 252 group_impl = calloc(1, sizeof(*group_impl)); 253 SPDK_CU_ASSERT_FATAL(group_impl != NULL); 254 255 return &group_impl->base; 256 } 257 258 static int 259 spdk_ut_sock_group_impl_add_sock(struct spdk_sock_group_impl *_group, struct spdk_sock *_sock) 260 { 261 struct spdk_ut_sock_group_impl *group = __ut_group(_group); 262 struct spdk_ut_sock *sock = __ut_sock(_sock); 263 264 group->sock = sock; 265 266 return 0; 267 } 268 269 static int 270 spdk_ut_sock_group_impl_remove_sock(struct spdk_sock_group_impl *_group, struct spdk_sock *_sock) 271 { 272 struct spdk_ut_sock_group_impl *group = __ut_group(_group); 273 struct spdk_ut_sock *sock = __ut_sock(_sock); 274 275 CU_ASSERT(group->sock == sock); 276 group->sock = NULL; 277 278 return 0; 279 } 280 281 static int 282 spdk_ut_sock_group_impl_poll(struct spdk_sock_group_impl *_group, int max_events, 283 struct spdk_sock **socks) 284 { 285 struct spdk_ut_sock_group_impl *group = __ut_group(_group); 286 287 if (group->sock != NULL && group->sock->bytes_avail > 0) { 288 socks[0] = &group->sock->base; 289 return 1; 290 } 291 292 return 0; 293 } 294 295 static int 296 spdk_ut_sock_group_impl_close(struct spdk_sock_group_impl *_group) 297 { 298 struct spdk_ut_sock_group_impl *group = __ut_group(_group); 299 300 CU_ASSERT(group->sock == NULL); 301 302 return 0; 303 } 304 305 static struct spdk_net_impl g_ut_net_impl = { 306 .name = "ut", 307 .getaddr = spdk_ut_sock_getaddr, 308 .connect = spdk_ut_sock_connect, 309 .listen = spdk_ut_sock_listen, 310 .accept = spdk_ut_sock_accept, 311 .close = spdk_ut_sock_close, 312 .recv = spdk_ut_sock_recv, 313 .readv = spdk_ut_sock_readv, 314 .writev = spdk_ut_sock_writev, 315 .set_recvlowat = spdk_ut_sock_set_recvlowat, 316 .set_recvbuf = spdk_ut_sock_set_recvbuf, 317 .set_sendbuf = spdk_ut_sock_set_sendbuf, 318 .is_ipv6 = spdk_ut_sock_is_ipv6, 319 .is_ipv4 = spdk_ut_sock_is_ipv4, 320 .group_impl_create = spdk_ut_sock_group_impl_create, 321 .group_impl_add_sock = spdk_ut_sock_group_impl_add_sock, 322 .group_impl_remove_sock = spdk_ut_sock_group_impl_remove_sock, 323 .group_impl_poll = spdk_ut_sock_group_impl_poll, 324 .group_impl_close = spdk_ut_sock_group_impl_close, 325 }; 326 327 SPDK_NET_IMPL_REGISTER(ut, &g_ut_net_impl); 328 329 static void 330 _sock(const char *ip, int port) 331 { 332 struct spdk_sock *listen_sock; 333 struct spdk_sock *server_sock; 334 struct spdk_sock *client_sock; 335 char *test_string = "abcdef"; 336 char buffer[64]; 337 ssize_t bytes_read, bytes_written; 338 struct iovec iov; 339 int rc; 340 341 listen_sock = spdk_sock_listen(ip, port); 342 SPDK_CU_ASSERT_FATAL(listen_sock != NULL); 343 344 server_sock = spdk_sock_accept(listen_sock); 345 CU_ASSERT(server_sock == NULL); 346 CU_ASSERT(errno == EAGAIN || errno == EWOULDBLOCK); 347 348 client_sock = spdk_sock_connect(ip, port); 349 SPDK_CU_ASSERT_FATAL(client_sock != NULL); 350 351 /* 352 * Delay a bit here before checking if server socket is 353 * ready. 354 */ 355 usleep(1000); 356 357 server_sock = spdk_sock_accept(listen_sock); 358 SPDK_CU_ASSERT_FATAL(server_sock != NULL); 359 360 /* Test spdk_sock_recv */ 361 iov.iov_base = test_string; 362 iov.iov_len = 7; 363 bytes_written = spdk_sock_writev(client_sock, &iov, 1); 364 CU_ASSERT(bytes_written == 7); 365 366 usleep(1000); 367 368 bytes_read = spdk_sock_recv(server_sock, buffer, 2); 369 CU_ASSERT(bytes_read == 2); 370 371 usleep(1000); 372 373 bytes_read += spdk_sock_recv(server_sock, buffer + 2, 5); 374 CU_ASSERT(bytes_read == 7); 375 376 CU_ASSERT(strncmp(test_string, buffer, 7) == 0); 377 378 /* Test spdk_sock_readv */ 379 iov.iov_base = test_string; 380 iov.iov_len = 7; 381 bytes_written = spdk_sock_writev(client_sock, &iov, 1); 382 CU_ASSERT(bytes_written == 7); 383 384 usleep(1000); 385 386 iov.iov_base = buffer; 387 iov.iov_len = 2; 388 bytes_read = spdk_sock_readv(server_sock, &iov, 1); 389 CU_ASSERT(bytes_read == 2); 390 391 usleep(1000); 392 393 iov.iov_base = buffer + 2; 394 iov.iov_len = 5; 395 bytes_read += spdk_sock_readv(server_sock, &iov, 1); 396 CU_ASSERT(bytes_read == 7); 397 398 usleep(1000); 399 400 CU_ASSERT(strncmp(test_string, buffer, 7) == 0); 401 402 rc = spdk_sock_close(&client_sock); 403 CU_ASSERT(client_sock == NULL); 404 CU_ASSERT(rc == 0); 405 406 rc = spdk_sock_close(&server_sock); 407 CU_ASSERT(server_sock == NULL); 408 CU_ASSERT(rc == 0); 409 410 rc = spdk_sock_close(&listen_sock); 411 CU_ASSERT(listen_sock == NULL); 412 CU_ASSERT(rc == 0); 413 } 414 415 static void 416 posix_sock(void) 417 { 418 _sock("127.0.0.1", UT_PORT); 419 } 420 421 static void 422 ut_sock(void) 423 { 424 _sock(UT_IP, UT_PORT); 425 } 426 427 static void 428 read_data(void *cb_arg, struct spdk_sock_group *group, struct spdk_sock *sock) 429 { 430 struct spdk_sock *server_sock = cb_arg; 431 432 CU_ASSERT(server_sock == sock); 433 434 g_read_data_called = true; 435 g_bytes_read += spdk_sock_recv(server_sock, g_buf + g_bytes_read, sizeof(g_buf) - g_bytes_read); 436 } 437 438 static void 439 _sock_group(const char *ip, int port) 440 { 441 struct spdk_sock_group *group; 442 struct spdk_sock *listen_sock; 443 struct spdk_sock *server_sock; 444 struct spdk_sock *client_sock; 445 char *test_string = "abcdef"; 446 ssize_t bytes_written; 447 struct iovec iov; 448 int rc; 449 450 listen_sock = spdk_sock_listen(ip, port); 451 SPDK_CU_ASSERT_FATAL(listen_sock != NULL); 452 453 server_sock = spdk_sock_accept(listen_sock); 454 CU_ASSERT(server_sock == NULL); 455 CU_ASSERT(errno == EAGAIN || errno == EWOULDBLOCK); 456 457 client_sock = spdk_sock_connect(ip, port); 458 SPDK_CU_ASSERT_FATAL(client_sock != NULL); 459 460 usleep(1000); 461 462 server_sock = spdk_sock_accept(listen_sock); 463 SPDK_CU_ASSERT_FATAL(server_sock != NULL); 464 465 group = spdk_sock_group_create(); 466 SPDK_CU_ASSERT_FATAL(group != NULL); 467 468 /* pass null cb_fn */ 469 rc = spdk_sock_group_add_sock(group, server_sock, NULL, NULL); 470 CU_ASSERT(rc == -1); 471 CU_ASSERT(errno == EINVAL); 472 473 rc = spdk_sock_group_add_sock(group, server_sock, read_data, server_sock); 474 CU_ASSERT(rc == 0); 475 476 /* try adding sock a second time */ 477 rc = spdk_sock_group_add_sock(group, server_sock, read_data, server_sock); 478 CU_ASSERT(rc == -1); 479 CU_ASSERT(errno == EBUSY); 480 481 g_read_data_called = false; 482 g_bytes_read = 0; 483 rc = spdk_sock_group_poll(group); 484 485 CU_ASSERT(rc == 0); 486 CU_ASSERT(g_read_data_called == false); 487 488 iov.iov_base = test_string; 489 iov.iov_len = 7; 490 bytes_written = spdk_sock_writev(client_sock, &iov, 1); 491 CU_ASSERT(bytes_written == 7); 492 493 usleep(1000); 494 495 g_read_data_called = false; 496 g_bytes_read = 0; 497 rc = spdk_sock_group_poll(group); 498 499 CU_ASSERT(rc == 0); 500 CU_ASSERT(g_read_data_called == true); 501 CU_ASSERT(g_bytes_read == 7); 502 503 CU_ASSERT(strncmp(test_string, g_buf, 7) == 0); 504 505 rc = spdk_sock_close(&client_sock); 506 CU_ASSERT(client_sock == NULL); 507 CU_ASSERT(rc == 0); 508 509 /* Try to close sock_group while it still has sockets. */ 510 rc = spdk_sock_group_close(&group); 511 CU_ASSERT(rc == -1); 512 CU_ASSERT(errno == EBUSY); 513 514 /* Try to close sock while it is still part of a sock_group. */ 515 rc = spdk_sock_close(&server_sock); 516 CU_ASSERT(rc == -1); 517 CU_ASSERT(errno == EBUSY); 518 519 rc = spdk_sock_group_remove_sock(group, server_sock); 520 CU_ASSERT(rc == 0); 521 522 rc = spdk_sock_group_close(&group); 523 CU_ASSERT(group == NULL); 524 CU_ASSERT(rc == 0); 525 526 rc = spdk_sock_close(&server_sock); 527 CU_ASSERT(server_sock == NULL); 528 CU_ASSERT(rc == 0); 529 530 rc = spdk_sock_close(&listen_sock); 531 CU_ASSERT(listen_sock == NULL); 532 CU_ASSERT(rc == 0); 533 } 534 535 static void 536 posix_sock_group(void) 537 { 538 _sock_group("127.0.0.1", UT_PORT); 539 } 540 541 static void 542 ut_sock_group(void) 543 { 544 _sock_group(UT_IP, UT_PORT); 545 } 546 547 static void 548 read_data_fairness(void *cb_arg, struct spdk_sock_group *group, struct spdk_sock *sock) 549 { 550 struct spdk_sock *server_sock = cb_arg; 551 ssize_t bytes_read; 552 char buf[1]; 553 554 CU_ASSERT(g_server_sock_read == NULL); 555 CU_ASSERT(server_sock == sock); 556 557 g_server_sock_read = server_sock; 558 bytes_read = spdk_sock_recv(server_sock, buf, 1); 559 CU_ASSERT(bytes_read == 1); 560 } 561 562 static void 563 posix_sock_group_fairness(void) 564 { 565 struct spdk_sock_group *group; 566 struct spdk_sock *listen_sock; 567 struct spdk_sock *server_sock[3]; 568 struct spdk_sock *client_sock[3]; 569 char test_char = 'a'; 570 ssize_t bytes_written; 571 struct iovec iov; 572 int i, rc; 573 574 listen_sock = spdk_sock_listen("127.0.0.1", UT_PORT); 575 SPDK_CU_ASSERT_FATAL(listen_sock != NULL); 576 577 group = spdk_sock_group_create(); 578 SPDK_CU_ASSERT_FATAL(group != NULL); 579 580 for (i = 0; i < 3; i++) { 581 client_sock[i] = spdk_sock_connect("127.0.0.1", UT_PORT); 582 SPDK_CU_ASSERT_FATAL(client_sock[i] != NULL); 583 584 usleep(1000); 585 586 server_sock[i] = spdk_sock_accept(listen_sock); 587 SPDK_CU_ASSERT_FATAL(server_sock[i] != NULL); 588 589 rc = spdk_sock_group_add_sock(group, server_sock[i], 590 read_data_fairness, server_sock[i]); 591 CU_ASSERT(rc == 0); 592 } 593 594 iov.iov_base = &test_char; 595 iov.iov_len = 1; 596 597 for (i = 0; i < 3; i++) { 598 bytes_written = spdk_sock_writev(client_sock[i], &iov, 1); 599 CU_ASSERT(bytes_written == 1); 600 } 601 602 usleep(1000); 603 604 /* 605 * Poll for just one event - this should be server sock 0, since that 606 * is the peer of the first client sock that we wrote to. 607 */ 608 g_server_sock_read = NULL; 609 rc = spdk_sock_group_poll_count(group, 1); 610 CU_ASSERT(rc == 0); 611 CU_ASSERT(g_server_sock_read == server_sock[0]); 612 613 /* 614 * Now write another byte to client sock 0. We want to ensure that 615 * the sock group does not unfairly process the event for this sock 616 * before the socks that were written to earlier. 617 */ 618 bytes_written = spdk_sock_writev(client_sock[0], &iov, 1); 619 CU_ASSERT(bytes_written == 1); 620 621 usleep(1000); 622 623 g_server_sock_read = NULL; 624 rc = spdk_sock_group_poll_count(group, 1); 625 CU_ASSERT(rc == 0); 626 CU_ASSERT(g_server_sock_read == server_sock[1]); 627 628 g_server_sock_read = NULL; 629 rc = spdk_sock_group_poll_count(group, 1); 630 CU_ASSERT(rc == 0); 631 CU_ASSERT(g_server_sock_read == server_sock[2]); 632 633 g_server_sock_read = NULL; 634 rc = spdk_sock_group_poll_count(group, 1); 635 CU_ASSERT(rc == 0); 636 CU_ASSERT(g_server_sock_read == server_sock[0]); 637 638 for (i = 0; i < 3; i++) { 639 rc = spdk_sock_group_remove_sock(group, server_sock[i]); 640 CU_ASSERT(rc == 0); 641 642 rc = spdk_sock_close(&client_sock[i]); 643 CU_ASSERT(client_sock[i] == NULL); 644 CU_ASSERT(rc == 0); 645 646 rc = spdk_sock_close(&server_sock[i]); 647 CU_ASSERT(server_sock[i] == NULL); 648 CU_ASSERT(rc == 0); 649 } 650 651 rc = spdk_sock_group_close(&group); 652 CU_ASSERT(group == NULL); 653 CU_ASSERT(rc == 0); 654 655 rc = spdk_sock_close(&listen_sock); 656 CU_ASSERT(listen_sock == NULL); 657 CU_ASSERT(rc == 0); 658 } 659 660 int 661 main(int argc, char **argv) 662 { 663 CU_pSuite suite = NULL; 664 unsigned int num_failures; 665 666 if (CU_initialize_registry() != CUE_SUCCESS) { 667 return CU_get_error(); 668 } 669 670 suite = CU_add_suite("sock", NULL, NULL); 671 if (suite == NULL) { 672 CU_cleanup_registry(); 673 return CU_get_error(); 674 } 675 676 if ( 677 CU_add_test(suite, "posix_sock", posix_sock) == NULL || 678 CU_add_test(suite, "ut_sock", ut_sock) == NULL || 679 CU_add_test(suite, "posix_sock_group", posix_sock_group) == NULL || 680 CU_add_test(suite, "ut_sock_group", ut_sock_group) == NULL || 681 CU_add_test(suite, "posix_sock_group_fairness", posix_sock_group_fairness) == NULL) { 682 CU_cleanup_registry(); 683 return CU_get_error(); 684 } 685 686 CU_basic_set_mode(CU_BRM_VERBOSE); 687 688 CU_basic_run_tests(); 689 690 num_failures = CU_get_number_of_failures(); 691 CU_cleanup_registry(); 692 693 return num_failures; 694 } 695