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>
19 #define CHECK(cmd) do { if ((cmd) == -1) { perror(#cmd); exit(1); } } while (0)
23 enum { READ, RECVMMSG } recv_method = READ;
26 /* Subtract the `struct timespec' values X and Y,
27 storing the result in RESULT (result = x - y).
28 Return 1 if the difference is negative, otherwise 0. */
31 timespec_subtract (struct timespec *result,
35 /* Perform the carry for the later subtraction by updating Y. */
36 if (x->tv_nsec < y->tv_nsec) {
37 int num_sec = (y->tv_nsec - x->tv_nsec) / 1000000000 + 1;
38 y->tv_nsec -= 1000000000 * num_sec;
41 if (x->tv_nsec - y->tv_nsec > 1000000000) {
42 int num_sec = (x->tv_nsec - y->tv_nsec) / 1000000000;
43 y->tv_nsec += 1000000000 * num_sec;
47 /* Compute the time remaining to wait.
48 `tv_nsec' is certainly positive. */
49 result->tv_sec = x->tv_sec - y->tv_sec;
50 result->tv_nsec = x->tv_nsec - y->tv_nsec;
52 /* Return 1 if result is negative. */
53 return x->tv_sec < y->tv_sec;
60 struct sockaddr_can addr;
64 struct timespec t, t1, t2;
66 ss = socket(PF_CAN, SOCK_RAW, CAN_RAW);
67 sr = socket(PF_CAN, SOCK_RAW, CAN_RAW);
69 strcpy(ifr.ifr_name, dev);
70 ioctl(ss, SIOCGIFINDEX, &ifr);
72 addr.can_family = AF_CAN;
73 addr.can_ifindex = ifr.ifr_ifindex;
75 bind(ss, (struct sockaddr *)&addr, sizeof(addr));
76 bind(sr, (struct sockaddr *)&addr, sizeof(addr));
78 int rcvbuf = 30 * count * sizeof(cf);
79 CHECK(setsockopt(sr, SOL_SOCKET, SO_RCVBUFFORCE, &rcvbuf, sizeof(rcvbuf)));
81 memset(&cf, 0, sizeof(cf));
84 if (!quiet) fprintf(stderr, "Sending %d frames\n", count);
85 for (i = 0; i < count; i++) {
86 ret = write(ss, &cf, sizeof(cf));
87 if (ret != sizeof(cf)) {
93 switch (recv_method) {
95 if (!quiet) fprintf(stderr, "Receiving %d frames with read()\n", count);
96 clock_gettime(CLOCK_MONOTONIC, &t1);
97 for (i = 0; i < count; i++) {
98 //fprintf(stderr, "Receiving frame %d\r", i);
99 ret = read(sr, &cf, sizeof(cf));
100 if (ret != sizeof(cf)) {
105 clock_gettime(CLOCK_MONOTONIC, &t2);
106 //fprintf(stderr, "\n");
110 if (!quiet) fprintf(stderr, "Receiving %d frames with recvmmsg()\n", count);
111 struct mmsghdr msgs[count];
112 struct iovec iovecs[count];
113 char bufs[count][sizeof(struct can_frame)];
115 memset(msgs, 0, sizeof(msgs));
116 for (i = 0; i < count; i++) {
117 iovecs[i].iov_base = bufs[i];
118 iovecs[i].iov_len = sizeof(struct can_frame);
119 msgs[i].msg_hdr.msg_iov = &iovecs[i];
120 msgs[i].msg_hdr.msg_iovlen = 1;
123 clock_gettime(CLOCK_MONOTONIC, &t1);
124 ret = recvmmsg(sr, msgs, count, 0, NULL);
125 clock_gettime(CLOCK_MONOTONIC, &t2);
127 perror("recvmmsg()");
129 } else if (ret != count) {
130 fprintf(stderr, "Error: Only %d messages received\n", ret);
136 timespec_subtract(&t, &t2, &t1);
137 printf("%d us\n", t.tv_nsec/1000);
140 int main(int argc, char *argv[])
144 while ((opt = getopt(argc, argv, "c:mrq")) != -1) {
147 count = atoi(optarg);
150 recv_method = RECVMMSG;
159 fprintf(stderr, "Usage: %s [-c <count>] [-r] [-m] [interface]\n",