#!/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 # update_rate - Custom update_rate, to be used with async # graph_data_size - Custom graph_data_size, to be used with async & custom update_rate # # 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"; } } else { 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 && $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 "update_rate $ENV{update_rate}\n" if $ENV{update_rate}; print "graph_data_size $ENV{graph_data_size}\n" if $ENV{graph_data_size}; print "graph_order "; foreach my $key (sort by_handle keys %queues) { delete $queues{$key} if $key =~ /sfq/i; next if $key =~ /sfq/i; $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 DERIVE\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) { next if $key =~ /sfq/i; $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