4 # real-time performance and health monitoring, done right!
5 # (C) 2016 Costa Tsaousis <costa@tsaousis.gr>
8 # This script is a helper to allow netdata collect tc data.
9 # tc output parsing has been implemented in C, inside netdata
10 # This script allows setting names to dimensions.
12 export PATH="${PATH}:/sbin:/usr/sbin:/usr/local/sbin"
16 # -----------------------------------------------------------------------------
17 # find /var/run/fireqos
20 fireqos_run_dir="/var/run/fireqos"
24 local t=$(readlink "$r")
28 r=$(cd $(dirname "$r") && cd $(dirname "$t") && pwd -P)/$(basename "$t")
35 if [ ! -d "${fireqos_run_dir}" ]
38 # the fireqos executable - we will use it to find its config
39 fireqos="$(which fireqos 2>/dev/null || command -v fireqos 2>/dev/null)"
41 if [ ! -z "${fireqos}" ]
44 fireqos_exec_dir="$(realdir ${fireqos})"
46 if [ ! -z "${fireqos_exec_dir}" -a "${fireqos_exec_dir}" != "." -a -f "${fireqos_exec_dir}/install.config" ]
50 source "${fireqos_exec_dir}/install.config"
52 if [ -d "${LOCALSTATEDIR}/run/fireqos" ]
54 fireqos_run_dir="${LOCALSTATEDIR}/run/fireqos"
60 # -----------------------------------------------------------------------------
64 PROGRAM_NAME="$(basename $0)"
65 PROGRAM_NAME="${PROGRAM_NAME/.plugin}"
68 date "+%Y-%m-%d %H:%M:%S"
75 echo >&2 "$(logdate): ${PROGRAM_NAME}: ${status}: ${*}"
98 [ $debug -eq 1 ] && log DEBUG "${@}"
102 # -----------------------------------------------------------------------------
104 plugins_dir="${NETDATA_PLUGINS_DIR}"
105 [ -z "$plugins_dir" ] && plugins_dir="$( dirname $PROGRAM_FILE )"
107 config_dir=${NETDATA_CONFIG_DIR-/etc/netdata}
108 tc="$(which tc 2>/dev/null || command -v tc 2>/dev/null)"
111 # -----------------------------------------------------------------------------
114 # time in seconds to refresh QoS class/qdisc names
115 qos_get_class_names_every=120
117 # time in seconds to exit - netdata will restart the script
120 # what to use? classes or qdiscs?
121 tc_show="qdisc" # can also be "class"
124 # -----------------------------------------------------------------------------
125 # check if we have a valid number for interval
129 [ $((update_every)) -lt 1 ] && update_every=${NETDATA_UPDATE_EVERY}
130 [ $((update_every)) -lt 1 ] && update_every=1
133 # -----------------------------------------------------------------------------
134 # allow the user to override our defaults
136 if [ -f "${config_dir}/tc-qos-helper.conf" ]
138 source "${config_dir}/tc-qos-helper.conf"
146 error "tc_show variable can be either 'qdisc' or 'class' but is set to '${tc_show}'. Assuming it is 'qdisc'."
152 # -----------------------------------------------------------------------------
153 # default sleep function
155 LOOPSLEEPMS_LASTWORK=0
160 # if found and included, this file overwrites loopsleepms()
161 # with a high resolution timer function for precise looping.
162 . "${plugins_dir}/loopsleepms.sh.inc"
165 # -----------------------------------------------------------------------------
166 # final checks we can run
168 if [ -z "${tc}" -o ! -x "${tc}" ]
170 fatal "cannot find command 'tc' in this system."
176 # -----------------------------------------------------------------------------
179 if [ "${tc_show}" = "qdisc" ]
181 echo "SETCLASSNAME $4 $2"
183 echo "SETCLASSNAME $3 $2"
188 [ "${tc_show}" = "qdisc" ] && return 1
192 if [ -f /etc/iproute2/tc_cls ]
194 local classid name rest
195 while read classid name rest
197 [ -z "${classid}" -o -z "${name}" -o "${classid}" = "#" -o "${name}" = "#" -o "${classid:0:1}" = "#" -o "${name:0:1}" = "#" ] && continue
198 setclassname "" "${name}" "${classid}"
199 done </etc/iproute2/tc_cls
205 show_fireqos_names() {
206 local x="${1}" name n interface_dev interface_classes interface_classes_monitor
208 if [ -f "${fireqos_run_dir}/ifaces/${x}" ]
210 name="$(<"${fireqos_run_dir}/ifaces/${x}")"
211 echo "SETDEVICENAME ${name}"
215 interface_classes_monitor=
216 source "${fireqos_run_dir}/${name}.conf"
217 for n in ${interface_classes_monitor}
219 setclassname ${n//|/ }
221 [ ! -z "${interface_dev}" ] && echo "SETDEVICEGROUP ${interface_dev}"
234 # netdata can parse the output of tc
235 ${tc} -s ${tc_show} show dev ${x}
237 # check FireQOS names for classes
238 if [ ! -z "${fix_names}" ]
240 show_fireqos_names "${x}" || show_tc_cls "${x}"
247 local count=0 devs= dev rest l
249 # find all the devices in the system
251 while IFS=":| " read dev rest
254 [ ${count} -le 2 ] && continue
255 devs="${devs} ${dev}"
258 # from all the devices find the ones
259 # that have QoS defined
260 # unfortunately, one fork per device cannot be avoided
264 l="$(${tc} class show dev ${dev} 2>/dev/null)"
265 [ ! -z "${l}" ] && tc_devices="${tc_devices} ${dev}"
269 # update devices and class names
270 # once every 2 minutes
271 names_every=$((qos_get_class_names_every / update_every))
273 # exit this script every hour
274 # it will be restarted automatically
275 exit_after=$((qos_exit_every / update_every))
285 if [ ${c} -le 1 -o ${c} -ge ${names_every} ]
292 for d in ${tc_devices}
297 echo "WORKTIME ${LOOPSLEEPMS_LASTWORK}"
299 loopsleepms ${update_every}
301 [ ${gc} -gt ${exit_after} ] && exit 0