summaryrefslogtreecommitdiff
path: root/torrus/perllib/Torrus/DevDiscover/JunOS.pm
diff options
context:
space:
mode:
Diffstat (limited to 'torrus/perllib/Torrus/DevDiscover/JunOS.pm')
-rw-r--r--torrus/perllib/Torrus/DevDiscover/JunOS.pm657
1 files changed, 657 insertions, 0 deletions
diff --git a/torrus/perllib/Torrus/DevDiscover/JunOS.pm b/torrus/perllib/Torrus/DevDiscover/JunOS.pm
new file mode 100644
index 000000000..ff5c3f8a0
--- /dev/null
+++ b/torrus/perllib/Torrus/DevDiscover/JunOS.pm
@@ -0,0 +1,657 @@
+#
+# Copyright (C) 2007 Jon Nistor
+#
+# 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: JunOS.pm,v 1.1 2010-12-27 00:03:53 ivan Exp $
+# Jon Nistor <nistor at snickers.org>
+
+# Juniper JunOS Discovery Module
+#
+# NOTE: For Class of service, if you are noticing that you are not seeing
+# all of your queue names show up, this is by design of Juniper.
+# Solution: Put place-holder names for those queues such as:
+# "UNUSED-queue-#"
+# This is in reference to JunOS 7.6
+#
+# NOTE: Options for this module:
+# JunOS::disable-cos
+# JunOS::disable-cos-red
+# JunOS::disable-cos-tail
+# JunOS::disable-firewall
+# JunOS::disable-operating
+# JunOS::disable-rpf
+
+package Torrus::DevDiscover::JunOS;
+
+use strict;
+use Torrus::Log;
+
+
+$Torrus::DevDiscover::registry{'JunOS'} = {
+ 'sequence' => 500,
+ 'checkdevtype' => \&checkdevtype,
+ 'discover' => \&discover,
+ 'buildConfig' => \&buildConfig
+};
+
+
+our %oiddef =
+ (
+ # JUNIPER-SMI
+ 'jnxProducts' => '1.3.6.1.4.1.2636.1',
+ 'jnxBoxDescr' => '1.3.6.1.4.1.2636.3.1.2.0',
+ 'jnxBoxSerialNo' => '1.3.6.1.4.1.2636.3.1.3.0',
+
+ # Operating status
+ 'jnxOperatingDescr' => '1.3.6.1.4.1.2636.3.1.13.1.5',
+ 'jnxOperatingTemp' => '1.3.6.1.4.1.2636.3.1.13.1.7',
+ 'jnxOperatingCPU' => '1.3.6.1.4.1.2636.3.1.13.1.8',
+ 'jnxOperatingISR' => '1.3.6.1.4.1.2636.3.1.13.1.9',
+ 'jnxOperatingDRAMSize' => '1.3.6.1.4.1.2636.3.1.13.1.10', # deprecated
+ 'jnxOperatingBuffer' => '1.3.6.1.4.1.2636.3.1.13.1.11',
+ 'jnxOperatingMemory' => '1.3.6.1.4.1.2636.3.1.13.1.15',
+
+ # Firewall filter
+ 'jnxFWCounterDisplayFilterName' => '1.3.6.1.4.1.2636.3.5.2.1.6',
+ 'jnxFWCounterDisplayName' => '1.3.6.1.4.1.2636.3.5.2.1.7',
+ 'jnxFWCounterDisplayType' => '1.3.6.1.4.1.2636.3.5.2.1.8',
+
+ # Class of Service (jnxCosIfqStatsTable deprecated, use jnxCosQstatTable)
+ # COS - Class Of Service
+ # RED - Random Early Detection
+ # PLP - Packet Loss Priority
+ # DSCP - Differential Service Code Point
+
+ 'jnxCosFcIdToFcName' => '1.3.6.1.4.1.2636.3.15.3.1.2',
+ 'jnxCosQstatQedPkts' => '1.3.6.1.4.1.2636.3.15.4.1.3',
+
+ # Reverse path forwarding
+ 'jnxRpfStatsPackets' => '1.3.6.1.4.1.2636.3.17.1.1.1.3'
+
+ );
+
+
+# Not all interfaces are normally needed to monitor.
+# You may override the interface filtering in devdiscover-siteconfig.pl:
+# redefine $Torrus::DevDiscover::JunOS::interfaceFilter
+# or define $Torrus::DevDiscover::JunOS::interfaceFilterOverlay
+
+our $interfaceFilter;
+our $interfaceFilterOverlay;
+my %junosInterfaceFilter;
+
+if( not defined( $interfaceFilter ) )
+{
+ $interfaceFilter = \%junosInterfaceFilter;
+}
+
+
+# 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
+%junosInterfaceFilter =
+ (
+ 'lsi' => {
+ 'ifType' => 150, # mplsTunnel
+ 'ifDescr' => '^lsi$'
+ },
+
+ 'other' => {
+ 'ifType' => 1, # other
+ },
+
+ 'loopback' => {
+ 'ifType' => 24, # softwareLoopback
+ },
+
+ 'propVirtual' => {
+ 'ifType' => 53, # propVirtual
+ },
+
+ 'gre_ipip_pime_pimd_mtun' => {
+ 'ifType' => 131, # tunnel
+ 'ifDescr' => '^(gre)|(ipip)|(pime)|(pimd)|(mtun)$'
+ },
+
+ 'pd_pe_gr_ip_mt_lt' => {
+ 'ifType' => 131, # tunnel
+ 'ifDescr' => '^(pd)|(pe)|(gr)|(ip)|(mt)|(lt)-\d+\/\d+\/\d+$'
+ },
+
+ 'ls' => {
+ 'ifType' => 108, # pppMultilinkBundle
+ 'ifDescr' => '^ls-\d+\/\d+\/\d+$'
+ },
+ );
+
+
+
+sub checkdevtype
+{
+ my $dd = shift;
+ my $devdetails = shift;
+
+ if( not $dd->oidBaseMatch
+ ( 'jnxProducts',
+ $devdetails->snmpVar( $dd->oiddef('sysObjectID') ) )
+ )
+ {
+ return 0;
+ }
+
+ &Torrus::DevDiscover::RFC2863_IF_MIB::addInterfaceFilter
+ ($devdetails, $interfaceFilter);
+
+ if( defined( $interfaceFilterOverlay ) )
+ {
+ &Torrus::DevDiscover::RFC2863_IF_MIB::addInterfaceFilter
+ ($devdetails, $interfaceFilterOverlay);
+ }
+
+ $devdetails->setCap('interfaceIndexingPersistent');
+
+ return 1;
+}
+
+
+sub discover
+{
+ my $dd = shift;
+ my $devdetails = shift;
+
+ my $session = $dd->session();
+ my $data = $devdetails->data();
+
+ # NOTE: Comments and Serial number of device
+ my $chassisSerial =
+ $dd->retrieveSnmpOIDs( 'jnxBoxDescr', 'jnxBoxSerialNo' );
+
+ if( defined( $chassisSerial ) )
+ {
+ $data->{'param'}{'comment'} = $chassisSerial->{'jnxBoxDescr'} .
+ ', Hw Serial#: ' . $chassisSerial->{'jnxBoxSerialNo'};
+ } else
+ {
+ $data->{'param'}{'comment'} = "Juniper router";
+ }
+
+
+ # PROG: Class of Service
+ #
+ if( $devdetails->param('JunOS::disable-cos') ne 'yes' )
+ {
+ # Poll table to translate the CoS Index to a Name
+ my $cosQueueNumTable =
+ $session->get_table( -baseoid =>
+ $dd->oiddef('jnxCosFcIdToFcName') );
+ $devdetails->storeSnmpVars( $cosQueueNumTable );
+
+ if( $cosQueueNumTable )
+ {
+ $devdetails->setCap('jnxCoS');
+
+ # Find the index of the CoS queue name
+ foreach my $cosFcIndex ( $devdetails->getSnmpIndices
+ ($dd->oiddef('jnxCosFcIdToFcName')) )
+ {
+ my $cosFcNameOid = $dd->oiddef('jnxCosFcIdToFcName') . "." .
+ $cosFcIndex;
+ my $cosFcName = $cosQueueNumTable->{$cosFcNameOid};
+
+ Debug("JunOS::CoS FC index: $cosFcIndex name: $cosFcName");
+
+ # Construct the data ...
+ $data->{'jnxCos'}{'queue'}{$cosFcIndex} = $cosFcName;
+ }
+
+ # We need to find out all the interfaces that have CoS enabled
+ # on them. We will use jnxCosQstatQedPkts as our reference point.
+ my $cosIfIndex =
+ $session->get_table( -baseoid =>
+ $dd->oiddef('jnxCosQstatQedPkts') );
+ $devdetails->storeSnmpVars( $cosIfIndex );
+
+ if( $cosIfIndex )
+ {
+ foreach my $INDEX ( $devdetails->getSnmpIndices
+ ($dd->oiddef('jnxCosQstatQedPkts')) )
+ {
+ my( $ifIndex, $cosQueueIndex ) = split( '\.', $INDEX );
+ $data->{'jnxCos'}{'ifIndex'}{$ifIndex} = 1;
+ }
+ }
+ }
+ } # END JunOS::disable-cos
+
+
+ # PROG: Grab and store description of parts
+ #
+ if( $devdetails->param('JunOS::disable-operating') ne 'yes' )
+ {
+ my $tableDesc = $session->get_table( -baseoid =>
+ $dd->oiddef('jnxOperatingDescr'));
+ $devdetails->storeSnmpVars( $tableDesc );
+
+ if ( $tableDesc )
+ {
+ # PROG: Set Capability flag
+ $devdetails->setCap('jnxOperating');
+
+ # PROG: Poll tables for more info to match and index on
+ my $tableCPU =
+ $session->get_table( -baseoid =>
+ $dd->oiddef('jnxOperatingCPU'));
+ $devdetails->storeSnmpVars( $tableCPU );
+
+ my $tableISR =
+ $session->get_table( -baseoid =>
+ $dd->oiddef('jnxOperatingISR'));
+ $devdetails->storeSnmpVars( $tableISR );
+
+ my $tableMEM =
+ $session->get_table( -baseoid =>
+ $dd->oiddef('jnxOperatingMemory'));
+ $devdetails->storeSnmpVars( $tableMEM );
+
+ my $tableTemp =
+ $session->get_table( -baseoid =>
+ $dd->oiddef('jnxOperatingTemp'));
+ $devdetails->storeSnmpVars( $tableTemp );
+
+ # PROG: Build tables for all the oids
+ # We are using the Descr oid base for matching. (cheap hack)
+ foreach my $opIndex ( $devdetails->getSnmpIndices
+ ($dd->oiddef('jnxOperatingDescr')) )
+ {
+ my $opCPU = $devdetails->snmpVar
+ ($dd->oiddef('jnxOperatingCPU') . '.' . $opIndex);
+ my $opDesc = $devdetails->snmpVar
+ ($dd->oiddef('jnxOperatingDescr') . '.' . $opIndex);
+ my $opMem = $devdetails->snmpVar
+ ($dd->oiddef('jnxOperatingMemory') . '.' . $opIndex);
+ my $opISR = $devdetails->snmpVar
+ ($dd->oiddef('jnxOperatingISR') . '.' . $opIndex);
+ my $opTemp = $devdetails->snmpVar
+ ($dd->oiddef('jnxOperatingTemp') . '.' . $opIndex);
+
+ Debug("JunOS:: opIdx: $opIndex Desc: $opDesc");
+ Debug("JunOS:: CPU: $opCPU, CPU: $opISR, MEM: $opMem");
+ Debug("JunOS:: Temp: $opTemp");
+
+ # Construct the data
+ $data->{'jnxOperating'}{$opIndex}{'index'} = $opIndex;
+ $data->{'jnxOperating'}{$opIndex}{'cpu'} = $opCPU;
+ $data->{'jnxOperating'}{$opIndex}{'desc'} = $opDesc;
+ $data->{'jnxOperating'}{$opIndex}{'isr'} = $opISR;
+ $data->{'jnxOperating'}{$opIndex}{'mem'} = $opMem;
+ $data->{'jnxOperating'}{$opIndex}{'temp'} = $opTemp;
+ }
+ } # END: if $tableDesc
+ } # END: JunOS::disable-operating
+
+
+ # PROG: Firewall statistics
+ if( $devdetails->param('JunOS::disable-firewall') ne 'yes' )
+ {
+ my $tableFWFilter =
+ $session->get_table( -baseoid =>
+ $dd->oiddef('jnxFWCounterDisplayFilterName'));
+ $devdetails->storeSnmpVars( $tableFWFilter );
+
+ if( $tableFWFilter )
+ {
+ # PROG: Set Capability flag
+ $devdetails->setCap('jnxFirewall');
+
+ # PROG: Poll tables for more info to match and index on
+ my $tableFWCounter =
+ $session->get_table( -baseoid =>
+ $dd->oiddef('jnxFWCounterDisplayName') );
+ $devdetails->storeSnmpVars( $tableFWCounter );
+
+ # Firewall Type (counter = 2, policer = 3)
+ my $tableFWType =
+ $session->get_table( -baseoid =>
+ $dd->oiddef('jnxFWCounterDisplayType') );
+ $devdetails->storeSnmpVars( $tableFWType );
+
+ # PROG: Build tables for all the oids
+ # We are using the FW Filter name as the Indexing
+ foreach my $fwIndex ( $devdetails->getSnmpIndices
+ ($dd->oiddef('jnxFWCounterDisplayName')) )
+ {
+ my $fwFilter = $devdetails->snmpVar
+ ($dd->oiddef('jnxFWCounterDisplayFilterName') .
+ '.' . $fwIndex);
+ my $fwCounter = $devdetails->snmpVar
+ ($dd->oiddef('jnxFWCounterDisplayName') .
+ '.' . $fwIndex);
+ my $fwType = $devdetails->snmpVar
+ ($dd->oiddef('jnxFWCounterDisplayType') .
+ '.' . $fwIndex);
+ Debug("JunOS::fw Filter: $fwFilter");
+ Debug("JunOS::fw Counter: $fwCounter");
+ Debug("JunOS::fw Type: $fwType");
+
+ # Construct the data
+ $data->{'jnxFirewall'}{$fwFilter}{$fwCounter}{'oid'} =
+ $fwIndex;
+ $data->{'jnxFirewall'}{$fwFilter}{$fwCounter}{'type'} =
+ $fwType;
+ }
+ } # END: if $tableFWfilter
+ } # END: JunOS::diable-firewall
+
+
+ # PROG: Check for RPF availability
+ if( $devdetails->param('JunOS::disable-rpf') ne 'yes' )
+ {
+ my $tableRPF =
+ $session->get_table( -baseoid =>
+ $dd->oiddef('jnxRpfStatsPackets') );
+ $devdetails->storeSnmpVars( $tableRPF );
+
+ if( $tableRPF )
+ {
+ # PROG: Set capability flag
+ $devdetails->setCap('jnxRPF');
+
+ # PROG: Find all the relevent interfaces
+ foreach my $rpfIndex ( $devdetails->getSnmpIndices
+ ($dd->oiddef('jnxRpfStatsPackets')) )
+ {
+ my ($ifIndex,$addrFamily) = split('\.',$rpfIndex);
+ if( defined( $data->{'interfaces'}{$ifIndex} ) )
+ {
+ my $ifAddrFam = $addrFamily == 1 ? 'ipv4' : 'ipv6';
+ my $intName = $data->{'interfaces'}{$ifIndex}{'ifName'};
+ my $intNameT = $data->{'interfaces'}{$ifIndex}{'ifNameT'};
+
+ # Construct data
+ $data->{'jnxRPF'}{$ifIndex}{'ifName'} = $intName;
+ $data->{'jnxRPF'}{$ifIndex}{'ifNameT'} = $intNameT;
+
+ if( $addrFamily == 1 )
+ {
+ $data->{'jnxRPF'}{$ifIndex}{'ipv4'} = 1;
+ }
+ if( $addrFamily == 2 )
+ {
+ $data->{'jnxRPF'}{$ifIndex}{'ipv6'} = 2;
+ }
+ }
+ }
+ }
+ }
+
+ return 1;
+}
+
+
+sub buildConfig
+{
+ my $devdetails = shift;
+ my $cb = shift;
+ my $devNode = shift;
+ my $data = $devdetails->data();
+
+
+ # PROG: Class of Service information
+ if( $devdetails->hasCap('jnxCoS') &&
+ ( keys %{$data->{'jnxCos'}{'ifIndex'}} > 0 )
+ )
+ {
+ # PROG: Add CoS information if it exists.
+ my $nodeTop = $cb->addSubtree( $devNode, 'CoS', undef,
+ [ 'JunOS::junos-cos-subtree']);
+
+ foreach my $ifIndex ( sort {$a <=> $b} keys
+ %{$data->{'jnxCos'}{'ifIndex'}} )
+ {
+ my $interface = $data->{'interfaces'}{$ifIndex};
+ my $ifAlias = $interface->{'ifAlias'};
+ my $ifDescr = $interface->{'ifDescr'};
+ my $ifName = $interface->{'ifNameT'};
+
+ next if( not $ifName ); # Skip since port is likely 'disabled'
+ # This might be better to match against ifType
+ # as well since not all of them support Q's.
+
+ # Add Subtree per port
+ my $nodePort =
+ $cb->addSubtree( $nodeTop, $ifName,
+ { 'comment' => $ifAlias,
+ 'precedence' => 1000 - $ifIndex },
+ [ 'JunOS::junos-cos-subtree-interface' ]);
+
+ # Loop to create subtree's for each QueueName/ID pair
+ foreach my $cosIndex ( sort keys %{$data->{'jnxCos'}{'queue'}} )
+ {
+ my $cosName = $data->{'jnxCos'}{'queue'}{$cosIndex};
+
+ # Add Leaf for each one
+ Debug("JunOS::CoS ifIndex: $ifIndex ($ifName -> $cosName)");
+ my $nodeIFCOS =
+ $cb->addSubtree( $nodePort, $cosName,
+ { 'comment' => "Class: " . $cosName,
+ 'cos-index' => $cosIndex,
+ 'cos-name' => $cosName,
+ 'ifDescr' => $ifDescr,
+ 'ifIndex' => $ifIndex,
+ 'ifName' => $ifName,
+ 'precedence' => 1000 - $cosIndex },
+ [ 'JunOS::junos-cos-leaf' ]);
+
+ if( $devdetails->param('JunOS::disable-cos-tail') ne 'yes' )
+ {
+ $cb->addSubtree( $nodeIFCOS, "Tail_drop_stats",
+ { 'comment' => 'Tail drop statistics' },
+ [ 'JunOS::junos-cos-tail' ]);
+ }
+
+ if( $devdetails->param('JunOS::disable-cos-red') ne 'yes' )
+ {
+ $cb->addSubtree
+ ( $nodeIFCOS, "RED_stats",
+ { 'comment' => 'Random Early Detection' },
+ [ 'JunOS::junos-cos-red' ]);
+ }
+
+ } # end foreach (INDEX of queue's [Q-ID])
+ } # end foreach (INDEX of port)
+ } # end if HasCap->{CoS}
+
+
+ # PROG: Firewall Table (filters and counters)
+ if( $devdetails->hasCap('jnxFirewall') )
+ {
+ # Add subtree first
+ my $nodeFW = $cb->addSubtree( $devNode, 'Firewall', undef,
+ [ 'JunOS::junos-firewall-subtree' ]);
+
+ # Loop through and find all the filter names
+ foreach my $fwFilter
+ ( sort {$a <=> $b} keys %{$data->{'jnxFirewall'}} )
+ {
+ my $firewall = $data->{'jnxFirewall'}{$fwFilter};
+
+ # Add subtree for FilterName
+ my $nodeFWFilter =
+ $cb->addSubtree( $nodeFW, $fwFilter,
+ { 'comment' => 'Filter: ' . $fwFilter },
+ [ 'JunOS::junos-firewall-filter-subtree' ]);
+
+ # Loop through and find all the counter names within the filter
+ foreach my $fwCounter ( sort {$a <=> $b} keys %{$firewall} )
+ {
+ my $fwOid = $firewall->{$fwCounter}{'oid'};
+ my $fwType = $firewall->{$fwCounter}{'type'};
+ my @templates = ( 'JunOS::junos-firewall-filter' );
+
+ # Figure out which templates to apply ...
+ if ($fwType == 2)
+ {
+ # fwType is a counter ...
+ push( @templates,
+ 'JunOS::junos-firewall-filter-counter',
+ 'JunOS::junos-firewall-filter-policer' );
+ }
+ elsif ($fwType == 3)
+ {
+ # fwType is a policer ...
+ push( @templates,
+ 'JunOS::junos-firewall-filter-policer' );
+ } # END: if $fwType
+
+ # Finally, add the subtree...
+ my $fwTypeName = $fwType == 2 ? 'Counter: ' : 'Policer: ';
+ my $nodeFWCounter =
+ $cb->addSubtree($nodeFWFilter, $fwCounter,
+ { 'comment' => $fwTypeName . $fwCounter,
+ 'fw-counter' => $fwCounter,
+ 'fw-filter' => $fwFilter,
+ 'fw-index' => $fwOid }, \@templates );
+ } # END foreach $fwCounter
+ } # END foreach $fwFilter
+ } # END: if hasCap jnxFirewall
+
+
+ # PROG: Operating Status Table
+ # NOTE: According to the Juniper MIB, the following is a statement:
+ # jnxOperatingTemp: The temperature in Celsius (degrees C) of this
+ # subject. Zero if unavailable or inapplicable.
+ # The same applies for all values under Operating status table, if
+ # Zero is shown it might be considered unavail or N/A. We will
+ # also take that into consideration.
+ # NOTE: Also so poorly written, its great.
+ if( $devdetails->hasCap('jnxOperating') )
+ {
+ my $nodeCPU = $cb->addSubtree( $devNode, 'CPU_Usage', undef,
+ [ 'JunOS::junos-cpu-subtree' ]);
+
+ my $nodeMem = $cb->addSubtree( $devNode, 'Memory_Usage', undef,
+ [ 'JunOS::junos-memory-subtree' ]);
+
+ my $nodeTemp =
+ $cb->addSubtree( $devNode, 'Temperature_Sensors', undef,
+ [ 'JunOS::junos-temperature-subtree' ]);
+
+
+ foreach my $opIndex
+ ( sort {$a <=> $b} keys %{$data->{'jnxOperating'}} )
+ {
+ my $operating = $data->{'jnxOperating'}{$opIndex};
+ my $jnxCPU = $operating->{'cpu'};
+ my $jnxDesc = $operating->{'desc'};
+ my $jnxMem = $operating->{'mem'};
+ my $jnxTemp = $operating->{'temp'};
+ my $jnxTag = $jnxDesc;
+ $jnxTag =~ s/\W+/_/go;
+ $jnxTag =~ s/_$//go;
+ # Fix the .'s into _'s for the RRD-DS and name of leaf
+ my $opIndexFix = $opIndex;
+ $opIndexFix =~ s/\./_/g;
+
+ # PROG: Find CPU that does not equal 0
+ if ($jnxCPU > 0)
+ {
+ $cb->addSubtree( $nodeCPU, $jnxTag,
+ { 'comment' => $jnxDesc,
+ 'cpu-index' => $opIndex },
+ [ 'JunOS::junos-cpu' ]);
+ }
+
+ # PROG: Find memory that does not equal 0
+ if ($jnxMem > 0)
+ {
+ $cb->addSubtree( $nodeMem, $jnxTag,
+ { 'comment' => $jnxDesc,
+ 'mem-index' => $opIndex,
+ 'mem-indexFix' => $opIndexFix },
+ [ 'JunOS::junos-memory' ]);
+ }
+
+ # PROG: Find Temperature that does not equal 0
+ if ($jnxTemp > 0)
+ {
+ if ($jnxDesc =~ /(temp.* sensor|Engine)/) {
+ # Small little hack to cleanup the sensor tags
+ $jnxTag =~ s/_temp(erature|)_sensor//g;
+ $cb->addLeaf( $nodeTemp, $jnxTag,
+ { 'comment' => $jnxDesc,
+ 'sensor-desc' => $jnxDesc,
+ 'sensor-index' => $opIndex,
+ 'sensor-indexFix' => $opIndexFix },
+ [ 'JunOS::junos-temperature-sensor' ]);
+ }
+ }
+ } # END foreach $opIndex
+ } # END if jnxOperating
+
+
+ # PROG: Reverse Forwarding Path (RPF)
+ if( $devdetails->hasCap('jnxRPF') )
+ {
+ # Add subtree first
+ my $nodeRPF = $cb->addSubtree( $devNode, 'RPF', undef,
+ [ 'JunOS::junos-rpf-subtree' ]);
+
+ # Loop through and find all interfaces with RPF enabled
+ foreach my $ifIndex ( sort {$a <=> $b} keys %{$data->{'jnxRPF'}} )
+ {
+ # Set some names
+ my $ifAlias = $data->{'interfaces'}{$ifIndex}{'ifAlias'};
+ my $ifName = $data->{'interfaces'}{$ifIndex}{'ifName'};
+ my $ifNameT = $data->{'interfaces'}{$ifIndex}{'ifNameT'};
+ my $hasIPv4 = $data->{'jnxRPF'}{$ifIndex}{'ipv4'};
+ my $hasIPv6 = $data->{'jnxRPF'}{$ifIndex}{'ipv6'};
+
+ Debug("JunOS:: RPF int: $ifName IPv4: $hasIPv4 IPv6: $hasIPv6");
+
+ # PROG: Process IPv4 first ...
+ if( $hasIPv4 )
+ {
+ $cb->addSubtree( $nodeRPF, 'IPv4_' . $ifNameT,
+ { 'comment' => $ifAlias,
+ 'ifAddrType' => "ipv4",
+ 'ifName' => $ifName,
+ 'ifNameT' => $ifNameT,
+ 'rpfIndex' => $ifIndex . "." . $hasIPv4 },
+ [ 'JunOS::junos-rpf' ]);
+ }
+
+ if( $hasIPv6 )
+ {
+ $cb->addSubtree( $nodeRPF, 'IPv6_' . $ifNameT,
+ { 'comment' => $ifAlias,
+ 'ifAddrType' => "ipv6",
+ 'ifName' => $ifName,
+ 'ifNameT' => $ifNameT,
+ 'rpfIndex' => $ifIndex . "." . $hasIPv6 },
+ [ 'JunOS::junos-rpf' ]);
+ }
+ }
+ } # END: if jnxRPF
+}
+
+
+1;
+
+# Local Variables:
+# mode: perl
+# indent-tabs-mode: nil
+# perl-indent-level: 4
+# End: