#!/bin/bash
#
# Usage -A | -i <interface> [ -f file name | -d dir_name ]
#
# Script to generate equivalent of /proc info previously
# Being generated by network drivers

ioption=0
foption=0
doption=0
Aoption=0
multiport=0
#For Debian
#debian=0
#if [ ! -e /etc/SuSE-release ] && [ ! -e /etc/redhat-release ];then
#	debian=1
#fi

# For test purposes, use junk paths
#INTEL_PROC_DIR=/proc/net/nothing
#BCOM_PROC_DIR=/proc/net/nothing
INTEL_PROC_DIR=/proc/net/PRO_LAN_Adapters
BCOM_PROC_DIR=/proc/net/nicinfo
INTEL_VMWARE_PROC_DIR=/proc/vmware/vmkdev/net/PRO_LAN_Adapters
BCOM_VMWARE_PROC_DIR=/proc/vmware/vmkdev/net/nicinfo

if [ "$MIN_ETHTOOL_VER_REQ" = "" ]
then
   MIN_ETHTOOL_VER_REQ="1.8"
   if [ -e /etc/SuSE-release ]
     then
     SUSE_8=`cat /etc/SuSE-release | grep "SLES-8"`
     if [ "$SUSE_8" != "" ]
       then
       MIN_ETHTOOL_VER_REQ="1.6"
     fi
   fi
fi

INSTALLED_ETHTOOL=`which ethtool 2>/dev/null`
if [ "$?" == "0" ]
then
#   if [ $debian -eq 1 ];then
#   	INSTALLED_VERSION=`$INSTALLED_ETHTOOL -h 2>&1 |grep "ethtool version" | cut -d" " -f3`
#   else
#   	INSTALLED_VERSION=`$INSTALLED_ETHTOOL 2>&1 |grep "ethtool version" | cut -d" " -f3`
#   fi
   INSTALLED_VERSION=`$INSTALLED_ETHTOOL -h 2>&1 |grep "ethtool version" | cut -d" " -f3`

   if [ -n $INSTALLED_VERSION ] && 
      [ ! "$INSTALLED_VERSION" \< "$MIN_ETHTOOL_VER_REQ" ]
   then
      # we have a good ethtool version
      LOCAL_ETHTOOL=$INSTALLED_ETHTOOL
   elif [ "$ETHTOOL_PATH" = "" ]
   then
         # no user over-ride and old version of ethtool installed.
         # if user over-ride given, we don't check version as that ethtool
         # version may have been patched...
         echo "------------------------------------------------------------"
         echo "Ethtool version $MIN_ETHTOOL_VER_REQ or later is required,"
         echo "install the latest version from the following URL:"
         echo ""
         echo "http://sourceforge.net/projects/gkernel/"
         echo "------------------------------------------------------------"
         exit 1
   fi
fi

# use user specified ethtool if set; if not set and local ethtool
# version is >=1.8, use it; otherwise use our private copy.
ETHTOOL=${ETHTOOL_PATH:-$LOCAL_ETHTOOL}

usage()
{
hpetfe_version=2.0
printf "\nhpetfe version %s\n" "$hpetfe_version"

echo "Usage: $0 [<switches>]"
printf "\n"
echo "-i <interface>  Specifies the ethernet interface "
echo "-f <file>       Specifies the file in which the output is saved"
echo "-d <dir>        Specifies the directory in which files named"
echo "                  ethX.info are saved for each ethernet interface"
echo "                  specified by the -i option."
echo "-A              Use all ethernet interfaces on the system"
printf "\n"

echo "Note: -i or -A option should be specified"
echo "Note: -f and -d are mutually Exclusive"
printf "\n"
}


# convert a hex value to an int (i.e. ff to 255)
hex_to_int()
{
   local n=$1
   local ret=0
   local base=1

   local prefix
   local lowdigit_a
   local lowdigit_b

   while [ $n ]; do
      prefix=${n%[0-9a-fA-F]}
      lowdigit_a=${n#$prefix}
      if [ ! $lowdigit_a ]; then
         echo "error in value"
         return 0
      fi
      lowdigit_b=$lowdigit_a
      case $lowdigit_a in
         a|A)   lowdigit_b=10 ;;
         b|B)   lowdigit_b=11 ;;
         c|C)   lowdigit_b=12 ;;
         d|D)   lowdigit_b=13 ;;
         e|E)   lowdigit_b=14 ;;
         f|F)   lowdigit_b=15 ;;
      esac
      ret=$[$ret + $[$lowdigit_b*$base]]
      base=$[$base*16]
      n=$prefix
   done
        
   echo $ret
}


# take a MAC in XX:XX:XX:XX:XX:XX format and
# add 1, returning the same format
incr_mac ()
{
        local n=$1

        n=`echo $n | sed 's/://g'`
        
        ret=`hex_to_int $n`
        
        if [ $ret -gt 281474976710654 ]; then
           ret="00:00:00:00:00:00"
        else
          #add 1
          ret=$[$ret+1]
          #convert back to hex MAC format
          ret=`printf "%012x" $ret | sed 's/[0-9a-fA-F][0-9a-fA-F]/& /g' | awk '{printf "%s:%s:%s:%s:%s:%s",$1,$2,$3,$4,$5,$6}'`
        fi
        
        echo $ret
}

check_for_errors()
{
if [ "$ioption" = "0" -a "$Aoption" = "0" ]
then
	usage
	exit 1
fi

if [ "$ioption" = "1" -a "$Aoption" = "1" ]
then
	echo "Error!! -i and -A options cannot be used together"
	usage
	exit 1
fi

if [ "$foption" = "1" -a "$doption" = "1" ]
then
  echo "Error!! -f and -d options cannot be used together"
  usage
  exit 1
fi

if [ "$foption" = "1" ]
then
  if [ -f $fname -a ! -w $fname ]
  then
   echo "Error!! $fname Exists or Write permission denied. Exiting"
   exit 1
  fi
fi
if [ "$doption" = "1" ]
then
  mkdir -p $dirname
  if [ ! -d $dirname ]
  then
   echo "Error!! Error in creating $dirname. Exiting"
  exit 1
  fi
  if [ ! -w $dirname ]
  then
   echo "Error!! $dirname Exists. Write permission denied. Exiting"
  exit 1
  fi
fi

#Verify for proper interface name

if [ "$ioption" = "1" -a "$Aoption" = "1" ]
then
  echo "Error!! -i and -A options cannot be used together. Exiting"
  exit 1
fi

if [ "$ioption" == "0" -a "$Aoption" == "0" ]
then
   usage
   exit 1
fi
}


check_for_ethtool_ver()
{

if [ -z $ETHTOOL ] || [ ! -f "$ETHTOOL" ]
then
  if [ -d /etc/vmware ]
  then
    if [ -d $INTEL_PROC_DIR ] ||
       [ -d $BCOM_PROC_DIR ] ||
       [ -d $INTEL_VMWARE_PROC_DIR ] ||
       [ -d $BCOM_VMWARE_PROC_DIR ]       
    then
      return 0
    fi
  fi

  echo "------------------------------------------------------------"
  echo "It appears the ethtool application is not installed on"
  echo "this system, or version $MIN_ETHTOOL_VER_REQ or later is"
  echo "not installed. Install the latest version from the following URL:"
  echo ""
  echo "http://sourceforge.net/projects/gkernel/"
  echo "------------------------------------------------------------"
  exit 1
fi

}

display_entry()
{
variable="$1"
varvalue="$2"

if [ "$variable" = "Speed" ] || [ "$variable" = "Duplex" ] || [ "$variable" = "Link" ]
then
	printf "%-25s %s\n" "$variable" "$varvalue"
	return 0
fi

# empty hex values come in a "0x"
if [ "$varvalue" = "" ] || [ "$varvalue" = "N/A" ] || [ "$varvalue" = "0x" ]
then
	return 1
else
	printf "%-25s %s\n" "$variable" "$varvalue"
fi
}

display_static_proc()
{
display_entry "Description" "$descr"
display_entry "Driver_Name" "$drvname"
display_entry "Driver_Version" "$drvversion"
display_entry "PCI_Vendor" "0x$pcivendor"
display_entry "PCI_Device_ID" "0x$pcidevice"
display_entry "PCI_Subsystem_Vendor" "0x$pcisubsys"
display_entry "PCI_Subsystem_ID" "0x$pcisubdev"
display_entry "PCI_Revision_ID" "0x$pcirevid"
display_entry "PCI_Bus" "$busnum"
display_entry "PCI_Slot" "$slotnum"
display_entry "IRQ" "$irq"
display_entry "Memory" "0x$memory"
display_entry "Part_Number" "$partno"
display_entry "System_Device_Name" "$iname"
display_entry "Current_HWaddr" "$caddr"
display_entry "Permanent_HWaddr" "$phwaddr"
display_entry "AdapterPort" "$aport"
printf "\n"
}

get_basic_stats()
{
   iface="$1"

   rx_bytes=0
   rx_packets=1
   rx_errors=2
   rx_dropped=3
   rx_fifo_errors=4
   rx_frame_errors=5
   rx_compressed=6
   rx_multicast=7

   tx_bytes=8
   tx_packets=9
   tx_errors=10
   tx_dropped=11
   tx_fifo_errors=12
   collisions=13
   tx_carrier_errors=14
   tx_compressed=15

   err=1
   if [ -f /proc/net/dev ]
   then
      declare -a nic_stats
      nic_stats=(`cat /proc/net/dev|grep -w "$iface"|cut -d: -f2`)
      num_stats=${#nic_stats[*]}

      if [ $num_stats -ge 16 ]
      then
         err=0
         display_entry "Rx_Bytes"           ${nic_stats[$rx_bytes]}
         display_entry "Rx_Packets"         ${nic_stats[$rx_packets]}
         display_entry "Rx_Errors"          ${nic_stats[$rx_errors]}
         display_entry "Rx_Dropped"         ${nic_stats[$rx_dropped]}
         display_entry "Rx_FIFO_Errors"     ${nic_stats[$rx_fifo_errors]}
         display_entry "Rx_Frame_Errors"    ${nic_stats[$rx_frame_errors]}
         display_entry "Rx_Compressed"      ${nic_stats[$rx_compressed]}
         display_entry "Multicast"          ${nic_stats[$rx_multicast]}
         display_entry "Tx_Bytes"           ${nic_stats[$tx_bytes]}
         display_entry "Tx_Packets"         ${nic_stats[$tx_packets]}
         display_entry "Tx_Errors"          ${nic_stats[$tx_errors]}
         display_entry "Tx_Dropped"         ${nic_stats[$tx_dropped]}
         display_entry "Tx_FIFO_Errors"     ${nic_stats[$tx_fifo_errors]}
         display_entry "Collisions"         ${nic_stats[$collisions]}
         display_entry "Tx_Carrier_Errors"  ${nic_stats[$tx_carrier_errors]}
         display_entry "Tx_Compressed"      ${nic_stats[$tx_compressed]}

         # Rx_Length_Errors
         # Rx_Over_Errors
         # Rx_CRC_Errors
         # Rx_Missed_Errors
         # Tx_Aborted_Errors
         # Tx_Heartbeat_Errors
         # Tx_Window_Errors
      fi

   fi

   if [ $err -eq 1 ]
   then
      echo "WARNING: unable to read/parse basice stats from /proc/net/dev"
      echo "         for interface $interface"
   fi
}


display_dynamic_proc()
{
# Print the Statistics
display_entry "Link" "$link"
display_entry "Speed" "$speed"
display_entry "Duplex" "$duplex"
display_entry "State" "$state"
display_entry "Auto_Negotiate" "$auto_negotiate"
display_entry "Speed_Advertisement" "$speed_advertisement"
printf "\n"
printf "\n"
display_entry "Rx_Packets" "$rxpack"
display_entry "Tx_Packets" "$txpack"
display_entry "Rx_Bytes" "$rxbytes"
display_entry "Tx_Bytes" "$txbytes"
display_entry "Rx_Errors" "$rxerrors"
display_entry "Tx_Errors" "$txerrors"
printf "\n"
printf "\n"
display_entry "Rx_CRC_Errors" "$rx_crc_errors"
display_entry "Tx_Carrier_Errors" "$tx_carrier_errors"
display_entry "Tx_Abort_Excess_Coll" "$tx_abort_excess_coll"
display_entry "Tx_Abort_Late_Coll" "$tx_abort_late_coll"
display_entry "Tx_Deferred_Ok" "$tx_deferred_ok"
display_entry "Tx_Single_Coll_Ok" "$tx_single_coll_ok"
display_entry "Tx_Multi_Coll_Ok" "$tx_multi_coll_ok"
display_entry "Rx_Short_Length_Errors" "$rx_short_length_errors"
display_entry "Rx_Long_Length_Errors" "$rx_long_length_errors"
display_entry "Rx_Align_Errors" "$rx_align_errors"

# if the driver doesn't provide all the stats via ethtool gstats, try to
# get them from /proc/net/dev - tc
if [ "$rxpack" = "" ] || [ "$rxpack" = "N/A" ] || [ "$txpack" = "" ] || [ "$txpack" = "N/A" ]
then
   printf "\n"
   get_basic_stats $iname
fi

printf "\n"
printf "\n"
}

# create tmp directory
create_tmp_dir()
{
   nictmp=${TMPDIR-/tmp}
   nictmp=$nictmp/nicdir.$RANDOM.$RANDOM.$RANDOM.$$
   (umask 077 && mkdir $nictmp) || {
        echo "Could not create temporary directory! Exiting." 1>&2
            exit 1
	}

}
#delete tmp directory
del_tmp_dir()
{
	rm -rf $nictmp
}

# Get the Driver and PCI Related Info First
get_drv_info()
{
#create_tmp_dir
$ETHTOOL -i $iname > $nictmp/$iname.iopt
if [ $? -ne 0 ]
then
		invalid_interface=1
		return
fi

drvname=`egrep ^driver $nictmp/$iname.iopt | awk -F":" '{print $2}'|sed 's/^[ 	]*//g'`
drvversion=`egrep ^version $nictmp/$iname.iopt | awk -F":" '{print $2}'|sed 's/^[ 	]*//g'`


bus_info=`grep bus-info $nictmp/$iname.iopt`
slotinfo=`echo $bus_info | awk '{print $2}'`

bus_info_string_seperator=`echo $bus_info|awk -F":" '{print NF-1}'`
if [ $bus_info_string_seperator -eq 2 ]
then
   # bus-info: 02:03.0
   busnum=`echo $bus_info | awk -F":" '{print $2}'| sed 's/^[ ]*0//g'`
   slotnum=`echo $bus_info | awk -F":" '{print $3}' | awk -F"." '{print $1}'| sed 's/^[         ]*0//g'`
   long_businfo=0
else
   # bus-info: 0000:02:03.0
   busnum=`echo $bus_info | awk -F":" '{print $3}'| sed 's/^[ ]*0//g'`
   slotnum=`echo $bus_info | awk -F":" '{print $4}' | awk -F"." '{print $1}'| sed 's/^[         ]*0//g'`

   # handle distros that return nothing when the domain is given to
   # lspci -s, even though the usage shows 
   # "[[[[<domain>]:]<bus>]:][<slot>][.[<func>]]"
   domain_test=`lspci -s $slotinfo 2> /dev/null`
   if [ "$domain_test" = "" ]
   then
      # strip the domain from the bus-info
      slotinfo=`echo $slotinfo | awk -F":" '{printf "%s:%s",$2,$3}'`
      long_businfo=0
   else
      long_businfo=1
   fi
fi

busnum=`hex_to_int $busnum`
slotnum=`hex_to_int $slotnum`


get_speed_duplex_link

/bin/rm -rf $nictmp/$iname.iopt
}

get_pci_info()
{

if [ ! -z "$bus_info" ]
then
	pcivendor=`lspci -s $slotinfo -n -m -v | grep '^Vendor:' | awk '{print $2}' | sed 's/"//g'`
	pcidevice=`lspci -s $slotinfo -n -m -v | grep '^Device:' | tail -n 1 | awk '{print $2}' | sed 's/"//g'`
	# There is a BUG in lspci version < 2.1.99. It returns same values
	# for DeviceID and SVendorID.
	LS_PCI_VER=`lspci --version | awk '{print $3}'`
	if [ "$LS_PCI_VER" \< "2.1.99" ]; then
		pcisubsys=`lspci -s $slotinfo -n -v | egrep -i subsystem | awk -F":" '{print $2}' | sed 's/"//g' | sed 's/^[    ]*//g'`	
	else
		pcisubsys=`lspci -s $slotinfo -n -m -v | grep '^SVendor:' | awk '{print $2}' | sed 's/"//g'`
	fi
	pcisubdev=`lspci -s $slotinfo -n -m -v | grep '^SDevice:' | awk '{print $2}' | sed 's/"//g'`
	#00d0 = dual port Broadcom
	#00db = dual port Intel copper
	#00dc = dual port Intel fiber
	#3109 = PCI-X Quad Port Intel Copper
   	#7044 = PCI Express Dual Port Intel Copper 
    	#List of mulitple port card
	pcimsubdevarr=(00d0 00db 00dc 3109 7044 703c 7059 171d 704b 170c 703e 323f 31fe 3226 3070 7055 7056 1707 7039 171c 7058 7035 1717 3380 1716 18d1)
    	for i in ${pcimsubdevarr[@]}
    	do
		if [ "$pcisubdev" = "$i" ]; then
        		getnexttoken=1
			#We have a multiport card here. Read both MAC addresses
			multiport=1
			break
        	fi
	done
	pcirevid=`lspci -s $slotinfo -n -m -v | grep '^Rev:' | awk '{print $2}' | sed 's/"//g'`
	descr=`lspci -s $slotinfo -v | grep "Subsystem" | awk -F":" '{print $2}'`
	irqstring=`lspci -s $slotinfo -n -v | egrep IRQ `
	getnexttoken=0
	irq=0
	for i in  `echo $irqstring`
	do
		if [ $getnexttoken = 1 ]
		then
	       		irq=$i
			break
		fi
		if [ $i = "IRQ" ]
		then
			getnexttoken=1
		fi
	done
	memory=`lspci -s $slotinfo -n -v | egrep -i "Memory at" | head -1 | awk '{print $3}' | sed 's/^[ 	]*//g'`
fi

caddr=`ifconfig $iname | grep HWaddr | awk  '{print $5}'`
phwaddr=
partno=
func=`echo "$slotinfo" | awk -F"." '{print $2}'`
$ETHTOOL -e $iname offset 0 length 1 >/dev/null 2>&1
eeret=$?

#Finding permanent physical address of Intel adapter
if [ "$pcivendor" = "8086" ] && [ $eeret -eq 0 ]
then
	# We Have an Intel Card. Offset is 0x0
        get_part_no intel
       	# For Intel Cards, Permanent MAC Offset is 0x0
       	eeprom_offset="0x0"
       	bytes=6
        phwaddr=`$ETHTOOL -e $iname offset $eeprom_offset length $bytes | tail -1 | awk '{printf "%s:%s:%s:%s:%s:%s",$2,$3,$4,$5,$6,$7}'`
        if [ "$pcisubdev" = "704b" ] || [ "$pcisubdev" = "3380" ] 
	then
   		#this is the second port of a intel gigabit NIC NC364T
  		#so increment the MAC by 1 if func == 0
   		if [ "$multiport" = "1" ] && [ "$func" = "0" ]
   		then
	       		phwaddr=`incr_mac "$phwaddr"`
 		fi
	elif [ "$multiport" = "1" ] && [ "$func" = "1" ]
        then
        	#this is the second port of a multiport intel gigabit NIC (NC7170)
          	#so increment the MAC by 1
          	phwaddr=`incr_mac "$phwaddr"`
		phwaddr1=$phwaddr
	elif [ "$multiport" = "1" ] && [ "$func" = "2" ]
	then
		phwaddr=`incr_mac "$phwaddr1"`
		phwaddr1=$phwaddr
	elif [ "$multiport" = "1" ] && [ "$func" = "3" ]
	then
		phwaddr=`incr_mac "$phwaddr1"`
		phwaddr1=$phwaddr	
	fi
	phwaddr=`echo $phwaddr | awk '{printf "%s", toupper($1)}'`
fi
#Finding permanent physical address of Broadcom/tg3 adapter
if  [ "$pcivendor" = "14e4" ] && [ $eeret -eq 0 ]
then
	get_part_no broadcom
	brcpcidev=( 16aa 164a 16ac 164c 1639 163a 16c7 )
	flag=0
	for i in ${brcpcidev[@]}
 	do
        	if [ "$pcidevice" = "$i" ]
        	then
			flag=1
   			break
         	fi
 	done
    	if [  "$flag" -eq "1" ]
	then
		# bcm5706, bcm5708 (Single port) and bcm5709 (Dual Port)
		eeprom_offset="0x136"
		bytes=6
		phwaddr=`$ETHTOOL -e $iname offset $eeprom_offset length $bytes | tail -1 | awk '{printf "%s:%s:%s:%s:%s:%s",$2,$3,$4,$5,$6,$7}'`
		if [ "$multiport" == "1" ] && [ "$func" = "1" ]
		then
		   #this is the second port of a multiport Broadcom gigabit
		   #NIC (bcm5709) so increment the MAC by 2
		   phwaddr=`incr_mac "$phwaddr"`
		   phwaddr=`incr_mac "$phwaddr"`
	    	fi
	else	
		eeprom_offset="0x7c"
		bytes=8
		if [ "$multiport" == "1" ] 
		then
			brmmulti=(703c 170c 703e 3226 1707 7039 7035)
            		flag1=1
            		for i in ${brmmulti[@]}
           		do
				if [ "$pcisubdev" = "$i" ]
                		then
               				flag1=0
					break
               			 fi
            		done
            		if [ "$func" -eq 0 ]&&[ "$flag1" -eq 1 ]
       			then
           		 	eeprom_offset="0xcc"
           		fi
            		if [ "$func" -eq 1 ]&&[ "$flag1" -eq 0 ]
            		then
            			eeprom_offset="0xcc"
         		 fi
		fi
		if [ "$drvname" = "tg3" ]
        	then
			phwaddr=`$ETHTOOL -e $iname offset $eeprom_offset length $bytes | tail -6 | awk -Fx '{printf("%s:",$3)}' | sed 's/:$//g'`
		else
			phwaddr=`$ETHTOOL -e $iname offset $eeprom_offset length $bytes | tail -1 | awk '{printf "%s:%s:%s:%s:%s:%s",$4,$5,$6,$7,$8,$9}'`
        	fi
	fi
	phwaddr=`echo $phwaddr | awk '{printf "%s", toupper($1)}'`
fi
#Finding permanent physical address of Netxen adapters
if  [ "$pcivendor" = "4040" ] && [ $eeret -eq 0 ]
then
       portoff=0
       mac_base=4097048
       bytes=6
       brdtype=`$ETHTOOL -e $iname offset 0x4008 length 4 |awk '/^0x/ {print "0x"$2}'`
       if [ "$brdtype" == "0x80" ]
       then
               portoff=16
       fi
       eeprom_offset=`expr $mac_base + $portoff`
       multi_portoff=`echo $func|awk '{print $1*8}'`
       eeprom_offset=`expr $eeprom_offset + $multi_portoff`
       phwaddr=`$ETHTOOL -e $iname offset $eeprom_offset length $bytes | awk 'BEGIN {OFS=":"} /^0x3/ {print $7,$6,$5,$4,$3,$2}'`
       phwaddr=`echo $phwaddr | awk '{printf "%s", toupper($1)}'`
fi

if [ -z "$phwaddr" ] || [ "$phwaddr" = ":::::" ]
then
	phwaddr=`echo $caddr | awk '{printf "%s", toupper($1)}'`
fi
# get Adapter port
#aport=$func
#portcount=`lspci -s $slotnum.$func | grep Ether | wc -l`
#if [ $portcount = 2 ]
#then
 #   aport=`lspci -s $slotnum.$func | grep -n Ether |nl | grep "$busnum:" | cut -f1`
 #   aport=`expr $aport - 1`
#fi
}
SYSTEM_PATH=/sys/class/net/
get_port_no()
{
   interface_names=
   # Generate the ethX interface list
   for i in `ifconfig -a | egrep "^eth[0-9]*[0-9]" | awk '{print $1}' | egrep -v "[.:]"`
   do
      interface_names="$interface_names $i"
   done
   for i in `ifconfig -a | egrep "^vmnic[0-9]*[0-9]" | awk '{print $1}' `
   do
      interface_names="$interface_names $i"
   done
#       Support for XEN OS. Xen moves physical interface to peth* if bridge
#       is attached to corrosponding eth*
   for i in `ifconfig -a | egrep "^peth[0-9]*[0-9]" | awk '{print $1}' | egrep -v "[.:]"`
   do
      interface_names="$interface_names $i"
   done
   > $nictmp/portinfo
   count=0
   for i in $interface_names
   do
      tmpvendor=`cat $SYSTEM_PATH/$i/device/vendor`
      tmpdevice=`cat $SYSTEM_PATH/$i/device/device`
      tmpsubdevice=`cat $SYSTEM_PATH/$i/device/subsystem_device`
      tmpsubvendor=`cat $SYSTEM_PATH/$i/device/subsystem_vendor`
#      echo $tmpvendor $tmpdevice $tmpsubdevice $tmpsubvendor
      if [ "0x$pcivendor" = "$tmpvendor" ]&&[ "0x$pcidevice" = "$tmpdevice" ] \
	&& [ "0x$pcisubsys" = "$tmpsubvendor" ]&&[ "0x$pcisubdev" = "$tmpsubdevice" ] ;then
        echo "$count $i" >> $nictmp/portinfo
        count=`expr $count + 1`
      fi
   done
   aport=`grep $iname $nictmp/portinfo | awk -F" " '{print $1}'`
   rm $nictmp/portinfo
#   echo $aport
}

generate_statistics()
{

 einame=$1
 $ETHTOOL -S $einame > $nictmp/$einame.stats 2>/dev/null
 if [ $? -ne 0 ]
 then
	invalid_interface=1
	return
 fi
}
get_value()
{
 string1=$1
 string2=$2
 if [ -z "$string2" ];then
	 value=`egrep "^[ 	]*\$string1" $nictmp/$iname.stats`
 else
	 value=`egrep "^[ 	]*\$string1|\$string2" $nictmp/$iname.stats`
 fi
 value=${value## *:}
 echo ${value:-"N/A"}

}

get_speed_duplex_link()
{

$ETHTOOL $iname > $nictmp/$iname.noopt

ifconfig $iname | grep UP > /dev/null 2>&1
if [ $? = 0 ]
then
   state=up
   links=`egrep "Link" $nictmp/$iname.noopt`
   links=`echo ${links##*:} | sed 's/[ 	]*//g'`
   if [ "$links" = "yes" ]
   then
      link="Up"
      speedtmp=`egrep "Speed" $nictmp/$iname.noopt`
      speedtmp=`echo ${speedtmp##*:} | sed 's/[ 	]*//g'`
      # Remove the Mb/s at the end of the string
      speed=${speedtmp/Mb\/s/}

      duplex=`egrep "Duplex" $nictmp/$iname.noopt`
      duplex=`echo ${duplex##*:} | sed 's/[ 	]*//g'`

      echo $speed | egrep -i unknown > /dev/null 2>&1
      if [ $? = 0 ]
      then
         speed="N/A"
      fi
      echo $duplex | egrep -i unknown > /dev/null 2>&1
      if [ $? = 0 ]
      then
         duplex="N/A"
      fi
   else
      link="Down"
      speed="N/A"
      duplex="N/A"
   fi
else
   # if the interface is down, we can't trust that the driver will continue
   # to check the physical link status
   state=down
   link="N/A"
   speed="N/A"
   duplex="N/A"
fi

auto_negotiate="N/A"
auto_line=`grep "Advertised auto-negotiation:" $nictmp/$iname.noopt 2>&1`

echo $auto_line | grep "Yes" >/dev/null
if [ $? = 0 ]
then
   auto_negotiate="on"
else
   echo $auto_line | grep "No" >/dev/null
   if [ $? = 0 ]
   then
      auto_negotiate="off"
   fi
fi

/bin/rm -rf $nictmp/$iname.noopt

}

# Now we need to get the Statistics of the Appropriate interface
# Through the ethtool interface

get_stats()
{
generate_statistics $iname
if [ "$pcivendor" = "8086" ]||[ "$pcivendor" = "15b3" ]
then
	rxpack=`get_value rx_packets`
	txpack=`get_value tx_packets`
	txbytes=`get_value tx_bytes`
	rxbytes=`get_value rx_bytes`
	txdrop=`get_value tx_dropped`
	rxdrop=`get_value rx_dropped`
	rxerrors=`get_value rx_errors`
	txerrors=`get_value tx_errors`
	multicast=`get_value multicast`
	collisions=`get_value collisions`
	rx_crc_errors=`get_value rx_crc_errors`
	tx_carrier_errors=`get_value tx_carrier_errors`
	rx_length_errors=`get_value rx_length_errors`
	rx_over_errors=`get_value rx_over_errors`
	rx_frame_errors=`get_value rx_frame_errors`
	rx_fifo_errors=`get_value rx_fifo_errors`
	rx_missed_errors=`get_value rx_missed_errors`
        tx_aborted_errors=`get_value tx_aborted_errors` 
        tx_fifo_errors=`get_value tx_fifo_errors`
	if [ "$pcivendor" = "8086" ] 
	then
     	   tx_abort_excess_coll="N/A"
	   tx_abort_late_coll=`get_value tx_abort_late_coll`
	   tx_deferred_ok=`get_value tx_deferred_ok`
	   tx_single_coll_ok=`get_value tx_single_coll_ok`
	   tx_multi_coll_ok=`get_value tx_multi_coll_ok`
	   rx_short_length_errors=`get_value rx_length_errors`
	   rx_long_length_errors=0
	   rx_align_errors=`get_value rx_frame_errors`
	else
           tx_heartbeat_errors=`get_value tx_heartbeat_errors`
           tx_window_errors=`get_value tx_window_errors`
	fi
elif [ "$pcivendor" = "19a2" ]
then
        rxpack=`get_value rx_packets`
        txpack=`get_value tx_packets`
        txbytes=`get_value tx_bytes`
        rxbytes=`get_value rx_bytes`
        txdrop=`get_value tx_dropped`
        rxdrop=`get_value rx_dropped`
        rxerrors=`get_value rx_errors`
        txerrors=`get_value tx_errors`
        multicast="N/A"
        collisions="N/A"
        rx_crc_errors=`get_value rx_crc_errors`
        rx_alignment_symbol_errors=`get_value rx_alignment_symbol_errors`
        rx_address_match_errors=`get_value rx_address_match_errors`
        rx_vlan_mismatch=`get_value rx_vlan_mismatch`
        rx_dropped_too_small=`get_value rx_dropped_too_small`
        rx_dropped_too_short=`get_value rx_dropped_too_short`
        rx_dropped_header_too_small=`get_value rx_dropped_header_too_small`
        rx_dropped_tcp_length=`get_value rx_dropped_tcp_length`
        rx_dropped_runt=`get_value rx_dropped_runt`
        rx_fifo_overflow=`get_value rx_fifo_overflow`
        rx_input_fifo_overflow=`get_value rx_input_fifo_overflow`
        rx_ip_checksum_errs=`get_value rx_ip_checksum_errs`
        rx_tcp_checksum_errs=`get_value rx_tcp_checksum_errs`
        rx_udp_checksum_errs=`get_value rx_udp_checksum_errs`
        rx_non_rss_packets=`get_value rx_non_rss_packets`
        rx_drops_too_many_frags=`get_value rx_non_rss_packets`
        rx_drops_invalid_ring=`get_value rx_drops_invalid_ring`
        rx_drops_mtu=`get_value rx_drops_mtu`
        rx_drops_no_fragments=`get_value rx_drops_no_fragments`
        tx_carrier_errors=`get_value tx_carrier_errors`
        rx_length_errors=`get_value rx_length_errors`
        rx_over_errors=`get_value rx_over_errors`
        rx_frame_errors=`get_value rx_frame_errors`
        rx_fifo_errors=`get_value rx_fifo_errors`
        tx_abort_excess_coll=`get_value tx_abort_excess_coll`
        tx_abort_late_coll=`get_value tx_abort_late_coll`
        tx_deferred_ok=`get_value tx_deferred_ok` 
        tx_single_coll_ok=`get_value tx_single_coll_errors`
        tx_multi_coll_ok=`get_value tx_multi_coll_errors`
        rx_long_length_errors=0
        rx_short_length_errors=`get_value rx_short_length_errors`
        rx_align_errors=`get_value rx_align_errors`
else
	rxupack=`get_value rx_unicast_packets rx_ucast_packets`
	rxmpack=`get_value rx_multicast_packets rx_mcast_packets`
	rxbpack=`get_value rx_broadcast_packets rx_bcast_packets`
	rxpack=`expr $rxupack + $rxmpack + $rxbpack 2>/dev/null`
	txupack=`get_value tx_unicast_packets tx_ucast_packets`
	txmpack=`get_value tx_multicast_packets tx_mcast_packets`
	txbpack=`get_value tx_broadcast_packets tx_bcast_packets`
	txpack=`expr $txupack + $txmpack + $txbpack 2>/dev/null`
	txbytes=`get_value tx_bytes tx_octets`
	rxbytes=`get_value rx_bytes rx_octets`
	rxerrors=`get_value rx_errors`
	txerrors=`get_value tx_errors`
	rx_crc_errors=`get_value rx_crc_errors`
	tx_carrier_errors=`get_value tx_carrier_errors`
	tx_abort_excess_coll=`get_value tx_excess_collisions`
	tx_abort_late_coll=`get_value tx_late_collisions`
	rx_length_errors=`get_value rx_length_errors`
	rx_over_errors=`get_value rx_over_errors`
	rx_frame_errors=`get_value rx_frame_errors`
	rx_fifo_errors=`get_value rx_fifo_errors`
        tx_deferred_ok=`get_value tx_deferred`
	tx_single_coll_ok=`get_value tx_single_coll_ok`
	tx_multi_coll_ok=`get_value tx_multi_coll_ok`
	rx_short_length_errors=`get_value rx_short_length_errors`
	rx_long_length_errors=`get_value rx_long_length_errors`
	rx_align_errors=`get_value rx_align_errors`

fi
/bin/rm -rf $nictmp/$iname.stats
}

get_part_no()
{
$ETHTOOL -e $iname offset 0 length 1 >/dev/null 2>&1
eeret=$?
if [ "$1" = "intel" ] && [ $eeret -eq 0 ]
then
   count=0
   partno=`$ETHTOOL -e $iname offset 16 length 4 | tail -1 | awk '{printf "%s%s%s-%s", $3,$2,$5,$4}'`
else # For Broadcom Cards partnumber is stored as hex. Convert to ASCII
	if [ "$pcidevice" = "164a" -o "$pcidevice" = "16aa" -o "$pcidevice" = "164c" -o "$pcidevice" = "16ac" ]
	then
		partnohex=`$ETHTOOL -e $iname offset 0x10c length 16 | tail -1 | cut -f3`
		partno=`echo "$partnohex" | perl -nle 'print join "", map { chr hex $_ } split " ";'`
	else
	if [ "$drvname" = "tg3" ]
	then
		partnohex=`$ETHTOOL -e $iname offset 0x84 length 10 | tail | awk -Fx '{ printf("%s ",$3)}'`
		partno=`echo "$partnohex" | perl -nle 'print join "", map { chr hex $_ } split " ";'`
	else
		partnohex=`$ETHTOOL -e $iname offset 0x84 length 10 | tail -1 | cut -f3`
		partno=`echo "$partnohex" | perl -nle 'print join "", map { chr hex $_ } split " ";'`
   	fi
   fi	
fi   

}

#========================================================
# 		Main Program Starts Here
#========================================================
TEMP=`/usr/bin/getopt 'i:f:d:A' "$@" 2>/dev/null`

if [ $? != 0 ] ; then
    usage
    exit 1
fi

eval set -- "$TEMP"
while true ; do
    case "$1" in
        -i) iname="$2" ; ioption=1 ; shift 2 ;;
        -f) fname="$2" ; foption=1 ; shift 2 ;;
        -d) dirname="$2" ; doption=1 ; shift 2 ;;
        -A) Aoption=1 ; shift ;;
         --) shift ; break ;;
         *) shift ; break ;;
    esac
done

# Perform sanity checks
check_for_errors
check_for_ethtool_ver

if [ "$foption" = "1" ]
then
  /bin/touch $fname >/dev/null 2>&1
  if [ "$?" != "0" ]
  then
    echo "Error!! Could not create $fname. Pl. check write permissions"
    exit 1
  else # Zero out the file contents if present
    > $fname
  fi
fi


# Generate Interface list if the user has given the -A option

if [ "$Aoption" = "1" ]
then
   interface_list=
   # Generate the ethX interface list
   for i in `ifconfig -a | egrep "^eth[0-9]*[0-9]" | awk '{print $1}' | egrep -v "[.:]"`
   do
      interface_list="$interface_list $i"
   done
   for i in `ifconfig -a | egrep "^vmnic[0-9]*[0-9]" | awk '{print $1}' `
   do
      interface_list="$interface_list $i"
   done
   for i in `ifconfig -a | egrep "^em[0-9]*[0-9]" | awk '{print $1}' | egrep -v "[.:]"`
   do
      interface_list="$interface_list $i"
   done
#	Support for XEN OS. Xen moves physical interface to peth* if bridge 
#	is attached to corrosponding eth*
   for i in `ifconfig -a | egrep "^peth[0-9]*[0-9]" | awk '{print $1}' | egrep -v "[.:]"`
   do
      interface_list="$interface_list $i"
   done
else
      # Check if this device exists on the system
      interface_list=$iname
      /sbin/ifconfig $iname > /dev/null 2>&1
      if [ $? != 0 ]
      then
           echo "Error!! $iname: Device does not exist. Exiting"
           exit 1
      fi
fi


# Now Dump the info either in the file for -f, directory
# For -d or stdout if none
# Create temp directory
create_tmp_dir
for i in `echo $interface_list`
do
   iname=$i
   invalid_interface=0
   err=0
   if [ "$doption" = "1" ]
   then
      fname=$dirname/$iname.info
      /bin/touch $fname > /dev/null 2>&1
      if [ "$?" != "0" ]
      then
        echo "Warning!! Could not create $fname. Pl. check write permissions"
        continue
      else # Zero out the file contents if present
        > $fname
      fi
   fi
   # If proc entries exist, use them
   if [ "$foption" = "1" -o "$doption" = "1" ]
   then
      # we cannot use copy here since -A with -f will overwrite.
      if [ -f $INTEL_PROC_DIR/$iname.info ]
      then
		cat $INTEL_PROC_DIR/$iname.info >> $fname
		echo -e "\n\n" >> $fname
		continue
      elif [ -f $BCOM_PROC_DIR/$iname.info ]
      then
		cat $BCOM_PROC_DIR/$iname.info >> $fname
		echo -e "\n\n" >> $fname
		continue
      elif [ -f $INTEL_VMWARE_PROC_DIR/$iname.info ]
      then
		cat $INTEL_VMWARE_PROC_DIR/$iname.info >> $fname
		echo -e "\n\n" >> $fname
		continue
      elif [ -f $BCOM_VMWARE_PROC_DIR/$iname.info ]
      then
		cat $BCOM_VMWARE_PROC_DIR/$iname.info >> $fname
		echo -e "\n\n" >> $fname
		continue
      fi
   else  # display to stdout
      if [ -f $INTEL_PROC_DIR/$iname.info ]
      then
		cat $INTEL_PROC_DIR/$iname.info
		continue
      elif [ -f $BCOM_PROC_DIR/$iname.info ]
      then
		cat $BCOM_PROC_DIR/$iname.info
		continue
      elif [ -f $INTEL_VMWARE_PROC_DIR/$iname.info ]
      then
		cat $INTEL_VMWARE_PROC_DIR/$iname.info
		continue
      elif [ -f $BCOM_VMWARE_PROC_DIR/$iname.info ]
      then
		cat $BCOM_VMWARE_PROC_DIR/$iname.info
		continue
      fi
   fi
   # 
   # Note that always the get_drv_info
   # needs to be called first
   #
   if [ "$doption" = "1" ]
   then
	staticfname=$dirname/.$iname.sinfo
        if [ ! -f "$staticfname" ]
	then
   		get_drv_info 
		if [ $invalid_interface -eq 1 ]
		then
			rm -f $fname
			continue;
		fi
   		get_pci_info
	#	get_port_no
	else
		# We still need pcivendor to determine
		# Which card this is.
		pcivendor=`grep -i pci_vendor $staticfname|awk '{print $2}' | sed 's/0x//g'`
	fi
   else
   		get_drv_info 
		if [ $invalid_interface -eq 1 ]
		then
			continue;
		fi
   		get_pci_info
	#	get_port_no
   fi
   
   # This code changes are done for hiding the VF's showing in SMH
   if [ "$irq" = "0" ]
   then 
      continue;
   fi   
   
   get_speed_duplex_link
   get_stats
   if [ $invalid_interface -eq 1 ]
   then
	[ -f "$fname" ] && rm -f $fname
	[ -f "$staticfname" ] && rm -f $staticfname
	continue;
   fi
   #
   # Re-direct output appropriately
   #
   if [ "$doption" = "1" ]
   then
        if [ -f "$staticfname" ]
	then
          cp $staticfname $fname
          display_dynamic_proc >> $fname 2>&1
	else
          display_static_proc > $staticfname 2>&1
          cp $staticfname $fname
          display_dynamic_proc >> $fname 2>&1
	fi
   elif [ "$foption" = "1" ]
   then
      display_static_proc >> $fname 2>&1
      display_dynamic_proc >> $fname 2>&1
   else
      display_static_proc
      display_dynamic_proc
   fi
   if [ $err -eq 1 ]
   then
   		rm -f $fname
        if [ -f "$staticfname" ]
		then
			rm -f $staticfname
        fi
   fi
done
   del_tmp_dir
exit 0
