about summary refs log tree commit homepage
path: root/t
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2019-06-24 02:52:54 +0000
committerEric Wong <e@80x24.org>2019-06-24 05:26:27 +0000
commitfbcd2b5eb401a8e1811d803cef9b1c156acb50f6 (patch)
tree508abd361276280bd5d53be46f92b4167309d215 /t
parent4e1a84c2a97c319862c960a34e3a7a8bf31d5274 (diff)
downloadpublic-inbox-fbcd2b5eb401a8e1811d803cef9b1c156acb50f6.tar.gz
Similar to TCP_DEFER_ACCEPT on Linux, FreeBSD has a 'dataready'
accept filter which we can use to reduce wakeups when doing
TLS negotiation or plain HTTP.  There's also a 'httpready'
which we can use for plain HTTP connections.
Diffstat (limited to 't')
-rw-r--r--t/httpd-corner.t21
-rw-r--r--t/httpd.t10
-rw-r--r--t/nntpd-tls.t14
3 files changed, 41 insertions, 4 deletions
diff --git a/t/httpd-corner.t b/t/httpd-corner.t
index 13befcf1..1cfc2565 100644
--- a/t/httpd-corner.t
+++ b/t/httpd-corner.t
@@ -18,7 +18,7 @@ use File::Temp qw/tempdir/;
 use IO::Socket;
 use IO::Socket::UNIX;
 use Fcntl qw(:seek);
-use Socket qw(IPPROTO_TCP TCP_NODELAY);
+use Socket qw(IPPROTO_TCP TCP_NODELAY SOL_SOCKET);
 use POSIX qw(mkfifo);
 require './t/common.perl';
 my $tmpdir = tempdir('httpd-corner-XXXXXX', TMPDIR => 1, CLEANUP => 1);
@@ -36,7 +36,10 @@ my %opts = (
         Listen => 1024,
 );
 my $sock = IO::Socket::INET->new(%opts);
-my $defer_accept_val;
+
+# Make sure we don't clobber socket options set by systemd or similar
+# using socket activation:
+my ($defer_accept_val, $accf_arg);
 if ($^O eq 'linux') {
         setsockopt($sock, IPPROTO_TCP, Socket::TCP_DEFER_ACCEPT(), 5) or die;
         my $x = getsockopt($sock, IPPROTO_TCP, Socket::TCP_DEFER_ACCEPT());
@@ -45,6 +48,11 @@ if ($^O eq 'linux') {
         if ($defer_accept_val <= 0) {
                 die "unexpected TCP_DEFER_ACCEPT value: $defer_accept_val";
         }
+} elsif ($^O eq 'freebsd' && system('kldstat -m accf_data >/dev/null') == 0) {
+        require PublicInbox::Daemon;
+        my $var = PublicInbox::Daemon::SO_ACCEPTFILTER();
+        $accf_arg = pack('a16a240', 'dataready', '');
+        setsockopt($sock, SOL_SOCKET, $var, $accf_arg) or die "setsockopt: $!";
 }
 
 my $upath = "$tmpdir/s";
@@ -100,7 +108,7 @@ my $spawn_httpd = sub {
         is(scalar(grep(/CLOSE FAIL/, @$after)), 1, 'body->close not called');
 }
 
-{
+SKIP: {
         my $conn = conn_for($sock, 'excessive header');
         $SIG{PIPE} = 'IGNORE';
         $conn->write("GET /callback HTTP/1.0\r\n");
@@ -515,6 +523,13 @@ SKIP: {
         is(unpack('i', $x), $defer_accept_val,
                 'TCP_DEFER_ACCEPT unchanged if previously set');
 };
+SKIP: {
+        skip 'SO_ACCEPTFILTER is FreeBSD-only', 1 if $^O ne 'freebsd';
+        skip 'accf_data not loaded: kldload accf_data' if !defined $accf_arg;
+        my $var = PublicInbox::Daemon::SO_ACCEPTFILTER();
+        defined(my $x = getsockopt($sock, SOL_SOCKET, $var)) or die;
+        is($x, $accf_arg, 'SO_ACCEPTFILTER unchanged if previously set');
+};
 
 done_testing();
 
diff --git a/t/httpd.t b/t/httpd.t
index 8c2a3173..e085c4b9 100644
--- a/t/httpd.t
+++ b/t/httpd.t
@@ -106,6 +106,16 @@ SKIP: {
         defined(my $x = getsockopt($sock, IPPROTO_TCP, $var)) or die;
         ok(unpack('i', $x) > 0, 'TCP_DEFER_ACCEPT set');
 };
+SKIP: {
+        skip 'SO_ACCEPTFILTER is FreeBSD-only', 1 if $^O ne 'freebsd';
+        if (system('kldstat -m accf_http >/dev/null') != 0) {
+                skip 'accf_http not loaded: kldload accf_http', 1;
+        }
+        require PublicInbox::Daemon;
+        my $var = PublicInbox::Daemon::SO_ACCEPTFILTER();
+        my $x = getsockopt($sock, SOL_SOCKET, $var);
+        like($x, qr/\Ahttpready\0+\z/, 'got httpready accf for HTTP');
+};
 
 done_testing();
 
diff --git a/t/nntpd-tls.t b/t/nntpd-tls.t
index ef683cab..427d370f 100644
--- a/t/nntpd-tls.t
+++ b/t/nntpd-tls.t
@@ -4,7 +4,7 @@ use strict;
 use warnings;
 use Test::More;
 use File::Temp qw(tempdir);
-use Socket qw(SOCK_STREAM IPPROTO_TCP);
+use Socket qw(SOCK_STREAM IPPROTO_TCP SOL_SOCKET);
 # IO::Poll and Net::NNTP are part of the standard library, but
 # distros may split them off...
 foreach my $mod (qw(DBD::SQLite IO::Socket::SSL Net::NNTP IO::Poll)) {
@@ -190,6 +190,18 @@ for my $args (
                 defined($x = getsockopt($starttls, IPPROTO_TCP, $var)) or die;
                 is(unpack('i', $x), 0, 'TCP_DEFER_ACCEPT is 0 on plain NNTP');
         };
+        SKIP: {
+                skip 'SO_ACCEPTFILTER is FreeBSD-only', 2 if $^O ne 'freebsd';
+                if (system('kldstat -m accf_data >/dev/null')) {
+                        skip 'accf_data not loaded? kldload accf_data', 2;
+                }
+                require PublicInbox::Daemon;
+                my $var = PublicInbox::Daemon::SO_ACCEPTFILTER();
+                my $x = getsockopt($nntps, SOL_SOCKET, $var);
+                like($x, qr/\Adataready\0+\z/, 'got dataready accf for NNTPS');
+                $x = getsockopt($starttls, IPPROTO_TCP, $var);
+                is($x, undef, 'no BSD accept filter for plain NNTP');
+        };
 
         $c = undef;
         kill('TERM', $pid);