plugin/dnssec: use entire RRset as key input (#4537)

* plugin/dnssec: use entire RRset as key input

This uses the entire rrset as input for the hash key; this is to detect
differences in the RRset and generate the correct signature.

As this would then lead to unbounded growth, we periodically (every 8h)
prune the cache of old entries. In theory we could rely on the random
eviction, but it seems nicer to do this in a maintannce loop so that we
remove the unused ones. This required adding a Walk function to the
plugin/pkg/cache.

Signed-off-by: Miek Gieben <miek@miek.nl>

* Update plugin/dnssec/cache.go

Co-authored-by: Chris O'Haver <cohaver@infoblox.com>

Co-authored-by: Chris O'Haver <cohaver@infoblox.com>
This commit is contained in:
Miek Gieben
2021-04-05 15:45:28 +02:00
committed by GitHub
parent 454bc9e0b9
commit 13cef2ee09
5 changed files with 98 additions and 15 deletions

View File

@@ -72,6 +72,13 @@ func (c *Cache) Len() int {
return l
}
// Walk walks each shard in the cache.
func (c *Cache) Walk(f func(map[uint64]interface{}, uint64) bool) {
for _, s := range c.shards {
s.Walk(f)
}
}
// newShard returns a new shard with size.
func newShard(size int) *shard { return &shard{items: make(map[uint64]interface{}), size: size} }
@@ -127,4 +134,24 @@ func (s *shard) Len() int {
return l
}
// Walk walks the shard for each element the function f is executed while holding a write lock.
func (s *shard) Walk(f func(map[uint64]interface{}, uint64) bool) {
items := make([]uint64, len(s.items))
s.RLock()
i := 0
for k := range s.items {
items[i] = k
i++
}
s.RUnlock()
for _, k := range items {
s.Lock()
ok := f(s.items, k)
s.Unlock()
if !ok {
return
}
}
}
const shardSize = 256

View File

@@ -1,6 +1,8 @@
package cache
import "testing"
import (
"testing"
)
func TestCacheAddAndGet(t *testing.T) {
const N = shardSize * 4
@@ -53,6 +55,25 @@ func TestCacheSharding(t *testing.T) {
}
}
func TestCacheWalk(t *testing.T) {
c := New(10)
exp := make([]int, 10*2)
for i := 0; i < 10*2; i++ {
c.Add(uint64(i), 1)
exp[i] = 1
}
got := make([]int, 10*2)
c.Walk(func(items map[uint64]interface{}, key uint64) bool {
got[key] = items[key].(int)
return true
})
for i := range exp {
if exp[i] != got[i] {
t.Errorf("Expected %d, got %d", exp[i], got[i])
}
}
}
func BenchmarkCache(b *testing.B) {
b.ReportAllocs()