#!/bin/ksh # $Id: duplex,v 1.30 2009/04/13 01:30:18 jad Exp $ # We're a netlint plugin that checks the duplex & speed of our (petef,ksb) # network interfaces. #****p* netlint/duplex # NAME # duplex # DESCRIPTION # A host's network interfaces can be set to any speed, and duplex, and either # forced or auto. Site policy determines which combinations are allowed for # any given host, interface, and/or OS. #*** PROGNAME=`basename $0` OS=`uname -s | tr -d '-'` : ${CARP:=echo} SUDO="" if [ -x /usr/bin/sudo ]; then SUDO="/usr/bin/sudo" elif [ -x /usr/local/bin/sudo ]; then SUDO="/usr/local/bin/sudo" fi PATH=/usr/xpg4/bin:$PATH:/usr/sbin:/sbin:/etc if [ `id -u` -eq 0 ]; then SUDO=" " fi for Prog in mii-tool ethtool ndd lanadmin do V=`echo $Prog | tr '-' '_'` W=`whence $Prog 2>/dev/null` [ ! -z "$W" ] && [ ! -z "$SUDO" ] && eval SUDO_$V=\"\$SUDO \$W\" && export SUDO_$V if [ -x /usr/local/bin/op ] && /usr/local/bin/op help 2>/dev/null | grep "^$Prog[ ]" >/dev/null ; then eval OP_$V=\"/usr/local/bin/op \$Prog\" fi eval : \${OP_$Prog:=SUDO_$Prog} export OP_$V done export CARP if [ _"$1" = _"-V" ]; then echo "$PROGNAME: "'$Id: duplex,v 1.30 2009/04/13 01:30:18 jad Exp $' exit 0 fi #****a* duplex/DUPLEX_OP # NAME # DUPLEX_OP # FORMAT # DUPLEX_OP: op rule interface # DESCRIPTION # The op program is used to gain access to the programs needed to display the # attributes of an interface. If the rules which allow the monitor user to # display an interface are missing this tag is presented in the report. # REMEDIATION # Install the correct op and/or op rule-base from the master-source. #*** #****a* duplex/DUPLEX_SPEED # NAME # DUPLEX_SPEED # FORMAT # DUPLEX_SPEED: interface: speed/duplex # DESCRIPTION # This is not an error by itself, netlint just reports the speed returned by # the OS on the host (viz. 10, 100 or 1000). # IMPACT # Duplex issues cause slugish performance in network application, like DNS # lookups, ssh session startup, and PEG droppouts. # REMEDIATION # If site policy says the reported speed should be changed: # * Check that the full-duplex script is installed an up to date on the host. # * Check that the policy in ~netlint/lib/duplex is correct. # * Check to see if the host's interfaces were added after the last boot. # # Fix the issues you uncovered: Update software, reboot the host, and/or # fix the policy file. #*** #****a* duplex/DUPLEX_NEG # NAME # DUPLEX_NEG # FORMAT # DUPLEX_NEG: interface: negotiation # DESCRIPTION # This is not an error by itself. It reports the the negotiation status of # the interface, either force or auto. # REMEDIATION # If site policy says the reported negotiation status should be changed, # remediate it as you would DUPLEX_SPEED. #*** # duplex ref: http://www-didc.lbl.gov/TCP-tuning/duplex.htm # function check_Linux { # Use mii-tool on pre 2.6 kernels if uname -r | grep '^2\.[24]\.' >/dev/null 2>&1 ; then # if we can't find mii-tool, we loose [ -z "$OP_mii_tool" ] && return 1 s=`$OP_mii_tool $1 2>/dev/null` || { $CARP "DUPLEX_OP: $OP_mii_tool $1" return 1 } expr "$s" : ".*no link.*" >/dev/null && { return 0 } # mii-tool will only say negotiated, link ok when it negotiates gig-E expr "$s" : ".*negotiated, link ok" >/dev/null && { $CARP "DUPLEX_SPEED: $1: auto/auto" $CARP "DUPLEX_NEG: $1: auto" return 0 } speed=`echo $s | sed -n -e 's,.* \([0-9]*\) Mbit.*,\1,p' -e 's,.* \([0-9]*\)base.*,\1,p'` case "$s" in *full*duplex*|*-FD*) duplex='full' ;; *half*duplex*|*-HD*) duplex='half' ;; *) duplex='unknown' ;; esac $CARP "DUPLEX_SPEED: $1: $speed/$duplex" case "$s" in *no*autonegotiation*) $CARP "DUPLEX_NEG: $1: force" ;; *negotiate*) $CARP "DUPLEX_NEG: $1: auto" ;; *) $CARP "DUPLEX_NEG: $1: force" ;; esac else [ -z "$OP_ethtool" ] && return 1 s=`$OP_ethtool $1 2>/dev/null` || { $CARP "DUPLEX_OP: $OP_ethtool $1" return 1 } expr "$s" : ".*Link detected: no.*" >/dev/null && { return 0 } speed=`echo $s | sed -n -e 's,.*Speed: \([0-9]*\)Mb/s.*,\1,p'` case "$s" in *Duplex:*Full*) duplex='full' ;; *Duplex:*Half*) duplex='half' ;; *) duplex='unknown' ;; esac $CARP "DUPLEX_SPEED: $1: $speed/$duplex" case "$s" in *Auto-negotiation:*off*) $CARP "DUPLEX_NEG: $1: force" ;; *Auto-negotiation:*on*) $CARP "DUPLEX_NEG: $1: auto" ;; *) $CARP "DUPLEX_NEG: $1: force" ;; esac fi if grep ^ETHTOOL_OPTS /etc/sysconfig/network-scripts/ifcfg-$1 2>/dev/null | grep "autoneg on" >/dev/null 2>&1 ; then $CARP "DUPLEX_CONF: $1: 1000/full/auto" fi return 0 } function check_FreeBSD { case _$1 in _pflog*|_) return 0 ;; *) ;; esac s="`ifconfig $1 | sed -n -e 's,status:.*,,' -e 's,^[^s]*media:,,p'`" speed=`echo "$s" | sed -n -e 's,.*[ (]\([0-9]*\)base.*,\1,p'` case "$s" in *full*duplex*) duplex='full' ;; *) duplex='half' ;; esac $CARP "DUPLEX_SPEED: $1: $speed/$duplex" case "$s" in *autoselect*) $CARP "DUPLEX_NEG: $1: auto" ;; *) $CARP "DUPLEX_NEG: $1: force" ;; esac return 0 } function check_SunOS { # stolen from full_duplex and hmestat IDEV=`expr $1 : '\(......\)[0-9][0-9]*' \| $1 : '\(....\)[0-9][0-9]*' \| $1 : '\(...\)[0-9][0-9]*' \| $1 : '\(..\)[0-9][0-9]*'` NBRCHARS=`expr $IDEV : '.*'` if [ 0$NBRCHARS -eq 6 ]; then INST=`expr $1 : '......\(.*\)'` elif [ 0$NBRCHARS -eq 4 ]; then INST=`expr $1 : '....\(.*\)'` elif [ 0$NBRCHARS -eq 3 ]; then INST=`expr $1 : '...\(.*\)'` elif [ 0$NBRCHARS -eq 2 ]; then INST=`expr $1 : '..\(.*\)'` fi case $IDEV in le) $CARP "DUPLEX_SPEED: $1: 10/half" $CARP "DUPLEX_NEG: $1: auto" return 0 ;; bge|e1000g|nxge) OLDINST="" IDEV=$IDEV$INST O=`$OP_ndd /dev/$IDEV \? 2>&1` KNM=$IDEV ;; ipge) $CARP "DUPLEX_BADINT: Bad Interface driver" return ;; *) OLDINST=`$OP_ndd /dev/$IDEV instance` O=`$OP_ndd -set /dev/$IDEV instance $INST 2>&1` KNM=$IDEV:$INST ;; esac if expr "$O" : "op:.*" >/dev/null ; then $CARP "DUPLEX_OP: $OP_ndd" return 1 fi export IDEV speed=`$OP_ndd /dev/$IDEV link_speed 2>/dev/null| grep '[0-9]'` case "$speed" in 1000|2) speed=1000 ;; 100|1) speed=100 ;; 10|0) speed=10 ;; *) speed=auto ;; esac duplex=`$OP_ndd /dev/$IDEV link_status 2>/dev/null` case "$duplex" in *full*|1) duplex='full' ;; *half*|0) duplex='half' ;; *) duplex=unknown if $OP_ndd /dev/$IDEV \? | grep adv_1000 >/dev/null; then duplex=auto fi ;; esac $CARP "DUPLEX_SPEED: $1: $speed/$duplex" # are we a gigabit card? if $OP_ndd /dev/$IDEV \? | grep adv_1000autoneg_cap >/dev/null; then $CARP "DUPLEX_NEG: $1: auto" else case `$OP_ndd /dev/$IDEV adv_autoneg_cap` in 0) $CARP "DUPLEX_NEG: $1: force" ;; 1) $CARP "DUPLEX_NEG: $1: auto" ;; *) $CARP "DUPLEX_NEG: $1: unknown" ;; esac fi # What does the setgid bet tell us we should be? if [ ! -e /etc/hostname.$1 ] ; then : 'interface owned by VCS or the like' else BIT="`stat /etc/hostname.$1 2>/dev/null | sed -n -e 's,.*Mode: ([^/]*/......\(.\)...).*,\1,p'`" if [ _s = _"$BIT" -o _l = _"$BIT" ] ; then $CARP "DUPLEX_CONF: $1: 1000/full/auto" fi fi # Check not solaris 7 (e.g. guardsman.sac) # Is our link partner configured for gigabit? Let's ask the kernel. if whence kstat >/dev/null 2>&1 ; then lp_auto=`kstat $KNM | grep lp_cap_autoneg | awk '{ print $2}'` if [ "`kstat $KNM | grep lp_cap_1000fdx | awk '{ print $2}'`" -eq 1 -a "$lp_auto" -eq 1 ] ; then $CARP "DUPLEX_SWITCH: $1: 1000/full/auto" elif [ "`kstat $KNM | grep lp_cap_100fdx | awk '{ print $2}'`" -eq 1 -a "$lp_auto" -eq 0 ] ; then $CARP "DUPLEX_SWITCH: $1: 100/full/force" fi fi [ -z "$OLDINST" ] || $OP_ndd -set /dev/$IDEV instance $OLDINST return 0 } # all possible media settings: lsattr -REl ent0 -a media_speed function check_AIX { adapter=`echo $1 | sed 's/en/ent/'` # This line returns either Enabled or Disabled n=`entstat -d $adapter | grep ^Autonegotiation | cut -b18-` expr "$n" : "Enabled" >/dev/null && { $CARP "DUPLEX_SPEED: $1: auto/auto" $CARP "DUPLEX_NEG: $1: auto" return 0 } # This line gets a value with format 1000 Mbps Full Duplex s=`entstat -d $adapter | grep "Media Speed Running:" | cut -b20-` speed=`echo $s | cut -f1 -d" "` duplex=`echo $s | cut -f3 -d" " | tr '[A-Z]' '[a-z]'` $CARP "DUPLEX_SPEED: $1: $speed/$duplex" $CARP "DUPLEX_NEG: $1: force" return 0 } function check_HPUX { n=`expr "$1" : ".*[^0-9]\([0-9]*\)"` # HP 715's can only do 10/half, and lanadmin doesn't work on them if [ _`uname -m` = _"9000/715" ]; then $CARP "DUPLEX_SPEED: $1: 10/half" $CARP "DUPLEX_NEG: $1: auto" return 0 fi s=`$OP_lanadmin -x $n 2>/dev/null` || { $CARP "DUPLEX_OP: $OP_lanadmin -x $n" return 1 } expr "$s" : ".*NO LINK.*" >/dev/null && { return 0 } speed=`echo $s | sed -n -e 's,.*= \([0-9]*\) .*,\1,p'` duplex=`echo $s | sed -n -e 's,.* \([^-]*\)-[Dd]uplex.*,\1,p' | tr '[A-Z]' '[a-z]'` $CARP "DUPLEX_SPEED: $1: $speed/$duplex" case "$s" in *AUTONEG*) $CARP "DUPLEX_NEG: $1: auto" ;; *MANUAL*) $CARP "DUPLEX_NEG: $1: force" ;; *) $CARP "DUPLEX_NEG: $1: unknown" ;; esac return 0 } # INTS from netlint itself, skip the virtual ones (foo:1, etc) for int in $INTS do expr "$int" : ".*:.*" >/dev/null && continue set _ `echo " $IFACE_LIST" | sed -n -e "s/.*\( $int\)(\([^)]*\)).*/\1 \2/p"` if [ ether != ${6:-ether} ] ; then continue fi eval check_$OS \$int done exit 0