xref: /spdk/lib/sock/sock.c (revision 8a0a98d35e21f282088edf28b9e8da66ec390e3a)
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, char *caddr, int clen)
45 {
46 	return sock->net_impl->getaddr(sock, saddr, slen, caddr, clen);
47 }
48 
49 struct spdk_sock *
50 spdk_sock_connect(const char *ip, int port)
51 {
52 	struct spdk_net_impl *impl = NULL;
53 	struct spdk_sock *sock;
54 
55 	STAILQ_FOREACH_FROM(impl, &g_net_impls, link) {
56 		sock = impl->connect(ip, port);
57 		if (sock != NULL) {
58 			sock->net_impl = impl;
59 			return sock;
60 		}
61 	}
62 
63 	return NULL;
64 }
65 
66 struct spdk_sock *
67 spdk_sock_listen(const char *ip, int port)
68 {
69 	struct spdk_net_impl *impl = NULL;
70 	struct spdk_sock *sock;
71 
72 	STAILQ_FOREACH_FROM(impl, &g_net_impls, link) {
73 		sock = impl->listen(ip, port);
74 		if (sock != NULL) {
75 			sock->net_impl = impl;
76 			return sock;
77 		}
78 	}
79 
80 	return NULL;
81 }
82 
83 struct spdk_sock *
84 spdk_sock_accept(struct spdk_sock *sock)
85 {
86 	struct spdk_sock *new_sock;
87 
88 	new_sock = sock->net_impl->accept(sock);
89 	if (new_sock != NULL) {
90 		new_sock->net_impl = sock->net_impl;
91 	}
92 
93 	return new_sock;
94 }
95 
96 int
97 spdk_sock_close(struct spdk_sock **sock)
98 {
99 	int rc;
100 
101 	if (*sock == NULL) {
102 		errno = EBADF;
103 		return -1;
104 	}
105 
106 	if ((*sock)->cb_fn != NULL) {
107 		/* This sock is still part of a sock_group. */
108 		errno = EBUSY;
109 		return -1;
110 	}
111 
112 	rc = (*sock)->net_impl->close(*sock);
113 	if (rc == 0) {
114 		free(*sock);
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 }
374