#!/bin/bash
################################################################################
#
# lseth - Display Ethernet NIC information in a compact easy to read way.
#
# Usage: lseth [-6][-d][-h][-i][-k][-l][-n] [interfaces]
#
#   -6               Show ipv6 addresses
#   -d <driver>      Show only drivers of the specified type
#   -h               Help
#   -i               NIC info (symbolic names)
#   -I               NIC info (numeric codes)
#   -k               List offload information
#   -l               Long list
#   -n               Do not resolve ip addresses
#
# Notes:
#      - lseth uses ifconfig, ethtool, lspci and host to gather information
#        about the NIC.
#      - Wildcards may be used to specify NICs (i.e. eth[2-4])
#      - You need to be root to run this script
#
# Tehuti Networks(R) Network Driver
# Copyright (C) 2010 Tehuti Networks Ltd. All rights reserved
#
# Author: Arnon Kanfi
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
################################################################################
################################################################################
#
# Variable initialization
#
################################################################################
interfaces=eth*
driver=""
offload_info=0
long_list=0
resolve_names=1
nic_info=0
ipv6=0


################################################################################
#
# PRINT_USAGE
#
################################################################################

function print_usage {

    cat <<EOF
$0 [-6][-d][-h][-i][-k][-l][-n] [interfaces]

   -6               Show ipv6 addresses
   -d <driver>      Show only drivers of the specified type
   -h               Help
   -i               NIC info (symbolic names)
   -I               NIC info (numeric codes)
   -k               List offload information
   -l               Long list
   -n               Do not resolve ip addresses
EOF
    exit
}


################################################################################
#
# GET_INTERFACES    Return interfaces (handles wildcards)
#
################################################################################

function get_interfaces {(
    cd /sys/class/net
    echo $*
)}


################################################################################
#
# MAIN SCRIPT
#
################################################################################

# PROCESS COMMAND LINE FLAGS

while getopts  "6d:hiIkln" opt
do
    case $opt in
        6)
            ipv6=1
            ;;
        
        d)
            driver=$OPTARG
            ;;
        
        h)
            print_usage
            ;;

        I)
            nic_info=2
            ;;

        i)
            nic_info=1
            ;;

        k)
            offload_info=1
            ;;

        l)
            long_list=1
            ipv6=1
            ;;
        
        n)
            resolve_names=0
            ;;
    esac
done

# PROCESS THE OPTIONAL COMMAND LINE THREAD AND ITER ARGUMENTS

shift `expr $OPTIND - 1`
[ -z "$*" ] || interfaces=$*

interfaces=`get_interfaces $interfaces`

for xface in $interfaces
do
    if [ -z "$driver" ] || ethtool -i "$xface" 2>/dev/null | grep -q "$driver"
    then
        printf "%-8s" "$xface"
        # Show driver & version

        tmp_file=`mktemp`
        ethtool -i $xface 2>/dev/null | awk \
             '/driver:/      { print "Driver:           " $2} 
              /version:/     { print "        Version:          " $2 ; exit }' \
             > $tmp_file
        [ -s $tmp_file ] || echo > $tmp_file
        cat $tmp_file
        rm $tmp_file
        
        # Show ifconfig info
        ifconfig $xface | awk -v resolve_names=$resolve_names -v ipv6=$ipv6 \
             '/HWaddr/      {print "        HWaddr:           " $5} 
              /inet addr/   { sub("addr:", "", $2)  
                              sub("Bcast:", "", $3) 
                              sub("Mask:", "", $4)
                              printf "        IP addr:          %-12s                     ", $2
                              cmd="host " $2 "| cut -d \" \" -f 5" ;
                              if (resolve_names)
                                  system(cmd)
                              else
                                  print ""
                              print "        Broadcast:        " $3
                              print "        Mask:             " $4 }
              /inet6 addr/   { if (ipv6)
                               {
                                   sub("addr:", "", $2)  
                                   printf "        IPv6 addr:        %-32s %s        ", $3, $4
                                   cmd="host " $3 "| cut -d \" \" -f 5" ;
                                   # if (resolve_names)
                                   #     system(cmd)
                                   # else
                                       print ""
                                }}
              /MTU/         { s = substr($0, index($0, "MTU:") + 4)
                              split(s, a, " ")
                              print "        MTU:              " a[1] }'

        # Show offload features
        [ $offload_info -eq 1 ] &&
        ethtool -k $xface 2>/dev/null | awk \
             '/rx-checksumming:/      { print "        rx-checksumming:  " $2} 
              /tx-checksumming:/      { print "        tx-checksumming:  " $2 }
              /scatter-gather:/       { print "        scatter-gather:   " $2 }
              /tcp segmentation/      { print "        tso:              " $4 }
              /generic segmentation/  { print "        gso:              " $4 }
              /receive-offload:/      { print "        gro:              " $2 }'

        if [ $nic_info -eq 1 ]
        then
            bus_address=`ethtool -i $xface | awk '/bus-info:/      { print $2}'`
            echo "        Bus address:     " $bus_address
            lspci -vs $bus_address | awk \
                ' NR == 1    {sub(".+: ", "", $0) 
                              print  "        Device:           " $0 }
                  NR == 2    {sub(".+: ", "", $0) 
                              print  "        Subsystem:        " $0 }
                                '
        elif [ $nic_info -eq 2 ]
        then
            bus_address=`ethtool -i $xface | awk '/bus-info:/      { print $2}'`
            echo "        Bus address:     " $bus_address
            lspci -vns $bus_address | awk \
                ' NR == 1    {print  "        Vendor:           " \
                                     substr($0, length($0) - 8, 4)
                              print  "        Device:           " \
                                     substr($0, length($0) - 3)}
                  NR == 2    {print  "        Subsystem:        " \
                                     substr($0, length($0) - 3) }
                                '
       fi    
        # Show long features
        if [ $long_list -eq 1 ]
        then
            ethtool $xface | awk \
                '/Speed:/                { print "        Speed:            " $2} 
                 /Duplex:/               { print "        Duplex:           " $2 }
                 /Auto-negotiation:/     { print "        Auto-negotiation: " $2 }
                 /Link detected:/        { print "        Link detected:    " $3 }'
        else
            ethtool $xface | awk \
                '/Link detected:/        { print "        Link detected:    " $3 }'
        fi
        echo
    fi
done
