Selective Port polling improvements (#8650)

Don't delete skipped ports when using selected polling
Improve output of port polling module.
Update ifOperStatus and ifAdminStatus even when skipping.

Warning! causes a semantic change where ifAdminStatus_prev and ifOperStatus_prev are updated every poll, so they will only be mismatched for one poll.  This could cause alerts to behave differently.

Add an optimization if less than 10% of the ports are disabled (or less than 5), walk the base oids.
Time improvement on test device Full: 12s, Selective: 8s, Optimized 4s. (no disabled ports on device, many down)

Another test device.

![image](https://user-images.githubusercontent.com/39462/40066671-46cdc956-582a-11e8-928a-80bbd81dd423.png)


DO NOT DELETE THIS TEXT

#### Please note

> Please read this information carefully. You can run `./scripts/pre-commit.php` to check your code before submitting.

- [ ] Have you followed our [code guidelines?](http://docs.librenms.org/Developing/Code-Guidelines/)

#### Testers

If you would like to test this pull request then please run: `./scripts/github-apply <pr_id>`, i.e `./scripts/github-apply 5926`
This commit is contained in:
Tony Murray
2018-08-04 16:10:57 -05:00
committed by Neil Lathwood
parent f659ed8c41
commit e5fb7c9f16
2 changed files with 234 additions and 200 deletions

View File

@@ -1190,11 +1190,13 @@ function is_port_valid($port, $device)
if (empty($port['ifDescr'])) {
// If these are all empty, we are just going to show blank names in the ui
if (empty($port['ifAlias']) && empty($port['ifName'])) {
d_echo("ignored: empty ifDescr, ifAlias and ifName\n");
return false;
}
// ifDescr should not be empty unless it is explicitly allowed
if (!Config::getOsSetting($device['os'], 'empty_ifdescr', false)) {
d_echo("ignored: empty ifDescr\n");
return false;
}
}

View File

@@ -175,45 +175,87 @@ $dot3_oids = [
'dot3StatsDuplexStatus',
];
// Query known ports and mapping table in order of discovery to make sure
// the latest discoverd/polled port is in the mapping tables.
$ports_mapped = get_ports_mapped($device['device_id'], true);
$ports = $ports_mapped['ports'];
//
// Rename any old RRD files still named after the previous ifIndex based naming schema.
foreach ($ports_mapped['maps']['ifIndex'] as $ifIndex => $port_id) {
foreach (array ('', '-adsl', '-dot3') as $suffix) {
$old_rrd_name = "port-$ifIndex$suffix";
$new_rrd_name = getPortRrdName($port_id, ltrim($suffix, '-'));
rrd_file_rename($device, $old_rrd_name, $new_rrd_name);
}
}
echo 'Caching Oids: ';
$port_stats = array();
$data = array();
$port_stats = [];
if ($device['os'] === 'f5' && (version_compare($device['version'], '11.2.0', '>=') && version_compare($device['version'], '11.7', '<'))) {
require_once 'ports/f5.inc.php';
} else {
if ($config['polling']['selected_ports'] === true || $config['os'][$device['os']]['polling']['selected_ports'] === true || $device['attribs']['selected_ports'] == 'true') {
echo('Select ports polling');
$lports = dbFetchRows("SELECT * FROM `ports` where `device_id` = ? AND `deleted` = 0 AND `disabled` = 0", array($device['device_id']));
foreach ($lports as $lport) {
if (is_port_valid($lport, $device)) {
$i = $lport['ifIndex'];
$base_oids = implode(".$i ", $table_base_oids) . ".$i";
$data = snmp_get_multi($device, $base_oids, '-OQUst', 'IF-MIB', null, $data);
if ($lport['ifAdminStatus_prev'] === 'down' && $data[$i]['ifAdminStatus'] === 'down') {
echo 'port is still admin down';
} elseif ($lport['ifOperStatus_prev'] === 'down' && $data[$i]['ifOperStatus'] === 'down') {
echo 'port is still down';
echo 'Selected ports polling ';
// remove the deleted and disabled ports and mark them skipped
$polled_ports = array_filter($ports, function ($port) use ($ports) {
$ports[$port['ifIndex']]['skipped'] = true;
return !($port['deleted'] || $port['disabled']);
});
// if less than 5 ports or less than 10% of the total ports are skipped, walk the base oids instead of get
$polled_port_count = count($polled_ports);
$total_port_count = count($ports);
$walk_base = $total_port_count - $polled_port_count < 5 || $polled_port_count / $total_port_count > 0.9 ;
if ($walk_base) {
foreach ($table_base_oids as $oid) {
$port_stats = snmpwalk_cache_oid($device, $oid, $port_stats, 'IF-MIB');
}
}
foreach ($polled_ports as $port_id => $port) {
$ifIndex = $port['ifIndex'];
if (is_port_valid($port, $device)) {
if (!$walk_base) {
// we didn't walk,so snmpget the base oids
$base_oids = implode(".$ifIndex ", $table_base_oids) . ".$ifIndex";
$port_stats = snmp_get_multi($device, $base_oids, '-OQUst', 'IF-MIB', null, $port_stats);
}
// if admin down or operator down since the last poll, skip polling this port
$admin_down = $port['ifAdminStatus_prev'] === 'down' && $port_stats[$ifIndex]['ifAdminStatus'] === 'down';
$oper_down = $port['ifOperStatus_prev'] === 'down' && $port_stats[$ifIndex]['ifOperStatus'] === 'down';
if ($admin_down || $oper_down) {
if ($admin_down) {
d_echo(" port $ifIndex is still admin down\n");
} else {
d_echo(" port $ifIndex is still down\n");
}
$ports[$port_id]['skipped'] = true;
} else {
echo 'valid';
if (is_numeric($data[$i]['ifHighSpeed']) && $data[$i]['ifHighSpeed'] > 0) {
d_echo(" $ifIndex: valid\n");
if (is_numeric($port_stats[$ifIndex]['ifHighSpeed']) && $port_stats[$ifIndex]['ifHighSpeed'] > 0) {
$full_oids = array_merge($hc_oids, $shared_oids);
} else {
$full_oids = array_merge($nonhc_oids, $shared_oids);
}
$oids = implode(".$i ", $full_oids) . ".$i";
$extra_oids = implode(".$i ", $dot3_oids) . ".$i";
$oids = implode(".$ifIndex ", $full_oids) . ".$ifIndex";
$extra_oids = implode(".$ifIndex ", $dot3_oids) . ".$ifIndex";
unset($full_oids);
if (is_array($data[$i])) {
$port_stats[$i] = $data[$i];
}
$port_stats = snmp_get_multi($device, $oids, '-OQUst', 'IF-MIB', null, $port_stats);
$port_stats = snmp_get_multi($device, $extra_oids, '-OQUst', 'EtherLike-MIB', null, $port_stats);
}
}
}
unset($data);
} else {
echo 'Full ports polling ';
// For devices that are on the bad_ifXentry list, try fetching ifAlias to have nice interface descriptions.
if (!in_array(strtolower($device['hardware']), array_map('strtolower', (array)Config::getOsSetting($device['os'], 'bad_ifXEntry', [])))) {
@@ -353,24 +395,7 @@ if ($device['port_association_mode']) {
$port_association_mode = get_port_assoc_mode_name($device['port_association_mode']);
}
// Query known ports and mapping table in order of discovery to make sure
// the latest discoverd/polled port is in the mapping tables.
$ports_mapped = get_ports_mapped($device['device_id'], true);
$ports = $ports_mapped['ports'];
//
// Rename any old RRD files still named after the previous ifIndex based naming schema.
foreach ($ports_mapped['maps']['ifIndex'] as $ifIndex => $port_id) {
foreach (array ('', '-adsl', '-dot3') as $suffix) {
$old_rrd_name = "port-$ifIndex$suffix";
$new_rrd_name = getPortRrdName($port_id, ltrim($suffix, '-'));
rrd_file_rename($device, $old_rrd_name, $new_rrd_name);
}
}
$ports_found = array ();
$ports_found = [];
// New interface detection
foreach ($port_stats as $ifIndex => $port) {
// Store ifIndex in port entry and prefetch ifName as we'll need it multiple times
@@ -381,7 +406,7 @@ foreach ($port_stats as $ifIndex => $port) {
$port_id = get_port_id($ports_mapped, $port, $port_association_mode);
if (is_port_valid($port, $device)) {
echo 'valid';
d_echo(' valid');
// Port newly discovered?
if (! $ports[$port_id]) {
@@ -410,7 +435,7 @@ foreach ($port_stats as $ifIndex => $port) {
continue;
}
$port_id = dbInsert(array('device_id' => $device['device_id'], 'ifIndex' => $ifIndex, 'ifName' => $ifName), 'ports');
$port_id = dbInsert(array('device_id' => $device['device_id'], 'ifIndex' => $ifIndex, 'ifName' => $ifName), 'ports');
dbInsert(array('port_id' => $port_id), 'ports_statistics');
$ports[$port_id] = dbFetchRow('SELECT * FROM `ports` WHERE `port_id` = ?', array($port_id));
echo 'Adding: '.$ifName.'('.$ifIndex.')('.$port_id.')';
@@ -437,8 +462,8 @@ foreach ($port_stats as $ifIndex => $port) {
/* Build a list of all ports, identified by their port_id, found within this poller run. */
$ports_found[] = $port_id;
} // Port vanished (mark as deleted)
else {
} // Port vanished (mark as deleted) (except when skipped by selective port polling)
elseif (empty($ports[$port_id]['skipped'])) {
if ($ports[$port_id]['deleted'] != '1') {
dbUpdate(array('deleted' => '1'), 'ports', '`port_id` = ?', array($port_id));
$ports[$port_id]['deleted'] = '1';
@@ -457,7 +482,7 @@ foreach ($ports as $port) {
/* We don't care for disabled ports, go on */
if ($port['disabled'] == 1) {
echo "$port_info_string disabled.\n";
echo "{$port_info_string}disabled.\n";
continue;
}
@@ -468,7 +493,7 @@ foreach ($ports as $port) {
if (! in_array($port_id, $ports_found)) {
if ($port['deleted'] != '1') {
dbUpdate(array('deleted' => '1'), 'ports', '`device_id` = ? AND `port_id` = ?', array($device['device_id'], $port_id));
echo "$port_info_string deleted.\n";
echo "{$port_info_string}deleted.\n";
}
continue;
}
@@ -486,15 +511,15 @@ foreach ($ports as $port) {
$port['update'] = array();
$port['update_extended'] = array();
$port['state'] = array();
$port['state'] = array();
if ($port_association_mode != "ifIndex") {
$port['update']['ifIndex'] = $ifIndex;
}
if ($config['slow_statistics'] == true) {
$port['update']['poll_time'] = $polled;
$port['update']['poll_prev'] = $port['poll_time'];
$port['update']['poll_time'] = $polled;
$port['update']['poll_prev'] = $port['poll_time'];
$port['update']['poll_period'] = $polled_period;
}
@@ -525,7 +550,7 @@ foreach ($ports as $port) {
// rewrite the ifPhysAddress
if (strpos($this_port['ifPhysAddress'], ':')) {
list($a_a, $a_b, $a_c, $a_d, $a_e, $a_f) = explode(':', $this_port['ifPhysAddress']);
$this_port['ifPhysAddress'] = zeropad($a_a).zeropad($a_b).zeropad($a_c).zeropad($a_d).zeropad($a_e).zeropad($a_f);
$this_port['ifPhysAddress'] = zeropad($a_a) . zeropad($a_b) . zeropad($a_c) . zeropad($a_d) . zeropad($a_e) . zeropad($a_f);
}
// use HC values if they are available
@@ -579,7 +604,7 @@ foreach ($ports as $port) {
}
// FIXME use $q_bridge_mib[$this_port['ifIndex']] to see if it is a trunk (>1 array count)
echo 'VLAN == '.$this_port['ifVlan'];
echo "VLAN = {$this_port['ifVlan']} ";
// When devices do not provide ifDescr data, populate with ifName data if available
if ($this_port['ifDescr'] == '' || $this_port['ifDescr'] == null) {
@@ -602,12 +627,12 @@ foreach ($ports as $port) {
$tune_port = false;
foreach ($data_oids as $oid) {
if ($oid == 'ifAlias') {
if ($attribs['ifName:'.$port['ifName']]) {
if ($attribs['ifName:' . $port['ifName']]) {
$this_port['ifAlias'] = $port['ifAlias'];
}
}
if ($oid == 'ifSpeed' || $oid == 'ifHighSpeed') {
if ($attribs['ifSpeed:'.$port['ifName']]) {
if ($attribs['ifSpeed:' . $port['ifName']]) {
$this_port[$oid] = $port[$oid];
}
}
@@ -616,15 +641,15 @@ foreach ($ports as $port) {
$port['update'][$oid] = array('NULL');
log_event($oid . ': ' . $port[$oid] . ' -> NULL', $device, 'interface', 4, $port['port_id']);
if ($debug) {
d_echo($oid.': '.$port[$oid].' -> NULL ');
d_echo($oid . ': ' . $port[$oid] . ' -> NULL ');
} else {
echo $oid.' ';
echo $oid . ' ';
}
} elseif ($port[$oid] != $this_port[$oid]) {
// if the value is different, update it
// rrdtune if needed
$port_tune = $attribs['ifName_tune:'.$port['ifName']];
$port_tune = $attribs['ifName_tune:' . $port['ifName']];
$device_tune = $attribs['override_rrdtool_tune'];
if ($port_tune == "true" ||
($device_tune == "true" && $port_tune != 'false') ||
@@ -639,26 +664,26 @@ foreach ($ports as $port) {
// store the previous values for alerting
if ($oid == 'ifOperStatus' || $oid == 'ifAdminStatus') {
$port['update'][$oid.'_prev'] = $port[$oid];
$port['update'][$oid . '_prev'] = $port[$oid];
}
log_event($oid . ': ' . $port[$oid] . ' -> ' . $this_port[$oid], $device, 'interface', 3, $port['port_id']);
if ($debug) {
d_echo($oid.': '.$port[$oid].' -> '.$this_port[$oid].' ');
d_echo($oid . ': ' . $port[$oid] . ' -> ' . $this_port[$oid] . ' ');
} else {
echo $oid.' ';
echo $oid . ' ';
}
} else {
if ($oid == 'ifOperStatus' || $oid == 'ifAdminStatus') {
if ($port[$oid.'_prev'] == null) {
$port['update'][$oid.'_prev'] = $this_port[$oid];
if ($port[$oid . '_prev'] != $this_port[$oid]) {
$port['update'][$oid . '_prev'] = $this_port[$oid];
}
}
}
}//end foreach
// Parse description (usually ifAlias) if config option set
if (isset($config['port_descr_parser']) && is_file($config['install_dir'].'/'.$config['port_descr_parser'])) {
if (isset($config['port_descr_parser']) && is_file($config['install_dir'] . '/' . $config['port_descr_parser'])) {
$port_attribs = array(
'type',
'descr',
@@ -667,14 +692,14 @@ foreach ($ports as $port) {
'notes',
);
include $config['install_dir'].'/'.$config['port_descr_parser'];
include $config['install_dir'] . '/' . $config['port_descr_parser'];
foreach ($port_attribs as $attrib) {
$attrib_key = 'port_descr_'.$attrib;
$attrib_key = 'port_descr_' . $attrib;
if ($port_ifAlias[$attrib] != $port[$attrib_key]) {
if (!isset($port_ifAlias[$attrib])) {
$port_ifAlias[$attrib] = array('NULL');
$log_port = 'NULL';
$log_port = 'NULL';
} else {
$log_port = $port_ifAlias[$attrib];
}
@@ -686,161 +711,166 @@ foreach ($ports as $port) {
}
}//end if
// End parse ifAlias
// Update IF-MIB metrics
$_stat_oids = array_merge($stat_oids_db, $stat_oids_db_extended);
foreach ($_stat_oids as $oid) {
$port_update = 'update';
$extended_metric = !in_array($oid, $stat_oids_db, true);
if ($extended_metric) {
$port_update = 'update_extended';
}
if ($config['slow_statistics'] == true) {
$port[$port_update][$oid] = set_numeric($this_port[$oid]);
$port[$port_update][$oid.'_prev'] = set_numeric($port[$oid]);
}
$oid_prev = $oid.'_prev';
if (isset($port[$oid])) {
$oid_diff = ($this_port[$oid] - $port[$oid]);
$oid_rate = ($oid_diff / $polled_period);
if ($oid_rate < 0) {
$oid_rate = '0';
echo "negative $oid";
// We don't care about statistics for skipped selective polling ports
if (!empty($port['skipped'])) {
echo " $port_id skipped.";
} else {
// End parse ifAlias
// Update IF-MIB metrics
$_stat_oids = array_merge($stat_oids_db, $stat_oids_db_extended);
foreach ($_stat_oids as $oid) {
$port_update = 'update';
$extended_metric = !in_array($oid, $stat_oids_db, true);
if ($extended_metric) {
$port_update = 'update_extended';
}
$port['stats'][$oid.'_rate'] = $oid_rate;
$port['stats'][$oid.'_diff'] = $oid_diff;
if ($config['slow_statistics'] == true) {
$port[$port_update][$oid.'_rate'] = $oid_rate;
$port[$port_update][$oid.'_delta'] = $oid_diff;
$port[$port_update][$oid] = set_numeric($this_port[$oid]);
$port[$port_update][$oid . '_prev'] = set_numeric($port[$oid]);
}
d_echo("\n $oid ($oid_diff B) $oid_rate Bps $polled_period secs\n");
}//end if
}//end foreach
$oid_prev = $oid . '_prev';
if (isset($port[$oid])) {
$oid_diff = ($this_port[$oid] - $port[$oid]);
$oid_rate = ($oid_diff / $polled_period);
if ($oid_rate < 0) {
$oid_rate = '0';
echo "negative $oid";
}
if ($config['debug_port'][$port['port_id']]) {
$port_debug = $port['port_id'].'|'.$polled.'|'.$polled_period.'|'.$this_port['ifHCInOctets'].'|'.$this_port['ifHCOutOctets'];
$port_debug .= '|'.$port['stats']['ifInOctets_rate'].'|'.$port['stats']['ifOutOctets_rate']."\n";
file_put_contents('/tmp/port_debug.txt', $port_debug, FILE_APPEND);
echo 'Wrote port debugging data';
}
$port['stats'][$oid . '_rate'] = $oid_rate;
$port['stats'][$oid . '_diff'] = $oid_diff;
$port['stats']['ifInBits_rate'] = round(($port['stats']['ifInOctets_rate'] * 8));
$port['stats']['ifOutBits_rate'] = round(($port['stats']['ifOutOctets_rate'] * 8));
if ($config['slow_statistics'] == true) {
$port[$port_update][$oid . '_rate'] = $oid_rate;
$port[$port_update][$oid . '_delta'] = $oid_diff;
}
// If we have a valid ifSpeed we should populate the stats for checking.
if (is_numeric($this_port['ifSpeed']) && $this_port['ifSpeed'] > 0) {
$port['stats']['ifInBits_perc'] = round(($port['stats']['ifInBits_rate'] / $this_port['ifSpeed'] * 100));
$port['stats']['ifOutBits_perc'] = round(($port['stats']['ifOutBits_rate'] / $this_port['ifSpeed'] * 100));
}
echo 'bps('.formatRates($port['stats']['ifInBits_rate']).'/'.formatRates($port['stats']['ifOutBits_rate']).')';
echo 'bytes('.formatStorage($port['stats']['ifInOctets_diff']).'/'.formatStorage($port['stats']['ifOutOctets_diff']).')';
echo 'pkts('.format_si($port['stats']['ifInUcastPkts_rate']).'pps/'.format_si($port['stats']['ifOutUcastPkts_rate']).'pps)';
d_echo("\n $oid ($oid_diff B) $oid_rate Bps $polled_period secs\n");
}//end if
}//end foreach
// Port utilisation % threshold alerting. // FIXME allow setting threshold per-port. probably 90% of ports we don't care about.
if ($config['alerts']['port_util_alert'] && $port['ignore'] == '0') {
// Check for port saturation of $config['alerts']['port_util_perc'] or higher. Alert if we see this.
// Check both inbound and outbound rates
$saturation_threshold = ($this_port['ifSpeed'] * ( $config['alerts']['port_util_perc'] / 100 ));
echo 'IN: '.$port['stats']['ifInBits_rate'].' OUT: '.$port['stats']['ifOutBits_rate'].' THRESH: '.$saturation_threshold;
if (($port['stats']['ifInBits_rate'] >= $saturation_threshold || $port['stats']['ifOutBits_rate'] >= $saturation_threshold) && $saturation_threshold > 0) {
log_event('Port reached saturation threshold: ' . formatRates($port['stats']['ifInBits_rate']) . '/' . formatRates($port['stats']['ifOutBits_rate']) . ' - ifspeed: ' . formatRates($this_port['stats']['ifSpeed']), $device, 'interface', 4, $port['port_id']);
if ($config['debug_port'][$port['port_id']]) {
$port_debug = $port['port_id'] . '|' . $polled . '|' . $polled_period . '|' . $this_port['ifHCInOctets'] . '|' . $this_port['ifHCOutOctets'];
$port_debug .= '|' . $port['stats']['ifInOctets_rate'] . '|' . $port['stats']['ifOutOctets_rate'] . "\n";
file_put_contents('/tmp/port_debug.txt', $port_debug, FILE_APPEND);
echo 'Wrote port debugging data';
}
}
// Update data stores
$rrd_name = getPortRrdName($port_id);
$rrdfile = rrd_name($device['hostname'], $rrd_name);
$rrd_def = RrdDefinition::make()
->addDataset('INOCTETS', 'DERIVE', 0, 12500000000)
->addDataset('OUTOCTETS', 'DERIVE', 0, 12500000000)
->addDataset('INERRORS', 'DERIVE', 0, 12500000000)
->addDataset('OUTERRORS', 'DERIVE', 0, 12500000000)
->addDataset('INUCASTPKTS', 'DERIVE', 0, 12500000000)
->addDataset('OUTUCASTPKTS', 'DERIVE', 0, 12500000000)
->addDataset('INNUCASTPKTS', 'DERIVE', 0, 12500000000)
->addDataset('OUTNUCASTPKTS', 'DERIVE', 0, 12500000000)
->addDataset('INDISCARDS', 'DERIVE', 0, 12500000000)
->addDataset('OUTDISCARDS', 'DERIVE', 0, 12500000000)
->addDataset('INUNKNOWNPROTOS', 'DERIVE', 0, 12500000000)
->addDataset('INBROADCASTPKTS', 'DERIVE', 0, 12500000000)
->addDataset('OUTBROADCASTPKTS', 'DERIVE', 0, 12500000000)
->addDataset('INMULTICASTPKTS', 'DERIVE', 0, 12500000000)
->addDataset('OUTMULTICASTPKTS', 'DERIVE', 0, 12500000000);
$port['stats']['ifInBits_rate'] = round(($port['stats']['ifInOctets_rate'] * 8));
$port['stats']['ifOutBits_rate'] = round(($port['stats']['ifOutOctets_rate'] * 8));
$fields = array(
'INOCTETS' => $this_port['ifInOctets'],
'OUTOCTETS' => $this_port['ifOutOctets'],
'INERRORS' => $this_port['ifInErrors'],
'OUTERRORS' => $this_port['ifOutErrors'],
'INUCASTPKTS' => $this_port['ifInUcastPkts'],
'OUTUCASTPKTS' => $this_port['ifOutUcastPkts'],
'INNUCASTPKTS' => $this_port['ifInNUcastPkts'],
'OUTNUCASTPKTS' => $this_port['ifOutNUcastPkts'],
'INDISCARDS' => $this_port['ifInDiscards'],
'OUTDISCARDS' => $this_port['ifOutDiscards'],
'INUNKNOWNPROTOS' => $this_port['ifInUnknownProtos'],
'INBROADCASTPKTS' => $this_port['ifInBroadcastPkts'],
'OUTBROADCASTPKTS' => $this_port['ifOutBroadcastPkts'],
'INMULTICASTPKTS' => $this_port['ifInMulticastPkts'],
'OUTMULTICASTPKTS' => $this_port['ifOutMulticastPkts'],
);
// If we have a valid ifSpeed we should populate the stats for checking.
if (is_numeric($this_port['ifSpeed']) && $this_port['ifSpeed'] > 0) {
$port['stats']['ifInBits_perc'] = round(($port['stats']['ifInBits_rate'] / $this_port['ifSpeed'] * 100));
$port['stats']['ifOutBits_perc'] = round(($port['stats']['ifOutBits_rate'] / $this_port['ifSpeed'] * 100));
}
if ($tune_port === true) {
rrdtool_tune('port', $rrdfile, $this_port['ifSpeed']);
}
echo 'bps(' . formatRates($port['stats']['ifInBits_rate']) . '/' . formatRates($port['stats']['ifOutBits_rate']) . ')';
echo 'bytes(' . formatStorage($port['stats']['ifInOctets_diff']) . '/' . formatStorage($port['stats']['ifOutOctets_diff']) . ')';
echo 'pkts(' . format_si($port['stats']['ifInUcastPkts_rate']) . 'pps/' . format_si($port['stats']['ifOutUcastPkts_rate']) . 'pps)';
$port_descr_type = $port['port_descr_type'];
$ifName = $port['ifName'];
$ifAlias = $port['ifAlias'];
$tags = compact('ifName', 'ifAlias', 'port_descr_type', 'rrd_name', 'rrd_def');
rrdtool_data_update($device, 'ports', $tags, $fields);
$fields['ifInUcastPkts_rate'] = $port['ifInUcastPkts_rate'];
$fields['ifOutUcastPkts_rate'] = $port['ifOutUcastPkts_rate'];
$fields['ifInErrors_rate'] = $port['ifInErrors_rate'];
$fields['ifOutErrors_rate'] = $port['ifOutErrors_rate'];
$fields['ifInOctets_rate'] = $port['ifInOctets_rate'];
$fields['ifOutOctets_rate'] = $port['ifOutOctets_rate'];
prometheus_push($device, 'ports', rrd_array_filter($tags), $fields);
influx_update($device, 'ports', rrd_array_filter($tags), $fields);
graphite_update($device, 'ports|' . $ifName, $tags, $fields);
opentsdb_update($device, 'port', array('ifName' => $this_port['ifName'], 'ifIndex' => getPortRrdName($port_id)), $fields);
// End Update IF-MIB
// Update PAgP
if ($this_port['pagpOperationMode'] || $port['pagpOperationMode']) {
foreach ($pagp_oids as $oid) {
// Loop the OIDs
if ($this_port[$oid] != $port[$oid]) {
// If data has changed, build a query
$port['update'][$oid] = $this_port[$oid];
echo 'PAgP ';
log_event("$oid -> " . $this_port[$oid], $device, 'interface', 3, $port['port_id']);
// Port utilisation % threshold alerting. // FIXME allow setting threshold per-port. probably 90% of ports we don't care about.
if ($config['alerts']['port_util_alert'] && $port['ignore'] == '0') {
// Check for port saturation of $config['alerts']['port_util_perc'] or higher. Alert if we see this.
// Check both inbound and outbound rates
$saturation_threshold = ($this_port['ifSpeed'] * ($config['alerts']['port_util_perc'] / 100));
echo 'IN: ' . $port['stats']['ifInBits_rate'] . ' OUT: ' . $port['stats']['ifOutBits_rate'] . ' THRESH: ' . $saturation_threshold;
if (($port['stats']['ifInBits_rate'] >= $saturation_threshold || $port['stats']['ifOutBits_rate'] >= $saturation_threshold) && $saturation_threshold > 0) {
log_event('Port reached saturation threshold: ' . formatRates($port['stats']['ifInBits_rate']) . '/' . formatRates($port['stats']['ifOutBits_rate']) . ' - ifspeed: ' . formatRates($this_port['stats']['ifSpeed']), $device, 'interface', 4, $port['port_id']);
}
}
}
// End Update PAgP
// Do EtherLike-MIB
if ($config['enable_ports_etherlike']) {
include 'ports/port-etherlike.inc.php';
}
// Update data stores
$rrd_name = getPortRrdName($port_id);
$rrdfile = rrd_name($device['hostname'], $rrd_name);
$rrd_def = RrdDefinition::make()
->addDataset('INOCTETS', 'DERIVE', 0, 12500000000)
->addDataset('OUTOCTETS', 'DERIVE', 0, 12500000000)
->addDataset('INERRORS', 'DERIVE', 0, 12500000000)
->addDataset('OUTERRORS', 'DERIVE', 0, 12500000000)
->addDataset('INUCASTPKTS', 'DERIVE', 0, 12500000000)
->addDataset('OUTUCASTPKTS', 'DERIVE', 0, 12500000000)
->addDataset('INNUCASTPKTS', 'DERIVE', 0, 12500000000)
->addDataset('OUTNUCASTPKTS', 'DERIVE', 0, 12500000000)
->addDataset('INDISCARDS', 'DERIVE', 0, 12500000000)
->addDataset('OUTDISCARDS', 'DERIVE', 0, 12500000000)
->addDataset('INUNKNOWNPROTOS', 'DERIVE', 0, 12500000000)
->addDataset('INBROADCASTPKTS', 'DERIVE', 0, 12500000000)
->addDataset('OUTBROADCASTPKTS', 'DERIVE', 0, 12500000000)
->addDataset('INMULTICASTPKTS', 'DERIVE', 0, 12500000000)
->addDataset('OUTMULTICASTPKTS', 'DERIVE', 0, 12500000000);
// Do ADSL MIB
if ($config['enable_ports_adsl']) {
include 'ports/port-adsl.inc.php';
}
$fields = array(
'INOCTETS' => $this_port['ifInOctets'],
'OUTOCTETS' => $this_port['ifOutOctets'],
'INERRORS' => $this_port['ifInErrors'],
'OUTERRORS' => $this_port['ifOutErrors'],
'INUCASTPKTS' => $this_port['ifInUcastPkts'],
'OUTUCASTPKTS' => $this_port['ifOutUcastPkts'],
'INNUCASTPKTS' => $this_port['ifInNUcastPkts'],
'OUTNUCASTPKTS' => $this_port['ifOutNUcastPkts'],
'INDISCARDS' => $this_port['ifInDiscards'],
'OUTDISCARDS' => $this_port['ifOutDiscards'],
'INUNKNOWNPROTOS' => $this_port['ifInUnknownProtos'],
'INBROADCASTPKTS' => $this_port['ifInBroadcastPkts'],
'OUTBROADCASTPKTS' => $this_port['ifOutBroadcastPkts'],
'INMULTICASTPKTS' => $this_port['ifInMulticastPkts'],
'OUTMULTICASTPKTS' => $this_port['ifOutMulticastPkts'],
);
// Do PoE MIBs
if ($config['enable_ports_poe']) {
include 'ports/port-poe.inc.php';
if ($tune_port === true) {
rrdtool_tune('port', $rrdfile, $this_port['ifSpeed']);
}
$port_descr_type = $port['port_descr_type'];
$ifName = $port['ifName'];
$ifAlias = $port['ifAlias'];
$tags = compact('ifName', 'ifAlias', 'port_descr_type', 'rrd_name', 'rrd_def');
rrdtool_data_update($device, 'ports', $tags, $fields);
$fields['ifInUcastPkts_rate'] = $port['ifInUcastPkts_rate'];
$fields['ifOutUcastPkts_rate'] = $port['ifOutUcastPkts_rate'];
$fields['ifInErrors_rate'] = $port['ifInErrors_rate'];
$fields['ifOutErrors_rate'] = $port['ifOutErrors_rate'];
$fields['ifInOctets_rate'] = $port['ifInOctets_rate'];
$fields['ifOutOctets_rate'] = $port['ifOutOctets_rate'];
prometheus_push($device, 'ports', rrd_array_filter($tags), $fields);
influx_update($device, 'ports', rrd_array_filter($tags), $fields);
graphite_update($device, 'ports|' . $ifName, $tags, $fields);
opentsdb_update($device, 'port', array('ifName' => $this_port['ifName'], 'ifIndex' => getPortRrdName($port_id)), $fields);
// End Update IF-MIB
// Update PAgP
if ($this_port['pagpOperationMode'] || $port['pagpOperationMode']) {
foreach ($pagp_oids as $oid) {
// Loop the OIDs
if ($this_port[$oid] != $port[$oid]) {
// If data has changed, build a query
$port['update'][$oid] = $this_port[$oid];
echo 'PAgP ';
log_event("$oid -> " . $this_port[$oid], $device, 'interface', 3, $port['port_id']);
}
}
}
// End Update PAgP
// Do EtherLike-MIB
if ($config['enable_ports_etherlike']) {
include 'ports/port-etherlike.inc.php';
}
// Do ADSL MIB
if ($config['enable_ports_adsl']) {
include 'ports/port-adsl.inc.php';
}
// Do PoE MIBs
if ($config['enable_ports_poe']) {
include 'ports/port-poe.inc.php';
}
}
foreach ($port['update'] as $key => $val_check) {
@@ -853,7 +883,9 @@ foreach ($ports as $port) {
if (count($port['update'])) {
$updated = dbUpdate($port['update'], 'ports', '`port_id` = ?', array($port_id));
// do we want to do something else with this?
$updated += dbUpdate($port['update_extended'], 'ports_statistics', '`port_id` = ?', array($port_id));
if (!empty($port['update_extended'])) {
$updated += dbUpdate($port['update_extended'], 'ports_statistics', '`port_id` = ?', array($port_id));
}
d_echo("$updated updated");
}
// End Update Database