modules/admin-full: rework realtime stats to start luci-bwc on demand, kill daemon after ten seconds of inactivity
This commit is contained in:
parent
37df666e0a
commit
8bbf59dcc6
3 changed files with 186 additions and 111 deletions
|
@ -69,57 +69,42 @@ function action_bandwidth()
|
||||||
local path = luci.dispatcher.context.requestpath
|
local path = luci.dispatcher.context.requestpath
|
||||||
local iface = path[#path]
|
local iface = path[#path]
|
||||||
|
|
||||||
local fs = require "luci.fs"
|
luci.http.prepare_content("application/json")
|
||||||
if fs.access("/var/lib/luci-bwc/if/%s" % iface) then
|
|
||||||
luci.http.prepare_content("application/json")
|
|
||||||
|
|
||||||
local bwc = io.popen("luci-bwc -i %q 2>/dev/null" % iface)
|
local bwc = io.popen("luci-bwc -i %q 2>/dev/null" % iface)
|
||||||
if bwc then
|
if bwc then
|
||||||
luci.http.write("[")
|
luci.http.write("[")
|
||||||
|
|
||||||
while true do
|
while true do
|
||||||
local ln = bwc:read("*l")
|
local ln = bwc:read("*l")
|
||||||
if not ln then break end
|
if not ln then break end
|
||||||
luci.http.write(ln)
|
luci.http.write(ln)
|
||||||
end
|
|
||||||
|
|
||||||
luci.http.write("]")
|
|
||||||
bwc:close()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return
|
luci.http.write("]")
|
||||||
|
bwc:close()
|
||||||
end
|
end
|
||||||
|
|
||||||
luci.http.status(404, "No data available")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function action_load()
|
function action_load()
|
||||||
local fs = require "luci.fs"
|
luci.http.prepare_content("application/json")
|
||||||
if fs.access("/var/lib/luci-bwc/load") then
|
|
||||||
luci.http.prepare_content("application/json")
|
|
||||||
|
|
||||||
local bwc = io.popen("luci-bwc -l 2>/dev/null")
|
local bwc = io.popen("luci-bwc -l 2>/dev/null")
|
||||||
if bwc then
|
if bwc then
|
||||||
luci.http.write("[")
|
luci.http.write("[")
|
||||||
|
|
||||||
while true do
|
while true do
|
||||||
local ln = bwc:read("*l")
|
local ln = bwc:read("*l")
|
||||||
if not ln then break end
|
if not ln then break end
|
||||||
luci.http.write(ln)
|
luci.http.write(ln)
|
||||||
end
|
|
||||||
|
|
||||||
luci.http.write("]")
|
|
||||||
bwc:close()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return
|
luci.http.write("]")
|
||||||
|
bwc:close()
|
||||||
end
|
end
|
||||||
|
|
||||||
luci.http.status(404, "No data available")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function action_connections()
|
function action_connections()
|
||||||
local fs = require "luci.fs"
|
|
||||||
local sys = require "luci.sys"
|
local sys = require "luci.sys"
|
||||||
|
|
||||||
luci.http.prepare_content("application/json")
|
luci.http.prepare_content("application/json")
|
||||||
|
@ -127,20 +112,18 @@ function action_connections()
|
||||||
luci.http.write("{ connections: ")
|
luci.http.write("{ connections: ")
|
||||||
luci.http.write_json(sys.net.conntrack())
|
luci.http.write_json(sys.net.conntrack())
|
||||||
|
|
||||||
if fs.access("/var/lib/luci-bwc/connections") then
|
local bwc = io.popen("luci-bwc -c 2>/dev/null")
|
||||||
local bwc = io.popen("luci-bwc -c 2>/dev/null")
|
if bwc then
|
||||||
if bwc then
|
luci.http.write(", statistics: [")
|
||||||
luci.http.write(", statistics: [")
|
|
||||||
|
|
||||||
while true do
|
while true do
|
||||||
local ln = bwc:read("*l")
|
local ln = bwc:read("*l")
|
||||||
if not ln then break end
|
if not ln then break end
|
||||||
luci.http.write(ln)
|
luci.http.write(ln)
|
||||||
end
|
|
||||||
|
|
||||||
luci.http.write("]")
|
|
||||||
bwc:close()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
luci.http.write("]")
|
||||||
|
bwc:close()
|
||||||
end
|
end
|
||||||
|
|
||||||
luci.http.write(" }")
|
luci.http.write(" }")
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
#!/bin/sh /etc/rc.common
|
|
||||||
|
|
||||||
START=95
|
|
||||||
STOP=95
|
|
||||||
|
|
||||||
BWC=/usr/bin/luci-bwc
|
|
||||||
|
|
||||||
start() {
|
|
||||||
$BWC -d
|
|
||||||
}
|
|
||||||
|
|
||||||
stop() {
|
|
||||||
killall ${BWC##*/}
|
|
||||||
}
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
@ -33,6 +34,9 @@
|
||||||
|
|
||||||
#define STEP_COUNT 60
|
#define STEP_COUNT 60
|
||||||
#define STEP_TIME 1
|
#define STEP_TIME 1
|
||||||
|
#define TIMEOUT 10
|
||||||
|
|
||||||
|
#define PID_PATH "/var/run/luci-bwc.pid"
|
||||||
|
|
||||||
#define DB_PATH "/var/lib/luci-bwc"
|
#define DB_PATH "/var/lib/luci-bwc"
|
||||||
#define DB_IF_FILE DB_PATH "/if/%s"
|
#define DB_IF_FILE DB_PATH "/if/%s"
|
||||||
|
@ -90,6 +94,53 @@ static uint64_t htonll(uint64_t value)
|
||||||
|
|
||||||
#define ntohll htonll
|
#define ntohll htonll
|
||||||
|
|
||||||
|
static int readpid(void)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
int pid = -1;
|
||||||
|
char buf[9] = { 0 };
|
||||||
|
|
||||||
|
if ((fd = open(PID_PATH, O_RDONLY)) > -1)
|
||||||
|
{
|
||||||
|
if (read(fd, buf, sizeof(buf)))
|
||||||
|
{
|
||||||
|
buf[8] = 0;
|
||||||
|
pid = atoi(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int writepid(void)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
int wlen;
|
||||||
|
char buf[9] = { 0 };
|
||||||
|
|
||||||
|
if ((fd = open(PID_PATH, O_WRONLY | O_CREAT | O_TRUNC, 0600)) > -1)
|
||||||
|
{
|
||||||
|
wlen = snprintf(buf, sizeof(buf), "%i", getpid());
|
||||||
|
write(fd, buf, wlen);
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int timeout = TIMEOUT;
|
||||||
|
static int countdown = -1;
|
||||||
|
|
||||||
|
static void reset_countdown(int sig)
|
||||||
|
{
|
||||||
|
countdown = timeout;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int init_directory(char *path)
|
static int init_directory(char *path)
|
||||||
{
|
{
|
||||||
|
@ -135,6 +186,11 @@ static int init_file(char *path, int esize)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline uint64_t timeof(void *entry)
|
||||||
|
{
|
||||||
|
return ((struct traffic_entry *)entry)->time;
|
||||||
|
}
|
||||||
|
|
||||||
static int update_file(const char *path, void *entry, int esize)
|
static int update_file(const char *path, void *entry, int esize)
|
||||||
{
|
{
|
||||||
int rv = -1;
|
int rv = -1;
|
||||||
|
@ -148,8 +204,11 @@ static int update_file(const char *path, void *entry, int esize)
|
||||||
|
|
||||||
if ((map != NULL) && (map != MAP_FAILED))
|
if ((map != NULL) && (map != MAP_FAILED))
|
||||||
{
|
{
|
||||||
memmove(map, map + esize, esize * (STEP_COUNT-1));
|
if (timeof(entry) > timeof(map + esize * (STEP_COUNT-1)))
|
||||||
memcpy(map + esize * (STEP_COUNT-1), entry, esize);
|
{
|
||||||
|
memmove(map, map + esize, esize * (STEP_COUNT-1));
|
||||||
|
memcpy(map + esize * (STEP_COUNT-1), entry, esize);
|
||||||
|
}
|
||||||
|
|
||||||
munmap(map, esize * STEP_COUNT);
|
munmap(map, esize * STEP_COUNT);
|
||||||
|
|
||||||
|
@ -277,7 +336,7 @@ static int update_ldstat(uint16_t load1, uint16_t load5, uint16_t load15)
|
||||||
return update_file(path, &e, sizeof(struct load_entry));
|
return update_file(path, &e, sizeof(struct load_entry));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int run_daemon(int nofork)
|
static int run_daemon(char *progname)
|
||||||
{
|
{
|
||||||
FILE *info;
|
FILE *info;
|
||||||
uint64_t rxb, txb, rxp, txp;
|
uint64_t rxb, txb, rxp, txp;
|
||||||
|
@ -286,39 +345,53 @@ static int run_daemon(int nofork)
|
||||||
char line[1024];
|
char line[1024];
|
||||||
char ifname[16];
|
char ifname[16];
|
||||||
|
|
||||||
|
struct sigaction sa;
|
||||||
|
|
||||||
struct stat s;
|
struct stat s;
|
||||||
const char *ipc = stat("/proc/net/nf_conntrack", &s)
|
const char *ipc = stat("/proc/net/nf_conntrack", &s)
|
||||||
? "/proc/net/ip_conntrack" : "/proc/net/nf_conntrack";
|
? "/proc/net/ip_conntrack" : "/proc/net/nf_conntrack";
|
||||||
|
|
||||||
if (!nofork)
|
switch (fork())
|
||||||
{
|
{
|
||||||
switch (fork())
|
case -1:
|
||||||
{
|
perror("fork()");
|
||||||
case -1:
|
return -1;
|
||||||
perror("fork()");
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
case 0:
|
case 0:
|
||||||
if (chdir("/") < 0)
|
if (chdir("/") < 0)
|
||||||
{
|
{
|
||||||
perror("chdir()");
|
perror("chdir()");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
close(0);
|
close(0);
|
||||||
close(1);
|
close(1);
|
||||||
close(2);
|
close(2);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
exit(0);
|
return 0;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* setup USR1 signal handler to reset timer */
|
||||||
|
sa.sa_handler = reset_countdown;
|
||||||
|
sa.sa_flags = SA_RESTART;
|
||||||
|
sigemptyset(&sa.sa_mask);
|
||||||
|
sigaction(SIGUSR1, &sa, NULL);
|
||||||
|
|
||||||
|
/* write pid */
|
||||||
|
if (writepid())
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to write pid file: %s\n", strerror(errno));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* go */
|
/* go */
|
||||||
while (1)
|
for (reset_countdown(0); countdown >= 0; countdown--)
|
||||||
{
|
{
|
||||||
|
/* alter progname for ps, top */
|
||||||
|
sprintf(progname, "luci-bwc %d", countdown);
|
||||||
|
|
||||||
if ((info = fopen("/proc/net/dev", "r")) != NULL)
|
if ((info = fopen("/proc/net/dev", "r")) != NULL)
|
||||||
{
|
{
|
||||||
while (fgets(line, sizeof(line), info))
|
while (fgets(line, sizeof(line), info))
|
||||||
|
@ -377,9 +450,38 @@ static int run_daemon(int nofork)
|
||||||
|
|
||||||
sleep(STEP_TIME);
|
sleep(STEP_TIME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unlink(PID_PATH);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int run_dump_ifname(const char *ifname)
|
static int check_daemon(char *progname)
|
||||||
|
{
|
||||||
|
int pid;
|
||||||
|
|
||||||
|
if ((pid = readpid()) < 0 || kill(pid, 0) < 0)
|
||||||
|
{
|
||||||
|
/* daemon ping failed, try to start it up */
|
||||||
|
if (run_daemon(progname))
|
||||||
|
{
|
||||||
|
fprintf(stderr,
|
||||||
|
"Failed to ping daemon and unable to start it up: %s\n",
|
||||||
|
strerror(errno));
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (kill(pid, SIGUSR1))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to send signal: %s\n", strerror(errno));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int run_dump_ifname(char *progname, const char *ifname)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
char path[1024];
|
char path[1024];
|
||||||
|
@ -388,6 +490,11 @@ static int run_dump_ifname(const char *ifname)
|
||||||
|
|
||||||
snprintf(path, sizeof(path), DB_IF_FILE, ifname);
|
snprintf(path, sizeof(path), DB_IF_FILE, ifname);
|
||||||
|
|
||||||
|
if (check_daemon(progname))
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (mmap_file(path, sizeof(struct traffic_entry), &m))
|
if (mmap_file(path, sizeof(struct traffic_entry), &m))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno));
|
fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno));
|
||||||
|
@ -414,7 +521,7 @@ static int run_dump_ifname(const char *ifname)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int run_dump_conns(void)
|
static int run_dump_conns(char *progname)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
char path[1024];
|
char path[1024];
|
||||||
|
@ -423,6 +530,11 @@ static int run_dump_conns(void)
|
||||||
|
|
||||||
snprintf(path, sizeof(path), DB_CN_FILE);
|
snprintf(path, sizeof(path), DB_CN_FILE);
|
||||||
|
|
||||||
|
if (check_daemon(progname))
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (mmap_file(path, sizeof(struct conn_entry), &m))
|
if (mmap_file(path, sizeof(struct conn_entry), &m))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno));
|
fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno));
|
||||||
|
@ -447,7 +559,7 @@ static int run_dump_conns(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int run_dump_load(void)
|
static int run_dump_load(char *progname)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
char path[1024];
|
char path[1024];
|
||||||
|
@ -456,6 +568,11 @@ static int run_dump_load(void)
|
||||||
|
|
||||||
snprintf(path, sizeof(path), DB_LD_FILE);
|
snprintf(path, sizeof(path), DB_LD_FILE);
|
||||||
|
|
||||||
|
if (check_daemon(progname))
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (mmap_file(path, sizeof(struct load_entry), &m))
|
if (mmap_file(path, sizeof(struct load_entry), &m))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno));
|
fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno));
|
||||||
|
@ -484,49 +601,38 @@ static int run_dump_load(void)
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int opt;
|
int opt;
|
||||||
int daemon = 0;
|
|
||||||
int nofork = 0;
|
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "dfi:cl")) > -1)
|
while ((opt = getopt(argc, argv, "t:i:cl")) > -1)
|
||||||
{
|
{
|
||||||
switch (opt)
|
switch (opt)
|
||||||
{
|
{
|
||||||
case 'd':
|
case 't':
|
||||||
daemon = 1;
|
timeout = atoi(optarg);
|
||||||
break;
|
|
||||||
|
|
||||||
case 'f':
|
|
||||||
nofork = 1;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'i':
|
case 'i':
|
||||||
if (optarg)
|
if (optarg)
|
||||||
return run_dump_ifname(optarg);
|
return run_dump_ifname(argv[0], optarg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'c':
|
case 'c':
|
||||||
return run_dump_conns();
|
return run_dump_conns(argv[0]);
|
||||||
|
|
||||||
case 'l':
|
case 'l':
|
||||||
return run_dump_load();
|
return run_dump_load(argv[0]);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (daemon)
|
fprintf(stderr,
|
||||||
return run_daemon(nofork);
|
"Usage:\n"
|
||||||
|
" %s [-t timeout] -i ifname\n"
|
||||||
else
|
" %s [-t timeout] -c\n"
|
||||||
fprintf(stderr,
|
" %s [-t timeout] -l\n",
|
||||||
"Usage:\n"
|
argv[0], argv[0], argv[0]
|
||||||
" %s -d [-f]\n"
|
);
|
||||||
" %s -i ifname\n"
|
|
||||||
" %s -c\n"
|
|
||||||
" %s -l\n",
|
|
||||||
argv[0], argv[0], argv[0], argv[0]
|
|
||||||
);
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue