-
Notifications
You must be signed in to change notification settings - Fork 680
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WIP] cake plugins #941
base: master
Are you sure you want to change the base?
[WIP] cake plugins #941
Changes from 24 commits
052a824
467720a
f202a4d
507d7f1
dd3f63f
12c4695
af12747
d7f9176
5d31b60
8e2aac4
a7bd7e3
e336264
afb969f
b0c1e96
491bfc1
5e74931
86df21b
d95aa75
455effd
749d302
34d81f7
234db28
fc8ca5b
7540eb3
00888cd
6760871
8cc759a
0ea29f8
b75fa5c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,210 @@ | ||
#!/bin/bash | ||
# -*- sh -*- | ||
|
||
: << =cut | ||
|
||
=pod | ||
|
||
=encoding UTF-8 | ||
|
||
=head1 NAME | ||
|
||
cake_ - Plugin to monitor cake's backlog, dropped, overlimits and requeues | ||
|
||
=head1 CONFIGURATION | ||
|
||
None needed. | ||
|
||
=head1 INTERPRETATION | ||
|
||
Cake, also known as sch_cake is a modern bandwidth limiter, which eliminates | ||
buffer bloat over slow links. It's also capable to give flows, hosts and each | ||
flow of each host a fair part of the avaible bandwidth. | ||
|
||
This plugin allows for a monitor of the pressure on the qdisc, by monitoring key | ||
values. | ||
|
||
=head1 SEE ALSO | ||
|
||
Take a look at "man cake" to get more information about cake. | ||
|
||
=head1 MAGIC MARKERS | ||
|
||
#%# family=auto | ||
#%# capabilities=autoconf suggest | ||
|
||
=head1 AUTHORS | ||
|
||
RubenKelevra <[email protected]> | ||
|
||
work based on the tc plugin, authors: | ||
Steve Schnepp <[email protected]>, | ||
Samuel Smith <[email protected]>, | ||
Nye Liu <[email protected]> | ||
|
||
=head1 LICENSE | ||
|
||
GPLv2 or later | ||
|
||
=cut | ||
|
||
DEVICE="${0##*/cake_}" | ||
|
||
tc_get_ifb_dev() { | ||
dev="$(/sbin/tc filter show dev "$DEVICE" parent ffff: protocol all | grep "mirred" | grep "Egress Redirect to device")" | ||
[ $? -eq 1 ] && return 1 | ||
|
||
echo "$dev" | sed -n 's/.* device \([^ ]*\).*/\1/p' | tr ')' ' ' | awk '{ print $1 }' | ||
} | ||
|
||
tc_cake_sent() { | ||
/sbin/tc -s qdisc show dev "$1" | grep -E "^ Sent" | tr ',' ' ' | tr ')' ' ' | ||
} | ||
tc_cake_backlog() { | ||
/sbin/tc -s qdisc show dev "$1" | grep -E "^ backlog" | tr 'p' ' ' | ||
} | ||
|
||
DEVICE_IN="$(tc_get_ifb_dev)" | ||
has_if_in=$? | ||
|
||
case "$1" in | ||
autoconf) | ||
if [ -r /proc/net/dev ]; then | ||
echo yes | ||
exit 0 | ||
else | ||
echo "no (/proc/net/dev not found)" | ||
exit 1 | ||
fi | ||
;; | ||
suggest) | ||
if [ -r /proc/net/dev ]; then | ||
ifs="$(awk ' | ||
/^ *(eth|tap|bond|wlan|ath|ra|sw|eno|ens|enp|wlp|wl)[0-9]*/ { | ||
split($0, a, /: */); | ||
gsub(/^ +/,"",a[1]); | ||
if (($2 > 0) || ($10 > 0)) print a[1]; }' /proc/net/dev)" | ||
cake_ifs=() | ||
for if in $ifs; do | ||
qdisc="$(/sbin/tc -s qdisc show dev "$if" | head -n1 | awk '{ print $2 }')" | ||
if [ "$qdisc" == "cake" ]; then | ||
cake_ifs+=("$if") | ||
fi | ||
done | ||
echo "$cake_ifs" | ||
fi | ||
exit 0 | ||
;; | ||
config) | ||
|
||
if [ $has_if_in -eq 0 ]; then | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please quote variables. We are striving for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, shellcheck isn't complaining about this line, what exactly is wrong with it? integer comparisons AFAIK cannot be double quoted and since it's not an input variable I don't see any point changing this to a string, just to make any sanitizer happy. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Correct: in this case it does not complain, since you are assigning only fixed strings to this variable. Overly simple static parsers (e.g.: humans like me) will repeatedly stumble over this, nevertheless :)
Please rest assured, that the shell parser will never forbid you to double-quote a variable :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well no, I assigned integers to the variables, that's why it's probably not complaining. You're sure that openwrt's There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hehe - yes, that works. I am writing way too much shell code for busybox's ash. All the usual features of |
||
echo "graph_title $DEVICE ($DEVICE_IN) cake queuing" | ||
else | ||
echo "graph_title $DEVICE cake queuing" | ||
fi | ||
echo 'graph_args --base 1000' | ||
if [ $has_if_in -eq 0 ]; then | ||
echo 'graph_vlabel pps in (-) / out (+)' | ||
else | ||
echo 'graph_vlabel packets per second' | ||
fi | ||
echo 'graph_category network' | ||
if [ $has_if_in -eq 0 ]; then | ||
echo "graph_info This graph shows the general packet handling status of egress+ingress traffic of the $DEVICE ($DEVICE_IN) network interface." | ||
else | ||
echo "graph_info This graph shows the general packet handling status of egress traffic of the $DEVICE network interface." | ||
fi | ||
|
||
if [ $has_if_in -eq 0 ]; then | ||
echo "backlog_in.label backlog" | ||
echo "backlog_in.draw LINE2" | ||
echo "backlog_in.colour 85c4e0" | ||
echo "backlog_in.min 0" | ||
echo "backlog_in.info amount of packets currently buffered. This is an absolut value at the time the plugin is running, not an avg over the last 5 minutes (as all other values in this graph)" | ||
echo "backlog_in.graph no" | ||
fi | ||
echo "backlog.label backlog (absolute)" | ||
echo "backlog.draw LINE2" | ||
echo "backlog.colour 85c4e0" | ||
echo "backlog.min 0" | ||
echo "backlog.info amount of packets currently buffered" | ||
[ $has_if_in -eq 0 ] && echo "backlog.negative backlog_in" | ||
|
||
if [ $has_if_in -eq 0 ]; then | ||
echo "dropped_in.label dropped" | ||
echo "dropped_in.draw AREA" | ||
echo "dropped_in.colour c77223" | ||
echo "dropped_in.type DERIVE" | ||
echo "dropped_in.min 0" | ||
echo "dropped_in.info dropped packets in queue" | ||
echo "dropped_in.graph no" | ||
fi | ||
echo "dropped.label dropped" | ||
echo "dropped.draw AREA" | ||
echo "dropped.colour c77223" | ||
echo "dropped.type DERIVE" | ||
echo "dropped.min 0" | ||
echo "dropped.info dropped packets in queue" | ||
[ $has_if_in -eq 0 ] && echo "dropped.negative dropped_in" | ||
|
||
if [ $has_if_in -eq 0 ]; then | ||
echo "overlimits_in.label overlimits" | ||
echo "overlimits_in.draw STACK" | ||
echo "overlimits_in.colour b6655c" | ||
echo "overlimits_in.type DERIVE" | ||
echo "overlimits_in.min 0" | ||
echo "overlimits_in.info packets exeeded a limit" | ||
echo "overlimits_in.graph no" | ||
fi | ||
echo "overlimits.label overlimits" | ||
echo "overlimits.draw STACK" | ||
echo "overlimits.colour b6655c" | ||
echo "overlimits.type DERIVE" | ||
echo "overlimits.min 0" | ||
echo "overlimits.info packets exeeded a limit" | ||
[ $has_if_in -eq 0 ] && echo "overlimits.negative overlimits_in" | ||
|
||
if [ $has_if_in -eq 0 ]; then | ||
echo "requeues_in.label requeues" | ||
echo "requeues_in.draw STACK" | ||
echo "requeues_in.colour 4e9e14" | ||
echo "requeues_in.type DERIVE" | ||
echo "requeues_in.min 0" | ||
echo "requeues_in.info packets requeued in queue" | ||
echo "requeues_in.graph no" | ||
fi | ||
echo "requeues.label requeues" | ||
echo "requeues.draw STACK" | ||
echo "requeues.colour 4e9e14" | ||
echo "requeues.type DERIVE" | ||
echo "requeues.min 0" | ||
echo "requeues.info packets requeued in queue" | ||
[ $has_if_in -eq 0 ] && echo "requeues.negative requeues_in" | ||
|
||
exit 0 | ||
;; | ||
esac | ||
|
||
tc_cake_sent "$DEVICE" | awk '{ | ||
print "dropped.value " $7 | ||
print "overlimits.value " $9 | ||
print "requeues.value " $11 | ||
}' | ||
|
||
tc_cake_backlog "$DEVICE" | awk '{ | ||
print "backlog.value " $3 | ||
}' | ||
|
||
if [ $has_if_in -eq 1 ]; then | ||
RubenKelevra marked this conversation as resolved.
Show resolved
Hide resolved
|
||
exit 0 | ||
fi | ||
|
||
tc_cake_sent "$DEVICE_IN" | awk '{ | ||
print "dropped_in.value " $7 | ||
print "overlimits_in.value " $9 | ||
print "requeues_in.value " $11 | ||
}' | ||
|
||
tc_cake_backlog "$DEVICE_IN" | awk '{ | ||
print "backlog_in.value " $3 | ||
}' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there really no specific test for the actual use of
cake
on the system?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not in all cases. You could check if the sch_cake module is loaded, but if it's compiled as a built-in module that won't catch it. Also, the module can be loaded without being active.
The only sure way to see if cake is active is to do a
tc qdisc
and loop through all interfaces to try to find it. You could probably dotc -j qdisc
and construct a query with jq that will spit out all cake instances...There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about this one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks great, thanks!
But do we really want to get rid of the filter with packets received?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So... I'll leave it the way it it. If you want to replace this function, feel free to suggest one which covers all features.
Also make sure to add a simple test, if jq is installed with an error-output for autoconf - for example it isn't installed on my system - never had the need for it - so an output about this dependency would be nice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure, what this means. How would you detect this situation? I would be happy to suggest a suitable filter.
Regarding the check of for
jq
- this is simply part of "autoconf", too:There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's the
if (($2 > 0) || ($10 > 0))
-part of line 26. This was part of the tc_ plugin. :)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK - I see.
Maybe we have different perceptions regarding the purpose of the "autoconf" test.
Here the plugin needs to answer two questions:
The "autoconf" call should return "yes" only if both questions are affirmed.
Your current implementation of "autoconf" only cares (partly) for the first question.
Additionally it should check two more details:
tc
available? (see my example forjq
above)The latter can probably be tested like this: