• February 11, 2012, 09:37:02 AM
Welcome, Guest. Please login or register.
Did you miss your activation email?

Author Topic: trying Build a MAC address DB  (Read 2868 times)

0 Members and 2 Guests are viewing this topic.

Offline merrittr

  • Rookie
  • **
  • Posts: 12
trying Build a MAC address DB
« on: January 14, 2010, 05:11:37 PM »
Hi


I would like to be able to query a bunch of Nortel BS 5510 5520 BayStack-460 and dump the "CAM" table
so I can build a DB and spot new macs as they come up. Is this possible can I list all the MACs on each port of a switch using perl and SNMP???


Online Michael McNamara

  • Administrator
  • Hero Member
  • *****
  • Posts: 2164
    • Michael McNamara
Re: trying Build a MAC address DB
« Reply #1 on: January 14, 2010, 05:51:07 PM »
Hi Merrit and welcome to the forums!

You can most certainly poll the ERS 5500 series and BayStack 460 switch for the FDB/MAC(CAM) table and build a table of results.

You should be able to just look at the standard enterprise MIBS, no need for Nortel proprietary MIBS.

I would suggest you start with dot1dTpFdbTable and work from there. If you have additional questions please ask. I already have a script that does exactly what you are looking to-do by polling the ARP and FDB(MAC) tables from the switches and then building a database where we can track devices.

You can specifically look at dot1dTpFdbAddress, dot1dTpFdbPort and dot1dTpFdbStatus. You should be able to walk (SNMP) those variables and get some output from your switches. Then you just need to code up some perl to organize and store the data for you.

Good Luck!
If you've found this site useful and helpful, please help me spread the word. Link to us in your blog or homepage or Tweet about us! - Thanks!

Offline merrittr

  • Rookie
  • **
  • Posts: 12
Re: trying Build a MAC address DB
« Reply #2 on: January 14, 2010, 05:53:10 PM »
thanks Mike

Can you send me that script?

Online Michael McNamara

  • Administrator
  • Hero Member
  • *****
  • Posts: 2164
    • Michael McNamara
Re: trying Build a MAC address DB
« Reply #3 on: January 14, 2010, 07:08:34 PM »
Unfortunately the script has a lot of code and documentation that would not be suitable for public consumption.

You can look at my blog under Scripting; http://blog.michaelfmcnamara.com/scripting/ for passportarp.pl. That's a good example of how simple the code can be.

Here's some code that should help, this code will walk (snmpgetnext) the switch polling the FDB/MAC table;

Code: [Select]
#######################################################################
# Subroutine get_BoSS_fdb
#
# Purpose: retrieve MAC/FDB table from Nortel (BoSS) switch using SNMP MIB-2 dot1dTpFdbTable
#######################################################################
sub get_BoSS_fdb {

   #Declare Local Variables
   my $flag;

   $sess = new SNMP::Session (  DestHost   =>  $snmphost,
                                Community  =>  $community,
                                Retry      =>  RETRIES,
                                Timeout    =>  TIMEOUT,
                                Version    =>  SNMPVER );

   our $vars = new SNMP::VarList(['dot1dTpFdbAddress', 0],
                                 ['dot1dTpFdbPort', 0],
                                 ['dot1dTpFdbStatus', 0] );

   while (1) {

      @vals = $sess->getnext($vars);    # retreive SNMP information

      last unless ($vars->[0]->tag eq 'dot1dTpFdbAddress');  # if we've walked outside of SNMP MIB let's stop

      my $temp1 = $vars->[0]->tag;

      $vals[0] =~ s/\n//g;
      $vals[0] =~ s/"//g;
      $vals[0] =~ s/ //g;

      print "DEBUG: $temp1 $vals[0] $vals[1] $vals[2]\n" if ($DEBUG);

      # Ignore any ports which could be uplinks/downlinks to other switches
      $flag = 0;
      for my $port (@nnmports) {
         if ($port == $vals[1]) {
            $flag=1;
            print "DEBUG: NNM port detected, skipping $vals[1]\n" if ($DEBUG);
         }
      }
      next if $flag;

      # Ignore any ports which could be SMLT links to other switches
      $flag = 0;
      for my $port (@smltports) {
         #print "DEBUG: checking for ifNum=$vals[1] in smltport=$port\n" if ($DEBUG);
         #$flag = 1 if $port =~ /$vals[1]/;
         if ($port == $vals[1]) {
            $flag=1;
            print "DEBUG: SMLT port detected, skipping $vals[1]\n" if ($DEBUG);
         }
      }
      next if $flag;

      # Check the ifIndex value before proceeding
      if ($vals[1] < 1024) {
         # Let's count only the ifNums that are below 1024

         ($card, $port) = get_cardport($vals[1]);

         if ($vals[1] < 10) { $vals[1] = "0".$vals[1] }
         if ($vals[1] < 100 ) { $vals[1] = "0".$vals[1] }

         print "DEBUG: storing $snmphost, $vals[0], $vals[1], ($card/$port), $vals[2], 0\n" if ($DEBUG);
         print OUTPUTFILE "$snmphost, $vals[0], $vals[1], ($card/$port), $vals[2], 0\n";

      } else {
         # If we're going to skip the ifNum let's report it
         print "DEBUG: skipping port $vals[1]\n" if ($DEBUG);

      }#end if

      # We've had issues with CPU utilization if we poll the switches too hard,
      # so we'll throttle the rate of our SNMPGETNEXT commands by pausing in
      # between each by 100ms

      usleep(100);

   } #end while

   return 1;

} #end sub#######################################################

Good Luck!
If you've found this site useful and helpful, please help me spread the word. Link to us in your blog or homepage or Tweet about us! - Thanks!

Offline merrittr

  • Rookie
  • **
  • Posts: 12
Re: trying Build a MAC address DB
« Reply #4 on: January 15, 2010, 02:08:54 PM »
Thats great Mike

one thing though I am getting this error

subroutine &main::get_cardport called at ./walk.pl line 70.

         ($card, $port) = get_cardport($vals[1]);
also those OID dont seem to be defined for me since

root@PARUS:/scripts/SNMP# snmpwalk -v 2c -c public 172.17.151.200 dot1dTpFdbAddress
dot1dTpFdbAddress: Unknown Object Identifier (Sub-id not found: (top) -> dot1dTpFdbAddress)
root@PARUS:/scripts/SNMP# snmpwalk -v 2c -c public 172.17.151.200 dot1dTpFdbPort
dot1dTpFdbPort: Unknown Object Identifier (Sub-id not found: (top) -> dot1dTpFdbPort)
root@PARUS:/scripts/SNMP# snmpwalk -v 2c -c public 172.17.151.200 dot1dTpFdbStatus
dot1dTpFdbStatus: Unknown Object Identifier (Sub-id not found: (top) -> dot1dTpFdbStatus)


any ideas on those 2 problems?

Online Michael McNamara

  • Administrator
  • Hero Member
  • *****
  • Posts: 2164
    • Michael McNamara
Re: trying Build a MAC address DB
« Reply #5 on: January 15, 2010, 02:42:28 PM »
Yes... this brings back memories, some ugly. The subroutine get_cardport is a one that I wrote in the script. It determines the card and port information given the ifNum value from the SNMP query.

Here's the code for it; please note that I'm use Nortel SNMP MIB values in the code, if you wish to use the code you'll need to load the Nortel SNMP MIBS into your MIBS directory.

Code: [Select]
############################################################################
# Subroutine get_cardport
#
# Purpose: return card/port from ifIndex value based on sysObjectID
############################################################################
sub get_cardport
{
   # Declare Local Variables
   my $xifnum = $_[0];  # ifIndex value passed to subroutine`
   #my $msg = $_[1];

   my $xcard;           # Local variable for card assignment
   my $xport;           # Local variable for port assignment

   # Nortel Ethernet Routing Switch 8600 and 1600
   if ( ($sysObjectID eq "rcA8610") ||
        ($sysObjectID eq "rcA8606") ||
        ($sysObjectID eq "rcA1648")
      ) {
      $xcard = int($xifnum/64);
      $xport = ($xifnum - ($xcard * 64) + 1);

   # Nortel Ethernet Switch 470/5510/5520/5530
   } elsif ( ($sysObjectID eq "sreg-BayStack470-48T-ethSwitchNMM") ||
             ($sysObjectID eq "sreg-BayStack470-24T-ethSwitchNMM") ||
             ($sysObjectID eq "sreg-BayStack5510-48T-ethSwitchNMM") ||
             ($sysObjectID eq "sreg-BayStack5510-24T-ethSwitchNMM") ||
             ($sysObjectID eq "sreg-EthernetRoutingSwitch5530-24TFD") ||
             ($sysObjectID eq "sreg-BayStack5520-48T-PWR")
           ) {
      $xcard = int($xifnum/64);
      $xport = ($xifnum - ($xcard * 64) );
      $xcard++;
   # Nortel BPS2000/350/450/460 Switch
   } elsif ( ($sysObjectID eq "BPS2000-24T-ethSwitchNMM") ||
             ($sysObjectID eq "sreg-BPS2000-24T-ethSwitchNMM") ||
             ($sysObjectID eq "sreg-BayStack460-24T-PWR-ethSwitchNMM") ||
             ($sysObjectID eq "sreg-BayStack450-ethSwitchNMM" ) ||
             ($sysObjectID eq "sreg-BayStack350-24T-ethSwitchNMM")
           ) {
      $xcard = int($xifnum / 32);
      $xport = ( $xifnum - ($xcard * 32) );
      $xcard++;

   # HP GbE2 Ethernet Switch Interconnect - Blade Infrastructure
   } elsif ( $sysObjectID eq "hpProLiant-p-GbE2-InterconnectSwitch") {
      $xcard = 1;
      ##$xport = $xifnum - 256;
      $xport = $xifnum;

   # Cisco Catalyst Switches
   } elsif ( ( $sysObjectID eq "catalyst295024G") ||
             ( $sysObjectID eq "catalyst295048G") ||
             ( $sysObjectID eq "workgroup.44") ){
      $xcard = 0;
      $xport = $xifnum;
   } else {
      die "ERROR: unable to determine ifIndex conversion from $snmphost($sysObjectID)\n";

   } #end if

   return ($xcard, $xport);

} #end sub

Are you sure you have all the SNMP mibs? I would suggest try configuring the MIBS environment variable before you execute the command; type the following command 'export MIBS=ALL' before you try your SNMP walk.

Good Luck!

If you've found this site useful and helpful, please help me spread the word. Link to us in your blog or homepage or Tweet about us! - Thanks!

Offline merrittr

  • Rookie
  • **
  • Posts: 12
Re: trying Build a MAC address DB
« Reply #6 on: January 15, 2010, 02:57:25 PM »
Thanks Mike

Sorry to be a dummy but how do I load those mibs , or rather where do I get the MIB files and where do I put them?

Offline merrittr

  • Rookie
  • **
  • Posts: 12
Re: trying Build a MAC address DB
« Reply #7 on: January 15, 2010, 06:16:10 PM »
one other thing

could I just sub in the OIDs like this?

   our $vars = new SNMP::VarList(['.1.3.6.1.2.1.17.4.3.1.1', 0],
                                 ['.1.3.6.1.2.1.17.4.3.1.2', 0],
                                 ['.1.3.6.1.2.1.17.4.3.1.3', 0] );


print "DEBUG: outsidei \n";

   while (1) {

print "DEBUG: inside \n";

      @vals = $sess->getnext($vars);    # retreive SNMP information
print $vars->
  • ->tag."\n";

      last unless ($vars->
  • ->tag eq '.1.3.6.1.2.1.17.4.3.1.1');  # if we've walked outside of SNMP MIB let's stop



Online Michael McNamara

  • Administrator
  • Hero Member
  • *****
  • Posts: 2164
    • Michael McNamara
Re: trying Build a MAC address DB
« Reply #8 on: January 15, 2010, 09:09:26 PM »
You can download the SNMP mibs for each product/switch from the Nortel website. You'll also find a great many of the SNMP mibs already on a PC if you have Nortel's Java Device Manager installed.

You can call the OIDs using their numeric format but that is really ugly in my opinion.

Assuming that you are using Linux (I use CentOS) you can install the following net-snmp packages;

net-snmp.i386 : A collection of SNMP protocol tools and libraries.
net-snmp-devel.i386 : The development environment for the NET-SNMP project.
net-snmp-libs.i386 : The NET-SNMP runtime libraries.
net-snmp-perl.i386 : The perl NET-SNMP module and the mib2c tool.
net-snmp-utils.i386 : Network management utilities using SNMP, from the NET-SNMP project.

Then you should find the SNMP mibs under /usr/share/snmp/mibs

If you set the proper variables in the Perl script you should be able to call the standard SNMP MIBS by their name as opposed to their numeric format.

Code: [Select]
# SNMP Settings
$SNMP::verbose = 0;
$SNMP::use_enums = 1;
$SNMP::use_sprint_value = 1;
&SNMP::initMib();
&SNMP::loadModules('ALL');

Have you ever written a Perl application that makes SNMP queries? If you have then it should be pretty easy to adopt that code, if you haven't then you need to build the base and then work from there.

Good Luck!
« Last Edit: January 15, 2010, 09:11:04 PM by Michael McNamara »
If you've found this site useful and helpful, please help me spread the word. Link to us in your blog or homepage or Tweet about us! - Thanks!

Offline merrittr

  • Rookie
  • **
  • Posts: 12
Re: trying Build a MAC address DB
« Reply #9 on: February 12, 2010, 08:40:10 AM »
Hi Mkke

One last dumb question
I get this error are the *.my mibs you built?

root@PARUS:/scripts/SNMP# ./getmac.pl 172.16.3.200 public
CISCO-SMI.my: No such file or directory
FDDI-SMT73-MIB.my: No such file or directory
CISCO-STACK-MIB.my: No such file or directory
CISCO-SMI.my: No such file or directory
Unknown Object Identifier at ./getmac.pl line 22.


Online Michael McNamara

  • Administrator
  • Hero Member
  • *****
  • Posts: 2164
    • Michael McNamara
Re: trying Build a MAC address DB
« Reply #10 on: February 12, 2010, 10:32:49 AM »
With the global SNMP options you added to your script your now seeing some general Net-SNMP warnings. They can be ignored but if you want to clean them up you need to check your SNMP repository (should be in /usr/share/snmp/mibs by default). Check that directory and remove any of the .my files that aren't real SNMP MIBs.

That error that stops your script is "Unknown Object Identifier" on line 22. The OID that you are using on line 22 isn't being recognized as valid.

Good Luck!
If you've found this site useful and helpful, please help me spread the word. Link to us in your blog or homepage or Tweet about us! - Thanks!

Offline merrittr

  • Rookie
  • **
  • Posts: 12
Re: trying Build a MAC address DB
« Reply #11 on: February 16, 2010, 09:34:17 AM »
Hi Mike,

Contrary to my last post where I said I had one last dumb question...I have another

$sysObjectID seems to be undefined not sure where I should be getting it so I drop through to the error
ERROR: unable to determine ifIndex conversion from ()



# Cisco Catalyst Switches
   } elsif ( ( $sysObjectID eq "catalyst295024G") ||
             ( $sysObjectID eq "catalyst295048G") ||
             ( $sysObjectID eq "workgroup.44") ){
      $xcard = 0;
      $xport = $xifnum;
   } else {
      die "ERROR: unable to determine ifIndex conversion from $snmphost($sysObjectID)\n";




sub get_cardport
{
   # Declare Local Variables
   my $xifnum = $_[0];  # ifIndex value passed to subroutine`
   #my $msg = $_[1];

   my $xcard;           # Local variable for card assignment
   my $xport;           # Local variable for port assignment

print "DEBUG: subroutine1 $xifnum \n";
print "DEBUG: subroutine2 $sysObjectID \n";

   # Nortel Ethernet Routing Switch 8600 and 1600
   if ( ($sysObjectID eq "rcA8610") ||
        ($sysObjectID eq "rcA8606") ||
        ($sysObjectID eq "rcA1648")
      ) {
      $xcard = int($xifnum/64);
      $xport = ($xifnum - ($xcard * 64) + 1);

   # Nortel Ethernet Switch 470/5510/5520/5530
   } elsif ( ($sysObjectID eq "sreg-BayStack470-48T-ethSwitchNMM") ||
             ($sysObjectID eq "sreg-BayStack470-24T-ethSwitchNMM") ||
             ($sysObjectID eq "sreg-BayStack5510-48T-ethSwitchNMM") ||
             ($sysObjectID eq "sreg-BayStack5510-24T-ethSwitchNMM") ||
             ($sysObjectID eq "sreg-EthernetRoutingSwitch5530-24TFD") ||
             ($sysObjectID eq "sreg-BayStack5520-48T-PWR")
           ) {

Online Michael McNamara

  • Administrator
  • Hero Member
  • *****
  • Posts: 2164
    • Michael McNamara
Re: trying Build a MAC address DB
« Reply #12 on: February 16, 2010, 09:30:56 PM »
In a previous subroutine we poll the switch to get various pieces of information, including checking that the switch is reachable and online. The SNMP MIB sysObjectID is one of the MIB values we poll and store in a global variable $sysObjectID. We do this so we can tell what type of switch we are dealing with and how we should treat the different values.

Here's the subroutine that fills in those values;
Code: [Select]
###################################################################
# Subroutine grab_snmpsystem
#
# Purpose: perform SNMP query against device and return sysObjectID
###################################################################
sub grab_snmpsystem {

   # DEBUG
   print "DEBUG: IN grab_snmpsystem VAR snmphost = $snmphost\n" if ($DEBUG);

   # Let's create a new SNMP session and object using global variables
   my $grab_sess = new SNMP::Session (  DestHost  =>  $snmphost,
                                       Community  =>  $community,
                                         Version  =>  SNMPVER );

   # SNMP OIDs
   my $grab_vars = new SNMP::VarList(
                                ['sysDescr', 0],
                                ['sysObjectID', 0],
                                ['sysUpTime', 0],
                                ['sysContact', 0],
                                ['sysName', 0],
                                ['sysLocation', 0],
                                ['s5AgInfoVer',0] );

   # DEBUG
   print "DEBUG: snmphost = $snmphost and community = $community\n" if ($DEBUG);

   # Let's actually retrieve some information
   my @grab_vals = $grab_sess->get($grab_vars);   

   # If there was an error let's catch that and output an error
   if ( $grab_sess->{ErrorStr} ) {
      print "ERROR: sess->{ErrorStr} = $grab_sess->{ErrorStr}\n";
   }

   # If we don't get any values from the sysObjectID let's assume that we are
   # unable to poll the switch for whatever reason and return errorlevel 99 (abort)
   if ($grab_vals[0] eq "") {
        print "ERROR: Unable to poll the switch $snmphost. !!!\n";
        return 99;
   }

   # Let's assign the variables from the array
   $sysDescr = $grab_vals[0];
   $sysObjectID = $grab_vals[1];
   $sysUpTime = $grab_vals[2];
   $sysContact = $grab_vals[3];
   $sysName = $grab_vals[4];
   $sysLocation = $grab_vals[5];
   $sysSoftware = $grab_vals[6];

   # Old hack when using numeric OIDs, should be removed
   $sysObjectID =~ s/.1.3.6.1.4.1/enterprises/;

   # DEBUG
   print "DEBUG: $snmphost sysObjectID = $sysObjectID \n" if ($DEBUG);

   return 1;
};
#end sub grab_snmpsystem ########################################

Let me spend a little time sanitizing the script and I'll post it here in it's entirety. You may not want/need to use it in it's entirety but it should be helpfully enough so you can code your own solution.

Cheers!
If you've found this site useful and helpful, please help me spread the word. Link to us in your blog or homepage or Tweet about us! - Thanks!

Offline merrittr

  • Rookie
  • **
  • Posts: 12
Re: trying Build a MAC address DB
« Reply #13 on: February 17, 2010, 05:07:02 PM »
Hey Mike I think it is working

root@PARUS:/scripts/SNMP# ./walk.pl 172.17.136.1 public
DEBUG: IN grab_snmpsystem VAR snmphost = 172.17.136.1
DEBUG: snmphost = 172.17.136.1 and community = public
DEBUG: 172.17.136.1 sysObjectID = sreg-BayStack5510-24T-ethSwitchNMM
DEBUG: dot1dTpFdbAddress 0:0:50:e:ed:4a 24 learned
DEBUG: storing 172.17.136.1, 0:0:50:e:ed:4a, 024, (1/24), learned, 0
DEBUG: dot1dTpFdbAddress 0:0:50:e:ed:4c 24 learned
DEBUG: storing 172.17.136.1, 0:0:50:e:ed:4c, 024, (1/24), learned, 0

this looks like its getting the MAC for each port on the switch?

what I am looking for is to compile a list of all pc, VOIP sets that are connected to the switch

maybe I can do it just parseing the output from snmpwalk?
what is the nortel equivilent t snmpwalk a 5520 or 460 switch 

%snmpwalk -c public crumpy .1.3.6.1.4.1.9.9.46.1.3.1.1.2
%snmpwalk -c public@1 crumpy vtpVlanState

maybe if I get that I can do this
http://www.cisco.com/en/US/tech/tk648/tk362/technologies_tech_note09186a00801c9199.shtml

Online Michael McNamara

  • Administrator
  • Hero Member
  • *****
  • Posts: 2164
    • Michael McNamara
Re: trying Build a MAC address DB
« Reply #14 on: February 17, 2010, 08:33:55 PM »
Great job!

Hopefully you konw that VTP is proprietary to Cisco (so it won't work on any Nortel switches) but you can certainly walk the Nortel SNMP MIBS and there's tons of information available through the MIBS.

I use the script to record/store the MAC address of all edge devices. If someone calls with an issue I can quickly search for the MAC address and locate the port which they are connected to without physically going to look at the data jack and patch panel and without having to manually document it which becomes a nightmare to maintain.

I still use it just with flat file output but you could definitely adopt the script to output to a MySQL table and then index the table and then write a Perl/PHP web based application around the whole thing giving it a really clean look at feel. There's just never enough free time to 'clean up' the code and make it pretty.

I'll try to sanitize the whole script and I'll update this thread when I've posted it up somewhere.

Good Luck!
If you've found this site useful and helpful, please help me spread the word. Link to us in your blog or homepage or Tweet about us! - Thanks!