+/**************************************************************************/
+/* CAN performance benchmark for recvmmsg() */
+/* Copyright (C) 2013, 2014 Michal Sojka, DCE, FEE, CTU Prague */
+/* License: GPLv2 */
+/**************************************************************************/
+
+#define _GNU_SOURCE
+#include <sys/socket.h>
+#include <linux/can.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+
+#define CHECK(cmd) do { if ((cmd) == -1) { perror(#cmd); exit(1); } } while (0)
+
+int count = 10000;
+
+int main(int argc, char *argv[])
+{
+ int ss, sr;
+ struct sockaddr_can addr;
+ struct ifreq ifr;
+ struct can_frame cf;
+ int ret, i;
+ struct timespec t1, t2;
+
+ ss = socket(PF_CAN, SOCK_RAW, CAN_RAW);
+ sr = socket(PF_CAN, SOCK_RAW, CAN_RAW);
+
+ strcpy(ifr.ifr_name, "vcan0" );
+ ioctl(ss, SIOCGIFINDEX, &ifr);
+
+ addr.can_family = AF_CAN;
+ addr.can_ifindex = ifr.ifr_ifindex;
+
+ bind(ss, (struct sockaddr *)&addr, sizeof(addr));
+ bind(sr, (struct sockaddr *)&addr, sizeof(addr));
+
+ int rcvbuf = 30 * count * sizeof(cf);
+ CHECK(setsockopt(sr, SOL_SOCKET, SO_RCVBUFFORCE, &rcvbuf, sizeof(rcvbuf)));
+
+ memset(&cf, 0, sizeof(cf));
+ cf.can_dlc = 8;
+
+ fprintf(stderr, "Sending %d frames\n", count);
+ for (i = 0; i < count; i++) {
+ ret = write(ss, &cf, sizeof(cf));
+ if (ret != sizeof(cf)) {
+ perror("write");
+ exit(1);
+ }
+ }
+
+#if 0
+ fprintf(stderr, "Receiving %d frames with read()\n", count);
+ for (i = 0; i < count; i++) {
+ //fprintf(stderr, "Receiving frame %d\r", i);
+ ret = read(sr, &cf, sizeof(cf));
+ if (ret != sizeof(cf)) {
+ perror("read");
+ exit(1);
+ }
+ }
+ //fprintf(stderr, "\n");
+#endif
+
+ fprintf(stderr, "Receiving %d frames with recvmmsg()\n", count);
+ struct mmsghdr msgs[count];
+ struct iovec iovecs[count];
+ char bufs[count][sizeof(struct can_frame)];
+
+ memset(msgs, 0, sizeof(msgs));
+ for (i = 0; i < count; i++) {
+ iovecs[i].iov_base = bufs[i];
+ iovecs[i].iov_len = sizeof(struct can_frame);
+ msgs[i].msg_hdr.msg_iov = &iovecs[i];
+ msgs[i].msg_hdr.msg_iovlen = 1;
+ }
+
+ ret = recvmmsg(sr, msgs, count, 0, NULL);
+ if (ret == -1) {
+ perror("recvmmsg()");
+ exit(1);
+ } else if (ret != count) {
+ fprintf(stderr, "Error: Only %d messages received\n", ret);
+ exit(1);
+ }
+
+ return 0;
+}