]> arthur.barton.de Git - netdata.git/commitdiff
tc now supports hierarchical qdiscs too
authorCosta Tsaousis (ktsaou) <costa@tsaousis.gr>
Sun, 29 Jan 2017 06:47:56 +0000 (08:47 +0200)
committerCosta Tsaousis (ktsaou) <costa@tsaousis.gr>
Sun, 29 Jan 2017 06:47:56 +0000 (08:47 +0200)
plugins.d/tc-qos-helper.sh
src/plugin_tc.c

index 60342e9fe5378f94c087a4d9b988194a39ff44b3..6dd9bfb59b29da4b3e5e70c167547b99d2eed265 100755 (executable)
@@ -63,6 +63,8 @@ fireqos_run_dir="/var/run/fireqos"
 qos_get_class_names_every=120
 qos_exit_every=3600
 
+tc_show="qdisc" # can also be "class"
+
 # check if we have a valid number for interval
 t=${1}
 update_every=$((t))
@@ -75,6 +77,16 @@ if [ -f "${config_dir}/tc-qos-helper.conf" ]
     source "${config_dir}/tc-qos-helper.conf"
 fi
 
+case "${tc_show}" in
+    qdisc|class)
+        ;;
+
+    *)
+        error "tc_show variable can be either 'qdisc' or 'class' but is set to '${tc_show}'. Assuming it is 'qdisc'."
+        tc_show="qdisc"
+        ;;
+esac
+
 # default sleep function
 LOOPSLEEPMS_LASTWORK=0
 loopsleepms() {
@@ -94,10 +106,17 @@ tc_devices=
 fix_names=
 
 setclassname() {
-    echo "SETCLASSNAME $3 $2"
+    if [ "${tc_show}" = "qdisc" ]
+        then
+        echo "SETCLASSNAME $4 $2"
+    else
+        echo "SETCLASSNAME $3 $2"
+    fi
 }
 
 show_tc_cls() {
+    [ "${tc_show}" = "qdisc" ] && return 1
+
     local x="${1}"
 
     if [ -f /etc/iproute2/tc_cls ]
@@ -143,8 +162,7 @@ show_tc() {
     echo "BEGIN ${x}"
 
     # netdata can parse the output of tc
-    ${tc} -s class show dev ${x}
-    ${tc} -s qdisc show dev ${x}
+    ${tc} -s ${tc_show} show dev ${x}
 
     # check FireQOS names for classes
     if [ ! -z "${fix_names}" ]
index b848b7575147f108e1d86d29a6b02fb9a9372b7b..95a4d3dcadb29ec43cd5dc8080204ceefcf6dbd7 100644 (file)
@@ -267,13 +267,20 @@ static inline void tc_device_commit(struct tc_device *d) {
     for(c = d->classes; c; c = c->next) {
         if(unlikely(!c->updated)) continue;
 
+        //debug(D_TC_LOOP, "TC: In device '%s', %s '%s'  has leafid: '%s' and parentid '%s'.",
+        //    d->id,
+        //    c->isqdisc?"qdisc":"class",
+        //    c->id,
+        //    c->leafid?c->leafid:"NULL",
+        //    c->parentid?c->parentid:"NULL");
+
         // find if c is leaf or not
         for(x = d->classes; x; x = x->next) {
             if(unlikely(!x->updated || c == x || !x->parentid)) continue;
 
             if( (c->hash == x->parent_hash && strcmp(c->id, x->parentid) == 0) ||
                 (c->leafid && c->leaf_hash == x->parent_hash && strcmp(c->leafid, x->parentid) == 0)) {
-                // 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);
+                // 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);
                 c->isleaf = 0;
                 x->hasparent = 1;
             }
@@ -284,8 +291,8 @@ static inline void tc_device_commit(struct tc_device *d) {
     /*
     if(unlikely(debug_flags & D_TC_LOOP)) {
         for(c = d->classes ; c ; c = c->next) {
-            if((c->isleaf && c->hasparent) || d->enabled_all_classes_qdiscs) debug(D_TC_LOOP, "TC: Device '%s', class %s, OK", d->name, c->id);
-            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)");
+            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);
+            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)");
         }
     }
     */
@@ -293,7 +300,7 @@ static inline void tc_device_commit(struct tc_device *d) {
     for(c = d->classes ; c ; c = c->next) {
         if(unlikely(!c->updated)) continue;
 
-        // 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);
+        // 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);
 
         if(unlikely((c->isleaf && c->hasparent) || d->enabled_all_classes_qdiscs)) {
             c->render = 1;
@@ -787,26 +794,45 @@ void *tc_main(void *ptr) {
             if(unlikely(device && ((first_hash == CLASS_HASH && strcmp(words[0], "class") == 0) ||  (first_hash == QDISC_HASH && strcmp(words[0], "qdisc") == 0)))) {
                 // 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]);
 
-                // words[1] : class type
-                // words[2] : N:XX
-                // words[3] : parent or root
-                if(likely(words[1] && words[2] && words[3] && (strcmp(words[3], "parent") == 0 || strcmp(words[3], "root") == 0))) {
-                    //char *type     = words[1];  // the class: htb, fq_codel, etc
+                char *type     = words[1];  // the class/qdisc type: htb, fq_codel, etc
+                char *id       = words[2];  // the class/qdisc major:minor
+                char *parent   = words[3];  // the word 'parent' or 'root'
+                char *parentid = words[4];  // parentid
+                char *leaf     = words[5];  // the word 'leaf'
+                char *leafid   = words[6];  // leafid
+
+                int parent_is_root = 0;
+                int parent_is_parent = 0;
+                if(likely(parent)) {
+                    parent_is_parent = !strcmp(parent, "parent");
 
-                    // we are only interested for HTB classes
-                    //if(strcmp(type, "htb") != 0) continue;
+                    if(!parent_is_parent)
+                        parent_is_root = !strcmp(parent, "root");
+                }
 
-                    char *id       = words[2];  // the class major:minor
-                    char *parent   = words[3];  // 'parent' or 'root'
-                    char *parentid = words[4];  // the parent's id
-                    char *leaf     = words[5];  // 'leaf'
-                    char *leafid   = words[6];  // leafid
+                if(likely(type && id && (parent_is_root || parent_is_parent))) {
                     char qdisc = 0;
 
-                    if(first_hash == QDISC_HASH)
+                    if(first_hash == QDISC_HASH) {
                         qdisc = 1;
 
-                    if(strcmp(parent, "root") == 0) {
+                        if(!strcmp(type, "ingress")) {
+                            // we don't want to get the ingress qdisc
+                            // there should be an IFB interface for this
+
+                            class = NULL;
+                            continue;
+                        }
+
+                        if(parent_is_parent && parentid) {
+                            // eliminate the minor number from parentid
+                            char *s = parentid;
+                            while(*s && *s != ':') s++;
+                            if(*s == ':') s[1] = '\0';
+                        }
+                    }
+
+                    if(parent_is_root) {
                         parentid = NULL;
                         leafid = NULL;
                     }