• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <stdio.h>
18 #include <errno.h>
19 #include <stdbool.h>
20 #include <string.h>
21 #include <stdlib.h>
22 #include <unistd.h>
23 #include <getopt.h>
24 #define __USE_GNU
25 #include <sys/mman.h>
26 #include <sys/uio.h>
27 
28 #include <BufferAllocator/BufferAllocatorWrapper.h>
29 
30 #include <trusty/tipc.h>
31 
32 #define TIPC_DEFAULT_DEVNAME "/dev/trusty-ipc-dev0"
33 
34 static const char *dev_name = NULL;
35 static const char *test_name = NULL;
36 
37 static const char *uuid_name = "com.android.ipc-unittest.srv.uuid";
38 static const char *echo_name = "com.android.ipc-unittest.srv.echo";
39 static const char *ta_only_name = "com.android.ipc-unittest.srv.ta_only";
40 static const char *ns_only_name = "com.android.ipc-unittest.srv.ns_only";
41 static const char *datasink_name = "com.android.ipc-unittest.srv.datasink";
42 static const char *closer1_name = "com.android.ipc-unittest.srv.closer1";
43 static const char *closer2_name = "com.android.ipc-unittest.srv.closer2";
44 static const char *closer3_name = "com.android.ipc-unittest.srv.closer3";
45 static const char *main_ctrl_name = "com.android.ipc-unittest.ctrl";
46 static const char* receiver_name = "com.android.trusty.memref.receiver";
47 
48 static const char *_sopts = "hsvD:t:r:m:b:";
49 static const struct option _lopts[] =  {
50 	{"help",    no_argument,       0, 'h'},
51 	{"silent",  no_argument,       0, 's'},
52 	{"variable",no_argument,       0, 'v'},
53 	{"dev",     required_argument, 0, 'D'},
54 	{"repeat",  required_argument, 0, 'r'},
55 	{"burst",   required_argument, 0, 'b'},
56 	{"msgsize", required_argument, 0, 'm'},
57 	{0, 0, 0, 0}
58 };
59 
60 static const char *usage =
61 "Usage: %s [options]\n"
62 "\n"
63 "options:\n"
64 "  -h, --help            prints this message and exit\n"
65 "  -D, --dev name        device name\n"
66 "  -t, --test name       test to run\n"
67 "  -r, --repeat cnt      repeat count\n"
68 "  -m, --msgsize size    max message size\n"
69 "  -v, --variable        variable message size\n"
70 "  -s, --silent          silent\n"
71 "\n"
72 ;
73 
74 static const char* usage_long =
75         "\n"
76         "The following tests are available:\n"
77         "   connect      - connect to datasink service\n"
78         "   connect_foo  - connect to non existing service\n"
79         "   burst_write  - send messages to datasink service\n"
80         "   echo         - send/receive messages to echo service\n"
81         "   select       - test select call\n"
82         "   blocked_read - test blocked read\n"
83         "   closer1      - connection closed by remote (test1)\n"
84         "   closer2      - connection closed by remote (test2)\n"
85         "   closer3      - connection closed by remote (test3)\n"
86         "   ta2ta-ipc    - execute TA to TA unittest\n"
87         "   dev-uuid     - print device uuid\n"
88         "   ta-access    - test ta-access flags\n"
89         "   writev       - writev test\n"
90         "   readv        - readv test\n"
91         "   send-fd      - transmit dma_buf to trusty, use as shm\n"
92         "\n";
93 
94 static uint opt_repeat  = 1;
95 static uint opt_msgsize = 32;
96 static uint opt_msgburst = 32;
97 static bool opt_variable = false;
98 static bool opt_silent = false;
99 
print_usage_and_exit(const char * prog,int code,bool verbose)100 static void print_usage_and_exit(const char *prog, int code, bool verbose)
101 {
102 	fprintf (stderr, usage, prog);
103 	if (verbose)
104 		fprintf (stderr, "%s", usage_long);
105 	exit(code);
106 }
107 
parse_options(int argc,char ** argv)108 static void parse_options(int argc, char **argv)
109 {
110 	int c;
111 	int oidx = 0;
112 
113 	while (1)
114 	{
115 		c = getopt_long (argc, argv, _sopts, _lopts, &oidx);
116 		if (c == -1)
117 			break; /* done */
118 
119 		switch (c) {
120 
121 		case 'D':
122 			dev_name = strdup(optarg);
123 		break;
124 
125 		case 't':
126 			test_name = strdup(optarg);
127 		break;
128 
129 		case 'v':
130 			opt_variable = true;
131 		break;
132 
133 		case 'r':
134 			opt_repeat = atoi(optarg);
135 		break;
136 
137 		case 'm':
138 			opt_msgsize = atoi(optarg);
139 		break;
140 
141 		case 'b':
142 			opt_msgburst = atoi(optarg);
143 		break;
144 
145 		case 's':
146 			opt_silent = true;
147 		break;
148 
149 		case 'h':
150 		      print_usage_and_exit(argv[0], EXIT_SUCCESS, true);
151 		break;
152 
153 		default:
154 		      print_usage_and_exit(argv[0], EXIT_FAILURE, false);
155 		}
156 	}
157 }
158 
connect_test(uint repeat)159 static int connect_test(uint repeat)
160 {
161 	uint i;
162 	int  echo_fd;
163 	int  dsink_fd;
164 
165 	if (!opt_silent) {
166 		printf("%s: repeat = %u\n", __func__, repeat);
167 	}
168 
169 	for (i = 0; i < repeat; i++) {
170 		echo_fd = tipc_connect(dev_name, echo_name);
171 		if (echo_fd < 0) {
172 			fprintf(stderr, "Failed to connect to '%s' service\n",
173 				"echo");
174 		}
175 		dsink_fd = tipc_connect(dev_name, datasink_name);
176 		if (dsink_fd < 0) {
177 			fprintf(stderr, "Failed to connect to '%s' service\n",
178 				"datasink");
179 		}
180 
181 		if (echo_fd >= 0) {
182 			tipc_close(echo_fd);
183 		}
184 		if (dsink_fd >= 0) {
185 			tipc_close(dsink_fd);
186 		}
187 	}
188 
189 	if (!opt_silent) {
190 		printf("%s: done\n", __func__);
191 	}
192 
193 	return 0;
194 }
195 
connect_foo(uint repeat)196 static int connect_foo(uint repeat)
197 {
198 	uint i;
199 	int  fd;
200 
201 	if (!opt_silent) {
202 		printf("%s: repeat = %u\n", __func__, repeat);
203 	}
204 
205 	for (i = 0; i < repeat; i++) {
206 		fd = tipc_connect(dev_name, "foo");
207 		if (fd >= 0) {
208 			fprintf(stderr, "succeeded to connect to '%s' service\n",
209 				"foo");
210 			tipc_close(fd);
211 		}
212 	}
213 
214 	if (!opt_silent) {
215 		printf("%s: done\n", __func__);
216 	}
217 
218 	return 0;
219 }
220 
221 
closer1_test(uint repeat)222 static int closer1_test(uint repeat)
223 {
224 	uint i;
225 	int  fd;
226 
227 	if (!opt_silent) {
228 		printf("%s: repeat = %u\n", __func__, repeat);
229 	}
230 
231 	for (i = 0; i < repeat; i++) {
232 		fd = tipc_connect(dev_name, closer1_name);
233 		if (fd < 0) {
234 			fprintf(stderr, "Failed to connect to '%s' service\n",
235 				"closer1");
236 			continue;
237 		}
238 		if (!opt_silent) {
239 			printf("%s: connected\n", __func__);
240 		}
241 		tipc_close(fd);
242 	}
243 
244 	if (!opt_silent) {
245 		printf("%s: done\n", __func__);
246 	}
247 
248 	return 0;
249 }
250 
closer2_test(uint repeat)251 static int closer2_test(uint repeat)
252 {
253 	uint i;
254 	int  fd;
255 
256 	if (!opt_silent) {
257 		printf("%s: repeat = %u\n", __func__, repeat);
258 	}
259 
260 	for (i = 0; i < repeat; i++) {
261 		fd = tipc_connect(dev_name, closer2_name);
262 		if (fd < 0) {
263 			if (!opt_silent) {
264 				printf("failed to connect to '%s' service\n", "closer2");
265 			}
266 		} else {
267 			/* this should always fail */
268 			fprintf(stderr, "connected to '%s' service\n", "closer2");
269 			tipc_close(fd);
270 		}
271 	}
272 
273 	if (!opt_silent) {
274 		printf("%s: done\n", __func__);
275 	}
276 
277 	return 0;
278 }
279 
closer3_test(uint repeat)280 static int closer3_test(uint repeat)
281 {
282 	uint i, j;
283 	ssize_t rc;
284 	int  fd[4];
285 	char buf[64];
286 
287 	if (!opt_silent) {
288 		printf("%s: repeat = %u\n", __func__, repeat);
289 	}
290 
291 	for (i = 0; i < repeat; i++) {
292 
293 		/* open 4 connections to closer3 service */
294 		for (j = 0; j < 4; j++) {
295 			fd[j] = tipc_connect(dev_name, closer3_name);
296 			if (fd[j] < 0) {
297 				fprintf(stderr, "fd[%d]: failed to connect to '%s' service\n", j, "closer3");
298 			} else {
299 				if (!opt_silent) {
300 					printf("%s: fd[%d]=%d: connected\n", __func__, j, fd[j]);
301 				}
302 				memset(buf, i + j, sizeof(buf));
303 				rc = write(fd[j], buf, sizeof(buf));
304 				if (rc != sizeof(buf)) {
305 					if (!opt_silent) {
306 						printf("%s: fd[%d]=%d: write returned  = %zd\n",
307 							__func__, j, fd[j], rc);
308 					}
309 					perror("closer3_test: write");
310 				}
311 			}
312 		}
313 
314 		/* sleep a bit */
315 		sleep(1);
316 
317 		/* It is expected that they will be closed by remote */
318 		for (j = 0; j < 4; j++) {
319 			if (fd[j] < 0)
320 				continue;
321 			rc = write(fd[j], buf, sizeof(buf));
322 			if (rc != sizeof(buf)) {
323 				if (!opt_silent) {
324 					printf("%s: fd[%d]=%d: write returned = %zd\n",
325 						__func__, j, fd[j], rc);
326 				}
327 				perror("closer3_test: write");
328 			}
329 		}
330 
331 		/* then they have to be closed by remote */
332 		for (j = 0; j < 4; j++) {
333 			if (fd[j] >= 0) {
334 				tipc_close(fd[j]);
335 			}
336 		}
337 	}
338 
339 	if (!opt_silent) {
340 		printf("%s: done\n", __func__);
341 	}
342 
343 	return 0;
344 }
345 
346 
echo_test(uint repeat,uint msgsz,bool var)347 static int echo_test(uint repeat, uint msgsz, bool var)
348 {
349 	uint i;
350 	ssize_t rc;
351 	size_t  msg_len;
352 	int  echo_fd =-1;
353 	char tx_buf[msgsz];
354 	char rx_buf[msgsz];
355 
356 	if (!opt_silent) {
357 		printf("%s: repeat %u: msgsz %u: variable %s\n",
358 			__func__, repeat, msgsz, var ? "true" : "false");
359 	}
360 
361 	echo_fd = tipc_connect(dev_name, echo_name);
362 	if (echo_fd < 0) {
363 		fprintf(stderr, "Failed to connect to service\n");
364 		return echo_fd;
365 	}
366 
367 	for (i = 0; i < repeat; i++) {
368 
369 		msg_len = msgsz;
370 		if (opt_variable && msgsz) {
371 			msg_len = rand() % msgsz;
372 		}
373 
374 		memset(tx_buf, i + 1, msg_len);
375 
376 		rc = write(echo_fd, tx_buf, msg_len);
377 		if ((size_t)rc != msg_len) {
378 			perror("echo_test: write");
379 			break;
380 		}
381 
382 		rc = read(echo_fd, rx_buf, msg_len);
383 		if (rc < 0) {
384 			perror("echo_test: read");
385 			break;
386 		}
387 
388 		if ((size_t)rc != msg_len) {
389 			fprintf(stderr, "data truncated (%zu vs. %zu)\n",
390 			                 rc, msg_len);
391 			continue;
392 		}
393 
394 		if (memcmp(tx_buf, rx_buf, (size_t) rc)) {
395 			fprintf(stderr, "data mismatch\n");
396 			continue;
397 		}
398 	}
399 
400 	tipc_close(echo_fd);
401 
402 	if (!opt_silent) {
403 		printf("%s: done\n",__func__);
404 	}
405 
406 	return 0;
407 }
408 
burst_write_test(uint repeat,uint msgburst,uint msgsz,bool var)409 static int burst_write_test(uint repeat, uint msgburst, uint msgsz, bool var)
410 {
411 	int fd;
412 	uint i, j;
413 	ssize_t rc;
414 	size_t  msg_len;
415 	char tx_buf[msgsz];
416 
417 	if (!opt_silent) {
418 		printf("%s: repeat %u: burst %u: msgsz %u: variable %s\n",
419 			__func__, repeat, msgburst, msgsz,
420 			var ? "true" : "false");
421 	}
422 
423 	for (i = 0; i < repeat; i++) {
424 
425 		fd = tipc_connect(dev_name, datasink_name);
426 		if (fd < 0) {
427 			fprintf(stderr, "Failed to connect to '%s' service\n",
428 				"datasink");
429 			break;
430 		}
431 
432 		for (j = 0; j < msgburst; j++) {
433 			msg_len = msgsz;
434 			if (var && msgsz) {
435 				msg_len = rand() % msgsz;
436 			}
437 
438 			memset(tx_buf, i + 1, msg_len);
439 			rc = write(fd, tx_buf, msg_len);
440 			if ((size_t)rc != msg_len) {
441 				perror("burst_test: write");
442 				break;
443 			}
444 		}
445 
446 		tipc_close(fd);
447 	}
448 
449 	if (!opt_silent) {
450 		printf("%s: done\n",__func__);
451 	}
452 
453 	return 0;
454 }
455 
456 
_wait_for_msg(int fd,uint msgsz,int timeout)457 static int _wait_for_msg(int fd, uint msgsz, int timeout)
458 {
459 	int rc;
460 	fd_set rfds;
461 	uint msgcnt = 0;
462 	char rx_buf[msgsz];
463 	struct timeval tv;
464 
465 	if (!opt_silent) {
466 		printf("waiting (%d) for msg\n", timeout);
467 	}
468 
469 	FD_ZERO(&rfds);
470 	FD_SET(fd, &rfds);
471 
472 	tv.tv_sec = timeout;
473 	tv.tv_usec = 0;
474 
475 	for(;;) {
476 		rc = select(fd+1, &rfds, NULL, NULL, &tv);
477 
478 		if (rc == 0) {
479 			if (!opt_silent) {
480 				printf("select timedout\n");
481 			}
482 			break;
483 		}
484 
485 		if (rc == -1) {
486 			perror("select_test: select");
487 			return rc;
488 		}
489 
490 		rc = read(fd, rx_buf, sizeof(rx_buf));
491 		if (rc < 0) {
492 			perror("select_test: read");
493 			return rc;
494 		} else {
495 			if (rc > 0) {
496 				msgcnt++;
497 			}
498 		}
499 	}
500 
501 	if (!opt_silent) {
502 		printf("got %u messages\n", msgcnt);
503 	}
504 
505 	return 0;
506 }
507 
508 
select_test(uint repeat,uint msgburst,uint msgsz)509 static int select_test(uint repeat, uint msgburst, uint msgsz)
510 {
511 	int fd;
512 	uint i, j;
513 	ssize_t rc;
514 	char tx_buf[msgsz];
515 
516 	if (!opt_silent) {
517 		printf("%s: repeat %u\n", __func__, repeat);
518 	}
519 
520 	fd = tipc_connect(dev_name, echo_name);
521 	if (fd < 0) {
522 		fprintf(stderr, "Failed to connect to '%s' service\n",
523 			"echo");
524 		return fd;
525 	}
526 
527 	for (i = 0; i < repeat; i++) {
528 
529 		_wait_for_msg(fd, msgsz, 1);
530 
531 		if (!opt_silent) {
532 			printf("sending burst: %u msg\n", msgburst);
533 		}
534 
535 		for (j = 0; j < msgburst; j++) {
536 			memset(tx_buf, i + j, msgsz);
537 			rc = write(fd, tx_buf, msgsz);
538 			if ((size_t)rc != msgsz) {
539 				perror("burst_test: write");
540 				break;
541 			}
542 		}
543 	}
544 
545 	tipc_close(fd);
546 
547 	if (!opt_silent) {
548 		printf("%s: done\n",__func__);
549 	}
550 
551 	return 0;
552 }
553 
blocked_read_test(uint repeat)554 static int blocked_read_test(uint repeat)
555 {
556 	int fd;
557 	uint i;
558 	ssize_t rc;
559 	char rx_buf[512];
560 
561 	if (!opt_silent) {
562 		printf("%s: repeat %u\n", __func__, repeat);
563 	}
564 
565 	fd = tipc_connect(dev_name, echo_name);
566 	if (fd < 0) {
567 		fprintf(stderr, "Failed to connect to '%s' service\n",
568 			"echo");
569 		return fd;
570 	}
571 
572 	for (i = 0; i < repeat; i++) {
573 		rc = read(fd, rx_buf, sizeof(rx_buf));
574 		if (rc < 0) {
575 			perror("select_test: read");
576 			break;
577 		} else {
578 			if (!opt_silent) {
579 				printf("got %zd bytes\n", rc);
580 			}
581 		}
582 	}
583 
584 	tipc_close(fd);
585 
586 	if (!opt_silent) {
587 		printf("%s: done\n",__func__);
588 	}
589 
590 	return 0;
591 }
592 
ta2ta_ipc_test(void)593 static int ta2ta_ipc_test(void)
594 {
595 	enum test_message_header {
596 		TEST_PASSED = 0,
597 		TEST_FAILED = 1,
598 		TEST_MESSAGE = 2,
599 	};
600 
601 	int fd;
602 	int ret;
603 	unsigned char rx_buf[256];
604 
605 	if (!opt_silent) {
606 		printf("%s:\n", __func__);
607 	}
608 
609 	fd = tipc_connect(dev_name, main_ctrl_name);
610 	if (fd < 0) {
611 		fprintf(stderr, "Failed to connect to '%s' service\n",
612 			"main_ctrl");
613 		return fd;
614 	}
615 
616 	/* Wait for tests to complete and read status */
617 	while (true) {
618 		ret = read(fd, rx_buf, sizeof(rx_buf));
619 		if (ret <= 0 || ret >= (int)sizeof(rx_buf)) {
620 			fprintf(stderr, "%s: Read failed: %d\n", __func__, ret);
621 			tipc_close(fd);
622 			return -1;
623 		}
624 
625 		if (rx_buf[0] == TEST_PASSED) {
626 			break;
627 		} else if (rx_buf[0] == TEST_FAILED) {
628 			break;
629 		} else if (rx_buf[0] == TEST_MESSAGE) {
630 			write(STDOUT_FILENO, rx_buf + 1, ret - 1);
631 		} else {
632 			fprintf(stderr, "%s: Bad message header: %d\n",
633 			        __func__, rx_buf[0]);
634 			break;
635 		}
636 	}
637 
638 	tipc_close(fd);
639 
640 	return rx_buf[0] == TEST_PASSED ? 0 : -1;
641 }
642 
643 typedef struct uuid
644 {
645 	uint32_t time_low;
646 	uint16_t time_mid;
647 	uint16_t time_hi_and_version;
648 	uint8_t clock_seq_and_node[8];
649 } uuid_t;
650 
print_uuid(const char * dev,uuid_t * uuid)651 static void print_uuid(const char *dev, uuid_t *uuid)
652 {
653 	printf("%s:", dev);
654 	printf("uuid: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
655 	       uuid->time_low,
656 	       uuid->time_mid,
657 	       uuid->time_hi_and_version,
658 	       uuid->clock_seq_and_node[0],
659 	       uuid->clock_seq_and_node[1],
660 	       uuid->clock_seq_and_node[2],
661 	       uuid->clock_seq_and_node[3],
662 	       uuid->clock_seq_and_node[4],
663 	       uuid->clock_seq_and_node[5],
664 	       uuid->clock_seq_and_node[6],
665 	       uuid->clock_seq_and_node[7]
666 	       );
667 }
668 
dev_uuid_test(void)669 static int dev_uuid_test(void)
670 {
671 	int fd;
672 	ssize_t rc;
673 	uuid_t uuid;
674 
675 	fd = tipc_connect(dev_name, uuid_name);
676 	if (fd < 0) {
677 		fprintf(stderr, "Failed to connect to '%s' service\n",
678 			"uuid");
679 		return fd;
680 	}
681 
682 	/* wait for test to complete */
683 	rc = read(fd, &uuid, sizeof(uuid));
684 	if (rc < 0) {
685 		perror("dev_uuid_test: read");
686 	} else if (rc != sizeof(uuid)) {
687 		fprintf(stderr, "unexpected uuid size (%d vs. %d)\n",
688 			(int)rc, (int)sizeof(uuid));
689 	} else {
690 		print_uuid(dev_name, &uuid);
691 	}
692 
693 	tipc_close(fd);
694 
695 	return 0;
696 }
697 
ta_access_test(void)698 static int ta_access_test(void)
699 {
700 	int fd;
701 
702 	if (!opt_silent) {
703 		printf("%s:\n", __func__);
704 	}
705 
706 	fd = tipc_connect(dev_name, ta_only_name);
707 	if (fd >= 0) {
708 		fprintf(stderr, "Succeed to connect to '%s' service\n",
709 			"ta_only");
710 		tipc_close(fd);
711 	}
712 
713 	fd = tipc_connect(dev_name, ns_only_name);
714 	if (fd < 0) {
715 		fprintf(stderr, "Failed to connect to '%s' service\n",
716 			"ns_only");
717 		return fd;
718 	}
719 	tipc_close(fd);
720 
721 	if (!opt_silent) {
722 		printf("%s: done\n",__func__);
723 	}
724 
725 	return 0;
726 }
727 
728 
writev_test(uint repeat,uint msgsz,bool var)729 static int writev_test(uint repeat, uint msgsz, bool var)
730 {
731 	uint i;
732 	ssize_t rc;
733 	size_t  msg_len;
734 	int  echo_fd = -1;
735 	char tx0_buf[msgsz];
736 	char tx1_buf[msgsz];
737 	char rx_buf [msgsz];
738 	struct iovec iovs[2]= {{tx0_buf, 0}, {tx1_buf, 0}};
739 
740 	if (!opt_silent) {
741 		printf("%s: repeat %u: msgsz %u: variable %s\n",
742 			__func__, repeat, msgsz, var ? "true" : "false");
743 	}
744 
745 	echo_fd = tipc_connect(dev_name, echo_name);
746 	if (echo_fd < 0) {
747 		fprintf(stderr, "Failed to connect to service\n");
748 		return echo_fd;
749 	}
750 
751 	for (i = 0; i < repeat; i++) {
752 
753 		msg_len = msgsz;
754 		if (opt_variable && msgsz) {
755 			msg_len = rand() % msgsz;
756 		}
757 
758 		iovs[0].iov_len = msg_len / 3;
759 		iovs[1].iov_len = msg_len - iovs[0].iov_len;
760 
761 		memset(tx0_buf, i + 1, iovs[0].iov_len);
762 		memset(tx1_buf, i + 2, iovs[1].iov_len);
763 		memset(rx_buf,  i + 3, sizeof(rx_buf));
764 
765 		rc = writev(echo_fd, iovs, 2);
766 		if (rc < 0) {
767 			perror("writev_test: writev");
768 			break;
769 		}
770 
771 		if ((size_t)rc != msg_len) {
772 			fprintf(stderr,
773 				"%s: %s: data size mismatch (%zd vs. %zd)\n",
774 				__func__, "writev", (size_t)rc, msg_len);
775 			break;
776 		}
777 
778 		rc = read(echo_fd, rx_buf, sizeof(rx_buf));
779 		if (rc < 0) {
780 			perror("writev_test: read");
781 			break;
782 		}
783 
784 		if ((size_t)rc != msg_len) {
785 			fprintf(stderr,
786 				"%s: %s: data size mismatch (%zd vs. %zd)\n",
787 				__func__, "read", (size_t)rc, msg_len);
788 			break;
789 		}
790 
791 		if (memcmp(tx0_buf, rx_buf, iovs[0].iov_len)) {
792 			fprintf(stderr, "%s: data mismatch: buf 0\n", __func__);
793 			break;
794 		}
795 
796 		if (memcmp(tx1_buf, rx_buf + iovs[0].iov_len, iovs[1].iov_len)) {
797 			fprintf(stderr, "%s: data mismatch, buf 1\n", __func__);
798 			break;
799 		}
800 	}
801 
802 	tipc_close(echo_fd);
803 
804 	if (!opt_silent) {
805 		printf("%s: done\n",__func__);
806 	}
807 
808 	return 0;
809 }
810 
readv_test(uint repeat,uint msgsz,bool var)811 static int readv_test(uint repeat, uint msgsz, bool var)
812 {
813 	uint i;
814 	ssize_t rc;
815 	size_t  msg_len;
816 	int  echo_fd = -1;
817 	char tx_buf [msgsz];
818 	char rx0_buf[msgsz];
819 	char rx1_buf[msgsz];
820 	struct iovec iovs[2]= {{rx0_buf, 0}, {rx1_buf, 0}};
821 
822 	if (!opt_silent) {
823 		printf("%s: repeat %u: msgsz %u: variable %s\n",
824 			__func__, repeat, msgsz, var ? "true" : "false");
825 	}
826 
827 	echo_fd = tipc_connect(dev_name, echo_name);
828 	if (echo_fd < 0) {
829 		fprintf(stderr, "Failed to connect to service\n");
830 		return echo_fd;
831 	}
832 
833 	for (i = 0; i < repeat; i++) {
834 
835 		msg_len = msgsz;
836 		if (opt_variable && msgsz) {
837 			msg_len = rand() % msgsz;
838 		}
839 
840 		iovs[0].iov_len = msg_len / 3;
841 		iovs[1].iov_len = msg_len - iovs[0].iov_len;
842 
843 		memset(tx_buf,  i + 1, sizeof(tx_buf));
844 		memset(rx0_buf, i + 2, iovs[0].iov_len);
845 		memset(rx1_buf, i + 3, iovs[1].iov_len);
846 
847 		rc = write(echo_fd, tx_buf, msg_len);
848 		if (rc < 0) {
849 			perror("readv_test: write");
850 			break;
851 		}
852 
853 		if ((size_t)rc != msg_len) {
854 			fprintf(stderr,
855 				"%s: %s: data size mismatch (%zd vs. %zd)\n",
856 				__func__, "write", (size_t)rc, msg_len);
857 			break;
858 		}
859 
860 		rc = readv(echo_fd, iovs, 2);
861 		if (rc < 0) {
862 			perror("readv_test: readv");
863 			break;
864 		}
865 
866 		if ((size_t)rc != msg_len) {
867 			fprintf(stderr,
868 				"%s: %s: data size mismatch (%zd vs. %zd)\n",
869 				__func__, "write", (size_t)rc, msg_len);
870 			break;
871 		}
872 
873 		if (memcmp(rx0_buf, tx_buf, iovs[0].iov_len)) {
874 			fprintf(stderr, "%s: data mismatch: buf 0\n", __func__);
875 			break;
876 		}
877 
878 		if (memcmp(rx1_buf, tx_buf + iovs[0].iov_len, iovs[1].iov_len)) {
879 			fprintf(stderr, "%s: data mismatch, buf 1\n", __func__);
880 			break;
881 		}
882 	}
883 
884 	tipc_close(echo_fd);
885 
886 	if (!opt_silent) {
887 		printf("%s: done\n",__func__);
888 	}
889 
890 	return 0;
891 }
892 
send_fd_test(void)893 static int send_fd_test(void) {
894     int ret;
895     int dma_buf = -1;
896     int fd = -1;
897     volatile char* buf = MAP_FAILED;
898     BufferAllocator* allocator = NULL;
899 
900     const size_t num_pages = 10;
901 
902     fd = tipc_connect(dev_name, receiver_name);
903     if (fd < 0) {
904         fprintf(stderr, "Failed to connect to test support TA - is it missing?\n");
905         ret = -1;
906         goto cleanup;
907     }
908 
909     allocator = CreateDmabufHeapBufferAllocator();
910     if (!allocator) {
911         fprintf(stderr, "Failed to create dma-buf allocator.\n");
912         ret = -1;
913         goto cleanup;
914     }
915 
916     size_t buf_size = PAGE_SIZE * num_pages;
917     dma_buf = DmabufHeapAlloc(allocator, "system", buf_size, 0, 0 /* legacy align */);
918     if (dma_buf < 0) {
919         ret = dma_buf;
920         fprintf(stderr, "Failed to create dma-buf fd of size %zu err (%d)\n", buf_size, ret);
921         goto cleanup;
922     }
923 
924     buf = mmap(0, buf_size, PROT_READ | PROT_WRITE, MAP_SHARED, dma_buf, 0);
925     if (buf == MAP_FAILED) {
926         fprintf(stderr, "Failed to map dma-buf: %s\n", strerror(errno));
927         ret = -1;
928         goto cleanup;
929     }
930 
931     strcpy((char*)buf, "From NS");
932 
933     struct trusty_shm shm = {
934             .fd = dma_buf,
935             .transfer = TRUSTY_SHARE,
936     };
937 
938     ssize_t rc = tipc_send(fd, NULL, 0, &shm, 1);
939     if (rc < 0) {
940         fprintf(stderr, "tipc_send failed: %zd\n", rc);
941         ret = rc;
942         goto cleanup;
943     }
944     char c;
945     read(fd, &c, 1);
946     tipc_close(fd);
947 
948     ret = 0;
949     for (size_t skip = 0; skip < num_pages; skip++) {
950         ret |= strcmp("Hello from Trusty!", (const char*)&buf[skip * PAGE_SIZE]) ? (-1) : 0;
951     }
952 
953 cleanup:
954     if (buf != MAP_FAILED) {
955         munmap((char*)buf, PAGE_SIZE);
956     }
957     close(dma_buf);
958     if (allocator) {
959         FreeDmabufHeapBufferAllocator(allocator);
960     }
961     tipc_close(fd);
962     return ret;
963 }
964 
main(int argc,char ** argv)965 int main(int argc, char **argv)
966 {
967 	int rc = 0;
968 
969 	if (argc <= 1) {
970 		print_usage_and_exit(argv[0], EXIT_FAILURE, false);
971 	}
972 
973 	parse_options(argc, argv);
974 
975 	if (!dev_name) {
976 		dev_name = TIPC_DEFAULT_DEVNAME;
977 	}
978 
979 	if (!test_name) {
980 		fprintf(stderr, "need a Test to run\n");
981 		print_usage_and_exit(argv[0], EXIT_FAILURE, true);
982 	}
983 
984 	if (strcmp(test_name, "connect") == 0) {
985 		rc = connect_test(opt_repeat);
986 	} else if (strcmp(test_name, "connect_foo") == 0) {
987 		rc = connect_foo(opt_repeat);
988 	} else if (strcmp(test_name, "burst_write") == 0) {
989 		rc = burst_write_test(opt_repeat, opt_msgburst, opt_msgsize, opt_variable);
990 	} else if (strcmp(test_name, "select") == 0) {
991 		rc = select_test(opt_repeat, opt_msgburst,  opt_msgsize);
992 	} else if (strcmp(test_name, "blocked_read") == 0) {
993 		rc = blocked_read_test(opt_repeat);
994 	} else if (strcmp(test_name, "closer1") == 0) {
995 		rc = closer1_test(opt_repeat);
996 	} else if (strcmp(test_name, "closer2") == 0) {
997 		rc = closer2_test(opt_repeat);
998 	} else if (strcmp(test_name, "closer3") == 0) {
999 		rc = closer3_test(opt_repeat);
1000 	} else if (strcmp(test_name, "echo") == 0) {
1001 		rc = echo_test(opt_repeat, opt_msgsize, opt_variable);
1002 	} else if(strcmp(test_name, "ta2ta-ipc") == 0) {
1003 		rc = ta2ta_ipc_test();
1004 	} else if (strcmp(test_name, "dev-uuid") == 0) {
1005 		rc = dev_uuid_test();
1006 	} else if (strcmp(test_name, "ta-access") == 0) {
1007 		rc = ta_access_test();
1008 	} else if (strcmp(test_name, "writev") == 0) {
1009 		rc = writev_test(opt_repeat, opt_msgsize, opt_variable);
1010 	} else if (strcmp(test_name, "readv") == 0) {
1011 		rc = readv_test(opt_repeat, opt_msgsize, opt_variable);
1012     } else if (strcmp(test_name, "send-fd") == 0) {
1013         rc = send_fd_test();
1014     } else {
1015         fprintf(stderr, "Unrecognized test name '%s'\n", test_name);
1016         print_usage_and_exit(argv[0], EXIT_FAILURE, true);
1017     }
1018 
1019     return rc == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
1020 }
1021