summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Hemminger <stephen.hemminger@vyatta.com>2010-04-06 10:04:39 -0700
committerStephen Hemminger <stephen.hemminger@vyatta.com>2010-04-06 10:50:03 -0700
commit7a4dfd3f3fbaf975e6d2f766086a0e56a96bba8e (patch)
tree75cfe183460e94e7c1c4dc5fa38994e52be88c0b
parent2aa8a18e97fb5081691dca399ceada8fcae21ec7 (diff)
downloadvyatta-cfg-qos-7a4dfd3f3fbaf975e6d2f766086a0e56a96bba8e.tar.gz
vyatta-cfg-qos-7a4dfd3f3fbaf975e6d2f766086a0e56a96bba8e.zip
Preliminary support of input-policy
Support mirror and redirect. Note: traffic-limiter is broken (ignored), and will later be moved to input-policy/limit
-rw-r--r--Makefile.am3
-rw-r--r--interface-templates/input-policy/mirror/node.def3
-rw-r--r--interface-templates/input-policy/node.def3
-rw-r--r--interface-templates/input-policy/redirect/node.def3
-rw-r--r--lib/Vyatta/Qos/IngressMirror.pm56
-rw-r--r--lib/Vyatta/Qos/IngressRedirect.pm57
-rwxr-xr-xscripts/vyatta-qos.pl120
7 files changed, 197 insertions, 48 deletions
diff --git a/Makefile.am b/Makefile.am
index d70d917..818a38d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -13,11 +13,12 @@ share_perl5_DATA += lib/Vyatta/Qos/ShaperClass.pm
share_perl5_DATA += lib/Vyatta/Qos/Match.pm
share_perl5_DATA += lib/Vyatta/Qos/RateLimiter.pm
share_perl5_DATA += lib/Vyatta/Qos/DropTail.pm
-share_perl5_DATA += lib/Vyatta/Qos/TrafficLimiter.pm
share_perl5_DATA += lib/Vyatta/Qos/LimiterClass.pm
share_perl5_DATA += lib/Vyatta/Qos/RoundRobin.pm
share_perl5_DATA += lib/Vyatta/Qos/NetworkEmulator.pm
share_perl5_DATA += lib/Vyatta/Qos/RandomDetect.pm
+share_perl5_DATA += lib/Vyatta/Qos/IngressRedirect.pm
+share_perl5_DATA += lib/Vyatta/Qos/IngressMirror.pm
etcdir = /etc
etc_SCRIPTS =
diff --git a/interface-templates/input-policy/mirror/node.def b/interface-templates/input-policy/mirror/node.def
new file mode 100644
index 0000000..49fb3df
--- /dev/null
+++ b/interface-templates/input-policy/mirror/node.def
@@ -0,0 +1,3 @@
+type: txt
+help: Set incoming packet mirroring destination
+allowed: ${vyatta_sbindir}/vyatta-interfaces.pl --show=all
diff --git a/interface-templates/input-policy/node.def b/interface-templates/input-policy/node.def
new file mode 100644
index 0000000..094375e
--- /dev/null
+++ b/interface-templates/input-policy/node.def
@@ -0,0 +1,3 @@
+help: Set incoming packet policy
+update: /opt/vyatta/sbin/vyatta-qos.pl --update-ingress $IFNAME
+delete: sudo tc qdisc del dev $IFNAME ingress 2>/dev/null
diff --git a/interface-templates/input-policy/redirect/node.def b/interface-templates/input-policy/redirect/node.def
new file mode 100644
index 0000000..5582d07
--- /dev/null
+++ b/interface-templates/input-policy/redirect/node.def
@@ -0,0 +1,3 @@
+type: txt
+help: Set incoming packet redirection destination
+allowed: ${vyatta_sbindir}/vyatta-interfaces.pl --show=all
diff --git a/lib/Vyatta/Qos/IngressMirror.pm b/lib/Vyatta/Qos/IngressMirror.pm
new file mode 100644
index 0000000..d3e52c0
--- /dev/null
+++ b/lib/Vyatta/Qos/IngressMirror.pm
@@ -0,0 +1,56 @@
+# Ingress Mirror
+# Duplicate all packets to another interface
+# This is useful for some forms of IDS or capture
+#
+# **** License ****
+# 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) 2010 Vyatta, Inc.
+# All Rights Reserved.
+# **** End License ****
+
+package Vyatta::Qos::IngressMirror;
+use strict;
+use warnings;
+
+require Vyatta::Config;
+
+sub new {
+ my ( $that, $config, $name ) = @_;
+ my $self = {};
+ my $class = ref($that) || $that;
+
+ bless $self, $class;
+ $self->_define($config);
+
+ return $self;
+}
+
+# Setup new instance.
+sub _define {
+ my ( $self, $config ) = @_;
+ # config is at level: interfaces ethernet $dev input-policy redirect
+ $self->{_target} = $config->returnValue();
+}
+
+sub commands {
+ my ( $self, $dev, $parent ) = @_;
+ my $target = $self->{_target};
+
+ # Apply filter to ingress qdisc
+ # NB: action is egress because we are in ingress (upside down)
+ printf "filter add dev %s parent %x: ", $dev, $parent;
+ print " protocol all prio 10 u32";
+ print " match u32 0 0 flowid 1:1";
+ print " action mirred egress mirror dev $target\n";
+}
+
+1;
diff --git a/lib/Vyatta/Qos/IngressRedirect.pm b/lib/Vyatta/Qos/IngressRedirect.pm
new file mode 100644
index 0000000..a04018f
--- /dev/null
+++ b/lib/Vyatta/Qos/IngressRedirect.pm
@@ -0,0 +1,57 @@
+# Ingress Redirect
+# Forward all packets to another interface
+#
+# **** License ****
+# 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) 2010 Vyatta, Inc.
+# All Rights Reserved.
+# **** End License ****
+
+package Vyatta::Qos::IngressRedirect;
+use strict;
+use warnings;
+
+require Vyatta::Config;
+
+sub new {
+ my ( $that, $config, $name ) = @_;
+ my $self = {};
+ my $class = ref($that) || $that;
+
+ bless $self, $class;
+ $self->_define($config);
+
+ return $self;
+}
+
+# Setup new instance.
+sub _define {
+ my ( $self, $config, $dev ) = @_;
+ # config is at level: interfaces ethernet $dev input-policy redirect
+ $self->{_target} = $config->returnValue();
+}
+
+sub commands {
+ my ( $self, $dev, $parent ) = @_;
+ my $target = $self->{_target};
+
+ # Apply filter to ingress qdisc
+ # NB: action is egress because we are in ingress (upside down)
+ printf "filter add dev %s parent %x: ", $dev, $parent;
+ print " protocol all prio 10 u32";
+ print " match u32 0 0 flowid 1:1";
+ print " action mirred egress redirect dev $target\n";
+}
+
+1;
+
+
diff --git a/scripts/vyatta-qos.pl b/scripts/vyatta-qos.pl
index 7abfacc..b26b3c1 100755
--- a/scripts/vyatta-qos.pl
+++ b/scripts/vyatta-qos.pl
@@ -34,7 +34,6 @@ my %policies = (
'round-robin' => 'RoundRobin',
'priority-queue' => 'Priority',
'random-detect' => 'RandomDetect',
- 'traffic-limiter' => 'TrafficLimiter',
);
# find policy for name - also check for duplicates
@@ -107,13 +106,6 @@ sub delete_interface {
# ignore errors (may have no qdisc)
system($cmd);
-
- # remove IFB device if any
- my $ifb = "ifb.$interface";
- if ( -d "/sys/class/net/$ifb") {
- $cmd = "sudo ip link delete dev $ifb";
- system ($cmd);
- }
}
## start_interface('ppp0')
@@ -164,40 +156,6 @@ sub update_interface {
}
my $parent = 1;
- # Special case for traffic-limiter (not a real qdisc)
- if ($policy eq 'traffic-limiter') {
- if ($direction eq 'in') {
- $parent = 0xffff;
- print "qdisc add dev $device ingress\n";
- } else {
- print "qdisc add dev $device root handle 1: prio\n";
- }
- }
-
- # For non-ingress Qos use ifb device
- elsif ($direction eq 'in') {
- # load module but don't make any ifb's
- system("sudo modprobe ifb numifbs=0") unless ( -d '/sys/module/ifb' );
-
- # create new ifb device
- my $ifb = "ifb.$device";
- system("sudo ip link add dev $ifb type ifb") == 0
- or die "Can't create $ifb: $!";
- system("sudo ip link set dev $ifb up") == 0
- or die "Can't bring $ifb up: $!";
-
- # create ingress queue discipline
- print "qdisc add dev $device ingress\n";
-
- # redirect incoming packets to ifb
- print "filter add dev $device parent ffff: protocol all prio 10";
- print " u32 match u32 0 0 flowid 1:1";
- print " action mirred egress redirect dev $ifb\n";
-
- # tell shaper to use ifb device
- $device = $ifb;
- }
-
$shaper->commands( $device, $parent );
return if ($debug);
@@ -274,6 +232,68 @@ sub apply_policy {
}
}
+# ingress policy factory
+sub ingress_policy {
+ my ($ifname) = @_;
+ my $intf = new Vyatta::Interface($ifname);
+ die "Unknown interface name $ifname\n" unless $intf;
+
+ my $path = $intf->path();
+ die "Can't find $ifname in configuration\n" unless $path;
+
+ my $config = new Vyatta::Config;
+ $config->setLevel( "$path input-policy" );
+
+ my @names = $config->listNodes( );
+ return if $#names < 0;
+ die "Only one incoming policy is allowed\n" if ($#names > 0);
+
+ $config->setLevel( "$path input-policy " . $names[0] );
+ my $type = ucfirst($names[0]);
+ my $location = "Vyatta/Qos/Ingress$type.pm";
+ require $location;
+
+ my $class = "Vyatta::Qos::Ingress$type";
+ return $class->new( $config, $ifname );
+}
+
+# sets up input filtering
+sub update_ingress {
+ my $device = shift;
+
+ die "$device not present\n" unless (-d "/sys/class/net/$device");
+
+ my $ingress = ingress_policy( $device );
+ return unless $ingress;
+
+ # Drop existing ingress filters
+ system("sudo tc filter dev $device root 2>/dev/null");
+
+ # When doing debugging just echo the commands
+ my $out;
+ unless ($debug) {
+ open $out, "|-"
+ or exec qw:sudo /sbin/tc -batch -:
+ or die "Tc setup failed: $!\n";
+
+ select $out;
+ }
+
+ my $parent = 0xffff;
+ $ingress->commands( $device, $parent );
+ return if ($debug);
+
+ select STDOUT;
+ unless (close $out) {
+ # cleanup any partial commands
+ system("sudo tc del dev $device ingress 2>/dev/null");
+
+ # replay commands to stdout
+ $ingress->commands($device, $parent );
+ die "TC command failed.";
+ }
+}
+
sub usage {
print <<EOF;
usage: vyatta-qos.pl --list-policy direction
@@ -284,6 +304,7 @@ usage: vyatta-qos.pl --list-policy direction
vyatta-qos.pl --update-interface interface direction policy-name
vyatta-qos.pl --delete-interface interface direction
+ vyatta-qos.pl --update-ingress interface
EOF
exit 1;
}
@@ -296,22 +317,27 @@ my @applyPolicy = ();
my @deletePolicy = ();
my @startList = ();
+my $updateIngress;
+
GetOptions(
"start-interface=s" => \@startList,
"update-interface=s{3}" => \@updateInterface,
"delete-interface=s{2}" => \@deleteInterface,
-
- "list-policy=s" => \@listPolicy,
- "delete-policy=s" => \@deletePolicy,
- "create-policy=s{2}" => \@createPolicy,
- "apply-policy=s" => \@applyPolicy,
+ "list-policy=s" => \@listPolicy,
+ "delete-policy=s" => \@deletePolicy,
+ "create-policy=s{2}" => \@createPolicy,
+ "apply-policy=s" => \@applyPolicy,
+ "update-ingress=s" => \$updateIngress
) or usage();
delete_interface(@deleteInterface) if ( $#deleteInterface == 1 );
update_interface(@updateInterface) if ( $#updateInterface == 2 );
start_interface(@startList) if (@startList);
+
list_policy(@listPolicy) if (@listPolicy);
create_policy(@createPolicy) if ( $#createPolicy == 1 );
delete_policy(@deletePolicy) if (@deletePolicy);
apply_policy(@applyPolicy) if (@applyPolicy);
+update_ingress($updateIngress) if ($updateIngress);
+