xref: /spdk/lib/sock/sock.c (revision 1fc4165fe9bf8512483356ad8e6d27f793f2e3db)
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 }
384