collectd: sqm_collect: handle being orphaned
[feed/packages.git] / utils / collectd / files / exec-scripts / sqm_collectd.sh
1 #!/bin/sh
2
3 . /usr/share/libubox/jshn.sh
4
5 HOSTNAME="${COLLECTD_HOSTNAME:-localhost}"
6 INTERVAL="${COLLECTD_INTERVAL:-60}"
7
8 handle_cake() {
9 local ifc ifr tin i
10
11 ifc="$1"
12 ifr="${ifc//[!0-9A-Za-z]/_}"
13
14 # Overall
15 json_get_vars bytes packets drops backlog qlen
16
17 # Options
18 json_select options
19 json_get_vars bandwidth diffserv
20 json_select ".."
21
22 echo "PUTVAL \"$HOSTNAME/sqm-$ifc/qdisc_bytes\" interval=$INTERVAL N:$bytes"
23 echo "PUTVAL \"$HOSTNAME/sqm-$ifc/qdisc_drops\" interval=$INTERVAL N:$drops"
24 echo "PUTVAL \"$HOSTNAME/sqm-$ifc/qdisc_backlog\" interval=$INTERVAL N:$backlog"
25
26 # ash doesn't have arrays so prepare to get a little creative
27 case "$diffserv" in
28 diffserv3 | diffserv4) tns="BKBEVIVO"
29 ;;
30 *) tns="T0T1T2T3T4T5T6T7"
31 ;;
32 esac
33
34 # Tins
35 # Flows & delays indicate the state as of the last packet that flowed through, so they appear to get stuck.
36 # Discard the results from a stuck tin.
37 json_get_keys tins tins
38 json_select tins
39 i=0
40 for tin in $tins; do
41 json_select "$tin"
42 json_get_vars threshold_rate sent_bytes sent_packets backlog_bytes target_us peak_delay_us avg_delay_us base_delay_us drops ecn_mark ack_drops sparse_flows bulk_flows unresponsive_flows
43
44 eval osp="\$osp${ifr}t${i}"
45 if [ "$osp" ] && [ "$osp" -eq "$sent_packets" ] ; then
46 peak_delay_us=0; avg_delay_us=0; base_delay_us=0
47 sparse_flows=0; bulk_flows=0; unresponsive_flows=0
48 else
49 eval "osp${ifr}t${i}=$sent_packets"
50 fi
51
52 tn=${tns:$((i<<1)):2}
53
54 echo "PUTVAL \"$HOSTNAME/sqmcake-$ifc/qdisct_bytes-$tn\" interval=$INTERVAL N:$sent_bytes"
55 echo "PUTVAL \"$HOSTNAME/sqmcake-$ifc/qdisct_thres-$tn\" interval=$INTERVAL N:$threshold_rate"
56 echo "PUTVAL \"$HOSTNAME/sqmcake-$ifc/qdisct_drops-$tn\" interval=$INTERVAL N:$drops:$ecn_mark:$ack_drops"
57 echo "PUTVAL \"$HOSTNAME/sqmcake-$ifc/qdisct_backlog-$tn\" interval=$INTERVAL N:$backlog_bytes"
58 echo "PUTVAL \"$HOSTNAME/sqmcake-$ifc/qdisct_flows-$tn\" interval=$INTERVAL N:$sparse_flows:$bulk_flows:$unresponsive_flows"
59 echo "PUTVAL \"$HOSTNAME/sqmcake-$ifc/qdisct_latencyus-$tn\" interval=$INTERVAL N:$target_us:$peak_delay_us:$avg_delay_us:$base_delay_us"
60
61 json_select ..
62 i=$((i+1))
63 done
64 json_select ..
65 }
66
67 handle_mq() {
68 ifc="$1"
69
70 # Overall
71 json_get_vars bytes drops backlog
72
73 echo "PUTVAL \"$HOSTNAME/sqm-$ifc/qdisc_bytes\" interval=$INTERVAL N:$bytes"
74 echo "PUTVAL \"$HOSTNAME/sqm-$ifc/qdisc_drops\" interval=$INTERVAL N:$drops"
75 echo "PUTVAL \"$HOSTNAME/sqm-$ifc/qdisc_backlog\" interval=$INTERVAL N:$backlog"
76 }
77
78 process_qdisc() {
79 local ifc jsn
80
81 ifc="$1"
82 jsn=$(tc -s -j qdisc show dev "$ifc") || return
83
84 # strip leading & trailing []
85 jsn="${jsn#[}" ; jsn="${jsn%]}"
86
87 json_load "${jsn}"
88 json_get_var qdisc kind
89
90 case "$qdisc" in
91 cake) handle_cake "$ifc"
92 ;;
93 mq) handle_mq "$ifc"
94 ;;
95
96 *) echo "Unknown qdisc type '$qdisc' on interface '$ifc'" 1>&2
97 ;;
98 esac
99 json_cleanup
100 }
101
102 # while not orphaned
103 while [ $(awk '$1 ~ "^PPid:" {print $2}' /proc/$$/status) -ne 1 ] ; do
104 for ifc in "$@" ; do
105 process_qdisc "$ifc"
106 done
107 sleep "${INTERVAL%%.*}"
108 done