#!/bin/sh /etc/rc.common
# Copyright (C) 2024 OpenWrt.org

START=99
STOP=10

USE_PROCD=1

PROG=/usr/sbin/bpftune
CONFIGFILE=/etc/config/bpftune
ALL_TUNERS="tcp_buffer tcp_conn ip_frag neigh_table sysctl net_buffer netns route_table udp_buffer"

# rc.common only dispatches actions listed in EXTRA_COMMANDS; without this,
# "/etc/init.d/bpftune query ..." silently falls through to the generic
# help text instead of calling query() below.
EXTRA_COMMANDS="query"
EXTRA_HELP="	query <tuner_query>	Query a running bpftune tuner"

start_service() {
    local enabled logging_stdout tuners_disabled tuners_allowed learning_rate rollback legacy cgroup libdir respawn_threshold respawn_timeout respawn_retry

    config_load bpftune
    config_get_bool enabled config 'enabled' '0'
    config_get_bool logging_stdout config 'logging_stdout' '0'
    config_get learning_rate config 'learning_rate' ''
    config_get_bool rollback config 'rollback' '0'
    config_get_bool legacy config 'legacy' '0'
    config_get cgroup config 'cgroup' ''
    config_get libdir config 'libdir' ''
    config_get tuners_disabled config 'tuners_disabled' ''
    config_get tuners_allowed config 'tuners_allowed' ''
    config_get respawn_threshold config 'respawn_threshold' '3600'
    config_get respawn_timeout config 'respawn_timeout' '5'
    config_get respawn_retry config 'respawn_retry' '5'

    [ "$enabled" -eq 0 ] && {
	echo "bpftune is disabled in config"
	return 1
    }

    procd_open_instance
    procd_set_param command "$PROG"

    # Never pass -D (self-daemonize): procd supervises the foreground process
    # directly, and if bpftune forks away procd sees the tracked child exit
    # and respawns it, leaking a duplicate daemon each time.
    [ "$rollback" -eq 1 ] && procd_append_param command -R
    [ "$legacy" -eq 1 ] && procd_append_param command -L
    [ "$logging_stdout" -eq 1 ] && procd_append_param command -s
    [ -n "$learning_rate" ] && procd_append_param command -r "$learning_rate"
    [ -n "$cgroup" ] && procd_append_param command -c "$cgroup"
    [ -n "$libdir" ] && procd_append_param command -l "$libdir"

    # bpftune has no "disable a tuner" flag, only -a/--allow (an allowlist),
    # and -a matches the tuner's .so filename, not its short name.
    # tuners_allowed wins if set; otherwise tuners_disabled is honored by
    # allow-listing everything except the disabled ones.
    if [ -n "$tuners_allowed" ]; then
	for tuner in $tuners_allowed; do
	    procd_append_param command -a "${tuner}_tuner.so"
	done
    elif [ -n "$tuners_disabled" ]; then
	for tuner in $ALL_TUNERS; do
	    case " $tuners_disabled " in
		*" $tuner "*) ;;
		*) procd_append_param command -a "${tuner}_tuner.so" ;;
	    esac
	done
    fi

    procd_set_param respawn ${respawn_threshold:-3600} ${respawn_timeout:-5} ${respawn_retry:-5}
    procd_set_param stdout 1
    procd_set_param stderr 1

    procd_close_instance
}

service_triggers() {
    procd_add_reload_trigger "bpftune"
}

reload_service() {
    stop
    start
}

status_service() {
    $PROG -S
}

query() {
    [ -n "$1" ] || {
	echo "Usage: $0 query <tuner_query>"
	return 1
    }
    $PROG -q "$1"
}