summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/dnsperf.1.in17
-rw-r--r--src/dnsperf.c54
-rw-r--r--src/net_doh.c81
-rw-r--r--src/opt.c35
-rw-r--r--src/opt.h11
-rw-r--r--src/resperf.c23
6 files changed, 159 insertions, 62 deletions
diff --git a/src/dnsperf.1.in b/src/dnsperf.1.in
index 55cbdf1..99c0785 100644
--- a/src/dnsperf.1.in
+++ b/src/dnsperf.1.in
@@ -397,6 +397,23 @@ The URI to use for DNS-over-HTTPS, default value is
The HTTP method to use when querying with DNS-over-HTTPS, default is GET.
Available methods are: GET, POST.
.RE
+
+\fBsuppress=\fIMESSAGE[,MESSAGE,...]\fR
+.br
+.RS
+Suppress various messages and warnings that may be shown excessively in some
+situations, such as socket readiness when connecting to a slow service.
+Can suppress multiple types by listing them as a comma separated list.
+Following type are available.
+
+\fBtimeouts\fR: Suppress messages about queries being timed out
+.br
+\fBcongestion\fR: Suppress messages about network congestion
+.br
+\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
+.RE
.SH "SEE ALSO"
\fBresperf\fR(1)
.SH AUTHOR
diff --git a/src/dnsperf.c b/src/dnsperf.c
index 0f312ce..c3ff297 100644
--- a/src/dnsperf.c
+++ b/src/dnsperf.c
@@ -88,6 +88,7 @@ typedef struct {
bool updates;
bool verbose;
enum perf_net_mode mode;
+ perf_suppress_t suppress;
} config_t;
typedef struct {
@@ -399,17 +400,18 @@ stringify(unsigned int value)
static void
setup(int argc, char** argv, config_t* config)
{
- const char* family = NULL;
- const char* server_name = DEFAULT_SERVER_NAME;
- in_port_t server_port = 0;
- const char* local_name = NULL;
- in_port_t local_port = DEFAULT_LOCAL_PORT;
- const char* filename = NULL;
- const char* edns_option = NULL;
- const char* tsigkey = NULL;
- const char* mode = 0;
- const char* doh_uri = DEFAULT_DOH_URI;
- const char* doh_method = DEFAULT_DOH_METHOD;
+ const char* family = NULL;
+ const char* server_name = DEFAULT_SERVER_NAME;
+ in_port_t server_port = 0;
+ const char* local_name = NULL;
+ in_port_t local_port = DEFAULT_LOCAL_PORT;
+ const char* filename = NULL;
+ const char* edns_option = NULL;
+ const char* tsigkey = NULL;
+ const char* mode = 0;
+ const char* doh_uri = DEFAULT_DOH_URI;
+ const char* doh_method = DEFAULT_DOH_METHOD;
+ const char* local_suppress = 0;
memset(config, 0, sizeof(*config));
config->argc = argc;
@@ -487,6 +489,8 @@ setup(int argc, char** argv, config_t* config)
"the URI to use for DNS-over-HTTPS", DEFAULT_DOH_URI, &doh_uri);
perf_long_opt_add("doh-method", perf_opt_string, "doh_method",
"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);
bool log_stdout = false;
perf_opt_add('W', perf_opt_boolean, NULL, "log warnings and errors to stdout instead of stderr", NULL, &log_stdout);
@@ -497,6 +501,8 @@ setup(int argc, char** argv, config_t* config)
perf_log_tostdout();
}
+ config->suppress = perf_opt_parse_suppress(local_suppress);
+
if (mode != 0)
config->mode = perf_net_parsemode(mode);
@@ -695,14 +701,14 @@ do_send(void* arg)
q->sock = tinfo->socks[tinfo->current_sock++ % tinfo->nsocks];
switch (perf_net_sockready(q->sock, threadpipe[0], TIMEOUT_CHECK_TIME)) {
case 0:
- if (config->verbose) {
+ if (config->verbose && !config->suppress.sockready) {
perf_log_warning("socket %p not ready", q->sock);
}
q->sock = 0;
all_fail = false;
continue;
case -1:
- if (config->verbose) {
+ if (config->verbose && !config->suppress.sockready) {
perf_log_warning("socket %p readiness check timed out", q->sock);
}
q->sock = 0;
@@ -765,12 +771,12 @@ do_send(void* arg)
config->server_addr.length);
if (n < 0) {
if (errno == EINPROGRESS) {
- if (config->verbose) {
+ if (config->verbose && !config->suppress.congestion) {
perf_log_warning("network congested, packet sending in progress");
}
any_inprogress = 1;
} else {
- if (config->verbose) {
+ if (config->verbose && !config->suppress.sendfailed) {
char __s[256];
perf_log_warning("failed to send packet: %s", perf_strerror_r(errno, __s, sizeof(__s)));
}
@@ -780,7 +786,9 @@ do_send(void* arg)
continue;
}
} else if ((unsigned int)n != length) {
- perf_log_warning("failed to send full packet: only sent %d of %u", n, length);
+ if (!config->suppress.sendfailed) {
+ perf_log_warning("failed to send full packet: only sent %d of %u", n, length);
+ }
PERF_LOCK(&tinfo->lock);
query_move(tinfo, q, prepend_unused);
PERF_UNLOCK(&tinfo->lock);
@@ -827,12 +835,14 @@ process_timeouts(threadinfo_t* tinfo, uint64_t now)
tinfo->stats.num_timedout++;
- if (q->desc != NULL) {
- perf_log_printf("> T %s", q->desc);
- } else {
- perf_log_printf("[Timeout] %s timed out: msg id %u",
- config->updates ? "Update" : "Query",
- (unsigned int)(q - tinfo->queries));
+ if (!config->suppress.timeouts) {
+ if (q->desc != NULL) {
+ perf_log_printf("> T %s", q->desc);
+ } else {
+ perf_log_printf("[Timeout] %s timed out: msg id %u",
+ config->updates ? "Update" : "Query",
+ (unsigned int)(q - tinfo->queries));
+ }
}
q = perf_list_tail(tinfo->outstanding_queries);
} while (q != NULL && q->timestamp < now && now - q->timestamp >= config->timeout);
diff --git a/src/net_doh.c b/src/net_doh.c
index 0689fc6..0920696 100644
--- a/src/net_doh.c
+++ b/src/net_doh.c
@@ -115,6 +115,9 @@ struct perf__doh_socket {
bool http2_is_dns;
struct _doh_stats stats;
+
+ char recvbuf[TCP_RECV_BUF_SIZE];
+ size_t recv_at;
};
static pthread_mutex_t _nghttp2_lock = PTHREAD_MUTEX_INITIALIZER;
@@ -291,50 +294,62 @@ static ssize_t perf__doh_recv(struct perf_net_socket* sock, void* buf, size_t le
return -1;
}
- uint8_t recvbuf[TCP_RECV_BUF_SIZE];
- ssize_t n = SSL_read(self->ssl, recvbuf, TCP_RECV_BUF_SIZE);
- if (!n) {
- perf__doh_reconnect(sock);
- PERF_UNLOCK(&self->lock);
- errno = EAGAIN;
- return -1;
- }
- if (n < 0) {
- int err = SSL_get_error(self->ssl, n);
- switch (err) {
- case SSL_ERROR_WANT_READ:
+ if (self->recv_at < sizeof(self->recvbuf)) {
+ // try to recv more if we can
+ ssize_t n = SSL_read(self->ssl, self->recvbuf + self->recv_at, sizeof(self->recvbuf) - self->recv_at);
+ if (!n) {
+ perf__doh_reconnect(sock);
+ PERF_UNLOCK(&self->lock);
errno = EAGAIN;
- break;
- case SSL_ERROR_SYSCALL:
- switch (errno) {
- case ECONNREFUSED:
- case ECONNRESET:
- case ENOTCONN:
- perf__doh_reconnect(sock);
+ return -1;
+ }
+ if (n < 0) {
+ int err = SSL_get_error(self->ssl, n);
+ switch (err) {
+ case SSL_ERROR_WANT_READ:
+ if (self->recv_at) {
+ // did not recv but we got something in buffer
+ break;
+ }
errno = EAGAIN;
- break;
+ PERF_UNLOCK(&self->lock);
+ return -1;
+ case SSL_ERROR_SYSCALL:
+ switch (errno) {
+ case ECONNREFUSED:
+ case ECONNRESET:
+ case ENOTCONN:
+ perf__doh_reconnect(sock);
+ errno = EAGAIN;
+ break;
+ default:
+ break;
+ }
+ PERF_UNLOCK(&self->lock);
+ return -1;
default:
- break;
+ errno = EBADF;
+ PERF_UNLOCK(&self->lock);
+ return -1;
}
- break;
- default:
- errno = EBADF;
- break;
+ } else {
+ self->recv_at += n;
}
- PERF_UNLOCK(&self->lock);
- return -1;
}
// this will be processed by nghttp2 callbacks
- int ret = nghttp2_session_mem_recv(self->http2.session, recvbuf, n);
+ ssize_t ret = nghttp2_session_mem_recv(self->http2.session, (uint8_t*)self->recvbuf, self->recv_at);
if (ret < 0) {
perf_log_warning("nghttp2_session_mem_recv failed: %s", nghttp2_strerror(ret));
PERF_UNLOCK(&self->lock);
return -1;
}
- // TODO: handle partial mem_recv
- if (ret != n) {
- perf_log_fatal("perf__doh_recv() mem_recv did not take all");
+ if (ret != self->recv_at) {
+ // only process one response per call
+ memmove(self->recvbuf, self->recvbuf + ret, self->recv_at - ret);
+ self->recv_at -= ret;
+ } else {
+ self->recv_at = 0;
}
// TODO: is this faster then mem_recv?
@@ -850,7 +865,9 @@ static int _http2_data_chunk_recv_cb(nghttp2_session* session,
}
if (self->http2.dnsmsg_completed) {
- perf_log_fatal("_http2_data_chunk_recv_cb: chunk received when already having a dns msg");
+ // pause for now and don't process this chunk
+ // can only do one response at a time in perf__doh_recv()
+ return NGHTTP2_ERR_PAUSE;
}
// TODO: point of nghttp2_session_get_stream_user_data() code?
diff --git a/src/opt.c b/src/opt.c
index 4ea798d..01949e6 100644
--- a/src/opt.c
+++ b/src/opt.c
@@ -366,3 +366,38 @@ void perf_opt_parse(int argc, char** argv)
exit(1);
}
}
+
+perf_suppress_t perf_opt_parse_suppress(const char* val)
+{
+ perf_suppress_t s = { false, false, false };
+
+ while (val && *val) {
+ const char* next = strchr(val, ',');
+ int len;
+ if (next) {
+ len = next - val;
+ next += 1;
+ } else {
+ len = strlen(val);
+ next = 0;
+ }
+
+ if (!strncmp(val, "timeouts", len)) {
+ s.timeouts = true;
+ } else if (!strncmp(val, "congestion", len)) {
+ s.congestion = true;
+ } else if (!strncmp(val, "sendfailed", len)) {
+ s.sendfailed = true;
+ } else if (!strncmp(val, "sockready", len)) {
+ s.sockready = true;
+ } else {
+ fprintf(stderr, "unknown message type to suppress: %.*s\n", len, val);
+ perf_opt_usage();
+ exit(1);
+ }
+
+ val = next;
+ }
+
+ return s;
+}
diff --git a/src/opt.h b/src/opt.h
index 22a460b..7e8433f 100644
--- a/src/opt.h
+++ b/src/opt.h
@@ -20,6 +20,8 @@
#ifndef PERF_OPT_H
#define PERF_OPT_H 1
+#include <stdbool.h>
+
typedef enum {
perf_opt_string,
perf_opt_boolean,
@@ -30,6 +32,13 @@ typedef enum {
perf_opt_port,
} perf_opttype_t;
+typedef struct {
+ bool timeouts;
+ bool congestion;
+ bool sendfailed;
+ bool sockready;
+} perf_suppress_t;
+
void perf_opt_add(char c, perf_opttype_t type, const char* desc, const char* help, const char* defval, void* valp);
void perf_long_opt_add(const char* name, perf_opttype_t type, const char* desc, const char* help, const char* defval, void* valp);
@@ -38,4 +47,6 @@ void perf_long_opt_usage(void);
void perf_opt_parse(int argc, char** argv);
+perf_suppress_t perf_opt_parse_suppress(const char* val);
+
#endif
diff --git a/src/resperf.c b/src/resperf.c
index 2a93bf1..a62c819 100644
--- a/src/resperf.c
+++ b/src/resperf.c
@@ -205,6 +205,8 @@ static perf_tsigkey_t* tsigkey;
static bool verbose;
static unsigned int max_fall_behind;
+static perf_suppress_t suppress;
+
const char* progname = "resperf";
static char*
@@ -251,6 +253,7 @@ static void setup(int argc, char** argv)
const char* edns_option_str = NULL;
const char* doh_uri = DEFAULT_DOH_URI;
const char* doh_method = DEFAULT_DOH_METHOD;
+ const char* local_suppress = 0;
sock_family = AF_UNSPEC;
server_port = 0;
@@ -332,6 +335,8 @@ static void setup(int argc, char** argv)
"the URI to use for DNS-over-HTTPS", DEFAULT_DOH_URI, &doh_uri);
perf_long_opt_add("doh-method", perf_opt_string, "doh_method",
"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_opt_parse(argc, argv);
@@ -339,6 +344,8 @@ static void setup(int argc, char** argv)
perf_log_tostdout();
}
+ suppress = perf_opt_parse_suppress(local_suppress);
+
if (_mode != 0)
mode = perf_net_parsemode(_mode);
@@ -574,11 +581,11 @@ do_one_line(perf_buffer_t* lines, perf_buffer_t* msg)
while (q->is_inprogress) {
if (perf_net_sockready(socks[sock], dummypipe[0], TIMEOUT_CHECK_TIME) == -1) {
if (errno == EINPROGRESS) {
- if (verbose) {
+ if (verbose && !suppress.congestion) {
perf_log_warning("network congested, packet sending in progress");
}
} else {
- if (verbose) {
+ if (verbose && !suppress.sockready) {
char __s[256];
perf_log_warning("failed to check socket readiness: %s", perf_strerror_r(errno, __s, sizeof(__s)));
}
@@ -603,16 +610,16 @@ do_one_line(perf_buffer_t* lines, perf_buffer_t* msg)
switch (perf_net_sockready(socks[sock], dummypipe[0], TIMEOUT_CHECK_TIME)) {
case 0:
- if (verbose) {
+ if (verbose && !suppress.sockready) {
perf_log_warning("failed to send packet: socket %d not ready", sock);
}
return (PERF_R_FAILURE);
case -1:
if (errno == EINPROGRESS) {
- if (verbose) {
+ if (verbose && !suppress.congestion) {
perf_log_warning("network congested, packet sending in progress");
}
- } else {
+ } else if (!suppress.sockready) {
perf_log_warning("failed to send packet: socket %d not ready", sock);
}
return (PERF_R_FAILURE);
@@ -642,12 +649,12 @@ do_one_line(perf_buffer_t* lines, perf_buffer_t* msg)
&server_addr.sa.sa, server_addr.length)
< 1) {
if (errno == EINPROGRESS) {
- if (verbose) {
+ if (verbose && !suppress.congestion) {
perf_log_warning("network congested, packet sending in progress");
}
q->is_inprogress = true;
} else {
- if (verbose) {
+ if (verbose && !suppress.sendfailed) {
char __s[256];
perf_log_warning("failed to send packet: %s", perf_strerror_r(errno, __s, sizeof(__s)));
}
@@ -702,7 +709,7 @@ try_process_response(unsigned int sockindex)
if (perf_net_sockready(socks[sockindex], dummypipe[0], TIMEOUT_CHECK_TIME) == -1) {
if (errno != EINPROGRESS) {
- if (verbose) {
+ if (verbose && !suppress.sockready) {
char __s[256];
perf_log_warning("failed to check socket readiness: %s", perf_strerror_r(errno, __s, sizeof(__s)));
}