Observium_CE/includes/polling/mac-accounting.inc.php

243 lines
8.1 KiB
PHP

<?php
/**
* Observium
*
* This file is part of Observium.
*
* @package observium
* @subpackage poller
* @copyright (C) Adam Armstrong
*
*/
// FIXME -- we're walking, so we can discover here too.
/// FIXME FIXME REWRITE ME please ;)
print_cli_data_field('MIBs', 2);
// Cache DB entries
$sql = 'SELECT * FROM `mac_accounting`';
$sql .= ' WHERE `device_id` = ?';
$acc_id_db = [];
foreach (dbFetchRows($sql, [$device['device_id']]) as $acc) {
$port = get_port_by_id($acc['port_id']);
if (is_array($port)) {
$acc['ifIndex'] = $port['ifIndex'];
unset($port);
$ma_db_array[$acc['ifIndex'] . '-' . $acc['vlan_id'] . '-' . $acc['mac']] = $acc;
}
$acc_id_db[$acc['ma_id']] = $acc['ma_id'];
}
print_debug_vars($ma_db_array);
if (is_device_mib($device, 'JUNIPER-MAC-MIB')) {
$datas = snmp_walk($device, 'jnxMacStatsEntry', '-OUqsX', 'JUNIPER-MAC-MIB');
if ($GLOBALS['snmp_status']) {
foreach (explode("\n", $datas) as $data) {
[$oid, $ifIndex, $vlan, $mac, $value] = parse_oid2($data);
[$a_a, $a_b, $a_c, $a_d, $a_e, $a_f] = explode(':', $mac);
$ah_a = zeropad($a_a);
$ah_b = zeropad($a_b);
$ah_c = zeropad($a_c);
$ah_d = zeropad($a_d);
$ah_e = zeropad($a_e);
$ah_f = zeropad($a_f);
$mac = "$ah_a$ah_b$ah_c$ah_d$ah_e$ah_f";
if ($mac == '000000000000') {
continue;
} // Skip entries with "zero" mac
$oid = str_replace(['cipMacSwitchedBytes', 'cipMacSwitchedPkts'], ['bytes', 'pkts'], $oid);
if ($oid == 'jnxMacHCOutFrames') {
$oid = 'pkts';
$dir = 'output';
}
if ($oid == 'jnxMacHCInFrames') {
$oid = 'pkts';
$dir = 'input';
}
if ($oid == 'jnxMacHCOutOctets') {
$oid = 'bytes';
$dir = 'output';
}
if ($oid == 'jnxMacHCInOctets') {
$oid = 'bytes';
$dir = 'input';
}
$ma_array[$ifIndex . '-' . $vlan . '-' . $mac]['ifIndex'] = $ifIndex;
$ma_array[$ifIndex . '-' . $vlan . '-' . $mac]['vlan'] = $vlan;
$ma_array[$ifIndex . '-' . $vlan . '-' . $mac]['mac'] = $mac;
$ma_array[$ifIndex . '-' . $vlan . '-' . $mac][$oid][$dir] = $value;
}
}
}
// Cisco MAC Accounting
// FIXME. Rewrite
if (is_device_mib($device, 'CISCO-IP-STAT-MIB')) {
echo('Cisco ');
$device_context = $device;
if (!safe_count($ma_db_array)) {
// Set retries to 0 for speedup first walking, only if previously polling also empty (DB empty)
$device_context['snmp_retries'] = 0;
}
$datas32 = snmp_walk($device_context, 'cipMacSwitchedBytes', '-OUqsX', 'CISCO-IP-STAT-MIB');
unset($device_context);
if ($GLOBALS['snmp_status']) {
$datas = snmp_walk($device, 'cipMacHCSwitchedBytes', '-OUqsX', 'CISCO-IP-STAT-MIB');
if (snmp_status()) {
$datas .= "\n" . snmp_walk($device, 'cipMacHCSwitchedPkts', '-OUqsX', 'CISCO-IP-STAT-MIB');
} else {
// No 64-bit counters? Try 32-bit. How necessary is this? How lacking is 64-bit support?
$datas = $datas32;
$datas .= "\n" . snmp_walk($device, 'cipMacSwitchedPkts', '-OUqsX', 'CISCO-IP-STAT-MIB');
}
foreach (explode("\n", $datas) as $data) {
[$oid, $ifIndex, $dir, $mac, $value] = parse_oid2($data);
[$a_a, $a_b, $a_c, $a_d, $a_e, $a_f] = explode(':', $mac);
$ah_a = zeropad($a_a);
$ah_b = zeropad($a_b);
$ah_c = zeropad($a_c);
$ah_d = zeropad($a_d);
$ah_e = zeropad($a_e);
$ah_f = zeropad($a_f);
$mac = "$ah_a$ah_b$ah_c$ah_d$ah_e$ah_f";
if ($mac == '000000000000') {
continue;
} // Skip entries with "zero" mac
// Cisco isn't per-VLAN.
$vlan = '0';
$oid = str_replace(['cipMacSwitchedBytes', 'cipMacSwitchedPkts', 'cipMacHCSwitchedBytes', 'cipMacHCSwitchedPkts'], ['bytes', 'pkts', 'bytes', 'pkts'], $oid);
$ma_array[$ifIndex . '-' . $vlan . '-' . $mac]['ifIndex'] = $ifIndex;
$ma_array[$ifIndex . '-' . $vlan . '-' . $mac]['vlan'] = $vlan;
$ma_array[$ifIndex . '-' . $vlan . '-' . $mac]['mac'] = $mac;
$ma_array[$ifIndex . '-' . $vlan . '-' . $mac][$oid][$dir] = $value;
}
}
}
// Below this should be MIB / vendor agnostic.
#function array_defuffle_three($array)
#{
# foreach ($array as $key_a => $a)
# {
# foreach ($a as $key_b => $b)
# {
# foreach ($b as $key_c => $c)
# {
# $new_array[] = array($key_a, $key_b, $key_c, $c);
# }
# }
# }
# return $new_array;
#}
$acc_id = []; // Count exist ma_ids
if (safe_count($ma_array)) {
if (OBS_DEBUG > 1) {
print_vars($ma_array);
}
$polled = time();
$mac_entries = 0;
echo('Entries: ' . count($ma_array) . PHP_EOL);
foreach ($ma_array as $id => $ma) {
$port = get_port_by_index_cache($device['device_id'], $ma['ifIndex']);
echo(' ' . $id . ' ');
if (!is_array($ma_db_array[$id])) {
$ma_id = dbInsert(['port_id' => $port['port_id'], 'device_id' => $device['device_id'], 'vlan_id' => $ma['vlan'], 'mac' => $ma['mac']], 'mac_accounting');
if ($ma_id) {
echo('+');
$acc_id[$ma_id] = $ma_id;
} else {
echo('-');
continue; // wrong adding to DB, not exist id - delete
}
} else {
echo('.');
$ma_db = $ma_db_array[$id];
$acc_id[$ma_db['ma_id']] = $ma_db['ma_id'];
}
$polled_period = $polled - $acc['poll_time'];
if (OBS_DEBUG > 1) {
print_vars($ma_array[$ifIndex][$vlan_id][$mac]);
}
$ma['update']['poll_time'] = $polled;
$ma['update']['poll_period'] = $polled_period;
$mac_entries++;
$b_in = $ma['bytes']['input'];
$b_out = $ma['bytes']['output'];
$p_in = $ma['pkts']['input'];
$p_out = $ma['pkts']['output'];
echo(' ' . $port['ifDescr'] . '(' . $ifIndex . ') -> ' . $mac);
// Update metrics
foreach (['bytes', 'pkts'] as $oid) {
foreach (['input', 'output'] as $dir) {
$oid_dir = $oid . '_' . $dir;
$ma['update'][$oid_dir] = $ma[$oid][$dir];
if ($ma[$oid][$dir] && $ma_db[$oid_dir]) {
$oid_diff = $ma[$oid][$dir] - $ma_db[$oid_dir];
$oid_rate = $oid_diff / $polled_period;
$ma['update'][$oid_dir . '_rate'] = $oid_rate;
$ma['update'][$oid_dir . '_delta'] = $oid_diff;
print_debug("\n $oid_dir ($oid_diff B) $oid_rate Bps $polled_period secs");
}
}
print_debug($ma['hostname'] . ' ' . $ma['ifDescr'] . " $mac -> $b_in:$b_out:$p_in:$p_out ");
// FIXME - use memory tables to make sure these values don't go backwards?
rrdtool_update_ng($device, 'mac_acc', [
'IN' => $b_in,
'OUT' => $b_out,
'PIN' => $p_in,
'POUT' => $p_out,
], $port['ifIndex'] . '-' . $ma['vlan'] . '-' . $ma['mac']);
if (OBS_DEBUG > 1) {
print_vars($ma['update']);
}
if (is_array($ma['update'])) { // Do Updates
dbUpdate($ma['update'], 'mac_accounting', '`ma_id` = ?', [$ma_db['ma_id']]);
} // End Updates
}
}
unset($ma_array);
if ($mac_entries) {
echo(" $mac_entries MAC accounting entries\n");
}
echo(PHP_EOL);
}
// CLEAN not exist entries
foreach ($acc_id_db as $ma_id => $entry) {
if (!isset($acc_id[$ma_id])) {
dbDelete('mac_accounting', '`ma_id` = ?', [$ma_id]);
}
}
echo(PHP_EOL);
// EOF