From 5f19707fc625e279427f74ce7e852ede5ad8ead8 Mon Sep 17 00:00:00 2001
From: Stephen Hemminger <shemminger@vyatta.com>
Date: Thu, 9 Apr 2009 17:36:55 -0700
Subject: Add IPV6 support to QoS

Bug 4230
Allow matching based on IPV6 addresses and ports
Generalize existing matching code.
---
 lib/Vyatta/Qos/Match.pm | 102 +++++++++++++++++++++++-------------------------
 1 file changed, 49 insertions(+), 53 deletions(-)

(limited to 'lib')

diff --git a/lib/Vyatta/Qos/Match.pm b/lib/Vyatta/Qos/Match.pm
index 587704f..0c45958 100644
--- a/lib/Vyatta/Qos/Match.pm
+++ b/lib/Vyatta/Qos/Match.pm
@@ -20,83 +20,79 @@ use Vyatta::Qos::Util qw(getIfIndex getDsfield getProtocol);
 use strict;
 use warnings;
 
-my %fields = (
-	_dev      => undef,
-	_vif      => undef,
-	_ip	  => undef,
-);
-
 sub new {
     my ( $that, $config ) = @_;
-    my $self = {%fields};
+    my $self = { };
     my $class = ref($that) || $that;
 
     bless $self, $class;
-    $self->_define($config);
-
-    return $self;
-}
-
-sub _define {
-    my ( $self, $config ) = @_;
-    my $level = $config->setLevel();
 
     $self->{_vif} = $config->returnValue("vif");
     $self->{_dev} = getIfIndex($config->returnValue("interface"));
 
-    if ($config->exists("ip")) {
-	my %ip;
+    foreach my $ip (qw(ip ipv6)) {
+	next unless $config->exists($ip);
 
-	$ip{dsfield} = getDsfield( $config->returnValue("ip dscp"));
-	$ip{protocol} = getProtocol($config->returnValue("ip protocol"));
-	$ip{src} = $config->returnValue("ip source address");
-	$ip{dst} = $config->returnValue("ip destination address");
-	$ip{sport} = $config->returnValue("ip source port");
-	$ip{dport} = $config->returnValue("ip destination port");
-	$self->{_ip} = \%ip;
+	# 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;
     }
+
+    return $self;
 }
 
 sub filter {
     my ( $self, $dev, $parent, $prio, $dsmark ) = @_;
-    my $ip = $self->{_ip};
-    my $indev = $self->{_dev};
-    my $vif = $self->{_vif};
-
-    # Catch empty match
-    if (! (defined $ip || defined $indev || defined $vif)) {
-	return;
-    }
+    
+    # empty match
+    return unless %{ $self };
 
     # Special case for when dsmarking is used with ds matching
     # original dscp is saved in tc_index
-    if (defined $dsmark && defined $ip && defined $$ip{dsfield}) {
-	printf "filter add dev %s parent %x: protocol ip prio 1",
-		$dev, $parent;
-	printf " handle %d tcindex", $$ip{dsfield};
+    if ($dsmark) {
+	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: prio %d", $dev, $parent, $prio;
-    if (defined $ip) {
-	print " protocol ip u32";
-	print " match ip dsfield $$ip{dsfield} 0xff"
+    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 ip protocol $$ip{protocol} 0xff"
-	    if defined $$ip{protocol};
-	print " match ip src $$ip{src}"
+	print " match $ipver protocol $$ip{protocol} 0xff"
+		if defined $$ip{protocol};
+	print " match $ipver src $$ip{src}"
 	    if defined $$ip{src};
-	print " match ip sport $$ip{sport} 0xffff"
+	print " match $ipver sport $$ip{sport} 0xffff"
 	    if defined $$ip{sport};
-	print " match ip dst $$ip{dst}"
-	    if defined $$ip{dst};
-	print " match ip dport $$ip{dport} 0xffff"
-	    if defined $$ip{dport};
-    } else {
+	print " match $ipver dst $$ip{dst}"
+		if defined $$ip{dst};
+	print " match $ipver dport $$ip{dport} 0xffff"
+		if defined $$ip{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 (defined $indev);
-	print " match meta\(vlan mask 0xfff eq $vif\)"
-	    if (defined $vif);
+	print " match meta\(rt_iif eq $indev\)"		if $indev;
+	print " match meta\(vlan mask 0xfff eq $vif\)" if $vif;
     }
 }
-- 
cgit v1.2.3