#  $Header: network.pl 26-oct-2007.18:47:30 ssalunke Exp $
#
# Copyright (c) 2001, 2007, Oracle. All rights reserved.  
#
#    NAME
#      network.pl - <one-line expansion of the name>
#
#    DESCRIPTION
#      Percentage of input/output errors and collisions for every network card.
#
#    NOTES
#      <other useful comments, qualifications, etc.>
#
#    MODIFIED   (MM/DD/YY)
#    ssalunke    12/30/07  - XbranchMerge ssalunke_nim1 from main
#    ssalunke    10/26/07  - Randomizing temporary file created on HPUX
#    svrrao      10/10/06  - HPUX specific netstat and lanadmin changes
#    rrawat      07/11/06  - Backport rrawat_bug-4745376 from main 
#    ajayshar    01/18/06  - Backport ajayshar_bug-4896038 from main 
#    ajayshar    12/05/05  - backported from bug 2893945 to 10.2.0.2.0
#    rrawat      01/25/06 - Bug-4745376
#    ajayshar    01/17/05 - bug-4896038 , Network.pl throws metric collection error 
#                           'invalid number format' in some linux boxes.
#    ajayshar    12/02/05 - bug-fix:2893945-network % utilization metrics do not work
#    sreddy      10/18/04 - code clean up
#    sacgoyal    10/14/04 - for fixing bug # 3845398 
#    rzkrishn    06/11/04 - using hostGenFunctions 
#    vsekuboy    05/05/03 - modified comments
#    vsekuboy    04/29/03 - Changes for HP and Linux in EM 4.0.0
#    vsekuboy    10/08/02 - Changes for HP
#    xxu         06/25/02 - remove /usr/local/bin/perl
#    Ash: Added test for zero packets to avoid devide by 0 error and now
#         skipping virtual interfaces, which was major source of such.
#    Ash: Updated description for CGI index generation.
#    Ash: Updated to v0.5 of the spec.
#    Ash: Initial version.
#

use strict;
use hostGenFunctions;

$ENV{PATH} = "/bin:/usr/bin:/usr/sbin:/usr/lib";

my @data = ();
my @speed = ();
my @UNET = ();
my @DATA = ();
my @DATA1 = ();
my @STAT = ();
my @lanData = ();
my @temp = ();
my @dmesgtokens = ();
my $dmsglines ="";
my $dmsgval ="";
my $value = "";
my $ifname = "";
my $user = "";
my $tmp = "";
my $tmp1 = "";
my $tmp2 = "";
my $tmp3 = "";
my $ppanum = "";
my $ppa = "";
my $inpErr = "";
my $outErr = "";
my $coll = "";
my $singleColl = "";
my $multColl = "";
my $excessColl = "";
my $lateColl = "";
my $irbytes = "";
my $orbytes = "";
my $host = "";
my $ignore = "";
my $speed = "";
my $in_pct = "";
my $out_pct = "";
my $coll_pct = "";

my $uname = `uname -s`;
chomp($uname);

if ( "$uname" eq "Linux" )
{
$ENV{PATH} = "/bin:/usr/bin:/usr/sbin:/usr/lib";

open FH, "/proc/net/dev" or die "Could not open /proc/net/dev\n";

while (<FH>)
{
  # ifname:<data>
  if (/(.*):(.*)/)
      {

        $speed[0]="";
        next if ($1 =~ /lo/);
        $ifname = trim($1);
        @data = split(/[\s\t]+/, trim($2));


        # this block checks for entries in the network_speed file .speed[0] will remain "" , if either
        # the file is not found or there is no entry for this interface in the network_speed file
        if (-e "$ENV{ORACLE_HOME}/sysman/config/network_speed")
        {
          $value = `cat $ENV{ORACLE_HOME}/sysman/config/network_speed`;
          @UNET = split(/[\n\r]/, $value);
          foreach $user (@UNET)
          {
            my ($UName, $USpeed) = split(/[\s\t]+/, $user);
            if ($UName =~ /$ifname/)
            {
              $speed[0] = $USpeed;
            }
          }
        }


        # if the network_speed is not found or entry of the interface not found
        # then use the dmesg output.
        if($speed[0] eq "")
        {
          # Output only those lines which have the string "Link is up" and ("Mbps" or "Mbps,") 
          $value = `dmesg | grep $ifname | grep -i "Link is up" | grep "Mbps"`;
          chomp($value);
          @dmesgtokens = split(/[\s\t]+/, $value);
          $dmsgval ="";

          for my $dmsglines (@dmesgtokens)
          {
            if ($dmsglines ne "Mbps" && $dmsglines ne "Mbps,")
            {
              $dmsgval=$dmsglines;
            }
            else
            {
              last;
            }
          } # for

          $speed[0] = $dmsgval;
          # If speed is "" or contains a non-numeral character then return 0 
          if($speed[0] eq "" || $speed[0]=~ m/\D/ )
          {
            $speed[0] = 0;
          }
        }
    
        print "em_result=$ifname|$data[2]|$data[1]|$data[10]|$data[9]|$data[13]|$speed[0]|$data[0]|$data[8]|4294967295\n";
      }
    }

exit 0;
}
elsif ( "$uname" eq "HP-UX" )
{
    my $found = 0;
    my $rc    = 0; 
    @DATA = `netstat -in | grep -v Name ` or die "Could not run netstat -in.\n" ;

    for (@DATA)
    {
	next if /^\s*$/;

	my ($interface, $inpkt , $opkt)  = (split)[0,4,5];
        next if $interface =~ /\*/;
        next if $interface =~ /^[ \t]*$/;
        next if $interface  =~ /Ipv[0-9]/i;
	next if $interface eq "lo0";
	next if $interface =~ /:/;
        next if $interface  =~ /Name/i;
        next if $interface =~ /\*/;

	#
	# interface|i/p Errors|i/p Pkts |o/p Errors | o/p Pkts | Collisions
#	print "em_result=$interface|$inpErr|$inpkt|$outErr|$opkt|$coll\n";
	$found++;

	@temp =`lanscan | grep $interface`;
	($tmp1, $tmp2, $ppanum, $tmp3) = split(' ',$temp[0],4);
	chomp($ppanum);
	$ppa="ppa $ppanum";
	open(INFO, ">/tmp/.cmdfile$$") or die "Could not open /tmp/.cmdfile$$ \n";
	print INFO "cmdfile\nlan\n$ppa\ndisplay\n\n\n\n\nquit\n";
	close(INFO);

        $rc = checkCmd($hostGenFunctions::LANADMIN);
        if ($rc != 1) {
            unlink ("/tmp/.cmdfile$$");
	    die "Could not run lanadmin.\n";
        }

        @lanData = `lanadmin -t < /tmp/.cmdfile$$ 2>/dev/null`;

        # Remove the temporary file
        unlink ("/tmp/.cmdfile$$");

        foreach $_ (@lanData)
	{
	    if (/Speed/)
	    {
		($tmp, $speed) = split ("=", $_);
		$speed = $speed/(1024*1024);
	    }
	    if (/Inbound Errors/)
	    {
		($tmp, $inpErr) = split("=",$_);
	    }
	    if (/Outbound Errors/)
	    {
		 ($tmp, $outErr) = split("=",$_);
	    }
	    if (/Single Collision Frames/)
	    {
		 ($tmp, $singleColl) = split("=",$_);
	    }
	    if (/Multiple Collision Frames/)
	    {
		 ($tmp, $multColl) = split("=",$_);
	    }
	    if (/Late Collision Frames/)
	    {
		 ($tmp, $lateColl) = split("=",$_);
	    }
	    if (/Excessive Collision Frames/)
	    {
		 ($tmp, $excessColl) = split("=",$_);
	    }
	    if (/Inbound Octets/)
	    {
		 ($tmp, $irbytes) = split("=",$_);
		 chomp ($irbytes);
	    }
	    if (/Outbound Octets/)
	    {
		 ($tmp, $orbytes) = split("=",$_);
		 chomp ($orbytes);
	    }
        }
        $coll = $singleColl + $multColl + $lateColl + $excessColl;
        chomp($inpErr);
        chomp($outErr);

	#
	# interface|i/p Errors|i/p Pkts |o/p Errors | o/p Pkts | Collisions| Speed | Rbytes | Wbytes | max counter
	print "em_result=$interface|$inpErr|$inpkt|$outErr|$opkt|$coll|$speed|$irbytes|$orbytes|4294967295\n";
	$found++;
    }

    die "Unable to parse data.\n" unless $found > 0;
}
elsif ( "$uname" eq "OSF1" )
{
   ($host, $ignore) = split(/\./, `hostname`);
   $speed = 0; # 'hwmgr' can be run only as root
    @DATA = `netstat -i | grep $host`;
    for (@DATA)
    {
      chomp;
      my ($interface,$mtu,$nw,$addr,$inpkt,$inpErr,$opkt,$outErr,$coll)  = split(/ +/);
      @STAT = `netstat -I $interface -s`;
      for (@STAT) {
        next if /multicast/;
        if (/bytes received/) {
           $irbytes = (split)[0];
        }
        if (/bytes sent/) {
           $orbytes = (split)[0];
        }
      }
      print "em_result=$interface|$inpErr|$inpkt|$outErr|$opkt|$coll|$speed|$irbytes|$orbytes|4294967295\n";
    }
}
elsif ( "$uname" eq "Darwin" )
{
    $speed = 0;
    ($host, $ignore) = split(/\./, `hostname`);
    @DATA1 = `netstat -ib` or die "Could not run netstat -ib.\n" ;
    @DATA = grep { /$host/ } @DATA1;
    map { tr/-/0/d; $_; } @DATA;
    for (@DATA)
    {
      chomp;
      my ($interface,$mtu,$nw,$addr,$inpkt,$inpErr,$irbytes,$opkt,$outErr,$orbytes,$coll)  = split(/ +/);
      $speed = `$ENV{EMDROOT}/bin/nmupm ifspeed $interface`;
      chomp($speed);
      $speed /= (1000 * 1000); # MBits per sec
      print "em_result=$interface|$inpErr|$inpkt|$outErr|$opkt|$coll|$speed|$irbytes|$orbytes|4294967295\n";
    }
}
else
{
@DATA = `netstat -in`;
shift @DATA;

my $found = 0;

for (@DATA) {
  next if /^\s*$/;

  my ($interface, $in, $in_error, $out, $out_error, $coll) = (split)[0,4..8];
  next if $interface eq "lo0";
  next if $interface =~ /:/;

  if ($in == 0)  { $in_pct = 0; }
  else           { $in_pct =  sprintf "%0.2f", $in_error/$in*100; }
  if ($out == 0) { $out_pct = 0; $coll_pct = 0; }
  else           { $out_pct =  sprintf "%0.2f", $out_error/$out*100;
		   $coll_pct =  sprintf "%0.2f", $coll/$out*100; }

#  print "em_result=$interface input errors=$in_pct|There are $in_pct% input errors on $interface.\n";
#  print "em_result=$interface output errors=$out_pct|There are $out_pct% output errors on $interface.\n";
#  print "em_result=$interface collisions=$coll_pct|There are $coll_pct% output colissions on $interface.\n";
  print "em_result=$interface|$in_pct|$out_pct|$coll_pct\n";
  $found++;
}

die "Unable to parse data.\n" unless $found > 0;
}


sub checkCmd($)
{
    # Purpose: To check whether the given command is present and executable

    my ($cmd) = @_;
    my $rc  = 1;
    if (!(-x "$cmd"))
    {
        $rc = 0;
    }

    return $rc;
}

