diff options
Diffstat (limited to 'scripts')
| -rwxr-xr-x | scripts/vyatta-qos.pl | 89 | 
1 files changed, 50 insertions, 39 deletions
| 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. | 
