h2load: Add --max-udp-payload-size option

This commit is contained in:
Tatsuhiro Tsujikawa 2021-09-07 14:42:35 +09:00
parent 1657a425c1
commit 7ea57eaa18
3 changed files with 38 additions and 13 deletions

View File

@ -124,7 +124,8 @@ Config::Config()
base_uri_unix(false), base_uri_unix(false),
unix_addr{}, unix_addr{},
rps(0.), rps(0.),
no_udp_gso(false) {} no_udp_gso(false),
max_udp_payload_size(0) {}
Config::~Config() { Config::~Config() {
if (addrs) { if (addrs) {
@ -2247,6 +2248,8 @@ Options:
<< config.groups << R"( << config.groups << R"(
--no-udp-gso --no-udp-gso
Disable UDP GSO. Disable UDP GSO.
--max-udp-payload-size=<SIZE>
Specify the maximum outgoing UDP datagram payload size.
-v, --verbose -v, --verbose
Output debug information. Output debug information.
--version Display version information and exit. --version Display version information and exit.
@ -2312,6 +2315,7 @@ int main(int argc, char **argv) {
{"tls13-ciphers", required_argument, &flag, 14}, {"tls13-ciphers", required_argument, &flag, 14},
{"no-udp-gso", no_argument, &flag, 15}, {"no-udp-gso", no_argument, &flag, 15},
{"qlog-file-base", required_argument, &flag, 16}, {"qlog-file-base", required_argument, &flag, 16},
{"max-udp-payload-size", required_argument, &flag, 17},
{nullptr, 0, nullptr, 0}}; {nullptr, 0, nullptr, 0}};
int option_index = 0; int option_index = 0;
auto c = getopt_long(argc, argv, auto c = getopt_long(argc, argv,
@ -2578,6 +2582,22 @@ int main(int argc, char **argv) {
// --qlog-file-base // --qlog-file-base
qlog_base = optarg; qlog_base = optarg;
break; break;
case 17: {
// --max-udp-payload-size
auto n = util::parse_uint_with_unit(optarg);
if (n == -1) {
std::cerr << "--max-udp-payload-size: bad option value: " << optarg
<< std::endl;
exit(EXIT_FAILURE);
}
if (n > 64_k) {
std::cerr << "--max-udp-payload-size: must not exceed 65536"
<< std::endl;
exit(EXIT_FAILURE);
}
config.max_udp_payload_size = n;
break;
}
} }
break; break;
default: default:

View File

@ -133,6 +133,8 @@ struct Config {
double rps; double rps;
// Disables GSO for UDP connections. // Disables GSO for UDP connections.
bool no_udp_gso; bool no_udp_gso;
// The maximum UDP datagram payload size to send.
size_t max_udp_payload_size;
Config(); Config();
~Config(); ~Config();
@ -336,7 +338,6 @@ struct Client {
ev_timer pkt_timer; ev_timer pkt_timer;
ngtcp2_conn *conn; ngtcp2_conn *conn;
quic::Error last_error; quic::Error last_error;
size_t max_pktlen;
bool close_requested; bool close_requested;
FILE *qlog_file; FILE *qlog_file;
} quic; } quic;

View File

@ -305,8 +305,6 @@ int Client::quic_init(const sockaddr *local_addr, socklen_t local_addrlen,
SSL_set_quic_use_legacy_codepoint(ssl, 0); SSL_set_quic_use_legacy_codepoint(ssl, 0);
} }
quic.max_pktlen = NGTCP2_MAX_UDP_PAYLOAD_SIZE;
auto callbacks = ngtcp2_callbacks{ auto callbacks = ngtcp2_callbacks{
ngtcp2_crypto_client_initial_cb, ngtcp2_crypto_client_initial_cb,
nullptr, // recv_client_initial nullptr, // recv_client_initial
@ -373,6 +371,10 @@ int Client::quic_init(const sockaddr *local_addr, socklen_t local_addrlen,
} }
settings.qlog.write = qlog_write_cb; settings.qlog.write = qlog_write_cb;
} }
if (config->max_udp_payload_size) {
settings.max_udp_payload_size = config->max_udp_payload_size;
settings.no_udp_payload_size_shaping = 1;
}
ngtcp2_transport_params params; ngtcp2_transport_params params;
ngtcp2_transport_params_default(&params); ngtcp2_transport_params_default(&params);
@ -424,7 +426,7 @@ void Client::quic_close_connection() {
return; return;
} }
std::array<uint8_t, 1500> buf; std::array<uint8_t, NGTCP2_MAX_UDP_PAYLOAD_SIZE> buf;
ngtcp2_ssize nwrite; ngtcp2_ssize nwrite;
ngtcp2_path_storage ps; ngtcp2_path_storage ps;
ngtcp2_path_storage_zero(&ps); ngtcp2_path_storage_zero(&ps);
@ -434,12 +436,12 @@ void Client::quic_close_connection() {
return; return;
case quic::ErrorType::Transport: case quic::ErrorType::Transport:
nwrite = ngtcp2_conn_write_connection_close( nwrite = ngtcp2_conn_write_connection_close(
quic.conn, &ps.path, nullptr, buf.data(), quic.max_pktlen, quic.conn, &ps.path, nullptr, buf.data(), buf.size(),
quic.last_error.code, timestamp(worker->loop)); quic.last_error.code, timestamp(worker->loop));
break; break;
case quic::ErrorType::Application: case quic::ErrorType::Application:
nwrite = ngtcp2_conn_write_application_close( nwrite = ngtcp2_conn_write_application_close(
quic.conn, &ps.path, nullptr, buf.data(), quic.max_pktlen, quic.conn, &ps.path, nullptr, buf.data(), buf.size(),
quic.last_error.code, timestamp(worker->loop)); quic.last_error.code, timestamp(worker->loop));
break; break;
default: default:
@ -575,12 +577,14 @@ int Client::write_quic() {
std::array<nghttp3_vec, 16> vec; std::array<nghttp3_vec, 16> vec;
size_t pktcnt = 0; size_t pktcnt = 0;
auto max_udp_payload_size =
ngtcp2_conn_get_path_max_udp_payload_size(quic.conn);
size_t max_pktcnt = size_t max_pktcnt =
#ifdef UDP_SEGMENT #ifdef UDP_SEGMENT
worker->config->no_udp_gso worker->config->no_udp_gso
? 1 ? 1
: std::min(static_cast<size_t>(10), : std::min(static_cast<size_t>(10),
static_cast<size_t>(64_k / quic.max_pktlen)); static_cast<size_t>(64_k / max_udp_payload_size));
#else // !UDP_SEGMENT #else // !UDP_SEGMENT
1; 1;
#endif // !UDP_SEGMENT #endif // !UDP_SEGMENT
@ -614,8 +618,8 @@ int Client::write_quic() {
} }
auto nwrite = ngtcp2_conn_writev_stream( auto nwrite = ngtcp2_conn_writev_stream(
quic.conn, &ps.path, nullptr, bufpos, quic.max_pktlen, &ndatalen, flags, quic.conn, &ps.path, nullptr, bufpos, max_udp_payload_size, &ndatalen,
stream_id, reinterpret_cast<const ngtcp2_vec *>(v), vcnt, flags, stream_id, reinterpret_cast<const ngtcp2_vec *>(v), vcnt,
timestamp(worker->loop)); timestamp(worker->loop));
if (nwrite < 0) { if (nwrite < 0) {
switch (nwrite) { switch (nwrite) {
@ -650,7 +654,7 @@ int Client::write_quic() {
if (nwrite == 0) { if (nwrite == 0) {
if (bufpos - buf.data()) { if (bufpos - buf.data()) {
write_udp(ps.path.remote.addr, ps.path.remote.addrlen, buf.data(), write_udp(ps.path.remote.addr, ps.path.remote.addrlen, buf.data(),
bufpos - buf.data(), quic.max_pktlen); bufpos - buf.data(), max_udp_payload_size);
} }
return 0; return 0;
} }
@ -659,9 +663,9 @@ int Client::write_quic() {
// Assume that the path does not change. // Assume that the path does not change.
if (++pktcnt == max_pktcnt || if (++pktcnt == max_pktcnt ||
static_cast<size_t>(nwrite) < quic.max_pktlen) { static_cast<size_t>(nwrite) < max_udp_payload_size) {
write_udp(ps.path.remote.addr, ps.path.remote.addrlen, buf.data(), write_udp(ps.path.remote.addr, ps.path.remote.addrlen, buf.data(),
bufpos - buf.data(), quic.max_pktlen); bufpos - buf.data(), max_udp_payload_size);
signal_write(); signal_write();
return 0; return 0;
} }