xref: /spdk/test/unit/lib/sock/sock.c/sock_ut.c (revision c10f8e160e42a2a642e8a593b60c2f84561d5eba)
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 #include "spdk/util.h"
36 
37 #include "spdk_cunit.h"
38 
39 #include "sock/sock.c"
40 #include "sock/posix/posix.c"
41 
42 #define UT_IP	"test_ip"
43 #define UT_PORT	1234
44 
45 bool g_read_data_called;
46 ssize_t g_bytes_read;
47 char g_buf[256];
48 struct spdk_sock *g_server_sock_read;
49 int g_ut_accept_count;
50 struct spdk_ut_sock *g_ut_listen_sock;
51 struct spdk_ut_sock *g_ut_client_sock;
52 
53 struct spdk_ut_sock {
54 	struct spdk_sock	base;
55 	struct spdk_ut_sock	*peer;
56 	size_t			bytes_avail;
57 	char			buf[256];
58 };
59 
60 struct spdk_ut_sock_group_impl {
61 	struct spdk_sock_group_impl	base;
62 	struct spdk_ut_sock		*sock;
63 };
64 
65 #define __ut_sock(sock) (struct spdk_ut_sock *)sock
66 #define __ut_group(group) (struct spdk_ut_sock_group_impl *)group
67 
68 static int
69 spdk_ut_sock_getaddr(struct spdk_sock *_sock, char *saddr, int slen, uint16_t *sport,
70 		     char *caddr, int clen, uint16_t *cport)
71 {
72 	return 0;
73 }
74 
75 static struct spdk_sock *
76 spdk_ut_sock_listen(const char *ip, int port)
77 {
78 	struct spdk_ut_sock *sock;
79 
80 	if (strcmp(ip, UT_IP) || port != UT_PORT) {
81 		return NULL;
82 	}
83 
84 	CU_ASSERT(g_ut_listen_sock == NULL);
85 
86 	sock = calloc(1, sizeof(*sock));
87 	SPDK_CU_ASSERT_FATAL(sock != NULL);
88 	g_ut_listen_sock = sock;
89 
90 	return &sock->base;
91 }
92 
93 static struct spdk_sock *
94 spdk_ut_sock_connect(const char *ip, int port)
95 {
96 	struct spdk_ut_sock *sock;
97 
98 	if (strcmp(ip, UT_IP) || port != UT_PORT) {
99 		return NULL;
100 	}
101 
102 	sock = calloc(1, sizeof(*sock));
103 	SPDK_CU_ASSERT_FATAL(sock != NULL);
104 	g_ut_accept_count++;
105 	CU_ASSERT(g_ut_client_sock == NULL);
106 	g_ut_client_sock = sock;
107 
108 	return &sock->base;
109 }
110 
111 static struct spdk_sock *
112 spdk_ut_sock_accept(struct spdk_sock *_sock)
113 {
114 	struct spdk_ut_sock *sock = __ut_sock(_sock);
115 	struct spdk_ut_sock *new_sock;
116 
117 	CU_ASSERT(sock == g_ut_listen_sock);
118 
119 	if (g_ut_accept_count == 0) {
120 		errno = EAGAIN;
121 		return NULL;
122 	}
123 
124 	g_ut_accept_count--;
125 	new_sock = calloc(1, sizeof(*sock));
126 	if (new_sock == NULL) {
127 		SPDK_ERRLOG("sock allocation failed\n");
128 		return NULL;
129 	}
130 
131 	SPDK_CU_ASSERT_FATAL(g_ut_client_sock != NULL);
132 	g_ut_client_sock->peer = new_sock;
133 
134 	return &new_sock->base;
135 }
136 
137 static int
138 spdk_ut_sock_close(struct spdk_sock *_sock)
139 {
140 	struct spdk_ut_sock *sock = __ut_sock(_sock);
141 
142 	if (sock == g_ut_listen_sock) {
143 		g_ut_listen_sock = NULL;
144 	}
145 	if (sock == g_ut_client_sock) {
146 		g_ut_client_sock = NULL;
147 	}
148 	free(_sock);
149 
150 	return 0;
151 }
152 
153 static ssize_t
154 spdk_ut_sock_recv(struct spdk_sock *_sock, void *buf, size_t len)
155 {
156 	struct spdk_ut_sock *sock = __ut_sock(_sock);
157 	char tmp[256];
158 
159 	len = spdk_min(len, sock->bytes_avail);
160 
161 	if (len == 0) {
162 		errno = EAGAIN;
163 		return -1;
164 	}
165 
166 	memcpy(buf, sock->buf, len);
167 	memcpy(tmp, &sock->buf[len], sock->bytes_avail - len);
168 	memcpy(sock->buf, tmp, sock->bytes_avail - len);
169 	sock->bytes_avail -= len;
170 
171 	return len;
172 }
173 
174 static ssize_t
175 spdk_ut_sock_writev(struct spdk_sock *_sock, struct iovec *iov, int iovcnt)
176 {
177 	struct spdk_ut_sock *sock = __ut_sock(_sock);
178 	struct spdk_ut_sock *peer;
179 
180 	SPDK_CU_ASSERT_FATAL(sock->peer != NULL);
181 	peer = sock->peer;
182 
183 	/* Test implementation only supports single iov for now. */
184 	CU_ASSERT(iovcnt == 1);
185 
186 	memcpy(&peer->buf[peer->bytes_avail], iov[0].iov_base, iov[0].iov_len);
187 	peer->bytes_avail += iov[0].iov_len;
188 
189 	return iov[0].iov_len;
190 }
191 
192 static int
193 spdk_ut_sock_set_recvlowat(struct spdk_sock *_sock, int nbytes)
194 {
195 	return 0;
196 }
197 
198 static int
199 spdk_ut_sock_set_recvbuf(struct spdk_sock *_sock, int sz)
200 {
201 	return 0;
202 }
203 
204 static int
205 spdk_ut_sock_set_sendbuf(struct spdk_sock *_sock, int sz)
206 {
207 	return 0;
208 }
209 
210 static bool
211 spdk_ut_sock_is_ipv6(struct spdk_sock *_sock)
212 {
213 	return false;
214 }
215 
216 static bool
217 spdk_ut_sock_is_ipv4(struct spdk_sock *_sock)
218 {
219 	return true;
220 }
221 
222 static struct spdk_sock_group_impl *
223 spdk_ut_sock_group_impl_create(void)
224 {
225 	struct spdk_ut_sock_group_impl *group_impl;
226 
227 	group_impl = calloc(1, sizeof(*group_impl));
228 	SPDK_CU_ASSERT_FATAL(group_impl != NULL);
229 
230 	return &group_impl->base;
231 }
232 
233 static int
234 spdk_ut_sock_group_impl_add_sock(struct spdk_sock_group_impl *_group, struct spdk_sock *_sock)
235 {
236 	struct spdk_ut_sock_group_impl *group = __ut_group(_group);
237 	struct spdk_ut_sock *sock = __ut_sock(_sock);
238 
239 	group->sock = sock;
240 
241 	return 0;
242 }
243 
244 static int
245 spdk_ut_sock_group_impl_remove_sock(struct spdk_sock_group_impl *_group, struct spdk_sock *_sock)
246 {
247 	struct spdk_ut_sock_group_impl *group = __ut_group(_group);
248 	struct spdk_ut_sock *sock = __ut_sock(_sock);
249 
250 	CU_ASSERT(group->sock == sock);
251 	group->sock = NULL;
252 
253 	return 0;
254 }
255 
256 static int
257 spdk_ut_sock_group_impl_poll(struct spdk_sock_group_impl *_group, int max_events,
258 			     struct spdk_sock **socks)
259 {
260 	struct spdk_ut_sock_group_impl *group = __ut_group(_group);
261 
262 	if (group->sock != NULL && group->sock->bytes_avail > 0) {
263 		socks[0] = &group->sock->base;
264 		return 1;
265 	}
266 
267 	return 0;
268 }
269 
270 static int
271 spdk_ut_sock_group_impl_close(struct spdk_sock_group_impl *_group)
272 {
273 	struct spdk_ut_sock_group_impl *group = __ut_group(_group);
274 
275 	CU_ASSERT(group->sock == NULL);
276 
277 	return 0;
278 }
279 
280 static struct spdk_net_impl g_ut_net_impl = {
281 	.name		= "ut",
282 	.getaddr	= spdk_ut_sock_getaddr,
283 	.connect	= spdk_ut_sock_connect,
284 	.listen		= spdk_ut_sock_listen,
285 	.accept		= spdk_ut_sock_accept,
286 	.close		= spdk_ut_sock_close,
287 	.recv		= spdk_ut_sock_recv,
288 	.writev		= spdk_ut_sock_writev,
289 	.set_recvlowat	= spdk_ut_sock_set_recvlowat,
290 	.set_recvbuf	= spdk_ut_sock_set_recvbuf,
291 	.set_sendbuf	= spdk_ut_sock_set_sendbuf,
292 	.is_ipv6	= spdk_ut_sock_is_ipv6,
293 	.is_ipv4	= spdk_ut_sock_is_ipv4,
294 	.group_impl_create	= spdk_ut_sock_group_impl_create,
295 	.group_impl_add_sock	= spdk_ut_sock_group_impl_add_sock,
296 	.group_impl_remove_sock = spdk_ut_sock_group_impl_remove_sock,
297 	.group_impl_poll	= spdk_ut_sock_group_impl_poll,
298 	.group_impl_close	= spdk_ut_sock_group_impl_close,
299 };
300 
301 SPDK_NET_IMPL_REGISTER(ut, &g_ut_net_impl);
302 
303 static void
304 _sock(const char *ip, int port)
305 {
306 	struct spdk_sock *listen_sock;
307 	struct spdk_sock *server_sock;
308 	struct spdk_sock *client_sock;
309 	char *test_string = "abcdef";
310 	char buffer[64];
311 	ssize_t bytes_read, bytes_written;
312 	struct iovec iov;
313 	int rc;
314 
315 	listen_sock = spdk_sock_listen(ip, port);
316 	SPDK_CU_ASSERT_FATAL(listen_sock != NULL);
317 
318 	server_sock = spdk_sock_accept(listen_sock);
319 	CU_ASSERT(server_sock == NULL);
320 	CU_ASSERT(errno == EAGAIN || errno == EWOULDBLOCK);
321 
322 	client_sock = spdk_sock_connect(ip, port);
323 	SPDK_CU_ASSERT_FATAL(client_sock != NULL);
324 
325 	/*
326 	 * Delay a bit here before checking if server socket is
327 	 *  ready.
328 	 */
329 	usleep(1000);
330 
331 	server_sock = spdk_sock_accept(listen_sock);
332 	SPDK_CU_ASSERT_FATAL(server_sock != NULL);
333 
334 	iov.iov_base = test_string;
335 	iov.iov_len = 7;
336 	bytes_written = spdk_sock_writev(client_sock, &iov, 1);
337 	CU_ASSERT(bytes_written == 7);
338 
339 	usleep(1000);
340 
341 	bytes_read = spdk_sock_recv(server_sock, buffer, 2);
342 	CU_ASSERT(bytes_read == 2);
343 
344 	usleep(1000);
345 
346 	bytes_read += spdk_sock_recv(server_sock, buffer + 2, 5);
347 	CU_ASSERT(bytes_read == 7);
348 
349 	CU_ASSERT(strncmp(test_string, buffer, 7) == 0);
350 
351 	rc = spdk_sock_close(&client_sock);
352 	CU_ASSERT(client_sock == NULL);
353 	CU_ASSERT(rc == 0);
354 
355 	rc = spdk_sock_close(&server_sock);
356 	CU_ASSERT(server_sock == NULL);
357 	CU_ASSERT(rc == 0);
358 
359 	rc = spdk_sock_close(&listen_sock);
360 	CU_ASSERT(listen_sock == NULL);
361 	CU_ASSERT(rc == 0);
362 }
363 
364 static void
365 posix_sock(void)
366 {
367 	_sock("127.0.0.1", 3260);
368 }
369 
370 static void
371 ut_sock(void)
372 {
373 	_sock(UT_IP, UT_PORT);
374 }
375 
376 static void
377 read_data(void *cb_arg, struct spdk_sock_group *group, struct spdk_sock *sock)
378 {
379 	struct spdk_sock *server_sock = cb_arg;
380 
381 	CU_ASSERT(server_sock == sock);
382 
383 	g_read_data_called = true;
384 	g_bytes_read += spdk_sock_recv(server_sock, g_buf + g_bytes_read, sizeof(g_buf) - g_bytes_read);
385 }
386 
387 static void
388 _sock_group(const char *ip, int port)
389 {
390 	struct spdk_sock_group *group;
391 	struct spdk_sock *listen_sock;
392 	struct spdk_sock *server_sock;
393 	struct spdk_sock *client_sock;
394 	char *test_string = "abcdef";
395 	ssize_t bytes_written;
396 	struct iovec iov;
397 	int rc;
398 
399 	listen_sock = spdk_sock_listen(ip, port);
400 	SPDK_CU_ASSERT_FATAL(listen_sock != NULL);
401 
402 	server_sock = spdk_sock_accept(listen_sock);
403 	CU_ASSERT(server_sock == NULL);
404 	CU_ASSERT(errno == EAGAIN || errno == EWOULDBLOCK);
405 
406 	client_sock = spdk_sock_connect(ip, port);
407 	SPDK_CU_ASSERT_FATAL(client_sock != NULL);
408 
409 	usleep(1000);
410 
411 	server_sock = spdk_sock_accept(listen_sock);
412 	SPDK_CU_ASSERT_FATAL(server_sock != NULL);
413 
414 	group = spdk_sock_group_create();
415 	SPDK_CU_ASSERT_FATAL(group != NULL);
416 
417 	/* pass null cb_fn */
418 	rc = spdk_sock_group_add_sock(group, server_sock, NULL, NULL);
419 	CU_ASSERT(rc == -1);
420 	CU_ASSERT(errno == EINVAL);
421 
422 	rc = spdk_sock_group_add_sock(group, server_sock, read_data, server_sock);
423 	CU_ASSERT(rc == 0);
424 
425 	/* try adding sock a second time */
426 	rc = spdk_sock_group_add_sock(group, server_sock, read_data, server_sock);
427 	CU_ASSERT(rc == -1);
428 	CU_ASSERT(errno == EBUSY);
429 
430 	g_read_data_called = false;
431 	g_bytes_read = 0;
432 	rc = spdk_sock_group_poll(group);
433 
434 	CU_ASSERT(rc == 0);
435 	CU_ASSERT(g_read_data_called == false);
436 
437 	iov.iov_base = test_string;
438 	iov.iov_len = 7;
439 	bytes_written = spdk_sock_writev(client_sock, &iov, 1);
440 	CU_ASSERT(bytes_written == 7);
441 
442 	usleep(1000);
443 
444 	g_read_data_called = false;
445 	g_bytes_read = 0;
446 	rc = spdk_sock_group_poll(group);
447 
448 	CU_ASSERT(rc == 0);
449 	CU_ASSERT(g_read_data_called == true);
450 	CU_ASSERT(g_bytes_read == 7);
451 
452 	CU_ASSERT(strncmp(test_string, g_buf, 7) == 0);
453 
454 	rc = spdk_sock_close(&client_sock);
455 	CU_ASSERT(client_sock == NULL);
456 	CU_ASSERT(rc == 0);
457 
458 	/* Try to close sock_group while it still has sockets. */
459 	rc = spdk_sock_group_close(&group);
460 	CU_ASSERT(rc == -1);
461 	CU_ASSERT(errno == EBUSY);
462 
463 	/* Try to close sock while it is still part of a sock_group. */
464 	rc = spdk_sock_close(&server_sock);
465 	CU_ASSERT(rc == -1);
466 	CU_ASSERT(errno == EBUSY);
467 
468 	rc = spdk_sock_group_remove_sock(group, server_sock);
469 	CU_ASSERT(rc == 0);
470 
471 	rc = spdk_sock_group_close(&group);
472 	CU_ASSERT(group == NULL);
473 	CU_ASSERT(rc == 0);
474 
475 	rc = spdk_sock_close(&server_sock);
476 	CU_ASSERT(server_sock == NULL);
477 	CU_ASSERT(rc == 0);
478 
479 	rc = spdk_sock_close(&listen_sock);
480 	CU_ASSERT(listen_sock == NULL);
481 	CU_ASSERT(rc == 0);
482 }
483 
484 static void
485 posix_sock_group(void)
486 {
487 	_sock_group("127.0.0.1", 3260);
488 }
489 
490 static void
491 ut_sock_group(void)
492 {
493 	_sock_group(UT_IP, UT_PORT);
494 }
495 
496 static void
497 read_data_fairness(void *cb_arg, struct spdk_sock_group *group, struct spdk_sock *sock)
498 {
499 	struct spdk_sock *server_sock = cb_arg;
500 	ssize_t bytes_read;
501 	char buf[1];
502 
503 	CU_ASSERT(g_server_sock_read == NULL);
504 	CU_ASSERT(server_sock == sock);
505 
506 	g_server_sock_read = server_sock;
507 	bytes_read = spdk_sock_recv(server_sock, buf, 1);
508 	CU_ASSERT(bytes_read == 1);
509 }
510 
511 static void
512 posix_sock_group_fairness(void)
513 {
514 	struct spdk_sock_group *group;
515 	struct spdk_sock *listen_sock;
516 	struct spdk_sock *server_sock[3];
517 	struct spdk_sock *client_sock[3];
518 	char test_char = 'a';
519 	ssize_t bytes_written;
520 	struct iovec iov;
521 	int i, rc;
522 
523 	listen_sock = spdk_sock_listen("127.0.0.1", 3260);
524 	SPDK_CU_ASSERT_FATAL(listen_sock != NULL);
525 
526 	group = spdk_sock_group_create();
527 	SPDK_CU_ASSERT_FATAL(group != NULL);
528 
529 	for (i = 0; i < 3; i++) {
530 		client_sock[i] = spdk_sock_connect("127.0.0.1", 3260);
531 		SPDK_CU_ASSERT_FATAL(client_sock[i] != NULL);
532 
533 		usleep(1000);
534 
535 		server_sock[i] = spdk_sock_accept(listen_sock);
536 		SPDK_CU_ASSERT_FATAL(server_sock[i] != NULL);
537 
538 		rc = spdk_sock_group_add_sock(group, server_sock[i],
539 					      read_data_fairness, server_sock[i]);
540 		CU_ASSERT(rc == 0);
541 	}
542 
543 	iov.iov_base = &test_char;
544 	iov.iov_len = 1;
545 
546 	for (i = 0; i < 3; i++) {
547 		bytes_written = spdk_sock_writev(client_sock[i], &iov, 1);
548 		CU_ASSERT(bytes_written == 1);
549 	}
550 
551 	usleep(1000);
552 
553 	/*
554 	 * Poll for just one event - this should be server sock 0, since that
555 	 *  is the peer of the first client sock that we wrote to.
556 	 */
557 	g_server_sock_read = NULL;
558 	rc = spdk_sock_group_poll_count(group, 1);
559 	CU_ASSERT(rc == 0);
560 	CU_ASSERT(g_server_sock_read == server_sock[0]);
561 
562 	/*
563 	 * Now write another byte to client sock 0.  We want to ensure that
564 	 *  the sock group does not unfairly process the event for this sock
565 	 *  before the socks that were written to earlier.
566 	 */
567 	bytes_written = spdk_sock_writev(client_sock[0], &iov, 1);
568 	CU_ASSERT(bytes_written == 1);
569 
570 	usleep(1000);
571 
572 	g_server_sock_read = NULL;
573 	rc = spdk_sock_group_poll_count(group, 1);
574 	CU_ASSERT(rc == 0);
575 	CU_ASSERT(g_server_sock_read == server_sock[1]);
576 
577 	g_server_sock_read = NULL;
578 	rc = spdk_sock_group_poll_count(group, 1);
579 	CU_ASSERT(rc == 0);
580 	CU_ASSERT(g_server_sock_read == server_sock[2]);
581 
582 	g_server_sock_read = NULL;
583 	rc = spdk_sock_group_poll_count(group, 1);
584 	CU_ASSERT(rc == 0);
585 	CU_ASSERT(g_server_sock_read == server_sock[0]);
586 
587 	for (i = 0; i < 3; i++) {
588 		rc = spdk_sock_group_remove_sock(group, server_sock[i]);
589 		CU_ASSERT(rc == 0);
590 
591 		rc = spdk_sock_close(&client_sock[i]);
592 		CU_ASSERT(client_sock[i] == NULL);
593 		CU_ASSERT(rc == 0);
594 
595 		rc = spdk_sock_close(&server_sock[i]);
596 		CU_ASSERT(server_sock[i] == NULL);
597 		CU_ASSERT(rc == 0);
598 	}
599 
600 	rc = spdk_sock_group_close(&group);
601 	CU_ASSERT(group == NULL);
602 	CU_ASSERT(rc == 0);
603 
604 	rc = spdk_sock_close(&listen_sock);
605 	CU_ASSERT(listen_sock == NULL);
606 	CU_ASSERT(rc == 0);
607 }
608 
609 int
610 main(int argc, char **argv)
611 {
612 	CU_pSuite	suite = NULL;
613 	unsigned int	num_failures;
614 
615 	if (CU_initialize_registry() != CUE_SUCCESS) {
616 		return CU_get_error();
617 	}
618 
619 	suite = CU_add_suite("sock", NULL, NULL);
620 	if (suite == NULL) {
621 		CU_cleanup_registry();
622 		return CU_get_error();
623 	}
624 
625 	if (
626 		CU_add_test(suite, "posix_sock", posix_sock) == NULL ||
627 		CU_add_test(suite, "ut_sock", ut_sock) == NULL ||
628 		CU_add_test(suite, "posix_sock_group", posix_sock_group) == NULL ||
629 		CU_add_test(suite, "ut_sock_group", ut_sock_group) == NULL ||
630 		CU_add_test(suite, "posix_sock_group_fairness", posix_sock_group_fairness) == NULL) {
631 		CU_cleanup_registry();
632 		return CU_get_error();
633 	}
634 
635 	CU_basic_set_mode(CU_BRM_VERBOSE);
636 
637 	CU_basic_run_tests();
638 
639 	num_failures = CU_get_number_of_failures();
640 	CU_cleanup_registry();
641 
642 	return num_failures;
643 }
644