]> rtime.felk.cvut.cz Git - can-utils.git/blobdiff - canbusload.c
candump: use UINT32_MAX define from stdint.h
[can-utils.git] / canbusload.c
index 4bc3bed16a2f1399034f886464591fb4a1652c6c..8f6b10dc2ccb878a17e7035cda20906e971e0833 100644 (file)
@@ -1,7 +1,3 @@
-/*
- *  $Id$
- */
-
 /*
  * canbusload.c
  *
@@ -41,7 +37,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  * DAMAGE.
  *
- * Send feedback to <socketcan-users@lists.berlios.de>
+ * Send feedback to <linux-can@vger.kernel.org>
  *
  */
 
@@ -65,6 +61,7 @@
 #include <linux/can/raw.h>
 
 #include "terminal.h"
+#include "canframelen.h"
 
 #define MAXSOCK 16    /* max. number of CAN interfaces given on the cmdline */
 
 extern int optind, opterr, optopt;
 
 static struct {
-    char devname[IFNAMSIZ+1];
-    unsigned int bitrate;
-    unsigned int recv_frames;
-    unsigned int recv_bits_total;
-    unsigned int recv_bits_payload;
+       char devname[IFNAMSIZ+1];
+       unsigned int bitrate;
+       unsigned int recv_frames;
+       unsigned int recv_bits_total;
+       unsigned int recv_bits_payload;
 } stat[MAXSOCK+1];
 
 static int  max_devname_len; /* to prevent frazzled device name output */ 
@@ -88,293 +85,329 @@ static unsigned char redraw;
 static unsigned char timestamp;
 static unsigned char color;
 static unsigned char bargraph;
+static enum cfl_mode mode = CFL_WORSTCASE;
 static char *prg;
 
 void print_usage(char *prg)
 {
-    fprintf(stderr, "\nUsage: %s [options] <CAN interface>+\n", prg);
-    fprintf(stderr, "  (use CTRL-C to terminate %s)\n\n", prg);
-    fprintf(stderr, "Options: -t (show current time on the first line)\n");
-    fprintf(stderr, "         -c (colorize lines)\n");
-    fprintf(stderr, "         -b (show bargraph in %d%% resolution)\n", PERCENTRES);
-    fprintf(stderr, "         -r (redraw the terminal - similar to top)\n");
-    fprintf(stderr, "\n");
-    fprintf(stderr, "Up to %d CAN interfaces with mandatory bitrate can be specified on the \n", MAXSOCK);
-    fprintf(stderr, "commandline in the form: <ifname>@<bitrate>\n\n");
-    fprintf(stderr, "The bitrate is mandatory as it is needed to know the CAN bus bitrate to\n");
-    fprintf(stderr, "calcultate the bus load percentage based on the received CAN frames.\n");
-    fprintf(stderr, "For each given interface the data is presented in one line which contains:\n\n");
-    fprintf(stderr, "(interface) (received CAN frames) (used bits total) (used bits for payload)\n");
-    fprintf(stderr, "\nExample:\n");
-    fprintf(stderr, "\nuser$> canbusload can0@100000 can1@500000 can2@500000 can3@500000 -r -t -b -c\n\n");
-    fprintf(stderr, "%s 2008-05-27 15:18:49\n", prg);
-    fprintf(stderr, " can0@100000  805  74491  36656  74%%  |XXXXXXXXXXXXXX......|\n");
-    fprintf(stderr, " can1@500000  796  75140  37728  15%%  |XXX.................|\n");
-    fprintf(stderr, " can2@500000    0      0      0   0%%  |....................|\n");
-    fprintf(stderr, " can3@500000   47   4633   2424   0%%  |....................|\n");
-    fprintf(stderr, "\n");
+       fprintf(stderr, "\nUsage: %s [options] <CAN interface>+\n", prg);
+       fprintf(stderr, "  (use CTRL-C to terminate %s)\n\n", prg);
+       fprintf(stderr, "Options: -t (show current time on the first line)\n");
+       fprintf(stderr, "         -c (colorize lines)\n");
+       fprintf(stderr, "         -b (show bargraph in %d%% resolution)\n", PERCENTRES);
+       fprintf(stderr, "         -r (redraw the terminal - similar to top)\n");
+       fprintf(stderr, "         -i (ignore bitstuffing in bandwidth calculation)\n");
+       fprintf(stderr, "         -e (exact calculation of stuffed bits)\n");
+       fprintf(stderr, "\n");
+       fprintf(stderr, "Up to %d CAN interfaces with mandatory bitrate can be specified on the \n", MAXSOCK);
+       fprintf(stderr, "commandline in the form: <ifname>@<bitrate>\n\n");
+       fprintf(stderr, "The bitrate is mandatory as it is needed to know the CAN bus bitrate to\n");
+       fprintf(stderr, "calcultate the bus load percentage based on the received CAN frames.\n");
+       fprintf(stderr, "Due to the bitstuffing estimation the calculated busload may exceed 100%%.\n");
+       fprintf(stderr, "For each given interface the data is presented in one line which contains:\n\n");
+       fprintf(stderr, "(interface) (received CAN frames) (used bits total) (used bits for payload)\n");
+       fprintf(stderr, "\nExample:\n");
+       fprintf(stderr, "\nuser$> canbusload can0@100000 can1@500000 can2@500000 can3@500000 -r -t -b -c\n\n");
+       fprintf(stderr, "%s 2014-02-01 21:13:16 (worst case bitstuffing)\n", prg);
+       fprintf(stderr, " can0@100000   805   74491  36656  74%% |XXXXXXXXXXXXXX......|\n");
+       fprintf(stderr, " can1@500000   796   75140  37728  15%% |XXX.................|\n");
+       fprintf(stderr, " can2@500000     0       0      0   0%% |....................|\n");
+       fprintf(stderr, " can3@500000    47    4633   2424   0%% |....................|\n");
+       fprintf(stderr, "\n");
 }
 
 void sigterm(int signo)
 {
-    exit(0);
+       exit(0);
 }
 
 void printstats(int signo)
 {
-    int i, j, percent;
+       int i, j, percent;
+
+       if (redraw)
+               printf("%s", CSR_HOME);
 
-    if (redraw)
-       printf("%s", CSR_HOME);
+       if (timestamp) {
+               time_t currtime;
+               struct tm now;
 
-    if (timestamp) {
-       time_t currtime;
-       struct tm now;
+               if (time(&currtime) == (time_t)-1) {
+                       perror("time");
+                       exit(1);
+               }
 
-       if (time(&currtime) == (time_t)-1) {
-           perror("time");
-           exit(1);
+               localtime_r(&currtime, &now);
+
+               printf("%s %04d-%02d-%02d %02d:%02d:%02d ",
+                      prg,
+                      now.tm_year + 1900,
+                      now.tm_mon + 1,
+                      now.tm_mday,
+                      now.tm_hour,
+                      now.tm_min,
+                      now.tm_sec);
+
+               switch (mode) {
+
+               case CFL_NO_BITSTUFFING:
+                       /* plain bit calculation without bitstuffing */
+                       printf("(ignore bitstuffing)\n");
+                       break;
+
+               case CFL_WORSTCASE:
+                       /* worst case estimation - see above */
+                       printf("(worst case bitstuffing)\n");
+                       break;
+
+               case CFL_EXACT:
+                       /* exact calculation of stuffed bits based on frame content and CRC */
+                       printf("(exact bitstuffing)\n");
+                       break;
+
+               default:
+                       printf("(unknown bitstuffing)\n");
+                       break;
+               }
        }
 
-       localtime_r(&currtime, &now);
-
-       printf("%s %04d-%02d-%02d %02d:%02d:%02d\n",
-              prg,
-              now.tm_year + 1900,
-              now.tm_mon + 1,
-              now.tm_mday,
-              now.tm_hour,
-              now.tm_min,
-              now.tm_sec);
-    }
-
-    for (i=0; i<currmax; i++) {
-
-       if (color)
-           if (i%2)
-               printf("%s", FGRED);
-           else
-               printf("%s", FGBLUE);
-
-       if (stat[i].bitrate)
-           percent = (stat[i].recv_bits_total*100)/stat[i].bitrate;
-       else
-           percent = 0;
-
-       printf(" %*s@%-*d %4d %6d %6d %3d%%",
-              max_devname_len, stat[i].devname,
-              max_bitrate_len, stat[i].bitrate,
-              stat[i].recv_frames,
-              stat[i].recv_bits_total,
-              stat[i].recv_bits_payload,
-              percent);
-
-       if (bargraph) {
-
-           printf("  |");
-
-           for (j=0; j < NUMBAR; j++){
-               if (j < percent/PERCENTRES)
-                   printf("X");
+       for (i=0; i<currmax; i++) {
+
+               if (color) {
+                       if (i%2)
+                               printf("%s", FGRED);
+                       else
+                               printf("%s", FGBLUE);
+               }
+
+               if (stat[i].bitrate)
+                       percent = (stat[i].recv_bits_total*100)/stat[i].bitrate;
                else
-                   printf(".");
-           }
+                       percent = 0;
+
+               printf(" %*s@%-*d %5d %7d %6d %3d%%",
+                      max_devname_len, stat[i].devname,
+                      max_bitrate_len, stat[i].bitrate,
+                      stat[i].recv_frames,
+                      stat[i].recv_bits_total,
+                      stat[i].recv_bits_payload,
+                      percent);
+
+               if (bargraph) {
+
+                       printf(" |");
+
+                       if (percent > 100)
+                               percent = 100;
+
+                       for (j=0; j < NUMBAR; j++){
+                               if (j < percent/PERCENTRES)
+                                       printf("X");
+                               else
+                                       printf(".");
+                       }
            
-           printf("|");
-       }
+                       printf("|");
+               }
        
-       if (color)
-           printf("%s", ATTRESET);
+               if (color)
+                       printf("%s", ATTRESET);
 
-       printf("\n");
+               printf("\n");
 
-       stat[i].recv_frames = 0;
-       stat[i].recv_bits_total = 0;
-       stat[i].recv_bits_payload = 0;
-    }
+               stat[i].recv_frames = 0;
+               stat[i].recv_bits_total = 0;
+               stat[i].recv_bits_payload = 0;
+       }
 
-    printf("\n");
+       printf("\n");
+       fflush(stdout);
 
-    alarm(1);
+       alarm(1);
 }
 
 int main(int argc, char **argv)
 {
-    fd_set rdfs;
-    int s[MAXSOCK];
-
-    int opt;
-    char *ptr, *nptr;
-    struct sockaddr_can addr;
-    struct can_frame frame;
-    int nbytes, i;
-    struct ifreq ifr;
-    sigset_t sigmask, savesigmask;
-
-    signal(SIGTERM, sigterm);
-    signal(SIGHUP, sigterm);
-    signal(SIGINT, sigterm);
-
-    signal(SIGALRM, printstats);
-
-    prg = basename(argv[0]);
-
-    while ((opt = getopt(argc, argv, "rtbch?")) != -1) {
-       switch (opt) {
-       case 'r':
-           redraw = 1;
-           break;
-
-       case 't':
-           timestamp = 1;
-           break;
-
-       case 'b':
-           bargraph = 1;
-           break;
-
-       case 'c':
-           color = 1;
-           break;
-
-       default:
-           print_usage(prg);
-           exit(1);
-           break;
+       fd_set rdfs;
+       int s[MAXSOCK];
+
+       int opt;
+       char *ptr, *nptr;
+       struct sockaddr_can addr;
+       struct can_frame frame;
+       int nbytes, i;
+       struct ifreq ifr;
+       sigset_t sigmask, savesigmask;
+
+       signal(SIGTERM, sigterm);
+       signal(SIGHUP, sigterm);
+       signal(SIGINT, sigterm);
+
+       signal(SIGALRM, printstats);
+
+       prg = basename(argv[0]);
+
+       while ((opt = getopt(argc, argv, "rtbcieh?")) != -1) {
+               switch (opt) {
+               case 'r':
+                       redraw = 1;
+                       break;
+
+               case 't':
+                       timestamp = 1;
+                       break;
+
+               case 'b':
+                       bargraph = 1;
+                       break;
+
+               case 'c':
+                       color = 1;
+                       break;
+
+               case 'i':
+                       mode = CFL_NO_BITSTUFFING;
+                       break;
+
+               case 'e':
+                       mode = CFL_EXACT;
+                       break;
+
+               default:
+                       print_usage(prg);
+                       exit(1);
+                       break;
+               }
        }
-    }
 
-    if (optind == argc) {
-       print_usage(prg);
-       exit(0);
-    }
+       if (optind == argc) {
+               print_usage(prg);
+               exit(0);
+       }
        
-    currmax = argc - optind; /* find real number of CAN devices */
+       currmax = argc - optind; /* find real number of CAN devices */
 
-    if (currmax > MAXSOCK) {
-       printf("More than %d CAN devices given on commandline!\n", MAXSOCK);
-       return 1;
-    }
+       if (currmax > MAXSOCK) {
+               printf("More than %d CAN devices given on commandline!\n", MAXSOCK);
+               return 1;
+       }
 
-    for (i=0; i < currmax; i++) {
+       for (i=0; i < currmax; i++) {
 
-       ptr = argv[optind+i];
+               ptr = argv[optind+i];
 
-       nbytes = strlen(ptr);
-       if (nbytes >= IFNAMSIZ+sizeof("@1000000")+1) {
-           printf("name of CAN device '%s' is too long!\n", ptr);
-           return 1;
-       }
+               nbytes = strlen(ptr);
+               if (nbytes >= IFNAMSIZ+sizeof("@1000000")+1) {
+                       printf("name of CAN device '%s' is too long!\n", ptr);
+                       return 1;
+               }
 
 #ifdef DEBUG
-       printf("open %d '%s'.\n", i, ptr);
+               printf("open %d '%s'.\n", i, ptr);
 #endif
 
-       s[i] = socket(PF_CAN, SOCK_RAW, CAN_RAW);
-       if (s[i] < 0) {
-           perror("socket");
-           return 1;
-       }
+               s[i] = socket(PF_CAN, SOCK_RAW, CAN_RAW);
+               if (s[i] < 0) {
+                       perror("socket");
+                       return 1;
+               }
 
-       nptr = strchr(ptr, '@');
+               nptr = strchr(ptr, '@');
 
-       if (!nptr) {
-           print_usage(prg);
-           return 1;
-       }
+               if (!nptr) {
+                       print_usage(prg);
+                       return 1;
+               }
 
-       nbytes = nptr - ptr;  /* interface name is up the first '@' */
+               nbytes = nptr - ptr;  /* interface name is up the first '@' */
 
-       if (nbytes >= IFNAMSIZ) {
-           printf("name of CAN device '%s' is too long!\n", ptr);
-           return 1;
-       }
+               if (nbytes >= IFNAMSIZ) {
+                       printf("name of CAN device '%s' is too long!\n", ptr);
+                       return 1;
+               }
 
-       strncpy(stat[i].devname, ptr, nbytes);
-       memset(&ifr.ifr_name, 0, sizeof(ifr.ifr_name));
-       strncpy(ifr.ifr_name, ptr, nbytes);
+               strncpy(stat[i].devname, ptr, nbytes);
+               memset(&ifr.ifr_name, 0, sizeof(ifr.ifr_name));
+               strncpy(ifr.ifr_name, ptr, nbytes);
 
-       if (nbytes > max_devname_len)
-           max_devname_len = nbytes; /* for nice printing */
+               if (nbytes > max_devname_len)
+                       max_devname_len = nbytes; /* for nice printing */
 
-       stat[i].bitrate = atoi(nptr+1); /* bitrate is placed behind the '@' */
+               stat[i].bitrate = atoi(nptr+1); /* bitrate is placed behind the '@' */
 
-       if (!stat[i].bitrate || stat[i].bitrate > 1000000) {
-           printf("invalid bitrate for CAN device '%s'!\n", ptr);
-           return 1;
-       }
+               if (!stat[i].bitrate || stat[i].bitrate > 1000000) {
+                       printf("invalid bitrate for CAN device '%s'!\n", ptr);
+                       return 1;
+               }
 
-       nbytes = strlen(nptr+1);
-       if (nbytes > max_bitrate_len)
-           max_bitrate_len = nbytes; /* for nice printing */
+               nbytes = strlen(nptr+1);
+               if (nbytes > max_bitrate_len)
+                       max_bitrate_len = nbytes; /* for nice printing */
 
 
 #ifdef DEBUG
-       printf("using interface name '%s'.\n", ifr.ifr_name);
+               printf("using interface name '%s'.\n", ifr.ifr_name);
 #endif
 
-       if (ioctl(s[i], SIOCGIFINDEX, &ifr) < 0) {
-           perror("SIOCGIFINDEX");
-           exit(1);
-       }
+               if (ioctl(s[i], SIOCGIFINDEX, &ifr) < 0) {
+                       perror("SIOCGIFINDEX");
+                       exit(1);
+               }
 
-       addr.can_family = AF_CAN;
-       addr.can_ifindex = ifr.ifr_ifindex;
+               addr.can_family = AF_CAN;
+               addr.can_ifindex = ifr.ifr_ifindex;
 
-       if (bind(s[i], (struct sockaddr *)&addr, sizeof(addr)) < 0) {
-           perror("bind");
-           return 1;
+               if (bind(s[i], (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+                       perror("bind");
+                       return 1;
+               }
        }
-    }
 
-    alarm(1);
+       alarm(1);
 
-    if (redraw)
-       printf("%s", CLR_SCREEN);
+       if (redraw)
+               printf("%s", CLR_SCREEN);
 
-    while (1) {
+       while (1) {
 
-       FD_ZERO(&rdfs);
-       for (i=0; i<currmax; i++)
-           FD_SET(s[i], &rdfs);
+               FD_ZERO(&rdfs);
+               for (i=0; i<currmax; i++)
+                       FD_SET(s[i], &rdfs);
 
-       savesigmask = sigmask;
+               savesigmask = sigmask;
 
-       if (pselect(s[currmax-1]+1, &rdfs, NULL, NULL, NULL, &sigmask) < 0) {
-           //perror("pselect");
-           sigmask = savesigmask;
-           continue;
-       }
+               if (pselect(s[currmax-1]+1, &rdfs, NULL, NULL, NULL, &sigmask) < 0) {
+                       //perror("pselect");
+                       sigmask = savesigmask;
+                       continue;
+               }
 
-       for (i=0; i<currmax; i++) {  /* check all CAN RAW sockets */
+               for (i=0; i<currmax; i++) {  /* check all CAN RAW sockets */
 
-           if (FD_ISSET(s[i], &rdfs)) {
+                       if (FD_ISSET(s[i], &rdfs)) {
 
-               nbytes = read(s[i], &frame, sizeof(struct can_frame));
+                               nbytes = read(s[i], &frame, sizeof(struct can_frame));
 
-               if (nbytes < 0) {
-                   perror("read");
-                   return 1;
-               }
+                               if (nbytes < 0) {
+                                       perror("read");
+                                       return 1;
+                               }
 
-               if (nbytes < sizeof(struct can_frame)) {
-                   fprintf(stderr, "read: incomplete CAN frame\n");
-                   return 1;
-               }
+                               if (nbytes < sizeof(struct can_frame)) {
+                                       fprintf(stderr, "read: incomplete CAN frame\n");
+                                       return 1;
+                               }
 
-               stat[i].recv_frames++;
-               stat[i].recv_bits_payload += frame.can_dlc*8;
-               stat[i].recv_bits_total += frame.can_dlc*8;
-               if (frame.can_id & CAN_EFF_FLAG)
-                   stat[i].recv_bits_total += 67;
-               else
-                   stat[i].recv_bits_total += 47;
-           }
+                               stat[i].recv_frames++;
+                               stat[i].recv_bits_payload += frame.can_dlc*8;
+                               stat[i].recv_bits_total += can_frame_length((struct canfd_frame*)&frame,
+                                                                           mode, sizeof(frame));
+                       }
+               }
        }
-    }
 
-    for (i=0; i<currmax; i++)
-       close(s[i]);
+       for (i=0; i<currmax; i++)
+               close(s[i]);
 
-    return 0;
+       return 0;
 }