package Agent::BROCADE;
#<copyright>
# ----------------------------------------------------------
# Sun Proprietary/Confidential Code
# Copyright 2001, Sun Microsystems, Inc. All rights reserved.
# ----------------------------------------------------------
#</copyright>

#  $Name:  $ 
#  $Id: BROCADE.pm,v 1.46 2002/10/27 21:39:11 ccadieux Exp $

use strict;
use Agent;
use base 'Agent';
use Net::Telnet;
use Util;

sub isSelectable {"Brocade Silkworm"}

sub revision {'$Revision: 1.46 $'}
sub new {
  my($self) = Agent->new();

  bless ($self, 'Agent::BROCADE');
  return $self;
}
use vars qw($ERR);

  
sub RUN {
  my($agent,$ras_flag) = @_;
  my(%DONE, $HBA, $logfile, $r, @results);
  my( @all_connect_errors);
  my( @lux_dif, $dif, $xml, @all_dif);
  my($ev, @stats, $id, $log_lines, $sdt, $pdm);
  $pdm = $agent->{pdm};
  my($renv) = System->get_renv();

  $DB::single=1;
  Timelapse->start(ref($agent));

  my($today) = Util->today("YMDH");
  my($dc) = 0;

  foreach my $device ( $agent->deviceList()) {
    next if ($device->{active} eq "N"); 
    $dc++;
    Debug->print1("-> Brocade: Reading device $device->{name}: $device->{ip}");

    if (!$device->{ip}) {
        Debug->err( 'IP_NOT_FOUND',"Switch at $device->{name}" );
        next;
    }

    my($connect_errs, $wwn, $report) = $agent->read_brocade($device);
    $wwn = lc($wwn);
    if ($wwn && $wwn ne $device->{wwn}) {
       Debug->errNoRepeat(SWITCH_NEWIP => $device->{ipno}, 24, "wwn of brocade $device->{ipno} changed from $device->{wwn} to $wwn");
    }

    $id = {   accessName  => $device->{name},
              deviceName  => $device->{wwn},
              active      => $device->{active},
              display     => "$device->{name} (ip=$device->{ip})",
              class       => $device->{class},
              name        => $device->{name},
              category    => Report::CAT_BROCADE,
              ip          => $device->{ip},
           };

    $report = {} if (!$report);
    $agent->copyDev($device, $report);

    $device->{ipno} = Util->name2ip($device->{ip});
    $report->{"id.name"} = $device->{name};
    $report->{"id.ip"}   = $device->{ip};
    $report->{"id.ipno"} = $device->{ipno};

    if ($connect_errs || !$wwn) {
        $report->{'id.connect_errs'} = $connect_errs;
        $pdm->saveReport(
          Report->new($id, $report , [], Report::STATUS_CANNOT_CONNECT));

    } else {
        $pdm->saveReport(Report->new($id, $report , $log_lines));
    }
  }
  Debug->print2("  No devices found") if (!$dc);

  Timelapse->stop(ref($agent));
}

sub getWWN {
  my($class, $ip, $host, $TO) = @_;
  my $rc;
  $ERR = undef;
  if ($host) {
      $rc = Util::Http->getCommand($host, "Agent::BROCADE::WWN&ip=$ip&HTTP=1", $TO);
      if ($rc =~ /ERR/) {
         $ERR = $rc;
         return undef;
      } else {
         return substr($rc,4);
      }
  } else {
      return get_WWN({ip => $ip});
  }
}

sub get_WWN {
  my($q) = @_;
  my $ip = $q->{ip};
  my ($name, $wwn);
  my $DIR = System->get_home();

  my $mymodel = Agent::BROCADE->getModel($ip); 

  my $comm;

  if($mymodel =~ /1200/){
     $comm = "$DIR/snmp/bin/snmpwalk -r 0 -t 5 -m $DIR/snmp/share/snmp/mibs/v4/V4_0FE.mib -Os  $ip public fcFeElementName";
  }
  else{
     $comm = "$DIR/snmp/bin/snmpwalk -r 0 -t 5 -m all -Os  $ip public fcElementName";
  }
  my($err,$id) = Util->run_command($comm, "getWWN", 10);

  ($name, $wwn) = split(/ *= */, $id->[0]);
  $wwn = lc($wwn);
  $wwn =~ s/hex://; 
  $wwn =~ s/ //g;

  if ($q->{HTTP}) {
    if ($wwn) {
      print "\nOK $wwn";
    } else {
      print "\nERR $err";
    }
  } else {
    return $wwn;
  }
}


sub getDevStatus {
  my($class, $dev) = @_;
  my %R;
  $ENV{LD_LIBRARY_PATH} = System->get_home() . "/bin/lib";
  my $OPT;
  my $ip = $dev->{ipno};

  $ERR = $class->getStatusLinks($OPT, $dev, \%R);
  return ($ERR, \%R);
}


sub getStatusLinks {
  my($class, $OPT, $dev, $R) = @_;
  my($x, $err, $ports, $rem, $portids);
  my $DIR  = System->get_home() . "/snmp/bin";
  my($renv) = System->get_renv();
  my($TO) = $renv->{'timeout.snmp'} || 10;
  
  my $mymodel = Agent::BROCADE->getModel($dev->{ipno}); 
  if($mymodel =~ /1200/){
     # The 12000 brocade takes longer to complete because there is more information.
     # Increase timeout by 15
     $TO = $TO + 15;
  }
 
 
  my($MIBS) = System->get_home() . "/snmp/mibs";
  $OPT = "-t $TO -r 0 -m all -Ose ";

  ($err,$ports) = Util->run_command(
                 "$DIR/snmpwalk $OPT $dev->{ipno} public swFCPortCapacity", 
                 "sanbox_version.txt", $TO+5);

  my($l)  = $ports->[0];
  my(@a) = split(/ +\= */, $l);
  $R->{"port.count"} = $a[1];

  ($err,$rem) = Util->run_command(
                 "$DIR/snmpwalk $OPT $dev->{ipno} public swNbEntry", 
                 "sanbox_version.txt", $TO+5);

  my ($curr, @MAP, @index_array, $mycount, $remindex, $wwnindex);
  $mycount = 1;
  $remindex = 1;
  $wwnindex = 1;
  foreach my $l (@$rem) {
     if ($l =~ /swNbMyPort.\d+ = (\d+)/) {
       $curr = $1 - 1;
       $index_array[$mycount] = $curr;
       $mycount +=  1;

     } elsif ($l =~ /swNbRemPort\.\d = (\d+)/) {
       $R->{"port.$index_array[$remindex].link_port"} = $1 - 1;
       $remindex += 1;

     } elsif ($l =~ /swNbRemPortName\.\d =  Hex: (.*)/) {
       my $wwn = lc($1);
       $wwn =~ s/ //g;
       $R->{"port.$index_array[$wwnindex].link_wwn"} = "1000" . substr($wwn,4);
       $wwnindex += 1;

     }
  }

  ($err,$rem) = Util->run_command(
                 "$DIR/snmpwalk $OPT $dev->{ipno} public swNsLocalTable", 
                 "sanbox_version.txt", $TO+5);
  foreach my $l (@$rem) {
    my($n,$val) = split(/ = /, $l);
    my($f, $no) = split(/\./, $n);
    if (index("swNsPortID,swNsPortType,swNsPortName,swNsPortSymb,swNsNodeName",
            $f) >= 0) {
       if ($val =~ /Hex:/) {
         $val =~ s/Hex://;
         $val =~ s/ //g;
       } 
       $MAP[$no]{$f} = $val;
    }
  }
  

 # my($err,$rem) = Util->run_command(
 #                "$DIR/snmpwalk $OPT $dev->{ipno} public fcFxPortNxPortName", 
 #                "sanbox_version.txt", $TO+5);
 #
 # foreach my $l (@$rem) {
 #     my($f, $col, $port, $row, $wwn) = split(/[=\.]+/, $l);
 #     $port--;
 #     $wwn =~ s/Hex://;
 #     $wwn =~ s/ //g;
 #     if (!$R->{"port.$port.link_wwn"}) {
 #       $R->{"port.$port.link_wwn"} = lc($wwn);
 #     }
 # }


  # get WWN of devices attached to port

  # first get an array of ports and there id's
  my (@port_array);

  ($err,$portids) = Util->run_command(
                 "$DIR/snmpwalk $OPT $dev->{ipno} public swNsPortID", 
                 "sanbox_version.txt", $TO+5);

  foreach my $l (@$portids) {
      my($f, $entry, $wwn) = split(/[=\.]+/, $l);

      $wwn =~ s/Hex://;
      my($f0, $col, $zone, $port, $alpa) = split(/ +/, $wwn);
      #Entry now contains the port plus compatibility mode
      # only want the last digit.
      my $realport = substr($port,1) ; 
      $port_array[$entry] = hex($realport);

  }
  # now get attached WWN's 
  ($err,$portids) = Util->run_command(
                 "$DIR/snmpwalk $OPT $dev->{ipno} public swNsPortName", 
                 "sanbox_version.txt", $TO+5);

  foreach my $l (@$portids) {
      my($f, $entry, $wwn) = split(/[=\.]+/, $l);
      $wwn =~ s/Hex://;
      $wwn =~ s/ //g;

      if (!$R->{"port.$port_array[$entry].link_wwn"}) {
        $R->{"port.$port_array[$entry].link_wwn"} = lc($wwn);
      }

  }

  $OPT = "-t $TO -r 0 -m all -Os ";

  foreach my $el ('Type','State','Status') {

    my($err,$rem) = Util->run_command(
                 "$DIR/snmpwalk $OPT $dev->{ipno} public connUnitPort$el", 
                 "sanbox_version.txt", $TO+5);

    foreach my $l (@$rem) {
      my($f1, $f2) = split(/ = /, $l);
      my $ix = rindex($f1, ".");
      my $port = substr($f1,$ix+1) - 1;
      $ix = index($f2,"(");
      my $type = substr($f2,0,$ix);
      $R->{"port.$port." . lc($el)} = $type;
    }
  }
}

#./snmpwalk -m all  -t 30 -Os -M /opt/stade21/snmp/mibs 172.20.67.167 public connUnitPortT>
#connUnitPortType.'...`i ..........'.1 = g-port(10)
#connUnitPortType.'...`i ..........'.2 = f-port(8)
#connUnitPortType.'...`i ..........'.3 = g-port(10)
#connUnitPortType.'...`i ..........'.4 = e-port(9)
#connUnitPortType.'...`i ..........'.5 = g-port(10)
#connUnitPortType.'...`i ..........'.6 = other(2)
#connUnitPortType.'...`i ..........'.7 = f-port(8)
#connUnitPortType.'...`i ..........'.8 = fl-port(7)


# 1 = nport (hba (F_Port)), 2=nlport (storage (L_Port))
# s2s = E_Port

#./snmpwalk -m all  -Ose -M /opt/ras22/snmp/mibs 
#                   172.20.67.167 public  swNsLocalTable
# swNsEntryIndex.1 = 1
# swNsPortID.1 =  Hex: 00 01 11 00
# swNsPortType.1 = 1
# swNsPortName.1 =  Hex: 21 01 00 E0 8B 23 61 F
# swNsPortSymb.3 = "SUN     SENA            1.09"
# swNsNodeName.1 =  Hex: 20 01 00 E0 8B 23 61 F9


# HBA and A5K
#./snmpwalk -m all  -Ose -M /opt/ras22/snmp/mibs 
#                   172.20.67.167 public fcFxPortNxPortName
#fcFxPortNxPortName.1.2.1 =  Hex: 21 01 00 E0 8B 23 61 F9 
#fcFxPortNxPortName.1.7.1 =  Hex: 21 00 00 E0 8B 00 B5 06 
#fcFxPortNxPortName.1.8.2 =  Hex: 50 80 02 00 00 03 25 12 
#fcFxPortNxPortName.1.8.9 =  Hex: 21 00 00 20 37 04 98 B2 
#fcFxPortNxPortName.1.8.12 =  Hex: 21 00 00 20 37 04 9A D1 
#fcFxPortNxPortName.1.8.15 =  Hex: 21 00 00 20 37 0E FA 09 
#fcFxPortNxPortName.1.8.18 =  Hex: 50 80 02 00 00 03 25 11 
#fcFxPortNxPortName.1.8.25 =  Hex: 21 00 00 20 37 04 98 06 
#fcFxPortNxPortName.1.8.26 =  Hex: 21 00 00 20 37 04 9B C0 
#fcFxPortNxPortName.1.8.27 =  Hex: 21 00 00 20 37 04 9F 7A 
#fcFxPortNxPortName.1.8.28 =  Hex: 21 00 00 20 37 04 97 6F 
#fcFxPortNxPortName.1.8.29 =  Hex: 21 00 00 20 37 04 98 26 
#fcFxPortNxPortName.1.8.30 =  Hex: 21 00 00 20 37 04 98 C6 
#fcFxPortNxPortName.1.8.31 =  Hex: 21 00 00 20 37 04 98 1A 

# Switch2Switch
#./snmpwalk -m all  -Ose -M /opt/ras22/snmp/mibs 172.20.67.167  public swNbEntry
#swNbIndex.1 = 1
#swNbMyPort.1 = 4
#swNbRemDomain.1 = 3
#swNbRemPort.1 = 5
#swNbBaudRate.1 = 16
#swNbIslState.1 = 5
#swNbIslCost.1 = 1000
#swNbRemPortName.1 =  Hex: 20 04 00 60 69 10 71 25 


# T3
#./snmpwalk -m all  -Ose -M /opt/ras22/snmp/mibs 172.20.67.164 
#                           public fcFxPortNxPortName
#fcFxPortNxPortName.1.7.125 =  Hex: 50 02 0F 23 00 00 3D 2C 


sub getStats {
  my($class, $OPT, $ip, $R, $dev) = @_;

  my $DIR  = System->get_home() . "/snmp/bin";

  my($renv) = System->get_renv();
  my($TO) = $renv->{'timeout.snmp'} || 60;

  if($dev->{userLabel} =~ /12000/){
     $TO = $TO+60;
  }
 
  my($err4,$ports) = Util->run_command(
             "$DIR/snmpwalk $OPT $ip public fcSwitch.sw.swFCport", 
             "sanbox_version.txt", $TO+5);
  if ($err4) {
     Debug->print2("snmpwalk $ip: $err4");
     return undef;
  }

  my($l)  = $ports->[0];
  my(@a) = split(/ +\= */, $l);
  my($size) = $a[1];
  $R->{"port.count"} = $size;
  my($ERR_LIST) = ",RxTooLongs,LipOuts,RxBadEofs,RxBadOs,McastTimedOuts,LipIns,C3Discards,RxEncInFrs,RxCrcs,RxTruncs";

  my($x, $port, $name);
  for ($x=1; $x <= $#$ports; $x++) {
     my(@a) = split(/ +\= */, $ports->[$x]);
     $a[1] = substr($a[1],1,-1) if (substr($a[1],0,1) eq "\"");
     my($ix) = rindex($a[0], "-");
     $port = substr($a[0],$ix+1);
     $name = substr($a[0], 8);
     $ix = index($name, ".");
     $name = substr($name, 0, $ix);
     $a[1] =~ s/Counter\d\d\://;
     if (index(",AdmStatus,LinkState,PhyState,OpStatus,", ",$name,") >= 0) {
        $R->{"port.$port.state.$name"} =  $a[1];

     } elsif (index($ERR_LIST, ",$name,") >= 0) {
        $R->{"port.$port.error.$name"} =  $a[1];

     } else {
        $R->{"port.$port.stats.$name"} =  $a[1];
     }
  }
}


# snmpwalk  -O s -m all -M /opt/ras22/snmp/mibs 172.20.67.167 public swFirmwareVersion 

sub getVersion {
  my($agent, $ip) = @_;

  my($DIR) = System->get_home() . "/snmp/bin";
  my($renv) = System->get_renv();
  my($TO) = $renv->{'timeout.snmp'} || 10;

  my($MIBS) = System->get_home() . "/snmp/mibs";
  $ENV{LD_LIBRARY_PATH} = System->get_home() . "/bin/lib";
  my($OPT) = "-r 0 -t $TO -m all ";
  my $v = ".iso.3.6.1.4.1.1588.2.1.1.1.1.6.0";

  my($err0,$version) = Util->run_command("$DIR/snmpget $OPT $ip public $v", 
                      "sanbox_version.txt", $TO + 5);
  if ($err0) {
     $ERR = $err0;
     return undef;
  } else {
     my ($x, $y) = split(/\s*=\s*/, "@$version");
     if (substr($y,0,1) eq "\"") {
        $y = substr($y,1,-1);
     }
     return $y;
  }
}

sub getModel {
  my($agent, $ip) = @_;

  my $myversion = Agent::BROCADE->getVersion($ip); 

  if($myversion =~ /v2/){
     return "2x00 Brocade";
  }
  elsif($myversion =~ /v3/){
     return "3x00 Brocade";
  }
  elsif($myversion =~ /4./){
     return "12000 Brocade";
  }
  else{
     return "Brocade";
  }

}

sub read_brocade {
  my($agent, $device) = @_;
  my(@s, %dev, $in, %info);
  my($connect_err, %C);
  my($port,  $config, $err4);
  my(%R);
  my($ip)    = $device->{ip};
  my(@counts, @stats, $stat, $x);
  my($DIR)   = System->get_home() . "/snmp/bin";
  my($renv)  = System->get_renv();
  my($TO)    = $renv->{'timeout.snmp'};


  my $mymodel = Agent::BROCADE->getModel($ip); 
  if($mymodel =~ /1200/){
     # The 12000 brocade takes longer to complete because there is more information.
     # Increase timeout by 15
     $TO = $TO + 15;
  }
 

  my($MIBS)  = System->get_home() . "/snmp/mibs";
  $ENV{LD_LIBRARY_PATH} = System->get_home() . "/bin/lib";
  my($OPT)   = "-r 0 -t $TO -m all -Os ";

  my($err0,$system) = Util->run_command("$DIR/snmpwalk $OPT $ip public system", 
                      "sanbox_version.txt", $TO+5);

  if ($err0) {
     return ($err0, undef,undef);

  } elsif ("@$system" =~ /Timeout:/) {
     return ("@$system", undef,undef);
  }

  my($err3,$swsystem) = Util->run_command("$DIR/snmpwalk $OPT $ip public fcSwitch.sw.swSystem",
                       "sanbox_version.txt", $TO +5);



  my($err6,$san1) = Util->run_command("$DIR/snmpwalk $OPT $ip public fcFxPortNxPortName", 
                       "sanbox_version.txt", $TO+5);

  my($err8,$uptime) = Util->run_command("$DIR/snmpwalk $OPT $ip public sysuptime ", 
                       "sanbox_version.txt", $TO+5);



  if ($err0 || $err3 || $err4 || $err6  || $err8) {
    Debug->err(SNMP => "Cannot run snmp on $ip:$err0$err3$err4$err6$err8");
    return ("$err0$err3$err4$err6$err8","", undef) 
  }
# fcFxPortNxPortName.1.1.2 =  Hex: 21 00 00 E0 8B 03 09 26 

  
  foreach my $x (@$san1) {
     my(@a) = split(/ +\= */, $x);
     my(@b) = split(/\./, $a[0]);
     $port = $b[2] - 1;
     $R{"port.$port.attach.$b[3]"} =  $a[1];
  }

  foreach my $x (@$system) {
     my(@a) = split(/ +\= */, $x);
     $a[1] = substr($a[1],1,-1) if (substr($a[1],0,1) eq "\"");
     $a[0] = substr($a[0],0,-2) if (substr($a[0], -2) eq ".0");
     $a[1] =~ s/Counter\d\d\://;
     $R{"system.$a[0]"} =  $a[1];
  }

  my($sensor,  $name);
  my($max) = 0;
  my(@SENS, %CNT);
  foreach my $x (@$swsystem) {
     my(@a) = split(/ +\= */, $x);
     $a[1] = substr($a[1],1,-1) if (substr($a[1],0,1) eq "\"");
     $a[1] =~ s/Counter\d\d\://;
     if ($a[0] =~ /^swSensor/) {
        my($ix) = rindex($a[0], ".");
        $sensor = substr($a[0],$ix+1) + 0;
        $max = $sensor if ($sensor > $max);
        $name = substr($a[0], 0, $ix);
        $name = substr($name, 8);
        my $val = $a[1]; $val =~ s/\(\d+\)$//;
        if ($name eq "Type") {
            $CNT{$val}++;
            $SENS[$sensor] = "$val.$CNT{$val}";
        } elsif ($SENS[$sensor]) {
	    if (($SENS[$sensor] =~ /power-supply/) && $val =~ ("-2147483648") ) 
	    { 
	       # -2147483648 is really 0x80000000 which is okay
	       #$R{"sensor.$SENS[$sensor]." . lc($name)} = "N/A";
	       #Don't save this field since it doesn't tell the user anything
	    }
	    elsif (($SENS[$sensor] =~ /fan/) && $val =~ ("-2147483648") ) 
	    { 
	       # If the value for the fan is the -2..., it means that
	       # the fan isn't installed and this value has no meaning.
	       #$R{"sensor.$SENS[$sensor]." . lc($name)} = "N/A";

	       #Don't save this field since it doesn't tell the user anything

	    }
	    elsif (($SENS[$sensor] =~ /temperature/) && $val =~ ("-2147483648") ) 
	    { 
	       # If the value for the temperature is the -2..., it means that
	       # the temp isn't installed and this value has no meaning.
	       #$R{"sensor.$SENS[$sensor]." . lc($name)} = "N/A";

	       #Don't save this field since it doesn't tell the user anything

	    }
	    else{
               $R{"sensor.$SENS[$sensor]." . lc($name)} = $val;
	    }
        }
       
     } else {
       $a[0] = substr($a[0],0,-2) if (substr($a[0], -2) eq ".0");
       $R{"swSystem.$a[0]"} =  $a[1];
     }
  }

  $R{"sensor.count"} = $max;

  # Save system uptime
  foreach my $x (@$uptime) {
     my(@a) = split(/\(/, $x);
     my(@b) = split(/\)/, $a[1]);
     $R{"system.uptime"} =  $b[0];
  }


  
  $agent->getStats($OPT, $ip, \%R, $device);
  $agent->getStatusLinks($OPT, $device, \%R);

  $agent->addIdentification(\%R);

  $R{"id.wwn"} = $agent->getWWN($ip);

  if($R{"swSystem.swFirmwareVersion"} =~ /v2/){
     $R{"id.switch_type"} = "1 Gig Switch";
  }else{
     $R{"id.switch_type"} = "2 Gig Switch";
  }

  return (undef, $R{"id.wwn"}, \%R);
}


sub FCCounters {
  my($class,$arg) = @_;

  return $class->switchFCCounters("brocade", $arg);
}


sub FCfromDevice {
  my($class, $dev) = @_;
  my (%X, @R, $x);
  my $renv = System->get_renv();
  my $DIR = System->get_home() . "/snmp/bin";

  my($TO)    = $renv->{'timeout.snmp'};

  my($MIBS)  = System->get_home() . "/snmp/mibs";
  my($OPT)   = "-r 0 -t $TO -m all -Os ";
  my $ip = $dev->{ipno} || $dev->{ip};
  my ($inframes, $outframes);
  
  my $mymodel = Agent::BROCADE->getModel($ip); 
  if($mymodel =~ /1200/){
     # The 12000 brocade takes longer to complete because there is more information.
     # Increase timeout by 15
     $TO = $TO + 15;
  }

  my($err5,$errors) = Util->run_command(
      "$DIR/snmpwalk $OPT $ip public swFCPortRxCrcs",
      "sanbox_version.txt", $TO+5);

  my @CRC;
  for ($x=0; $x <= $#$errors; $x++) {
     my(@a) = split(/ +\= */, $errors->[$x]);
     my $ix = index($a[0], "portNum");
     my $port = substr($a[0],$ix+8);
     $a[1] =~ s/Counter\d\d\://;
     $CRC[$port] = $a[1];
  }

  ($err5,$errors) = Util->run_command(
      "$DIR/snmpwalk $OPT $ip public fibreChannel.fcFabric.fcFe.fcFeError", 
      "sanbox_version.txt", $TO+5);

  ($err5,$inframes ) = Util->run_command(
      "$DIR/snmpwalk $OPT $ip public swFCPortRxFrames", "sanbox_version.txt", $TO+5);

  ($err5,$outframes ) = Util->run_command(
      "$DIR/snmpwalk $OPT $ip public swFCPortTxFrames", "sanbox_version.txt", $TO+5);

  for ($x=0; $x <= $#$inframes; $x++) {
     my(@a) = split(/ +\= */, $inframes->[$x]);
     my $ix = rindex($a[0],"-");
     my $port = substr($a[0],$ix+1); 
     $a[1] =~ s/Counter\d\d\://;
     $R[$port]{Inframes} =  $a[1] + 0;
  }

  for ($x=0; $x <= $#$outframes; $x++) {
     my(@a) = split(/ +\= */, $outframes->[$x]);
     my $ix = rindex($a[0],"-");
     my $port = substr($a[0],$ix+1);
     $a[1] =~ s/Counter\d\d\://;
     $R[$port]{Outframes} =  $a[1] + 0;
  }

  my $max = 8;

  for ($x=1; $x <= $#$errors; $x++) {
     my(@a) = split(/ +\= */, $errors->[$x]);
     my $ix = rindex($a[0],".");
     my $port = substr($a[0],$ix+1) - 1;
     $a[1] =~ s/Counter\d\d\://;
     my $a0 = substr($a[0],0,$ix);
     $a0 =~ s/\./-/g;
     $R[$port]{$a0} =  $a[1] + 0;
     $max = $port if ($port > $max);
  }

  for ($x=0; $x <= $max; $x++) {
      my $key = "|$dev->{key}|port.$x|switch";
      next if (!defined($R[$x]));
      my $t = time;

      $X{$key} = ($R[$x]{'fcFxPortLinkFailures-1'}+0) . "\t" .
                 ($R[$x]{'fcFxPortSigLosses-1'}+0)    . "\t".
                 ($R[$x]{'fcFxPortPrimSeqProtoErrors-1'}+0) . "\t".
                 ($CRC[$x]+0) . "\t" .            #   $R[$x]{'fcFxPortInvalidCrcs-1'}  . "\t".
                 ($R[$x]{'fcFxPortSyncLosses-1'}+0)     . "\t".
                 ($R[$x]{'fcFxPortInvalidTxWords-1'}+0) . "\t" .
                 ($R[$x]{'Inframes'}+0)                 . "\t" .
                 ($R[$x]{'Outframes'}+0) ;

  }
  return {enc => {$dev->{wwn} => $dev->{name}} , data => \%X };

}


# fcFxPortNxPortName.1.1.2 =  Hex: 21 00 00 E0 8B 03 09 26 
# fcFxPortNxPortName.1.4.98 =  Hex: 50 80 02 00 00 08 3C B2 
# fcFxPortNxPortName.1.4.101 =  Hex: 21 00 00 20 37 45 04 E2 
# fcFxPortNxPortName.1.4.102 =  Hex: 21 00 00 20 37 45 0D 3A 
# fcFxPortNxPortName.1.4.103 =  Hex: 21 00 00 20 37 45 07 DE 

# swNsPortSymb.2 = "SUN     SENA            1.09"
# swNsPortSymb.3 = "SEAGATE ST39103FCSUN9.0G034A"

sub REPORT {
  my($class, $host, $r, $arg) = @_;

  my($out);
  my($v) = $r->{_value};

  my $last;
  $out = $class->reportHead("Brocade", $r);

  if(exists($v->{"id.connect_errs"})){
     print "<b><font color=red>NOTE: Errors were encountered when this report was generated. The data being displayed could be from an old report.</font></b>";
  }


  my $port;
  $out .= "
     <table border=0><tr><td></table>
     <table border=1 width=95% bgcolor=white cellspacing=0 cellpadding=0>
     <tr bgcolor=#CCCCFF><td><b>&nbsp;<th>Port</th><th>Admin State</th><th>Port State</th>";
     for ($port=0; $port < $v->{"port.count"}; $port++) {
        my $admstat = $v->{"port.$port.state.AdmStatus"};
        my $state = $v->{"port.$port.state"};
        my $bg = ($state eq "online")? "":"bgcolor=#FFFFD0";

        $out .= "<tr><td>&nbsp;$port</td><td>&nbsp;$admstat</td><td $bg>&nbsp;$state</td>";
     }
  $out .= "</table>&nbsp;<p>";


  foreach my $el (sort keys %$v) {
     if($el =~ /id.device_telnet/){
        #skip displaying password
        next;
     }
     if($el =~ /port\./){
      next;
     }
     my($a, $b) = split(/\./, $el);
     if ($a ne $last) {
        $out .= "<tr bgcolor=#CCCCFF><td colspan=2>&nbsp;<b>$a<th> <th></th></td>\n" if ($a);
        $last = $a;
     }

     $out .= "<tr><td>&nbsp;$el<td>&nbsp;$v->{$el}</td>";
  }
  $out .= "</table>";
  return $out;

}

sub getZones {
  my($class, $DIR, $s_ip, $TO, $V, $dev) = @_;
  my($err);
  my $totzones;
  $totzones = -1;
  my $password = Util->decode($dev->{telnet});
  my($err1,$info) = Util->run_command("$DIR/brocadezone $s_ip $password", "sanbox_status.txt", $TO);
  $err .= $err1;

  foreach my $l (@$info) {

     if ($l =~ /Zone Name/) {
        $totzones++;
     } elsif ($l =~ /Port = (\d+)/) {
        my $po = $1;
      
        $V->{"zone.hd.$totzones.members"} .= "$po ";
     }
     elsif( $l =~ /ERROR/)
     {
        $err .= "$l " ;
     }
        
  }
  $V->{"zone.total"} = $totzones;
  return $err;

}

1;
