mirror of
https://github.com/lucaspalomodevelop/core.git
synced 2026-03-13 16:14:40 +00:00
interfaces: revamp overview page (#7019)
This commit omits some of the link-specific information such as ppp uptime, disconnect/release mechanism, as well as wireless and bridge information. Since there is more of this type of information available than was originally being handled by get_interfaces_info(), perhaps it makes more sense to extend the backend script with the relevant bits in time.
This commit is contained in:
parent
e90571fe6b
commit
5da37a7fac
4
plist
4
plist
@ -387,12 +387,14 @@
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/Api/LaggSettingsController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/Api/LoopbackSettingsController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/Api/NeighborSettingsController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/Api/OverviewController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/Api/VipSettingsController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/Api/VlanSettingsController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/Api/VxlanSettingsController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/LaggController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/LoopbackController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/NeighborController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/OverviewController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/VipController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/VlanController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/VxlanController.php
|
||||
@ -833,6 +835,7 @@
|
||||
/usr/local/opnsense/mvc/app/views/OPNsense/Interface/lagg.volt
|
||||
/usr/local/opnsense/mvc/app/views/OPNsense/Interface/loopback.volt
|
||||
/usr/local/opnsense/mvc/app/views/OPNsense/Interface/neighbor.volt
|
||||
/usr/local/opnsense/mvc/app/views/OPNsense/Interface/overview.volt
|
||||
/usr/local/opnsense/mvc/app/views/OPNsense/Interface/vip.volt
|
||||
/usr/local/opnsense/mvc/app/views/OPNsense/Interface/vlan.volt
|
||||
/usr/local/opnsense/mvc/app/views/OPNsense/Interface/vxlan.volt
|
||||
@ -2152,7 +2155,6 @@
|
||||
/usr/local/www/vpn_openvpn_client.php
|
||||
/usr/local/www/vpn_openvpn_server.php
|
||||
/usr/local/www/widgets/api/get.php
|
||||
/usr/local/www/widgets/api/plugins/interfaces.inc
|
||||
/usr/local/www/widgets/api/plugins/system.inc
|
||||
/usr/local/www/widgets/api/plugins/temperature.inc
|
||||
/usr/local/www/widgets/include/carp_status.inc
|
||||
|
||||
@ -0,0 +1,278 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2023 Deciso B.V.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
namespace OPNsense\Interfaces\Api;
|
||||
|
||||
use OPNsense\Base\ApiControllerBase;
|
||||
use OPNsense\Core\Backend;
|
||||
use OPNsense\Core\Config;
|
||||
use OPNsense\Firewall\Util;
|
||||
use OPNsense\Routing\Gateways;
|
||||
|
||||
class OverviewController extends ApiControllerBase
|
||||
{
|
||||
private static function translations()
|
||||
{
|
||||
return [
|
||||
'flags' => gettext('Flags'),
|
||||
'options' => gettext('Options'),
|
||||
'supported_media' => gettext('Supported Media'),
|
||||
'is_physical' => gettext('Physical'),
|
||||
'device' => gettext('Device'),
|
||||
'name' => gettext('Name'),
|
||||
'description' => gettext('Description'),
|
||||
'status' => gettext('Status'),
|
||||
'enabled' => gettext('Enabled'),
|
||||
'link_type' => gettext('Link Type'),
|
||||
'ipv4' => gettext('IPv4 Addresses'),
|
||||
'ipv6' => gettext('IPv6 Addresses'),
|
||||
'gateways' => gettext('Gateways'),
|
||||
'routes' => gettext('Routes'),
|
||||
'macaddr' => gettext('MAC Address'),
|
||||
'media_raw' => gettext('Media'),
|
||||
'mediaopt' => gettext('Media Options'),
|
||||
'capabilities' => gettext('Capabilities'),
|
||||
'identifier' => gettext('Identifier'),
|
||||
'ipaddr' => gettext('IP Address'),
|
||||
'subnetbits' => gettext('Subnet Bits'),
|
||||
'statistics' => gettext('Statistics'),
|
||||
'driver' => gettext('Driver'),
|
||||
'index' => gettext('Index'),
|
||||
'promiscuous listeners' => gettext('Promiscuous Listeners'),
|
||||
'send queue length' => gettext('Send Queue Length'),
|
||||
'send queue max length' => gettext('Send Queue Max Length'),
|
||||
'send queue drops' => gettext('Send Queue Drops'),
|
||||
'type' => gettext('Type'),
|
||||
'address length' => gettext('Address Length'),
|
||||
'header length' => gettext('Header Length'),
|
||||
'link state' => gettext('Link State'),
|
||||
'datalen' => gettext('Data Length'),
|
||||
'metric' => gettext('Metric'),
|
||||
'line rate' => gettext('Line Rate'),
|
||||
'packets received' => gettext('Packets Received'),
|
||||
'input errors' => gettext('Input Errors'),
|
||||
'packets transmitted' => gettext('Packets Transmitted'),
|
||||
'output errors' => gettext('Output Errors'),
|
||||
'collisions' => gettext('Collisions'),
|
||||
'bytes received' => gettext('Bytes Received'),
|
||||
'bytes transmitted' => gettext('Bytes Transmitted'),
|
||||
'multicasts received' => gettext('Multicasts Received'),
|
||||
'multicasts transmitted' => gettext('Multicasts Transmitted'),
|
||||
'input queue drops' => gettext('Input Queue Drops'),
|
||||
'packets for unknown protocol' => gettext('Packets for Unknown Protocol'),
|
||||
'HW offload capabilities' => gettext('Hardware Offload Capabilities'),
|
||||
'uptime at attach or stat reset' => gettext('Uptime at Attach or Statistics Reset'),
|
||||
];
|
||||
}
|
||||
|
||||
private function parseIfInfo($interface = null, $detailed = false)
|
||||
{
|
||||
$backend = new Backend();
|
||||
$gateways = new Gateways();
|
||||
$cfg = Config::getInstance()->object();
|
||||
$result = [];
|
||||
|
||||
/* quick information */
|
||||
$ifinfo = json_decode($backend->configdpRun('interface list ifconfig', [$interface]), true);
|
||||
$routes = json_decode($backend->configdRun('interface routes list -n json'), true);
|
||||
|
||||
/* detailed information */
|
||||
if ($detailed) {
|
||||
$stats = json_decode($backend->configdpRun('interface list stats', [$interface]), true);
|
||||
if (!$interface) {
|
||||
foreach ($ifinfo as $if => $info) {
|
||||
if (array_key_exists($if, $stats)) {
|
||||
$ifinfo[$if]['statistics'] = $stats[$if];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$ifinfo[$interface]['statistics'] = $stats;
|
||||
}
|
||||
}
|
||||
|
||||
/* map routes to interfaces */
|
||||
foreach($routes as $route) {
|
||||
if (!empty($route['netif']) && !empty($ifinfo[$route['netif']])) {
|
||||
$ifinfo[$route['netif']]['routes'][] = $route['destination'];
|
||||
}
|
||||
}
|
||||
|
||||
/* combine interfaces details with config */
|
||||
foreach ($cfg->interfaces->children() as $key => $node) {
|
||||
if (!empty((string)$node->if) && !empty($ifinfo[(string)$node->if])) {
|
||||
$props = [];
|
||||
foreach ($node->children() as $property) {
|
||||
$props[$property->getName()] = (string)$property;
|
||||
}
|
||||
$ifinfo[(string)$node->if]['config'] = $props;
|
||||
$ifinfo[(string)$node->if]['config']['identifier'] = $key;
|
||||
}
|
||||
}
|
||||
|
||||
/* format information */
|
||||
foreach ($ifinfo as $if => $details) {
|
||||
$tmp = $details;
|
||||
|
||||
if ($if == 'pfsync0') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$tmp['status'] = (!empty($details['flags']) && in_array('up', $details['flags'])) ? 'up' : 'down';
|
||||
if (!empty($details['status'])) {
|
||||
if (!(in_array($details['status'] , ['active', 'running']))) {
|
||||
/* reflect current ifconfig status, such as 'no carrier' */
|
||||
$tmp['status'] = $details['status'];
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($details['config'])) {
|
||||
$tmp['identifier'] = '';
|
||||
$tmp['description'] = gettext('Unassigned Interface');
|
||||
$result[] = $tmp;
|
||||
continue;
|
||||
}
|
||||
|
||||
$config = $details['config'];
|
||||
|
||||
$tmp['identifier'] = $config['identifier'];
|
||||
$tmp['description'] = !empty($config['descr']) ? $config['descr'] : strtoupper($config['identifier']);
|
||||
$tmp['enabled'] = !empty($config['enable']);
|
||||
$tmp['link_type'] = !empty($config['ipaddr']) ? $config['ipaddr'] : 'none';
|
||||
if (Util::isIpAddress($tmp['link_type'])) {
|
||||
$tmp['link_type'] = 'static';
|
||||
}
|
||||
|
||||
/* parse IP configuration */
|
||||
unset($tmp['ipv4'], $tmp['ipv6']);
|
||||
foreach (['ipv4', 'ipv6'] as $ipproto) {
|
||||
if (!empty($details[$ipproto])) {
|
||||
foreach ($details[$ipproto] as $ip) {
|
||||
if (!empty($ip['ipaddr'])) {
|
||||
$entry = [];
|
||||
$entry['ipaddr'] = $ip['ipaddr'] . '/' . $ip['subnetbits'];
|
||||
|
||||
if (!empty($ip['vhid'])) {
|
||||
$vhid = $ip['vhid'];
|
||||
$entry['vhid'] = $vhid;
|
||||
|
||||
if (!empty($details['carp'])) {
|
||||
foreach ($details['carp'] as $carp) {
|
||||
if ($carp['vhid'] == $vhid) {
|
||||
$entry['status'] = $carp['status'];
|
||||
$entry['advbase'] = $carp['advbase'];
|
||||
$entry['advskew'] = $carp['advskew'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$tmp[$ipproto][] = $entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* gateway(s) */
|
||||
$gatewayv4 = $gateways->getInterfaceGateway($tmp['identifier'] , 'inet');
|
||||
$gatewayv6 = $gateways->getInterfaceGateway($tmp['identifier'], 'inet6');
|
||||
$tmp['gateways'] = array_filter([$gatewayv4, $gatewayv6]);
|
||||
|
||||
$result[] = $tmp;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function interfacesInfoAction($details = false)
|
||||
{
|
||||
$this->sessionClose();
|
||||
$result = $this->parseIfInfo(null, $details);
|
||||
return $this->searchRecordsetBase($result);
|
||||
}
|
||||
|
||||
public function getInterfaceAction($if = null)
|
||||
{
|
||||
$this->sessionClose();
|
||||
$result = ["message" => "failed"];
|
||||
if ($if != null) {
|
||||
$ifinfo = $this->parseIfInfo($if, true)[0] ?? [];
|
||||
if (!empty($ifinfo)) {
|
||||
if (!empty($ifinfo['macaddr'])) {
|
||||
$macs = json_decode((new Backend())->configdRun('interface list macdb json'), true);
|
||||
$mac_hi = strtoupper(substr(str_replace(':', '', $ifinfo['macaddr']), 0, 6));
|
||||
if (array_key_exists($mac_hi, $macs)) {
|
||||
$ifinfo['macaddr'] = $ifinfo['macaddr'] . ' - ' . $macs[$mac_hi];
|
||||
}
|
||||
}
|
||||
|
||||
/* move statistics one level up */
|
||||
if (isset($ifinfo['statistics'])) {
|
||||
$stats = $ifinfo['statistics'];
|
||||
unset($ifinfo['statistics']);
|
||||
|
||||
$ifinfo = array_merge($ifinfo, $stats);
|
||||
}
|
||||
|
||||
unset($ifinfo['config']);
|
||||
|
||||
/* apply translations */
|
||||
foreach ($ifinfo as $key => $value) {
|
||||
$ifinfo[$key] = [
|
||||
'value' => $value,
|
||||
'translation' => self::translations()[$key] ?? $key
|
||||
];
|
||||
}
|
||||
|
||||
$result['message'] = $ifinfo;
|
||||
}
|
||||
}
|
||||
|
||||
return json_encode($result);
|
||||
}
|
||||
|
||||
public function reloadInterfaceAction($identifier = null)
|
||||
{
|
||||
$this->sessionClose();
|
||||
$result = ["message" => "failed"];
|
||||
|
||||
if ($identifier != null) {
|
||||
$backend = new Backend();
|
||||
$result['message'] = $backend->configdpRun('interface reconfigure', [$identifier]);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function exportAction()
|
||||
{
|
||||
$this->sessionClose();
|
||||
$this->response->setRawHeader('Content-Type: application/json');
|
||||
$this->response->setRawHeader('Content-Disposition: attachment; filename=ifconfig.json');
|
||||
echo (new Backend())->configdRun('interface list ifconfig');
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013 Deciso B.V.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
namespace OPNsense\Interfaces;
|
||||
|
||||
class OverviewController extends \OPNsense\Base\IndexController
|
||||
{
|
||||
public function indexAction()
|
||||
{
|
||||
$this->view->pick('OPNsense/Interface/overview');
|
||||
}
|
||||
}
|
||||
@ -99,6 +99,7 @@
|
||||
<Interfaces order="30" cssClass="fa fa-sitemap">
|
||||
<Assignments order="900" url="/interfaces_assign.php" cssClass="fa fa-pencil fa-fw"/>
|
||||
<Overview order="910" url="/status_interfaces.php" cssClass="fa fa-tasks fa-fw"/>
|
||||
<Overview_new VisibleName="Overview [new]" order="915" url="/ui/interfaces/overview" cssClass="fa fa-tasks fa-fw"/>
|
||||
<Settings order="920" url="/system_advanced_network.php" cssClass="fa fa-cogs fa-fw"/>
|
||||
<Neighbors order="930" url="/ui/interfaces/neighbor" cssClass="fa fa-users fa-fw"/>
|
||||
<Wireless order="940" cssClass="fa fa-wifi fa-fw">
|
||||
|
||||
318
src/opnsense/mvc/app/views/OPNsense/Interface/overview.volt
Normal file
318
src/opnsense/mvc/app/views/OPNsense/Interface/overview.volt
Normal file
@ -0,0 +1,318 @@
|
||||
{#
|
||||
# Copyright (c) 2023 Deciso B.V.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#}
|
||||
|
||||
<script>
|
||||
$( document ).ready(function() {
|
||||
function format_linerate(value) {
|
||||
if (!isNaN(value) && value > 0) {
|
||||
let fileSizeTypes = ["", "K", "M", "G", "T", "P", "E", "Z", "Y"];
|
||||
let ndx = Math.floor(Math.log(value) / Math.log(1000) );
|
||||
if (ndx > 0) {
|
||||
return (value / Math.pow(1000, ndx)).toFixed(2) + ' ' + fileSizeTypes[ndx] + 'bit/s';
|
||||
} else {
|
||||
return value.toFixed(2).toString();
|
||||
}
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
function iterate_ips(obj) {
|
||||
let $elements = $('<div></div>');
|
||||
obj.forEach(function (ip) {
|
||||
$span = $('<span></span><br/>').text(ip['ipaddr'] + ' ');
|
||||
if ('vhid' in ip) {
|
||||
$carp = $('<span></span>').text('vhid ' + ip['vhid']);
|
||||
$carp.attr('class', 'bootgrid-tooltip badge badge-pill');
|
||||
$carp.css('background-color', ip['status'] == 'MASTER' ? 'green' : 'primary');
|
||||
$carp.attr('data-toggle', 'tooltip');
|
||||
$carp.attr('title', ip['status']);
|
||||
$span.append($carp);
|
||||
}
|
||||
$elements.append($span);
|
||||
});
|
||||
return $elements.prop('outerHTML');
|
||||
}
|
||||
|
||||
$("#grid-overview").UIBootgrid(
|
||||
{
|
||||
search: '/api/interfaces/overview/interfacesInfo',
|
||||
options: {
|
||||
selection: false,
|
||||
formatters: {
|
||||
"interface": function (column, row) {
|
||||
let descr = row.description;
|
||||
if (row.identifier) {
|
||||
descr += ' (' + row.identifier + ')';
|
||||
}
|
||||
return descr;
|
||||
},
|
||||
"routes": function (column, row) {
|
||||
let $elements = $('<div></div>').attr('class', 'route-container');
|
||||
if (row.routes) {
|
||||
let i = 0;
|
||||
row.routes.forEach(function (route) {
|
||||
let $route = $('<span></span>').attr('class', 'route-content').text(route);
|
||||
if (route == 'default') {
|
||||
$route.css('color', 'green');
|
||||
}
|
||||
if (i > 1) {
|
||||
$route.css("display", "none");
|
||||
}
|
||||
$elements.append($route.append($('<br/>')));
|
||||
i++;
|
||||
});
|
||||
$elements.append($('<button></button>')
|
||||
.attr('class', 'route-expand btn btn-primary btn-xs')
|
||||
.text('Expand'));
|
||||
}
|
||||
return $elements.prop('outerHTML');
|
||||
|
||||
},
|
||||
"status": function (column, row) {
|
||||
let connected = row.status == 'up' ? 'text-success' : 'text-danger';
|
||||
|
||||
if (!row.enabled) {
|
||||
row.status += ' (disabled)';
|
||||
}
|
||||
|
||||
return '<i class="fa fa-plug ' + connected + '" title="' + row.status + '" data-toggle="tooltip"></i>';
|
||||
},
|
||||
"ipv4": function (column, row) {
|
||||
if (row.ipv4) {
|
||||
return iterate_ips(row.ipv4);
|
||||
}
|
||||
|
||||
return '';
|
||||
},
|
||||
"ipv6": function (column, row) {
|
||||
if (row.ipv6) {
|
||||
return iterate_ips(row.ipv6);
|
||||
}
|
||||
|
||||
return '';
|
||||
},
|
||||
"gateways": function (column, row) {
|
||||
let $elements = $('<div></div>');
|
||||
if (row.gateways) {
|
||||
row.gateways.forEach(function (gw) {
|
||||
let $span = $('<span></span><br/>').text(gw);
|
||||
$elements.append($span);
|
||||
});
|
||||
}
|
||||
return $elements.prop('outerHTML');
|
||||
},
|
||||
"commands": function (column, row) {
|
||||
let $commands = $('<div></div>');
|
||||
let $btn = $('<button type="button" class="btn btn-xs btn-default" data-toggle="tooltip"">\
|
||||
<i></i></button>');
|
||||
|
||||
if ('link_type' in row) {
|
||||
if (["dhcp", "pppoe", "pptp", "l2tp", "ppp"].includes(row.link_type)) {
|
||||
let $command = $btn.clone();
|
||||
$command.addClass('interface-reload').attr('title', 'Reload').attr('data-device-id', row.identifier);
|
||||
$command.find('i').addClass('fa fa-fw fa-refresh');
|
||||
$commands.append($command);
|
||||
}
|
||||
}
|
||||
$btn.addClass('interface-info').attr('title', 'Info').attr('data-row-id', row.device);
|
||||
$btn.find('i').addClass('fa fa-fw fa-search');
|
||||
$commands.append($btn);
|
||||
return $commands.prop('outerHTML');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
).on("loaded.rs.jquery.bootgrid", function (e) {
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
|
||||
/* attach event handler to reload buttons */
|
||||
$('.interface-reload').each(function () {
|
||||
$(this).click(function () {
|
||||
let $element = $(this);
|
||||
let device = $(this).data("device-id");
|
||||
$element.remove('i').html('<i class="fa fa-spinner fa-spin"></i>');
|
||||
ajaxCall('/api/interfaces/overview/reloadInterface/' + device, {}, function (data, status) {
|
||||
/* delay slightly to allow the interface to come up */
|
||||
setTimeout(function() {
|
||||
$element.remove('i').html('<i class="fa fa-fw fa-refresh"></i>');
|
||||
$("#grid-overview").bootgrid('reload');
|
||||
}, 1000);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
/* attach event handler to the command-info button */
|
||||
$(".interface-info").each(function () {
|
||||
$(this).click(function () {
|
||||
let $element = $(this);
|
||||
let device = $(this).data("row-id");
|
||||
|
||||
ajaxGet('/api/interfaces/overview/getInterface/' + device, {}, function(data, status) {
|
||||
data = data['message'];
|
||||
let $table = $('<table class="table table-bordered table-condensed table-hover table-striped"></table>');
|
||||
let $table_body = $('<tbody/>');
|
||||
|
||||
for (let key in data) {
|
||||
let $row = $('<tr/>');
|
||||
let value = data[key]['value'];
|
||||
if (key === 'line rate') {
|
||||
value = format_linerate(value.split(" ")[0]);
|
||||
}
|
||||
if (key === 'ipv4' || key === 'ipv6') {
|
||||
value = iterate_ips(value);
|
||||
}
|
||||
|
||||
if (!'translation' in data[key]) {
|
||||
continue;
|
||||
}
|
||||
key = data[key]['translation'];
|
||||
if (typeof value === 'string' || Array.isArray(value)) {
|
||||
value = value.toString().split(",").join("<br/>");
|
||||
}
|
||||
$row.append($('<td/>').text(key));
|
||||
$row.append($('<td/>').html(value));
|
||||
$table_body.append($row);
|
||||
}
|
||||
|
||||
$table.append($table_body);
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
BootstrapDialog.show({
|
||||
title: data['description']['value'],
|
||||
message: $table.prop('outerHTML'),
|
||||
type: BootstrapDialog.TYPE_INFO,
|
||||
draggable: true,
|
||||
cssClass: 'details-dialog',
|
||||
buttons: [{
|
||||
label: "{{ lang._('Close') }}",
|
||||
action: function (dialogRef) {
|
||||
dialogRef.close();
|
||||
}
|
||||
}]
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
$(".route-container").each(function () {
|
||||
let $route_container = $(this);
|
||||
let count = $(this).children('.route-content').length;
|
||||
let $expand = $(this).find(".route-expand");
|
||||
|
||||
if (count > 2) {
|
||||
$expand.show();
|
||||
}
|
||||
|
||||
$expand.click(function () {
|
||||
let $collapsed = $route_container.children('.route-content').filter(function() {
|
||||
return $(this).css('display').toLowerCase().indexOf('none') > -1;
|
||||
});
|
||||
if ($collapsed.length > 0) {
|
||||
$collapsed.show();
|
||||
$expand.html('Collapse');
|
||||
} else {
|
||||
$collapse = $route_container.children('.route-content').slice(2);
|
||||
$collapse.hide();
|
||||
$expand.html('Expand');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
$("#export-wrapper").detach().appendTo('#grid-overview-header > .row > .actionBar > .btn-group');
|
||||
|
||||
$("#export").click(function () {
|
||||
$('<a></a>').attr('href', '/api/interfaces/overview/export').get(0).click();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.route-content {
|
||||
white-space: pre-line;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.route-expand {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.bootgrid-table {
|
||||
table-layout: auto;
|
||||
}
|
||||
|
||||
.bootgrid-table td {
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.bootgrid-table th {
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.details-dialog .modal-dialog{
|
||||
position: relative;
|
||||
display: table;
|
||||
overflow-y: auto;
|
||||
overflow-x: auto;
|
||||
width: auto;
|
||||
min-width: 600px;
|
||||
}
|
||||
|
||||
.details-dialog .modal-body {
|
||||
height: 60vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="tab-content content-box">
|
||||
<div id="export-wrapper" class="btn-group">
|
||||
<button id="export" class="btn btn-default" data-toggle="tooltip" title="" type="button" data-original-title="Download raw ifconfig output">
|
||||
<span class="fa fa-cloud-download"></span>
|
||||
</button>
|
||||
</div>
|
||||
<table id="grid-overview" class="table table-bordered table-condensed table-hover table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-column-id="status" data-width="5em" data-formatter="status" data-type="string">{{ lang._('Status') }}</th>
|
||||
<th data-column-id="description" data-formatter="interface" data-type="string">{{ lang._('Interface') }}</th>
|
||||
<th data-column-id="device" data-identifier="true" data-width="5em" data-type="string">{{ lang._('Device') }}</th>
|
||||
<th data-column-id="link_type" data-type="string">{{ lang._('Link Type') }}</th>
|
||||
<th data-column-id="ipv4" data-formatter="ipv4" data-type="string">{{ lang._('IPv4') }}</th>
|
||||
<th data-column-id="ipv6" data-formatter="ipv6" data-type="string">{{ lang._('IPv6') }}</th>
|
||||
<th data-column-id="gateways" data-formatter="gateways" data-type="string">{{ lang._('Gateway') }}</th>
|
||||
<th data-column-id="routes" data-formatter="routes" data-type="string">{{ lang._('Routes') }}</th>
|
||||
<th data-column-id="commands" data-width="7em" data-formatter="commands" data-sortable="false">{{ lang._('Commands') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
@ -91,10 +91,16 @@ message:request mac table
|
||||
|
||||
[list.ifconfig]
|
||||
command:/usr/local/sbin/pluginctl -D
|
||||
parameters:
|
||||
parameters: %s
|
||||
type:script_output
|
||||
message:request ifconfig
|
||||
|
||||
[list.stats]
|
||||
command:/usr/local/sbin/pluginctl -I
|
||||
parameters: %s
|
||||
type:script_output
|
||||
message:request interface stats
|
||||
|
||||
[show.traffic]
|
||||
command:/usr/local/opnsense/scripts/interfaces/traffic_stats.php
|
||||
parameters:
|
||||
|
||||
@ -1,67 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
Copyright (C) 2016 Deciso B.V.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* widget interfaces data
|
||||
*/
|
||||
function interfaces_api()
|
||||
{
|
||||
$result = array();
|
||||
$ifsinfo = get_interfaces_info();
|
||||
foreach (get_configured_interface_with_descr() as $ifdescr => $ifname) {
|
||||
$ifinfo = $ifsinfo[$ifdescr];
|
||||
$interfaceItem = array();
|
||||
$interfaceItem['inpkts'] = $ifinfo['inpkts'];
|
||||
$interfaceItem['outpkts'] = $ifinfo['outpkts'];
|
||||
$interfaceItem['inbytes'] = $ifinfo['inbytes'];
|
||||
$interfaceItem['outbytes'] = $ifinfo['outbytes'];
|
||||
$interfaceItem['inbytes_frmt'] = format_bytes($ifinfo['inbytes']);
|
||||
$interfaceItem['outbytes_frmt'] = format_bytes($ifinfo['outbytes']);
|
||||
$interfaceItem['inerrs'] = isset($ifinfo['inerrs']) ? $ifinfo['inerrs'] : "0";
|
||||
$interfaceItem['outerrs'] = isset($ifinfo['outerrs']) ? $ifinfo['outerrs'] : "0";
|
||||
$interfaceItem['collisions'] = isset($ifinfo['collisions']) ? $ifinfo['collisions'] : "0";
|
||||
$interfaceItem['descr'] = $ifdescr;
|
||||
$interfaceItem['name'] = $ifname;
|
||||
switch ($ifinfo['status']) {
|
||||
case 'down':
|
||||
case 'no carrier':
|
||||
case 'up':
|
||||
$interfaceItem['status'] = $ifinfo['status'];
|
||||
break;
|
||||
case 'associated':
|
||||
$interfaceItem['status'] = 'up';
|
||||
break;
|
||||
default:
|
||||
$interfaceItem['status'] = '';
|
||||
break;
|
||||
}
|
||||
$interfaceItem['ipaddr'] = empty($ifinfo['ipaddr']) ? "" : $ifinfo['ipaddr'];
|
||||
$interfaceItem['media'] = empty($ifinfo['media']) ? "" : $ifinfo['media'];
|
||||
$result[] = $interfaceItem;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
<?php
|
||||
|
||||
$interface_list_title = gettext('Interfaces');
|
||||
$interface_list_title_link = 'status_interfaces.php';
|
||||
$interface_list_title_link = 'interfaces_assign.php';
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
<?php
|
||||
|
||||
$interface_statistics_title = gettext('Interface Statistics');
|
||||
$interface_statistics_title_link = 'status_interfaces.php';
|
||||
$interface_statistics_title_link = 'ui/interfaces/overview';
|
||||
|
||||
@ -61,34 +61,67 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') {
|
||||
?>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* Hybrid widget only update interface status using ajax
|
||||
*/
|
||||
function interface_widget_update(sender, data)
|
||||
{
|
||||
data.map(function(interface_data) {
|
||||
var tr_id = 'interface_widget_item_' + interface_data['name'];
|
||||
if ($("#"+tr_id).length) {
|
||||
switch (interface_data['status']) {
|
||||
case 'up':
|
||||
$("#"+tr_id).find('.text-danger').removeClass('text-danger').addClass('text-success');
|
||||
$("#"+tr_id).find('.fa-arrow-down').removeClass('fa-arrow-down').addClass('fa-arrow-up');
|
||||
$("#"+tr_id).find('.fa-times').removeClass('fa-times').addClass('fa-arrow-up');
|
||||
break;
|
||||
case 'down':
|
||||
$("#"+tr_id).find('.text-success').removeClass('text-success').addClass('text-danger');
|
||||
$("#"+tr_id).find('.fa-arrow-up').removeClass('fa-arrow-up').addClass('fa-arrow-down');
|
||||
$("#"+tr_id).find('.fa-times').removeClass('fa-times').addClass('fa-arrow-down');
|
||||
break;
|
||||
default:
|
||||
$("#"+tr_id).find('.text-success').removeClass('text-success').addClass('text-danger');
|
||||
$("#"+tr_id).find('.fa-arrow-down').removeClass('fa-arrow-down').addClass('fa-times');
|
||||
$("#"+tr_id).find('.fa-arrow-up').removeClass('fa-arrow-up').addClass('fa-times');
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
ajaxGet('/api/interfaces/overview/interfacesInfo', {}, function(data, status) {
|
||||
data.rows.map(function(interface_data) {
|
||||
var tr_id = 'interface_widget_item_' + interface_data['identifier'];
|
||||
if ($("#"+tr_id).length) {
|
||||
let row = $("#"+tr_id);
|
||||
let $link_status = $("#"+tr_id).find('#link_status');
|
||||
let $if_status = $("#"+tr_id).find('#if_status');
|
||||
$link_status.empty();
|
||||
$if_status.empty();
|
||||
let $status_symbol = $('<span></span>');
|
||||
switch (interface_data['link_type']) {
|
||||
case 'ppp':
|
||||
$status_symbol.addClass('fa fa-mobile');
|
||||
break;
|
||||
case 'wireless':
|
||||
$status_symbol.addClass('fa fa-signal');
|
||||
break;
|
||||
default:
|
||||
$status_symbol.addClass('fa fa-exchange');
|
||||
break;
|
||||
}
|
||||
$link_status.append($status_symbol.addClass('text-success'));
|
||||
$if_status.append($('<span class="fa fa-arrow-up text-success" title="' + interface_data['status'] + '"></span>'));
|
||||
|
||||
|
||||
switch (interface_data['status']) {
|
||||
case 'up':
|
||||
//case 'associated':
|
||||
$("#"+tr_id).find('.text-danger').removeClass('text-danger').addClass('text-success');
|
||||
$("#"+tr_id).find('.fa-arrow-down').removeClass('fa-arrow-down').addClass('fa-arrow-up');
|
||||
$("#"+tr_id).find('.fa-times').removeClass('fa-times').addClass('fa-arrow-up');
|
||||
break;
|
||||
case 'down':
|
||||
$("#"+tr_id).find('.text-success').removeClass('text-success').addClass('text-danger');
|
||||
$("#"+tr_id).find('.fa-arrow-up').removeClass('fa-arrow-up').addClass('fa-arrow-down');
|
||||
$("#"+tr_id).find('.fa-times').removeClass('fa-times').addClass('fa-arrow-down');
|
||||
break;
|
||||
default:
|
||||
$("#"+tr_id).find('.text-success').removeClass('text-success').addClass('text-danger');
|
||||
$("#"+tr_id).find('.fa-arrow-down').removeClass('fa-arrow-down').addClass('fa-times');
|
||||
$("#"+tr_id).find('.fa-arrow-up').removeClass('fa-arrow-up').addClass('fa-times');
|
||||
break;
|
||||
}
|
||||
|
||||
let $name = $("#"+tr_id).find('#if_name');
|
||||
$name.empty();
|
||||
let $name_span = $('<span style="cursor:pointer" onclick="location.href=\'/interfaces.php?if=' + interface_data['identifier'] +
|
||||
'\'"><strong><u>' + interface_data['description'] +'</strong></u></span>');
|
||||
$name.append($name_span)
|
||||
|
||||
|
||||
$media = $("#"+tr_id).find('#if_media');
|
||||
$media.empty();
|
||||
if (!'media' in interface_data) {
|
||||
$media.html(interface_data['cell_mode']);
|
||||
} else {
|
||||
$media.html(interface_data['media']);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<div id="interface_list-settings" class="widgetconfigdiv" style="display:none;">
|
||||
@ -112,61 +145,27 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') {
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<table class="table table-striped table-condensed" data-plugin="interfaces" data-callback="interface_widget_update">
|
||||
<table class="table table-striped table-condensed">
|
||||
<?php
|
||||
$ifsinfo = get_interfaces_info();
|
||||
foreach ($interfaces as $ifdescr => $ifname):
|
||||
$listed = in_array($ifdescr, $pconfig['interfaceslistfilter']);
|
||||
foreach ($interfaces as $ident => $ifname):
|
||||
$listed = in_array($ident, $pconfig['interfaceslistfilter']);
|
||||
$listed = !empty($pconfig['interfaceslistinvert']) ? $listed : !$listed;
|
||||
if (!$listed) {
|
||||
continue;
|
||||
}
|
||||
$ifinfo = $ifsinfo[$ifdescr]; ?>
|
||||
<tr id="interface_widget_item_<?= html_safe($ifname) ?>">
|
||||
<td style="width:5%; word-break: break-word;">
|
||||
<?php if (isset($ifinfo['ppplink'])): ?>
|
||||
<span title="3g" class="fa fa-mobile text-success"></span>
|
||||
<?php elseif (isset($config['interfaces'][$ifdescr]['wireless'])): ?>
|
||||
<?php if ($ifinfo['status'] == 'associated' || $ifinfo['status'] == 'up'): ?>
|
||||
<span title="wlan" class="fa fa-signal text-success"></span>
|
||||
<?php else: ?>
|
||||
<span title="wlan_d" class="fa fa-signal text-danger"></span>
|
||||
<?php endif ?>
|
||||
<?php else: ?>
|
||||
<?php if ($ifinfo['status'] == 'up'): ?>
|
||||
<span title="cablenic" class="fa fa-exchange text-success"></span>
|
||||
<?php else: ?>
|
||||
<span title="cablenic" class="fa fa-exchange text-danger"></span>
|
||||
<?php endif ?>
|
||||
<?php endif ?>
|
||||
</td>
|
||||
<td style="width:15%; word-break: break-word;">
|
||||
<strong>
|
||||
<u>
|
||||
<span onclick="location.href='/interfaces.php?if=<?= html_safe($ifdescr) ?>'" style="cursor:pointer">
|
||||
<?= html_safe($ifname) ?>
|
||||
</span>
|
||||
</u>
|
||||
</strong>
|
||||
</td>
|
||||
<td style="width:5%; word-break: break-word;">
|
||||
<?php if ($ifinfo['status'] == 'up' || $ifinfo['status'] == 'associated'): ?>
|
||||
<span class="fa fa-arrow-up text-success"></span>
|
||||
<?php elseif ($ifinfo['status'] == "down"): ?>
|
||||
<span class="fa fa-arrow-down text-danger"></span>
|
||||
<?php elseif ($ifinfo['status'] == "no carrier"): ?>
|
||||
<span class="fa fa-times text-danger"></span>
|
||||
<?php else: ?>
|
||||
<?= html_safe($ifinfo['status']) ?>
|
||||
<?php endif ?>
|
||||
</td>
|
||||
<td style="width:32%; word-break: break-word;">
|
||||
<?= html_safe(empty($ifinfo['media']) ? $ifinfo['cell_mode'] ?? '' : $ifinfo['media']) ?>
|
||||
</td>
|
||||
|
||||
list($primary4,, $bits4) = interfaces_primary_address($ident);
|
||||
list($primary6,, $bits6) = interfaces_primary_address6($ident);
|
||||
?>
|
||||
<tr id="interface_widget_item_<?= html_safe($ident) ?>">
|
||||
<td style="width:5%; word-break: break-word;" id="link_status"></td>
|
||||
<td style="width:15%; word-break: break-word;" id="if_name"></td>
|
||||
<td style="width:5%; word-break: break-word;" id="if_status"></td>
|
||||
<td style="width:32%; word-break: break-word;" id="if_media"></td>
|
||||
<td style="width:43%; word-break: break-word;">
|
||||
<?= html_safe($ifinfo['ipaddr']) ?>
|
||||
<?= !empty($ifinfo['ipaddr']) ? '<br/>' : '' ?>
|
||||
<?= html_safe(interfaces_has_prefix_only($ifdescr) ? $ifinfo['linklocal'] : $ifinfo['ipaddrv6']) ?>
|
||||
<?= html_safe($primary4) ?>
|
||||
<?= !empty($primary4) ? '<br/>' : '' ?>
|
||||
<?= html_safe($primary6) ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach ?>
|
||||
|
||||
@ -71,25 +71,41 @@ $ifvalues = array(
|
||||
?>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* update interface statistics
|
||||
*/
|
||||
function interface_statistics_widget_update(sender, data)
|
||||
{
|
||||
data.map(function(interface_data) {
|
||||
// fill in stats, use column index to determine td location
|
||||
var item_index = $("#interface_statistics_widget_intf_" + interface_data['descr']).index();
|
||||
if (item_index != -1) {
|
||||
$("#interface_statistics_widget_intf_" + interface_data['descr'] +" > td:eq(1)").html(parseInt(interface_data['inpkts']).toLocaleString());
|
||||
$("#interface_statistics_widget_intf_" + interface_data['descr'] +" > td:eq(2)").html(parseInt(interface_data['outpkts']).toLocaleString());
|
||||
$("#interface_statistics_widget_intf_" + interface_data['descr'] +" > td:eq(3)").html(interface_data['inbytes_frmt']);
|
||||
$("#interface_statistics_widget_intf_" + interface_data['descr'] +" > td:eq(4)").html(interface_data['outbytes_frmt']);
|
||||
$("#interface_statistics_widget_intf_" + interface_data['descr'] +" > td:eq(5)").html(interface_data['inerrs']);
|
||||
$("#interface_statistics_widget_intf_" + interface_data['descr'] +" > td:eq(6)").html(interface_data['outerrs']);
|
||||
$("#interface_statistics_widget_intf_" + interface_data['descr'] +" > td:eq(7)").html(interface_data['collisions']);
|
||||
}
|
||||
});
|
||||
}
|
||||
function format_field(value) {
|
||||
if (!isNaN(value) && value > 0) {
|
||||
let fileSizeTypes = ["", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
|
||||
let ndx = Math.floor(Math.log(value) / Math.log(1000) );
|
||||
if (ndx > 0) {
|
||||
return (value / Math.pow(1000, ndx)).toFixed(2) + ' ' + fileSizeTypes[ndx];
|
||||
} else {
|
||||
return value.toFixed(2);
|
||||
}
|
||||
} else {
|
||||
return "0";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* update interface statistics
|
||||
*/
|
||||
ajaxGet('/api/interfaces/overview/interfacesInfo/1', {}, function(data, status) {
|
||||
data.rows.map(function(interface_data) {
|
||||
let stats = interface_data['statistics'];
|
||||
let inbytes = format_field(parseInt(stats['bytes received']));
|
||||
let outbytes = format_field(parseInt(stats['bytes transmitted']));
|
||||
// fill in stats, use column index to determine td location
|
||||
var item_index = $("#interface_statistics_widget_intf_" + interface_data['identifier']).index();
|
||||
if (item_index != -1) {
|
||||
$("#interface_statistics_widget_intf_" + interface_data['identifier'] +" > td:eq(1)").html(parseInt(stats['packets received']).toLocaleString());
|
||||
$("#interface_statistics_widget_intf_" + interface_data['identifier'] +" > td:eq(2)").html(parseInt(stats['packets transmitted']).toLocaleString());
|
||||
$("#interface_statistics_widget_intf_" + interface_data['identifier'] +" > td:eq(3)").html(inbytes);
|
||||
$("#interface_statistics_widget_intf_" + interface_data['identifier'] +" > td:eq(4)").html(outbytes);
|
||||
$("#interface_statistics_widget_intf_" + interface_data['identifier'] +" > td:eq(5)").html(stats['input errors']);
|
||||
$("#interface_statistics_widget_intf_" + interface_data['identifier'] +" > td:eq(6)").html(stats['output errors']);
|
||||
$("#interface_statistics_widget_intf_" + interface_data['identifier'] +" > td:eq(7)").html(stats['collisions']);
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<div id="interface_statistics-settings" class="widgetconfigdiv" style="display:none;">
|
||||
@ -113,7 +129,7 @@ $ifvalues = array(
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<table class="table table-striped table-condensed" data-plugin="interfaces" data-callback="interface_statistics_widget_update">
|
||||
<table class="table table-striped table-condensed">
|
||||
<tr>
|
||||
<th> </th>
|
||||
<?php foreach ($ifvalues as $ifkey => $iflabel): ?>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user