diff options
-rw-r--r-- | lib/Vyatta/Qos/TrafficLimiter.pm | 11 | ||||
-rwxr-xr-x | scripts/vyatta-qos.pl | 80 |
2 files changed, 66 insertions, 25 deletions
diff --git a/lib/Vyatta/Qos/TrafficLimiter.pm b/lib/Vyatta/Qos/TrafficLimiter.pm index 246d593..2d973c5 100644 --- a/lib/Vyatta/Qos/TrafficLimiter.pm +++ b/lib/Vyatta/Qos/TrafficLimiter.pm @@ -76,8 +76,17 @@ sub _define { } sub commands { - my ( $self, $dev, $parent ) = @_; + my ( $self, $dev, $direction ) = @_; my $classes = $self->{_classes}; + my $parent; + + if ($direction eq 'in') { + $parent = 0xffff; + printf "qdisc add dev %s handle %x: ingress\n", $dev, $parent; + } else { + $parent = 1; + printf "qdisc add dev %s handle $x: prio\n", $dev, $parent; + } foreach my $class (@$classes) { foreach my $match ( $class->matchRules() ) { diff --git a/scripts/vyatta-qos.pl b/scripts/vyatta-qos.pl index e552497..4d882aa 100755 --- a/scripts/vyatta-qos.pl +++ b/scripts/vyatta-qos.pl @@ -26,14 +26,20 @@ use Getopt::Long; my $debug = $ENV{'QOS_DEBUG'}; my %policies = ( - 'traffic-shaper' => 'TrafficShaper', - 'fair-queue' => 'FairQueue', - 'rate-control' => 'RateLimiter', - 'drop-tail' => 'DropTail', - 'network-emulator' => 'NetworkEmulator', - 'round-robin' => 'RoundRobin', - 'priority-queue' => 'Priority', - 'random-detect' => 'RandomDetect', + 'out' => { + 'traffic-shaper' => 'TrafficShaper', + 'fair-queue' => 'FairQueue', + 'rate-limit' => 'RateLimiter', + 'drop-tail' => 'DropTail', + 'network-emulator' => 'NetworkEmulator', + 'round-robin' => 'RoundRobin', + 'priority-queue' => 'Priority', + 'random-detect' => 'RandomDetect', + 'traffic-limiter' => 'TrafficLimiter', + }, + 'in' => { + 'traffic-limiter' => 'TrafficLimiter', + } ); # find policy for name - also check for duplicates @@ -54,13 +60,28 @@ sub find_policy { # class factory for policies ## make_policy('traffic-shaper', 'limited', 'out') sub make_policy { - my ( $type, $name ) = @_; + my ( $type, $name, $direction ) = @_; my $policy_type; - $policy_type = $policies{$type}; + if ($direction) { + $policy_type = $policies{$direction}{$type}; + } + else { + foreach my $direction ( keys %policies ) { + $policy_type = $policies{$direction}{$type}; + last if defined $policy_type; + } + } # This means template exists but we don't know what it is. - return unless ($policy_type); + unless ($policy_type) { + foreach my $direction ( keys %policies ) { + die +"QoS policy $name is type $type and is only valid for $direction\n" + if $policies{$direction}{$type}; + } + die "QoS policy $name has not been created\n"; + } my $config = new Vyatta::Config; $config->setLevel("qos-policy $type $name"); @@ -70,7 +91,7 @@ sub make_policy { require $location; - return $class->new( $config, $name ); + return $class->new( $config, $name, $direction ); } ## list defined qos policy names @@ -78,23 +99,34 @@ sub list_policy { my $config = new Vyatta::Config; $config->setLevel('qos-policy'); - # list all nodes under qos-policy and match those we know about - my @qos = grep { $policies{$_} } $config->listNodes(); - - my @names = (); - foreach my $type (@qos) { + while ( my $direction = shift ) { + my @qos = grep { $policies{$direction}{$_} } $config->listNodes(); + my @names = (); + foreach my $type (@qos) { my @n = $config->listNodes($type); push @names, @n; + } + print join( ' ', @names ), "\n"; } - print join( ' ', sort ( @names )), "\n"; } +my %delcmd = ( + 'out' => 'root', + 'in' => 'parent ffff:', +); + ## delete_interface('eth0') # remove all filters and qdisc's sub delete_interface { my ( $interface ) = @_; + my $arg = $delcmd{$direction}; + + die "bad direction $direction\n" unless $arg; + + my $cmd = "sudo tc qdisc del dev $interface ". $arg . " 2>/dev/null"; - system("sudo tc qdisc del dev $interface root 2>/dev/null"); + # ignore errors (may have no qdisc) + system($cmd); } ## start_interface('ppp0') @@ -123,7 +155,7 @@ sub update_interface { my $policy = find_policy($name); die "Unknown qos-policy $name\n" unless $policy; - my $shaper = make_policy( $policy, $name ); + my $shaper = make_policy( $policy, $name, $direction ); exit 1 unless $shaper; if ( ! -d "/sys/class/net/$device" ) { @@ -131,6 +163,7 @@ sub update_interface { return; } + # Remove old policy delete_interface( $device ); @@ -144,8 +177,7 @@ sub update_interface { select $out; } - my $parent = 1; - $shaper->commands( $device, $parent ); + $shaper->commands( $device, $direction ); return if ($debug); select STDOUT; @@ -154,7 +186,7 @@ sub update_interface { delete_interface( $device ); # replay commands to stdout - $shaper->commands($device, $parent ); + $shaper->commands($device, $direction ); die "TC command failed."; } } @@ -200,7 +232,7 @@ sub create_policy { # Check policy for validity my $shaper = make_policy( $policy, $name ); - die "QoS policy $name has not been created\n" unless $shaper; + exit 1 unless $shaper; } # Configuration changed, reapply to all interfaces. |