#define CHECK(cmd) do { if ((cmd) == -1) { perror(#cmd); exit(1); } } while (0)
+char *dev = "vcan0";
int count = 10000;
+enum { READ, RECVMMSG } recv_method = READ;
-int main(int argc, char *argv[])
+/* Subtract the `struct timespec' values X and Y,
+ storing the result in RESULT (result = x - y).
+ Return 1 if the difference is negative, otherwise 0. */
+
+int
+timespec_subtract (struct timespec *result,
+ struct timespec *x,
+ struct timespec *y)
+{
+ /* Perform the carry for the later subtraction by updating Y. */
+ if (x->tv_nsec < y->tv_nsec) {
+ int num_sec = (y->tv_nsec - x->tv_nsec) / 1000000000 + 1;
+ y->tv_nsec -= 1000000000 * num_sec;
+ y->tv_sec += num_sec;
+ }
+ if (x->tv_nsec - y->tv_nsec > 1000000000) {
+ int num_sec = (x->tv_nsec - y->tv_nsec) / 1000000000;
+ y->tv_nsec += 1000000000 * num_sec;
+ y->tv_sec -= num_sec;
+ }
+
+ /* Compute the time remaining to wait.
+ `tv_nsec' is certainly positive. */
+ result->tv_sec = x->tv_sec - y->tv_sec;
+ result->tv_nsec = x->tv_nsec - y->tv_nsec;
+
+ /* Return 1 if result is negative. */
+ return x->tv_sec < y->tv_sec;
+}
+
+
+void benchmark()
{
int ss, sr;
struct sockaddr_can addr;
struct ifreq ifr;
struct can_frame cf;
int ret, i;
- struct timespec t1, t2;
+ struct timespec t, t1, t2;
ss = socket(PF_CAN, SOCK_RAW, CAN_RAW);
sr = socket(PF_CAN, SOCK_RAW, CAN_RAW);
- strcpy(ifr.ifr_name, "vcan0" );
+ strcpy(ifr.ifr_name, dev);
ioctl(ss, SIOCGIFINDEX, &ifr);
addr.can_family = AF_CAN;
}
}
-#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);
+ switch (recv_method) {
+ case READ: {
+ fprintf(stderr, "Receiving %d frames with read()\n", count);
+ clock_gettime(CLOCK_MONOTONIC, &t1);
+ 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);
+ }
}
+ clock_gettime(CLOCK_MONOTONIC, &t2);
+ //fprintf(stderr, "\n");
+ break;
}
- //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)];
+ case RECVMMSG: {
+ 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;
+ }
- 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;
+ clock_gettime(CLOCK_MONOTONIC, &t1);
+ ret = recvmmsg(sr, msgs, count, 0, NULL);
+ clock_gettime(CLOCK_MONOTONIC, &t2);
+ if (ret == -1) {
+ perror("recvmmsg()");
+ exit(1);
+ } else if (ret != count) {
+ fprintf(stderr, "Error: Only %d messages received\n", ret);
+ exit(1);
+ }
+ break;
+ }
}
+ timespec_subtract(&t, &t2, &t1);
+ printf("%d us\n", t.tv_nsec/1000);
+}
- 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);
+int main(int argc, char *argv[])
+{
+ int opt;
+
+ while ((opt = getopt(argc, argv, "c:mr")) != -1) {
+ switch (opt) {
+ case 'c':
+ count = atoi(optarg);
+ break;
+ case 'm':
+ recv_method = RECVMMSG;
+ break;
+ case 'r':
+ recv_method = READ;
+ break;
+ default: /* '?' */
+ fprintf(stderr, "Usage: %s [-c <count>] [-r] [-m] [interface]\n",
+ argv[0]);
+ exit(EXIT_FAILURE);
+ }
}
+ if (optind < argc)
+ dev = argv[optind];
+
+ benchmark();
+
return 0;
}