123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507 |
- <?php
- /**
- * Live switch/routers SNMP bandwidth monitoring implementation
- */
- class SwitchSonic {
- /**
- * Contains remote device IP address
- *
- * @var string
- */
- protected $ip = '';
- /**
- * Contains remote device SNMP read community
- *
- * @var string
- */
- protected $community = '';
- /**
- * SNMP helper object placeholder
- *
- * @var object
- */
- protected $snmp = '';
- /**
- * Caching engine object placeholder
- *
- * @var object
- */
- protected $cache = '';
- /**
- * Default caching timeout to store switch/auth data in seconds
- *
- * @var int
- */
- protected $cachingTimeout = 120;
- /**
- * Time window to display on charts in seconds
- *
- * @var int
- */
- protected $timeWindow = 300;
- /**
- * Contains default kilo-multiplier to convert bits in Kilo
- *
- * @var int
- */
- protected $offsetKilo = 1024;
- /**
- * Contains default kilo-multiplier to convert bits in Mega
- *
- * @var int
- */
- protected $offsetMega = 1024000;
- /**
- * Contains default kilo-multiplier to convert bits in Giga
- *
- * @var int
- */
- protected $offsetGiga = 1024000000;
- //some predefined stuff
- const CACHE_KEY = 'SWITCHSONICDATA';
- const AUTH_KEY = 'SWITCHSONICAUTH';
- const OID_CHECK = '.1.3.6.1.2.1.1.1.0';
- const OID_IFINDEX = '.1.3.6.1.2.1.2.2.1.1';
- const OID_IFDESCR = '.1.3.6.1.2.1.31.1.1.1.18';
- const OID_OCTIN = '.1.3.6.1.2.1.31.1.1.1.6';
- const OID_OCTOUT = '.1.3.6.1.2.1.31.1.1.1.10';
- const OID_STATE = '.1.3.6.1.2.1.2.2.1.8';
- /**
- * Cretes new Sonic instance
- *
- * @param string $ip
- * @param string $community
- */
- public function __construct($ip, $community) {
- $this->setOptions($ip, $community);
- $this->initCache();
- $this->initSnmp();
- // ___------__
- // |\__-- /\ _-
- // |/ __ -
- // //\ / \ /__
- // | o| 0|__ --_
- // \\____-- __ \ ___-
- // (@@ __/ / /_
- // -_____--- --_
- // // \ \\ ___-
- // //|\__/ \\ \
- // \_-\_____/ \-\
- // // \\--\|
- // ____// ||_
- // /_____\ /___\
- }
- /**
- * Sets IP/community to current instance
- *
- * @param string $ip
- * @param string $community
- *
- * @return void
- */
- protected function setOptions($ip, $community) {
- if (!empty($ip)) {
- if (filter_var($ip, FILTER_VALIDATE_IP)) {
- if (!empty($community)) {
- $this->ip = $ip;
- $this->community = $community;
- } else {
- throw new Exception('EX_EMPTY_SNMPCOMMUNITY');
- }
- } else {
- throw new Exception('EX_WRONG_IP');
- }
- } else {
- throw new Exception('EX_EMPTY_IP');
- }
- }
- /**
- * Inits system caching engine
- *
- * @return void
- */
- protected function initCache() {
- $this->cache = new UbillingCache();
- }
- /**
- * Inits SNMP helper instance for further usage
- *
- * @return void
- */
- protected function initSnmp() {
- $this->snmp = new SNMPHelper();
- $this->snmp->setMode('system');
- }
- /**
- * Returns array of available interfaces on device as port=>iface
- *
- * @return array
- */
- protected function getIfaces() {
- return($this->receiveOidData(self::OID_IFINDEX));
- }
- /**
- * Returns available ports description as port=>desc
- *
- * @return array
- */
- protected function getIfDescr() {
- return($this->receiveOidData(self::OID_IFDESCR));
- }
- /**
- * Returns array of interfaces octets in as port=>octets
- *
- * @return array
- */
- protected function getOctIn() {
- return($this->receiveOidData(self::OID_OCTIN));
- }
- /**
- * Returns array of interfaces octets out as port=>octets
- *
- * @return array
- */
- protected function getOctOut() {
- return($this->receiveOidData(self::OID_OCTOUT));
- }
- /**
- * Returns array of interface activity states as port=>state up/down
- *
- * @return array
- */
- protected function getLinks() {
- return($this->receiveOidData(self::OID_STATE));
- }
- /**
- * Checks can we auth on device and receive some data or not?
- *
- * @return bool
- */
- public function checkAuth() {
- $result = false;
- $rawCache = $this->cache->get(self::AUTH_KEY, $this->cachingTimeout);
- if (empty($rawCache)) {
- $rawCache = array();
- }
- if (isset($rawCache[$this->ip])) {
- $result = true;
- } else {
- $checkResult = $this->snmp->walk($this->ip, $this->community, self::OID_CHECK, false);
- if (!empty($checkResult)) {
- $rawCache[$this->ip] = 1;
- $this->cache->set(self::AUTH_KEY, $rawCache, $this->cachingTimeout);
- $result = true;
- }
- }
- return($result);
- }
- /**
- * Returns port/interface ID extracted from left part of OID
- *
- * @param string $rawSnmpData
- * @param string $oid
- *
- * @return string
- */
- protected function extractPortNum($rawSnmpData, $oid) {
- $result = '';
- $removeMask = $oid . '.';
- if (!empty($rawSnmpData)) {
- $result = explode('=', $rawSnmpData);
- $result = trim($result[0]);
- $result = str_replace($removeMask, '', $result);
- }
- return($result);
- }
- /**
- * Returns preprocessed data extracted from OID as port=>value
- *
- * @param string $oid
- *
- * @return array
- */
- protected function receiveOidData($oid) {
- $result = array();
- $raw = $this->snmp->walk($this->ip, $this->community, $oid, false);
- if (!empty($raw)) {
- $raw = explodeRows($raw);
- if (!empty($raw)) {
- foreach ($raw as $io => $each) {
- if (!empty($each)) {
- $portNum = $this->extractPortNum($each, $oid);
- if (!empty($portNum)) {
- $result[$portNum] = zb_SanitizeSNMPValue($each);
- }
- }
- }
- }
- }
- return($result);
- }
- /**
- * Rturns array of preprocessed device stats
- *
- * @return array
- */
- public function getStats() {
- $devStats = array();
- $cachedStats = $this->cache->get(self::CACHE_KEY, $this->cachingTimeout);
- if (empty($cachedStats)) {
- $cachedStats = array();
- }
- //initial filling
- if (!isset($cachedStats[$this->ip])) {
- $devIfindex = $this->getIfaces();
- //interfaces index received?
- if (!empty($devIfindex)) {
- $devPortDesc = $this->getIfDescr();
- $devInOcts = $this->getOctIn();
- $devOutOcts = $this->getOctOut();
- $devLinks = $this->getLinks();
- $pollTime = time();
- $devStats['lasttime'] = $pollTime;
- $devStats['ifaces'] = $devIfindex;
- $devStats['portdescr'] = $devPortDesc;
- $devStats['previn'] = $devInOcts;
- $devStats['prevout'] = $devOutOcts;
- $devStats['links'] = $devLinks;
- foreach ($devOutOcts as $eachOutPort => $eachOutOct) {
- $devStats['speedin'][$eachOutPort] = 0;
- $devStats['speedout'][$eachOutPort] = 0;
- }
- $devStats['speedline'] = array();
- }
- } else {
- $devTmp = $cachedStats[$this->ip];
- $newOctIn = $this->getOctIn();
- $newOctOut = $this->getOctOut();
- $newLinks = $this->getLinks();
- $pollTime = time();
- $timePast = $pollTime - $devTmp['lasttime'];
- $timePast = ($timePast != 0) ? $timePast : 1; //prevent div by zero
- foreach ($newOctIn as $io => $eachIn) {
- $speedIn = ($eachIn - $devTmp['previn'][$io]) / $timePast;
- $rawSpeed = round($speedIn);
- $devTmp['speedin'][$io] = $rawSpeed;
- $devTmp['speedline'][$io]['in'][$pollTime] = $rawSpeed;
- }
- foreach ($newOctOut as $io => $eachOut) {
- $speedOut = ($eachOut - $devTmp['prevout'][$io]) / $timePast;
- $rawSpeed = round($speedOut);
- $devTmp['speedout'][$io] = $rawSpeed;
- $devTmp['speedline'][$io]['out'][$pollTime] = $rawSpeed;
- }
- $devStats['lasttime'] = $pollTime;
- $devStats['ifaces'] = $devTmp['ifaces'];
- $devStats['portdescr'] = $devTmp['portdescr'];
- $devStats['previn'] = $newOctIn;
- $devStats['prevout'] = $newOctOut;
- $devStats['speedin'] = $devTmp['speedin'];
- $devStats['speedout'] = $devTmp['speedout'];
- $devStats['links'] = $newLinks;
- $devStats['speedline'] = $devTmp['speedline'];
- }
- //cache update
- $cachedStats[$this->ip] = $devStats;
- $this->cache->set(self::CACHE_KEY, $cachedStats, $this->cachingTimeout);
- return($devStats);
- }
- /**
- * Converts actual octet counters into human-readable speed value
- *
- * @param int $octets
- *
- * @return string
- */
- protected function convertSpeed($octets) {
- $result = '';
- $bits = $octets * 8;
- $result = $bits;
- if ($bits > $this->offsetKilo) {
- $result = round($bits / $this->offsetKilo) . ' ' . __('Kbit/s');
- }
- if ($bits > $this->offsetMega) {
- $result = round($bits / $this->offsetMega, 1) . ' ' . __('Mbit/s');
- }
- if ($bits > $this->offsetGiga) {
- $result = round($bits / $this->offsetGiga, 1) . ' ' . __('Gbit/s');
- }
- return($result);
- }
- /**
- * Converts octet speed values into Mbit/s
- *
- * @param int $octetSpeed
- *
- * @return float
- */
- protected function speedForCharts($octetSpeed) {
- $result = 0;
- $bits = $octetSpeed * 8;
- $result = $bits / $this->offsetMega;
- $result = round($result, 1);
- return($result);
- }
- /**
- * Converts basic port infor into link state led
- *
- * @param string $linkState
- * @param int $speedIn
- * @param int $speedOut
- *
- * @return string
- */
- protected function convertLinkState($linkState, $speedIn = 0, $speedOut = 0) {
- $result = '';
- $result = (ispos($linkState, 'up')) ? web_green_led() : web_red_led();
- if (ispos($linkState, 'up')) {
- //ok, interface is up
- if ($speedIn OR $speedOut) {
- $result = web_green_led('Active');
- } else {
- $result = web_yellow_led('Link up');
- }
- } else {
- //port is offline at all
- $result = web_red_led('Offline');
- }
- return($result);
- }
- /**
- * Renders device stats
- *
- * @return string
- */
- public function renderSpeeds() {
- $result = '';
- $devStats = $this->getStats();
- if (!empty($devStats)) {
- $ifaces = $devStats['ifaces'];
- $ifdescr = $devStats['portdescr'];
- $prevOut = $devStats['prevout'];
- $cells = wf_tableCell(__('Interface'), '5%');
- $cells .= wf_tableCell(__('Status'), '5%');
- $cells .= wf_tableCell(__('Description'));
- $cells .= wf_tableCell(__('Speed') . ' ' . __('TX'));
- $cells .= wf_tableCell(__('Speed') . ' ' . __('RX'));
- $cells .= wf_tableCell(__('Bytes TX'));
- $cells .= wf_tableCell(__('Bytes RX'));
- $rows = wf_tableRow($cells, 'row1');
- foreach ($prevOut as $portNum => $eachPrevOut) {
- $speedIn = $devStats['speedin'][$portNum];
- $speedOut = $devStats['speedout'][$portNum];
- $cells = wf_tableCell($ifaces[$portNum]);
- $cells .= wf_tableCell($this->convertLinkState($devStats['links'][$portNum], $speedIn, $speedOut));
- $descrLabel = (isset($ifdescr[$portNum])) ? $ifdescr[$portNum] : '';
- $cells .= wf_tableCell($descrLabel);
- $cells .= wf_tableCell($this->convertSpeed($speedIn));
- $cells .= wf_tableCell($this->convertSpeed($speedOut));
- $cells .= wf_tableCell(stg_convert_size($devStats['previn'][$portNum]));
- $cells .= wf_tableCell(stg_convert_size($devStats['prevout'][$portNum]));
- $rows .= wf_tableRow($cells, 'row5');
- }
- $result .= wf_tableBody($rows, '100%');
- } else {
- $messages = new UbillingMessageHelper();
- $result .= $messages->getStyledMessage(__('Nothing to show'), 'warning');
- }
- return($result);
- }
- /**
- * Renders charts based on speedline of some ports
- *
- * @return string
- */
- public function renderCharts() {
- $result = '';
- $devStats = $this->getStats();
- if (!empty($devStats)) {
- $ifaces = $devStats['ifaces'];
- $ifdescr = $devStats['portdescr'];
- $prevOut = $devStats['prevout'];
- $speedLine = $devStats['speedline'];
- $options = '';
- if (!empty($speedLine)) {
- foreach ($speedLine as $portNum => $speedData) {
- $csvData = '';
- $portLabel = __('Interface') . ' ' . $portNum;
- if (isset($ifdescr[$portNum])) {
- $portDescr = $ifdescr[$portNum];
- if (!empty($portDescr)) {
- $portLabel .= ' - ' . $portDescr;
- }
- foreach ($speedData['in'] as $timeIn => $speedIn) {
- $timeLabel = date("Y-m-d H:i:s", $timeIn);
- $speedOut = $speedData['out'][$timeIn];
- if ($speedIn OR $speedOut) {
- $curTime = time();
- if (($timeIn) > ($curTime - $this->timeWindow)) {
- $inLabel = $this->speedForCharts($speedIn);
- $outLabel = $this->speedForCharts($speedOut);
- $csvData .= $timeLabel . ',' . $inLabel . ',' . $outLabel . PHP_EOL;
- }
- }
- }
- }
- if (!empty($csvData)) {
- $result .= wf_Graph($csvData, '100%', '200px;', false, $portLabel, __('Time'), __('Mbit/s'), false);
- }
- }
- } else {
- $messages = new UbillingMessageHelper();
- $result .= $messages->getStyledMessage(__('Nothing to show') . '. ' . __('Collecting data') . '...', 'warning');
- }
- }
- return($result);
- }
- }
|