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 #include "spdk/log.h" 37 #include "spdk/sock.h" 38 #include "spdk_internal/sock.h" 39 #include "spdk/queue.h" 40 41 static STAILQ_HEAD(, spdk_net_impl) g_net_impls = STAILQ_HEAD_INITIALIZER(g_net_impls); 42 43 int 44 spdk_sock_getaddr(struct spdk_sock *sock, char *saddr, int slen, uint16_t *sport, 45 char *caddr, int clen, uint16_t *cport) 46 { 47 return sock->net_impl->getaddr(sock, saddr, slen, sport, caddr, clen, cport); 48 } 49 50 struct spdk_sock * 51 spdk_sock_connect(const char *ip, int port) 52 { 53 struct spdk_net_impl *impl = NULL; 54 struct spdk_sock *sock; 55 56 STAILQ_FOREACH_FROM(impl, &g_net_impls, link) { 57 sock = impl->connect(ip, port); 58 if (sock != NULL) { 59 sock->net_impl = impl; 60 return sock; 61 } 62 } 63 64 return NULL; 65 } 66 67 struct spdk_sock * 68 spdk_sock_listen(const char *ip, int port) 69 { 70 struct spdk_net_impl *impl = NULL; 71 struct spdk_sock *sock; 72 73 STAILQ_FOREACH_FROM(impl, &g_net_impls, link) { 74 sock = impl->listen(ip, port); 75 if (sock != NULL) { 76 sock->net_impl = impl; 77 return sock; 78 } 79 } 80 81 return NULL; 82 } 83 84 struct spdk_sock * 85 spdk_sock_accept(struct spdk_sock *sock) 86 { 87 struct spdk_sock *new_sock; 88 89 new_sock = sock->net_impl->accept(sock); 90 if (new_sock != NULL) { 91 new_sock->net_impl = sock->net_impl; 92 } 93 94 return new_sock; 95 } 96 97 int 98 spdk_sock_close(struct spdk_sock **sock) 99 { 100 int rc; 101 102 if (*sock == NULL) { 103 errno = EBADF; 104 return -1; 105 } 106 107 if ((*sock)->cb_fn != NULL) { 108 /* This sock is still part of a sock_group. */ 109 errno = EBUSY; 110 return -1; 111 } 112 113 rc = (*sock)->net_impl->close(*sock); 114 if (rc == 0) { 115 *sock = NULL; 116 } 117 118 return rc; 119 } 120 121 ssize_t 122 spdk_sock_recv(struct spdk_sock *sock, void *buf, size_t len) 123 { 124 if (sock == NULL) { 125 errno = EBADF; 126 return -1; 127 } 128 129 return sock->net_impl->recv(sock, buf, len); 130 } 131 132 ssize_t 133 spdk_sock_readv(struct spdk_sock *sock, struct iovec *iov, int iovcnt) 134 { 135 if (sock == NULL) { 136 errno = EBADF; 137 return -1; 138 } 139 140 return sock->net_impl->readv(sock, iov, iovcnt); 141 } 142 143 ssize_t 144 spdk_sock_writev(struct spdk_sock *sock, struct iovec *iov, int iovcnt) 145 { 146 if (sock == NULL) { 147 errno = EBADF; 148 return -1; 149 } 150 151 return sock->net_impl->writev(sock, iov, iovcnt); 152 } 153 154 int 155 spdk_sock_set_recvlowat(struct spdk_sock *sock, int nbytes) 156 { 157 return sock->net_impl->set_recvlowat(sock, nbytes); 158 } 159 160 int 161 spdk_sock_set_recvbuf(struct spdk_sock *sock, int sz) 162 { 163 return sock->net_impl->set_recvbuf(sock, sz); 164 } 165 166 int 167 spdk_sock_set_sendbuf(struct spdk_sock *sock, int sz) 168 { 169 return sock->net_impl->set_sendbuf(sock, sz); 170 } 171 172 bool 173 spdk_sock_is_ipv6(struct spdk_sock *sock) 174 { 175 return sock->net_impl->is_ipv6(sock); 176 } 177 178 bool 179 spdk_sock_is_ipv4(struct spdk_sock *sock) 180 { 181 return sock->net_impl->is_ipv4(sock); 182 } 183 184 struct spdk_sock_group * 185 spdk_sock_group_create(void) 186 { 187 struct spdk_net_impl *impl = NULL; 188 struct spdk_sock_group *group; 189 struct spdk_sock_group_impl *group_impl; 190 191 group = calloc(1, sizeof(*group)); 192 if (group == NULL) { 193 return NULL; 194 } 195 196 STAILQ_INIT(&group->group_impls); 197 198 STAILQ_FOREACH_FROM(impl, &g_net_impls, link) { 199 group_impl = impl->group_impl_create(); 200 if (group_impl != NULL) { 201 STAILQ_INSERT_TAIL(&group->group_impls, group_impl, link); 202 TAILQ_INIT(&group_impl->socks); 203 group_impl->net_impl = impl; 204 } 205 } 206 207 return group; 208 } 209 210 int 211 spdk_sock_group_add_sock(struct spdk_sock_group *group, struct spdk_sock *sock, 212 spdk_sock_cb cb_fn, void *cb_arg) 213 { 214 struct spdk_sock_group_impl *group_impl = NULL; 215 int rc; 216 217 if (cb_fn == NULL) { 218 errno = EINVAL; 219 return -1; 220 } 221 222 if (sock->cb_fn != NULL) { 223 /* 224 * This sock is already part of a sock_group. Currently we don't 225 * support this. 226 */ 227 errno = EBUSY; 228 return -1; 229 } 230 231 STAILQ_FOREACH_FROM(group_impl, &group->group_impls, link) { 232 if (sock->net_impl == group_impl->net_impl) { 233 break; 234 } 235 } 236 237 if (group_impl == NULL) { 238 errno = EINVAL; 239 return -1; 240 } 241 242 rc = group_impl->net_impl->group_impl_add_sock(group_impl, sock); 243 if (rc == 0) { 244 TAILQ_INSERT_TAIL(&group_impl->socks, sock, link); 245 sock->cb_fn = cb_fn; 246 sock->cb_arg = cb_arg; 247 } 248 249 return rc; 250 } 251 252 int 253 spdk_sock_group_remove_sock(struct spdk_sock_group *group, struct spdk_sock *sock) 254 { 255 struct spdk_sock_group_impl *group_impl = NULL; 256 int rc; 257 258 STAILQ_FOREACH_FROM(group_impl, &group->group_impls, link) { 259 if (sock->net_impl == group_impl->net_impl) { 260 break; 261 } 262 } 263 264 if (group_impl == NULL) { 265 errno = EINVAL; 266 return -1; 267 } 268 269 rc = group_impl->net_impl->group_impl_remove_sock(group_impl, sock); 270 if (rc == 0) { 271 TAILQ_REMOVE(&group_impl->socks, sock, link); 272 sock->cb_fn = NULL; 273 sock->cb_arg = NULL; 274 } 275 276 return rc; 277 } 278 279 int 280 spdk_sock_group_poll(struct spdk_sock_group *group) 281 { 282 return spdk_sock_group_poll_count(group, MAX_EVENTS_PER_POLL); 283 } 284 285 static int 286 spdk_sock_group_impl_poll_count(struct spdk_sock_group_impl *group_impl, 287 struct spdk_sock_group *group, 288 int max_events) 289 { 290 struct spdk_sock *socks[MAX_EVENTS_PER_POLL]; 291 int num_events, i; 292 293 if (TAILQ_EMPTY(&group_impl->socks)) { 294 return 0; 295 } 296 297 num_events = group_impl->net_impl->group_impl_poll(group_impl, max_events, socks); 298 if (num_events == -1) { 299 return -1; 300 } 301 302 for (i = 0; i < num_events; i++) { 303 struct spdk_sock *sock = socks[i]; 304 305 assert(sock->cb_fn != NULL); 306 sock->cb_fn(sock->cb_arg, group, sock); 307 } 308 return 0; 309 } 310 311 int 312 spdk_sock_group_poll_count(struct spdk_sock_group *group, int max_events) 313 { 314 struct spdk_sock_group_impl *group_impl = NULL; 315 int rc, final_rc = 0; 316 317 if (max_events < 1) { 318 errno = -EINVAL; 319 return -1; 320 } 321 322 /* 323 * Only poll for up to 32 events at a time - if more events are pending, 324 * the next call to this function will reap them. 325 */ 326 if (max_events > MAX_EVENTS_PER_POLL) { 327 max_events = MAX_EVENTS_PER_POLL; 328 } 329 330 STAILQ_FOREACH_FROM(group_impl, &group->group_impls, link) { 331 rc = spdk_sock_group_impl_poll_count(group_impl, group, max_events); 332 if (rc != 0) { 333 final_rc = rc; 334 SPDK_ERRLOG("group_impl_poll_count for net(%s) failed\n", 335 group_impl->net_impl->name); 336 } 337 } 338 339 return final_rc; 340 } 341 342 int 343 spdk_sock_group_close(struct spdk_sock_group **group) 344 { 345 struct spdk_sock_group_impl *group_impl = NULL, *tmp; 346 int rc; 347 348 if (*group == NULL) { 349 errno = EBADF; 350 return -1; 351 } 352 353 STAILQ_FOREACH_SAFE(group_impl, &(*group)->group_impls, link, tmp) { 354 if (!TAILQ_EMPTY(&group_impl->socks)) { 355 errno = EBUSY; 356 return -1; 357 } 358 } 359 360 STAILQ_FOREACH_SAFE(group_impl, &(*group)->group_impls, link, tmp) { 361 rc = group_impl->net_impl->group_impl_close(group_impl); 362 if (rc != 0) { 363 SPDK_ERRLOG("group_impl_close for net(%s) failed\n", 364 group_impl->net_impl->name); 365 } 366 free(group_impl); 367 } 368 369 free(*group); 370 *group = NULL; 371 372 return 0; 373 } 374 375 void 376 spdk_net_impl_register(struct spdk_net_impl *impl) 377 { 378 if (!strcmp("posix", impl->name)) { 379 STAILQ_INSERT_TAIL(&g_net_impls, impl, link); 380 } else { 381 STAILQ_INSERT_HEAD(&g_net_impls, impl, link); 382 } 383 } 384