diff options
author | Stephen Hemminger <stephen.hemminger@vyatta.com> | 2010-03-29 13:51:38 -0700 |
---|---|---|
committer | Stephen Hemminger <stephen.hemminger@vyatta.com> | 2010-03-29 13:56:26 -0700 |
commit | c8f2c288665143e2b165b7d448555af9d657b56c (patch) | |
tree | 70d6e77e7a43379029e208e559f15614235efa55 | |
parent | 0c166d59d9adc0d73bf91f1f9f9b025c09d4948b (diff) | |
download | vyatta-cfg-qos-c8f2c288665143e2b165b7d448555af9d657b56c.tar.gz vyatta-cfg-qos-c8f2c288665143e2b165b7d448555af9d657b56c.zip |
Allow any Qos policy to be used for input
Bug 5123
Add ability to use traffic-shaper and other policies
for input traffic.
-rw-r--r-- | lib/Vyatta/Qos/TrafficLimiter.pm | 11 | ||||
-rwxr-xr-x | scripts/vyatta-qos.pl | 89 |
2 files changed, 51 insertions, 49 deletions
diff --git a/lib/Vyatta/Qos/TrafficLimiter.pm b/lib/Vyatta/Qos/TrafficLimiter.pm index ff4a8d2..1ac61b2 100644 --- a/lib/Vyatta/Qos/TrafficLimiter.pm +++ b/lib/Vyatta/Qos/TrafficLimiter.pm @@ -76,17 +76,8 @@ sub _define { } sub commands { - my ( $self, $dev, $direction ) = @_; + my ( $self, $dev, $parent ) = @_; 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 c962324..e5ea69a 100755 --- a/scripts/vyatta-qos.pl +++ b/scripts/vyatta-qos.pl @@ -26,20 +26,15 @@ use Getopt::Long; my $debug = $ENV{'QOS_DEBUG'}; my %policies = ( - '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', - } + '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', ); # find policy for name - also check for duplicates @@ -60,28 +55,13 @@ sub find_policy { # class factory for policies ## make_policy('traffic-shaper', 'limited', 'out') sub make_policy { - my ( $type, $name, $direction ) = @_; + my ( $type, $name ) = @_; my $policy_type; - if ($direction) { - $policy_type = $policies{$direction}{$type}; - } - else { - foreach my $direction ( keys %policies ) { - $policy_type = $policies{$direction}{$type}; - last if defined $policy_type; - } - } + $policy_type = $policies{$type}; # This means template exists but we don't know what it is. - 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"; - } + return unless ($policy_type); my $config = new Vyatta::Config; $config->setLevel("qos-policy $type $name"); @@ -91,7 +71,7 @@ sub make_policy { require $location; - return $class->new( $config, $name, $direction ); + return $class->new( $config, $name ); } ## list defined qos policy names for a direction @@ -100,7 +80,7 @@ sub list_policy { $config->setLevel('qos-policy'); while ( my $direction = shift ) { - my @qos = grep { $policies{$direction}{$_} } $config->listNodes(); + my @qos = grep { $policies{$_} } $config->listNodes(); my @names = (); foreach my $type (@qos) { my @n = $config->listNodes($type); @@ -127,6 +107,12 @@ sub delete_interface { # ignore errors (may have no qdisc) system($cmd); + + # remove IFB device if any + if ($direction eq 'in') { + $cmd = "sudo ip link delete dev $interface-in"; + system ($cmd); + } } ## start_interface('ppp0') @@ -155,7 +141,7 @@ sub update_interface { my $policy = find_policy($name); die "Unknown qos-policy $name\n" unless $policy; - my $shaper = make_policy( $policy, $name, $direction ); + my $shaper = make_policy( $policy, $name ); exit 1 unless $shaper; if ( ! -d "/sys/class/net/$device" ) { @@ -163,7 +149,6 @@ sub update_interface { return; } - # Remove old policy delete_interface( $device, $direction ); @@ -177,7 +162,33 @@ sub update_interface { select $out; } - $shaper->commands( $device, $direction ); + my $parent = 1; + # Special case for traffic-limiter (not a real qdisc) + if ($policy eq 'traffic-limiter') { + if ($direction eq 'in') { + $parent = 0xffff; + print "qdisc add dev $device ingress\n"; + } else { + print "qdisc add dev $device handle 1: prio\n"; + } + } + + # For non-ingress Qos use ifb device + elsif ($direction eq 'in') { + my $ifb = $device . "-in"; + system("sudo ip link add dev $ifb type ifb") == 0 + or die "Can't create $ifb: $!"; + + system("sudo ip link set dev $ifb up") + or die "Can't bring $ifb up: $!"; + + print "qdisc add dev $device ingress\n"; + print "filter add dev $device parent ffff: protocol all prio 10"; + print " action mirred egress redirect dev $ifb\n"; + $device = $ifb; + } + + $shaper->commands( $device, $parent ); return if ($debug); select STDOUT; @@ -186,7 +197,7 @@ sub update_interface { delete_interface( $device, $direction ); # replay commands to stdout - $shaper->commands($device, $direction ); + $shaper->commands($device, $parent ); die "TC command failed."; } } @@ -234,7 +245,7 @@ sub create_policy { # Check policy for validity my $shaper = make_policy( $policy, $name ); - exit 1 unless $shaper; + die "QoS policy $name has not been created\n" unless $shaper; } # Configuration changed, reapply to all interfaces. |