#include <u.h>
#include <libc.h>
#include <thread.h>
#include <bio.h>
#include "collectd.h"
#define MAXETHER 8
typedef struct Ether Ether;
struct Ether {
char* name;
uvlong n;
};
static Biobuf *
readether(Biobuf *bp, char *file, Ether *ether)
{
char *p, *q;
if(bp == nil){
bp = Bopen(file, OREAD);
if(bp == nil)
sysfatal("couldn't open %s: %r", file);
}
p = Brdline(bp, '\n');
if(p == nil){
Bterm(bp);
return nil;
}
p[Blinelen(bp)-1] = '\0';
if(q = strchr(p, ':'))
*q++ = '\0';
else
sysfatal("unexpected stats output");
ether->name = p;
ether->n = strtoull(q, nil, 0);
return bp;
}
static void
submit(Channel *c, char *name, char *type, uvlong rx, uvlong tx)
{
Packet *pp;
pp = palloc();
pp->host = estrdup(hostname);
pp->interval = interval;
pp->time = time(nil);
pp->plugin = estrdup("interface");
pp->pinst = estrdup(name);
pp->type = estrdup(type);
addcounter(pp, rx);
addcounter(pp, tx);
if(nbsendp(c, pp) < 1)
pfree(pp);
}
void
interfaceproc(void *arg)
{
Channel *c;
int i;
char name[NAMELEN];
char file[NAMELEN];
Biobuf *bp;
Ether ether;
uvlong in, out;
uvlong ierrs, oerrs;
c = arg;
bp = nil;
for(;;){
snooze();
for(i = 0; i < MAXETHER; ++i){
snprint(name, sizeof name, "ether%d", i);
snprint(file, sizeof file, "/net/%s/stats", name);
/*
* Interfaces may be specified using
* non-contiguous numbers; rather than bail,
* we skip stats files we cannot read.
*/
if(access(file, AREAD) != 0)
continue;
ierrs = 0;
oerrs = 0;
while(bp = readether(bp, file, ðer)){
if(strcmp(ether.name, "in") == 0)
in = ether.n;
else if(strcmp(ether.name, "out") == 0)
out = ether.n;
else if(strcmp(ether.name, "crc errs") == 0 ||
strcmp(ether.name, "overflows") == 0 ||
strcmp(ether.name, "soft overflows") == 0 ||
strcmp(ether.name, "framing errs") == 0 ||
strcmp(ether.name, "buffer errs") == 0)
ierrs += ether.n;
else if(strcmp(ether.name, "output errs") == 0)
oerrs += ether.n;
}
submit(c, name, "if_packets", in, out);
submit(c, name, "if_errors", ierrs, oerrs);
}
}
}
|