QUIC UDP GSO
This commit is contained in:
parent
eb1607890a
commit
a37117a98b
|
@ -35,6 +35,7 @@
|
|||
# include <fcntl.h>
|
||||
#endif // HAVE_FCNTL_H
|
||||
#include <sys/mman.h>
|
||||
#include <netinet/udp.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
|
@ -117,7 +118,8 @@ Config::Config()
|
|||
timing_script(false),
|
||||
base_uri_unix(false),
|
||||
unix_addr{},
|
||||
rps(0.) {}
|
||||
rps(0.),
|
||||
no_udp_gso(false) {}
|
||||
|
||||
Config::~Config() {
|
||||
if (addrs) {
|
||||
|
@ -1375,8 +1377,32 @@ int Client::write_tls() {
|
|||
}
|
||||
|
||||
int Client::write_udp(const sockaddr *addr, socklen_t addrlen,
|
||||
const uint8_t *data, size_t datalen) {
|
||||
auto nwrite = sendto(fd, data, datalen, MSG_DONTWAIT, addr, addrlen);
|
||||
const uint8_t *data, size_t datalen, size_t gso_size) {
|
||||
iovec msg_iov;
|
||||
msg_iov.iov_base = const_cast<uint8_t *>(data);
|
||||
msg_iov.iov_len = datalen;
|
||||
|
||||
msghdr msg{};
|
||||
msg.msg_name = const_cast<sockaddr *>(addr);
|
||||
msg.msg_namelen = addrlen;
|
||||
msg.msg_iov = &msg_iov;
|
||||
msg.msg_iovlen = 1;
|
||||
|
||||
#ifdef UDP_SEGMENT
|
||||
std::array<uint8_t, CMSG_SPACE(sizeof(uint16_t))> msg_ctrl{};
|
||||
if (gso_size && datalen > gso_size) {
|
||||
msg.msg_control = msg_ctrl.data();
|
||||
msg.msg_controllen = msg_ctrl.size();
|
||||
|
||||
auto cm = CMSG_FIRSTHDR(&msg);
|
||||
cm->cmsg_level = SOL_UDP;
|
||||
cm->cmsg_type = UDP_SEGMENT;
|
||||
cm->cmsg_len = CMSG_LEN(sizeof(uint16_t));
|
||||
*(reinterpret_cast<uint16_t *>(CMSG_DATA(cm))) = gso_size;
|
||||
}
|
||||
#endif // UDP_SEGMENT
|
||||
|
||||
auto nwrite = sendmsg(fd, &msg, 0);
|
||||
if (nwrite < 0) {
|
||||
std::cerr << "sendto: errno=" << errno << std::endl;
|
||||
} else {
|
||||
|
@ -2183,6 +2209,8 @@ Options:
|
|||
Specify the supported groups.
|
||||
Default: )"
|
||||
<< config.groups << R"(
|
||||
--no-udp-gso
|
||||
Disable UDP GSO.
|
||||
-v, --verbose
|
||||
Output debug information.
|
||||
--version Display version information and exit.
|
||||
|
@ -2245,6 +2273,7 @@ int main(int argc, char **argv) {
|
|||
{"rps", required_argument, &flag, 12},
|
||||
{"groups", required_argument, &flag, 13},
|
||||
{"tls13-ciphers", required_argument, &flag, 14},
|
||||
{"no-udp-gso", no_argument, &flag, 15},
|
||||
{nullptr, 0, nullptr, 0}};
|
||||
int option_index = 0;
|
||||
auto c = getopt_long(argc, argv,
|
||||
|
@ -2503,6 +2532,10 @@ int main(int argc, char **argv) {
|
|||
// --tls13-ciphers
|
||||
config.tls13_ciphers = optarg;
|
||||
break;
|
||||
case 15:
|
||||
// --no-udp-gso
|
||||
config.no_udp_gso = true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -125,6 +125,8 @@ struct Config {
|
|||
std::vector<std::string> npn_list;
|
||||
// The number of request per second for each client.
|
||||
double rps;
|
||||
// Disables GSO for UDP connections.
|
||||
bool no_udp_gso;
|
||||
|
||||
Config();
|
||||
~Config();
|
||||
|
@ -458,7 +460,7 @@ struct Client {
|
|||
int read_quic();
|
||||
int write_quic();
|
||||
int write_udp(const sockaddr *addr, socklen_t addrlen, const uint8_t *data,
|
||||
size_t datalen);
|
||||
size_t datalen, size_t gso_size);
|
||||
void quic_close_connection();
|
||||
|
||||
int quic_recv_crypto_data(ngtcp2_crypto_level crypto_level,
|
||||
|
|
|
@ -402,6 +402,15 @@ int Http3Session::block_stream(int64_t stream_id) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int Http3Session::shutdown_stream_write(int64_t stream_id) {
|
||||
auto rv = nghttp3_conn_shutdown_stream_write(conn_, stream_id);
|
||||
if (rv != 0) {
|
||||
client_->quic.last_error = quic::err_application(rv);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Http3Session::add_write_offset(int64_t stream_id, size_t ndatalen) {
|
||||
auto rv = nghttp3_conn_add_write_offset(conn_, stream_id, ndatalen);
|
||||
if (rv != 0) {
|
||||
|
|
|
@ -63,6 +63,7 @@ public:
|
|||
ssize_t write_stream(int64_t &stream_id, int &fin, nghttp3_vec *vec,
|
||||
size_t veccnt);
|
||||
int block_stream(int64_t stream_id);
|
||||
int shutdown_stream_write(int64_t stream_id);
|
||||
int add_write_offset(int64_t stream_id, size_t ndatalen);
|
||||
int add_ack_offset(int64_t stream_id, size_t datalen);
|
||||
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
*/
|
||||
#include "h2load_quic.h"
|
||||
|
||||
#include <netinet/udp.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <ngtcp2/ngtcp2_crypto_openssl.h>
|
||||
|
@ -425,7 +427,7 @@ void Client::quic_close_connection() {
|
|||
}
|
||||
|
||||
write_udp(reinterpret_cast<sockaddr *>(ps.path.remote.addr),
|
||||
ps.path.remote.addrlen, buf.data(), nwrite);
|
||||
ps.path.remote.addrlen, buf.data(), nwrite, 0);
|
||||
}
|
||||
|
||||
int Client::quic_on_key(ngtcp2_crypto_level level, const uint8_t *rx_secret,
|
||||
|
@ -554,7 +556,18 @@ int Client::write_quic() {
|
|||
}
|
||||
|
||||
std::array<nghttp3_vec, 16> vec;
|
||||
std::array<uint8_t, 1500> buf;
|
||||
size_t pktcnt = 0;
|
||||
size_t max_pktcnt =
|
||||
#ifdef UDP_SEGMENT
|
||||
worker->config->no_udp_gso
|
||||
? 1
|
||||
: std::min(static_cast<size_t>(10),
|
||||
static_cast<size_t>(64_k / quic.max_pktlen));
|
||||
#else // !UDP_SEGMENT
|
||||
1;
|
||||
#endif // !UDP_SEGMENT
|
||||
std::array<uint8_t, 64_k> buf;
|
||||
uint8_t *bufpos = buf.data();
|
||||
ngtcp2_path_storage ps;
|
||||
|
||||
ngtcp2_path_storage_zero(&ps);
|
||||
|
@ -583,16 +596,20 @@ int Client::write_quic() {
|
|||
}
|
||||
|
||||
auto nwrite = ngtcp2_conn_writev_stream(
|
||||
quic.conn, &ps.path, nullptr, buf.data(), quic.max_pktlen, &ndatalen,
|
||||
flags, stream_id, reinterpret_cast<const ngtcp2_vec *>(v), vcnt,
|
||||
quic.conn, &ps.path, nullptr, bufpos, quic.max_pktlen, &ndatalen, flags,
|
||||
stream_id, reinterpret_cast<const ngtcp2_vec *>(v), vcnt,
|
||||
timestamp(worker->loop));
|
||||
if (nwrite < 0) {
|
||||
switch (nwrite) {
|
||||
case NGTCP2_ERR_STREAM_DATA_BLOCKED:
|
||||
assert(ndatalen == -1);
|
||||
if (s->block_stream(stream_id) != 0) {
|
||||
return -1;
|
||||
}
|
||||
continue;
|
||||
case NGTCP2_ERR_STREAM_SHUT_WR:
|
||||
assert(ndatalen == -1);
|
||||
|
||||
if (s->block_stream(stream_id) != 0) {
|
||||
if (s->shutdown_stream_write(stream_id) != 0) {
|
||||
return -1;
|
||||
}
|
||||
continue;
|
||||
|
@ -613,11 +630,23 @@ int Client::write_quic() {
|
|||
quic_restart_pkt_timer();
|
||||
|
||||
if (nwrite == 0) {
|
||||
if (bufpos - buf.data()) {
|
||||
write_udp(ps.path.remote.addr, ps.path.remote.addrlen, buf.data(),
|
||||
bufpos - buf.data(), quic.max_pktlen);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
write_udp(reinterpret_cast<sockaddr *>(ps.path.remote.addr),
|
||||
ps.path.remote.addrlen, buf.data(), nwrite);
|
||||
bufpos += nwrite;
|
||||
|
||||
// Assume that the path does not change.
|
||||
if (++pktcnt == max_pktcnt ||
|
||||
static_cast<size_t>(nwrite) < quic.max_pktlen) {
|
||||
write_udp(ps.path.remote.addr, ps.path.remote.addrlen, buf.data(),
|
||||
bufpos - buf.data(), quic.max_pktlen);
|
||||
signal_write();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue