On Wed, May 31, 2023 at 01:40:30PM +0200, Petr Menšík wrote:
> Attached my bigger attempt to solve this problem.


> 7 separate patches included.
> 
> Because in rare circumstances servers might have changed since TCP
> connection process started, I serialize domain, server address and its last
> position in server array. Hacked a redirection with special -2 value from
> cache inserting, where it always reads just one server. It then tries server
> at reported position first, iterating on all servers for this domain.
> 
> In rare cases there might be a problem, because it does not send source
> address or interface, which might identify correct server. But I doubt those
> would make it different in any real world examples. We have no simple
> identification for changed servers. It works in basic testing well.
> 
> Added also separation of TCP and UDP last servers. It should be able to
> forward UDP to server responding just over UDP and TCP to server responding
> just TCP. That should be quite rare case, more teoretical than real-world.
> Maybe change of UDP server should change also TCP, because UDP test can be
> done in parallel.
> 
> I have found also unwanted difference from UDP queries. If the response is
> REFUSED, even that were accepted as valid last_server response. Now it sets
> TCP last_server just after non-refused response, not just successful
> connection.
> 
> I have tried to look into glibc, that does not seem to set any timeout for
> TCP (vc) queries. Default timeout in dig tool is 10 seconds, it does not
> seem to tweak number of SYN packets sent. I think it just measures time
> before reply arrives. I think ideally we should be able to spawn another TCP
> connection to the other server if it didn't respond in few seconds. And wait
> for fastest response from any of those. But that would require quite
> significant rework of current code.
> 
> Did just a basic testing, but those changes improve tested situation.
> 
> What do you think about it?

I haven't yet reviewed the patch at the begin of this thread ...

Below some feedback
 

> Cheers,
> Petr

> From c02cfcb0a358e04636ffd2bcc595860b25b3a440 Mon Sep 17 00:00:00 2001
> From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= <pemen...@redhat.com>
> Date: Wed, 17 May 2023 21:40:19 +0200
> Subject: [PATCH 1/7] Add --dns-tcp-timeout option
> 
> Changes send timeout of outgoing TCP connections. Allows waiting just
> short time for successful connection before trying another server.
> Makes possible faster switch to working server if previous is not
> responding. Default socket timeout seems too high for DNS connections.
> ---
>  man/dnsmasq.8 |  4 ++++
>  src/config.h  |  1 +
>  src/dnsmasq.h |  1 +
>  src/forward.c | 10 ++++++++--
>  src/option.c  | 10 +++++++++-
>  5 files changed, 23 insertions(+), 3 deletions(-)
> 
> diff --git a/man/dnsmasq.8 b/man/dnsmasq.8
> index 30429df..94fd5b1 100644
> --- a/man/dnsmasq.8
> +++ b/man/dnsmasq.8
> @@ -860,6 +860,10 @@ where this needs to be increased is when using 
> web-server log file
>  resolvers, which can generate large numbers of concurrent queries. This
>  parameter actually controls the number of concurrent queries per server 
> group, where a server group is the set of server(s) associated with a single 
> domain. So if a domain has it's own server via --server=/example.com/1.2.3.4 
> and 1.2.3.4 is not responding, but queries for *.example.com cannot go 
> elsewhere, then other queries will not be affected. On configurations with 
> many such server groups and tight resources, this value may need to be 
> reduced.
>  .TP
> +.B --dns-tcp-timeout=<seconds>
> +Sets send timeout for forwarded TCP connections. Can be used to reduce time 
> of waiting
> +for successful TCP connection. Default value 0 skips the change of it.
> +.TP
>  .B --dnssec
>  Validate DNS replies and cache DNSSEC data. When forwarding DNS queries, 
> dnsmasq requests the 
>  DNSSEC records needed to validate the replies. The replies are validated and 
> the result returned as 
      ...
> diff --git a/src/forward.c b/src/forward.c
> index ecfeebd..f323fee 100644
> --- a/src/forward.c
> +++ b/src/forward.c
> @@ -1929,8 +1929,14 @@ static ssize_t tcp_talk(int first, int last, int 
> start, unsigned char *packet,
>         /* Copy connection mark of incoming query to outgoing connection. */
>         if (have_mark)
>           setsockopt(serv->tcpfd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned 
> int));
> -#endif                         
> -       

Thanks for removing those trailing white spaces.


> +#endif
> +
> +       if (daemon->tcp_timeout>0)
> +         {
> +           struct timeval tv = {daemon->tcp_timeout, 0};
> +           setsockopt(serv->tcpfd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
> +         }
> +
>         if ((!local_bind(serv->tcpfd,  &serv->source_addr, serv->interface, 
> 0, 1)))
>           {
>             close(serv->tcpfd);
> diff --git a/src/option.c b/src/option.c
> index 8322725..b94a5ff 100644
> --- a/src/option.c
> +++ b/src/option.c
> @@ -190,6 +190,7 @@ struct myoption {
>  #define LOPT_FILTER_RR     381
>  #define LOPT_NO_DHCP6      382
>  #define LOPT_NO_DHCP4      383
> +#define LOPT_TCP_TIMEOUT   384
>  
>  #ifdef HAVE_GETOPT_LONG
>  static const struct option opts[] =  
> @@ -3391,7 +3393,12 @@ static int one_opt(int option, char *arg, char 
> *errstr, char *gen_err, int comma
>      case '0':  /* --dns-forward-max */
>        if (!atoi_check(arg, &daemon->ftabsize))
>       ret_err(gen_err);
> -      break;  

 ;-)


> +      break;
> +
> +    case LOPT_TCP_TIMEOUT: /* --dns-tcp-timeout */
> +      if (!atoi_check(arg, &daemon->tcp_timeout))
> +      ret_err(gen_err);
> +      break;
>      
>      case 'q': /* --log-queries */
>        set_option_bool(OPT_LOG);
> @@ -5833,6 +5840,7 @@ void read_opts(int argc, char **argv, char 
> *compile_opts)
>    daemon->soa_expiry = SOA_EXPIRY;
>    daemon->randport_limit = 1;
>    daemon->host_index = SRC_AH;
> +  daemon->tcp_timeout = TCP_TIMEOUT;
>    
>    /* See comment above make_servers(). Optimises server-read code. */
>    mark_servers(0);
> -- 
> 2.40.1
> 

> From d9a8d33f195c6c406ff28a0084d1be8b46583b08 Mon Sep 17 00:00:00 2001
> From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= <pemen...@redhat.com>
> Date: Tue, 23 May 2023 21:31:05 +0200
> Subject: [PATCH 2/7] Reduce few TCP related repeated code
> 
> Provide special function for repeated setting of ede code in
> pseudoheader. Introduce read_tcp reusing query length and payload.
> ---
>  src/dnsmasq.h |   2 +
>  src/edns0.c   |   9 ++
>  src/forward.c | 223 ++++++++++++++++++++------------------------------
>  3 files changed, 100 insertions(+), 134 deletions(-)
> 
> diff --git a/src/dnsmasq.h b/src/dnsmasq.h
> index 4113ccb..77296ed 100644
> --- a/src/dnsmasq.h
> +++ b/src/dnsmasq.h
> @@ -1852,6 +1852,8 @@ unsigned char *find_pseudoheader(struct dns_header 
> *header, size_t plen,
>                                  size_t *len, unsigned char **p, int 
> *is_sign, int *is_last);
>  size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned 
> char *limit, 
>                       unsigned short udp_sz, int optno, unsigned char *opt, 
> size_t optlen, int set_do, int replace);
> +size_t add_pseudoheader_ede(struct dns_header *header, size_t plen, unsigned 
> char *limit,
> +                     unsigned short udp_sz, int ede, int set_do, int 
> replace);
>  size_t add_do_bit(struct dns_header *header, size_t plen, unsigned char 
> *limit);
>  size_t add_edns0_config(struct dns_header *header, size_t plen, unsigned 
> char *limit, 
>                       union mysockaddr *source, time_t now, int *cacheable);
         ....
> diff --git a/src/forward.c b/src/forward.c
> index f323fee..37696c8 100644
> --- a/src/forward.c
> +++ b/src/forward.c
         ....
> @@ -1694,7 +1708,6 @@ void receive_query(struct listener *listen, time_t now)
>    if (extract_request(header, (size_t)n, daemon->namebuff, &type))
>      {
>  #ifdef HAVE_AUTH
> -      struct auth_zone *zone;
>  #endif

That would become

>  #ifdef HAVE_AUTH
>  #endif

I suggest

> -#ifdef HAVE_AUTH
> -      struct auth_zone *zone;
> -#endif

(removing three lines)


>        log_query_mysockaddr(F_QUERY | F_FORWARD, daemon->namebuff,
>                          &source_addr, auth_dns ? "auth" : "query", type);
> @@ -1704,15 +1717,8 @@ void receive_query(struct listener *listen, time_t now)
   .....


Groeten
Geert Stappers
-- 
Silence is hard to parse

_______________________________________________
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
https://lists.thekelleys.org.uk/cgi-bin/mailman/listinfo/dnsmasq-discuss

Reply via email to