SNMP Monitoring again

Andre Beck (beck@ibh-dd.de)
Fri, 7 Jul 1995 15:45:02 +0200 (MET DST)

Hi,

some weeks ago I asked why the interface load monitor gets suddenly
stuck now and then, and why it won't display 'down' interfaces in the
first place. I decided to look this problem up for myself (I don't like
TCL but...). Here is what I came out with:

1) The code in snmp_monitor.tcl proc show_ifload has a bug. If the
ifSpeed is zero, a division by zero occurs and the whole loop bails
out (thus this and all following interfaces get stuck). The /0 stays
otherwise undetected (did I say may blurb on TCL already ? ;)

2) The code in proc "Interface load" tries to avoid problems by just not
regarding any interface which is down (sensed by ifAdminStatus, what
should be ifOperStatus IMHO) or has an ifSpeed < 300. Now the joke is,
if this interface is up and the config is saved, the check is not made
on loading the config later, which causes the stuck effect abovementioned.
It would appear as well if an IF goes down during display.

I made a patch which turns the behavior into something more useful (IMHO),
the diff is following. If it could make it into the next Scotty release
(evtl. with extensions, esp. I did not implement MoJoAction when the IF
goes up or down, which would be nice to have) I would be pleased.

Now the diff (thanks to patch I don't have anything to mark here ;) :

*** snmp_monitor.tcl.orig Fri Jul 7 13:43:17 1995
--- snmp_monitor.tcl Fri Jul 7 15:20:50 1995
***************
*** 280,286 ****
--- 280,292 ----
global sv_snmp sv_idx sv_time sv_duplex
global sv_ifInOctets sv_ifOutOctets sv_ifSpeed sv_ifDescr

+ ## saved ifOperStatus currently unused but should be used to call the
+ ## MoJoAction on changing (flashing, writing, etc.)
+
+ global sv_ifOperStatus
+
set ids [MoJoCheckIds show_ifload $ids]
+
if {$ids == ""} return

foreach id $ids {
***************
*** 287,298 ****

set idx $sv_idx($id)

! set value [SnmpGet $sv_snmp($id) "ifInOctets.$idx ifOutOctets.$idx"]

set ifIn [lindex $value 0]
set ifOut [lindex $value 1]
set now [getclock]

set deltaIn [expr {$ifIn - $sv_ifInOctets($id)}]
set deltaOut [expr {$ifOut - $sv_ifOutOctets($id)}]

--- 293,306 ----

set idx $sv_idx($id)

! set value [SnmpGet $sv_snmp($id) "ifInOctets.$idx ifOutOctets.$idx ifOperStatus.$idx"]

set ifIn [lindex $value 0]
set ifOut [lindex $value 1]
+ set ifOS [lindex $value 2]
set now [getclock]

+
set deltaIn [expr {$ifIn - $sv_ifInOctets($id)}]
set deltaOut [expr {$ifOut - $sv_ifOutOctets($id)}]

***************
*** 302,323 ****
set delta [expr $deltaIn + $deltaOut]
}

! if {$now > $sv_time($id)} {
set val [expr {( 8.0 * $delta / ($now - $sv_time($id)) )
/ $sv_ifSpeed($id) * 100}]
} else {
set val 0
}
ined values $id $val
- ined -noupdate attribute $id "interface load" \
- [format "$sv_ifDescr($id) %.2f %%" $val]

set txt "[ined name $id] $sv_ifDescr($id) interface load"
MoJoCheckThreshold $id $txt $val "%%"

set sv_time($id) $now
set sv_ifInOctets($id) $ifIn
set sv_ifOutOctets($id) $ifOut
}
}

--- 310,343 ----
set delta [expr $deltaIn + $deltaOut]
}

!
! if {$now > $sv_time($id) && $sv_ifSpeed($id) > 0} {
set val [expr {( 8.0 * $delta / ($now - $sv_time($id)) )
/ $sv_ifSpeed($id) * 100}]
} else {
set val 0
}
+
+
ined values $id $val

+ if {$ifOS != "up" && $ifOS != "1"} {
+ ined -noupdate attribute $id "interface load" \
+ "$sv_ifDescr($id) $ifOS"
+ } else {
+ ined -noupdate attribute $id "interface load" \
+ [format "$sv_ifDescr($id) %.2f %%" $val]
+ }
+
set txt "[ined name $id] $sv_ifDescr($id) interface load"
+
MoJoCheckThreshold $id $txt $val "%%"

set sv_time($id) $now
set sv_ifInOctets($id) $ifIn
set sv_ifOutOctets($id) $ifOut
+ set sv_ifOperStatus($id) $ifOS
+
}
}

***************
*** 331,336 ****
--- 351,357 ----
global interval
global sv_snmp sv_idx sv_time sv_duplex
global sv_ifInOctets sv_ifOutOctets sv_ifSpeed sv_ifDescr
+ global sv_ifOperStatus

# Note, IANAifType (RFC 1573) has somewhat different encodings
# than RFC 1213. We use RFC 1213 style.
***************
*** 353,359 ****
if {$id != ""} {

if {[catch {$sh get [list ifInOctets.$idx ifOutOctets.$idx \
! ifSpeed.$idx ifDescr.$idx ifType.$idx ]} value]} {
writeln "fatal error for $ip ($id) : $value"
set args [lrange $args 2 end]
continue
--- 374,381 ----
if {$id != ""} {

if {[catch {$sh get [list ifInOctets.$idx ifOutOctets.$idx \
! ifSpeed.$idx ifDescr.$idx ifType.$idx \
! ifOperStatus.$idx]} value]} {
writeln "fatal error for $ip ($id) : $value"
set args [lrange $args 2 end]
continue
***************
*** 364,369 ****
--- 386,392 ----
set sv_ifSpeed($id) [lindex [lindex $value 2] 2]
set sv_ifDescr($id) [lindex [lindex $value 3] 2]
set sv_ifType($id) [lindex [lindex $value 4] 2]
+ set sv_ifOperStatus($id) [lindex [lindex $value 5] 2]
set sv_time($id) [getclock]
set sv_snmp($id) $sh
set sv_idx($id) $idx
***************
*** 398,416 ****
set iflist ""
if {[catch {
$sh walk x "ifIndex ifAdminStatus ifSpeed ifInOctets ifOutOctets" {
set idx [lindex [lindex $x 0] 2]
set status [lindex [lindex $x 1] 2]
set speed [lindex [lindex $x 2] 2]

! if {$status != "up" && $status != "1"} {
! writeln "Interface $idx on $host \[$ip\] ignored (ifAdminStatus = $status)"
! continue
! }
!
! if {$speed < 300} {
! writeln "Interface $idx on $host \[$ip\] ignored (ifSpeed = $speed)"
! continue
! }

lappend iflist $idx
}
--- 421,448 ----
set iflist ""
if {[catch {
$sh walk x "ifIndex ifAdminStatus ifSpeed ifInOctets ifOutOctets" {
+
+ ## Nice question whether this should have been ifOperStatus anyway
+
set idx [lindex [lindex $x 0] 2]
set status [lindex [lindex $x 1] 2]
set speed [lindex [lindex $x 2] 2]
+
+ ## There exist interfaces which all of a sudden change
+ ## - their ifOperStatus
+ ## - their ifSpeed
+ ##
+ ## We want to see this happen, so don't kill 'em here
+
+ ## if {$status != "up" && $status != "1"} {
+ ## writeln "Interface $idx on $host \[$ip\] ignored (ifAdminStatus = $status)"
+ ## continue
+ ## }

! ## if {$speed < 300} {
! ## writeln "Interface $idx on $host \[$ip\] ignored (ifSpeed = $speed)"
! ## continue
! ## }

lappend iflist $idx
}

Andre.

-- 
+-o-+--------------------------------------------------------+-o-+
| o |               \\\- Brain Inside -///                   | o |
| o |                   ^^^^^^^^^^^^^^                       | o |
| o | Andre' Beck (ABPSoft) beck@ibh-dd.de XLink PoP Dresden | o |
+-o-+--------------------------------------------------------+-o-+