summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorStephen Hemminger <stephen.hemminger@vyatta.com>2010-06-07 10:46:43 -0700
committerStephen Hemminger <stephen.hemminger@vyatta.com>2010-06-07 15:56:10 -0700
commit31a8ab66f49ad26b376d552ec468b21e15835daf (patch)
tree50a0d0eb271f1bb830668ce018c3b1d7027570b5 /scripts
parenta6fc0cd96c30422732fd4006dfed22fedc4c624d (diff)
downloadvyatta-cfg-qos-31a8ab66f49ad26b376d552ec468b21e15835daf.tar.gz
vyatta-cfg-qos-31a8ab66f49ad26b376d552ec468b21e15835daf.zip
Rearrange Qos commands for Larkspur
Current (Kenwood and earlier): set qos-policy traffic-shaper TS { ...classes } set qos-policy traffic-limiter TL { ...classes } seq qos-policy network-emulator NE ... set qos-policy random-detect RD ... set qos-policy rate-limiter RC ... set qos-policy round-robin RR ... set interfaces ethernet eth0 qos-policy out TS set interfaces ethernet eth0 qos-policy in TL New (Larkspur and later): set traffic-policy shaper TS { ...classes } set traffic-policy limiter TL { ...classes } seq traffic-policy network-emulator NE ... set traffic-policy random-detect RD ... set traffic-policy rate-control RC ... set traffic-policy round-robin RR ... set interfaces ethernet eth0 traffic-policy out TS set interfaces ethernet eth0 traffic-policy in TL set interfaces ethernet eth0 redirect ifb0 set interfaces ethernet eth0 mirror eth2 Note: 1. Only one of the following is allowed: "redirect", or "mirror" 2. Traffic-policy limiter is allowed with redirection/mirror and takes place before mirror/redirect action (NEW) 3. Limiter policy may applied on output (NEW) 4. Only limiter policies can be applied on input (same as previous releases) This does add some new functionality (#2, and #3) which are possible because of how filter classes are implemented.
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/vyatta-qos.pl213
1 files changed, 89 insertions, 124 deletions
diff --git a/scripts/vyatta-qos.pl b/scripts/vyatta-qos.pl
index 4d882aa..d901027 100755
--- a/scripts/vyatta-qos.pl
+++ b/scripts/vyatta-qos.pl
@@ -27,17 +27,17 @@ 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',
+ 'shaper' => 'TrafficShaper',
+ 'limiter' => 'TrafficLimiter',
+ 'fair-queue' => 'FairQueue',
+ 'rate-control' => 'RateLimiter',
+ 'drop-tail' => 'DropTail',
+ 'network-emulator' => 'NetworkEmulator',
+ 'round-robin' => 'RoundRobin',
'priority-queue' => 'Priority',
'random-detect' => 'RandomDetect',
- 'traffic-limiter' => 'TrafficLimiter',
},
- 'in' => {
+ 'in' => {
'traffic-limiter' => 'TrafficLimiter',
}
);
@@ -48,7 +48,7 @@ sub find_policy {
my $name = shift;
my $config = new Vyatta::Config;
- $config->setLevel('qos-policy');
+ $config->setLevel('traffic-policy');
my @policy = grep { $config->exists("$_ $name") } $config->listNodes();
die "Policy name \"$name\" conflict, used by: ", join( ' ', @policy ), "\n"
@@ -65,8 +65,7 @@ sub make_policy {
if ($direction) {
$policy_type = $policies{$direction}{$type};
- }
- else {
+ } else {
foreach my $direction ( keys %policies ) {
$policy_type = $policies{$direction}{$type};
last if defined $policy_type;
@@ -84,7 +83,7 @@ sub make_policy {
}
my $config = new Vyatta::Config;
- $config->setLevel("qos-policy $type $name");
+ $config->setLevel("traffic-policy $type $name");
my $location = "Vyatta/Qos/$policy_type.pm";
my $class = "Vyatta::Qos::$policy_type";
@@ -97,7 +96,7 @@ sub make_policy {
## list defined qos policy names
sub list_policy {
my $config = new Vyatta::Config;
- $config->setLevel('qos-policy');
+ $config->setLevel('traffic-policy');
while ( my $direction = shift ) {
my @qos = grep { $policies{$direction}{$_} } $config->listNodes();
@@ -118,7 +117,7 @@ my %delcmd = (
## delete_interface('eth0')
# remove all filters and qdisc's
sub delete_interface {
- my ( $interface ) = @_;
+ my ( $interface, $direction ) = @_;
my $arg = $delcmd{$direction};
die "bad direction $direction\n" unless $arg;
@@ -141,36 +140,35 @@ sub start_interface {
my $config = new Vyatta::Config;
$config->setLevel( $path );
- my $policy = $config->returnValue('qos-policy');
- next unless $policy;
+ my $policy = $config->returnValue('traffic-policy');
- update_interface( $ifname, $policy );
+ update_interface( $ifname, $policy ) if ($policy);
+ update_action( $ifname );
}
}
## update_interface('eth0', 'my-shaper')
# update policy to interface
sub update_interface {
- my ( $device, $name ) = @_;
+ my ( $device, $direction, $name ) = @_;
my $policy = find_policy($name);
- die "Unknown qos-policy $name\n" unless $policy;
+ die "Unknown traffic-policy $name\n" unless $policy;
my $shaper = make_policy( $policy, $name, $direction );
exit 1 unless $shaper;
if ( ! -d "/sys/class/net/$device" ) {
- warn "$device not present yet, qos-policy will be applied later\n";
+ warn "$device not present yet, traffic-policy will be applied later\n";
return;
}
-
# Remove old policy
- delete_interface( $device );
+ delete_interface( $device, $direction );
# When doing debugging just echo the commands
my $out;
unless ($debug) {
- open $out, "|-"
+ open $out, '|-'
or exec qw:sudo /sbin/tc -batch -:
or die "Tc setup failed: $!\n";
@@ -178,12 +176,14 @@ sub update_interface {
}
$shaper->commands( $device, $direction );
+
return if ($debug);
select STDOUT;
- unless (close $out) {
+
+ unless(close($out)) {
# cleanup any partial commands
- delete_interface( $device );
+ delete_interface( $device, $direction );
# replay commands to stdout
$shaper->commands($device, $direction );
@@ -191,8 +191,7 @@ sub update_interface {
}
}
-
-# return array of references to (name, policy)
+# return array of references to (name, direction, policy)
sub interfaces_using {
my $policy = shift;
my $config = new Vyatta::Config;
@@ -201,15 +200,17 @@ sub interfaces_using {
foreach my $name ( getInterfaces() ) {
my $intf = new Vyatta::Interface($name);
next unless $intf;
- my $path = $intf->path();
- next unless $path;
-
- $config->setLevel($path);
- my $cur = $config->returnValue('qos-policy');
- next unless $cur;
-
- # these are arguments to update_interface()
- push @inuse, [ $name, $policy ] if ($cur eq $policy);
+ my $level = $intf->path() . ' traffic-policy';
+ $config->setLevel($level);
+
+ foreach my $direction ($config->listNodes()) {
+ my $cur = $config->returnValue($direction);
+ next unless $cur;
+
+ # these are arguments to update_interface()
+ push @inuse, [ $name, $direction, $policy ]
+ if ($cur eq $policy);
+ }
}
return @inuse;
}
@@ -220,7 +221,7 @@ sub delete_policy {
# interfaces_using returns array of array and only want name
my @inuse = map { @$_[0] } interfaces_using($name);
- die "Can not delete qos-policy $name, still applied"
+ die "Can not delete traffic-policy $name, still applied"
. " to interface ", join(' ', @inuse), "\n"
if @inuse;
}
@@ -251,82 +252,57 @@ sub apply_policy {
}
}
-# ingress policy factory
-sub ingress_policy {
- my ($ifname) = @_;
- my $intf = new Vyatta::Interface($ifname);
- die "Unknown interface name $ifname\n" unless $intf;
-
- my $path = $intf->path();
- unless ($path) {
- warn "Can't find $ifname in configuration\n";
- exit 0;
+#
+# This is used for actions mirror and redirect
+sub update_action {
+ while ( my $dev = shift ) {
+ apply_action($dev);
}
-
- my $config = new Vyatta::Config;
- $config->setLevel( "$path input-policy" );
-
- my @names = $config->listNodes();
- return if ($#names < 0);
-
- die "Only one incoming policy is allowed\n" if ($#names > 0);
-
- $config->setLevel( "$path input-policy " . $names[0] );
- my $type = ucfirst($names[0]);
- my $location = "Vyatta/Qos/Ingress$type.pm";
- require $location;
-
- my $class = "Vyatta::Qos::Ingress$type";
- return $class->new( $config, $ifname );
}
+
+sub apply_action{
+ my $dev = shift;
+ my $interface = new Vyatta::Interface($dev);
+ die "Unknown interface type: $dev" unless $interface;
-# check definition of input filtering
-sub check_ingress {
- my $device = shift;
-
- my $ingress = ingress_policy( $device );
- return unless $ingress;
-}
-
-# sets up input filtering
-sub update_ingress {
- my $device = shift;
-
- die "Interface $device not present\n"
- unless (-d "/sys/class/net/$device");
-
- # Drop existing ingress and recreate
- system("sudo tc qdisc del dev $device ingress 2>/dev/null");
+ my $path = $interface->path();
+ next unless $path;
- my $ingress = ingress_policy( $device );
- return unless $ingress;
-
- system("sudo tc qdisc add dev $device ingress") == 0
- or die "Can not set ingress qdisc";
-
- # When doing debugging just echo the commands
- my $out;
- unless ($debug) {
- open $out, "|-"
- or exec qw:sudo /sbin/tc -batch -:
- or die "Tc setup failed: $!\n";
-
- select $out;
+ my $config = new Vyatta::Config;
+ $config->setLevel( $path );
+
+ my $ingress = $config->returnValue('traffic-policy in');
+
+ foreach my $action (qw(mirror redirect)) {
+ my $target = $config->returnValue($action);
+ next unless $target;
+
+ # TODO support combination of limiting and redirect/mirror
+ die "interface $dev: combination of $action"
+ . " and traffic-policy $ingress not supported\n"
+ if ($ingress);
+
+ # Clear existing ingress
+ system("sudo tc qdisc del dev $dev parent ffff: 2>/dev/null");
+
+ system("sudo tc qdisc add dev $dev handle ffff: ingress") == 0
+ or die "tc qdisc ingress failed";
+
+ my $cmd =
+ "tc filter add dev $dev parent ffff:"
+ . " protocol all prio 10 u32"
+ . " match u32 0 0 flowid 1:1"
+ . " action mirred egress $action dev $target";
+
+ system($cmd) == 0
+ or die "tc action $action command failed";
+
+ return;
}
- my $parent = 0xffff;
- $ingress->commands( $device, $parent );
- return if ($debug);
-
- select STDOUT;
- unless (close $out) {
- # cleanup any partial commands
- system("sudo tc del dev $device ingress 2>/dev/null");
-
- # replay commands to stdout
- $ingress->commands($device, $parent );
- die "TC command failed.";
- }
+ # Drop what ever was there before...
+ system("sudo tc qdisc del dev $dev parent ffff: 2>/dev/null")
+ unless($ingress);
}
sub usage {
@@ -339,22 +315,13 @@ usage: vyatta-qos.pl --list-policy
vyatta-qos.pl --update-interface interface policy-name
vyatta-qos.pl --delete-interface interface
- vyatta-qos.pl --check-ingress interface
- vyatta-qos.pl --update-ingress interface
+ vyatta-qos.pl --start-interface interface
EOF
exit 1;
}
-my @updateInterface = ();
-my $deleteInterface;
-
-my $listPolicy;
-my @createPolicy = ();
-my @applyPolicy = ();
-my @deletePolicy = ();
-my @startList = ();
-
-my ($checkIngress, $updateIngress);
+my (@startList, @updateInterface, $deleteInterface, $updateAction);
+my ($listPolicy, @createPolicy, @applyPolicy, @deletePolicy);
GetOptions(
"start-interface=s" => \@startList,
@@ -366,8 +333,8 @@ GetOptions(
"create-policy=s{2}" => \@createPolicy,
"apply-policy=s" => \@applyPolicy,
- "check-ingress=s" => \$checkIngress,
- "update-ingress=s" => \$updateIngress
+ "update-action=s" => \$updateAction,
+
) or usage();
delete_interface($deleteInterface) if ( $deleteInterface );
@@ -379,6 +346,4 @@ create_policy(@createPolicy) if ( $#createPolicy == 1 );
delete_policy(@deletePolicy) if (@deletePolicy);
apply_policy(@applyPolicy) if (@applyPolicy);
-check_ingress($checkIngress) if ($checkIngress);
-update_ingress($updateIngress) if ($updateIngress);
-
+update_action($updateAction) if ($updateAction);