Subject: | get_table returns some junk entries |
The attached file named GetArpNew.pl contains a program that reliably
demonstrates the problem. The comment at the top of the file describes
the problem. The program contains some hard-coded device names and a
community string that you'll have to change. I attached the output
of a run. It shows that get_table basically works, and works
without error when talking to some of my routers. When it fails,
some of the values in the table it returns are junk. Most of the
table is fine - it's just some entries that are junk. It produces
the same output on multiple runs.
Here's some details about my system:
$ perl -V
Summary of my perl5 (revision 5 version 8 subversion 4) configuration:
Platform:
osname=linux, osvers=2.6.15.6, archname=i386-linux-thread-multi
uname='linux ernie 2.6.15.6 #1 thu mar 16 13:11:55 est 2006 i686
gnulinux '
config_args='-Dusethreads -Duselargefiles -Dccflags=-DDEBIAN
-Dcccdlflags=-fPIC -Darchname=i386-linux -Dprefix=/usr
-Dprivlib=/usr/share/perl/5.8 -Darchlib=/usr/lib/perl/5.8
-Dvendorprefix=/usr -Dvendorlib=/usr/share/perl5
-Dvendorarch=/usr/lib/perl5 -Dsiteprefix=/usr/local
-Dsitelib=/usr/local/share/perl/5.8.4
-Dsitearch=/usr/local/lib/perl/5.8.4 -Dman1dir=/usr/share/man/man1
-Dman3dir=/usr/share/man/man3 -Dsiteman1dir=/usr/local/man/man1
-Dsiteman3dir=/usr/local/man/man3 -Dman1ext=1 -Dman3ext=3perl
-Dpager=/usr/bin/sensible-pager -Uafs -Ud_csh -Uusesfio -Uusenm
-Duseshrplib -Dlibperl=libperl.so.5.8.4 -Dd_dosuid -des'
hint=recommended, useposix=true, d_sigaction=define
usethreads=define use5005threads=undef useithreads=define
usemultiplicity=define
useperlio=define d_sfio=undef uselargefiles=define usesocks=undef
use64bitint=undef use64bitall=undef uselongdouble=undef
usemymalloc=n, bincompat5005=undef
Compiler:
cc='cc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS
-DDEBIAN -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE
-D_FILE_OFFSET_BITS=64',
optimize='-O2',
cppflags='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBIAN
-fno-strict-aliasing -I/usr/local/include'
ccversion='', gccversion='3.3.5 (Debian 1:3.3.5-13)', gccosandvers=''
intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t',
lseeksize=8
alignbytes=4, prototype=define
Linker and Libraries:
ld='cc', ldflags =' -L/usr/local/lib'
libpth=/usr/local/lib /lib /usr/lib
libs=-lgdbm -lgdbm_compat -ldb -ldl -lm -lpthread -lc -lcrypt
perllibs=-ldl -lm -lpthread -lc -lcrypt
libc=/lib/libc-2.3.2.so, so=so, useshrplib=true,
libperl=libperl.so.5.8.4
gnulibc_version='2.3.2'
Dynamic Linking:
dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
cccdlflags='-fPIC', lddlflags='-shared -L/usr/local/lib'
Characteristics of this binary (from libperl):
Compile-time options: MULTIPLICITY USE_ITHREADS USE_LARGE_FILES
PERL_IMPLICIT_CONTEXT
Built under linux
Compiled at May 10 2006 03:55:26
@INC:
/etc/perl
/usr/local/lib/perl/5.8.4
/usr/local/share/perl/5.8.4
/usr/lib/perl5
/usr/share/perl5
/usr/lib/perl/5.8
/usr/share/perl/5.8
/usr/local/lib/site_perl
.
The devices that I am accessing are Cisco routers.
If I can get past this bug, I'd like to replace SNMP_Session
with Net::SNMP throughout my program. It is faster than SNMP_Session.
One interesting thing: when I change the first argument from 'snmpv2'
to 'snmpv1', Net::SNMP is significantly slower than SNMP_Session. I
would've assumed that they'd run with similar times.
Subject: | GetArpNew.pl |
#!/usr/bin/perl -w
#
# GetArpWithNetSnmp.pl
#
# This program demonstrates a bug in the Net::SNMP Perl module.
#
# The program is a simplified version of a production program called
# GetArp.pl. The real GetArp program has been running successfully
# for years. It uses SNMP to retrieve ARP information from routers.
# It uses the SNMP_Session module to do the actual SNMP communication.
# The SNMP_Session module works fine, but it doesn't directly support
# GETBULK, or SNMPv3, and the API is cumbersome. The Net::SNMP module
# seems to be more popular and more current, and it supports GETBULK
# and SNMPv3, and it has a much more convenient API. I want to
# convert GetArp to use Net::SNMP. I want the basic function of
# GetArp to stay the same, except that it might run faster due to
# GETBULK suppert.
#
# I'm a suspicious person, so I wrote this progrom to test that
# Net::SNMP actually returns the same data as SNMP_Session. This
# program does the same SNMP access using both modules. The results
# should be the same. They aren't. Net::SNMP seems to have a bug.
#
# I've removed all the extraneous stuff that doesn't have to do with SNMP.
use strict;
use FindBin;
use lib $FindBin::Bin; # find modules in the same dir as this file
use lib "SNMP_Session-1.08/lib"; # find modules in SNMP lib directory
use SNMP_Session;
use BER;
use Net::SNMP 5.2.0 qw(:snmp);
use Data::Dumper;
use Time::HiRes;
sub GetRouterArpTableUsingSnmpSession ($$$) {
my $session = shift;
my $routername = shift;
my $Oid = shift;
print "Getting ARPs from $routername using SNMP_Session...\n";
my($nxt_oid, $bindings, $binding, $value);
my $orig_oid = encode_oid(split /\./, $Oid);
my $enoid = $orig_oid;
my %table = ();
my $counter = 0;
while ($session->getnext_request_response(($enoid))) {
$counter ++;
my $response = $session->pdu_buffer;
($bindings) = $session->decode_get_response ($response);
($binding, $bindings) = decode_sequence ($bindings);
($nxt_oid, $value) = decode_by_template ($binding, "%O%@");
last unless BER::encoded_oid_prefix_p($orig_oid, $nxt_oid);
my $p_oid = BER::pretty_oid $nxt_oid;
my @snmpid = split /\./, $p_oid;
my $mac='';
foreach (unpack "xxCCCCCC", $value) {
$mac = $mac . sprintf "%02x", $_;
}
my $ip = "$snmpid[12].$snmpid[13].$snmpid[14].$snmpid[15]";
$table{$ip} = $mac;
$enoid = $nxt_oid;
}
print "returning success, did $counter requests\n";
return (%table);
}
sub GetRouterArpTableUsingNetSnmp ($$$) {
my $Session = shift;
my $RouterName = shift;
my $Oid = shift;
print "Getting ARPs from $RouterName using Net::Snmp...\n";
my $Arps = $Session->get_table($Oid);
if (!defined($Arps)) {
my $tmp = $Session->error();
print "couldn't get SNMP values, $tmp\n";
}
my %table = ();
foreach my $RetOid (keys %{$Arps}) {
my $newoid = $RetOid;
$newoid =~ s/^\.1\.3\.6\.1\.2\.1\.3\.1\.1\.2\.\d+\.\d+\.//; # strip off the leading oid octets
my $newmac = $$Arps{$RetOid};
$newmac =~ s/^0x//; # strip aff the leading "0x"
$table{$newoid} = $newmac;
}
print "returning success\n";
return (%table);
}
#
# Main. ======================================================================
#
my @routers = ();
push @routers, 'blura';
push @routers, 'cg-voipr';
push @routers, 'cgra';
push @routers, 'cgrb';
push @routers, 'fl-voipr';
push @routers, 'flra';
push @routers, 'flrb';
push @routers, 'jef-voipr';
push @routers, 'jeffcor';
push @routers, 'marshallr';
push @routers, 'mlra';
push @routers, 'voip1r';
foreach my $RouterName (@routers) {
print "reading ARP table from $RouterName...\n";
my $Community = 'ncar-read';
my $Oid = '.1.3.6.1.2.1.3.1.1.2'; # the ARP table
#=============================================================================
# Try it using SNMP_Session
my ($seconds, $microseconds) = Time::HiRes::gettimeofday;
my $session = SNMP_Session->open($RouterName,
$Community,
161);
if (!$session) {
die "couldn't open SNMP session to $RouterName, returning\n";
}
my %Arp = GetRouterArpTableUsingSnmpSession($session, $RouterName, $Oid);
$session->close();
my $elapsed = Time::HiRes::tv_interval([$seconds, $microseconds]);
print "SNMP_Session took $elapsed seconds\n";
# print Dumper \%Arp;
#=============================================================================
# Try it using Net::SNMP
($seconds, $microseconds) = Time::HiRes::gettimeofday;
my ($Session, $Error) = Net::SNMP->session(
-version => 'snmpv2',
-timeout => 2,
-hostname => $RouterName,
-community => $Community
);
if (!defined($Session)) {
die "couldn't open SNMP session to $RouterName: $Error";
}
my %Arp2 = GetRouterArpTableUsingNetSnmp($Session, $RouterName, $Oid);
$Session->close;
my $elapsed = Time::HiRes::tv_interval([$seconds, $microseconds]);
print "Net::SNMP took $elapsed seconds\n";
# print Dumper \%Arp2;
#=============================================================================
# compare the results
foreach my $Ip (keys %Arp) {
if ($Arp{$Ip} ne $Arp2{$Ip}) {
my $tmp1 = $Arp{$Ip};
my $tmp2 = $Arp2{$Ip};
print "Arp{$Ip} = \"$tmp1\", NOT EQUAL TO Arp2{$Ip} = \"$tmp2\"\n";
}
}
}
Subject: | out.txt |
���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������