Re: relayd socket splicing timeout

2011-09-04 Thread Alexander Bluhm
On Sat, Sep 03, 2011 at 02:25:37AM +0200, Alexander Bluhm wrote:
 During socket splicing the relayd session timeouts could not be
 measured exactly in user land.  Use the new idle timeout for socket
 splicing in the kernel to make it correct.

I think, I got the flag handling wrong.  Make sure that the error
flag is set.

-+  if (error  (EVBUFFER_READ|EVBUFFER_ERROR)  errno == ETIMEDOUT) {
++  if (error  EVBUFFER_ERROR  errno == ETIMEDOUT) {

Updated diff below.

bluhm


Index: usr.sbin/relayd/parse.y
===
RCS file: /cvs/src/usr.sbin/relayd/parse.y,v
retrieving revision 1.158
diff -u -p -r1.158 parse.y
--- usr.sbin/relayd/parse.y 26 May 2011 14:48:20 -  1.158
+++ usr.sbin/relayd/parse.y 4 Sep 2011 11:22:59 -
@@ -833,13 +833,6 @@ proto  : relay_proto PROTO STRING  {
p-type = $1;
p-cache = RELAY_CACHESIZE;
p-tcpflags = TCPFLAG_DEFAULT;
-   if (p-type != RELAY_PROTO_TCP) {
-   /*
-* Splicing is currently only supported
-* for plain TCP relays.
-*/
-   p-tcpflags |= TCPFLAG_NSPLICE;
-   }
p-sslflags = SSLFLAG_DEFAULT;
p-tcpbacklog = RELAY_BACKLOG;
(void)strlcpy(p-sslciphers, SSLCIPHERS_DEFAULT,
Index: usr.sbin/relayd/relay.c
===
RCS file: /cvs/src/usr.sbin/relayd/relay.c,v
retrieving revision 1.140
diff -u -p -r1.140 relay.c
--- usr.sbin/relayd/relay.c 4 Sep 2011 10:42:47 -   1.140
+++ usr.sbin/relayd/relay.c 4 Sep 2011 11:23:03 -
@@ -77,10 +77,12 @@ u_int32_trelay_hash_addr(struct sockad
 
 voidrelay_write(struct bufferevent *, void *);
 voidrelay_read(struct bufferevent *, void *);
-int relay_splicelen(struct ctl_relay_event *);
 voidrelay_error(struct bufferevent *, short, void *);
 voidrelay_dump(struct ctl_relay_event *, const void *, size_t);
 
+int relay_splice(struct ctl_relay_event *);
+int relay_splicelen(struct ctl_relay_event *);
+
 int relay_resolve(struct ctl_relay_event *,
struct protonode *, struct protonode *);
 int relay_handle_http(struct ctl_relay_event *,
@@ -675,26 +677,10 @@ relay_connected(int fd, short sig, void 
}
break;
case RELAY_PROTO_TCP:
-   if ((proto-tcpflags  TCPFLAG_NSPLICE) ||
-   (rlay-rl_conf.flags  (F_SSL|F_SSLCLIENT)))
-   break;
-   if (setsockopt(con-se_in.s, SOL_SOCKET, SO_SPLICE,
-   con-se_out.s, sizeof(int)) == -1) {
-   log_debug(%s: session %d: splice forward failed: %s,
-   __func__, con-se_id, strerror(errno));
-   return;
-   }
-   con-se_in.splicelen = 0;
-   if (setsockopt(con-se_out.s, SOL_SOCKET, SO_SPLICE,
-   con-se_in.s, sizeof(int)) == -1) {
-   log_debug(%s: session %d: splice backward failed: %s,
-   __func__, con-se_id, strerror(errno));
-   return;
-   }
-   con-se_out.splicelen = 0;
+   /* Use defaults */
break;
default:
-   fatalx(relay_input: unknown protocol);
+   fatalx(relay_connected: unknown protocol);
}
 
/*
@@ -719,6 +705,9 @@ relay_connected(int fd, short sig, void 
bufferevent_settimeout(bev,
rlay-rl_conf.timeout.tv_sec, rlay-rl_conf.timeout.tv_sec);
bufferevent_enable(bev, EV_READ|EV_WRITE);
+
+   if (relay_splice(con-se_out) == -1)
+   relay_close(con, strerror(errno));
 }
 
 void
@@ -766,6 +755,9 @@ relay_input(struct rsession *con)
bufferevent_settimeout(con-se_in.bev,
rlay-rl_conf.timeout.tv_sec, rlay-rl_conf.timeout.tv_sec);
bufferevent_enable(con-se_in.bev, EV_READ|EV_WRITE);
+
+   if (relay_splice(con-se_in) == -1)
+   relay_close(con, strerror(errno));
 }
 
 void
@@ -1842,16 +1834,46 @@ relay_close_http(struct rsession *con, u
 }
 
 int
+relay_splice(struct ctl_relay_event *cre)
+{
+   struct rsession *con = cre-con;
+   struct relay*rlay = (struct relay *)con-se_relay;
+   struct protocol *proto = rlay-rl_proto;
+   struct splicesp;
+
+   if ((rlay-rl_conf.flags  (F_SSL|F_SSLCLIENT)) ||
+   (proto-tcpflags  TCPFLAG_NSPLICE))
+   return (0);
+
+   if (cre-bev-readcb != relay_read)
+   return (0);
+
+   

relayd socket splicing timeout

2011-09-02 Thread Alexander Bluhm
Hi,

During socket splicing the relayd session timeouts could not be
measured exactly in user land.  Use the new idle timeout for socket
splicing in the kernel to make it correct.

ok?

bluhm


Index: usr.sbin/relayd//parse.y
===
RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/relayd/parse.y,v
retrieving revision 1.158
diff -u -p -r1.158 parse.y
--- usr.sbin/relayd//parse.y26 May 2011 14:48:20 -  1.158
+++ usr.sbin/relayd//parse.y3 Sep 2011 00:11:25 -
@@ -833,13 +833,6 @@ proto  : relay_proto PROTO STRING  {
p-type = $1;
p-cache = RELAY_CACHESIZE;
p-tcpflags = TCPFLAG_DEFAULT;
-   if (p-type != RELAY_PROTO_TCP) {
-   /*
-* Splicing is currently only supported
-* for plain TCP relays.
-*/
-   p-tcpflags |= TCPFLAG_NSPLICE;
-   }
p-sslflags = SSLFLAG_DEFAULT;
p-tcpbacklog = RELAY_BACKLOG;
(void)strlcpy(p-sslciphers, SSLCIPHERS_DEFAULT,
Index: usr.sbin/relayd//relay.c
===
RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/relayd/relay.c,v
retrieving revision 1.138
diff -u -p -r1.138 relay.c
--- usr.sbin/relayd//relay.c20 May 2011 09:43:53 -  1.138
+++ usr.sbin/relayd//relay.c2 Sep 2011 23:53:48 -
@@ -77,10 +77,12 @@ u_int32_trelay_hash_addr(struct sockad
 
 voidrelay_write(struct bufferevent *, void *);
 voidrelay_read(struct bufferevent *, void *);
-int relay_splicelen(struct ctl_relay_event *);
 voidrelay_error(struct bufferevent *, short, void *);
 voidrelay_dump(struct ctl_relay_event *, const void *, size_t);
 
+int relay_splice(struct ctl_relay_event *);
+int relay_splicelen(struct ctl_relay_event *);
+
 int relay_resolve(struct ctl_relay_event *,
struct protonode *, struct protonode *);
 int relay_handle_http(struct ctl_relay_event *,
@@ -675,26 +677,10 @@ relay_connected(int fd, short sig, void 
}
break;
case RELAY_PROTO_TCP:
-   if ((proto-tcpflags  TCPFLAG_NSPLICE) ||
-   (rlay-rl_conf.flags  (F_SSL|F_SSLCLIENT)))
-   break;
-   if (setsockopt(con-se_in.s, SOL_SOCKET, SO_SPLICE,
-   con-se_out.s, sizeof(int)) == -1) {
-   log_debug(%s: session %d: splice forward failed: %s,
-   __func__, con-se_id, strerror(errno));
-   return;
-   }
-   con-se_in.splicelen = 0;
-   if (setsockopt(con-se_out.s, SOL_SOCKET, SO_SPLICE,
-   con-se_in.s, sizeof(int)) == -1) {
-   log_debug(%s: session %d: splice backward failed: %s,
-   __func__, con-se_id, strerror(errno));
-   return;
-   }
-   con-se_out.splicelen = 0;
+   /* Use defaults */
break;
default:
-   fatalx(relay_input: unknown protocol);
+   fatalx(relay_connected: unknown protocol);
}
 
/*
@@ -719,6 +705,9 @@ relay_connected(int fd, short sig, void 
bufferevent_settimeout(bev,
rlay-rl_conf.timeout.tv_sec, rlay-rl_conf.timeout.tv_sec);
bufferevent_enable(bev, EV_READ|EV_WRITE);
+
+   if (relay_splice(con-se_out) == -1)
+   relay_close(con, strerror(errno));
 }
 
 void
@@ -766,6 +755,9 @@ relay_input(struct rsession *con)
bufferevent_settimeout(con-se_in.bev,
rlay-rl_conf.timeout.tv_sec, rlay-rl_conf.timeout.tv_sec);
bufferevent_enable(con-se_in.bev, EV_READ|EV_WRITE);
+
+   if (relay_splice(con-se_in) == -1)
+   relay_close(con, strerror(errno));
 }
 
 void
@@ -1842,16 +1834,46 @@ relay_close_http(struct rsession *con, u
 }
 
 int
+relay_splice(struct ctl_relay_event *cre)
+{
+   struct rsession *con = cre-con;
+   struct relay*rlay = (struct relay *)con-se_relay;
+   struct protocol *proto = rlay-rl_proto;
+   struct splicesp;
+
+   if ((rlay-rl_conf.flags  (F_SSL|F_SSLCLIENT)) ||
+   (proto-tcpflags  TCPFLAG_NSPLICE))
+   return (0);
+
+   if (cre-bev-readcb != relay_read)
+   return (0);
+
+   bzero(sp, sizeof(sp));
+   sp.sp_fd = cre-dst-s;
+   sp.sp_idle = rlay-rl_conf.timeout;
+   if (setsockopt(cre-s, SOL_SOCKET, SO_SPLICE, sp, sizeof(sp)) == -1) {
+   log_debug(%s: session %d: splice dir %d failed: %s,
+   

Re: relayd socket splicing

2011-03-15 Thread Alexander Bluhm
On Tue, Mar 08, 2011 at 02:11:31AM +0100, Alexander Bluhm wrote:
 Hmm, perhaps too small.  There is a session timeout and relayctl
 show sessions idle time.  Relayd does not realize when the kernel
 is transferring data automatically.  It should check the splice
 data length with getsockopt() periodically or when the timeout
 fires.

This diff fixes the timeout issues.  If a timeout occured and
splicing is active, check wether the splice length has changed.  If
so, reset the timeout and idle counter.  Thay may make timeout
detection longer than without splicing.

Socket splicing works for plain TCP conections now.  I have tested
that HTTP keep-alive and SSL are not affected.

As requested by Theo splicing cannot be turned off.

ok?

bluhm


Index: usr.sbin/relayd/relay.c
===
RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/relayd/relay.c,v
retrieving revision 1.130
diff -u -p -r1.130 relay.c
--- usr.sbin/relayd/relay.c 12 Mar 2011 21:06:40 -  1.130
+++ usr.sbin/relayd/relay.c 16 Mar 2011 01:04:38 -
@@ -77,6 +77,7 @@ u_int32_t  relay_hash_addr(struct sockad
 
 voidrelay_write(struct bufferevent *, void *);
 voidrelay_read(struct bufferevent *, void *);
+int relay_splicelen(struct ctl_relay_event *);
 voidrelay_error(struct bufferevent *, short, void *);
 voidrelay_dump(struct ctl_relay_event *, const void *, size_t);
 
@@ -1938,15 +1939,47 @@ relay_close_http(struct rsession *con, u
}
 }
 
+int
+relay_splicelen(struct ctl_relay_event *cre)
+{
+   struct rsession *con = (struct rsession *)cre-con;
+   off_t len;
+   socklen_t optlen;
+
+   optlen = sizeof(len);
+   if (getsockopt(cre-s, SOL_SOCKET, SO_SPLICE, len, optlen) == -1) {
+   relay_close(con, strerror(errno));
+   return (0);
+   }
+   if (len  cre-splicelen) {
+   cre-splicelen = len;
+   return (1);
+   }
+   return (0);
+}
+
 void
 relay_error(struct bufferevent *bev, short error, void *arg)
 {
struct ctl_relay_event *cre = (struct ctl_relay_event *)arg;
struct rsession *con = (struct rsession *)cre-con;
struct evbuffer *dst;
+   struct timeval tv, tv_now;
 
if (error  EVBUFFER_TIMEOUT) {
-   relay_close(con, buffer event timeout);
+   if (gettimeofday(tv_now, NULL) == -1) {
+   relay_close(con, strerror(errno));
+   return;
+   }
+   if (cre-splicelen = 0  relay_splicelen(cre))
+   con-se_tv_last = tv_now;
+   if (cre-dst-splicelen = 0  relay_splicelen(cre-dst))
+   con-se_tv_last = tv_now;
+   timersub(tv_now, con-se_tv_last, tv);
+   if (timercmp(tv, con-se_relay-rl_conf.timeout, =))
+   relay_close(con, buffer event timeout);
+   else
+   bufferevent_enable(cre-dst-bev, EV_READ);
return;
}
if (error  (EVBUFFER_READ|EVBUFFER_WRITE|EVBUFFER_EOF)) {
@@ -2000,6 +2033,8 @@ relay_accept(int fd, short sig, void *ar
con-se_out.dst = con-se_in;
con-se_in.con = con;
con-se_out.con = con;
+   con-se_in.splicelen = -1;
+   con-se_out.splicelen = -1;
con-se_relay = rlay;
con-se_id = ++relay_conid;
con-se_relayid = rlay-rl_conf.id;
@@ -2327,6 +2362,24 @@ relay_connect(struct rsession *con)
log_debug(relay_connect: session %d: forward failed: %s,
con-se_id, strerror(errno));
return (-1);
+   }
+
+   if (rlay-rl_proto-type == RELAY_PROTO_TCP 
+   (rlay-rl_conf.flags  (F_SSL|F_SSLCLIENT)) == 0) {
+   if (setsockopt(con-se_in.s, SOL_SOCKET, SO_SPLICE,
+   con-se_out.s, sizeof(int)) == -1) {
+   log_debug(relay_connect: session %d: splice forward 
+   failed: %s, con-se_id, strerror(errno));
+   return (-1);
+   }
+   con-se_in.splicelen = 0;
+   if (setsockopt(con-se_out.s, SOL_SOCKET, SO_SPLICE,
+   con-se_in.s, sizeof(int)) == -1) {
+   log_debug(relay_connect: session %d: splice backward 
+   failed: %s, con-se_id, strerror(errno));
+   return (-1);
+   }
+   con-se_out.splicelen = 0;
}
 
if (errno == EINPROGRESS)
Index: usr.sbin/relayd/relayd.h
===
RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/relayd/relayd.h,v
retrieving revision 1.140
diff -u -p -r1.140 relayd.h
--- usr.sbin/relayd/relayd.h31 Dec 2010 21:22:42 -  1.140
+++ usr.sbin/relayd/relayd.h12 Mar 2011 19:54:53 -
@@ -162,6 +162,7 @@ 

Re: relayd socket splicing

2011-03-07 Thread Alexander Bluhm
On Sun, Mar 06, 2011 at 09:12:41AM +0100, Reyk Floeter wrote:
 this diff will break chunked encoding and keep-alive connections where
 we need to enable splicing for a specified amount of data only and
 return for the next HTTP header.

I don't think so.  I only set F_SPLICE for RELAY_PROTO_TCP and not
for RELAY_PROTO_HTTP.

 the env variable should be replaced
 with a permanent config option in parse.y.

New diff with nosplice protocol option.  The config looks like this:

tcp protocol copy { nosplice }
tcp protocol splice
relay tcpbench { 
listen on 10.188.50.50 port 12345
forward to 10.188.50.10 port 12345
}
relay slow { 
protocol copy
listen on 10.188.50.50 port 12346
forward to 10.188.50.10 port 12345
}
relay fast { 
protocol splice
listen on 10.188.50.50 port 12347
forward to 10.188.50.10 port 12345
}

Note that the default tcp protocol comes with splicing enabled.
The option nosplice is useful for performance comparison and
debugging.

I have also tested with http connection keep-alive, client ssl and
server ssl.  In these cases, socket splicing is not used.

ok?

bluhm


Index: usr.sbin/relayd/parse.y
===
RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/relayd/parse.y,v
retrieving revision 1.149
diff -u -p -r1.149 parse.y
--- usr.sbin/relayd/parse.y 26 Oct 2010 15:04:37 -  1.149
+++ usr.sbin/relayd/parse.y 7 Mar 2011 21:03:34 -
@@ -145,7 +145,7 @@ typedef struct {
 %token EXTERNAL FILENAME FILTER FORWARD FROM HASH HEADER HOST ICMP
 %token INCLUDE INET INET6 INTERFACE INTERVAL IP LABEL LISTEN
 %token LOADBALANCE LOG LOOKUP MARK MARKED MODE NAT NO
-%token NODELAY NOTHING ON PARENT PATH PORT PREFORK PROTO
+%token NODELAY NOSPLICE NOTHING ON PARENT PATH PORT PREFORK PROTO
 %token QUERYSTR REAL REDIRECT RELAY REMOVE REQUEST RESPONSE RETRY
 %token RETURN ROUNDROBIN ROUTE SACK SCRIPT SEND SESSION SOCKET
 %token SSL STICKYADDR STYLE TABLE TAG TCP TIMEOUT TO ROUTER RTLABEL
@@ -796,6 +796,8 @@ proto   : relay_proto PROTO STRING  {
free($3);
p-id = ++last_proto_id;
p-type = $1;
+   if (p-type == RELAY_PROTO_TCP)
+   p-flags |= F_SPLICE;
p-cache = RELAY_CACHESIZE;
p-tcpflags = TCPFLAG_DEFAULT;
p-sslflags = SSLFLAG_DEFAULT;
@@ -835,6 +837,7 @@ protoptsl   : SSL sslflags
| SSL '{' sslflags_l '}'
| TCP tcpflags
| TCP '{' tcpflags_l '}'
+   | NOSPLICE  { proto-flags = ~F_SPLICE; }
| RETURN ERROR opteflags{ proto-flags |= F_RETURN; }
| RETURN ERROR '{' eflags_l '}' { proto-flags |= F_RETURN; }
| LABEL STRING  {
@@ -1747,6 +1750,7 @@ lookup(char *s)
{ nat,NAT },
{ no, NO },
{ nodelay,NODELAY },
+   { nosplice,   NOSPLICE },
{ nothing,NOTHING },
{ on, ON },
{ parent, PARENT },
@@ -2162,7 +2166,7 @@ parse_config(const char *filename, int o
sizeof(conf-sc_empty_table.conf.name));
 
bzero(conf-sc_proto_default, sizeof(conf-sc_proto_default));
-   conf-sc_proto_default.flags = F_USED;
+   conf-sc_proto_default.flags = F_USED|F_SPLICE;
conf-sc_proto_default.cache = RELAY_CACHESIZE;
conf-sc_proto_default.tcpflags = TCPFLAG_DEFAULT;
conf-sc_proto_default.tcpbacklog = RELAY_BACKLOG;
Index: usr.sbin/relayd/relay.c
===
RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/relayd/relay.c,v
retrieving revision 1.128
diff -u -p -r1.128 relay.c
--- usr.sbin/relayd/relay.c 20 Dec 2010 12:38:06 -  1.128
+++ usr.sbin/relayd/relay.c 22 Feb 2011 22:54:05 -
@@ -2328,6 +2328,22 @@ relay_connect(struct rsession *con)
return (-1);
}
 
+   if (rlay-rl_proto-flags  F_SPLICE 
+   (rlay-rl_conf.flags  (F_SSL|F_SSLCLIENT)) == 0) {
+   if (setsockopt(con-se_in.s, SOL_SOCKET, SO_SPLICE,
+   con-se_out.s, sizeof(int)) == -1) {
+   log_debug(relay_connect: session %d: splice forward 
+   failed: %s, con-se_id, strerror(errno));
+   return (-1);
+   }
+   if (setsockopt(con-se_out.s, SOL_SOCKET, SO_SPLICE,
+   con-se_in.s, sizeof(int)) == -1) {
+   log_debug(relay_connect: session %d: splice backward 
+   failed: %s, con-se_id, strerror(errno));
+   return (-1);
+   }
+   }
+

Re: relayd socket splicing

2011-03-07 Thread Theo de Raadt
I do not think splice should be an option that is exposed to
users.

Either the kernel support works, or doesn't.

 The option nosplice is useful for performance comparison and
 debugging.

+   { nosplice,   NOSPLICE },

That is crazy notion.  Either it is faster and works, and it should be
used when possible, or we should not have the code in the kernel or in
userland.

Secondly, bugs should not be diagnosed using new 'options' in a
configuration file.  Bugs will be found a different way, and then
fixed.

 ok?

No.



Re: relayd socket splicing

2011-03-07 Thread Alexander Bluhm
On Mon, Mar 07, 2011 at 04:23:08PM -0700, Theo de Raadt wrote:
 I do not think splice should be an option that is exposed to
 users.

That makes the diff much smaller.

ok?


Index: usr.sbin/relayd/relay.c
===
RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/relayd/relay.c,v
retrieving revision 1.128
diff -u -p -r1.128 relay.c
--- usr.sbin/relayd/relay.c 20 Dec 2010 12:38:06 -  1.128
+++ usr.sbin/relayd/relay.c 7 Mar 2011 23:36:43 -
@@ -2328,6 +2328,22 @@ relay_connect(struct rsession *con)
return (-1);
}
 
+   if (rlay-rl_proto-type == RELAY_PROTO_TCP 
+   (rlay-rl_conf.flags  (F_SSL|F_SSLCLIENT)) == 0) {
+   if (setsockopt(con-se_in.s, SOL_SOCKET, SO_SPLICE,
+   con-se_out.s, sizeof(int)) == -1) {
+   log_debug(relay_connect: session %d: splice forward 
+   failed: %s, con-se_id, strerror(errno));
+   return (-1);
+   }
+   if (setsockopt(con-se_out.s, SOL_SOCKET, SO_SPLICE,
+   con-se_in.s, sizeof(int)) == -1) {
+   log_debug(relay_connect: session %d: splice backward 
+   failed: %s, con-se_id, strerror(errno));
+   return (-1);
+   }
+   }
+
if (errno == EINPROGRESS)
event_again(con-se_ev, con-se_out.s, EV_WRITE|EV_TIMEOUT,
relay_connected, con-se_tv_start, env-sc_timeout, con);



Re: relayd socket splicing

2011-03-07 Thread Alexander Bluhm
On Tue, Mar 08, 2011 at 01:00:48AM +0100, Alexander Bluhm wrote:
 On Mon, Mar 07, 2011 at 04:23:08PM -0700, Theo de Raadt wrote:
  I do not think splice should be an option that is exposed to
  users.
 
 That makes the diff much smaller.

Hmm, perhaps too small.  There is a session timeout and relayctl
show sessions idle time.  Relayd does not realize when the kernel
is transferring data automatically.  It should check the splice
data length with getsockopt() periodically or when the timeout
fires.

bluhm

 
 ok?
 
 
 Index: usr.sbin/relayd/relay.c
 ===
 RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/relayd/relay.c,v
 retrieving revision 1.128
 diff -u -p -r1.128 relay.c
 --- usr.sbin/relayd/relay.c   20 Dec 2010 12:38:06 -  1.128
 +++ usr.sbin/relayd/relay.c   7 Mar 2011 23:36:43 -
 @@ -2328,6 +2328,22 @@ relay_connect(struct rsession *con)
   return (-1);
   }
  
 + if (rlay-rl_proto-type == RELAY_PROTO_TCP 
 + (rlay-rl_conf.flags  (F_SSL|F_SSLCLIENT)) == 0) {
 + if (setsockopt(con-se_in.s, SOL_SOCKET, SO_SPLICE,
 + con-se_out.s, sizeof(int)) == -1) {
 + log_debug(relay_connect: session %d: splice forward 
 + failed: %s, con-se_id, strerror(errno));
 + return (-1);
 + }
 + if (setsockopt(con-se_out.s, SOL_SOCKET, SO_SPLICE,
 + con-se_in.s, sizeof(int)) == -1) {
 + log_debug(relay_connect: session %d: splice backward 
 + failed: %s, con-se_id, strerror(errno));
 + return (-1);
 + }
 + }
 +
   if (errno == EINPROGRESS)
   event_again(con-se_ev, con-se_out.s, EV_WRITE|EV_TIMEOUT,
   relay_connected, con-se_tv_start, env-sc_timeout, con);



Re: relayd socket splicing

2011-03-06 Thread Reyk Floeter
hi,

this diff will break chunked encoding and keep-alive connections where
we need to enable splicing for a specified amount of data only and
return for the next HTTP header.  the env variable should be replaced
with a permanent config option in parse.y.

reyk

On Wed, Mar 02, 2011 at 09:34:14PM +0100, Alexander Bluhm wrote:
 I just relized that I did send out an outdated diff.  This one has
 an additional check for F_SSL and F_SSLCLIENT to avoid splicing ssl
 connections.
 
 The RELAY_NOSPLICE environment variable is only for testing and
 will be removed in the final version.
 
 bluhm
 
 
 Index: usr.sbin/relayd/parse.y
 ===
 RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/relayd/parse.y,v
 retrieving revision 1.149
 diff -u -p -r1.149 parse.y
 --- usr.sbin/relayd/parse.y   26 Oct 2010 15:04:37 -  1.149
 +++ usr.sbin/relayd/parse.y   22 Feb 2011 22:54:05 -
 @@ -796,6 +796,9 @@ proto : relay_proto PROTO STRING  {
   free($3);
   p-id = ++last_proto_id;
   p-type = $1;
 + if (p-type == RELAY_PROTO_TCP 
 + !getenv(RELAY_NOSPLICE))
 + p-flags |= F_SPLICE;
   p-cache = RELAY_CACHESIZE;
   p-tcpflags = TCPFLAG_DEFAULT;
   p-sslflags = SSLFLAG_DEFAULT;
 @@ -2170,6 +2173,8 @@ parse_config(const char *filename, int o
   (void)strlcpy(conf-sc_proto_default.sslciphers, SSLCIPHERS_DEFAULT,
   sizeof(conf-sc_proto_default.sslciphers));
   conf-sc_proto_default.type = RELAY_PROTO_TCP;
 + if (!getenv(RELAY_NOSPLICE))
 + conf-sc_proto_default.flags |= F_SPLICE;
   (void)strlcpy(conf-sc_proto_default.name, default,
   sizeof(conf-sc_proto_default.name));
   RB_INIT(conf-sc_proto_default.request_tree);
 Index: usr.sbin/relayd/relay.c
 ===
 RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/relayd/relay.c,v
 retrieving revision 1.128
 diff -u -p -r1.128 relay.c
 --- usr.sbin/relayd/relay.c   20 Dec 2010 12:38:06 -  1.128
 +++ usr.sbin/relayd/relay.c   22 Feb 2011 22:54:05 -
 @@ -2328,6 +2328,22 @@ relay_connect(struct rsession *con)
   return (-1);
   }
  
 + if (rlay-rl_proto-flags  F_SPLICE 
 + (rlay-rl_conf.flags  (F_SSL|F_SSLCLIENT)) == 0) {
 + if (setsockopt(con-se_in.s, SOL_SOCKET, SO_SPLICE,
 + con-se_out.s, sizeof(int)) == -1) {
 + log_debug(relay_connect: session %d: splice forward 
 + failed: %s, con-se_id, strerror(errno));
 + return (-1);
 + }
 + if (setsockopt(con-se_out.s, SOL_SOCKET, SO_SPLICE,
 + con-se_in.s, sizeof(int)) == -1) {
 + log_debug(relay_connect: session %d: splice backward 
 + failed: %s, con-se_id, strerror(errno));
 + return (-1);
 + }
 + }
 +
   if (errno == EINPROGRESS)
   event_again(con-se_ev, con-se_out.s, EV_WRITE|EV_TIMEOUT,
   relay_connected, con-se_tv_start, env-sc_timeout, con);
 Index: usr.sbin/relayd/relayd.8
 ===
 RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/relayd/relayd.8,v
 retrieving revision 1.23
 diff -u -p -r1.23 relayd.8
 --- usr.sbin/relayd/relayd.8  24 May 2010 19:44:23 -  1.23
 +++ usr.sbin/relayd/relayd.8  22 Feb 2011 23:00:20 -
 @@ -121,6 +121,12 @@ Only check the configuration file for va
  .It Fl v
  Produce more verbose output.
  .El
 +.Sh ENVIRONMENT
 +It is possible to disable support for socket splicing by setting
 +the environment variable
 +.Ev RELAY_NOSPLICE .
 +Socket splicing is used by default to speed up plain TCP connections
 +without ssl.
  .Sh FILES
  .Bl -tag -width /var/run/relayd.sockXX -compact
  .It /etc/relayd.conf
 Index: usr.sbin/relayd/relayd.h
 ===
 RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/relayd/relayd.h,v
 retrieving revision 1.140
 diff -u -p -r1.140 relayd.h
 --- usr.sbin/relayd/relayd.h  31 Dec 2010 21:22:42 -  1.140
 +++ usr.sbin/relayd/relayd.h  22 Feb 2011 22:54:05 -
 @@ -249,6 +249,7 @@ TAILQ_HEAD(addresslist, address);
  #define F_SSLCLIENT  0x0020
  #define F_NEEDRT 0x0040
  #define F_MATCH  0x0080
 +#define F_SPLICE 0x0100
  
  enum forwardmode {
   FWD_NORMAL  = 0,



relayd socket splicing

2011-03-02 Thread Alexander Bluhm
This diff implements socket splicing for relayd.  Instead of copying
data in userland from one TCP socket into another, the kernel is
told to move the data himself.

The environment variable RELAY_NOSPLICE works like EVENT_NOKQUEUE
from libevent.  It can be used to easily turn it on and off for
testing.

At the moment, I have only implemented plain TCP connections in
relayd.  HTTP can be done later.

If you are using relayd with OpenBSD 4.9 to relay TCP connections,
please test this.

ok?

bluhm


Index: usr.sbin/relayd/parse.y
===
RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/relayd/parse.y,v
retrieving revision 1.149
diff -u -p -r1.149 parse.y
--- usr.sbin/relayd/parse.y 26 Oct 2010 15:04:37 -  1.149
+++ usr.sbin/relayd/parse.y 31 Jan 2011 23:34:13 -
@@ -796,6 +796,9 @@ proto   : relay_proto PROTO STRING  {
free($3);
p-id = ++last_proto_id;
p-type = $1;
+   if (p-type == RELAY_PROTO_TCP 
+   !getenv(RELAY_NOSPLICE))
+   p-flags |= F_SPLICE;
p-cache = RELAY_CACHESIZE;
p-tcpflags = TCPFLAG_DEFAULT;
p-sslflags = SSLFLAG_DEFAULT;
@@ -2170,6 +2173,8 @@ parse_config(const char *filename, int o
(void)strlcpy(conf-sc_proto_default.sslciphers, SSLCIPHERS_DEFAULT,
sizeof(conf-sc_proto_default.sslciphers));
conf-sc_proto_default.type = RELAY_PROTO_TCP;
+   if (!getenv(RELAY_NOSPLICE))
+   conf-sc_proto_default.flags |= F_SPLICE;
(void)strlcpy(conf-sc_proto_default.name, default,
sizeof(conf-sc_proto_default.name));
RB_INIT(conf-sc_proto_default.request_tree);
Index: usr.sbin/relayd/relay.c
===
RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/relayd/relay.c,v
retrieving revision 1.128
diff -u -p -r1.128 relay.c
--- usr.sbin/relayd/relay.c 20 Dec 2010 12:38:06 -  1.128
+++ usr.sbin/relayd/relay.c 31 Jan 2011 23:19:59 -
@@ -2328,6 +2328,21 @@ relay_connect(struct rsession *con)
return (-1);
}
 
+   if (rlay-rl_proto-flags  F_SPLICE) {
+   if (setsockopt(con-se_in.s, SOL_SOCKET, SO_SPLICE,
+   con-se_out.s, sizeof(int)) == -1) {
+   log_debug(relay_connect: session %d: splice forward 
+   failed: %s, con-se_id, strerror(errno));
+   return (-1);
+   }
+   if (setsockopt(con-se_out.s, SOL_SOCKET, SO_SPLICE,
+   con-se_in.s, sizeof(int)) == -1) {
+   log_debug(relay_connect: session %d: splice backward 
+   failed: %s, con-se_id, strerror(errno));
+   return (-1);
+   }
+   }
+
if (errno == EINPROGRESS)
event_again(con-se_ev, con-se_out.s, EV_WRITE|EV_TIMEOUT,
relay_connected, con-se_tv_start, env-sc_timeout, con);
Index: usr.sbin/relayd/relayd.8
===
RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/relayd/relayd.8,v
retrieving revision 1.23
diff -u -p -r1.23 relayd.8
--- usr.sbin/relayd/relayd.824 May 2010 19:44:23 -  1.23
+++ usr.sbin/relayd/relayd.81 Feb 2011 00:10:22 -
@@ -121,6 +121,10 @@ Only check the configuration file for va
 .It Fl v
 Produce more verbose output.
 .El
+.Sh ENVIRONMENT
+It is possible to disable support for socket splicing by setting
+the environment variable
+.Ev RELAY_NOSPLICE .
 .Sh FILES
 .Bl -tag -width /var/run/relayd.sockXX -compact
 .It /etc/relayd.conf
Index: usr.sbin/relayd/relayd.h
===
RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/relayd/relayd.h,v
retrieving revision 1.140
diff -u -p -r1.140 relayd.h
--- usr.sbin/relayd/relayd.h31 Dec 2010 21:22:42 -  1.140
+++ usr.sbin/relayd/relayd.h31 Jan 2011 23:18:49 -
@@ -249,6 +249,7 @@ TAILQ_HEAD(addresslist, address);
 #define F_SSLCLIENT0x0020
 #define F_NEEDRT   0x0040
 #define F_MATCH0x0080
+#define F_SPLICE   0x0100
 
 enum forwardmode {
FWD_NORMAL  = 0,



Re: relayd socket splicing

2011-03-02 Thread Alexander Bluhm
I just relized that I did send out an outdated diff.  This one has
an additional check for F_SSL and F_SSLCLIENT to avoid splicing ssl
connections.

The RELAY_NOSPLICE environment variable is only for testing and
will be removed in the final version.

bluhm


Index: usr.sbin/relayd/parse.y
===
RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/relayd/parse.y,v
retrieving revision 1.149
diff -u -p -r1.149 parse.y
--- usr.sbin/relayd/parse.y 26 Oct 2010 15:04:37 -  1.149
+++ usr.sbin/relayd/parse.y 22 Feb 2011 22:54:05 -
@@ -796,6 +796,9 @@ proto   : relay_proto PROTO STRING  {
free($3);
p-id = ++last_proto_id;
p-type = $1;
+   if (p-type == RELAY_PROTO_TCP 
+   !getenv(RELAY_NOSPLICE))
+   p-flags |= F_SPLICE;
p-cache = RELAY_CACHESIZE;
p-tcpflags = TCPFLAG_DEFAULT;
p-sslflags = SSLFLAG_DEFAULT;
@@ -2170,6 +2173,8 @@ parse_config(const char *filename, int o
(void)strlcpy(conf-sc_proto_default.sslciphers, SSLCIPHERS_DEFAULT,
sizeof(conf-sc_proto_default.sslciphers));
conf-sc_proto_default.type = RELAY_PROTO_TCP;
+   if (!getenv(RELAY_NOSPLICE))
+   conf-sc_proto_default.flags |= F_SPLICE;
(void)strlcpy(conf-sc_proto_default.name, default,
sizeof(conf-sc_proto_default.name));
RB_INIT(conf-sc_proto_default.request_tree);
Index: usr.sbin/relayd/relay.c
===
RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/relayd/relay.c,v
retrieving revision 1.128
diff -u -p -r1.128 relay.c
--- usr.sbin/relayd/relay.c 20 Dec 2010 12:38:06 -  1.128
+++ usr.sbin/relayd/relay.c 22 Feb 2011 22:54:05 -
@@ -2328,6 +2328,22 @@ relay_connect(struct rsession *con)
return (-1);
}
 
+   if (rlay-rl_proto-flags  F_SPLICE 
+   (rlay-rl_conf.flags  (F_SSL|F_SSLCLIENT)) == 0) {
+   if (setsockopt(con-se_in.s, SOL_SOCKET, SO_SPLICE,
+   con-se_out.s, sizeof(int)) == -1) {
+   log_debug(relay_connect: session %d: splice forward 
+   failed: %s, con-se_id, strerror(errno));
+   return (-1);
+   }
+   if (setsockopt(con-se_out.s, SOL_SOCKET, SO_SPLICE,
+   con-se_in.s, sizeof(int)) == -1) {
+   log_debug(relay_connect: session %d: splice backward 
+   failed: %s, con-se_id, strerror(errno));
+   return (-1);
+   }
+   }
+
if (errno == EINPROGRESS)
event_again(con-se_ev, con-se_out.s, EV_WRITE|EV_TIMEOUT,
relay_connected, con-se_tv_start, env-sc_timeout, con);
Index: usr.sbin/relayd/relayd.8
===
RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/relayd/relayd.8,v
retrieving revision 1.23
diff -u -p -r1.23 relayd.8
--- usr.sbin/relayd/relayd.824 May 2010 19:44:23 -  1.23
+++ usr.sbin/relayd/relayd.822 Feb 2011 23:00:20 -
@@ -121,6 +121,12 @@ Only check the configuration file for va
 .It Fl v
 Produce more verbose output.
 .El
+.Sh ENVIRONMENT
+It is possible to disable support for socket splicing by setting
+the environment variable
+.Ev RELAY_NOSPLICE .
+Socket splicing is used by default to speed up plain TCP connections
+without ssl.
 .Sh FILES
 .Bl -tag -width /var/run/relayd.sockXX -compact
 .It /etc/relayd.conf
Index: usr.sbin/relayd/relayd.h
===
RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/relayd/relayd.h,v
retrieving revision 1.140
diff -u -p -r1.140 relayd.h
--- usr.sbin/relayd/relayd.h31 Dec 2010 21:22:42 -  1.140
+++ usr.sbin/relayd/relayd.h22 Feb 2011 22:54:05 -
@@ -249,6 +249,7 @@ TAILQ_HEAD(addresslist, address);
 #define F_SSLCLIENT0x0020
 #define F_NEEDRT   0x0040
 #define F_MATCH0x0080
+#define F_SPLICE   0x0100
 
 enum forwardmode {
FWD_NORMAL  = 0,