From 94c0bf978ac376be6bae91681704758d1edf2396 Mon Sep 17 00:00:00 2001
From: Pierre Souchay
Date: Tue, 17 Apr 2018 00:50:00 +0200
Subject: [PATCH 01/11] Perform a binary search to find optimal size of DNS
responses
Will fix https://github.com/hashicorp/consul/issues/4036
Instead of removing one by one the entries, find the optimal
size using binary search.
For SRV records, with 5k nodes, duration of DNS lookups is
divided by 4 or more.
---
agent/dns.go | 42 ++++++++++++++++++++++++++++++++++++++++--
1 file changed, 40 insertions(+), 2 deletions(-)
diff --git a/agent/dns.go b/agent/dns.go
index 98cb5a9b5b..e5abb05fb0 100644
--- a/agent/dns.go
+++ b/agent/dns.go
@@ -717,6 +717,32 @@ func syncExtra(index map[string]dns.RR, resp *dns.Msg) {
resp.Extra = extra
}
+func dnsBinaryTruncate(resp *dns.Msg, maxSize int, index map[string]dns.RR, hasExtra bool) int {
+ originalAnswser := resp.Answer
+ startIndex := 0
+ endIndex := len(resp.Answer)
+ for endIndex-startIndex > 1 {
+ median := startIndex + (endIndex-startIndex)/2
+
+ resp.Answer = originalAnswser[:median]
+ resp.Extra = originalAnswser[:median]
+ if hasExtra {
+ syncExtra(index, resp)
+ }
+ aLen := resp.Len()
+ if aLen <= maxSize {
+ if maxSize-aLen < 10 {
+ // We are good, increasing will go out of bounds
+ return median
+ }
+ startIndex = median
+ } else {
+ endIndex = median
+ }
+ }
+ return startIndex
+}
+
// trimTCPResponse limit the MaximumSize of messages to 64k as it is the limit
// of DNS responses
func (d *DNSServer) trimTCPResponse(req, resp *dns.Msg) (trimmed bool) {
@@ -752,7 +778,13 @@ func (d *DNSServer) trimTCPResponse(req, resp *dns.Msg) (trimmed bool) {
// This enforces the given limit on 64k, the max limit for DNS messages
for len(resp.Answer) > 0 && resp.Len() > maxSize {
truncated = true
- resp.Answer = resp.Answer[:len(resp.Answer)-1]
+ // More than 100 bytes, find with a binary search
+ if resp.Len()-maxSize > 100 {
+ bestIndex := dnsBinaryTruncate(resp, maxSize, index, hasExtra)
+ resp.Answer = resp.Answer[:bestIndex]
+ } else {
+ resp.Answer = resp.Answer[:len(resp.Answer)-1]
+ }
if hasExtra {
syncExtra(index, resp)
}
@@ -809,7 +841,13 @@ func trimUDPResponse(req, resp *dns.Msg, udpAnswerLimit int) (trimmed bool) {
compress := resp.Compress
resp.Compress = false
for len(resp.Answer) > 0 && resp.Len() > maxSize {
- resp.Answer = resp.Answer[:len(resp.Answer)-1]
+ // More than 100 bytes, find with a binary search
+ if resp.Len()-maxSize > 100 {
+ bestIndex := dnsBinaryTruncate(resp, maxSize, index, hasExtra)
+ resp.Answer = resp.Answer[:bestIndex]
+ } else {
+ resp.Answer = resp.Answer[:len(resp.Answer)-1]
+ }
if hasExtra {
syncExtra(index, resp)
}
From c838376dfa03807e89a04b04c9eef6d1d3e6a59f Mon Sep 17 00:00:00 2001
From: Pierre Souchay
Date: Tue, 17 Apr 2018 01:10:52 +0200
Subject: [PATCH 02/11] Added comment for function dnsBinaryTruncate
---
agent/dns.go | 2 ++
1 file changed, 2 insertions(+)
diff --git a/agent/dns.go b/agent/dns.go
index e5abb05fb0..9e3b5216e2 100644
--- a/agent/dns.go
+++ b/agent/dns.go
@@ -717,6 +717,8 @@ func syncExtra(index map[string]dns.RR, resp *dns.Msg) {
resp.Extra = extra
}
+// dnsBinaryTruncate find the optimal number of records using a fast binary search and return
+// it in order to return a DNS answer lower than maxSize parameter.
func dnsBinaryTruncate(resp *dns.Msg, maxSize int, index map[string]dns.RR, hasExtra bool) int {
originalAnswser := resp.Answer
startIndex := 0
From fadfb95e075113cea60f7e0257b02539c9300348 Mon Sep 17 00:00:00 2001
From: Pierre Souchay
Date: Tue, 17 Apr 2018 09:31:30 +0200
Subject: [PATCH 03/11] Added Unit tests + fixed boudary limit
---
agent/dns.go | 2 +-
agent/dns_test.go | 35 +++++++++++++++++++++++++++++++++++
2 files changed, 36 insertions(+), 1 deletion(-)
diff --git a/agent/dns.go b/agent/dns.go
index 9e3b5216e2..599d758226 100644
--- a/agent/dns.go
+++ b/agent/dns.go
@@ -722,7 +722,7 @@ func syncExtra(index map[string]dns.RR, resp *dns.Msg) {
func dnsBinaryTruncate(resp *dns.Msg, maxSize int, index map[string]dns.RR, hasExtra bool) int {
originalAnswser := resp.Answer
startIndex := 0
- endIndex := len(resp.Answer)
+ endIndex := len(resp.Answer) + 1
for endIndex-startIndex > 1 {
median := startIndex + (endIndex-startIndex)/2
diff --git a/agent/dns_test.go b/agent/dns_test.go
index 83bf2ca871..5257075746 100644
--- a/agent/dns_test.go
+++ b/agent/dns_test.go
@@ -2983,6 +2983,41 @@ func TestDNS_ServiceLookup_Randomize(t *testing.T) {
}
}
+func TestBinarySearch(t *testing.T) {
+ msgSrc := new(dns.Msg)
+ msgSrc.Compress = true
+ msgSrc.SetQuestion("redis.service.consul.", dns.TypeSRV)
+
+ for i := 0; i < 50; i++ {
+ target := fmt.Sprintf("host-redis-%d-%d.test.acme.com.node.dc1.consul.", i/256, i%256)
+ msgSrc.Answer = append(msgSrc.Answer, &dns.SRV{Hdr: dns.RR_Header{Name: "redis.service.consul.", Class: 1, Rrtype: dns.TypeSRV, Ttl: 0x3c}, Port: 0x4c57, Target: target})
+ msgSrc.Extra = append(msgSrc.Extra, &dns.CNAME{Hdr: dns.RR_Header{Name: target, Class: 1, Rrtype: dns.TypeCNAME, Ttl: 0x3c}, Target: fmt.Sprintf("fx.168.%d.%d.", i/256, i%256)})
+ }
+ for _, maxSize := range []int{256, 512, 8192} {
+ msg := new(dns.Msg)
+ msgSrc.Compress = true
+ msgSrc.SetQuestion("redis.service.consul.", dns.TypeSRV)
+ msg.Answer = msgSrc.Answer
+ msg.Extra = msgSrc.Extra
+ index := make(map[string]dns.RR, len(msg.Extra))
+ indexRRs(msg.Extra, index)
+ blen := dnsBinaryTruncate(msg, maxSize, index, true)
+ msg.Answer = msg.Answer[:blen]
+ syncExtra(index, msg)
+ predicted := msg.Len()
+ buf, err := msg.Pack()
+ if err != nil {
+ t.Error(err)
+ }
+ if predicted < len(buf) {
+ t.Fatalf("Bug in DNS library: %d != %d", predicted, len(buf))
+ }
+ if len(buf) > maxSize || len(buf) < 1 {
+ t.Fatalf("bad: %d > %d", predicted, maxSize)
+ }
+ }
+}
+
func TestDNS_TCP_and_UDP_Truncate(t *testing.T) {
t.Parallel()
a := NewTestAgent(t.Name(), `
From 5b4905e11da2a52afa0c3c0173328d4d8cfddb4e Mon Sep 17 00:00:00 2001
From: Pierre Souchay
Date: Tue, 17 Apr 2018 09:42:08 +0200
Subject: [PATCH 04/11] More test cases + travis flacky
---
agent/dns_test.go | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/agent/dns_test.go b/agent/dns_test.go
index 5257075746..a428e153d9 100644
--- a/agent/dns_test.go
+++ b/agent/dns_test.go
@@ -2993,7 +2993,7 @@ func TestBinarySearch(t *testing.T) {
msgSrc.Answer = append(msgSrc.Answer, &dns.SRV{Hdr: dns.RR_Header{Name: "redis.service.consul.", Class: 1, Rrtype: dns.TypeSRV, Ttl: 0x3c}, Port: 0x4c57, Target: target})
msgSrc.Extra = append(msgSrc.Extra, &dns.CNAME{Hdr: dns.RR_Header{Name: target, Class: 1, Rrtype: dns.TypeCNAME, Ttl: 0x3c}, Target: fmt.Sprintf("fx.168.%d.%d.", i/256, i%256)})
}
- for _, maxSize := range []int{256, 512, 8192} {
+ for idx, maxSize := range []int{12, 256, 512, 8192, 65535} {
msg := new(dns.Msg)
msgSrc.Compress = true
msgSrc.SetQuestion("redis.service.consul.", dns.TypeSRV)
@@ -3012,8 +3012,8 @@ func TestBinarySearch(t *testing.T) {
if predicted < len(buf) {
t.Fatalf("Bug in DNS library: %d != %d", predicted, len(buf))
}
- if len(buf) > maxSize || len(buf) < 1 {
- t.Fatalf("bad: %d > %d", predicted, maxSize)
+ if len(buf) > maxSize || (idx != 0 && len(buf) < 16) || (maxSize == 65535 && blen != 50) {
+ t.Fatalf("bad[%d]: %d > %d", idx, len(buf), maxSize)
}
}
}
From 8a5028e4af22a0718c3d2dfccd375c6ee610d7ac Mon Sep 17 00:00:00 2001
From: Pierre Souchay
Date: Tue, 17 Apr 2018 10:01:41 +0200
Subject: [PATCH 05/11] Increase timeout in travis tests
---
GNUmakefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/GNUmakefile b/GNUmakefile
index ef1a3bb0a4..48456a2241 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -76,7 +76,7 @@ test: other-consul dev-build vet
@# hide it from travis as it exceeds their log limits and causes job to be
@# terminated (over 4MB and over 10k lines in the UI). We need to output
@# _something_ to stop them terminating us due to inactivity...
- { go test $(GOTEST_FLAGS) -tags '$(GOTAGS)' -timeout 5m $(GOTEST_PKGS) 2>&1 ; echo $$? > exit-code ; } | tee test.log | egrep '^(ok|FAIL)\s*github.com/hashicorp/consul'
+ { go test $(GOTEST_FLAGS) -tags '$(GOTAGS)' -timeout 6m $(GOTEST_PKGS) 2>&1 ; echo $$? > exit-code ; } | tee test.log | egrep '^(ok|FAIL)\s*github.com/hashicorp/consul'
@echo "Exit code: $$(cat exit-code)" >> test.log
@grep -A5 'DATA RACE' test.log || true
@grep -A10 'panic: test timed out' test.log || true
From 9243daeb0eb2f1e163bb32d37d3e038cab0ba723 Mon Sep 17 00:00:00 2001
From: Pierre Souchay
Date: Tue, 17 Apr 2018 10:36:12 +0200
Subject: [PATCH 06/11] Run new test in parallel
---
agent/dns_test.go | 45 ++++++++++++++++++++++++---------------------
1 file changed, 24 insertions(+), 21 deletions(-)
diff --git a/agent/dns_test.go b/agent/dns_test.go
index a428e153d9..1dec5100d7 100644
--- a/agent/dns_test.go
+++ b/agent/dns_test.go
@@ -2984,6 +2984,7 @@ func TestDNS_ServiceLookup_Randomize(t *testing.T) {
}
func TestBinarySearch(t *testing.T) {
+ t.Parallel()
msgSrc := new(dns.Msg)
msgSrc.Compress = true
msgSrc.SetQuestion("redis.service.consul.", dns.TypeSRV)
@@ -2994,27 +2995,29 @@ func TestBinarySearch(t *testing.T) {
msgSrc.Extra = append(msgSrc.Extra, &dns.CNAME{Hdr: dns.RR_Header{Name: target, Class: 1, Rrtype: dns.TypeCNAME, Ttl: 0x3c}, Target: fmt.Sprintf("fx.168.%d.%d.", i/256, i%256)})
}
for idx, maxSize := range []int{12, 256, 512, 8192, 65535} {
- msg := new(dns.Msg)
- msgSrc.Compress = true
- msgSrc.SetQuestion("redis.service.consul.", dns.TypeSRV)
- msg.Answer = msgSrc.Answer
- msg.Extra = msgSrc.Extra
- index := make(map[string]dns.RR, len(msg.Extra))
- indexRRs(msg.Extra, index)
- blen := dnsBinaryTruncate(msg, maxSize, index, true)
- msg.Answer = msg.Answer[:blen]
- syncExtra(index, msg)
- predicted := msg.Len()
- buf, err := msg.Pack()
- if err != nil {
- t.Error(err)
- }
- if predicted < len(buf) {
- t.Fatalf("Bug in DNS library: %d != %d", predicted, len(buf))
- }
- if len(buf) > maxSize || (idx != 0 && len(buf) < 16) || (maxSize == 65535 && blen != 50) {
- t.Fatalf("bad[%d]: %d > %d", idx, len(buf), maxSize)
- }
+ t.Run(fmt.Sprintf("binarySearch %d", maxSize), func(t *testing.T) {
+ msg := new(dns.Msg)
+ msgSrc.Compress = true
+ msgSrc.SetQuestion("redis.service.consul.", dns.TypeSRV)
+ msg.Answer = msgSrc.Answer
+ msg.Extra = msgSrc.Extra
+ index := make(map[string]dns.RR, len(msg.Extra))
+ indexRRs(msg.Extra, index)
+ blen := dnsBinaryTruncate(msg, maxSize, index, true)
+ msg.Answer = msg.Answer[:blen]
+ syncExtra(index, msg)
+ predicted := msg.Len()
+ buf, err := msg.Pack()
+ if err != nil {
+ t.Error(err)
+ }
+ if predicted < len(buf) {
+ t.Fatalf("Bug in DNS library: %d != %d", predicted, len(buf))
+ }
+ if len(buf) > maxSize || (idx != 0 && len(buf) < 16) || (maxSize == 65535 && blen != 50) {
+ t.Fatalf("bad[%d]: %d > %d", idx, len(buf), maxSize)
+ }
+ })
}
}
From 89ba5165f995687835cfb525451c33eea1191490 Mon Sep 17 00:00:00 2001
From: Pierre Souchay
Date: Tue, 17 Apr 2018 13:40:57 +0200
Subject: [PATCH 07/11] Revert timeout changes
---
GNUmakefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/GNUmakefile b/GNUmakefile
index 48456a2241..ef1a3bb0a4 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -76,7 +76,7 @@ test: other-consul dev-build vet
@# hide it from travis as it exceeds their log limits and causes job to be
@# terminated (over 4MB and over 10k lines in the UI). We need to output
@# _something_ to stop them terminating us due to inactivity...
- { go test $(GOTEST_FLAGS) -tags '$(GOTAGS)' -timeout 6m $(GOTEST_PKGS) 2>&1 ; echo $$? > exit-code ; } | tee test.log | egrep '^(ok|FAIL)\s*github.com/hashicorp/consul'
+ { go test $(GOTEST_FLAGS) -tags '$(GOTAGS)' -timeout 5m $(GOTEST_PKGS) 2>&1 ; echo $$? > exit-code ; } | tee test.log | egrep '^(ok|FAIL)\s*github.com/hashicorp/consul'
@echo "Exit code: $$(cat exit-code)" >> test.log
@grep -A5 'DATA RACE' test.log || true
@grep -A10 'panic: test timed out' test.log || true
From 728c5308dfb8b3eae5b54ddf89930437c25ff0d8 Mon Sep 17 00:00:00 2001
From: Pierre Souchay
Date: Wed, 18 Apr 2018 14:17:44 +0200
Subject: [PATCH 08/11] Fixed sync of Extra in binarySearch
---
agent/dns.go | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/agent/dns.go b/agent/dns.go
index 599d758226..457674bb1f 100644
--- a/agent/dns.go
+++ b/agent/dns.go
@@ -721,14 +721,17 @@ func syncExtra(index map[string]dns.RR, resp *dns.Msg) {
// it in order to return a DNS answer lower than maxSize parameter.
func dnsBinaryTruncate(resp *dns.Msg, maxSize int, index map[string]dns.RR, hasExtra bool) int {
originalAnswser := resp.Answer
+ originalExtra := resp.Extra
+ originalIndex := index
startIndex := 0
endIndex := len(resp.Answer) + 1
for endIndex-startIndex > 1 {
median := startIndex + (endIndex-startIndex)/2
resp.Answer = originalAnswser[:median]
- resp.Extra = originalAnswser[:median]
if hasExtra {
+ resp.Extra = originalExtra[:median]
+ index := originalIndex
syncExtra(index, resp)
}
aLen := resp.Len()
From 36827418b70530d4c141b8a92d586480b061b3d7 Mon Sep 17 00:00:00 2001
From: Pierre Souchay
Date: Wed, 18 Apr 2018 14:18:17 +0200
Subject: [PATCH 09/11] Improved unit tests debug info when it fails
---
agent/dns_test.go | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/agent/dns_test.go b/agent/dns_test.go
index 1dec5100d7..b68b0b99cb 100644
--- a/agent/dns_test.go
+++ b/agent/dns_test.go
@@ -3349,17 +3349,17 @@ func testDNSServiceLookupResponseLimits(t *testing.T, answerLimit int, qType uin
case 0:
if (expectedService > 0 && len(in.Answer) != expectedService) ||
(expectedService < -1 && len(in.Answer) < lib.AbsInt(expectedService)) {
- return false, fmt.Errorf("%d/%d answers received for type %v for %s", len(in.Answer), answerLimit, qType, question)
+ return false, fmt.Errorf("%d/%d answers received for type %v for %s, sz:=%d", len(in.Answer), answerLimit, qType, question, in.Len())
}
case 1:
if (expectedQuery > 0 && len(in.Answer) != expectedQuery) ||
(expectedQuery < -1 && len(in.Answer) < lib.AbsInt(expectedQuery)) {
- return false, fmt.Errorf("%d/%d answers received for type %v for %s", len(in.Answer), answerLimit, qType, question)
+ return false, fmt.Errorf("%d/%d answers received for type %v for %s, sz:=%d", len(in.Answer), answerLimit, qType, question, in.Len())
}
case 2:
if (expectedQueryID > 0 && len(in.Answer) != expectedQueryID) ||
(expectedQueryID < -1 && len(in.Answer) < lib.AbsInt(expectedQueryID)) {
- return false, fmt.Errorf("%d/%d answers received for type %v for %s", len(in.Answer), answerLimit, qType, question)
+ return false, fmt.Errorf("%d/%d answers received for type %v for %s, sz:=%d", len(in.Answer), answerLimit, qType, question, in.Len())
}
default:
panic("abort")
@@ -3511,7 +3511,7 @@ func TestDNS_ServiceLookup_ARecordLimits(t *testing.T) {
t.Parallel()
err := checkDNSService(t, test.numNodesTotal, test.aRecordLimit, qType, test.expectedAResults, test.udpSize, test.udpAnswerLimit)
if err != nil {
- t.Errorf("Expected lookup %s to pass: %v", test.name, err)
+ t.Fatalf("Expected lookup %s to pass: %v", test.name, err)
}
})
}
@@ -3520,7 +3520,7 @@ func TestDNS_ServiceLookup_ARecordLimits(t *testing.T) {
t.Parallel()
err := checkDNSService(t, test.expectedSRVResults, test.aRecordLimit, dns.TypeSRV, test.numNodesTotal, test.udpSize, test.udpAnswerLimit)
if err != nil {
- t.Errorf("Expected service SRV lookup %s to pass: %v", test.name, err)
+ t.Fatalf("Expected service SRV lookup %s to pass: %v", test.name, err)
}
})
}
@@ -3566,27 +3566,27 @@ func TestDNS_ServiceLookup_AnswerLimits(t *testing.T) {
}
for _, test := range tests {
test := test // capture loop var
- t.Run("A lookup", func(t *testing.T) {
+ t.Run(fmt.Sprintf("A lookup %v", test), func(t *testing.T) {
t.Parallel()
ok, err := testDNSServiceLookupResponseLimits(t, test.udpAnswerLimit, dns.TypeA, test.expectedAService, test.expectedAQuery, test.expectedAQueryID)
if !ok {
- t.Errorf("Expected service A lookup %s to pass: %v", test.name, err)
+ t.Fatalf("Expected service A lookup %s to pass: %v", test.name, err)
}
})
- t.Run("AAAA lookup", func(t *testing.T) {
+ t.Run(fmt.Sprintf("AAAA lookup %v", test), func(t *testing.T) {
t.Parallel()
ok, err := testDNSServiceLookupResponseLimits(t, test.udpAnswerLimit, dns.TypeAAAA, test.expectedAAAAService, test.expectedAAAAQuery, test.expectedAAAAQueryID)
if !ok {
- t.Errorf("Expected service AAAA lookup %s to pass: %v", test.name, err)
+ t.Fatalf("Expected service AAAA lookup %s to pass: %v", test.name, err)
}
})
- t.Run("ANY lookup", func(t *testing.T) {
+ t.Run(fmt.Sprintf("ANY lookup %v", test), func(t *testing.T) {
t.Parallel()
ok, err := testDNSServiceLookupResponseLimits(t, test.udpAnswerLimit, dns.TypeANY, test.expectedANYService, test.expectedANYQuery, test.expectedANYQueryID)
if !ok {
- t.Errorf("Expected service ANY lookup %s to pass: %v", test.name, err)
+ t.Fatalf("Expected service ANY lookup %s to pass: %v", test.name, err)
}
})
}
From 076ecf9712266ce77ba9bc079cbd5b23e7d89269 Mon Sep 17 00:00:00 2001
From: Pierre Souchay
Date: Fri, 20 Apr 2018 22:51:04 +0200
Subject: [PATCH 10/11] Removed unecessary copy of Extra and index
---
agent/dns.go | 4 ----
1 file changed, 4 deletions(-)
diff --git a/agent/dns.go b/agent/dns.go
index 457674bb1f..6211e71b95 100644
--- a/agent/dns.go
+++ b/agent/dns.go
@@ -721,8 +721,6 @@ func syncExtra(index map[string]dns.RR, resp *dns.Msg) {
// it in order to return a DNS answer lower than maxSize parameter.
func dnsBinaryTruncate(resp *dns.Msg, maxSize int, index map[string]dns.RR, hasExtra bool) int {
originalAnswser := resp.Answer
- originalExtra := resp.Extra
- originalIndex := index
startIndex := 0
endIndex := len(resp.Answer) + 1
for endIndex-startIndex > 1 {
@@ -730,8 +728,6 @@ func dnsBinaryTruncate(resp *dns.Msg, maxSize int, index map[string]dns.RR, hasE
resp.Answer = originalAnswser[:median]
if hasExtra {
- resp.Extra = originalExtra[:median]
- index := originalIndex
syncExtra(index, resp)
}
aLen := resp.Len()
From c715408c87d271cb7a137275b1ab18999a78c59e Mon Sep 17 00:00:00 2001
From: Pierre Souchay
Date: Sat, 21 Apr 2018 17:18:39 +0200
Subject: [PATCH 11/11] More Tests cases compression/no compression
---
agent/dns_test.go | 55 ++++++++++++++++++++++++-----------------------
1 file changed, 28 insertions(+), 27 deletions(-)
diff --git a/agent/dns_test.go b/agent/dns_test.go
index b68b0b99cb..0770c92a0a 100644
--- a/agent/dns_test.go
+++ b/agent/dns_test.go
@@ -2989,35 +2989,37 @@ func TestBinarySearch(t *testing.T) {
msgSrc.Compress = true
msgSrc.SetQuestion("redis.service.consul.", dns.TypeSRV)
- for i := 0; i < 50; i++ {
+ for i := 0; i < 5000; i++ {
target := fmt.Sprintf("host-redis-%d-%d.test.acme.com.node.dc1.consul.", i/256, i%256)
msgSrc.Answer = append(msgSrc.Answer, &dns.SRV{Hdr: dns.RR_Header{Name: "redis.service.consul.", Class: 1, Rrtype: dns.TypeSRV, Ttl: 0x3c}, Port: 0x4c57, Target: target})
msgSrc.Extra = append(msgSrc.Extra, &dns.CNAME{Hdr: dns.RR_Header{Name: target, Class: 1, Rrtype: dns.TypeCNAME, Ttl: 0x3c}, Target: fmt.Sprintf("fx.168.%d.%d.", i/256, i%256)})
}
- for idx, maxSize := range []int{12, 256, 512, 8192, 65535} {
- t.Run(fmt.Sprintf("binarySearch %d", maxSize), func(t *testing.T) {
- msg := new(dns.Msg)
- msgSrc.Compress = true
- msgSrc.SetQuestion("redis.service.consul.", dns.TypeSRV)
- msg.Answer = msgSrc.Answer
- msg.Extra = msgSrc.Extra
- index := make(map[string]dns.RR, len(msg.Extra))
- indexRRs(msg.Extra, index)
- blen := dnsBinaryTruncate(msg, maxSize, index, true)
- msg.Answer = msg.Answer[:blen]
- syncExtra(index, msg)
- predicted := msg.Len()
- buf, err := msg.Pack()
- if err != nil {
- t.Error(err)
- }
- if predicted < len(buf) {
- t.Fatalf("Bug in DNS library: %d != %d", predicted, len(buf))
- }
- if len(buf) > maxSize || (idx != 0 && len(buf) < 16) || (maxSize == 65535 && blen != 50) {
- t.Fatalf("bad[%d]: %d > %d", idx, len(buf), maxSize)
- }
- })
+ for _, compress := range []bool{true, false} {
+ for idx, maxSize := range []int{12, 256, 512, 8192, 65535} {
+ t.Run(fmt.Sprintf("binarySearch %d", maxSize), func(t *testing.T) {
+ msg := new(dns.Msg)
+ msgSrc.Compress = compress
+ msgSrc.SetQuestion("redis.service.consul.", dns.TypeSRV)
+ msg.Answer = msgSrc.Answer
+ msg.Extra = msgSrc.Extra
+ index := make(map[string]dns.RR, len(msg.Extra))
+ indexRRs(msg.Extra, index)
+ blen := dnsBinaryTruncate(msg, maxSize, index, true)
+ msg.Answer = msg.Answer[:blen]
+ syncExtra(index, msg)
+ predicted := msg.Len()
+ buf, err := msg.Pack()
+ if err != nil {
+ t.Error(err)
+ }
+ if predicted < len(buf) {
+ t.Fatalf("Bug in DNS library: %d != %d", predicted, len(buf))
+ }
+ if len(buf) > maxSize || (idx != 0 && len(buf) < 16) {
+ t.Fatalf("bad[%d]: %d > %d", idx, len(buf), maxSize)
+ }
+ })
+ }
}
}
@@ -3095,9 +3097,8 @@ func TestDNS_TCP_and_UDP_Truncate(t *testing.T) {
if err != nil && err != dns.ErrTruncated {
t.Fatalf("err: %v", err)
}
-
// Check for the truncate bit
- shouldBeTruncated := numServices > 4095
+ shouldBeTruncated := numServices > 5000
if shouldBeTruncated != in.Truncated || len(in.Answer) > 2000 || len(in.Answer) < 1 || in.Len() > 65535 {
info := fmt.Sprintf("service %s question:=%s (%s) (%d total records) sz:= %d in %v",