]> git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/lib/sock/sock.c
import 15.2.0 Octopus source
[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_readv(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->readv(sock, iov, iovcnt);
141 }
142
143 ssize_t
144 spdk_sock_writev(struct spdk_sock *sock, struct iovec *iov, int iovcnt)
145 {
146 if (sock == NULL) {
147 errno = EBADF;
148 return -1;
149 }
150
151 return sock->net_impl->writev(sock, iov, iovcnt);
152 }
153
154 int
155 spdk_sock_set_recvlowat(struct spdk_sock *sock, int nbytes)
156 {
157 return sock->net_impl->set_recvlowat(sock, nbytes);
158 }
159
160 int
161 spdk_sock_set_recvbuf(struct spdk_sock *sock, int sz)
162 {
163 return sock->net_impl->set_recvbuf(sock, sz);
164 }
165
166 int
167 spdk_sock_set_sendbuf(struct spdk_sock *sock, int sz)
168 {
169 return sock->net_impl->set_sendbuf(sock, sz);
170 }
171
172 bool
173 spdk_sock_is_ipv6(struct spdk_sock *sock)
174 {
175 return sock->net_impl->is_ipv6(sock);
176 }
177
178 bool
179 spdk_sock_is_ipv4(struct spdk_sock *sock)
180 {
181 return sock->net_impl->is_ipv4(sock);
182 }
183
184 struct spdk_sock_group *
185 spdk_sock_group_create(void)
186 {
187 struct spdk_net_impl *impl = NULL;
188 struct spdk_sock_group *group;
189 struct spdk_sock_group_impl *group_impl;
190
191 group = calloc(1, sizeof(*group));
192 if (group == NULL) {
193 return NULL;
194 }
195
196 STAILQ_INIT(&group->group_impls);
197
198 STAILQ_FOREACH_FROM(impl, &g_net_impls, link) {
199 group_impl = impl->group_impl_create();
200 if (group_impl != NULL) {
201 STAILQ_INSERT_TAIL(&group->group_impls, group_impl, link);
202 TAILQ_INIT(&group_impl->socks);
203 group_impl->net_impl = impl;
204 }
205 }
206
207 return group;
208 }
209
210 int
211 spdk_sock_group_add_sock(struct spdk_sock_group *group, struct spdk_sock *sock,
212 spdk_sock_cb cb_fn, void *cb_arg)
213 {
214 struct spdk_sock_group_impl *group_impl = NULL;
215 int rc;
216
217 if (cb_fn == NULL) {
218 errno = EINVAL;
219 return -1;
220 }
221
222 if (sock->cb_fn != NULL) {
223 /*
224 * This sock is already part of a sock_group. Currently we don't
225 * support this.
226 */
227 errno = EBUSY;
228 return -1;
229 }
230
231 STAILQ_FOREACH_FROM(group_impl, &group->group_impls, link) {
232 if (sock->net_impl == group_impl->net_impl) {
233 break;
234 }
235 }
236
237 if (group_impl == NULL) {
238 errno = EINVAL;
239 return -1;
240 }
241
242 rc = group_impl->net_impl->group_impl_add_sock(group_impl, sock);
243 if (rc == 0) {
244 TAILQ_INSERT_TAIL(&group_impl->socks, sock, link);
245 sock->cb_fn = cb_fn;
246 sock->cb_arg = cb_arg;
247 }
248
249 return rc;
250 }
251
252 int
253 spdk_sock_group_remove_sock(struct spdk_sock_group *group, struct spdk_sock *sock)
254 {
255 struct spdk_sock_group_impl *group_impl = NULL;
256 int rc;
257
258 STAILQ_FOREACH_FROM(group_impl, &group->group_impls, link) {
259 if (sock->net_impl == group_impl->net_impl) {
260 break;
261 }
262 }
263
264 if (group_impl == NULL) {
265 errno = EINVAL;
266 return -1;
267 }
268
269 rc = group_impl->net_impl->group_impl_remove_sock(group_impl, sock);
270 if (rc == 0) {
271 TAILQ_REMOVE(&group_impl->socks, sock, link);
272 sock->cb_fn = NULL;
273 sock->cb_arg = NULL;
274 }
275
276 return rc;
277 }
278
279 int
280 spdk_sock_group_poll(struct spdk_sock_group *group)
281 {
282 return spdk_sock_group_poll_count(group, MAX_EVENTS_PER_POLL);
283 }
284
285 static int
286 spdk_sock_group_impl_poll_count(struct spdk_sock_group_impl *group_impl,
287 struct spdk_sock_group *group,
288 int max_events)
289 {
290 struct spdk_sock *socks[MAX_EVENTS_PER_POLL];
291 int num_events, i;
292
293 if (TAILQ_EMPTY(&group_impl->socks)) {
294 return 0;
295 }
296
297 num_events = group_impl->net_impl->group_impl_poll(group_impl, max_events, socks);
298 if (num_events == -1) {
299 return -1;
300 }
301
302 for (i = 0; i < num_events; i++) {
303 struct spdk_sock *sock = socks[i];
304
305 assert(sock->cb_fn != NULL);
306 sock->cb_fn(sock->cb_arg, group, sock);
307 }
308 return 0;
309 }
310
311 int
312 spdk_sock_group_poll_count(struct spdk_sock_group *group, int max_events)
313 {
314 struct spdk_sock_group_impl *group_impl = NULL;
315 int rc, final_rc = 0;
316
317 if (max_events < 1) {
318 errno = -EINVAL;
319 return -1;
320 }
321
322 /*
323 * Only poll for up to 32 events at a time - if more events are pending,
324 * the next call to this function will reap them.
325 */
326 if (max_events > MAX_EVENTS_PER_POLL) {
327 max_events = MAX_EVENTS_PER_POLL;
328 }
329
330 STAILQ_FOREACH_FROM(group_impl, &group->group_impls, link) {
331 rc = spdk_sock_group_impl_poll_count(group_impl, group, max_events);
332 if (rc != 0) {
333 final_rc = rc;
334 SPDK_ERRLOG("group_impl_poll_count for net(%s) failed\n",
335 group_impl->net_impl->name);
336 }
337 }
338
339 return final_rc;
340 }
341
342 int
343 spdk_sock_group_close(struct spdk_sock_group **group)
344 {
345 struct spdk_sock_group_impl *group_impl = NULL, *tmp;
346 int rc;
347
348 if (*group == NULL) {
349 errno = EBADF;
350 return -1;
351 }
352
353 STAILQ_FOREACH_SAFE(group_impl, &(*group)->group_impls, link, tmp) {
354 if (!TAILQ_EMPTY(&group_impl->socks)) {
355 errno = EBUSY;
356 return -1;
357 }
358 }
359
360 STAILQ_FOREACH_SAFE(group_impl, &(*group)->group_impls, link, tmp) {
361 rc = group_impl->net_impl->group_impl_close(group_impl);
362 if (rc != 0) {
363 SPDK_ERRLOG("group_impl_close for net(%s) failed\n",
364 group_impl->net_impl->name);
365 }
366 free(group_impl);
367 }
368
369 free(*group);
370 *group = NULL;
371
372 return 0;
373 }
374
375 void
376 spdk_net_impl_register(struct spdk_net_impl *impl)
377 {
378 if (!strcmp("posix", impl->name)) {
379 STAILQ_INSERT_TAIL(&g_net_impls, impl, link);
380 } else {
381 STAILQ_INSERT_HEAD(&g_net_impls, impl, link);
382 }
383 }