summaryrefslogtreecommitdiff
path: root/torrus/perllib/Torrus/DevDiscover/CiscoIOS.pm
diff options
context:
space:
mode:
Diffstat (limited to 'torrus/perllib/Torrus/DevDiscover/CiscoIOS.pm')
-rw-r--r--torrus/perllib/Torrus/DevDiscover/CiscoIOS.pm687
1 files changed, 687 insertions, 0 deletions
diff --git a/torrus/perllib/Torrus/DevDiscover/CiscoIOS.pm b/torrus/perllib/Torrus/DevDiscover/CiscoIOS.pm
new file mode 100644
index 000000000..6bd6d91c2
--- /dev/null
+++ b/torrus/perllib/Torrus/DevDiscover/CiscoIOS.pm
@@ -0,0 +1,687 @@
+# 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.pm,v 1.1 2010-12-27 00:03:47 ivan Exp $
+# Stanislav Sinyagin <ssinyagin@yahoo.com>
+
+# Cisco IOS devices discovery
+# To do:
+# SA Agent MIB
+# DiffServ MIB
+
+package Torrus::DevDiscover::CiscoIOS;
+
+use strict;
+use Torrus::Log;
+
+
+$Torrus::DevDiscover::registry{'CiscoIOS'} = {
+ 'sequence' => 500,
+ 'checkdevtype' => \&checkdevtype,
+ 'discover' => \&discover,
+ 'buildConfig' => \&buildConfig
+ };
+
+
+our %oiddef =
+ (
+ # CISCO-SMI
+ 'ciscoProducts' => '1.3.6.1.4.1.9.1',
+ # CISCO-PRODUCTS-MIB
+ 'ciscoLS1010' => '1.3.6.1.4.1.9.1.107',
+ # CISCO-IMAGE-MIB
+ 'ciscoImageTable' => '1.3.6.1.4.1.9.9.25.1.1',
+ # CISCO-ENHANCED-IMAGE-MIB
+ 'ceImageTable' => '1.3.6.1.4.1.9.9.249.1.1.1',
+ # OLD-CISCO-MEMORY-MIB
+ 'bufferElFree' => '1.3.6.1.4.1.9.2.1.9.0',
+ # CISCO-IPSEC-FLOW-MONITOR-MIB
+ 'cipSecGlobalHcInOctets' => '1.3.6.1.4.1.9.9.171.1.3.1.4.0',
+ # CISCO-BGP4-MIB
+ 'cbgpPeerAddrFamilyName' => '1.3.6.1.4.1.9.9.187.1.2.3.1.3',
+ 'cbgpPeerAcceptedPrefixes' => '1.3.6.1.4.1.9.9.187.1.2.4.1.1',
+ 'cbgpPeerPrefixAdminLimit' => '1.3.6.1.4.1.9.9.187.1.2.4.1.3',
+ # CISCO-CAR-MIB
+ 'ccarConfigTable' => '1.3.6.1.4.1.9.9.113.1.1.1',
+ 'ccarConfigType' => '1.3.6.1.4.1.9.9.113.1.1.1.1.3',
+ 'ccarConfigAccIdx' => '1.3.6.1.4.1.9.9.113.1.1.1.1.4',
+ 'ccarConfigRate' => '1.3.6.1.4.1.9.9.113.1.1.1.1.5',
+ 'ccarConfigLimit' => '1.3.6.1.4.1.9.9.113.1.1.1.1.6',
+ 'ccarConfigExtLimit' => '1.3.6.1.4.1.9.9.113.1.1.1.1.7',
+ 'ccarConfigConformAction' => '1.3.6.1.4.1.9.9.113.1.1.1.1.8',
+ 'ccarConfigExceedAction' => '1.3.6.1.4.1.9.9.113.1.1.1.1.9',
+ # CISCO-VPDN-MGMT-MIB
+ 'cvpdnSystemTunnelTotal' => '1.3.6.1.4.1.9.10.24.1.1.4.1.2'
+ );
+
+
+# Not all interfaces are normally needed to monitor.
+# You may override the interface filtering in devdiscover-siteconfig.pl:
+# redefine $Torrus::DevDiscover::CiscoIOS::interfaceFilter
+# or define $Torrus::DevDiscover::CiscoIOS::interfaceFilterOverlay
+
+our $interfaceFilter;
+our $interfaceFilterOverlay;
+my %ciscoInterfaceFilter;
+
+if( not defined( $interfaceFilter ) )
+{
+ $interfaceFilter = \%ciscoInterfaceFilter;
+}
+
+
+# Key is some unique symbolic name, does not mean anything
+# ifType is the number to match the interface type
+# ifDescr is the regexp to match the interface description
+%ciscoInterfaceFilter =
+ (
+ 'Null0' => {
+ 'ifType' => 1, # other
+ 'ifDescr' => '^Null'
+ },
+
+ 'E1 N/N/N' => {
+ 'ifType' => 18, # ds1
+ 'ifDescr' => '^E1'
+ },
+
+ 'Virtual-AccessN' => {
+ 'ifType' => 23, # ppp
+ 'ifDescr' => '^Virtual-Access'
+ },
+
+ 'DialerN' => {
+ 'ifType' => 23, # ppp
+ 'ifDescr' => '^Dialer'
+ },
+
+ 'LoopbackN' => {
+ 'ifType' => 24, # softwareLoopback
+ 'ifDescr' => '^Loopback'
+ },
+
+ 'SerialN:N-Bearer Channel' => {
+ 'ifType' => 81, # ds0, Digital Signal Level 0
+ 'ifDescr' => '^Serial.*Bearer\s+Channel'
+ },
+
+ 'Voice Encapsulation (POTS) Peer: N' => {
+ 'ifType' => 103 # voiceEncap
+ },
+
+ 'Voice Over IP Peer: N' => {
+ 'ifType' => 104 # voiceOverIp
+ },
+
+ 'ATMN/N/N.N-atm subif' => {
+ 'ifType' => 134, # atmSubInterface
+ 'ifDescr' => '^ATM[0-9\/]+\.[0-9]+\s+subif'
+ },
+
+ 'BundleN' => {
+ 'ifType' => 127, # docsCableMaclayer
+ 'ifDescr' => '^Bundle'
+ },
+
+ 'EOBCN/N' => {
+ 'ifType' => 53, # propVirtual
+ 'ifDescr' => '^EOBC'
+ },
+
+ 'FIFON/N' => {
+ 'ifType' => 53, # propVirtual
+ 'ifDescr' => '^FIFO'
+ },
+ );
+
+our %tunnelType =
+ (
+ # CISCO-VPDN-MGMT-MIB Tunnel Types
+ '1' => 'L2F',
+ '2' => 'L2TP',
+ '3' => 'PPTP'
+ );
+
+
+sub checkdevtype
+{
+ my $dd = shift;
+ my $devdetails = shift;
+
+ if( not $dd->oidBaseMatch
+ ( 'ciscoProducts',
+ $devdetails->snmpVar( $dd->oiddef('sysObjectID') ) ) )
+ {
+ return 0;
+ }
+
+ my $session = $dd->session();
+ if( not $dd->checkSnmpTable('ciscoImageTable') )
+ {
+ if( $dd->checkSnmpTable('ceImageTable') )
+ {
+ # IOS XR has a new MIB for software image management
+ $devdetails->setCap('CiscoIOSXR');
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ # On some Layer3 switching devices, VlanXXX interfaces give some
+ # useful stats, while on others the stats are not relevant at all
+
+ if( $devdetails->param('CiscoIOS::enable-vlan-interfaces') ne 'yes' )
+ {
+ $interfaceFilter->{'VlanN'} = {
+ 'ifType' => 53, # propVirtual
+ 'ifDescr' => '^Vlan\d+'
+ };
+ }
+
+ # same thing with unrouted VLAN interfaces
+ if( $devdetails->param('CiscoIOS::enable-unrouted-vlan-interfaces')
+ ne 'yes' )
+ {
+ $interfaceFilter->{'unrouted VLAN N'} => {
+ 'ifType' => 53, # propVirtual
+ 'ifDescr' => '^unrouted\s+VLAN\s+\d+'
+ };
+ }
+
+ &Torrus::DevDiscover::RFC2863_IF_MIB::addInterfaceFilter
+ ($devdetails, $interfaceFilter);
+
+ if( defined( $interfaceFilterOverlay ) )
+ {
+ &Torrus::DevDiscover::RFC2863_IF_MIB::addInterfaceFilter
+ ($devdetails, $interfaceFilterOverlay);
+ }
+
+ $devdetails->setCap('interfaceIndexingManaged');
+
+ return 1;
+}
+
+
+my %ccarConfigType =
+ ( 1 => 'all',
+ 2 => 'quickAcc',
+ 3 => 'standardAcc' );
+
+my %ccarAction =
+ ( 1 => 'drop',
+ 2 => 'xmit',
+ 3 => 'continue',
+ 4 => 'precedXmit',
+ 5 => 'precedCont' );
+
+
+
+sub discover
+{
+ my $dd = shift;
+ my $devdetails = shift;
+
+ my $session = $dd->session();
+ my $data = $devdetails->data();
+
+ # Old mkroutercfg used cisco-interface-counters
+ if( $Torrus::DevDiscover::CiscoIOS::useCiscoInterfaceCounters )
+ {
+ foreach my $interface ( values %{$data->{'interfaces'}} )
+ {
+ $interface->{'hasHCOctets'} = 0;
+ $interface->{'hasOctets'} = 0;
+ push( @{$interface->{'templates'}},
+ 'CiscoIOS::cisco-interface-counters' );
+ }
+ }
+ else
+ {
+ # This is a well-known bug in IOS: HC counters are implemented,
+ # but always zero. We can catch this only for active interfaces.
+
+ foreach my $ifIndex ( sort {$a<=>$b} keys %{$data->{'interfaces'}} )
+ {
+ my $interface = $data->{'interfaces'}{$ifIndex};
+
+ if( $interface->{'hasHCOctets'} and
+ ( (
+ $devdetails->snmpVar( $dd->oiddef('ifHCInOctets')
+ . '.' . $ifIndex ) == 0 and
+ $devdetails->snmpVar( $dd->oiddef('ifInOctets')
+ . '.' . $ifIndex ) > 0
+ )
+ or
+ (
+ $devdetails->snmpVar( $dd->oiddef('ifHCOutOctets')
+ . '.' . $ifIndex ) == 0 and
+ $devdetails->snmpVar( $dd->oiddef('ifOutOctets')
+ . '.' . $ifIndex ) > 0
+ ) ) )
+ {
+ Debug('Disabling HC octets for ' . $ifIndex . ': ' .
+ $interface->{'ifDescr'});
+
+ $interface->{'hasHCOctets'} = 0;
+ $interface->{'hasHCUcastPkts'} = 0;
+ }
+ }
+ }
+
+ if( $devdetails->param('CiscoIOS::enable-membuf-stats') eq 'yes' )
+ {
+ # Old Memory Buffers, if we have bufferElFree we assume
+ # the rest as they are "required"
+
+ if( $dd->checkSnmpOID('bufferElFree') )
+ {
+ $devdetails->setCap('old-ciscoMemoryBuffers');
+ push( @{$data->{'templates'}},
+ 'CiscoIOS::old-cisco-memory-buffers' );
+ }
+ }
+
+ if( $devdetails->param('CiscoIOS::disable-ipsec-stats') ne 'yes' )
+ {
+ if( $dd->checkSnmpOID('cipSecGlobalHcInOctets') )
+ {
+ $devdetails->setCap('ciscoIPSecGlobalStats');
+ push( @{$data->{'templates'}},
+ 'CiscoIOS::cisco-ipsec-flow-globals' );
+ }
+
+ if( $dd->oidBaseMatch
+ ( 'ciscoLS1010',
+ $devdetails->snmpVar( $dd->oiddef('sysObjectID') ) ) )
+ {
+ $data->{'param'}{'snmp-oids-per-pdu'} = 10;
+ }
+ }
+
+ if( $devdetails->param('CiscoIOS::disable-bgp-stats') ne 'yes' )
+ {
+ my $peerTable =
+ $session->get_table( -baseoid =>
+ $dd->oiddef('cbgpPeerAcceptedPrefixes') );
+ if( defined( $peerTable ) and scalar( %{$peerTable} ) > 0 )
+ {
+ $devdetails->storeSnmpVars( $peerTable );
+ $devdetails->setCap('CiscoBGP');
+
+ my $limitsTable =
+ $session->get_table( -baseoid =>
+ $dd->oiddef('cbgpPeerPrefixAdminLimit') );
+ $limitsTable = {} if not defined( $limitsTable );
+
+ $data->{'cbgpPeers'} = {};
+
+ # retrieve AS numbers for neighbor peers
+ Torrus::DevDiscover::RFC1657_BGP4_MIB::discover($dd, $devdetails);
+
+ # list of indices for peers that are not IPv4 Unicast
+ my @nonV4Unicast;
+
+ # Number of peers for each AS
+ my %asNumbers;
+
+ foreach my $INDEX
+ ( $devdetails->
+ getSnmpIndices( $dd->oiddef('cbgpPeerAcceptedPrefixes') ) )
+ {
+ my ($a1, $a2, $a3, $a4, $afi, $safi) = split(/\./, $INDEX);
+ my $peerIP = join('.', $a1, $a2, $a3, $a4);
+
+ my $peer = {
+ 'peerIP' => $peerIP,
+ 'addrFamily' => 'IPv4 Unicast'
+ };
+
+ if( $afi != 1 and $safi != 1 )
+ {
+ push( @nonV4Unicast, $INDEX );
+ }
+
+ my $desc =
+ $devdetails->param('peer-ipaddr-description-' .
+ join('_', split('\.', $peerIP)));
+ if( length( $desc ) > 0 )
+ {
+ $peer->{'description'} = $desc;
+ }
+
+ my $peerAS = $data->{'bgpPeerAS'}{$peerIP};
+ if( defined( $peerAS ) )
+ {
+ $peer->{'peerAS'} = $data->{'bgpPeerAS'}{$peerIP};
+ $asNumbers{$peer->{'peerAS'}}++;
+
+ my $desc =
+ $devdetails->param('bgp-as-description-' . $peerAS);
+ if( length( $desc ) > 0 )
+ {
+ if( defined( $peer->{'description'} ) )
+ {
+ Warn('Conflicting descriptions for peer ' .
+ $peerIP);
+ }
+ $peer->{'description'} = $desc;
+ }
+ }
+ else
+ {
+ Error('Cannot find AS number for BGP peer ' . $peerIP);
+ next;
+ }
+
+ if( defined( $peer->{'description'} ) )
+ {
+ $peer->{'description'} .= ' ';
+ }
+ $peer->{'description'} .= '[' . $peerIP . ']';
+
+ $peer->{'prefixLimit'} =
+ $limitsTable->{$dd->oiddef('cbgpPeerPrefixAdminLimit') .
+ '.' . $INDEX};
+
+ $data->{'cbgpPeers'}{$INDEX} = $peer;
+ }
+
+ if( scalar( @nonV4Unicast ) > 0 )
+ {
+ my $addrFamTable =
+ $session->get_table
+ ( -baseoid => $dd->oiddef('cbgpPeerAddrFamilyName') );
+
+ foreach my $INDEX ( @nonV4Unicast )
+ {
+ my $peer = $data->{'cbgpPeers'}{$INDEX};
+
+ my $fam = $addrFamTable->{
+ $dd->oiddef('cbgpPeerAddrFamilyName') .
+ '.' . $INDEX};
+
+ $peer->{'addrFamily'} = $fam;
+ $peer->{'otherAddrFamily'} = 1;
+ $peer->{'description'} .= ' ' . $fam;
+ }
+ }
+
+ # Construct the subtree names from AS, peer IP, and address
+ # family
+ foreach my $INDEX ( keys %{$data->{'cbgpPeers'}} )
+ {
+ my $peer = $data->{'cbgpPeers'}{$INDEX};
+
+ my $subtreeName = 'AS' . $peer->{'peerAS'};
+ if( $asNumbers{$peer->{'peerAS'}} > 1 )
+ {
+ $subtreeName .= '_' . $peer->{'peerIP'};
+ }
+
+ if( $peer->{'otherAddrFamily'} )
+ {
+ my $fam = $data->{'cbgpPeers'}{$INDEX}{'addrFamily'};
+ $fam =~ s/\W/_/g;
+ $subtreeName .= '_' . $fam;
+ }
+
+ $peer->{'subtreeName'} = $subtreeName;
+ }
+ }
+ }
+
+
+ if( $devdetails->param('CiscoIOS::disable-car-stats') ne 'yes' )
+ {
+ my $carTable =
+ $session->get_table( -baseoid =>
+ $dd->oiddef('ccarConfigTable') );
+ if( defined( $carTable ) and scalar( %{$carTable} ) > 0 )
+ {
+ $devdetails->storeSnmpVars( $carTable );
+ $devdetails->setCap('CiscoCAR');
+
+ $data->{'ccar'} = {};
+
+ foreach my $INDEX
+ ( $devdetails->
+ getSnmpIndices( $dd->oiddef('ccarConfigType') ) )
+ {
+ my ($ifIndex, $dir, $carIndex) = split(/\./, $INDEX);
+ my $interface = $data->{'interfaces'}{$ifIndex};
+
+ my $car = {
+ 'ifIndex' => $ifIndex,
+ 'direction' => $dir,
+ 'carIndex' => $carIndex };
+
+ $car->{'configType'} =
+ $ccarConfigType{ $carTable->{$dd->oiddef
+ ('ccarConfigType') .
+ '.' . $INDEX} };
+
+ $car->{'accIdx'} = $carTable->{$dd->oiddef
+ ('ccarConfigAccIdx') .
+ '.' . $INDEX};
+
+ $car->{'rate'} = $carTable->{$dd->oiddef
+ ('ccarConfigRate') .
+ '.' . $INDEX};
+
+
+ $car->{'limit'} = $carTable->{$dd->oiddef
+ ('ccarConfigLimit') .
+ '.' . $INDEX};
+
+ $car->{'extLimit'} = $carTable->{$dd->oiddef
+ ('ccarConfigExtLimit') .
+ '.' . $INDEX};
+ $car->{'conformAction'} =
+ $ccarAction{ $carTable->{$dd->oiddef
+ ('ccarConfigConformAction') .
+ '.' . $INDEX} };
+
+ $car->{'exceedAction'} =
+ $ccarAction{ $carTable->{$dd->oiddef
+ ('ccarConfigExceedAction') .
+ '.' . $INDEX} };
+
+ $data->{'ccar'}{$INDEX} = $car;
+ }
+ }
+ }
+
+
+ if( $devdetails->param('CiscoIOS::disable-vpdn-stats') ne 'yes' )
+ {
+ if( $dd->checkSnmpTable( 'cvpdnSystemTunnelTotal' ) )
+ {
+ # Find the Tunnel type
+ my $tableTun = $session->get_table(
+ -baseoid => $dd->oiddef('cvpdnSystemTunnelTotal') );
+
+ if( $tableTun )
+ {
+ $devdetails->setCap('ciscoVPDN');
+
+ $devdetails->storeSnmpVars( $tableTun );
+
+ # VPDN indexing: 1: l2f, 2: l2tp, 3: pptp
+ foreach my $typeIndex (
+ $devdetails->getSnmpIndices(
+ $dd->oiddef('cvpdnSystemTunnelTotal') ) )
+ {
+ Debug("CISCO-VPDN-MGMT-MIB: found Tunnel type " .
+ $tunnelType{$typeIndex} );
+
+ $data->{'ciscoVPDN'}{$typeIndex} = $tunnelType{$typeIndex};
+ }
+ }
+ }
+ }
+
+ if( $devdetails->param('CiscoIOS::short-device-comment') eq 'yes' )
+ {
+ # Remove serials from device comment
+ # 1841 chassis, Hw Serial#: 3625140487, Hw Revision: 6.0
+
+ $data->{'param'}{'comment'} =~ s/, Hw.*//o;
+ }
+
+ return 1;
+}
+
+
+sub buildConfig
+{
+ my $devdetails = shift;
+ my $cb = shift;
+ my $devNode = shift;
+
+ my $data = $devdetails->data();
+
+ if( $devdetails->hasCap('CiscoBGP') )
+ {
+ my $countersNode =
+ $cb->addSubtree( $devNode, 'BGP_Prefixes',
+ {
+ 'node-display-name' => 'BGP Prefixes',
+ 'comment' => 'Accepted prefixes',
+ } );
+
+ foreach my $INDEX ( sort
+ { $data->{'cbgpPeers'}{$a}{'subtreeName'} <=>
+ $data->{'cbgpPeers'}{$b}{'subtreeName'} }
+ keys %{$data->{'cbgpPeers'}} )
+ {
+ my $peer = $data->{'cbgpPeers'}{$INDEX};
+
+ my $param = {
+ 'peer-index' => $INDEX,
+ 'peer-ipaddr' => $peer->{'peerIP'},
+ 'comment' => $peer->{'description'},
+ 'descriptive-nickname' => $peer->{'subtreeName'},
+ 'precedence' => 65000 - $peer->{'peerAS'}
+ };
+
+ if( defined( $peer->{'prefixLimit'} ) and
+ $peer->{'prefixLimit'} > 0 )
+ {
+ $param->{'upper-limit'} = $peer->{'prefixLimit'};
+ $param->{'graph-upper-limit'} = $peer->{'prefixLimit'} * 1.03;
+ }
+
+ $cb->addLeaf
+ ( $countersNode, $peer->{'subtreeName'}, $param,
+ ['CiscoIOS::cisco-bgp'] );
+ }
+ }
+
+
+ if( $devdetails->hasCap('CiscoCAR') )
+ {
+ my $countersNode =
+ $cb->addSubtree( $devNode, 'CAR_Stats', {
+ 'comment' => 'Committed Access Rate statistics',
+ 'node-display-name' => 'CAR', },
+ ['CiscoIOS::cisco-car-subtree']);
+
+ foreach my $INDEX ( sort keys %{$data->{'ccar'}} )
+ {
+ my $car = $data->{'ccar'}{$INDEX};
+ my $interface = $data->{'interfaces'}{$car->{'ifIndex'}};
+
+ my $subtreeName =
+ $interface->{$data->{'nameref'}{'ifSubtreeName'}};
+
+ $subtreeName .= ($car->{'direction'} == 1) ? '_IN':'_OUT';
+ if( $car->{'carIndex'} > 1 )
+ {
+ $subtreeName .= '_' . $car->{'carIndex'};
+ }
+
+ my $param = {
+ 'searchable' => 'yes',
+ 'car-direction' => $car->{'direction'},
+ 'car-index' => $car->{'carIndex'} };
+
+ $param->{'interface-name'} =
+ $interface->{'param'}{'interface-name'};
+ $param->{'interface-nick'} =
+ $interface->{'param'}{'interface-nick'};
+ $param->{'comment'} =
+ $interface->{'param'}{'comment'};
+
+ my $legend = sprintf("Type: %s;", $car->{'configType'});
+ if( $car->{'accIdx'} > 0 )
+ {
+ $legend .= sprintf("Access list: %d;", $car->{'accIdx'});
+ }
+
+ $legend .=
+ sprintf("Rate: %d bps; Limit: %d bytes; Ext limit: %d bytes;" .
+ "Conform action: %s; Exceed action: %s",
+ $car->{'rate'},
+ $car->{'limit'},
+ $car->{'extLimit'},
+ $car->{'conformAction'},
+ $car->{'exceedAction'});
+
+ $param->{'legend'} = $legend;
+
+ $cb->addSubtree
+ ( $countersNode,
+ $subtreeName,
+ $param,
+ ['CiscoIOS::cisco-car']);
+ }
+ }
+
+
+ if( $devdetails->hasCap('ciscoVPDN') )
+ {
+ my $tunnelNode = $cb->addSubtree
+ ( $devNode, 'VPDN_Statistics',
+ {'node-display-name' => 'VPDN Statistics'},
+ [ 'CiscoIOS::cisco-vpdn-subtree' ] );
+
+ foreach my $INDEX ( sort keys %{$data->{'ciscoVPDN'}} )
+ {
+ my $tunnelProtocol = $data->{'ciscoVPDN'}{$INDEX};
+
+ $cb->addSubtree( $tunnelNode, $tunnelProtocol,
+ { 'comment' => $tunnelProtocol . ' information',
+ 'tunIndex' => $INDEX,
+ 'tunFile' => lc($tunnelProtocol) },
+ [ 'CiscoIOS::cisco-vpdn-leaf' ] );
+ }
+ }
+}
+
+
+
+
+1;
+
+
+# Local Variables:
+# mode: perl
+# indent-tabs-mode: nil
+# perl-indent-level: 4
+# End: