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