summaryrefslogtreecommitdiff
path: root/lib/Vyatta/Qos
diff options
context:
space:
mode:
authorStephen Hemminger <stephen.hemminger@vyatta.com>2010-12-07 17:20:43 -0800
committerStephen Hemminger <stephen.hemminger@vyatta.com>2010-12-08 12:31:19 -0800
commit110ffa598bd6ab3f4b91ddfa47f5f7528c35dee3 (patch)
treedd48a0c7073401c5073c52a0423b04b1dbe86258 /lib/Vyatta/Qos
parentded8a3bf9547df82b2f6b17ad39f269738c0e7c4 (diff)
downloadvyatta-cfg-qos-110ffa598bd6ab3f4b91ddfa47f5f7528c35dee3.tar.gz
vyatta-cfg-qos-110ffa598bd6ab3f4b91ddfa47f5f7528c35dee3.zip
Compute optimium rate to quantum value
Bug 6092 The code now calculates r2q value based on max rate and min rate which gives better accuracy and stops kernel message.
Diffstat (limited to 'lib/Vyatta/Qos')
-rw-r--r--lib/Vyatta/Qos/ShaperClass.pm15
-rw-r--r--lib/Vyatta/Qos/TrafficShaper.pm57
2 files changed, 67 insertions, 5 deletions
diff --git a/lib/Vyatta/Qos/ShaperClass.pm b/lib/Vyatta/Qos/ShaperClass.pm
index cc42f44..4afd90c 100644
--- a/lib/Vyatta/Qos/ShaperClass.pm
+++ b/lib/Vyatta/Qos/ShaperClass.pm
@@ -26,6 +26,8 @@ use Vyatta::Qos::Util qw/getDsfield getRate/;
use constant {
AVGPKT => 1024, # Average packet size for RED calculations
LATENCY => 250, # Worstcase latency for RED (ms)
+
+ MINQUANTUM => 1000, # Lowest allowable HTB quantum
};
sub new {
@@ -247,18 +249,27 @@ sub get_rate {
}
sub gen_class {
- my ( $self, $dev, $qdisc, $parent, $speed ) = @_;
+ my ( $self, $dev, $qdisc, $parent, $speed, $r2q ) = @_;
my $rate = _getPercentRate( $self->{_rate}, $speed );
my $ceil = _getPercentRate( $self->{_ceiling}, $speed );
+ my $quantum = $self->{_quantum};
+
+ # Hack to avoid kernel HTB message if quantum is small.
+ # Only occurs if link speed is high and offered bandwidth is small.
+ if ( defined($r2q) && !defined($quantum) && ($rate / 8) / $r2q < MINQUANTUM ) {
+ $quantum = MINQUANTUM;
+ }
printf "class add dev %s parent %x:1 classid %x:%x %s",
$dev, $parent, $parent, $self->{id}, $qdisc;
print " rate $rate" if ($rate);
print " ceil $ceil" if ($ceil);
+ print " quantum $quantum" if ($quantum);
print " burst $self->{_burst}" if ( $self->{_burst} );
print " prio $self->{_priority}" if ( $self->{_priority} );
- print " quantum $self->{_quantum}" if ( $self->{_quantum} );
+
+
print "\n";
}
diff --git a/lib/Vyatta/Qos/TrafficShaper.pm b/lib/Vyatta/Qos/TrafficShaper.pm
index 4d43c4e..3fd687a 100644
--- a/lib/Vyatta/Qos/TrafficShaper.pm
+++ b/lib/Vyatta/Qos/TrafficShaper.pm
@@ -25,6 +25,14 @@ use warnings;
require Vyatta::Config;
require Vyatta::Qos::ShaperClass;
use Vyatta::Qos::Util qw/getRate getAutoRate/;
+use POSIX;
+
+# Kernel limits on quantum (bytes)
+use constant {
+ MAXQUANTUM => 200000,
+ MINQUANTUM => 1000,
+};
+
# Create a new instance based on config information
sub new {
@@ -84,6 +92,47 @@ sub _checkClasses {
}
}
+sub _minRate {
+ my ($speed, $classes) = @_;
+ my $min = $speed / 8;
+
+ foreach my $class (@$classes) {
+ my $bps = $class->get_rate($speed) / 8; # bytes per second
+
+ $min = $bps if $bps < $min;
+ }
+
+ return $min;
+}
+
+# Compute optimum quantum scaling factor
+# quantum = Bps / r2q
+# and find r2q valute such that (1000 < quantum < 200000 )
+sub _r2q {
+ my ($speed, $classes) = @_;
+ my $maxbps = $speed / 8;
+ my $r2q = 10;
+
+ # need a bigger r2q if going fast than 16 mbits/sec
+ if ($maxbps / $r2q >= MAXQUANTUM) {
+ $r2q = ceil($maxbps / MAXQUANTUM);
+ } else {
+ # if there is a slow class then may need smaller value
+ my $minbps = _minRate($speed, $classes);
+
+ # try and find "just right value"
+ while ($r2q > 1 && ($minbps / $r2q) < MINQUANTUM) {
+ my $next = $r2q - 1;
+
+ # don't go too small
+ last if ($maxbps / $next >= MAXQUANTUM);
+ $r2q = $next;
+ }
+ }
+
+ return $r2q;
+}
+
sub commands {
my ( $self, $dev ) = @_;
my $rate = getAutoRate( $self->{_rate}, $dev );
@@ -142,13 +191,15 @@ sub commands {
$root = "parent 1:1";
}
- printf "qdisc add dev %s %s handle %x: htb default %x\n",
- $dev, $root, $parent, $default->{id};
+ my $r2q = _r2q($rate, $classes);
+
+ printf "qdisc add dev %s %s handle %x: htb r2q %d default %x\n",
+ $dev, $root, $parent, $r2q, $default->{id};
printf "class add dev %s parent %x: classid %x:1 htb rate %s\n",
$dev, $parent, $parent, $rate;
foreach my $class (@$classes) {
- $class->gen_class( $dev, 'htb', $parent, $rate );
+ $class->gen_class( $dev, 'htb', $parent, $rate, $r2q );
$class->gen_leaf( $dev, $parent, $rate );
my $prio = 1;