# Copyright (C) 2002 Stanislav Sinyagin # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. # $Id: CiscoIOS_SAA.pm,v 1.1 2010-12-27 00:03:50 ivan Exp $ # Stanislav Sinyagin # Cisco IOS Service Assurance Agent # TODO: # should really consider rtt-type and rtt-echo-protocol when applying # per-rtt templates # # translate TOS bits into DSCP values package Torrus::DevDiscover::CiscoIOS_SAA; use strict; use Socket qw(inet_ntoa); use Torrus::Log; $Torrus::DevDiscover::registry{'CiscoIOS_SAA'} = { 'sequence' => 510, 'checkdevtype' => \&checkdevtype, 'discover' => \&discover, 'buildConfig' => \&buildConfig }; our %oiddef = ( # CISCO-RTTMON-MIB 'rttMonCtrlAdminTable' => '1.3.6.1.4.1.9.9.42.1.2.1', 'rttMonCtrlAdminOwner' => '1.3.6.1.4.1.9.9.42.1.2.1.1.2', 'rttMonCtrlAdminTag' => '1.3.6.1.4.1.9.9.42.1.2.1.1.3', 'rttMonCtrlAdminRttType' => '1.3.6.1.4.1.9.9.42.1.2.1.1.4', 'rttMonCtrlAdminFrequency' => '1.3.6.1.4.1.9.9.42.1.2.1.1.6', 'rttMonCtrlAdminStatus' => '1.3.6.1.4.1.9.9.42.1.2.1.1.9', 'rttMonEchoAdminTable' => '1.3.6.1.4.1.9.9.42.1.2.2', 'rttMonEchoAdminProtocol' => '1.3.6.1.4.1.9.9.42.1.2.2.1.1', 'rttMonEchoAdminTargetAddress' => '1.3.6.1.4.1.9.9.42.1.2.2.1.2', 'rttMonEchoAdminPktDataRequestSize' => '1.3.6.1.4.1.9.9.42.1.2.2.1.3', 'rttMonEchoAdminTargetPort' => '1.3.6.1.4.1.9.9.42.1.2.2.1.5', 'rttMonEchoAdminTOS' => '1.3.6.1.4.1.9.9.42.1.2.2.1.9', 'rttMonEchoAdminTargetAddressString' => '1.3.6.1.4.1.9.9.42.1.2.2.1.11', 'rttMonEchoAdminNameServer' => '1.3.6.1.4.1.9.9.42.1.2.2.1.12', 'rttMonEchoAdminURL' => '1.3.6.1.4.1.9.9.42.1.2.2.1.15', 'rttMonEchoAdminInterval' => '1.3.6.1.4.1.9.9.42.1.2.2.1.17', 'rttMonEchoAdminNumPackets' => '1.3.6.1.4.1.9.9.42.1.2.2.1.18' ); our %adminInterpret = ( 'rttMonCtrlAdminOwner' => { 'order' => 10, 'legend' => 'Owner: %s;', 'param' => 'rtt-owner' }, 'rttMonCtrlAdminTag' => { 'order' => 20, 'legend' => 'Tag: %s;', 'comment' => '%s: ', 'param' => 'rtt-tag' }, 'rttMonCtrlAdminRttType' => { 'order' => 30, 'legend' => 'Type: %s;', 'translate' => \&translateRttType, 'param' => 'rtt-type' }, 'rttMonCtrlAdminFrequency' => { 'order' => 40, 'legend' => 'Frequency: %d seconds;', 'param' => 'rtt-frequency' }, 'rttMonEchoAdminProtocol' => { 'order' => 50, 'legend' => 'Protocol: %s;', 'translate' => \&translateRttEchoProtocol, 'param' => 'rtt-echo-protocol' }, 'rttMonEchoAdminTargetAddress' => { 'order' => 60, 'legend' => 'Target: %s;', 'comment' => 'Target=%s ', 'translate' => \&translateRttTargetAddr, 'param' => 'rtt-echo-target-addr', 'ignore-text' => '0.0.0.0' }, 'rttMonEchoAdminPktDataRequestSize' => { 'order' => 70, 'legend' => 'Packet size: %d octets;', 'param' => 'rtt-echo-request-size' }, 'rttMonEchoAdminTargetPort' => { 'order' => 80, 'legend' => 'Port: %d;', 'param' => 'rtt-echo-port', 'ignore-numeric' => 0 }, 'rttMonEchoAdminTOS' => { 'order' => 90, 'legend' => 'TOS: %d;', 'comment' => 'TOS=%d ', 'param' => 'rtt-echo-tos', 'ignore-numeric' => 0 }, 'rttMonEchoAdminTargetAddressString' => { 'order' => 100, 'legend' => 'Address string: %s;', 'param' => 'rtt-echo-addr-string' }, 'rttMonEchoAdminNameServer' => { 'order' => 110, 'legend' => 'NameServer: %s;', 'translate' => \&translateRttTargetAddr, 'param' => 'rtt-echo-name-server', 'ignore-text' => '0.0.0.0' }, 'rttMonEchoAdminURL' => { 'order' => 120, 'legend' => 'URL: %s;', 'param' => 'rtt-echo-url' }, 'rttMonEchoAdminInterval' => { 'order' => 130, 'legend' => 'Interval: %d milliseconds;', 'param' => 'rtt-echo-interval', 'ignore-numeric' => 0 }, 'rttMonEchoAdminNumPackets' => { 'order' => 140, 'legend' => 'Packets: %d;', 'param' => 'rtt-echo-num-packets', 'ignore-numeric' => 0 } ); sub checkdevtype { my $dd = shift; my $devdetails = shift; my $session = $dd->session(); if( $devdetails->isDevType('CiscoIOS') ) { my $rttAdminTable = $session->get_table( -baseoid => $dd->oiddef('rttMonCtrlAdminTable') ); if( defined $rttAdminTable and scalar( %{$rttAdminTable} ) > 0 ) { $devdetails->storeSnmpVars( $rttAdminTable ); return 1; } } return 0; } sub discover { my $dd = shift; my $devdetails = shift; my $session = $dd->session(); my $data = $devdetails->data(); my $rttEchoAdminTable = $session->get_table( -baseoid => $dd->oiddef('rttMonEchoAdminTable') ); if( defined $rttEchoAdminTable ) { $devdetails->storeSnmpVars( $rttEchoAdminTable ); undef $rttEchoAdminTable; } $data->{'rtt_entries'} = {}; foreach my $rttIndex ( $devdetails->getSnmpIndices( $dd->oiddef('rttMonCtrlAdminOwner') ) ) { # we're interested in Active agents only if( $devdetails->snmpVar($dd->oiddef('rttMonCtrlAdminStatus') . '.' . $rttIndex) != 1 ) { next; } my $ref = {}; $data->{'rtt_entries'}{$rttIndex} = $ref; $ref->{'param'} = {}; my $comment = ''; my $legend = ''; foreach my $adminField ( sort {$adminInterpret{$a}{'order'} <=> $adminInterpret{$b}{'order'}} keys %adminInterpret ) { my $value = $devdetails->snmpVar( $dd->oiddef( $adminField ) . '.' . $rttIndex ); if( defined( $value ) and length( $value ) > 0 ) { my $intrp = $adminInterpret{$adminField}; if( ref( $intrp->{'translate'} ) ) { $value = &{$intrp->{'translate'}}( $value ); } if( ( defined( $intrp->{'ignore-numeric'} ) and $value == $intrp->{'ignore-numeric'} ) or ( defined( $intrp->{'ignore-text'} ) and $value eq $intrp->{'ignore-text'} ) ) { next; } if( defined( $intrp->{'param'} ) ) { $ref->{'param'}{$intrp->{'param'}} = $value; } if( defined( $intrp->{'comment'} ) ) { $comment .= sprintf( $intrp->{'comment'}, $value ); } if( defined( $intrp->{'legend'} ) ) { $legend .= sprintf( $intrp->{'legend'}, $value ); } } } $ref->{'param'}{'rtt-index'} = $rttIndex; $ref->{'param'}{'comment'} = $comment; $ref->{'param'}{'legend'} = $legend; } return 1; } sub buildConfig { my $devdetails = shift; my $cb = shift; my $devNode = shift; my $data = $devdetails->data(); my $subtreeNode = $cb->addSubtree( $devNode, 'SAA', undef, ['CiscoIOS_SAA::cisco-saa-subtree']); foreach my $rttIndex ( sort {$a<=>$b} keys %{$data->{'rtt_entries'}} ) { my $subtreeName = 'rtt_' . $rttIndex; my $param = $data->{'rtt_entries'}{$rttIndex}{'param'}; $param->{'precedence'} = sprintf('%d', 10000 - $rttIndex); # TODO: should really consider rtt-type and rtt-echo-protocol $cb->addSubtree( $subtreeNode, $subtreeName, $param, ['CiscoIOS_SAA::cisco-rtt-echo-subtree']); } } our %rttType = ( '1' => 'echo', '2' => 'pathEcho', '3' => 'fileIO', '4' => 'script', '5' => 'udpEcho', '6' => 'tcpConnect', '7' => 'http', '8' => 'dns', '9' => 'jitter', '10' => 'dlsw', '11' => 'dhcp', '12' => 'ftp' ); sub translateRttType { my $value = shift; return $rttType{$value}; } our %rttEchoProtocol = ( '1' => 'notApplicable', '2' => 'ipIcmpEcho', '3' => 'ipUdpEchoAppl', '4' => 'snaRUEcho', '5' => 'snaLU0EchoAppl', '6' => 'snaLU2EchoAppl', '7' => 'snaLU62Echo', '8' => 'snaLU62EchoAppl', '9' => 'appleTalkEcho', '10' => 'appleTalkEchoAppl', '11' => 'decNetEcho', '12' => 'decNetEchoAppl', '13' => 'ipxEcho', '14' => 'ipxEchoAppl', '15' => 'isoClnsEcho', '16' => 'isoClnsEchoAppl', '17' => 'vinesEcho', '18' => 'vinesEchoAppl', '19' => 'xnsEcho', '20' => 'xnsEchoAppl', '21' => 'apolloEcho', '22' => 'apolloEchoAppl', '23' => 'netbiosEchoAppl', '24' => 'ipTcpConn', '25' => 'httpAppl', '26' => 'dnsAppl', '27' => 'jitterAppl', '28' => 'dlswAppl', '29' => 'dhcpAppl', '30' => 'ftpAppl' ); sub translateRttEchoProtocol { my $value = shift; return $rttEchoProtocol{$value}; } sub translateRttTargetAddr { my $value = shift; $value =~ s/^0x//; return inet_ntoa( pack( 'H8', $value ) ); } 1; # Local Variables: # mode: perl # indent-tabs-mode: nil # perl-indent-level: 4 # End: