summaryrefslogtreecommitdiff
path: root/scripts/VyattaQosUtil.pm
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/VyattaQosUtil.pm')
-rw-r--r--scripts/VyattaQosUtil.pm173
1 files changed, 173 insertions, 0 deletions
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;
+}