mirror of
https://github.com/Ysurac/openmptcprouter-feeds.git
synced 2025-02-12 10:31:51 +00:00
Disable processes list for now
This commit is contained in:
parent
509718c5cd
commit
0737e27eb8
27 changed files with 3496 additions and 0 deletions
18
luci-mod-status/Makefile
Normal file
18
luci-mod-status/Makefile
Normal file
|
@ -0,0 +1,18 @@
|
|||
#
|
||||
# Copyright (C) 2008-2014 The LuCI Team <luci@lists.subsignal.org>
|
||||
#
|
||||
# This is free software, licensed under the Apache License, Version 2.0 .
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
LUCI_TITLE:=LuCI Status Pages
|
||||
LUCI_DEPENDS:=+luci-base +libiwinfo +libiwinfo-lua
|
||||
|
||||
PKG_BUILD_DEPENDS:=iwinfo
|
||||
PKG_LICENSE:=Apache-2.0
|
||||
|
||||
include ../luci/luci.mk
|
||||
|
||||
# call BuildPackage - OpenWrt buildroot signature
|
||||
|
16
luci-mod-status/htdocs/luci-static/resources/bandwidth.svg
Normal file
16
luci-mod-status/htdocs/luci-static/resources/bandwidth.svg
Normal file
|
@ -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">
|
||||
<polyline id="rx" points="" style="fill:blue;fill-opacity:0.4;stroke:blue;stroke-width:1" />
|
||||
<polyline id="tx" points="" style="fill:green;fill-opacity:0.4;stroke:green;stroke-width:1" />
|
||||
|
||||
<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:#eee; font-size:9pt; font-family:sans-serif; text-shadow:1px 1px 1px #000"> </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:#eee; font-size:9pt; font-family:sans-serif; text-shadow:1px 1px 1px #000"> </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:#eee; font-size:9pt; font-family:sans-serif; text-shadow:1px 1px 1px #000"> </text>
|
||||
</svg>
|
After Width: | Height: | Size: 1 KiB |
17
luci-mod-status/htdocs/luci-static/resources/connections.svg
Normal file
17
luci-mod-status/htdocs/luci-static/resources/connections.svg
Normal file
|
@ -0,0 +1,17 @@
|
|||
<?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">
|
||||
<polyline id="tcp" points="" style="fill:green;fill-opacity:0.4;stroke:green;stroke-width:1" />
|
||||
<polyline id="udp" points="" style="fill:blue;fill-opacity:0.4;stroke:blue;stroke-width:1" />
|
||||
<polyline id="other" points="" style="fill:red;fill-opacity:0.4;stroke:red;stroke-width:1" />
|
||||
|
||||
<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:#eee; font-size:9pt; font-family:sans-serif; text-shadow:1px 1px 1px #000"> </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:#eee; font-size:9pt; font-family:sans-serif; text-shadow:1px 1px 1px #000"> </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:#eee; font-size:9pt; font-family:sans-serif; text-shadow:1px 1px 1px #000"> </text>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
17
luci-mod-status/htdocs/luci-static/resources/load.svg
Normal file
17
luci-mod-status/htdocs/luci-static/resources/load.svg
Normal file
|
@ -0,0 +1,17 @@
|
|||
<?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">
|
||||
<polyline id="load01" points="" style="fill:#ff0000;fill-opacity:0.4;stroke:#ff0000;stroke-width:1" />
|
||||
<polyline id="load05" points="" style="fill:#ff6600;fill-opacity:0.4;stroke:#ff6600;stroke-width:1" />
|
||||
<polyline id="load15" points="" style="fill:#ffaa00;fill-opacity:0.4;stroke:#ffaa00;stroke-width:1" />
|
||||
|
||||
<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:#eee; font-size:9pt; font-family:sans-serif; text-shadow:1px 1px 1px #000"> </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:#eee; font-size:9pt; font-family:sans-serif; text-shadow:1px 1px 1px #000"> </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:#eee; font-size:9pt; font-family:sans-serif; text-shadow:1px 1px 1px #000"> </text>
|
||||
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
|
@ -0,0 +1,239 @@
|
|||
function progressbar(query, value, max, byte)
|
||||
{
|
||||
var pg = document.querySelector(query),
|
||||
vn = parseInt(value) || 0,
|
||||
mn = parseInt(max) || 100,
|
||||
fv = byte ? String.format('%1024.2mB', value) : value,
|
||||
fm = byte ? String.format('%1024.2mB', max) : max,
|
||||
pc = Math.floor((100 / mn) * vn);
|
||||
|
||||
if (pg) {
|
||||
pg.firstElementChild.style.width = pc + '%';
|
||||
pg.setAttribute('title', '%s / %s (%d%%)'.format(fv, fm, pc));
|
||||
}
|
||||
}
|
||||
|
||||
function renderBox(title, active, childs) {
|
||||
childs = childs || [];
|
||||
childs.unshift(L.itemlist(E('span'), [].slice.call(arguments, 3)));
|
||||
|
||||
return E('div', { class: 'ifacebox' }, [
|
||||
E('div', { class: 'ifacebox-head center ' + (active ? 'active' : '') },
|
||||
E('strong', title)),
|
||||
E('div', { class: 'ifacebox-body left' }, childs)
|
||||
]);
|
||||
}
|
||||
|
||||
function renderBadge(icon, title) {
|
||||
return E('span', { class: 'ifacebadge' }, [
|
||||
E('img', { src: icon, title: title || '' }),
|
||||
L.itemlist(E('span'), [].slice.call(arguments, 2))
|
||||
]);
|
||||
}
|
||||
|
||||
L.poll(5, L.location(), { status: 1 },
|
||||
function(x, info)
|
||||
{
|
||||
var us = document.getElementById('upstream_status_table');
|
||||
|
||||
while (us.lastElementChild)
|
||||
us.removeChild(us.lastElementChild);
|
||||
|
||||
var wan_list = info.wan || [];
|
||||
|
||||
for (var i = 0; i < wan_list.length; i++) {
|
||||
var ifc = wan_list[i];
|
||||
|
||||
us.appendChild(renderBox(
|
||||
_('IPv4 Upstream'),
|
||||
(ifc.ifname && ifc.proto != 'none'),
|
||||
[ E('div', {}, renderBadge(
|
||||
L.resource('icons/%s.png').format((ifc && ifc.type) ? ifc.type : 'ethernet_disabled'), null,
|
||||
_('Device'), ifc ? (ifc.name || ifc.ifname || '-') : '-',
|
||||
_('MAC-Address'), (ifc && ifc.ether) ? ifc.mac : null)) ],
|
||||
_('Protocol'), ifc.i18n || E('em', _('Not connected')),
|
||||
_('Address'), (ifc.ipaddrs) ? ifc.ipaddrs[0] : null,
|
||||
_('Address'), (ifc.ipaddrs) ? ifc.ipaddrs[1] : null,
|
||||
_('Address'), (ifc.ipaddrs) ? ifc.ipaddrs[2] : null,
|
||||
_('Address'), (ifc.ipaddrs) ? ifc.ipaddrs[3] : null,
|
||||
_('Address'), (ifc.ipaddrs) ? ifc.ipaddrs[4] : null,
|
||||
_('Address'), (ifc.ipaddrs) ? ifc.ipaddrs[5] : null,
|
||||
_('Address'), (ifc.ipaddrs) ? ifc.ipaddrs[6] : null,
|
||||
_('Address'), (ifc.ipaddrs) ? ifc.ipaddrs[7] : null,
|
||||
_('Address'), (ifc.ipaddrs) ? ifc.ipaddrs[8] : null,
|
||||
_('Address'), (ifc.ipaddrs) ? ifc.ipaddrs[9] : null,
|
||||
_('Gateway'), (ifc.gwaddr) ? ifc.gwaddr : '0.0.0.0',
|
||||
_('DNS') + ' 1', (ifc.dns) ? ifc.dns[0] : null,
|
||||
_('DNS') + ' 2', (ifc.dns) ? ifc.dns[1] : null,
|
||||
_('DNS') + ' 3', (ifc.dns) ? ifc.dns[2] : null,
|
||||
_('DNS') + ' 4', (ifc.dns) ? ifc.dns[3] : null,
|
||||
_('DNS') + ' 5', (ifc.dns) ? ifc.dns[4] : null,
|
||||
_('Expires'), (ifc.expires > -1) ? '%t'.format(ifc.expires) : null,
|
||||
_('Connected'), (ifc.uptime > 0) ? '%t'.format(ifc.uptime) : null));
|
||||
}
|
||||
|
||||
var wan6_list = info.wan6 || [];
|
||||
|
||||
for (var i = 0; i < wan6_list.length; i++) {
|
||||
var ifc6 = wan6_list[i];
|
||||
|
||||
us.appendChild(renderBox(
|
||||
_('IPv6 Upstream'),
|
||||
(ifc6.ifname && ifc6.proto != 'none'),
|
||||
[ E('div', {}, renderBadge(
|
||||
L.resource('icons/%s.png').format(ifc6.type || 'ethernet_disabled'), null,
|
||||
_('Device'), ifc6 ? (ifc6.name || ifc6.ifname || '-') : '-',
|
||||
_('MAC-Address'), (ifc6 && ifc6.ether) ? ifc6.mac : null)) ],
|
||||
_('Protocol'), ifc6.i18n ? (ifc6.i18n + (ifc6.proto === 'dhcp' && ifc6.ip6prefix ? '-PD' : '')) : E('em', _('Not connected')),
|
||||
_('Prefix Delegated'), ifc6.ip6prefix,
|
||||
_('Address'), (ifc6.ip6addrs) ? ifc6.ip6addrs[0] : null,
|
||||
_('Address'), (ifc6.ip6addrs) ? ifc6.ip6addrs[1] : null,
|
||||
_('Address'), (ifc6.ip6addrs) ? ifc6.ip6addrs[2] : null,
|
||||
_('Address'), (ifc6.ip6addrs) ? ifc6.ip6addrs[3] : null,
|
||||
_('Address'), (ifc6.ip6addrs) ? ifc6.ip6addrs[4] : null,
|
||||
_('Address'), (ifc6.ip6addrs) ? ifc6.ip6addrs[5] : null,
|
||||
_('Address'), (ifc6.ip6addrs) ? ifc6.ip6addrs[6] : null,
|
||||
_('Address'), (ifc6.ip6addrs) ? ifc6.ip6addrs[7] : null,
|
||||
_('Address'), (ifc6.ip6addrs) ? ifc6.ip6addrs[8] : null,
|
||||
_('Address'), (ifc6.ip6addrs) ? ifc6.ip6addrs[9] : null,
|
||||
_('Gateway'), (ifc6.gw6addr) ? ifc6.gw6addr : '::',
|
||||
_('DNS') + ' 1', (ifc6.dns) ? ifc6.dns[0] : null,
|
||||
_('DNS') + ' 2', (ifc6.dns) ? ifc6.dns[1] : null,
|
||||
_('DNS') + ' 3', (ifc6.dns) ? ifc6.dns[2] : null,
|
||||
_('DNS') + ' 4', (ifc6.dns) ? ifc6.dns[3] : null,
|
||||
_('DNS') + ' 5', (ifc6.dns) ? ifc6.dns[4] : null,
|
||||
_('Connected'), (ifc6.uptime > 0) ? '%t'.format(ifc6.uptime) : null));
|
||||
}
|
||||
|
||||
var ds = document.getElementById('dsl_status_table');
|
||||
if (ds) {
|
||||
while (ds.lastElementChild)
|
||||
ds.removeChild(ds.lastElementChild);
|
||||
|
||||
ds.appendChild(renderBox(
|
||||
_('DSL Status'),
|
||||
(info.dsl.line_state === 'UP'), [ ],
|
||||
_('Line State'), '%s [0x%x]'.format(info.dsl.line_state, info.dsl.line_state_detail),
|
||||
_('Line Mode'), info.dsl.line_mode_s || '-',
|
||||
_('Line Uptime'), info.dsl.line_uptime_s || '-',
|
||||
_('Annex'), info.dsl.annex_s || '-',
|
||||
_('Profile'), info.dsl.profile_s || '-',
|
||||
_('Data Rate'), '%s/s / %s/s'.format(info.dsl.data_rate_down_s, info.dsl.data_rate_up_s),
|
||||
_('Max. Attainable Data Rate (ATTNDR)'), '%s/s / %s/s'.format(info.dsl.max_data_rate_down_s, info.dsl.max_data_rate_up_s),
|
||||
_('Latency'), '%s / %s'.format(info.dsl.latency_num_down, info.dsl.latency_num_up),
|
||||
_('Line Attenuation (LATN)'), '%.1f dB / %.1f dB'.format(info.dsl.line_attenuation_down, info.dsl.line_attenuation_up),
|
||||
_('Signal Attenuation (SATN)'), '%.1f dB / %.1f dB'.format(info.dsl.signal_attenuation_down, info.dsl.signal_attenuation_up),
|
||||
_('Noise Margin (SNR)'), '%.1f dB / %.1f dB'.format(info.dsl.noise_margin_down, info.dsl.noise_margin_up),
|
||||
_('Aggregate Transmit Power(ACTATP)'), '%.1f dB / %.1f dB'.format(info.dsl.actatp_down, info.dsl.actatp_up),
|
||||
_('Forward Error Correction Seconds (FECS)'), '%d / %d'.format(info.dsl.errors_fec_near, info.dsl.errors_fec_far),
|
||||
_('Errored seconds (ES)'), '%d / %d'.format(info.dsl.errors_es_near, info.dsl.errors_es_far),
|
||||
_('Severely Errored Seconds (SES)'), '%d / %d'.format(info.dsl.errors_ses_near, info.dsl.errors_ses_far),
|
||||
_('Loss of Signal Seconds (LOSS)'), '%d / %d'.format(info.dsl.errors_loss_near, info.dsl.errors_loss_far),
|
||||
_('Unavailable Seconds (UAS)'), '%d / %d'.format(info.dsl.errors_uas_near, info.dsl.errors_uas_far),
|
||||
_('Header Error Code Errors (HEC)'), '%d / %d'.format(info.dsl.errors_hec_near, info.dsl.errors_hec_far),
|
||||
_('Non Pre-emtive CRC errors (CRC_P)'), '%d / %d'.format(info.dsl.errors_crc_p_near, info.dsl.errors_crc_p_far),
|
||||
_('Pre-emtive CRC errors (CRCP_P)'), '%d / %d'.format(info.dsl.errors_crcp_p_near, info.dsl.errors_crcp_p_far),
|
||||
_('ATU-C System Vendor ID'), info.dsl.atuc_vendor_id,
|
||||
_('Power Management Mode'), info.dsl.power_mode_s));
|
||||
}
|
||||
|
||||
var ws = document.getElementById('wifi_status_table');
|
||||
if (ws)
|
||||
{
|
||||
while (ws.lastElementChild)
|
||||
ws.removeChild(ws.lastElementChild);
|
||||
|
||||
for (var didx = 0; didx < info.wifinets.length; didx++)
|
||||
{
|
||||
var dev = info.wifinets[didx];
|
||||
var net0 = (dev.networks && dev.networks[0]) ? dev.networks[0] : {};
|
||||
var vifs = [];
|
||||
|
||||
for (var nidx = 0; nidx < dev.networks.length; nidx++)
|
||||
{
|
||||
var net = dev.networks[nidx];
|
||||
var is_assoc = (net.bssid != '00:00:00:00:00:00' && net.channel && !net.disabled);
|
||||
|
||||
var icon;
|
||||
if (net.disabled)
|
||||
icon = L.resource('icons/signal-none.png');
|
||||
else if (net.quality <= 0)
|
||||
icon = L.resource('icons/signal-0.png');
|
||||
else if (net.quality < 25)
|
||||
icon = L.resource('icons/signal-0-25.png');
|
||||
else if (net.quality < 50)
|
||||
icon = L.resource('icons/signal-25-50.png');
|
||||
else if (net.quality < 75)
|
||||
icon = L.resource('icons/signal-50-75.png');
|
||||
else
|
||||
icon = L.resource('icons/signal-75-100.png');
|
||||
|
||||
vifs.push(renderBadge(
|
||||
icon,
|
||||
'%s: %d dBm / %s: %d%%'.format(_('Signal'), net.signal, _('Quality'), net.quality),
|
||||
_('SSID'), E('a', { href: net.link }, [ net.ssid || '?' ]),
|
||||
_('Mode'), net.mode,
|
||||
_('BSSID'), is_assoc ? (net.bssid || '-') : null,
|
||||
_('Encryption'), is_assoc ? net.encryption : null,
|
||||
_('Associations'), is_assoc ? (net.num_assoc || '-') : null,
|
||||
null, is_assoc ? null : E('em', net.disabled ? _('Wireless is disabled') : _('Wireless is not associated'))));
|
||||
}
|
||||
|
||||
ws.appendChild(renderBox(
|
||||
dev.device, dev.up || net0.up,
|
||||
[ E('div', vifs) ],
|
||||
_('Type'), dev.name.replace(/^Generic | Wireless Controller .+$/g, ''),
|
||||
_('Channel'), net0.channel ? '%d (%.3f %s)'.format(net0.channel, net0.frequency, _('GHz')) : '-',
|
||||
_('Bitrate'), net0.bitrate ? '%d %s'.format(net0.bitrate, _('Mbit/s')) : '-'));
|
||||
}
|
||||
|
||||
if (!ws.lastElementChild)
|
||||
ws.appendChild(E('em', _('No information available')));
|
||||
}
|
||||
|
||||
var e;
|
||||
|
||||
if (e = document.getElementById('localtime'))
|
||||
e.innerHTML = info.localtime;
|
||||
|
||||
if (e = document.getElementById('uptime'))
|
||||
e.innerHTML = String.format('%t', info.uptime);
|
||||
|
||||
if (e = document.getElementById('loadavg'))
|
||||
e.innerHTML = String.format(
|
||||
'%.02f, %.02f, %.02f',
|
||||
info.loadavg[0] / 65535.0,
|
||||
info.loadavg[1] / 65535.0,
|
||||
info.loadavg[2] / 65535.0
|
||||
);
|
||||
|
||||
progressbar('#memtotal',
|
||||
info.memory.free + info.memory.buffered,
|
||||
info.memory.total,
|
||||
true);
|
||||
|
||||
progressbar('#memfree',
|
||||
info.memory.free,
|
||||
info.memory.total,
|
||||
true);
|
||||
|
||||
progressbar('#membuff',
|
||||
info.memory.buffered,
|
||||
info.memory.total,
|
||||
true);
|
||||
|
||||
progressbar('#swaptotal',
|
||||
info.swap.free,
|
||||
info.swap.total,
|
||||
true);
|
||||
|
||||
progressbar('#swapfree',
|
||||
info.swap.free,
|
||||
info.swap.total,
|
||||
true);
|
||||
|
||||
progressbar('#conns',
|
||||
info.conncount, info.connmax, false);
|
||||
|
||||
}
|
||||
);
|
|
@ -0,0 +1,253 @@
|
|||
var table_names = [ 'Filter', 'NAT', 'Mangle', 'Raw' ],
|
||||
current_mode = document.querySelector('.cbi-tab[data-mode="6"]') ? 6 : 4;
|
||||
|
||||
function create_table_section(table)
|
||||
{
|
||||
var idiv = document.getElementById('iptables'),
|
||||
tdiv = idiv.querySelector('[data-table="%s"]'.format(table)),
|
||||
title = '%s: %s'.format(_('Table'), table);
|
||||
|
||||
if (!tdiv) {
|
||||
tdiv = E('div', { 'data-table': table }, [
|
||||
E('h3', {}, title),
|
||||
E('div')
|
||||
]);
|
||||
|
||||
if (idiv.firstElementChild.nodeName.toLowerCase() === 'p')
|
||||
idiv.removeChild(idiv.firstElementChild);
|
||||
|
||||
var added = false, thisIdx = table_names.indexOf(table);
|
||||
|
||||
idiv.querySelectorAll('[data-table]').forEach(function(child) {
|
||||
var childIdx = table_names.indexOf(child.getAttribute('data-table'));
|
||||
|
||||
if (added === false && childIdx > thisIdx) {
|
||||
idiv.insertBefore(tdiv, child);
|
||||
added = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (added === false)
|
||||
idiv.appendChild(tdiv);
|
||||
}
|
||||
|
||||
return tdiv.lastElementChild;
|
||||
}
|
||||
|
||||
function create_chain_section(table, chain, policy, packets, bytes, references)
|
||||
{
|
||||
var tdiv = create_table_section(table),
|
||||
cdiv = tdiv.querySelector('[data-chain="%s"]'.format(chain)),
|
||||
title;
|
||||
|
||||
if (policy)
|
||||
title = '%s <em>%s</em> <span>(%s: <em>%s</em>, %d %s, %.2mB %s)</span>'
|
||||
.format(_('Chain'), chain, _('Policy'), policy, packets, _('Packets'), bytes, _('Traffic'));
|
||||
else
|
||||
title = '%s <em>%s</em> <span class="references">(%d %s)</span>'
|
||||
.format(_('Chain'), chain, references, _('References'));
|
||||
|
||||
if (!cdiv) {
|
||||
cdiv = E('div', { 'data-chain': chain }, [
|
||||
E('h4', { 'id': 'rule_%s_%s'.format(table.toLowerCase(), chain) }, title),
|
||||
E('div', { 'class': 'table' }, [
|
||||
E('div', { 'class': 'tr table-titles' }, [
|
||||
E('div', { 'class': 'th center' }, _('Pkts.')),
|
||||
E('div', { 'class': 'th center' }, _('Traffic')),
|
||||
E('div', { 'class': 'th' }, _('Target')),
|
||||
E('div', { 'class': 'th' }, _('Prot.')),
|
||||
E('div', { 'class': 'th' }, _('In')),
|
||||
E('div', { 'class': 'th' }, _('Out')),
|
||||
E('div', { 'class': 'th' }, _('Source')),
|
||||
E('div', { 'class': 'th' }, _('Destination')),
|
||||
E('div', { 'class': 'th' }, _('Options')),
|
||||
E('div', { 'class': 'th' }, _('Comment'))
|
||||
])
|
||||
])
|
||||
]);
|
||||
|
||||
tdiv.appendChild(cdiv);
|
||||
}
|
||||
else {
|
||||
cdiv.firstElementChild.innerHTML = title;
|
||||
}
|
||||
|
||||
return cdiv.lastElementChild;
|
||||
}
|
||||
|
||||
function update_chain_section(chaintable, rows)
|
||||
{
|
||||
if (!chaintable)
|
||||
return;
|
||||
|
||||
cbi_update_table(chaintable, rows, _('No rules in this chain.'));
|
||||
|
||||
if (rows.length === 0 &&
|
||||
document.querySelector('form > [data-hide-empty="true"]'))
|
||||
chaintable.parentNode.style.display = 'none';
|
||||
else
|
||||
chaintable.parentNode.style.display = '';
|
||||
|
||||
chaintable.parentNode.setAttribute('data-empty', rows.length === 0);
|
||||
}
|
||||
|
||||
function hide_empty(btn)
|
||||
{
|
||||
var hide = (btn.getAttribute('data-hide-empty') === 'false');
|
||||
|
||||
btn.setAttribute('data-hide-empty', hide);
|
||||
btn.value = hide ? _('Show empty chains') : _('Hide empty chains');
|
||||
btn.blur();
|
||||
|
||||
document.querySelectorAll('[data-chain][data-empty="true"]')
|
||||
.forEach(function(chaintable) {
|
||||
chaintable.style.display = hide ? 'none' : '';
|
||||
});
|
||||
}
|
||||
|
||||
function jump_target(ev)
|
||||
{
|
||||
var link = ev.target,
|
||||
table = findParent(link, '[data-table]').getAttribute('data-table'),
|
||||
chain = link.textContent,
|
||||
num = +link.getAttribute('data-num'),
|
||||
elem = document.getElementById('rule_%s_%s'.format(table.toLowerCase(), chain));
|
||||
|
||||
if (elem) {
|
||||
(document.documentElement || document.body.parentNode || document.body).scrollTop = elem.offsetTop - 40;
|
||||
elem.classList.remove('flash');
|
||||
void elem.offsetWidth;
|
||||
elem.classList.add('flash');
|
||||
|
||||
if (num) {
|
||||
var rule = elem.nextElementSibling.childNodes[num];
|
||||
if (rule) {
|
||||
rule.classList.remove('flash');
|
||||
void rule.offsetWidth;
|
||||
rule.classList.add('flash');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function parse_output(table, s)
|
||||
{
|
||||
var current_chain = null;
|
||||
var current_rules = [];
|
||||
var seen_chains = {};
|
||||
var chain_refs = {};
|
||||
var re = /([^\n]*)\n/g;
|
||||
var m, m2;
|
||||
|
||||
while ((m = re.exec(s)) != null) {
|
||||
if (m[1].match(/^Chain (.+) \(policy (\w+) (\d+) packets, (\d+) bytes\)$/)) {
|
||||
var chain = RegExp.$1,
|
||||
policy = RegExp.$2,
|
||||
packets = +RegExp.$3,
|
||||
bytes = +RegExp.$4;
|
||||
|
||||
update_chain_section(current_chain, current_rules);
|
||||
|
||||
seen_chains[chain] = true;
|
||||
current_chain = create_chain_section(table, chain, policy, packets, bytes);
|
||||
current_rules = [];
|
||||
}
|
||||
else if (m[1].match(/^Chain (.+) \((\d+) references\)$/)) {
|
||||
var chain = RegExp.$1,
|
||||
references = +RegExp.$2;
|
||||
|
||||
update_chain_section(current_chain, current_rules);
|
||||
|
||||
seen_chains[chain] = true;
|
||||
current_chain = create_chain_section(table, chain, null, null, null, references);
|
||||
current_rules = [];
|
||||
}
|
||||
else if (m[1].match(/^num /)) {
|
||||
continue;
|
||||
}
|
||||
else if ((m2 = m[1].match(/^(\d+) +(\d+) +(\d+) +(.*?) +(\S+) +(\S*) +(\S+) +(\S+) +([a-f0-9:.]+(?:\/[a-f0-9:.]+)?) +([a-f0-9:.]+(?:\/[a-f0-9:.]+)?) +(.+)$/)) !== null) {
|
||||
var num = +m2[1],
|
||||
pkts = +m2[2],
|
||||
bytes = +m2[3],
|
||||
target = m2[4],
|
||||
proto = m2[5],
|
||||
indev = m2[7],
|
||||
outdev = m2[8],
|
||||
srcnet = m2[9],
|
||||
dstnet = m2[10],
|
||||
options = m2[11] || '-',
|
||||
comment = '-';
|
||||
|
||||
options = options.trim().replace(/(?:^| )\/\* (.+) \*\//,
|
||||
function(m1, m2) {
|
||||
comment = m2.replace(/^!fw3(: |$)/, '').trim() || '-';
|
||||
return '';
|
||||
}) || '-';
|
||||
|
||||
current_rules.push([
|
||||
'%.2m'.format(pkts).nobr(),
|
||||
'%.2mB'.format(bytes).nobr(),
|
||||
target ? '<span class="target">%s</span>'.format(target) : '-',
|
||||
proto,
|
||||
(indev !== '*') ? '<span class="ifacebadge">%s</span>'.format(indev) : '*',
|
||||
(outdev !== '*') ? '<span class="ifacebadge">%s</span>'.format(outdev) : '*',
|
||||
srcnet,
|
||||
dstnet,
|
||||
options,
|
||||
comment
|
||||
]);
|
||||
|
||||
if (target) {
|
||||
chain_refs[target] = chain_refs[target] || [];
|
||||
chain_refs[target].push([ current_chain, num ]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
update_chain_section(current_chain, current_rules);
|
||||
|
||||
document.querySelectorAll('[data-table="%s"] [data-chain]'.format(table))
|
||||
.forEach(function(cdiv) {
|
||||
if (!seen_chains[cdiv.getAttribute('data-chain')]) {
|
||||
cdiv.parentNode.removeChild(cdiv);
|
||||
return;
|
||||
}
|
||||
|
||||
cdiv.querySelectorAll('.target').forEach(function(tspan) {
|
||||
if (seen_chains[tspan.textContent]) {
|
||||
tspan.classList.add('jump');
|
||||
tspan.addEventListener('click', jump_target);
|
||||
}
|
||||
});
|
||||
|
||||
cdiv.querySelectorAll('.references').forEach(function(rspan) {
|
||||
var refs = chain_refs[cdiv.getAttribute('data-chain')];
|
||||
if (refs && refs.length) {
|
||||
rspan.classList.add('cbi-tooltip-container');
|
||||
rspan.appendChild(E('small', { 'class': 'cbi-tooltip ifacebadge', 'style': 'top:1em; left:auto' }, [ E('ul') ]));
|
||||
|
||||
refs.forEach(function(ref) {
|
||||
var chain = ref[0].parentNode.getAttribute('data-chain'),
|
||||
num = ref[1];
|
||||
|
||||
rspan.lastElementChild.lastElementChild.appendChild(E('li', {}, [
|
||||
_('Chain'), ' ',
|
||||
E('span', {
|
||||
'class': 'jump',
|
||||
'data-num': num,
|
||||
'onclick': 'jump_target(event)'
|
||||
}, chain),
|
||||
', %s #%d'.format(_('Rule'), num)
|
||||
]));
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
table_names.forEach(function(table) {
|
||||
L.poll(5, L.url('admin/status/iptables_dump', current_mode, table.toLowerCase()), null,
|
||||
function (xhr) {
|
||||
parse_output(table, xhr.responseText);
|
||||
});
|
||||
});
|
15
luci-mod-status/htdocs/luci-static/resources/wifirate.svg
Normal file
15
luci-mod-status/htdocs/luci-static/resources/wifirate.svg
Normal file
|
@ -0,0 +1,15 @@
|
|||
<?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">
|
||||
<polyline id="rate" points="" style="fill:green;fill-opacity:0.4;stroke:green;stroke-width:1" />
|
||||
|
||||
<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:#eee; font-size:9pt; font-family:sans-serif; text-shadow:1px 1px 1px #000"> </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:#eee; font-size:9pt; font-family:sans-serif; text-shadow:1px 1px 1px #000"> </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:#eee; font-size:9pt; font-family:sans-serif; text-shadow:1px 1px 1px #000"> </text>
|
||||
</svg>
|
After Width: | Height: | Size: 973 B |
16
luci-mod-status/htdocs/luci-static/resources/wireless.svg
Normal file
16
luci-mod-status/htdocs/luci-static/resources/wireless.svg
Normal file
|
@ -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">
|
||||
<polyline id="rssi" points="" style="fill:blue;fill-opacity:0.4;stroke:blue;stroke-width:1" />
|
||||
<polyline id="noise" points="" style="fill:red;fill-opacity:0.4;stroke:red;stroke-width:1" />
|
||||
|
||||
<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:#eee; font-size:9pt; font-family:sans-serif; text-shadow:1px 1px 1px #000"> </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:#eee; font-size:9pt; font-family:sans-serif; text-shadow:1px 1px 1px #000"> </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:#eee; font-size:9pt; font-family:sans-serif; text-shadow:1px 1px 1px #000"> </text>
|
||||
</svg>
|
After Width: | Height: | Size: 1 KiB |
175
luci-mod-status/luasrc/controller/admin/status.lua
Normal file
175
luci-mod-status/luasrc/controller/admin/status.lua
Normal file
|
@ -0,0 +1,175 @@
|
|||
-- Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
-- Copyright 2011 Jo-Philipp Wich <jow@openwrt.org>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
module("luci.controller.admin.status", package.seeall)
|
||||
|
||||
function index()
|
||||
entry({"admin", "status", "overview"}, template("admin_status/index"), _("Overview"), 1)
|
||||
|
||||
entry({"admin", "status", "iptables"}, template("admin_status/iptables"), _("Firewall"), 2).leaf = true
|
||||
entry({"admin", "status", "iptables_dump"}, call("dump_iptables")).leaf = true
|
||||
entry({"admin", "status", "iptables_action"}, post("action_iptables")).leaf = true
|
||||
|
||||
entry({"admin", "status", "routes"}, template("admin_status/routes"), _("Routes"), 3)
|
||||
entry({"admin", "status", "syslog"}, call("action_syslog"), _("System Log"), 4)
|
||||
entry({"admin", "status", "dmesg"}, call("action_dmesg"), _("Kernel Log"), 5)
|
||||
--entry({"admin", "status", "processes"}, form("admin_status/processes"), _("Processes"), 6)
|
||||
|
||||
entry({"admin", "status", "realtime"}, alias("admin", "status", "realtime", "load"), _("Realtime Graphs"), 7)
|
||||
|
||||
entry({"admin", "status", "realtime", "load"}, template("admin_status/load"), _("Load"), 1).leaf = true
|
||||
entry({"admin", "status", "realtime", "load_status"}, call("action_load")).leaf = true
|
||||
|
||||
entry({"admin", "status", "realtime", "bandwidth"}, template("admin_status/bandwidth"), _("Traffic"), 2).leaf = true
|
||||
entry({"admin", "status", "realtime", "bandwidth_status"}, call("action_bandwidth")).leaf = true
|
||||
|
||||
if nixio.fs.access("/etc/config/wireless") then
|
||||
entry({"admin", "status", "realtime", "wireless"}, template("admin_status/wireless"), _("Wireless"), 3).leaf = true
|
||||
entry({"admin", "status", "realtime", "wireless_status"}, call("action_wireless")).leaf = true
|
||||
end
|
||||
|
||||
entry({"admin", "status", "realtime", "connections"}, template("admin_status/connections"), _("Connections"), 4).leaf = true
|
||||
entry({"admin", "status", "realtime", "connections_status"}, call("action_connections")).leaf = true
|
||||
|
||||
entry({"admin", "status", "nameinfo"}, call("action_nameinfo")).leaf = true
|
||||
end
|
||||
|
||||
function action_syslog()
|
||||
local syslog = luci.sys.syslog()
|
||||
luci.template.render("admin_status/syslog", {syslog=syslog})
|
||||
end
|
||||
|
||||
function action_dmesg()
|
||||
local dmesg = luci.sys.dmesg()
|
||||
luci.template.render("admin_status/dmesg", {dmesg=dmesg})
|
||||
end
|
||||
|
||||
function dump_iptables(family, table)
|
||||
local prefix = (family == "6") and "ip6" or "ip"
|
||||
local ok, lines = pcall(io.lines, "/proc/net/%s_tables_names" % prefix)
|
||||
if ok and lines then
|
||||
local s
|
||||
for s in lines do
|
||||
if s == table then
|
||||
luci.http.prepare_content("text/plain")
|
||||
luci.sys.process.exec({
|
||||
"/usr/sbin/%stables" % prefix, "-w", "-t", table,
|
||||
"--line-numbers", "-nxvL"
|
||||
}, luci.http.write)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
luci.http.status(404, "No such table")
|
||||
luci.http.prepare_content("text/plain")
|
||||
end
|
||||
|
||||
function action_iptables()
|
||||
if luci.http.formvalue("zero") then
|
||||
if luci.http.formvalue("family") == "6" then
|
||||
luci.util.exec("/usr/sbin/ip6tables -Z")
|
||||
else
|
||||
luci.util.exec("/usr/sbin/iptables -Z")
|
||||
end
|
||||
elseif luci.http.formvalue("restart") then
|
||||
luci.util.exec("/etc/init.d/firewall restart")
|
||||
end
|
||||
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin/status/iptables"))
|
||||
end
|
||||
|
||||
function action_bandwidth(iface)
|
||||
luci.http.prepare_content("application/json")
|
||||
|
||||
local bwc = io.popen("luci-bwc -i %s 2>/dev/null"
|
||||
% luci.util.shellquote(iface))
|
||||
|
||||
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
|
||||
end
|
||||
|
||||
function action_wireless(iface)
|
||||
luci.http.prepare_content("application/json")
|
||||
|
||||
local bwc = io.popen("luci-bwc -r %s 2>/dev/null"
|
||||
% luci.util.shellquote(iface))
|
||||
|
||||
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
|
||||
end
|
||||
|
||||
function action_load()
|
||||
luci.http.prepare_content("application/json")
|
||||
|
||||
local bwc = io.popen("luci-bwc -l 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
|
||||
end
|
||||
|
||||
function action_connections()
|
||||
local sys = require "luci.sys"
|
||||
|
||||
luci.http.prepare_content("application/json")
|
||||
|
||||
luci.http.write('{ "connections": ')
|
||||
luci.http.write_json(sys.net.conntrack())
|
||||
|
||||
local bwc = io.popen("luci-bwc -c 2>/dev/null")
|
||||
if bwc then
|
||||
luci.http.write(', "statistics": [')
|
||||
|
||||
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
|
||||
|
||||
luci.http.write(" }")
|
||||
end
|
||||
|
||||
function action_nameinfo(...)
|
||||
local util = require "luci.util"
|
||||
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(util.ubus("network.rrdns", "lookup", {
|
||||
addrs = { ... },
|
||||
timeout = 5000,
|
||||
limit = 1000
|
||||
}) or { })
|
||||
end
|
34
luci-mod-status/luasrc/model/cbi/admin_status/processes.lua
Normal file
34
luci-mod-status/luasrc/model/cbi/admin_status/processes.lua
Normal file
|
@ -0,0 +1,34 @@
|
|||
-- Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
-- Copyright 2008 Jo-Philipp Wich <jow@openwrt.org>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
f = SimpleForm("processes", translate("Processes"), translate("This list gives an overview over currently running system processes and their status."))
|
||||
f.reset = false
|
||||
f.submit = false
|
||||
|
||||
t = f:section(Table, luci.sys.process.list())
|
||||
t:option(DummyValue, "PID", translate("PID"))
|
||||
t:option(DummyValue, "USER", translate("Owner"))
|
||||
t:option(DummyValue, "COMMAND", translate("Command"))
|
||||
t:option(DummyValue, "%CPU", translate("CPU usage (%)"))
|
||||
t:option(DummyValue, "%MEM", translate("Memory usage (%)"))
|
||||
|
||||
hup = t:option(Button, "_hup", translate("Hang Up"))
|
||||
hup.inputstyle = "reload"
|
||||
function hup.write(self, section)
|
||||
null, self.tag_error[section] = luci.sys.process.signal(section, 1)
|
||||
end
|
||||
|
||||
term = t:option(Button, "_term", translate("Terminate"))
|
||||
term.inputstyle = "remove"
|
||||
function term.write(self, section)
|
||||
null, self.tag_error[section] = luci.sys.process.signal(section, 15)
|
||||
end
|
||||
|
||||
kill = t:option(Button, "_kill", translate("Kill"))
|
||||
kill.inputstyle = "reset"
|
||||
function kill.write(self, section)
|
||||
null, self.tag_error[section] = luci.sys.process.signal(section, 9)
|
||||
end
|
||||
|
||||
return f
|
308
luci-mod-status/luasrc/view/admin_status/bandwidth.htm
Normal file
308
luci-mod-status/luasrc/view/admin_status/bandwidth.htm
Normal file
|
@ -0,0 +1,308 @@
|
|||
<%#
|
||||
Copyright 2010-2018 Jo-Philipp Wich <jo@mein.io>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<%-
|
||||
local ntm = require "luci.model.network".init()
|
||||
|
||||
local dev
|
||||
local devices = { }
|
||||
for _, dev in luci.util.vspairs(luci.sys.net.devices()) do
|
||||
if dev ~= "lo" and not ntm:ignore_interface(dev) then
|
||||
devices[#devices+1] = dev
|
||||
end
|
||||
end
|
||||
|
||||
local curdev = luci.http.formvalue("dev") or devices[1]
|
||||
-%>
|
||||
|
||||
<%+header%>
|
||||
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
var bwxhr = new XHR();
|
||||
|
||||
var G;
|
||||
var TIME = 0;
|
||||
var RXB = 1;
|
||||
var RXP = 2;
|
||||
var TXB = 3;
|
||||
var TXP = 4;
|
||||
|
||||
var width = 760;
|
||||
var height = 300;
|
||||
var step = 5;
|
||||
|
||||
var data_wanted = Math.floor(width / step);
|
||||
var data_fill = 1;
|
||||
var data_stamp = 0;
|
||||
|
||||
var data_rx = [ ];
|
||||
var data_tx = [ ];
|
||||
|
||||
var line_rx;
|
||||
var line_tx;
|
||||
|
||||
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;
|
||||
|
||||
|
||||
Math.log2 = Math.log2 || function(x) { return Math.log(x) * Math.LOG2E; };
|
||||
|
||||
function bandwidth_label(bytes, br)
|
||||
{
|
||||
var uby = '<%:kB/s%>';
|
||||
var kby = (bytes / 1024);
|
||||
|
||||
if (kby >= 1024)
|
||||
{
|
||||
uby = '<%:MB/s%>';
|
||||
kby = kby / 1024;
|
||||
}
|
||||
|
||||
var ubi = '<%:kbit/s%>';
|
||||
var kbi = (bytes * 8 / 1024);
|
||||
|
||||
if (kbi >= 1024)
|
||||
{
|
||||
ubi = '<%:Mbit/s%>';
|
||||
kbi = kbi / 1024;
|
||||
}
|
||||
|
||||
return String.format("%f %s%s(%f %s)",
|
||||
kbi.toFixed(2), ubi,
|
||||
br ? '<br />' : ' ',
|
||||
kby.toFixed(2), uby
|
||||
);
|
||||
}
|
||||
|
||||
/* 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_rx[i] = 0;
|
||||
data_tx[i] = 0;
|
||||
}
|
||||
|
||||
/* find svg elements */
|
||||
line_rx = G.getElementById('rx');
|
||||
line_tx = G.getElementById('tx');
|
||||
|
||||
label_25 = G.getElementById('label_25');
|
||||
label_50 = G.getElementById('label_50');
|
||||
label_75 = G.getElementById('label_75');
|
||||
|
||||
label_rx_cur = document.getElementById('rx_bw_cur');
|
||||
label_rx_avg = document.getElementById('rx_bw_avg');
|
||||
label_rx_peak = document.getElementById('rx_bw_peak');
|
||||
|
||||
label_tx_cur = document.getElementById('tx_bw_cur');
|
||||
label_tx_avg = document.getElementById('tx_bw_avg');
|
||||
label_tx_peak = document.getElementById('tx_bw_peak');
|
||||
|
||||
label_scale = document.getElementById('scale');
|
||||
|
||||
|
||||
/* plot horizontal time interval lines */
|
||||
for (var i = width % (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:#eee; font-size:9pt; font-family:sans-serif; text-shadow:1px 1px 1px #000');
|
||||
text.appendChild(G.createTextNode(Math.round((width - 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, 3);
|
||||
|
||||
/* render datasets, start update interval */
|
||||
XHR.poll(3, '<%=build_url("admin/status/realtime/bandwidth_status", curdev)%>', null,
|
||||
function(x, data)
|
||||
{
|
||||
var data_max = 0;
|
||||
var data_scale = 0;
|
||||
|
||||
var data_rx_avg = 0;
|
||||
var data_tx_avg = 0;
|
||||
|
||||
var data_rx_peak = 0;
|
||||
var data_tx_peak = 0;
|
||||
|
||||
for (var i = data_stamp ? 0 : 1; i < data.length; i++)
|
||||
{
|
||||
/* skip overlapping entries */
|
||||
if (data[i][TIME] <= data_stamp)
|
||||
continue;
|
||||
|
||||
data_fill++;
|
||||
|
||||
/* normalize difference against time interval */
|
||||
if (i > 0)
|
||||
{
|
||||
var time_delta = data[i][TIME] - data[i-1][TIME];
|
||||
if (time_delta)
|
||||
{
|
||||
data_rx.push((data[i][RXB] - data[i-1][RXB]) / time_delta);
|
||||
data_tx.push((data[i][TXB] - data[i-1][TXB]) / time_delta);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* cut off outdated entries */
|
||||
data_rx = data_rx.slice(data_rx.length - data_wanted, data_rx.length);
|
||||
data_tx = data_tx.slice(data_tx.length - data_wanted, data_tx.length);
|
||||
data_fill = Math.min(data_fill, data_wanted);
|
||||
|
||||
/* find peak */
|
||||
for (var i = 0; i < data_rx.length; i++)
|
||||
{
|
||||
data_max = Math.max(data_max, data_rx[i]);
|
||||
data_max = Math.max(data_max, data_tx[i]);
|
||||
|
||||
data_rx_peak = Math.max(data_rx_peak, data_rx[i]);
|
||||
data_tx_peak = Math.max(data_tx_peak, data_tx[i]);
|
||||
|
||||
data_rx_avg += data_rx[i];
|
||||
data_tx_avg += data_tx[i];
|
||||
}
|
||||
|
||||
data_rx_avg = (data_rx_avg / data_fill);
|
||||
data_tx_avg = (data_tx_avg / data_fill);
|
||||
|
||||
var size = Math.floor(Math.log2(data_max)),
|
||||
div = Math.pow(2, size - (size % 10)),
|
||||
mult = data_max / div,
|
||||
mult = (mult < 5) ? 2 : ((mult < 50) ? 10 : ((mult < 500) ? 100 : 1000));
|
||||
|
||||
data_max = data_max + (mult * div) - (data_max % (mult * div));
|
||||
|
||||
/* remember current timestamp, calculate horizontal scale */
|
||||
data_stamp = data[data.length-1][TIME];
|
||||
data_scale = height / data_max;
|
||||
|
||||
/* 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_rx.length; i++)
|
||||
{
|
||||
var x = i * step;
|
||||
|
||||
y_rx = height - Math.floor(data_rx[i] * data_scale);
|
||||
y_tx = height - Math.floor(data_tx[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_rx.setAttribute('points', pt_rx);
|
||||
line_tx.setAttribute('points', pt_tx);
|
||||
|
||||
label_25.firstChild.data = bandwidth_label(0.25 * data_max);
|
||||
label_50.firstChild.data = bandwidth_label(0.50 * data_max);
|
||||
label_75.firstChild.data = bandwidth_label(0.75 * data_max);
|
||||
|
||||
label_rx_cur.innerHTML = bandwidth_label(data_rx[data_rx.length-1], true);
|
||||
label_tx_cur.innerHTML = bandwidth_label(data_tx[data_tx.length-1], true);
|
||||
|
||||
label_rx_avg.innerHTML = bandwidth_label(data_rx_avg, true);
|
||||
label_tx_avg.innerHTML = bandwidth_label(data_tx_avg, true);
|
||||
|
||||
label_rx_peak.innerHTML = bandwidth_label(data_rx_peak, true);
|
||||
label_tx_peak.innerHTML = bandwidth_label(data_tx_peak, true);
|
||||
}
|
||||
);
|
||||
|
||||
XHR.run();
|
||||
}
|
||||
}, 1000
|
||||
);
|
||||
//]]></script>
|
||||
|
||||
<h2 name="content"><%:Realtime Traffic%></h2>
|
||||
|
||||
<ul class="cbi-tabmenu">
|
||||
<% for _, dev in ipairs(devices) do %>
|
||||
<li class="cbi-tab<%= dev == curdev and "" or "-disabled" %>"><a href="?dev=<%=pcdata(dev)%>"><%=pcdata(dev)%></a></li>
|
||||
<% end %>
|
||||
</ul>
|
||||
|
||||
<embed id="bwsvg" style="width:100%; height:300px; border:1px solid #000000; background-color:#FFFFFF" src="<%=resource%>/bandwidth.svg" />
|
||||
<div style="text-align:right"><small id="scale">-</small></div>
|
||||
<br />
|
||||
|
||||
<div class="table" style="width:100%; table-layout:fixed" cellspacing="5">
|
||||
<div class="tr">
|
||||
<div class="td" style="text-align:right; vertical-align:top"><strong style="border-bottom:2px solid blue"><%:Inbound:%></strong></div>
|
||||
<div class="td" id="rx_bw_cur">0 <%:kbit/s%><br />(0 <%:kB/s%>)</div>
|
||||
|
||||
<div class="td" style="text-align:right; vertical-align:top"><strong><%:Average:%></strong></div>
|
||||
<div class="td" id="rx_bw_avg">0 <%:kbit/s%><br />(0 <%:kB/s%>)</div>
|
||||
|
||||
<div class="td" style="text-align:right; vertical-align:top"><strong><%:Peak:%></strong></div>
|
||||
<div class="td" id="rx_bw_peak">0 <%:kbit/s%><br />(0 <%:kB/s%>)</div>
|
||||
</div>
|
||||
<div class="tr">
|
||||
<div class="td" style="text-align:right; vertical-align:top"><strong style="border-bottom:2px solid green"><%:Outbound:%></strong></div>
|
||||
<div class="td" id="tx_bw_cur">0 <%:kbit/s%><br />(0 <%:kB/s%>)</div>
|
||||
|
||||
<div class="td" style="text-align:right; vertical-align:top"><strong><%:Average:%></strong></div>
|
||||
<div class="td" id="tx_bw_avg">0 <%:kbit/s%><br />(0 <%:kB/s%>)</div>
|
||||
|
||||
<div class="td" style="text-align:right; vertical-align:top"><strong><%:Peak:%></strong></div>
|
||||
<div class="td" id="tx_bw_peak">0 <%:kbit/s%><br />(0 <%:kB/s%>)</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%+footer%>
|
405
luci-mod-status/luasrc/view/admin_status/connections.htm
Normal file
405
luci-mod-status/luasrc/view/admin_status/connections.htm
Normal file
|
@ -0,0 +1,405 @@
|
|||
<%#
|
||||
Copyright 2010-2018 Jo-Philipp Wich <jo@mein.io>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<%+header%>
|
||||
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
var bwxhr = new XHR();
|
||||
|
||||
var G;
|
||||
var TIME = 0;
|
||||
var UDP = 1;
|
||||
var TCP = 2;
|
||||
var OTHER = 3;
|
||||
|
||||
var width = 760;
|
||||
var height = 300;
|
||||
var step = 5;
|
||||
|
||||
var data_wanted = Math.floor(width / step);
|
||||
var data_fill = 1;
|
||||
var data_stamp = 0;
|
||||
|
||||
var data_udp = [ ];
|
||||
var data_tcp = [ ];
|
||||
var data_otr = [ ];
|
||||
|
||||
var line_udp;
|
||||
var line_tcp;
|
||||
|
||||
var label_25;
|
||||
var label_50;
|
||||
var label_75;
|
||||
|
||||
var label_udp_cur;
|
||||
var label_udp_avg;
|
||||
var label_udp_peak;
|
||||
|
||||
var label_tcp_cur;
|
||||
var label_tcp_avg;
|
||||
var label_tcp_peak;
|
||||
|
||||
var label_otr_cur;
|
||||
var label_otr_avg;
|
||||
var label_otr_peak;
|
||||
|
||||
var label_scale;
|
||||
|
||||
var conn_table;
|
||||
|
||||
var dns_cache = { };
|
||||
|
||||
|
||||
/* 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;
|
||||
data_otr[i] = 0;
|
||||
}
|
||||
|
||||
/* find svg elements */
|
||||
line_udp = G.getElementById('udp');
|
||||
line_tcp = G.getElementById('tcp');
|
||||
line_otr = G.getElementById('other');
|
||||
|
||||
label_25 = G.getElementById('label_25');
|
||||
label_50 = G.getElementById('label_50');
|
||||
label_75 = G.getElementById('label_75');
|
||||
|
||||
label_udp_cur = document.getElementById('lb_udp_cur');
|
||||
label_udp_avg = document.getElementById('lb_udp_avg');
|
||||
label_udp_peak = document.getElementById('lb_udp_peak');
|
||||
|
||||
label_tcp_cur = document.getElementById('lb_tcp_cur');
|
||||
label_tcp_avg = document.getElementById('lb_tcp_avg');
|
||||
label_tcp_peak = document.getElementById('lb_tcp_peak');
|
||||
|
||||
label_otr_cur = document.getElementById('lb_otr_cur');
|
||||
label_otr_avg = document.getElementById('lb_otr_avg');
|
||||
label_otr_peak = document.getElementById('lb_otr_peak');
|
||||
|
||||
label_scale = document.getElementById('scale');
|
||||
|
||||
conn_table = document.getElementById('connections');
|
||||
|
||||
|
||||
/* plot horizontal time interval lines */
|
||||
for (var i = width % (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:#eee; font-size:9pt; font-family:sans-serif; text-shadow:1px 1px 1px #000');
|
||||
text.appendChild(G.createTextNode(Math.round((width - 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, 3);
|
||||
|
||||
var recheck_lookup_queue = {};
|
||||
|
||||
/* render datasets, start update interval */
|
||||
XHR.poll(3, '<%=build_url("admin/status/realtime/connections_status")%>', null,
|
||||
function(x, json)
|
||||
{
|
||||
|
||||
if (!json.connections)
|
||||
return;
|
||||
|
||||
var conn = json.connections;
|
||||
|
||||
var lookup_queue = [ ];
|
||||
var rows = [];
|
||||
|
||||
conn.sort(function(a, b) {
|
||||
return b.bytes - a.bytes;
|
||||
});
|
||||
|
||||
for (var i = 0; i < conn.length; i++)
|
||||
{
|
||||
var c = conn[i];
|
||||
|
||||
if ((c.src == '127.0.0.1' && c.dst == '127.0.0.1') ||
|
||||
(c.src == '::1' && c.dst == '::1'))
|
||||
continue;
|
||||
|
||||
if (!dns_cache[c.src] && lookup_queue.indexOf(c.src) == -1)
|
||||
lookup_queue.push(c.src);
|
||||
|
||||
if (!dns_cache[c.dst] && lookup_queue.indexOf(c.dst) == -1)
|
||||
lookup_queue.push(c.dst);
|
||||
|
||||
var src = dns_cache[c.src] || (c.layer3 == 'ipv6' ? '[' + c.src + ']' : c.src);
|
||||
var dst = dns_cache[c.dst] || (c.layer3 == 'ipv6' ? '[' + c.dst + ']' : c.dst);
|
||||
|
||||
rows.push([
|
||||
c.layer3.toUpperCase(),
|
||||
c.layer4.toUpperCase(),
|
||||
c.hasOwnProperty('sport') ? (src + ':' + c.sport) : src,
|
||||
c.hasOwnProperty('dport') ? (dst + ':' + c.dport) : dst,
|
||||
'%1024.2mB (%d <%:Pkts.%>)'.format(c.bytes, c.packets)
|
||||
]);
|
||||
}
|
||||
|
||||
cbi_update_table(conn_table, rows, '<em><%:No information available%></em>');
|
||||
|
||||
if (lookup_queue.length > 0) {
|
||||
var reduced_lookup_queue = lookup_queue;
|
||||
|
||||
if (lookup_queue.length > 100)
|
||||
reduced_lookup_queue = lookup_queue.slice(0, 100);
|
||||
|
||||
XHR.get('<%=build_url("admin/status/nameinfo")%>/' + reduced_lookup_queue.join('/'), null,
|
||||
function(x, json) {
|
||||
if (!json)
|
||||
return;
|
||||
|
||||
for (var index in reduced_lookup_queue) {
|
||||
var address = reduced_lookup_queue[index];
|
||||
|
||||
if (!address)
|
||||
continue;
|
||||
|
||||
if (json[address]) {
|
||||
dns_cache[address] = json[address];
|
||||
lookup_queue.splice(reduced_lookup_queue.indexOf(address),1);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(recheck_lookup_queue[address] > 2) {
|
||||
dns_cache[address] = (address.match(/:/)) ? '[' + address + ']' : address;
|
||||
lookup_queue.splice(index,1);
|
||||
} else {
|
||||
recheck_lookup_queue[address] != null ? recheck_lookup_queue[address]++ : recheck_lookup_queue[address] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
var data = json.statistics;
|
||||
|
||||
var data_max = 0;
|
||||
var data_scale = 0;
|
||||
|
||||
var data_udp_avg = 0;
|
||||
var data_tcp_avg = 0;
|
||||
var data_otr_avg = 0;
|
||||
|
||||
var data_udp_peak = 0;
|
||||
var data_tcp_peak = 0;
|
||||
var data_otr_peak = 0;
|
||||
|
||||
for (var i = data_stamp ? 0 : 1; i < data.length; i++)
|
||||
{
|
||||
/* skip overlapping entries */
|
||||
if (data[i][TIME] <= data_stamp)
|
||||
continue;
|
||||
|
||||
data_fill++;
|
||||
|
||||
data_udp.push(data[i][UDP]);
|
||||
data_tcp.push(data[i][TCP]);
|
||||
data_otr.push(data[i][OTHER]);
|
||||
}
|
||||
|
||||
/* cut off outdated entries */
|
||||
data_fill = Math.min(data_fill, data_wanted);
|
||||
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);
|
||||
data_otr = data_otr.slice(data_otr.length - data_wanted, data_otr.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_max = Math.max(data_max, data_otr[i]);
|
||||
|
||||
data_udp_peak = Math.max(data_udp_peak, data_udp[i]);
|
||||
data_tcp_peak = Math.max(data_tcp_peak, data_tcp[i]);
|
||||
data_otr_peak = Math.max(data_otr_peak, data_otr[i]);
|
||||
|
||||
data_udp_avg += data_udp[i];
|
||||
data_tcp_avg += data_tcp[i];
|
||||
data_otr_avg += data_otr[i];
|
||||
}
|
||||
|
||||
data_udp_avg = data_udp_avg / data_fill;
|
||||
data_tcp_avg = data_tcp_avg / data_fill;
|
||||
data_otr_avg = data_otr_avg / data_fill;
|
||||
|
||||
/* remember current timestamp, calculate horizontal scale */
|
||||
data_stamp = data[data.length-1][TIME];
|
||||
data_scale = height / (data_max * 1.1);
|
||||
|
||||
|
||||
/* plot data */
|
||||
var pt_udp = '0,' + height;
|
||||
var pt_tcp = '0,' + height;
|
||||
var pt_otr = '0,' + height;
|
||||
|
||||
var y_udp = 0;
|
||||
var y_tcp = 0;
|
||||
var y_otr = 0;
|
||||
|
||||
for (var i = 0; i < data_udp.length; i++)
|
||||
{
|
||||
var x = i * step;
|
||||
|
||||
y_udp = height - Math.floor(data_udp[i] * data_scale);
|
||||
y_tcp = height - Math.floor(data_tcp[i] * data_scale);
|
||||
y_otr = height - Math.floor(data_otr[i] * data_scale);
|
||||
|
||||
pt_udp += ' ' + x + ',' + y_udp;
|
||||
pt_tcp += ' ' + x + ',' + y_tcp;
|
||||
pt_otr += ' ' + x + ',' + y_otr;
|
||||
}
|
||||
|
||||
pt_udp += ' ' + width + ',' + y_udp + ' ' + width + ',' + height;
|
||||
pt_tcp += ' ' + width + ',' + y_tcp + ' ' + width + ',' + height;
|
||||
pt_otr += ' ' + width + ',' + y_otr + ' ' + width + ',' + height;
|
||||
|
||||
|
||||
var order = [
|
||||
[ line_udp, data_udp[data_udp.length-1] ],
|
||||
[ line_tcp, data_tcp[data_tcp.length-1] ],
|
||||
[ line_otr, data_otr[data_otr.length-1] ]
|
||||
];
|
||||
|
||||
order.sort(function(a, b) { return b[1] - a[1] });
|
||||
|
||||
for (var i = 0; i < order.length; i++)
|
||||
order[i][0].parentNode.appendChild(order[i][0]);
|
||||
|
||||
|
||||
line_udp.setAttribute('points', pt_udp);
|
||||
line_tcp.setAttribute('points', pt_tcp);
|
||||
line_otr.setAttribute('points', pt_otr);
|
||||
|
||||
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_udp_cur.innerHTML = Math.floor(data_udp[data_udp.length-1]);
|
||||
label_tcp_cur.innerHTML = Math.floor(data_tcp[data_tcp.length-1]);
|
||||
label_otr_cur.innerHTML = Math.floor(data_otr[data_otr.length-1]);
|
||||
|
||||
label_udp_avg.innerHTML = Math.floor(data_udp_avg);
|
||||
label_tcp_avg.innerHTML = Math.floor(data_tcp_avg);
|
||||
label_otr_avg.innerHTML = Math.floor(data_otr_avg);
|
||||
|
||||
label_udp_peak.innerHTML = Math.floor(data_udp_peak);
|
||||
label_tcp_peak.innerHTML = Math.floor(data_tcp_peak);
|
||||
label_otr_peak.innerHTML = Math.floor(data_otr_peak);
|
||||
}
|
||||
);
|
||||
|
||||
XHR.run();
|
||||
}
|
||||
}, 1000
|
||||
);
|
||||
//]]></script>
|
||||
|
||||
<h2 name="content"><%:Realtime Connections%></h2>
|
||||
|
||||
<div class="cbi-map-descr"><%:This page gives an overview over currently active network connections.%></div>
|
||||
|
||||
<fieldset class="cbi-section" id="cbi-table-table">
|
||||
<legend><%:Active Connections%></legend>
|
||||
|
||||
<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 />
|
||||
|
||||
<div class="table">
|
||||
<div class="tr">
|
||||
<div class="td" style="text-align:right; vertical-align:top"><strong style="border-bottom:2px solid blue"><%:UDP:%></strong></div>
|
||||
<div class="td" id="lb_udp_cur">0</div>
|
||||
|
||||
<div class="td" style="text-align:right; vertical-align:top"><strong><%:Average:%></strong></div>
|
||||
<div class="td" id="lb_udp_avg">0</div>
|
||||
|
||||
<div class="td" style="text-align:right; vertical-align:top"><strong><%:Peak:%></strong></div>
|
||||
<div class="td" id="lb_udp_peak">0</div>
|
||||
</div>
|
||||
<div class="tr">
|
||||
<div class="td" style="text-align:right; vertical-align:top"><strong style="border-bottom:2px solid green"><%:TCP:%></strong></div>
|
||||
<div class="td" id="lb_tcp_cur">0</div>
|
||||
|
||||
<div class="td" style="text-align:right; vertical-align:top"><strong><%:Average:%></strong></div>
|
||||
<div class="td" id="lb_tcp_avg">0</div>
|
||||
|
||||
<div class="td" style="text-align:right; vertical-align:top"><strong><%:Peak:%></strong></div>
|
||||
<div class="td" id="lb_tcp_peak">0</div>
|
||||
</div>
|
||||
<div class="tr">
|
||||
<div class="td" style="text-align:right; vertical-align:top"><strong style="border-bottom:2px solid red"><%:Other:%></strong></div>
|
||||
<div class="td" id="lb_otr_cur">0</div>
|
||||
|
||||
<div class="td" style="text-align:right; vertical-align:top"><strong><%:Average:%></strong></div>
|
||||
<div class="td" id="lb_otr_avg">0</div>
|
||||
|
||||
<div class="td" style="text-align:right; vertical-align:top"><strong><%:Peak:%></strong></div>
|
||||
<div class="td" id="lb_otr_peak">0</div>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
|
||||
<div class="cbi-section-node">
|
||||
<div class="table" id="connections">
|
||||
<div class="tr table-titles">
|
||||
<div class="th col-2 hide-xs"><%:Network%></div>
|
||||
<div class="th col-2"><%:Protocol%></div>
|
||||
<div class="th col-7"><%:Source%></div>
|
||||
<div class="th col-7"><%:Destination%></div>
|
||||
<div class="th col-4"><%:Transfer%></div>
|
||||
</div>
|
||||
|
||||
<div class="tr placeholder">
|
||||
<div class="td">
|
||||
<em><%:Collecting data...%></em>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<%+footer%>
|
12
luci-mod-status/luasrc/view/admin_status/dmesg.htm
Normal file
12
luci-mod-status/luasrc/view/admin_status/dmesg.htm
Normal file
|
@ -0,0 +1,12 @@
|
|||
<%#
|
||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
Copyright 2008 Jo-Philipp Wich <jow@openwrt.org>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<%+header%>
|
||||
<h2 name="content"><%:Kernel Log%></h2>
|
||||
<div id="content_syslog">
|
||||
<textarea style="font-size: 12px;" readonly="readonly" wrap="off" rows="<%=dmesg:cmatch("\n")+2%>" id="syslog"><%=dmesg:pcdata()%></textarea>
|
||||
</div>
|
||||
<%+footer%>
|
148
luci-mod-status/luasrc/view/admin_status/index.htm
Normal file
148
luci-mod-status/luasrc/view/admin_status/index.htm
Normal file
|
@ -0,0 +1,148 @@
|
|||
<%#
|
||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
Copyright 2008-2018 Jo-Philipp Wich <jo@mein.io>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<%
|
||||
local fs = require "nixio.fs"
|
||||
local ipc = require "luci.ip"
|
||||
local util = require "luci.util"
|
||||
local stat = require "luci.tools.status"
|
||||
local ver = require "luci.version"
|
||||
|
||||
if luci.http.formvalue("status") == "1" then
|
||||
|
||||
local sysinfo = luci.util.ubus("system", "info") or { }
|
||||
|
||||
local meminfo = sysinfo.memory or {
|
||||
total = 0,
|
||||
free = 0,
|
||||
buffered = 0,
|
||||
shared = 0
|
||||
}
|
||||
|
||||
local swapinfo = sysinfo.swap or {
|
||||
total = 0,
|
||||
free = 0
|
||||
}
|
||||
|
||||
local has_dsl = fs.access("/etc/init.d/dsl_control")
|
||||
|
||||
local ntm = require "luci.model.network".init()
|
||||
local wan_nets = ntm:get_wan_networks()
|
||||
local wan6_nets = ntm:get_wan6_networks()
|
||||
|
||||
local conn_count = tonumber(
|
||||
fs.readfile("/proc/sys/net/netfilter/nf_conntrack_count") or "") or 0
|
||||
|
||||
local conn_max = tonumber(luci.sys.exec(
|
||||
"sysctl -n -e net.nf_conntrack_max net.ipv4.netfilter.ip_conntrack_max"
|
||||
):match("%d+")) or 4096
|
||||
|
||||
local rv = {
|
||||
uptime = sysinfo.uptime or 0,
|
||||
localtime = os.date(),
|
||||
loadavg = sysinfo.load or { 0, 0, 0 },
|
||||
memory = meminfo,
|
||||
swap = swapinfo,
|
||||
connmax = conn_max,
|
||||
conncount = conn_count,
|
||||
wifinets = stat.wifi_networks()
|
||||
}
|
||||
|
||||
if #wan_nets > 0 then
|
||||
local k, v
|
||||
|
||||
rv.wan = { }
|
||||
|
||||
for k, v in pairs(wan_nets) do
|
||||
local dev = v:get_interface()
|
||||
local link = dev and ipc.link(dev:name())
|
||||
|
||||
local wan_info = {
|
||||
ipaddrs = v:ipaddrs(),
|
||||
gwaddr = v:gwaddr(),
|
||||
dns = v:dnsaddrs(),
|
||||
expires = v:expires(),
|
||||
uptime = v:uptime(),
|
||||
proto = v:proto(),
|
||||
i18n = v:get_i18n(),
|
||||
ifname = v:ifname(),
|
||||
link = v:adminlink(),
|
||||
mac = dev and dev:mac(),
|
||||
type = dev and dev:type(),
|
||||
name = dev and dev:get_i18n(),
|
||||
ether = link and link.type == 1
|
||||
}
|
||||
|
||||
rv.wan[#rv.wan+1] = wan_info
|
||||
end
|
||||
end
|
||||
|
||||
if #wan6_nets > 0 then
|
||||
local k, v
|
||||
|
||||
rv.wan6 = { }
|
||||
|
||||
for k, v in pairs(wan6_nets) do
|
||||
local dev = v:get_interface()
|
||||
local link = dev and ipc.link(dev:name())
|
||||
local wan6_info = {
|
||||
ip6addrs = v:ip6addrs(),
|
||||
gw6addr = v:gw6addr(),
|
||||
dns = v:dns6addrs(),
|
||||
ip6prefix = v:ip6prefix(),
|
||||
uptime = v:uptime(),
|
||||
proto = v:proto(),
|
||||
i18n = v:get_i18n(),
|
||||
ifname = v:ifname(),
|
||||
link = v:adminlink(),
|
||||
mac = dev and dev:mac(),
|
||||
type = dev and dev:type(),
|
||||
name = dev and dev:get_i18n(),
|
||||
ether = link and link.type == 1
|
||||
}
|
||||
|
||||
rv.wan6[#rv.wan6+1] = wan6_info
|
||||
end
|
||||
end
|
||||
|
||||
if has_dsl then
|
||||
local dsl_stat = luci.sys.exec("/etc/init.d/dsl_control lucistat")
|
||||
local dsl_func = loadstring(dsl_stat)
|
||||
if dsl_func then
|
||||
rv.dsl = dsl_func()
|
||||
end
|
||||
end
|
||||
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(rv)
|
||||
|
||||
return
|
||||
end
|
||||
-%>
|
||||
|
||||
<%+header%>
|
||||
|
||||
<h2 name="content"><%:Status%></h2>
|
||||
|
||||
<%-
|
||||
local incdir = util.libpath() .. "/view/admin_status/index/"
|
||||
if fs.access(incdir) then
|
||||
local _, inc
|
||||
local includes = {}
|
||||
for inc in fs.dir(incdir) do
|
||||
if inc:match("%.htm$") then
|
||||
includes[#includes + 1] = inc:gsub("%.htm$", "")
|
||||
end
|
||||
end
|
||||
for _, inc in luci.util.vspairs(includes) do
|
||||
include("admin_status/index/" .. inc)
|
||||
end
|
||||
end
|
||||
-%>
|
||||
|
||||
<script type="text/javascript" src="<%=resource%>/view/status/index.js"></script>
|
||||
|
||||
<%+footer%>
|
29
luci-mod-status/luasrc/view/admin_status/index/10-system.htm
Normal file
29
luci-mod-status/luasrc/view/admin_status/index/10-system.htm
Normal file
|
@ -0,0 +1,29 @@
|
|||
<%#
|
||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
Copyright 2008-2018 Jo-Philipp Wich <jo@mein.io>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<%
|
||||
local boardinfo = luci.util.ubus("system", "board") or { }
|
||||
local unameinfo = nixio.uname() or { }
|
||||
local ver = require "luci.version"
|
||||
%>
|
||||
|
||||
<div class="cbi-section">
|
||||
<h3><%:System%></h3>
|
||||
|
||||
<div class="table" width="100%">
|
||||
<div class="tr"><div class="td left" width="33%"><%:Hostname%></div><div class="td left"><%=luci.sys.hostname() or "?"%></div></div>
|
||||
<div class="tr"><div class="td left" width="33%"><%:Model%></div><div class="td left"><%=pcdata(boardinfo.model or "?")%></div></div>
|
||||
<div class="tr"><div class="td left" width="33%"><%:Architecture%></div><div class="td left"><%=pcdata(boardinfo.system or "?")%></div></div>
|
||||
<div class="tr"><div class="td left" width="33%"><%:Firmware Version%></div><div class="td left">
|
||||
<%=pcdata(ver.distname)%> <%=pcdata(ver.distversion)%> /
|
||||
<%=pcdata(ver.luciname)%> (<%=pcdata(ver.luciversion)%>)
|
||||
</div></div>
|
||||
<div class="tr"><div class="td left" width="33%"><%:Kernel Version%></div><div class="td left"><%=unameinfo.release or "?"%></div></div>
|
||||
<div class="tr"><div class="td left" width="33%"><%:Local Time%></div><div class="td left" id="localtime">-</div></div>
|
||||
<div class="tr"><div class="td left" width="33%"><%:Uptime%></div><div class="td left" id="uptime">-</div></div>
|
||||
<div class="tr"><div class="td left" width="33%"><%:Load Average%></div><div class="td left" id="loadavg">-</div></div>
|
||||
</div>
|
||||
</div>
|
31
luci-mod-status/luasrc/view/admin_status/index/20-memory.htm
Normal file
31
luci-mod-status/luasrc/view/admin_status/index/20-memory.htm
Normal file
|
@ -0,0 +1,31 @@
|
|||
<%#
|
||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
Copyright 2008-2018 Jo-Philipp Wich <jo@mein.io>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<%
|
||||
local sysinfo = luci.util.ubus("system", "info") or { }
|
||||
local has_swap = sysinfo.swap and sysinfo.swap.total > 0 or false
|
||||
%>
|
||||
|
||||
<div class="cbi-section">
|
||||
<h3><%:Memory%></h3>
|
||||
|
||||
<div class="table" width="100%">
|
||||
<div class="tr"><div class="td left" width="33%"><%:Total Available%></div><div class="td left"><div id="memtotal" class="cbi-progressbar" title="-"><div></div></div></div></div>
|
||||
<div class="tr"><div class="td left" width="33%"><%:Free%></div><div class="td left"><div id="memfree" class="cbi-progressbar" title="-"><div></div></div></div></div>
|
||||
<div class="tr"><div class="td left" width="33%"><%:Buffered%></div><div class="td left"><div id="membuff" class="cbi-progressbar" title="-"><div></div></div></div></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<% if has_swap then %>
|
||||
<div class="cbi-section">
|
||||
<h3><%:Swap%></h3>
|
||||
|
||||
<div class="table" width="100%">
|
||||
<div class="tr"><div class="td left" width="33%"><%:Total Available%></div><div class="td left"><div id="swaptotal" class="cbi-progressbar" title="-"><div></div></div></div></div>
|
||||
<div class="tr"><div class="td left" width="33%"><%:Free%></div><div class="td left"><div id="swapfree" class="cbi-progressbar" title="-"><div></div></div></div></div>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
|
@ -0,0 +1,17 @@
|
|||
<%#
|
||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
Copyright 2008-2018 Jo-Philipp Wich <jo@mein.io>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<div class="cbi-section">
|
||||
<h3><%:Network%></h3>
|
||||
|
||||
<div id="upstream_status_table" class="network-status-table">
|
||||
<p><em><%:Collecting data...%></em></p>
|
||||
</div>
|
||||
|
||||
<div class="table" width="100%">
|
||||
<div class="tr"><div class="td left" width="33%"><%:Active Connections%></div><div class="td left"><div id="conns" class="cbi-progressbar" title="-"><div></div></div></div></div>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,14 @@
|
|||
<%#
|
||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
Copyright 2008-2018 Jo-Philipp Wich <jo@mein.io>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<%
|
||||
local fs = require "nixio.fs"
|
||||
local has_dhcp = fs.access("/etc/config/dhcp")
|
||||
|
||||
if has_dhcp then
|
||||
include("lease_status")
|
||||
end
|
||||
%>
|
20
luci-mod-status/luasrc/view/admin_status/index/50-dsl.htm
Normal file
20
luci-mod-status/luasrc/view/admin_status/index/50-dsl.htm
Normal file
|
@ -0,0 +1,20 @@
|
|||
<%#
|
||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
Copyright 2008-2018 Jo-Philipp Wich <jo@mein.io>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<%
|
||||
local fs = require "nixio.fs"
|
||||
local has_dsl = fs.access("/etc/init.d/dsl_control")
|
||||
%>
|
||||
|
||||
<% if has_dsl then %>
|
||||
<div class="cbi-section">
|
||||
<h3><%:DSL%></h3>
|
||||
|
||||
<div id="dsl_status_table" class="network-status-table">
|
||||
<p><em><%:Collecting data...%></em></p>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
26
luci-mod-status/luasrc/view/admin_status/index/60-wifi.htm
Normal file
26
luci-mod-status/luasrc/view/admin_status/index/60-wifi.htm
Normal file
|
@ -0,0 +1,26 @@
|
|||
<%#
|
||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
Copyright 2008-2018 Jo-Philipp Wich <jo@mein.io>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<%
|
||||
local fs = require "nixio.fs"
|
||||
local has_wifi = ((fs.stat("/etc/config/wireless", "size") or 0) > 0)
|
||||
%>
|
||||
|
||||
<% if has_wifi then %>
|
||||
<div class="cbi-section">
|
||||
<h3><%:Wireless%></h3>
|
||||
|
||||
<div id="wifi_status_table" class="network-status-table">
|
||||
<p><em><%:Collecting data...%></em></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cbi-section">
|
||||
<h3><%:Associated Stations%></h3>
|
||||
|
||||
<%+wifi_assoclist%>
|
||||
</div>
|
||||
<% end %>
|
73
luci-mod-status/luasrc/view/admin_status/iptables.htm
Normal file
73
luci-mod-status/luasrc/view/admin_status/iptables.htm
Normal file
|
@ -0,0 +1,73 @@
|
|||
<%#
|
||||
Copyright 2008-2009 Steven Barth <steven@midlink.org>
|
||||
Copyright 2008-2018 Jo-Philipp Wich <jo@mein.io>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<%-
|
||||
local fs = require "nixio.fs"
|
||||
local has_ip6tables = fs.access("/usr/sbin/ip6tables")
|
||||
local mode = 4
|
||||
|
||||
if has_ip6tables then
|
||||
mode = luci.dispatcher.context.requestpath
|
||||
mode = tonumber(mode[#mode] ~= "iptables" and mode[#mode]) or 4
|
||||
end
|
||||
-%>
|
||||
|
||||
<%+header%>
|
||||
|
||||
<style type="text/css">
|
||||
span.jump, .cbi-tooltip-container {
|
||||
border-bottom: 1px dotted blue;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.references {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.references .cbi-tooltip {
|
||||
left: 0 !important;
|
||||
top: 1.5em !important;
|
||||
}
|
||||
|
||||
h4 > span {
|
||||
font-size: 90%;
|
||||
}
|
||||
</style>
|
||||
|
||||
<h2 name="content"><%:Firewall Status%></h2>
|
||||
|
||||
<% if has_ip6tables then %>
|
||||
<ul class="cbi-tabmenu">
|
||||
<li data-mode="4" class="cbi-tab<%= mode ~= 4 and "-disabled" %>">
|
||||
<a href="<%=url("admin/status/iptables/4")%>"><%:IPv4 Firewall%></a>
|
||||
</li>
|
||||
<li data-mode="6" class="cbi-tab<%= mode ~= 6 and "-disabled" %>">
|
||||
<a href="<%=url("admin/status/iptables/6")%>"><%:IPv6 Firewall%></a>
|
||||
</li>
|
||||
</ul>
|
||||
<% end %>
|
||||
|
||||
<div style="position: relative">
|
||||
<form method="post" action="<%=url("admin/status/iptables_action")%>" style="position: absolute; right: 0">
|
||||
<input type="hidden" name="token" value="<%=token%>" />
|
||||
<input type="hidden" name="family" value="<%=mode%>" />
|
||||
<input type="button" class="cbi-button" data-hide-empty="false" value="<%:Hide empty chains%>" onclick="hide_empty(this)" />
|
||||
<input type="submit" class="cbi-button" name="zero" value="<%:Reset Counters%>" />
|
||||
<input type="submit" class="cbi-button" name="restart" value="<%:Restart Firewall%>" />
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="iptables">
|
||||
<p><em class="spinning"><%:Collecting data...%></em></p>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="<%=resource%>/view/status/iptables.js"></script>
|
||||
|
||||
<%+footer%>
|
283
luci-mod-status/luasrc/view/admin_status/load.htm
Normal file
283
luci-mod-status/luasrc/view/admin_status/load.htm
Normal file
|
@ -0,0 +1,283 @@
|
|||
<%#
|
||||
Copyright 2010-2018 Jo-Philipp Wich <jo@mein.io>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<%+header%>
|
||||
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
var bwxhr = new XHR();
|
||||
|
||||
var G;
|
||||
var TIME = 0;
|
||||
var L01 = 1;
|
||||
var L05 = 2;
|
||||
var L15 = 3;
|
||||
|
||||
var width = 760;
|
||||
var height = 300;
|
||||
var step = 5;
|
||||
|
||||
var data_wanted = Math.floor(width / step);
|
||||
var data_fill = 1;
|
||||
var data_stamp = 0;
|
||||
|
||||
var data_01 = [ ];
|
||||
var data_05 = [ ];
|
||||
var data_15 = [ ];
|
||||
|
||||
var line_01;
|
||||
var line_05;
|
||||
var line_15;
|
||||
|
||||
var label_25;
|
||||
var label_050;
|
||||
var label_75;
|
||||
|
||||
var label_01_cur;
|
||||
var label_01_avg;
|
||||
var label_01_peak;
|
||||
|
||||
var label_05_cur;
|
||||
var label_05_avg;
|
||||
var label_05_peak;
|
||||
|
||||
var label_15_cur;
|
||||
var label_15_avg;
|
||||
var label_15_peak;
|
||||
|
||||
var label_scale;
|
||||
|
||||
|
||||
/* 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_01[i] = 0;
|
||||
data_05[i] = 0;
|
||||
data_15[i] = 0;
|
||||
}
|
||||
|
||||
/* find svg elements */
|
||||
line_01 = G.getElementById('load01');
|
||||
line_05 = G.getElementById('load05');
|
||||
line_15 = G.getElementById('load15');
|
||||
|
||||
label_25 = G.getElementById('label_25');
|
||||
label_50 = G.getElementById('label_50');
|
||||
label_75 = G.getElementById('label_75');
|
||||
|
||||
label_01_cur = document.getElementById('lb_load01_cur');
|
||||
label_01_avg = document.getElementById('lb_load01_avg');
|
||||
label_01_peak = document.getElementById('lb_load01_peak');
|
||||
|
||||
label_05_cur = document.getElementById('lb_load05_cur');
|
||||
label_05_avg = document.getElementById('lb_load05_avg');
|
||||
label_05_peak = document.getElementById('lb_load05_peak');
|
||||
|
||||
label_15_cur = document.getElementById('lb_load15_cur');
|
||||
label_15_avg = document.getElementById('lb_load15_avg');
|
||||
label_15_peak = document.getElementById('lb_load15_peak');
|
||||
|
||||
label_scale = document.getElementById('scale');
|
||||
|
||||
|
||||
/* plot horizontal time interval lines */
|
||||
for (var i = width % (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:#eee; font-size:9pt; font-family:sans-serif; text-shadow:1px 1px 1px #000');
|
||||
text.appendChild(G.createTextNode(Math.round((width - 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, 3);
|
||||
|
||||
/* render datasets, start update interval */
|
||||
XHR.poll(3, '<%=build_url("admin/status/realtime/load_status")%>', null,
|
||||
function(x, data)
|
||||
{
|
||||
var data_max = 0;
|
||||
var data_scale = 0;
|
||||
|
||||
var data_01_avg = 0;
|
||||
var data_05_avg = 0;
|
||||
var data_15_avg = 0;
|
||||
|
||||
var data_01_peak = 0;
|
||||
var data_05_peak = 0;
|
||||
var data_15_peak = 0;
|
||||
|
||||
for (var i = data_stamp ? 0 : 1; i < data.length; i++)
|
||||
{
|
||||
/* skip overlapping entries */
|
||||
if (data[i][TIME] <= data_stamp)
|
||||
continue;
|
||||
|
||||
data_fill++;
|
||||
|
||||
data_01.push(data[i][L01]);
|
||||
data_05.push(data[i][L05]);
|
||||
data_15.push(data[i][L15]);
|
||||
}
|
||||
|
||||
/* cut off outdated entries */
|
||||
data_fill = Math.min(data_fill, data_wanted);
|
||||
data_01 = data_01.slice(data_01.length - data_wanted, data_01.length);
|
||||
data_05 = data_05.slice(data_05.length - data_wanted, data_05.length);
|
||||
data_15 = data_15.slice(data_15.length - data_wanted, data_15.length);
|
||||
|
||||
/* find peak */
|
||||
for (var i = 0; i < data_01.length; i++)
|
||||
{
|
||||
data_max = Math.max(data_max, data_01[i]);
|
||||
data_max = Math.max(data_max, data_05[i]);
|
||||
data_max = Math.max(data_max, data_15[i]);
|
||||
|
||||
data_01_peak = Math.max(data_01_peak, data_01[i]);
|
||||
data_05_peak = Math.max(data_05_peak, data_05[i]);
|
||||
data_15_peak = Math.max(data_15_peak, data_15[i]);
|
||||
|
||||
data_01_avg += data_01[i];
|
||||
data_05_avg += data_05[i];
|
||||
data_15_avg += data_15[i];
|
||||
}
|
||||
|
||||
data_01_avg = data_01_avg / data_fill;
|
||||
data_05_avg = data_05_avg / data_fill;
|
||||
data_15_avg = data_15_avg / data_fill;
|
||||
|
||||
/* remember current timestamp, calculate horizontal scale */
|
||||
data_stamp = data[data.length-1][TIME];
|
||||
data_scale = height / (data_max * 1.1);
|
||||
|
||||
|
||||
/* plot data */
|
||||
var pt_01 = '0,' + height;
|
||||
var pt_05 = '0,' + height;
|
||||
var pt_15 = '0,' + height;
|
||||
|
||||
var y_01 = 0;
|
||||
var y_05 = 0;
|
||||
var y_15 = 0;
|
||||
|
||||
for (var i = 0; i < data_01.length; i++)
|
||||
{
|
||||
var x = i * step;
|
||||
|
||||
y_01 = height - Math.floor(data_01[i] * data_scale);
|
||||
y_05 = height - Math.floor(data_05[i] * data_scale);
|
||||
y_15 = height - Math.floor(data_15[i] * data_scale);
|
||||
|
||||
pt_01 += ' ' + x + ',' + y_01;
|
||||
pt_05 += ' ' + x + ',' + y_05;
|
||||
pt_15 += ' ' + x + ',' + y_15;
|
||||
}
|
||||
|
||||
pt_01 += ' ' + width + ',' + y_01 + ' ' + width + ',' + height;
|
||||
pt_05 += ' ' + width + ',' + y_05 + ' ' + width + ',' + height;
|
||||
pt_15 += ' ' + width + ',' + y_15 + ' ' + width + ',' + height;
|
||||
|
||||
|
||||
line_01.setAttribute('points', pt_01);
|
||||
line_05.setAttribute('points', pt_05);
|
||||
line_15.setAttribute('points', pt_15);
|
||||
|
||||
label_25.firstChild.data = (1.1 * 0.25 * data_max / 100).toFixed(2);
|
||||
label_50.firstChild.data = (1.1 * 0.50 * data_max / 100).toFixed(2);
|
||||
label_75.firstChild.data = (1.1 * 0.75 * data_max / 100).toFixed(2);
|
||||
|
||||
label_01_cur.innerHTML = (data_01[data_01.length-1] / 100).toFixed(2);
|
||||
label_05_cur.innerHTML = (data_05[data_05.length-1] / 100).toFixed(2);
|
||||
label_15_cur.innerHTML = (data_15[data_15.length-1] / 100).toFixed(2);
|
||||
|
||||
label_01_avg.innerHTML = (data_01_avg / 100).toFixed(2);
|
||||
label_05_avg.innerHTML = (data_05_avg / 100).toFixed(2);
|
||||
label_15_avg.innerHTML = (data_15_avg / 100).toFixed(2);
|
||||
|
||||
label_01_peak.innerHTML = (data_01_peak / 100).toFixed(2);
|
||||
label_05_peak.innerHTML = (data_05_peak / 100).toFixed(2);
|
||||
label_15_peak.innerHTML = (data_15_peak / 100).toFixed(2);
|
||||
}
|
||||
);
|
||||
|
||||
XHR.run();
|
||||
}
|
||||
}, 1000
|
||||
);
|
||||
//]]></script>
|
||||
|
||||
<h2 name="content"><%:Realtime Load%></h2>
|
||||
|
||||
<embed id="bwsvg" style="width:100%; height:300px; border:1px solid #000000; background-color:#FFFFFF" src="<%=resource%>/load.svg" />
|
||||
<div style="text-align:right"><small id="scale">-</small></div>
|
||||
<br />
|
||||
|
||||
<div class="table" style="width:100%; table-layout:fixed" cellspacing="5">
|
||||
<div class="tr">
|
||||
<div class="td" style="text-align:right; vertical-align:top"><strong style="border-bottom:2px solid #ff0000; white-space:nowrap"><%:1 Minute Load:%></strong></div>
|
||||
<div class="td" id="lb_load01_cur">0</div>
|
||||
|
||||
<div class="td" style="text-align:right; vertical-align:top"><strong><%:Average:%></strong></div>
|
||||
<div class="td" id="lb_load01_avg">0</div>
|
||||
|
||||
<div class="td" style="text-align:right; vertical-align:top"><strong><%:Peak:%></strong></div>
|
||||
<div class="td" id="lb_load01_peak">0</div>
|
||||
</div>
|
||||
<div class="tr">
|
||||
<div class="td" style="text-align:right; vertical-align:top"><strong style="border-bottom:2px solid #ff6600; white-space:nowrap"><%:5 Minute Load:%></strong></div>
|
||||
<div class="td" id="lb_load05_cur">0</div>
|
||||
|
||||
<div class="td" style="text-align:right; vertical-align:top"><strong><%:Average:%></strong></div>
|
||||
<div class="td" id="lb_load05_avg">0</div>
|
||||
|
||||
<div class="td" style="text-align:right; vertical-align:top"><strong><%:Peak:%></strong></div>
|
||||
<div class="td" id="lb_load05_peak">0</div>
|
||||
</div>
|
||||
<div class="tr">
|
||||
<div class="td" style="text-align:right; vertical-align:top"><strong style="border-bottom:2px solid #ffaa00; white-space:nowrap"><%:15 Minute Load:%></strong></div>
|
||||
<div class="td" id="lb_load15_cur">0</div>
|
||||
|
||||
<div class="td" style="text-align:right; vertical-align:top"><strong><%:Average:%></strong></div>
|
||||
<div class="td" id="lb_load15_avg">0</div>
|
||||
|
||||
<div class="td" style="text-align:right; vertical-align:top"><strong><%:Peak:%></strong></div>
|
||||
<div class="td" id="lb_load15_peak">0</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%+footer%>
|
156
luci-mod-status/luasrc/view/admin_status/routes.htm
Normal file
156
luci-mod-status/luasrc/view/admin_status/routes.htm
Normal file
|
@ -0,0 +1,156 @@
|
|||
<%#
|
||||
Copyright 2008-2009 Steven Barth <steven@midlink.org>
|
||||
Copyright 2008-2015 Jo-Philipp Wich <jow@openwrt.org>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<%-
|
||||
require "luci.tools.webadmin"
|
||||
require "nixio.fs"
|
||||
|
||||
local ip = require "luci.ip"
|
||||
local style = true
|
||||
local _, v
|
||||
|
||||
local rtn = {
|
||||
[255] = "local",
|
||||
[254] = "main",
|
||||
[253] = "default",
|
||||
[0] = "unspec"
|
||||
}
|
||||
|
||||
if nixio.fs.access("/etc/iproute2/rt_tables") then
|
||||
local ln
|
||||
for ln in io.lines("/etc/iproute2/rt_tables") do
|
||||
local i, n = ln:match("^(%d+)%s+(%S+)")
|
||||
if i and n then
|
||||
rtn[tonumber(i)] = n
|
||||
end
|
||||
end
|
||||
end
|
||||
-%>
|
||||
|
||||
<%+header%>
|
||||
|
||||
|
||||
<div class="cbi-map" id="cbi-network">
|
||||
<h2 name="content"><%:Routes%></h2>
|
||||
<div class="cbi-map-descr"><%:The following rules are currently active on this system.%></div>
|
||||
|
||||
<div class="cbi-section">
|
||||
<legend>ARP</legend>
|
||||
<div class="cbi-section-node">
|
||||
<div class="table">
|
||||
<div class="tr table-titles">
|
||||
<div class="th"><%_<abbr title="Internet Protocol Version 4">IPv4</abbr>-Address%></div>
|
||||
<div class="th"><%_<abbr title="Media Access Control">MAC</abbr>-Address%></div>
|
||||
<div class="th"><%:Interface%></div>
|
||||
</div>
|
||||
|
||||
<%
|
||||
for _, v in ipairs(ip.neighbors({ family = 4 })) do
|
||||
if v.mac then
|
||||
%>
|
||||
<div class="tr cbi-rowstyle-<%=(style and 1 or 2)%>">
|
||||
<div class="td"><%=v.dest%></div>
|
||||
<div class="td"><%=v.mac%></div>
|
||||
<div class="td"><%=luci.tools.webadmin.iface_get_network(v.dev) or '(' .. v.dev .. ')'%></div>
|
||||
</div>
|
||||
<%
|
||||
style = not style
|
||||
end
|
||||
end
|
||||
%>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cbi-section">
|
||||
<legend><%_Active <abbr title="Internet Protocol Version 4">IPv4</abbr>-Routes%></legend>
|
||||
<div class="cbi-section-node">
|
||||
<div class="table">
|
||||
<div class="tr table-titles">
|
||||
<div class="th"><%:Network%></div>
|
||||
<div class="th"><%:Target%></div>
|
||||
<div class="th"><%_<abbr title="Internet Protocol Version 4">IPv4</abbr>-Gateway%></div>
|
||||
<div class="th"><%:Metric%></div>
|
||||
<div class="th"><%:Table%></div>
|
||||
</div>
|
||||
<% for _, v in ipairs(ip.routes({ family = 4, type = 1 })) do %>
|
||||
<div class="tr cbi-rowstyle-<%=(style and 1 or 2)%>">
|
||||
<div class="td"><%=luci.tools.webadmin.iface_get_network(v.dev) or v.dev%></div>
|
||||
<div class="td"><%=v.dest%></div>
|
||||
<div class="td"><%=v.gw or "-"%></div>
|
||||
<div class="td"><%=v.metric or 0%></div>
|
||||
<div class="td"><%=rtn[v.table] or v.table%></div>
|
||||
</div>
|
||||
<% style = not style end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%
|
||||
if nixio.fs.access("/proc/net/ipv6_route") then
|
||||
style = true
|
||||
%>
|
||||
<div class="cbi-section">
|
||||
<legend><%_Active <abbr title="Internet Protocol Version 6">IPv6</abbr>-Routes%></legend>
|
||||
<div class="cbi-section-node">
|
||||
<div class="table">
|
||||
<div class="tr table-titles">
|
||||
<div class="th"><%:Network%></div>
|
||||
<div class="th"><%:Target%></div>
|
||||
<div class="th"><%:Source%></div>
|
||||
<div class="th"><%:Metric%></div>
|
||||
<div class="th"><%:Table%></div>
|
||||
</div>
|
||||
<%
|
||||
for _, v in ipairs(ip.routes({ family = 6, type = 1 })) do
|
||||
if v.dest and not v.dest:is6linklocal() then
|
||||
%>
|
||||
<div class="tr cbi-rowstyle-<%=(style and 1 or 2)%>">
|
||||
<div class="td"><%=luci.tools.webadmin.iface_get_network(v.dev) or '(' .. v.dev .. ')'%></div>
|
||||
<div class="td"><%=v.dest%></div>
|
||||
<div class="td"><%=v.from%></div>
|
||||
<div class="td"><%=v.metric or 0%></div>
|
||||
<div class="td"><%=rtn[v.table] or v.table%></div>
|
||||
</div>
|
||||
<%
|
||||
style = not style
|
||||
end
|
||||
end
|
||||
%>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cbi-section">
|
||||
<legend><%:IPv6 Neighbours%></legend>
|
||||
<div class="cbi-section-node">
|
||||
<div class="table">
|
||||
<div class="tr table-titles">
|
||||
<div class="th"><%:IPv6-Address%></div>
|
||||
<div class="th"><%:MAC-Address%></div>
|
||||
<div class="th"><%:Interface%></div>
|
||||
</div>
|
||||
<%
|
||||
for _, v in ipairs(ip.neighbors({ family = 6 })) do
|
||||
if v.dest and not v.dest:is6linklocal() and v.mac then
|
||||
%>
|
||||
<div class="tr cbi-rowstyle-<%=(style and 1 or 2)%>">
|
||||
<div class="td"><%=v.dest%></div>
|
||||
<div class="td"><%=v.mac%></div>
|
||||
<div class="td"><%=luci.tools.webadmin.iface_get_network(v.dev) or '(' .. v.dev .. ')'%></div>
|
||||
</div>
|
||||
<%
|
||||
style = not style
|
||||
end
|
||||
end
|
||||
%>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<%+footer%>
|
12
luci-mod-status/luasrc/view/admin_status/syslog.htm
Normal file
12
luci-mod-status/luasrc/view/admin_status/syslog.htm
Normal file
|
@ -0,0 +1,12 @@
|
|||
<%#
|
||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
Copyright 2008 Jo-Philipp Wich <jow@openwrt.org>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<%+header%>
|
||||
<h2 name="content"><%:System Log%></h2>
|
||||
<div id="content_syslog">
|
||||
<textarea style="font-size: 12px;" readonly="readonly" wrap="off" rows="<%=syslog:cmatch("\n")+2%>" id="syslog"><%=syslog:pcdata()%></textarea>
|
||||
</div>
|
||||
<%+footer%>
|
370
luci-mod-status/luasrc/view/admin_status/wireless.htm
Normal file
370
luci-mod-status/luasrc/view/admin_status/wireless.htm
Normal file
|
@ -0,0 +1,370 @@
|
|||
<%#
|
||||
Copyright 2011-2018 Jo-Philipp Wich <jo@mein.io>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<%-
|
||||
local ntm = require "luci.model.network".init()
|
||||
|
||||
local dev
|
||||
local devices = { }
|
||||
for _, dev in luci.util.vspairs(luci.sys.net.devices()) do
|
||||
if dev:match("^wlan%d") or dev:match("^ath%d") or dev:match("^wl%d") then
|
||||
devices[#devices+1] = dev
|
||||
end
|
||||
end
|
||||
|
||||
local curdev = luci.http.formvalue("dev") or devices[1]
|
||||
-%>
|
||||
|
||||
<%+header%>
|
||||
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
var bwxhr = new XHR();
|
||||
|
||||
var G, G2;
|
||||
var TIME = 0;
|
||||
var RATE = 1;
|
||||
var RSSI = 2;
|
||||
var NOISE = 3;
|
||||
|
||||
var width = 760;
|
||||
var height = 300;
|
||||
var step = 5;
|
||||
|
||||
var data_wanted = Math.floor(width / step);
|
||||
var data_fill = 1;
|
||||
var data_stamp = 0;
|
||||
|
||||
var data_rssi = [ ];
|
||||
var data_noise = [ ];
|
||||
var data_rate = [ ];
|
||||
|
||||
var line_rssi;
|
||||
var line_noise;
|
||||
var line_rate;
|
||||
|
||||
var label_25, label_25_2;
|
||||
var label_50, label_50_2;
|
||||
var label_75, label_75_2;
|
||||
|
||||
var label_rssi_cur;
|
||||
var label_rssi_avg;
|
||||
var label_rssi_peak;
|
||||
|
||||
var label_noise_cur;
|
||||
var label_noise_avg;
|
||||
var label_noise_peak;
|
||||
|
||||
var label_rate_cur;
|
||||
var label_rate_avg;
|
||||
var label_rate_peak;
|
||||
|
||||
var label_scale;
|
||||
var label_scale_2;
|
||||
|
||||
|
||||
/* wait for SVG */
|
||||
window.setTimeout(
|
||||
function() {
|
||||
var svg = document.getElementById('iwsvg');
|
||||
var svg2 = document.getElementById('iwsvg2');
|
||||
|
||||
try {
|
||||
G = svg.getSVGDocument
|
||||
? svg.getSVGDocument() : svg.contentDocument;
|
||||
G2 = svg2.getSVGDocument
|
||||
? svg2.getSVGDocument() : svg2.contentDocument;
|
||||
}
|
||||
catch(e) {
|
||||
G = document.embeds['iwsvg'].getSVGDocument();
|
||||
G2 = document.embeds['iwsvg2'].getSVGDocument();
|
||||
}
|
||||
|
||||
if (!G || !G2)
|
||||
{
|
||||
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_rssi[i] = 0;
|
||||
data_noise[i] = 0;
|
||||
data_rate[i] = 0;
|
||||
}
|
||||
|
||||
/* find svg elements */
|
||||
line_rssi = G.getElementById('rssi');
|
||||
line_noise = G.getElementById('noise');
|
||||
line_rate = G2.getElementById('rate');
|
||||
|
||||
label_25 = G.getElementById('label_25');
|
||||
label_50 = G.getElementById('label_50');
|
||||
label_75 = G.getElementById('label_75');
|
||||
label_25_2 = G2.getElementById('label_25');
|
||||
label_50_2 = G2.getElementById('label_50');
|
||||
label_75_2 = G2.getElementById('label_75');
|
||||
|
||||
label_rssi_cur = document.getElementById('rssi_bw_cur');
|
||||
label_rssi_avg = document.getElementById('rssi_bw_avg');
|
||||
label_rssi_peak = document.getElementById('rssi_bw_peak');
|
||||
|
||||
label_noise_cur = document.getElementById('noise_bw_cur');
|
||||
label_noise_avg = document.getElementById('noise_bw_avg');
|
||||
label_noise_peak = document.getElementById('noise_bw_peak');
|
||||
|
||||
label_rate_cur = document.getElementById('rate_bw_cur');
|
||||
label_rate_avg = document.getElementById('rate_bw_avg');
|
||||
label_rate_peak = document.getElementById('rate_bw_peak');
|
||||
|
||||
label_scale = document.getElementById('scale');
|
||||
label_scale_2 = document.getElementById('scale2');
|
||||
|
||||
|
||||
/* plot horizontal time interval lines */
|
||||
for (var i = width % (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:#eee; font-size:9pt; font-family:sans-serif; text-shadow:1px 1px 1px #000');
|
||||
text.appendChild(G.createTextNode(Math.round((width - i) / step / 60) + 'm'));
|
||||
|
||||
label_25.parentNode.appendChild(line);
|
||||
label_25.parentNode.appendChild(text);
|
||||
|
||||
|
||||
var line2 = G2.createElementNS('http://www.w3.org/2000/svg', 'line');
|
||||
line2.setAttribute('x1', i);
|
||||
line2.setAttribute('y1', 0);
|
||||
line2.setAttribute('x2', i);
|
||||
line2.setAttribute('y2', '100%');
|
||||
line2.setAttribute('style', 'stroke:black;stroke-width:0.1');
|
||||
|
||||
var text2 = G2.createElementNS('http://www.w3.org/2000/svg', 'text');
|
||||
text2.setAttribute('x', i + 5);
|
||||
text2.setAttribute('y', 15);
|
||||
text2.setAttribute('style', 'fill:#eee; font-size:9pt; font-family:sans-serif; text-shadow:1px 1px 1px #000');
|
||||
text2.appendChild(G.createTextNode(Math.round((width - i) / step / 60) + 'm'));
|
||||
|
||||
label_25_2.parentNode.appendChild(line2);
|
||||
label_25_2.parentNode.appendChild(text2);
|
||||
}
|
||||
|
||||
label_scale.innerHTML = String.format('<%:(%d minute window, %d second interval)%>', data_wanted / 60, 3);
|
||||
label_scale_2.innerHTML = String.format('<%:(%d minute window, %d second interval)%>', data_wanted / 60, 3);
|
||||
|
||||
/* render datasets, start update interval */
|
||||
XHR.poll(3, '<%=build_url("admin/status/realtime/wireless_status", curdev)%>', null,
|
||||
function(x, data)
|
||||
{
|
||||
var noise_floor = 255;
|
||||
var rate_floor = 60000;
|
||||
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
noise_floor = Math.min(noise_floor, data[i][NOISE]);
|
||||
rate_floor = Math.min(rate_floor, data[i][RATE]);
|
||||
}
|
||||
|
||||
noise_floor -= 5;
|
||||
|
||||
var data_max = 0;
|
||||
var data_scale = 0;
|
||||
var data_max_2 = 0;
|
||||
var data_scale_2 = 0;
|
||||
|
||||
var data_rssi_avg = 0;
|
||||
var data_noise_avg = 0;
|
||||
var data_rate_avg = 0;
|
||||
|
||||
var data_rssi_peak = 0;
|
||||
var data_noise_peak = 0;
|
||||
var data_rate_peak = 0;
|
||||
|
||||
for (var i = data_stamp ? 0 : 1; i < data.length; i++)
|
||||
{
|
||||
/* skip overlapping entries */
|
||||
if (data[i][TIME] <= data_stamp)
|
||||
continue;
|
||||
|
||||
data_fill++;
|
||||
|
||||
data_rssi.push(data[i][RSSI] - noise_floor);
|
||||
data_noise.push(data[i][NOISE] - noise_floor);
|
||||
data_rate.push(Math.floor(data[i][RATE] / 1000));
|
||||
}
|
||||
|
||||
/* cut off outdated entries */
|
||||
data_fill = Math.min(data_fill, data_wanted);
|
||||
data_rssi = data_rssi.slice(data_rssi.length - data_wanted, data_rssi.length);
|
||||
data_noise = data_noise.slice(data_noise.length - data_wanted, data_noise.length);
|
||||
data_rate = data_rate.slice(data_rate.length - data_wanted, data_rate.length);
|
||||
|
||||
/* find peak */
|
||||
for (var i = 0; i < data_rssi.length; i++)
|
||||
{
|
||||
data_max = Math.max(data_max, data_rssi[i]);
|
||||
data_max_2 = Math.max(data_max_2, data_rate[i]);
|
||||
|
||||
data_rssi_peak = Math.max(data_rssi_peak, data_rssi[i]);
|
||||
data_noise_peak = Math.max(data_noise_peak, data_noise[i]);
|
||||
data_rate_peak = Math.max(data_rate_peak, data_rate[i]);
|
||||
|
||||
data_rssi_avg += data_rssi[i];
|
||||
data_noise_avg += data_noise[i];
|
||||
data_rate_avg += data_rate[i];
|
||||
}
|
||||
|
||||
data_rssi_avg = data_rssi_avg / data_fill;
|
||||
data_noise_avg = data_noise_avg / data_fill;
|
||||
data_rate_avg = data_rate_avg / data_fill;
|
||||
|
||||
/* remember current timestamp, calculate horizontal scale */
|
||||
data_stamp = data[data.length-1][TIME];
|
||||
data_scale = (height / (data_max * 1.1)).toFixed(1);
|
||||
data_scale_2 = (height / (data_max_2 * 1.1)).toFixed(1);
|
||||
|
||||
/* plot data */
|
||||
var pt_rssi = '0,' + height;
|
||||
var pt_noise = '0,' + height;
|
||||
var pt_rate = '0,' + height;
|
||||
|
||||
var y_rssi = 0;
|
||||
var y_noise = 0;
|
||||
var y_rate = 0;
|
||||
|
||||
for (var i = 0; i < data_rssi.length; i++)
|
||||
{
|
||||
var x = i * step;
|
||||
|
||||
y_rssi = height - Math.floor(data_rssi[i] * data_scale);
|
||||
y_noise = height - Math.floor(data_noise[i] * data_scale);
|
||||
y_rate = height - Math.floor(data_rate[i] * data_scale_2);
|
||||
|
||||
y_rssi -= Math.floor(y_rssi % (1/data_scale));
|
||||
y_noise -= Math.floor(y_noise % (1/data_scale));
|
||||
|
||||
pt_rssi += ' ' + x + ',' + y_rssi;
|
||||
pt_noise += ' ' + x + ',' + y_noise;
|
||||
pt_rate += ' ' + x + ',' + y_rate;
|
||||
}
|
||||
|
||||
pt_rssi += ' ' + width + ',' + y_rssi + ' ' + width + ',' + height;
|
||||
pt_noise += ' ' + width + ',' + y_noise + ' ' + width + ',' + height;
|
||||
pt_rate += ' ' + width + ',' + y_rate + ' ' + width + ',' + height;
|
||||
|
||||
line_rssi.setAttribute('points', pt_rssi);
|
||||
line_noise.setAttribute('points', pt_noise);
|
||||
line_rate.setAttribute('points', pt_rate);
|
||||
|
||||
function wireless_label(dbm, noise)
|
||||
{
|
||||
if (noise)
|
||||
return String.format("%d <%:dBm%> (SNR %d <%:dB%>)", noise_floor + dbm - 255, dbm - noise);
|
||||
else
|
||||
return String.format("%d <%:dBm%>", noise_floor + dbm - 255);
|
||||
}
|
||||
|
||||
function rate_label(mbit)
|
||||
{
|
||||
return String.format("%d <%:Mbit/s%>", mbit);
|
||||
}
|
||||
|
||||
label_25.firstChild.data = wireless_label(1.1 * 0.25 * data_max);
|
||||
label_50.firstChild.data = wireless_label(1.1 * 0.50 * data_max);
|
||||
label_75.firstChild.data = wireless_label(1.1 * 0.75 * data_max);
|
||||
|
||||
label_25_2.firstChild.data = rate_label(1.1 * 0.25 * data_max_2);
|
||||
label_50_2.firstChild.data = rate_label(1.1 * 0.50 * data_max_2);
|
||||
label_75_2.firstChild.data = rate_label(1.1 * 0.75 * data_max_2);
|
||||
|
||||
label_rssi_cur.innerHTML = wireless_label(data_rssi[data_rssi.length-1], data_noise[data_noise.length-1]).nobr();
|
||||
label_noise_cur.innerHTML = wireless_label(data_noise[data_noise.length-1]).nobr();
|
||||
|
||||
label_rssi_avg.innerHTML = wireless_label(data_rssi_avg, data_noise_avg).nobr();
|
||||
label_noise_avg.innerHTML = wireless_label(data_noise_avg).nobr();
|
||||
|
||||
label_rssi_peak.innerHTML = wireless_label(data_rssi_peak, data_noise_peak).nobr();
|
||||
label_noise_peak.innerHTML = wireless_label(data_noise_peak).nobr();
|
||||
|
||||
label_rate_cur.innerHTML = rate_label(data_rate[data_rate.length-1]);
|
||||
label_rate_avg.innerHTML = rate_label(data_rate_avg);
|
||||
label_rate_peak.innerHTML = rate_label(data_rate_peak);
|
||||
}
|
||||
);
|
||||
|
||||
XHR.run();
|
||||
}
|
||||
}, 1000
|
||||
);
|
||||
//]]></script>
|
||||
|
||||
<h2 name="content"><%:Realtime Wireless%></h2>
|
||||
|
||||
<ul class="cbi-tabmenu">
|
||||
<% for _, dev in ipairs(devices) do %>
|
||||
<li class="cbi-tab<%= dev == curdev and "" or "-disabled" %>"><a href="?dev=<%=pcdata(dev)%>"><%=pcdata(dev)%></a></li>
|
||||
<% end %>
|
||||
</ul>
|
||||
|
||||
<embed id="iwsvg" style="width:100%; height:300px; border:1px solid #000000; background-color:#FFFFFF" src="<%=resource%>/wireless.svg" />
|
||||
<div style="text-align:right"><small id="scale">-</small></div>
|
||||
<br />
|
||||
|
||||
<div class="table" style="width:100%; table-layout:fixed" cellspacing="5">
|
||||
<div class="tr">
|
||||
<div class="td" style="text-align:right; vertical-align:top"><strong style="border-bottom:2px solid blue"><%:Signal:%></strong></div>
|
||||
<div class="td" id="rssi_bw_cur">0 <%:dBm%></div>
|
||||
|
||||
<div class="td" style="text-align:right; vertical-align:top"><strong><%:Average:%></strong></div>
|
||||
<div class="td" id="rssi_bw_avg">0 <%:dBm%></div>
|
||||
|
||||
<div class="td" style="text-align:right; vertical-align:top"><strong><%:Peak:%></strong></div>
|
||||
<div class="td" id="rssi_bw_peak">0 <%:dBm%></div>
|
||||
</div>
|
||||
<div class="tr">
|
||||
<div class="td" style="text-align:right; vertical-align:top"><strong style="border-bottom:2px solid red"><%:Noise:%></strong></div>
|
||||
<div class="td" id="noise_bw_cur">0 <%:dBm%></div>
|
||||
|
||||
<div class="td" style="text-align:right; vertical-align:top"><strong><%:Average:%></strong></div>
|
||||
<div class="td" id="noise_bw_avg">0 <%:dBm%></div>
|
||||
|
||||
<div class="td" style="text-align:right; vertical-align:top"><strong><%:Peak:%></strong></div>
|
||||
<div class="td" id="noise_bw_peak">0 <%:dBm%></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
|
||||
<embed id="iwsvg2" style="width:100%; height:300px; border:1px solid #000000; background-color:#FFFFFF" src="<%=resource%>/wifirate.svg" />
|
||||
<div style="text-align:right"><small id="scale2">-</small></div>
|
||||
<br />
|
||||
|
||||
<div class="table" style="width:100%; table-layout:fixed" cellspacing="5">
|
||||
<div class="tr">
|
||||
<div class="td" style="text-align:right; vertical-align:top"><strong style="border-bottom:2px solid green"><%:Phy Rate:%></strong></div>
|
||||
<div class="td" id="rate_bw_cur">0 MBit/s</div>
|
||||
|
||||
<div class="td" style="text-align:right; vertical-align:top"><strong><%:Average:%></strong></div>
|
||||
<div class="td" id="rate_bw_avg">0 MBit/s</div>
|
||||
|
||||
<div class="td" style="text-align:right; vertical-align:top"><strong><%:Peak:%></strong></div>
|
||||
<div class="td" id="rate_bw_peak">0 MBit/s</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%+footer%>
|
14
luci-mod-status/src/Makefile
Normal file
14
luci-mod-status/src/Makefile
Normal file
|
@ -0,0 +1,14 @@
|
|||
%.o: %.c
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(FPIC) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
rm -f luci-bwc *.o
|
||||
|
||||
luci-bwc: luci-bwc.o
|
||||
$(CC) $(LDFLAGS) -o $@ $^ -ldl
|
||||
|
||||
compile: luci-bwc
|
||||
|
||||
install: compile
|
||||
mkdir -p $(DESTDIR)/usr/bin
|
||||
cp luci-bwc $(DESTDIR)/usr/bin/luci-bwc
|
778
luci-mod-status/src/luci-bwc.c
Normal file
778
luci-mod-status/src/luci-bwc.c
Normal file
|
@ -0,0 +1,778 @@
|
|||
/*
|
||||
* luci-bwc - Very simple bandwidth collector cache for LuCI realtime graphs
|
||||
*
|
||||
* Copyright (C) 2010 Jo-Philipp Wich <jow@openwrt.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
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <iwinfo.h>
|
||||
|
||||
#define STEP_COUNT 60
|
||||
#define STEP_TIME 1
|
||||
#define TIMEOUT 10
|
||||
|
||||
#define PID_PATH "/var/run/luci-bwc.pid"
|
||||
|
||||
#define DB_PATH "/var/lib/luci-bwc"
|
||||
#define DB_IF_FILE DB_PATH "/if/%s"
|
||||
#define DB_RD_FILE DB_PATH "/radio/%s"
|
||||
#define DB_CN_FILE DB_PATH "/connections"
|
||||
#define DB_LD_FILE DB_PATH "/load"
|
||||
|
||||
#define IF_SCAN_PATTERN \
|
||||
" %[^ :]:%u %u" \
|
||||
" %*d %*d %*d %*d %*d %*d" \
|
||||
" %u %u"
|
||||
|
||||
#define LD_SCAN_PATTERN \
|
||||
"%f %f %f"
|
||||
|
||||
|
||||
struct file_map {
|
||||
int fd;
|
||||
int size;
|
||||
char *mmap;
|
||||
};
|
||||
|
||||
struct traffic_entry {
|
||||
uint32_t time;
|
||||
uint32_t rxb;
|
||||
uint32_t rxp;
|
||||
uint32_t txb;
|
||||
uint32_t txp;
|
||||
};
|
||||
|
||||
struct conn_entry {
|
||||
uint32_t time;
|
||||
uint32_t udp;
|
||||
uint32_t tcp;
|
||||
uint32_t other;
|
||||
};
|
||||
|
||||
struct load_entry {
|
||||
uint32_t time;
|
||||
uint16_t load1;
|
||||
uint16_t load5;
|
||||
uint16_t load15;
|
||||
};
|
||||
|
||||
struct radio_entry {
|
||||
uint32_t time;
|
||||
uint16_t rate;
|
||||
uint8_t rssi;
|
||||
uint8_t noise;
|
||||
};
|
||||
|
||||
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 char *progname;
|
||||
static int prognamelen;
|
||||
|
||||
static struct iwinfo_ops *backend = NULL;
|
||||
|
||||
|
||||
static int init_directory(char *path)
|
||||
{
|
||||
char *p = path;
|
||||
|
||||
for (p = &path[1]; *p; p++)
|
||||
{
|
||||
if (*p == '/')
|
||||
{
|
||||
*p = 0;
|
||||
|
||||
if (mkdir(path, 0700) && (errno != EEXIST))
|
||||
return -1;
|
||||
|
||||
*p = '/';
|
||||
}
|
||||
}
|
||||
|
||||
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 inline uint32_t timeof(void *entry)
|
||||
{
|
||||
return ntohl(((struct traffic_entry *)entry)->time);
|
||||
}
|
||||
|
||||
static int update_file(const char *path, void *entry, int esize)
|
||||
{
|
||||
int rv = -1;
|
||||
int file;
|
||||
char *map;
|
||||
|
||||
if ((file = open(path, O_RDWR)) >= 0)
|
||||
{
|
||||
map = mmap(NULL, esize * STEP_COUNT, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED | MAP_LOCKED, file, 0);
|
||||
|
||||
if ((map != NULL) && (map != MAP_FAILED))
|
||||
{
|
||||
if (timeof(entry) > timeof(map + esize * (STEP_COUNT-1)))
|
||||
{
|
||||
memmove(map, map + esize, esize * (STEP_COUNT-1));
|
||||
memcpy(map + esize * (STEP_COUNT-1), entry, esize);
|
||||
}
|
||||
|
||||
munmap(map, esize * STEP_COUNT);
|
||||
|
||||
rv = 0;
|
||||
}
|
||||
|
||||
close(file);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int mmap_file(const char *path, int esize, struct file_map *m)
|
||||
{
|
||||
m->fd = -1;
|
||||
m->size = -1;
|
||||
m->mmap = NULL;
|
||||
|
||||
if ((m->fd = open(path, O_RDONLY)) >= 0)
|
||||
{
|
||||
m->size = STEP_COUNT * esize;
|
||||
m->mmap = mmap(NULL, m->size, PROT_READ,
|
||||
MAP_SHARED | MAP_LOCKED, m->fd, 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 void * iw_open(void)
|
||||
{
|
||||
return dlopen("/usr/lib/libiwinfo.so", RTLD_LAZY);
|
||||
}
|
||||
|
||||
static int iw_update(
|
||||
void *iw, const char *ifname, uint16_t *rate, uint8_t *rssi, uint8_t *noise
|
||||
) {
|
||||
struct iwinfo_ops *(*probe)(const char *);
|
||||
int val;
|
||||
|
||||
if (!backend)
|
||||
{
|
||||
probe = dlsym(iw, "iwinfo_backend");
|
||||
|
||||
if (!probe)
|
||||
return 0;
|
||||
|
||||
backend = probe(ifname);
|
||||
|
||||
if (!backend)
|
||||
return 0;
|
||||
}
|
||||
|
||||
*rate = (backend->bitrate && !backend->bitrate(ifname, &val)) ? val : 0;
|
||||
*rssi = (backend->signal && !backend->signal(ifname, &val)) ? val : 0;
|
||||
*noise = (backend->noise && !backend->noise(ifname, &val)) ? val : 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void iw_close(void *iw)
|
||||
{
|
||||
void (*finish)(void);
|
||||
|
||||
finish = dlsym(iw, "iwinfo_finish");
|
||||
|
||||
if (finish)
|
||||
finish();
|
||||
|
||||
dlclose(iw);
|
||||
}
|
||||
|
||||
|
||||
static int update_ifstat(
|
||||
const char *ifname, uint32_t rxb, uint32_t rxp, uint32_t txb, uint32_t txp
|
||||
) {
|
||||
char path[1024];
|
||||
|
||||
struct stat s;
|
||||
struct traffic_entry e;
|
||||
|
||||
snprintf(path, sizeof(path), DB_IF_FILE, ifname);
|
||||
|
||||
if (stat(path, &s))
|
||||
{
|
||||
if (init_file(path, sizeof(struct traffic_entry)))
|
||||
{
|
||||
fprintf(stderr, "Failed to init %s: %s\n",
|
||||
path, strerror(errno));
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
e.time = htonl(time(NULL));
|
||||
e.rxb = htonl(rxb);
|
||||
e.rxp = htonl(rxp);
|
||||
e.txb = htonl(txb);
|
||||
e.txp = htonl(txp);
|
||||
|
||||
return update_file(path, &e, sizeof(struct traffic_entry));
|
||||
}
|
||||
|
||||
static int update_radiostat(
|
||||
const char *ifname, uint16_t rate, uint8_t rssi, uint8_t noise
|
||||
) {
|
||||
char path[1024];
|
||||
|
||||
struct stat s;
|
||||
struct radio_entry e;
|
||||
|
||||
snprintf(path, sizeof(path), DB_RD_FILE, ifname);
|
||||
|
||||
if (stat(path, &s))
|
||||
{
|
||||
if (init_file(path, sizeof(struct radio_entry)))
|
||||
{
|
||||
fprintf(stderr, "Failed to init %s: %s\n",
|
||||
path, strerror(errno));
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
e.time = htonl(time(NULL));
|
||||
e.rate = htons(rate);
|
||||
e.rssi = rssi;
|
||||
e.noise = noise;
|
||||
|
||||
return update_file(path, &e, sizeof(struct radio_entry));
|
||||
}
|
||||
|
||||
static int update_cnstat(uint32_t udp, uint32_t tcp, uint32_t other)
|
||||
{
|
||||
char path[1024];
|
||||
|
||||
struct stat s;
|
||||
struct conn_entry e;
|
||||
|
||||
snprintf(path, sizeof(path), DB_CN_FILE);
|
||||
|
||||
if (stat(path, &s))
|
||||
{
|
||||
if (init_file(path, sizeof(struct conn_entry)))
|
||||
{
|
||||
fprintf(stderr, "Failed to init %s: %s\n",
|
||||
path, strerror(errno));
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
e.time = htonl(time(NULL));
|
||||
e.udp = htonl(udp);
|
||||
e.tcp = htonl(tcp);
|
||||
e.other = htonl(other);
|
||||
|
||||
return update_file(path, &e, sizeof(struct conn_entry));
|
||||
}
|
||||
|
||||
static int update_ldstat(uint16_t load1, uint16_t load5, uint16_t load15)
|
||||
{
|
||||
char path[1024];
|
||||
|
||||
struct stat s;
|
||||
struct load_entry e;
|
||||
|
||||
snprintf(path, sizeof(path), DB_LD_FILE);
|
||||
|
||||
if (stat(path, &s))
|
||||
{
|
||||
if (init_file(path, sizeof(struct load_entry)))
|
||||
{
|
||||
fprintf(stderr, "Failed to init %s: %s\n",
|
||||
path, strerror(errno));
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
e.time = htonl(time(NULL));
|
||||
e.load1 = htons(load1);
|
||||
e.load5 = htons(load5);
|
||||
e.load15 = htons(load15);
|
||||
|
||||
return update_file(path, &e, sizeof(struct load_entry));
|
||||
}
|
||||
|
||||
static int run_daemon(void)
|
||||
{
|
||||
FILE *info;
|
||||
uint32_t rxb, txb, rxp, txp;
|
||||
uint32_t udp, tcp, other;
|
||||
uint16_t rate;
|
||||
uint8_t rssi, noise;
|
||||
float lf1, lf5, lf15;
|
||||
char line[1024];
|
||||
char ifname[16];
|
||||
int i;
|
||||
void *iw;
|
||||
struct sigaction sa;
|
||||
|
||||
struct stat s;
|
||||
const char *ipc = stat("/proc/net/nf_conntrack", &s)
|
||||
? "/proc/net/ip_conntrack" : "/proc/net/nf_conntrack";
|
||||
|
||||
switch (fork())
|
||||
{
|
||||
case -1:
|
||||
perror("fork()");
|
||||
return -1;
|
||||
|
||||
case 0:
|
||||
if (chdir("/") < 0)
|
||||
{
|
||||
perror("chdir()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
close(0);
|
||||
close(1);
|
||||
close(2);
|
||||
break;
|
||||
|
||||
default:
|
||||
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;
|
||||
}
|
||||
|
||||
/* initialize iwinfo */
|
||||
iw = iw_open();
|
||||
|
||||
/* go */
|
||||
for (reset_countdown(0); countdown >= 0; countdown--)
|
||||
{
|
||||
/* alter progname for ps, top */
|
||||
memset(progname, 0, prognamelen);
|
||||
snprintf(progname, prognamelen, "luci-bwc %d", countdown);
|
||||
|
||||
if ((info = fopen("/proc/net/dev", "r")) != NULL)
|
||||
{
|
||||
while (fgets(line, sizeof(line), info))
|
||||
{
|
||||
if (strchr(line, '|'))
|
||||
continue;
|
||||
|
||||
if (sscanf(line, IF_SCAN_PATTERN, ifname, &rxb, &rxp, &txb, &txp))
|
||||
{
|
||||
if (strncmp(ifname, "lo", sizeof(ifname)))
|
||||
update_ifstat(ifname, rxb, rxp, txb, txp);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(info);
|
||||
}
|
||||
|
||||
if (iw)
|
||||
{
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
#define iw_checkif(pattern) \
|
||||
do { \
|
||||
snprintf(ifname, sizeof(ifname), pattern, i); \
|
||||
if (iw_update(iw, ifname, &rate, &rssi, &noise)) \
|
||||
{ \
|
||||
update_radiostat(ifname, rate, rssi, noise); \
|
||||
continue; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
iw_checkif("wlan%d");
|
||||
iw_checkif("ath%d");
|
||||
iw_checkif("wl%d");
|
||||
}
|
||||
}
|
||||
|
||||
if ((info = fopen(ipc, "r")) != NULL)
|
||||
{
|
||||
udp = 0;
|
||||
tcp = 0;
|
||||
other = 0;
|
||||
|
||||
while (fgets(line, sizeof(line), info))
|
||||
{
|
||||
if (strstr(line, "TIME_WAIT"))
|
||||
continue;
|
||||
|
||||
if ((strstr(line, "src=127.0.0.1 ") && strstr(line, "dst=127.0.0.1 "))
|
||||
|| (strstr(line, "src=::1 ") && strstr(line, "dst=::1 ")))
|
||||
continue;
|
||||
|
||||
if (sscanf(line, "%*s %*d %s", ifname) || sscanf(line, "%s %*d", ifname))
|
||||
{
|
||||
if (!strcmp(ifname, "tcp"))
|
||||
tcp++;
|
||||
else if (!strcmp(ifname, "udp"))
|
||||
udp++;
|
||||
else
|
||||
other++;
|
||||
}
|
||||
}
|
||||
|
||||
update_cnstat(udp, tcp, other);
|
||||
|
||||
fclose(info);
|
||||
}
|
||||
|
||||
if ((info = fopen("/proc/loadavg", "r")) != NULL)
|
||||
{
|
||||
if (fscanf(info, LD_SCAN_PATTERN, &lf1, &lf5, &lf15))
|
||||
{
|
||||
update_ldstat((uint16_t)(lf1 * 100),
|
||||
(uint16_t)(lf5 * 100),
|
||||
(uint16_t)(lf15 * 100));
|
||||
}
|
||||
|
||||
fclose(info);
|
||||
}
|
||||
|
||||
sleep(STEP_TIME);
|
||||
}
|
||||
|
||||
unlink(PID_PATH);
|
||||
|
||||
if (iw)
|
||||
iw_close(iw);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void check_daemon(void)
|
||||
{
|
||||
int pid;
|
||||
|
||||
if ((pid = readpid()) < 0 || kill(pid, 0) < 0)
|
||||
{
|
||||
/* daemon ping failed, try to start it up */
|
||||
if (run_daemon())
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Failed to ping daemon and unable to start it up: %s\n",
|
||||
strerror(errno));
|
||||
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else if (kill(pid, SIGUSR1))
|
||||
{
|
||||
fprintf(stderr, "Failed to send signal: %s\n", strerror(errno));
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
static int run_dump_ifname(const char *ifname)
|
||||
{
|
||||
int i;
|
||||
char path[1024];
|
||||
struct file_map m;
|
||||
struct traffic_entry *e;
|
||||
|
||||
check_daemon();
|
||||
snprintf(path, sizeof(path), DB_IF_FILE, ifname);
|
||||
|
||||
if (mmap_file(path, sizeof(struct traffic_entry), &m))
|
||||
{
|
||||
fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < m.size; i += sizeof(struct traffic_entry))
|
||||
{
|
||||
e = (struct traffic_entry *) &m.mmap[i];
|
||||
|
||||
if (!e->time)
|
||||
continue;
|
||||
|
||||
printf("[ %u, %u, %" PRIu32
|
||||
", %u, %u ]%s\n",
|
||||
ntohl(e->time),
|
||||
ntohl(e->rxb), ntohl(e->rxp),
|
||||
ntohl(e->txb), ntohl(e->txp),
|
||||
((i + sizeof(struct traffic_entry)) < m.size) ? "," : "");
|
||||
}
|
||||
|
||||
umap_file(&m);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int run_dump_radio(const char *ifname)
|
||||
{
|
||||
int i;
|
||||
char path[1024];
|
||||
struct file_map m;
|
||||
struct radio_entry *e;
|
||||
|
||||
check_daemon();
|
||||
snprintf(path, sizeof(path), DB_RD_FILE, ifname);
|
||||
|
||||
if (mmap_file(path, sizeof(struct radio_entry), &m))
|
||||
{
|
||||
fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < m.size; i += sizeof(struct radio_entry))
|
||||
{
|
||||
e = (struct radio_entry *) &m.mmap[i];
|
||||
|
||||
if (!e->time)
|
||||
continue;
|
||||
|
||||
printf("[ %u, %d, %d, %d ]%s\n",
|
||||
ntohl(e->time),
|
||||
e->rate, e->rssi, e->noise,
|
||||
((i + sizeof(struct radio_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;
|
||||
|
||||
check_daemon();
|
||||
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("[ %u, %u, %u, %u ]%s\n",
|
||||
ntohl(e->time), ntohl(e->udp),
|
||||
ntohl(e->tcp), ntohl(e->other),
|
||||
((i + sizeof(struct conn_entry)) < m.size) ? "," : "");
|
||||
}
|
||||
|
||||
umap_file(&m);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int run_dump_load(void)
|
||||
{
|
||||
int i;
|
||||
char path[1024];
|
||||
struct file_map m;
|
||||
struct load_entry *e;
|
||||
|
||||
check_daemon();
|
||||
snprintf(path, sizeof(path), DB_LD_FILE);
|
||||
|
||||
if (mmap_file(path, sizeof(struct load_entry), &m))
|
||||
{
|
||||
fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < m.size; i += sizeof(struct load_entry))
|
||||
{
|
||||
e = (struct load_entry *) &m.mmap[i];
|
||||
|
||||
if (!e->time)
|
||||
continue;
|
||||
|
||||
printf("[ %u, %u, %u, %u ]%s\n",
|
||||
ntohl(e->time),
|
||||
ntohs(e->load1), ntohs(e->load5), ntohs(e->load15),
|
||||
((i + sizeof(struct load_entry)) < m.size) ? "," : "");
|
||||
}
|
||||
|
||||
umap_file(&m);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int opt;
|
||||
|
||||
progname = argv[0];
|
||||
prognamelen = -1;
|
||||
|
||||
for (opt = 0; opt < argc; opt++)
|
||||
prognamelen += 1 + strlen(argv[opt]);
|
||||
|
||||
while ((opt = getopt(argc, argv, "t:i:r:cl")) > -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
case 't':
|
||||
timeout = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
if (optarg)
|
||||
return run_dump_ifname(optarg);
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
if (optarg)
|
||||
return run_dump_radio(optarg);
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
return run_dump_conns();
|
||||
|
||||
case 'l':
|
||||
return run_dump_load();
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr,
|
||||
"Usage:\n"
|
||||
" %s [-t timeout] -i ifname\n"
|
||||
" %s [-t timeout] -r radiodev\n"
|
||||
" %s [-t timeout] -c\n"
|
||||
" %s [-t timeout] -l\n",
|
||||
argv[0], argv[0], argv[0], argv[0]
|
||||
);
|
||||
|
||||
return 1;
|
||||
}
|
Loading…
Reference in a new issue