diff --git a/gennghttpxfun.py b/gennghttpxfun.py index eb95026d..90a4ffbb 100755 --- a/gennghttpxfun.py +++ b/gennghttpxfun.py @@ -102,6 +102,7 @@ OPTIONS = [ "response-phase-file", "accept-proxy-protocol", "conf", + "fastopen", ] LOGVARS = [ diff --git a/src/shrpx.cc b/src/shrpx.cc index a9cdfdd9..5935142e 100644 --- a/src/shrpx.cc +++ b/src/shrpx.cc @@ -107,6 +107,19 @@ namespace shrpx { // path. #define ENV_UNIX_PATH "NGHTTP2_UNIX_PATH" +#ifndef _KERNEL_FASTOPEN +#define _KERNEL_FASTOPEN +// conditional define for TCP_FASTOPEN mostly on ubuntu +#ifndef TCP_FASTOPEN +#define TCP_FASTOPEN 23 +#endif + +// conditional define for SOL_TCP mostly on ubuntu +#ifndef SOL_TCP +#define SOL_TCP 6 +#endif +#endif + struct SignalServer { SignalServer() : ipc_fd{{-1, -1}}, server_fd(-1), server_fd6(-1), @@ -605,6 +618,14 @@ int create_tcp_server_socket(int family) { continue; } + if(get_config()->fastopen > 0) { + val = get_config()->fastopen; + if (setsockopt(fd, SOL_TCP, TCP_FASTOPEN, &val, + static_cast(sizeof(val))) == -1) { + LOG(WARN) << "Failed to set TCP_FASTOPEN option to listener socket"; + } + } + if (listen(fd, get_config()->backlog) == -1) { auto error = errno; LOG(WARN) << "listen() syscall failed, error=" << error; @@ -1009,6 +1030,7 @@ void fill_default_config() { mod_config()->tls_ticket_key_memcached_max_retry = 3; mod_config()->tls_ticket_key_memcached_max_fail = 2; mod_config()->tls_ticket_key_memcached_interval = 10_min; + mod_config()->fastopen = 0; } } // namespace @@ -1217,7 +1239,14 @@ Performance: Default: )" << util::utos_with_unit(get_config()->downstream_response_buffer_size) << R"( - + --fastopen= + enables “TCP Fast Open” for the listening socket + and limits the maximum length for the queue of connections + that have not yet completed the three-way handshake. + If value is 0 then fast open is disabled. + Default: )" + << util::utos_with_unit(get_config()->fastopen) + << R"( Timeout: --frontend-http2-read-timeout= Specify read timeout for HTTP/2 and SPDY frontend @@ -1775,6 +1804,7 @@ int main(int argc, char **argv) { {SHRPX_OPT_REQUEST_PHASE_FILE, required_argument, &flag, 91}, {SHRPX_OPT_RESPONSE_PHASE_FILE, required_argument, &flag, 92}, {SHRPX_OPT_ACCEPT_PROXY_PROTOCOL, no_argument, &flag, 93}, + {SHRPX_OPT_FASTOPEN, required_argument, &flag, 94}, {nullptr, 0, nullptr, 0}}; int option_index = 0; @@ -2180,6 +2210,10 @@ int main(int argc, char **argv) { // --accept-proxy-protocol cmdcfgs.emplace_back(SHRPX_OPT_ACCEPT_PROXY_PROTOCOL, "yes"); break; + case 94: + // --fastopen + cmdcfgs.emplace_back(SHRPX_OPT_FASTOPEN, optarg); + break; default: break; } diff --git a/src/shrpx_config.cc b/src/shrpx_config.cc index bdab013d..d1d7bd52 100644 --- a/src/shrpx_config.cc +++ b/src/shrpx_config.cc @@ -649,6 +649,7 @@ enum { SHRPX_OPTID_DH_PARAM_FILE, SHRPX_OPTID_ERRORLOG_FILE, SHRPX_OPTID_ERRORLOG_SYSLOG, + SHRPX_OPTID_FASTOPEN, SHRPX_OPTID_FETCH_OCSP_RESPONSE_FILE, SHRPX_OPTID_FRONTEND, SHRPX_OPTID_FRONTEND_FRAME_DEBUG, @@ -814,6 +815,11 @@ int option_lookup_token(const char *name, size_t namelen) { return SHRPX_OPTID_PID_FILE; } break; + case 'n': + if (util::strieq_l("fastope", name, 7)) { + return SHRPX_OPTID_FASTOPEN; + } + break; case 't': if (util::strieq_l("npn-lis", name, 7)) { return SHRPX_OPTID_NPN_LIST; @@ -1444,6 +1450,21 @@ int parse_config(const char *opt, const char *optarg, mod_config()->errorlog_syslog = util::strieq(optarg, "yes"); return 0; + case SHRPX_OPTID_FASTOPEN: { + int n; + if (parse_int(&n, opt, optarg) != 0) { + return -1; + } + + if (n < 0) { + LOG(ERROR) << opt << ": " << optarg << " is not allowed"; + return -1; + } + + mod_config()->fastopen = n; + + return 0; + } case SHRPX_OPTID_BACKEND_KEEP_ALIVE_TIMEOUT: return parse_duration(&mod_config()->downstream_idle_read_timeout, opt, optarg); diff --git a/src/shrpx_config.h b/src/shrpx_config.h index 3cf81db1..8290b269 100644 --- a/src/shrpx_config.h +++ b/src/shrpx_config.h @@ -187,6 +187,7 @@ constexpr char SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_MAX_FAIL[] = constexpr char SHRPX_OPT_REQUEST_PHASE_FILE[] = "request-phase-file"; constexpr char SHRPX_OPT_RESPONSE_PHASE_FILE[] = "response-phase-file"; constexpr char SHRPX_OPT_ACCEPT_PROXY_PROTOCOL[] = "accept-proxy-protocol"; +constexpr char SHRPX_OPT_FASTOPEN[] = "fastopen"; union sockaddr_union { sockaddr_storage storage; @@ -377,6 +378,7 @@ struct Config { int syslog_facility; int backlog; int argc; + int fastopen; uid_t uid; gid_t gid; pid_t pid;