[re-resend]

[taking this to ntop-dev as there's actual code involved now...]

> -----Original Message-----
> From: Burton M. Strauss III [mailto:[EMAIL PROTECTED]
> Sent: Saturday, January 24, 2004 1:01 AM
> To: [EMAIL PROTECTED]
> Subject: RE: [Ntop] Per host/subdomain RRD stats?
> 
> 
> You probably could do it, but it would be a bit of work.
>
> Assuming the same definition of 'domain' as the rest of ntop 
> - strip the
> left most qualifier, then what you need to do is basically rip out the
> report routine and clone it into rrdPlugin.c

That was indeed my approach also.

> (remember, with 
> rrds you can do
> only one update per time interval, so you have to accumulate 
> and update, not
> update update update...)

You mean accumulate all hosts per domain, and then do UpdateCounter right?
My graphs indeed do look kinda edgy.

Anyway, I created a patch to add domain RRD's. Its modifies 2 files:
- report.c to add an RRD icon and link in the "Statistics for hosts in
Domain %s" page
- rrdPlugin.c to add the RRD code to dump domain data

Almost everything seems to work, RRDs are created and data is written to the
RRDs. Only there's one problem. After the rrdplugin has run on its regular
interval, the Domain Stats at the IP Summary->Domain page are reset!
I'm not sure what is causing this problem, but something (fillDomainName?)
must be modifying data that is depended upon by printDomainStats.

I attached my code and I hope someone can shed any light on this matter.

Thanks,
-- Robbert

--- report.c.orig       2004-01-26 22:29:42.000000000 +0100
+++ report.c    2004-01-28 10:59:57.000000000 +0100
@@ -4315,6 +4315,28 @@
     if(numEntries >= maxHosts) break;
   } /* for(;;) */
 
+#ifndef EMBEDDED
+  /* RRDs for domains */
+  if (domainName != NULL) {
+    struct stat statbufDomain;
+
+    /* Do NOT add a '/' at the end of the path because Win32 will complain
about it */
+    snprintf(buf, sizeof(buf), "%s/interfaces/%s/domains/%s", 
+          myGlobals.rrdPath != NULL ? myGlobals.rrdPath : ".",
+
myGlobals.device[myGlobals.actualReportDeviceId].humanFriendlyName,domainNam
e);
+  
+    if((i = stat(buf, &statbufDomain)) == 0) {
+      if(snprintf(buf, sizeof(buf), "<CENTER>"
+               "[ <A
HREF=\"/plugins/rrdPlugin?action=list&key=interfaces/%s/domains/%s&title=Dom
ain%%20%s\">"
+               "<IMG BORDER=0 SRC=/graph.gif></A> ]</CENTER>\n",
+
myGlobals.device[myGlobals.actualReportDeviceId].humanFriendlyName,
+               domainName,domainName) < 0)
+        BufferTooShort();
+      sendString(buf);
+    }
+  }
+#endif
+
   if(numEntries == 0) {
     printNoDataYet();
     free(tmpStats); free(stats); 


--- plugins/rrdPlugin.c.orig    2004-01-19 15:25:32.000000000 +0100
+++ plugins/rrdPlugin.c 2004-01-20 23:18:13.000000000 +0100
@@ -78,7 +78,7 @@
 pthread_t rrdThread;
 #endif
 
-static u_short dumpFlows, dumpHosts, dumpInterfaces, dumpMatrix,
shownCreate=0;
+static u_short dumpDomains, dumpFlows, dumpHosts, dumpInterfaces,
dumpMatrix, shownCreate=0;
 #ifndef WIN32
 static u_short dumpPermissions;
 #endif
@@ -905,6 +905,13 @@
     dumpMonths = atoi(value);
   }
 
+  if(fetchPrefsValue("rrd.dataDumpDomains", value, sizeof(value)) == -1) {
+    storePrefsValue("rrd.dataDumpDomains", "0");
+    dumpDomains = 0;
+  } else {
+    dumpDomains = atoi(value);
+  }
+
   if(fetchPrefsValue("rrd.dataDumpFlows", value, sizeof(value)) == -1) {
     storePrefsValue("rrd.dataDumpFlows", "0");
     dumpFlows = 0;
@@ -986,6 +993,7 @@
   traceEvent(CONST_TRACE_INFO, "RRD_DEBUG:     dumpHours %d hours by %d
seconds", dumpHours, dumpInterval);
   traceEvent(CONST_TRACE_INFO, "RRD_DEBUG:     dumpDays %d days by hour",
dumpDays);
   traceEvent(CONST_TRACE_INFO, "RRD_DEBUG:     dumpMonths %d months by
day", dumpMonths);
+  traceEvent(CONST_TRACE_INFO, "RRD_DEBUG:     dumpDomains %s", dumpDomains
== 0 ? "no" : "yes");
   traceEvent(CONST_TRACE_INFO, "RRD_DEBUG:     dumpFlows %s", dumpFlows ==
0 ? "no" : "yes");
   traceEvent(CONST_TRACE_INFO, "RRD_DEBUG:     dumpHosts %s", dumpHosts ==
0 ? "no" : "yes");
   traceEvent(CONST_TRACE_INFO, "RRD_DEBUG:     dumpInterfaces %s",
dumpInterfaces == 0 ? "no" : "yes");
@@ -1010,7 +1018,7 @@
   char buf[1024], *strtokState, *mainState, *urlPiece,
     rrdKey[64], rrdName[64], rrdTitle[64], startTime[32], endTime[32],
rrdPrefix[32];
   u_char action = FLAG_RRD_ACTION_NONE;
-  int _dumpFlows, _dumpHosts, _dumpInterfaces, _dumpMatrix, _dumpDetail,
_dumpInterval, _dumpHours, _dumpDays, _dumpMonths;
+  int _dumpDomains, _dumpFlows, _dumpHosts, _dumpInterfaces, _dumpMatrix,
_dumpDetail, _dumpInterval, _dumpHours, _dumpDays, _dumpMonths;
   char * _hostsFilter;
 #ifndef WIN32
   int _dumpPermissions;
@@ -1020,6 +1028,7 @@
     commonRRDinit();
 
   /* Initial values - remember, for checkboxes these need to be OFF
(there's no html UNCHECKED option) */
+  _dumpDomains=0;
   _dumpFlows=0;
   _dumpHosts=0;
   _dumpInterfaces=0;
@@ -1122,6 +1131,8 @@
          myGlobals.rrdPath  = (char*)malloc(vlen);
          unescape(myGlobals.rrdPath, vlen, value);
          storePrefsValue("rrd.rrdPath", myGlobals.rrdPath);
+       } else if(strcmp(key, "dumpDomains") == 0) {
+         _dumpDomains = 1;
        } else if(strcmp(key, "dumpFlows") == 0) {
          _dumpFlows = 1;
        } else if(strcmp(key, "dumpDetail") == 0) {
@@ -1155,6 +1166,7 @@
       dumpDays = _dumpDays;
       dumpMonths = _dumpMonths;
       /* traceEvent(CONST_TRACE_INFO, "RRD: dumpFlows=%d", dumpFlows); */
+      dumpDomains=_dumpDomains;
       dumpFlows=_dumpFlows;
       dumpHosts=_dumpHosts;
       dumpInterfaces=_dumpInterfaces;
@@ -1168,6 +1180,7 @@
       snprintf(buf, sizeof(buf), "%d", dumpHours);
storePrefsValue("rrd.dataDumpHours", buf);
       snprintf(buf, sizeof(buf), "%d", dumpDays);
storePrefsValue("rrd.dataDumpDays", buf);
       snprintf(buf, sizeof(buf), "%d", dumpMonths);
storePrefsValue("rrd.dataDumpMonths", buf);
+      snprintf(buf, sizeof(buf), "%d", dumpDomains);
storePrefsValue("rrd.dataDumpDomains", buf);
       snprintf(buf, sizeof(buf), "%d", dumpFlows);
storePrefsValue("rrd.dataDumpFlows", buf);
       snprintf(buf, sizeof(buf), "%d", dumpHosts);
storePrefsValue("rrd.dataDumpHosts", buf);
       snprintf(buf, sizeof(buf), "%d", dumpInterfaces);
storePrefsValue("rrd.dataDumpInterfaces", buf);
@@ -1247,6 +1260,11 @@
 
   sendString("<TR><TH ALIGN=LEFT "DARK_BG">Data to Dump</TH><TD>");
 
+  if(snprintf(buf, sizeof(buf), "<INPUT TYPE=checkbox NAME=dumpDomains
VALUE=1 %s> Domains<br>\n",
+             dumpDomains ? "CHECKED" : "" ) < 0)
+    BufferTooShort();
+  sendString(buf);
+
   if(snprintf(buf, sizeof(buf), "<INPUT TYPE=checkbox NAME=dumpFlows
VALUE=1 %s> Flows<br>\n",
              dumpFlows ? "CHECKED" : "" ) < 0)
     BufferTooShort();
@@ -1549,6 +1567,123 @@
 
     /* ****************************************************** */
 
+    DomainStats **stats, *tmpStats, *statsEntry;
+    u_int maxHosts, len = 0;
+    Counter totBytesSent = 0;
+    Counter totBytesRcvd = 0;
+
+    if(dumpDomains) {
+      for(devIdx=0; devIdx<myGlobals.numDevices; devIdx++) {
+
+       // save this as it may change
+       maxHosts = myGlobals.device[devIdx].hostsno;
+       len = sizeof(DomainStats)*maxHosts;
+       tmpStats = (DomainStats*)malloc(len);
+       memset(tmpStats, 0, len);
+
+       len = sizeof(DomainStats**)*maxHosts;
+       stats = (DomainStats**)malloc(len);
+       memset(stats, 0, len);
+
+        HostTraffic *el;
+       u_int numEntries = 0;
+
+       // walk through all hosts, getting their domain names and counting
stats
+       for (el = getFirstHost(devIdx);
+         el != NULL; el = getNextHost(devIdx, el)) {
+
+           fillDomainName(el);
+
+           // if we didn't get a domain name, bail out
+           if ((el->fullDomainName == NULL)
+              || (el->fullDomainName[0] == '\0')
+              || (el->dotDomainName == NULL)
+              || (el->hostSymIpAddress[0] == '\0')
+              || broadcastHost(el)
+              ) {
+             continue;
+           }
+
+            u_short keyValue=0;
+
+           for(keyValue=0, idx=0; el->fullDomainName[idx] != '\0'; idx++)
+             keyValue += (idx+1)*(u_short)el->fullDomainName[idx];
+
+           keyValue %= maxHosts;
+
+           while((stats[keyValue] != NULL)
+             && (strcasecmp(stats[keyValue]->domainHost->fullDomainName,
+             el->fullDomainName) != 0))
+               keyValue = (keyValue+1) %
myGlobals.device[devIdx].actualHashSize;
+
+           // if we just start counting for this domain...
+           if(stats[keyValue] != NULL)
+             statsEntry = stats[keyValue];
+           else {
+             statsEntry = &tmpStats[numEntries++];
+             memset(statsEntry, 0, sizeof(DomainStats));
+             statsEntry->domainHost = el;
+             stats[keyValue] = statsEntry;
+#if RRD_DEBUG >= 2
+             traceEvent(CONST_TRACE_INFO, "RRD_DEBUG [%d] %s/%s",
numEntries, el->fullDomainName, el->dotDomainName);
+#endif
+           }
+
+           // count this host's stats in the domain stats
+           totBytesSent += el->bytesSent.value;
+           statsEntry->bytesSent.value += el->bytesSent.value;
+           statsEntry->bytesRcvd.value += el->bytesRcvd.value;
+           totBytesRcvd          += el->bytesRcvd.value;
+           statsEntry->tcpSent.value   += el->tcpSentLoc.value +
el->tcpSentRem.value;
+           statsEntry->udpSent.value   += el->udpSentLoc.value +
el->udpSentRem.value;
+           statsEntry->icmpSent.value  += el->icmpSent.value;
+           statsEntry->icmp6Sent.value  += el->icmp6Sent.value;
+           statsEntry->tcpRcvd.value   += el->tcpRcvdLoc.value +
el->tcpRcvdFromRem.value;
+           statsEntry->udpRcvd.value   += el->udpRcvdLoc.value +
el->udpRcvdFromRem.value;
+           statsEntry->icmpRcvd.value  += el->icmpRcvd.value;
+           statsEntry->icmp6Rcvd.value  += el->icmp6Rcvd.value;
+
+           if(numEntries >= maxHosts) break;
+       }
+
+       // if we didn't find a single domain, continue with the next
interface
+       if (numEntries == 0) {
+           free(tmpStats); free(stats);
+           continue;
+       }
+
+       // insert all domain data for this interface into the RRDs
+       for (idx=0; idx < numEntries; idx++) {
+           statsEntry = &tmpStats[idx];
+
+           snprintf(rrdPath, sizeof(rrdPath),
"%s/interfaces/%s/domains/%s/",
+               myGlobals.rrdPath,
myGlobals.device[devIdx].humanFriendlyName,
+               statsEntry->domainHost->fullDomainName);
+           mkdir_p(rrdPath);
+
+#if RRD_DEBUG >= 2
+           traceEvent(CONST_TRACE_INFO, "RRD: Updating %s", rrdPath);
+#endif
+           updateCounter(rrdPath, "bytesSent",
statsEntry->bytesSent.value);
+           updateCounter(rrdPath, "bytesRcvd",
statsEntry->bytesRcvd.value);
+
+           updateCounter(rrdPath, "tcpSent", statsEntry->tcpSent.value);
+           updateCounter(rrdPath, "udpSent", statsEntry->udpSent.value);
+           updateCounter(rrdPath, "icmpSent", statsEntry->icmpSent.value);
+           updateCounter(rrdPath, "icmp6Sent",
statsEntry->icmp6Sent.value);
+
+           updateCounter(rrdPath, "tcpRcvd", statsEntry->tcpRcvd.value);
+           updateCounter(rrdPath, "udpRcvd", statsEntry->udpRcvd.value);
+           updateCounter(rrdPath, "icmpRcvd", statsEntry->icmpRcvd.value);
+           updateCounter(rrdPath, "icmp6Rcvd",
statsEntry->icmp6Rcvd.value);
+       }
+
+       free(tmpStats); free(stats);
+      }
+    }
+
+    /* ****************************************************** */
+
     if(dumpHosts) {
       for(devIdx=0; devIdx<myGlobals.numDevices; devIdx++) {
        for(i=1; i<myGlobals.device[devIdx].actualHashSize; i++) { 


_______________________________________________
Ntop-dev mailing list
[EMAIL PROTECTED]
http://listgateway.unipi.it/mailman/listinfo/ntop-dev

Reply via email to