Merging upstream version 2.9.0.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-09 09:03:47 +01:00
parent e32f91254b
commit a2303c9c61
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
13 changed files with 202 additions and 21 deletions

View file

@ -413,6 +413,24 @@ Following type are available.
\fBsendfailed\fR: Suppress messages about failure to send packets or if only parts of the packet were sent
.br
\fBsockready\fR: Suppress messages about socket readiness
.br
\fBunexpected\fR: Suppress messages about answers with an unexpected message ID
.RE
\fBnum-queries-per-conn=\fINUMBER\fR
.br
.RS
This will limit the number of queries sent over a connection before
triggering a re-connection. Once re-connected it will reset the counter and
continue sending queries until the limit is reached again, triggering
another re-connection and so on.
Using this option will also enable counting number of responses received
for each connection and once the limit is reached for sending queries it
will wait until the same amount of responses has been received before
re-connecting.
Waiting for responses may timeout and the timeout used for this is the
same as specified by \fB-t\fR.
Note that this option is only useful for connection oriented protocols.
.RE
.SH "SEE ALSO"
\fBresperf\fR(1)

View file

@ -89,6 +89,7 @@ typedef struct {
bool verbose;
enum perf_net_mode mode;
perf_suppress_t suppress;
size_t num_queries_per_conn;
} config_t;
typedef struct {
@ -491,6 +492,8 @@ setup(int argc, char** argv, config_t* config)
"the HTTP method to use for DNS-over-HTTPS: GET or POST", DEFAULT_DOH_METHOD, &doh_method);
perf_long_opt_add("suppress", perf_opt_string, "message[,message,...]",
"suppress messages/warnings, see man-page for list of message types", NULL, &local_suppress);
perf_long_opt_add("num-queries-per-conn", perf_opt_uint, "queries",
"Number of queries to send per connection", NULL, &config->num_queries_per_conn);
bool log_stdout = false;
perf_opt_add('W', perf_opt_boolean, NULL, "log warnings and errors to stdout instead of stderr", NULL, &log_stdout);
@ -1000,7 +1003,7 @@ do_recv(void* arg)
perf_log_warning("received short response");
continue;
}
if (recvd[i].unexpected) {
if (recvd[i].unexpected && !tinfo->config->suppress.unexpected) {
perf_log_warning("received a response with an "
"unexpected (maybe timed out) "
"id: %u",
@ -1222,6 +1225,9 @@ threadinfo_init(threadinfo_t* tinfo, const config_t* config,
if (!tinfo->socks[i]) {
perf_log_fatal("perf_net_opensocket(): no socket returned, out of memory?");
}
if (config->num_queries_per_conn && tinfo->socks[i]->num_queries_per_conn) {
tinfo->socks[i]->num_queries_per_conn(tinfo->socks[i], config->num_queries_per_conn, config->timeout);
}
}
tinfo->current_sock = 0;

View file

@ -80,6 +80,8 @@ typedef enum perf_socket_event {
/* Callback for socket events related to connection oriented protocols, for statistics */
typedef void (*perf_net_event_cb_t)(struct perf_net_socket* sock, perf_socket_event_t event, uint64_t elapsed_time);
typedef void (*perf_net_num_queries_per_conn_t)(struct perf_net_socket* sock, size_t num_queries_per_conn, size_t timeout);
struct perf_net_socket {
void* data; /* user data */
@ -91,6 +93,8 @@ struct perf_net_socket {
perf_net_sockready_t sockready;
perf_net_have_more_t have_more;
perf_net_num_queries_per_conn_t num_queries_per_conn;
/*
* Not set by protocol, set by caller.
* May be 0 if caller don't care.

View file

@ -118,6 +118,10 @@ struct perf__doh_socket {
char recvbuf[TCP_RECV_BUF_SIZE];
size_t recv_at;
size_t num_queries_per_conn, nqpc_timeout;
unsigned int nqpc_sent, nqpc_recv;
uint64_t nqpc_ts;
};
static pthread_mutex_t _nghttp2_lock = PTHREAD_MUTEX_INITIALIZER;
@ -157,6 +161,10 @@ static void perf__doh_connect(struct perf_net_socket* sock)
{
int ret;
self->nqpc_sent = 0;
ck_pr_store_uint(&self->nqpc_recv, 0);
self->nqpc_ts = 0;
nghttp2_session_del(self->http2.session);
ret = nghttp2_session_client_new2(&self->http2.session, _nghttp2_callbacks, sock, _nghttp2_option);
if (ret < 0) {
@ -394,6 +402,9 @@ static ssize_t perf__doh_recv(struct perf_net_socket* sock, void* buf, size_t le
// self->have_more = false; TODO
PERF_UNLOCK(&self->lock);
if (self->num_queries_per_conn) {
ck_pr_inc_uint(&self->nqpc_recv);
}
return len;
}
@ -586,6 +597,8 @@ static ssize_t perf__doh_sendto(struct perf_net_socket* sock, uint16_t qid, cons
}
PERF_UNLOCK(&self->lock);
self->nqpc_sent++;
return len;
}
@ -628,6 +641,21 @@ static int perf__doh_sockready(struct perf_net_socket* sock, int pipe_fd, int64_
}
self->is_sending = false;
sent = true;
self->nqpc_sent++;
}
if (self->num_queries_per_conn && self->nqpc_sent >= self->num_queries_per_conn) {
if (!self->nqpc_ts) {
self->nqpc_ts = perf_get_time() + self->nqpc_timeout;
}
unsigned int r = ck_pr_load_uint(&self->nqpc_recv);
if (r >= self->nqpc_sent || perf_get_time() > self->nqpc_ts) {
self->do_reconnect = true;
}
PERF_UNLOCK(&self->lock);
if (sent && sock->sent) {
sock->sent(sock, self->qid);
}
return 0;
}
PERF_UNLOCK(&self->lock);
if (sent && sock->sent) {
@ -898,6 +926,12 @@ static int select_next_proto_cb(SSL* ssl, unsigned char** out,
}
#endif /* !OPENSSL_NO_NEXTPROTONEG */
static void perf__doh_num_queries_per_conn(struct perf_net_socket* sock, size_t num_queries_per_conn, size_t timeout)
{
self->num_queries_per_conn = num_queries_per_conn;
self->nqpc_timeout = timeout;
}
struct perf_net_socket* perf_net_doh_opensocket(const perf_sockaddr_t* server, const perf_sockaddr_t* local, size_t bufsize, void* data, perf_net_sent_cb_t sent, perf_net_event_cb_t event)
{
struct perf__doh_socket* tmp = calloc(1, sizeof(struct perf__doh_socket)); // clang scan-build
@ -915,6 +949,8 @@ struct perf_net_socket* perf_net_doh_opensocket(const perf_sockaddr_t* server, c
sock->sockready = perf__doh_sockready;
sock->have_more = perf__doh_have_more;
sock->num_queries_per_conn = perf__doh_num_queries_per_conn;
sock->data = data;
sock->sent = sent;
sock->event = event;

View file

@ -55,12 +55,20 @@ struct perf__dot_socket {
uint64_t conn_ts;
perf_socket_event_t conn_event, conning_event;
size_t num_queries_per_conn, nqpc_timeout;
unsigned int nqpc_sent, nqpc_recv;
uint64_t nqpc_ts;
};
static void perf__dot_connect(struct perf_net_socket* sock)
{
int ret;
self->nqpc_sent = 0;
ck_pr_store_uint(&self->nqpc_recv, 0);
self->nqpc_ts = 0;
int fd = socket(self->server.sa.sa.sa_family, SOCK_STREAM, 0);
if (fd == -1) {
char __s[256];
@ -204,6 +212,9 @@ static ssize_t perf__dot_recv(struct perf_net_socket* sock, void* buf, size_t le
memcpy(buf, self->recvbuf + 2, len < dnslen ? len : dnslen);
memmove(self->recvbuf, self->recvbuf + 2 + dnslen, self->at - 2 - dnslen);
self->at -= 2 + dnslen;
if (self->num_queries_per_conn) {
ck_pr_inc_uint(&self->nqpc_recv);
}
if (self->at > 2) {
memcpy(&dnslen2, self->recvbuf, 2);
@ -283,6 +294,8 @@ static ssize_t perf__dot_sendto(struct perf_net_socket* sock, uint16_t qid, cons
}
PERF_UNLOCK(&self->lock);
self->nqpc_sent++;
return n - 2;
}
@ -342,9 +355,22 @@ static int perf__dot_sockready(struct perf_net_socket* sock, int pipe_fd, int64_
if (sock->sent) {
sock->sent(sock, self->qid);
}
return 1;
self->nqpc_sent++;
} else {
PERF_UNLOCK(&self->lock);
}
if (self->num_queries_per_conn && self->nqpc_sent >= self->num_queries_per_conn) {
if (!self->nqpc_ts) {
self->nqpc_ts = perf_get_time() + self->nqpc_timeout;
}
unsigned int r = ck_pr_load_uint(&self->nqpc_recv);
if (r >= self->nqpc_sent || perf_get_time() > self->nqpc_ts) {
PERF_LOCK(&self->lock);
perf__dot_reconnect(sock);
PERF_UNLOCK(&self->lock);
}
return 0;
}
PERF_UNLOCK(&self->lock);
return 1;
}
@ -417,6 +443,12 @@ static bool perf__dot_have_more(struct perf_net_socket* sock)
return self->have_more;
}
static void perf__dot_num_queries_per_conn(struct perf_net_socket* sock, size_t num_queries_per_conn, size_t timeout)
{
self->num_queries_per_conn = num_queries_per_conn;
self->nqpc_timeout = timeout;
}
struct perf_net_socket* perf_net_dot_opensocket(const perf_sockaddr_t* server, const perf_sockaddr_t* local, size_t bufsize, void* data, perf_net_sent_cb_t sent, perf_net_event_cb_t event)
{
struct perf__dot_socket* tmp = calloc(1, sizeof(struct perf__dot_socket)); // clang scan-build
@ -434,6 +466,8 @@ struct perf_net_socket* perf_net_dot_opensocket(const perf_sockaddr_t* server, c
sock->sockready = perf__dot_sockready;
sock->have_more = perf__dot_have_more;
sock->num_queries_per_conn = perf__dot_num_queries_per_conn;
sock->data = data;
sock->sent = sent;
sock->event = event;

View file

@ -80,13 +80,20 @@ struct perf__tcp_socket {
uint64_t conn_ts;
perf_socket_event_t conn_event, conning_event;
size_t num_queries_per_conn, nqpc_timeout;
unsigned int nqpc_sent, nqpc_recv;
uint64_t nqpc_ts;
};
static int perf__tcp_connect(struct perf_net_socket* sock)
{
int fd;
self->is_ready = true;
self->is_ready = true;
self->nqpc_sent = 0;
ck_pr_store_uint(&self->nqpc_recv, 0);
self->nqpc_ts = 0;
fd = socket(self->server.sa.sa.sa_family, SOCK_STREAM, 0);
if (fd == -1) {
@ -192,6 +199,9 @@ static ssize_t perf__tcp_recv(struct perf_net_socket* sock, void* buf, size_t le
memcpy(buf, self->recvbuf + 2, len < dnslen ? len : dnslen);
memmove(self->recvbuf, self->recvbuf + 2 + dnslen, self->at - 2 - dnslen);
self->at -= 2 + dnslen;
if (self->num_queries_per_conn) {
ck_pr_inc_uint(&self->nqpc_recv);
}
if (self->at > 2) {
memcpy(&dnslen2, self->recvbuf, 2);
@ -251,6 +261,7 @@ static ssize_t perf__tcp_sendto(struct perf_net_socket* sock, uint16_t qid, cons
errno = EINPROGRESS;
return -1;
}
self->nqpc_sent++;
return n - 2;
}
@ -302,6 +313,17 @@ static int perf__tcp_sockready(struct perf_net_socket* sock, int pipe_fd, int64_
if (sock->sent) {
sock->sent(sock, self->qid);
}
self->nqpc_sent++;
}
if (self->num_queries_per_conn && self->nqpc_sent >= self->num_queries_per_conn) {
if (!self->nqpc_ts) {
self->nqpc_ts = perf_get_time() + self->nqpc_timeout;
}
unsigned int r = ck_pr_load_uint(&self->nqpc_recv);
if (r >= self->nqpc_sent || perf_get_time() > self->nqpc_ts) {
self->need_reconnect = true;
}
return 0;
}
return 1;
}
@ -352,6 +374,7 @@ conn_cont:
if (sock->sent) {
sock->sent(sock, self->qid);
}
self->nqpc_sent++;
}
return 1;
}
@ -367,6 +390,12 @@ static bool perf__tcp_have_more(struct perf_net_socket* sock)
return self->have_more;
}
static void perf__tcp_num_queries_per_conn(struct perf_net_socket* sock, size_t num_queries_per_conn, size_t timeout)
{
self->num_queries_per_conn = num_queries_per_conn;
self->nqpc_timeout = timeout;
}
struct perf_net_socket* perf_net_tcp_opensocket(const perf_sockaddr_t* server, const perf_sockaddr_t* local, size_t bufsize, void* data, perf_net_sent_cb_t sent, perf_net_event_cb_t event)
{
struct perf__tcp_socket* tmp = calloc(1, sizeof(struct perf__tcp_socket)); // clang scan-build
@ -384,6 +413,8 @@ struct perf_net_socket* perf_net_tcp_opensocket(const perf_sockaddr_t* server, c
sock->sockready = perf__tcp_sockready;
sock->have_more = perf__tcp_have_more;
sock->num_queries_per_conn = perf__tcp_num_queries_per_conn;
sock->data = data;
sock->sent = sent;
sock->event = event;

View file

@ -369,7 +369,7 @@ void perf_opt_parse(int argc, char** argv)
perf_suppress_t perf_opt_parse_suppress(const char* val)
{
perf_suppress_t s = { false, false, false };
perf_suppress_t s = { false, false, false, false };
while (val && *val) {
const char* next = strchr(val, ',');
@ -390,6 +390,8 @@ perf_suppress_t perf_opt_parse_suppress(const char* val)
s.sendfailed = true;
} else if (!strncmp(val, "sockready", len)) {
s.sockready = true;
} else if (!strncmp(val, "unexpected", len)) {
s.unexpected = true;
} else {
fprintf(stderr, "unknown message type to suppress: %.*s\n", len, val);
perf_opt_usage();

View file

@ -37,6 +37,7 @@ typedef struct {
bool congestion;
bool sendfailed;
bool sockready;
bool unexpected;
} perf_suppress_t;
void perf_opt_add(char c, perf_opttype_t type, const char* desc, const char* help, const char* defval, void* valp);

View file

@ -255,6 +255,8 @@ static void setup(int argc, char** argv)
const char* doh_method = DEFAULT_DOH_METHOD;
const char* local_suppress = 0;
size_t num_queries_per_conn = 0;
sock_family = AF_UNSPEC;
server_port = 0;
local_port = DEFAULT_LOCAL_PORT;
@ -337,6 +339,8 @@ static void setup(int argc, char** argv)
"the HTTP method to use for DNS-over-HTTPS: GET or POST", DEFAULT_DOH_METHOD, &doh_method);
perf_long_opt_add("suppress", perf_opt_string, "message[,message,...]",
"suppress messages/warnings, see dnsperf(1) man-page for list of message types", NULL, &local_suppress);
perf_long_opt_add("num-queries-per-conn", perf_opt_uint, "queries",
"Number of queries to send per connection", NULL, &num_queries_per_conn);
perf_opt_parse(argc, argv);
@ -428,6 +432,9 @@ static void setup(int argc, char** argv)
if (!socks[i]) {
perf_log_fatal("perf_net_opensocket(): no socket returned, out of memory?");
}
if (num_queries_per_conn && socks[i]->num_queries_per_conn) {
socks[i]->num_queries_per_conn(socks[i], num_queries_per_conn, query_timeout);
}
}
}
@ -738,7 +745,9 @@ try_process_response(unsigned int sockindex)
size_t idx = qid * nsocks + sockindex;
if (idx >= max_outstanding || queries[idx].list != &outstanding_list) {
perf_log_warning("received a response with an unexpected id: %u", qid);
if (!suppress.unexpected) {
perf_log_warning("received a response with an unexpected id: %u", qid);
}
return;
}
q = &queries[idx];

View file

@ -3,21 +3,25 @@
test "$TEST_DNSPERF_WITH_NETWORK" = "1" || exit 0
dumdumd=`which dumdumd`
dumdohd=`which dumdohd`
pkill -9 dumdumd || true
pkill -9 dumdohd || true
if [ -n "$dumdumd" ]; then
pkill -9 dumdumd || true
$dumdumd 127.0.0.1 5353 -r -D 100 &
pid="$!"
sleep 2
../dnsperf -s 127.0.0.1 -p 5353 -d "$srcdir/datafile" -t 2 -l 2 -Q 10 -m tcp
kill "$pid"
sleep 2
$dumdumd 127.0.0.1 5353 -r -D 10 &
pid="$!"
sleep 2
../dnsperf -s 127.0.0.1 -p 5353 -d "$srcdir/datafile" -t 2 -l 10 -Q 100 -m tcp
kill "$pid"
sleep 2
rm -f key.pem cert.pem
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes -subj "/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd"
@ -27,12 +31,29 @@ if [ -n "$dumdumd" ]; then
sleep 2
../dnsperf -s 127.0.0.1 -p 5353 -d "$srcdir/datafile" -t 2 -l 2 -Q 10 -m dot
kill "$pid"
sleep 2
$dumdumd 127.0.0.1 5353 -r -T -D 10 &
pid="$!"
sleep 2
../dnsperf -s 127.0.0.1 -p 5353 -d "$srcdir/datafile" -t 2 -l 10 -Q 100 -m dot
kill "$pid"
pkill -9 dumdumd || true
fi
if [ -n "$dumdohd" ]; then
rm -f key.pem cert.pem
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes -subj "/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd"
$dumdohd 5353 key.pem cert.pem -D 100 &
pid="$!"
sleep 2
../dnsperf -s 127.0.0.1 -p 5353 -d "$srcdir/datafile" -t 2 -l 2 -Q 10 -m doh
kill "$pid"
sleep 2
$dumdohd 5353 key.pem cert.pem -D 10 &
pid="$!"
sleep 2
../dnsperf -s 127.0.0.1 -p 5353 -d "$srcdir/datafile" -t 2 -l 10 -Q 100 -m doh
kill "$pid"
fi