diff options
Diffstat (limited to 'regress')
122 files changed, 4241 insertions, 0 deletions
diff --git a/regress/sys/kern/sosplice/Child.pm b/regress/sys/kern/sosplice/Child.pm new file mode 100644 index 00000000000..59ab12c82d2 --- /dev/null +++ b/regress/sys/kern/sosplice/Child.pm @@ -0,0 +1,34 @@ +# $OpenBSD: Child.pm,v 1.1.1.1 2013/01/03 17:36:37 bluhm Exp $ + +# Copyright (c) 2010 Alexander Bluhm <bluhm@openbsd.org> +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +use strict; +use warnings; + +package Child; +use parent 'Proc'; + +sub new { + my $class = shift; + my %args = @_; + $args{up} ||= "Forked"; + my $self = Proc::new($class, %args); + return $self; +} + +sub child { +} + +1; diff --git a/regress/sys/kern/sosplice/Client.pm b/regress/sys/kern/sosplice/Client.pm new file mode 100644 index 00000000000..674cdeb7922 --- /dev/null +++ b/regress/sys/kern/sosplice/Client.pm @@ -0,0 +1,101 @@ +# $OpenBSD: Client.pm,v 1.1.1.1 2013/01/03 17:36:37 bluhm Exp $ + +# Copyright (c) 2010-2012 Alexander Bluhm <bluhm@openbsd.org> +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +use strict; +use warnings; + +package Client; +use parent 'Proc'; +use Carp; +use Socket qw(IPPROTO_TCP TCP_NODELAY); +use Socket6; +use IO::Socket; +use IO::Socket::INET6; + +sub new { + my $class = shift; + my %args = @_; + $args{logfile} ||= "client.log"; + $args{up} ||= "Connected"; + $args{down} ||= $args{alarm} ? "Alarm" : + "Shutdown|Broken pipe|Connection reset by peer"; + my $self = Proc::new($class, %args); + $self->{protocol} ||= "tcp"; + $self->{connectdomain} + or croak "$class connect domain not given"; + $self->{connectaddr} + or croak "$class connect addr not given"; + $self->{connectport} + or croak "$class connect port not given"; + + if ($self->{bindaddr}) { + my $cs = IO::Socket::INET6->new( + Proto => $self->{protocol}, + Domain => $self->{connectdomain}, + Blocking => ($self->{nonblocking} ? 0 : 1), + LocalAddr => $self->{bindaddr}, + LocalPort => $self->{bindport}, + ) or die ref($self), " socket connect failed: $!"; + $self->{bindaddr} = $cs->sockhost(); + $self->{bindport} = $cs->sockport(); + $self->{cs} = $cs; + } + + return $self; +} + +sub child { + my $self = shift; + + my $cs = $self->{cs} || IO::Socket::INET6->new( + Proto => $self->{protocol}, + Domain => $self->{connectdomain}, + Blocking => ($self->{nonblocking} ? 0 : 1), + ) or die ref($self), " socket connect failed: $!"; + if ($self->{oobinline}) { + setsockopt($cs, SOL_SOCKET, SO_OOBINLINE, pack('i', 1)) + or die ref($self), " set oobinline connect failed: $!"; + } + if ($self->{sndbuf}) { + setsockopt($cs, SOL_SOCKET, SO_SNDBUF, + pack('i', $self->{sndbuf})) + or die ref($self), " set sndbuf connect failed: $!"; + } + if ($self->{rcvbuf}) { + setsockopt($cs, SOL_SOCKET, SO_RCVBUF, + pack('i', $self->{rcvbuf})) + or die ref($self), " set rcvbuf connect failed: $!"; + } + if ($self->{protocol} eq "tcp") { + setsockopt($cs, IPPROTO_TCP, TCP_NODELAY, pack('i', 1)) + or die ref($self), " set nodelay connect failed: $!"; + } + my @rres = getaddrinfo($self->{connectaddr}, $self->{connectport}, + $self->{connectdomain}, SOCK_STREAM); + $cs->connect($rres[3]) + or die ref($self), " connect failed: $!"; + print STDERR "connect sock: ",$cs->sockhost()," ",$cs->sockport(),"\n"; + print STDERR "connect peer: ",$cs->peerhost()," ",$cs->peerport(),"\n"; + $self->{bindaddr} = $cs->sockhost(); + $self->{bindport} = $cs->sockport(); + + open(STDOUT, '>&', $cs) + or die ref($self), " dup STDOUT failed: $!"; + open(STDIN, '<&', $cs) + or die ref($self), " dup STDIN failed: $!"; +} + +1; diff --git a/regress/sys/kern/sosplice/Makefile b/regress/sys/kern/sosplice/Makefile new file mode 100644 index 00000000000..ece974717cc --- /dev/null +++ b/regress/sys/kern/sosplice/Makefile @@ -0,0 +1,8 @@ +# $OpenBSD: Makefile,v 1.1.1.1 2013/01/03 17:36:38 bluhm Exp $ + +SUBDIR = +SUBDIR += error +SUBDIR += tcp +SUBDIR += udp + +.include <bsd.subdir.mk> diff --git a/regress/sys/kern/sosplice/Makefile.inc b/regress/sys/kern/sosplice/Makefile.inc new file mode 100644 index 00000000000..25d8250e6e8 --- /dev/null +++ b/regress/sys/kern/sosplice/Makefile.inc @@ -0,0 +1,44 @@ +# $OpenBSD: Makefile.inc,v 1.1.1.1 2013/01/03 17:36:38 bluhm Exp $ + +# The following ports must be installed for the regression tests: +# p5-BSD-Socket-Splice perl interface to OpenBSD socket splicing +# p5-IO-Socket-INET6 object interface for AF_INET and AF_INET6 domain sockets +# p5-Socket6 Perl defines relating to AF_INET6 sockets + +ARGS != cd ${.CURDIR} && ls args-*.pl +TARGETS ?= ${ARGS} +REGRESS_TARGETS = ${TARGETS:S/^/run-regress-/} +CLEANFILES = *.log ktrace.out stamp-* + +# Fill out these variables if you want to test socket splicing with +# the relay process running on a remote machine. You have to specify +# a local and remote ip address for the tcp connections. To control +# the remote machine you need a hostname for ssh to log in. All the +# test files must be in the same directory local and remote. + +LOCAL_ADDR ?= +REMOTE_ADDR ?= +REMOTE_SSH ?= + +# Set variables so that make runs with and without obj directory. +# Only do that if necessary to keep visible output short. + +.if ${.CURDIR} == ${.OBJDIR} +PERLINC = -I.. +PERLPATH = +.else +PERLINC = -I${.CURDIR}/.. +PERLPATH = ${.CURDIR}/ +.endif + +# make perl syntax check for all args files + +.PHONY: syntax + +syntax: stamp-syntax + +stamp-syntax: ${ARGS} +.for a in ${ARGS} + @perl -c ${PERLPATH}$a +.endfor + @date >$@ diff --git a/regress/sys/kern/sosplice/Proc.pm b/regress/sys/kern/sosplice/Proc.pm new file mode 100644 index 00000000000..08d3301c6eb --- /dev/null +++ b/regress/sys/kern/sosplice/Proc.pm @@ -0,0 +1,159 @@ +# $OpenBSD: Proc.pm,v 1.1.1.1 2013/01/03 17:36:37 bluhm Exp $ + +# Copyright (c) 2010-2012 Alexander Bluhm <bluhm@openbsd.org> +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +use strict; +use warnings; + +package Proc; +use Carp; +use List::Util qw(first); +use POSIX; +use Time::HiRes qw(time alarm sleep); + +my %CHILDREN; + +BEGIN { + $SIG{TERM} = $SIG{INT} = sub { + my $sig = shift; + kill TERM => keys %CHILDREN; + $SIG{TERM} = $SIG{INT} = 'DEFAULT'; + POSIX::raise($sig); + }; +} + +END { + kill TERM => keys %CHILDREN; + $SIG{TERM} = $SIG{INT} = 'DEFAULT'; +} + +sub new { + my $class = shift; + my $self = { @_ }; + $self->{down} ||= $self->{alarm} ? "Alarm" : "Shutdown"; + $self->{func} && ref($self->{func}) eq 'CODE' + or croak "$class func not given"; + $self->{logfile} + or croak "$class log file not given"; + open(my $fh, '>', $self->{logfile}) + or die "$class log file $self->{logfile} create failed: $!"; + $fh->autoflush; + $self->{log} = $fh; + return bless $self, $class; +} + +sub run { + my $self = shift; + + defined(my $pid = fork()) + or die ref($self), " fork child failed"; + if ($pid) { + $CHILDREN{$pid} = 1; + $self->{pid} = $pid; + return $self; + } + %CHILDREN = (); + $SIG{TERM} = $SIG{INT} = 'DEFAULT'; + $SIG{__DIE__} = sub { + die @_ if $^S; + warn @_; + IO::Handle::flush(\*STDERR); + POSIX::_exit(255); + }; + open(STDERR, '>&', $self->{log}) + or die ref($self), " dup STDERR failed: $!"; + + $self->child(); + print STDERR $self->{up}, "\n"; + alarm($self->{alarm}) if $self->{alarm}; + $self->{func}->($self); + print STDERR "Shutdown", "\n"; + IO::Handle::flush(\*STDOUT); + IO::Handle::flush(\*STDERR); + + POSIX::_exit(0); +} + +sub wait { + my $self = shift; + my $flags = shift; + + my $pid = $self->{pid} + or croak ref($self), " no child pid"; + my $kid = waitpid($pid, $flags); + if ($kid > 0) { + my $status = $?; + my $code; + $code = "exit: ". WEXITSTATUS($?) if WIFEXITED($?); + $code = "signal: ". WTERMSIG($?) if WIFSIGNALED($?); + $code = "stop: ". WSTOPSIG($?) if WIFSTOPPED($?); + return wantarray ? ($kid, $status, $code) : $kid; + } + return $kid; +} + +sub loggrep { + my $self = shift; + my($regex, $timeout) = @_; + + my $end = time() + $timeout if $timeout; + + do { + my($kid, $status, $code) = $self->wait(WNOHANG); + if ($self->{alarm} && $kid > 0 && + WIFSIGNALED($status) && WTERMSIG($status) == 14 ) { + # child killed by SIGALRM as expected + print {$self->{log}} "Alarm", "\n"; + } elsif ($kid > 0 && $status != 0) { + # child terminated with failure + die ref($self), " child status: $status $code"; + } + open(my $fh, '<', $self->{logfile}) + or die ref($self), " log file open failed: $!"; + my $match = first { /$regex/ } <$fh>; + return $match if $match; + close($fh); + # pattern not found + if ($kid == 0) { + # child still running, wait for log data + sleep .1; + } else { + # child terminated, no new log data possible + return; + } + } while ($timeout and time() < $end); + + return; +} + +sub up { + my $self = shift; + my $timeout = shift || 10; + $self->loggrep(qr/$self->{up}/, $timeout) + or croak ref($self), " no $self->{up} in $self->{logfile} ". + "after $timeout seconds"; + return $self; +} + +sub down { + my $self = shift; + my $timeout = shift || 30; + $self->loggrep(qr/$self->{down}/, $timeout) + or croak ref($self), " no $self->{down} in $self->{logfile} ". + "after $timeout seconds"; + return $self; +} + +1; diff --git a/regress/sys/kern/sosplice/Relay.pm b/regress/sys/kern/sosplice/Relay.pm new file mode 100644 index 00000000000..4cd9527ed27 --- /dev/null +++ b/regress/sys/kern/sosplice/Relay.pm @@ -0,0 +1,135 @@ +# $OpenBSD: Relay.pm,v 1.1.1.1 2013/01/03 17:36:37 bluhm Exp $ + +# Copyright (c) 2010 Alexander Bluhm <bluhm@openbsd.org> +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +use strict; +use warnings; + +package Relay; +use parent 'Proc'; +use Carp; +use Socket qw(IPPROTO_TCP TCP_NODELAY); +use Socket6; +use IO::Socket; +use IO::Socket::INET6; + +sub new { + my $class = shift; + my %args = @_; + $args{logfile} ||= "relay.log"; + $args{up} ||= "Connected"; + $args{forward} + or croak "$class forward not given"; + my $self = Proc::new($class, %args); + $self->{protocol} ||= "tcp"; + $self->{listendomain} + or croak "$class listen domain not given"; + $self->{connectdomain} + or croak "$class connect domain not given"; + $self->{connectaddr} + or croak "$class connect addr not given"; + $self->{connectport} + or croak "$class connect port not given"; + my $ls = IO::Socket::INET6->new( + Proto => $self->{protocol}, + ReuseAddr => 1, + Domain => $self->{listendomain}, + $self->{listenaddr} ? (LocalAddr => $self->{listenaddr}) : (), + $self->{listenport} ? (LocalPort => $self->{listenport}) : (), + ) or die ref($self), " socket failed: $!"; + if ($self->{oobinline}) { + setsockopt($ls, SOL_SOCKET, SO_OOBINLINE, pack('i', 1)) + or die ref($self), " set oobinline listen failed: $!"; + } + if ($self->{sndbuf}) { + setsockopt($ls, SOL_SOCKET, SO_SNDBUF, + pack('i', $self->{sndbuf})) + or die ref($self), " set sndbuf listen failed: $!"; + } + if ($self->{rcvbuf}) { + setsockopt($ls, SOL_SOCKET, SO_RCVBUF, + pack('i', $self->{rcvbuf})) + or die ref($self), " set rcvbuf listen failed: $!"; + } + if ($self->{protocol} eq "tcp") { + setsockopt($ls, IPPROTO_TCP, TCP_NODELAY, pack('i', 1)) + or die ref($self), " set nodelay listen failed: $!"; + listen($ls, 1) + or die ref($self), " listen failed: $!"; + } + my $log = $self->{log}; + print $log "listen sock: ",$ls->sockhost()," ",$ls->sockport(),"\n"; + $self->{listenaddr} = $ls->sockhost() unless $self->{listenaddr}; + $self->{listenport} = $ls->sockport() unless $self->{listenport}; + $self->{ls} = $ls; + return $self; +} + +sub child { + my $self = shift; + + my $as = $self->{ls}; + if ($self->{protocol} eq "tcp") { + $as = $self->{ls}->accept() + or die ref($self), " socket accept failed: $!"; + print STDERR "accept sock: ",$as->sockhost()," ", + $as->sockport(),"\n"; + print STDERR "accept peer: ",$as->peerhost()," ", + $as->peerport(),"\n"; + } + $as->blocking($self->{nonblocking} ? 0 : 1) + or die ref($self), " non-blocking accept failed: $!"; + + open(STDIN, '<&', $as) + or die ref($self), " dup STDIN failed: $!"; + print STDERR "Accepted\n"; + + my $cs = IO::Socket::INET6->new( + Proto => $self->{protocol}, + Domain => $self->{connectdomain}, + Blocking => ($self->{nonblocking} ? 0 : 1), + ) or die ref($self), " socket connect failed: $!"; + if ($self->{oobinline}) { + setsockopt($cs, SOL_SOCKET, SO_OOBINLINE, pack('i', 1)) + or die ref($self), " set oobinline connect failed: $!"; + } + if ($self->{sndbuf}) { + setsockopt($cs, SOL_SOCKET, SO_SNDBUF, + pack('i', $self->{sndbuf})) + or die ref($self), " set sndbuf connect failed: $!"; + } + if ($self->{rcvbuf}) { + setsockopt($cs, SOL_SOCKET, SO_RCVBUF, + pack('i', $self->{rcvbuf})) + or die ref($self), " set rcvbuf connect failed: $!"; + } + if ($self->{protocol} eq "tcp") { + setsockopt($cs, IPPROTO_TCP, TCP_NODELAY, pack('i', 1)) + or die ref($self), " set nodelay connect failed: $!"; + } + my @rres = getaddrinfo($self->{connectaddr}, $self->{connectport}, + $self->{connectdomain}, SOCK_STREAM); + $cs->connect($rres[3]) + or die ref($self), " connect failed: $!"; + print STDERR "connect sock: ",$cs->sockhost()," ",$cs->sockport(),"\n"; + print STDERR "connect peer: ",$cs->peerhost()," ",$cs->peerport(),"\n"; + $self->{bindaddr} = $cs->sockhost(); + $self->{bindport} = $cs->sockport(); + + open(STDOUT, '>&', $cs) + or die ref($self), " dup STDOUT failed: $!"; +} + +1; diff --git a/regress/sys/kern/sosplice/Remote.pm b/regress/sys/kern/sosplice/Remote.pm new file mode 100644 index 00000000000..94880e1226f --- /dev/null +++ b/regress/sys/kern/sosplice/Remote.pm @@ -0,0 +1,76 @@ +# $OpenBSD: Remote.pm,v 1.1.1.1 2013/01/03 17:36:38 bluhm Exp $ + +# Copyright (c) 2010 Alexander Bluhm <bluhm@openbsd.org> +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +use strict; +use warnings; + +package Remote; +use parent 'Proc'; +use Carp; +use Cwd; +use File::Basename; + +sub new { + my $class = shift; + my %args = @_; + $args{logfile} ||= "remote.log"; + $args{up} ||= "Started"; + $args{func} = sub { Carp::confess "$class func may not be called" }; + $args{remotessh} + or croak "$class remote ssh host not given"; + $args{forward} + or croak "$class forward not given"; + my $self = Proc::new($class, %args); + $self->{listenaddr} + or croak "$class listen addr not given"; + $self->{connectaddr} + or croak "$class connect addr not given"; + $self->{connectport} + or croak "$class connect port not given"; + return $self; +} + +sub up { + my $self = Proc::up(shift, @_); + my $timeout = shift || 10; + my $lsock = $self->loggrep(qr/^listen sock: /, $timeout) + or croak ref($self), " no listen sock in $self->{logfile} ". + "after $timeout seconds"; + my($addr, $port) = $lsock =~ /: (\S+) (\S+)$/ + or croak ref($self), " no listen addr and port in $self->{logfile}"; + $self->{listenaddr} = $addr; + $self->{listenport} = $port; + return $self; +} + +sub child { + my $self = shift; + + print STDERR $self->{up}, "\n"; + my @opts = split(' ', $ENV{SSH_OPTIONS}) if $ENV{SSH_OPTIONS}; + my $dir = dirname($0); + $dir = getcwd() if ! $dir || $dir eq '.'; + my @cmd = ('ssh', '-n', @opts, $self->{remotessh}, 'perl', + '-I', "$dir/..", "$dir/".basename($0), $self->{forward}, + $self->{listenaddr}, $self->{connectaddr}, $self->{connectport}, + ($self->{testfile} ? "$dir/".basename($self->{testfile}) : + ())); + print STDERR "execute: @cmd\n"; + exec @cmd; + die "Exec @cmd failed: $!"; +} + +1; diff --git a/regress/sys/kern/sosplice/Server.pm b/regress/sys/kern/sosplice/Server.pm new file mode 100644 index 00000000000..e9b831dd7e0 --- /dev/null +++ b/regress/sys/kern/sosplice/Server.pm @@ -0,0 +1,93 @@ +# $OpenBSD: Server.pm,v 1.1.1.1 2013/01/03 17:36:38 bluhm Exp $ + +# Copyright (c) 2010 Alexander Bluhm <bluhm@openbsd.org> +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +use strict; +use warnings; + +package Server; +use parent 'Proc'; +use Carp; +use Socket qw(IPPROTO_TCP TCP_NODELAY); +use Socket6; +use IO::Socket; +use IO::Socket::INET6; + +sub new { + my $class = shift; + my %args = @_; + $args{logfile} ||= "server.log"; + $args{up} ||= "Accepted"; + my $self = Proc::new($class, %args); + $self->{protocol} ||= "tcp"; + $self->{listendomain} + or croak "$class listen domain not given"; + my $ls = IO::Socket::INET6->new( + Proto => $self->{protocol}, + ReuseAddr => 1, + Domain => $self->{listendomain}, + $self->{listenaddr} ? (LocalAddr => $self->{listenaddr}) : (), + $self->{listenport} ? (LocalPort => $self->{listenport}) : (), + ) or die ref($self), " socket failed: $!"; + if ($self->{oobinline}) { + setsockopt($ls, SOL_SOCKET, SO_OOBINLINE, pack('i', 1)) + or die ref($self), " set oobinline listen failed: $!"; + } + if ($self->{sndbuf}) { + setsockopt($ls, SOL_SOCKET, SO_SNDBUF, + pack('i', $self->{sndbuf})) + or die ref($self), " set sndbuf listen failed: $!"; + } + if ($self->{rcvbuf}) { + setsockopt($ls, SOL_SOCKET, SO_RCVBUF, + pack('i', $self->{rcvbuf})) + or die ref($self), " set rcvbuf listen failed: $!"; + } + if ($self->{protocol} eq "tcp") { + setsockopt($ls, IPPROTO_TCP, TCP_NODELAY, pack('i', 1)) + or die ref($self), " set nodelay listen failed: $!"; + listen($ls, 1) + or die ref($self), " socket failed: $!"; + } + my $log = $self->{log}; + print $log "listen sock: ",$ls->sockhost()," ",$ls->sockport(),"\n"; + $self->{listenaddr} = $ls->sockhost() unless $self->{listenaddr}; + $self->{listenport} = $ls->sockport() unless $self->{listenport}; + $self->{ls} = $ls; + return $self; +} + +sub child { + my $self = shift; + + my $as = $self->{ls}; + if ($self->{protocol} eq "tcp") { + $as = $self->{ls}->accept() + or die ref($self), " socket accept failed: $!"; + print STDERR "accept sock: ",$as->sockhost()," ", + $as->sockport(),"\n"; + print STDERR "accept peer: ",$as->peerhost()," ", + $as->peerport(),"\n"; + } + $as->blocking($self->{nonblocking} ? 0 : 1) + or die ref($self), " non-blocking accept failed: $!"; + + open(STDIN, '<&', $as) + or die ref($self), " dup STDIN failed: $!"; + open(STDOUT, '>&', $as) + or die ref($self), " dup STDOUT failed: $!"; +} + +1; diff --git a/regress/sys/kern/sosplice/error/Makefile b/regress/sys/kern/sosplice/error/Makefile new file mode 100644 index 00000000000..6c2dadb7889 --- /dev/null +++ b/regress/sys/kern/sosplice/error/Makefile @@ -0,0 +1,15 @@ +# $OpenBSD: Makefile,v 1.1.1.1 2013/01/03 17:36:39 bluhm Exp $ + +.include <bsd.regress.mk> + +# The error tests try to splice unsuitable sockets and check the +# kernel error code. + +.for a in ${ARGS} +run-regress-$a: $a +.if empty (REMOTE_SSH) + time perl ${PERLINC} ${PERLPATH}error.pl ${PERLPATH}$a +.else + time perl ${PERLINC} ${PERLPATH}remote.pl ${REMOTE_SSH} ${PERLPATH}$a +.endif +.endfor diff --git a/regress/sys/kern/sosplice/error/args-EBUSY.pl b/regress/sys/kern/sosplice/error/args-EBUSY.pl new file mode 100644 index 00000000000..85375681575 --- /dev/null +++ b/regress/sys/kern/sosplice/error/args-EBUSY.pl @@ -0,0 +1,41 @@ +# test EBUSY for splicing from a spliced socket + +use strict; +use warnings; +use IO::Socket; +use BSD::Socket::Splice "SO_SPLICE"; + +our %args = ( + errno => 'EBUSY', + func => sub { + my $sl = IO::Socket::INET->new( + Proto => "tcp", + Listen => 5, + LocalAddr => "127.0.0.1", + ) or die "socket listen failed: $!"; + + my $s = IO::Socket::INET->new( + Proto => "tcp", + PeerAddr => $sl->sockhost(), + PeerPort => $sl->sockport(), + ) or die "socket connect failed: $!"; + + my $ss = IO::Socket::INET->new( + Proto => "tcp", + PeerAddr => $sl->sockhost(), + PeerPort => $sl->sockport(), + ) or die "socket splice connect failed: $!"; + + $s->setsockopt(SOL_SOCKET, SO_SPLICE, pack('i', $ss->fileno())) + or die "splice failed: $!"; + + my $so = IO::Socket::INET->new( + Proto => "tcp", + PeerAddr => $sl->sockhost(), + PeerPort => $sl->sockport(), + ) or die "socket other failed: $!"; + + $s->setsockopt(SOL_SOCKET, SO_SPLICE, pack('i', $so->fileno())) + and die "splice from spliced socket succeeded"; + }, +); diff --git a/regress/sys/kern/sosplice/error/args-ENOTCONN.pl b/regress/sys/kern/sosplice/error/args-ENOTCONN.pl new file mode 100644 index 00000000000..484e1fc5725 --- /dev/null +++ b/regress/sys/kern/sosplice/error/args-ENOTCONN.pl @@ -0,0 +1,22 @@ +# test ENOTCONN for splicing from unconnected socket + +use strict; +use warnings; +use IO::Socket; +use BSD::Socket::Splice "SO_SPLICE"; + +our %args = ( + errno => 'ENOTCONN', + func => sub { + my $s = IO::Socket::INET->new( + Proto => "tcp", + ) or die "socket failed: $!"; + + my $ss = IO::Socket::INET->new( + Proto => "tcp", + ) or die "socket splice failed: $!"; + + $s->setsockopt(SOL_SOCKET, SO_SPLICE, pack('i', $ss->fileno())) + and die "splice from unconnected socket succeeded"; + }, +); diff --git a/regress/sys/kern/sosplice/error/args-EOPNOTSUPP.pl b/regress/sys/kern/sosplice/error/args-EOPNOTSUPP.pl new file mode 100644 index 00000000000..790098618ca --- /dev/null +++ b/regress/sys/kern/sosplice/error/args-EOPNOTSUPP.pl @@ -0,0 +1,23 @@ +# test EOPNOTSUPP for splicing from listen socket + +use strict; +use warnings; +use IO::Socket; +use BSD::Socket::Splice "SO_SPLICE"; + +our %args = ( + errno => 'EOPNOTSUPP', + func => sub { + my $s = IO::Socket::INET->new( + Proto => "tcp", + Listen => 1, + ) or die "socket failed: $!"; + + my $ss = IO::Socket::INET->new( + Proto => "tcp", + ) or die "socket splice failed: $!"; + + $s->setsockopt(SOL_SOCKET, SO_SPLICE, pack('i', $ss->fileno())) + and die "splice from listen socket succeeded"; + }, +); diff --git a/regress/sys/kern/sosplice/error/args-idle-EINVAL.pl b/regress/sys/kern/sosplice/error/args-idle-EINVAL.pl new file mode 100644 index 00000000000..fccf11ecf1f --- /dev/null +++ b/regress/sys/kern/sosplice/error/args-idle-EINVAL.pl @@ -0,0 +1,39 @@ +# test EINVAL for splicing with negative idle timeout + +use strict; +use warnings; +use IO::Socket; +use BSD::Socket::Splice "SO_SPLICE"; +use Config; + +our %args = ( + errno => 'EINVAL', + func => sub { + my $sl = IO::Socket::INET->new( + Proto => "tcp", + Listen => 5, + LocalAddr => "127.0.0.1", + ) or die "socket listen failed: $!"; + + my $s = IO::Socket::INET->new( + Proto => "tcp", + PeerAddr => $sl->sockhost(), + PeerPort => $sl->sockport(), + ) or die "socket failed: $!"; + + my $ss = IO::Socket::INET->new( + Proto => "tcp", + PeerAddr => $sl->sockhost(), + PeerPort => $sl->sockport(), + ) or die "socket splice failed: $!"; + + my $packed; + if ($Config{longsize} == 8) { + $packed = pack('iiiiiiii', $ss->fileno(),0,0,0,-1,-1,-1,-1); + } else { + $packed = pack('iiiii', $ss->fileno(),0,0,-1,-1); + } + $s->setsockopt(SOL_SOCKET, SO_SPLICE, $packed) + and die "splice to unconnected socket succeeded"; + }, +); diff --git a/regress/sys/kern/sosplice/error/args-max-EINVAL.pl b/regress/sys/kern/sosplice/error/args-max-EINVAL.pl new file mode 100644 index 00000000000..e61d83a81b5 --- /dev/null +++ b/regress/sys/kern/sosplice/error/args-max-EINVAL.pl @@ -0,0 +1,39 @@ +# test EINVAL for splicing with negative maximum + +use strict; +use warnings; +use IO::Socket; +use BSD::Socket::Splice "SO_SPLICE"; +use Config; + +our %args = ( + errno => 'EINVAL', + func => sub { + my $sl = IO::Socket::INET->new( + Proto => "tcp", + Listen => 5, + LocalAddr => "127.0.0.1", + ) or die "socket listen failed: $!"; + + my $s = IO::Socket::INET->new( + Proto => "tcp", + PeerAddr => $sl->sockhost(), + PeerPort => $sl->sockport(), + ) or die "socket failed: $!"; + + my $ss = IO::Socket::INET->new( + Proto => "tcp", + PeerAddr => $sl->sockhost(), + PeerPort => $sl->sockport(), + ) or die "socket splice failed: $!"; + + my $packed; + if ($Config{longsize} == 8) { + $packed = pack('iiiiiiii', $ss->fileno(),0,-1,-1,0,0,0,0); + } else { + $packed = pack('iiiii', $ss->fileno(),-1,-1,0,0); + } + $s->setsockopt(SOL_SOCKET, SO_SPLICE, $packed) + and die "splice to unconnected socket succeeded"; + }, +); diff --git a/regress/sys/kern/sosplice/error/args-splice-EBADF.pl b/regress/sys/kern/sosplice/error/args-splice-EBADF.pl new file mode 100644 index 00000000000..acc86323cc0 --- /dev/null +++ b/regress/sys/kern/sosplice/error/args-splice-EBADF.pl @@ -0,0 +1,26 @@ +# test EBADF for splicing with non existing fileno + +use strict; +use warnings; +use IO::Socket; +use BSD::Socket::Splice "SO_SPLICE"; + +our %args = ( + errno => 'EBADF', + func => sub { + my $sl = IO::Socket::INET->new( + Proto => "tcp", + Listen => 5, + LocalAddr => "127.0.0.1", + ) or die "socket listen failed: $!"; + + my $s = IO::Socket::INET->new( + Proto => "tcp", + PeerAddr => $sl->sockhost(), + PeerPort => $sl->sockport(), + ) or die "socket failed: $!"; + + $s->setsockopt(SOL_SOCKET, SO_SPLICE, pack('i', 23)) + and die "splice with non existing fileno succeeded"; + }, +); diff --git a/regress/sys/kern/sosplice/error/args-splice-EBUSY.pl b/regress/sys/kern/sosplice/error/args-splice-EBUSY.pl new file mode 100644 index 00000000000..a5ad9f40116 --- /dev/null +++ b/regress/sys/kern/sosplice/error/args-splice-EBUSY.pl @@ -0,0 +1,41 @@ +# test EBUSY for splicing to a spliced socket + +use strict; +use warnings; +use IO::Socket; +use BSD::Socket::Splice "SO_SPLICE"; + +our %args = ( + errno => 'EBUSY', + func => sub { + my $sl = IO::Socket::INET->new( + Proto => "tcp", + Listen => 5, + LocalAddr => "127.0.0.1", + ) or die "socket listen failed: $!"; + + my $s = IO::Socket::INET->new( + Proto => "tcp", + PeerAddr => $sl->sockhost(), + PeerPort => $sl->sockport(), + ) or die "socket connect failed: $!"; + + my $ss = IO::Socket::INET->new( + Proto => "tcp", + PeerAddr => $sl->sockhost(), + PeerPort => $sl->sockport(), + ) or die "socket splice connect failed: $!"; + + $s->setsockopt(SOL_SOCKET, SO_SPLICE, pack('i', $ss->fileno())) + or die "splice failed: $!"; + + my $so = IO::Socket::INET->new( + Proto => "tcp", + PeerAddr => $sl->sockhost(), + PeerPort => $sl->sockport(), + ) or die "socket other failed: $!"; + + $so->setsockopt(SOL_SOCKET, SO_SPLICE, pack('i', $ss->fileno())) + and die "splice to spliced socket succeeded"; + }, +); diff --git a/regress/sys/kern/sosplice/error/args-splice-EINVAL.pl b/regress/sys/kern/sosplice/error/args-splice-EINVAL.pl new file mode 100644 index 00000000000..563426c0993 --- /dev/null +++ b/regress/sys/kern/sosplice/error/args-splice-EINVAL.pl @@ -0,0 +1,30 @@ +# test EINVAL for splicing with short fileno size + +use strict; +use warnings; +use IO::Socket; +use BSD::Socket::Splice "SO_SPLICE"; + +our %args = ( + errno => 'EINVAL', + func => sub { + my $sl = IO::Socket::INET->new( + Proto => "tcp", + Listen => 5, + LocalAddr => "127.0.0.1", + ) or die "socket listen failed: $!"; + + my $s = IO::Socket::INET->new( + Proto => "tcp", + PeerAddr => $sl->sockhost(), + PeerPort => $sl->sockport(), + ) or die "socket failed: $!"; + + my $ss = IO::Socket::INET->new( + Proto => "tcp", + ) or die "socket splice failed: $!"; + + $s->setsockopt(SOL_SOCKET, SO_SPLICE, pack('s', $ss->fileno())) + and die "splice with short fileno size succeeded"; + }, +); diff --git a/regress/sys/kern/sosplice/error/args-splice-ENOTCONN.pl b/regress/sys/kern/sosplice/error/args-splice-ENOTCONN.pl new file mode 100644 index 00000000000..4a04c16cb76 --- /dev/null +++ b/regress/sys/kern/sosplice/error/args-splice-ENOTCONN.pl @@ -0,0 +1,30 @@ +# test ENOTCONN for splicing to unconnected socket + +use strict; +use warnings; +use IO::Socket; +use BSD::Socket::Splice "SO_SPLICE"; + +our %args = ( + errno => 'ENOTCONN', + func => sub { + my $sl = IO::Socket::INET->new( + Proto => "tcp", + Listen => 5, + LocalAddr => "127.0.0.1", + ) or die "socket listen failed: $!"; + + my $s = IO::Socket::INET->new( + Proto => "tcp", + PeerAddr => $sl->sockhost(), + PeerPort => $sl->sockport(), + ) or die "socket failed: $!"; + + my $ss = IO::Socket::INET->new( + Proto => "tcp", + ) or die "socket splice failed: $!"; + + $s->setsockopt(SOL_SOCKET, SO_SPLICE, pack('i', $ss->fileno())) + and die "splice to unconnected socket succeeded"; + }, +); diff --git a/regress/sys/kern/sosplice/error/args-splice-ENOTSOCK.pl b/regress/sys/kern/sosplice/error/args-splice-ENOTSOCK.pl new file mode 100644 index 00000000000..3a240d1ff5c --- /dev/null +++ b/regress/sys/kern/sosplice/error/args-splice-ENOTSOCK.pl @@ -0,0 +1,26 @@ +# test ENOTSOCK for splicing with non-socket + +use strict; +use warnings; +use IO::Socket; +use BSD::Socket::Splice "SO_SPLICE"; + +our %args = ( + errno => 'ENOTSOCK', + func => sub { + my $sl = IO::Socket::INET->new( + Proto => "tcp", + Listen => 5, + LocalAddr => "127.0.0.1", + ) or die "socket listen failed: $!"; + + my $s = IO::Socket::INET->new( + Proto => "tcp", + PeerAddr => $sl->sockhost(), + PeerPort => $sl->sockport(), + ) or die "socket failed: $!"; + + $s->setsockopt(SOL_SOCKET, SO_SPLICE, pack('i', 0)) + and die "splice with non non-socket fileno succeeded"; + }, +); diff --git a/regress/sys/kern/sosplice/error/args-splice-EOPNOTSUPP.pl b/regress/sys/kern/sosplice/error/args-splice-EOPNOTSUPP.pl new file mode 100644 index 00000000000..d7446435c79 --- /dev/null +++ b/regress/sys/kern/sosplice/error/args-splice-EOPNOTSUPP.pl @@ -0,0 +1,31 @@ +# test EOPNOTSUPP for splicing to listen socket + +use strict; +use warnings; +use IO::Socket; +use BSD::Socket::Splice "SO_SPLICE"; + +our %args = ( + errno => 'EOPNOTSUPP', + func => sub { + my $sl = IO::Socket::INET->new( + Proto => "tcp", + Listen => 5, + LocalAddr => "127.0.0.1", + ) or die "socket listen failed: $!"; + + my $s = IO::Socket::INET->new( + Proto => "tcp", + PeerAddr => $sl->sockhost(), + PeerPort => $sl->sockport(), + ) or die "socket failed: $!"; + + my $ss = IO::Socket::INET->new( + Proto => "tcp", + Listen => 1, + ) or die "socket splice failed: $!"; + + $s->setsockopt(SOL_SOCKET, SO_SPLICE, pack('i', $ss->fileno())) + and die "splice to listen socket succeeded"; + }, +); diff --git a/regress/sys/kern/sosplice/error/args-splice-EPROTONOSUPPORT.pl b/regress/sys/kern/sosplice/error/args-splice-EPROTONOSUPPORT.pl new file mode 100644 index 00000000000..018dd0c904b --- /dev/null +++ b/regress/sys/kern/sosplice/error/args-splice-EPROTONOSUPPORT.pl @@ -0,0 +1,30 @@ +# test EPROTONOSUPPORT for splicing to udp socket + +use strict; +use warnings; +use IO::Socket; +use BSD::Socket::Splice "SO_SPLICE"; + +our %args = ( + errno => 'EPROTONOSUPPORT', + func => sub { + my $sl = IO::Socket::INET->new( + Proto => "tcp", + Listen => 5, + LocalAddr => "127.0.0.1", + ) or die "socket listen failed: $!"; + + my $s = IO::Socket::INET->new( + Proto => "tcp", + PeerAddr => $sl->sockhost(), + PeerPort => $sl->sockport(), + ) or die "socket failed: $!"; + + my $ss = IO::Socket::INET->new( + Proto => "udp", + ) or die "socket splice failed: $!"; + + $s->setsockopt(SOL_SOCKET, SO_SPLICE, pack('i', $ss->fileno())) + and die "splice to udp socket succeeded"; + }, +); diff --git a/regress/sys/kern/sosplice/error/args-udp-ENOTCONN.pl b/regress/sys/kern/sosplice/error/args-udp-ENOTCONN.pl new file mode 100644 index 00000000000..94a95d4ea9b --- /dev/null +++ b/regress/sys/kern/sosplice/error/args-udp-ENOTCONN.pl @@ -0,0 +1,27 @@ +# test ENOTCONN for splicing to unconnected udp socket + +use strict; +use warnings; +use IO::Socket; +use BSD::Socket::Splice "SO_SPLICE"; + +our %args = ( + errno => 'ENOTCONN', + func => sub { + my $sb = IO::Socket::INET->new( + Proto => "udp", + LocalAddr => "127.0.0.1", + ) or die "bind socket failed: $!"; + + my $sc = IO::Socket::INET->new( + Proto => "udp", + PeerAddr => $sb->sockhost(), + PeerPort => $sb->sockport(), + ) or die "connect socket failed: $!"; + + $sb->setsockopt(SOL_SOCKET, SO_SPLICE, pack('i', $sc->fileno())) + or die "splice from unconnected socket failed: $!"; + $sc->setsockopt(SOL_SOCKET, SO_SPLICE, pack('i', $sb->fileno())) + and die "splice to unconnected socket succeeded"; + }, +); diff --git a/regress/sys/kern/sosplice/error/args-udp-EPROTONOSUPPORT.pl b/regress/sys/kern/sosplice/error/args-udp-EPROTONOSUPPORT.pl new file mode 100644 index 00000000000..dacfa3bfb58 --- /dev/null +++ b/regress/sys/kern/sosplice/error/args-udp-EPROTONOSUPPORT.pl @@ -0,0 +1,22 @@ +# test EPROTONOSUPPORT for splicing tcp with udp sockets + +use strict; +use warnings; +use IO::Socket; +use BSD::Socket::Splice "SO_SPLICE"; + +our %args = ( + errno => 'EPROTONOSUPPORT', + func => sub { + my $s = IO::Socket::INET->new( + Proto => "udp", + ) or die "socket failed: $!"; + + my $ss = IO::Socket::INET->new( + Proto => "tcp", + ) or die "socket splice failed: $!"; + + $s->setsockopt(SOL_SOCKET, SO_SPLICE, pack('i', $ss->fileno())) + and die "splice udp sockets succeeded"; + }, +); diff --git a/regress/sys/kern/sosplice/error/args-unix-EPROTONOSUPPORT.pl b/regress/sys/kern/sosplice/error/args-unix-EPROTONOSUPPORT.pl new file mode 100644 index 00000000000..e664ec8d11f --- /dev/null +++ b/regress/sys/kern/sosplice/error/args-unix-EPROTONOSUPPORT.pl @@ -0,0 +1,23 @@ +# test EPROTONOSUPPORT for splicing unix sockets + +use strict; +use warnings; +use IO::Socket; +use BSD::Socket::Splice "SO_SPLICE"; +use IO::Socket::UNIX; + +our %args = ( + errno => 'EPROTONOSUPPORT', + func => sub { + my $s = IO::Socket::UNIX->new( + Type => SOCK_STREAM, + ) or die "socket failed: $!"; + + my $ss = IO::Socket::UNIX->new( + Type => SOCK_STREAM, + ) or die "socket splice failed: $!"; + + $s->setsockopt(SOL_SOCKET, SO_SPLICE, pack('i', $ss->fileno())) + and die "splice udp sockets succeeded"; + }, +); diff --git a/regress/sys/kern/sosplice/error/error.pl b/regress/sys/kern/sosplice/error/error.pl new file mode 100644 index 00000000000..b6a1c583a8b --- /dev/null +++ b/regress/sys/kern/sosplice/error/error.pl @@ -0,0 +1,40 @@ +#!/usr/bin/perl +# $OpenBSD: error.pl,v 1.1.1.1 2013/01/03 17:36:39 bluhm Exp $ + +# Copyright (c) 2010-2013 Alexander Bluhm <bluhm@openbsd.org> +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +use strict; +use warnings; +use Errno; + +sub usage { + die "usage: error.pl test-args.pl\n"; +} + +@ARGV == 1 or usage(); + +my $test; +our %args; +if (@ARGV and -f $ARGV[-1]) { + $test = pop; + do $test + or die "Do test file $test failed: ", $@ || $!; +} + +@ARGV == 0 or usage(); + +$args{func}->(); +$!{$args{errno}} + or die "error not $args{errno}: $!" diff --git a/regress/sys/kern/sosplice/error/remote.pl b/regress/sys/kern/sosplice/error/remote.pl new file mode 100644 index 00000000000..c3cf881544a --- /dev/null +++ b/regress/sys/kern/sosplice/error/remote.pl @@ -0,0 +1,38 @@ +#!/usr/bin/perl +# $OpenBSD: remote.pl,v 1.1.1.1 2013/01/03 17:36:39 bluhm Exp $ + +# Copyright (c) 2010-2013 Alexander Bluhm <bluhm@openbsd.org> +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +use strict; +use warnings; +use Cwd; +use File::Basename; + +sub usage { + die "usage: remote.pl remotessh test-args.pl\n"; +} + +@ARGV == 2 or usage(); + +my($remotessh, $testfile) = @ARGV; + +my @opts = split(' ', $ENV{SSH_OPTIONS}) if $ENV{SSH_OPTIONS}; +my $dir = dirname($0); +$dir = getcwd() if ! $dir || $dir eq '.'; +my @cmd = ('ssh', '-n', @opts, $remotessh, 'perl', + '-I', "$dir/..", "$dir/error.pl", "$dir/".basename($testfile)); +#print STDERR "execute: @cmd\n"; +exec @cmd; +die "Exec @cmd failed: $!"; diff --git a/regress/sys/kern/sosplice/funcs.pl b/regress/sys/kern/sosplice/funcs.pl new file mode 100644 index 00000000000..8bbf471b40a --- /dev/null +++ b/regress/sys/kern/sosplice/funcs.pl @@ -0,0 +1,653 @@ +# $OpenBSD: funcs.pl,v 1.1.1.1 2013/01/03 17:36:39 bluhm Exp $ + +# Copyright (c) 2010-2013 Alexander Bluhm <bluhm@openbsd.org> +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +use strict; +use warnings; +use feature 'switch'; +use Errno; +use Digest::MD5; +use IO::Socket qw(sockatmark); +use Socket; +use Time::HiRes qw(time alarm sleep); +use BSD::Socket::Splice qw(setsplice getsplice geterror); + +######################################################################## +# Client funcs +######################################################################## + +sub write_stream { + my $self = shift; + my $len = shift // $self->{len} // 251; + my $sleep = $self->{sleep}; + + my $ctx = Digest::MD5->new(); + my $char = '0'; + for (my $i = 1; $i < $len; $i++) { + $ctx->add($char); + print $char + or die ref($self), " print failed: $!"; + given ($char) { + when(/9/) { $char = 'A' } + when(/Z/) { $char = 'a' } + when(/z/) { $char = "\n" } + when(/\n/) { print STDERR "."; $char = '0' } + default { $char++ } + } + if ($self->{sleep}) { + IO::Handle::flush(\*STDOUT); + sleep $self->{sleep}; + } + } + if ($len) { + $char = "\n"; + $ctx->add($char); + print $char + or die ref($self), " print failed: $!"; + print STDERR ".\n"; + } + IO::Handle::flush(\*STDOUT); + + print STDERR "LEN: $len\n"; + print STDERR "MD5: ", $ctx->hexdigest, "\n"; +} + +sub write_oob { + my $self = shift; + my $len = shift // $self->{len} // 251; + + my $ctx = Digest::MD5->new(); + my $msg = ""; + my $char = '0'; + for (my $i = 1; $i < $len; $i++) { + $msg .= $char; + given ($char) { + when(/9/) { + $ctx->add("[$char]"); + defined(send(STDOUT, $msg, MSG_OOB)) + or die ref($self), " send OOB failed: $!"; + # If tcp urgent data is sent too fast, + # it may get overwritten and lost. + sleep .1; + $msg = ""; + $char = 'A'; + } + when(/Z/) { $ctx->add($char); $char = 'a' } + when(/z/) { $ctx->add($char); $char = "\n" } + when(/\n/) { + $ctx->add($char); + defined(send(STDOUT, $msg, 0)) + or die ref($self), " send failed: $!"; + print STDERR "."; + $msg = ""; + $char = '0'; + } + default { $ctx->add($char); $char++ } + } + } + if ($len) { + $char = "\n"; + $msg .= $char; + $ctx->add($char); + send(STDOUT, $msg, 0) + or die ref($self), " send failed: $!"; + print STDERR ".\n"; + } + IO::Handle::flush(\*STDOUT); + + print STDERR "LEN: $len\n"; + print STDERR "MD5: ", $ctx->hexdigest, "\n"; +} + +sub write_datagram { + my $self = shift; + my @lengths = @{$self->{lengths} || [ shift // $self->{len} // 251 ]}; + my $sleep = $self->{sleep}; + + my $len = 0; + my $ctx = Digest::MD5->new(); + my $char = '0'; + my @md5s; + for (my $num = 0; $num < @lengths; $num++) { + my $l = $lengths[$num]; + my $string = ""; + for (my $i = 1; $i < $l; $i++) { + $ctx->add($char); + $string .= $char; + given ($char) { + when(/9/) { $char = 'A' } + when(/Z/) { $char = 'a' } + when(/z/) { $char = "\n" } + when(/\n/) { $char = '0' } + default { $char++ } + } + } + if ($l) { + $char = "\n"; + $ctx->add($char); + $string .= $char; + } + defined(my $write = syswrite(STDOUT, $string)) + or die ref($self), " syswrite number $num failed: $!"; + $write == $l + or die ref($self), " syswrite length $l did write $write"; + $len += $write; + print STDERR "."; + sleep $self->{sleep} if $self->{sleep}; + } + print STDERR "\n"; + + print STDERR "LEN: $len\n"; + print STDERR "LENGTHS: @lengths\n"; + print STDERR "MD5: ", $ctx->hexdigest, "\n"; +} + +sub solingerout { + my $self = shift; + + setsockopt(STDOUT, SOL_SOCKET, SO_LINGER, pack('ii', 1, 0)) + or die ref($self), " set linger out failed: $!"; +} + +######################################################################## +# Relay funcs +######################################################################## + +sub relay_copy_stream { + my $self = shift; + my $max = $self->{max}; + my $idle = $self->{idle}; + my $size = $self->{size} || 8093; + + my $len = 0; + while (1) { + my $rin = my $win = my $ein = ''; + vec($rin, fileno(STDIN), 1) = 1; + vec($ein, fileno(STDIN), 1) = 1 unless $self->{oobinline}; + defined(my $n = select($rin, undef, $ein, $idle)) + or die ref($self), " select failed: $!"; + if ($idle && $n == 0) { + print STDERR "\n"; + print STDERR "Timeout\n"; + last; + } + my $buf; + my $atmark = sockatmark(\*STDIN) + or die ref($self), " sockatmark failed: $!"; + if ($atmark == 1) { + if ($self->{oobinline}) { + defined(recv(STDIN, $buf, 1, 0)) + or die ref($self), " recv OOB failed: $!"; + $len += length($buf); + defined(send(STDOUT, $buf, MSG_OOB)) + or die ref($self), " send OOB failed: $!"; + } else { + defined(recv(STDIN, $buf, 1, MSG_OOB)) || + $!{EINVAL} + or die ref($self), " recv OOB failed: $!"; + print STDERR "OOB: $buf\n" if length($buf); + } + } + if ($self->{nonblocking}) { + vec($rin, fileno(STDIN), 1) = 1; + select($rin, undef, undef, undef) + or die ref($self), " select read failed: $!"; + } + my $read = sysread(STDIN, $buf, + $max && $max < $size ? $max : $size); + defined($read) + or die ref($self), " sysread at $len failed: $!"; + if ($read == 0) { + print STDERR "\n"; + print STDERR "End\n"; + last; + } + print STDERR "."; + if ($max && $len + $read > $max) { + $read = $max - $len; + } + my $off = 0; + while ($off < $read) { + if ($self->{nonblocking}) { + vec($win, fileno(STDOUT), 1) = 1; + select(undef, $win, undef, undef) + or die ref($self), + " select write failed: $!"; + } + my $write; + # Unfortunately Perl installs signal handlers without + # SA_RESTART. Work around by restarting manually. + do { + $write = syswrite(STDOUT, $buf, $read - $off, + $off); + } while (!defined($write) && $!{EINTR}); + defined($write) || $!{ETIMEDOUT} + or die ref($self), " syswrite at $len failed: $!"; + defined($write) or next; + $off += $write; + $len += $write; + } + if ($max && $len == $max) { + print STDERR "\n"; + print STDERR "Max\n"; + last; + } + } + + print STDERR "LEN: $len\n"; +} + +sub relay_copy_datagram { + my $self = shift; + my $max = $self->{max}; + my $idle = $self->{idle}; + my $size = $self->{size} || 2**16; + + my $len = 0; + for (my $num = 0;; $num++) { + my $rin = my $win = ''; + if ($idle) { + vec($rin, fileno(STDIN), 1) = 1; + defined(my $n = select($rin, undef, undef, $idle)) + or die ref($self), " select idle failed: $!"; + if ($n == 0) { + print STDERR "\n"; + print STDERR "Timeout\n"; + last; + } + } elsif ($self->{nonblocking}) { + vec($rin, fileno(STDIN), 1) = 1; + select($rin, undef, undef, undef) + or die ref($self), " select read failed: $!"; + } + defined(my $read = sysread(STDIN, my $buf, $size)) + or die ref($self), " sysread number $num failed: $!"; + print STDERR "."; + + if ($max && $len + $read > $max) { + print STDERR "\n"; + print STDERR "Max\n"; + last; + } + + if ($self->{nonblocking}) { + vec($win, fileno(STDOUT), 1) = 1; + select(undef, $win, undef, undef) + or die ref($self), " select write failed: $!"; + } + defined(my $write = syswrite(STDOUT, $buf)) || $!{EMSGSIZE} + or die ref($self), " syswrite number $num failed: $!"; + if (defined($write)) { + $read == $write + or die ref($self), " syswrite read $read ". + "did write $write"; + $len += $write; + } + + if ($max && $len == $max) { + print STDERR "\n"; + print STDERR "Max\n"; + last; + } + } + + print STDERR "LEN: $len\n"; +} + +sub relay_copy { + my $self = shift; + my $protocol = $self->{protocol} || "tcp"; + + given ($protocol) { + when (/tcp/) { relay_copy_stream($self, @_) } + when (/udp/) { relay_copy_datagram($self, @_) } + default { die ref($self), " unknown protocol name: $protocol" } + } +} + +sub relay_splice { + my $self = shift; + my $max = $self->{max}; + my $idle = $self->{idle}; + + my $len = 0; + my $splicelen; + my $shortsplice = 0; + my $error; + do { + my $splicemax = $max ? $max - $len : 0; + setsplice(\*STDIN, \*STDOUT, $splicemax, $idle) + or die ref($self), " splice stdin to stdout failed: $!"; + + if ($self->{readblocking}) { + my $read; + # block by reading from the source socket + do { + # busy loop to test soreceive + $read = sysread(STDIN, my $buf, 2**16); + } while ($self->{nonblocking} && !defined($read) && + $!{EAGAIN}); + defined($read) + or die ref($self), " read blocking failed: $!"; + $read > 0 and die ref($self), + " read blocking has data: $read"; + print STDERR "Read\n"; + } else { + my $rin = ''; + vec($rin, fileno(STDIN), 1) = 1; + select($rin, undef, undef, undef) + or die ref($self), " select failed: $!"; + } + + defined($error = geterror(\*STDIN)) + or die ref($self), " get error from stdin failed: $!"; + ($! = $error) && ! $!{ETIMEDOUT} && ! $!{EMSGSIZE} + and die ref($self), " splice failed: $!"; + + defined($splicelen = getsplice(\*STDIN)) + or die ref($self), " get splice len from stdin failed: $!"; + print STDERR "SPLICELEN: $splicelen\n"; + !$max || $splicelen <= $splicemax + or die ref($self), " splice len $splicelen ". + "greater than max $splicemax"; + $len += $splicelen; + } while ($max && $max > $len && !$shortsplice++); + + if ($idle && $error == Errno::ETIMEDOUT) { + print STDERR "Timeout\n"; + } + if ($max && $max == $len) { + print STDERR "Max\n"; + } elsif ($max && $max < $len) { + die ref($self), " max $max less than len $len"; + } elsif ($max && $max > $len && $splicelen) { + die ref($self), " max $max greater than len $len"; + } elsif (!$error) { + defined(my $read = sysread(STDIN, my $buf, 2**16)) + or die ref($self), " sysread stdin failed: $!"; + $read > 0 + and die ref($self), " sysread stdin has data: $read"; + print STDERR "End\n"; + } + print STDERR "LEN: $len\n"; +} + +sub relay { + my $self = shift; + my $forward = $self->{forward}; + + given ($forward) { + when (/copy/) { relay_copy($self, @_) } + when (/splice/) { relay_splice($self, @_) } + default { die ref($self), " unknown forward name: $forward" } + } + + my $soerror; + $soerror = getsockopt(STDIN, SOL_SOCKET, SO_ERROR) + or die ref($self), " get error from stdin failed: $!"; + print STDERR "ERROR IN: ", unpack('i', $soerror), "\n"; + $soerror = getsockopt(STDOUT, SOL_SOCKET, SO_ERROR) + or die ref($self), " get error from stdout failed: $!"; + print STDERR "ERROR OUT: ", unpack('i', $soerror), "\n"; +} + +sub ioflip { + my $self = shift; + + open(my $fh, '<&', \*STDIN) + or die ref($self), " ioflip dup failed: $!"; + open(STDIN, '<&', \*STDOUT) + or die ref($self), " ioflip dup STDIN failed: $!"; + open(STDOUT, '>&', $fh) + or die ref($self), " ioflip dup STDOUT failed: $!"; + close($fh) + or die ref($self), " ioflip close failed: $!"; +} + +sub errignore { + $SIG{PIPE} = 'IGNORE'; + $SIG{__DIE__} = sub { + die @_ if $^S; + warn @_; + my $soerror; + $soerror = getsockopt(STDIN, SOL_SOCKET, SO_ERROR); + print STDERR "ERROR IN: ", unpack('i', $soerror), "\n"; + $soerror = getsockopt(STDOUT, SOL_SOCKET, SO_ERROR); + print STDERR "ERROR OUT: ", unpack('i', $soerror), "\n"; + IO::Handle::flush(\*STDERR); + POSIX::_exit(0); + }; +} + +sub shutin { + my $self = shift; + shutdown(\*STDIN, SHUT_RD) + or die ref($self), " shutdown read failed: $!"; +} + +sub shutout { + my $self = shift; + IO::Handle::flush(\*STDOUT) + or die ref($self), " flush stdout failed: $!"; + shutdown(\*STDOUT, SHUT_WR) + or die ref($self), " shutdown write failed: $!"; +} + +######################################################################## +# Server funcs +######################################################################## + +sub read_stream { + my $self = shift; + my $max = $self->{max}; + + my $ctx = Digest::MD5->new(); + my $len = 0; + while (<STDIN>) { + $len += length($_); + $ctx->add($_); + print STDERR "."; + if ($max && $len >= $max) { + print STDERR "\nMax"; + last; + } + } + print STDERR "\n"; + + print STDERR "LEN: $len\n"; + print STDERR "MD5: ", $ctx->hexdigest, "\n"; +} + +sub read_oob { + my $self = shift; + my $size = $self->{size} || 4091; + + my $ctx = Digest::MD5->new(); + my $len = 0; + while (1) { + my $rin = my $ein = ''; + vec($rin, fileno(STDIN), 1) = 1; + vec($ein, fileno(STDIN), 1) = 1 unless $self->{oobinline}; + select($rin, undef, $ein, undef) + or die ref($self), " select failed: $!"; + my $buf; + my $atmark = sockatmark(\*STDIN) + or die ref($self), " sockatmark failed: $!"; + if ($atmark == 1) { + if ($self->{oobinline}) { + defined(recv(STDIN, $buf, 1, 0)) + or die ref($self), " recv OOB failed: $!"; + print STDERR "[$buf]"; + $ctx->add("[$buf]"); + $len += length($buf); + } else { + defined(recv(STDIN, $buf, 1, MSG_OOB)) || + $!{EINVAL} + or die ref($self), " recv OOB failed: $!"; + print STDERR "OOB: $buf\n" if length($buf); + } + } + defined(recv(STDIN, $buf, $size, 0)) + or die ref($self), " recv failed: $!"; + last unless length($buf); + print STDERR $buf; + $ctx->add($buf); + $len += length($buf); + print STDERR "."; + } + print STDERR "\n"; + + print STDERR "LEN: $len\n"; + print STDERR "MD5: ", $ctx->hexdigest, "\n"; +} + +sub read_datagram { + my $self = shift; + my $num = $self->{num} // 1; + my $max = $self->{max}; + my $size = $self->{size} || 2**16; + + my $ctx = Digest::MD5->new(); + my $len = 0; + my @lengths; + for (my $i = 0; $i < $num; $i++) { + defined(my $read = sysread(STDIN, my $buf, $size)) + or die ref($self), " sysread number $i failed: $!"; + $len += $read; + push @lengths, $read; + $ctx->add($buf); + print STDERR "."; + if ($max && $len >= $max) { + print STDERR "\nMax"; + last; + } + } + print STDERR "\n"; + + print STDERR "LEN: $len\n"; + print STDERR "LENGTHS: @lengths\n"; + print STDERR "MD5: ", $ctx->hexdigest, "\n"; +} + +sub solingerin { + my $self = shift; + + setsockopt(STDIN, SOL_SOCKET, SO_LINGER, pack('ii', 1, 0)) + or die ref($self), " set linger in failed: $!"; +} + +######################################################################## +# Script funcs +######################################################################## + +sub check_logs { + my ($c, $r, $s, %args) = @_; + + return if $args{nocheck}; + + $r->loggrep(qr/^Timeout$/) or die "no relay timeout" + if $r && $args{relay}{timeout}; + $r->loggrep(qr/^Max$/) or die "no relay max" + if $r && $args{relay}{max} && $args{len}; + + check_len($c, $r, $s, %args); + check_lengths($c, $r, $s, %args); + check_md5($c, $r, $s, %args); + check_error($c, $r, $s, %args); +} + +sub check_len { + my ($c, $r, $s, %args) = @_; + + my $clen = $c->loggrep(qr/^LEN: /) // die "no client len" + unless $args{client}{nocheck}; + my $rlen = $r->loggrep(qr/^LEN: /) // die "no relay len" + if $r && ! $args{relay}{nocheck}; + my $slen = $s->loggrep(qr/^LEN: /) // die "no server len" + unless $args{server}{nocheck}; + !$clen || !$rlen || $clen eq $rlen + or die "client: $clen", "relay: $rlen", "len mismatch"; + !$rlen || !$slen || $rlen eq $slen + or die "relay: $rlen", "server: $slen", "len mismatch"; + !$clen || !$slen || $clen eq $slen + or die "client: $clen", "server: $slen", "len mismatch"; + !defined($args{len}) || !$clen || $clen eq "LEN: $args{len}\n" + or die "client: $clen", "len $args{len} expected"; + !defined($args{len}) || !$rlen || $rlen eq "LEN: $args{len}\n" + or die "relay: $rlen", "len $args{len} expected"; + !defined($args{len}) || !$slen || $slen eq "LEN: $args{len}\n" + or die "server: $slen", "len $args{len} expected"; +} + +sub check_lengths { + my ($c, $r, $s, %args) = @_; + + my $clengths = $c->loggrep(qr/^LENGTHS: /) + unless $args{client}{nocheck}; + my $slengths = $s->loggrep(qr/^LENGTHS: /) + unless $args{server}{nocheck}; + !$clengths || !$slengths || $clengths eq $slengths + or die "client: $clengths", "server: $slengths", "lengths mismatch"; + !defined($args{lengths}) || !$clengths || + $clengths eq "LENGTHS: $args{lengths}\n" + or die "client: $clengths", "lengths $args{lengths} expected"; + !defined($args{lengths}) || !$slengths || + $slengths eq "LENGTHS: $args{lengths}\n" + or die "server: $slengths", "lengths $args{lengths} expected"; +} + +sub check_md5 { + my ($c, $r, $s, %args) = @_; + + my $cmd5 = $c->loggrep(qr/^MD5: /) unless $args{client}{nocheck}; + my $smd5 = $s->loggrep(qr/^MD5: /) unless $args{server}{nocheck}; + !$cmd5 || !$smd5 || ref($args{md5}) eq 'ARRAY' || $cmd5 eq $smd5 + or die "client: $cmd5", "server: $smd5", "md5 mismatch"; + my $md5 = ref($args{md5}) eq 'ARRAY' ? + join('|', @{$args{md5}}) : $args{md5}; + !$md5 || !$cmd5 || $cmd5 =~ /^MD5: ($md5)$/ + or die "client: $cmd5", "md5 $md5 expected"; + !$md5 || !$smd5 || $smd5 =~ /^MD5: ($md5)$/ + or die "server: $smd5", "md5 $md5 expected"; +} + +sub check_error { + my ($c, $r, $s, %args) = @_; + + $args{relay}{errorin} //= 0 unless $args{relay}{nocheck}; + $args{relay}{errorout} //= 0 unless $args{relay}{nocheck}; + my %name2proc = (client => $c, relay => $r, server => $s); + foreach my $name (qw(client relay server)) { + my $p = $name2proc{$name} + or next; + $args{$name}{errorin} //= $args{$name}{error}; + if (defined($args{$name}{errorin})) { + my $ein = $p->loggrep(qr/^ERROR IN: /); + defined($ein) && + $ein eq "ERROR IN: $args{$name}{errorin}\n" + or die "$name: $ein", + "error in $args{$name}{errorin} expected"; + } + if (defined($args{$name}{errorout})) { + my $eout = $p->loggrep(qr/^ERROR OUT: /); + defined($eout) && + $eout eq "ERROR OUT: $args{$name}{errorout}\n" + or die "$name: $eout", + "error out $args{$name}{errorout} expected"; + } + } +} + +1; diff --git a/regress/sys/kern/sosplice/tcp/Makefile b/regress/sys/kern/sosplice/tcp/Makefile new file mode 100644 index 00000000000..df5dfe54b65 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/Makefile @@ -0,0 +1,25 @@ +# $OpenBSD: Makefile,v 1.1.1.1 2013/01/03 17:36:39 bluhm Exp $ + +.include <bsd.regress.mk> + +# The arg tests take a perl hash with arguments controlling the +# test parameters. Generally they consist of client, relay, server. +# The relay.pl test fork these three processes locally. The remote.pl +# test has local client and server but the relay process is running +# on a remote machine reachable with ssh. For echo.pl test the +# relay is an echo process and the client and server process share +# the same tcp connection. All tests can run with a regular userland +# copy relay or with a kernel socket splicing relay. + +.for a in ${ARGS} +run-regress-$a: $a +.if empty (REMOTE_SSH) + time perl ${PERLINC} ${PERLPATH}relay.pl copy ${PERLPATH}$a + time perl ${PERLINC} ${PERLPATH}relay.pl splice ${PERLPATH}$a + time perl ${PERLINC} ${PERLPATH}echo.pl copy ${PERLPATH}$a + time perl ${PERLINC} ${PERLPATH}echo.pl splice ${PERLPATH}$a +.else + time perl ${PERLINC} ${PERLPATH}remote.pl copy ${LOCAL_ADDR} ${REMOTE_ADDR} ${REMOTE_SSH} ${PERLPATH}$a + time perl ${PERLINC} ${PERLPATH}remote.pl splice ${LOCAL_ADDR} ${REMOTE_ADDR} ${REMOTE_SSH} ${PERLPATH}$a +.endif +.endfor diff --git a/regress/sys/kern/sosplice/tcp/args-default.pl b/regress/sys/kern/sosplice/tcp/args-default.pl new file mode 100644 index 00000000000..1caa30bc13f --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-default.pl @@ -0,0 +1,9 @@ +# test default values + +use strict; +use warnings; + +our %args = ( + len => 251, + md5 => "bc3a3f39af35fe5b1687903da2b00c7f", +); diff --git a/regress/sys/kern/sosplice/tcp/args-idle-reverse.pl b/regress/sys/kern/sosplice/tcp/args-idle-reverse.pl new file mode 100644 index 00000000000..8d87c69762b --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-idle-reverse.pl @@ -0,0 +1,25 @@ +# test non idle connection while reverse splicing gets timeout + +use strict; +use warnings; +use BSD::Socket::Splice qw(setsplice); + +our %args = ( + client => { + func => sub { errignore(@_); write_stream(@_); }, + len => 6, + sleep => 1, + }, + relay => { + func => sub { + setsplice(\*STDOUT, \*STDIN, undef, 3) + or die "reverse splice failed: $!"; + relay(@_); + }, + idle => 2, + nocheck => 1, + }, + len => 6, + md5 => "857f2261690a2305dba03062e778a73b", + noecho => 1, +); diff --git a/regress/sys/kern/sosplice/tcp/args-idle-timeout.pl b/regress/sys/kern/sosplice/tcp/args-idle-timeout.pl new file mode 100644 index 00000000000..28a1e0e0235 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-idle-timeout.pl @@ -0,0 +1,16 @@ +# test idle timeout + +use strict; +use warnings; + +our %args = ( + client => { + func => sub { sleep 1; write_stream(@_); sleep 3; }, + }, + relay => { + idle => 2, + timeout => 1, + }, + len => 251, + md5 => "bc3a3f39af35fe5b1687903da2b00c7f", +); diff --git a/regress/sys/kern/sosplice/tcp/args-idle-trickle.pl b/regress/sys/kern/sosplice/tcp/args-idle-trickle.pl new file mode 100644 index 00000000000..ca744a56ac3 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-idle-trickle.pl @@ -0,0 +1,16 @@ +# test non idle connection does not timeout by sending a byte every second + +use strict; +use warnings; + +our %args = ( + client => { + len => 6, + sleep => 1, + }, + relay => { + idle => 2, + }, + len => 6, + md5 => "857f2261690a2305dba03062e778a73b", +); diff --git a/regress/sys/kern/sosplice/tcp/args-inet6-client.pl b/regress/sys/kern/sosplice/tcp/args-inet6-client.pl new file mode 100644 index 00000000000..0a676835700 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-inet6-client.pl @@ -0,0 +1,22 @@ +# test ipv6 client + +use strict; +use warnings; +use Socket qw(AF_INET AF_INET6); + +our %args = ( + client => { + connectdomain => AF_INET6, + connectaddr => "::1", + }, + relay => { + listendomain => AF_INET6, + listenaddr => "::1", + connectdomain => AF_INET, + connectaddr => "127.0.0.1", + }, + server => { + listendomain => AF_INET, + listenaddr => "127.0.0.1", + }, +); diff --git a/regress/sys/kern/sosplice/tcp/args-inet6-server.pl b/regress/sys/kern/sosplice/tcp/args-inet6-server.pl new file mode 100644 index 00000000000..66975ce563a --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-inet6-server.pl @@ -0,0 +1,22 @@ +# test ipv6 server + +use strict; +use warnings; +use Socket qw(AF_INET AF_INET6); + +our %args = ( + client => { + connectdomain => AF_INET, + connectaddr => "127.0.0.1", + }, + relay => { + listendomain => AF_INET, + listenaddr => "127.0.0.1", + connectdomain => AF_INET6, + connectaddr => "::1", + }, + server => { + listendomain => AF_INET6, + listenaddr => "::1", + }, +); diff --git a/regress/sys/kern/sosplice/tcp/args-inet6.pl b/regress/sys/kern/sosplice/tcp/args-inet6.pl new file mode 100644 index 00000000000..c84a85f61a4 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-inet6.pl @@ -0,0 +1,22 @@ +# test ipv6 client and server + +use strict; +use warnings; +use Socket qw(AF_INET AF_INET6); + +our %args = ( + client => { + connectdomain => AF_INET6, + connectaddr => "::1", + }, + relay => { + listendomain => AF_INET6, + listenaddr => "::1", + connectdomain => AF_INET6, + connectaddr => "::1", + }, + server => { + listendomain => AF_INET6, + listenaddr => "::1", + }, +); diff --git a/regress/sys/kern/sosplice/tcp/args-long.pl b/regress/sys/kern/sosplice/tcp/args-long.pl new file mode 100644 index 00000000000..6a8da22b184 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-long.pl @@ -0,0 +1,12 @@ +# test longer data length + +use strict; +use warnings; + +our %args = ( + client => { + len => 2**17, + }, + len => 131072, + md5 => "31e5ad3d0d2aeb1ad8aaa847dfa665c2", +); diff --git a/regress/sys/kern/sosplice/tcp/args-max-sleep-client-nonblock.pl b/regress/sys/kern/sosplice/tcp/args-max-sleep-client-nonblock.pl new file mode 100644 index 00000000000..b47e156d06a --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-max-sleep-client-nonblock.pl @@ -0,0 +1,17 @@ +# test maximum data length with delay before client write with non-blocking relay + +use strict; +use warnings; + +our %args = ( + client => { + func => sub { sleep 3; write_stream(@_); }, + nocheck => 1, + }, + relay => { + max => 113, + nonblocking => 1, + }, + len => 113, + md5 => "dc099ef642faa02bce71298f11e7d44d", +); diff --git a/regress/sys/kern/sosplice/tcp/args-max-sleep-client-short.pl b/regress/sys/kern/sosplice/tcp/args-max-sleep-client-short.pl new file mode 100644 index 00000000000..a9dac043f23 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-max-sleep-client-short.pl @@ -0,0 +1,16 @@ +# test maximum data length with delay before client write + +use strict; +use warnings; + +our %args = ( + client => { + func => sub { sleep 3; write_stream(@_); }, + nocheck => 1, + }, + relay => { + max => 113, + }, + len => 113, + md5 => "dc099ef642faa02bce71298f11e7d44d", +); diff --git a/regress/sys/kern/sosplice/tcp/args-max-sleep-client.pl b/regress/sys/kern/sosplice/tcp/args-max-sleep-client.pl new file mode 100644 index 00000000000..bb5644c608a --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-max-sleep-client.pl @@ -0,0 +1,17 @@ +# test maximum data length with delay before client write + +use strict; +use warnings; + +our %args = ( + client => { + func => sub { errignore(@_); sleep 3; write_stream(@_); }, + len => 2**17, + nocheck => 1, + }, + relay => { + max => 32117, + }, + len => 32117, + md5 => "ee338e9693fb2a2ec101bb28935ed123", +); diff --git a/regress/sys/kern/sosplice/tcp/args-max-sleep-relay-short.pl b/regress/sys/kern/sosplice/tcp/args-max-sleep-relay-short.pl new file mode 100644 index 00000000000..353aa12d7cd --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-max-sleep-relay-short.pl @@ -0,0 +1,16 @@ +# test maximum data length with delay before relay copy and short len + +use strict; +use warnings; + +our %args = ( + client => { + nocheck => 1, + }, + relay => { + func => sub { sleep 3; relay(@_); }, + max => 113, + }, + len => 113, + md5 => "dc099ef642faa02bce71298f11e7d44d", +); diff --git a/regress/sys/kern/sosplice/tcp/args-max-sleep-relay.pl b/regress/sys/kern/sosplice/tcp/args-max-sleep-relay.pl new file mode 100644 index 00000000000..7363ef6fcf8 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-max-sleep-relay.pl @@ -0,0 +1,19 @@ +# test maximum data length with delay before relay copy + +use strict; +use warnings; + +our %args = ( + client => { + func => sub { errignore(@_); write_stream(@_); }, + len => 2**17, + down => "Client print failed: Broken pipe", + nocheck => 1, + }, + relay => { + func => sub { sleep 3; relay(@_); shutin(@_); sleep 1; }, + max => 32117, + }, + len => 32117, + md5 => "ee338e9693fb2a2ec101bb28935ed123", +); diff --git a/regress/sys/kern/sosplice/tcp/args-max-sleep-server.pl b/regress/sys/kern/sosplice/tcp/args-max-sleep-server.pl new file mode 100644 index 00000000000..91d2a7af8f7 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-max-sleep-server.pl @@ -0,0 +1,21 @@ +# test maximum data length with delay before server read + +use strict; +use warnings; + +our %args = ( + client => { + func => sub { errignore(@_); write_stream(@_); }, + len => 2**17, + nocheck => 1, + }, + relay => { + max => 32117, + }, + server => { + func => sub { sleep 3; read_stream(@_); }, + }, + len => 32117, + md5 => "ee338e9693fb2a2ec101bb28935ed123", + noecho => 1, +); diff --git a/regress/sys/kern/sosplice/tcp/args-max-time.pl b/regress/sys/kern/sosplice/tcp/args-max-time.pl new file mode 100644 index 00000000000..abf22c9e53b --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-max-time.pl @@ -0,0 +1,21 @@ +# test immediate data transfer after maximum data length + +use strict; +use warnings; + +our %args = ( + client => { + func => sub { $| = 1; errignore(@_); write_stream(@_); sleep(6); }, + nocheck => 1, + }, + relay => { + func => sub { relay(@_); sleep(5); }, + max => 63, + }, + server => { + func => sub { alarm(4); read_stream(@_); }, + max => 63, + }, + len => 63, + md5 => "4a3c3783fc56943715c53e435973b2ee", +); diff --git a/regress/sys/kern/sosplice/tcp/args-max.pl b/regress/sys/kern/sosplice/tcp/args-max.pl new file mode 100644 index 00000000000..889927b7a88 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-max.pl @@ -0,0 +1,17 @@ +# test maximum data length + +use strict; +use warnings; + +our %args = ( + client => { + func => sub { errignore(@_); write_stream(@_); }, + len => 2**17, + nocheck => 1, + }, + relay => { + max => 32117, + }, + len => 32117, + md5 => "ee338e9693fb2a2ec101bb28935ed123", +); diff --git a/regress/sys/kern/sosplice/tcp/args-maxcopy-sleep-client.pl b/regress/sys/kern/sosplice/tcp/args-maxcopy-sleep-client.pl new file mode 100644 index 00000000000..5f40cf86400 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-maxcopy-sleep-client.pl @@ -0,0 +1,16 @@ +# test relay maximum data length then copy with delay before client + +use strict; +use warnings; + +our %args = ( + client => { + func => sub { sleep 3; write_stream(@_); }, + }, + relay => { + func => sub { relay(@_, 61); relay_copy(@_); }, + nocheck => 1, + }, + len => 251, + md5 => "bc3a3f39af35fe5b1687903da2b00c7f", +); diff --git a/regress/sys/kern/sosplice/tcp/args-maxcopy-sleep-relay.pl b/regress/sys/kern/sosplice/tcp/args-maxcopy-sleep-relay.pl new file mode 100644 index 00000000000..088250d6fb9 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-maxcopy-sleep-relay.pl @@ -0,0 +1,13 @@ +# test relay maximum data length then copy with delay before relay + +use strict; +use warnings; + +our %args = ( + relay => { + func => sub { sleep 3; relay(@_, 61); relay_copy(@_); }, + nocheck => 1, + }, + len => 251, + md5 => "bc3a3f39af35fe5b1687903da2b00c7f", +); diff --git a/regress/sys/kern/sosplice/tcp/args-maxcopy-sleep-server.pl b/regress/sys/kern/sosplice/tcp/args-maxcopy-sleep-server.pl new file mode 100644 index 00000000000..fee64499e92 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-maxcopy-sleep-server.pl @@ -0,0 +1,16 @@ +# test relay maximum data length then copy with delay before server + +use strict; +use warnings; + +our %args = ( + relay => { + func => sub { relay(@_, 61); relay_copy(@_); }, + nocheck => 1, + }, + server => { + func => sub { sleep 3; read_stream(@_); }, + }, + len => 251, + md5 => "bc3a3f39af35fe5b1687903da2b00c7f", +); diff --git a/regress/sys/kern/sosplice/tcp/args-nonblock.pl b/regress/sys/kern/sosplice/tcp/args-nonblock.pl new file mode 100644 index 00000000000..0400c4c8641 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-nonblock.pl @@ -0,0 +1,15 @@ +# test with non-blocking relay + +use strict; +use warnings; + +our %args = ( + client => { + len => 2**17, + }, + relay => { + nonblocking => 1, + }, + len => 131072, + md5 => "31e5ad3d0d2aeb1ad8aaa847dfa665c2", +); diff --git a/regress/sys/kern/sosplice/tcp/args-null-max-sleep-client-nonblock.pl b/regress/sys/kern/sosplice/tcp/args-null-max-sleep-client-nonblock.pl new file mode 100644 index 00000000000..d065c29ed99 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-null-max-sleep-client-nonblock.pl @@ -0,0 +1,17 @@ +# test maximum data length with delay before empty client write with non-blocking relay + +use strict; +use warnings; + +our %args = ( + client => { + func => sub { sleep 3; write_stream(@_); }, + len => 0, + }, + relay => { + max => 113, + nonblocking => 1, + }, + len => 0, + md5 => "d41d8cd98f00b204e9800998ecf8427e", +); diff --git a/regress/sys/kern/sosplice/tcp/args-null-max-sleep-client.pl b/regress/sys/kern/sosplice/tcp/args-null-max-sleep-client.pl new file mode 100644 index 00000000000..4b00840c17e --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-null-max-sleep-client.pl @@ -0,0 +1,16 @@ +# test maximum data length with delay before empty client write + +use strict; +use warnings; + +our %args = ( + client => { + func => sub { sleep 3; write_stream(@_); }, + len => 0, + }, + relay => { + max => 113, + }, + len => 0, + md5 => "d41d8cd98f00b204e9800998ecf8427e", +); diff --git a/regress/sys/kern/sosplice/tcp/args-null-sleep-client.pl b/regress/sys/kern/sosplice/tcp/args-null-sleep-client.pl new file mode 100644 index 00000000000..d974ebd00e8 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-null-sleep-client.pl @@ -0,0 +1,13 @@ +# test with delay before empty client write + +use strict; +use warnings; + +our %args = ( + client => { + func => sub { sleep 3; write_stream(@_); }, + len => 0, + }, + len => 0, + md5 => "d41d8cd98f00b204e9800998ecf8427e", +); diff --git a/regress/sys/kern/sosplice/tcp/args-null.pl b/regress/sys/kern/sosplice/tcp/args-null.pl new file mode 100644 index 00000000000..bcc768ddcb8 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-null.pl @@ -0,0 +1,12 @@ +# test emtpy client write + +use strict; +use warnings; + +our %args = ( + client => { + len => 0, + }, + len => 0, + md5 => "d41d8cd98f00b204e9800998ecf8427e", +); diff --git a/regress/sys/kern/sosplice/tcp/args-oob-max-sleep-client.pl b/regress/sys/kern/sosplice/tcp/args-oob-max-sleep-client.pl new file mode 100644 index 00000000000..9fbf9c321bf --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-oob-max-sleep-client.pl @@ -0,0 +1,20 @@ +# test out-of-band data with maximum data length delay before client + +use strict; +use warnings; + +our %args = ( + client => { + func => sub { errignore(@_); sleep 3; write_oob(@_); }, + nocheck => 1, + }, + relay => { + max => 61, + nocheck => 1, + }, + server => { + func => \&read_oob, + }, + len => 61, + md5 => "e4282daf8d2ca21cc8b70b1314713314", +); diff --git a/regress/sys/kern/sosplice/tcp/args-oob-max-sleep-relay.pl b/regress/sys/kern/sosplice/tcp/args-oob-max-sleep-relay.pl new file mode 100644 index 00000000000..21fcf6fb2e6 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-oob-max-sleep-relay.pl @@ -0,0 +1,21 @@ +# test out-of-band data with maximum data length delay before relay + +use strict; +use warnings; + +our %args = ( + client => { + func => sub { errignore(@_); write_oob(@_); }, + nocheck => 1, + }, + relay => { + func => sub { sleep 3; relay(@_); }, + max => 61, + nocheck => 1, + }, + server => { + func => \&read_oob, + }, + len => 61, + md5 => "e4282daf8d2ca21cc8b70b1314713314", +); diff --git a/regress/sys/kern/sosplice/tcp/args-oob-max-sleep-server.pl b/regress/sys/kern/sosplice/tcp/args-oob-max-sleep-server.pl new file mode 100644 index 00000000000..89bc64ad986 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-oob-max-sleep-server.pl @@ -0,0 +1,20 @@ +# test out-of-band data with maximum data length delay before server + +use strict; +use warnings; + +our %args = ( + client => { + func => sub { errignore(@_); write_oob(@_); }, + nocheck => 1, + }, + relay => { + max => 61, + }, + server => { + func => sub { sleep 3; read_oob(@_); }, + }, + len => 61, + md5 => "e4282daf8d2ca21cc8b70b1314713314", + noecho => 1, +); diff --git a/regress/sys/kern/sosplice/tcp/args-oob-max.pl b/regress/sys/kern/sosplice/tcp/args-oob-max.pl new file mode 100644 index 00000000000..a46786338ba --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-oob-max.pl @@ -0,0 +1,21 @@ +# test out-of-band data with maximum data length + +use strict; +use warnings; + +our %args = ( + client => { + func => sub { errignore(@_); write_oob(@_); }, + nocheck => 1, + }, + relay => { + max => 61, + nocheck => 1, + }, + server => { + func => \&read_oob, + }, + len => 61, + md5 => "e4282daf8d2ca21cc8b70b1314713314", + noecho => 1, +); diff --git a/regress/sys/kern/sosplice/tcp/args-oob-nonblock.pl b/regress/sys/kern/sosplice/tcp/args-oob-nonblock.pl new file mode 100644 index 00000000000..69099417482 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-oob-nonblock.pl @@ -0,0 +1,20 @@ +# test out-of-band data with non-blocking relay + +use strict; +use warnings; + +our %args = ( + client => { + func => \&write_oob, + nocheck => 1, + }, + relay => { + nonblocking => 1, + nocheck => 1, + }, + server => { + func => \&read_oob, + }, + len => 247, + md5 => "f76df02a35322058b8c29002aaea944f", +); diff --git a/regress/sys/kern/sosplice/tcp/args-oob-reverse-nonblock.pl b/regress/sys/kern/sosplice/tcp/args-oob-reverse-nonblock.pl new file mode 100644 index 00000000000..b3d4b1afdab --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-oob-reverse-nonblock.pl @@ -0,0 +1,21 @@ +# test out-of-band data when reverse sending with non-blocking relay + +use strict; +use warnings; + +our %args = ( + client => { + func => \&read_oob, + }, + relay => { + func => sub { ioflip(@_); relay(@_); }, + nonblocking => 1, + nocheck => 1, + }, + server => { + func => \&write_oob, + nocheck => 1, + }, + len => 247, + md5 => "f76df02a35322058b8c29002aaea944f", +); diff --git a/regress/sys/kern/sosplice/tcp/args-oob-reverse.pl b/regress/sys/kern/sosplice/tcp/args-oob-reverse.pl new file mode 100644 index 00000000000..93b31a363c0 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-oob-reverse.pl @@ -0,0 +1,20 @@ +# test out-of-band data when reverse sending + +use strict; +use warnings; + +our %args = ( + client => { + func => \&read_oob, + }, + relay => { + func => sub { ioflip(@_); relay(@_); }, + nocheck => 1, + }, + server => { + func => \&write_oob, + nocheck => 1, + }, + len => 247, + md5 => "f76df02a35322058b8c29002aaea944f", +); diff --git a/regress/sys/kern/sosplice/tcp/args-oob.pl b/regress/sys/kern/sosplice/tcp/args-oob.pl new file mode 100644 index 00000000000..26f5dc388b5 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-oob.pl @@ -0,0 +1,19 @@ +# test out-of-band data + +use strict; +use warnings; + +our %args = ( + client => { + func => \&write_oob, + nocheck => 1, + }, + relay => { + nocheck => 1, + }, + server => { + func => \&read_oob, + }, + len => 247, + md5 => "f76df02a35322058b8c29002aaea944f", +); diff --git a/regress/sys/kern/sosplice/tcp/args-oobinline-max-sleep-client.pl b/regress/sys/kern/sosplice/tcp/args-oobinline-max-sleep-client.pl new file mode 100644 index 00000000000..d007443328e --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-oobinline-max-sleep-client.pl @@ -0,0 +1,21 @@ +# test inline out-of-band data with maximum data length delay before client + +use strict; +use warnings; + +our %args = ( + client => { + func => sub { errignore(@_); sleep 3; write_oob(@_); }, + nocheck => 1, + }, + relay => { + oobinline => 1, + max => 61, + nocheck => 1, + }, + server => { + func => \&read_oob, + }, + len => 61, + md5 => "c9f459db9b4f369980c79bff17e1c2a0", +); diff --git a/regress/sys/kern/sosplice/tcp/args-oobinline-max-sleep-relay.pl b/regress/sys/kern/sosplice/tcp/args-oobinline-max-sleep-relay.pl new file mode 100644 index 00000000000..a468c4be940 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-oobinline-max-sleep-relay.pl @@ -0,0 +1,23 @@ +# test inline out-of-band data with maximum data length delay before relay + +use strict; +use warnings; + +our %args = ( + client => { + func => sub { errignore(@_); write_oob(@_); }, + nocheck => 1, + }, + relay => { + func => sub { sleep 3; relay(@_); }, + oobinline => 1, + max => 61, + nocheck => 1, + }, + server => { + func => \&read_oob, + }, + len => 61, + # the oob data is converted to non-oob + md5 => "4b5efc5f86fa5fc873c82103ceece85d", +); diff --git a/regress/sys/kern/sosplice/tcp/args-oobinline-max-sleep-server.pl b/regress/sys/kern/sosplice/tcp/args-oobinline-max-sleep-server.pl new file mode 100644 index 00000000000..d473fb04a5d --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-oobinline-max-sleep-server.pl @@ -0,0 +1,24 @@ +# test inline out-of-band data with maximum data length delay before server + +use strict; +use warnings; + +our %args = ( + client => { + func => sub { errignore(@_); write_oob(@_); }, + nocheck => 1, + }, + relay => { + oobinline => 1, + max => 61, + }, + server => { + func => sub { sleep 3; read_oob(@_); }, + }, + len => 61, + md5 => [ + "c9f459db9b4f369980c79bff17e1c2a0", + "4b5efc5f86fa5fc873c82103ceece85d", + ], + noecho => 1, +); diff --git a/regress/sys/kern/sosplice/tcp/args-oobinline-max.pl b/regress/sys/kern/sosplice/tcp/args-oobinline-max.pl new file mode 100644 index 00000000000..c43f9038584 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-oobinline-max.pl @@ -0,0 +1,25 @@ +# test inline out-of-band data with maximum data length + +use strict; +use warnings; + +our %args = ( + client => { + func => sub { errignore(@_); write_oob(@_); }, + nocheck => 1, + }, + relay => { + oobinline => 1, + max => 61, + nocheck => 1, + }, + server => { + func => \&read_oob, + }, + len => 61, + md5 => [ + "c9f459db9b4f369980c79bff17e1c2a0", + "4b5efc5f86fa5fc873c82103ceece85d", + ], + noecho => 1, +); diff --git a/regress/sys/kern/sosplice/tcp/args-oobinline-nonblock.pl b/regress/sys/kern/sosplice/tcp/args-oobinline-nonblock.pl new file mode 100644 index 00000000000..f63724084c8 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-oobinline-nonblock.pl @@ -0,0 +1,25 @@ +# test inline out-of-band data with non-blocking relay + +use strict; +use warnings; + +our %args = ( + client => { + func => \&write_oob, + }, + relay => { + oobinline => 1, + nonblocking => 1, + }, + server => { + func => \&read_oob, + oobinline => 1, + }, + len => 251, + md5 => [ + "24b69642243fee9834bceee5b47078ae", + "5aa8135a1340e173a7d7a5fa048a999e", + "e5be513d9d2b877b6841bbb4790c67dc", + "5cf8c3fd08f541ae07361a11f17213fe", + ], +); diff --git a/regress/sys/kern/sosplice/tcp/args-oobinline-reverse-nonblock.pl b/regress/sys/kern/sosplice/tcp/args-oobinline-reverse-nonblock.pl new file mode 100644 index 00000000000..25864520af7 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-oobinline-reverse-nonblock.pl @@ -0,0 +1,26 @@ +# test inline out-of-band data when reverse sending with non-blocking relay + +use strict; +use warnings; + +our %args = ( + client => { + func => \&read_oob, + oobinline => 1, + }, + relay => { + func => sub { ioflip(@_); relay(@_); }, + oobinline => 1, + nonblocking => 1, + }, + server => { + func => \&write_oob, + }, + len => 251, + md5 => [ + "24b69642243fee9834bceee5b47078ae", + "5aa8135a1340e173a7d7a5fa048a999e", + "e5be513d9d2b877b6841bbb4790c67dc", + "5cf8c3fd08f541ae07361a11f17213fe", + ], +); diff --git a/regress/sys/kern/sosplice/tcp/args-oobinline-reverse.pl b/regress/sys/kern/sosplice/tcp/args-oobinline-reverse.pl new file mode 100644 index 00000000000..0f21d6473c8 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-oobinline-reverse.pl @@ -0,0 +1,25 @@ +# test inline out-of-band data when reverse sending + +use strict; +use warnings; + +our %args = ( + client => { + func => \&read_oob, + oobinline => 1, + }, + relay => { + func => sub { ioflip(@_); relay(@_); }, + oobinline => 1, + }, + server => { + func => \&write_oob, + }, + len => 251, + md5 => [ + "24b69642243fee9834bceee5b47078ae", + "5aa8135a1340e173a7d7a5fa048a999e", + "e5be513d9d2b877b6841bbb4790c67dc", + "5cf8c3fd08f541ae07361a11f17213fe", + ], +); diff --git a/regress/sys/kern/sosplice/tcp/args-oobinline.pl b/regress/sys/kern/sosplice/tcp/args-oobinline.pl new file mode 100644 index 00000000000..decbcc93523 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-oobinline.pl @@ -0,0 +1,24 @@ +# test inline out-of-band data + +use strict; +use warnings; + +our %args = ( + client => { + func => \&write_oob, + }, + relay => { + oobinline => 1, + }, + server => { + func => \&read_oob, + oobinline => 1, + }, + len => 251, + md5 => [ + "24b69642243fee9834bceee5b47078ae", + "5aa8135a1340e173a7d7a5fa048a999e", + "e5be513d9d2b877b6841bbb4790c67dc", + "5cf8c3fd08f541ae07361a11f17213fe", + ], +); diff --git a/regress/sys/kern/sosplice/tcp/args-relay-close-in.pl b/regress/sys/kern/sosplice/tcp/args-relay-close-in.pl new file mode 100644 index 00000000000..e01f96030e6 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-relay-close-in.pl @@ -0,0 +1,29 @@ +# test relay closes stdin after relaying some data + +use strict; +use warnings; + +our %args = ( + client => { + func => sub { errignore(@_); write_stream(@_); }, + len => 2**30, # not reached + sndbuf => 2**10, # small buffer triggers error during write + # the error message seems to be timing dependent + down => "Client print failed: (Broken pipe|Connection reset by peer)", + nocheck => 1, + error => 54, + }, + relay => { + func => sub { errignore(@_); $SIG{ALRM} = sub { close STDIN }; + alarm(3); relay(@_); }, + rcvbuf => 2**10, + sndbuf => 2**10, + down => "Bad file descriptor", + nocheck => 1, + errorin => "", + }, + server => { + rcvbuf => 2**10, + nocheck => 1, + }, +); diff --git a/regress/sys/kern/sosplice/tcp/args-relay-read-blocking.pl b/regress/sys/kern/sosplice/tcp/args-relay-read-blocking.pl new file mode 100644 index 00000000000..fe67ad42570 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-relay-read-blocking.pl @@ -0,0 +1,15 @@ +# test waiting for splice finish with blocking read + +use strict; +use warnings; + +our %args = ( + client => { + len => 2**17, + }, + relay => { + readblocking => 1, + }, + len => 131072, + md5 => "31e5ad3d0d2aeb1ad8aaa847dfa665c2", +); diff --git a/regress/sys/kern/sosplice/tcp/args-relay-read-eof.pl b/regress/sys/kern/sosplice/tcp/args-relay-read-eof.pl new file mode 100644 index 00000000000..4394efca336 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-relay-read-eof.pl @@ -0,0 +1,25 @@ +# test waiting for splice finish with read and eof has happend + +use strict; +use warnings; + +our %args = ( + client => { + # fill server buffer, relay send buffer, half relay recv buffer + # then send eof + len => 2**13 + 2**10, + }, + relay => { + nonblocking => 1, + readblocking => 1, + sndbuf => 2**12, + rcvbuf => 2**12, + }, + server => { + # wait until all buffers are filled and client sends eof + func => sub { sleep 4; read_stream(@_); }, + rcvbuf => 2**12, + }, + len => 9216, + md5 => "6d263239be35ccf30cb04c5f58a35dbe", +); diff --git a/regress/sys/kern/sosplice/tcp/args-relay-read-forked.pl b/regress/sys/kern/sosplice/tcp/args-relay-read-forked.pl new file mode 100644 index 00000000000..374e07c26ee --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-relay-read-forked.pl @@ -0,0 +1,39 @@ +# test concurrent read and splice + +use strict; +use warnings; +use POSIX; +use Time::HiRes; + +our %args = ( + client => { + len => 2**20, + }, + relay => { + nonblocking => 1, + func => sub { + defined(my $pid = fork()) + or die "relay func: fork failed: $!"; + if ($pid == 0) { + my $n; + do { + $n = sysread(STDIN, my $buf, 10); + } while (!defined($n) || $n); + POSIX::_exit(0); + } + # give the userland a moment to read, even if splicing + sleep .1; + relay(@_); + kill 9, $pid; + }, + # As sysread() may extract data from the socket before splicing starts, + # the spliced content length is not reliable. Disable the checks. + nocheck => 1, + }, + server => { + func => sub { sleep 2; read_stream(@_); }, + nocheck => 1, + }, + len => 1048576, + md5 => '6649bbec13f3d7efaedf01c0cfa54f88', +); diff --git a/regress/sys/kern/sosplice/tcp/args-relay-write-forked.pl b/regress/sys/kern/sosplice/tcp/args-relay-write-forked.pl new file mode 100644 index 00000000000..5496bd3291e --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-relay-write-forked.pl @@ -0,0 +1,38 @@ +# test concurrent write and splice + +use strict; +use warnings; +use POSIX; +use Time::HiRes; + +our %args = ( + client => { + len => 2**20, + }, + relay => { + func => sub { + defined(my $pid = fork()) + or die "relay func: fork failed: $!"; + if ($pid == 0) { + my $n; + do { + $n = syswrite(STDOUT, "\n foo bar\n"); + sleep .01; + } while (!defined($n) || $n); + POSIX::_exit(0); + } + # give the userland a moment to wite, even if splicing + sleep .1; + relay(@_); + kill 9, $pid; + }, + }, + server => { + func => sub { sleep 2; read_stream(@_); }, + # As syswrite() adds data to the socket, the content length is not + # correct. Disable the checks. + nocheck => 1, + }, + len => 1048576, + md5 => '6649bbec13f3d7efaedf01c0cfa54f88', +); diff --git a/regress/sys/kern/sosplice/tcp/args-reset-eof.pl b/regress/sys/kern/sosplice/tcp/args-reset-eof.pl new file mode 100644 index 00000000000..07b7d1a5e21 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-reset-eof.pl @@ -0,0 +1,10 @@ +# test connection reset by server at eof, after all data has been read + +use strict; +use warnings; + +our %args = ( + server => { + func => sub { read_stream(@_); sleep 3; solingerin(@_); }, + }, +); diff --git a/regress/sys/kern/sosplice/tcp/args-reset-sleep-server.pl b/regress/sys/kern/sosplice/tcp/args-reset-sleep-server.pl new file mode 100644 index 00000000000..68330ce5413 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-reset-sleep-server.pl @@ -0,0 +1,26 @@ +# test delay before server read, client sends reset during splice + +use strict; +use warnings; + +our %args = ( + client => { + alarm => 1, + func => sub { solingerout(@_); write_stream(@_); }, + len => 2**19, + nocheck => 1, + }, + relay => { + func => sub { errignore(@_); relay(@_); }, + rcvbuf => 2**10, + sndbuf => 2**10, + down => "Broken pipe|Connection reset by peer", + nocheck => 1, + }, + server => { + func => sub { sleep 3; read_stream(@_); }, + nocheck => 1, + }, + len => 131072, + md5 => "31e5ad3d0d2aeb1ad8aaa847dfa665c2", +); diff --git a/regress/sys/kern/sosplice/tcp/args-reset.pl b/regress/sys/kern/sosplice/tcp/args-reset.pl new file mode 100644 index 00000000000..2887826468c --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-reset.pl @@ -0,0 +1,23 @@ +# test connection reset by server + +use strict; +use warnings; + +our %args = ( + client => { + func => sub { errignore(@_); write_stream(@_); }, + len => 2**17, + }, + relay => { + func => sub { errignore(@_); relay(@_); }, + sndbuf => 2**12, + rcvbuf => 2**12, + down => "Broken pipe|Connection reset by peer", + }, + server => { + func => sub { sleep 3; solingerin(@_); }, + rcvbuf => 2**12, + }, + nocheck => 1, + noecho => 1, +); diff --git a/regress/sys/kern/sosplice/tcp/args-reverse-long.pl b/regress/sys/kern/sosplice/tcp/args-reverse-long.pl new file mode 100644 index 00000000000..488e37f34e5 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-reverse-long.pl @@ -0,0 +1,19 @@ +# test longer data lenght when reverse sending + +use strict; +use warnings; + +our %args = ( + client => { + func => \&read_stream, + }, + relay => { + func => sub { ioflip(@_); relay(@_); }, + }, + server => { + func => \&write_stream, + len => 2**17, + }, + len => 131072, + md5 => "31e5ad3d0d2aeb1ad8aaa847dfa665c2", +); diff --git a/regress/sys/kern/sosplice/tcp/args-reverse-nonblock.pl b/regress/sys/kern/sosplice/tcp/args-reverse-nonblock.pl new file mode 100644 index 00000000000..06591cf6697 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-reverse-nonblock.pl @@ -0,0 +1,19 @@ +# test reverse sending with non-blocking relay + +use strict; +use warnings; + +our %args = ( + client => { + func => \&read_stream, + }, + relay => { + func => sub { ioflip(@_); relay(@_); }, + nonblocking => 1, + }, + server => { + func => \&write_stream, + }, + len => 251, + md5 => "bc3a3f39af35fe5b1687903da2b00c7f", +); diff --git a/regress/sys/kern/sosplice/tcp/args-reverse-null.pl b/regress/sys/kern/sosplice/tcp/args-reverse-null.pl new file mode 100644 index 00000000000..9751b9fff00 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-reverse-null.pl @@ -0,0 +1,19 @@ +# test emtpy server write when reverse sending + +use strict; +use warnings; + +our %args = ( + client => { + func => \&read_stream, + }, + relay => { + func => sub { ioflip(@_); relay(@_); }, + }, + server => { + func => \&write_stream, + len => 0, + }, + len => 0, + md5 => "d41d8cd98f00b204e9800998ecf8427e", +); diff --git a/regress/sys/kern/sosplice/tcp/args-reverse-sleep-client.pl b/regress/sys/kern/sosplice/tcp/args-reverse-sleep-client.pl new file mode 100644 index 00000000000..65bd03caf16 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-reverse-sleep-client.pl @@ -0,0 +1,19 @@ +# test delay before client read when reverse sending + +use strict; +use warnings; + +our %args = ( + client => { + func => sub { sleep 3; read_stream(@_); }, + }, + relay => { + func => sub { ioflip(@_); relay(@_); }, + }, + server => { + func => \&write_stream, + len => 2**17, + }, + len => 131072, + md5 => "31e5ad3d0d2aeb1ad8aaa847dfa665c2", +); diff --git a/regress/sys/kern/sosplice/tcp/args-reverse-sleep-relay.pl b/regress/sys/kern/sosplice/tcp/args-reverse-sleep-relay.pl new file mode 100644 index 00000000000..aa454a72df3 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-reverse-sleep-relay.pl @@ -0,0 +1,19 @@ +# test delay before relay copy when reverse sending + +use strict; +use warnings; + +our %args = ( + client => { + func => \&read_stream, + }, + relay => { + func => sub { ioflip(@_); sleep 3; relay(@_); }, + }, + server => { + func => \&write_stream, + len => 2**17, + }, + len => 131072, + md5 => "31e5ad3d0d2aeb1ad8aaa847dfa665c2", +); diff --git a/regress/sys/kern/sosplice/tcp/args-reverse-sleep-server.pl b/regress/sys/kern/sosplice/tcp/args-reverse-sleep-server.pl new file mode 100644 index 00000000000..69f2b97885b --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-reverse-sleep-server.pl @@ -0,0 +1,19 @@ +# test delay before server write when reverse sending + +use strict; +use warnings; + +our %args = ( + client => { + func => \&read_stream, + }, + relay => { + func => sub { ioflip(@_); relay(@_); }, + }, + server => { + func => sub { sleep 3; write_stream(@_); }, + len => 2**17, + }, + len => 131072, + md5 => "31e5ad3d0d2aeb1ad8aaa847dfa665c2", +); diff --git a/regress/sys/kern/sosplice/tcp/args-reverse.pl b/regress/sys/kern/sosplice/tcp/args-reverse.pl new file mode 100644 index 00000000000..d66dcef69cb --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-reverse.pl @@ -0,0 +1,18 @@ +# test reverse sending from server to client + +use strict; +use warnings; + +our %args = ( + client => { + func => \&read_stream, + }, + relay => { + func => sub { ioflip(@_); relay(@_); }, + }, + server => { + func => \&write_stream, + }, + len => 251, + md5 => "bc3a3f39af35fe5b1687903da2b00c7f", +); diff --git a/regress/sys/kern/sosplice/tcp/args-server-abort.pl b/regress/sys/kern/sosplice/tcp/args-server-abort.pl new file mode 100644 index 00000000000..31cd885d95b --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-server-abort.pl @@ -0,0 +1,30 @@ +# test server reads and exits after reading some data + +use strict; +use warnings; + +our %args = ( + client => { + func => sub { errignore(@_); write_stream(@_); }, + len => 2**30, # not reached + sndbuf => 2**10, # small buffer triggers error during write + # the error message seems to be timing dependent + down => "Client print failed: (Broken pipe|Connection reset by peer)", + nocheck => 1, + error => 54, + }, + relay => { + func => sub { errignore(@_); relay(@_); }, + rcvbuf => 2**10, + sndbuf => 2**10, + down => "Broken pipe|Connection reset by peer", + nocheck => 1, + errorin => 0, # syscall has read the error and resetted it + errorout => 54, + }, + server => { + alarm => 3, + nocheck => 1, + }, + noecho => 1, +); diff --git a/regress/sys/kern/sosplice/tcp/args-server-exit.pl b/regress/sys/kern/sosplice/tcp/args-server-exit.pl new file mode 100644 index 00000000000..e966492ea52 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-server-exit.pl @@ -0,0 +1,31 @@ +# test server sleeps and exits without reading data + +use strict; +use warnings; + +our %args = ( + client => { + func => sub { errignore(@_); write_stream(@_); }, + len => 2**17, + sndbuf => 2**10, # small buffer triggers error during write + # the error message seems to be timing dependent + down => "Client print failed: (Broken pipe|Connection reset by peer)", + nocheck => 1, + error => 54, + }, + relay => { + func => sub { errignore(@_); relay(@_); }, + rcvbuf => 2**10, + sndbuf => 2**10, + down => "Broken pipe", + nocheck => 1, + errorin => 0, # syscall has read the error and resetted it + errorout => 54, + }, + server => { + func => sub { sleep 3; }, + rcvbuf => 2**10, + nocheck => 1, + }, + noecho => 1, +); diff --git a/regress/sys/kern/sosplice/tcp/args-short.pl b/regress/sys/kern/sosplice/tcp/args-short.pl new file mode 100644 index 00000000000..8dee78fc991 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-short.pl @@ -0,0 +1,12 @@ +# test copy with short block size + +use strict; +use warnings; + +our %args = ( + realy => { + size => 17, + }, + len => 251, + md5 => "bc3a3f39af35fe5b1687903da2b00c7f", +); diff --git a/regress/sys/kern/sosplice/tcp/args-sleep-client.pl b/regress/sys/kern/sosplice/tcp/args-sleep-client.pl new file mode 100644 index 00000000000..70f7a1f62f9 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-sleep-client.pl @@ -0,0 +1,13 @@ +# test delay before client write + +use strict; +use warnings; + +our %args = ( + client => { + func => sub { sleep 3; write_stream(@_); }, + len => 2**17, + }, + len => 131072, + md5 => "31e5ad3d0d2aeb1ad8aaa847dfa665c2", +); diff --git a/regress/sys/kern/sosplice/tcp/args-sleep-relay.pl b/regress/sys/kern/sosplice/tcp/args-sleep-relay.pl new file mode 100644 index 00000000000..8c6341bcaf0 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-sleep-relay.pl @@ -0,0 +1,15 @@ +# test delay before relay copy + +use strict; +use warnings; + +our %args = ( + client => { + len => 2**17, + }, + relay => { + func => sub { sleep 3; relay(@_); }, + }, + len => 131072, + md5 => "31e5ad3d0d2aeb1ad8aaa847dfa665c2", +); diff --git a/regress/sys/kern/sosplice/tcp/args-sleep-server.pl b/regress/sys/kern/sosplice/tcp/args-sleep-server.pl new file mode 100644 index 00000000000..ec027822f17 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-sleep-server.pl @@ -0,0 +1,15 @@ +# test delay before server read + +use strict; +use warnings; + +our %args = ( + client => { + len => 2**17, + }, + server => { + func => sub { sleep 3; read_stream(@_); }, + }, + len => 131072, + md5 => "31e5ad3d0d2aeb1ad8aaa847dfa665c2", +); diff --git a/regress/sys/kern/sosplice/tcp/args-smallbuf-sleep-client.pl b/regress/sys/kern/sosplice/tcp/args-smallbuf-sleep-client.pl new file mode 100644 index 00000000000..88227d33ee3 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-smallbuf-sleep-client.pl @@ -0,0 +1,17 @@ +# test with smaller relay send and receive buffers delay before client + +use strict; +use warnings; + +our %args = ( + client => { + func => sub { sleep 3; write_stream(@_); }, + len => 2**17, + }, + relay => { + sndbuf => 2**12, + rcvbuf => 2**12, + }, + len => 131072, + md5 => "31e5ad3d0d2aeb1ad8aaa847dfa665c2", +); diff --git a/regress/sys/kern/sosplice/tcp/args-smallbuf-sleep-relay.pl b/regress/sys/kern/sosplice/tcp/args-smallbuf-sleep-relay.pl new file mode 100644 index 00000000000..e8d430f0ecc --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-smallbuf-sleep-relay.pl @@ -0,0 +1,17 @@ +# test with smaller relay send and receive buffers delay before relay + +use strict; +use warnings; + +our %args = ( + client => { + len => 2**17, + }, + relay => { + func => sub { sleep 3; relay(@_); }, + sndbuf => 2**12, + rcvbuf => 2**12, + }, + len => 131072, + md5 => "31e5ad3d0d2aeb1ad8aaa847dfa665c2", +); diff --git a/regress/sys/kern/sosplice/tcp/args-smallbuf-sleep-server.pl b/regress/sys/kern/sosplice/tcp/args-smallbuf-sleep-server.pl new file mode 100644 index 00000000000..ee4765ff1b0 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-smallbuf-sleep-server.pl @@ -0,0 +1,19 @@ +# test with smaller relay send and receive buffers delay before server + +use strict; +use warnings; + +our %args = ( + client => { + len => 2**17, + }, + relay => { + sndbuf => 2**12, + rcvbuf => 2**12, + }, + server => { + func => sub { sleep 3; read_stream(@_); }, + }, + len => 131072, + md5 => "31e5ad3d0d2aeb1ad8aaa847dfa665c2", +); diff --git a/regress/sys/kern/sosplice/tcp/args-smallbuf.pl b/regress/sys/kern/sosplice/tcp/args-smallbuf.pl new file mode 100644 index 00000000000..5f31d87eccd --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-smallbuf.pl @@ -0,0 +1,16 @@ +# test with smaller relay send and receive buffers + +use strict; +use warnings; + +our %args = ( + client => { + len => 2**17, + }, + relay => { + sndbuf => 2**12, + rcvbuf => 2**12, + }, + len => 131072, + md5 => "31e5ad3d0d2aeb1ad8aaa847dfa665c2", +); diff --git a/regress/sys/kern/sosplice/tcp/args-smallrcv-sleep-client.pl b/regress/sys/kern/sosplice/tcp/args-smallrcv-sleep-client.pl new file mode 100644 index 00000000000..9a51835e070 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-smallrcv-sleep-client.pl @@ -0,0 +1,16 @@ +# test with smaller relay receive buffer delay before client + +use strict; +use warnings; + +our %args = ( + client => { + func => sub { sleep 3; write_stream(@_); }, + len => 2**17, + }, + relay => { + rcvbuf => 2**12, + }, + len => 131072, + md5 => "31e5ad3d0d2aeb1ad8aaa847dfa665c2", +); diff --git a/regress/sys/kern/sosplice/tcp/args-smallrcv-sleep-relay.pl b/regress/sys/kern/sosplice/tcp/args-smallrcv-sleep-relay.pl new file mode 100644 index 00000000000..90629b5e717 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-smallrcv-sleep-relay.pl @@ -0,0 +1,16 @@ +# test with smaller relay receive buffer delay before relay + +use strict; +use warnings; + +our %args = ( + client => { + len => 2**17, + }, + relay => { + func => sub { sleep 3; relay(@_); }, + rcvbuf => 2**12, + }, + len => 131072, + md5 => "31e5ad3d0d2aeb1ad8aaa847dfa665c2", +); diff --git a/regress/sys/kern/sosplice/tcp/args-smallrcv-sleep-server.pl b/regress/sys/kern/sosplice/tcp/args-smallrcv-sleep-server.pl new file mode 100644 index 00000000000..2654c07b343 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-smallrcv-sleep-server.pl @@ -0,0 +1,18 @@ +# test with smaller relay receive buffer delay before server + +use strict; +use warnings; + +our %args = ( + client => { + len => 2**17, + }, + relay => { + rcvbuf => 2**12, + }, + server => { + func => sub { sleep 3; read_stream(@_); }, + }, + len => 131072, + md5 => "31e5ad3d0d2aeb1ad8aaa847dfa665c2", +); diff --git a/regress/sys/kern/sosplice/tcp/args-smallrcv.pl b/regress/sys/kern/sosplice/tcp/args-smallrcv.pl new file mode 100644 index 00000000000..7d2d1017fe5 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-smallrcv.pl @@ -0,0 +1,15 @@ +# test with smaller relay receive buffer + +use strict; +use warnings; + +our %args = ( + client => { + len => 2**17, + }, + relay => { + rcvbuf => 2**12, + }, + len => 131072, + md5 => "31e5ad3d0d2aeb1ad8aaa847dfa665c2", +); diff --git a/regress/sys/kern/sosplice/tcp/args-smallsnd-sleep-client.pl b/regress/sys/kern/sosplice/tcp/args-smallsnd-sleep-client.pl new file mode 100644 index 00000000000..f8b3719fea7 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-smallsnd-sleep-client.pl @@ -0,0 +1,16 @@ +# test with smaller relay send buffer delay before client + +use strict; +use warnings; + +our %args = ( + client => { + func => sub { sleep 3; write_stream(@_); }, + len => 2**17, + }, + relay => { + sndbuf => 2**12, + }, + len => 131072, + md5 => "31e5ad3d0d2aeb1ad8aaa847dfa665c2", +); diff --git a/regress/sys/kern/sosplice/tcp/args-smallsnd-sleep-relay.pl b/regress/sys/kern/sosplice/tcp/args-smallsnd-sleep-relay.pl new file mode 100644 index 00000000000..6bc7cfc09cf --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-smallsnd-sleep-relay.pl @@ -0,0 +1,16 @@ +# test with smaller relay send buffer delay before relay + +use strict; +use warnings; + +our %args = ( + client => { + len => 2**17, + }, + relay => { + func => sub { sleep 3; relay(@_); }, + sndbuf => 2**12, + }, + len => 131072, + md5 => "31e5ad3d0d2aeb1ad8aaa847dfa665c2", +); diff --git a/regress/sys/kern/sosplice/tcp/args-smallsnd-sleep-server.pl b/regress/sys/kern/sosplice/tcp/args-smallsnd-sleep-server.pl new file mode 100644 index 00000000000..9ca1e2fa0ca --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-smallsnd-sleep-server.pl @@ -0,0 +1,18 @@ +# test with smaller relay send buffer delay before server + +use strict; +use warnings; + +our %args = ( + client => { + len => 2**17, + }, + relay => { + sndbuf => 2**12, + }, + server => { + func => sub { sleep 3; read_stream(@_); }, + }, + len => 131072, + md5 => "31e5ad3d0d2aeb1ad8aaa847dfa665c2", +); diff --git a/regress/sys/kern/sosplice/tcp/args-smallsnd.pl b/regress/sys/kern/sosplice/tcp/args-smallsnd.pl new file mode 100644 index 00000000000..968dbe34d81 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-smallsnd.pl @@ -0,0 +1,15 @@ +# test with smaller relay send buffer + +use strict; +use warnings; + +our %args = ( + client => { + len => 2**17, + }, + relay => { + sndbuf => 2**12, + }, + len => 131072, + md5 => "31e5ad3d0d2aeb1ad8aaa847dfa665c2", +); diff --git a/regress/sys/kern/sosplice/tcp/args-unsplice-forked.pl b/regress/sys/kern/sosplice/tcp/args-unsplice-forked.pl new file mode 100644 index 00000000000..9b8ae668353 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-unsplice-forked.pl @@ -0,0 +1,51 @@ +# test delay before server read, unsplice during client write + +use strict; +use warnings; +use POSIX; + +our %args = ( + client => { + len => 2**17, + func => sub { errignore(@_); write_stream(@_); }, + }, + relay => { + func => sub { + my $self = shift; + defined(my $pid = fork()) + or die "relay func: fork failed: $!"; + if ($pid == 0) { + sleep 2; + setsplice(\*STDIN) + or die ref($self), " unsplice stdin failed: $!"; + POSIX::_exit(0); + } + sleep 1; + eval { relay($self, @_) }; + if ($self->{forward} =~ /splice/) { + $@ =~ /^Relay sysread stdin has data:/ + or die ref($self), " no data after unsplice: $@"; + } + sleep 2; + kill 9, $pid; + (my $kid = waitpid($pid, 0)) > 0 + or die ref($self), " wait unsplice child failed: $!"; + my $status = $?; + my $code; + $code = "exit: ". WEXITSTATUS($?) if WIFEXITED($?); + $code = "signal: ". WTERMSIG($?) if WIFSIGNALED($?); + $code = "stop: ". WSTOPSIG($?) if WIFSTOPPED($?); + $status == 0 + or die ref($self), " unsplice child status: $status $code"; + }, + rcvbuf => 2**10, + sndbuf => 2**10, + }, + server => { + func => sub { sleep 3; read_stream(@_); }, + }, + noecho => 1, + nocheck => 1, + len => 131072, + md5 => "31e5ad3d0d2aeb1ad8aaa847dfa665c2", +); diff --git a/regress/sys/kern/sosplice/tcp/args-write-sleep-server.pl b/regress/sys/kern/sosplice/tcp/args-write-sleep-server.pl new file mode 100644 index 00000000000..bff55e49836 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-write-sleep-server.pl @@ -0,0 +1,26 @@ +# test mix write and relay delaying before server read + +use strict; +use warnings; + +our %args = ( + client => { + func => sub { sleep 4; write_stream(@_); }, + len => 65521, + nocheck => 1, + }, + relay => { + func => sub { + write_stream(@_, 32749); + IO::Handle::flush(\*STDOUT); + relay(@_); + write_stream(@_, 2039); + }, + nocheck => 1, + }, + server => { + func => sub { sleep 3; read_stream(@_); }, + }, + len => 100309, + md5 => "0efc7833e5c0652823ca63eaccb9918f", +); diff --git a/regress/sys/kern/sosplice/tcp/args-write.pl b/regress/sys/kern/sosplice/tcp/args-write.pl new file mode 100644 index 00000000000..22fa57eba6f --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/args-write.pl @@ -0,0 +1,22 @@ +# test mix write and relay + +use strict; +use warnings; + +our %args = ( + client => { + len => 65521, + nocheck => 1, + }, + relay => { + func => sub { + write_stream(@_, 32749); + IO::Handle::flush(\*STDOUT); + relay(@_); + write_stream(@_, 2039); + }, + nocheck => 1, + }, + len => 100309, + md5 => "0efc7833e5c0652823ca63eaccb9918f", +); diff --git a/regress/sys/kern/sosplice/tcp/direct.pl b/regress/sys/kern/sosplice/tcp/direct.pl new file mode 100644 index 00000000000..e2cc0c8ac33 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/direct.pl @@ -0,0 +1,62 @@ +#!/usr/bin/perl +# $OpenBSD: direct.pl,v 1.1.1.1 2013/01/03 17:36:39 bluhm Exp $ + +# Copyright (c) 2010-2013 Alexander Bluhm <bluhm@openbsd.org> +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +use strict; +use warnings; +use Socket; +use Socket6; + +use Client; +use Server; +require 'funcs.pl'; + +sub usage { + die "usage: direct.pl [test-args.pl]\n"; +} + +my $test; +our %args; +if (@ARGV and -f $ARGV[-1]) { + $test = pop; + do $test + or die "Do test file $test failed: ", $@ || $!; +} + +@ARGV == 0 or usage(); + +my $s = Server->new( + func => \&read_stream, + %{$args{server}}, + listendomain => AF_INET, + listenaddr => "127.0.0.1", +); +my $c = Client->new( + func => \&write_stream, + %{$args{client}}, + connectdomain => AF_INET, + connectaddr => "127.0.0.1", + connectport => $s->{listenport}, +); + +$s->run; +$c->run->up; +$s->up; + +$c->down; +$s->down; + +check_logs($c, undef, $s, %args); diff --git a/regress/sys/kern/sosplice/tcp/echo.pl b/regress/sys/kern/sosplice/tcp/echo.pl new file mode 100755 index 00000000000..b432bffd37a --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/echo.pl @@ -0,0 +1,86 @@ +#!/usr/bin/perl +# $OpenBSD: echo.pl,v 1.1.1.1 2013/01/03 17:36:39 bluhm Exp $ + +# Copyright (c) 2010-2013 Alexander Bluhm <bluhm@openbsd.org> +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +use strict; +use warnings; +use Socket; +use Socket6; + +use Child; +use Client; +use Server; +require 'funcs.pl'; + +sub usage { + die "usage: echo.pl copy|splice [test-args.pl]\n"; +} + +my $test; +our %args; +if (@ARGV and -f $ARGV[-1]) { + $test = pop; + do $test + or die "Do test file $test failed: ", $@ || $!; +} +@ARGV == 1 or usage(); + +exit 0 if $args{noecho} || $args{client}{alarm} || $args{server}{alarm}; + +my $r = Server->new( + forward => $ARGV[0], + func => \&relay, + logfile => "relay.log", + listendomain => AF_INET, + listenaddr => "127.0.0.1", + %{$args{relay}}, +); +my $s = Child->new( + logfile => "server.log", + oobinline => 1, + %{$args{server}}, + func => sub { + ($args{server}{func} || \&read_stream)->(@_); + eval { shutout(@_) }; + }, +); +my $c = Client->new( + connectdomain => AF_INET, + connectaddr => "127.0.0.1", + connectport => $r->{listenport}, + oobinline => 1, + %{$args{client}}, + func => sub { + $s->run->up; + eval { ($args{client}{func} || \&write_stream)->(@_) }; + warn $@ if $@; + eval { shutout(@_) }; + $s->down; + }, +); + +$r->run; +$c->run->up; +$r->up; + +$c->down; +$r->down; +$s->{pid} = -1; # XXX hack +$s->down; + +exit if $args{nocheck} || $args{client}{nocheck}; + +check_logs($c, $r, $s, %args); diff --git a/regress/sys/kern/sosplice/tcp/relay.pl b/regress/sys/kern/sosplice/tcp/relay.pl new file mode 100644 index 00000000000..b7d7525f239 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/relay.pl @@ -0,0 +1,77 @@ +#!/usr/bin/perl +# $OpenBSD: relay.pl,v 1.1.1.1 2013/01/03 17:36:39 bluhm Exp $ + +# Copyright (c) 2010-2013 Alexander Bluhm <bluhm@openbsd.org> +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +use strict; +use warnings; +use Socket; +use Socket6; + +use Client; +use Relay; +use Server; +require 'funcs.pl'; + +sub usage { + die "usage: relay.pl copy|splice [test-args.pl]\n"; +} + +my $test; +our %args; +if (@ARGV and -f $ARGV[-1]) { + $test = pop; + do $test + or die "Do test file $test failed: ", $@ || $!; +} +@ARGV == 1 or usage(); + +my $s = Server->new( + func => \&read_stream, + listendomain => AF_INET, + listenaddr => "127.0.0.1", + oobinline => 1, + %{$args{server}}, +); +my $r = Relay->new( + forward => $ARGV[0], + func => \&relay, + listendomain => AF_INET, + listenaddr => "127.0.0.1", + connectdomain => AF_INET, + connectaddr => "127.0.0.1", + connectport => $s->{listenport}, + %{$args{relay}}, +); +my $c = Client->new( + func => \&write_stream, + connectdomain => AF_INET, + connectaddr => "127.0.0.1", + connectport => $r->{listenport}, + oobinline => 1, + %{$args{client}}, +); + +$s->run; +$r->run; +$c->run->up; +$r->up; +$s->up; + +$c->down; +$r->down; +$s->down; + +check_logs($c, $r, $s, %args); diff --git a/regress/sys/kern/sosplice/tcp/remote.pl b/regress/sys/kern/sosplice/tcp/remote.pl new file mode 100644 index 00000000000..1da634617c4 --- /dev/null +++ b/regress/sys/kern/sosplice/tcp/remote.pl @@ -0,0 +1,129 @@ +#!/usr/bin/perl +# $OpenBSD: remote.pl,v 1.1.1.1 2013/01/03 17:36:39 bluhm Exp $ + +# Copyright (c) 2010-2013 Alexander Bluhm <bluhm@openbsd.org> +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +use strict; +use warnings; +use File::Basename; +use File::Copy; +use Socket; +use Socket6; + +use Client; +use Relay; +use Server; +use Remote; +require 'funcs.pl'; + +sub usage { + die <<"EOF"; +usage: + remote.pl localport remoteaddr remoteport [test-args.pl] + Run test with local client and server. Remote relay + forwarding from remoteaddr remoteport to server localport + has to be started manually. + remote.pl copy|splice listenaddr connectaddr connectport [test-args.pl] + Only start remote relay. + remote.pl copy|splice localaddr remoteaddr remotessh [test-args.pl] + Run test with local client and server. Remote relay is + started automatically with ssh on remotessh. +EOF +} + +my $test; +our %args; +if (@ARGV and -f $ARGV[-1]) { + $test = pop; + do $test + or die "Do test file $test failed: ", $@ || $!; +} +my $mode = + @ARGV == 3 && $ARGV[0] =~ /^\d+$/ && $ARGV[2] =~ /^\d+$/ ? "manual" : + @ARGV == 4 && $ARGV[1] !~ /^\d+$/ && $ARGV[3] =~ /^\d+$/ ? "relay" : + @ARGV == 4 && $ARGV[1] !~ /^\d+$/ && $ARGV[3] !~ /^\d+$/ ? "auto" : + usage(); + +my $r; +if ($mode eq "relay") { + $r = Relay->new( + forward => $ARGV[0], + logfile => dirname($0)."/remote.log", + func => \&relay, + %{$args{relay}}, + listendomain => AF_INET, + listenaddr => $ARGV[1], + connectdomain => AF_INET, + connectaddr => $ARGV[2], + connectport => $ARGV[3], + ); + open(my $log, '<', $r->{logfile}) + or die "Remote log file open failed: $!"; + $SIG{__DIE__} = sub { + die @_ if $^S; + copy($log, \*STDERR); + warn @_; + exit 255; + }; + copy($log, \*STDERR); + $r->run; + copy($log, \*STDERR); + $r->up; + copy($log, \*STDERR); + $r->down; + copy($log, \*STDERR); + + exit; +} + +my $s = Server->new( + func => \&read_stream, + oobinline => 1, + %{$args{server}}, + listendomain => AF_INET, + listenaddr => ($mode eq "auto" ? $ARGV[1] : undef), + listenport => ($mode eq "manual" ? $ARGV[0] : undef), +); +if ($mode eq "auto") { + $r = Remote->new( + forward => $ARGV[0], + logfile => "relay.log", + testfile => $test, + %{$args{relay}}, + remotessh => $ARGV[3], + listenaddr => $ARGV[2], + connectaddr => $ARGV[1], + connectport => $s->{listenport}, + ); + $r->run->up; +} +my $c = Client->new( + func => \&write_stream, + oobinline => 1, + %{$args{client}}, + connectdomain => AF_INET, + connectaddr => ($mode eq "manual" ? $ARGV[1] : $r->{listenaddr}), + connectport => ($mode eq "manual" ? $ARGV[2] : $r->{listenport}), +); + +$s->run; +$c->run->up; +$s->up; + +$c->down; +$r->down if $r; +$s->down; + +check_logs($c, $r, $s, %args); diff --git a/regress/sys/kern/sosplice/udp/Makefile b/regress/sys/kern/sosplice/udp/Makefile new file mode 100644 index 00000000000..bd10dd6daf7 --- /dev/null +++ b/regress/sys/kern/sosplice/udp/Makefile @@ -0,0 +1,22 @@ +# $OpenBSD: Makefile,v 1.1.1.1 2013/01/03 17:36:39 bluhm Exp $ + +.include <bsd.regress.mk> + +# The arg tests take a perl hash with arguments controlling the +# test parameters. Generally they consist of client, relay, server. +# The relay.pl test fork these three processes locally. The remote.pl +# test has local client and server but the relay process is running +# on a remote machine reachable with ssh. All tests can run with +# a regular userland copy relay or with a kernel socket splicing +# relay. + +.for a in ${ARGS} +run-regress-$a: $a +.if empty (REMOTE_SSH) + time perl ${PERLINC} ${PERLPATH}relay.pl copy ${PERLPATH}$a + time perl ${PERLINC} ${PERLPATH}relay.pl splice ${PERLPATH}$a +.else + time perl ${PERLINC} ${PERLPATH}remote.pl copy ${LOCAL_ADDR} ${REMOTE_ADDR} ${REMOTE_SSH} ${PERLPATH}$a + time perl ${PERLINC} ${PERLPATH}remote.pl splice ${LOCAL_ADDR} ${REMOTE_ADDR} ${REMOTE_SSH} ${PERLPATH}$a +.endif +.endfor diff --git a/regress/sys/kern/sosplice/udp/args-default.pl b/regress/sys/kern/sosplice/udp/args-default.pl new file mode 100644 index 00000000000..1caa30bc13f --- /dev/null +++ b/regress/sys/kern/sosplice/udp/args-default.pl @@ -0,0 +1,9 @@ +# test default values + +use strict; +use warnings; + +our %args = ( + len => 251, + md5 => "bc3a3f39af35fe5b1687903da2b00c7f", +); diff --git a/regress/sys/kern/sosplice/udp/args-idle-timeout.pl b/regress/sys/kern/sosplice/udp/args-idle-timeout.pl new file mode 100644 index 00000000000..5e58a1225e4 --- /dev/null +++ b/regress/sys/kern/sosplice/udp/args-idle-timeout.pl @@ -0,0 +1,16 @@ +# test idle timeout + +use strict; +use warnings; + +our %args = ( + client => { + func => sub { sleep 1; write_datagram(@_); sleep 3; }, + }, + relay => { + idle => 2, + timeout => 1, + }, + len => 251, + md5 => "bc3a3f39af35fe5b1687903da2b00c7f", +); diff --git a/regress/sys/kern/sosplice/udp/args-idle-trickle.pl b/regress/sys/kern/sosplice/udp/args-idle-trickle.pl new file mode 100644 index 00000000000..738c0278f09 --- /dev/null +++ b/regress/sys/kern/sosplice/udp/args-idle-trickle.pl @@ -0,0 +1,24 @@ +# test idle timeout + +use strict; +use warnings; +use List::Util qw(sum); + +my @lengths = (0, 1, 2, 3, 4, 5); + +our %args = ( + client => { + lengths => \@lengths, + sleep => 1, + }, + relay => { + idle => 2, + timeout => 1, + }, + server => { + num => scalar @lengths, + }, + len => sum(@lengths), + lengths => "@lengths", + md5 => "a5612eb5137e859bf52c515a890241a5", +); diff --git a/regress/sys/kern/sosplice/udp/args-inet6-client.pl b/regress/sys/kern/sosplice/udp/args-inet6-client.pl new file mode 100644 index 00000000000..0a676835700 --- /dev/null +++ b/regress/sys/kern/sosplice/udp/args-inet6-client.pl @@ -0,0 +1,22 @@ +# test ipv6 client + +use strict; +use warnings; +use Socket qw(AF_INET AF_INET6); + +our %args = ( + client => { + connectdomain => AF_INET6, + connectaddr => "::1", + }, + relay => { + listendomain => AF_INET6, + listenaddr => "::1", + connectdomain => AF_INET, + connectaddr => "127.0.0.1", + }, + server => { + listendomain => AF_INET, + listenaddr => "127.0.0.1", + }, +); diff --git a/regress/sys/kern/sosplice/udp/args-inet6-server.pl b/regress/sys/kern/sosplice/udp/args-inet6-server.pl new file mode 100644 index 00000000000..66975ce563a --- /dev/null +++ b/regress/sys/kern/sosplice/udp/args-inet6-server.pl @@ -0,0 +1,22 @@ +# test ipv6 server + +use strict; +use warnings; +use Socket qw(AF_INET AF_INET6); + +our %args = ( + client => { + connectdomain => AF_INET, + connectaddr => "127.0.0.1", + }, + relay => { + listendomain => AF_INET, + listenaddr => "127.0.0.1", + connectdomain => AF_INET6, + connectaddr => "::1", + }, + server => { + listendomain => AF_INET6, + listenaddr => "::1", + }, +); diff --git a/regress/sys/kern/sosplice/udp/args-inet6.pl b/regress/sys/kern/sosplice/udp/args-inet6.pl new file mode 100644 index 00000000000..c84a85f61a4 --- /dev/null +++ b/regress/sys/kern/sosplice/udp/args-inet6.pl @@ -0,0 +1,22 @@ +# test ipv6 client and server + +use strict; +use warnings; +use Socket qw(AF_INET AF_INET6); + +our %args = ( + client => { + connectdomain => AF_INET6, + connectaddr => "::1", + }, + relay => { + listendomain => AF_INET6, + listenaddr => "::1", + connectdomain => AF_INET6, + connectaddr => "::1", + }, + server => { + listendomain => AF_INET6, + listenaddr => "::1", + }, +); diff --git a/regress/sys/kern/sosplice/udp/args-long.pl b/regress/sys/kern/sosplice/udp/args-long.pl new file mode 100644 index 00000000000..0323385faf9 --- /dev/null +++ b/regress/sys/kern/sosplice/udp/args-long.pl @@ -0,0 +1,23 @@ +# test longer data length + +use strict; +use warnings; + +our %args = ( + client => { + len => 2**16 - 20 - 8 - 1, + sndbuf => 2**16, + }, + relay => { + timeout => 10, + size => 2**16, + sndbuf => 2**16, + rcvbuf => 2**16, + }, + server => { + num => 1, + rcvbuf => 2**16, + }, + len => 65507, + md5 => "20f83f523b6b48b11d9f8a15e507e16a", +); diff --git a/regress/sys/kern/sosplice/udp/args-max.pl b/regress/sys/kern/sosplice/udp/args-max.pl new file mode 100644 index 00000000000..8d8beac72de --- /dev/null +++ b/regress/sys/kern/sosplice/udp/args-max.pl @@ -0,0 +1,21 @@ +# test maximum data length + +use strict; +use warnings; + +our %args = ( + client => { + lengths => [ 1, 3, 1 ], + func => sub { errignore(@_); write_datagram(@_); }, + nocheck => 1, + }, + relay => { + max => 4, + }, + server => { + num => 2, + }, + len => 4, + lengths => "1 3", + md5 => "07515c3ca1f21779d63135eb5531eca2", +); diff --git a/regress/sys/kern/sosplice/udp/args-multi.pl b/regress/sys/kern/sosplice/udp/args-multi.pl new file mode 100644 index 00000000000..b61b812c6aa --- /dev/null +++ b/regress/sys/kern/sosplice/udp/args-multi.pl @@ -0,0 +1,25 @@ +# test with mutiple packets + +use strict; +use warnings; +use List::Util qw(sum); + +my @lengths = (251, 16384, 0, 1, 2, 3, 4, 5); + +our %args = ( + client => { + lengths => \@lengths, + sndbuf => 20000, + }, + relay => { + rcvbuf => 20000, + sndbuf => 20000, + }, + server => { + num => scalar @lengths, + rcvbuf => 20000, + }, + len => sum(@lengths), + lengths => "@lengths", + md5 => "f5b58b46c97b566fc8d34080c475d637", +); diff --git a/regress/sys/kern/sosplice/udp/args-nospace.pl b/regress/sys/kern/sosplice/udp/args-nospace.pl new file mode 100644 index 00000000000..06d517eb191 --- /dev/null +++ b/regress/sys/kern/sosplice/udp/args-nospace.pl @@ -0,0 +1,23 @@ +# test sending an udp packet that does not fit into splice space + +use strict; +use warnings; + +our %args = ( + client => { + lengths => [ 1, 10000, 2, 10001, 3 ], + sndbuf => 30000, + nocheck => 1, + }, + relay => { + rcvbuf => 30000, + sndbuf => 10000, + }, + server => { + num => 4, + rcvbuf => 30000, + }, + len => 10006, + lengths => "1 10000 2 3", + md5 => "90c347b1853f03d6e73aa88c9d12ce55", +); diff --git a/regress/sys/kern/sosplice/udp/direct.pl b/regress/sys/kern/sosplice/udp/direct.pl new file mode 100644 index 00000000000..12b029c4c86 --- /dev/null +++ b/regress/sys/kern/sosplice/udp/direct.pl @@ -0,0 +1,64 @@ +#!/usr/bin/perl +# $OpenBSD: direct.pl,v 1.1.1.1 2013/01/03 17:36:39 bluhm Exp $ + +# Copyright (c) 2010-2013 Alexander Bluhm <bluhm@openbsd.org> +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +use strict; +use warnings; +use Socket; +use Socket6; + +use Client; +use Server; +require 'funcs.pl'; + +sub usage { + die "usage: direct.pl [test-args.pl]\n"; +} + +my $test; +our %args; +if (@ARGV and -f $ARGV[-1]) { + $test = pop; + do $test + or die "Do test file $test failed: ", $@ || $!; +} + +@ARGV == 0 or usage(); + +my $s = Server->new( + func => \&read_datagram, + %{$args{server}}, + protocol => "udp", + listendomain => AF_INET, + listenaddr => "127.0.0.1", +); +my $c = Client->new( + func => \&write_datagram, + %{$args{client}}, + protocol => "udp", + connectdomain => AF_INET, + connectaddr => "127.0.0.1", + connectport => $s->{listenport}, +); + +$s->run; +$c->run->up; +$s->up; + +$c->down; +$s->down; + +check_logs($c, undef, $s, %args); diff --git a/regress/sys/kern/sosplice/udp/relay.pl b/regress/sys/kern/sosplice/udp/relay.pl new file mode 100644 index 00000000000..a06fdc2ab14 --- /dev/null +++ b/regress/sys/kern/sosplice/udp/relay.pl @@ -0,0 +1,79 @@ +#!/usr/bin/perl +# $OpenBSD: relay.pl,v 1.1.1.1 2013/01/03 17:36:39 bluhm Exp $ + +# Copyright (c) 2010-2013 Alexander Bluhm <bluhm@openbsd.org> +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +use strict; +use warnings; +use Socket; +use Socket6; + +use Client; +use Relay; +use Server; +require 'funcs.pl'; + +sub usage { + die "usage: relay.pl copy|splice [test-args.pl]\n"; +} + +my $test; +our %args; +if (@ARGV and -f $ARGV[-1]) { + $test = pop; + do $test + or die "Do test file $test failed: ", $@ || $!; +} +@ARGV == 1 or usage(); + +my $s = Server->new( + func => \&read_datagram, + listendomain => AF_INET, + listenaddr => "127.0.0.1", + %{$args{server}}, + protocol => "udp", +); +my $r = Relay->new( + forward => $ARGV[0], + idle => 5, + func => \&relay, + listendomain => AF_INET, + listenaddr => "127.0.0.1", + connectdomain => AF_INET, + connectaddr => "127.0.0.1", + connectport => $s->{listenport}, + %{$args{relay}}, + protocol => "udp", +); +my $c = Client->new( + func => \&write_datagram, + connectdomain => AF_INET, + connectaddr => "127.0.0.1", + connectport => $r->{listenport}, + %{$args{client}}, + protocol => "udp", +); + +$s->run; +$r->run; +$c->run->up; +$r->up; +$s->up; + +$c->down; +$r->down; +$s->down; + +check_logs($c, $r, $s, %args); diff --git a/regress/sys/kern/sosplice/udp/remote.pl b/regress/sys/kern/sosplice/udp/remote.pl new file mode 100644 index 00000000000..8bcc773e86a --- /dev/null +++ b/regress/sys/kern/sosplice/udp/remote.pl @@ -0,0 +1,132 @@ +#!/usr/bin/perl +# $OpenBSD: remote.pl,v 1.1.1.1 2013/01/03 17:36:39 bluhm Exp $ + +# Copyright (c) 2010-2013 Alexander Bluhm <bluhm@openbsd.org> +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +use strict; +use warnings; +use File::Basename; +use File::Copy; +use Socket; +use Socket6; + +use Client; +use Relay; +use Server; +use Remote; +require 'funcs.pl'; + +sub usage { + die <<"EOF"; +usage: + remote.pl localport remoteaddr remoteport [test-args.pl] + Run test with local client and server. Remote relay + forwarding from remoteaddr remoteport to server localport + has to be started manually. + remote.pl copy|splice listenaddr connectaddr connectport [test-args.pl] + Only start remote relay. + remote.pl copy|splice localaddr remoteaddr remotessh [test-args.pl] + Run test with local client and server. Remote relay is + started automatically with ssh on remotessh. +EOF +} + +my $test; +our %args; +if (@ARGV and -f $ARGV[-1]) { + $test = pop; + do $test + or die "Do test file $test failed: ", $@ || $!; +} +my $mode = + @ARGV == 3 && $ARGV[0] =~ /^\d+$/ && $ARGV[2] =~ /^\d+$/ ? "manual" : + @ARGV == 4 && $ARGV[1] !~ /^\d+$/ && $ARGV[3] =~ /^\d+$/ ? "relay" : + @ARGV == 4 && $ARGV[1] !~ /^\d+$/ && $ARGV[3] !~ /^\d+$/ ? "auto" : + usage(); + +my $r; +if ($mode eq "relay") { + $r = Relay->new( + forward => $ARGV[0], + logfile => dirname($0)."/remote.log", + idle => 5, + func => \&relay, + %{$args{relay}}, + protocol => "udp", + listendomain => AF_INET, + listenaddr => $ARGV[1], + connectdomain => AF_INET, + connectaddr => $ARGV[2], + connectport => $ARGV[3], + ); + open(my $log, '<', $r->{logfile}) + or die "Remote log file open failed: $!"; + $SIG{__DIE__} = sub { + die @_ if $^S; + copy($log, \*STDERR); + warn @_; + exit 255; + }; + copy($log, \*STDERR); + $r->run; + copy($log, \*STDERR); + $r->up; + copy($log, \*STDERR); + $r->down; + copy($log, \*STDERR); + + exit; +} + +my $s = Server->new( + func => \&read_datagram, + %{$args{server}}, + protocol => "udp", + listendomain => AF_INET, + listenaddr => ($mode eq "auto" ? $ARGV[1] : undef), + listenport => ($mode eq "manual" ? $ARGV[0] : undef), +); +if ($mode eq "auto") { + $r = Remote->new( + forward => $ARGV[0], + logfile => "relay.log", + testfile => $test, + %{$args{relay}}, + remotessh => $ARGV[3], + protocol => "udp", + listenaddr => $ARGV[2], + connectaddr => $ARGV[1], + connectport => $s->{listenport}, + ); + $r->run->up; +} +my $c = Client->new( + func => \&write_datagram, + %{$args{client}}, + protocol => "udp", + connectdomain => AF_INET, + connectaddr => ($mode eq "manual" ? $ARGV[1] : $r->{listenaddr}), + connectport => ($mode eq "manual" ? $ARGV[2] : $r->{listenport}), +); + +$s->run; +$c->run->up; +$s->up; + +$c->down; +$r->down if $r; +$s->down; + +check_logs($c, $r, $s, %args); |