1<?php 2 3/** 4 * Observium 5 * 6 * This file is part of Observium. 7 * 8 * @package observium 9 * @subpackage poller 10 * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2019 Observium Limited 11 * 12 */ 13 14// FIXME -- we're walking, so we can discover here too. 15 16/// FIXME FIXME REWRITE ME please ;) 17 18print_cli_data_field('MIBs', 2); 19 20// Cache DB entries 21$sql = 'SELECT * FROM `mac_accounting`'; 22$sql .= ' WHERE `device_id` = ?'; 23 24$acc_id_db = array(); 25foreach (dbFetchRows($sql, array($device['device_id'])) as $acc) 26{ 27 $port = get_port_by_id($acc['port_id']); 28 if (is_array($port)) 29 { 30 $acc['ifIndex'] = $port['ifIndex']; 31 unset($port); 32 $ma_db_array[$acc['ifIndex'].'-'.$acc['vlan_id'].'-'.$acc['mac']] = $acc; 33 } 34 $acc_id_db[$acc['ma_id']] = $acc['ma_id']; 35} 36 37if (OBS_DEBUG > 1 && count($ma_db_array)) 38{ 39 print_vars($ma_db_array); 40} 41 42if (is_device_mib($device, 'JUNIPER-MAC-MIB')) 43{ 44 $datas = snmp_walk($device, 'jnxMacStatsEntry', '-OUqsX', 'JUNIPER-MAC-MIB'); 45 if ($GLOBALS['snmp_status']) 46 { 47 foreach (explode("\n", $datas) as $data) 48 { 49 list($oid,$ifIndex,$vlan,$mac,$value) = parse_oid2($data); 50 list($a_a, $a_b, $a_c, $a_d, $a_e, $a_f) = explode(':', $mac); 51 $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); 52 $mac = "$ah_a$ah_b$ah_c$ah_d$ah_e$ah_f"; 53 if ($mac == '000000000000') { continue; } // Skip entries with "zero" mac 54 55 $oid = str_replace(array('cipMacSwitchedBytes', 'cipMacSwitchedPkts'), array('bytes', 'pkts'), $oid); 56 57 if ($oid == 'jnxMacHCOutFrames') { $oid = 'pkts'; $dir = 'output'; } 58 if ($oid == 'jnxMacHCInFrames') { $oid = 'pkts'; $dir = 'input'; } 59 if ($oid == 'jnxMacHCOutOctets') { $oid = 'bytes'; $dir = 'output'; } 60 if ($oid == 'jnxMacHCInOctets') { $oid = 'bytes'; $dir = 'input'; } 61 62 $ma_array[$ifIndex.'-'.$vlan.'-'.$mac]['ifIndex'] = $ifIndex; 63 $ma_array[$ifIndex.'-'.$vlan.'-'.$mac]['vlan'] = $vlan; 64 $ma_array[$ifIndex.'-'.$vlan.'-'.$mac]['mac'] = $mac; 65 $ma_array[$ifIndex.'-'.$vlan.'-'.$mac][$oid][$dir] = $value; 66 } 67 } 68} 69 70// Cisco MAC Accounting 71// FIXME. Rewrite 72if (is_device_mib($device, 'CISCO-IP-STAT-MIB')) 73{ 74 echo('Cisco '); 75 76 $device_context = $device; 77 if (!count($ma_db_array)) 78 { 79 // Set retries to 0 for speedup first walking, only if previously polling also empty (DB empty) 80 $device_context['snmp_retries'] = 0; 81 } 82 $datas32 = snmp_walk($device_context, 'cipMacSwitchedBytes', '-OUqsX', 'CISCO-IP-STAT-MIB'); 83 unset($device_context); 84 if ($GLOBALS['snmp_status']) 85 { 86 $datas = snmp_walk($device, 'cipMacHCSwitchedBytes', '-OUqsX', 'CISCO-IP-STAT-MIB'); 87 if ($GLOBALS['snmp_status']) 88 { 89 $datas .= "\n".snmp_walk($device, 'cipMacHCSwitchedPkts', '-OUqsX', 'CISCO-IP-STAT-MIB'); 90 } else { 91 // No 64-bit counters? Try 32-bit. How necessary is this? How lacking is 64-bit support? 92 $datas = $datas32; 93 $datas .= "\n".snmp_walk($device, 'cipMacSwitchedPkts', '-OUqsX', 'CISCO-IP-STAT-MIB'); 94 } 95 96 foreach (explode("\n", $datas) as $data) 97 { 98 list($oid,$ifIndex,$dir,$mac,$value) = parse_oid2($data); 99 list($a_a, $a_b, $a_c, $a_d, $a_e, $a_f) = explode(':', $mac); 100 $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); 101 $mac = "$ah_a$ah_b$ah_c$ah_d$ah_e$ah_f"; 102 if ($mac == '000000000000') { continue; } // Skip entries with "zero" mac 103 104 // Cisco isn't per-VLAN. 105 $vlan = '0'; 106 107 $oid = str_replace(array('cipMacSwitchedBytes', 'cipMacSwitchedPkts', 'cipMacHCSwitchedBytes', 'cipMacHCSwitchedPkts'), array('bytes', 'pkts', 'bytes', 'pkts'), $oid); 108 $ma_array[$ifIndex.'-'.$vlan.'-'.$mac]['ifIndex'] = $ifIndex; 109 $ma_array[$ifIndex.'-'.$vlan.'-'.$mac]['vlan'] = $vlan; 110 $ma_array[$ifIndex.'-'.$vlan.'-'.$mac]['mac'] = $mac; 111 $ma_array[$ifIndex.'-'.$vlan.'-'.$mac][$oid][$dir] = $value; 112 } 113 } 114} 115 116// Below this should be MIB / vendor agnostic. 117 118#function array_defuffle_three($array) 119#{ 120# foreach ($array as $key_a => $a) 121# { 122# foreach ($a as $key_b => $b) 123# { 124# foreach ($b as $key_c => $c) 125# { 126# $new_array[] = array($key_a, $key_b, $key_c, $c); 127# } 128# } 129# } 130# return $new_array; 131#} 132 133$acc_id = array(); // Count exist ma_ids 134if (count($ma_array)) 135{ 136 if (OBS_DEBUG > 1) { print_vars($ma_array); } 137 $polled = time(); 138 $mac_entries = 0; 139 echo('Entries: '.count($ma_array).PHP_EOL); 140 141 foreach ($ma_array as $id => $ma) 142 { 143 $port = get_port_by_index_cache($device['device_id'], $ma['ifIndex']); 144 145 echo(' '.$id.' '); 146 147 if (!is_array($ma_db_array[$id])) 148 { 149 $ma_id = dbInsert(array('port_id' => $port['port_id'], 'device_id' => $device['device_id'], 'vlan_id' => $ma['vlan'], 'mac' => $ma['mac'] ), 'mac_accounting'); 150 if ($ma_id) 151 { 152 echo('+'); 153 $acc_id[$ma_id] = $ma_id; 154 } else { 155 echo('-'); 156 continue; // wrong adding to DB, not exist id - delete 157 } 158 } else { 159 echo('.'); 160 $ma_db = $ma_db_array[$id]; 161 $acc_id[$ma_db['ma_id']] = $ma_db['ma_id']; 162 } 163 164 $polled_period = $polled - $acc['poll_time']; 165 166 if (OBS_DEBUG > 1) { print_vars($ma_array[$ifIndex][$vlan_id][$mac]); } 167 168 $ma['update']['poll_time'] = $polled; 169 $ma['update']['poll_period'] = $polled_period; 170 $mac_entries++; 171 $b_in = $ma['bytes']['input']; 172 $b_out = $ma['bytes']['output']; 173 $p_in = $ma['pkts']['input']; 174 $p_out = $ma['pkts']['output']; 175 176 echo(' '.$port['ifDescr'].'('.$ifIndex.') -> '.$mac); 177 178 // Update metrics 179 foreach (array('bytes','pkts') as $oid) 180 { 181 foreach (array('input','output') as $dir) 182 { 183 $oid_dir = $oid . '_' . $dir; 184 $ma['update'][$oid_dir] = $ma[$oid][$dir]; 185 186 if ($ma[$oid][$dir] && $ma_db[$oid_dir]) 187 { 188 $oid_diff = $ma[$oid][$dir] - $ma_db[$oid_dir]; 189 $oid_rate = $oid_diff / $polled_period; 190 $ma['update'][$oid_dir.'_rate'] = $oid_rate; 191 $ma['update'][$oid_dir.'_delta'] = $oid_diff; 192 print_debug("\n $oid_dir ($oid_diff B) $oid_rate Bps $polled_period secs"); 193 } 194 } 195 196 print_debug($ma['hostname'].' '.$ma['ifDescr'] . " $mac -> $b_in:$b_out:$p_in:$p_out "); 197 198 // FIXME - use memory tables to make sure these values don't go backwards? 199 rrdtool_update_ng($device, 'mac_acc', array( 200 'IN' => $b_in, 201 'OUT' => $b_out, 202 'PIN' => $p_in, 203 'POUT' => $p_out, 204 ), $port['ifIndex'] . '-' . $ma['vlan'] .'-' . $ma['mac']); 205 206 if (OBS_DEBUG > 1) { print_vars($ma['update']); } 207 208 if (is_array($ma['update'])) 209 { // Do Updates 210 dbUpdate($ma['update'], 'mac_accounting', '`ma_id` = ?', array($ma_db['ma_id'])); 211 } // End Updates 212 } 213 } 214 215 unset($ma_array); 216 217 if ($mac_entries) { echo(" $mac_entries MAC accounting entries\n"); } 218 219 echo(PHP_EOL); 220} 221 222// CLEAN not exist entries 223foreach ($acc_id_db as $ma_id => $entry) 224{ 225 if (!isset($acc_id[$ma_id])) 226 { 227 dbDelete('mac_accounting', '`ma_id` = ?', array($ma_id)); 228 } 229} 230echo(PHP_EOL); 231 232// EOF 233