#!/bin/sh /etc/rc.common
# Copyright (C) 2018 Lean <coolsnowwolf@gmail.com>
# Copyright (C) 2019-2022 Tianling Shen <cnsztl@immortalwrt.org>

START=90
STOP=10
USE_PROCD=1

MTK_WED_MODULES="mt7915e mt7996e"

start_service() {
	config_load "turboacc"

	local fastpath
	config_get fastpath "config" "fastpath"
	local fastpath_fo_hw
	config_get_bool fastpath_fo_hw "config" "fastpath_fo_hw" "0"
	local fastpath_mh_eth_hnat_wed
	config_get_bool fastpath_mh_eth_hnat_wed "config" "fastpath_mh_eth_hnat_wed" "0"

	local kernel_version
	kernel_version="$(uname -r)"

	find_wed_param() {
		local mod

		for mod in $MTK_WED_MODULES; do
			[ -e "/sys/module/$mod/parameters/wed_enable" ] && {
				echo "/sys/module/$mod/parameters/wed_enable"
				return 0
			}
		done

		return 1
	}

	get_wed_param_value() {
		local param_path="$1"

		[ -n "$param_path" ] || return 1
		[ -r "$param_path" ] || return 1

		cat "$param_path" 2>/dev/null
	}

	set_wed_wo() {
		local target_value="$1"
		local param_path
		local current_value

		param_path="$(find_wed_param)" || return 0
		current_value="$(get_wed_param_value "$param_path")" || return 0
		[ -w "$param_path" ] || return 0

		case "$target_value" in
		Y)
			[ "$current_value" = "Y" ] || [ "$current_value" = "1" ] && return 0
			;;
		N)
			[ "$current_value" = "N" ] || [ "$current_value" = "0" ] && return 0
			;;
		esac

		echo "$target_value" > "$param_path" 2>/dev/null || true
	}

	load_wed_wo() {
		set_wed_wo "Y"
	}

	unload_wed_wo() {
		set_wed_wo "N"
	}

	if [ "$fastpath" != "fast_classifier" ] && lsmod | grep -q "fast_classifier"; then
		echo "0" > "/sys/fast_classifier/skip_to_bridge_ingress" 2>"/dev/null"
		rm -f "/dev/sfe_ipv6"
		rmmod "fast_classifier" 2>"/dev/null"
	fi

	if [ "$fastpath" != "shortcut_fe_cm" ] && lsmod | grep -q "shortcut_fe_cm"; then
		rmmod "shortcut_fe_cm" 2>"/dev/null"
	fi

	if [ "$fastpath" != "mediatek_hnat" ] && lsmod | grep -q "mtkhnat"; then
		echo "0" > "/sys/kernel/debug/hnat/hook_toggle" 2>"/dev/null"
	fi

	local flow_offloading="0"
	local flow_offloading_hw="0"
	case "$fastpath" in
	"flow_offloading")
		flow_offloading="1"
		local fastpath_fo_hw flow_offloading_hw
		config_get_bool fastpath_fo_hw "config" "fastpath_fo_hw" "0"
		[ "$fastpath_fo_hw" -eq "0" ] || flow_offloading_hw="1"
		;;
	"fast_classifier")
		local fastpath_fc_br fastpath_fc_ipv6
		config_get_bool fastpath_fc_br "config" "fastpath_fc_br" "0"
		config_get_bool fastpath_fc_ipv6 "config" "fastpath_fc_ipv6" "0"

		lsmod | grep -q "fast_classifier" || modprobe "fast_classifier" 2>"/dev/null"
		echo "$fastpath_fc_br" > "/sys/fast_classifier/skip_to_bridge_ingress" 2>"/dev/null"
		if [ "$fastpath_fc_ipv6" -eq "1" ]; then
			[ -e "/dev/sfe_ipv6" ] || mknod "/dev/sfe_ipv6" "c" "$(cat "/sys/sfe_ipv6/debug_dev")" "0"
		else
			[ ! -e "/dev/sfe_ipv6" ] || rm -f "/dev/sfe_ipv6"
		fi
		;;
	"shortcut_fe_cm")
		lsmod |grep -q "shortcut_fe_cm" || modprobe "shortcut_fe_cm" 2>"/dev/null"
		;;
	"qca_nss_ecm")
		[ -x "/etc/init.d/qca-nss-ecm" ] && /etc/init.d/qca-nss-ecm restart >/dev/null 2>&1
		;;
	"mediatek_hnat")
		local fastpath_mh_eth_hnat fastpath_mh_eth_hnat_v6
		config_get_bool fastpath_mh_eth_hnat "config" "fastpath_mh_eth_hnat" "1"
		config_get_bool fastpath_mh_eth_hnat_v6 "config" "fastpath_mh_eth_hnat_v6" "1"

		local hnat_path="/sys/kernel/debug/hnat"
		echo "$fastpath_mh_eth_hnat" > "$hnat_path/hook_toggle"
		echo "8 $fastpath_mh_eth_hnat_v6" > "$hnat_path/hnat_setting"
		;;
	esac

	if [ "$fastpath_mh_eth_hnat_wed" -eq "1" ] &&
	   [ "$fastpath" = "flow_offloading" ] &&
	   [ "$fastpath_fo_hw" -eq "1" ]; then
		load_wed_wo
	else
		unload_wed_wo
	fi

	uci -q set "firewall.@defaults[0].flow_offloading"="$flow_offloading"
	uci -q set "firewall.@defaults[0].flow_offloading_hw"="$flow_offloading_hw"

	local fullcone
	config_get "fullcone" "config" "fullcone" "0"
	uci -q set "firewall.@defaults[0].fullcone"="$fullcone"

	local tcpcca
	config_get "tcpcca" "config" "tcpcca" "cubic"
	sysctl -w net.ipv4.tcp_congestion_control="$tcpcca" >"/dev/null"

	uci -q commit "firewall"
	/etc/init.d/firewall restart >"/dev/null" 2>&1
}

reload_service() {
	stop
	start
}

service_triggers() {
	procd_add_reload_trigger "turboacc"
}
