diff options
author | Stephen Hemminger <stephen.hemminger@vyatta.com> | 2010-01-12 08:00:04 -0800 |
---|---|---|
committer | Stephen Hemminger <stephen.hemminger@vyatta.com> | 2010-01-12 08:00:04 -0800 |
commit | 092a710bbe0ac05607ca9d4417b534597849aaa9 (patch) | |
tree | dce90d3674e31cd196e3f0464e9862970d64b8c0 /lib | |
parent | 1f8762b9f955bd2b4c024012df783a1d51191a86 (diff) | |
parent | 33b8a1ebeb7925890bd744d1bda5f5c6c686c537 (diff) | |
download | vyatta-cfg-qos-092a710bbe0ac05607ca9d4417b534597849aaa9.tar.gz vyatta-cfg-qos-092a710bbe0ac05607ca9d4417b534597849aaa9.zip |
Merge branch 'kenwood' of suva.vyatta.com:/git/vyatta-cfg-qos into kenwood
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Vyatta/Qos/DropTail.pm | 8 | ||||
-rw-r--r-- | lib/Vyatta/Qos/FairQueue.pm | 11 | ||||
-rw-r--r-- | lib/Vyatta/Qos/Match.pm | 66 | ||||
-rw-r--r-- | lib/Vyatta/Qos/NetworkEmulator.pm | 31 | ||||
-rw-r--r-- | lib/Vyatta/Qos/RandomDetect.pm | 97 | ||||
-rw-r--r-- | lib/Vyatta/Qos/RateLimiter.pm | 11 | ||||
-rw-r--r-- | lib/Vyatta/Qos/RoundRobin.pm | 67 | ||||
-rw-r--r-- | lib/Vyatta/Qos/ShaperClass.pm | 24 | ||||
-rw-r--r-- | lib/Vyatta/Qos/TrafficLimiter.pm | 51 | ||||
-rw-r--r-- | lib/Vyatta/Qos/TrafficShaper.pm | 72 | ||||
-rw-r--r-- | lib/Vyatta/Qos/Util.pm | 2 |
11 files changed, 123 insertions, 317 deletions
diff --git a/lib/Vyatta/Qos/DropTail.pm b/lib/Vyatta/Qos/DropTail.pm index 1b14a81..0ff15e9 100644 --- a/lib/Vyatta/Qos/DropTail.pm +++ b/lib/Vyatta/Qos/DropTail.pm @@ -47,12 +47,4 @@ sub commands { printf "%s\n", $cmd; } -sub isChanged { - my ($self, $name) = @_; - my $config = new Vyatta::Config; - - $config->setLevel("qos-policy drop-tail $name"); - return $config->isChanged('queue-limit'); -} - 1; diff --git a/lib/Vyatta/Qos/FairQueue.pm b/lib/Vyatta/Qos/FairQueue.pm index bc3a872..c74cb01 100644 --- a/lib/Vyatta/Qos/FairQueue.pm +++ b/lib/Vyatta/Qos/FairQueue.pm @@ -52,15 +52,4 @@ sub commands { print "\n"; } -sub isChanged { - my ( $self, $name ) = @_; - my $config = new Vyatta::Config; - - $config->setLevel("qos-policy fair-queue $name"); - foreach my $attr ('hash-interval', 'queue-limit') { - return $attr if ($config->isChanged($attr)); - } - return; # false -} - 1; diff --git a/lib/Vyatta/Qos/Match.pm b/lib/Vyatta/Qos/Match.pm index 8dda94d..327fbd4 100644 --- a/lib/Vyatta/Qos/Match.pm +++ b/lib/Vyatta/Qos/Match.pm @@ -63,7 +63,7 @@ sub new { } sub filter { - my ( $self, $dev, $parent, $prio, $dsmark ) = @_; + my ( $self, $dev, $parent, $classid, $prio, $dsmark, $police ) = @_; # empty match return unless %{$self}; @@ -75,10 +75,13 @@ sub filter { my $ip = $self->{$ipver}; next unless $ip && $$ip{dsfield}; - printf "filter add dev %s parent %x: protocol $ipver prio 1", - $dev, $parent; - printf " handle %d tcindex", $$ip{dsfield}; - } + printf "filter add dev %s parent %x: protocol %s prio $prio", + $dev, $parent, $ipver; + printf " handle %s tcindex classid %x:%x\n", + $$ip{dsfield}, $parent, $classid; + + $prio += 1; + } return; } @@ -87,29 +90,54 @@ sub filter { next unless $p; printf "filter add dev %s parent %x:", $dev, $parent; - printf " prio %d", $prio if ($prio); - if ($proto ne 'ether') { - print " protocol $proto u32"; - print " match $proto dsfield $$p{dsfield} 0xff" if $$p{dsfield}; - print " match $proto protocol $$p{protocol} 0xff" if $$p{protocol}; - } else { + if ($prio) { + printf " prio %d", $prio; + $prio += 1; + } + + if ($proto eq 'ether') { my $type = $$p{protocol}; $type = 'all' unless $type; - print " protocol $type u32"; + if (defined($$p{src}) || defined($$p{dest})) { + print " protocol $type u32"; + print " match ether src $$p{src}" if $$p{src}; + print " match ether dst $$p{dst}" if $$p{dst}; + } else { + # u32 requires some options to work but basic works + print " protocol $type basic"; + } + } else { + print " protocol $proto u32"; + + # workaround inconsistent usage in tc u32 match + my $sel = $proto; + if ($proto eq 'ipv6') { + $sel = 'ip6'; + printf " match u16 0x%x 0x0ff0 at 0", hex($$p{dsfield}) << 4, + if $$p{dsfield}; + } else { + print " match $sel dsfield $$p{dsfield} 0xff" if $$p{dsfield}; + } + print " match $sel protocol $$p{protocol} 0xff" if $$p{protocol}; + + print " match $sel src $$p{src}" if $$p{src}; + print " match $sel sport $$p{sport} 0xffff" if $$p{sport}; + print " match $sel dst $$p{dst}" if $$p{dst}; + print " match $sel dport $$p{dport} 0xffff" if $$p{dport}; } - print " match $proto src $$p{src}" if $$p{src}; - print " match $proto sport $$p{sport} 0xffff" if $$p{sport}; - print " match $proto dst $$p{dst}" if $$p{dst}; - print " match $proto dport $$p{dport} 0xffff" if $$p{dport}; + print " $police" if $police; + printf " flowid %x:%x\n", $parent, $classid; } - my $indev = $self->{indev}; - my $vif = $self->{vif}; - if ( $vif || $indev ) { + my $indev = $self->{_indev}; + my $vif = $self->{_vif}; + if ( defined($vif) || defined($indev) ) { printf "filter add dev %s parent %x: prio %d", $dev, $parent, $prio; print " protocol all basic"; print " match meta\(rt_iif eq $indev\)" if $indev; print " match meta\(vlan mask 0xfff eq $vif\)" if $vif; + print " $police" if $police; + printf " flowid %x:%x\n", $parent, $classid; } } diff --git a/lib/Vyatta/Qos/NetworkEmulator.pm b/lib/Vyatta/Qos/NetworkEmulator.pm index 2a87407..602393c 100644 --- a/lib/Vyatta/Qos/NetworkEmulator.pm +++ b/lib/Vyatta/Qos/NetworkEmulator.pm @@ -46,23 +46,28 @@ sub new { sub commands { my ( $self, $dev ) = @_; my $rate = $self->{_rate}; + my $limit = $self->{_limit}; + my $delay = $self->{_delay}; if ($rate) { my $burst = $self->{_burst}; $burst or $burst = "15K"; - printf "qdisc add dev %s root handle 1:0 tbf rate %s burst %s\n", + printf "qdisc add dev %s root handle 1:0 tbf rate %s burst %s", $dev, $rate, $burst; - printf "qdisc add dev %s parent 1:1 handle 10: netem", $dev; + if ($limit) { + print " limit $limit"; + } elsif ($delay) { + print " latency $delay"; + } else { + print " latency 50ms"; + } + printf "\nqdisc add dev %s parent 1:1 handle 10: netem", $dev; } else { printf "qdisc add dev %s root netem", $dev; } - - my $delay = $self->{_delay}; - print " delay $delay" if ($delay); - - my $limit = $self->{_limit}; print " limit $limit" if ($limit); + print " delay $delay" if ($delay); my $drop = $self->{_drop}; print " drop $drop" if ($drop); @@ -76,16 +81,4 @@ sub commands { print "\n"; } -sub isChanged { - my ( $self, $name ) = @_; - my $config = new Vyatta::Config; - - $config->setLevel("qos-policy network-emulator $name"); - foreach my $attr ( "bandwidth", "burst", "queue-limit", "network-delay", - "packet-loss", "packet-corruption", "packet-reordering", ) { - return $attr if ( $config->isChanged($attr) ); - } - return; -} - 1; diff --git a/lib/Vyatta/Qos/RandomDetect.pm b/lib/Vyatta/Qos/RandomDetect.pm index 1918711..e7f16f3 100644 --- a/lib/Vyatta/Qos/RandomDetect.pm +++ b/lib/Vyatta/Qos/RandomDetect.pm @@ -29,18 +29,6 @@ use warnings; require Vyatta::Config; use Vyatta::Qos::Util qw/getRate getAutoRate getTime/; -# default values for different precedence levels -my @default_fields = ( - { 'min-threshold' => 9, 'max-threshold' => 18, 'mark-probability' => 1/2 }, - { 'min-threshold' => 10, 'max-threshold' => 18, 'mark-probability' => 5/9 }, - { 'min-threshold' => 11, 'max-threshold' => 18, 'mark-probability' => .1 }, - { 'min-threshold' => 12, 'max-threshold' => 18, 'mark-probability' => 2/3 }, - { 'min-threshold' => 13, 'max-threshold' => 18, 'mark-probability' => .1 }, - { 'min-threshold' => 14, 'max-threshold' => 18, 'mark-probability' => 7/9 }, - { 'min-threshold' => 15, 'max-threshold' => 18, 'mark-probability' => 5/6 }, - { 'min-threshold' => 16, 'max-threshold' => 18, 'mark-probability' => 8/9 }, -); - # Create a new instance based on config information sub new { my ( $that, $config, $name ) = @_; @@ -66,22 +54,37 @@ sub getPrecedence { my @precedence; for ( my $i = 0 ; $i <= 7 ; $i++ ) { - my $defaults = $default_fields[$i]; - my %param; - + my %pred; + $config->setLevel("$level precedence $i"); - foreach my $field (keys %$defaults) { - my $val = $config->returnValue($field); - - if ( !defined $val ) { - $param{$field} = $defaults->{$field}; - } elsif ( $field eq 'mark-probability' ) { - $param{$field} = 1 / $val; - } else { - $param{$field} = $val; - } - } - $precedence[$i] = \%param; + + # Compute some sane defaults based on predence and max-threshold + $pred{qmax} = $config->returnValue('maximum-threshold'); + $pred{qmax} = 18 unless $pred{qmax}; + + $pred{qmin} = $config->returnValue('minimum-threshold'); + if ($pred{qmin}) { + die "min-threshold: $pred{qmin} >= max-threshold: $pred{qmax}\n" + if ($pred{qmin} >= $pred{qmax}); + } else { + $pred{qmin} = ((9 + $i) * $pred{qmax})/ 18; + } + + $pred{qlim} = $config->returnValue('queue-limit'); + if ($pred{qlim}) { + die "queue-limit: $pred{qlim} < max-threshold: $pred{qmax}\n" + if ($pred{qlim} < $pred{qmax}); + } else { + $pred{qlim} = 4 * $pred{qmax}; + } + + my $mp = $config->returnValue('mark-probablilty'); + $pred{prob} = (defined $mp) ? (1 / $mp) : (1 / 10); + + my $avgpkt = $config->returnValue('average-packet'); + $pred{avpkt} = (defined $avgpkt) ? $avgpkt : 1024; + + $precedence[$i] = \%pred; } return @precedence; @@ -98,7 +101,7 @@ sub commands { $dev, $root; # 2. use tcindex filter to convert tc_index to precedence - # + # # Precedence Field: the three leftmost bits in the TOS octet of an IPv4 # header. @@ -113,40 +116,18 @@ sub commands { # set VQ parameters for ( my $i = 0 ; $i <= 7 ; $i++ ) { - my $param = $precedence->[$i]; - my $qmin = $param->{'min-threshold'}; - my $qmax = $param->{'max-threshold'}; - my $prob = $param->{'mark-probability'}; + my $pred = $precedence->[$i]; + my $avg = $pred->{avpkt}; + my $burst = ( 2 * $pred->{qmin} + $pred->{qmax} ) / 3; printf "qdisc change dev %s handle %x:0 gred", $dev, $root+1, $i; - printf " limit %dK min %dK max %dK avpkt 1K", 4 * $qmax, $qmin, $qmax; - printf " burst %d bandwidth %d probability %f DP %d prio %d\n", - ( 2 * $qmin + $qmax ) / 3, $rate, $prob, $i, 8-$i; - } -} + printf " limit %d min %d max %d avpkt %d", + $pred->{qlim} * $avg, $pred->{qmin} * $avg, + $pred->{qmax} * $avg, $avg; -# Walk configuration tree and look for changed nodes -# The configuration system should do this but doesn't do it right -sub isChanged { - my ( $self, $name ) = @_; - my $config = new Vyatta::Config; - - $config->setLevel("qos-policy random-detect $name"); - - return 'bandwidth' if ( $config->isChanged('bandwidth') ); - - my %precedenceNodes = $config->listNodeStatus('precedence'); - while ( my ( $pred, $status ) = each %precedenceNodes ) { - return "precedence $pred" if ( $status ne 'static' ); - - my $defaults = $default_fields[0]; - foreach my $attr (keys %$defaults) { - return "precedence $pred $attr" - if ( $config->isChanged("precedence $pred $attr") ); - } + printf " burst %d bandwidth %d probability %f DP %d prio %d\n", + $burst, $rate, $pred->{prob}, $i, 8-$i; } - - return; # false } 1; diff --git a/lib/Vyatta/Qos/RateLimiter.pm b/lib/Vyatta/Qos/RateLimiter.pm index c20646e..ac0cd2c 100644 --- a/lib/Vyatta/Qos/RateLimiter.pm +++ b/lib/Vyatta/Qos/RateLimiter.pm @@ -55,15 +55,4 @@ sub commands { $dev, $self->{_rate}, $self->{_latency}, $self->{_burst}; } -sub isChanged { - my ($self, $name) = @_; - my $config = new Vyatta::Config; - - $config->setLevel("qos-policy rate-limit $name"); - foreach my $attr ('bandwidth', 'burst', 'latency') { - return $attr if ($config->isChanged($attr)); - } - return; # false -} - 1; diff --git a/lib/Vyatta/Qos/RoundRobin.pm b/lib/Vyatta/Qos/RoundRobin.pm index 83a41b7..a1d7787 100644 --- a/lib/Vyatta/Qos/RoundRobin.pm +++ b/lib/Vyatta/Qos/RoundRobin.pm @@ -41,16 +41,9 @@ sub _getClasses { my @classes; my $config = new Vyatta::Config; - $config->setLevel($level); - my $default; - if ( $config->exists("default") ) { - $config->setLevel("$level default"); - $default = new Vyatta::Qos::ShaperClass($config); - $config->setLevel($level); - } - else { - $default = new Vyatta::Qos::ShaperClass; - } + $config->setLevel("$level default"); + my $default = new Vyatta::Qos::ShaperClass($config); + push @classes, $default; $default->{id} = 1; @@ -75,61 +68,9 @@ sub commands { $class->gen_class( $dev, 'drr', $parent ); $class->gen_leaf( $dev, $parent ); foreach my $match ( $class->matchRules() ) { - $match->filter( $dev, $parent, 1 ); - printf " classid %x:%x\n", $parent, $class->{id}; - } - } -} - -# Walk configuration tree and look for changed nodes -# The configuration system should do this but doesn't do it right -sub isChanged { - my ( $self, $name ) = @_; - my $config = new Vyatta::Config; - - $config->setLevel("qos-policy round-robin $name"); - - return 'quantum' if ( $config->isChanged('quantum') ); - - foreach my $attr (qw(queue-limit queue-type)) { - return "default $attr" if ( $config->isChanged("default $attr") ); - } - - my %classNodes = $config->listNodeStatus('class'); - while ( my ( $class, $status ) = each %classNodes ) { - return "class $class" if ( $status ne 'static' ); - - foreach my $attr (qw(queue-limit queue-type)) { - return "class $class $attr" - if ( $config->isChanged("class $class $attr") ); - } - - my %matchNodes = $config->listNodeStatus("class $class match"); - while ( my ( $match, $status ) = each %matchNodes ) { - my $level = "class $class match $match"; - if ( $status ne 'static' ) { - return $level; - } - - foreach my $parm ( - ( - 'vif', - 'interface', - 'ip protocol', - 'ip source address', - 'ip destination address', - 'ip source port', - 'ip destination port' - ) - ) - { - return "$level $parm" - if ( $config->isChanged("$level $parm") ); - } + $match->filter( $dev, $parent, $class->{id}, 1); } } - - return; # false } 1; diff --git a/lib/Vyatta/Qos/ShaperClass.pm b/lib/Vyatta/Qos/ShaperClass.pm index 3a25233..361eb57 100644 --- a/lib/Vyatta/Qos/ShaperClass.pm +++ b/lib/Vyatta/Qos/ShaperClass.pm @@ -168,18 +168,12 @@ sub fifoQdisc { # sub redQdisc { my ( $self, $dev, $rate ) = @_; - my $qmax = ( $rate * 100 ) / 8000; - my $qmin = $qmax / 3; my $avg = 1024; - my $burst = ( 2 * $qmin + $qmax ) / (3*$avg); - + my $qmax = (defined $rate) ? (( $rate * 100 ) / 8000) : (18 * $avg); + my $qmin = $qmax / 3; + my $burst = ( 2 * $qmin + $qmax ) / (3 * $avg); my $limit = $self->{_limit}; - my $qlimit; - if ($limit) { - $qlimit = $limit * $avg; - } else { - $qlimit = 4 * $qmax; - } + my $qlimit = (defined $limit) ? ($limit * $avg) : (4 * $qmax); printf "red limit %d min %d max %d avpkt %d", $qlimit, $qmin, $qmax, $avg; printf " burst %d probability 0.1 bandwidth %s ecn\n", $burst, $rate; @@ -215,11 +209,15 @@ sub gen_class { sub gen_leaf { my ( $self, $dev, $parent, $rate ) = @_; + my $qtype = $self->{_qdisc}; + return unless $qtype; # default is okay - printf "qdisc add dev %s parent %x:%x ", $dev, $parent, $self->{id}; + my $q = $qdiscOptions{$qtype}; + die "Unknown queue-type $qtype\n" + unless $q; - my $q = $qdiscOptions{ $self->{_qdisc} }; - $q->( $self, $dev, $rate ) if ($q); + printf "qdisc add dev %s parent %x:%x ", $dev, $parent, $self->{id}; + $q->( $self, $dev, $rate ); } sub dsmarkClass { diff --git a/lib/Vyatta/Qos/TrafficLimiter.pm b/lib/Vyatta/Qos/TrafficLimiter.pm index fd3460c..e5731d0 100644 --- a/lib/Vyatta/Qos/TrafficLimiter.pm +++ b/lib/Vyatta/Qos/TrafficLimiter.pm @@ -83,56 +83,13 @@ sub commands { printf "qdisc add dev %s handle %x: ingress\n", $dev, $parent; foreach my $class (@$classes) { foreach my $match ( $class->matchRules() ) { - $match->filter( $dev, $parent, $class->{priority} ); - printf " police rate %s burst %s drop flowid :%x\n", - $class->{rate}, $class->{burst}, $class->{id}; - } - } -} - -# Walk configuration tree and look for changed nodes -# The configuration system should do this but doesn't do it right -sub isChanged { - my ( $self, $name ) = @_; - my $config = new Vyatta::Config; + my $police = " police rate " . $class->{rate} + . " burst " . $class->{burst}; - $config->setLevel("qos-policy traffic-limiter $name"); - my %classNodes = $config->listNodeStatus('class'); - while ( my ( $class, $status ) = each %classNodes ) { - if ( $status ne 'static' ) { - return "class $class"; - } - - foreach my $attr ( 'bandwidth', 'burst', 'priority' ) { - if ( $config->isChanged("class $class $attr") ) { - return "class $class $attr"; - } - } - - my %matchNodes = $config->listNodeStatus("class $class match"); - while ( my ( $match, $status ) = each %matchNodes ) { - my $level = "class $class match $match"; - if ( $status ne 'static' ) { - return $level; - } - - foreach my $parm ( - 'vif', - 'interface', - 'ip dscp', - 'ip protocol', - 'ip source address', - 'ip destination address', - 'ip source port', - 'ip destination port' - ) - { - return "$level $parm" if ( $config->isChanged("$level $parm") ); - } + $match->filter( $dev, $parent, $class->{id}, $class->{priority}, + undef, $police ); } } - - return; # false } 1; diff --git a/lib/Vyatta/Qos/TrafficShaper.pm b/lib/Vyatta/Qos/TrafficShaper.pm index c808c7d..f89ae60 100644 --- a/lib/Vyatta/Qos/TrafficShaper.pm +++ b/lib/Vyatta/Qos/TrafficShaper.pm @@ -72,8 +72,10 @@ sub _checkClasses { my $rate = shift; my $default = shift; - # if auto, can't check at create must wait for policy to be applied + # if auto, can't check for constraints until later $rate = ( $rate eq "auto") ? undef : getRate($rate); + die "Bandwidth not defined for default traffic\n" + unless $default->{_rate}; $default->rateCheck( $rate, "$level default" ) if $rate; foreach my $class (@_) { @@ -132,8 +134,7 @@ sub commands { foreach my $class (@$classes) { $class->dsmarkClass( 1, $dev ); foreach my $match ( $class->matchRules() ) { - $match->filter( $dev, 1, 1 ); - printf " classid %x:%x\n", $parent, $class->{id}; + $match->filter( $dev, $parent, $class->{id}, 1 ); } } @@ -151,72 +152,9 @@ sub commands { $class->gen_leaf( $dev, $parent, $rate ); foreach my $match ( $class->matchRules() ) { - $match->filter( $dev, $parent, 1, $class->{dsmark} ); - printf " classid %x:%x\n", $parent, $class->{id}; + $match->filter( $dev, $parent, $class->{id}, 1, $class->{dsmark} ); } } } -# Walk configuration tree and look for changed nodes -# The configuration system should do this but doesn't do it right -sub isChanged { - my ( $self, $name ) = @_; - my $config = new Vyatta::Config; - my @attributes = qw(bandwidth burst ceiling priority queue-limit queue-type); - - $config->setLevel("qos-policy traffic-shaper $name"); - - if ( $config->isChanged('bandwidth') ) { - return 'bandwidth'; - } - - foreach my $attr (@attributes) { - if ( $config->isChanged("default $attr") ) { - return "default $attr"; - } - } - - my %classNodes = $config->listNodeStatus('class'); - while ( my ( $class, $status ) = each %classNodes ) { - if ( $status ne 'static' ) { - return "class $class"; - } - - foreach my $attr (@attributes) { - if ( $config->isChanged("class $class $attr") ) { - return "class $class $attr"; - } - } - - my %matchNodes = $config->listNodeStatus("class $class match"); - while ( my ( $match, $status ) = each %matchNodes ) { - my $level = "class $class match $match"; - if ( $status ne 'static' ) { - return $level; - } - - foreach my $parm ( - 'vif', - 'ether destination', - 'ether source', - 'ether protocol', - 'interface', - 'ip dscp', - 'ip protocol', - 'ip source address', - 'ip destination address', - 'ip source port', - 'ip destination port' - ) - { - if ( $config->isChanged("$level $parm") ) { - return "$level $parm"; - } - } - } - } - - return; # false -} - 1; diff --git a/lib/Vyatta/Qos/Util.pm b/lib/Vyatta/Qos/Util.pm index 242e2b4..9686120 100644 --- a/lib/Vyatta/Qos/Util.pm +++ b/lib/Vyatta/Qos/Util.pm @@ -300,7 +300,7 @@ sub ethtoolRate { # Get rate of real device (ignore vlan) $dev =~ s/\.[0-9]+$//; - open( my $ethtool, "/usr/sbin/ethtool $dev 2>/dev/null |" ) + open( my $ethtool, "sudo /usr/sbin/ethtool $dev 2>/dev/null |" ) or die "ethtool failed: $!\n"; # ethtool produces: |