1 /**************************************************************************/
2 /* CAN performance benchmark for recvmmsg() */
3 /* Copyright (C) 2013, 2014 Michal Sojka, DCE, FEE, CTU Prague */
5 /**************************************************************************/
8 #include <sys/socket.h>
10 #include <sys/ioctl.h>
18 #define CHECK(cmd) do { if ((cmd) == -1) { perror(#cmd); exit(1); } } while (0)
22 enum { READ, RECVMMSG } recv_method = READ;
24 /* Subtract the `struct timespec' values X and Y,
25 storing the result in RESULT (result = x - y).
26 Return 1 if the difference is negative, otherwise 0. */
29 timespec_subtract (struct timespec *result,
33 /* Perform the carry for the later subtraction by updating Y. */
34 if (x->tv_nsec < y->tv_nsec) {
35 int num_sec = (y->tv_nsec - x->tv_nsec) / 1000000000 + 1;
36 y->tv_nsec -= 1000000000 * num_sec;
39 if (x->tv_nsec - y->tv_nsec > 1000000000) {
40 int num_sec = (x->tv_nsec - y->tv_nsec) / 1000000000;
41 y->tv_nsec += 1000000000 * num_sec;
45 /* Compute the time remaining to wait.
46 `tv_nsec' is certainly positive. */
47 result->tv_sec = x->tv_sec - y->tv_sec;
48 result->tv_nsec = x->tv_nsec - y->tv_nsec;
50 /* Return 1 if result is negative. */
51 return x->tv_sec < y->tv_sec;
58 struct sockaddr_can addr;
62 struct timespec t, t1, t2;
64 ss = socket(PF_CAN, SOCK_RAW, CAN_RAW);
65 sr = socket(PF_CAN, SOCK_RAW, CAN_RAW);
67 strcpy(ifr.ifr_name, dev);
68 ioctl(ss, SIOCGIFINDEX, &ifr);
70 addr.can_family = AF_CAN;
71 addr.can_ifindex = ifr.ifr_ifindex;
73 bind(ss, (struct sockaddr *)&addr, sizeof(addr));
74 bind(sr, (struct sockaddr *)&addr, sizeof(addr));
76 int rcvbuf = 30 * count * sizeof(cf);
77 CHECK(setsockopt(sr, SOL_SOCKET, SO_RCVBUFFORCE, &rcvbuf, sizeof(rcvbuf)));
79 memset(&cf, 0, sizeof(cf));
82 fprintf(stderr, "Sending %d frames\n", count);
83 for (i = 0; i < count; i++) {
84 ret = write(ss, &cf, sizeof(cf));
85 if (ret != sizeof(cf)) {
91 switch (recv_method) {
93 fprintf(stderr, "Receiving %d frames with read()\n", count);
94 clock_gettime(CLOCK_MONOTONIC, &t1);
95 for (i = 0; i < count; i++) {
96 //fprintf(stderr, "Receiving frame %d\r", i);
97 ret = read(sr, &cf, sizeof(cf));
98 if (ret != sizeof(cf)) {
103 clock_gettime(CLOCK_MONOTONIC, &t2);
104 //fprintf(stderr, "\n");
108 fprintf(stderr, "Receiving %d frames with recvmmsg()\n", count);
109 struct mmsghdr msgs[count];
110 struct iovec iovecs[count];
111 char bufs[count][sizeof(struct can_frame)];
113 memset(msgs, 0, sizeof(msgs));
114 for (i = 0; i < count; i++) {
115 iovecs[i].iov_base = bufs[i];
116 iovecs[i].iov_len = sizeof(struct can_frame);
117 msgs[i].msg_hdr.msg_iov = &iovecs[i];
118 msgs[i].msg_hdr.msg_iovlen = 1;
121 clock_gettime(CLOCK_MONOTONIC, &t1);
122 ret = recvmmsg(sr, msgs, count, 0, NULL);
123 clock_gettime(CLOCK_MONOTONIC, &t2);
125 perror("recvmmsg()");
127 } else if (ret != count) {
128 fprintf(stderr, "Error: Only %d messages received\n", ret);
134 timespec_subtract(&t, &t2, &t1);
135 printf("%d us\n", t.tv_nsec/1000);
138 int main(int argc, char *argv[])
142 while ((opt = getopt(argc, argv, "c:mr")) != -1) {
145 count = atoi(optarg);
148 recv_method = RECVMMSG;
154 fprintf(stderr, "Usage: %s [-c <count>] [-r] [-m] [interface]\n",