Graphical output distinguishes IPv4 and IPv6.
authorMats Erik Andersson <debian@gisladisker.se>
Thu, 30 Sep 2010 19:02:53 +0000 (21:02 +0200)
committerEmil Mikulic <emikulic@gmail.com>
Mon, 9 May 2011 13:16:56 +0000 (23:16 +1000)
Using a refined accounting and some extension of the javascript
and the traffic database, the graphical output presents IPv4 in
blue colour and IPv6 in green colour.

acct.c
daylog.c
graph_db.c
graph_db.h
static/graph.js
static/style.css

diff --git a/acct.c b/acct.c
index a00e86f..80b5479 100644 (file)
--- a/acct.c
+++ b/acct.c
@@ -128,14 +128,26 @@ acct_for(const pktsummary *sm)
          dir_in = 1;
    }
 
-   if (dir_out) {
+   if (dir_out && (sm->af == AF_INET
+                     || (sm->af == AF_INET6
+                           && IN6_IS_ADDR_V4MAPPED(&sm->dest_ip6)))) {
       daylog_acct((uint64_t)sm->len, GRAPH_OUT);
       graph_acct((uint64_t)sm->len, GRAPH_OUT);
    }
-   if (dir_in) {
+   else if (dir_in && (sm->af == AF_INET
+                        || (sm->af == AF_INET6
+                              && IN6_IS_ADDR_V4MAPPED(&sm->src_ip6)))) {
       daylog_acct((uint64_t)sm->len, GRAPH_IN);
       graph_acct((uint64_t)sm->len, GRAPH_IN);
    }
+   else if (dir_out && sm->af == AF_INET6) {
+      daylog_acct((uint64_t)sm->len, GRAPH_OUT6);
+      graph_acct((uint64_t)sm->len, GRAPH_OUT6);
+   }
+   else if (dir_in && sm->af == AF_INET6) {
+      daylog_acct((uint64_t)sm->len, GRAPH_IN6);
+      graph_acct((uint64_t)sm->len, GRAPH_IN6);
+   }
 
    if (sm->af == AF_INET6) return; /* Still no continuation for IPv6! */
 
index c9799b4..e6cb3ba 100644 (file)
--- a/daylog.c
+++ b/daylog.c
@@ -24,7 +24,7 @@
 
 static const char *daylog_fn = NULL;
 static time_t today_time, tomorrow_time;
-static uint64_t bytes_in, bytes_out, pkts_in, pkts_out;
+static uint64_t bytes_in, bytes_out, pkts_in, pkts_out, bytes_in6, bytes_out6;
 
 #define DAYLOG_DATE_LEN 26 /* strlen("1900-01-01 00:00:00 +1234") + 1 */
 static char datebuf[DAYLOG_DATE_LEN];
@@ -70,9 +70,9 @@ daylog_emit(void)
       struct str *buf = str_make();
       char *s;
       size_t len;
-      str_appendf(buf, "%s|%u|%qu|%qu|%qu|%qu\n",
+      str_appendf(buf, "%s|%u|%qu|%qu|%qu|%qu|%qu|%qu\n",
          fmt_date(today_time), (unsigned int)today_time,
-         bytes_in, bytes_out, pkts_in, pkts_out);
+         bytes_in, bytes_out, pkts_in, pkts_out, bytes_in6, bytes_out6);
       str_extract(buf, &len, &s);
 
       (void)write(fd, s, len); /* ignore write errors */
@@ -94,7 +94,7 @@ daylog_init(const char *filename)
    tomorrow_time = tomorrow(today_time);
    verbosef("today is %u, tomorrow is %u",
       (unsigned int)today_time, (unsigned int)tomorrow_time);
-   bytes_in = bytes_out = pkts_in = pkts_out = 0;
+   bytes_in = bytes_out = pkts_in = pkts_out = bytes_in6 = bytes_out6 = 0;
 
    fd = daylog_open();
    if (fd == -1)
@@ -144,7 +144,7 @@ daylog_acct(uint64_t amount, enum graph_dir dir)
 
       today_time = now;
       tomorrow_time = tomorrow(today_time);
-      bytes_in = bytes_out = pkts_in = pkts_out = 0;
+      bytes_in = bytes_out = pkts_in = pkts_out = bytes_in6 = bytes_out6 = 0;
       verbosef("rotated daylog, tomorrow = %u",
          (unsigned int)tomorrow_time);
    }
@@ -153,10 +153,16 @@ daylog_acct(uint64_t amount, enum graph_dir dir)
    if (dir == GRAPH_IN) {
       bytes_in += amount;
       pkts_in++;
-   } else {
-      assert(dir == GRAPH_OUT);
+   } else if (dir == GRAPH_OUT) {
       bytes_out += amount;
       pkts_out++;
+   } else if (dir == GRAPH_IN6) {
+      bytes_in6 += amount;
+      pkts_in++;
+   } else {
+      assert(dir == GRAPH_OUT6);
+      bytes_out6 += amount;
+      pkts_out++;
    }
 }
 
index 580f8ba..c1788f4 100644 (file)
@@ -31,7 +31,7 @@
 extern const char *interface;
 
 struct graph {
-   uint64_t *in, *out;
+   uint64_t *in, *out, *in6, *out6;
    unsigned int offset; /* i.e. seconds start at 0, days start at 1 */
    unsigned int pos, num_bars;
    const char *unit;
@@ -39,10 +39,10 @@ struct graph {
 };
 
 static struct graph
-   graph_secs = {NULL, NULL, 0, 0, 60, "seconds", 1},
-   graph_mins = {NULL, NULL, 0, 0, 60, "minutes", 60},
-   graph_hrs  = {NULL, NULL, 0, 0, 24, "hours",   3600},
-   graph_days = {NULL, NULL, 1, 0, 31, "days",    86400};
+   graph_secs = {NULL, NULL, NULL, NULL, 0, 0, 60, "seconds", 1},
+   graph_mins = {NULL, NULL, NULL, NULL, 0, 0, 60, "minutes", 60},
+   graph_hrs  = {NULL, NULL, NULL, NULL, 0, 0, 24, "hours",   3600},
+   graph_days = {NULL, NULL, NULL, NULL, 1, 0, 31, "days",    86400};
 
 static struct graph *graph_db[] = {
    &graph_secs, &graph_mins, &graph_hrs, &graph_days
@@ -59,6 +59,8 @@ graph_init(void)
    for (i=0; i<graph_db_size; i++) {
       graph_db[i]->in  = xmalloc(sizeof(uint64_t) * graph_db[i]->num_bars);
       graph_db[i]->out = xmalloc(sizeof(uint64_t) * graph_db[i]->num_bars);
+      graph_db[i]->in6  = xmalloc(sizeof(uint64_t) * graph_db[i]->num_bars);
+      graph_db[i]->out6 = xmalloc(sizeof(uint64_t) * graph_db[i]->num_bars);
    }
    start_time = time(NULL);
    graph_reset();
@@ -69,6 +71,8 @@ zero_graph(struct graph *g)
 {
    memset(g->in,  0, sizeof(uint64_t) * g->num_bars);
    memset(g->out, 0, sizeof(uint64_t) * g->num_bars);
+   memset(g->in6,  0, sizeof(uint64_t) * g->num_bars);
+   memset(g->out6, 0, sizeof(uint64_t) * g->num_bars);
 }
 
 void
@@ -87,6 +91,8 @@ graph_free(void)
    for (i=0; i<graph_db_size; i++) {
       free(graph_db[i]->in);
       free(graph_db[i]->out);
+      free(graph_db[i]->in6);
+      free(graph_db[i]->out6);
    }
 }
 
@@ -98,6 +104,8 @@ graph_acct(uint64_t amount, enum graph_dir dir)
     switch (dir) {
      case GRAPH_IN:  graph_db[i]->in[  graph_db[i]->pos ] += amount; break;
      case GRAPH_OUT: graph_db[i]->out[ graph_db[i]->pos ] += amount; break;
+     case GRAPH_IN6:  graph_db[i]->in6[  graph_db[i]->pos ] += amount; break;
+     case GRAPH_OUT6: graph_db[i]->out6[ graph_db[i]->pos ] += amount; break;
      default: errx(1, "unknown graph_dir in graph_acct: %d", dir);
     }
 }
@@ -111,6 +119,7 @@ advance(struct graph *g, const unsigned int pos)
    do {
       g->pos = (g->pos + 1) % g->num_bars;
       g->in[g->pos] = g->out[g->pos] = 0;
+      g->in6[g->pos] = g->out6[g->pos] = 0;
    } while (g->pos != pos);
 }
 
@@ -138,6 +147,14 @@ rotate(struct graph *g, const unsigned int pos)
       tmp[ (i+ofs) % g->num_bars ] = g->out[i];
    memcpy(g->out, tmp, size);
 
+   for (i=0; i<g->num_bars; i++)
+      tmp[ (i+ofs) % g->num_bars ] = g->in6[i];
+   memcpy(g->in6, tmp, size);
+
+   for (i=0; i<g->num_bars; i++)
+      tmp[ (i+ofs) % g->num_bars ] = g->out6[i];
+   memcpy(g->out6, tmp, size);
+
    free(tmp);
    assert(pos == ( (g->pos + ofs) % g->num_bars ));
    g->pos = pos;
@@ -274,6 +291,8 @@ graph_import(const int fd)
       for (j=0; j<num_bars; j++) {
          if (!read64(fd, &(graph_db[i]->in[j]))) return 0;
          if (!read64(fd, &(graph_db[i]->out[j]))) return 0;
+         if (!read64(fd, &(graph_db[i]->in6[j]))) return 0;
+         if (!read64(fd, &(graph_db[i]->out6[j]))) return 0;
       }
    }
 
@@ -297,6 +316,8 @@ graph_export(const int fd)
       for (j=0; j<graph_db[i]->num_bars; j++) {
          if (!write64(fd, graph_db[i]->in[j])) return 0;
          if (!write64(fd, graph_db[i]->out[j])) return 0;
+         if (!write64(fd, graph_db[i]->in6[j])) return 0;
+         if (!write64(fd, graph_db[i]->out6[j])) return 0;
       }
    }
    return 1;
@@ -403,8 +424,8 @@ xml_graphs(void)
       do {
          j = (j + 1) % g->num_bars;
          /* <element pos="" in="" out=""/> */
-         str_appendf(buf, "<e p=\"%u\" i=\"%qu\" o=\"%qu\"/>\n",
-            g->offset + j, g->in[j], g->out[j]);
+         str_appendf(buf, "<e p=\"%u\" i=\"%qu\" o=\"%qu\" i6=\"%qu\" o6=\"%qu\"/>\n",
+            g->offset + j, g->in[j], g->out[j], g->in6[j], g->out6[j]);
       } while (j != g->pos);
       str_appendf(buf, "</%s>\n", g->unit);
    }
index 0315680..2940ff7 100644 (file)
@@ -10,7 +10,9 @@ enum graph_dir {
    MIN_GRAPH_DIR = 1,
    GRAPH_IN = 1,
    GRAPH_OUT = 2,
-   MAX_GRAPH_DIR = 2
+   GRAPH_IN6 = 3,
+   GRAPH_OUT6 = 4,
+   MAX_GRAPH_DIR = 4
 };
 
 void graph_init(void);
index 6a90bdc..a7c748d 100644 (file)
@@ -183,11 +183,13 @@ function buildGraph(graph, title, bar_secs, elems) {
    var b_pos = Number( elem.getAttribute("p") );
    var b_in = Number( elem.getAttribute("i") );
    var b_out = Number( elem.getAttribute("o") );
-   var b_total = b_in + b_out;
+   var b_in6 = Number( elem.getAttribute("i6") );
+   var b_out6 = Number( elem.getAttribute("o6") );
+   var b_total = b_in + b_out + b_in6 + b_out6;
 /* FIXME: what happens when a bar's value is >4G? */
    if (b_total > total_max)
     total_max = b_total;
-   data.push( [b_pos, b_in, b_out] );
+   data.push( [b_pos, b_in, b_out, b_in6, b_out6] );
  }
 
  var igraph = makeElemClass("div", "graph"); // inner graph
@@ -204,10 +206,16 @@ function buildGraph(graph, title, bar_secs, elems) {
      max_i = 0, max_o = 0,
      tot_i = 0, tot_o = 0;
 
+ var min_i6 = 0, min_o6 = 0,
+     max_i6 = 0, max_o6 = 0,
+     tot_i6 = 0, tot_o6 = 0;
+
  for (var i=0; i<nbars; i++) {
   var b_p = data[i][0];
   var b_i = data[i][1];
   var b_o = data[i][2];
+  var b_i6 = data[i][3];
+  var b_o6 = data[i][4];
 
   if (b_i>0) { if (min_i == 0) min_i = b_i; else min_i = min(min_i, b_i); }
   max_i = max(max_i, b_i);
@@ -217,6 +225,14 @@ function buildGraph(graph, title, bar_secs, elems) {
   max_o = max(max_o, b_o);
   tot_o += b_o;
 
+  if (b_i6>0) { if (min_i6 == 0) min_i6 = b_i6; else min_i6 = min(min_i6, b_i6); }
+  max_i6 = max(max_i6, b_i6);
+  tot_i6 += b_i6;
+
+  if (b_o6>0) { if (min_o6 == 0) min_o6 = b_o6; else min_o6 = min(min_o6, b_o6); }
+  max_o6 = max(max_o6, b_o6);
+  tot_o6 += b_o6;
+
   var xofs = next_xofs;
 
   next_xofs = Math.round((b_width + bar_gap) * (i+1));
@@ -224,15 +240,19 @@ function buildGraph(graph, title, bar_secs, elems) {
 
   var h_i = Math.round( b_i * graph_height / total_max );
   var h_o = Math.round( b_o * graph_height / total_max );
+  var h_i6 = Math.round( b_i6 * graph_height / total_max );
+  var h_o6 = Math.round( b_o6 * graph_height / total_max );
 
   var label = b_p+": "+
-   thousands(b_i)+" bytes in, "+
-   thousands(b_o)+" bytes out | "+
-   kbps(b_i/bar_secs)+" KB/s in, "+
-   kbps(b_o/bar_secs)+" KB/s out";
+   thousands(b_i + b_i6)+" bytes in, "+
+   thousands(b_o + b_o6)+" bytes out | "+
+   kbps((b_i + b_i6)/bar_secs)+" KB/s in, "+
+   kbps((b_o + b_o6)/bar_secs)+" KB/s out";
 
   addBar(igraph, label, "bar_in", curr_w, h_i, xofs, 0);
   addBar(igraph, label, "bar_out", curr_w, h_o, xofs, h_i);
+  addBar(igraph, label, "bar_in6", curr_w, h_i6, xofs, h_i + h_o);
+  addBar(igraph, label, "bar_out6", curr_w, h_o6, xofs, h_i + h_o + h_i6);
  }
 
  function legendRow(dir_str, minb, avgb, maxb) {
@@ -260,11 +280,15 @@ function buildGraph(graph, title, bar_secs, elems) {
 
  var glegend = makeElemClass("div", "legend");
  var avg_i = tot_i / nbars,
-     avg_o = tot_o / nbars;
+     avg_o = tot_o / nbars,
+     avg_i6 = tot_i6 / nbars,
+     avg_o6 = tot_o6 / nbars;
  var tbl = document.createElement("table");
  var tb = document.createElement("tbody"); /* for MSIE */
  tb.appendChild( legendRow("in", min_i, avg_i, max_i) );
  tb.appendChild( legendRow("out", min_o, avg_o, max_o) );
+ tb.appendChild( legendRow("in6", min_i6, avg_i6, max_i6) );
+ tb.appendChild( legendRow("out6", min_o6, avg_o6, max_o6) );
  tbl.appendChild(tb);
  glegend.appendChild(tbl);
  setStyle(glegend, "width:"+graph_width+"px;");
index 691adb2..e55f3d8 100644 (file)
@@ -51,6 +51,8 @@ div.graph      { border: 1px solid black; }
 div.graphtitle { text-align:center; font-weight:bold; }
 div.bar_in     { background: #678; }
 div.bar_out    { background: #abc; }
+div.bar_in6    { background: #672; }
+div.bar_out6   { background: #ab4; }
 
 #graph_reload,#graph_autoreload { border:1px solid black;
  padding:2px 10px 2px 10px; margin-left:5px; color:black; }