summaryrefslogtreecommitdiff
path: root/scripts/VyattaQosTrafficShaper.pm
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/VyattaQosTrafficShaper.pm')
-rw-r--r--scripts/VyattaQosTrafficShaper.pm103
1 files changed, 79 insertions, 24 deletions
diff --git a/scripts/VyattaQosTrafficShaper.pm b/scripts/VyattaQosTrafficShaper.pm
index 2d09244..361a2dd 100644
--- a/scripts/VyattaQosTrafficShaper.pm
+++ b/scripts/VyattaQosTrafficShaper.pm
@@ -11,6 +11,7 @@
my %fields = (
id => undef,
+ dsmark => undef,
_priority => undef,
_rate => undef,
_ceiling => undef,
@@ -37,10 +38,11 @@
$self->{_rate} = $config->returnValue("bandwidth");
defined $self->{_rate} or die "Bandwidth not defined for class $id\n";
- $self->{_id} = sprintf "%04x", $id;
+ $self->{id} = $id;
$self->{_priority} = $config->returnValue("priority");
$self->{_ceiling} = $config->returnValue("ceiling");
$self->{_burst} = $config->returnValue("burst");
+ $self->{dsmark} = VyattaQosUtil::getDsfield($config->returnValue("set-dscp"));
foreach my $match ($config->listNodes("match")) {
$config->setLevel("$level match $match");
@@ -71,37 +73,53 @@
return $rate;
}
- sub commands {
- my ( $self, $out, $dev, $speed ) = @_;
+ sub rateCheck {
+ my ($self, $speed) = @_;
my $rate = _getPercentRate($self->{_rate}, $speed);
my $ceil = _getPercentRate($self->{_ceiling}, $speed);
- my $id = $self->{_id};
- my $matches = $self->{_match};
- $rate <= $speed or
- die "Bandwidth for class $id ($rate) must be less than overall bandwidth ($speed)\n";
+ if ($rate > $speed) {
+ die "Bandwidth for class $self->{id} ($rate) > overall limit ($speed)\n";
+ }
# create the class
- my $cmd ="class add dev $dev parent 1:1 classid 1:$id htb rate $rate";
- if ( defined $ceil) {
-
- $ceil >= $rate or
- die "Ceiling ($ceil) must be greater than bandwith ($rate)\n";
- $cmd .= " ceil $ceil";
+ if (defined $ceil && $ceil < $rate) {
+ die "Ceiling ($ceil) must be greater than bandwith ($rate)\n";
}
+ }
- $cmd .= " burst $self->{_burst}" if ( defined $self->{_burst} );
- $cmd .= " prio $self->{_priority}" if ( defined $self->{_priority} );
+ sub htbClass {
+ my ( $self, $out, $parent, $dev, $speed ) = @_;
+ my $rate = _getPercentRate($self->{_rate}, $speed);
+ my $ceil = _getPercentRate($self->{_ceiling}, $speed);
+ my $id = sprintf "%04x", $self->{id};
+ print ${out} "class add dev $dev parent $parent:1 classid 1:$id htb rate $rate";
- print {$out} $cmd . "\n";
+ print ${out} " burst $self->{_burst}" if ( defined $self->{_burst} );
+ print ${out} " prio $self->{_priority}" if ( defined $self->{_priority} );
+ print {$out} "\n";
# create leaf qdisc
- print {$out} "qdisc add dev $dev parent 1:$id sfq\n";
+ print {$out} "qdisc add dev $dev parent $parent:$id sfq\n";
+ my $matches = $self->{_match};
foreach my $match (@$matches) {
$match->filter( $out, $dev, $id );
}
}
+
+ sub dsmarkClass {
+ my ( $self, $out, $parent, $dev ) = @_;
+ my $id = sprintf "%x", $self->{id};
+
+ print ${out} "class change dev $dev classid $parent:$id dsmark";
+ if ($self->{dsmark}) {
+ print ${out} " mask 0 value $self->{dsmark}\n";
+ } else {
+ print ${out} " mask 0xff value 0\n";
+ }
+ }
+
}
package VyattaQosTrafficShaper;
@@ -110,8 +128,6 @@ use strict;
require VyattaConfig;
use VyattaQosUtil;
-my $defaultId = 0x4000;
-
my %fields = (
_rate => undef,
_classes => undef,
@@ -158,7 +174,7 @@ sub _define {
$config->exists("default")
or die "Configuration not complete: missing default class\n";
$config->setLevel("$level default");
- push @classes, new ShaperClass( $config, $defaultId);
+ push @classes, new ShaperClass($config, -1);
$config->setLevel($level);
foreach my $id ( $config->listNodes("class") ) {
@@ -172,13 +188,52 @@ sub commands {
my ( $self, $out, $dev ) = @_;
my $rate = _getAutoRate($self->{_rate}, $dev);
my $classes = $self->{_classes};
+ my %dsmark = ();
+
+ my $maxid = 1;
+ foreach my $class (@$classes) {
+ # rate constraints
+ $class->rateCheck($rate);
+
+ # find largest class id
+ if (defined $class->{id} && $class->{id} > $maxid) {
+ $maxid = $class->{id};
+ }
+ }
+
+ # fill in id of default
+ my $default = shift @$classes;
+ $default->{id} = ++$maxid;
+ unshift @$classes, $default;
+
+ # if any dscp marking, then set up hash
+ my $usedsmark;
+ foreach my $class (@$classes) {
+ if (defined $class->{dsmark}) {
+ print "Class $class->{id} uses dsmark\n";
+ $usedsmark = 1;
+ last;
+ }
+ }
+
+ my $parent = "1";
+ my $root = "root";
+ if ($usedsmark) {
+ print {$out} "qdisc add dev $dev root handle 1: dsmark "
+ . " indicies $maxid+1 default_index $default->{id}\n";
+ foreach my $class (@$classes) {
+ $class->dsmarkClass($out, "1", $dev);
+ }
+ $parent = "4000";
+ $root = "parent 1:1"
+ }
- print {$out} "qdisc add dev $dev root handle 1: htb default "
- . sprintf("%04x",$defaultId) . "\n";
- print {$out} "class add dev $dev parent 1: classid 1:1 htb rate $rate\n";
+ print {$out} "qdisc add dev $dev $root handle $parent: htb";
+ printf {$out} " default %x\n", $default->{id};
+ print {$out} "class add dev $dev parent 1: classid $parent:1 htb rate $rate\n";
foreach my $class (@$classes) {
- $class->commands( $out, $dev, $rate );
+ $class->htbClass($out, $parent, $dev, $rate);
}
}