#!/bin/sh . ${STREAMBOOST_CFGDIR:-/etc/appflow}/rc.appflow . ${STREAMBOOST_CFGDIR:-/etc/appflow}/classids.sh # Note: EXTRA_COMMANDS isn't actually used by the rc.appflow environment, but # it's defined here in the hopes that one day it will be. At that time, # the redefinition of action() and usage() in this file should be deleted. EXTRA_COMMANDS="start_qdiscs stop_qdiscs setup_iptables teardown_iptables" EXTRA_HELP=" start_qdiscs create root qdisc structure stop_qdiscs delete root qdisc structure setup_iptables insert iptables rules teardown_iptables delete iptables rules" # # Environment config # NAME="qdiscman" DISPLAY_NAME=${NAME} # path to binary BINARY="${BINDIR}/${NAME}" # path to pid file PIDFILE="${RUNDIR}/${NAME}.pid" # Redis server port REDIS_PORT=6379 # source the setup_iface, setup_iptables, and teardown_iptables functions, # switched by whether or not we're enabled for NSS mode. to be enabled # for NSS mode, the kmod-qca-nss-qdisc package must be installed and the # nss_qdisc variable in streamboost.user.conf must be 'yes'. if nss_qdisc_is_installed; then # we can potentially use NSS QDiscs, so see if we're configured for it. # the user config file contains the nss_qdisc setting . $STREAMBOOST_USER_CFG # test the nss_qdisc value to see if we're in NSS mode if [ "${nss_qdisc}" = "yes" ]; then . ${STREAMBOOST_CFGDIR:-/etc/appflow}/qdiscman-nss.sh else . ${STREAMBOOST_CFGDIR:-/etc/appflow}/qdiscman.sh fi else . ${STREAMBOOST_CFGDIR:-/etc/appflow}/qdiscman.sh fi [ -f /etc/dhcp.guest.conf ] && . /etc/dhcp.guest.conf # Format the command line parameters CMDLINE_OPTS="\ --daemon \ --run-dir=${RUNDIR} \ --pid-file=${PIDFILE} \ --redis-port=${REDIS_PORT} \ --redis-stat-prefix=flowdb:flows: \ --ifname-up=${WAN_IFACE} \ --ifname-down=${LAN_IFACE} \ ${EXTRA_CMD_ARGS} \ " # # Functions # sb_get_max_zone_id() { redis-cli get "settings:max_zone_id" } # prints 0 if a zone with the given ID is configured in redis, else 1 # $1: zone id sb_zone_is_configured() { local zone=$1 if [ $(redis-cli exists "settings:zone:${zone}") = "1" ] && [ $(redis-cli hexists "settings:zone:${zone}" "weight:up") = "1" ] && [ $(redis-cli hexists "settings:zone:${zone}" "weight:down") = "1" ]; then echo 0 else echo 1 fi } # echos the number of configured zones. a zone is considered "configured" # if it has a hash entry in settings:zone: where id is less than # settings:max_zone_id sb_get_zone_count() { local maxzoneid=$(sb_get_max_zone_id) local zone=0 local count=0 if [ -n "${maxzoneid}" ]; then while [ "${zone}" -le "${maxzoneid}" ]; do if [ $(sb_zone_is_configured ${zone}) = "0" ]; then let count=count+1 fi let zone=zone+1 done fi echo ${count} } # returns a zone config item from redis # $1: dev (e.g., eth0, br-lan, etc.) # $2: zone (integer zone identifier) # $3: key (e.g., bw, weight) # $4: default (returned if key doesn't exist) sb_get_zone_config() { local dev=$1 local zone=$2 local key=$3 local default=$4 if [ "${dev}" = "${WAN_IFACE}" ]; then redis-cli hget settings:zone:${zone} ${key}:up elif [ "${dev}" = "${LAN_IFACE}" ]; then redis-cli hget settings:zone:${zone} ${key}:down else echo ${default} echo "error: ${dev} is not a supported interface" 1>&2 fi } # returns the "bw" key from the zone config for the given interface zone # $1: dev # $2: zone sb_get_zone_rate() { sb_get_zone_config $1 $2 bw } # returns the "weight" key from the zone config for the given interface zone # $1: dev # $2: zone sb_get_zone_weight() { sb_get_zone_config $1 $2 weight 10000 } # generates a hex value in the CLASSID_ZONE_BASE range that can be # used as a classid or a qdisc handle # $1: zone id sb_gen_zone_classid() { printf "%x" $((0x${CLASSID_ZONE_BASE} + ${1})) } # generates a hex value in the CLASSID_ZONE_TBL_BASE range that can be # used as a classid or a qdisc handle for NSS-based zone # $1: zone id sb_gen_zone_tbl_classid() { printf "%x" $((0x${CLASSID_ZONE_TBL_BASE} + ${1})) } # generates a hex value in the CLASSID_ZONE_BG_BASE range that can be # used as a classid or a qdisc handle for NSS-based zone background qdisc # $1: zone id sb_gen_zone_bg_classid() { printf "%x" $((0x${CLASSID_ZONE_BG_BASE} + ${1})) } # generates a hex value in the CLASSID_ZONE_CL_BASE range that can be # used as a classid or a qdisc handle for NSS-based zone classified qdisc # $1: zone id sb_gen_zone_cl_classid() { printf "%x" $((0x${CLASSID_ZONE_CL_BASE} + ${1})) } # $1: dev # $2: parent # $3: handle # $4: qdisc type (default = fq_codel) # $5: extra opts add_interactive_qdisc() { tc qdisc add dev $1 parent $2 handle $3 \ ${4:-fq_codel} \ limit 100\ target 250000 interval 2500000 $5 [ $? = 0 ] || return $? } start_qdiscs() { echo "Setting up qdiscs on interface ${WAN_IFACE}" GUEST_BANDWIDTH_LIMIT="${GUEST_BANDWIDTH_LIMIT_UP}" setup_iface ${WAN_IFACE} [ $? = 0 ] || return $? echo "Setting up qdiscs on interface ${LAN_IFACE}" GUEST_BANDWIDTH_LIMIT="${GUEST_BANDWIDTH_LIMIT_DOWN}" setup_iface ${LAN_IFACE} [ $? = 0 ] || return $? } stop_qdiscs() { tc qdisc del dev ${WAN_IFACE} root tc qdisc del dev ${LAN_IFACE} root } start() { [ -f "${PIDFILE}" ] && { return 0 } [ ! -f /var/log/setup_iptables ] && { teardown_iptables 2>/dev/null setup_iptables } touch /var/log/setup_iptables for i in ${KERNEL_MODULES}; do insmod $i 2>/dev/null done [ ! -d "${RUNDIR}" ] && { mkdir ${RUNDIR} } [ -x ${BINARY} ] || { echo "${NAME} not found: ${BINARY}" exit 2 } stop_qdiscs 2>/dev/null start_qdiscs || exit 3 echo -n "Starting ${NAME}: " ${BINARY} ${CMDLINE_OPTS} "$@" retval=$? echo return ${retval} } boot() { start "$@" } stop() { default_stop local retval=$? stop_qdiscs teardown_iptables rm -rf /var/log/setup_iptables return ${retval} } usage() { cat <