diff options
| author | Stephen Hemminger <stephen.hemminger@vyatta.com> | 2008-07-15 14:13:51 -0700 | 
|---|---|---|
| committer | Stephen Hemminger <stephen.hemminger@vyatta.com> | 2008-07-15 14:13:51 -0700 | 
| commit | 81b51bb9270e77289604493761a2f7cb047bd3ea (patch) | |
| tree | bc8c6d8cb285ea99ba8b4296b9b2a26b6bb4efea | |
| parent | 3dd93c5175de9a4d32cadb7bb0c4f832fb14312d (diff) | |
| download | vyatta-cfg-qos-81b51bb9270e77289604493761a2f7cb047bd3ea.tar.gz vyatta-cfg-qos-81b51bb9270e77289604493761a2f7cb047bd3ea.zip | |
Look for changes in QoS after commit
Since configuration system doesn't correctly notify on addition/deletion,
have to introduce this extra verbosity to have each traffic-shaper type
check for changes.
Bugfix for 3452
| -rw-r--r-- | scripts/VyattaQosFairQueue.pm | 16 | ||||
| -rw-r--r-- | scripts/VyattaQosRateLimiter.pm | 13 | ||||
| -rw-r--r-- | scripts/VyattaQosTrafficShaper.pm | 50 | ||||
| -rwxr-xr-x | scripts/vyatta-qos.pl | 135 | ||||
| -rw-r--r-- | templates/qos-policy/node.def | 1 | ||||
| -rw-r--r-- | templates/qos-policy/traffic-shaper/node.def | 3 | 
6 files changed, 186 insertions, 32 deletions
| diff --git a/scripts/VyattaQosFairQueue.pm b/scripts/VyattaQosFairQueue.pm index 8a9dfdf..278bb77 100644 --- a/scripts/VyattaQosFairQueue.pm +++ b/scripts/VyattaQosFairQueue.pm @@ -37,8 +37,8 @@ sub new {      my $class = ref($that) || $that;      my $self = {%fields}; -    $self->{_perturb} = $config->returnValue("hash-interval"); -    $self->{_limit}   = $config->returnValue("queue-limit"); +    $self->{_perturb} = $config->returnValue('hash-interval'); +    $self->{_limit}   = $config->returnValue('queue-limit');      return bless $self, $class;  } @@ -51,4 +51,16 @@ sub commands {      print "\n";  } +sub isChanged { +    my ( $self, $name ) = @_; +    my $config = new VyattaConfig; + +    $config->setLevel("qos-policy fair-queue $name"); +    foreach my $attr ('hash-interval', 'queue-limit') { +	if ($config->isChanged($attr)) { +	    return $attr +	} +    } +    return undef; # false +}  1; diff --git a/scripts/VyattaQosRateLimiter.pm b/scripts/VyattaQosRateLimiter.pm index 548526b..f519683 100644 --- a/scripts/VyattaQosRateLimiter.pm +++ b/scripts/VyattaQosRateLimiter.pm @@ -55,4 +55,17 @@ sub commands {  	    $dev, $self->{_rate}, $self->{_latency}, $self->{_burst};  } +sub isChanged { +    my ($self, $name) = @_; +    my $config = new VyattaConfig; + +    $config->setLevel("qos-policy rate-limit $name"); +    foreach my $attr ('bandwidth', 'burst', 'latency') { +	if ($config->isChanged($attr)) { +	    return $attr +	} +    } +    return undef; # false +} +  1; diff --git a/scripts/VyattaQosTrafficShaper.pm b/scripts/VyattaQosTrafficShaper.pm index f321e9b..325c02e 100644 --- a/scripts/VyattaQosTrafficShaper.pm +++ b/scripts/VyattaQosTrafficShaper.pm @@ -404,4 +404,54 @@ sub commands {      }  } +# 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 VyattaConfig; + +    $config->setLevel("qos-policy traffic-shaper $name"); + +    if ($config->isChanged('bandwidth') ) { +	return 'bandwidth'; +    } + +    foreach my $attr ('bandwidth', 'burst', 'ceiling', 'priority', 'queue-limit', 'queue-type') { +	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 ('bandwidth', 'burst', 'ceiling', 'priority', 'queue-limit', 'queue-type') { +	    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')  { +		if ($config->isChanged("$level $parm")) { +		    return "$level $parm"; +		} +	    } +	} +    } + +    return undef; # false +} +  1; diff --git a/scripts/vyatta-qos.pl b/scripts/vyatta-qos.pl index ad97617..3d8e58b 100755 --- a/scripts/vyatta-qos.pl +++ b/scripts/vyatta-qos.pl @@ -21,24 +21,22 @@ use strict;  use Getopt::Long;  my $debug = $ENV{'QOS_DEBUG'}; -my $check = undef; +my ($check, $update, $applyChanges);  my @updateInterface = ();  my @deleteInterface = (); -my $listPolicy = undef; -my $deletePolicy = undef; +my ($listPolicy, $deletePolicy);  my @createPolicy = (); -my @updatePolicy = ();  GetOptions(      "check"		    => \$check, +    "apply-changes"         => \$applyChanges,      "update-interface=s{3}" => \@updateInterface,      "delete-interface=s{2}" => \@deleteInterface,      "list-policy"           => \$listPolicy,      "delete-policy=s"       => \$deletePolicy,      "create-policy=s{2}"    => \@createPolicy, -    "update-policy=s{2}"    => \@updatePolicy,  );  # class factory for policies @@ -135,19 +133,92 @@ sub update_interface {      die "Unknown qos-policy $name\n";  } -sub delete_policy { +sub using_policy { +    my ($config, $name, $interface) = @_; +    my @inuse = (); + +    foreach my $dir ( $config->listNodes("$interface qos-policy") ) { +	my $policy = $config->returnValue("$interface qos-policy $dir"); +	if ($policy eq $name) { +	    push @inuse, "$interface $dir"; +	} +    } +    return @inuse; +} + +sub interfaces_using {      my ($name) = @_;      my $config = new VyattaConfig; +    my @affected = (); + +    $config->setLevel('interfaces'); +    foreach my $type ( $config->listNodes() ) { +	foreach my $interface ( $config->listNodes($type) ) { +	    push @affected, using_policy($config, $name, "$type $interface"); + +	    if ($type eq 'ethernet') { +		foreach my $vif ( $config->listNodes("$type $interface vif") ) { +		    push @affected, using_policy($config, $name, "$type $interface vif $vif"); +		} +	    } -    $config->setLevel("interfaces ethernet"); -    foreach my $interface ( $config->listNodes() ) { -	foreach my $direction ( $config->listNodes("$interface qos-policy") ) { -	    if ($config->returnValue("$interface qos-policy $direction") eq $name) { -		# can't delete active policy -		die "Qos policy $name still in use on ethernet $interface $direction\n"; +	    if ($type eq 'adsl') { +		foreach my $pvc ( $config->listNodes("adsl $interface pvc") ) { +		    foreach my $pvctype ( $config->listNodes("adsl $interface pvc $pvc") ) { +			foreach my $vc ( $config->listNodes("adsl $interface pvc $pvc $pvctype") ) { +			    push @affected, using_policy($config, $name,  +						      "adsl $interface pvc $pvc $pvctype $vc"); +			} +		    } +		}  	    }  	}      } + +    return @affected; +} + +sub etherName { +    my $eth = shift; + +    if ($_ =~ /vif/) { +	shift;  +	$eth .= $_; +    } +    return $eth; +} + +sub serialName { +    my $wan = shift; +    # XXX add vif +    return $wan; +} + +sub adslName { +    # adsl-name pvc pvc-num ppp-type id +    my (undef, undef, undef, $type, $id) = @_; + +    return $type . $id; +} + +# Handle mapping of interface types to device names +my %interfaceTypes = ( +    'ethernet'	=> \ðerName, +    'serial'	=> \&serialName, +    'adsl'	=> \&adslName, +    ); + +sub delete_policy { +    my ($name) = @_; +    my @inuse = interfaces_using($name); + +    if ( @inuse ) { +	foreach my $usage (@inuse) { +	    warn "QoS policy $name used by $usage\n"; +	} +	# can't delete active policy +	die "Must delete QoS policy from interfaces before deleting rules\n"; +    }  }  sub check_conflict { @@ -172,18 +243,24 @@ sub create_policy {      make_policy($config, $shaper, $name);  } -sub update_policy { -    my ($shaper, $name) = @_; +sub apply_changes {      my $config = new VyattaConfig; -    # Syntax check -    make_policy($config, $shaper, $name); - -    $config->setLevel("interfaces ethernet"); -    foreach my $interface ( $config->listNodes() ) { -	foreach my $direction ( $config->listNodes("$interface qos-policy") ) { -	    if ($config->returnValue("$interface qos-policy $direction") eq $name) { -		update_interface($interface, $direction, $name); +    $config->setLevel('qos-policy'); +    foreach my $policy ($config->listNodes()) { +	foreach my $name ($config->listNodes($policy)) { +	    my $shaper = make_policy($config, $policy, $name); + +	    if ($shaper->isChanged($name)) { +		foreach my $cfgpath (interfaces_using($name)) { +		    my @elements = split / /, $cfgpath; +		    my $direction = pop @elements;  # out, in, ... +		    my $type = shift @elements;     # ethernet, serial, ... +		    my $interface = $interfaceTypes{$type}; +		    my $device = $interface->(@elements); + +		    update_interface($device, $direction, $name); +		}  	    }  	}      } @@ -214,22 +291,24 @@ if ( $#createPolicy == 1) {      exit 0;  } -if ( $#updatePolicy == 1) { -    update_policy(@updatePolicy); -    exit 0; -} -  if ( $deletePolicy ) {      delete_policy($deletePolicy);      exit 0; +}  + +if ( $applyChanges ) { +    apply_changes(); +    exit 0;  }  print <<EOF;  usage: vyatta-qos.pl --check         vyatta-qos.pl --list-policy +         vyatta-qos.pl --create-policy policy-type policy-name         vyatta-qos.pl --delete-policy policy-name -       vyatta-qos.pl --update-policy policy-type policy-name +       vyatta-qos.pl --apply-changes policy-type policy-name +         vyatta-qos.pl --update-interface interface direction policy-name         vyatta-qos.pl --delete-interface interface direction diff --git a/templates/qos-policy/node.def b/templates/qos-policy/node.def index 2499fd5..991b5f5 100644 --- a/templates/qos-policy/node.def +++ b/templates/qos-policy/node.def @@ -1,2 +1,3 @@  help: Configure Quality of Service (QOS) policy type  begin: /opt/vyatta/sbin/vyatta-qos.pl --check +end: /opt/vyatta/sbin/vyatta-qos.pl --apply diff --git a/templates/qos-policy/traffic-shaper/node.def b/templates/qos-policy/traffic-shaper/node.def index 31bdc93..b0b209d 100644 --- a/templates/qos-policy/traffic-shaper/node.def +++ b/templates/qos-policy/traffic-shaper/node.def @@ -3,6 +3,5 @@ type: txt  help: Set traffic shaping based policy  syntax:expression: pattern $VAR(@) "^[[:alnum:]][-_[:alnum:]]*$"                     ; "only alpha-numeric policy name allowed" -create: /opt/vyatta/sbin/vyatta-qos.pl --create-policy "$VAR(.)" "$VAR(@)" +update: /opt/vyatta/sbin/vyatta-qos.pl --create-policy "$VAR(.)" "$VAR(@)"  delete: /opt/vyatta/sbin/vyatta-qos.pl --delete-policy "$VAR(@)" -update: /opt/vyatta/sbin/vyatta-qos.pl --update-policy "$VAR(.)" "$VAR(@)" | 
