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_writev(struct spdk_sock *_sock, struct iovec *iov, int iovcnt) 176 { 177 struct spdk_ut_sock *sock = __ut_sock(_sock); 178 struct spdk_ut_sock *peer; 179 180 SPDK_CU_ASSERT_FATAL(sock->peer != NULL); 181 peer = sock->peer; 182 183 /* Test implementation only supports single iov for now. */ 184 CU_ASSERT(iovcnt == 1); 185 186 memcpy(&peer->buf[peer->bytes_avail], iov[0].iov_base, iov[0].iov_len); 187 peer->bytes_avail += iov[0].iov_len; 188 189 return iov[0].iov_len; 190 } 191 192 static int 193 spdk_ut_sock_set_recvlowat(struct spdk_sock *_sock, int nbytes) 194 { 195 return 0; 196 } 197 198 static int 199 spdk_ut_sock_set_recvbuf(struct spdk_sock *_sock, int sz) 200 { 201 return 0; 202 } 203 204 static int 205 spdk_ut_sock_set_sendbuf(struct spdk_sock *_sock, int sz) 206 { 207 return 0; 208 } 209 210 static bool 211 spdk_ut_sock_is_ipv6(struct spdk_sock *_sock) 212 { 213 return false; 214 } 215 216 static bool 217 spdk_ut_sock_is_ipv4(struct spdk_sock *_sock) 218 { 219 return true; 220 } 221 222 static struct spdk_sock_group_impl * 223 spdk_ut_sock_group_impl_create(void) 224 { 225 struct spdk_ut_sock_group_impl *group_impl; 226 227 group_impl = calloc(1, sizeof(*group_impl)); 228 SPDK_CU_ASSERT_FATAL(group_impl != NULL); 229 230 return &group_impl->base; 231 } 232 233 static int 234 spdk_ut_sock_group_impl_add_sock(struct spdk_sock_group_impl *_group, struct spdk_sock *_sock) 235 { 236 struct spdk_ut_sock_group_impl *group = __ut_group(_group); 237 struct spdk_ut_sock *sock = __ut_sock(_sock); 238 239 group->sock = sock; 240 241 return 0; 242 } 243 244 static int 245 spdk_ut_sock_group_impl_remove_sock(struct spdk_sock_group_impl *_group, struct spdk_sock *_sock) 246 { 247 struct spdk_ut_sock_group_impl *group = __ut_group(_group); 248 struct spdk_ut_sock *sock = __ut_sock(_sock); 249 250 CU_ASSERT(group->sock == sock); 251 group->sock = NULL; 252 253 return 0; 254 } 255 256 static int 257 spdk_ut_sock_group_impl_poll(struct spdk_sock_group_impl *_group, int max_events, 258 struct spdk_sock **socks) 259 { 260 struct spdk_ut_sock_group_impl *group = __ut_group(_group); 261 262 if (group->sock != NULL && group->sock->bytes_avail > 0) { 263 socks[0] = &group->sock->base; 264 return 1; 265 } 266 267 return 0; 268 } 269 270 static int 271 spdk_ut_sock_group_impl_close(struct spdk_sock_group_impl *_group) 272 { 273 struct spdk_ut_sock_group_impl *group = __ut_group(_group); 274 275 CU_ASSERT(group->sock == NULL); 276 277 return 0; 278 } 279 280 static struct spdk_net_impl g_ut_net_impl = { 281 .name = "ut", 282 .getaddr = spdk_ut_sock_getaddr, 283 .connect = spdk_ut_sock_connect, 284 .listen = spdk_ut_sock_listen, 285 .accept = spdk_ut_sock_accept, 286 .close = spdk_ut_sock_close, 287 .recv = spdk_ut_sock_recv, 288 .writev = spdk_ut_sock_writev, 289 .set_recvlowat = spdk_ut_sock_set_recvlowat, 290 .set_recvbuf = spdk_ut_sock_set_recvbuf, 291 .set_sendbuf = spdk_ut_sock_set_sendbuf, 292 .is_ipv6 = spdk_ut_sock_is_ipv6, 293 .is_ipv4 = spdk_ut_sock_is_ipv4, 294 .group_impl_create = spdk_ut_sock_group_impl_create, 295 .group_impl_add_sock = spdk_ut_sock_group_impl_add_sock, 296 .group_impl_remove_sock = spdk_ut_sock_group_impl_remove_sock, 297 .group_impl_poll = spdk_ut_sock_group_impl_poll, 298 .group_impl_close = spdk_ut_sock_group_impl_close, 299 }; 300 301 SPDK_NET_IMPL_REGISTER(ut, &g_ut_net_impl); 302 303 static void 304 _sock(const char *ip, int port) 305 { 306 struct spdk_sock *listen_sock; 307 struct spdk_sock *server_sock; 308 struct spdk_sock *client_sock; 309 char *test_string = "abcdef"; 310 char buffer[64]; 311 ssize_t bytes_read, bytes_written; 312 struct iovec iov; 313 int rc; 314 315 listen_sock = spdk_sock_listen(ip, port); 316 SPDK_CU_ASSERT_FATAL(listen_sock != NULL); 317 318 server_sock = spdk_sock_accept(listen_sock); 319 CU_ASSERT(server_sock == NULL); 320 CU_ASSERT(errno == EAGAIN || errno == EWOULDBLOCK); 321 322 client_sock = spdk_sock_connect(ip, port); 323 SPDK_CU_ASSERT_FATAL(client_sock != NULL); 324 325 /* 326 * Delay a bit here before checking if server socket is 327 * ready. 328 */ 329 usleep(1000); 330 331 server_sock = spdk_sock_accept(listen_sock); 332 SPDK_CU_ASSERT_FATAL(server_sock != NULL); 333 334 iov.iov_base = test_string; 335 iov.iov_len = 7; 336 bytes_written = spdk_sock_writev(client_sock, &iov, 1); 337 CU_ASSERT(bytes_written == 7); 338 339 usleep(1000); 340 341 bytes_read = spdk_sock_recv(server_sock, buffer, 2); 342 CU_ASSERT(bytes_read == 2); 343 344 usleep(1000); 345 346 bytes_read += spdk_sock_recv(server_sock, buffer + 2, 5); 347 CU_ASSERT(bytes_read == 7); 348 349 CU_ASSERT(strncmp(test_string, buffer, 7) == 0); 350 351 rc = spdk_sock_close(&client_sock); 352 CU_ASSERT(client_sock == NULL); 353 CU_ASSERT(rc == 0); 354 355 rc = spdk_sock_close(&server_sock); 356 CU_ASSERT(server_sock == NULL); 357 CU_ASSERT(rc == 0); 358 359 rc = spdk_sock_close(&listen_sock); 360 CU_ASSERT(listen_sock == NULL); 361 CU_ASSERT(rc == 0); 362 } 363 364 static void 365 posix_sock(void) 366 { 367 _sock("127.0.0.1", 3260); 368 } 369 370 static void 371 ut_sock(void) 372 { 373 _sock(UT_IP, UT_PORT); 374 } 375 376 static void 377 read_data(void *cb_arg, struct spdk_sock_group *group, struct spdk_sock *sock) 378 { 379 struct spdk_sock *server_sock = cb_arg; 380 381 CU_ASSERT(server_sock == sock); 382 383 g_read_data_called = true; 384 g_bytes_read += spdk_sock_recv(server_sock, g_buf + g_bytes_read, sizeof(g_buf) - g_bytes_read); 385 } 386 387 static void 388 _sock_group(const char *ip, int port) 389 { 390 struct spdk_sock_group *group; 391 struct spdk_sock *listen_sock; 392 struct spdk_sock *server_sock; 393 struct spdk_sock *client_sock; 394 char *test_string = "abcdef"; 395 ssize_t bytes_written; 396 struct iovec iov; 397 int rc; 398 399 listen_sock = spdk_sock_listen(ip, port); 400 SPDK_CU_ASSERT_FATAL(listen_sock != NULL); 401 402 server_sock = spdk_sock_accept(listen_sock); 403 CU_ASSERT(server_sock == NULL); 404 CU_ASSERT(errno == EAGAIN || errno == EWOULDBLOCK); 405 406 client_sock = spdk_sock_connect(ip, port); 407 SPDK_CU_ASSERT_FATAL(client_sock != NULL); 408 409 usleep(1000); 410 411 server_sock = spdk_sock_accept(listen_sock); 412 SPDK_CU_ASSERT_FATAL(server_sock != NULL); 413 414 group = spdk_sock_group_create(); 415 SPDK_CU_ASSERT_FATAL(group != NULL); 416 417 /* pass null cb_fn */ 418 rc = spdk_sock_group_add_sock(group, server_sock, NULL, NULL); 419 CU_ASSERT(rc == -1); 420 CU_ASSERT(errno == EINVAL); 421 422 rc = spdk_sock_group_add_sock(group, server_sock, read_data, server_sock); 423 CU_ASSERT(rc == 0); 424 425 /* try adding sock a second time */ 426 rc = spdk_sock_group_add_sock(group, server_sock, read_data, server_sock); 427 CU_ASSERT(rc == -1); 428 CU_ASSERT(errno == EBUSY); 429 430 g_read_data_called = false; 431 g_bytes_read = 0; 432 rc = spdk_sock_group_poll(group); 433 434 CU_ASSERT(rc == 0); 435 CU_ASSERT(g_read_data_called == false); 436 437 iov.iov_base = test_string; 438 iov.iov_len = 7; 439 bytes_written = spdk_sock_writev(client_sock, &iov, 1); 440 CU_ASSERT(bytes_written == 7); 441 442 usleep(1000); 443 444 g_read_data_called = false; 445 g_bytes_read = 0; 446 rc = spdk_sock_group_poll(group); 447 448 CU_ASSERT(rc == 0); 449 CU_ASSERT(g_read_data_called == true); 450 CU_ASSERT(g_bytes_read == 7); 451 452 CU_ASSERT(strncmp(test_string, g_buf, 7) == 0); 453 454 rc = spdk_sock_close(&client_sock); 455 CU_ASSERT(client_sock == NULL); 456 CU_ASSERT(rc == 0); 457 458 /* Try to close sock_group while it still has sockets. */ 459 rc = spdk_sock_group_close(&group); 460 CU_ASSERT(rc == -1); 461 CU_ASSERT(errno == EBUSY); 462 463 /* Try to close sock while it is still part of a sock_group. */ 464 rc = spdk_sock_close(&server_sock); 465 CU_ASSERT(rc == -1); 466 CU_ASSERT(errno == EBUSY); 467 468 rc = spdk_sock_group_remove_sock(group, server_sock); 469 CU_ASSERT(rc == 0); 470 471 rc = spdk_sock_group_close(&group); 472 CU_ASSERT(group == NULL); 473 CU_ASSERT(rc == 0); 474 475 rc = spdk_sock_close(&server_sock); 476 CU_ASSERT(server_sock == NULL); 477 CU_ASSERT(rc == 0); 478 479 rc = spdk_sock_close(&listen_sock); 480 CU_ASSERT(listen_sock == NULL); 481 CU_ASSERT(rc == 0); 482 } 483 484 static void 485 posix_sock_group(void) 486 { 487 _sock_group("127.0.0.1", 3260); 488 } 489 490 static void 491 ut_sock_group(void) 492 { 493 _sock_group(UT_IP, UT_PORT); 494 } 495 496 static void 497 read_data_fairness(void *cb_arg, struct spdk_sock_group *group, struct spdk_sock *sock) 498 { 499 struct spdk_sock *server_sock = cb_arg; 500 ssize_t bytes_read; 501 char buf[1]; 502 503 CU_ASSERT(g_server_sock_read == NULL); 504 CU_ASSERT(server_sock == sock); 505 506 g_server_sock_read = server_sock; 507 bytes_read = spdk_sock_recv(server_sock, buf, 1); 508 CU_ASSERT(bytes_read == 1); 509 } 510 511 static void 512 posix_sock_group_fairness(void) 513 { 514 struct spdk_sock_group *group; 515 struct spdk_sock *listen_sock; 516 struct spdk_sock *server_sock[3]; 517 struct spdk_sock *client_sock[3]; 518 char test_char = 'a'; 519 ssize_t bytes_written; 520 struct iovec iov; 521 int i, rc; 522 523 listen_sock = spdk_sock_listen("127.0.0.1", 3260); 524 SPDK_CU_ASSERT_FATAL(listen_sock != NULL); 525 526 group = spdk_sock_group_create(); 527 SPDK_CU_ASSERT_FATAL(group != NULL); 528 529 for (i = 0; i < 3; i++) { 530 client_sock[i] = spdk_sock_connect("127.0.0.1", 3260); 531 SPDK_CU_ASSERT_FATAL(client_sock[i] != NULL); 532 533 usleep(1000); 534 535 server_sock[i] = spdk_sock_accept(listen_sock); 536 SPDK_CU_ASSERT_FATAL(server_sock[i] != NULL); 537 538 rc = spdk_sock_group_add_sock(group, server_sock[i], 539 read_data_fairness, server_sock[i]); 540 CU_ASSERT(rc == 0); 541 } 542 543 iov.iov_base = &test_char; 544 iov.iov_len = 1; 545 546 for (i = 0; i < 3; i++) { 547 bytes_written = spdk_sock_writev(client_sock[i], &iov, 1); 548 CU_ASSERT(bytes_written == 1); 549 } 550 551 usleep(1000); 552 553 /* 554 * Poll for just one event - this should be server sock 0, since that 555 * is the peer of the first client sock that we wrote to. 556 */ 557 g_server_sock_read = NULL; 558 rc = spdk_sock_group_poll_count(group, 1); 559 CU_ASSERT(rc == 0); 560 CU_ASSERT(g_server_sock_read == server_sock[0]); 561 562 /* 563 * Now write another byte to client sock 0. We want to ensure that 564 * the sock group does not unfairly process the event for this sock 565 * before the socks that were written to earlier. 566 */ 567 bytes_written = spdk_sock_writev(client_sock[0], &iov, 1); 568 CU_ASSERT(bytes_written == 1); 569 570 usleep(1000); 571 572 g_server_sock_read = NULL; 573 rc = spdk_sock_group_poll_count(group, 1); 574 CU_ASSERT(rc == 0); 575 CU_ASSERT(g_server_sock_read == server_sock[1]); 576 577 g_server_sock_read = NULL; 578 rc = spdk_sock_group_poll_count(group, 1); 579 CU_ASSERT(rc == 0); 580 CU_ASSERT(g_server_sock_read == server_sock[2]); 581 582 g_server_sock_read = NULL; 583 rc = spdk_sock_group_poll_count(group, 1); 584 CU_ASSERT(rc == 0); 585 CU_ASSERT(g_server_sock_read == server_sock[0]); 586 587 for (i = 0; i < 3; i++) { 588 rc = spdk_sock_group_remove_sock(group, server_sock[i]); 589 CU_ASSERT(rc == 0); 590 591 rc = spdk_sock_close(&client_sock[i]); 592 CU_ASSERT(client_sock[i] == NULL); 593 CU_ASSERT(rc == 0); 594 595 rc = spdk_sock_close(&server_sock[i]); 596 CU_ASSERT(server_sock[i] == NULL); 597 CU_ASSERT(rc == 0); 598 } 599 600 rc = spdk_sock_group_close(&group); 601 CU_ASSERT(group == NULL); 602 CU_ASSERT(rc == 0); 603 604 rc = spdk_sock_close(&listen_sock); 605 CU_ASSERT(listen_sock == NULL); 606 CU_ASSERT(rc == 0); 607 } 608 609 int 610 main(int argc, char **argv) 611 { 612 CU_pSuite suite = NULL; 613 unsigned int num_failures; 614 615 if (CU_initialize_registry() != CUE_SUCCESS) { 616 return CU_get_error(); 617 } 618 619 suite = CU_add_suite("sock", NULL, NULL); 620 if (suite == NULL) { 621 CU_cleanup_registry(); 622 return CU_get_error(); 623 } 624 625 if ( 626 CU_add_test(suite, "posix_sock", posix_sock) == NULL || 627 CU_add_test(suite, "ut_sock", ut_sock) == NULL || 628 CU_add_test(suite, "posix_sock_group", posix_sock_group) == NULL || 629 CU_add_test(suite, "ut_sock_group", ut_sock_group) == NULL || 630 CU_add_test(suite, "posix_sock_group_fairness", posix_sock_group_fairness) == NULL) { 631 CU_cleanup_registry(); 632 return CU_get_error(); 633 } 634 635 CU_basic_set_mode(CU_BRM_VERBOSE); 636 637 CU_basic_run_tests(); 638 639 num_failures = CU_get_number_of_failures(); 640 CU_cleanup_registry(); 641 642 return num_failures; 643 } 644