#!/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
#			to_major - First number after the "v" in firmware version
#						upgraded to
#			to_minor - Second number after the "v" in firmware version
#						upgraded to
#
#       Example:
#			clean_portcfg 7 1 7 2
#

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

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

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

	# This holds the new config
	new_config=""
	found_bad=0
	# 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"

		# Upgrade from v7.0 or v7.1 or v7.2
		# clean unused bits in 7.2 and lower.
		if (( $CUR_MAJOR == 7 )) && (( $CUR_MINOR <= 2 )) ; then
			if (( $word2 & $PORTCFG_WORD2_MSK )) || (( $word3 != 0 )) ; then
				# echo "FOUND BAD!!!"
				found_bad=1
				let "word2 = word2 & PORTCFG_WORD2_CLR"
				# For E-port Credits, if there are no credits clear that bit
				if (( $word2 & $PORTCFG_EPORT_CREDIT_BIT )) ; then
					# E-port Credits need to be checked.
					num_credits=`/fabos/cliexec/config get portEportCredits.$port 5`
						
					if (( !${#num_credits} )) ; then
						num_credits=0
					fi

					# If no credits then clear the bit.
					if (($num_credits == 0)) ; then
						let "word2 = word2 & ~PORTCFG_EPORT_CREDIT_BIT"
					fi
				fi

				# For D-port DWDM, if the port is not D-port, then clear that bit
				if (( $word2 & $PORTCFG_DPORT_DWDM_BIT )) ; then
					# See if D-port config is enabled.
					if (( !($word2 & $PORTCFG_DPORT_BIT) )) ; then
						# If no D-port then clear the bit.
						let "word2 = word2 & ~PORTCFG_DPORT_DWDM_BIT"
					fi
				fi
				# For D-Port PROVISION (7.3), if the port is not configured as
				# D-Port, clear that bit. This is to cover downgrade to 7.2 and
				# upgrade again to 7.3 case.
				if (( $word2 & $PORTCFG_DPORT_PROV_BIT )) ; then
					if (( !($word2 & $PORTCFG_DPORT_BIT) )) ; then
						let "word2 = word2 & ~PORTCFG_DPORT_PROV_BIT"
					fi
				fi
				# For DFE config, if word3 is non-0 its a corruption as the
				# versions that support DFE feature will make word3 as 0.
				if (( $word2 & $PORTCFG_DFE_BIT )) && (( $word3 != 0 )) ; then
					let "word2 = word2 & ~PORTCFG_DFE_BIT"
				fi
				word3=0x0
			fi
		fi
		word2=`printf "0x%x" $word2`
		# echo "word2=$word2"

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

		# Add it to a new config value
		new_config="$new_config$new_port_config"
	done
	# echo "new_config=$new_config"
}

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

from_major=$1
from_minor=$2
to_major=$3
to_minor=$4
# 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"

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

# 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
	/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"

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

# 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
	/fabos/cliexec/config set lsportCfg 5 "$new_config"
	/fabos/cliexec/configcommit
# else
	# echo
	# echo "No changes needed."
	# echo
fi
