ugw: Add nonblocking mode
authorMichal Sojka <sojkam1@fel.cvut.cz>
Tue, 14 Jan 2014 10:17:01 +0000 (11:17 +0100)
committerMichal Sojka <sojkam1@fel.cvut.cz>
Tue, 14 Jan 2014 10:17:01 +0000 (11:17 +0100)
ugw/ugw.c

index 482f4e1..0e653d3 100644 (file)
--- a/ugw/ugw.c
+++ b/ugw/ugw.c
@@ -20,6 +20,8 @@
 #include <poll.h>
 #include <sys/mman.h>
 #include <arpa/inet.h>
+#include <fcntl.h>
+#include <errno.h>
 
 #ifndef SO_BUSY_POLL
 #define SO_BUSY_POLL 46
@@ -41,10 +43,12 @@ enum { IN_READ, IN_RECVMMSG, IN_MMAP, IN_MMAPBUSY } in_method = IN_READ;
 enum { WRITE, OUT_MMAP } out_method = WRITE;
 bool quiet = false;
 int busy_poll_us = 0;
+bool nonblocking = false;
 
 enum in2out {
        STORE_ONLY,
        SEND,
+       NOP,
 };
 
 
@@ -70,6 +74,8 @@ struct out_ctx {
 enum in2out in_read(struct in_ctx *ctx, struct can_frame *cf)
 {
        int ret = read(ctx->s, cf, sizeof(*cf));
+       if (nonblocking && ret == -1 && errno == EAGAIN)
+               return NOP;
        if (ret != sizeof(*cf)) {
                perror("read");
                exit(1);
@@ -85,6 +91,11 @@ void init_read(struct in_ctx *ctx)
 
        s = CHECK(socket(PF_CAN, SOCK_RAW, CAN_RAW));
 
+       if (nonblocking) {
+               int flags = CHECK(fcntl(s, F_GETFL, 0));
+               CHECK(fcntl(s, F_SETFL, flags | O_NONBLOCK));
+       }
+
        if (busy_poll_us) {
                CHECK(setsockopt(s, SOL_SOCKET, SO_BUSY_POLL,
                                 &busy_poll_us, sizeof(busy_poll_us)));
@@ -173,6 +184,9 @@ void init_packet_rx(struct in_ctx *ctx)
 
 int out_write(struct out_ctx *ctx, struct can_frame *cf)
 {
+       if (ctx->from_in == NOP)
+               return 0;
+
        int ret = write(ctx->s, cf, sizeof(*cf));
        if (ret != sizeof(*cf)) {
                perror("write");
@@ -209,6 +223,10 @@ int out_packet_tx(struct out_ctx *ctx, struct can_frame *cf)
        volatile struct tpacket2_hdr *hdr = ctx->ptr + ctx->current*FRAME_SIZE;
        int ret = -1;
 
+       if (ctx->from_in == NOP)
+               return 0;
+
+
        while (hdr->tp_status != TP_STATUS_AVAILABLE) {
                struct pollfd pfd = {.fd = ctx->s, .revents = 0,
                                     .events = POLLIN|POLLRDNORM|POLLERR };
@@ -319,6 +337,11 @@ void gw()
 
        while (1) {
                oc.from_in = in(&ic, &cf);
+               switch (oc.from_in) {
+               case SEND:       stats.send++;  break;
+               case STORE_ONLY: stats.store++; break;
+               case NOP:                       break;
+               }
                out(&oc, &cf);
        }
 }
@@ -328,11 +351,14 @@ int main(int argc, char *argv[])
 {
        int opt;
 
-       while ((opt = getopt(argc, argv, "b:qr:t:")) != -1) {
+       while ((opt = getopt(argc, argv, "b:nqr:t:")) != -1) {
                switch (opt) {
                case 'b':
                        busy_poll_us = atoi(optarg);
                        break;
+               case 'n':
+                       nonblocking = true;
+                       break;
                case 'q':
                        quiet = true;
                        break;