#! /bin/bash
### BEGIN INIT INFO
# Provides:          capture 
# Required-Start:    $remote_fs $syslog $time
# Required-Stop:     $remote_fs $syslog $time
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: DAG capture 
# Description:       Set DAG capture modules and parameters 
### END INIT INFO

NAME="DAG capture modules and parameters"

#  Memory in Kernel Space to be reserved for the capturing hardware interface
#  remmber that this buffer is entirely alloc'd in RAM, so the machine should
#  have enough RAM to perform correctly.
#  the suggested values are:
#     - 1 Gb total ram  = 256 dagmem size
#     - 2 Gb total ram  = 512 dagmem size
DAG_MEMSIZE=1024M

#  This is the device to be configured for capturing
DAG_DEVICE="/dev/dag0"

#  Add here the parameters to be injected to the DAG configuration
DAG_OPTIONS="default rxonly"

# 8 TX buffer, 128 MB each
MEM_BUFFERS="128:0:128:0:128:0:128:0:128:0:128:0:128:0:128:0"

# load balance on srcIP-dstIP tuple
N_TUPLE="2"

# divide evenly between all bins
HAT_RANGE="0-124:125-249:250-374:375-499:500-624:625-749:750-874:875-1000"

# setup 8 bins (one for each stream)
HASH_WIDTH="3"

# Set filter.rules
FILTER_RULES="/opt/td-config/share/filter.rules"

# Set cat.rules
CAT_RULES="/opt/td-config/share/cat.rules"

# Log file
ELOG="/tmp/endace_boot.log"

# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh

VERBOSE="yes"

# Define LSB log_* functions.
# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
# and status_of_proc is working.
. /lib/lsb/init-functions

# Function that starts the daemon/service
do_start()
{
	# Return
	#   0 if daemon has been started
	#   1 if daemon was already running
	#   2 if daemon could not be started
	
	device="dag"
	group="root"
	mode="664"

	if [ "`apparmor_status | grep -i tcpdump | wc -l`" != '0' ]; then 
		echo "Disable Apparmor for tcpdump"
		/bin/ln -s /etc/apparmor.d/usr.sbin.tcpdump /etc/apparmor.d/disable/ 2> /dev/null
		/sbin/apparmor_parser -R /etc/apparmor.d/usr.sbin.tcpdump 2> /dev/null
	fi

	[ "$VERBOSE" != no ] && log_daemon_msg "Starting the Hardware Capture Subsystem"

	rm -f $ELOG 2> /dev/null
	
	/sbin/depmod -a	
	/sbin/modprobe dagmem dsize=$DAG_MEMSIZE >> $ELOG 2>> $ELOG 
	if [ "`lsmod | grep -w dagmem`" ]; then
		[ "$VERBOSE" != no ] && log_daemon_msg "Loading the kernel memory modules..."

		/sbin/modprobe dag >> $ELOG 2>> $ELOG
         	if [ "`lsmod | grep -w dag`" ]; then
            		[ "$VERBOSE" != no ] && log_daemon_msg "Loading the kernel device modules..."
         	else
			logger -t modprobe -p local7.err "FATAL: unable to load device modules"
			[ "$VERBOSE" != no ] && log_daemon_msg "FATAL: Loading the kernel device modules..."
            		return 2
         	fi
      	else
		logger -t modprobe -p local7.err "FATAL: unable to load memory modules"
		[ "$VERBOSE" != no ] && log_daemon_msg "FATAL: Loading the kernel memory modules..."
         	return 2
      	fi

        major=`cat /proc/devices | awk "\\$2==\"dag\" {print \\$1}"`

        # The minor numbers need to be syncronized with the values in dag.c
        for i in mem iom arm "" ; do
        	rm -f /dev/${device}${i}*
        done

	for i in `seq 0 15` ; do
        	mknod /dev/${device}$i    c $major $i
             	mknod /dev/${device}mem$i c $major $((16+$i))
             	mknod /dev/${device}iom$i c $major $((32+$i))
             	mknod /dev/${device}arm$i c $major $((48+$i))
        done

        ln -sf ${device}0 /dev/${device}

        for i in mem iom arm "" ; do
        	chgrp $group /dev/${device}${i}*
             	chmod $mode  /dev/${device}${i}*
        done	

	[ "$VERBOSE" != no ] && log_daemon_msg "Creating the devices in /dev..."

	DAG_COMMAND="/usr/local/bin/dagconfig"
      	DAG_CAT="/usr/local/bin/dagcat-setup"
      	DAG_FILTER="/usr/local/bin/dagfilter-loader"
      	DAG_VERSION=`/usr/local/bin/dagdetect -np 2> /dev/null`

        if [ "$DAG_VERSION" == "DAG_7.5G2" ]; then
		[ "$VERBOSE" != no ] && log_daemon_msg "Searching for a supported Card... found DAG 7.5G2 card"
        elif [ "$DAG_VERSION" == "DAG_7.5G4" ]; then
                [ "$VERBOSE" != no ] && log_daemon_msg "Searching for a supported Card... found DAG 7.5G4 card"
        elif [ "$DAG_VERSION" == "DAG_9.2X2" ]; then
                [ "$VERBOSE" != no ] && log_daemon_msg "Searching for a supported Card... found DAG 9.2X2 card"
        elif [ "$DAG_VERSION" == "" ]; then
		[ "$VERBOSE" != no ] && log_daemon_msg "FATAL: Searching for a supported Card... not found card"
            	return 2
        else
		if [ "$DAG_VERSION" == "" ]; then
			[ "$VERBOSE" != no ] && log_daemon_msg "FATAL: Searching for a supported Card... unsupported card"
		else
			[ "$VERBOSE" != no ] && log_daemon_msg "FATAL: Searching for a supported Card... unsupported card ($DAG_VERSION)"
		fi

            	return 2
        fi

	$DAG_COMMAND -d $DAG_DEVICE -S hash_encoding_from_ipf=off >> $ELOG 2>> $ELOG 
	[ "$VERBOSE" != no ] && log_daemon_msg "Disabling load balancing on ($DAG_DEVICE)..."

	$DAG_COMMAND -d $DAG_DEVICE $DAG_OPTIONS mem=$MEM_BUFFERS >> $ELOG 2>> $ELOG 
      	if [ $? == 0 ]; then
        	[ "$VERBOSE" != no ] && log_daemon_msg "Configuring the capturing device ($DAG_VERSION)..." 
      	else
		logger -f $ELOG -p local7.info -t dag
		[ "$VERBOSE" != no ] && log_daemon_msg "FATAL: Configuring the capturing device ($DAG_VERSION)..."
         	return 2
      	fi

        $DAG_COMMAND -d $DAG_DEVICE -S hash_encoding_from_ipf=on >> $ELOG 2>> $ELOG 
	[ "$VERBOSE" != no ] && log_daemon_msg "Enabling load balancing on ($DAG_DEVICE)..."

        $DAG_COMMAND -d $DAG_DEVICE -S n_tuple_select=$N_TUPLE >> $ELOG 2>> $ELOG 
	[ "$VERBOSE" != no ] && log_daemon_msg "Balancing on source-destination IP..."

        $DAG_COMMAND -d $DAG_DEVICE -S hat_range=$HAT_RANGE >> $ELOG 2>> $ELOG 
	[ "$VERBOSE" != no ] && log_daemon_msg "Setting up bins for load balancing..."

        $DAG_COMMAND -d $DAG_DEVICE -S hash_width=$HASH_WIDTH >> $ELOG 2>> $ELOG 
	[ "$VERBOSE" != no ] && log_daemon_msg "Setting up balancing for 8 cores..."

	$DAG_CAT -d $DAG_DEVICE -f $CAT_RULES >> $ELOG 2>> $ELOG 
        if [ $? == 0 ]; then
        	[ "$VERBOSE" != no ] && log_daemon_msg "Loading configuration in CAT table on ($DAG_DEVICE)..."
        else
		logger -f $ELOG -p local7.info -t dag
		[ "$VERBOSE" != no ] && log_daemon_msg "FATAL: Loading configuration in CAT table on ($DAG_DEVICE)..."
            	return 2
        fi

	ACTIVE_BANK=`$DAG_COMMAND -d $DAG_DEVICE -G activate_bank | awk -F" = " '{ print $2 }' | tr -d '\n'`
        if [ "$ACTIVE_BANK" == "on" ]; then
        	BANK=0
        else
            	BANK=1
        fi

	[ "$VERBOSE" != no ] && log_daemon_msg "Setting up filters on ($DAG_DEVICE)..."
	
	$DAG_FILTER -d $DAG_DEVICE --db $BANK --initialize -f $FILTER_RULES >> $ELOG 2>> $ELOG 
        if [ $? == 0 ]; then
            	[ "$VERBOSE" != no ] && log_daemon_msg "Loading filters on bank $BANK..."
        else
		logger -f $ELOG -p local7.info -t dag
		[ "$VERBOSE" != no ] && log_daemon_msg "FATAL: Loading filters on bank $BANK..."
            	return 2
        fi

	logger -f $ELOG -p local7.info -t dag

	/usr/local/bin/dagclock -d0 none overin -kx >> $ELOG 2>> $ELOG 
	[ "$VERBOSE" != no ] && log_daemon_msg "Syncronizing clock with host..."

	return 0
}

# Function that stops the daemon/service
do_stop()
{
	# Return
	#   0 if daemon has been stopped
	#   1 if daemon was already stopped
	#   2 if daemon could not be stopped
	#   other if a failure occurred

	[ "$VERBOSE" != no ] && log_daemon_msg "Stopping the Hardware Capture Subsystem"
	rmmod dag
	rmmod divdi3 dagmem
	[ "$VERBOSE" != no ] && log_daemon_msg "Unloding the kernel modules..."

	rm -f /dev/dag{,mem,iom,arm}[0-3] >> /dev/null
	[ "$VERBOSE" != no ] && log_daemon_msg "Removing devices from /dev..."

	return 0
}

case "$1" in
  start)
	[ "$VERBOSE" != no ] && log_daemon_msg "Starting $NAME"
	do_start
	case "$?" in
		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
	esac
	;;
  stop)
	[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $NAME"
	do_stop
	case "$?" in
		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
	esac
	;;
  *)
	echo "Usage: $SCRIPTNAME {start|stop}" >&2
	exit 3
	;;
esac

:
