diff --git a/doc/Extensions/RRDTune.md b/doc/Extensions/RRDTune.md new file mode 100644 index 000000000..7ee7095d2 --- /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 d7317db4f..d6da5de50 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 d4ccba8a5..625ac5e75 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 034f1a945..b91090761 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 d1731ecdf..b46932a15 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 37cccb9d2..2e14cbb46 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 5459ed67e..a912ce403 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 01a8e09aa..c7602d6a2 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 3c35cec22..956649744 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 000000000..2798469cc --- /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 000000000..b4106e952 --- /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