diff options
58 files changed, 1123 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3f43d67 --- /dev/null +++ b/.gitignore @@ -0,0 +1,18 @@ +*~ +.*.swp +/aclocal.m4 +/autom4te.cache +/build-stamp +/ChangeLog +/config +/config.log +/config.guess +/config.status +/config.sub +/configure +/debian/files +/INSTALL +/Makefile.in +/Makefile +/scripts/install-system + @@ -0,0 +1 @@ +eng@vyatta.com @@ -0,0 +1,27 @@ +/* + * Package: vyatt-cfg-qos + * + * **** License **** + * Version: VPL 1.0 + * + * The contents of this file are subject to the Vyatta Public License + * Version 1.0 ("License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.vyatta.com/vpl + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * This code was originally developed by Vyatta, Inc. + * Portions created by Vyatta are Copyright (C) "YEAR" Vyatta, Inc. + * All Rights Reserved. + * + * Author: eng@vyatta.com + * Date: 2007 + * Description: Vyatta system-level configuration templates/scripts + * + * **** End License **** + * + */ diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..aaa1718 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,24 @@ +cfgdir = $(datadir)/vyatta-cfg/templates +share_perl5dir = /opt/vyatta/share/perl5 + +bin_SCRIPTS = +sbin_SCRIPTS = +sysconf_DATA = +share_perl5_DATA = + +sbin_SCRIPTS += scripts/vyatta-qos.pl +sbin_SCRIPTS += scripts/vyatta-qos-util.pl + +share_perl5_DATA += scripts/VyattaQosUtil.pm +share_perl5_DATA += scripts/VyattaQosPolicy.pm +share_perl5_DATA += scripts/VyattaQosFairQueue.pm +share_perl5_DATA += scripts/VyattaQosTrafficShaper.pm +share_perl5_DATA += scripts/VyattaQosMatch.pm + +cpiop = find . ! -regex '\(.*~\|.*\.bak\|.*\.swp\|.*\#.*\#\)' -print0 | \ + cpio -0pd + +install-exec-hook: + mkdir -p $(DESTDIR)$(cfgdir) + cd templates; $(cpiop) $(DESTDIR)$(cfgdir) + @@ -0,0 +1 @@ +see http://www.vyatta.com/news/ @@ -0,0 +1 @@ +This package has the Vyatta QoS configuration templates and scripts. diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..3f916a3 --- /dev/null +++ b/configure.ac @@ -0,0 +1,30 @@ +# Process this file with autoconf to produce a configure script. +AC_PREREQ(2.59) + +m4_define([VERSION_ID], [m4_esyscmd([ + if test -f .version ; then + head -n 1 .version | tr -d \\n + else + echo -n 2.4 + fi])]) +AC_INIT([vyatta-cfg-qos], VERSION_ID, [vyatta-support@vyatta.com]) + +test -n "$VYATTA_VERSION" || VYATTA_VERSION=$PACKAGE_VERSION + +AC_CONFIG_AUX_DIR([config]) +AM_INIT_AUTOMAKE([gnu no-dist-gzip dist-bzip2 subdir-objects]) +AC_PREFIX_DEFAULT([/opt/vyatta]) + +AC_ARG_ENABLE([nostrip], + AC_HELP_STRING([--enable-nostrip], + [include -nostrip option during packaging]), + [NOSTRIP=-nostrip], [NOSTRIP=]) + +AC_CONFIG_FILES( + [Makefile] + [debian/vyatta-cfg-qos.postinst]) + +AC_SUBST(NOSTRIP) + +AC_OUTPUT + diff --git a/debian/README b/debian/README new file mode 100644 index 0000000..aeae320 --- /dev/null +++ b/debian/README @@ -0,0 +1,5 @@ +The Debian Package vyatta-cfg-qos +---------------------------- + +This package has the Vyatta Qos configuration templates and scripts. + diff --git a/debian/autogen.sh b/debian/autogen.sh new file mode 100755 index 0000000..ff125d1 --- /dev/null +++ b/debian/autogen.sh @@ -0,0 +1,37 @@ +#!/bin/sh + + +if [ -d .git ] ; then +# generate GNU/Debian format ChangeLog from git log + + rm -f ChangeLog + + if which git2cl >/dev/null ; then + git-log --pretty --numstat --summary | git2cl >> ChangeLog + else + git-log --pretty=short >> ChangeLog + fi + +# append repository reference + + url=` git repo-config --get remote.origin.url` + test "x$url" = "x" && url=`pwd` + + branch=`git-branch --no-color | sed '/^\* /!d; s/^\* //'` + test "x$branch" = "x" && branch=master + + sha=`git log --pretty=oneline --no-color -n 1 | cut -c-8` + test "x$sha" = "x" && sha=00000000 + + echo "$url#$branch-$sha" >> ChangeLog + +fi + +rm -rf config +rm -f aclocal.m4 config.guess config.statusconfig.sub configure INSTALL + +autoreconf --force --install + +rm -f config.sub config.guess +ln -s /usr/share/misc/config.sub . +ln -s /usr/share/misc/config.guess . diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..82ef481 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,5 @@ +vyatta-cfg-qos (0.1) unstable; urgency=low + + * Initial Release. + + -- Stephen Hemminger <stephen.hemminger@vyatta.com> Wed, 30 Jan 2008 11:23:18 -0700 diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..7ed6ff8 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +5 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..73fac62 --- /dev/null +++ b/debian/control @@ -0,0 +1,20 @@ +Source: vyatta-cfg-qos +Section: contrib/net +Priority: extra +Maintainer: Stephen Hemminger <stephen.hemminger@vyatta.com> +Build-Depends: debhelper (>= 5), autotools-dev +Standards-Version: 3.7.2 + +Package: vyatta-cfg-qos +Architecture: all +Depends: bash (>= 3.1), + sed (>= 4.1.5), + perl (>= 5.8.8), + procps (>= 1:3.2.7-3), + coreutils (>= 5.97-5.3), + vyatta-cfg, sudo, + vyatta-bash, bridge-utils, vyatta-iproute, ethtool +Suggests: util-linux (>= 2.13-5), + net-tools, +Description: Vyatta Qos configuration templates/scripts + Vyatta Qos configuration templates and scripts. diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..a7d84e1 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,34 @@ +This package was created by Stephen Hemminger <stephen.hemminger@vyatta.com> +on Wed, Wed Jan 30 11:23:52 PST 2008 + +It's original content from the GIT repository <http://vyatt.com/git/vyatta-cfg-qos> + +Upstream Author: + + <eng@vyatta.com> + +Copyright: + + Copyright (C) 2008 Vyatta, Inc. + All Rights Reserved. + +License: + + The contents of this package are subject to the Vyatta Public License + Version 1.0 ("License"); you may not use this file except in + compliance with the License. You may obtain a copy of the License at + http://www.vyatta.com/vpl + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and limitations + under the License. + + This code was originally developed by Vyatta, Inc. + Portions created by Vyatta are Copyright (C) 2008 Vyatta, Inc. + +On Debian systems, the complete text of the GNU General +Public License can be found in `/usr/share/common-licenses/GPL'. + +The Debian packaging is (C) 2008, Stephen Hemminger +<stephen.hemminger@vyatta.com> and is licensed under the GPL, see above. diff --git a/debian/docs b/debian/docs new file mode 100644 index 0000000..50bd824 --- /dev/null +++ b/debian/docs @@ -0,0 +1,2 @@ +NEWS +README diff --git a/debian/linda b/debian/linda new file mode 100644 index 0000000..0381d9d --- /dev/null +++ b/debian/linda @@ -0,0 +1 @@ +Tag: file-in-opt diff --git a/debian/lintian b/debian/lintian new file mode 100644 index 0000000..f1dafbd --- /dev/null +++ b/debian/lintian @@ -0,0 +1,2 @@ +vyatta-cfg-qos: file-in-unusual-dir +vyatta-cfg-qos: dir-or-file-in-opt diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..b02c352 --- /dev/null +++ b/debian/rules @@ -0,0 +1,101 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + + +# These are used for cross-compiling and for saving the configure script +# from having to guess our platform (since we know it already) +DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE) +DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE) +PACKAGE=vyatta-cfg-qos +PKGDIR=$(CURDIR)/debian/$(PACKAGE) + +CFLAGS = -Wall -g + +configure = ./configure +configure += --host=$(DEB_HOST_GNU_TYPE) +configure += --build=$(DEB_BUILD_GNU_TYPE) +configure += --prefix=/opt/vyatta +configure += --mandir=\$${prefix}/share/man +configure += --infodir=\$${prefix}/share/info +configure += CFLAGS="$(CFLAGS)" +configure += LDFLAGS="-Wl,-z,defs" + +ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) + CFLAGS += -O0 +else + CFLAGS += -O2 +endif + +configure: configure.ac Makefile.am + chmod +x debian/autogen.sh + debian/autogen.sh + +config.status: configure + dh_testdir + rm -f config.cache + $(configure) + +build: build-stamp + +build-stamp: config.status + dh_testdir + $(MAKE) + touch $@ + +clean: clean-patched + +# Clean everything up, including everything auto-generated +# at build time that needs not to be kept around in the Debian diff +clean-patched: + dh_testdir + dh_testroot + if test -f Makefile ; then $(MAKE) clean distclean ; fi + rm -f build-stamp + rm -f config.status config.sub config.guess config.log + rm -f aclocal.m4 configure Makefile.in Makefile INSTALL + rm -rf config + dh_clean + +install: build + dh_testdir + dh_testroot + dh_clean -k + dh_installdirs + + $(MAKE) DESTDIR=$(PKGDIR) install + + install -D --mode=0644 debian/lintian $(PKGDIR)/usr/share/lintian/overrides/$(PACKAGE) + install -D --mode=0644 debian/linda $(PKGDIR)/usr/share/linda/overrides/$(PACKAGE) + +# Build architecture-independent files here. +binary-indep: build install + dh_testdir + dh_testroot + dh_installchangelogs ChangeLog + dh_installdocs + dh_install + dh_installdebconf + dh_link + dh_strip + dh_compress + dh_fixperms + dh_installdeb + dh_gencontrol + dh_md5sums + dh_builddeb + +# Build architecture-dependent files here. +binary-arch: build install +# This is an architecture independent package +# so; we have nothing to do by default. + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install diff --git a/debian/vyatta-cfg-qos.postinst.in b/debian/vyatta-cfg-qos.postinst.in new file mode 100644 index 0000000..3751d0b --- /dev/null +++ b/debian/vyatta-cfg-qos.postinst.in @@ -0,0 +1,9 @@ +#!/bin/bash + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +sysconfdir=@sysconfdir@ +bindir=@bindir@ +sbindir=@sbindir@ + +# Don't do anything for now. diff --git a/scripts/VyattaQosFairQueue.pm b/scripts/VyattaQosFairQueue.pm new file mode 100644 index 0000000..d943db2 --- /dev/null +++ b/scripts/VyattaQosFairQueue.pm @@ -0,0 +1,41 @@ +package VyattaQosFairQueue; +@ISA = qw/VyattaQosPolicy/; + +# +# This is a wrapper around Stochastic Fair Queue(SFQ) queue discipline +# Since SFQ is a hard to explain, use the name fair-queue since SFQ +# is most similar to Weighted Fair Queue (WFQ) on Cisco IOS. +# + +use strict; + +require VyattaConfig; + +# Fair Queue +# Uses SFQ which is similar to (but not same as) WFQ + +my %fields = ( + _perturb => undef, + _limit => undef, +); + +sub new { + my ( $that, $config ) = @_; + my $class = ref($that) || $that; + my $self = {%fields}; + + $self->{_perturb} = $config->returnValue("rekey-interval"); + $self->{_limit} = $config->returnValue("queue-limit"); + return bless $self, $class; +} + +sub commands { + my ( $self, $out, $dev ) = @_; + + print {$out} "qdisc add dev $dev root sfq"; + print {$out} " perturb $self->{_perturb}" if ( defined $self->{_perturb} ); + print {$out} " limit $self->{_limit}" if ( defined $self->{_limit} ); + print "\n"; +} + +1; diff --git a/scripts/VyattaQosMatch.pm b/scripts/VyattaQosMatch.pm new file mode 100644 index 0000000..72f7a36 --- /dev/null +++ b/scripts/VyattaQosMatch.pm @@ -0,0 +1,82 @@ +package VyattaQosMatch; +require VyattaConfig; +use VyattaQosUtil; +use strict; + +my %fields = ( + _dev => undef, + _vlan => undef, + _ip => { + _src => undef, + _dst => undef, + _dsfield => undef, + _protocol => undef, + _sport => undef, + _dport => undef, + } +); + +sub new { + my ( $that, $config ) = @_; + my $self = {%fields}; + my $class = ref($that) || $that; + + bless $self, $class; + $self->_define($config); + + return $self; +} + +sub _tos { + my $tos = shift; + my $ret = undef; + + if ( defined $tos ) { + $ret = VyattaQosUtil::getDsfield($tos); + if ( !defined $ret ) { + $tos = hex($tos); + } + } + return $ret; +} + +sub _define { + my ( $self, $config ) = @_; + + my $level=$config->setLevel(); + + $self->{_vlan} = $config->returnValue("vif"); + $self->{_dev} = $config->returnValue("interface"); + + $self->{_ip}->{_tos} = _tos( $config->returnValue("ip tos") ); + $self->{_ip}->{_protocol} = $config->returnValue("ip protocol"); + $self->{_ip}->{_src} = $config->returnValue("ip source address"); + $self->{_ip}->{_dst} = $config->returnValue("ip destination address"); + $self->{_ip}->{_sport} = $config->returnValue("ip source port"); + $self->{_ip}->{_dport} = $config->returnValue("ip source dport"); +} + +sub filter { + my ( $self, $out, $dev, $id ) = @_; + + print {$out} "filter add dev $dev parent 1:0 prio 10"; + + # TODO match on vlan, device, ... + if (defined $self->{_ip}) { + print {$out} " u32"; + print {$out} " match ip tos $self->{_ip}->{_tos} 0xff" + if defined $self->{_ip}->{_tos}; + print {$out} " match ip protocol $self->{_ip}->{_protcol} 0xff" + if defined $self->{_ip}->{_protocol}; + print {$out} " match ip src $self->{_ip}->{_src}" + if defined $self->{_ip}->{_src}; + print {$out} " match ip sport $self->{_ip}->{_sport}" + if defined $self->{_ip}->{_sport}; + print {$out} " match ip dst $self->{_ip}->{_dst}" + if defined $self->{_ip}->{_dst}; + print {$out} " match ip dport $self->{_ip}->{_dport}" + if defined $self->{_ip}->{_dport}; + } + + print {$out} " classid $id\n"; +} diff --git a/scripts/VyattaQosPolicy.pm b/scripts/VyattaQosPolicy.pm new file mode 100644 index 0000000..76f86eb --- /dev/null +++ b/scripts/VyattaQosPolicy.pm @@ -0,0 +1,34 @@ +package VyattaQosPolicy; + +use strict; + +require VyattaConfig; +use VyattaQosTrafficShaper; +use VyattaQosFairQueue; + +# Main class for all QoS policys +# It is a base class, and actual policies are subclass instances. + +# Build a new traffic shaper of the proper type based +# on the configuration information. +sub config { + my ( $class, $config, $type ) = @_; + my $object = undef; + + SWITCH: { + ( $type eq 'fair-queue' ) && do { + $object = new VyattaQosFairQueue($config); + last SWITCH; + }; + + ( $type eq 'traffic-shaper' ) && do { + $object = new VyattaQosTrafficShaper($config); + last SWITCH; + }; + + die "Unknown policy type \"$type\"\n"; + } + return $object; +} + +1; diff --git a/scripts/VyattaQosTrafficShaper.pm b/scripts/VyattaQosTrafficShaper.pm new file mode 100644 index 0000000..903aeeb --- /dev/null +++ b/scripts/VyattaQosTrafficShaper.pm @@ -0,0 +1,182 @@ +# Traffic shaper +# This is a extended form of Hierarchal Token Bucket with +# more admin friendly features. Similar in spirt to other shaper scripts +# such as wondershaper. + +{ + package ShaperClass; + use strict; + require VyattaConfig; + use VyattaQosMatch; + + my %fields = ( + id => undef, + _priority => undef, + _rate => undef, + _ceiling => undef, + _burst => undef, + _match => undef, + ); + + sub new { + my ( $that, $config, $id ) = @_; + my $class = ref($that) || $that; + my $self = {%fields}; + + bless $self, $class; + $self->_define($config, $id); + + return $self; + } + + sub _define { + my ( $self, $config, $id ) = @_; + my $level = $config->setLevel(); + my @matches = (); + + + $self->{_id} = sprintf "%04x", $id; + $self->{_priority} = $config->returnValue("priority"); + $self->{_rate} = $config->returnValue("rate"); + $self->{_ceiling} = $config->returnValue("ceiling"); + $self->{_burst} = $config->returnValue("burst"); + + foreach my $match ($config->listNodes("match")) { + $config->setLevel("$level match $match"); + push @matches, new VyattaQosMatch($config); + } + $self->{_match} = \@matches; + } + + sub _getPercentRate { + my ($rate, $speed) = @_; + + if ( ! defined $rate ) { + return; # leave rate undef + } + + # Rate might be a percentage of speed + if ( $rate =~ /%$/ ) { + my $percent = substr( $rate, 0, length($rate) - 1 ); + if ( $percent < 0 || $percent > 100 ) { + die "Invalid percentage bandwidth\n"; + } + + $rate = ( $percent * $speed ) / 100.; + } else { + $rate = VyattaQosUtil::getRate($rate); + } + + return $rate; + } + + sub commands { + my ( $self, $out, $dev, $speed ) = @_; + my $rate = _getPercentRate($self->{_rate}, $speed); + my $ceil = _getPercentRate($self->{_ceiling}, $speed); + my $id = $self->{_id}; + my $matches = $self->{_match}; + + die "Rate is not defined\n" if (! defined $rate ); + die "Class $id rate $rate > shaper rate $speed\n" if ($rate > $speed); + + # create the class + my $cmd ="class add dev $dev parent 1:1 classid 1:$id htb rate $rate"; + if ( defined $ceil) { + if ($ceil < $rate ) { + die "Rate limit (ceiling) $ceil < base rate $rate\n"; + } + $cmd .= " ceil $ceil"; + } + + $cmd .= " burst $self->{_burst}" if ( defined $self->{_burst} ); + $cmd .= " prio $self->{_priority}" if ( defined $self->{_priority} ); + + print {$out} $cmd . "\n"; + + # create leaf qdisc + print {$out} "qdisc add dev $dev parent 1:$id sfq\n"; + + foreach my $match (@$matches) { + $match->filter( $out, $dev, $id ); + } + } +} + +package VyattaQosTrafficShaper; +@ISA = qw/VyattaQosPolicy/; +use strict; +require VyattaConfig; +use VyattaQosUtil; + +my $defaultId = 0x4000; + +my %fields = ( + _rate => undef, + _classes => undef, +); + +# new VyattaQosTrafficShaper($config) +# Create a new instance based on config information +sub new { + my ( $that, $config ) = @_; + my $self = {%fields}; + my $class = ref($that) || $that; + + bless $self, $class; + $self->_define($config); + + return $self; +} + +# Rate can be something like "auto" or "10.2mbit" +sub _getAutoRate { + my ($rate, $dev) = @_; + + if ( $rate eq "auto" ) { + my $rate = VyattaQosUtil::interfaceRate($dev); + if ( ! defined $rate ) { + die "Auto speed setting but can't get rate from $dev\n"; + } + } else { + $rate = VyattaQosUtil::getRate($rate); + } + + return $rate; +} + +# Setup new instance. +# Assumes caller has done $config->setLevel to "traffic-shaper $name" +sub _define { + my ( $self, $config ) = @_; + my $level = $config->setLevel(); + my @classes = ( ); + + $self->{_rate} = $config->returnValue("rate"); + + $config->setLevel("$level default"); + push @classes, new ShaperClass( $config, $defaultId); + $config->setLevel($level); + + foreach my $id ( $config->listNodes("class") ) { + $config->setLevel("$level class $id"); + push @classes, new ShaperClass( $config, $id ); + } + $self->{_classes} = \@classes; +} + +sub commands { + my ( $self, $out, $dev ) = @_; + my $rate = _getAutoRate($self->{_rate}, $dev); + my $classes = $self->{_classes}; + my @tc = ( ); + + print {$out} "qdisc add dev $dev root handle 1: htb default $defaultId\n"; + print {$out} "class add dev $dev parent 1: classid 1:1 htb rate $rate\n"; + + foreach my $class (@$classes) { + $class->commands( $out, $dev, $rate ); + } +} + +1; diff --git a/scripts/VyattaQosUtil.pm b/scripts/VyattaQosUtil.pm new file mode 100644 index 0000000..121970e --- /dev/null +++ b/scripts/VyattaQosUtil.pm @@ -0,0 +1,173 @@ +package VyattaQosUtil; +use POSIX; +require Exporter; +@EXPORT = qw/getRate getSize getProtocol getDsfield interfaceRate/; + +sub get_num { + my ($str) = @_; + + # clear errno + $! = 0; + ($num, $unparsed) = POSIX::strtod($str); + if (($str eq '') || $!) { + die "Non-numeric input \"$str\"" . ($! ? ": $!\n" : "\n"); + } + + if ($unparsed > 0) { return $num, substr($str, -$unparsed); } + else { return $num; } +} + +## get_rate("10mbit") +# convert rate specification to number +# from tc/tc_util.c +sub getRate { + my ($num, $suffix) = get_num(@_); + + if (defined $suffix) { + SWITCH: { + ($suffix eq 'bit') && do { last SWITCH; }; + ($suffix eq 'kibit') && do { $num *= 1024.; last SWITCH }; + ($suffix eq 'kbit') && do { $num *= 1000.,; last SWITCH; }; + ($suffix eq 'mibit') && do { $num *= 1048576.,; last SWITCH; }; + ($suffix eq 'mbit') && do { $num *= 1000000.,; last SWITCH; }; + ($suffix eq 'gibit') && do { $num *= 1073741824.,; last SWITCH; }; + ($suffix eq 'gbit') && do { $num *= 1000000000.,; last SWITCH; }; + ($suffix eq 'tibit') && do { $num *= 1099511627776.,; last SWITCH; }; + ($suffix eq 'tbit') && do { $num *= 1000000000000.,; last SWITCH; }; + ($suffix eq 'bps') && do { $num *= 8.,; last SWITCH; }; + ($suffix eq 'kibps') && do { $num *= 8192.,; last SWITCH; }; + ($suffix eq 'kbps') && do { $num *= 8000.,; last SWITCH; }; + ($suffix eq 'mibps') && do { $num *= 8388608.,; last SWITCH; }; + ($suffix eq 'mbps') && do { $num *= 8000000.,; last SWITCH; }; + ($suffix eq 'gibps') && do { $num *= 8589934592.,; last SWITCH; }; + ($suffix eq 'gbps') && do { $num *= 8000000000.,; last SWITCH; }; + ($suffix eq 'tibps') && do { $num *= 8796093022208.,; last SWITCH; }; + ($suffix eq 'tbps') && do { $num *= 8000000000000.,; last SWITCH; }; + + die "Rate must be a number followed by a optional suffix (kbit, mbps, ...)\n"; + } + } + + die "Negative rate not allowed\n" if ($num < 0); + return $num; +} + +sub getSize { + my ($num, $suffix) = get_num(@_); + + if (defined $suffix) { + SWITCH: { + ($suffix eq 'b') && do { $num *= 1.,; last SWITCH; }; + ($suffix eq 'k') && do { $num *= 1024.,; last SWITCH; }; + ($suffix eq 'kb') && do { $num *= 1024.,; last SWITCH; }; + ($suffix eq 'kbit') && do { $num *= 128.,; last SWITCH; }; + ($suffix eq 'm') && do { $num *= 1048576.,; last SWITCH; }; + ($suffix eq 'mb') && do { $num *= 1048576.,; last SWITCH; }; + ($suffix eq 'mbit') && do { $num *= 131072.,; last SWITCH; }; + ($suffix eq 'g') && do { $num *= 1073741824.,; last SWITCH; }; + ($suffix eq 'gb') && do { $num *= 1073741824.,; last SWITCH; }; + ($suffix eq 'gbit') && do { $num *= 134217728.,; last SWITCH; }; + + die "Unknown suffix \"$suffix\"\n"; + } + } + + die "Negative size not allowed\n" if ($num < 0); + return $num; +} + +sub getProtocol { + my ($p) = @_; + + if ($p =~ /^([0-9]+)|(0x[0-9a-fA-F]+)$/) { + if ($p < 0 || $p > 255) { + die "$p is not a valid protocol number\n"; + } + return $p; + } + + ($name, $aliases, $proto) = getprotobyname($p); + (defined $proto) or die "\"$p\" unknown protocol\n"; + return $proto; +} + +# Parse /etc/iproute/rt_dsfield +# return a hex string "0x10" or undefined +sub getDsfield { + my ($str) = @_; + my $match = undef; + my $dsFileName = '/etc/iproute2/rt_dsfield'; + + if ($str =~ /^([0-9]+)|(0x[0-9a-fA-F]+)$/) { + if ($str < 0 || $str > 255) { + die "$str is not a valid dsfield value\n"; + } + return $str; + } + + open(DSFIELD,"<$dsFileName") || die "Can't open $dsFileName, $!\n"; + while (<DSFIELD>) { + next if /^#/; + chomp; + @fields = split; + if ($str eq $fields[1]) { + $match = $fields[0]; + last; + } + } + close(DSFIELD); + + return $match; +} + +# Utility routines + +## interfaceRate("eth0") +# return result in bits per second +sub interfaceRate { + my ($interface) = @_; + my $rate = undef; + my $config = new VyattaConfig; + + $config->setLevel("interfaces ethernet"); + if ($config->exists("$interface")) { + my $speed = $config->returnValue("$interface speed"); + if (defined($speed) && $speed != "auto") { + return $speed * 1000000; + } + } + + $rate = ethtoolRate($interface); + + if (! defined $rate) { + die "Interace speed for $interface unknown\n"; + } + + return $rate * 1000000; +} + +## ethtoolRate("eth0") +# Fetch actual rate using ethtool and format to valid tc rate +sub ethtoolRate { + my ($dev) = @_; + my $rate = undef; + + open(ETHTOOL, "sudo ethtool $dev |") or return $rate; + + # ethtool produces: + # + # Settings for eth1: + # Supported ports: [ TP ] + # ... + # Speed: 1000Mb/s + while (<ETHTOOL>) { + my @line = split; + if ($line[0] =~ /^Speed/) { + $rate = $line[1]; + $rate =~ s/Mb\/s/000000/; + last; + } + } + close(ETHTOOL); + return $rate; +} diff --git a/scripts/vyatta-qos-util.pl b/scripts/vyatta-qos-util.pl new file mode 100755 index 0000000..5dd869f --- /dev/null +++ b/scripts/vyatta-qos-util.pl @@ -0,0 +1,44 @@ +#!/usr/bin/perl +# +# Utility routines for validating input +# These functions don't change existing QoS parameters +# + +use lib "/opt/vyatta/share/perl5/"; +use VyattaQosUtil; +use Getopt::Long; + +GetOptions( + "rate=s" => \$rate, + "burst=s" => \$burst, + "protocol=s" => \$protocol, + "dsfield=s" => \$dsfield, +); + +if ( defined $rate ) { + my $r = VyattaQosUtil::getRate($rate); + exit 0; +} + +if ( defined $burst ) { + my $b = VyattaQosUtil::getSize($burst); + exit 0; +} + +if ( defined $protocol ) { + my $p = VyattaQosUtil::getProtocol($protocol); + exit 0; +} + +if ( defined $dsfield ) { + my $d = VyattaQosUtil::getDsfield($dsfield); + exit 0; +} + +print <<EOF; +usage: vyatta-qos-util.pl --rate rate + vyatta-qos-util.pl --burst size + vyatta-qos-util.pl --protocol protocol + vyatta-qos-util.pl --dsfield tos|dsfield +EOF +exit 1; diff --git a/scripts/vyatta-qos.pl b/scripts/vyatta-qos.pl new file mode 100755 index 0000000..86a0c62 --- /dev/null +++ b/scripts/vyatta-qos.pl @@ -0,0 +1,106 @@ +#!/usr/bin/perl + +use lib "/opt/vyatta/share/perl5/"; +use VyattaConfig; +use VyattaQosPolicy; + +use Getopt::Long; + +my $qosNode = 'qos-policy'; + +my @update = (); +my @delete = (); +my $debug = $ENV{"DEBUG"}; +my $list = undef; + +GetOptions( + "debug" => \$debug, + "list" => \$list, + "update=s{3}" => \@update, + "delete=s{2}" => \@delete, +); + +## list available qos policy names +sub list_available { + my $config = new VyattaConfig; + my @nodes = (); + + foreach my $policy ( $config->listNodes($qosNode) ) { + foreach my $name ( $config->listNodes("$qosNode $policy") ) { + push @nodes, $name; + } + } + + print join( ' ', @nodes ), "\n"; +} + +## delete_interface('eth0', 'out') +# remove all filters and qdisc's +sub delete_interface { + my ( $interface, $direction ) = @_; + + if ( $direction =~ /^out/ ) { + + # delete old qdisc - will give error if no policy in place + system("tc qdisc del dev $interface root 2>/dev/null"); + system("tc filter del dev $interface 2>/dev/null"); + } + else { + return -1; + } +} + +## update_interface('eth0', 'out', 'my-shaper') +# update policy to interface +sub update_interface { + my ( $interface, $direction, $name ) = @_; + my $config = new VyattaConfig; + + # TODO: add support for ingress + ( $direction =~ /^out/ ) or die "Only out direction supported"; + + foreach my $policy ( $config->listNodes($qosNode) ) { + if ( $config->exists("$qosNode $policy $name") ) { + $config->setLevel("$qosNode $policy $name"); + + my $policy = VyattaQosPolicy->config( $config, $policy ); + defined $policy or die "undefined policy"; + + # When doing debugging just echo the commands + if (defined $debug) { + open (my $out, ">&STDOUT"); + } else { + open( my $out, "|sudo tc -batch -" ) + or die "Tc setup failed: $!\n"; + } + + $policy->commands($out, $interface); + close $out or die "Tc command failed: $!\n"; + exit 0; + } + } + + die "Unknown $qosNode $name\n"; +} + +if ( defined $list ) { + list_available(); + exit 0; +} + +if ( $#delete == 1 ) { + delete_interface(@delete); + exit 0; +} + +if ( $#update == 2 ) { + update_interface(@update); + exit 0; +} + +print <<EOF; +usage: vyatta-qos.pl --list + vyatta-qos.pl --update interface direction policy + vyatta-qos.pl --delete interface direction +EOF +exit 1; diff --git a/templates/interfaces/ethernet/node.tag/qos-policy/node.def b/templates/interfaces/ethernet/node.tag/qos-policy/node.def new file mode 100644 index 0000000..b4ab8d8 --- /dev/null +++ b/templates/interfaces/ethernet/node.tag/qos-policy/node.def @@ -0,0 +1 @@ +help: "Configure qos-policy" diff --git a/templates/interfaces/ethernet/node.tag/qos-policy/out/node.def b/templates/interfaces/ethernet/node.tag/qos-policy/out/node.def new file mode 100644 index 0000000..bb9ea38 --- /dev/null +++ b/templates/interfaces/ethernet/node.tag/qos-policy/out/node.def @@ -0,0 +1,4 @@ +type: txt +help: "Set outbound QOS policy" +update: "sudo /opt/vyatta/sbin/vyatta-qos.pl --update $(../../@) out $(@)" +delete: "sudo /opt/vyatta/sbin/vyatta-qos.pl --delete $(../../@) out" diff --git a/templates/qos-policy/fair-queue/node.def b/templates/qos-policy/fair-queue/node.def new file mode 100644 index 0000000..36f3a35 --- /dev/null +++ b/templates/qos-policy/fair-queue/node.def @@ -0,0 +1,4 @@ +tag: +type: txt +syntax: pattern $(@) "^[^-]" ; "Qos queue name cannot start with \"-\"" +help: "Configure fair queueing based policy" diff --git a/templates/qos-policy/fair-queue/node.tag/description/node.def b/templates/qos-policy/fair-queue/node.tag/description/node.def new file mode 100644 index 0000000..335eb7e --- /dev/null +++ b/templates/qos-policy/fair-queue/node.tag/description/node.def @@ -0,0 +1,2 @@ +type: txt +help: "Description for this queuing policy" diff --git a/templates/qos-policy/fair-queue/node.tag/hash-interval/node.def b/templates/qos-policy/fair-queue/node.tag/hash-interval/node.def new file mode 100644 index 0000000..de3d6a0 --- /dev/null +++ b/templates/qos-policy/fair-queue/node.tag/hash-interval/node.def @@ -0,0 +1,3 @@ +type: u32 +default: 0 +help: "Rehash interval (seconds)" diff --git a/templates/qos-policy/fair-queue/node.tag/queue-limit/node.def b/templates/qos-policy/fair-queue/node.tag/queue-limit/node.def new file mode 100644 index 0000000..e6456f8 --- /dev/null +++ b/templates/qos-policy/fair-queue/node.tag/queue-limit/node.def @@ -0,0 +1,2 @@ +type: u32 +help: "Maximum queue size (packets)" diff --git a/templates/qos-policy/node.def b/templates/qos-policy/node.def new file mode 100644 index 0000000..9e04559 --- /dev/null +++ b/templates/qos-policy/node.def @@ -0,0 +1 @@ +help: "Qos policy type" diff --git a/templates/qos-policy/traffic-shaper/node.def b/templates/qos-policy/traffic-shaper/node.def new file mode 100644 index 0000000..3d623b7 --- /dev/null +++ b/templates/qos-policy/traffic-shaper/node.def @@ -0,0 +1,4 @@ +tag: +type: txt +syntax: pattern $(@) "^[^-]" ; "Qos queue name cannot start with \"-\"" +help: "Configure traffic shaping based policy" diff --git a/templates/qos-policy/traffic-shaper/node.tag/class/node.def b/templates/qos-policy/traffic-shaper/node.tag/class/node.def new file mode 100644 index 0000000..a9944bd --- /dev/null +++ b/templates/qos-policy/traffic-shaper/node.tag/class/node.def @@ -0,0 +1,4 @@ +tag: +type: u32 +help: "Configure class handle" +syntax: ($(@) > 1 && $(@) < 65536) ; "$(@) handle must be between 2 and 65535" diff --git a/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/burst/node.def b/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/burst/node.def new file mode 100644 index 0000000..d32af54 --- /dev/null +++ b/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/burst/node.def @@ -0,0 +1,3 @@ +type: txt +help: "Set the burst size for this class" +syntax: exec "/opt/vyatta/sbin/vyatta-qos-util.pl --burst \"$(@)\"" diff --git a/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/ceiling/node.def b/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/ceiling/node.def new file mode 100644 index 0000000..ad78fa2 --- /dev/null +++ b/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/ceiling/node.def @@ -0,0 +1,4 @@ +type: txt +help: "Set the limit for this class" +syntax: exec "[[ \"$(@)\" =~ \"[0-9]+(\.[0-9]*)?%\" ]] || \ + /opt/vyatta/sbin/vyatta-qos-util.pl --rate \"$(@)\"" diff --git a/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/description/node.def b/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/description/node.def new file mode 100644 index 0000000..f632aa0 --- /dev/null +++ b/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/description/node.def @@ -0,0 +1,2 @@ +type: txt +help: "Description for this traffic class" diff --git a/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/match/node.def b/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/match/node.def new file mode 100644 index 0000000..6b77136 --- /dev/null +++ b/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/match/node.def @@ -0,0 +1,4 @@ +tag: +type: txt +syntax: pattern $(@) "^[^-]" ; "Match queue name cannot start with \"-\"" +help: "Configure class matching rule name" diff --git a/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/match/node.tag/description/node.def b/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/match/node.tag/description/node.def new file mode 100644 index 0000000..e62ed79 --- /dev/null +++ b/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/match/node.tag/description/node.def @@ -0,0 +1,2 @@ +type: txt +help: "Description for this match" diff --git a/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/match/node.tag/interface/node.def b/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/match/node.tag/interface/node.def new file mode 100644 index 0000000..fa8f1cb --- /dev/null +++ b/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/match/node.tag/interface/node.def @@ -0,0 +1,11 @@ +tag: +type: txt +help: "Ethernet interface name" +syntax: exec " \ + if [ -z \"`ip link | egrep -v 'eth[0-9]+[.]' | grep $(@)`\" ]; then \ + echo Invalid ethernet interface [$(@)]; \ + exit 1 ; \ + fi ; " +#allowed: local -a array ; +# array=( /sys/class/net/{eth,vmnet}[0-9]+[^.] ) ; +# echo -n ${array[@]##*/} diff --git a/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/match/node.tag/ip/destination/address/node.def b/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/match/node.tag/ip/destination/address/node.def new file mode 100644 index 0000000..95087be --- /dev/null +++ b/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/match/node.tag/ip/destination/address/node.def @@ -0,0 +1,2 @@ +type: ipv4net +help: "Match IP destination address" diff --git a/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/match/node.tag/ip/destination/port/node.def b/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/match/node.tag/ip/destination/port/node.def new file mode 100644 index 0000000..a082a37 --- /dev/null +++ b/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/match/node.tag/ip/destination/port/node.def @@ -0,0 +1,3 @@ +type: u32 +help: "Match IP destination port" +syntax: ($(@) > 0 && $(@) < 65536) ; "port must be between 1 and 65535" diff --git a/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/match/node.tag/ip/dsfield/node.def b/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/match/node.tag/ip/dsfield/node.def new file mode 100644 index 0000000..4a9e22e --- /dev/null +++ b/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/match/node.tag/ip/dsfield/node.def @@ -0,0 +1,3 @@ +type: txt +help: "Match dsfield/TOS: either hexadecimal number (0x10) or identifier" +syntax: exec "/opt/vyatta/sbin/vyatta-qos-util.pl --dsfield \"$(@)\"" diff --git a/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/match/node.tag/ip/protocol/node.def b/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/match/node.tag/ip/protocol/node.def new file mode 100644 index 0000000..5681770 --- /dev/null +++ b/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/match/node.tag/ip/protocol/node.def @@ -0,0 +1,3 @@ +type: txt +help: "Match IP protocol name or number" +syntax: exec "/opt/vyatta/sbin/vyatta-qos-util.pl --protocol \"$(@)\"" diff --git a/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/match/node.tag/ip/source/address/node.def b/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/match/node.tag/ip/source/address/node.def new file mode 100644 index 0000000..e20679d --- /dev/null +++ b/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/match/node.tag/ip/source/address/node.def @@ -0,0 +1,2 @@ +type: ipv4net +help: "Match IP source address" diff --git a/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/match/node.tag/ip/source/port/node.def b/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/match/node.tag/ip/source/port/node.def new file mode 100644 index 0000000..c0af33f --- /dev/null +++ b/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/match/node.tag/ip/source/port/node.def @@ -0,0 +1,3 @@ +type: u32 +help: "Match IP source port" +syntax: ($(@) > 0 && $(@) < 65536) ; "port must be between 1 and 65535" diff --git a/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/match/node.tag/vif/node.def b/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/match/node.tag/vif/node.def new file mode 100644 index 0000000..3de7d2f --- /dev/null +++ b/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/match/node.tag/vif/node.def @@ -0,0 +1,6 @@ +tag: +type: u32 +help: "VLAN ID" +syntax: $(@) >= 0 && $(@) <= 4095; "VLAN ID must be between 0 and 4095" +#comp_help: possible completions: +# <0-4095> Set VLAN ID diff --git a/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/priority/node.def b/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/priority/node.def new file mode 100644 index 0000000..72b36e2 --- /dev/null +++ b/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/priority/node.def @@ -0,0 +1,4 @@ +type: u32 +default: 1 +help: "Priority for usage of extra bandwidth" +syntax: ($(@) > 0 && $(@) < 10) ; "priority must be between 1 and 10" diff --git a/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/queue/node.def b/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/queue/node.def new file mode 100644 index 0000000..a18ecc1 --- /dev/null +++ b/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/queue/node.def @@ -0,0 +1,8 @@ +type: txt +default: "SFQ" +syntax: $(@) in "SFQ", "FIFO", "RED"; "Queue must be SFQ, FIFO, or RED" +help: "Set the queue type for this class" +#comp_help:Possible completions: +# FIFO Use FIFO queue +# RED Random Exponential Drop - TCP friendly behaviour +# SFQ Use Stochastic Fair Queue - fairness by flow (default) diff --git a/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/rate/node.def b/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/rate/node.def new file mode 100644 index 0000000..9f9721a --- /dev/null +++ b/templates/qos-policy/traffic-shaper/node.tag/class/node.tag/rate/node.def @@ -0,0 +1,11 @@ +type: txt +default: "100%" +help: "Set the base rate for this class" +syntax: exec "[[ \"$(@)\" =~ \"[0-9]+(\.[0-9]*)?%\" ]] || \ + /opt/vyatta/sbin/vyatta-qos-util.pl --rate \"$(@)\"" +#comp_help: Allowed values: +# <number>% Percentage of overall rate (default 100%) +# <number><suffix> Bitrate with scaling suffix +# bits per sec (kbit, mbit, gbit) +# bytes per sec (kbps, mbps, gbps) + diff --git a/templates/qos-policy/traffic-shaper/node.tag/default/burst/node.def b/templates/qos-policy/traffic-shaper/node.tag/default/burst/node.def new file mode 100644 index 0000000..8360670 --- /dev/null +++ b/templates/qos-policy/traffic-shaper/node.tag/default/burst/node.def @@ -0,0 +1,4 @@ +type: txt +help: "Set the burst size for default traffic" +default: "15k" +syntax: exec "/opt/vyatta/sbin/vyatta-qos-util.pl --burst \"$(@)\"" diff --git a/templates/qos-policy/traffic-shaper/node.tag/default/ceiling/node.def b/templates/qos-policy/traffic-shaper/node.tag/default/ceiling/node.def new file mode 100644 index 0000000..7c501b3 --- /dev/null +++ b/templates/qos-policy/traffic-shaper/node.tag/default/ceiling/node.def @@ -0,0 +1,6 @@ +type: txt +help: "Set the limit for default traffic" +default: "100%" +syntax: exec "[[ \"$(@)\" =~ \"[0-9]+(\.[0-9]*)?%\" ]] || \ + /opt/vyatta/sbin/vyatta-qos-util.pl --rate \"$(@)\"" + diff --git a/templates/qos-policy/traffic-shaper/node.tag/default/node.def b/templates/qos-policy/traffic-shaper/node.tag/default/node.def new file mode 100644 index 0000000..f5adce3 --- /dev/null +++ b/templates/qos-policy/traffic-shaper/node.tag/default/node.def @@ -0,0 +1 @@ +help: "Configure default policy" diff --git a/templates/qos-policy/traffic-shaper/node.tag/default/priority/node.def b/templates/qos-policy/traffic-shaper/node.tag/default/priority/node.def new file mode 100644 index 0000000..ad6b9aa --- /dev/null +++ b/templates/qos-policy/traffic-shaper/node.tag/default/priority/node.def @@ -0,0 +1,4 @@ +type: u32 +default: 8 +help: "Priority for usage of extra bandwidth" +syntax: ($(@) > 0 && $(@) < 10) ; "priority must be between 1 and 10" diff --git a/templates/qos-policy/traffic-shaper/node.tag/default/queue/node.def b/templates/qos-policy/traffic-shaper/node.tag/default/queue/node.def new file mode 100644 index 0000000..a18ecc1 --- /dev/null +++ b/templates/qos-policy/traffic-shaper/node.tag/default/queue/node.def @@ -0,0 +1,8 @@ +type: txt +default: "SFQ" +syntax: $(@) in "SFQ", "FIFO", "RED"; "Queue must be SFQ, FIFO, or RED" +help: "Set the queue type for this class" +#comp_help:Possible completions: +# FIFO Use FIFO queue +# RED Random Exponential Drop - TCP friendly behaviour +# SFQ Use Stochastic Fair Queue - fairness by flow (default) diff --git a/templates/qos-policy/traffic-shaper/node.tag/default/rate/node.def b/templates/qos-policy/traffic-shaper/node.tag/default/rate/node.def new file mode 100644 index 0000000..b12c6b6 --- /dev/null +++ b/templates/qos-policy/traffic-shaper/node.tag/default/rate/node.def @@ -0,0 +1,11 @@ +type: txt +default: "50%" +help: "Set the rate for default traffic" +syntax: exec "[[ \"$(@)\" =~ \"[0-9]+(\.[0-9]*)?%\" ]] || \ + /opt/vyatta/sbin/vyatta-qos-util.pl --rate \"$(@)\"" +#comp_help: Allowed values: +# <number>% Percentage of overall rate (default 50%) +# <number><suffix> Bitrate with scaling suffix +# bits per sec (kbit, mbit, gbit) +# bytes per sec (kbps, mbps, gbps) + diff --git a/templates/qos-policy/traffic-shaper/node.tag/description/node.def b/templates/qos-policy/traffic-shaper/node.tag/description/node.def new file mode 100644 index 0000000..335eb7e --- /dev/null +++ b/templates/qos-policy/traffic-shaper/node.tag/description/node.def @@ -0,0 +1,2 @@ +type: txt +help: "Description for this queuing policy" diff --git a/templates/qos-policy/traffic-shaper/node.tag/rate/node.def b/templates/qos-policy/traffic-shaper/node.tag/rate/node.def new file mode 100644 index 0000000..22d54b5 --- /dev/null +++ b/templates/qos-policy/traffic-shaper/node.tag/rate/node.def @@ -0,0 +1,10 @@ +type: txt +help: "Set the base rate for this policy" +default: "auto" +syntax: exec "[[ \"$(@)\" == \"auto\" ]] || \ + /opt/vyatta/sbin/vyatta-qos-util.pl --rate \"$(@)\"" +#comp_help: Allowed values: +# auto Set rate based on interface speed (default) +# <number><suffix> Bitrate with scaling suffix +# bits per sec (kbit, mbit, gbit) +# bytes per sec (kbps, mbps, gbps) |