#!/bin/sh

. /lib/functions.sh

# ATM #
check_pvc() {
	local vpi=$1
	local vci=$2
	local ret

	ret=$(xtmctl operate conn --show | awk -v test="$vpi/$vci" '{if ($3==test ) print $5 }')

	case $ret in
		''|*[!0-9]*) return 0 ;;
		*) return $ret ;;
	esac
}

check_xtm_list() {
	local qclass=$1
	local pcr scr mbs
	local ret

	case $# in
		1)
			pcr=0
			scr=0
			mbs=0
		;;
		2)
			pcr=$2
			scr=0
			mbs=0
		;;
		4)
			pcr=$2
			scr=$3
			mbs=$4
		;;
	esac

	ret=$(xtmctl operate tdte --show | awk -v test="$qclass" -v pcr="$pcr" -v scr="$scr" -v mbs="$mbs" '{if ($2==test && $3==pcr && $4==scr && $5==mbs ) print $1 }')

	case $ret in
		''|*[!0-9]*) return 0 ;;
		*) return $ret ;;
	esac
}

configure_atm_device() {
	local name vpi vci device link_type encapsulation qos_class pcr mbs scr i

	config_get name $1 name "ATM"
	config_get vpi $1 vpi "8"
	config_get vci $1 vci "35"
	config_get device $1 device "atm0"
	config_get link_type $1 link_type "eoa"
	config_get encapsulation $1 encapsulation "llc"
	config_get qos_class $1 qos_class "ubr"
	config_get pcr $1 pcr
	config_get mbs $1 mbs
	config_get scr $1 scr

	check_pvc $vpi $vci
	ret=$?

	if [ "$ret" -eq 0 ]; then
		check_xtm_list $qos_class $pcr $scr $mbs
		ret=$?

		if [ "$ret" -eq 0 ]; then
			case $qos_class in # ubr, cbr, gfr, vbr-nrt, vbr-rt, ubr+, abr
				ubr)
					xtmctl operate tdte --add "$qos_class"
				;;
				ubr_pcr|ubr+)
					xtmctl operate tdte --add "$qos_class" $pcr
				;;
				cbr)
					xtmctl operate tdte --add "$qos_class" $pcr
				;;
				nrtvbr|vbr-nrt)
					xtmctl operate tdte --add "$qos_class" $pcr $scr $mbs
				;;
				rtvbr|vbr-rt)
					xtmctl operate tdte --add "$qos_class" $pcr $scr $mbs
				;;
				gfr)
				;;
				abr)
				;;
			esac
		fi

		case $link_type in # EoA, IPoA, PPPoA, CIP
			EoA|eoa)
				[ $encapsulation == "vcmux" ] && encapsulation="vcmux_eth" || encapsulation="llcsnap_eth"
			;;
			PPPoA|pppoa)
				[ $encapsulation == "vcmux" ] && encapsulation="vcmux_pppoa" || encapsulation="llcencaps_ppp"
			;;
			IPoA|ipoa)
				[ $encapsulation == "vcmux" ] && encapsulation="vcmux_ipoa" || encapsulation="llcsnap_rtip"
			;;
			CIP|cip)
			;;
		esac

		check_xtm_list $qos_class $pcr $scr $mbs
		ret="$?"

		xtmctl operate conn --add 1.$vpi.$vci aal5 $encapsulation 0 1 $ret
		for i in `seq 0 7`; do
			xtmctl operate conn --addq 1.$vpi.$vci $i wrr 1 dt # queue priority 0-7
		done
		xtmctl operate conn --createnetdev 1.$vpi.$vci $device
		xtmctl operate intf --state 1 enable
	fi
}

remove_atm_devices() {
	local vpi vci rest
	local vpivci=`xtmctl operate conn --show | grep "ATM\|mode" | awk '{if (NR!=1 && $1!="PTM") {print $3}}'`

	for i in $vpivci
	do
		rest=${i#\/}
		vpi=${rest%%\/*}
		vci=${rest#*\/}
		echo "xtmctl operate conn --delete 1.$vpi.$vci"
		xtmctl operate conn --delete 1.$vpi.$vci
		echo "xtmctl operate conn --deletenetdev 1.$vpi.$vci"
		xtmctl operate conn --deletenetdev 1.$vpi.$vci
	done
}

create_atm_devices() {
	echo "Creating ATM Device(s)"
	config_load dsl
	config_foreach configure_atm_device atm-device
}
# ATM END #

# PTM #
check_ptm() {
	local ret
	local ptmprio=$1
	local dslat=$2

	if [ "$ptmprio" -eq 2 ]; then
		ptmprio="high"
	else
		ptmprio="low"
	fi

	ret=$(xtmctl operate conn --show | awk -v dslat="$dslat" -v ptmprio="$ptmprio" '{if ($2 == dslat && $3 == ptmprio ) print $2 }')

	case $ret in
		''|*[!0-9]*) return 0 ;;
		*) return $ret ;;
	esac
}

configure_ptm_device() {
	local name device priority portid i

	config_get name $1 name "PTM"
	config_get device $1 device "ptm0"
	config_get priority $1 priority 1
	config_get portid $1 portid 1

	check_ptm $priority $portid
	ret=$?

	if [ "$ret" -eq 0 ]; then
		xtmctl operate conn --add $portid.$priority

		for i in `seq 0 7`; do
			xtmctl operate conn --addq $portid.$priority $i wrr 1 dt -1 -1 3000 # queue priority 0-7
		done
		echo "xtmctl operate conn --createnetdev $portid.$priority $device"
		xtmctl operate conn --createnetdev $portid.$priority $device
		xtmctl operate intf --state 1 enable
	fi
}

remove_ptm_devices() {
	local delptm
	local x=0

	IFS=$'\n'
	for i in `xtmctl operate conn --show | grep "PTM\|mode"`
	do
		if [ $x -eq 1 ]; then
			delptm=$(echo $i | awk '{if ($1!="ATM") print $2"."$11}')
			echo "xtmctl operate conn --delete $delptm"
			xtmctl operate conn --delete $delptm
			xtmctl operate conn --deletenetdev $delptm
		fi
		x=1
	done
	unset IFS
}

create_ptm_devices() {
	echo "Creating PTM Device(s)"
	config_load dsl
	config_foreach configure_ptm_device ptm-device
}
# PTM END #

prioritize_arp()
{
      ebtables --concurrent -t nat -D POSTROUTING -j mark --mark-or 0x7 -p ARP >/dev/null
      ebtables --concurrent -t nat -A POSTROUTING -j mark --mark-or 0x7 -p ARP >/dev/null
}

xtm_remove_devices() {
	remove_atm_devices
	remove_ptm_devices
}

xtm_create_devices() {
	local tpstc="$(xdslctl info --show | grep TPS-TC)"
	if echo "$tpstc" | grep -q "ATM Mode"; then
		create_atm_devices
	elif echo "$tpstc" | grep -q "PTM Mode"; then
		create_ptm_devices
	fi
}

xdsl_configure() {
	local VDSL=0
	local GFAST=0
	local mod=""
	local modes=""
	local profile=""

	config_load dsl

	# Modes
	config_get mode line mode
	for mod in $mode; do
		[ $mod == "gdmt" ] && modes="${modes}d"
		[ $mod == "glite" ] && modes="${modes}l"
		[ $mod == "t1413" ] && modes="${modes}t"
		[ $mod == "adsl2" ] && modes="${modes}2"
		[ $mod == "adsl2p" ] && modes="${modes}p"
		[ $mod == "annexl" ] && modes="${modes}e"
		[ $mod == "annexm" ] && modes="${modes}m"
		[ $mod == "vdsl2" ] && modes="${modes}v" && VDSL=1
		[ $mod == "gfast" ] && modes="${modes}f" && GFAST=1
	done

	# VDSL Profiles
	config_get profile line profile
	# Capabilities
	config_get_bool bitswap line bitswap 1
	[ $bitswap -eq 1 ] && bitswap="on" || bitswap="off"
	config_get_bool sra line sra 1
	[ $sra -eq 1 ] && sra="on" || sra="off"
#	config_get_bool trellis line trellis 1
	config_get_bool sesdrop line sesdrop 0
	[ $sesdrop -eq 1 ] && sesdrop="on" || sesdrop="off"
	# VDSL2 only
	config_get_bool us0 line us0 1
	[ $us0 -eq 1 ] && us0="on" || us0="off"
#	config_get_bool dynamicd line dynamicd 1
#	config_get_bool dynamicf line dynamicf 1
	config_get_bool sos line sos 0
	[ $sos -eq 1 ] && sos="on" || sos="off"

	config_get_bool phyReXmtUs line phyReXmtUs 0
	config_get_bool phyReXmtDs line phyReXmtDs 1
	phyReXmt=$(( $((phyReXmtUs<<1)) + phyReXmtDs))

	if [ $VDSL -eq 1 -o $GFAST -eq 1 ]; then
		echo "xdslctl start --up --mod $modes --profile "$profile" --sra $sra --bitswap $bitswap --us0 $us0 --sesdrop $sesdrop --SOS $sos --phyReXmt $phyReXmt"
		xdslctl start --up --mod $modes --profile "$profile" --sra $sra --bitswap $bitswap --us0 $us0 --sesdrop $sesdrop --SOS $sos --phyReXmt $phyReXmt
		# G.Fast hardware to VDSL hardware, to set the driver bit kPhyCfg2EnableGfastVdslMMTimeOut0.
		# Enable V43 tone for GFAST.
		echo "xdslctl configure1 --phycfg 0 0 0 0 0 0 0 0 0 0 0 0x1400400 0x1400400"
		xdslctl configure1 --phycfg 0 0 0 0 0 0 0 0 0 0 0 0x1400400 0x1400400
	else
		echo "xdslctl start --up --mod $modes --sra $sra --bitswap $bitswap --sesdrop $sesdrop --SOS $sos --phyReXmt $phyReXmt"
		xdslctl start --up --mod $modes --sra $sra --bitswap $bitswap --sesdrop $sesdrop --SOS $sos --phyReXmt $phyReXmt
	fi

	if [ $GFAST -eq 1 ]; then
		# G.Fast hardware to VDSL hardware, to set the driver bit kPhyCfg2EnableGfastVdslMMTimeOut0.
		# Enable V43 tone for GFAST.
		echo "xdslctl configure1 --phycfg 0 0 0 0 0 0 0 0 0 0 0 0x1400400 0x1400400"
		xdslctl configure1 --phycfg 0 0 0 0 0 0 0 0 0 0 0 0x1400400 0x1400400
	fi
}

xdsl_stop() {
	# echo "Stopping DSL"
	# stop causes IRQ issues
	# xdslctl stop
	return 0
}

xdsl_init() {
	[ -d /sys/class/net/dsl0/ ] || exit

	prioritize_arp

	echo "Starting DSL"

	xtmctl start
	xtmctl operate intf --state 1 enable
}
