tc now supports hierarchical qdiscs too
Costa Tsaousis (ktsaou) committed
Jan 29, 2017 at 08:47 UTC
2b183c2ab992540571df2d2d01c8b14edf038a42
2 files changed
+65
-21
plugins.d/tc-qos-helper.sh
+21
-3
@@ -63,6 +63,8 @@ fireqos_run_dir="/var/run/fireqos"
63
qos_get_class_names_every=120
64
qos_exit_every=3600
65
66
+tc_show="qdisc" # can also be "class"
67
+
68
# check if we have a valid number for interval
69
t=${1}
70
update_every=$((t))
@@ -75,6 +77,16 @@ if [ -f "${config_dir}/tc-qos-helper.conf" ]
77
source "${config_dir}/tc-qos-helper.conf"
78
fi
79
80
+case "${tc_show}" in
81
+ qdisc|class)
82
+ ;;
83
+
84
+ *)
85
+ error "tc_show variable can be either 'qdisc' or 'class' but is set to '${tc_show}'. Assuming it is 'qdisc'."
86
+ tc_show="qdisc"
87
+ ;;
88
+esac
89
+
90
# default sleep function
91
LOOPSLEEPMS_LASTWORK=0
92
loopsleepms() {
@@ -94,10 +106,17 @@ tc_devices=
106
fix_names=
107
108
setclassname() {
97
- echo "SETCLASSNAME $3 $2"
109
+ if [ "${tc_show}" = "qdisc" ]
110
+ then
111
+ echo "SETCLASSNAME $4 $2"
112
+ else
113
+ echo "SETCLASSNAME $3 $2"
114
+ fi
115
}
116
117
show_tc_cls() {
118
+ [ "${tc_show}" = "qdisc" ] && return 1
119
+
120
local x="${1}"
121
122
if [ -f /etc/iproute2/tc_cls ]
@@ -143,8 +162,7 @@ show_tc() {
162
echo "BEGIN ${x}"
163
164
# netdata can parse the output of tc
146
- ${tc} -s class show dev ${x}
147
- ${tc} -s qdisc show dev ${x}
165
+ ${tc} -s ${tc_show} show dev ${x}
166
167
# check FireQOS names for classes
168
if [ ! -z "${fix_names}" ]
src/plugin_tc.c
+44
-18
@@ -267,13 +267,20 @@ static inline void tc_device_commit(struct tc_device *d) {
267
for(c = d->classes; c; c = c->next) {
268
if(unlikely(!c->updated)) continue;
269
270
+ //debug(D_TC_LOOP, "TC: In device '%s', %s '%s' has leafid: '%s' and parentid '%s'.",
271
+ // d->id,
272
+ // c->isqdisc?"qdisc":"class",
273
+ // c->id,
274
+ // c->leafid?c->leafid:"NULL",
275
+ // c->parentid?c->parentid:"NULL");
276
+
277
// find if c is leaf or not
278
for(x = d->classes; x; x = x->next) {
279
if(unlikely(!x->updated || c == x || !x->parentid)) continue;
280
281
if( (c->hash == x->parent_hash && strcmp(c->id, x->parentid) == 0) ||
282
(c->leafid && c->leaf_hash == x->parent_hash && strcmp(c->leafid, x->parentid) == 0)) {
276
- // debug(D_TC_LOOP, "TC: In device '%s', class '%s' (leafid: '%s') has as leaf class '%s' (parentid: '%s').", d->name?d->name:d->id, c->name?c->name:c->id, c->leafid?c->leafid:c->id, x->name?x->name:x->id, x->parentid?x->parentid:x->id);
283
+ // debug(D_TC_LOOP, "TC: In device '%s', %s '%s' (leafid: '%s') has as leaf %s '%s' (parentid: '%s').", d->name?d->name:d->id, c->isqdisc?"qdisc":"class", c->name?c->name:c->id, c->leafid?c->leafid:c->id, x->isqdisc?"qdisc":"class", x->name?x->name:x->id, x->parentid?x->parentid:x->id);
284
c->isleaf = 0;
285
x->hasparent = 1;
286
}
@@ -284,8 +291,8 @@ static inline void tc_device_commit(struct tc_device *d) {
291
/*
292
if(unlikely(debug_flags & D_TC_LOOP)) {
293
for(c = d->classes ; c ; c = c->next) {
287
- if((c->isleaf && c->hasparent) || d->enabled_all_classes_qdiscs) debug(D_TC_LOOP, "TC: Device '%s', class %s, OK", d->name, c->id);
288
- else debug(D_TC_LOOP, "TC: Device '%s', class %s, IGNORE (isleaf: %d, hasparent: %d, parent: %s)", d->name?d->name:d->id, c->id, c->isleaf, c->hasparent, c->parentid?c->parentid:"(unset)");
294
+ if((c->isleaf && c->hasparent) || d->enabled_all_classes_qdiscs) debug(D_TC_LOOP, "TC: final nodes dump for '%s': class %s, OK", d->name, c->id);
295
+ else debug(D_TC_LOOP, "TC: final nodes dump for '%s': class %s, IGNORE (isleaf: %d, hasparent: %d, parent: %s)", d->name?d->name:d->id, c->id, c->isleaf, c->hasparent, c->parentid?c->parentid:"(unset)");
296
}
297
}
298
*/
@@ -293,7 +300,7 @@ static inline void tc_device_commit(struct tc_device *d) {
300
for(c = d->classes ; c ; c = c->next) {
301
if(unlikely(!c->updated)) continue;
302
296
- // debug(D_TC_LOOP, "TC: Device '%s', class '%s', isLeaf=%d, HasParent=%d, Seen=%d", d->name?d->name:d->id, c->name?c->name:c->id, c->isleaf, c->hasparent, c->seen);
303
+ // debug(D_TC_LOOP, "TC: device '%s', %s '%s' isleaf=%d, hasparent=%d", d->id, (c->isqdisc)?"qdisc":"class", c->id, c->isleaf, c->hasparent);
304
305
if(unlikely((c->isleaf && c->hasparent) || d->enabled_all_classes_qdiscs)) {
306
c->render = 1;
@@ -787,26 +794,45 @@ void *tc_main(void *ptr) {
794
if(unlikely(device && ((first_hash == CLASS_HASH && strcmp(words[0], "class") == 0) || (first_hash == QDISC_HASH && strcmp(words[0], "qdisc") == 0)))) {
795
// debug(D_TC_LOOP, "CLASS line on class id='%s', parent='%s', parentid='%s', leaf='%s', leafid='%s'", words[2], words[3], words[4], words[5], words[6]);
796
790
- // words[1] : class type
791
- // words[2] : N:XX
792
- // words[3] : parent or root
793
- if(likely(words[1] && words[2] && words[3] && (strcmp(words[3], "parent") == 0 || strcmp(words[3], "root") == 0))) {
794
- //char *type = words[1]; // the class: htb, fq_codel, etc
797
+ char *type = words[1]; // the class/qdisc type: htb, fq_codel, etc
798
+ char *id = words[2]; // the class/qdisc major:minor
799
+ char *parent = words[3]; // the word 'parent' or 'root'
800
+ char *parentid = words[4]; // parentid
801
+ char *leaf = words[5]; // the word 'leaf'
802
+ char *leafid = words[6]; // leafid
803
+
804
+ int parent_is_root = 0;
805
+ int parent_is_parent = 0;
806
+ if(likely(parent)) {
807
+ parent_is_parent = !strcmp(parent, "parent");
808
796
- // we are only interested for HTB classes
797
- //if(strcmp(type, "htb") != 0) continue;
809
+ if(!parent_is_parent)
810
+ parent_is_root = !strcmp(parent, "root");
811
+ }
812
799
- char *id = words[2]; // the class major:minor
800
- char *parent = words[3]; // 'parent' or 'root'
801
- char *parentid = words[4]; // the parent's id
802
- char *leaf = words[5]; // 'leaf'
803
- char *leafid = words[6]; // leafid
813
+ if(likely(type && id && (parent_is_root || parent_is_parent))) {
814
char qdisc = 0;
815
806
- if(first_hash == QDISC_HASH)
816
+ if(first_hash == QDISC_HASH) {
817
qdisc = 1;
818
809
- if(strcmp(parent, "root") == 0) {
819
+ if(!strcmp(type, "ingress")) {
820
+ // we don't want to get the ingress qdisc
821
+ // there should be an IFB interface for this
822
+
823
+ class = NULL;
824
+ continue;
825
+ }
826
+
827
+ if(parent_is_parent && parentid) {
828
+ // eliminate the minor number from parentid
829
+ char *s = parentid;
830
+ while(*s && *s != ':') s++;
831
+ if(*s == ':') s[1] = '\0';
832
+ }
833
+ }
834
+
835
+ if(parent_is_root) {
836
parentid = NULL;
837
leafid = NULL;
838
}