#!/bin/bash

#	Copyright (c) 2016 Brocade Communications Systems, Inc.
#	All rights reserved.

#	Ethernet Port Monitor - ethif - Use this CLI to display or set the link operating modes.

PATH=/fabos/link_bin:/bin:/usr/bin:/sbin:/usr/sbin:/fabos/link_abin:/fabos/link_sbin:/fabos/link_rbin:/fabos/factory:/fabos/xtool
STS_OK=0
STS_ERR=255

TOTAL_ARGS=0

ETHIF_OPT="help"

INTERFACE=0
value=0
AN_VALUE=0
SPEED_VALUE=0
CAP_VALUE=0

TIME_VAL=0
new_config=0
RETRY_VAL=0
TCP_PARAM="No"

SWBD=`/sbin/sin | /bin/sed -n -e 's/^.\+\(SWBD\)\([[:digit:]]\{1,\}\).\+$/\2/gp' 2> /dev/null`
LINUX_VER=`/bin/uname -r | /usr/bin/cut -c1-6` 
chassis_info=`/bin/getchassisconfig`

ischassis=`echo $chassis_info | \
        sed -n -e 's/.*Chassis based system: //gp' | \
        sed -n -e 's/ .*//gp'`


display_usage() {
	
		echo
		echo "Please enter the following options."
		echo
		echo "To display the link attributes."
		echo "ethif --show interface"
		echo "ethif --show -tcptimeoutlevel"
		echo
		echo "To set the attributes."
		echo "ethif --set interface -auto-negotiate | -an [on|off] -speed [10|100|1000] -duplex [full]"
		echo "ethif --set -tcptimeoutlevel [1|2|3|4|5]"
		echo "tcptimeoutlevel option configures the timeout for half open TCP IPv4 and IPv6 connections."
		echo "Approximate timeout value for each level is provided as below:

Timeout level   |  Timeout in seconds
     1          |        3
     2          |        7
     3          |        15
     4          |        31
     5          |        63"
		echo
		if [ ! $LINUX_VER \< "2.6.34" ]; then
			echo "To clear the error counters."
                	echo "ethif --reseterror interface"
                	echo
		fi
		echo "Usage."
		echo "ethif --help."
		echo
}

process_args() {

	argc=$#
	argv=("$@")
	TOTAL_ARGS=$argc

	for ((i=0;i<$argc;i=$((i+2))))
	do

		opt=${argv[$i]}
		value=${argv[$i+1]}

		if [ $i -eq 0 ]; then

			# Make sure that the first argument is only "show" or "set" or "help"

			if [ "$opt" == "--show" ]; then
				ETHIF_OPT="show"
				if [ "$value" == "-tcptimeoutlevel" ]; then
				  TCP_PARAM="Yes"
				else	
				   INTERFACE=$value
				fi
			elif [ "$opt" == "--set" ]; then
				ETHIF_OPT="set"
				if [ "$value" == "-tcptimeoutlevel" ]; then
				      TCP_PARAM="Yes"
				      RETRY_VAL=${argv[$i+2]}
				else
				      INTERFACE=$value
				fi
			elif [ "$opt" == "--reseterror" ]; then
				ETHIF_OPT="reseterror"
				INTERFACE=$value
			elif [ "$opt" == "--help" ]; then
				ETHIF_OPT="help"
			else
				echo "Unsupported option."
				return $STS_ERR
	        fi
			continue

		fi

		if [ "$opt" == "-auto-negotiate" -o "$opt" == "-an" ]; then
			AN_VALUE=$value
		elif [ "$opt" == "-speed" ]; then
			SPEED_VALUE="$value"
		elif [ "$opt" == "-duplex" ]; then
			CAP_VALUE="$value"
		else
			return $STS_ERR
		fi

	done

	return $STS_OK
}

validate_args() {

	if [ $TOTAL_ARGS -eq 0 -o $ETHIF_OPT = "help" -a $TOTAL_ARGS -eq 1 ]; then
		return $STS_OK
	fi

	if [ $ETHIF_OPT = "help" -a $TOTAL_ARGS -gt 1 ]; then
		# Make sure that help is not followed by any attributes."
		echo "Unsuppported options for the help command."
		return $STS_ERR
		fi

	if [ "$TCP_PARAM" = "Yes" ]; then
		if [ $ETHIF_OPT = "set" ]; then

			if [ $TOTAL_ARGS -lt 3 ]; then
				echo "TCP timeout level not specified"
				return $STS_ERR

			elif [ "$RETRY_VAL" -ge "1" -a "$RETRY_VAL" -le "5" ]; then
				return $STS_OK
			else
				echo "Unknown or invalid value of TCP timeout level."
				return $STS_ERR
			fi

		elif [ $ETHIF_OPT = "show" ]; then
			return $STS_OK
		fi
	fi
	
	if [ "$ischassis" = "Yes" ]; then
		if [ $ETHIF_OPT = "show" ]; then
			if [ "$INTERFACE" == "" -o "$INTERFACE" != "eth0" -a "$INTERFACE" != "eth3" -a "$INTERFACE" != "bond0" ]; then
				echo "Interface can only be eth0, eth3 or bond0."
				return $STS_ERR
			fi
		else
			if [ "$INTERFACE" == "" -o "$INTERFACE" != "eth0" -a "$INTERFACE" != "eth3" ]; then
				echo "Interface can only be eth0 or eth3."
				return $STS_ERR
			fi
		fi
	else
		if [ $ETHIF_OPT != "reseterror" ]; then
			if [ "$INTERFACE" != "eth0" ]; then
				echo "Interface can only be eth0."
				return $STS_ERR
			fi	
		fi
	fi
	
	if [ $ETHIF_OPT = "reseterror" -a $LINUX_VER \< "2.6.34" ]; then
                echo "Unsupported options for the command."
                return $STS_ERR
        fi
	

	if [ $ETHIF_OPT = "reseterror" -a $TOTAL_ARGS -gt 2 ]; then
                echo "Unsupported options for the command."
                return $STS_ERR
        fi
	
	if [ $ETHIF_OPT = "reseterror" ]; then 	
		if [ "$ischassis" = "Yes" ]; then
			if [ "$INTERFACE" == "" -o "$INTERFACE" != "eth0" -a "$INTERFACE" != "eth3" ]; then
                                echo "Interface can only be eth0 or eth3."
                                return $STS_ERR 
                        fi
		else
			if [ "$INTERFACE" != "eth0" ]; then
                                echo "Interface can only be eth0."
                                return $STS_ERR
			fi
		fi
	fi	

	if [ $ETHIF_OPT = "help" -o $ETHIF_OPT = "show" -o $ETHIF_OPT = "reseterror" ]; then
		# Return as we have completed the validation for help or show or reseterror.
		return $STS_OK
	fi

	if [ $ETHIF_OPT = "set" -a $TOTAL_ARGS -eq 2 ]; then
		return $STS_OK
	fi

	if [ "$AN_VALUE" == "" -o "$AN_VALUE" != "ON" -a "$AN_VALUE" != "OFF" -a "$AN_VALUE" != "on" -a "$AN_VALUE" != "off" ] ; then
		echo "Unknown or invalid value for \"an\"."
		return $STS_ERR
	fi

	if [ "$SPEED_VALUE" == "" -o "$SPEED_VALUE" != "1000" -a "$SPEED_VALUE" != "100" -a "$SPEED_VALUE" != "10" ] ; then
		echo "Unknown or invalid value for \"speed\"."
		return $STS_ERR
	fi

	#Restrict Graphite and Carbon to support only 1G Speed
        if [ $SWBD == "157" -o $SWBD == "158" -o $SWBD == "176" -o $SWBD == "177" ]; then
                if [ $SPEED_VALUE != "1000" ]; then
                        echo "Unknown or invalid value for \"speed\"."
                        return $STS_ERR
                fi
        fi

	if [ "$CAP_VALUE" == "" -o "$CAP_VALUE" != "FULL" -a "$CAP_VALUE" != "full" ] ; then
		echo "Unknown or invalid value for \"cap\"."
		return $STS_ERR

    fi

	return $STS_OK
}

ethif_show() {
	if [ $TCP_PARAM = "Yes" ]; then
		read new_config</proc/sys/net/ipv4/tcp_synack_retries
   	        if [ $new_config == 1 ]; then
                    TIME_VAL=3
           	elif [ $new_config == 2 ]; then
		    TIME_VAL=7
           	elif [ $new_config == 3 ]; then
                    TIME_VAL=15
		elif [ $new_config == 4 ]; then
		    TIME_VAL=31
           	elif [ $new_config == 5 ]; then
                    TIME_VAL=63
                fi
		echo "TCP timeout level : $new_config (~$TIME_VAL seconds)"  
		return $STS_OK
	fi
	echo "$INTERFACE interface:"
	echo

	if [ $INTERFACE = "bond0" ]; then

		# Read the entire output of bond0 and display the slave interfaces
		echo -n "bond0 includes physical interfaces:"
		/bin/cat /proc/net/bonding/bond0 | /bin/grep -i "Slave Interface" |
		while read LINE; do
			INTF=${LINE##*: }
			echo -n " $INTF"
		done

		echo
		ACT_INTF=`/bin/cat /proc/net/bonding/bond0 | /bin/grep -i "Currently Active Slave"`
		ACT_INTF=${ACT_INTF##*: }
		echo "Currently Active Interface: $ACT_INTF"

		# Read the entire output of bond0 and display the interfaces other than Active
		echo -n "Currently Slave Interface:"
		/bin/cat /proc/net/bonding/bond0 | /bin/grep -i "Slave Interface" |
		while read LINE; do
 			INTF=${LINE##*: }
			if [ $INTF != $ACT_INTF ]; then
				echo -n " $INTF "
			fi
		done

		echo

		# Display the link mode and mac address of curent active interface
		/fabos/rbin/ifmodeshow $ACT_INTF -support

	else

		/fabos/rbin/ifmodeshow $INTERFACE -support

	fi

	echo

	/sbin/ifconfig $INTERFACE

	return $STS_OK
}

ethif_set() {

	if [ $ETHIF_OPT = "set" -a $TCP_PARAM = "Yes" ]; then
		read new_config</proc/sys/net/ipv4/tcp_synack_retries
		if [ $new_config = $RETRY_VAL ]; then
			echo "No change in configuration. Timeout level already set to $RETRY_VAL"
			return $STS_OK
		fi
#set the proc entry
		echo $RETRY_VAL > /proc/sys/net/ipv4/tcp_synack_retries
   	        if [ $RETRY_VAL == 1 ]; then
                    TIME_VAL=3
           	elif [ $RETRY_VAL == 2 ]; then
		    TIME_VAL=7
           	elif [ $RETRY_VAL == 3 ]; then
                    TIME_VAL=15
		elif [ $RETRY_VAL == 4 ]; then
		    TIME_VAL=31
           	elif [ $RETRY_VAL == 5 ]; then
                    TIME_VAL=63
                fi
		echo "Timeout level changed to $RETRY_VAL (~$TIME_VAL seconds)"
		myFABOS_SWITCHNO=$FABOS_SWITCHNO
		FABOS_SWITCHNO=0;
#set config entry	
	        /fabos/cliexec/config set ipadm.tcptimeoutlevel 2 "$RETRY_VAL"
	        /fabos/cliexec/config update
		FABOS_SWITCHNO=${myFABOS_SWITCHNO};
#audit log
		/fabos/cliexec/errlogtest -i IPAD-1006 -a $RETRY_VAL
#set peer proc entry
           if [ "$ischassis" = "Yes" ]; then
                stby_addr="$(otherhost)"
                #echo $stby_addr
                /usr/bin/rsh $stby_addr "/bin/echo $RETRY_VAL > /proc/sys/net/ipv4/tcp_synack_retries"
           fi
	return $STS_OK

	fi

	if [ $ETHIF_OPT = "set" -a $TOTAL_ARGS -eq 2 ]; then
		/fabos/rbin/ifmodeset $INTERFACE -support
	else
		/fabos/rbin/ifmodeset $INTERFACE -an $AN_VALUE -speed $SPEED_VALUE -cap $CAP_VALUE -support
	fi

	return $STS_OK
}

#check half duplex support
ethif_duplex_support() {
        for bd in 148 171 141 142 157 158 165 166; do
                if [ $SWBD == "$bd" ]; then
                        return $STS_ERR
                fi
        done
        return $STS_OK
}

ethif_clear() {
	
	echo "Statistics cleared for $INTERFACE"

	echo $INTERFACE > /proc/net/clear-statistics
	if [ "$ischassis" = "Yes" ]; then
		echo "bond0" > /proc/net/clear-statistics
	fi
	
	#record a raslog for reesterror counters
        /fabos/cliexec/errlogtest -i SWCH-1032 -a $INTERFACE
	
	return $STS_OK
} 

distname=$(/sbin/sin|grep -i "platform:"|/usr/bin/cut -d" " -f2|/usr/bin/cut -d "," -f 1)
swbdnum=$(/bin/echo $distname | /bin/awk -F"SWBD" '{print $2}')
otherhost(){
 HASHOW="$(hashow)"
 that=${HASHOW#*Remote CP \(Slot}
 that="${that%%,*}"
 otherCpSlot=${that}
   case ${swbdnum} in
     '165' | '166' | '179' | '180')
 	ip=`echo "127.3.1."$otherCpSlot | /bin/awk -F ' ' '{print $1$2}'`
 	printf $ip
 	;;
    *)
	printf 0.0.0.0
	;;
     esac
}

# First perform the rbac check to see whether the command is supported.
/fabos/libexec/rbac_check `/bin/basename $0`
ret=$?
if [ $ret -ne 0 -a $ret -ne 2 ]; then
	exit $STS_ERR
fi

# Now process the args to perform the rbac check for options.
process_args $@
#if [ $? -ne $STS_OK ];then
#	display_usage
#	exit $STS_ERR
#fi

# Perform the rbac check for the options.
/fabos/libexec/rbac_check -opt `/bin/basename $0` $ETHIF_OPT
ret=$?
if [ $ret -ne 0 -a $ret -ne 2 ];then
	exit $STS_ERR
fi

# Validate the args.
validate_args
if [ $? -ne $STS_OK ]; then
	display_usage
	exit $STS_ERR
fi

if [ $ETHIF_OPT = "help" ]; then
	display_usage
elif [ $ETHIF_OPT = "show" ]; then
	ethif_show
elif [ $ETHIF_OPT = "set" ]; then
	ethif_set
elif [ $ETHIF_OPT = "reseterror" ]; then
	ethif_clear
else
	echo "Unknown option."
	display_usage
fi

exit $STS_OK
