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