From ead267bcbfc73d15ee58819b0fba8b392333e9f3 Mon Sep 17 00:00:00 2001 From: M.Gergő Date: Sat, 15 Sep 2018 22:28:44 +0200 Subject: Munin monitoring plugin for Ubiquity unifi AP network, over SNMPv2. --- .description-html | 19 +++ .gitignore | 2 +- README.md | 73 +++++++++- ubnt_unifi.php | 427 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 514 insertions(+), 7 deletions(-) create mode 100644 .description-html create mode 100644 ubnt_unifi.php diff --git a/.description-html b/.description-html new file mode 100644 index 0000000..d59cff1 --- /dev/null +++ b/.description-html @@ -0,0 +1,19 @@ + + + + + unifimunin.git + + + +

unifimunin.git

+ +

You should clone the repository first, because the raw reading is not allowed here!
+( #>> git clone http://git.bmrg.hu/unifimunin.git )

+ +
+

In browserable format:
https://github.com/EpeR1/unifimunin

+ +
+ + diff --git a/.gitignore b/.gitignore index 436dcca..178261d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ *~ -.description* +.description diff --git a/README.md b/README.md index f7a5b23..6c38edf 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,76 @@ This is a [Munin](http://munin-monitoring.org/) plugin to monitor your [Ubiquity Unifi](https://www.ubnt.com/products/#unifi) wireless network status. It uses SNMP v2 to get network data. -**Usage** : +## Usage +unifi_munin - Munin plugin to monitor UBNT unifi wireless APs -. +![munin](https://raw.githubusercontent.com/EpeR1/unifi-munin/img/munin-ssid.png) +Number of clients + +![munin](https://raw.githubusercontent.com/EpeR1/unifi-munin/img/munin-netw.png) +Network usage + + + + +## Installation on Debian + +1) Copy the **ubnt_unifi.php** into the **/usr/share/munin/plugins/** folder. +2) Set the rights: + `chmod 755 /usr/share/munin/plugins/ubnt_unifi.php` +3) Create a symlink to this file: + `ln -s /usr/share/munin/plugins/ubnt_unifi.php /etc/munin/plugins/ubnt_unifi` +4) Edit the **/etc/munin/plugin-conf.d/munin-node** file, and add the following configuration lines. +5) Test the plugin with the `munin-run ubnt_unifi` command. + +## CONFIGURATION + +The following environment variables are used: + +` [ubnt_unifi] ` +` timeout` - Munin-update timeout for this plugin. +` env.controller` - The unifi controller hostname/ip. +` env.devices` - A "space" separated list of the hostnames or IP addresses of wireless APs. +` env.timeout` - The maximum timeout in milliseconds of SNMP requests. (Be careful of munin max update time!). +` env.retry` - Number of retry after failed/time out SNMP requets. +` env.devnetw` - The network of the APs. (It is expreimental yet.) + + +Configuration example for Munin: + + +` [ubnt_unifi]` +` timeout 240` +` env.controller unifi.company.hu` +` env.devices ap01.wl.company.lan ap02.wl.company.lan ap03.wl.company.lan 10.10.1.6 10.10.1.7 10.10.1.8 ` +` env.devnetw 10.10.1.10/24` +` env.timeout 70` +` env.retry 1` + + + + +### AUTHOR + +Copyright (C) 2018 Gergő M. + + + +### LICENSE + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; version 2 dated June, +1991. ---------------------------------------------------------------------- +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. -**Munin Plugin** : +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -.. -![munin](https://raw.githubusercontent.com/EpeR1/.png) . diff --git a/ubnt_unifi.php b/ubnt_unifi.php new file mode 100644 index 0000000..aa4c315 --- /dev/null +++ b/ubnt_unifi.php @@ -0,0 +1,427 @@ +#!/usr/bin/php + $val){ + $cf .= "unifi_".$val['name'].".label ".$val['label']."\n"; + $cf .= "unifi_".$val['name'].".draw ".$val['draw']."\n"; + $cf .= "unifi_".$val['name'].".info ".$val['info']."\n"; + if(isset($val['type'])){ $cf .= "unifi_".$val['name'].".type ".$val['type']."\n"; } + if(isset($val['min'])) { $cf .= "unifi_".$val['name'].".min ".$val['min']."\n"; } + if(isset($val['cdef'])){ $cf .= "unifi_".$val['name'].".cdef ".$val['cdef']."\n"; } + if(isset($val['graph'])){ $cf .= "unifi_".$val['name'].".graph ".$val['graph']."\n"; } + if(isset($val['max'])){ $cf .= "unifi_".$val['name'].".max ".$val['max']."\n"; } + if(isset($val['negative'])){ $cf .= "unifi_".$val['name'].".negative ".$val['negative']."\n"; } + } + $cf .= "\n"; + echo iconv("UTF-8", "ISO-8859-2", $cf), PHP_EOL; +} + + +function print_data($inp) { + + $pf = "multigraph unifi_".$inp['g_multi']."\n"; + foreach($inp['data'] as $key => $val){ + $pf .= "unifi_".$val['name'].".value ".$val['value']."\n" ; + } + $pf .= "\n"; + + echo iconv("UTF-8", "ISO-8859-2", $pf), PHP_EOL; + +} + +function count_wl_networks($inp){ //Count wireless networks from interfade data + $num = -10; + foreach($inp as $key => $val){ // jump to the end of wl interface list + if(strpos($key, "iso.3.6.1.4.1.41112.1.6.1.2.1.1.") !== false){ + if(is_numeric(explode(": ", $val)[1]) and $num < explode(": ", $val)[1]){ + $num = explode(": ", $val)[1]; + } + } + } + $num = $num+1; //Because the snmp counts from 0 + + if($num > 0){ + return $num; + } else { + return -1; + } +} + + +function collect_radio_summary($inp,$host){ + global $controller, $replace_chars; + $ret = array(); + if(isset($host) and $host !== null and $host != "" ){ + $ret['g_multi'] = "radio_".str_replace( array(".", ":"), "_" ,$controller).".".str_replace( array(".", ":"), "_" ,$host); + $ret['g_controller'] = $controller; + $location = str_replace("\"", "", explode(": ", $inp[$host]["iso.3.6.1.2.1.1.6.0"])[1]); + if( $location != "Unknown" and $location != "" ){ $ret['g_title'] = "Unifi Clients on: ".$location ; } // if the Location is not filled in Controller settings, use the hostname or ip address + else { $ret['g_title'] = "Unifi Clients on: ".$host; }; + $ret['g_vlabel'] = "Users"; + $ret['g_category'] = "wl_clients_ap"; + $ret['g_info'] = "ubnt_wireless"; + } else { + $ret['g_multi'] = "radio_".str_replace( array(".", ":"), "_" ,$controller); + $ret['g_controller'] = $controller; + $ret['g_title'] = "Unifi Clients on: $controller (total)"; + $ret['g_vlabel'] = "Users"; + $ret['g_category'] = "Wl_clients_all"; + $ret['g_info'] = "ubnt_wireless"; + } + + $ret['head'][0]['name'] = "sum_clients"; + $ret['head'][0]['label'] = "Total clients"; + $ret['head'][0]['draw'] = "LINE1.2"; + $ret['head'][0]['info'] = "Total Clients"; + $ret['head'][0]['type'] = "GAUGE"; + $ret['head'][0]['min'] = "0"; + + $ret['head'][1]['name'] = "2g_clients"; + $ret['head'][1]['label'] = "2.4Ghz"; + $ret['head'][1]['draw'] = "LINE1.2"; + $ret['head'][1]['info'] = "2.4Ghz Clients"; + $ret['head'][1]['type'] = "GAUGE"; + $ret['head'][1]['min'] = "0"; + + $ret['head'][2]['name'] = "5g_clients"; + $ret['head'][2]['label'] = "5Ghz"; + $ret['head'][2]['draw'] = "LINE1.2"; + $ret['head'][2]['info'] = "2.4Ghz Clients"; + $ret['head'][2]['type'] = "GAUGE"; + $ret['head'][2]['min'] = "0"; + + + if(isset($host) and $host !== null and $host != "" ){ // trim raw data array to current device (in $host) or use the whole array when calculating controller's data + $temp = $inp; + unset($inp); + $inp = array($host => $temp[$host]); + unset($temp); + } + + foreach($inp as $key => $val){ + + for($i=1; $i<=count_wl_networks($inp[$key]); $i++){ //Collect clients by band. + if( explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.4.".$i])[1] < 15 ){ //2.4Ghz client + $ret['data'][1]['name'] = "2g_clients"; + @$ret['data'][1]['value'] += explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.8.".$i])[1]; + } else { // 5Ghz clients + $ret['data'][2]['name'] = "5g_clients"; + @$ret['data'][2]['value'] += explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.8.".$i])[1]; + } + } + $ret['data'][0]['name'] = "sum_clients"; + $ret['data'][0]['value'] = $ret['data'][1]['value'] + $ret['data'][2]['value']; + + + + for($i=1; $i<=count_wl_networks($inp[$key]); $i++){ //Collect clients by SSID. + + foreach($ret['data'] as $key2 => $val2){ //find if ssid is already used + if($ret['data'][$key2]['name'] == str_replace($replace_chars, "_", explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.6.".$i])[1]) ){ + break; + } + } + //found, update record + if($ret['data'][$key2]['name'] == str_replace($replace_chars, "_", explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.6.".$i])[1]) ){ + $ret['data'][$key2]['value'] += explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.8.".$i])[1]; + + } else { //not found, new record + $ret['data'][] = array( "name" => str_replace($replace_chars, "_", explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.6.".$i])[1]), + "value" => explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.8.".$i])[1] + ); + $ret['head'][] = array( "name" => str_replace($replace_chars, "_", explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.6.".$i])[1]), + "label" => str_replace("\"", "",explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.6.".$i])[1] ), + "draw" => "LINE1.2", + "info" => explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.6.".$i])[1], + "type" => "GAUGE", + "min" => "0", + ); + + } + } + } + + +return $ret; +} + + + + +function collect_netw_summary($inp,$host){ //network information + global $controller, $replace_chars; + $ret = array(); + + if(isset($host) and $host !== null and $host != "" ){ // When showing the Ap's summary. + $temp = $inp; + unset($inp); + $inp = array($host => $temp[$host]); + unset($temp); + $multiplier = 8; + $divider = 1; + } else { //because the normal INTEGER(32) would be overflowed + $multiplier = 8192; // When showing the controller's summary + $divider = 1024; + } + + + if(isset($host) and $host !== null and $host != "" ){ + $ret['g_multi'] = "netw_".str_replace( array(".", ":"), "_" ,$controller).".".str_replace( array(".", ":"), "_" ,$host); + $ret['g_controller'] = $controller; + $location = str_replace("\"", "", explode(": ", $inp[$host]["iso.3.6.1.2.1.1.6.0"])[1]); + if($location != "Unknown" and $location != ""){ $ret['g_title'] = "Network Usage on: ".$location; } + else{$ret['g_title'] = "Network Usage on: ".$host;} + $ret['g_vlabel'] = "bits in(-) / out(+) per second"; + $ret['g_category'] = "Wl_netw_ap"; + $ret['g_info'] = "ubnt_network"; + $ret['g_order'] = "rx_all tx_all rx_2g tx_2g rx_5g tx_5g"; + + } else { + $ret['g_multi'] = "netw_".str_replace( array(".", ":"), "_" ,$controller); + $ret['g_controller'] = $controller; + $ret['g_title'] = "Netwok Usage on: $controller (total)"; + $ret['g_vlabel'] = "bits in(-) / out(+) per second"; + $ret['g_category'] = "Wl_netw_all"; + $ret['g_info'] = "ubnt_network"; + $ret['g_order'] = "rx_all tx_all rx_2g tx_2g rx_5g tx_5g"; + } + + $ret['head'][0]['name'] = "rx_all"; + $ret['head'][0]['label'] = "RxTotal (bps)"; + $ret['head'][0]['draw'] = "LINE1.2"; + $ret['head'][0]['info'] = "Total Received"; + $ret['head'][0]['type'] = "DERIVE"; + $ret['head'][0]['min'] = "0"; + $ret['head'][0]['graph'] = "no"; + $ret['head'][0]['cdef'] = "unifi_rx_all,$multiplier,*"; + $ret['head'][0]['max'] = "1000000000"; + + $ret['head'][1]['name'] = "tx_all"; + $ret['head'][1]['label'] = "Total (bps)"; + $ret['head'][1]['draw'] = "LINE1.2"; + $ret['head'][1]['info'] = "Total Sent"; + $ret['head'][1]['type'] = "DERIVE"; + $ret['head'][1]['min'] = "0"; + $ret['head'][1]['cdef'] = "unifi_tx_all,$multiplier,*"; + $ret['head'][1]['max'] = "1000000000"; + $ret['head'][1]['negative'] = "unifi_rx_all"; + + $ret['head'][2]['name'] = "rx_2g"; + $ret['head'][2]['label'] = "2G (bps)"; + $ret['head'][2]['draw'] = "LINE1.2"; + $ret['head'][2]['info'] = "Total Received"; + $ret['head'][2]['type'] = "DERIVE"; + $ret['head'][2]['min'] = "0"; + $ret['head'][2]['graph'] = "no"; + $ret['head'][2]['cdef'] = "unifi_rx_2g,$multiplier,*"; + $ret['head'][2]['max'] = "1000000000"; + + $ret['head'][3]['name'] = "tx_2g"; + $ret['head'][3]['label'] = "2G (bps)"; + $ret['head'][3]['draw'] = "LINE1.2"; + $ret['head'][3]['info'] = "Total Sent"; + $ret['head'][3]['type'] = "DERIVE"; + $ret['head'][3]['min'] = "0"; + $ret['head'][3]['cdef'] = "unifi_tx_2g,$multiplier,*"; + $ret['head'][3]['max'] = "1000000000"; + $ret['head'][3]['negative'] = "unifi_rx_2g"; + + $ret['head'][4]['name'] = "rx_5g"; + $ret['head'][4]['label'] = "5G (bps)"; + $ret['head'][4]['draw'] = "LINE1.2"; + $ret['head'][4]['info'] = "Total Received"; + $ret['head'][4]['type'] = "DERIVE"; + $ret['head'][4]['min'] = "0"; + $ret['head'][4]['graph'] = "no"; + $ret['head'][4]['cdef'] = "unifi_rx_5g,$multiplier,*"; + $ret['head'][4]['max'] = "1000000000"; + + $ret['head'][5]['name'] = "tx_5g"; + $ret['head'][5]['label'] = "5G (bps)"; + $ret['head'][5]['draw'] = "LINE1.2"; + $ret['head'][5]['info'] = "Total Sent"; + $ret['head'][5]['type'] = "DERIVE"; + $ret['head'][5]['min'] = "0"; + $ret['head'][5]['cdef'] = "unifi_tx_5g,$multiplier,*"; + $ret['head'][5]['max'] = "1000000000"; + $ret['head'][5]['negative'] = "unifi_rx_5g"; + + + foreach($inp as $key => $val){ + + for($i=1; $i<=count_wl_networks($inp[$key]); $i++){ //Collect netw_bytes by band and direction. + if( explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.4.".$i])[1] < 15 ){ //2.4Ghz client + $ret['data'][2]['name'] = "rx_2g"; + @$ret['data'][2]['value'] += round((explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.10.".$i])[1]) / $divider); + $ret['data'][3]['name'] = "tx_2g"; + @$ret['data'][3]['value'] += round((explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.16.".$i])[1]) / $divider); + + } else { // 5Ghz clients + $ret['data'][4]['name'] = "rx_5g"; + @$ret['data'][4]['value'] += round((explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.10.".$i])[1]) / $divider); + $ret['data'][5]['name'] = "tx_5g"; + @$ret['data'][5]['value'] += round((explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.16.".$i])[1]) / $divider); + } + } + $ret['data'][0]['name'] = "rx_all"; + $ret['data'][0]['value'] = $ret['data'][2]['value'] + $ret['data'][4]['value']; + $ret['data'][1]['name'] = "tx_all"; + $ret['data'][1]['value'] = $ret['data'][3]['value'] + $ret['data'][5]['value']; + + + + for($i=1; $i<=count_wl_networks($inp[$key]); $i++){ //Collect netw_bytes by SSID. + + foreach($ret['data'] as $key2 => $val2){ //find if ssid is already used + if($ret['data'][$key2]['name'] == "rx_".str_replace($replace_chars, "_", explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.6.".$i])[1]) ){ + break; + } + } + //ssid found, update record + if($ret['data'][$key2]['name'] == "rx_".str_replace($replace_chars, "_", explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.6.".$i])[1]) ){ + $ret['data'][$key2]['value'] += round((explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.10.".$i])[1]) / $divider); + + } else { //ssid not found, new record + $ret['data'][] = array( "name" => "rx_".str_replace($replace_chars, "_", explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.6.".$i])[1]), + "value" => round((explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.10.".$i])[1]) / $divider) , + ); + $ret['head'][] = array( "name" => "rx_".str_replace($replace_chars, "_", explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.6.".$i])[1]), + "label" => "RX_".str_replace("\"", "",explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.6.".$i])[1] )."(bps)", + "draw" => "LINE1.2", + "info" => "Rx_".explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.6.".$i])[1], + "type" => "DERIVE", + "min" => "0", + "graph" => "no", + "cdef" => "unifi_rx_".str_replace($replace_chars, "_", explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.6.".$i])[1]).",$multiplier,*", + "max" => "1000000000", + ); + + } + + foreach($ret['data'] as $key2 => $val2){ //find if ssid is already used + if($ret['data'][$key2]['name'] == "tx_".str_replace($replace_chars, "_", explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.6.".$i])[1]) ){ + break; + } + } + //ssid found, update record + if($ret['data'][$key2]['name'] == "tx_".str_replace($replace_chars, "_", explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.6.".$i])[1]) ){ + $ret['data'][$key2]['value'] += round((explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.16.".$i])[1]) / $divider); + + } else { //ssid not found, new record + $ret['data'][] = array( "name" => "tx_".str_replace($replace_chars, "_", explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.6.".$i])[1]), + "value" => round((explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.16.".$i])[1]) / $divider) , + ); + $ret['head'][] = array( "name" => "tx_".str_replace($replace_chars, "_", explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.6.".$i])[1]), + "label" => "".str_replace("\"", "",explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.6.".$i])[1] )." (bps)", + "draw" => "LINE1.2", + "info" => "Tx_".explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.6.".$i])[1], + "type" => "DERIVE", + "min" => "0", + "cdef" => "unifi_tx_".str_replace($replace_chars, "_", explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.6.".$i])[1]).",$multiplier,*", + "max" => "1000000000", + "negative" => "unifi_rx_".str_replace($replace_chars, "_", explode(": ", $inp[$key]["iso.3.6.1.4.1.41112.1.6.1.2.1.6.".$i])[1]), + ); + } + + + } + } + + +return $ret; +} + + +$hosts = explode(" ", $hosts); +$netw = @explode('/', $devnetw)[0]; +$mask = @explode('/', $devnetw)[1]; +$hosts2 = array(); + +if($mask != 0 ){ + for($i=1; $i<(1 << (32 - $mask)); $i++ ){ // fetch ip addresses from given network and mask + $hosts2[] = long2ip((ip2long($netw) & ~((1 << (32 - $mask)) -1)) +$i ) ; + } +} + + +foreach($hosts as $key => $val){ // delete addresses which are given by hostname + if(in_array(gethostbyname($val), $hosts2)){ + unset($hosts2[ array_keys($hosts2, gethostbyname($val))[0] ]); + } + +} +$hosts = array_merge($hosts, $hosts2); + +$raw=array(); +foreach($hosts as $key => $val){ // get raw snmp data from unifi devices + if($hosts[$key] == ""){ + unset($hosts[$key]); + } + if($val != "") { + $raw[$val] = @snmp2_real_walk($val, "public", ".1.3.6.1.4.1.41112.1.6.1.2.1", $timeout*1000, $retry ); // wl network info + $raw[$val]["iso.3.6.1.2.1.1.6.0"] = @snmp2_get($val, "public", ".1.3.6.1.2.1.1.6.0", $timeout*1000, $retry ) ; // location info + $raw[$val]["iso.3.6.1.2.1.1.1.0"] = @snmp2_get($val, "public", ".1.3.6.1.2.1.1.1.0", $timeout*1000, $retry ) ; // descr. info + } + if( !isset($raw[$val]["iso.3.6.1.4.1.41112.1.6.1.2.1.1.1"]) ){ + unset($raw[$val]); + unset($hosts[$key]); + } +} + + +//print_r($raw); +//print_r($hosts); +//$valami = collect_netw_summary($raw,"ap12.wireless.lan"); +//print_r($valami); + + +if (isset($argv[1]) and $argv[1] == "config"){ // munin config + print_header(collect_radio_summary($raw,null)); + foreach($hosts as $key => $val){ + print_header(collect_radio_summary($raw,$val)); + } + print_header(collect_netw_summary($raw,null)); + foreach($hosts as $key => $val){ + print_header(collect_netw_summary($raw,$val)); + } + + +} else { // munin data + print_data(collect_radio_summary($raw,null)); + foreach($hosts as $key => $val){ + print_data(collect_radio_summary($raw,$val)); + } + print_data(collect_netw_summary($raw,null)); + foreach($hosts as $key => $val){ + print_data(collect_netw_summary($raw,$val)); + } + +} + + +echo "\n"; + +?> -- cgit v1.2.3