From 8f419a4869ae3c592d05635854a1c7f3b31422e8 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Mon, 13 Sep 2021 21:35:46 +0900 Subject: [PATCH] nghttpx: Add --frontend-quic-congestion-controller option --- gennghttpxfun.py | 1 + src/shrpx.cc | 18 ++++++++++++++++++ src/shrpx_config.cc | 16 ++++++++++++++++ src/shrpx_config.h | 4 ++++ src/shrpx_http3_upstream.cc | 9 ++++++++- 5 files changed, 47 insertions(+), 1 deletion(-) diff --git a/gennghttpxfun.py b/gennghttpxfun.py index 988cb331..13fecf26 100755 --- a/gennghttpxfun.py +++ b/gennghttpxfun.py @@ -191,6 +191,7 @@ OPTIONS = [ "frontend-quic-early-data", "frontend-quic-qlog-dir", "frontend-quic-require-token", + "frontend-quic-congestion-controller", ] LOGVARS = [ diff --git a/src/shrpx.cc b/src/shrpx.cc index ed7ff18f..c60e4143 100644 --- a/src/shrpx.cc +++ b/src/shrpx.cc @@ -1854,6 +1854,8 @@ void fill_default_config(Config *config) { auto &bpfconf = quicconf.bpf; bpfconf.prog_file = StringRef::from_lit(PKGLIBDIR "/reuseport_kern.o"); + + upstreamconf.congestion_controller = NGTCP2_CC_ALGO_CUBIC; } auto &http3conf = config->http3; @@ -3226,6 +3228,15 @@ HTTP/3 and QUIC: Require an address validation token for a frontend QUIC connection. Server sends a token in Retry packet or NEW_TOKEN frame in the previous connection. + --frontend-quic-congestion-controller= + Specify a congestion controller algorithm for a frontend + QUIC connection. should be either "cubic" or + "bbr". + Default: )" + << (config->quic.upstream.congestion_controller == NGTCP2_CC_ALGO_CUBIC + ? "cubic" + : "bbr") + << R"( --no-quic-bpf Disable eBPF. --frontend-http3-window-size= @@ -4022,6 +4033,8 @@ int main(int argc, char **argv) { 181}, {SHRPX_OPT_FRONTEND_QUIC_REQUIRE_TOKEN.c_str(), no_argument, &flag, 182}, + {SHRPX_OPT_FRONTEND_QUIC_CONGESTION_CONTROLLER.c_str(), + required_argument, &flag, 183}, {nullptr, 0, nullptr, 0}}; int option_index = 0; @@ -4894,6 +4907,11 @@ int main(int argc, char **argv) { cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_QUIC_REQUIRE_TOKEN, StringRef::from_lit("yes")); break; + case 183: + // --frontend-quic-congestion-controller + cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_QUIC_CONGESTION_CONTROLLER, + StringRef{optarg}); + break; default: break; } diff --git a/src/shrpx_config.cc b/src/shrpx_config.cc index a9886119..be272f62 100644 --- a/src/shrpx_config.cc +++ b/src/shrpx_config.cc @@ -2571,6 +2571,9 @@ int option_lookup_token(const char *name, size_t namelen) { if (util::strieq_l("frontend-http2-dump-response-heade", name, 34)) { return SHRPX_OPTID_FRONTEND_HTTP2_DUMP_RESPONSE_HEADER; } + if (util::strieq_l("frontend-quic-congestion-controlle", name, 34)) { + return SHRPX_OPTID_FRONTEND_QUIC_CONGESTION_CONTROLLER; + } break; } break; @@ -3997,6 +4000,19 @@ int parse_config(Config *config, int optid, const StringRef &opt, config->quic.upstream.require_token = util::strieq_l("yes", optarg); #endif // ENABLE_HTTP3 + return 0; + case SHRPX_OPTID_FRONTEND_QUIC_CONGESTION_CONTROLLER: +#ifdef ENABLE_HTTP3 + if (util::strieq_l("cubic", optarg)) { + config->quic.upstream.congestion_controller = NGTCP2_CC_ALGO_CUBIC; + } else if (util::strieq_l("bbr", optarg)) { + config->quic.upstream.congestion_controller = NGTCP2_CC_ALGO_BBR; + } else { + LOG(ERROR) << opt << ": must be either cubic or bbr"; + return -1; + } +#endif // ENABLE_HTTP3 + return 0; case SHRPX_OPTID_CONF: LOG(WARN) << "conf: ignored"; diff --git a/src/shrpx_config.h b/src/shrpx_config.h index 6b781f38..c46ebe5b 100644 --- a/src/shrpx_config.h +++ b/src/shrpx_config.h @@ -389,6 +389,8 @@ constexpr auto SHRPX_OPT_FRONTEND_QUIC_QLOG_DIR = StringRef::from_lit("frontend-quic-qlog-dir"); constexpr auto SHRPX_OPT_FRONTEND_QUIC_REQUIRE_TOKEN = StringRef::from_lit("frontend-quic-require-token"); +constexpr auto SHRPX_OPT_FRONTEND_QUIC_CONGESTION_CONTROLLER = + StringRef::from_lit("frontend-quic-congestion-controller"); constexpr size_t SHRPX_OBFUSCATED_NODE_LENGTH = 8; @@ -756,6 +758,7 @@ struct QUICConfig { struct { StringRef dir; } qlog; + ngtcp2_cc_algo congestion_controller; bool early_data; bool require_token; } upstream; @@ -1210,6 +1213,7 @@ enum { SHRPX_OPTID_FRONTEND_KEEP_ALIVE_TIMEOUT, SHRPX_OPTID_FRONTEND_MAX_REQUESTS, SHRPX_OPTID_FRONTEND_NO_TLS, + SHRPX_OPTID_FRONTEND_QUIC_CONGESTION_CONTROLLER, SHRPX_OPTID_FRONTEND_QUIC_DEBUG_LOG, SHRPX_OPTID_FRONTEND_QUIC_EARLY_DATA, SHRPX_OPTID_FRONTEND_QUIC_IDLE_TIMEOUT, diff --git a/src/shrpx_http3_upstream.cc b/src/shrpx_http3_upstream.cc index 4dd035af..29862e1d 100644 --- a/src/shrpx_http3_upstream.cc +++ b/src/shrpx_http3_upstream.cc @@ -573,7 +573,7 @@ int Http3Upstream::init(const UpstreamAddr *faddr, const Address &remote_addr, } settings.initial_ts = quic_timestamp(); - settings.cc_algo = NGTCP2_CC_ALGO_BBR; + settings.cc_algo = quicconf.upstream.congestion_controller; settings.max_window = http3conf.upstream.max_connection_window_size; settings.max_stream_window = http3conf.upstream.max_window_size; settings.max_udp_payload_size = SHRPX_QUIC_MAX_UDP_PAYLOAD_SIZE; @@ -665,6 +665,13 @@ int Http3Upstream::write_streams() { ngtcp2_path_storage_zero(&ps); ngtcp2_path_storage_zero(&prev_ps); + auto config = get_config(); + auto &quicconf = config->quic; + + if (quicconf.upstream.congestion_controller != NGTCP2_CC_ALGO_BBR) { + max_pktcnt = std::min(max_pktcnt, static_cast(10)); + } + for (;;) { int64_t stream_id = -1; int fin = 0;