diff --git a/plugins/other/qos_ b/plugins/other/qos_ new file mode 100755 index 00000000..6382cfe1 --- /dev/null +++ b/plugins/other/qos_ @@ -0,0 +1,167 @@ +#!/usr/bin/perl -w +# -*- perl -*- +# Wildcard plugin to monitor QoS queues. +# +# Requirements: +# - tc program installed and in path +# +# Parameters supported: +# +# config +# autoconf +# suggest +# +# Configurable variables +# +# tc - Override default program +# ignore_queue - Queue with handle not be plotted +# label_name - Queue with handle as defined label +# +# Magic markers: +#%# family=manual +#%# capabilities=autoconf suggest + +use strict; + +my $TC = $ENV{'tc'} || 'tc'; + +if ($ARGV[0] and $ARGV[0] eq 'suggest') { + my $text = `egrep '^ *(eth|wlan|ath|ra)[0-9]+:' /proc/net/dev | cut -f1 -d:`; + print $text; + exit; +} + +$0 =~ /qos_(.+)*$/; +my $IFACE = $1; +exit 2 unless defined $IFACE; + +if ( exists $ARGV[0] and $ARGV[0] eq 'autoconf' ) { + # Now see if "tc" can run + my $text = `$TC qdisc show dev $IFACE`; + if ($?) { + if ($? == -1) { + print "no (program $TC not found)\n"; + } else { + print "no (program $TC died)\n"; + } + exit 1; + } + print "yes\n"; + exit 0; +} + +my %queues; +my $qdisc; +my $queue; +my $handle; +my $one; +my $sent; +my $count; +my $haschild; + +#open(TEXT, "$TC -s qdisc show dev $IFACE|"); +#while (! eof(TEXT)) { +# ($qdisc, $queue, $handle) = split(" ", ); +# if ($qdisc eq "backlog") { +# ($qdisc, $queue, $handle) = split(" ", ); +# } +# ($one, $sent) = split(" ", ); +# $handle =~ s/://; +# $queues{$handle} = { +# queue => $queue, +# handle => $handle, +# sent => $sent +# }; +#} + +my @class = `$TC -s class show dev $IFACE`; +my( $name, $id1, $id2, $type, $rate, $parent); +for( my $x = 0; $x < scalar(@class); $x++ ) { + if($class[$x] =~ m/^class/i ) { + ( $name, $id1, $id2, $type, $parent) = ( $class[$x] =~ m/^class\s+(\w+)\s+(\d+):(\d+)\s+(\w+)\s([^\s]+)/i ); + if($type eq "parent") { + $x++; + ( $rate ) = ( $class[$x] =~ m/Sent\s+(\d+)\s+/i ); + $handle = "$name"."${id1}_${id2}"; + $queues{$handle} = { + queue => $name, + handle => "${id1}_${id2}", + id => "${id1}:${id2}", + sent => $rate, + parent => $parent + }; + } + } +} + +if ( exists $ARGV[0] and $ARGV[0] eq 'config' ) { + print "graph_title QoS queue on $IFACE\n"; + print "graph_args --base 1000\n"; + print "graph_vlabel bits per \${graph_period}\n"; + print "graph_category network\n"; + print "graph_info This graph shows the QoS queue of the $IFACE network interface.\n"; + print "graph_order "; + foreach my $key (sort by_handle keys %queues) { + $haschild = 0; + foreach my $key2 (sort by_handle keys %queues) { + if($queues{$key}->{id} eq $queues{$key2}->{parent}) { + $haschild = 1; + last; + } + } + if($haschild == 1) { + $queues{$key}->{leaf} = 0; + next; + } + $queues{$key}->{leaf} = 1; + print $queues{$key}->{queue},$queues{$key}->{handle}, " "; + } + print "\n"; + $count = 0; + foreach my $key (sort by_handle keys %queues) { + if($queues{$key}->{leaf} == 0) { next; } + print $queues{$key}->{queue},$queues{$key}->{handle}, ".label "; + if (exists $ENV{"label_name$queues{$key}->{handle}"}) { + print $ENV{"label_name$queues{$key}->{handle}"}; + } else { + print $queues{$key}->{queue},$queues{$key}->{handle}; + } + print "\n"; + if (exists $ENV{"max"}) { + print $queues{$key}->{queue},$queues{$key}->{handle}, ".max ",$ENV{"max"},"\n"; + } elsif (exists $ENV{"max$queues{$key}->{handle}"}) { + print $queues{$key}->{queue},$queues{$key}->{handle}, ".max ",$ENV{"max$queues{$key}->{handle}"},"\n"; + } + print $queues{$key}->{queue},$queues{$key}->{handle}, ".type COUNTER\n"; + if($count == 0){ + print $queues{$key}->{queue},$queues{$key}->{handle}, ".draw AREA\n"; + } else { + print $queues{$key}->{queue},$queues{$key}->{handle}, ".draw STACK\n"; + } + print $queues{$key}->{queue},$queues{$key}->{handle}, ".cdef ", $queues{$key}->{queue},$queues{$key}->{handle}, ",8,*\n"; + if (exists $ENV{"ignore_queue$queues{$key}->{handle}"}){ + print $queues{$key}->{queue},$queues{$key}->{handle}, ".graph no\n" ; + } else { + $count++; + } + } + exit 0; +} + +sub by_handle { + return $a cmp $b; +} + +foreach my $key (sort by_handle keys %queues) { + $haschild = 0; + foreach my $key2 (sort by_handle keys %queues) { + if($queues{$key}->{id} eq $queues{$key2}->{parent}) { + $haschild = 1; + last; + } + } + if($haschild == 1) { next; } + print $queues{$key}->{queue},$queues{$key}->{handle}, ".value ",$queues{$key}->{sent}, "\n"; +} +# +# vim:syntax=perl \ No newline at end of file