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 36 #if defined(__linux__) 37 #include <sys/epoll.h> 38 #elif defined(__FreeBSD__) 39 #include <sys/event.h> 40 #endif 41 42 #include "spdk/log.h" 43 #include "spdk/sock.h" 44 #include "spdk/string.h" 45 #include "spdk_internal/sock.h" 46 47 #define MAX_TMPBUF 1024 48 #define PORTNUMLEN 32 49 #define SO_RCVBUF_SIZE (2 * 1024 * 1024) 50 51 struct spdk_posix_sock { 52 struct spdk_sock base; 53 int fd; 54 }; 55 56 struct spdk_posix_sock_group_impl { 57 struct spdk_sock_group_impl base; 58 int fd; 59 }; 60 61 static int 62 get_addr_str(struct sockaddr *sa, char *host, size_t hlen) 63 { 64 const char *result = NULL; 65 66 if (sa == NULL || host == NULL) { 67 return -1; 68 } 69 70 switch (sa->sa_family) { 71 case AF_INET: 72 result = inet_ntop(AF_INET, &(((struct sockaddr_in *)sa)->sin_addr), 73 host, hlen); 74 break; 75 case AF_INET6: 76 result = inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)sa)->sin6_addr), 77 host, hlen); 78 break; 79 default: 80 break; 81 } 82 83 if (result != NULL) { 84 return 0; 85 } else { 86 return -1; 87 } 88 } 89 90 #define __posix_sock(sock) (struct spdk_posix_sock *)sock 91 #define __posix_group_impl(group) (struct spdk_posix_sock_group_impl *)group 92 93 static int 94 spdk_posix_sock_getaddr(struct spdk_sock *_sock, char *saddr, int slen, uint16_t *sport, 95 char *caddr, int clen, uint16_t *cport) 96 { 97 struct spdk_posix_sock *sock = __posix_sock(_sock); 98 struct sockaddr_storage sa; 99 socklen_t salen; 100 int rc; 101 102 assert(sock != NULL); 103 104 memset(&sa, 0, sizeof sa); 105 salen = sizeof sa; 106 rc = getsockname(sock->fd, (struct sockaddr *) &sa, &salen); 107 if (rc != 0) { 108 SPDK_ERRLOG("getsockname() failed (errno=%d)\n", errno); 109 return -1; 110 } 111 112 switch (sa.ss_family) { 113 case AF_UNIX: 114 /* Acceptable connection types that don't have IPs */ 115 return 0; 116 case AF_INET: 117 case AF_INET6: 118 /* Code below will get IP addresses */ 119 break; 120 default: 121 /* Unsupported socket family */ 122 return -1; 123 } 124 125 rc = get_addr_str((struct sockaddr *)&sa, saddr, slen); 126 if (rc != 0) { 127 SPDK_ERRLOG("getnameinfo() failed (errno=%d)\n", errno); 128 return -1; 129 } 130 131 if (sport) { 132 if (sa.ss_family == AF_INET) { 133 *sport = ntohs(((struct sockaddr_in *) &sa)->sin_port); 134 } else if (sa.ss_family == AF_INET6) { 135 *sport = ntohs(((struct sockaddr_in6 *) &sa)->sin6_port); 136 } 137 } 138 139 memset(&sa, 0, sizeof sa); 140 salen = sizeof sa; 141 rc = getpeername(sock->fd, (struct sockaddr *) &sa, &salen); 142 if (rc != 0) { 143 SPDK_ERRLOG("getpeername() failed (errno=%d)\n", errno); 144 return -1; 145 } 146 147 rc = get_addr_str((struct sockaddr *)&sa, caddr, clen); 148 if (rc != 0) { 149 SPDK_ERRLOG("getnameinfo() failed (errno=%d)\n", errno); 150 return -1; 151 } 152 153 if (cport) { 154 if (sa.ss_family == AF_INET) { 155 *cport = ntohs(((struct sockaddr_in *) &sa)->sin_port); 156 } else if (sa.ss_family == AF_INET6) { 157 *cport = ntohs(((struct sockaddr_in6 *) &sa)->sin6_port); 158 } 159 } 160 161 return 0; 162 } 163 164 enum spdk_posix_sock_create_type { 165 SPDK_SOCK_CREATE_LISTEN, 166 SPDK_SOCK_CREATE_CONNECT, 167 }; 168 169 static struct spdk_sock * 170 spdk_posix_sock_create(const char *ip, int port, enum spdk_posix_sock_create_type type) 171 { 172 struct spdk_posix_sock *sock; 173 char buf[MAX_TMPBUF]; 174 char portnum[PORTNUMLEN]; 175 char *p; 176 struct addrinfo hints, *res, *res0; 177 int fd, flag; 178 int val = 1; 179 int rc; 180 181 if (ip == NULL) { 182 return NULL; 183 } 184 if (ip[0] == '[') { 185 snprintf(buf, sizeof(buf), "%s", ip + 1); 186 p = strchr(buf, ']'); 187 if (p != NULL) { 188 *p = '\0'; 189 } 190 ip = (const char *) &buf[0]; 191 } 192 193 snprintf(portnum, sizeof portnum, "%d", port); 194 memset(&hints, 0, sizeof hints); 195 hints.ai_family = PF_UNSPEC; 196 hints.ai_socktype = SOCK_STREAM; 197 hints.ai_flags = AI_NUMERICSERV; 198 hints.ai_flags |= AI_PASSIVE; 199 hints.ai_flags |= AI_NUMERICHOST; 200 rc = getaddrinfo(ip, portnum, &hints, &res0); 201 if (rc != 0) { 202 SPDK_ERRLOG("getaddrinfo() failed (errno=%d)\n", errno); 203 return NULL; 204 } 205 206 /* try listen */ 207 fd = -1; 208 for (res = res0; res != NULL; res = res->ai_next) { 209 retry: 210 fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 211 if (fd < 0) { 212 /* error */ 213 continue; 214 } 215 rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof val); 216 if (rc != 0) { 217 close(fd); 218 /* error */ 219 continue; 220 } 221 rc = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof val); 222 if (rc != 0) { 223 close(fd); 224 /* error */ 225 continue; 226 } 227 228 if (res->ai_family == AF_INET6) { 229 rc = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &val, sizeof val); 230 if (rc != 0) { 231 close(fd); 232 /* error */ 233 continue; 234 } 235 } 236 237 if (type == SPDK_SOCK_CREATE_LISTEN) { 238 rc = bind(fd, res->ai_addr, res->ai_addrlen); 239 if (rc != 0) { 240 SPDK_ERRLOG("bind() failed at port %d, errno = %d\n", port, errno); 241 switch (errno) { 242 case EINTR: 243 /* interrupted? */ 244 close(fd); 245 goto retry; 246 case EADDRNOTAVAIL: 247 SPDK_ERRLOG("IP address %s not available. " 248 "Verify IP address in config file " 249 "and make sure setup script is " 250 "run before starting spdk app.\n", ip); 251 /* FALLTHROUGH */ 252 default: 253 /* try next family */ 254 close(fd); 255 fd = -1; 256 continue; 257 } 258 } 259 /* bind OK */ 260 rc = listen(fd, 512); 261 if (rc != 0) { 262 SPDK_ERRLOG("listen() failed, errno = %d\n", errno); 263 close(fd); 264 fd = -1; 265 break; 266 } 267 } else if (type == SPDK_SOCK_CREATE_CONNECT) { 268 rc = connect(fd, res->ai_addr, res->ai_addrlen); 269 if (rc != 0) { 270 SPDK_ERRLOG("connect() failed, errno = %d\n", errno); 271 /* try next family */ 272 close(fd); 273 fd = -1; 274 continue; 275 } 276 } 277 278 flag = fcntl(fd, F_GETFL); 279 if (fcntl(fd, F_SETFL, flag | O_NONBLOCK) < 0) { 280 SPDK_ERRLOG("fcntl can't set nonblocking mode for socket, fd: %d (%d)\n", fd, errno); 281 close(fd); 282 fd = -1; 283 break; 284 } 285 break; 286 } 287 freeaddrinfo(res0); 288 289 if (fd < 0) { 290 return NULL; 291 } 292 293 sock = calloc(1, sizeof(*sock)); 294 if (sock == NULL) { 295 SPDK_ERRLOG("sock allocation failed\n"); 296 close(fd); 297 return NULL; 298 } 299 300 sock->fd = fd; 301 return &sock->base; 302 } 303 304 static struct spdk_sock * 305 spdk_posix_sock_listen(const char *ip, int port) 306 { 307 return spdk_posix_sock_create(ip, port, SPDK_SOCK_CREATE_LISTEN); 308 } 309 310 static struct spdk_sock * 311 spdk_posix_sock_connect(const char *ip, int port) 312 { 313 return spdk_posix_sock_create(ip, port, SPDK_SOCK_CREATE_CONNECT); 314 } 315 316 static struct spdk_sock * 317 spdk_posix_sock_accept(struct spdk_sock *_sock) 318 { 319 struct spdk_posix_sock *sock = __posix_sock(_sock); 320 struct sockaddr_storage sa; 321 socklen_t salen; 322 int rc, fd; 323 struct spdk_posix_sock *new_sock; 324 int flag; 325 size_t sz = 0; 326 327 memset(&sa, 0, sizeof(sa)); 328 salen = sizeof(sa); 329 330 assert(sock != NULL); 331 332 rc = accept(sock->fd, (struct sockaddr *)&sa, &salen); 333 334 if (rc == -1) { 335 return NULL; 336 } 337 338 fd = rc; 339 340 flag = fcntl(fd, F_GETFL); 341 if ((!(flag & O_NONBLOCK)) && (fcntl(fd, F_SETFL, flag | O_NONBLOCK) < 0)) { 342 SPDK_ERRLOG("fcntl can't set nonblocking mode for socket, fd: %d (%d)\n", fd, errno); 343 close(fd); 344 return NULL; 345 } 346 347 rc = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &sz, &salen); 348 if (rc < 0) { 349 SPDK_ERRLOG("Unable to get recvbuf size for socket fd %d (%s)\n", fd, spdk_strerror(errno)); 350 close(fd); 351 return NULL; 352 } 353 354 if (sz < SO_RCVBUF_SIZE) { 355 sz = SO_RCVBUF_SIZE; 356 rc = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &sz, sizeof(sz)); 357 if (rc < 0) { 358 SPDK_WARNLOG("Unable to increase size of rcvbuf for socket fd %d (%s)", fd, spdk_strerror(errno)); 359 } 360 } 361 362 new_sock = calloc(1, sizeof(*sock)); 363 if (new_sock == NULL) { 364 SPDK_ERRLOG("sock allocation failed\n"); 365 close(fd); 366 return NULL; 367 } 368 369 new_sock->fd = fd; 370 return &new_sock->base; 371 } 372 373 static int 374 spdk_posix_sock_close(struct spdk_sock *_sock) 375 { 376 struct spdk_posix_sock *sock = __posix_sock(_sock); 377 int rc; 378 379 rc = close(sock->fd); 380 if (rc == 0) { 381 free(sock); 382 } 383 384 return rc; 385 } 386 387 static ssize_t 388 spdk_posix_sock_recv(struct spdk_sock *_sock, void *buf, size_t len) 389 { 390 struct spdk_posix_sock *sock = __posix_sock(_sock); 391 392 return recv(sock->fd, buf, len, MSG_DONTWAIT); 393 } 394 395 static ssize_t 396 spdk_posix_sock_readv(struct spdk_sock *_sock, struct iovec *iov, int iovcnt) 397 { 398 struct spdk_posix_sock *sock = __posix_sock(_sock); 399 400 return readv(sock->fd, iov, iovcnt); 401 } 402 403 static ssize_t 404 spdk_posix_sock_writev(struct spdk_sock *_sock, struct iovec *iov, int iovcnt) 405 { 406 struct spdk_posix_sock *sock = __posix_sock(_sock); 407 408 return writev(sock->fd, iov, iovcnt); 409 } 410 411 static int 412 spdk_posix_sock_set_recvlowat(struct spdk_sock *_sock, int nbytes) 413 { 414 struct spdk_posix_sock *sock = __posix_sock(_sock); 415 int val; 416 int rc; 417 418 assert(sock != NULL); 419 420 val = nbytes; 421 rc = setsockopt(sock->fd, SOL_SOCKET, SO_RCVLOWAT, &val, sizeof val); 422 if (rc != 0) { 423 return -1; 424 } 425 return 0; 426 } 427 428 static int 429 spdk_posix_sock_set_recvbuf(struct spdk_sock *_sock, int sz) 430 { 431 struct spdk_posix_sock *sock = __posix_sock(_sock); 432 433 assert(sock != NULL); 434 435 return setsockopt(sock->fd, SOL_SOCKET, SO_RCVBUF, 436 &sz, sizeof(sz)); 437 } 438 439 static int 440 spdk_posix_sock_set_sendbuf(struct spdk_sock *_sock, int sz) 441 { 442 struct spdk_posix_sock *sock = __posix_sock(_sock); 443 444 assert(sock != NULL); 445 446 return setsockopt(sock->fd, SOL_SOCKET, SO_SNDBUF, 447 &sz, sizeof(sz)); 448 } 449 450 static int 451 spdk_posix_sock_set_priority(struct spdk_sock *_sock, int priority) 452 { 453 int rc = 0; 454 455 #if defined(SO_PRIORITY) 456 struct spdk_posix_sock *sock = __posix_sock(_sock); 457 458 assert(sock != NULL); 459 460 rc = setsockopt(sock->fd, SOL_SOCKET, SO_PRIORITY, 461 &priority, sizeof(priority)); 462 #endif 463 return rc; 464 } 465 466 static bool 467 spdk_posix_sock_is_ipv6(struct spdk_sock *_sock) 468 { 469 struct spdk_posix_sock *sock = __posix_sock(_sock); 470 struct sockaddr_storage sa; 471 socklen_t salen; 472 int rc; 473 474 assert(sock != NULL); 475 476 memset(&sa, 0, sizeof sa); 477 salen = sizeof sa; 478 rc = getsockname(sock->fd, (struct sockaddr *) &sa, &salen); 479 if (rc != 0) { 480 SPDK_ERRLOG("getsockname() failed (errno=%d)\n", errno); 481 return false; 482 } 483 484 return (sa.ss_family == AF_INET6); 485 } 486 487 static bool 488 spdk_posix_sock_is_ipv4(struct spdk_sock *_sock) 489 { 490 struct spdk_posix_sock *sock = __posix_sock(_sock); 491 struct sockaddr_storage sa; 492 socklen_t salen; 493 int rc; 494 495 assert(sock != NULL); 496 497 memset(&sa, 0, sizeof sa); 498 salen = sizeof sa; 499 rc = getsockname(sock->fd, (struct sockaddr *) &sa, &salen); 500 if (rc != 0) { 501 SPDK_ERRLOG("getsockname() failed (errno=%d)\n", errno); 502 return false; 503 } 504 505 return (sa.ss_family == AF_INET); 506 } 507 508 static int 509 spdk_posix_sock_get_placement_id(struct spdk_sock *_sock, int *placement_id) 510 { 511 int rc = -1; 512 513 #if defined(SO_INCOMING_NAPI_ID) 514 struct spdk_posix_sock *sock = __posix_sock(_sock); 515 socklen_t salen = sizeof(int); 516 517 rc = getsockopt(sock->fd, SOL_SOCKET, SO_INCOMING_NAPI_ID, placement_id, &salen); 518 if (rc != 0) { 519 SPDK_ERRLOG("getsockopt() failed (errno=%d)\n", errno); 520 } 521 522 #endif 523 return rc; 524 } 525 526 static struct spdk_sock_group_impl * 527 spdk_posix_sock_group_impl_create(void) 528 { 529 struct spdk_posix_sock_group_impl *group_impl; 530 int fd; 531 532 #if defined(__linux__) 533 fd = epoll_create1(0); 534 #elif defined(__FreeBSD__) 535 fd = kqueue(); 536 #endif 537 if (fd == -1) { 538 return NULL; 539 } 540 541 group_impl = calloc(1, sizeof(*group_impl)); 542 if (group_impl == NULL) { 543 SPDK_ERRLOG("group_impl allocation failed\n"); 544 close(fd); 545 return NULL; 546 } 547 548 group_impl->fd = fd; 549 550 return &group_impl->base; 551 } 552 553 static int 554 spdk_posix_sock_group_impl_add_sock(struct spdk_sock_group_impl *_group, struct spdk_sock *_sock) 555 { 556 struct spdk_posix_sock_group_impl *group = __posix_group_impl(_group); 557 struct spdk_posix_sock *sock = __posix_sock(_sock); 558 int rc; 559 560 #if defined(__linux__) 561 struct epoll_event event; 562 563 memset(&event, 0, sizeof(event)); 564 event.events = EPOLLIN; 565 event.data.ptr = sock; 566 567 rc = epoll_ctl(group->fd, EPOLL_CTL_ADD, sock->fd, &event); 568 #elif defined(__FreeBSD__) 569 struct kevent event; 570 struct timespec ts = {0}; 571 572 EV_SET(&event, sock->fd, EVFILT_READ, EV_ADD, 0, 0, sock); 573 574 rc = kevent(group->fd, &event, 1, NULL, 0, &ts); 575 #endif 576 return rc; 577 } 578 579 static int 580 spdk_posix_sock_group_impl_remove_sock(struct spdk_sock_group_impl *_group, struct spdk_sock *_sock) 581 { 582 struct spdk_posix_sock_group_impl *group = __posix_group_impl(_group); 583 struct spdk_posix_sock *sock = __posix_sock(_sock); 584 int rc; 585 #if defined(__linux__) 586 struct epoll_event event; 587 588 /* Event parameter is ignored but some old kernel version still require it. */ 589 rc = epoll_ctl(group->fd, EPOLL_CTL_DEL, sock->fd, &event); 590 #elif defined(__FreeBSD__) 591 struct kevent event; 592 struct timespec ts = {0}; 593 594 EV_SET(&event, sock->fd, EVFILT_READ, EV_DELETE, 0, 0, NULL); 595 596 rc = kevent(group->fd, &event, 1, NULL, 0, &ts); 597 if (rc == 0 && event.flags & EV_ERROR) { 598 rc = -1; 599 errno = event.data; 600 } 601 #endif 602 return rc; 603 } 604 605 static int 606 spdk_posix_sock_group_impl_poll(struct spdk_sock_group_impl *_group, int max_events, 607 struct spdk_sock **socks) 608 { 609 struct spdk_posix_sock_group_impl *group = __posix_group_impl(_group); 610 int num_events, i; 611 612 #if defined(__linux__) 613 struct epoll_event events[MAX_EVENTS_PER_POLL]; 614 615 num_events = epoll_wait(group->fd, events, max_events, 0); 616 #elif defined(__FreeBSD__) 617 struct kevent events[MAX_EVENTS_PER_POLL]; 618 struct timespec ts = {0}; 619 620 num_events = kevent(group->fd, NULL, 0, events, max_events, &ts); 621 #endif 622 623 if (num_events == -1) { 624 return -1; 625 } 626 627 for (i = 0; i < num_events; i++) { 628 #if defined(__linux__) 629 socks[i] = events[i].data.ptr; 630 #elif defined(__FreeBSD__) 631 socks[i] = events[i].udata; 632 #endif 633 } 634 635 return num_events; 636 } 637 638 static int 639 spdk_posix_sock_group_impl_close(struct spdk_sock_group_impl *_group) 640 { 641 struct spdk_posix_sock_group_impl *group = __posix_group_impl(_group); 642 643 return close(group->fd); 644 } 645 646 static struct spdk_net_impl g_posix_net_impl = { 647 .name = "posix", 648 .getaddr = spdk_posix_sock_getaddr, 649 .connect = spdk_posix_sock_connect, 650 .listen = spdk_posix_sock_listen, 651 .accept = spdk_posix_sock_accept, 652 .close = spdk_posix_sock_close, 653 .recv = spdk_posix_sock_recv, 654 .readv = spdk_posix_sock_readv, 655 .writev = spdk_posix_sock_writev, 656 .set_recvlowat = spdk_posix_sock_set_recvlowat, 657 .set_recvbuf = spdk_posix_sock_set_recvbuf, 658 .set_sendbuf = spdk_posix_sock_set_sendbuf, 659 .set_priority = spdk_posix_sock_set_priority, 660 .is_ipv6 = spdk_posix_sock_is_ipv6, 661 .is_ipv4 = spdk_posix_sock_is_ipv4, 662 .get_placement_id = spdk_posix_sock_get_placement_id, 663 .group_impl_create = spdk_posix_sock_group_impl_create, 664 .group_impl_add_sock = spdk_posix_sock_group_impl_add_sock, 665 .group_impl_remove_sock = spdk_posix_sock_group_impl_remove_sock, 666 .group_impl_poll = spdk_posix_sock_group_impl_poll, 667 .group_impl_close = spdk_posix_sock_group_impl_close, 668 }; 669 670 SPDK_NET_IMPL_REGISTER(posix, &g_posix_net_impl); 671