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