#! /bin/bash

# This script performs initialization for switchd that needs to be done prior to
# starting switchd.

PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/usr/cumulus/bin
DESC="Cumulus Networks switch chip daemon"
NAME=switchd
DAEMON=/usr/sbin/$NAME
PIDFILE=/run/$NAME.pid
SCRIPTNAME=$0
BCMDIR=/etc/bcm.d
BCMCFGDIR=/etc/bcm.d/config.d
SWITCHD_INIT=/etc/cumulus/switchd.init
SWITCHD_CFG=/etc/cumulus/switchd.conf

# Read configuration variable file if it is present
[ -r /etc/default/$NAME ] && . /etc/default/$NAME

#
# Starting in release 2.1, switch configuration is stored in
# /etc/cumulus/switchd.conf.  Transfer pre-2.1 release configuration
# from /etc/default/switchd (in DAEMON_OPT_ARGS) to
# /etc/cumulus/switchd.conf
#
do_cfg_upgrade()
{
	a=($DAEMON_OPT_ARGS)
	for i in "${!a[@]}"; do
		match=""
		if [ ${a[i]} = "-L" ]; then
			match="logging = "
			a[((i+1))]=${a[((i+1))]//\//\\/}
		fi
		if [ ${a[i]} = "-bp" ]; then
			match="buf_util.poll_interval = "
		fi
		if [ ${a[i]} = "-bm" ]; then
			match="buf_util.measure_interval = "
		fi
		if [ ${a[i]} = "-c" ]; then
			match="coalescing.reducer = "
		fi
		if [ ${a[i]} = "-C" ]; then
			match="coalescing.timeout = "
		fi
		if [ ${a[i]} = "-t" ]; then
			match="route.table = "
		fi
		if [ ${a[i]} = "-s" ]; then
			sed -i -e "s/^#*ignore_non_swps = .*$/ignore_non_swps = TRUE/" $file
		fi
		if [ ${a[i]} = "-n" ]; then
			sed -i -e "s/^#*arp.next_hops = .*$/arp.next_hops = TRUE/" $file
		fi
		if [ ${a[i]} = "-d" ]; then
			sed -i -e "s/^#*route.delete_dead_routes = .*$/route.delete_dead_routes = TRUE/" $file
		fi
		if [ -n "$match" ]; then
			sed -i -e "s/^#*$match.*$/$match${a[((i+1))]}/" $SWITCHD_CFG
		fi
	done
}

do_cfg_upgrade

#
# Generate switchd configuration

# The TUNTAP check here must match the update-ports.service check
check_and_set_port_type()
{
	if grep -iq "^use_tuntap[[:space:]]*=[[:space:]]*TRUE" /etc/cumulus/switchd.conf; then
		export SWPORT_USE_TUNTAP=1
	fi
}

do_setup_random_number()
{
    if [ ! -d "/var/lib/switchd/" ]
    then
        mkdir -p /var/lib/switchd/
    fi

    if [ ! -s "/var/lib/switchd/ecmp_rand_seed" ]
    then
        openssl rand 4 | hexdump -e '/4 "%u\n"' > /var/lib/switchd/ecmp_rand_seed
    fi

    if [ ! -s "/var/lib/switchd/ecmp_rand_seed1" ]
    then
        openssl rand 4 | hexdump -e '/4 "%u\n"' > /var/lib/switchd/ecmp_rand_seed1
    fi
}

do_init()
{
	# run any switchd setup scripts
	#
	if [ -x $SWITCHD_INIT ]; then
		$SWITCHD_INIT || { echo $SWITCHD_INIT failed; return 2; }
	fi

        check_and_set_port_type

        # generate datapath configurations
        #
        if [ -x /usr/lib/cumulus/datapath-config ]; then
                /usr/lib/cumulus/datapath-config ||
                { echo datapath-config failed: $?; return 2; }
        fi

        # generate the backend config file
        #
        if [ -x /usr/lib/cumulus/generate-backend-config ]; then
                /usr/lib/cumulus/generate-backend-config ||
                { echo generate-backend-config failed: $?; return 2; }
        fi

        # setup random for use as load-balance seed
        do_setup_random_number
}  

# If module $1 is loaded return - 0 else - 1
is_module()
{
        local RC

        /sbin/lsmod | grep -w "$1" > /dev/null
        RC=$?

        return $RC
}

#
# Function that starts the daemon/service
#
do_start()
{
	# Signal clagd (if clagd is running, so ignore errors) on switchd
	# state changes (starting) with SIGRTMIN+2
	# Python thinks SIGRTMIN is 34, so in the clagd code this is SIGRTMIN
	/usr/bin/killall -q -s 34 clagd

	/usr/sbin/switchd -lic
	RETVAL="$?"
	if [ "$RETVAL" = 1 ]; then
		logger -s -p syslog.alert -- "No license.  Switchd will not start"
		return 2;
	fi

	if [ "$RETVAL" = 2 ]; then
	    logger -s -p syslog.alert -- "No valid license.  Switchd will not start"
	    return 2;
	fi

	rm -f /run/problems/switchd* # licensed; clear previous fatal errors

	if [ -n "$SEPARATE_ROUTING" ]; then
		separate_routing $SEPARATE_ROUTING
		SEPARATE_ROUTING_ARGS="-s -t 1"
	fi

	do_init 
	RETVAL="$?"
	if [ "$RETVAL" = 2 ]; then
        # 42 is handled in unit script so we do not attempt a restart if there are
        # initialization script failures
        logger -s -p syslog.alert -- "Generation of configuration files failed.  Switchd will not start"
        return 42;
	fi
	RETVAL="$?"

	# be sure fuse mount point is present
	mkdir -p /cumulus/switchd 2>/dev/null
  
	return $RETVAL
}

sendsigs_omit() {
        OMITDIR=/run/sendsigs.omit.d
        mkdir -p $OMITDIR
        ln -sf $PIDFILE $OMITDIR/switchd
}

# We can run in normal mode (start), and diags mode (start-offline)
# handle both cases, and error out with other (or no) arguments.

case "$1" in
  start)
	echo "Initializing $DESC $NAME"
	do_start
	rval=$?
	case "$rval" in
		0) sendsigs_omit ;;
		*) exit $rval ;;
	esac

	# Signal clagd (if clagd is running, so ignore errors) on switchd
	# state changes.  35==SIGRTMIN+3 tells clag switchd is ready.
	# Python thinks SIGRTMIN is 34, so in the clagd code this is SIGRTMIN+1
	# It needs to be set after switchd becomes ready, so loop until
	# switchd is active or failed.
	setsid /bin/sh -c '(while ! systemctl -q is-active switchd; do 
	  systemctl -q is-failed switchd && exit 1; sleep 3; done;
	  /usr/bin/killall -q -s 35 clagd)&'

	exec /usr/sbin/switchd ${SEPARATE_ROUTING_ARGS} $VX
	;;
  start-offline)
	echo "Starting $DESC $NAME in diag mode"
	do_start
	rval=$?
	case "$rval" in
		0) ;;
		*) exit $rval ;;
	esac
	exec /usr/sbin/switchd -do ${SEPARATE_ROUTING_ARGS} $VX
	;;
  *)
	echo "Usage: $SCRIPTNAME {start|start-offline}" >&2
	exit 3
	;;
esac

exit 0
