Re: relayd socket splicing timeout
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
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
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
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
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
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
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
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
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
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,