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