diff options
author | jfbus <jf@bustarret.com> | 2019-03-26 18:21:53 +0000 |
---|---|---|
committer | Brad Fitzpatrick <bradfitz@golang.org> | 2019-04-17 14:42:35 +0000 |
commit | dbc17037815bdce5df3f355f2171c57804f7870e (patch) | |
tree | d1b7e6669f254f3642b3e9aa3c11d151cc6d9bb5 /src/net/dnsclient_unix.go | |
parent | 33e5da48d5d22a722f2363b15e2d53061fb71cf4 (diff) | |
download | go-dbc17037815bdce5df3f355f2171c57804f7870e.tar.gz go-dbc17037815bdce5df3f355f2171c57804f7870e.zip |
net: support single-request resolv.conf option in pure Go resolver
There is a DNS resolution issue in Kubernetes (UDP response packets get dropped due to a race in conntrack between the parallel A and AAAA queries, causing timeouts in DNS queries).
A workaround is to enable single-request / single-request-reopen in resolv.conf in order to use sequential A and AAAA queries instead of parallel queries.
With this PR, the pure Go resolver searches for "single-request" and "single-request-reopen" in resolv.conf and send A and AAAA queries sequentially when found.
Fixes #29644
Change-Id: I906b3484008c1b9adf2e3e9241ea23767e29df59
GitHub-Last-Rev: d481acfb4c49d82fd474078b31a1a4697b57dadf
GitHub-Pull-Request: golang/go#29661
Reviewed-on: https://go-review.googlesource.com/c/go/+/157377
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Diffstat (limited to 'src/net/dnsclient_unix.go')
-rw-r--r-- | src/net/dnsclient_unix.go | 58 |
1 files changed, 38 insertions, 20 deletions
diff --git a/src/net/dnsclient_unix.go b/src/net/dnsclient_unix.go index 5472494356..4e7462b66f 100644 --- a/src/net/dnsclient_unix.go +++ b/src/net/dnsclient_unix.go @@ -569,34 +569,52 @@ func (r *Resolver) goLookupIPCNAMEOrder(ctx context.Context, name string, order resolvConf.mu.RLock() conf := resolvConf.dnsConfig resolvConf.mu.RUnlock() - type racer struct { + type result struct { p dnsmessage.Parser server string error } - lane := make(chan racer, 1) + lane := make(chan result, 1) qtypes := [...]dnsmessage.Type{dnsmessage.TypeA, dnsmessage.TypeAAAA} - var lastErr error - for _, fqdn := range conf.nameList(name) { - for _, qtype := range qtypes { + var queryFn func(fqdn string, qtype dnsmessage.Type) + var responseFn func(fqdn string, qtype dnsmessage.Type) result + if conf.singleRequest { + queryFn = func(fqdn string, qtype dnsmessage.Type) {} + responseFn = func(fqdn string, qtype dnsmessage.Type) result { + dnsWaitGroup.Add(1) + defer dnsWaitGroup.Done() + p, server, err := r.tryOneName(ctx, conf, fqdn, qtype) + return result{p, server, err} + } + } else { + queryFn = func(fqdn string, qtype dnsmessage.Type) { dnsWaitGroup.Add(1) go func(qtype dnsmessage.Type) { p, server, err := r.tryOneName(ctx, conf, fqdn, qtype) - lane <- racer{p, server, err} + lane <- result{p, server, err} dnsWaitGroup.Done() }(qtype) } + responseFn = func(fqdn string, qtype dnsmessage.Type) result { + return <-lane + } + } + var lastErr error + for _, fqdn := range conf.nameList(name) { + for _, qtype := range qtypes { + queryFn(fqdn, qtype) + } hitStrictError := false - for range qtypes { - racer := <-lane - if racer.error != nil { - if nerr, ok := racer.error.(Error); ok && nerr.Temporary() && r.strictErrors() { + for _, qtype := range qtypes { + result := responseFn(fqdn, qtype) + if result.error != nil { + if nerr, ok := result.error.(Error); ok && nerr.Temporary() && r.strictErrors() { // This error will abort the nameList loop. hitStrictError = true - lastErr = racer.error + lastErr = result.error } else if lastErr == nil || fqdn == name+"." { // Prefer error for original name. - lastErr = racer.error + lastErr = result.error } continue } @@ -618,12 +636,12 @@ func (r *Resolver) goLookupIPCNAMEOrder(ctx context.Context, name string, order loop: for { - h, err := racer.p.AnswerHeader() + h, err := result.p.AnswerHeader() if err != nil && err != dnsmessage.ErrSectionDone { lastErr = &DNSError{ Err: "cannot marshal DNS message", Name: name, - Server: racer.server, + Server: result.server, } } if err != nil { @@ -631,35 +649,35 @@ func (r *Resolver) goLookupIPCNAMEOrder(ctx context.Context, name string, order } switch h.Type { case dnsmessage.TypeA: - a, err := racer.p.AResource() + a, err := result.p.AResource() if err != nil { lastErr = &DNSError{ Err: "cannot marshal DNS message", Name: name, - Server: racer.server, + Server: result.server, } break loop } addrs = append(addrs, IPAddr{IP: IP(a.A[:])}) case dnsmessage.TypeAAAA: - aaaa, err := racer.p.AAAAResource() + aaaa, err := result.p.AAAAResource() if err != nil { lastErr = &DNSError{ Err: "cannot marshal DNS message", Name: name, - Server: racer.server, + Server: result.server, } break loop } addrs = append(addrs, IPAddr{IP: IP(aaaa.AAAA[:])}) default: - if err := racer.p.SkipAnswer(); err != nil { + if err := result.p.SkipAnswer(); err != nil { lastErr = &DNSError{ Err: "cannot marshal DNS message", Name: name, - Server: racer.server, + Server: result.server, } break loop } |