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