The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Router::Statistics - Router Statistics and Information Collection

VERSION

Version 0.99_989

SYNOPSIS

Router Statistics and Information Colleciton. Currently this covers a multitude of areas from different types of routers and in a future release this will change. There are some 'action' functions within this module which do need moving to another module so no complaining too much, please.

The following examples shows how to setup the module to retrieve interface statistics from routers that support the standard IFMIB. All the work about OIDs etc is taken care of by the module so you are left with a hash tree, rooted by the router IPs information was received for.

    use Router::Statistics;
    use strict;

    my ( $result, $statistics );
    my ( %routers, %interfaces );

    $statistics = new Router::Statistics();

    $result = $statistics->Router_Add( "10.1.1.1" , "public" );
    $result = $statistics->Router_Ready_Blocking( "10.1.1.1" );
    ....
    $result = $statistics->Router_Add( "10.1.1.200" , "public" );
    $result = $statistics->Router_Ready_Blocking( "10.1.1.200" );

    $result = $statistics->Router_Test_Connection_Blocking(\%routers);

    if ( !%routers )
        { print "No access to Any of the Routers specified.\n";exit(0); }

    $result = $statistics->Router_get_interfaces_Blocking( \%interfaces );

    foreach my $router ( keys %interfaces )
        {
        print "Router IP is '$router'\n";
        print "Router Hostname is '$routers{$router}{'hostName'}'\n";
        foreach my $interface ( keys %{$interfaces{$router}} )
                {
                print "Interface ID '$interface'\n";
                print "Interface Description '$interfaces{$ubr}{$interface}{'ifDescr'}'\n";
                print "Interface ifType '$interfaces{$ubr}{$interface}{'ifType'}'\n";
                print "Interface ifMtu  '$interfaces{$ubr}{$interface}{'ifMtu'}'\n";
                print "Interface ifSpeed '$interfaces{$ubr}{$interface}{'ifSpeed'}'\n";
                print "Interface ifPhysAddress '$interfaces{$ubr}{$interface}{'ifPhysAddress'}'\n";
                print "Interface ifOperStatus '$interfaces{$ubr}{$interface}{'ifOperStatus'}'\n";
                print "Interface ifInOctets '$interfaces{$ubr}{$interface}{'ifInOctets'}'\n";
                print "Interface ifInUcastPkts '$interfaces{$ubr}{$interface}{'ifInUcastPkts'}'\n";
                print "Interface ifInNUcastPkts '$interfaces{$ubr}{$interface}{'ifInNUcastPkts'}'\n";
                print "Interface ifInDiscards '$interfaces{$ubr}{$interface}{'ifInDiscards'}'\n";
                print "Interface ifInErrors '$interfaces{$ubr}{$interface}{'ifInErrors'}'\n";
                print "Interface ifInUnknownProtos '$interfaces{$ubr}{$interface}{'ifInUnknownProtos'}'\n";
                print "Interface ifOutOctets '$interfaces{$ubr}{$interface}{'ifOutOctets'}'\n";
                print "Interface ifOutUcastPkts '$interfaces{$ubr}{$interface}{'ifOutUcastPkts'}'\n";
                print "Interface ifOutNUcastPkts '$interfaces{$ubr}{$interface}{'ifOutNUcastPkts'}'\n";
                print "Interface ifOutDiscards '$interfaces{$ubr}{$interface}{'ifOutDiscards'}'\n";
                print "Interface ifOutErrors '$interfaces{$ubr}{$interface}{'ifOutErrors'}'\n";
                print "\n";
                }
       }

I am currently in need of access to alternative vendor routers, ie. anyone but Cisco ( ABC ) as I only have real access to Cisco equipment so this code can not be confirmed 100% against anyone else.

I would also like to expand the library to cover other actions , rather than just DOCSIS functions, which is the primary action focus at the moment.

The module current has two(2) global variables that can be set when creating the object the first DEBUG turns on all the debug output, the second, STM_Safety_Limit, allows you to change the STM safety margin by subtracting the number (minutes) specified from the end time. This is also settable in the STM functions but only if you are also using an enable password.

An example of how to use them is

    $statistics = new Router::Statistics(
                              [
                              DEBUG => 1,
                              STM_Safety_Limit => 10
                              ]
                              );

This would turn on debug and set the safety marging to 10 minutes. The default safety marging is 15 minutes.

FUNCTIONS

Router_Add

This function adds a Router IP, Community String and Timeout to the internal list of usable routers. It does not initialise any SNMP functionality at this stage. If no timeout is specified 2 seconds is the default.

    Router_Add ( "<ip>", "<community>", <timeout> );

Example of Use

    my $result = $test->Router_Add( "10.1.1.1" , "public" );

    is the same as this

    my $result = $test->Router_Add( "10.1.1.1" , "public" , 2 );
Router_Remove

The function removes a Router IP from the internal list of usable router. If there is an open SNMP session, it is closed.

Example of Use

    my $result = $test->Router_Remove ( "10.1.1.1" );
Router_Remove_All

The function removes ALL Router IPs from the internal list of usable router. If there is an open SNMP session, it is closed.

Example of Use

    my $result = $test->Router_Remove_All ( );

The function was added so you can switch between blocking and non-blocking objects quickly and without the need to manually delete any routers already setup.

Router_Ready

This function sets up the SNMP session object for the IP specified. This is for the non blocking function set.

Example of Use

    my $result = $test->Router_Ready ( "10.1.1.1" );
Router_Ready_Blocking

This function sets up the SNMP session object for the IP specified. This is for the blocking function set.

Example of Use

    my $result = $test->Router_Ready_Blocking ( "10.1.1.1" );
Router_Test_Connection

This function sends requests for sysUpTime, hostName and sysDescr SNMP variables and if successful populates a given hash pointer rooted by the IP of the routers specified.

If the router is not reachable the SNMP session is destroyed ( created by Router_Ready ) and thus not polled for information when other functions are called.

Example of Use

    my %routers;
    my $result = $test->Router_Test_Connection(\%routers);
Router_Test_Connection_Blocking

This function sends requests for sysUpTime, hostName and sysDescr SNMP variables and if successful populates a given hash pointer rooted by the IP of the routers specified.

This is the Blocking mirror to the Router_Test_Connection function

Example of Use

    my %routers;
    my $result = $test->Router_Test_Connection_Blocking(\%routers);
Router_Return_All

This function returns a hash with all the current Routers which were added with Router_Add. There is little reason to call this function in your own routines and may be move to an internal view.

Example of Use

    my %routers = $test->Router_Return_All();
Router_get_networks

No detail given.

Router_get_interfaces

This function returns the following for each interface found on the router in 32bit mode.

    ifDescr ifType ifMtu ifSpeed ifPhysAddress ifAdminStatus ifOperStatus ifLastChange
    ifInOctets ifInUcastPkts ifInNUcastPkts ifInDiscards ifInErrors ifInUnknownProtos
    ifOutOctets ifOutUcastPkts ifOutNUcastPkts ifOutDiscards ifOutErrors ifAlias

you can specify 64Bit when calling this function and it will then get and return

    ifName ifInMulticastPkts ifInBroadcastPkts ifOutMulticastPkts ifOutBroadcastPkts
    ifHCInOctets ifHCInUcastPkts ifHCInMulticastPkts ifHCInBroadcastPkts ifHCOutOctets
    ifHCOutUcastPkts ifHCOutMulticastPkts ifHCOutBroadcastPkts ifLinkUpDownTrapEnable
    ifHighSpeed ifPromiscuousMode ifConnectorPresent ifAlias ifCounterDiscontinuityTime

The data is returned in a structured hash as follows

    Router IP Address
           Interface Instance Number
                 Interface Attribute ie. ifDescr
                 Interface Attribute ie. ifType

Example of Use

    my %interface_information;
    my $test = $test->Router_get_interfaces( \%interface_information, "32Bit" );

You can omit 32Bit as it is 32Bit by default, but is shown for clarity here.

Router_get_interfaces_Blocking

This function returns the following for each interface found on the router and is the blocking mirror to the Router_get_interfaces function

This function returns the following for each interface found on the router

    ifDescr ifType ifMtu ifSpeed ifPhysAddress ifAdminStatus ifOperStatus ifLastChange
    ifInOctets ifInUcastPkts ifInNUcastPkts ifInDiscards ifInErrors ifInUnknownProtos
    ifOutOctets ifOutUcastPkts ifOutNUcastPkts ifOutDiscards ifOutErrors ifAlias

you can specify 64Bit when calling this function and it will then get and return

    ifName ifInMulticastPkts ifInBroadcastPkts ifOutMulticastPkts ifOutBroadcastPkts
    ifHCInOctets ifHCInUcastPkts ifHCInMulticastPkts ifHCInBroadcastPkts ifHCOutOctets
    ifHCOutUcastPkts ifHCOutMulticastPkts ifHCOutBroadcastPkts ifLinkUpDownTrapEnable
    ifHighSpeed ifPromiscuousMode ifConnectorPresent ifAlias ifCounterDiscontinuityTime

The data is returned in a structured hash as follows

    Router IP Address
           Interface Instance Number
                 Interface Attribute ie. ifDescr
                 Interface Attribute ie. ifType

Example of Use

    my %interface_information;
    my $test = $test->Router_get_interfaces_Blocking( \%interface_information, "32Bit" );

You can omit 32Bit as it is 32Bit by default, but is shown for clarity here.

CPE_Add

This function adds a CPE IP, Community String and Timeout to the internal list of CPEs that can be polled for information. All CPE polling is non blocking and also currently requires a unique ID.

It is possible to specify multiple community strings and these will be used in turn should no response be received, until no more can be tried.

    CPE_Add ( "<ip>", "<community>", "<router IP>", "<unique ID>", <timeout> );

Example of Use

    my $result = $test->CPE_Add( "10.1.2.100" , "public,testing,hello","10.1.1.1","dr3423d3",2 );
CPE_Remove

The function removes a CPE from the internal list of usable CPEs. If there is an open SNMP session, it is closed.

    CPE_Remove ("<ip>")

Example of Use

    my $result = $test->CPE_Remove ( "10.1.2.100" );
CPE_Ready

This function sets up the SNMP session object for the CPE IP specified. This is for the non blocking function set. (CPE functions do not have non-blocking counterparts)

    CPE_Ready ("<ip>", [ array containing OIDs of the SNMP variables to get ] )

Example of Use

    my $result = $test-> CPE_Ready ( 
                        "10.1.2.100",
                        [ 1.3.6.1.2.1.1.3.0 , 1.3.6.1.2.1.1.1.0 ] );

    This would retrieve sysUptime and sysDescr for the CPE when the collection functions are
called. You can of course use the references in the OID module provided with this module so
you can use names instead of OIDs.
CPE_Return_All

No detail given.

CPE_export_import_fields

No detail given.

CPE_export_fields

No detail given.

CPE_export_schema

No detail given.

CPE_export_data_start

No detail given.

CPE_export_data_end

No detail given.

CPE_export_data

No detail given.

CPE_gather_all_data_walk

No detail given.

CPE_gather_all_data

This function attempts to collect the CPE data previously configured with CPE_Ready. The function attempts to use non blocking functionality to do this as quickly as possible, however the more OIDs to collect per CPE the longer it will take.

Preliminary testing shows the 5000 CPE devices can be polled, with 4 OIDs each, in 45 seconds, making it relatively painless when polling large scale networks.

When using this function and using multiple community strings will cause a significant slowing of performance.

The function requires a pointer to a hash

    CPE_gather_all_data ( <hash pointer> )

Example of Use

    my $result = $test-> CPE_gather_all_data (
                                \%cpe_data 
                                );

    The result is rooted by the unique ID and contains the OIDs, converted to name,
with their results. If the CPE is NOT in this hash then it was not successfully 
contacted.

    CPE Hash
        -- Unique ID
           --  OID (converted to name)
           --  OID (converted to name)
           --  etc
CPE_Test_Connection
Get_UBR_Inventory

This has been replaced with

UBR_get_Inventory

This function remains for backward compatibility.

Export_UBR_Slot_Inventory
Export_UBR_Port_Inventory
UBR_get_DOCSIS_upstream_interfaces
UBR_get_DOCSIS_upstream_interfaces_Blocking
UBR_get_DOCSIS_interface_information
UBR_get_DOCSIS_interface_information_Blocking
UBR_get_DOCSIS_downstream_interfaces
UBR_get_DOCSIS_downstream_interfaces_Blocking
UBR_get_CPE_information
UBR_get_CPE_information_Blocking
UBR_modify_cpe_DOCSIS_profile
UBR_reset_cpe_device
UBR_get_active_cpe_profiles
UBR_get_active_cpe_profiles_Blocking
UBR_get_active_upstream_profiles
UBR_get_active_upstream_profiles_Blocking
UBR_get_stm

The use of the STM functions come with a MASSIVE warning, that due to bugs in Cisco IOS your UBR ( Cable router ) will drop all currently connected devices if you poll it OUTSIDE of the configured STM time scope. This is a known defect so you HAVE BEEN WARNED. There are a couple of possible workarounds however none have been confirmed.

Use of the Non Blocking function should be done with care and the UBR_get_stm_Blocking is preferred.

Example of Use

    use Router::Statistics;
    use strict;

    my $test= new Router::Statistics;
    my (%stm_inventory, %stm_telnet_inventory , %router);
    my $result = $test->Router_Add( "10.1.1.1" , "public" );
    $result = $test->Router_Ready ( "10.1.1.1" );
    $result = $test->UBR_get_stm( 
        \%router,
        \%stm_information,
        \%stm_telnet_inventory,
        "telnetlogin",
        "telnetpassword",
        "enablepassword",
        "15" );

The enable password is only required if your login does not put you into the correct privs account when logged in initially.

The 15 is the amount of minutes to subtract from the end of the STM period as a safety margin for polling.

The %stm_information hash contains a tree rooted by the IP address of the routers Added initially and the STM information as follows

     Router IP
          -- STM Instance Number
             --  ccqmEnfRuleViolateID ( never seems to be populated )
             --  ccqmEnfRuleViolateMacAddr  - MAC address of the device
             --  ccqmEnfRuleViolateRuleName - Name of the STM rule specified
             --  ccqmEnfRuleViolateByteCount - The Cisco specification is wrong
             --  ccqmEnfRuleViolateLastDetectTime - The time the violation occured
             --  ccqmEnfRuleViolatePenaltyExpTime - The time the violation finishes

It should be noted that due to another bug not all entries for STM violations end up in the STM MIB. This appears to be caused by the end time of the STM configuration, if a devices expiry time is after the end of the STM window, it does not go into the MIB.

UBR_get_stm_Blocking

The use of the STM functions come with a MASSIVE warning, that due to bugs in Cisco IOS your UBR ( Cable router ) will drop all currently connected devices if you poll it OUTSIDE of the configured STM time scope. This is a known defect so you HAVE BEEN WARNED. There are a couple of possible workarounds however none have been confirmed.

Example of Use

    use Router::Statistics;
    use strict;

    my $test= new Router::Statistics;
    my (%stm_inventory, %stm_telnet_inventory , %router);
    my $result = $test->Router_Add( "10.1.1.1" , "public" );
    $result = $test->Router_Ready_Blocking ( "10.1.1.1" );
    $result = $test->Router_Test_Connection_Blocking(\%routers);
    $result = $test->UBR_get_stm_Blocking( 
        \%router,
        \%stm_information,
        \%stm_telnet_inventory,
        "telnetlogin",
        "telnetpassword",
        "enablepassword",
        "15" );

The enable password is only required if your login does not put you into the correct privs account when logged in initially.

The 15 is the amount of minutes to subtract from the end of the STM period as a safety margin for polling.

The %stm_information and %stm_telnet_inventory hashes contains a tree rooted by the IP address of the routers Added initially and the STM information as follows

    Router IP
        -- STM Instance Number
           --  ccqmEnfRuleViolateID ( never seems to be populated )
           --  ccqmEnfRuleViolateMacAddr  - MAC address of the device
           --  ccqmEnfRuleViolateRuleName - Name of the STM rule specified
           --  ccqmEnfRuleViolateByteCount - The Cisco specification is wrong
           --  ccqmEnfRuleViolateLastDetectTime - The time the violation occured
           --  ccqmEnfRuleViolatePenaltyExpTime - The time the violation finishes

It should be noted that due to another bug not all entries for STM violations end up in the STM MIB. This appears to be caused by the end time of the STM configuration, if a devices expiry time is after the end of the STM window, it does not go into the MIB.

Get_7500_Inventory
    The same construct as Get_UBR_Inventory
Export_7500_Slot_Inventory
Export_7500_Port_Inventory
Get_GSR_Inventory
    The same construct as Get_UBR_Inventory
Export_GSR_Slot_Inventory
Export_GSR_Port_Inventory
Get_7600_Inventory
Export_7600_Slot_Inventory
Export_7600_Port_Inventory
c<< set_format >>
    This function sets the format of the date/time output used in the STM
functions. The default is 

    <year> <MonName> <day> <HH>:<MM>:<SS>

    The format can include the following

    <Year>      - 4 number year ie. 2007
    <MonName>   - Name of the Month, ie January
    <Mon>       - Number of the Month ie. 1 for January
    <Day>       - Day of the month ie. 21
    <HH>        - The hour ie. 10 or 22 ( am or pm )
    <MM>        - The minute
    <SS>        - The second

Example of Use

    use Router::Statistics;
    use strict;

    my $test= new Router::Statistics;
    my $result = $test->set_format("<Year> <Mon> <Day> <HH>:<MM>:<SS>");

BUGS

It is has been discovered using Non blocking functions on Cisco routers does not always return the same consistent information compared to Blocking. It is the opinion of the author to only use Blocking unless you know what you are doing, and all functions will have Blocking mirrors in the first public release.

Module now semi supports blocking and non blocking mode. It has been discovered that non-blocking is significantly longer to execute. Not entirely sure why, however to speed things up some functions now have _Blocking mirrors so they can be called instead.

Added support to retrieve the STM information very simple implementation to poll the STM mib provided on Cisco equipment. Added support to ONLY poll STM information when within all STM windows.

Added Network Link Map Generator Added CPE snmp read key cycler ( not finished ).

Please report any bugs or feature requests to bug-router-statistics at rt.cpan.org, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Router-Statistics. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.

SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc Router::Statistics

ACKNOWLEDGEMENTS

Cisco I suppose for making their products such a nightmare to manage using SNMP.

Joshua Keroes for pointing out some of the make test issues ( thanks!! ) Joshua Keroes for requesting HC (64bit) for interfaces

Motorola for some pointers with their CMTS ( still waiting on some info )

COPYRIGHT & LICENSE

Copyright 2007 Andrew S. Kennedy, all rights reserved.

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

2 POD Errors

The following errors were encountered while parsing the POD:

Around line 110:

'=item' outside of any '=over'

Around line 4504:

You forgot a '=back' before '=head1'