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 : 23932 : sock_get_group_impl_from_group(struct spdk_sock *sock, struct spdk_sock_group *group)
36 : : {
37 : 23932 : struct spdk_sock_group_impl *group_impl = NULL;
38 : :
39 [ + - + - ]: 50214 : STAILQ_FOREACH_FROM(group_impl, &group->group_impls, link) {
40 [ + + ]: 50214 : if (sock->net_impl == group_impl->net_impl) {
41 : 23932 : 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 [ + + ]: 43 : STAILQ_FOREACH(entry, &map->entries, link) {
75 [ + + ]: 25 : 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 [ + - ]: 16 : STAILQ_FOREACH(entry, &map->entries, link) {
116 [ + + ]: 16 : 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 [ + + ]: 46 : STAILQ_FOREACH(entry, &map->entries, link) {
139 [ + + ]: 38 : 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 : 2952 : spdk_sock_map_cleanup(struct spdk_sock_map *map)
173 : : {
174 : : struct spdk_sock_placement_id_entry *entry, *tmp;
175 : :
176 [ - + ]: 2952 : pthread_mutex_lock(&map->mtx);
177 [ + + ]: 2975 : 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 [ - + ]: 2952 : pthread_mutex_unlock(&map->mtx);
182 : 2952 : }
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 : 6714 : 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 : 6714 : struct spdk_sock_group_impl *hint_group_impl = NULL;
209 : :
210 [ - + ]: 6714 : assert(group != NULL);
211 : :
212 [ + - ]: 6714 : if (hint != NULL) {
213 : 6714 : hint_group_impl = sock_get_group_impl_from_group(sock, hint);
214 [ - + ]: 6714 : if (hint_group_impl == NULL) {
215 : 0 : return -EINVAL;
216 : : }
217 : : }
218 : :
219 : 6714 : group_impl = sock->net_impl->group_impl_get_optimal(sock, hint_group_impl);
220 : :
221 [ + + ]: 6714 : if (group_impl) {
222 : 3 : *group = group_impl->group;
223 : : }
224 : :
225 : 6714 : return 0;
226 : : }
227 : :
228 : : int
229 : 14001 : spdk_sock_getaddr(struct spdk_sock *sock, char *saddr, int slen, uint16_t *sport,
230 : : char *caddr, int clen, uint16_t *cport)
231 : : {
232 : 14001 : return sock->net_impl->getaddr(sock, saddr, slen, sport, caddr, clen, cport);
233 : : }
234 : :
235 : : const char *
236 : 522 : spdk_sock_get_impl_name(struct spdk_sock *sock)
237 : : {
238 : 522 : return sock->net_impl->name;
239 : : }
240 : :
241 : : void
242 : 26348 : spdk_sock_get_default_opts(struct spdk_sock_opts *opts)
243 : : {
244 [ - + ]: 26348 : assert(opts);
245 : :
246 [ + + ]: 26348 : if (SPDK_SOCK_OPTS_FIELD_OK(opts, priority)) {
247 : 26342 : opts->priority = SPDK_SOCK_DEFAULT_PRIORITY;
248 : : }
249 : :
250 [ + + ]: 26348 : if (SPDK_SOCK_OPTS_FIELD_OK(opts, zcopy)) {
251 : 26342 : opts->zcopy = SPDK_SOCK_DEFAULT_ZCOPY;
252 : : }
253 : :
254 [ + + ]: 26348 : if (SPDK_SOCK_OPTS_FIELD_OK(opts, ack_timeout)) {
255 : 26342 : opts->ack_timeout = SPDK_SOCK_DEFAULT_ACK_TIMEOUT;
256 : : }
257 : :
258 [ + + ]: 26348 : if (SPDK_SOCK_OPTS_FIELD_OK(opts, impl_opts)) {
259 : 26342 : opts->impl_opts = NULL;
260 : : }
261 : :
262 [ + + ]: 26348 : if (SPDK_SOCK_OPTS_FIELD_OK(opts, impl_opts_size)) {
263 : 26342 : opts->impl_opts_size = 0;
264 : : }
265 : 26348 : }
266 : :
267 : : /*
268 : : * opts The opts allocated in the current library.
269 : : * opts_user The opts passed by the caller.
270 : : * */
271 : : static void
272 : 13168 : sock_init_opts(struct spdk_sock_opts *opts, struct spdk_sock_opts *opts_user)
273 : : {
274 [ - + ]: 13168 : assert(opts);
275 [ - + ]: 13168 : assert(opts_user);
276 : :
277 : 13168 : opts->opts_size = sizeof(*opts);
278 : 13168 : spdk_sock_get_default_opts(opts);
279 : :
280 : : /* reset the size according to the user */
281 : 13168 : opts->opts_size = opts_user->opts_size;
282 [ + - ]: 13168 : if (SPDK_SOCK_OPTS_FIELD_OK(opts, priority)) {
283 : 13168 : opts->priority = opts_user->priority;
284 : : }
285 : :
286 [ + - ]: 13168 : if (SPDK_SOCK_OPTS_FIELD_OK(opts, zcopy)) {
287 [ - + ]: 13168 : opts->zcopy = opts_user->zcopy;
288 : : }
289 : :
290 [ + - ]: 13168 : if (SPDK_SOCK_OPTS_FIELD_OK(opts, ack_timeout)) {
291 : 13168 : opts->ack_timeout = opts_user->ack_timeout;
292 : : }
293 : :
294 [ + - ]: 13168 : if (SPDK_SOCK_OPTS_FIELD_OK(opts, impl_opts)) {
295 : 13168 : opts->impl_opts = opts_user->impl_opts;
296 : : }
297 : :
298 [ + - ]: 13168 : if (SPDK_SOCK_OPTS_FIELD_OK(opts, impl_opts)) {
299 : 13168 : opts->impl_opts_size = opts_user->impl_opts_size;
300 : : }
301 : 13168 : }
302 : :
303 : : struct spdk_sock *
304 : 26 : spdk_sock_connect(const char *ip, int port, const char *impl_name)
305 : : {
306 : 24 : struct spdk_sock_opts opts;
307 : :
308 : 26 : opts.opts_size = sizeof(opts);
309 : 26 : spdk_sock_get_default_opts(&opts);
310 : 26 : return spdk_sock_connect_ext(ip, port, impl_name, &opts);
311 : : }
312 : :
313 : : struct spdk_sock *
314 : 12815 : spdk_sock_connect_ext(const char *ip, int port, const char *_impl_name, struct spdk_sock_opts *opts)
315 : : {
316 : 12815 : struct spdk_net_impl *impl = NULL;
317 : : struct spdk_sock *sock;
318 : 126 : struct spdk_sock_opts opts_local;
319 : 12815 : const char *impl_name = NULL;
320 : :
321 [ - + ]: 12815 : if (opts == NULL) {
322 : 0 : SPDK_ERRLOG("the opts should not be NULL pointer\n");
323 : 0 : return NULL;
324 : : }
325 : :
326 [ + + ]: 12815 : if (_impl_name) {
327 : 178 : impl_name = _impl_name;
328 [ + - ]: 12637 : } else if (g_default_impl) {
329 : 12637 : impl_name = g_default_impl->name;
330 : : }
331 : :
332 [ + - + + ]: 34565 : STAILQ_FOREACH_FROM(impl, &g_net_impls, link) {
333 [ + - + + : 25944 : if (impl_name && strncmp(impl_name, impl->name, strlen(impl->name) + 1)) {
- + - + +
+ ]
334 : 13129 : continue;
335 : : }
336 : :
337 [ - + + + ]: 12815 : SPDK_DEBUGLOG(sock, "Creating a client socket using impl %s\n", impl->name);
338 : 12815 : sock_init_opts(&opts_local, opts);
339 : 12815 : sock = impl->connect(ip, port, &opts_local);
340 [ + + ]: 12815 : if (sock != NULL) {
341 : : /* Copy the contents, both the two structures are the same ABI version */
342 [ - + ]: 4194 : memcpy(&sock->opts, &opts_local, sizeof(sock->opts));
343 : : /* Clear out impl_opts to make sure we don't keep reference to a dangling
344 : : * pointer */
345 : 4194 : sock->opts.impl_opts = NULL;
346 : 4194 : sock->net_impl = impl;
347 : 4194 : TAILQ_INIT(&sock->queued_reqs);
348 : 4194 : TAILQ_INIT(&sock->pending_reqs);
349 : :
350 : 4194 : return sock;
351 : : }
352 : : }
353 : :
354 : 8621 : return NULL;
355 : : }
356 : :
357 : : struct spdk_sock *
358 : 74 : spdk_sock_listen(const char *ip, int port, const char *impl_name)
359 : : {
360 : 18 : struct spdk_sock_opts opts;
361 : :
362 : 74 : opts.opts_size = sizeof(opts);
363 : 74 : spdk_sock_get_default_opts(&opts);
364 : 74 : return spdk_sock_listen_ext(ip, port, impl_name, &opts);
365 : : }
366 : :
367 : : struct spdk_sock *
368 : 353 : spdk_sock_listen_ext(const char *ip, int port, const char *_impl_name, struct spdk_sock_opts *opts)
369 : : {
370 : 353 : struct spdk_net_impl *impl = NULL;
371 : : struct spdk_sock *sock;
372 : 43 : struct spdk_sock_opts opts_local;
373 : 353 : const char *impl_name = NULL;
374 : :
375 [ - + ]: 353 : if (opts == NULL) {
376 : 0 : SPDK_ERRLOG("the opts should not be NULL pointer\n");
377 : 0 : return NULL;
378 : : }
379 : :
380 [ + + ]: 353 : if (_impl_name) {
381 : 63 : impl_name = _impl_name;
382 [ + - ]: 290 : } else if (g_default_impl) {
383 : 290 : impl_name = g_default_impl->name;
384 : : }
385 : :
386 [ + - + - ]: 755 : STAILQ_FOREACH_FROM(impl, &g_net_impls, link) {
387 [ + - + + : 755 : if (impl_name && strncmp(impl_name, impl->name, strlen(impl->name) + 1)) {
- + - + +
+ ]
388 : 402 : continue;
389 : : }
390 : :
391 [ - + - + ]: 353 : SPDK_DEBUGLOG(sock, "Creating a listening socket using impl %s\n", impl->name);
392 : 353 : sock_init_opts(&opts_local, opts);
393 : 353 : sock = impl->listen(ip, port, &opts_local);
394 [ + - ]: 353 : if (sock != NULL) {
395 : : /* Copy the contents, both the two structures are the same ABI version */
396 [ - + ]: 353 : memcpy(&sock->opts, &opts_local, sizeof(sock->opts));
397 : : /* Clear out impl_opts to make sure we don't keep reference to a dangling
398 : : * pointer */
399 : 353 : sock->opts.impl_opts = NULL;
400 : 353 : sock->net_impl = impl;
401 : : /* Don't need to initialize the request queues for listen
402 : : * sockets. */
403 : 353 : return sock;
404 : : }
405 : : }
406 : :
407 : 0 : return NULL;
408 : : }
409 : :
410 : : struct spdk_sock *
411 : 965107 : spdk_sock_accept(struct spdk_sock *sock)
412 : : {
413 : : struct spdk_sock *new_sock;
414 : :
415 : 965107 : new_sock = sock->net_impl->accept(sock);
416 [ + + ]: 965107 : if (new_sock != NULL) {
417 : : /* Inherit the opts from the "accept sock" */
418 : 7302 : new_sock->opts = sock->opts;
419 [ - + - + ]: 7302 : memcpy(&new_sock->opts, &sock->opts, sizeof(new_sock->opts));
420 : 7302 : new_sock->net_impl = sock->net_impl;
421 : 7302 : TAILQ_INIT(&new_sock->queued_reqs);
422 : 7302 : TAILQ_INIT(&new_sock->pending_reqs);
423 : : }
424 : :
425 : 965107 : return new_sock;
426 : : }
427 : :
428 : : int
429 : 20483 : spdk_sock_close(struct spdk_sock **_sock)
430 : : {
431 : 20483 : struct spdk_sock *sock = *_sock;
432 : :
433 [ + + ]: 20483 : if (sock == NULL) {
434 : 8608 : errno = EBADF;
435 : 8608 : return -1;
436 : : }
437 : :
438 [ + + ]: 11875 : if (sock->cb_fn != NULL) {
439 : : /* This sock is still part of a sock_group. */
440 : 6 : errno = EBUSY;
441 : 6 : return -1;
442 : : }
443 : :
444 : : /* Beyond this point the socket is considered closed. */
445 : 11869 : *_sock = NULL;
446 : :
447 : 11869 : sock->flags.closed = true;
448 : :
449 [ + + ]: 11869 : if (sock->cb_cnt > 0) {
450 : : /* Let the callback unwind before destroying the socket */
451 : 20 : return 0;
452 : : }
453 : :
454 : 11849 : spdk_sock_abort_requests(sock);
455 : :
456 : 11849 : return sock->net_impl->close(sock);
457 : : }
458 : :
459 : : ssize_t
460 : 240084004 : spdk_sock_recv(struct spdk_sock *sock, void *buf, size_t len)
461 : : {
462 [ + - - + ]: 240084004 : if (sock == NULL || sock->flags.closed) {
463 : 0 : errno = EBADF;
464 : 0 : return -1;
465 : : }
466 : :
467 : 240084004 : return sock->net_impl->recv(sock, buf, len);
468 : : }
469 : :
470 : : ssize_t
471 : 2797226 : spdk_sock_readv(struct spdk_sock *sock, struct iovec *iov, int iovcnt)
472 : : {
473 [ + - - + ]: 2797226 : if (sock == NULL || sock->flags.closed) {
474 : 0 : errno = EBADF;
475 : 0 : return -1;
476 : : }
477 : :
478 : 2797226 : return sock->net_impl->readv(sock, iov, iovcnt);
479 : : }
480 : :
481 : : ssize_t
482 : 825 : spdk_sock_writev(struct spdk_sock *sock, struct iovec *iov, int iovcnt)
483 : : {
484 [ + - - + ]: 825 : if (sock == NULL || sock->flags.closed) {
485 : 0 : errno = EBADF;
486 : 0 : return -1;
487 : : }
488 : :
489 : 825 : return sock->net_impl->writev(sock, iov, iovcnt);
490 : : }
491 : :
492 : : void
493 : 44663684 : spdk_sock_writev_async(struct spdk_sock *sock, struct spdk_sock_request *req)
494 : : {
495 [ - + ]: 44663684 : assert(req->cb_fn != NULL);
496 : :
497 [ + - - + ]: 44663684 : if (sock == NULL || sock->flags.closed) {
498 : 0 : req->cb_fn(req->cb_arg, -EBADF);
499 : 0 : return;
500 : : }
501 : :
502 : 44663684 : sock->net_impl->writev_async(sock, req);
503 : : }
504 : :
505 : : int
506 : 34 : spdk_sock_recv_next(struct spdk_sock *sock, void **buf, void **ctx)
507 : : {
508 [ + - - + ]: 34 : if (sock == NULL || sock->flags.closed) {
509 : 0 : errno = EBADF;
510 : 0 : return -1;
511 : : }
512 : :
513 [ - + ]: 34 : if (sock->group_impl == NULL) {
514 : 0 : errno = ENOTSUP;
515 : 0 : return -1;
516 : : }
517 : :
518 : 34 : return sock->net_impl->recv_next(sock, buf, ctx);
519 : : }
520 : :
521 : : int
522 : 25040244 : spdk_sock_flush(struct spdk_sock *sock)
523 : : {
524 [ + + - + ]: 25040244 : if (sock == NULL || sock->flags.closed) {
525 : 476 : errno = EBADF;
526 : 476 : return -1;
527 : : }
528 : :
529 : 25039768 : return sock->net_impl->flush(sock);
530 : : }
531 : :
532 : : int
533 : 7265 : spdk_sock_set_recvlowat(struct spdk_sock *sock, int nbytes)
534 : : {
535 : 7265 : return sock->net_impl->set_recvlowat(sock, nbytes);
536 : : }
537 : :
538 : : int
539 : 15439 : spdk_sock_set_recvbuf(struct spdk_sock *sock, int sz)
540 : : {
541 : 15439 : return sock->net_impl->set_recvbuf(sock, sz);
542 : : }
543 : :
544 : : int
545 : 6 : spdk_sock_set_sendbuf(struct spdk_sock *sock, int sz)
546 : : {
547 : 6 : return sock->net_impl->set_sendbuf(sock, sz);
548 : : }
549 : :
550 : : bool
551 : 6 : spdk_sock_is_ipv6(struct spdk_sock *sock)
552 : : {
553 : 6 : return sock->net_impl->is_ipv6(sock);
554 : : }
555 : :
556 : : bool
557 : 8946 : spdk_sock_is_ipv4(struct spdk_sock *sock)
558 : : {
559 : 8946 : return sock->net_impl->is_ipv4(sock);
560 : : }
561 : :
562 : : bool
563 : 339100 : spdk_sock_is_connected(struct spdk_sock *sock)
564 : : {
565 : 339100 : return sock->net_impl->is_connected(sock);
566 : : }
567 : :
568 : : struct spdk_sock_group *
569 : 2079 : spdk_sock_group_create(void *ctx)
570 : : {
571 : 2079 : struct spdk_net_impl *impl = NULL;
572 : : struct spdk_sock_group *group;
573 : : struct spdk_sock_group_impl *group_impl;
574 : :
575 : 2079 : group = calloc(1, sizeof(*group));
576 [ - + ]: 2079 : if (group == NULL) {
577 : 0 : return NULL;
578 : : }
579 : :
580 : 2079 : STAILQ_INIT(&group->group_impls);
581 : 2079 : STAILQ_INIT(&group->pool);
582 : :
583 [ + - + + ]: 6658 : STAILQ_FOREACH_FROM(impl, &g_net_impls, link) {
584 : 4579 : group_impl = impl->group_impl_create();
585 [ + - ]: 4579 : if (group_impl != NULL) {
586 : 4579 : STAILQ_INSERT_TAIL(&group->group_impls, group_impl, link);
587 : 4579 : TAILQ_INIT(&group_impl->socks);
588 : 4579 : group_impl->net_impl = impl;
589 : 4579 : group_impl->group = group;
590 : : }
591 : : }
592 : :
593 : 2079 : group->ctx = ctx;
594 : :
595 : 2079 : return group;
596 : : }
597 : :
598 : : void *
599 : 6714 : spdk_sock_group_get_ctx(struct spdk_sock_group *group)
600 : : {
601 [ + + ]: 6714 : if (group == NULL) {
602 : 3 : return NULL;
603 : : }
604 : :
605 : 6711 : return group->ctx;
606 : : }
607 : :
608 : : int
609 : 8621 : spdk_sock_group_add_sock(struct spdk_sock_group *group, struct spdk_sock *sock,
610 : : spdk_sock_cb cb_fn, void *cb_arg)
611 : : {
612 : 8621 : struct spdk_sock_group_impl *group_impl = NULL;
613 : : int rc;
614 : :
615 [ + + ]: 8621 : if (cb_fn == NULL) {
616 : 6 : errno = EINVAL;
617 : 6 : return -1;
618 : : }
619 : :
620 [ + + ]: 8615 : if (sock->group_impl != NULL) {
621 : : /*
622 : : * This sock is already part of a sock_group.
623 : : */
624 : 6 : errno = EINVAL;
625 : 6 : return -1;
626 : : }
627 : :
628 : 8609 : group_impl = sock_get_group_impl_from_group(sock, group);
629 [ - + ]: 8609 : if (group_impl == NULL) {
630 : 0 : errno = EINVAL;
631 : 0 : return -1;
632 : : }
633 : :
634 : 8609 : rc = group_impl->net_impl->group_impl_add_sock(group_impl, sock);
635 [ - + ]: 8609 : if (rc != 0) {
636 : 0 : return rc;
637 : : }
638 : :
639 : 8609 : TAILQ_INSERT_TAIL(&group_impl->socks, sock, link);
640 : 8609 : sock->group_impl = group_impl;
641 : 8609 : sock->cb_fn = cb_fn;
642 : 8609 : sock->cb_arg = cb_arg;
643 : :
644 : 8609 : return 0;
645 : : }
646 : :
647 : : int
648 : 8609 : spdk_sock_group_remove_sock(struct spdk_sock_group *group, struct spdk_sock *sock)
649 : : {
650 : 8609 : struct spdk_sock_group_impl *group_impl = NULL;
651 : : int rc;
652 : :
653 : 8609 : group_impl = sock_get_group_impl_from_group(sock, group);
654 [ - + ]: 8609 : if (group_impl == NULL) {
655 : 0 : errno = EINVAL;
656 : 0 : return -1;
657 : : }
658 : :
659 [ - + ]: 8609 : assert(group_impl == sock->group_impl);
660 : :
661 : 8609 : rc = group_impl->net_impl->group_impl_remove_sock(group_impl, sock);
662 [ + - ]: 8609 : if (rc == 0) {
663 [ + + ]: 8609 : TAILQ_REMOVE(&group_impl->socks, sock, link);
664 : 8609 : sock->group_impl = NULL;
665 : 8609 : sock->cb_fn = NULL;
666 : 8609 : sock->cb_arg = NULL;
667 : : }
668 : :
669 : 8609 : return rc;
670 : : }
671 : :
672 : : int
673 : 38 : spdk_sock_group_provide_buf(struct spdk_sock_group *group, void *buf, size_t len, void *ctx)
674 : : {
675 : : struct spdk_sock_group_provided_buf *provided;
676 : :
677 : 38 : provided = (struct spdk_sock_group_provided_buf *)buf;
678 : :
679 : 38 : provided->len = len;
680 : 38 : provided->ctx = ctx;
681 [ + - ]: 38 : STAILQ_INSERT_HEAD(&group->pool, provided, link);
682 : :
683 : 38 : return 0;
684 : : }
685 : :
686 : : size_t
687 : 34 : spdk_sock_group_get_buf(struct spdk_sock_group *group, void **buf, void **ctx)
688 : : {
689 : : struct spdk_sock_group_provided_buf *provided;
690 : :
691 : 34 : provided = STAILQ_FIRST(&group->pool);
692 [ - + ]: 34 : if (provided == NULL) {
693 : 0 : *buf = NULL;
694 : 0 : return 0;
695 : : }
696 [ + - ]: 34 : STAILQ_REMOVE_HEAD(&group->pool, link);
697 : :
698 : 34 : *buf = provided;
699 : 34 : *ctx = provided->ctx;
700 : 34 : return provided->len;
701 : : }
702 : :
703 : : int
704 : 594916214 : spdk_sock_group_poll(struct spdk_sock_group *group)
705 : : {
706 : 594916214 : return spdk_sock_group_poll_count(group, MAX_EVENTS_PER_POLL);
707 : : }
708 : :
709 : : static int
710 : 1284664266 : sock_group_impl_poll_count(struct spdk_sock_group_impl *group_impl,
711 : : struct spdk_sock_group *group,
712 : : int max_events)
713 : : {
714 : 68435479 : struct spdk_sock *socks[MAX_EVENTS_PER_POLL];
715 : : int num_events, i;
716 : :
717 [ + + ]: 1284664266 : if (TAILQ_EMPTY(&group_impl->socks)) {
718 : 714342523 : return 0;
719 : : }
720 : :
721 : 570321743 : num_events = group_impl->net_impl->group_impl_poll(group_impl, max_events, socks);
722 [ - + ]: 570321743 : if (num_events == -1) {
723 : 0 : return -1;
724 : : }
725 : :
726 [ + + ]: 684424398 : for (i = 0; i < num_events; i++) {
727 : 114102655 : struct spdk_sock *sock = socks[i];
728 [ - + ]: 114102655 : assert(sock->cb_fn != NULL);
729 : 114102655 : sock->cb_fn(sock->cb_arg, group, sock);
730 : : }
731 : :
732 : 570321743 : return num_events;
733 : : }
734 : :
735 : : int
736 : 594916226 : spdk_sock_group_poll_count(struct spdk_sock_group *group, int max_events)
737 : : {
738 : 594916226 : struct spdk_sock_group_impl *group_impl = NULL;
739 : 594916226 : int rc, num_events = 0;
740 : :
741 [ - + ]: 594916226 : if (max_events < 1) {
742 : 0 : errno = -EINVAL;
743 : 0 : return -1;
744 : : }
745 : :
746 : : /*
747 : : * Only poll for up to 32 events at a time - if more events are pending,
748 : : * the next call to this function will reap them.
749 : : */
750 [ - + ]: 594916226 : if (max_events > MAX_EVENTS_PER_POLL) {
751 : 0 : max_events = MAX_EVENTS_PER_POLL;
752 : : }
753 : :
754 [ + - + + ]: 1879580492 : STAILQ_FOREACH_FROM(group_impl, &group->group_impls, link) {
755 : 1284664266 : rc = sock_group_impl_poll_count(group_impl, group, max_events);
756 [ - + ]: 1284664266 : if (rc < 0) {
757 : 0 : num_events = -1;
758 : 0 : SPDK_ERRLOG("group_impl_poll_count for net(%s) failed\n",
759 : : group_impl->net_impl->name);
760 [ + - ]: 1284664266 : } else if (num_events >= 0) {
761 : 1284664266 : num_events += rc;
762 : : }
763 : : }
764 : :
765 : 594916226 : return num_events;
766 : : }
767 : :
768 : : int
769 : 2101 : spdk_sock_group_close(struct spdk_sock_group **group)
770 : : {
771 : 2101 : struct spdk_sock_group_impl *group_impl = NULL, *tmp;
772 : : int rc;
773 : :
774 [ + + ]: 2101 : if (*group == NULL) {
775 : 16 : errno = EBADF;
776 : 16 : return -1;
777 : : }
778 : :
779 [ + + ]: 6670 : STAILQ_FOREACH_SAFE(group_impl, &(*group)->group_impls, link, tmp) {
780 [ + + ]: 4591 : if (!TAILQ_EMPTY(&group_impl->socks)) {
781 : 6 : errno = EBUSY;
782 : 6 : return -1;
783 : : }
784 : : }
785 : :
786 [ + + ]: 6658 : STAILQ_FOREACH_SAFE(group_impl, &(*group)->group_impls, link, tmp) {
787 : 4579 : rc = group_impl->net_impl->group_impl_close(group_impl);
788 [ - + ]: 4579 : if (rc != 0) {
789 : 0 : SPDK_ERRLOG("group_impl_close for net failed\n");
790 : : }
791 : : }
792 : :
793 : 2079 : free(*group);
794 : 2079 : *group = NULL;
795 : :
796 : 2079 : return 0;
797 : : }
798 : :
799 : : static inline struct spdk_net_impl *
800 : 3458 : sock_get_impl_by_name(const char *impl_name)
801 : : {
802 : : struct spdk_net_impl *impl;
803 : :
804 [ - + ]: 3458 : assert(impl_name != NULL);
805 [ + - ]: 4393 : STAILQ_FOREACH(impl, &g_net_impls, link) {
806 [ + + - + : 4393 : if (0 == strcmp(impl_name, impl->name)) {
+ + ]
807 : 3458 : return impl;
808 : : }
809 : : }
810 : :
811 : 0 : return NULL;
812 : : }
813 : :
814 : : int
815 : 384 : spdk_sock_impl_get_opts(const char *impl_name, struct spdk_sock_impl_opts *opts, size_t *len)
816 : : {
817 : : struct spdk_net_impl *impl;
818 : :
819 [ + - + + : 384 : if (!impl_name || !opts || !len) {
+ + ]
820 : 12 : errno = EINVAL;
821 : 12 : return -1;
822 : : }
823 : :
824 : 372 : impl = sock_get_impl_by_name(impl_name);
825 [ - + ]: 372 : if (!impl) {
826 : 0 : errno = EINVAL;
827 : 0 : return -1;
828 : : }
829 : :
830 [ + + ]: 372 : if (!impl->get_opts) {
831 : 3 : errno = ENOTSUP;
832 : 3 : return -1;
833 : : }
834 : :
835 : 369 : return impl->get_opts(opts, len);
836 : : }
837 : :
838 : : int
839 : 155 : spdk_sock_impl_set_opts(const char *impl_name, const struct spdk_sock_impl_opts *opts, size_t len)
840 : : {
841 : : struct spdk_net_impl *impl;
842 : :
843 [ + - + + ]: 155 : if (!impl_name || !opts) {
844 : 6 : errno = EINVAL;
845 : 6 : return -1;
846 : : }
847 : :
848 : 149 : impl = sock_get_impl_by_name(impl_name);
849 [ - + ]: 149 : if (!impl) {
850 : 0 : errno = EINVAL;
851 : 0 : return -1;
852 : : }
853 : :
854 [ + + ]: 149 : if (!impl->set_opts) {
855 : 3 : errno = ENOTSUP;
856 : 3 : return -1;
857 : : }
858 : :
859 : 146 : return impl->set_opts(opts, len);
860 : : }
861 : :
862 : : void
863 : 118 : spdk_sock_write_config_json(struct spdk_json_write_ctx *w)
864 : : {
865 : : struct spdk_net_impl *impl;
866 : 40 : struct spdk_sock_impl_opts opts;
867 : 40 : size_t len;
868 : :
869 [ - + ]: 118 : assert(w != NULL);
870 : :
871 : 118 : spdk_json_write_array_begin(w);
872 : :
873 [ + - ]: 118 : if (g_default_impl) {
874 : 118 : spdk_json_write_object_begin(w);
875 : 118 : spdk_json_write_named_string(w, "method", "sock_set_default_impl");
876 : 118 : spdk_json_write_named_object_begin(w, "params");
877 : 118 : spdk_json_write_named_string(w, "impl_name", g_default_impl->name);
878 : 118 : spdk_json_write_object_end(w);
879 : 118 : spdk_json_write_object_end(w);
880 : : }
881 : :
882 [ + + ]: 371 : STAILQ_FOREACH(impl, &g_net_impls, link) {
883 [ - + ]: 253 : if (!impl->get_opts) {
884 : 0 : continue;
885 : : }
886 : :
887 : 253 : len = sizeof(opts);
888 [ + - ]: 253 : if (impl->get_opts(&opts, &len) == 0) {
889 : 253 : spdk_json_write_object_begin(w);
890 : 253 : spdk_json_write_named_string(w, "method", "sock_impl_set_options");
891 : 253 : spdk_json_write_named_object_begin(w, "params");
892 : 253 : spdk_json_write_named_string(w, "impl_name", impl->name);
893 : 253 : spdk_json_write_named_uint32(w, "recv_buf_size", opts.recv_buf_size);
894 : 253 : spdk_json_write_named_uint32(w, "send_buf_size", opts.send_buf_size);
895 [ - + ]: 253 : spdk_json_write_named_bool(w, "enable_recv_pipe", opts.enable_recv_pipe);
896 [ - + ]: 253 : spdk_json_write_named_bool(w, "enable_quickack", opts.enable_quickack);
897 : 253 : spdk_json_write_named_uint32(w, "enable_placement_id", opts.enable_placement_id);
898 [ - + ]: 253 : spdk_json_write_named_bool(w, "enable_zerocopy_send_server", opts.enable_zerocopy_send_server);
899 [ - + ]: 253 : spdk_json_write_named_bool(w, "enable_zerocopy_send_client", opts.enable_zerocopy_send_client);
900 : 253 : spdk_json_write_named_uint32(w, "zerocopy_threshold", opts.zerocopy_threshold);
901 : 253 : spdk_json_write_named_uint32(w, "tls_version", opts.tls_version);
902 [ - + ]: 253 : spdk_json_write_named_bool(w, "enable_ktls", opts.enable_ktls);
903 : 253 : spdk_json_write_object_end(w);
904 : 253 : spdk_json_write_object_end(w);
905 : : } else {
906 : 0 : SPDK_ERRLOG("Failed to get socket options for socket implementation %s\n", impl->name);
907 : : }
908 : : }
909 : :
910 : 118 : spdk_json_write_array_end(w);
911 : 118 : }
912 : :
913 : : void
914 : 5488 : spdk_net_impl_register(struct spdk_net_impl *impl)
915 : : {
916 [ + + ]: 5488 : STAILQ_INSERT_HEAD(&g_net_impls, impl, link);
917 : 5488 : }
918 : :
919 : : int
920 : 2943 : spdk_sock_set_default_impl(const char *impl_name)
921 : : {
922 : : struct spdk_net_impl *impl;
923 : :
924 [ + + ]: 2943 : if (!impl_name) {
925 : 6 : errno = EINVAL;
926 : 6 : return -1;
927 : : }
928 : :
929 : 2937 : impl = sock_get_impl_by_name(impl_name);
930 [ - + ]: 2937 : if (!impl) {
931 : 0 : errno = EINVAL;
932 : 0 : return -1;
933 : : }
934 : :
935 [ + + ]: 2937 : if (impl == g_default_impl) {
936 : 61 : return 0;
937 : : }
938 : :
939 [ + + ]: 2876 : if (g_default_impl) {
940 [ - + - + ]: 323 : SPDK_DEBUGLOG(sock, "Change the default sock impl from %s to %s\n", g_default_impl->name,
941 : : impl->name);
942 : : } else {
943 [ - + - + ]: 2553 : SPDK_DEBUGLOG(sock, "Set default sock implementation to %s\n", impl_name);
944 : : }
945 : :
946 : 2876 : g_default_impl = impl;
947 : :
948 : 2876 : return 0;
949 : : }
950 : :
951 : : const char *
952 : 2 : spdk_sock_get_default_impl(void)
953 : : {
954 [ + - ]: 2 : if (g_default_impl) {
955 : 2 : return g_default_impl->name;
956 : : }
957 : :
958 : 0 : return NULL;
959 : : }
960 : :
961 : : int
962 : 0 : spdk_sock_group_register_interrupt(struct spdk_sock_group *group, uint32_t events,
963 : : spdk_interrupt_fn fn,
964 : : void *arg, const char *name)
965 : : {
966 : 0 : struct spdk_sock_group_impl *group_impl = NULL;
967 : : int rc;
968 : :
969 [ # # ]: 0 : assert(group != NULL);
970 [ # # ]: 0 : assert(fn != NULL);
971 : :
972 [ # # # # ]: 0 : STAILQ_FOREACH_FROM(group_impl, &group->group_impls, link) {
973 : 0 : rc = group_impl->net_impl->group_impl_register_interrupt(group_impl, events, fn, arg, name);
974 [ # # ]: 0 : if (rc != 0) {
975 : 0 : return rc;
976 : : }
977 : : }
978 : :
979 : 0 : return 0;
980 : : }
981 : :
982 : : void
983 : 0 : spdk_sock_group_unregister_interrupt(struct spdk_sock_group *group)
984 : : {
985 : 0 : struct spdk_sock_group_impl *group_impl = NULL;
986 : :
987 [ # # ]: 0 : assert(group != NULL);
988 : :
989 [ # # # # ]: 0 : STAILQ_FOREACH_FROM(group_impl, &group->group_impls, link) {
990 : 0 : group_impl->net_impl->group_impl_unregister_interrupt(group_impl);
991 : : }
992 : 0 : }
993 : :
994 : 2567 : SPDK_LOG_REGISTER_COMPONENT(sock)
995 : :
996 : 4669 : SPDK_TRACE_REGISTER_FN(sock_trace, "sock", TRACE_GROUP_SOCK)
997 : : {
998 : 2102 : struct spdk_trace_tpoint_opts opts[] = {
999 : : {
1000 : : "SOCK_REQ_QUEUE", TRACE_SOCK_REQ_QUEUE,
1001 : : OWNER_TYPE_SOCK, OBJECT_SOCK_REQ, 1,
1002 : : {
1003 : : { "ctx", SPDK_TRACE_ARG_TYPE_PTR, 8 },
1004 : : }
1005 : : },
1006 : : {
1007 : : "SOCK_REQ_PEND", TRACE_SOCK_REQ_PEND,
1008 : : OWNER_TYPE_SOCK, OBJECT_SOCK_REQ, 0,
1009 : : {
1010 : : { "ctx", SPDK_TRACE_ARG_TYPE_PTR, 8 },
1011 : : }
1012 : : },
1013 : : {
1014 : : "SOCK_REQ_COMPLETE", TRACE_SOCK_REQ_COMPLETE,
1015 : : OWNER_TYPE_SOCK, OBJECT_SOCK_REQ, 0,
1016 : : {
1017 : : { "ctx", SPDK_TRACE_ARG_TYPE_PTR, 8 },
1018 : : }
1019 : : },
1020 : : };
1021 : :
1022 : 2102 : spdk_trace_register_owner_type(OWNER_TYPE_SOCK, 's');
1023 : 2102 : spdk_trace_register_object(OBJECT_SOCK_REQ, 's');
1024 : 2102 : spdk_trace_register_description_ext(opts, SPDK_COUNTOF(opts));
1025 : 2102 : }
|