modules/admin-full: implement connection graph, cross browser fixes
This commit is contained in:
parent
750b023494
commit
ceff3fc35c
6 changed files with 511 additions and 129 deletions
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
|
||||
<svg width="100%" height="100%" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<line x1="0" y1="25%" x2="100%" y2="25%" style="stroke:black;stroke-width:0.1" />
|
||||
<text id="label_75" x="20" y="24%" style="fill:#999999; font-size:9pt"> </text>
|
||||
|
||||
<line x1="0" y1="50%" x2="100%" y2="50%" style="stroke:black;stroke-width:0.1" />
|
||||
<text id="label_50" x="20" y="49%" style="fill:#999999; font-size:9pt"> </text>
|
||||
|
||||
<line x1="0" y1="75%" x2="100%" y2="75%" style="stroke:black;stroke-width:0.1" />
|
||||
<text id="label_25" x="20" y="74%" style="fill:#999999; font-size:9pt"> </text>
|
||||
|
||||
<polyline id="udp" points="" style="fill:blue;fill-opacity:0.4;stroke:blue;stroke-width:1" />
|
||||
<polyline id="tcp" points="" style="fill:green;fill-opacity:0.4;stroke:green;stroke-width:1" />
|
||||
</svg>
|
After Width: | Height: | Size: 914 B |
|
@ -31,6 +31,8 @@ function index()
|
|||
entry({"admin", "status", "bandwidth"}, template("admin_status/bandwidth"), i18n("Realtime Traffic"), 8).leaf = true
|
||||
entry({"admin", "status", "bandwidth_status"}, call("action_bandwidth")).leaf = true
|
||||
|
||||
entry({"admin", "status", "connections"}, template("admin_status/connections"), i18n("Realtime Connections"), 9).leaf = true
|
||||
entry({"admin", "status", "connections_status"}, call("action_connections")).leaf = true
|
||||
end
|
||||
|
||||
function action_syslog()
|
||||
|
@ -111,3 +113,28 @@ function action_load()
|
|||
|
||||
luci.http.status(404, "No data available")
|
||||
end
|
||||
|
||||
function action_connections()
|
||||
local fs = require "luci.fs"
|
||||
if fs.access("/var/lib/luci-bwc/connections") then
|
||||
luci.http.prepare_content("application/json")
|
||||
|
||||
local bwc = io.popen("luci-bwc -c 2>/dev/null")
|
||||
if bwc then
|
||||
luci.http.write("[")
|
||||
|
||||
while true do
|
||||
local ln = bwc:read("*l")
|
||||
if not ln then break end
|
||||
luci.http.write(ln)
|
||||
end
|
||||
|
||||
luci.http.write("]")
|
||||
bwc:close()
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
luci.http.status(404, "No data available")
|
||||
end
|
||||
|
|
|
@ -202,7 +202,15 @@ $Id$
|
|||
/* wait for SVG */
|
||||
window.setTimeout(
|
||||
function() {
|
||||
G = document.embeds["bwsvg"].getSVGDocument();
|
||||
var svg = document.getElementById('bwsvg');
|
||||
|
||||
try {
|
||||
G = svg.getSVGDocument
|
||||
? svg.getSVGDocument() : svg.contentDocument;
|
||||
}
|
||||
catch(e) {
|
||||
G = document.embeds['bwsvg'].getSVGDocument();
|
||||
}
|
||||
|
||||
if (!G)
|
||||
{
|
||||
|
@ -211,8 +219,8 @@ $Id$
|
|||
else
|
||||
{
|
||||
/* find sizes */
|
||||
width = document.embeds["bwsvg"].offsetWidth - 2;
|
||||
height = document.embeds["bwsvg"].offsetHeight - 2;
|
||||
width = svg.offsetWidth - 2;
|
||||
height = svg.offsetHeight - 2;
|
||||
data_wanted = Math.ceil(width / step);
|
||||
|
||||
/* prefill datasets */
|
||||
|
|
261
modules/admin-full/luasrc/view/admin_status/connections.htm
Normal file
261
modules/admin-full/luasrc/view/admin_status/connections.htm
Normal file
|
@ -0,0 +1,261 @@
|
|||
<%#
|
||||
LuCI - Lua Configuration Interface
|
||||
Copyright 2010 Jo-Philipp Wich <xm@subsignal.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
|
||||
-%>
|
||||
|
||||
<%+header%>
|
||||
|
||||
<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
var bwxhr = new XHR();
|
||||
|
||||
var G;
|
||||
var TIME = 0;
|
||||
var UDP = 1;
|
||||
var TCP = 2;
|
||||
|
||||
var width = 760;
|
||||
var height = 300;
|
||||
var step = 5;
|
||||
|
||||
var data_wanted = Math.floor(width / step);
|
||||
var data_fill = 0;
|
||||
var data_stamp = 0;
|
||||
|
||||
var data_udp = [ ];
|
||||
var data_tcp = [ ];
|
||||
|
||||
var line_udp;
|
||||
var line_tcp;
|
||||
|
||||
var label_25;
|
||||
var label_50;
|
||||
var label_75;
|
||||
|
||||
var label_rx_cur;
|
||||
var label_rx_avg;
|
||||
var label_rx_peak;
|
||||
|
||||
var label_tx_cur;
|
||||
var label_tx_avg;
|
||||
var label_tx_peak;
|
||||
|
||||
var label_scale;
|
||||
|
||||
|
||||
function update_graph()
|
||||
{
|
||||
bwxhr.get('<%=build_url("admin/status/connections_status")%>', null,
|
||||
function(x, data)
|
||||
{
|
||||
var data_max = 0;
|
||||
var data_scale = 0;
|
||||
|
||||
var data_udp_avg = 0;
|
||||
var data_tcp_avg = 0;
|
||||
|
||||
var data_udp_peak = 0;
|
||||
var data_tcp_peak = 0;
|
||||
|
||||
for (var i = data_stamp ? 0 : 1; i < data.length; i++)
|
||||
{
|
||||
/* skip overlapping entries */
|
||||
if (data[i][TIME] <= data_stamp)
|
||||
continue;
|
||||
|
||||
data_udp.push(data[i][UDP]);
|
||||
data_tcp.push(data[i][TCP]);
|
||||
}
|
||||
|
||||
/* cut off outdated entries */
|
||||
data_udp = data_udp.slice(data_udp.length - data_wanted, data_udp.length);
|
||||
data_tcp = data_tcp.slice(data_tcp.length - data_wanted, data_tcp.length);
|
||||
|
||||
/* find peak */
|
||||
for (var i = 0; i < data_udp.length; i++)
|
||||
{
|
||||
data_max = Math.max(data_max, data_udp[i]);
|
||||
data_max = Math.max(data_max, data_tcp[i]);
|
||||
|
||||
data_udp_peak = Math.max(data_udp_peak, data_udp[i]);
|
||||
data_tcp_peak = Math.max(data_tcp_peak, data_tcp[i]);
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
data_udp_avg = (data_udp_avg + data_udp[i]) / 2;
|
||||
data_tcp_avg = (data_tcp_avg + data_tcp[i]) / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
data_udp_avg = data_udp[i];
|
||||
data_tcp_avg = data_tcp[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* remember current timestamp, calculate horizontal scale */
|
||||
data_stamp = data[data.length-1][TIME];
|
||||
data_scale = height / (data_max * 1.1);
|
||||
|
||||
|
||||
/* plot data */
|
||||
var pt_rx = '0,' + height;
|
||||
var pt_tx = '0,' + height;
|
||||
|
||||
var y_rx = 0;
|
||||
var y_tx = 0;
|
||||
|
||||
for (var i = 0; i < data_udp.length; i++)
|
||||
{
|
||||
var x = i * step;
|
||||
|
||||
y_rx = height - Math.floor(data_udp[i] * data_scale);
|
||||
y_tx = height - Math.floor(data_tcp[i] * data_scale);
|
||||
|
||||
pt_rx += ' ' + x + ',' + y_rx;
|
||||
pt_tx += ' ' + x + ',' + y_tx;
|
||||
}
|
||||
|
||||
pt_rx += ' ' + width + ',' + y_rx + ' ' + width + ',' + height;
|
||||
pt_tx += ' ' + width + ',' + y_tx + ' ' + width + ',' + height;
|
||||
|
||||
|
||||
line_udp.setAttribute('points', pt_rx);
|
||||
line_tcp.setAttribute('points', pt_tx);
|
||||
|
||||
label_25.firstChild.data = Math.floor(1.1 * 0.25 * data_max);
|
||||
label_50.firstChild.data = Math.floor(1.1 * 0.50 * data_max);
|
||||
label_75.firstChild.data = Math.floor(1.1 * 0.75 * data_max);
|
||||
|
||||
label_rx_cur.innerHTML = Math.floor(data_udp[data_udp.length-1]);
|
||||
label_tx_cur.innerHTML = Math.floor(data_tcp[data_tcp.length-1]);
|
||||
|
||||
label_rx_avg.innerHTML = Math.floor(data_udp_avg);
|
||||
label_tx_avg.innerHTML = Math.floor(data_tcp_avg);
|
||||
|
||||
label_rx_peak.innerHTML = Math.floor(data_udp_peak);
|
||||
label_tx_peak.innerHTML = Math.floor(data_tcp_peak);
|
||||
|
||||
/* reset timer */
|
||||
window.setTimeout(update_graph, 1000);
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/* wait for SVG */
|
||||
window.setTimeout(
|
||||
function() {
|
||||
var svg = document.getElementById('bwsvg');
|
||||
|
||||
try {
|
||||
G = svg.getSVGDocument
|
||||
? svg.getSVGDocument() : svg.contentDocument;
|
||||
}
|
||||
catch(e) {
|
||||
G = document.embeds['bwsvg'].getSVGDocument();
|
||||
}
|
||||
|
||||
if (!G)
|
||||
{
|
||||
window.setTimeout(arguments.callee, 1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* find sizes */
|
||||
width = svg.offsetWidth - 2;
|
||||
height = svg.offsetHeight - 2;
|
||||
data_wanted = Math.ceil(width / step);
|
||||
|
||||
/* prefill datasets */
|
||||
for (var i = 0; i < data_wanted; i++)
|
||||
{
|
||||
data_udp[i] = 0;
|
||||
data_tcp[i] = 0;
|
||||
}
|
||||
|
||||
/* find svg elements */
|
||||
line_udp = G.getElementById('udp');
|
||||
line_tcp = G.getElementById('tcp');
|
||||
|
||||
label_25 = G.getElementById('label_25');
|
||||
label_50 = G.getElementById('label_50');
|
||||
label_75 = G.getElementById('label_75');
|
||||
|
||||
label_rx_cur = document.getElementById('lb_udp_cur');
|
||||
label_rx_avg = document.getElementById('lb_udp_avg');
|
||||
label_rx_peak = document.getElementById('lb_udp_peak');
|
||||
|
||||
label_tx_cur = document.getElementById('lb_tcp_cur');
|
||||
label_tx_avg = document.getElementById('lb_tcp_avg');
|
||||
label_tx_peak = document.getElementById('lb_tcp_peak');
|
||||
|
||||
label_scale = document.getElementById('scale');
|
||||
|
||||
|
||||
/* plot horizontal time interval lines */
|
||||
for (var i = step * 60; i < width; i += step * 60)
|
||||
{
|
||||
var line = G.createElementNS('http://www.w3.org/2000/svg', 'line');
|
||||
line.setAttribute('x1', i);
|
||||
line.setAttribute('y1', 0);
|
||||
line.setAttribute('x2', i);
|
||||
line.setAttribute('y2', '100%');
|
||||
line.setAttribute('style', 'stroke:black;stroke-width:0.1');
|
||||
|
||||
var text = G.createElementNS('http://www.w3.org/2000/svg', 'text');
|
||||
text.setAttribute('x', i + 5);
|
||||
text.setAttribute('y', 15);
|
||||
text.setAttribute('style', 'fill:#999999; font-size:9pt');
|
||||
text.appendChild(G.createTextNode(Math.round(i / step / 60) + 'm'));
|
||||
|
||||
label_25.parentNode.appendChild(line);
|
||||
label_25.parentNode.appendChild(text);
|
||||
}
|
||||
|
||||
label_scale.innerHTML = String.format('<%:(%d minute window, %d second interval)%>', data_wanted / 60, 1);
|
||||
|
||||
/* render datasets, start update interval */
|
||||
update_graph();
|
||||
}
|
||||
}, 1000
|
||||
);
|
||||
//]]></script>
|
||||
|
||||
<h2><a id="content" name="content"><%:Realtime Connections%></a></h2>
|
||||
|
||||
<embed id="bwsvg" style="width:100%; height:300px; border:1px solid #000000; background-color:#FFFFFF" src="<%=resource%>/connections.svg" />
|
||||
<div style="text-align:right"><small id="scale">-</small></div>
|
||||
<br />
|
||||
|
||||
<table style="width:100%; table-layout:fixed" cellspacing="5">
|
||||
<tr>
|
||||
<td style="text-align:right; vertical-align:top"><strong style="border-bottom:2px solid blue"><%:UDP:%></strong></td>
|
||||
<td id="lb_udp_cur">0</td>
|
||||
|
||||
<td style="text-align:right; vertical-align:top"><strong><%:Average:%></strong></td>
|
||||
<td id="lb_udp_avg">0</td>
|
||||
|
||||
<td style="text-align:right; vertical-align:top"><strong><%:Peak:%></strong></td>
|
||||
<td id="lb_udp_peak">0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align:right; vertical-align:top"><strong style="border-bottom:2px solid green"><%:TCP:%></strong></td>
|
||||
<td id="lb_tcp_cur">0</td>
|
||||
|
||||
<td style="text-align:right; vertical-align:top"><strong><%:Average:%></strong></td>
|
||||
<td id="lb_tcp_avg">0</td>
|
||||
|
||||
<td style="text-align:right; vertical-align:top"><strong><%:Peak:%></strong></td>
|
||||
<td id="lb_tcp_peak">0</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<%+footer%>
|
|
@ -177,7 +177,15 @@ $Id$
|
|||
/* wait for SVG */
|
||||
window.setTimeout(
|
||||
function() {
|
||||
G = document.embeds["bwsvg"].getSVGDocument();
|
||||
var svg = document.getElementById('bwsvg');
|
||||
|
||||
try {
|
||||
G = svg.getSVGDocument
|
||||
? svg.getSVGDocument() : svg.contentDocument;
|
||||
}
|
||||
catch(e) {
|
||||
G = document.embeds['bwsvg'].getSVGDocument();
|
||||
}
|
||||
|
||||
if (!G)
|
||||
{
|
||||
|
@ -186,8 +194,8 @@ $Id$
|
|||
else
|
||||
{
|
||||
/* find sizes */
|
||||
width = document.embeds["bwsvg"].offsetWidth - 2;
|
||||
height = document.embeds["bwsvg"].offsetHeight - 2;
|
||||
width = svg.offsetWidth - 2;
|
||||
height = svg.offsetHeight - 2;
|
||||
data_wanted = Math.ceil(width / step);
|
||||
|
||||
/* prefill datasets */
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
|
||||
#define DB_PATH "/var/lib/luci-bwc"
|
||||
#define DB_IF_FILE DB_PATH "/if/%s"
|
||||
#define DB_CN_FILE DB_PATH "/connections"
|
||||
#define DB_LD_FILE DB_PATH "/load"
|
||||
|
||||
#define IF_SCAN_PATTERN \
|
||||
|
@ -47,6 +48,12 @@
|
|||
"%f %f %f"
|
||||
|
||||
|
||||
struct file_map {
|
||||
int fd;
|
||||
int size;
|
||||
char *mmap;
|
||||
};
|
||||
|
||||
struct traffic_entry {
|
||||
uint64_t time;
|
||||
uint64_t rxb;
|
||||
|
@ -55,6 +62,12 @@ struct traffic_entry {
|
|||
uint64_t txp;
|
||||
};
|
||||
|
||||
struct conn_entry {
|
||||
uint64_t time;
|
||||
uint32_t udp;
|
||||
uint32_t tcp;
|
||||
};
|
||||
|
||||
struct load_entry {
|
||||
uint64_t time;
|
||||
uint16_t load1;
|
||||
|
@ -97,6 +110,30 @@ static int init_directory(char *path)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int init_file(char *path, int esize)
|
||||
{
|
||||
int i, file;
|
||||
char buf[sizeof(struct traffic_entry)] = { 0 };
|
||||
|
||||
if (init_directory(path))
|
||||
return -1;
|
||||
|
||||
if ((file = open(path, O_WRONLY | O_CREAT, 0600)) >= 0)
|
||||
{
|
||||
for (i = 0; i < STEP_COUNT; i++)
|
||||
{
|
||||
if (write(file, buf, esize) < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
close(file);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int update_file(const char *path, void *entry, int esize)
|
||||
{
|
||||
int rv = -1;
|
||||
|
@ -124,34 +161,35 @@ static int update_file(const char *path, void *entry, int esize)
|
|||
return rv;
|
||||
}
|
||||
|
||||
|
||||
static int init_ifstat(const char *ifname)
|
||||
static int mmap_file(const char *path, int esize, struct file_map *m)
|
||||
{
|
||||
int i, file;
|
||||
char path[1024];
|
||||
struct traffic_entry e = { 0 };
|
||||
m->fd = -1;
|
||||
m->size = -1;
|
||||
m->mmap = NULL;
|
||||
|
||||
snprintf(path, sizeof(path), DB_IF_FILE, ifname);
|
||||
|
||||
if (init_directory(path))
|
||||
return -1;
|
||||
|
||||
if ((file = open(path, O_WRONLY | O_CREAT, 0600)) >= 0)
|
||||
if ((m->fd = open(path, O_RDONLY)) >= 0)
|
||||
{
|
||||
for (i = 0; i < STEP_COUNT; i++)
|
||||
{
|
||||
if (write(file, &e, sizeof(struct traffic_entry)) < 0)
|
||||
break;
|
||||
}
|
||||
m->size = STEP_COUNT * esize;
|
||||
m->mmap = mmap(NULL, m->size, PROT_READ,
|
||||
MAP_SHARED | MAP_LOCKED, m->fd, 0);
|
||||
|
||||
close(file);
|
||||
|
||||
return 0;
|
||||
if ((m->mmap != NULL) && (m->mmap != MAP_FAILED))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void umap_file(struct file_map *m)
|
||||
{
|
||||
if ((m->mmap != NULL) && (m->mmap != MAP_FAILED))
|
||||
munmap(m->mmap, m->size);
|
||||
|
||||
if (m->fd > -1)
|
||||
close(m->fd);
|
||||
}
|
||||
|
||||
|
||||
static int update_ifstat(
|
||||
const char *ifname, uint64_t rxb, uint64_t rxp, uint64_t txb, uint64_t txp
|
||||
) {
|
||||
|
@ -164,7 +202,7 @@ static int update_ifstat(
|
|||
|
||||
if (stat(path, &s))
|
||||
{
|
||||
if (init_ifstat(ifname))
|
||||
if (init_file(path, sizeof(struct traffic_entry)))
|
||||
{
|
||||
fprintf(stderr, "Failed to init %s: %s\n",
|
||||
path, strerror(errno));
|
||||
|
@ -182,31 +220,31 @@ static int update_ifstat(
|
|||
return update_file(path, &e, sizeof(struct traffic_entry));
|
||||
}
|
||||
|
||||
static int init_ldstat(void)
|
||||
static int update_cnstat(uint32_t udp, uint32_t tcp)
|
||||
{
|
||||
int i, file;
|
||||
char path[1024];
|
||||
struct load_entry e = { 0 };
|
||||
|
||||
snprintf(path, sizeof(path), DB_LD_FILE);
|
||||
struct stat s;
|
||||
struct conn_entry e;
|
||||
|
||||
if (init_directory(path))
|
||||
return -1;
|
||||
snprintf(path, sizeof(path), DB_CN_FILE);
|
||||
|
||||
if ((file = open(path, O_WRONLY | O_CREAT, 0600)) >= 0)
|
||||
if (stat(path, &s))
|
||||
{
|
||||
for (i = 0; i < STEP_COUNT; i++)
|
||||
if (init_file(path, sizeof(struct conn_entry)))
|
||||
{
|
||||
if (write(file, &e, sizeof(struct load_entry)) < 0)
|
||||
break;
|
||||
fprintf(stderr, "Failed to init %s: %s\n",
|
||||
path, strerror(errno));
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
close(file);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
e.time = htonll(time(NULL));
|
||||
e.udp = htonl(udp);
|
||||
e.tcp = htonl(tcp);
|
||||
|
||||
return update_file(path, &e, sizeof(struct conn_entry));
|
||||
}
|
||||
|
||||
static int update_ldstat(uint16_t load1, uint16_t load5, uint16_t load15)
|
||||
|
@ -220,7 +258,7 @@ static int update_ldstat(uint16_t load1, uint16_t load5, uint16_t load15)
|
|||
|
||||
if (stat(path, &s))
|
||||
{
|
||||
if (init_ldstat())
|
||||
if (init_file(path, sizeof(struct load_entry)))
|
||||
{
|
||||
fprintf(stderr, "Failed to init %s: %s\n",
|
||||
path, strerror(errno));
|
||||
|
@ -241,6 +279,7 @@ static int run_daemon(int nofork)
|
|||
{
|
||||
FILE *info;
|
||||
uint64_t rxb, txb, rxp, txp;
|
||||
uint32_t udp, tcp;
|
||||
float lf1, lf5, lf15;
|
||||
char line[1024];
|
||||
char ifname[16];
|
||||
|
@ -292,6 +331,33 @@ static int run_daemon(int nofork)
|
|||
fclose(info);
|
||||
}
|
||||
|
||||
if ((info = fopen("/proc/net/ip_conntrack", "r")) != NULL)
|
||||
{
|
||||
udp = 0;
|
||||
tcp = 0;
|
||||
|
||||
while (fgets(line, sizeof(line), info))
|
||||
{
|
||||
switch (line[0])
|
||||
{
|
||||
case 't':
|
||||
tcp++;
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
udp++;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
update_cnstat(udp, tcp);
|
||||
|
||||
fclose(info);
|
||||
}
|
||||
|
||||
if ((info = fopen("/proc/loadavg", "r")) != NULL)
|
||||
{
|
||||
if (fscanf(info, LD_SCAN_PATTERN, &lf1, &lf5, &lf15))
|
||||
|
@ -310,100 +376,102 @@ static int run_daemon(int nofork)
|
|||
|
||||
static int run_dump_ifname(const char *ifname)
|
||||
{
|
||||
int rv = 1;
|
||||
|
||||
int i, file;
|
||||
int entrysize = sizeof(struct traffic_entry);
|
||||
int mapsize = STEP_COUNT * entrysize;
|
||||
|
||||
int i;
|
||||
char path[1024];
|
||||
char *map;
|
||||
|
||||
struct file_map m;
|
||||
struct traffic_entry *e;
|
||||
|
||||
snprintf(path, sizeof(path), DB_IF_FILE, ifname);
|
||||
|
||||
if ((file = open(path, O_RDONLY)) >= 0)
|
||||
{
|
||||
map = mmap(NULL, mapsize, PROT_READ, MAP_SHARED | MAP_LOCKED, file, 0);
|
||||
|
||||
if ((map != NULL) && (map != MAP_FAILED))
|
||||
{
|
||||
for (i = 0; i < mapsize; i += entrysize)
|
||||
{
|
||||
e = (struct traffic_entry *) &map[i];
|
||||
|
||||
if (!e->time)
|
||||
continue;
|
||||
|
||||
printf("[ %" PRIu64 ", %" PRIu64 ", %" PRIu64
|
||||
", %" PRIu64 ", %" PRIu64 " ]%s\n",
|
||||
ntohll(e->time),
|
||||
ntohll(e->rxb), ntohll(e->rxp),
|
||||
ntohll(e->txb), ntohll(e->txp),
|
||||
((i + entrysize) < mapsize) ? "," : "");
|
||||
}
|
||||
|
||||
munmap(map, mapsize);
|
||||
rv = 0;
|
||||
}
|
||||
|
||||
close(file);
|
||||
}
|
||||
else
|
||||
if (mmap_file(path, sizeof(struct traffic_entry), &m))
|
||||
{
|
||||
fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
return rv;
|
||||
for (i = 0; i < m.size; i += sizeof(struct traffic_entry))
|
||||
{
|
||||
e = (struct traffic_entry *) &m.mmap[i];
|
||||
|
||||
if (!e->time)
|
||||
continue;
|
||||
|
||||
printf("[ %" PRIu64 ", %" PRIu64 ", %" PRIu64
|
||||
", %" PRIu64 ", %" PRIu64 " ]%s\n",
|
||||
ntohll(e->time),
|
||||
ntohll(e->rxb), ntohll(e->rxp),
|
||||
ntohll(e->txb), ntohll(e->txp),
|
||||
((i + sizeof(struct traffic_entry)) < m.size) ? "," : "");
|
||||
}
|
||||
|
||||
umap_file(&m);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int run_dump_conns(void)
|
||||
{
|
||||
int i;
|
||||
char path[1024];
|
||||
struct file_map m;
|
||||
struct conn_entry *e;
|
||||
|
||||
snprintf(path, sizeof(path), DB_CN_FILE);
|
||||
|
||||
if (mmap_file(path, sizeof(struct conn_entry), &m))
|
||||
{
|
||||
fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < m.size; i += sizeof(struct conn_entry))
|
||||
{
|
||||
e = (struct conn_entry *) &m.mmap[i];
|
||||
|
||||
if (!e->time)
|
||||
continue;
|
||||
|
||||
printf("[ %" PRIu64 ", %u, %u ]%s\n",
|
||||
ntohll(e->time), ntohl(e->udp), ntohl(e->tcp),
|
||||
((i + sizeof(struct conn_entry)) < m.size) ? "," : "");
|
||||
}
|
||||
|
||||
umap_file(&m);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int run_dump_load(void)
|
||||
{
|
||||
int rv = 1;
|
||||
|
||||
int i, file;
|
||||
int entrysize = sizeof(struct load_entry);
|
||||
int mapsize = STEP_COUNT * entrysize;
|
||||
|
||||
int i;
|
||||
char path[1024];
|
||||
char *map;
|
||||
|
||||
struct file_map m;
|
||||
struct load_entry *e;
|
||||
|
||||
snprintf(path, sizeof(path), DB_LD_FILE);
|
||||
|
||||
if ((file = open(path, O_RDONLY)) >= 0)
|
||||
{
|
||||
map = mmap(NULL, mapsize, PROT_READ, MAP_SHARED | MAP_LOCKED, file, 0);
|
||||
|
||||
if ((map != NULL) && (map != MAP_FAILED))
|
||||
{
|
||||
for (i = 0; i < mapsize; i += entrysize)
|
||||
{
|
||||
e = (struct load_entry *) &map[i];
|
||||
|
||||
if (!e->time)
|
||||
continue;
|
||||
|
||||
printf("[ %" PRIu64 ", %u, %u, %u ]%s\n",
|
||||
ntohll(e->time),
|
||||
ntohs(e->load1), ntohs(e->load5), ntohs(e->load15),
|
||||
((i + entrysize) < mapsize) ? "," : "");
|
||||
}
|
||||
|
||||
munmap(map, mapsize);
|
||||
rv = 0;
|
||||
}
|
||||
|
||||
close(file);
|
||||
}
|
||||
else
|
||||
if (mmap_file(path, sizeof(struct load_entry), &m))
|
||||
{
|
||||
fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
return rv;
|
||||
for (i = 0; i < m.size; i += sizeof(struct load_entry))
|
||||
{
|
||||
e = (struct load_entry *) &m.mmap[i];
|
||||
|
||||
if (!e->time)
|
||||
continue;
|
||||
|
||||
printf("[ %" PRIu64 ", %u, %u, %u ]%s\n",
|
||||
ntohll(e->time),
|
||||
ntohs(e->load1), ntohs(e->load5), ntohs(e->load15),
|
||||
((i + sizeof(struct load_entry)) < m.size) ? "," : "");
|
||||
}
|
||||
|
||||
umap_file(&m);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -412,11 +480,8 @@ int main(int argc, char *argv[])
|
|||
int opt;
|
||||
int daemon = 0;
|
||||
int nofork = 0;
|
||||
int iprint = 0;
|
||||
int lprint = 0;
|
||||
char *ifname = NULL;
|
||||
|
||||
while ((opt = getopt(argc, argv, "dfi:l")) > -1)
|
||||
while ((opt = getopt(argc, argv, "dfi:cl")) > -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
|
@ -429,13 +494,15 @@ int main(int argc, char *argv[])
|
|||
break;
|
||||
|
||||
case 'i':
|
||||
iprint = 1;
|
||||
ifname = optarg;
|
||||
if (optarg)
|
||||
return run_dump_ifname(optarg);
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
return run_dump_conns();
|
||||
|
||||
case 'l':
|
||||
lprint = 1;
|
||||
break;
|
||||
return run_dump_load();
|
||||
|
||||
default:
|
||||
break;
|
||||
|
@ -445,19 +512,14 @@ int main(int argc, char *argv[])
|
|||
if (daemon)
|
||||
return run_daemon(nofork);
|
||||
|
||||
else if (iprint && ifname)
|
||||
return run_dump_ifname(ifname);
|
||||
|
||||
else if (lprint)
|
||||
return run_dump_load();
|
||||
|
||||
else
|
||||
fprintf(stderr,
|
||||
"Usage:\n"
|
||||
" %s -d [-f]\n"
|
||||
" %s -i ifname\n"
|
||||
" %s -c\n"
|
||||
" %s -l\n",
|
||||
argv[0], argv[0], argv[0]
|
||||
argv[0], argv[0], argv[0], argv[0]
|
||||
);
|
||||
|
||||
return 1;
|
||||
|
|
Loading…
Reference in a new issue