From 94dbb8e916981506c40608e43b5d951a2f78320e Mon Sep 17 00:00:00 2001 From: Shikha Sharma Date: Mon, 13 Jun 2022 17:06:55 +0200 Subject: [PATCH] Update stub.c Fix for issue mentioned below: Scenario: 4 UDP steams corresponding to 4 IP's configured. Outbound query is always sent to 1st IP in the list unless there is a timeout. If there is a timeout, the next outbound query is sent to the 2nd IP in the list. If the 1st IP still times out then the next 2n queries (this increases in powers of 2) go to the 2nd IP. If the 2nd IP times out at any point, then queries are sent to the 3rd IP (following the same algorithm of 2n queries before reverting to the 2nd IP) Observation: Even if there is no timeout on 2nd IP, some queries are still sent to 3rd IP. From code: The stream is switched whenever there is a timeout. If 10 messages were sent to first IP and they all timeout , the stream is switched 10 times in the current code. Suggestion: Switch stream only on the first timeout on a stream or ignore when the timeout occurs on a stream which is not the current_udp stream. --- src/stub.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/stub.c b/src/stub.c index 78d83696..ee319312 100644 --- a/src/stub.c +++ b/src/stub.c @@ -709,6 +709,8 @@ static void stub_timeout_cb(void *userarg) { getdns_network_req *netreq = (getdns_network_req *)userarg; + getdns_upstream *upstream = netreq? netreq->upstream: NULL; + getdns_upstreams *upstreams = upstream? upstream->upstreams: NULL; DEBUG_STUB("%s %-35s: MSG: %p\n", STUB_DEBUG_CLEANUP, __FUNC__, (void*)netreq); stub_cleanup(netreq); @@ -723,7 +725,9 @@ stub_timeout_cb(void *userarg) "%-40s : Upstream : UDP - Resps=%6d, Timeouts =%6d (logged every 100 responses)\n", netreq->upstream->addr_str, (int)netreq->upstream->udp_responses, (int)netreq->upstream->udp_timeouts); - stub_next_upstream(netreq); + /* Only choose next stream if the timeout is on current UDP stream */ + if (upstreams && (upstream == &upstreams->upstreams[upstreams->current_udp])) + stub_next_upstream(netreq); } else { netreq->upstream->responses_timeouts++; }