]> git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/lib/sock/sock.c
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / spdk / lib / sock / sock.c
1 /*-
2 * BSD LICENSE
3 *
4 * Copyright (c) Intel Corporation.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * * Neither the name of Intel Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include "spdk/stdinc.h"
35
36 #include "spdk/log.h"
37 #include "spdk/sock.h"
38 #include "spdk_internal/sock.h"
39 #include "spdk/queue.h"
40
41 static STAILQ_HEAD(, spdk_net_impl) g_net_impls = STAILQ_HEAD_INITIALIZER(g_net_impls);
42
43 int
44 spdk_sock_getaddr(struct spdk_sock *sock, char *saddr, int slen, uint16_t *sport,
45 char *caddr, int clen, uint16_t *cport)
46 {
47 return sock->net_impl->getaddr(sock, saddr, slen, sport, caddr, clen, cport);
48 }
49
50 struct spdk_sock *
51 spdk_sock_connect(const char *ip, int port)
52 {
53 struct spdk_net_impl *impl = NULL;
54 struct spdk_sock *sock;
55
56 STAILQ_FOREACH_FROM(impl, &g_net_impls, link) {
57 sock = impl->connect(ip, port);
58 if (sock != NULL) {
59 sock->net_impl = impl;
60 return sock;
61 }
62 }
63
64 return NULL;
65 }
66
67 struct spdk_sock *
68 spdk_sock_listen(const char *ip, int port)
69 {
70 struct spdk_net_impl *impl = NULL;
71 struct spdk_sock *sock;
72
73 STAILQ_FOREACH_FROM(impl, &g_net_impls, link) {
74 sock = impl->listen(ip, port);
75 if (sock != NULL) {
76 sock->net_impl = impl;
77 return sock;
78 }
79 }
80
81 return NULL;
82 }
83
84 struct spdk_sock *
85 spdk_sock_accept(struct spdk_sock *sock)
86 {
87 struct spdk_sock *new_sock;
88
89 new_sock = sock->net_impl->accept(sock);
90 if (new_sock != NULL) {
91 new_sock->net_impl = sock->net_impl;
92 }
93
94 return new_sock;
95 }
96
97 int
98 spdk_sock_close(struct spdk_sock **sock)
99 {
100 int rc;
101
102 if (*sock == NULL) {
103 errno = EBADF;
104 return -1;
105 }
106
107 if ((*sock)->cb_fn != NULL) {
108 /* This sock is still part of a sock_group. */
109 errno = EBUSY;
110 return -1;
111 }
112
113 rc = (*sock)->net_impl->close(*sock);
114 if (rc == 0) {
115 *sock = NULL;
116 }
117
118 return rc;
119 }
120
121 ssize_t
122 spdk_sock_recv(struct spdk_sock *sock, void *buf, size_t len)
123 {
124 if (sock == NULL) {
125 errno = EBADF;
126 return -1;
127 }
128
129 return sock->net_impl->recv(sock, buf, len);
130 }
131
132 ssize_t
133 spdk_sock_writev(struct spdk_sock *sock, struct iovec *iov, int iovcnt)
134 {
135 if (sock == NULL) {
136 errno = EBADF;
137 return -1;
138 }
139
140 return sock->net_impl->writev(sock, iov, iovcnt);
141 }
142
143
144 int
145 spdk_sock_set_recvlowat(struct spdk_sock *sock, int nbytes)
146 {
147 return sock->net_impl->set_recvlowat(sock, nbytes);
148 }
149
150 int
151 spdk_sock_set_recvbuf(struct spdk_sock *sock, int sz)
152 {
153 return sock->net_impl->set_recvbuf(sock, sz);
154 }
155
156 int
157 spdk_sock_set_sendbuf(struct spdk_sock *sock, int sz)
158 {
159 return sock->net_impl->set_sendbuf(sock, sz);
160 }
161
162 bool
163 spdk_sock_is_ipv6(struct spdk_sock *sock)
164 {
165 return sock->net_impl->is_ipv6(sock);
166 }
167
168 bool
169 spdk_sock_is_ipv4(struct spdk_sock *sock)
170 {
171 return sock->net_impl->is_ipv4(sock);
172 }
173
174 struct spdk_sock_group *
175 spdk_sock_group_create(void)
176 {
177 struct spdk_net_impl *impl = NULL;
178 struct spdk_sock_group *group;
179 struct spdk_sock_group_impl *group_impl;
180
181 group = calloc(1, sizeof(*group));
182 if (group == NULL) {
183 return NULL;
184 }
185
186 STAILQ_INIT(&group->group_impls);
187
188 STAILQ_FOREACH_FROM(impl, &g_net_impls, link) {
189 group_impl = impl->group_impl_create();
190 if (group_impl != NULL) {
191 STAILQ_INSERT_TAIL(&group->group_impls, group_impl, link);
192 TAILQ_INIT(&group_impl->socks);
193 group_impl->net_impl = impl;
194 }
195 }
196
197 return group;
198 }
199
200 int
201 spdk_sock_group_add_sock(struct spdk_sock_group *group, struct spdk_sock *sock,
202 spdk_sock_cb cb_fn, void *cb_arg)
203 {
204 struct spdk_sock_group_impl *group_impl = NULL;
205 int rc;
206
207 if (cb_fn == NULL) {
208 errno = EINVAL;
209 return -1;
210 }
211
212 if (sock->cb_fn != NULL) {
213 /*
214 * This sock is already part of a sock_group. Currently we don't
215 * support this.
216 */
217 errno = EBUSY;
218 return -1;
219 }
220
221 STAILQ_FOREACH_FROM(group_impl, &group->group_impls, link) {
222 if (sock->net_impl == group_impl->net_impl) {
223 break;
224 }
225 }
226
227 if (group_impl == NULL) {
228 errno = EINVAL;
229 return -1;
230 }
231
232 rc = group_impl->net_impl->group_impl_add_sock(group_impl, sock);
233 if (rc == 0) {
234 TAILQ_INSERT_TAIL(&group_impl->socks, sock, link);
235 sock->cb_fn = cb_fn;
236 sock->cb_arg = cb_arg;
237 }
238
239 return rc;
240 }
241
242 int
243 spdk_sock_group_remove_sock(struct spdk_sock_group *group, struct spdk_sock *sock)
244 {
245 struct spdk_sock_group_impl *group_impl = NULL;
246 int rc;
247
248 STAILQ_FOREACH_FROM(group_impl, &group->group_impls, link) {
249 if (sock->net_impl == group_impl->net_impl) {
250 break;
251 }
252 }
253
254 if (group_impl == NULL) {
255 errno = EINVAL;
256 return -1;
257 }
258
259 rc = group_impl->net_impl->group_impl_remove_sock(group_impl, sock);
260 if (rc == 0) {
261 TAILQ_REMOVE(&group_impl->socks, sock, link);
262 sock->cb_fn = NULL;
263 sock->cb_arg = NULL;
264 }
265
266 return rc;
267 }
268
269 int
270 spdk_sock_group_poll(struct spdk_sock_group *group)
271 {
272 return spdk_sock_group_poll_count(group, MAX_EVENTS_PER_POLL);
273 }
274
275 static int
276 spdk_sock_group_impl_poll_count(struct spdk_sock_group_impl *group_impl,
277 struct spdk_sock_group *group,
278 int max_events)
279 {
280 struct spdk_sock *socks[MAX_EVENTS_PER_POLL];
281 int num_events, i;
282
283 if (TAILQ_EMPTY(&group_impl->socks)) {
284 return 0;
285 }
286
287 num_events = group_impl->net_impl->group_impl_poll(group_impl, max_events, socks);
288 if (num_events == -1) {
289 return -1;
290 }
291
292 for (i = 0; i < num_events; i++) {
293 struct spdk_sock *sock = socks[i];
294
295 assert(sock->cb_fn != NULL);
296 sock->cb_fn(sock->cb_arg, group, sock);
297 }
298 return 0;
299 }
300
301 int
302 spdk_sock_group_poll_count(struct spdk_sock_group *group, int max_events)
303 {
304 struct spdk_sock_group_impl *group_impl = NULL;
305 int rc, final_rc = 0;
306
307 if (max_events < 1) {
308 errno = -EINVAL;
309 return -1;
310 }
311
312 /*
313 * Only poll for up to 32 events at a time - if more events are pending,
314 * the next call to this function will reap them.
315 */
316 if (max_events > MAX_EVENTS_PER_POLL) {
317 max_events = MAX_EVENTS_PER_POLL;
318 }
319
320 STAILQ_FOREACH_FROM(group_impl, &group->group_impls, link) {
321 rc = spdk_sock_group_impl_poll_count(group_impl, group, max_events);
322 if (rc != 0) {
323 final_rc = rc;
324 SPDK_ERRLOG("group_impl_poll_count for net(%s) failed\n",
325 group_impl->net_impl->name);
326 }
327 }
328
329 return final_rc;
330 }
331
332 int
333 spdk_sock_group_close(struct spdk_sock_group **group)
334 {
335 struct spdk_sock_group_impl *group_impl = NULL, *tmp;
336 int rc;
337
338 if (*group == NULL) {
339 errno = EBADF;
340 return -1;
341 }
342
343 STAILQ_FOREACH_SAFE(group_impl, &(*group)->group_impls, link, tmp) {
344 if (!TAILQ_EMPTY(&group_impl->socks)) {
345 errno = EBUSY;
346 return -1;
347 }
348 }
349
350 STAILQ_FOREACH_SAFE(group_impl, &(*group)->group_impls, link, tmp) {
351 rc = group_impl->net_impl->group_impl_close(group_impl);
352 if (rc != 0) {
353 SPDK_ERRLOG("group_impl_close for net(%s) failed\n",
354 group_impl->net_impl->name);
355 }
356 free(group_impl);
357 }
358
359 free(*group);
360 *group = NULL;
361
362 return 0;
363 }
364
365 void
366 spdk_net_impl_register(struct spdk_net_impl *impl)
367 {
368 if (!strcmp("posix", impl->name)) {
369 STAILQ_INSERT_TAIL(&g_net_impls, impl, link);
370 } else {
371 STAILQ_INSERT_HEAD(&g_net_impls, impl, link);
372 }
373 }