From 4b52698c4a6a384ff8e682dc0838c037c6bc2a42 Mon Sep 17 00:00:00 2001 From: Marko Kreen Date: Tue, 22 Jan 2008 15:27:17 +0000 Subject: [PATCH] tcp_defer_accept improvements. - support freebsd accept filter - remove user control of actual value, as its basically undocumented - allow online setting change --- include/pooler.h | 2 +- src/main.c | 17 +++++++++++--- src/pooler.c | 61 ++++++++++++++++++++++++++++++++++-------------- 3 files changed, 59 insertions(+), 21 deletions(-) diff --git a/include/pooler.h b/include/pooler.h index 5775d22..3a98ca9 100644 --- a/include/pooler.h +++ b/include/pooler.h @@ -22,4 +22,4 @@ void resume_pooler(void); void suspend_pooler(void); void get_pooler_fds(int *p_net, int *p_unix); void per_loop_pooler_maint(void); - +void pooler_tune_accept(bool on); diff --git a/src/main.c b/src/main.c index 7235872..2963f46 100644 --- a/src/main.c +++ b/src/main.c @@ -31,6 +31,7 @@ static bool set_mode(ConfElem *elem, const char *val, PgSocket *console); static const char *get_mode(ConfElem *elem); static bool set_auth(ConfElem *elem, const char *val, PgSocket *console); static const char *get_auth(ConfElem *elem); +static bool set_defer_accept(ConfElem *elem, const char *val, PgSocket *console); static const char *usage_str = "usage: pgbouncer [-d] [-R] [-q] [-v] [-h|-V] config.ini\n"; @@ -64,8 +65,8 @@ int cf_pool_mode = POOL_SESSION; /* sbuf config */ int cf_sbuf_len = 2048; int cf_tcp_socket_buffer = 0; -#ifdef TCP_DEFER_ACCEPT -int cf_tcp_defer_accept = 45; +#if defined(TCP_DEFER_ACCEPT) || defined(SO_ACCEPTFILTER) +int cf_tcp_defer_accept = 1; #else int cf_tcp_defer_accept = 0; #endif @@ -141,7 +142,7 @@ ConfElem bouncer_params[] = { {"suspend_timeout", true, CF_TIME, &cf_suspend_timeout}, {"pkt_buf", false, CF_INT, &cf_sbuf_len}, -{"tcp_defer_accept", false, CF_INT, &cf_tcp_defer_accept}, +{"tcp_defer_accept", true, {cf_get_int, set_defer_accept}}, {"tcp_socket_buffer", true, CF_INT, &cf_tcp_socket_buffer}, {"tcp_keepalive", true, CF_INT, &cf_tcp_keepalive}, {"tcp_keepcnt", true, CF_INT, &cf_tcp_keepcnt}, @@ -223,6 +224,16 @@ static bool set_auth(ConfElem *elem, const char *val, PgSocket *console) return true; } +static bool set_defer_accept(ConfElem *elem, const char *val, PgSocket *console) +{ + bool ok; + int oldval = cf_tcp_defer_accept; + ok = cf_set_int(elem, val, console); + if (ok && !!oldval != !!cf_tcp_defer_accept) + pooler_tune_accept(cf_tcp_defer_accept); + return true; +} + static void set_dbs_dead(bool flag) { List *item; diff --git a/src/pooler.c b/src/pooler.c index c37033d..60f3d39 100644 --- a/src/pooler.c +++ b/src/pooler.c @@ -111,6 +111,47 @@ static int create_unix_socket(const char *socket_dir, int listen_port) return sock; } +/* + * Notify pooler only when also data is arrived. + * + * optval specifies how long after connection attempt to wait for data. + * + * Related to tcp_synack_retries sysctl, default 5 (corresponds 180 secs). + * + * SO_ACCEPTFILTER needs to be set after listern(), maybe TCP_DEFER_ACCEPT too. + */ +static void tune_accept(int sock, bool on) +{ + const char *act = on ? "install" : "uninstall"; + int res = 0; +#ifdef TCP_DEFER_ACCEPT + int val = 45; /* fixme: proper value */ + res = getsockopt(sock, IPPROTO_TCP, TCP_DEFER_ACCEPT, &val, sizeof(val)); + log_noise("old TCP_DEFER_ACCEPT on %d = %d", sock, val); + val = on ? 1 : 0; + log_noise("%s TCP_DEFER_ACCEPT on %d", act, sock); + res = setsockopt(sock, IPPROTO_TCP, TCP_DEFER_ACCEPT, &val, sizeof(val)); +#else +#ifdef SO_ACCEPTFILTER + struct accept_filter_arg af, *afp = on ? &af : NULL; + socklen_t af_len = on ? sizeof(af) : 0; + memset(&af, 0, sizeof(af)); + strcpy(af.af_name, "dataready"); + log_noise("%s SO_ACCEPTFILTER on %d", act, sock); + res = setsockopt(sock, SOL_SOCKET, SO_ACCEPTFILTER, afp, af_len); +#endif +#endif + if (res < 0) + log_warning("tune_accept: %s TCP_DEFER_ACCEPT/SO_ACCEPTFILTER: %s", + act, strerror(errno)); +} + +void pooler_tune_accept(bool on) +{ + if (fd_net > 0) + tune_accept(fd_net, on); +} + static int create_net_socket(const char *listen_addr, int listen_port) { int sock; @@ -149,27 +190,13 @@ static int create_net_socket(const char *listen_addr, int listen_port) /* set common options */ tune_socket(sock, false); -#ifdef TCP_DEFER_ACCEPT - /* - * Notify pooler only when also data is arrived. - * - * optval specifies how long after connection attempt to wait for data. - * - * Related to tcp_synack_retries sysctl, default 5 (corresponds 180 secs). - */ - if (cf_tcp_defer_accept > 0) { - val = cf_tcp_defer_accept; - res = setsockopt(sock, IPPROTO_TCP, TCP_DEFER_ACCEPT, &val, sizeof(val)); - if (res < 0) - fatal_perror("setsockopt TCP_DEFER_ACCEPT"); - } -#endif - - /* finally, accept connections */ + /* make it accept connections */ res = listen(sock, 100); if (res < 0) fatal_perror("listen"); + tune_accept(sock, cf_tcp_defer_accept); + log_info("listening on %s:%d", cf_listen_addr, cf_listen_port); return sock; -- 2.40.0