Note that there are some explanatory texts on larger screens.

plurals
  1. POPerl / Net::SNMP : script too slow, need to optimize
    primarykey
    data
    text
    <p><br> I would like to optimize my perl script because it is a bit slow for displaying informations about the network.<br> I don't know what can be changed or ameliorated to boost the script execution.<br> I manipulate several hashes, to get : mac add, index, etc... I think it's a bit heavy, but no other choice.<br> Moreover, I do a lot of SNMP request and the handling of errors is maybe not great.<br> I copy/paste my script and its module.<br> Thanks in advance for reading my code. </p> <p>It takes in args : </p> <ol> <li>interface name (ex. FastEthernet0/9 or FastEthernet0/1...)</li> <li>hostname : ip of the switch</li> <li>community (often =public) </li> </ol> <p>Hope this is comprehensible. </p> <pre><code> #!/usr/bin/perl use strict; use warnings; use Getopt::Long; use SnmpUtil; use AdresseMac; use Net::SNMP; use Net::SNMP::Interfaces; my $ifname; my $hostname; my $community; my $version = 1; GetOptions( "ifname=s" =&gt; \$ifname, "host=s" =&gt; \$hostname, "community=s" =&gt; \$community, "protocol:s" =&gt; \$version); my $interfaces = Net::SNMP::Interfaces-&gt;new(Hostname =&gt; $hostname, Community =&gt; $community); my $inter = $interfaces-&gt;interface($ifname); #Get interface $ifname my $ifindex = $inter-&gt;index(); #Vitesse my $vitesse = $inter-&gt;ifHighSpeed(); #Alias my $ifalias = $inter-&gt;ifAlias(); #Seek for VLANs my $vlan_trouve; #Listing all VLANS my $vmVlan = "1.3.6.1.4.1.9.9.68.1.2.2.1.2"; #OID of vlan table my $vlans = SnmpUtil-&gt;new($hostname, $community); my %vl = $vlans-&gt;requeteTable($vmVlan); $vlans-&gt;deconnexion(); #Get the good VLAN corresponding to index interface $vlan_trouve = $vl{$ifindex}; #Listing : port VLAN &lt;-&gt; @mac my $dot1dTpFdbAddress = "1.3.6.1.2.1.17.4.3.1.1"; my $dot = SnmpUtil-&gt;new($hostname, $community."@".$vlan_trouve); my %dot1address = $dot-&gt;requeteTable($dot1dTpFdbAddress); #Listing : numPortBridge &lt;-&gt; port VLAN my $dot1dTpFdbPort = "1.3.6.1.2.1.17.4.3.1.2"; my %portdot = reverse($dot-&gt;requeteTable($dot1dTpFdbPort)); #Listing : num Port bridge &lt;-&gt; ID port switch my $dot1dBasePortIfIndex = "1.3.6.1.2.1.17.1.4.1.2"; my %dotindex = reverse($dot-&gt;requeteTable($dot1dBasePortIfIndex)); #Duplex (auto, half or full) my $oid_cisco_duplex = "1.3.6.1.2.1.10.7.2.1.19.".$ifindex; my $duplex = $dot-&gt;requete($oid_cisco_duplex); if ($duplex==1) { $duplex= "Auto"; } elsif ($duplex==2) { $duplex = "Half"; } elsif ($duplex==3) { $duplex= "Full"; } #Close connection $dot-&gt;deconnexion(); #Go back up, to find mac add my $numportbridge = $dotindex{$ifindex}; if (!defined($numportbridge)) { print "Erreur : $ifindex not found in list : num Port bridge &lt;-&gt; ID port switch\n"; exit 2; } my $portVlan = $portdot{$numportbridge}; if (!defined($portVlan)) { print "Erreur : $numportbridge not found in list : numPortBridge &lt;-&gt; ports du VLAN\n"; exit 3; } my $add = uc($dot1address{$portVlan}); if (!defined($add)) { print "Erreur : $portVlan not found in list : ports du VLAN &lt;-&gt; \@mac\n"; exit 4; } $add =~ s/^0X//g; printf "&lt;b&gt;Port : $ifname&lt;/b&gt;&lt;br/&gt;Index $ifindex on VLAN : $vlan_trouve&lt;br/&gt;\@mac : $add&lt;br/&gt;Speed=$vitesse Mbps Alias=$ifalias&lt;br/&gt;Duplex: $duplex\n"; </code></pre> <p>Here's SnmpUtil.pm :</p> <pre><code>#!/usr/bin/perl use strict; use warnings; use Net::SNMP; package SnmpUtil; our ($session, $error); sub new { my ($classe, $hostname, $community) = @_; my $this = { "hostname" =&gt; $hostname, "community" =&gt; $community }; bless($this, $classe); $this-&gt;{connexion} = $this-&gt;connexion; return $this; } sub connexion { my ($this) = @_; ($session, $error) = Net::SNMP-&gt;session( -hostname =&gt; $this-&gt;{hostname}, -community =&gt; $this-&gt;{community}, -version =&gt; "1", -timeout =&gt; 3, ); request_error_connexion() if (!defined($session)); } sub request_error_connexion { my ($this) = @_; print "Erreur : can't connect to host\n"; print "Erreur : $error\n"; if ($error =~ /The argument "-community" is unknown/) { # protocol SNMP version 3 not working exit 3; # code ret final = 3*256 = 768 } else { exit 1; # code retour final = 1*256 = 256 } } sub request_error { my ($this) = @_; print "Error : no answer from host\n"; printf "Erreur : %s\n",$session-&gt;error; if ($session-&gt;error =~ /No response from remote host/) { #host ok, bad community or host refuse connection $session-&gt;close; exit 2; # code retour final = 2*256 = 512 } else { #can not find table $session-&gt;close; exit 4; # code retour final = 4*256 = 1024 } } sub requeteTable { my ($this, $oid) = @_; my $result = $session-&gt;get_table( -baseoid =&gt; $oid ); request_error() if (!defined($result)); my %tab = (); foreach my $i (Net::SNMP::oid_lex_sort(keys %{$result})) { my $index = $i; $index =~ s/$oid.//; $tab{ $index } = $result-&gt;{$i}; #print $index."--".$result-&gt;{$i}."\n"; } return %tab; } sub requete { my ($this, $oid) = @_; my $result = $session-&gt;get_request($oid); request_error() if (!defined($result)); return $result-&gt;{$oid}; } sub deconnexion { my ($this) = @_; $session-&gt;close(); } 1; </code></pre> <p>AdresseMac.pm module is useless, it's just to convert dec to hex &amp; vice-versa.</p> <p>Thanks for your help,<br> big reward for the one who find optimization ;)</p> <p>PS: forgot to say, I work on cisco switch 2960.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload