Hi,

We've been using SNMP.pm to pull out various tables from our switches into
our home-grown network management system. However, there's one thing that's
been causing issues for us for a long time, and that's getting the LLDP
tables (lldpRemTable).

The basic issues is that the values, at least when you query Cisco equipment,
tends to be so big that the packets get truncated. There's logic to try to
estimate the result size in the module and scale back accordingly on the
number of repetitions, but it fails in this case because the average value is
so big (it typically contains the entire “show ver” for the remote device).
This causes “ack: gettable results not appropriate”, even the results _are_
fully appropriate. (We've been turning off bulk gets, but it's not an ideal
solution, and in any case, it can still fail in the same way, it just needs
bigger values to do so.)

The attached patch (in context diff, because unified diff became unusually
unreadable!) first rewrites _gettable_do_it to be a bit less $#{$ everywhere
(so that I could understand it myself :-) ), and then fixes so that it
properly deals with a truncated response: For each value returned, the right
varbind is advanced, and the decision of which ones to keep querying is
delayed until the very end.

We've queried a variety of equipment we've got around (mostly Cisco and HP,
though), and this seems to fix the issue for us. Would you consider this for
inclusion in a future version?

Thanks!

/* Steinar */
-- 
Homepage: http://www.sesse.net/
*** /usr/lib/perl5/SNMP.pm	2009-10-29 17:05:23.000000000 +0100
--- include/SNMP.old.pm	2014-04-01 00:29:08.418112879 +0200
***************
*** 790,811 ****
  
      $vbl = $_[$#_] if ($state->{'options'}{'callback'});
  
!     while ($#$vbl > -1 && !$this->{ErrorNum}) {
! 	if (($#$vbl + 1) % ($#{$state->{'stopconds'}} + 1) != 0) {
! 	    if ($vbl->[$#$vbl][2] ne 'ENDOFMIBVIEW') {
! 		# unless it's an end of mib view we didn't get the
! 		# proper number of results back.
! 		print STDERR "ack: gettable results not appropriate\n";
! 	    }
! 	    my @k = keys(%{$state->{'result_hash'}});
! 	    last if ($#k > -1);  # bail with what we have
! 	    return;
! 	}
! 
! 	$state->{'varbinds'} = [];
! 	my $newstopconds;
  
! 	my $lastsetstart = ($state->{'repeatcount'}-1) * ($#{$state->{'stopconds'}}+1);
  
  	for (my $i = 0; $i <= $#$vbl; $i++) {
  	    my $row_oid = SNMP::translateObj($vbl->[$i][0]);
--- 790,800 ----
  
      $vbl = $_[$#_] if ($state->{'options'}{'callback'});
  
!     my $num_vbls = scalar @$vbl;
!     my $num_stopconds = scalar @{$state->{'stopconds'}};
  
!     while ($num_vbls > 0 && !$this->{ErrorNum}) {
! 	my @found_eof = (0) x $num_stopconds;
  
  	for (my $i = 0; $i <= $#$vbl; $i++) {
  	    my $row_oid = SNMP::translateObj($vbl->[$i][0]);
***************
*** 814,822 ****
  	    my $row_value = $vbl->[$i][2];
  	    my $row_type = $vbl->[$i][3];
  
! 	    if ($row_oid =~ 
! 		/^$state->{'stopconds'}[$i % ($#{$state->{'stopconds'}}+1)]/ &&
! 		$row_value ne 'ENDOFMIBVIEW' ){
  
  		if ($row_type eq "OBJECTID") {
  
--- 803,813 ----
  	    my $row_value = $vbl->[$i][2];
  	    my $row_type = $vbl->[$i][3];
  
! 	    my $stopcond_num = $i % $num_stopconds;
! 	    my $stopcond = $state->{'stopconds'}[$stopcond_num];
! 	    if ($row_oid !~ /^\Q$stopcond\E/ || $row_value eq 'ENDOFMIBVIEW') {
! 		$found_eof[$stopcond_num] = 1;
! 	    } else {
  
  		if ($row_type eq "OBJECTID") {
  
***************
*** 827,852 ****
  
  		}
  
  		# Place the results in a hash
  
  		$state->{'result_hash'}{$row_index}{$row_text} = $row_value;
  
! 		# continue past this next time
! 		if ($i >= $lastsetstart) {
! 		    push @$newstopconds,
! 		      $state->{'stopconds'}->[$i%($#{$state->{'stopconds'}}+1)];
! 		    push @{$state->{'varbinds'}},[$vbl->[$i][0],$vbl->[$i][1]];
! 		}
  	    }
  	}
! 	if ($#$newstopconds == -1) {
  	    last;
  	}
! 	if ($#{$state->{'varbinds'}} == -1) {
! 	    print "gettable ack.  shouldn't get here\n";
! 	}
  	$vbl = $state->{'varbinds'};
- 	$state->{'stopconds'} = $newstopconds;
  
          #
          # if we've been configured with a callback, then call the
--- 818,847 ----
  
  		}
  
+ 		# continue past this next time
+ 
+ 		$state->{'varbinds'}[$stopcond_num] = [ $row_text, $row_index ];
+ 
  		# Place the results in a hash
  
  		$state->{'result_hash'}{$row_index}{$row_text} = $row_value;
+ 	    }
+ 	}
  
! 	my @newstopconds = ();
! 	my @newvarbinds = ();
! 	for (my $i = 0; $i < $num_stopconds; ++$i) {
! 	    unless ($found_eof[$i]) {
! 		push @newstopconds, $state->{'stopconds'}[$i];
! 		push @newvarbinds, $state->{'varbinds'}[$i];
  	    }
  	}
! 	if ($#newstopconds == -1) {
  	    last;
  	}
! 	$state->{'varbinds'} = \@newvarbinds;
! 	$state->{'stopconds'} = \@newstopconds;
  	$vbl = $state->{'varbinds'};
  
          #
          # if we've been configured with a callback, then call the
------------------------------------------------------------------------------
_______________________________________________
Net-snmp-coders mailing list
Net-snmp-coders@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/net-snmp-coders

Reply via email to