diff options
author | Stephen Hemminger <stephen.hemminger@vyatta.com> | 2009-04-15 16:00:16 -0700 |
---|---|---|
committer | Stephen Hemminger <stephen.hemminger@vyatta.com> | 2009-04-15 16:00:16 -0700 |
commit | a6208952a366096657d15c7a955180d02c88b87d (patch) | |
tree | 202a85a9df92c74c6cde15e6343552ac83f52974 /lib/Vyatta/Qos/Match.pm | |
parent | 1943bf57c3566cfd3818e31c894590ea371a35e2 (diff) | |
download | vyatta-cfg-qos-a6208952a366096657d15c7a955180d02c88b87d.tar.gz vyatta-cfg-qos-a6208952a366096657d15c7a955180d02c88b87d.zip |
Add Qos matching based on Ethernet MAC address
Use existing u32 infrastructure to match in header
Diffstat (limited to 'lib/Vyatta/Qos/Match.pm')
-rw-r--r-- | lib/Vyatta/Qos/Match.pm | 116 |
1 files changed, 64 insertions, 52 deletions
diff --git a/lib/Vyatta/Qos/Match.pm b/lib/Vyatta/Qos/Match.pm index 765bcb8..7ac9ce9 100644 --- a/lib/Vyatta/Qos/Match.pm +++ b/lib/Vyatta/Qos/Match.pm @@ -2,12 +2,12 @@ # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 as # published by the Free Software Foundation. -# +# # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. -# +# # This code was originally developed by Vyatta, Inc. # Portions created by Vyatta are Copyright (C) 2008 Vyatta, Inc. # All Rights Reserved. @@ -22,81 +22,93 @@ use warnings; sub new { my ( $that, $config ) = @_; - my $self = { }; + my $self = {}; my $class = ref($that) || $that; bless $self, $class; - foreach my $ip (qw(ip ipv6)) { - next unless $config->exists($ip); + foreach my $proto (qw(ip ipv6 ether)) { + next unless $config->exists($proto); - foreach my $t (qw(vif dev)) { - die "can not match on $ip and $t\n" if $config->exists($t); - } + foreach my $t (qw(vif dev)) { + die "can not match on $proto and $t\n" if $config->exists($t); + } + + my %fields; - # TODO make this data driven? - my %fields; - $fields{dsfield} = getDsfield( $config->returnValue("$ip dscp")); - $fields{protocol} = getProtocol($config->returnValue("$ip protocol")); - $fields{src} = $config->returnValue("$ip source address"); - $fields{dst} = $config->returnValue("$ip destination address"); - $fields{sport} = $config->returnValue("$ip source port"); - $fields{dport} = $config->returnValue("$ip destination port"); - $self->{$ip} = \%fields; + if ( $proto eq 'ether' ) { + $fields{protocol} = + getProtocol( $config->returnValue("ether protocol") ); + $fields{src} = $config->returnValue("ether source"); + $fields{dst} = $config->returnValue("ether destination"); + } + else { + $fields{dsfield} = + getDsfield( $config->returnValue("$proto dscp") ); + $fields{protocol} = + getProtocol( $config->returnValue("$proto protocol") ); + $fields{src} = $config->returnValue("$proto source address"); + $fields{dst} = $config->returnValue("$proto destination address"); + $fields{sport} = $config->returnValue("$proto source port"); + $fields{dport} = $config->returnValue("$proto destination port"); + } + + $self->{$proto} = \%fields; } $self->{_vif} = $config->returnValue("vif"); - $self->{_dev} = getIfIndex($config->returnValue("interface")); + $self->{_dev} = getIfIndex( $config->returnValue("interface") ); return $self; } sub filter { my ( $self, $dev, $parent, $prio, $dsmark ) = @_; - + # empty match - return unless %{ $self }; + return unless %{$self}; # Special case for when dsmarking is used with ds matching # original dscp is saved in tc_index if ($dsmark) { - foreach my $ipver (qw(ip ipv6)) { - my $ip = $self->{$ipver}; - next unless $ip && $$ip{dsfield}; + foreach my $ipver (qw(ip ipv6)) { + 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}; - } - return; + printf "filter add dev %s parent %x: protocol $ipver prio 1", + $dev, $parent; + printf " handle %d tcindex", $$ip{dsfield}; + } + return; } - foreach my $ipver (qw(ip ipv6)) { - my $ip = $self->{$ipver}; - next unless $ip; - - printf "filter add dev %s parent %x: prio %d", $dev, $parent, $prio; - print " protocol $ipver u32"; - print " match $ipver dsfield $$ip{dsfield} 0xff" - if defined $$ip{dsfield}; - print " match $ipver protocol $$ip{protocol} 0xff" - if defined $$ip{protocol}; - print " match $ipver src $$ip{src}" - if defined $$ip{src}; - print " match $ipver sport $$ip{sport} 0xffff" - if defined $$ip{sport}; - print " match $ipver dst $$ip{dst}" - if defined $$ip{dst}; - print " match $ipver dport $$ip{dport} 0xffff" - if defined $$ip{dport}; + foreach my $proto (qw(ip ipv6 ether)) { + my $p = $self->{$proto}; + next unless $p; + + printf "filter add dev %s parent %x: prio %d", $dev, $parent, $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 { + my $type = $$p{protocol}; + $type = 'all' unless $type; + + print " protocol $type u32"; + } + 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}; } my $indev = $self->{indev}; - my $vif = $self->{vif}; - if ($vif || $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; + my $vif = $self->{vif}; + if ( $vif || $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; } } |