int kerneltest(void) { int i=0, bmax, bmin, btemp; bmax=bmin=getbtime(); printf("This test will take about 60 seconds.\n"); printf("[ ]"); for (i=0; i<=30; i++) { printf("\b"); } fflush(stdout); for (i=0;i<30;i++) { sleep(2); fflush(stdout); btemp=getbtime(); if (btemp > bmax) { bmax = btemp; } if (btemp < bmin) { bmin = btemp; } printf("="); fflush(stdout); } printf("] done.\n\n"); printf("Detected boot time variation during test: %2d\n", bmax-bmin); printf("Maximum boot time variation set in config: %2d\n\n", cfg.bvar); if ((bmax-bmin)>20) { printf("The current kernel has a broken boot time information and\n"); printf("vnStat is likely not to work correctly. Upgrading the kernel\n"); printf("is likely to solve this problem.\n\n"); return 1; } else if ((bmax-bmin)>cfg.bvar) { printf("The current kernel has a boot time variation greater than assumed\n"); printf("in the vnStat config. That it likely to cause errors in results.\n"); printf("Set \"BootVariation\" to something greater than \"%d\" and run this\n", (bmax-bmin)); printf("test again.\n\n"); return 1; } else if ((bmax-bmin)==0) { printf("The current kernel doesn't seem to suffer from boot time variation problems.\n"); printf("Everything is ok.\n\n"); return 0; } else { printf("The current kernel is ok.\n\n"); return 0; } }
END_TEST START_TEST(parseifinfo_1kb_change) { initdb(); data.btime = getbtime(); data.lastupdated -= 100; data.currx = 1024; data.curtx = 1024; strcpy(data.interface, "eth0"); ck_assert_int_eq(ibwadd("eth0", 10), 1); strcpy(ifinfo.name, "eth0"); ifinfo.filled = 1; ifinfo.rx = 2048; ifinfo.tx = 2048; ifinfo.rxp = ifinfo.txp = 0; parseifinfo(0); ck_assert_int_eq(ifinfo.rx, 2048); ck_assert_int_eq(ifinfo.tx, 2048); ck_assert_int_eq(ifinfo.rxp, 0); ck_assert_int_eq(ifinfo.txp, 0); ck_assert_int_eq(data.day[0].rx, 0); ck_assert_int_eq(data.day[0].tx, 0); ck_assert_int_eq(data.day[0].rxk, 1); ck_assert_int_eq(data.day[0].txk, 1); ck_assert_int_eq(data.month[0].rx, 0); ck_assert_int_eq(data.month[0].tx, 0); ck_assert_int_eq(data.month[0].rxk, 1); ck_assert_int_eq(data.month[0].txk, 1); ck_assert_int_eq(data.totalrx, 0); ck_assert_int_eq(data.totaltx, 0); ck_assert_int_eq(data.totalrxk, 1); ck_assert_int_eq(data.totaltxk, 1); ck_assert_int_eq(data.currx, 2048); ck_assert_int_eq(data.curtx, 2048); }
END_TEST START_TEST(parseifinfo_hitting_maxbw_limit_causes_sync) { initdb(); data.btime = getbtime(); data.lastupdated -= 1; data.currx = 1024; data.curtx = 1024; strcpy(data.interface, "eth0"); ck_assert_int_eq(ibwadd("eth0", 10), 1); strcpy(ifinfo.name, "eth0"); ifinfo.filled = 1; ifinfo.rx = 123456789; ifinfo.tx = 123456789; ifinfo.rxp = ifinfo.txp = 0; debug = 1; suppress_output(); parseifinfo(0); ck_assert_int_eq(ifinfo.rx, 123456789); ck_assert_int_eq(ifinfo.tx, 123456789); ck_assert_int_eq(ifinfo.rxp, 0); ck_assert_int_eq(ifinfo.txp, 0); ck_assert_int_eq(data.day[0].rx, 0); ck_assert_int_eq(data.day[0].tx, 0); ck_assert_int_eq(data.day[0].rxk, 0); ck_assert_int_eq(data.day[0].txk, 0); ck_assert_int_eq(data.totalrx, 0); ck_assert_int_eq(data.totaltx, 0); ck_assert_int_eq(data.totalrxk, 0); ck_assert_int_eq(data.totaltxk, 0); ck_assert_int_eq(data.currx, 123456789); ck_assert_int_eq(data.curtx, 123456789); }
END_TEST START_TEST(parseifinfo_long_update_interval_causes_sync) { initdb(); data.btime = getbtime(); data.lastupdated -= (60*MAXUPDATEINTERVAL + 10); strcpy(data.interface, "eth0"); ck_assert_int_eq(ibwadd("eth0", 10), 1); strcpy(ifinfo.name, "eth0"); ifinfo.filled = 1; ifinfo.rx = 1024; ifinfo.tx = 1024; ifinfo.rxp = ifinfo.txp = 0; parseifinfo(0); ck_assert_int_eq(ifinfo.rx, 1024); ck_assert_int_eq(ifinfo.tx, 1024); ck_assert_int_eq(ifinfo.rxp, 0); ck_assert_int_eq(ifinfo.txp, 0); ck_assert_int_eq(data.day[0].rx, 0); ck_assert_int_eq(data.day[0].tx, 0); ck_assert_int_eq(data.day[0].rxk, 0); ck_assert_int_eq(data.day[0].txk, 0); ck_assert_int_eq(data.totalrx, 0); ck_assert_int_eq(data.totaltx, 0); ck_assert_int_eq(data.totalrxk, 0); ck_assert_int_eq(data.totaltxk, 0); ck_assert_int_eq(data.currx, 1024); ck_assert_int_eq(data.curtx, 1024); }
END_TEST START_TEST(parseifinfo_multiple_parses) { initdb(); data.btime = getbtime(); data.lastupdated -= 20; data.currx = 0; data.curtx = 0; strcpy(data.interface, "eth0"); ck_assert_int_eq(ibwadd("eth0", 10), 1); strcpy(ifinfo.name, "eth0"); ifinfo.filled = 1; ifinfo.rx = 2049; ifinfo.tx = 2049; ifinfo.rxp = ifinfo.txp = 0; parseifinfo(0); ck_assert_int_eq(ifinfo.rx, 2049); ck_assert_int_eq(ifinfo.tx, 2049); ck_assert_int_eq(ifinfo.rxp, 1); ck_assert_int_eq(ifinfo.txp, 1); ck_assert_int_eq(data.day[0].rx, 0); ck_assert_int_eq(data.day[0].tx, 0); ck_assert_int_eq(data.day[0].rxk, 2); ck_assert_int_eq(data.day[0].txk, 2); ck_assert_int_eq(data.totalrx, 0); ck_assert_int_eq(data.totaltx, 0); ck_assert_int_eq(data.totalrxk, 2); ck_assert_int_eq(data.totaltxk, 2); ck_assert_int_eq(data.currx, 2048); ck_assert_int_eq(data.curtx, 2048); data.lastupdated -= 15; ifinfo.rx = 4098; ifinfo.tx = 4098; ifinfo.rxp = ifinfo.txp = 0; parseifinfo(0); ck_assert_int_eq(ifinfo.rx, 4098); ck_assert_int_eq(ifinfo.tx, 4098); ck_assert_int_eq(ifinfo.rxp, 2); ck_assert_int_eq(ifinfo.txp, 2); ck_assert_int_eq(data.day[0].rx, 0); ck_assert_int_eq(data.day[0].tx, 0); ck_assert_int_eq(data.day[0].rxk, 4); ck_assert_int_eq(data.day[0].txk, 4); ck_assert_int_eq(data.totalrx, 0); ck_assert_int_eq(data.totaltx, 0); ck_assert_int_eq(data.totalrxk, 4); ck_assert_int_eq(data.totaltxk, 4); ck_assert_int_eq(data.currx, 4096); ck_assert_int_eq(data.curtx, 4096); data.lastupdated -= 10; ifinfo.rx = 8192; ifinfo.tx = 8192; ifinfo.rxp = ifinfo.txp = 0; parseifinfo(0); ck_assert_int_eq(ifinfo.rx, 8192); ck_assert_int_eq(ifinfo.tx, 8192); ck_assert_int_eq(ifinfo.rxp, 0); ck_assert_int_eq(ifinfo.txp, 0); ck_assert_int_eq(data.day[0].rx, 0); ck_assert_int_eq(data.day[0].tx, 0); ck_assert_int_eq(data.day[0].rxk, 8); ck_assert_int_eq(data.day[0].txk, 8); ck_assert_int_eq(data.totalrx, 0); ck_assert_int_eq(data.totaltx, 0); ck_assert_int_eq(data.totalrxk, 8); ck_assert_int_eq(data.totaltxk, 8); ck_assert_int_eq(data.currx, 8192); ck_assert_int_eq(data.curtx, 8192); data.lastupdated -= 5; ifinfo.rx = 1048576; ifinfo.tx = 1048576; ifinfo.rxp = ifinfo.txp = 0; parseifinfo(0); ck_assert_int_eq(ifinfo.rx, 1048576); ck_assert_int_eq(ifinfo.tx, 1048576); ck_assert_int_eq(ifinfo.rxp, 0); ck_assert_int_eq(ifinfo.txp, 0); ck_assert_int_eq(data.day[0].rx, 1); ck_assert_int_eq(data.day[0].tx, 1); ck_assert_int_eq(data.day[0].rxk, 0); ck_assert_int_eq(data.day[0].txk, 0); ck_assert_int_eq(data.totalrx, 1); ck_assert_int_eq(data.totaltx, 1); ck_assert_int_eq(data.totalrxk, 0); ck_assert_int_eq(data.totaltxk, 0); ck_assert_int_eq(data.currx, 1048576); ck_assert_int_eq(data.curtx, 1048576); }
void parseifinfo(int newdb) { uint64_t rxchange=0, txchange=0, btime, cc; /* rxchange = rx change in MB */ uint64_t krxchange=0, ktxchange=0, maxtransfer; /* krxchange = rx change in kB */ time_t current, interval; struct tm *d; int day, month, year, hour, min, shift, maxbw; int rxkchange=0, txkchange=0; /* changes in the kB counters */ ifinfo.rxp = ifinfo.txp = 0; current=time(NULL); interval=current-data.lastupdated; btime=getbtime(); /* count traffic only if previous update wasn't too long ago */ if ( interval < (60*MAXUPDATEINTERVAL) ) { /* btime in /proc/stat seems to vary ±1 second so we use btime-BVAR just to be safe */ /* the variation is also slightly different between various kernels... */ if (data.btime < (btime-cfg.bvar)) { data.currx=0; data.curtx=0; if (debug) printf("System has been booted.\n"); } /* process rx & tx */ if (newdb!=1) { cc = countercalc(data.currx, ifinfo.rx); rxchange = cc/1048576; /* 1024/1024 */ rxkchange = (cc/1024)%1024; krxchange = cc/1024; ifinfo.rxp = cc%1024; cc = countercalc(data.curtx, ifinfo.tx); txchange = cc/1048576; /* 1024/1024 */ txkchange = (cc/1024)%1024; ktxchange = cc/1024; ifinfo.txp = cc%1024; } /* get bandwidth limit for current interface */ maxbw = ibwget(data.interface); if (maxbw > 0) { /* calculate maximum possible transfer since last update based on set maximum rate */ /* and add 10% in order to be on the safe side */ maxtransfer = ceil((maxbw/(float)8)*interval*(float)1.1); if (debug) printf("interval: %"PRIu64" maxbw: %d maxrate: %"PRIu64" rxc: %"PRIu64" txc: %"PRIu64"\n", (uint64_t)interval, maxbw, maxtransfer, rxchange, txchange); /* sync counters if traffic is greater than set maximum */ if ( (rxchange > maxtransfer) || (txchange > maxtransfer) ) { snprintf(errorstring, 512, "Traffic rate for \"%s\" higher than set maximum %d Mbit (%"PRIu64"->%"PRIu64", r%"PRIu64" t%"PRIu64"), syncing.", data.interface, maxbw, (uint64_t)interval, maxtransfer, rxchange, txchange); printe(PT_Info); rxchange = krxchange = rxkchange = txchange = ktxchange = txkchange = 0; ifinfo.rxp = ifinfo.txp = 0; } } } else { if (debug) printf("Too much time passed since previous update, syncing. (%"PRIu64" < %d)\n", (uint64_t)interval, 60*MAXUPDATEINTERVAL); } /* keep btime updated in case it drifts slowly */ data.btime = btime; data.currx = ifinfo.rx - ifinfo.rxp; data.curtx = ifinfo.tx - ifinfo.txp; addtraffic(&data.totalrx, &data.totalrxk, rxchange, rxkchange); addtraffic(&data.totaltx, &data.totaltxk, txchange, txkchange); /* update days and months */ addtraffic(&data.day[0].rx, &data.day[0].rxk, rxchange, rxkchange); addtraffic(&data.day[0].tx, &data.day[0].txk, txchange, txkchange); addtraffic(&data.month[0].rx, &data.month[0].rxk, rxchange, rxkchange); addtraffic(&data.month[0].tx, &data.month[0].txk, txchange, txkchange); /* fill some variables from current date & time */ d=localtime(¤t); day=d->tm_mday; month=d->tm_mon; year=d->tm_year; hour=d->tm_hour; min=d->tm_min; shift=hour; /* add traffic to previous hour when update happens at X:00 */ /* and previous update was during previous hour */ d=localtime(&data.lastupdated); if ((min==0) && (d->tm_hour!=hour) && ((current-data.lastupdated)<=3600)) { hour--; if (hour<0) { hour=23; } } /* clean and update hourly */ cleanhours(); data.hour[shift].date=current; /* avoid shifting timestamp */ data.hour[hour].rx+=krxchange; data.hour[hour].tx+=ktxchange; /* rotate days in database if needed */ d=localtime(&data.day[0].date); if ((d->tm_mday!=day) || (d->tm_mon!=month) || (d->tm_year!=year)) { /* make a new entry only if there's something to remember (configuration dependent) */ if ( (data.day[0].rx==0) && (data.day[0].tx==0) && (data.day[0].rxk==0) && (data.day[0].txk==0) && (cfg.traflessday==0) ) { data.day[0].date=current; } else { rotatedays(); } } /* rotate months in database if needed */ d=localtime(&data.month[0].month); if ((d->tm_mon!=month) && (day>=cfg.monthrotate)) { rotatemonths(); } }