diff --git a/doc/Extensions/RRDTune.md b/doc/Extensions/RRDTune.md new file mode 100644 index 0000000000..7ee7095d29 --- /dev/null +++ b/doc/Extensions/RRDTune.md @@ -0,0 +1,21 @@ +# RRDTune? + +When we create rrd files for ports, we currently do so with a max value of 12500000000 (100G). Because of this if a device sends us bad data back then it can appear as though +a 100M port is doing 40G+ which is impossible. To counter this you can enable the rrdtool tune option which will fix the max value to the interfaces physical speed (minimum of 10M). + +To enable this you can do so in three ways! + + - Globally under Global Settings -> External Settings -> RRDTool Setup + - For the actual device, Edit Device -> Misc + - For each port, Edit Device -> Port Settings + +Now when a port interface speed changes (this can happen because of a physical change or just because the device has mis-reported) the max value is set. If you don't want to wait until +a port speed changes then you can run the included script: + +script/tune_port.php -h -p + +Wildcards are supported using *, i.e: + +script/tune_port.php -h local* -p eth* + +This script will then perform the rrdtool tune on each port found using the provided ifSpeed for that port. diff --git a/doc/Support/FAQ.md b/doc/Support/FAQ.md index d7317db4fe..d6da5de502 100644 --- a/doc/Support/FAQ.md +++ b/doc/Support/FAQ.md @@ -12,6 +12,7 @@ - [How do I debug the discovery process?](#faq11) - [How do I debug the poller process?](#faq12) - [Why do I get a lot apache or rrdtool zombies in my process list?](#faq14) + - [Why do I see traffic spikes in my graphs?](#faq15) ### Developing - [How do I add support for a new OS?](#faq8) @@ -94,6 +95,13 @@ Please see the [Poller Support](http://docs.librenms.org/Support/Poller Support) If this is related to your web service for LibreNMS then this has been tracked down to an issue within php which the developers aren't fixing. We have implemented a work around which means you shouldn't be seeing this. If you are, please report this in [issue 443](https://github.com/librenms/librenms/issues/443). +#### Why do I see traffic spikes in my graphs? + +This occurs either when a counter resets or the device sends back bogus data making it look like a counter reset. We have enabled support for setting a maximum value for rrd files for ports. +Before this all rrd files were set to 100G max values, now you can enable support to limit this to the actual port speed. + +rrdtool tune will change the max value when the interface speed is detected as being changed (min value will be set for anything 10M or over) or when you run the included script (scripts/tune_port.php). + #### How do I add support for a new OS? The easiest way to show you how to do that is to link to an existing pull request that has been merged in on [GitHub](https://github.com/librenms/librenms/pull/352/files) diff --git a/html/includes/table/edit-ports.inc.php b/html/includes/table/edit-ports.inc.php index d4ccba8a59..625ac5e75d 100644 --- a/html/includes/table/edit-ports.inc.php +++ b/html/includes/table/edit-ports.inc.php @@ -54,17 +54,22 @@ foreach (dbFetchRows($sql, $param) as $port) { $isportbad = ($port['ifOperStatus'] == 'down' && $port['ifAdminStatus'] != 'down') ? 1 : 0; $dowecare = ($port['ignore'] == 0 && $port['disabled'] == 0) ? $isportbad : !$isportbad; $outofsync = $dowecare ? " class='red'" : ''; + $checked = ''; + if (get_dev_attrib($device_id, 'ifName_tune:'.$port['ifName']) == "true") { + $checked = 'checked'; + } $response[] = array( - 'ifIndex' => $port['ifIndex'], - 'ifName' => $port['label'], - 'ifAdminStatus' => $port['ifAdminStatus'], - 'ifOperStatus' => ''.$port['ifOperStatus'].'', - 'disabled' => ' - ', - 'ignore' => ' - ', - 'ifAlias' => '
' + 'ifIndex' => $port['ifIndex'], + 'ifName' => $port['label'], + 'ifAdminStatus' => $port['ifAdminStatus'], + 'ifOperStatus' => ''.$port['ifOperStatus'].'', + 'disabled' => ' + ', + 'ignore' => ' + ', + 'port_tune' => '', + 'ifAlias' => '
', ); }//end foreach diff --git a/html/js/librenms.js b/html/js/librenms.js index 034f1a9452..b910907618 100644 --- a/html/js/librenms.js +++ b/html/js/librenms.js @@ -1,30 +1,34 @@ +function override_config(event, state, tmp_this) { + event.preventDefault(); + var $this = tmp_this; + var attrib = $this.data('attrib'); + var device_id = $this.data('device_id'); + $.ajax({ + type: 'POST', + url: 'ajax_form.php', + data: { type: 'override-config', device_id: device_id, attrib: attrib, state: state }, + dataType: 'json', + success: function(data) { + if (data.status == 'ok') { + toastr.success(data.message); + } + else { + toastr.error(data.message); + } + }, + error: function() { + toastr.error('Could not set this override'); + } + }); +} + var oldH; var oldW; $(document).ready(function() { // Device override ajax calls $("[name='override_config']").bootstrapSwitch('offColor','danger'); $('input[name="override_config"]').on('switchChange.bootstrapSwitch', function(event, state) { - event.preventDefault(); - var $this = $(this); - var attrib = $this.data('attrib'); - var device_id = $this.data('device_id'); - $.ajax({ - type: 'POST', - url: 'ajax_form.php', - data: { type: 'override-config', device_id: device_id, attrib: attrib, state: state }, - dataType: 'json', - success: function(data) { - if (data.status == 'ok') { - toastr.success(data.message); - } - else { - toastr.error(data.message); - } - }, - error: function() { - toastr.error('Could not set this override'); - } - }); + override_config(event,state,$(this)); }); // Device override for text inputs diff --git a/html/pages/device/edit/misc.inc.php b/html/pages/device/edit/misc.inc.php index d1731ecdfd..b46932a15f 100644 --- a/html/pages/device/edit/misc.inc.php +++ b/html/pages/device/edit/misc.inc.php @@ -3,23 +3,29 @@ echo '
- -
+ +
'.dynamic_override_config('checkbox','override_icmp_disable', $device).'
- -
+ +
'.dynamic_override_config('checkbox','override_Oxidized_disable', $device).'
- -
+ +
'.dynamic_override_config('text','override_Unixagent_port', $device).'
+
+ +
+ '.dynamic_override_config('checkbox','override_rrdtool_tune', $device).' +
+
'; diff --git a/html/pages/device/edit/ports.inc.php b/html/pages/device/edit/ports.inc.php index 37cccb9d23..2e14cbb467 100644 --- a/html/pages/device/edit/ports.inc.php +++ b/html/pages/device/edit/ports.inc.php @@ -5,7 +5,7 @@ '> -
+
@@ -15,6 +15,7 @@ + @@ -23,6 +24,7 @@ diff --git a/html/pages/settings/external.inc.php b/html/pages/settings/external.inc.php index 5459ed67eb..a912ce403e 100644 --- a/html/pages/settings/external.inc.php +++ b/html/pages/settings/external.inc.php @@ -34,6 +34,17 @@ $unixagent_conf = array( ), ); +$rrdtool_conf = array( + array('name' => 'rrdtool', + 'descr' => 'Path to rrdtool binary', + 'type' => 'text', + ), + array('name' => 'rrdtool_tune', + 'descr' => 'Tune all rrd port files to use max values', + 'type' => 'checkbox', + ), +); + echo '
@@ -41,6 +52,7 @@ echo ' echo generate_dynamic_config_panel('Oxidized integration',true,$config_groups,$oxidized_conf); echo generate_dynamic_config_panel('Unix-agent integration',true,$config_groups,$unixagent_conf); +echo generate_dynamic_config_panel('RRDTool Setup',true,$config_groups,$rrdtool_conf); echo ' diff --git a/includes/polling/ports.inc.php b/includes/polling/ports.inc.php index 01a8e09aa1..c7602d6a22 100644 --- a/includes/polling/ports.inc.php +++ b/includes/polling/ports.inc.php @@ -339,6 +339,7 @@ foreach ($ports as $port) { } // Update IF-MIB data + $tune_port = false; foreach ($data_oids as $oid) { if ($oid == 'ifAlias') { @@ -358,6 +359,15 @@ foreach ($ports as $port) { } } else if ($port[$oid] != $this_port[$oid]) { + $port_tune = get_dev_attrib($device, 'ifName_tune:'.$port['ifName']); + $device_tune = get_dev_attrib($device,'override_rrdtool_tune'); + if ($port_tune == "true" || + ($device_tune == "true" && $port_tune != 'false') || + ($config['rrdtool_tune'] == "true" && $port_tune != 'false' && $device_tune != 'false')) { + if ($oid == 'ifSpeed') { + $tune_port = true; + } + } $port['update'][$oid] = $this_port[$oid]; log_event($oid.': '.$port[$oid].' -> '.$this_port[$oid], $device, 'interface', $port['port_id']); if ($debug) { @@ -501,6 +511,9 @@ foreach ($ports as $port) { 'OUTMULTICASTPKTS' => $this_port['ifOutMulticastPkts'], ); + if ($tune_port === true) { + rrdtool_tune('port',$rrdfile,$this_port['ifSpeed']); + } rrdtool_update("$rrdfile", $fields); // End Update IF-MIB // Update PAgP diff --git a/includes/rrdtool.inc.php b/includes/rrdtool.inc.php index 3c35cec224..9566497441 100644 --- a/includes/rrdtool.inc.php +++ b/includes/rrdtool.inc.php @@ -166,7 +166,11 @@ function rrdtool_graph($graph_file, $options) { function rrdtool($command, $filename, $options) { global $config, $debug, $rrd_pipes, $console_color; - if ($config['rrdcached'] && ($config['rrdtool_version'] >= 1.5 || $command != "create")) { + if ($config['rrdcached'] && + (version_compare($config['rrdtool_version'], '1.5.5', '>=') || + (version_compare($config['rrdtool_version'], '1.5', '>=') && $command != "tune") || + ($command != "create" && $command != "tune")) + ) { if (isset($config['rrdcached_dir']) && $config['rrdcached_dir'] !== false) { $filename = str_replace($config['rrd_dir'].'/', './'.$config['rrdcached_dir'].'/', $filename); $filename = str_replace($config['rrd_dir'], './'.$config['rrdcached_dir'].'/', $filename); @@ -294,3 +298,20 @@ function rrdtool_escape($string, $maxlength=null){ return $result.' '; } + +function rrdtool_tune($type, $filename, $max) { + $fields = array(); + if ($type === 'port') { + if ($max < 10000000) { + return false; + } + $max = $max / 8; + $fields = array( +'INOCTETS','OUTOCTETS','INERRORS','OUTERRORS','INUCASTPKTS','OUTUCASTPKTS','INNUCASTPKTS','OUTNUCASTPKTS','INDISCARDS','OUTDISCARDS','INUNKNOWNPROTOS','INBROADCASTPKTS','OUTBROADCASTPKTS','INMULTICASTPKTS','OUTMULTICASTPKTS' + ); + } + if (count($fields) > 0) { + $options = "--maximum " . implode(":$max --maximum ", $fields). ":$max"; + rrdtool('tune', $filename, $options); + } +} diff --git a/scripts/tune_port.php b/scripts/tune_port.php new file mode 100755 index 0000000000..2798469cc9 --- /dev/null +++ b/scripts/tune_port.php @@ -0,0 +1,32 @@ +#!/usr/bin/env php + Device(s) to match\n"; + echo "-p Port(s) to match using ifName\n"; + echo "\n"; + +} + +foreach (dbFetchRows("SELECT `device_id`,`hostname` FROM `devices` WHERE `hostname` LIKE ?", array('%'.$hosts.'%')) as $device) { + echo "Found hostname " . $device['hostname'].".......\n"; + foreach (dbFetchRows("SELECT `ifIndex`,`ifName`,`ifSpeed` FROM `ports` WHERE `ifName` LIKE ? AND `device_id` = ?", array('%'.$ports.'%',$device['device_id'])) as $port) { + echo "Tuning port " . $port['ifName'].".......\n"; + $host_rrd = $config['rrd_dir'].'/'.$device['hostname']; + $rrdfile = $host_rrd.'/port-'.safename($port['ifIndex'].'.rrd'); + rrdtool_tune('port',$rrdfile,$port['ifSpeed']); + } +} + diff --git a/sql-schema/079.sql b/sql-schema/079.sql new file mode 100644 index 0000000000..b4106e9528 --- /dev/null +++ b/sql-schema/079.sql @@ -0,0 +1 @@ +INSERT INTO config (config_name,config_value,config_default,config_descr,config_group,config_group_order,config_sub_group,config_sub_group_order,config_hidden,config_disabled) values ('rrdtool','/usr/bin/rrdtool','/usr/bin/rrdtool','Path to rrdtool','external',0,'rrdtool',0,'0','0'), ('rrdtool_tune','false','false','Auto tune maximum value for rrd port files','external',0,'rrdtool',0,'0','0');
Oper Disable IgnoreRRD Tune Description