1#!/bin/sh 2 3. ${STREAMBOOST_CFGDIR:-/etc/appflow}/rc.appflow 4. ${STREAMBOOST_CFGDIR:-/etc/appflow}/classids.sh 5 6# Note: EXTRA_COMMANDS isn't actually used by the rc.appflow environment, but 7# it's defined here in the hopes that one day it will be. At that time, 8# the redefinition of action() and usage() in this file should be deleted. 9EXTRA_COMMANDS="start_qdiscs stop_qdiscs setup_iptables teardown_iptables" 10EXTRA_HELP=" start_qdiscs create root qdisc structure 11 stop_qdiscs delete root qdisc structure 12 setup_iptables insert iptables rules 13 teardown_iptables delete iptables rules" 14 15# 16# Environment config 17# 18NAME="qdiscman" 19DISPLAY_NAME=${NAME} 20 21# path to binary 22BINARY="${BINDIR}/${NAME}" 23 24# path to pid file 25PIDFILE="${RUNDIR}/${NAME}.pid" 26 27# Redis server port 28REDIS_PORT=6379 29 30# source the setup_iface, setup_iptables, and teardown_iptables functions, 31# switched by whether or not we're enabled for NSS mode. to be enabled 32# for NSS mode, the kmod-qca-nss-qdisc package must be installed and the 33# nss_qdisc variable in streamboost.user.conf must be 'yes'. 34if nss_qdisc_is_installed; then 35 # we can potentially use NSS QDiscs, so see if we're configured for it. 36 # the user config file contains the nss_qdisc setting 37 . $STREAMBOOST_USER_CFG 38 # test the nss_qdisc value to see if we're in NSS mode 39 if [ "${nss_qdisc}" = "yes" ]; then 40 . ${STREAMBOOST_CFGDIR:-/etc/appflow}/qdiscman-nss.sh 41 else 42 . ${STREAMBOOST_CFGDIR:-/etc/appflow}/qdiscman.sh 43 fi 44else 45 . ${STREAMBOOST_CFGDIR:-/etc/appflow}/qdiscman.sh 46fi 47 48[ -f /etc/dhcp.guest.conf ] && . /etc/dhcp.guest.conf 49 50# Format the command line parameters 51CMDLINE_OPTS="\ 52--daemon \ 53--run-dir=${RUNDIR} \ 54--pid-file=${PIDFILE} \ 55--redis-port=${REDIS_PORT} \ 56--redis-stat-prefix=flowdb:flows: \ 57--ifname-up=${WAN_IFACE} \ 58--ifname-down=${LAN_IFACE} \ 59${EXTRA_CMD_ARGS} \ 60" 61 62# 63# Functions 64# 65sb_get_max_zone_id() { 66 redis-cli get "settings:max_zone_id" 67} 68 69# prints 0 if a zone with the given ID is configured in redis, else 1 70# $1: zone id 71sb_zone_is_configured() { 72 local zone=$1 73 if [ $(redis-cli exists "settings:zone:${zone}") = "1" ] && 74 [ $(redis-cli hexists "settings:zone:${zone}" "weight:up") = "1" ] && 75 [ $(redis-cli hexists "settings:zone:${zone}" "weight:down") = "1" ]; then 76 echo 0 77 else 78 echo 1 79 fi 80} 81 82# echos the number of configured zones. a zone is considered "configured" 83# if it has a hash entry in settings:zone:<id> where id is less than 84# settings:max_zone_id 85sb_get_zone_count() { 86 local maxzoneid=$(sb_get_max_zone_id) 87 local zone=0 88 local count=0 89 90 if [ -n "${maxzoneid}" ]; then 91 while [ "${zone}" -le "${maxzoneid}" ]; do 92 if [ $(sb_zone_is_configured ${zone}) = "0" ]; then 93 let count=count+1 94 fi 95 let zone=zone+1 96 done 97 fi 98 99 echo ${count} 100} 101 102# returns a zone config item from redis 103# $1: dev (e.g., eth0, br-lan, etc.) 104# $2: zone (integer zone identifier) 105# $3: key (e.g., bw, weight) 106# $4: default (returned if key doesn't exist) 107sb_get_zone_config() { 108 local dev=$1 109 local zone=$2 110 local key=$3 111 local default=$4 112 113 if [ "${dev}" = "${WAN_IFACE}" ]; then 114 redis-cli hget settings:zone:${zone} ${key}:up 115 elif [ "${dev}" = "${LAN_IFACE}" ]; then 116 redis-cli hget settings:zone:${zone} ${key}:down 117 else 118 echo ${default} 119 echo "error: ${dev} is not a supported interface" 1>&2 120 fi 121} 122 123# returns the "bw" key from the zone config for the given interface zone 124# $1: dev 125# $2: zone 126sb_get_zone_rate() { 127 sb_get_zone_config $1 $2 bw 128} 129 130# returns the "weight" key from the zone config for the given interface zone 131# $1: dev 132# $2: zone 133sb_get_zone_weight() { 134 sb_get_zone_config $1 $2 weight 10000 135} 136 137# generates a hex value in the CLASSID_ZONE_BASE range that can be 138# used as a classid or a qdisc handle 139# $1: zone id 140sb_gen_zone_classid() { 141 printf "%x" $((0x${CLASSID_ZONE_BASE} + ${1})) 142} 143 144# generates a hex value in the CLASSID_ZONE_TBL_BASE range that can be 145# used as a classid or a qdisc handle for NSS-based zone 146# $1: zone id 147sb_gen_zone_tbl_classid() { 148 printf "%x" $((0x${CLASSID_ZONE_TBL_BASE} + ${1})) 149} 150 151# generates a hex value in the CLASSID_ZONE_BG_BASE range that can be 152# used as a classid or a qdisc handle for NSS-based zone background qdisc 153# $1: zone id 154sb_gen_zone_bg_classid() { 155 printf "%x" $((0x${CLASSID_ZONE_BG_BASE} + ${1})) 156} 157 158# generates a hex value in the CLASSID_ZONE_CL_BASE range that can be 159# used as a classid or a qdisc handle for NSS-based zone classified qdisc 160# $1: zone id 161sb_gen_zone_cl_classid() { 162 printf "%x" $((0x${CLASSID_ZONE_CL_BASE} + ${1})) 163} 164 165# $1: dev 166# $2: parent 167# $3: handle 168# $4: qdisc type (default = fq_codel) 169# $5: extra opts 170add_interactive_qdisc() { 171 tc qdisc add dev $1 parent $2 handle $3 \ 172 ${4:-fq_codel} \ 173 limit 100\ 174 target 250000 interval 2500000 $5 175 [ $? = 0 ] || return $? 176} 177 178start_qdiscs() { 179 echo "Setting up qdiscs on interface ${WAN_IFACE}" 180 GUEST_BANDWIDTH_LIMIT="${GUEST_BANDWIDTH_LIMIT_UP}" 181 setup_iface ${WAN_IFACE} 182 [ $? = 0 ] || return $? 183 184 echo "Setting up qdiscs on interface ${LAN_IFACE}" 185 GUEST_BANDWIDTH_LIMIT="${GUEST_BANDWIDTH_LIMIT_DOWN}" 186 setup_iface ${LAN_IFACE} 187 [ $? = 0 ] || return $? 188} 189 190stop_qdiscs() { 191 tc qdisc del dev ${WAN_IFACE} root 192 tc qdisc del dev ${LAN_IFACE} root 193} 194 195start() { 196 [ -f "${PIDFILE}" ] && { 197 return 0 198 } 199 200 [ ! -f /var/log/setup_iptables ] && { 201 teardown_iptables 2>/dev/null 202 setup_iptables 203 } 204 touch /var/log/setup_iptables 205 206 for i in ${KERNEL_MODULES}; do 207 insmod $i 2>/dev/null 208 done 209 210 [ ! -d "${RUNDIR}" ] && { 211 mkdir ${RUNDIR} 212 } 213 214 [ -x ${BINARY} ] || { 215 echo "${NAME} not found: ${BINARY}" 216 exit 2 217 } 218 219 stop_qdiscs 2>/dev/null 220 start_qdiscs || exit 3 221 222 echo -n "Starting ${NAME}: " 223 ${BINARY} ${CMDLINE_OPTS} "$@" 224 retval=$? 225 echo 226 return ${retval} 227} 228 229boot() { 230 start "$@" 231} 232 233stop() { 234 default_stop 235 local retval=$? 236 237 stop_qdiscs 238 teardown_iptables 239 rm -rf /var/log/setup_iptables 240 241 return ${retval} 242} 243 244usage() { 245 cat <<EOF 246Usage: $0 [command] 247 248Commands: 249 start 250 stop 251 restart 252 reload 253 boot 254 init 255 status 256${EXTRA_HELP} 257EOF 258} 259 260action() { 261 action=${1:-$DEFAULT_ACTION} 262 # this shift is required because the start() function accepts 263 # parameters from the command line and passes them through to the 264 # daemon 265 shift 266 267 BINARY=${BINARY:-$(echo $0 | sed 's/.*\///')} 268 DISPLAY_NAME=${DISPLAY_NAME:-${NAME:-$BINARY}} 269 PIDFILE=${PIDFILE:-$RUNDIR/$BINARY.pid} 270 271 case "${action}" in 272 boot|init) 273 boot "$@" 274 ;; 275 start|stop|restart|reload|status|start_qdiscs|stop_qdiscs|setup_iptables|teardown_iptables) 276 ${action} "$@" 277 ;; 278 *) 279 usage 280 exit 3 281 esac 282} 283 284action "$@" 285exit $? 286