• 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 = "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