Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2016 Intel Corporation. All rights reserved.
3 : : * Copyright (c) 2020 Mellanox Technologies LTD. All rights reserved.
4 : : * Copyright (c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
5 : : */
6 : :
7 : : #include "spdk/stdinc.h"
8 : :
9 : : #include "spdk/sock.h"
10 : : #include "spdk_internal/sock.h"
11 : : #include "spdk/log.h"
12 : : #include "spdk/env.h"
13 : : #include "spdk/util.h"
14 : : #include "spdk/trace.h"
15 : : #include "spdk/thread.h"
16 : : #include "spdk_internal/trace_defs.h"
17 : :
18 : : #define SPDK_SOCK_DEFAULT_PRIORITY 0
19 : : #define SPDK_SOCK_DEFAULT_ZCOPY true
20 : : #define SPDK_SOCK_DEFAULT_ACK_TIMEOUT 0
21 : :
22 : : #define SPDK_SOCK_OPTS_FIELD_OK(opts, field) (offsetof(struct spdk_sock_opts, field) + sizeof(opts->field) <= (opts->opts_size))
23 : :
24 : : static STAILQ_HEAD(, spdk_net_impl) g_net_impls = STAILQ_HEAD_INITIALIZER(g_net_impls);
25 : : static struct spdk_net_impl *g_default_impl;
26 : :
27 : : struct spdk_sock_placement_id_entry {
28 : : int placement_id;
29 : : uint32_t ref;
30 : : struct spdk_sock_group_impl *group;
31 : : STAILQ_ENTRY(spdk_sock_placement_id_entry) link;
32 : : };
33 : :
34 : : static inline struct spdk_sock_group_impl *
35 : 19543 : sock_get_group_impl_from_group(struct spdk_sock *sock, struct spdk_sock_group *group)
36 : : {
37 : 19543 : struct spdk_sock_group_impl *group_impl = NULL;
38 : :
39 [ + - + - ]: 41436 : STAILQ_FOREACH_FROM(group_impl, &group->group_impls, link) {
40 [ + + ]: 41436 : if (sock->net_impl == group_impl->net_impl) {
41 : 19543 : return group_impl;
42 : : }
43 : : }
44 : 0 : return NULL;
45 : : }
46 : :
47 : : /* Called under map->mtx lock */
48 : : static struct spdk_sock_placement_id_entry *
49 : 23 : _sock_map_entry_alloc(struct spdk_sock_map *map, int placement_id)
50 : : {
51 : : struct spdk_sock_placement_id_entry *entry;
52 : :
53 : 23 : entry = calloc(1, sizeof(*entry));
54 [ - + ]: 23 : if (!entry) {
55 : 0 : SPDK_ERRLOG("Cannot allocate an entry for placement_id=%u\n", placement_id);
56 : 0 : return NULL;
57 : : }
58 : :
59 : 23 : entry->placement_id = placement_id;
60 : :
61 : 23 : STAILQ_INSERT_TAIL(&map->entries, entry, link);
62 : :
63 : 23 : return entry;
64 : : }
65 : :
66 : : int
67 : 38 : spdk_sock_map_insert(struct spdk_sock_map *map, int placement_id,
68 : : struct spdk_sock_group_impl *group)
69 : : {
70 : : struct spdk_sock_placement_id_entry *entry;
71 : 38 : int rc = 0;
72 : :
73 [ - + ]: 38 : pthread_mutex_lock(&map->mtx);
74 [ + + ]: 42 : STAILQ_FOREACH(entry, &map->entries, link) {
75 [ + + ]: 24 : if (placement_id == entry->placement_id) {
76 : : /* Can't set group to NULL if it is already not-NULL */
77 [ - + ]: 20 : if (group == NULL) {
78 [ # # ]: 0 : rc = (entry->group == NULL) ? 0 : -EINVAL;
79 : 0 : goto end;
80 : : }
81 : :
82 [ + + ]: 20 : if (entry->group == NULL) {
83 : 3 : entry->group = group;
84 [ + + ]: 17 : } else if (entry->group != group) {
85 : 6 : rc = -EINVAL;
86 : 6 : goto end;
87 : : }
88 : :
89 : 14 : entry->ref++;
90 : 14 : goto end;
91 : : }
92 : : }
93 : :
94 : 18 : entry = _sock_map_entry_alloc(map, placement_id);
95 [ - + ]: 18 : if (entry == NULL) {
96 : 0 : rc = -ENOMEM;
97 : 0 : goto end;
98 : : }
99 [ + + ]: 18 : if (group) {
100 : 15 : entry->group = group;
101 : 15 : entry->ref++;
102 : : }
103 : 3 : end:
104 [ - + ]: 38 : pthread_mutex_unlock(&map->mtx);
105 : :
106 : 38 : return rc;
107 : : }
108 : :
109 : : void
110 : 14 : spdk_sock_map_release(struct spdk_sock_map *map, int placement_id)
111 : : {
112 : : struct spdk_sock_placement_id_entry *entry;
113 : :
114 [ - + ]: 14 : pthread_mutex_lock(&map->mtx);
115 [ + - ]: 15 : STAILQ_FOREACH(entry, &map->entries, link) {
116 [ + + ]: 15 : if (placement_id == entry->placement_id) {
117 [ - + ]: 14 : assert(entry->ref > 0);
118 : 14 : entry->ref--;
119 : :
120 [ + + ]: 14 : if (entry->ref == 0) {
121 : 8 : entry->group = NULL;
122 : : }
123 : 14 : break;
124 : : }
125 : : }
126 : :
127 [ - + ]: 14 : pthread_mutex_unlock(&map->mtx);
128 : 14 : }
129 : :
130 : : int
131 : 41 : spdk_sock_map_lookup(struct spdk_sock_map *map, int placement_id,
132 : : struct spdk_sock_group_impl **group, struct spdk_sock_group_impl *hint)
133 : : {
134 : : struct spdk_sock_placement_id_entry *entry;
135 : :
136 : 41 : *group = NULL;
137 [ - + ]: 41 : pthread_mutex_lock(&map->mtx);
138 [ + + ]: 45 : STAILQ_FOREACH(entry, &map->entries, link) {
139 [ + + ]: 37 : if (placement_id == entry->placement_id) {
140 : 33 : *group = entry->group;
141 [ + + ]: 33 : if (*group != NULL) {
142 : : /* Return previously assigned sock_group */
143 [ - + ]: 27 : pthread_mutex_unlock(&map->mtx);
144 : 27 : return 0;
145 : : }
146 : 6 : break;
147 : : }
148 : : }
149 : :
150 : : /* No entry with assigned sock_group, nor hint to use */
151 [ + + ]: 14 : if (hint == NULL) {
152 [ - + ]: 9 : pthread_mutex_unlock(&map->mtx);
153 : 9 : return -EINVAL;
154 : : }
155 : :
156 : : /* Create new entry if there is none with matching placement_id */
157 [ + - ]: 5 : if (entry == NULL) {
158 : 5 : entry = _sock_map_entry_alloc(map, placement_id);
159 [ - + ]: 5 : if (entry == NULL) {
160 [ # # ]: 0 : pthread_mutex_unlock(&map->mtx);
161 : 0 : return -ENOMEM;
162 : : }
163 : : }
164 : :
165 : 5 : entry->group = hint;
166 [ - + ]: 5 : pthread_mutex_unlock(&map->mtx);
167 : :
168 : 5 : return 0;
169 : : }
170 : :
171 : : void
172 : 2953 : spdk_sock_map_cleanup(struct spdk_sock_map *map)
173 : : {
174 : : struct spdk_sock_placement_id_entry *entry, *tmp;
175 : :
176 [ - + ]: 2953 : pthread_mutex_lock(&map->mtx);
177 [ + + ]: 2976 : STAILQ_FOREACH_SAFE(entry, &map->entries, link, tmp) {
178 [ + - + + : 23 : STAILQ_REMOVE(&map->entries, entry, spdk_sock_placement_id_entry, link);
- - - - ]
179 : 23 : free(entry);
180 : : }
181 [ - + ]: 2953 : pthread_mutex_unlock(&map->mtx);
182 : 2953 : }
183 : :
184 : : int
185 : 15 : spdk_sock_map_find_free(struct spdk_sock_map *map)
186 : : {
187 : : struct spdk_sock_placement_id_entry *entry;
188 : 15 : int placement_id = -1;
189 : :
190 [ - + ]: 15 : pthread_mutex_lock(&map->mtx);
191 [ + + ]: 21 : STAILQ_FOREACH(entry, &map->entries, link) {
192 [ + + ]: 12 : if (entry->group == NULL) {
193 : 6 : placement_id = entry->placement_id;
194 : 6 : break;
195 : : }
196 : : }
197 : :
198 [ - + ]: 15 : pthread_mutex_unlock(&map->mtx);
199 : :
200 : 15 : return placement_id;
201 : : }
202 : :
203 : : int
204 : 5251 : spdk_sock_get_optimal_sock_group(struct spdk_sock *sock, struct spdk_sock_group **group,
205 : : struct spdk_sock_group *hint)
206 : : {
207 : : struct spdk_sock_group_impl *group_impl;
208 : 5251 : struct spdk_sock_group_impl *hint_group_impl = NULL;
209 : :
210 [ - + ]: 5251 : assert(group != NULL);
211 : :
212 [ + - ]: 5251 : if (hint != NULL) {
213 : 5251 : hint_group_impl = sock_get_group_impl_from_group(sock, hint);
214 [ - + ]: 5251 : if (hint_group_impl == NULL) {
215 : 0 : return -EINVAL;
216 : : }
217 : : }
218 : :
219 : 5251 : group_impl = sock->net_impl->group_impl_get_optimal(sock, hint_group_impl);
220 : :
221 [ + + ]: 5251 : if (group_impl) {
222 : 3 : *group = group_impl->group;
223 : : }
224 : :
225 : 5251 : return 0;
226 : : }
227 : :
228 : : int
229 : 11075 : spdk_sock_getaddr(struct spdk_sock *sock, char *saddr, int slen, uint16_t *sport,
230 : : char *caddr, int clen, uint16_t *cport)
231 : : {
232 : 11075 : return sock->net_impl->getaddr(sock, saddr, slen, sport, caddr, clen, cport);
233 : : }
234 : :
235 : : const char *
236 : 18 : spdk_sock_get_interface_name(struct spdk_sock *sock)
237 : : {
238 [ + - ]: 18 : if (sock->net_impl->get_interface_name) {
239 : 18 : return sock->net_impl->get_interface_name(sock);
240 : : } else {
241 : 0 : return NULL;
242 : : }
243 : : }
244 : :
245 : : uint32_t
246 : 1204 : spdk_sock_get_numa_socket_id(struct spdk_sock *sock)
247 : : {
248 [ + - ]: 1204 : if (sock->net_impl->get_numa_socket_id) {
249 : 1204 : return sock->net_impl->get_numa_socket_id(sock);
250 : : } else {
251 : 0 : return SPDK_ENV_SOCKET_ID_ANY;
252 : : }
253 : : }
254 : :
255 : : const char *
256 : 522 : spdk_sock_get_impl_name(struct spdk_sock *sock)
257 : : {
258 : 522 : return sock->net_impl->name;
259 : : }
260 : :
261 : : void
262 : 40108 : spdk_sock_get_default_opts(struct spdk_sock_opts *opts)
263 : : {
264 [ - + ]: 40108 : assert(opts);
265 : :
266 [ + + ]: 40108 : if (SPDK_SOCK_OPTS_FIELD_OK(opts, priority)) {
267 : 40102 : opts->priority = SPDK_SOCK_DEFAULT_PRIORITY;
268 : : }
269 : :
270 [ + + ]: 40108 : if (SPDK_SOCK_OPTS_FIELD_OK(opts, zcopy)) {
271 : 40102 : opts->zcopy = SPDK_SOCK_DEFAULT_ZCOPY;
272 : : }
273 : :
274 [ + + ]: 40108 : if (SPDK_SOCK_OPTS_FIELD_OK(opts, ack_timeout)) {
275 : 40102 : opts->ack_timeout = SPDK_SOCK_DEFAULT_ACK_TIMEOUT;
276 : : }
277 : :
278 [ + + ]: 40108 : if (SPDK_SOCK_OPTS_FIELD_OK(opts, impl_opts)) {
279 : 40102 : opts->impl_opts = NULL;
280 : : }
281 : :
282 [ + + ]: 40108 : if (SPDK_SOCK_OPTS_FIELD_OK(opts, impl_opts_size)) {
283 : 40102 : opts->impl_opts_size = 0;
284 : : }
285 : 40108 : }
286 : :
287 : : /*
288 : : * opts The opts allocated in the current library.
289 : : * opts_user The opts passed by the caller.
290 : : * */
291 : : static void
292 : 20048 : sock_init_opts(struct spdk_sock_opts *opts, struct spdk_sock_opts *opts_user)
293 : : {
294 [ - + ]: 20048 : assert(opts);
295 [ - + ]: 20048 : assert(opts_user);
296 : :
297 : 20048 : opts->opts_size = sizeof(*opts);
298 : 20048 : spdk_sock_get_default_opts(opts);
299 : :
300 : : /* reset the size according to the user */
301 : 20048 : opts->opts_size = opts_user->opts_size;
302 [ + - ]: 20048 : if (SPDK_SOCK_OPTS_FIELD_OK(opts, priority)) {
303 : 20048 : opts->priority = opts_user->priority;
304 : : }
305 : :
306 [ + - ]: 20048 : if (SPDK_SOCK_OPTS_FIELD_OK(opts, zcopy)) {
307 [ - + ]: 20048 : opts->zcopy = opts_user->zcopy;
308 : : }
309 : :
310 [ + - ]: 20048 : if (SPDK_SOCK_OPTS_FIELD_OK(opts, ack_timeout)) {
311 : 20048 : opts->ack_timeout = opts_user->ack_timeout;
312 : : }
313 : :
314 [ + - ]: 20048 : if (SPDK_SOCK_OPTS_FIELD_OK(opts, impl_opts)) {
315 : 20048 : opts->impl_opts = opts_user->impl_opts;
316 : : }
317 : :
318 [ + - ]: 20048 : if (SPDK_SOCK_OPTS_FIELD_OK(opts, impl_opts)) {
319 : 20048 : opts->impl_opts_size = opts_user->impl_opts_size;
320 : : }
321 : 20048 : }
322 : :
323 : : struct spdk_sock *
324 : 26 : spdk_sock_connect(const char *ip, int port, const char *impl_name)
325 : : {
326 : 24 : struct spdk_sock_opts opts;
327 : :
328 : 26 : opts.opts_size = sizeof(opts);
329 : 26 : spdk_sock_get_default_opts(&opts);
330 : 26 : return spdk_sock_connect_ext(ip, port, impl_name, &opts);
331 : : }
332 : :
333 : : struct spdk_sock *
334 : 19692 : spdk_sock_connect_ext(const char *ip, int port, const char *_impl_name, struct spdk_sock_opts *opts)
335 : : {
336 : 19692 : struct spdk_net_impl *impl = NULL;
337 : : struct spdk_sock *sock;
338 : 129 : struct spdk_sock_opts opts_local;
339 : 19692 : const char *impl_name = NULL;
340 : :
341 [ - + ]: 19692 : if (opts == NULL) {
342 : 0 : SPDK_ERRLOG("the opts should not be NULL pointer\n");
343 : 0 : return NULL;
344 : : }
345 : :
346 [ + + ]: 19692 : if (_impl_name) {
347 : 181 : impl_name = _impl_name;
348 [ + - ]: 19511 : } else if (g_default_impl) {
349 : 19511 : impl_name = g_default_impl->name;
350 : : }
351 : :
352 [ + - + + ]: 55237 : STAILQ_FOREACH_FROM(impl, &g_net_impls, link) {
353 [ + - + + : 39701 : if (impl_name && strncmp(impl_name, impl->name, strlen(impl->name) + 1)) {
- + - + +
+ ]
354 : 20009 : continue;
355 : : }
356 : :
357 [ - + + + ]: 19692 : SPDK_DEBUGLOG(sock, "Creating a client socket using impl %s\n", impl->name);
358 : 19692 : sock_init_opts(&opts_local, opts);
359 : 19692 : sock = impl->connect(ip, port, &opts_local);
360 [ + + ]: 19692 : if (sock != NULL) {
361 : : /* Copy the contents, both the two structures are the same ABI version */
362 [ - + ]: 4156 : memcpy(&sock->opts, &opts_local, sizeof(sock->opts));
363 : : /* Clear out impl_opts to make sure we don't keep reference to a dangling
364 : : * pointer */
365 : 4156 : sock->opts.impl_opts = NULL;
366 : 4156 : sock->net_impl = impl;
367 : 4156 : TAILQ_INIT(&sock->queued_reqs);
368 : 4156 : TAILQ_INIT(&sock->pending_reqs);
369 : :
370 : 4156 : return sock;
371 : : }
372 : : }
373 : :
374 : 15536 : return NULL;
375 : : }
376 : :
377 : : struct spdk_sock *
378 : 74 : spdk_sock_listen(const char *ip, int port, const char *impl_name)
379 : : {
380 : 18 : struct spdk_sock_opts opts;
381 : :
382 : 74 : opts.opts_size = sizeof(opts);
383 : 74 : spdk_sock_get_default_opts(&opts);
384 : 74 : return spdk_sock_listen_ext(ip, port, impl_name, &opts);
385 : : }
386 : :
387 : : struct spdk_sock *
388 : 356 : spdk_sock_listen_ext(const char *ip, int port, const char *_impl_name, struct spdk_sock_opts *opts)
389 : : {
390 : 356 : struct spdk_net_impl *impl = NULL;
391 : : struct spdk_sock *sock;
392 : 46 : struct spdk_sock_opts opts_local;
393 : 356 : const char *impl_name = NULL;
394 : :
395 [ - + ]: 356 : if (opts == NULL) {
396 : 0 : SPDK_ERRLOG("the opts should not be NULL pointer\n");
397 : 0 : return NULL;
398 : : }
399 : :
400 [ + + ]: 356 : if (_impl_name) {
401 : 66 : impl_name = _impl_name;
402 [ + - ]: 290 : } else if (g_default_impl) {
403 : 290 : impl_name = g_default_impl->name;
404 : : }
405 : :
406 [ + - + - ]: 764 : STAILQ_FOREACH_FROM(impl, &g_net_impls, link) {
407 [ + - + + : 764 : if (impl_name && strncmp(impl_name, impl->name, strlen(impl->name) + 1)) {
- + - + +
+ ]
408 : 408 : continue;
409 : : }
410 : :
411 [ - + - + ]: 356 : SPDK_DEBUGLOG(sock, "Creating a listening socket using impl %s\n", impl->name);
412 : 356 : sock_init_opts(&opts_local, opts);
413 : 356 : sock = impl->listen(ip, port, &opts_local);
414 [ + - ]: 356 : if (sock != NULL) {
415 : : /* Copy the contents, both the two structures are the same ABI version */
416 [ - + ]: 356 : memcpy(&sock->opts, &opts_local, sizeof(sock->opts));
417 : : /* Clear out impl_opts to make sure we don't keep reference to a dangling
418 : : * pointer */
419 : 356 : sock->opts.impl_opts = NULL;
420 : 356 : sock->net_impl = impl;
421 : : /* Don't need to initialize the request queues for listen
422 : : * sockets. */
423 : 356 : return sock;
424 : : }
425 : : }
426 : :
427 : 0 : return NULL;
428 : : }
429 : :
430 : : struct spdk_sock *
431 : 981523 : spdk_sock_accept(struct spdk_sock *sock)
432 : : {
433 : : struct spdk_sock *new_sock;
434 : :
435 : 981523 : new_sock = sock->net_impl->accept(sock);
436 [ + + ]: 981523 : if (new_sock != NULL) {
437 : : /* Inherit the opts from the "accept sock" */
438 : 5842 : new_sock->opts = sock->opts;
439 [ - + - + ]: 5842 : memcpy(&new_sock->opts, &sock->opts, sizeof(new_sock->opts));
440 : 5842 : new_sock->net_impl = sock->net_impl;
441 : 5842 : TAILQ_INIT(&new_sock->queued_reqs);
442 : 5842 : TAILQ_INIT(&new_sock->pending_reqs);
443 : : }
444 : :
445 : 981523 : return new_sock;
446 : : }
447 : :
448 : : int
449 : 25905 : spdk_sock_close(struct spdk_sock **_sock)
450 : : {
451 : 25905 : struct spdk_sock *sock = *_sock;
452 : :
453 [ + + ]: 25905 : if (sock == NULL) {
454 : 15523 : errno = EBADF;
455 : 15523 : return -1;
456 : : }
457 : :
458 [ + + ]: 10382 : if (sock->cb_fn != NULL) {
459 : : /* This sock is still part of a sock_group. */
460 : 6 : errno = EBUSY;
461 : 6 : return -1;
462 : : }
463 : :
464 : : /* Beyond this point the socket is considered closed. */
465 : 10376 : *_sock = NULL;
466 : :
467 : 10376 : sock->flags.closed = true;
468 : :
469 [ + + ]: 10376 : if (sock->cb_cnt > 0) {
470 : : /* Let the callback unwind before destroying the socket */
471 : 22 : return 0;
472 : : }
473 : :
474 : 10354 : spdk_sock_abort_requests(sock);
475 : :
476 : 10354 : return sock->net_impl->close(sock);
477 : : }
478 : :
479 : : ssize_t
480 : 232684763 : spdk_sock_recv(struct spdk_sock *sock, void *buf, size_t len)
481 : : {
482 [ + - - + ]: 232684763 : if (sock == NULL || sock->flags.closed) {
483 : 0 : errno = EBADF;
484 : 0 : return -1;
485 : : }
486 : :
487 : 232684763 : return sock->net_impl->recv(sock, buf, len);
488 : : }
489 : :
490 : : ssize_t
491 : 2983904 : spdk_sock_readv(struct spdk_sock *sock, struct iovec *iov, int iovcnt)
492 : : {
493 [ + - - + ]: 2983904 : if (sock == NULL || sock->flags.closed) {
494 : 0 : errno = EBADF;
495 : 0 : return -1;
496 : : }
497 : :
498 : 2983904 : return sock->net_impl->readv(sock, iov, iovcnt);
499 : : }
500 : :
501 : : ssize_t
502 : 568 : spdk_sock_writev(struct spdk_sock *sock, struct iovec *iov, int iovcnt)
503 : : {
504 [ + - - + ]: 568 : if (sock == NULL || sock->flags.closed) {
505 : 0 : errno = EBADF;
506 : 0 : return -1;
507 : : }
508 : :
509 : 568 : return sock->net_impl->writev(sock, iov, iovcnt);
510 : : }
511 : :
512 : : void
513 : 43884945 : spdk_sock_writev_async(struct spdk_sock *sock, struct spdk_sock_request *req)
514 : : {
515 [ - + ]: 43884945 : assert(req->cb_fn != NULL);
516 : :
517 [ + - - + ]: 43884945 : if (sock == NULL || sock->flags.closed) {
518 : 0 : req->cb_fn(req->cb_arg, -EBADF);
519 : 0 : return;
520 : : }
521 : :
522 : 43884945 : sock->net_impl->writev_async(sock, req);
523 : : }
524 : :
525 : : int
526 : 35 : spdk_sock_recv_next(struct spdk_sock *sock, void **buf, void **ctx)
527 : : {
528 [ + - - + ]: 35 : if (sock == NULL || sock->flags.closed) {
529 : 0 : errno = EBADF;
530 : 0 : return -1;
531 : : }
532 : :
533 [ - + ]: 35 : if (sock->group_impl == NULL) {
534 : 0 : errno = ENOTSUP;
535 : 0 : return -1;
536 : : }
537 : :
538 : 35 : return sock->net_impl->recv_next(sock, buf, ctx);
539 : : }
540 : :
541 : : int
542 : 25009889 : spdk_sock_flush(struct spdk_sock *sock)
543 : : {
544 [ + + - + ]: 25009889 : if (sock == NULL || sock->flags.closed) {
545 : 484 : errno = EBADF;
546 : 484 : return -1;
547 : : }
548 : :
549 : 25009405 : return sock->net_impl->flush(sock);
550 : : }
551 : :
552 : : int
553 : 5802 : spdk_sock_set_recvlowat(struct spdk_sock *sock, int nbytes)
554 : : {
555 : 5802 : return sock->net_impl->set_recvlowat(sock, nbytes);
556 : : }
557 : :
558 : : int
559 : 13569 : spdk_sock_set_recvbuf(struct spdk_sock *sock, int sz)
560 : : {
561 : 13569 : return sock->net_impl->set_recvbuf(sock, sz);
562 : : }
563 : :
564 : : int
565 : 6 : spdk_sock_set_sendbuf(struct spdk_sock *sock, int sz)
566 : : {
567 : 6 : return sock->net_impl->set_sendbuf(sock, sz);
568 : : }
569 : :
570 : : bool
571 : 6 : spdk_sock_is_ipv6(struct spdk_sock *sock)
572 : : {
573 : 6 : return sock->net_impl->is_ipv6(sock);
574 : : }
575 : :
576 : : bool
577 : 7483 : spdk_sock_is_ipv4(struct spdk_sock *sock)
578 : : {
579 : 7483 : return sock->net_impl->is_ipv4(sock);
580 : : }
581 : :
582 : : bool
583 : 221125 : spdk_sock_is_connected(struct spdk_sock *sock)
584 : : {
585 : 221125 : return sock->net_impl->is_connected(sock);
586 : : }
587 : :
588 : : struct spdk_sock_group *
589 : 2080 : spdk_sock_group_create(void *ctx)
590 : : {
591 : 2080 : struct spdk_net_impl *impl = NULL;
592 : : struct spdk_sock_group *group;
593 : : struct spdk_sock_group_impl *group_impl;
594 : :
595 : 2080 : group = calloc(1, sizeof(*group));
596 [ - + ]: 2080 : if (group == NULL) {
597 : 0 : return NULL;
598 : : }
599 : :
600 : 2080 : STAILQ_INIT(&group->group_impls);
601 : 2080 : STAILQ_INIT(&group->pool);
602 : :
603 [ + - + + ]: 6661 : STAILQ_FOREACH_FROM(impl, &g_net_impls, link) {
604 : 4581 : group_impl = impl->group_impl_create();
605 [ + - ]: 4581 : if (group_impl != NULL) {
606 : 4581 : STAILQ_INSERT_TAIL(&group->group_impls, group_impl, link);
607 : 4581 : TAILQ_INIT(&group_impl->socks);
608 : 4581 : group_impl->net_impl = impl;
609 : 4581 : group_impl->group = group;
610 : : }
611 : : }
612 : :
613 : 2080 : group->ctx = ctx;
614 : :
615 : 2080 : return group;
616 : : }
617 : :
618 : : void *
619 : 5251 : spdk_sock_group_get_ctx(struct spdk_sock_group *group)
620 : : {
621 [ + + ]: 5251 : if (group == NULL) {
622 : 3 : return NULL;
623 : : }
624 : :
625 : 5248 : return group->ctx;
626 : : }
627 : :
628 : : int
629 : 7158 : spdk_sock_group_add_sock(struct spdk_sock_group *group, struct spdk_sock *sock,
630 : : spdk_sock_cb cb_fn, void *cb_arg)
631 : : {
632 : 7158 : struct spdk_sock_group_impl *group_impl = NULL;
633 : : int rc;
634 : :
635 [ + + ]: 7158 : if (cb_fn == NULL) {
636 : 6 : errno = EINVAL;
637 : 6 : return -1;
638 : : }
639 : :
640 [ + + ]: 7152 : if (sock->group_impl != NULL) {
641 : : /*
642 : : * This sock is already part of a sock_group.
643 : : */
644 : 6 : errno = EINVAL;
645 : 6 : return -1;
646 : : }
647 : :
648 : 7146 : group_impl = sock_get_group_impl_from_group(sock, group);
649 [ - + ]: 7146 : if (group_impl == NULL) {
650 : 0 : errno = EINVAL;
651 : 0 : return -1;
652 : : }
653 : :
654 : 7146 : rc = group_impl->net_impl->group_impl_add_sock(group_impl, sock);
655 [ - + ]: 7146 : if (rc != 0) {
656 : 0 : return rc;
657 : : }
658 : :
659 : 7146 : TAILQ_INSERT_TAIL(&group_impl->socks, sock, link);
660 : 7146 : sock->group_impl = group_impl;
661 : 7146 : sock->cb_fn = cb_fn;
662 : 7146 : sock->cb_arg = cb_arg;
663 : :
664 : 7146 : return 0;
665 : : }
666 : :
667 : : int
668 : 7146 : spdk_sock_group_remove_sock(struct spdk_sock_group *group, struct spdk_sock *sock)
669 : : {
670 : 7146 : struct spdk_sock_group_impl *group_impl = NULL;
671 : : int rc;
672 : :
673 : 7146 : group_impl = sock_get_group_impl_from_group(sock, group);
674 [ - + ]: 7146 : if (group_impl == NULL) {
675 : 0 : errno = EINVAL;
676 : 0 : return -1;
677 : : }
678 : :
679 [ - + ]: 7146 : assert(group_impl == sock->group_impl);
680 : :
681 : 7146 : rc = group_impl->net_impl->group_impl_remove_sock(group_impl, sock);
682 [ + - ]: 7146 : if (rc == 0) {
683 [ + + ]: 7146 : TAILQ_REMOVE(&group_impl->socks, sock, link);
684 : 7146 : sock->group_impl = NULL;
685 : 7146 : sock->cb_fn = NULL;
686 : 7146 : sock->cb_arg = NULL;
687 : : }
688 : :
689 : 7146 : return rc;
690 : : }
691 : :
692 : : int
693 : 39 : spdk_sock_group_provide_buf(struct spdk_sock_group *group, void *buf, size_t len, void *ctx)
694 : : {
695 : : struct spdk_sock_group_provided_buf *provided;
696 : :
697 : 39 : provided = (struct spdk_sock_group_provided_buf *)buf;
698 : :
699 : 39 : provided->len = len;
700 : 39 : provided->ctx = ctx;
701 [ + - ]: 39 : STAILQ_INSERT_HEAD(&group->pool, provided, link);
702 : :
703 : 39 : return 0;
704 : : }
705 : :
706 : : size_t
707 : 35 : spdk_sock_group_get_buf(struct spdk_sock_group *group, void **buf, void **ctx)
708 : : {
709 : : struct spdk_sock_group_provided_buf *provided;
710 : :
711 : 35 : provided = STAILQ_FIRST(&group->pool);
712 [ - + ]: 35 : if (provided == NULL) {
713 : 0 : *buf = NULL;
714 : 0 : return 0;
715 : : }
716 [ + - ]: 35 : STAILQ_REMOVE_HEAD(&group->pool, link);
717 : :
718 : 35 : *buf = provided;
719 : 35 : *ctx = provided->ctx;
720 : 35 : return provided->len;
721 : : }
722 : :
723 : : int
724 : 579687328 : spdk_sock_group_poll(struct spdk_sock_group *group)
725 : : {
726 : 579687328 : return spdk_sock_group_poll_count(group, MAX_EVENTS_PER_POLL);
727 : : }
728 : :
729 : : static int
730 : 1252812487 : sock_group_impl_poll_count(struct spdk_sock_group_impl *group_impl,
731 : : struct spdk_sock_group *group,
732 : : int max_events)
733 : : {
734 : 72760679 : struct spdk_sock *socks[MAX_EVENTS_PER_POLL];
735 : : int num_events, i;
736 : :
737 [ + + ]: 1252812487 : if (TAILQ_EMPTY(&group_impl->socks)) {
738 : 700323071 : return 0;
739 : : }
740 : :
741 : 552489416 : num_events = group_impl->net_impl->group_impl_poll(group_impl, max_events, socks);
742 [ - + ]: 552489416 : if (num_events == -1) {
743 : 0 : return -1;
744 : : }
745 : :
746 [ + + ]: 661222565 : for (i = 0; i < num_events; i++) {
747 : 108733149 : struct spdk_sock *sock = socks[i];
748 [ - + ]: 108733149 : assert(sock->cb_fn != NULL);
749 : 108733149 : sock->cb_fn(sock->cb_arg, group, sock);
750 : : }
751 : :
752 : 552489416 : return num_events;
753 : : }
754 : :
755 : : int
756 : 579687340 : spdk_sock_group_poll_count(struct spdk_sock_group *group, int max_events)
757 : : {
758 : 579687340 : struct spdk_sock_group_impl *group_impl = NULL;
759 : 579687340 : int rc, num_events = 0;
760 : :
761 [ - + ]: 579687340 : if (max_events < 1) {
762 : 0 : errno = -EINVAL;
763 : 0 : return -1;
764 : : }
765 : :
766 : : /*
767 : : * Only poll for up to 32 events at a time - if more events are pending,
768 : : * the next call to this function will reap them.
769 : : */
770 [ - + ]: 579687340 : if (max_events > MAX_EVENTS_PER_POLL) {
771 : 0 : max_events = MAX_EVENTS_PER_POLL;
772 : : }
773 : :
774 [ + - + + ]: 1832499827 : STAILQ_FOREACH_FROM(group_impl, &group->group_impls, link) {
775 : 1252812487 : rc = sock_group_impl_poll_count(group_impl, group, max_events);
776 [ - + ]: 1252812487 : if (rc < 0) {
777 : 0 : num_events = -1;
778 : 0 : SPDK_ERRLOG("group_impl_poll_count for net(%s) failed\n",
779 : : group_impl->net_impl->name);
780 [ + - ]: 1252812487 : } else if (num_events >= 0) {
781 : 1252812487 : num_events += rc;
782 : : }
783 : : }
784 : :
785 : 579687340 : return num_events;
786 : : }
787 : :
788 : : int
789 : 2102 : spdk_sock_group_close(struct spdk_sock_group **group)
790 : : {
791 : 2102 : struct spdk_sock_group_impl *group_impl = NULL, *tmp;
792 : : int rc;
793 : :
794 [ + + ]: 2102 : if (*group == NULL) {
795 : 16 : errno = EBADF;
796 : 16 : return -1;
797 : : }
798 : :
799 [ + + ]: 6673 : STAILQ_FOREACH_SAFE(group_impl, &(*group)->group_impls, link, tmp) {
800 [ + + ]: 4593 : if (!TAILQ_EMPTY(&group_impl->socks)) {
801 : 6 : errno = EBUSY;
802 : 6 : return -1;
803 : : }
804 : : }
805 : :
806 [ + + ]: 6661 : STAILQ_FOREACH_SAFE(group_impl, &(*group)->group_impls, link, tmp) {
807 : 4581 : rc = group_impl->net_impl->group_impl_close(group_impl);
808 [ - + ]: 4581 : if (rc != 0) {
809 : 0 : SPDK_ERRLOG("group_impl_close for net failed\n");
810 : : }
811 : : }
812 : :
813 : 2080 : free(*group);
814 : 2080 : *group = NULL;
815 : :
816 : 2080 : return 0;
817 : : }
818 : :
819 : : static inline struct spdk_net_impl *
820 : 3465 : sock_get_impl_by_name(const char *impl_name)
821 : : {
822 : : struct spdk_net_impl *impl;
823 : :
824 [ - + ]: 3465 : assert(impl_name != NULL);
825 [ + - ]: 4412 : STAILQ_FOREACH(impl, &g_net_impls, link) {
826 [ + + - + : 4412 : if (0 == strcmp(impl_name, impl->name)) {
+ + ]
827 : 3465 : return impl;
828 : : }
829 : : }
830 : :
831 : 0 : return NULL;
832 : : }
833 : :
834 : : int
835 : 390 : spdk_sock_impl_get_opts(const char *impl_name, struct spdk_sock_impl_opts *opts, size_t *len)
836 : : {
837 : : struct spdk_net_impl *impl;
838 : :
839 [ + - + + : 390 : if (!impl_name || !opts || !len) {
+ + ]
840 : 12 : errno = EINVAL;
841 : 12 : return -1;
842 : : }
843 : :
844 : 378 : impl = sock_get_impl_by_name(impl_name);
845 [ - + ]: 378 : if (!impl) {
846 : 0 : errno = EINVAL;
847 : 0 : return -1;
848 : : }
849 : :
850 [ + + ]: 378 : if (!impl->get_opts) {
851 : 3 : errno = ENOTSUP;
852 : 3 : return -1;
853 : : }
854 : :
855 : 375 : return impl->get_opts(opts, len);
856 : : }
857 : :
858 : : int
859 : 155 : spdk_sock_impl_set_opts(const char *impl_name, const struct spdk_sock_impl_opts *opts, size_t len)
860 : : {
861 : : struct spdk_net_impl *impl;
862 : :
863 [ + - + + ]: 155 : if (!impl_name || !opts) {
864 : 6 : errno = EINVAL;
865 : 6 : return -1;
866 : : }
867 : :
868 : 149 : impl = sock_get_impl_by_name(impl_name);
869 [ - + ]: 149 : if (!impl) {
870 : 0 : errno = EINVAL;
871 : 0 : return -1;
872 : : }
873 : :
874 [ + + ]: 149 : if (!impl->set_opts) {
875 : 3 : errno = ENOTSUP;
876 : 3 : return -1;
877 : : }
878 : :
879 : 146 : return impl->set_opts(opts, len);
880 : : }
881 : :
882 : : void
883 : 118 : spdk_sock_write_config_json(struct spdk_json_write_ctx *w)
884 : : {
885 : : struct spdk_net_impl *impl;
886 : 40 : struct spdk_sock_impl_opts opts;
887 : 40 : size_t len;
888 : :
889 [ - + ]: 118 : assert(w != NULL);
890 : :
891 : 118 : spdk_json_write_array_begin(w);
892 : :
893 [ + - ]: 118 : if (g_default_impl) {
894 : 118 : spdk_json_write_object_begin(w);
895 : 118 : spdk_json_write_named_string(w, "method", "sock_set_default_impl");
896 : 118 : spdk_json_write_named_object_begin(w, "params");
897 : 118 : spdk_json_write_named_string(w, "impl_name", g_default_impl->name);
898 : 118 : spdk_json_write_object_end(w);
899 : 118 : spdk_json_write_object_end(w);
900 : : }
901 : :
902 [ + + ]: 371 : STAILQ_FOREACH(impl, &g_net_impls, link) {
903 [ - + ]: 253 : if (!impl->get_opts) {
904 : 0 : continue;
905 : : }
906 : :
907 : 253 : len = sizeof(opts);
908 [ + - ]: 253 : if (impl->get_opts(&opts, &len) == 0) {
909 : 253 : spdk_json_write_object_begin(w);
910 : 253 : spdk_json_write_named_string(w, "method", "sock_impl_set_options");
911 : 253 : spdk_json_write_named_object_begin(w, "params");
912 : 253 : spdk_json_write_named_string(w, "impl_name", impl->name);
913 : 253 : spdk_json_write_named_uint32(w, "recv_buf_size", opts.recv_buf_size);
914 : 253 : spdk_json_write_named_uint32(w, "send_buf_size", opts.send_buf_size);
915 [ - + ]: 253 : spdk_json_write_named_bool(w, "enable_recv_pipe", opts.enable_recv_pipe);
916 [ - + ]: 253 : spdk_json_write_named_bool(w, "enable_quickack", opts.enable_quickack);
917 : 253 : spdk_json_write_named_uint32(w, "enable_placement_id", opts.enable_placement_id);
918 [ - + ]: 253 : spdk_json_write_named_bool(w, "enable_zerocopy_send_server", opts.enable_zerocopy_send_server);
919 [ - + ]: 253 : spdk_json_write_named_bool(w, "enable_zerocopy_send_client", opts.enable_zerocopy_send_client);
920 : 253 : spdk_json_write_named_uint32(w, "zerocopy_threshold", opts.zerocopy_threshold);
921 : 253 : spdk_json_write_named_uint32(w, "tls_version", opts.tls_version);
922 [ - + ]: 253 : spdk_json_write_named_bool(w, "enable_ktls", opts.enable_ktls);
923 : 253 : spdk_json_write_object_end(w);
924 : 253 : spdk_json_write_object_end(w);
925 : : } else {
926 : 0 : SPDK_ERRLOG("Failed to get socket options for socket implementation %s\n", impl->name);
927 : : }
928 : : }
929 : :
930 : 118 : spdk_json_write_array_end(w);
931 : 118 : }
932 : :
933 : : void
934 : 5490 : spdk_net_impl_register(struct spdk_net_impl *impl)
935 : : {
936 [ + + ]: 5490 : STAILQ_INSERT_HEAD(&g_net_impls, impl, link);
937 : 5490 : }
938 : :
939 : : int
940 : 2944 : spdk_sock_set_default_impl(const char *impl_name)
941 : : {
942 : : struct spdk_net_impl *impl;
943 : :
944 [ + + ]: 2944 : if (!impl_name) {
945 : 6 : errno = EINVAL;
946 : 6 : return -1;
947 : : }
948 : :
949 : 2938 : impl = sock_get_impl_by_name(impl_name);
950 [ - + ]: 2938 : if (!impl) {
951 : 0 : errno = EINVAL;
952 : 0 : return -1;
953 : : }
954 : :
955 [ + + ]: 2938 : if (impl == g_default_impl) {
956 : 61 : return 0;
957 : : }
958 : :
959 [ + + ]: 2877 : if (g_default_impl) {
960 [ - + - + ]: 323 : SPDK_DEBUGLOG(sock, "Change the default sock impl from %s to %s\n", g_default_impl->name,
961 : : impl->name);
962 : : } else {
963 [ - + - + ]: 2554 : SPDK_DEBUGLOG(sock, "Set default sock implementation to %s\n", impl_name);
964 : : }
965 : :
966 : 2877 : g_default_impl = impl;
967 : :
968 : 2877 : return 0;
969 : : }
970 : :
971 : : const char *
972 : 2 : spdk_sock_get_default_impl(void)
973 : : {
974 [ + - ]: 2 : if (g_default_impl) {
975 : 2 : return g_default_impl->name;
976 : : }
977 : :
978 : 0 : return NULL;
979 : : }
980 : :
981 : : int
982 : 0 : spdk_sock_group_register_interrupt(struct spdk_sock_group *group, uint32_t events,
983 : : spdk_interrupt_fn fn,
984 : : void *arg, const char *name)
985 : : {
986 : 0 : struct spdk_sock_group_impl *group_impl = NULL;
987 : : int rc;
988 : :
989 [ # # ]: 0 : assert(group != NULL);
990 [ # # ]: 0 : assert(fn != NULL);
991 : :
992 [ # # # # ]: 0 : STAILQ_FOREACH_FROM(group_impl, &group->group_impls, link) {
993 : 0 : rc = group_impl->net_impl->group_impl_register_interrupt(group_impl, events, fn, arg, name);
994 [ # # ]: 0 : if (rc != 0) {
995 : 0 : return rc;
996 : : }
997 : : }
998 : :
999 : 0 : return 0;
1000 : : }
1001 : :
1002 : : void
1003 : 0 : spdk_sock_group_unregister_interrupt(struct spdk_sock_group *group)
1004 : : {
1005 : 0 : struct spdk_sock_group_impl *group_impl = NULL;
1006 : :
1007 [ # # ]: 0 : assert(group != NULL);
1008 : :
1009 [ # # # # ]: 0 : STAILQ_FOREACH_FROM(group_impl, &group->group_impls, link) {
1010 : 0 : group_impl->net_impl->group_impl_unregister_interrupt(group_impl);
1011 : : }
1012 : 0 : }
1013 : :
1014 : 2568 : SPDK_LOG_REGISTER_COMPONENT(sock)
1015 : :
1016 : 4671 : SPDK_TRACE_REGISTER_FN(sock_trace, "sock", TRACE_GROUP_SOCK)
1017 : : {
1018 : 2103 : struct spdk_trace_tpoint_opts opts[] = {
1019 : : {
1020 : : "SOCK_REQ_QUEUE", TRACE_SOCK_REQ_QUEUE,
1021 : : OWNER_TYPE_SOCK, OBJECT_SOCK_REQ, 1,
1022 : : {
1023 : : { "ctx", SPDK_TRACE_ARG_TYPE_PTR, 8 },
1024 : : }
1025 : : },
1026 : : {
1027 : : "SOCK_REQ_PEND", TRACE_SOCK_REQ_PEND,
1028 : : OWNER_TYPE_SOCK, OBJECT_SOCK_REQ, 0,
1029 : : {
1030 : : { "ctx", SPDK_TRACE_ARG_TYPE_PTR, 8 },
1031 : : }
1032 : : },
1033 : : {
1034 : : "SOCK_REQ_COMPLETE", TRACE_SOCK_REQ_COMPLETE,
1035 : : OWNER_TYPE_SOCK, OBJECT_SOCK_REQ, 0,
1036 : : {
1037 : : { "ctx", SPDK_TRACE_ARG_TYPE_PTR, 8 },
1038 : : }
1039 : : },
1040 : : };
1041 : :
1042 : 2103 : spdk_trace_register_owner_type(OWNER_TYPE_SOCK, 's');
1043 : 2103 : spdk_trace_register_object(OBJECT_SOCK_REQ, 's');
1044 : 2103 : spdk_trace_register_description_ext(opts, SPDK_COUNTOF(opts));
1045 : 2103 : }
|