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