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