summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Hemminger <stephen.hemminger@vyatta.com>2010-03-29 13:51:38 -0700
committerStephen Hemminger <stephen.hemminger@vyatta.com>2010-03-29 13:56:26 -0700
commitc8f2c288665143e2b165b7d448555af9d657b56c (patch)
tree70d6e77e7a43379029e208e559f15614235efa55
parent0c166d59d9adc0d73bf91f1f9f9b025c09d4948b (diff)
downloadvyatta-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.pm11
-rwxr-xr-xscripts/vyatta-qos.pl89
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.