X-Git-Url: http://rtime.felk.cvut.cz/gitweb/can-benchmark.git/blobdiff_plain/71621938d63ddfaf199741657e185d5c0a68cf3a..ae829d30657a177845d8a5555218bc39dd52003a:/recvmmsg/can_recvmmsg.c diff --git a/recvmmsg/can_recvmmsg.c b/recvmmsg/can_recvmmsg.c index 9dc57e0..7e21c65 100644 --- a/recvmmsg/can_recvmmsg.c +++ b/recvmmsg/can_recvmmsg.c @@ -14,24 +14,54 @@ #include #include #include +#include -#define CHECK(cmd) do { if ((cmd) == -1) { perror(#cmd); exit(1); } } while (0) +#define STRINGIFY(val) #val +#define TOSTRING(val) STRINGIFY(val) +#define CHECK(cmd) ({ int ret = (cmd); if (ret == -1) { perror(#cmd " line " TOSTRING(__LINE__)); exit(1); }; ret; }) +char *dev = "vcan0"; int count = 10000; +enum { READWRITE, MMSG } method = READWRITE; +bool quiet = false; -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, + const struct timespec *x, + const struct timespec *y) +{ + int carry = (x->tv_nsec < y->tv_nsec); + + result->tv_sec = x->tv_sec - y->tv_sec - carry; + result->tv_nsec = x->tv_nsec + carry*1000000000 - y->tv_nsec; + +/* printf("%ld.%09ld - %ld.%09ld = %ld.%09ld\n", */ +/* x->tv_sec, x->tv_nsec, */ +/* y->tv_sec, y->tv_nsec, */ +/* result->tv_sec, result->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 ttx, trx, 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; @@ -46,49 +76,118 @@ int main(int argc, char *argv[]) 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); + switch (method) { + case READWRITE: { + if (!quiet) fprintf(stderr, "Sending %d frames via write()\n", count); + clock_gettime(CLOCK_MONOTONIC, &t1); + for (i = 0; i < count; i++) { + ret = write(ss, &cf, sizeof(cf)); + if (ret != sizeof(cf)) { + perror("write"); + exit(1); + } + } + clock_gettime(CLOCK_MONOTONIC, &t2); + break; + } + case MMSG: { + if (!quiet) fprintf(stderr, "Sending %d frames via sendmmsg()\n", count); + struct mmsghdr msgs[count]; + struct iovec iovecs[count]; + memset(msgs, 0, sizeof(msgs)); + memset(iovecs, 0, sizeof(iovecs)); + for (i = 0; i < count; i++) { + iovecs[i].iov_base = &cf; + iovecs[i].iov_len = sizeof(cf); + msgs[i].msg_hdr.msg_iov = &iovecs[i]; + msgs[i].msg_hdr.msg_iovlen = 1; } + clock_gettime(CLOCK_MONOTONIC, &t1); + for (i = 0; i < count; i += ret) + ret = CHECK(sendmmsg(ss, &msgs[i], count - i, 0)); + clock_gettime(CLOCK_MONOTONIC, &t2); + break; } + } + timespec_subtract(&ttx, &t2, &t1); + + switch (method) { + case READWRITE: { + if (!quiet) 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; + } + case MMSG: { + if (!quiet) 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; + } -#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"); + 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; } - //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; } + timespec_subtract(&trx, &t2, &t1); + printf("tx %ld rx %ld [us]\n", ttx.tv_sec*1000000 + ttx.tv_nsec/1000, + trx.tv_sec*1000000 + trx.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:mrq")) != -1) { + switch (opt) { + case 'c': + count = atoi(optarg); + break; + case 'm': + method = MMSG; + break; + case 'r': + method = READWRITE; + break; + case 'q': + quiet = true; + break; + default: /* '?' */ + fprintf(stderr, "Usage: %s [-c ] [-r] [-m] [interface]\n", + argv[0]); + exit(EXIT_FAILURE); + } } + if (optind < argc) + dev = argv[optind]; + + benchmark(); + return 0; }