#!/bin/bash

# clean_portcfg
#
#		Inspect all of the portCfg and lsportCfg entries on a switch and
#		correct these bits:
#			E-port Credit
#			D-Port DWDM
#			FEC
#			Network Patroller Mirror Port
#
#		Input:
#			from_major - First number after the "v" in firmware version
#						upgraded from
#			from_minor - Second number after the "v" in firmware version
#						upgraded from
#			from_patch - Third number after the "v" in firmware version
#						upgraded from
#			to_major - First number after the "v" in firmware version
#						upgraded to
#			to_minor - Second number after the "v" in firmware version
#						upgraded to
#			to_patch - Third number after the "v" in firmware version
#						upgraded to
#
#       Example:
#			clean_portcfg 7 1 0 7 2 0
#
PORTCFG_WORD2_MSK=0x0bfbffff

let "PORTCFG_WORD2_CLR = ~PORTCFG_WORD2_MSK"
PORTCFG_EPORT_CREDIT_BIT=0x10000000

PORTCFG_DPORT_DWDM_BIT=0x20000000
PORTCFG_DPORT_PROV_BIT=0x04000000
PORTCFG_DPORT_BIT=0x80000000

PORTCFG_DFE_BIT=0x00040000
PORTCFG_TRUNKING_BIT=0x10000000
PORTCFG_ENCR_BIT=0x100

CUR_MAJOR=`/sbin/getfabosver | sed -n -e 's/Major://gp'`
CUR_MINOR=`/sbin/getfabosver | sed -n -e 's/Minor://gp'`
found_bad=0
MAX_ENCRYPTION_FC_PORT=0
size1=0
size2=0
size3=0

swbd() {
    /bin/sed -n -e 's/^.*\(SWBD[[:digit:]]\{1,\}\).\+$/\1/gp'
}

SWBD=$(/sbin/sin | swbd 2> /dev/null)

case ${SWBD##SWBD} in
'161')
	MAX_ENCRYPTION_FC_PORT=48
	;;
'162')
	MAX_ENCRYPTION_FC_PORT=64
	;;
'165')
	MAX_ENCRYPTION_FC_PORT=256
	;;
'166')
	MAX_ENCRYPTION_FC_PORT=384
	;;
*)
	MAX_ENCRYPTION_FC_PORT=0
	;;
esac

STS_OK=0

#echo "MAX_ENCRYPTION_FC_PORT=$MAX_ENCRYPTION_FC_PORT"

do_clean()
{
	in_from_major=$1
	in_from_minor=$2
	in_from_patch=$3
	in_to_major=$4
	in_to_minor=$5
	in_to_patch=$6
	in_config=$7

	# This holds the new config
	new_config=""
	found_bad=0

	if [ $MAX_ENCRYPTION_FC_PORT -eq 0 ]; then
		return $STS_OK
	fi

	# Take one port at a time up to a semicolon ";"
	while (( ${#in_config} ))
	do
		port_cfg=${in_config%%;*}
		in_config=${in_config#*;}
		# echo "port_cfg=$port_cfg"
		# echo "new in_config=$in_config"
		more_config=`expr index "$in_config" ";"`
		if (( $more_config == 0 )) ; then
			# echo "No semicolon..."
			in_config=""
		fi

		# Seperate out the words
		port=${port_cfg%%,*}
		next_word=${port_cfg#*,}
		word0=${next_word%%,*}
		next_word=${next_word#*,}
		word1=${next_word%%,*}
		next_word=${next_word#*,}
		word2=${next_word%%,*}
		next_word=${next_word#*,}
		word3=${next_word%%,*}
		# echo "port=$port word0=$word0 word1=$word1 word2=$word2 word3=$word3"

		if [ $port -ge $MAX_ENCRYPTION_FC_PORT ] ; then
			break;
		fi

#if [ $port -lt $MAX_ENCRYPTION_FC_PORT ] ; then
		if (( $word1 & $PORTCFG_ENCR_BIT )) ; then
			if (( $word0 & $PORTCFG_TRUNKING_BIT )) ; then
				found_bad=1
				let "word0 = word0 & ~PORTCFG_TRUNKING_BIT"
				word0=`printf "0x%x" $word0`
			fi
		fi
#fi

		# After any changes, reconstruct the port config
		new_port_config="$port,$word0,$word1,$word2,$word3;"
		# echo "new_port_config=$new_port_config"

		printf $new_port_config >> /tmp/post_clean_2
		# Add it to a new config value
		#new_config="$new_config$new_port_config"
	done
	if (( $found_bad == 1 )) ; then
		size1=$(find /tmp/post_clean_1 -printf "%s")
		size2=$(find /tmp/post_clean_2 -printf "%s")
		if [ $size1 == $size2 ] ; then
			read new_config</tmp/post_clean_2
		else
			size3=`expr $size1 - $size2`
			tail --bytes=$size3 /tmp/post_clean_1 > /tmp/post_clean_3
			read new_config</tmp/post_clean_2
			printf "%s" $new_config>/tmp/post_clean_1
			read new_config</tmp/post_clean_3
			printf "%s" $new_config>>/tmp/post_clean_1
			read new_config</tmp/post_clean_1
		fi
	fi
	#new_config=`cat /tmp/post_clean`
	#echo "new_config=$new_config"
}

if (( $# < 6 )) ; then
	echo "Not enough parameters"
	echo "Usage: clean_portcfg <from_major> <from_minor> < from_patch> <to_major> <to_minor> <to_patch>"
	exit -3
fi

from_major=$1
from_minor=$2
from_patch=$3
to_major=$4
to_minor=$5
to_patch=$6

# echo "From v$from_major.$from_minor to v$to_major.$to_minor"

# Get portCfg for this Fabric ID
# echo "Checking portCfg for FID=$fabric_id"
portCfg=`/fabos/cliexec/config get portCfg 5`
# echo "portCfg=$portCfg"

if [ ! -f /tmp/post_clean_1 ]; then
	touch /tmp/post_clean_1
fi

if [ ! -f /tmp/post_clean_2 ]; then
	touch /tmp/post_clean_2
fi

if [ ! -f /tmp/post_clean_3 ]; then
	touch /tmp/post_clean_3
fi

#/fabos/cliexec/config get portCfg 5 > /tmp/post_clean_1
printf "%s" $portCfg>/tmp/post_clean_1

# Clean up invalid bits
do_clean $from_major $from_minor $from_patch $to_major $to_minor $to_patch $portCfg

rm /tmp/post_clean_1 2>/dev/null
rm /tmp/post_clean_2 2>/dev/null
rm /tmp/post_clean_3 2>/dev/null

# If something changed, then write the config back to the config DB
if (( $found_bad == 1 )) ; then
	# echo
	# echo "Writing new config to DB of FID..."
	# echo
	#echo "after do_clean set portcfg $new_config"
	/fabos/cliexec/config set portCfg 5 "$new_config"
	/fabos/cliexec/configcommit
# else
	# echo
	# echo "No changes needed."
	# echo
fi

# Get lsportCfg for this Fabric ID
# echo "Checking lsportCfg for FID=$fabric_id"
portCfg=`/fabos/cliexec/config get lsportCfg 5`
# echo "portCfg=$portCfg"

if [ ! -f /tmp/post_clean_1 ]; then
	touch /tmp/post_clean_1
fi

if [ ! -f /tmp/post_clean_2 ]; then
	touch /tmp/post_clean_2
fi

if [ ! -f /tmp/post_clean_3 ]; then
	touch /tmp/post_clean_3
fi

#/fabos/cliexec/config get lsportCfg 5 > /tmp/post_clean_1
printf "%s" $portCfg>/tmp/post_clean_1

# Clean up invalid bits
do_clean $from_major $from_minor $from_patch $to_major $to_minor $to_patch $portCfg

rm /tmp/post_clean_1 2>/dev/null
rm /tmp/post_clean_2 2>/dev/null
rm /tmp/post_clean_3 2>/dev/null

# If something changed, then write the config back to the config DB
if (( $found_bad == 1 )) ; then
	# echo
	# echo "Writing new config to DB of FID..."
	# echo
	#echo "after do_clean set lsportcfg $new_config"
	/fabos/cliexec/config set lsportCfg 5 "$new_config"
	/fabos/cliexec/configcommit
# else
	# echo
	# echo "No changes needed."
	# echo
fi
