]>
git.ipfire.org Git - thirdparty/pdns.git/blob - regression-tests.dnsdist/test_Caching.py
5 import clientsubnetoption
6 from dnsdisttests
import DNSDistTest
8 class TestCaching ( DNSDistTest
):
10 _config_template
= """
11 pc = newPacketCache(100, {maxTTL=86400, minTTL=1})
12 getPool(""):setCache(pc)
13 addAction(makeRule("nocache.cache.tests.powerdns.com."), SkipCacheAction())
14 function skipViaLua(dq)
16 return DNSAction.None, ""
18 addAction("nocachevialua.cache.tests.powerdns.com.", LuaAction(skipViaLua))
19 newServer{address="127.0.0.1: %d "}
24 Cache: Served from cache
26 dnsdist is configured to cache entries, we are sending several
27 identical requests and checking that the backend only receive
31 name
= 'cached.cache.tests.powerdns.com.'
32 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
33 response
= dns
. message
. make_response ( query
)
34 rrset
= dns
. rrset
. from_text ( name
,
39 response
. answer
. append ( rrset
)
41 # first query to fill the cache
42 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
43 self
. assertTrue ( receivedQuery
)
44 self
. assertTrue ( receivedResponse
)
45 receivedQuery
. id = query
. id
46 self
. assertEquals ( query
, receivedQuery
)
47 self
. assertEquals ( receivedResponse
, response
)
49 for _
in range ( numberOfQueries
):
50 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
51 self
. assertEquals ( receivedResponse
, response
)
54 for key
in self
._ responsesCounter
:
55 total
+= self
._ responsesCounter
[ key
]
56 TestCaching
._ responsesCounter
[ key
] = 0
58 self
. assertEquals ( total
, 1 )
60 # TCP should not be cached
61 # first query to fill the cache
62 ( receivedQuery
, receivedResponse
) = self
. sendTCPQuery ( query
, response
)
63 self
. assertTrue ( receivedQuery
)
64 self
. assertTrue ( receivedResponse
)
65 receivedQuery
. id = query
. id
66 self
. assertEquals ( query
, receivedQuery
)
67 self
. assertEquals ( receivedResponse
, response
)
69 for _
in range ( numberOfQueries
):
70 ( _
, receivedResponse
) = self
. sendTCPQuery ( query
, response
= None , useQueue
= False )
71 self
. assertEquals ( receivedResponse
, response
)
74 for key
in self
._ responsesCounter
:
75 total
+= self
._ responsesCounter
[ key
]
76 TestCaching
._ responsesCounter
[ key
] = 0
78 self
. assertEquals ( total
, 1 )
80 def testDOCached ( self
):
82 Cache: Served from cache, query has DO bit set
84 dnsdist is configured to cache entries, we are sending several
85 identical requests and checking that the backend only receive
89 name
= 'cached-do.cache.tests.powerdns.com.'
90 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' , use_edns
= True , payload
= 4096 , want_dnssec
= True )
91 response
= dns
. message
. make_response ( query
)
92 rrset
= dns
. rrset
. from_text ( name
,
97 response
. answer
. append ( rrset
)
99 # first query to fill the cache
100 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
101 self
. assertTrue ( receivedQuery
)
102 self
. assertTrue ( receivedResponse
)
103 receivedQuery
. id = query
. id
104 self
. assertEquals ( query
, receivedQuery
)
105 self
. assertEquals ( receivedResponse
, response
)
107 for _
in range ( numberOfQueries
):
108 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
109 self
. assertEquals ( receivedResponse
, response
)
112 for key
in self
._ responsesCounter
:
113 total
+= self
._ responsesCounter
[ key
]
114 TestCaching
._ responsesCounter
[ key
] = 0
116 self
. assertEquals ( total
, 1 )
118 # TCP should not be cached
119 # first query to fill the cache
120 ( receivedQuery
, receivedResponse
) = self
. sendTCPQuery ( query
, response
)
121 self
. assertTrue ( receivedQuery
)
122 self
. assertTrue ( receivedResponse
)
123 receivedQuery
. id = query
. id
124 self
. assertEquals ( query
, receivedQuery
)
125 self
. assertEquals ( receivedResponse
, response
)
127 for _
in range ( numberOfQueries
):
128 ( _
, receivedResponse
) = self
. sendTCPQuery ( query
, response
= None , useQueue
= False )
129 self
. assertEquals ( receivedResponse
, response
)
132 for key
in self
._ responsesCounter
:
133 total
+= self
._ responsesCounter
[ key
]
134 TestCaching
._ responsesCounter
[ key
] = 0
136 self
. assertEquals ( total
, 1 )
138 def testSkipCache ( self
):
140 Cache: SkipCacheAction
142 dnsdist is configured to not cache entries for nocache.cache.tests.powerdns.com.
143 we are sending several requests and checking that the backend get them all.
145 name
= 'nocache.cache.tests.powerdns.com.'
147 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
148 response
= dns
. message
. make_response ( query
)
149 rrset
= dns
. rrset
. from_text ( name
,
154 response
. answer
. append ( rrset
)
156 for _
in range ( numberOfQueries
):
157 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
158 sender
= getattr ( self
, method
)
159 ( receivedQuery
, receivedResponse
) = sender ( query
, response
)
160 self
. assertTrue ( receivedQuery
)
161 self
. assertTrue ( receivedResponse
)
162 receivedQuery
. id = query
. id
163 self
. assertEquals ( query
, receivedQuery
)
164 self
. assertEquals ( receivedResponse
, response
)
166 for key
in self
._ responsesCounter
:
167 value
= self
._ responsesCounter
[ key
]
168 self
. assertEquals ( value
, numberOfQueries
)
170 def testSkipCacheViaLua ( self
):
172 Cache: SkipCache via Lua
174 dnsdist is configured to not cache entries for nocachevialua.cache.tests.powerdns.com.
175 we are sending several requests and checking that the backend get them all.
177 name
= 'nocachevialua.cache.tests.powerdns.com.'
179 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
180 response
= dns
. message
. make_response ( query
)
181 rrset
= dns
. rrset
. from_text ( name
,
186 response
. answer
. append ( rrset
)
188 for _
in range ( numberOfQueries
):
189 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
190 sender
= getattr ( self
, method
)
191 ( receivedQuery
, receivedResponse
) = sender ( query
, response
)
192 self
. assertTrue ( receivedQuery
)
193 self
. assertTrue ( receivedResponse
)
194 receivedQuery
. id = query
. id
195 self
. assertEquals ( query
, receivedQuery
)
196 self
. assertEquals ( receivedResponse
, response
)
198 for key
in self
._ responsesCounter
:
199 value
= self
._ responsesCounter
[ key
]
200 self
. assertEquals ( value
, numberOfQueries
)
202 def testCacheExpiration ( self
):
204 Cache: Cache expiration
206 dnsdist is configured to cache entries, we are sending one request
207 (cache miss) with a very short TTL, checking that the next requests
208 are cached. Then we wait for the TTL to expire, check that the
209 next request is a miss but the following one a hit.
213 name
= 'cacheexpiration.cache.tests.powerdns.com.'
214 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
215 response
= dns
. message
. make_response ( query
)
216 rrset
= dns
. rrset
. from_text ( name
,
221 response
. answer
. append ( rrset
)
223 # first query to fill the cache
224 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
225 self
. assertTrue ( receivedQuery
)
226 self
. assertTrue ( receivedResponse
)
227 receivedQuery
. id = query
. id
228 self
. assertEquals ( query
, receivedQuery
)
229 self
. assertEquals ( receivedResponse
, response
)
232 # next queries should hit the cache
233 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
234 self
. assertEquals ( receivedResponse
, response
)
236 # now we wait a bit for the cache entry to expire
239 # next query should be a miss, fill the cache again
240 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
241 self
. assertTrue ( receivedQuery
)
242 self
. assertTrue ( receivedResponse
)
243 receivedQuery
. id = query
. id
244 self
. assertEquals ( query
, receivedQuery
)
245 self
. assertEquals ( receivedResponse
, response
)
248 # following queries should hit the cache again
249 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
250 self
. assertEquals ( receivedResponse
, response
)
253 for key
in self
._ responsesCounter
:
254 total
+= self
._ responsesCounter
[ key
]
256 self
. assertEquals ( total
, misses
)
258 def testCacheExpirationDifferentSets ( self
):
260 Cache: Cache expiration with different sets
262 dnsdist is configured to cache entries, we are sending one request
263 (cache miss) whose response has a long and a very short TTL,
264 checking that the next requests are cached. Then we wait for the
265 short TTL to expire, check that the
266 next request is a miss but the following one a hit.
270 name
= 'cacheexpirationdifferentsets.cache.tests.powerdns.com.'
271 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
272 response
= dns
. message
. make_response ( query
)
273 rrset
= dns
. rrset
. from_text ( name
,
277 'cname.cacheexpirationdifferentsets.cache.tests.powerdns.com.' )
278 response
. answer
. append ( rrset
)
279 rrset
= dns
. rrset
. from_text ( 'cname.cacheexpirationdifferentsets.cache.tests.powerdns.com.' ,
284 response
. additional
. append ( rrset
)
286 # first query to fill the cache
287 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
288 self
. assertTrue ( receivedQuery
)
289 self
. assertTrue ( receivedResponse
)
290 receivedQuery
. id = query
. id
291 self
. assertEquals ( query
, receivedQuery
)
292 self
. assertEquals ( receivedResponse
, response
)
295 # next queries should hit the cache
296 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
297 self
. assertEquals ( receivedResponse
, response
)
299 # now we wait a bit for the cache entry to expire
302 # next query should be a miss, fill the cache again
303 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
304 self
. assertTrue ( receivedQuery
)
305 self
. assertTrue ( receivedResponse
)
306 receivedQuery
. id = query
. id
307 self
. assertEquals ( query
, receivedQuery
)
308 self
. assertEquals ( receivedResponse
, response
)
311 # following queries should hit the cache again
312 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
313 self
. assertEquals ( receivedResponse
, response
)
316 for key
in self
._ responsesCounter
:
317 total
+= self
._ responsesCounter
[ key
]
319 self
. assertEquals ( total
, misses
)
321 def testCacheDecreaseTTL ( self
):
323 Cache: Cache decreases TTL
325 dnsdist is configured to cache entries, we are sending one request
326 (cache miss) and verify that the cache hits have a decreasing TTL.
330 name
= 'cachedecreasettl.cache.tests.powerdns.com.'
331 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
332 response
= dns
. message
. make_response ( query
)
333 rrset
= dns
. rrset
. from_text ( name
,
338 response
. answer
. append ( rrset
)
340 # first query to fill the cache
341 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
342 self
. assertTrue ( receivedQuery
)
343 self
. assertTrue ( receivedResponse
)
344 receivedQuery
. id = query
. id
345 self
. assertEquals ( query
, receivedQuery
)
346 self
. assertEquals ( receivedResponse
, response
)
349 # next queries should hit the cache
350 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
351 self
. assertEquals ( receivedResponse
, response
)
352 for an
in receivedResponse
. answer
:
353 self
. assertTrue ( an
. ttl
<= ttl
)
355 # now we wait a bit for the TTL to decrease
358 # next queries should hit the cache
359 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
360 self
. assertEquals ( receivedResponse
, response
)
361 for an
in receivedResponse
. answer
:
362 self
. assertTrue ( an
. ttl
< ttl
)
365 for key
in self
._ responsesCounter
:
366 total
+= self
._ responsesCounter
[ key
]
368 self
. assertEquals ( total
, misses
)
370 def testCacheDifferentCase ( self
):
372 Cache: Cache matches different case
374 dnsdist is configured to cache entries, we are sending one request
375 (cache miss) and verify that the same one with a different case
379 name
= 'cachedifferentcase.cache.tests.powerdns.com.'
380 differentCaseName
= 'CacheDifferentCASE.cache.tests.powerdns.com.'
381 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
382 differentCaseQuery
= dns
. message
. make_query ( differentCaseName
, 'AAAA' , 'IN' )
383 response
= dns
. message
. make_response ( query
)
384 differentCaseResponse
= dns
. message
. make_response ( differentCaseQuery
)
385 rrset
= dns
. rrset
. from_text ( name
,
390 response
. answer
. append ( rrset
)
391 differentCaseResponse
. answer
. append ( rrset
)
393 # first query to fill the cache
394 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
395 self
. assertTrue ( receivedQuery
)
396 self
. assertTrue ( receivedResponse
)
397 receivedQuery
. id = query
. id
398 self
. assertEquals ( query
, receivedQuery
)
399 self
. assertEquals ( receivedResponse
, response
)
401 # different case query should still hit the cache
402 ( _
, receivedResponse
) = self
. sendUDPQuery ( differentCaseQuery
, response
= None , useQueue
= False )
403 self
. assertEquals ( receivedResponse
, differentCaseResponse
)
406 class TestTempFailureCacheTTLAction ( DNSDistTest
):
408 _config_template
= """
409 pc = newPacketCache(100, {maxTTL=86400, minTTL=1})
410 getPool(""):setCache(pc)
411 addAction("servfail.cache.tests.powerdns.com.", TempFailureCacheTTLAction(1))
412 newServer{address="127.0.0.1: %d "}
415 def testTempFailureCacheTTLAction ( self
):
417 Cache: When a TempFailure TTL is set, it should be honored
419 dnsdist is configured to cache packets, plus a specific qname is
420 set up with a lower TempFailure Cache TTL. we are sending one request
421 (cache miss) and verify that the cache is hit for the following query,
422 but the TTL then expires before the larger "good" packetcache TTL.
424 name
= 'servfail.cache.tests.powerdns.com.'
425 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
426 response
= dns
. message
. make_response ( query
)
427 response
. set_rcode ( dns
. rcode
. SERVFAIL
)
429 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
430 self
. assertTrue ( receivedQuery
)
431 self
. assertTrue ( receivedResponse
)
432 receivedQuery
. id = query
. id
433 self
. assertEquals ( query
, receivedQuery
)
434 self
. assertEquals ( receivedResponse
, response
)
436 # next query should hit the cache
437 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
438 self
. assertFalse ( receivedQuery
)
439 self
. assertTrue ( receivedResponse
)
440 self
. assertEquals ( receivedResponse
, response
)
442 # now we wait a bit for the Failure-Cache TTL to expire
445 # next query should NOT hit the cache
446 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
447 self
. assertTrue ( receivedQuery
)
448 self
. assertTrue ( receivedResponse
)
449 self
. assertEquals ( receivedResponse
, response
)
452 class TestCachingWithExistingEDNS ( DNSDistTest
):
454 _config_template
= """
455 pc = newPacketCache(5, {maxTTL=86400, minTTL=1})
456 getPool(""):setCache(pc)
457 newServer{address="127.0.0.1: %d "}
459 def testCacheWithEDNS ( self
):
461 Cache: Cache should not match different EDNS value
463 dnsdist is configured to cache entries, we are sending one request
464 (cache miss) and verify that the same one with a different EDNS UDP
465 Payload size is not served from the cache.
468 name
= 'cachedifferentedns.cache.tests.powerdns.com.'
469 query
= dns
. message
. make_query ( name
, 'A' , 'IN' , use_edns
= True , payload
= 512 )
470 response
= dns
. message
. make_response ( query
)
471 rrset
= dns
. rrset
. from_text ( name
,
476 response
. answer
. append ( rrset
)
478 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
479 self
. assertTrue ( receivedQuery
)
480 self
. assertTrue ( receivedResponse
)
481 receivedQuery
. id = query
. id
482 self
. assertEquals ( query
, receivedQuery
)
483 self
. assertEquals ( response
, receivedResponse
)
486 query
= dns
. message
. make_query ( name
, 'A' , 'IN' , use_edns
= True , payload
= 4096 )
487 response
= dns
. message
. make_response ( query
)
488 rrset
= dns
. rrset
. from_text ( name
,
493 response
. answer
. append ( rrset
)
495 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
496 self
. assertTrue ( receivedQuery
)
497 self
. assertTrue ( receivedResponse
)
498 receivedQuery
. id = query
. id
499 self
. assertEquals ( query
, receivedQuery
)
500 self
. assertEquals ( response
, receivedResponse
)
504 for key
in self
._ responsesCounter
:
505 total
+= self
._ responsesCounter
[ key
]
507 self
. assertEquals ( total
, misses
)
509 class TestCachingCacheFull ( DNSDistTest
):
511 _config_template
= """
512 pc = newPacketCache(1, {maxTTL=86400, minTTL=1})
513 getPool(""):setCache(pc)
514 newServer{address="127.0.0.1: %d "}
516 def testCacheFull ( self
):
518 Cache: No new entries are cached when the cache is full
522 name
= 'cachenotfullyet.cache.tests.powerdns.com.'
523 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
524 response
= dns
. message
. make_response ( query
)
525 rrset
= dns
. rrset
. from_text ( name
,
530 response
. answer
. append ( rrset
)
533 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
534 self
. assertTrue ( receivedQuery
)
535 self
. assertTrue ( receivedResponse
)
536 receivedQuery
. id = query
. id
537 self
. assertEquals ( query
, receivedQuery
)
538 self
. assertEquals ( response
, receivedResponse
)
541 # next queries should hit the cache
542 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
543 self
. assertEquals ( receivedResponse
, response
)
545 # ok, now the cache is full, send another query
546 name
= 'cachefull.cache.tests.powerdns.com.'
547 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
548 response
= dns
. message
. make_response ( query
)
549 rrset
= dns
. rrset
. from_text ( name
,
554 response
. answer
. append ( rrset
)
557 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
558 self
. assertTrue ( receivedQuery
)
559 self
. assertTrue ( receivedResponse
)
560 receivedQuery
. id = query
. id
561 self
. assertEquals ( query
, receivedQuery
)
562 self
. assertEquals ( response
, receivedResponse
)
565 # next queries should NOT hit the cache
566 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
567 self
. assertTrue ( receivedQuery
)
568 self
. assertTrue ( receivedResponse
)
569 receivedQuery
. id = query
. id
570 self
. assertEquals ( query
, receivedQuery
)
571 self
. assertEquals ( response
, receivedResponse
)
575 for key
in self
._ responsesCounter
:
576 total
+= self
._ responsesCounter
[ key
]
578 self
. assertEquals ( total
, misses
)
580 class TestCachingNoStale ( DNSDistTest
):
582 _consoleKey
= DNSDistTest
. generateConsoleKey ()
583 _consoleKeyB64
= base64
. b64encode ( _consoleKey
). decode ( 'ascii' )
584 _config_params
= [ '_consoleKeyB64' , '_consolePort' , '_testServerPort' ]
585 _config_template
= """
586 pc = newPacketCache(100, {maxTTL=86400, minTTL=1})
587 getPool(""):setCache(pc)
589 controlSocket("127.0.0.1: %d ")
590 newServer{address="127.0.0.1: %d "}
592 def testCacheNoStale ( self
):
594 Cache: Cache entry, set backend down, we should not get a stale entry
598 name
= 'nostale.cache.tests.powerdns.com.'
599 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
600 response
= dns
. message
. make_response ( query
)
601 rrset
= dns
. rrset
. from_text ( name
,
606 response
. answer
. append ( rrset
)
609 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
610 self
. assertTrue ( receivedQuery
)
611 self
. assertTrue ( receivedResponse
)
612 receivedQuery
. id = query
. id
613 self
. assertEquals ( query
, receivedQuery
)
614 self
. assertEquals ( response
, receivedResponse
)
616 # next queries should hit the cache
617 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
618 self
. assertEquals ( receivedResponse
, response
)
620 # ok, we mark the backend as down
621 self
. sendConsoleCommand ( "getServer(0):setDown()" )
622 # and we wait for the entry to expire
625 # we should NOT get a cached, stale, entry
626 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
627 self
. assertEquals ( receivedResponse
, None )
630 class TestCachingStale ( DNSDistTest
):
632 _consoleKey
= DNSDistTest
. generateConsoleKey ()
633 _consoleKeyB64
= base64
. b64encode ( _consoleKey
). decode ( 'ascii' )
635 _config_params
= [ '_staleCacheTTL' , '_consoleKeyB64' , '_consolePort' , '_testServerPort' ]
636 _config_template
= """
637 pc = newPacketCache(100, {maxTTL=86400, minTTL=1, temporaryFailureTTL=0, staleTTL= %d })
638 getPool(""):setCache(pc)
639 setStaleCacheEntriesTTL(600)
641 controlSocket("127.0.0.1: %d ")
642 newServer{address="127.0.0.1: %d "}
644 def testCacheStale ( self
):
646 Cache: Cache entry, set backend down, get stale entry
651 name
= 'stale.cache.tests.powerdns.com.'
652 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
653 response
= dns
. message
. make_response ( query
)
654 rrset
= dns
. rrset
. from_text ( name
,
659 response
. answer
. append ( rrset
)
662 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
663 self
. assertTrue ( receivedQuery
)
664 self
. assertTrue ( receivedResponse
)
665 receivedQuery
. id = query
. id
666 self
. assertEquals ( query
, receivedQuery
)
667 self
. assertEquals ( response
, receivedResponse
)
670 # next queries should hit the cache
671 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
672 self
. assertEquals ( receivedResponse
, response
)
674 # ok, we mark the backend as down
675 self
. sendConsoleCommand ( "getServer(0):setDown()" )
676 # and we wait for the entry to expire
679 # we should get a cached, stale, entry
680 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
681 self
. assertEquals ( receivedResponse
, response
)
682 for an
in receivedResponse
. answer
:
683 self
. assertEquals ( an
. ttl
, self
._ staleCacheTTL
)
686 for key
in self
._ responsesCounter
:
687 total
+= self
._ responsesCounter
[ key
]
689 self
. assertEquals ( total
, misses
)
691 class TestCachingStaleExpunged ( DNSDistTest
):
693 _consoleKey
= DNSDistTest
. generateConsoleKey ()
694 _consoleKeyB64
= base64
. b64encode ( _consoleKey
). decode ( 'ascii' )
696 _config_params
= [ '_staleCacheTTL' , '_consoleKeyB64' , '_consolePort' , '_testServerPort' ]
697 _config_template
= """
698 pc = newPacketCache(100, {maxTTL=86400, minTTL=1, temporaryFailureTTL=0, staleTTL= %d })
699 getPool(""):setCache(pc)
700 setStaleCacheEntriesTTL(600)
701 -- try to remove all expired entries
702 setCacheCleaningPercentage(100)
703 -- clean the cache every second
704 setCacheCleaningDelay(1)
706 controlSocket("127.0.0.1: %d ")
707 newServer{address="127.0.0.1: %d "}
709 def testCacheStale ( self
):
711 Cache: Cache entry, set backend down, wait for the cache cleaning to run and remove the entry, get no entry
716 name
= 'stale-but-expunged.cache.tests.powerdns.com.'
717 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
718 response
= dns
. message
. make_response ( query
)
719 rrset
= dns
. rrset
. from_text ( name
,
724 response
. answer
. append ( rrset
)
727 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
728 self
. assertTrue ( receivedQuery
)
729 self
. assertTrue ( receivedResponse
)
730 receivedQuery
. id = query
. id
731 self
. assertEquals ( query
, receivedQuery
)
732 self
. assertEquals ( response
, receivedResponse
)
734 self
. assertEquals ( int ( self
. sendConsoleCommand ( "getPool( \"\" ):getCache():getStats()[ \" misses \" ]" ). strip ( " \n " )), misses
+ drops
)
736 # next queries should hit the cache
737 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
738 self
. assertEquals ( receivedResponse
, response
)
739 # the cache should have one entry
740 self
. assertEquals ( int ( self
. sendConsoleCommand ( "getPool( \"\" ):getCache():getStats()[ \" entries \" ]" ). strip ( " \n " )), 1 )
741 self
. assertEquals ( int ( self
. sendConsoleCommand ( "getPool( \"\" ):getCache():getStats()[ \" hits \" ]" ). strip ( " \n " )), 1 )
743 # ok, we mark the backend as down
744 self
. sendConsoleCommand ( "getServer(0):setDown()" )
745 # and we wait for the entry to expire
747 # wait a bit more to be sure that the cache cleaning algo has been run
749 # the cache should be empty now
750 self
. assertEquals ( int ( self
. sendConsoleCommand ( "getPool( \"\" ):getCache():getStats()[ \" entries \" ]" ). strip ( " \n " )), 0 )
752 # we should get a DROP (backend is down, nothing in the cache anymore)
753 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
754 self
. assertEquals ( receivedResponse
, None )
757 self
. assertEquals ( int ( self
. sendConsoleCommand ( "getPool( \"\" ):getCache():getStats()[ \" misses \" ]" ). strip ( " \n " )), misses
+ drops
)
758 self
. assertEquals ( int ( self
. sendConsoleCommand ( "getPool( \"\" ):getCache():getStats()[ \" hits \" ]" ). strip ( " \n " )), 1 )
761 for key
in self
._ responsesCounter
:
762 total
+= self
._ responsesCounter
[ key
]
764 self
. assertEquals ( total
, misses
)
766 class TestCachingStaleExpungePrevented ( DNSDistTest
):
768 _consoleKey
= DNSDistTest
. generateConsoleKey ()
769 _consoleKeyB64
= base64
. b64encode ( _consoleKey
). decode ( 'ascii' )
770 _config_params
= [ '_consoleKeyB64' , '_consolePort' , '_testServerPort' ]
771 _config_template
= """
772 pc = newPacketCache(100, {maxTTL=86400, minTTL=1, temporaryFailureTTL=0, staleTTL=60, dontAge=false, numberOfShards=1, deferrableInsertLock=true, maxNegativeTTL=3600, ecsParsing=false, keepStaleData=true})
773 getPool(""):setCache(pc)
774 setStaleCacheEntriesTTL(600)
775 -- try to remove all expired entries
776 setCacheCleaningPercentage(100)
777 -- clean the cache every second
778 setCacheCleaningDelay(1)
780 controlSocket("127.0.0.1: %d ")
781 newServer{address="127.0.0.1: %d "}
783 def testCacheStale ( self
):
785 Cache: Cache entry, set backend down, wait for the cache cleaning to run and remove the entry, still get a cache HIT because the stale entry was not removed
789 name
= 'stale-not-expunged.cache.tests.powerdns.com.'
790 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
791 response
= dns
. message
. make_response ( query
)
792 rrset
= dns
. rrset
. from_text ( name
,
797 response
. answer
. append ( rrset
)
800 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
801 self
. assertTrue ( receivedQuery
)
802 self
. assertTrue ( receivedResponse
)
803 receivedQuery
. id = query
. id
804 self
. assertEquals ( query
, receivedQuery
)
805 self
. assertEquals ( response
, receivedResponse
)
807 self
. assertEquals ( int ( self
. sendConsoleCommand ( "getPool( \"\" ):getCache():getStats()[ \" misses \" ]" ). strip ( " \n " )), 1 )
809 # next queries should hit the cache
810 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
811 self
. assertEquals ( receivedResponse
, response
)
812 # the cache should have one entry
813 self
. assertEquals ( int ( self
. sendConsoleCommand ( "getPool( \"\" ):getCache():getStats()[ \" entries \" ]" ). strip ( " \n " )), 1 )
814 self
. assertEquals ( int ( self
. sendConsoleCommand ( "getPool( \"\" ):getCache():getStats()[ \" hits \" ]" ). strip ( " \n " )), 1 )
816 # ok, we mark the backend as down
817 self
. sendConsoleCommand ( "getServer(0):setDown()" )
818 # and we wait for the entry to expire
820 # wait a bit more to be sure that the cache cleaning algo has been run
822 # the cache should NOT be empty because the removal of the expired entry should have been prevented
823 # since all backends for this pool are down
824 self
. assertEquals ( int ( self
. sendConsoleCommand ( "getPool( \"\" ):getCache():getStats()[ \" entries \" ]" ). strip ( " \n " )), 1 )
826 # we should get a HIT
827 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
828 self
. assertEquals ( receivedResponse
, response
)
830 self
. assertEquals ( int ( self
. sendConsoleCommand ( "getPool( \"\" ):getCache():getStats()[ \" misses \" ]" ). strip ( " \n " )), 1 )
831 self
. assertEquals ( int ( self
. sendConsoleCommand ( "getPool( \"\" ):getCache():getStats()[ \" hits \" ]" ). strip ( " \n " )), 2 )
834 for key
in self
._ responsesCounter
:
835 total
+= self
._ responsesCounter
[ key
]
837 self
. assertEquals ( total
, misses
)
839 class TestCacheManagement ( DNSDistTest
):
841 _consoleKey
= DNSDistTest
. generateConsoleKey ()
842 _consoleKeyB64
= base64
. b64encode ( _consoleKey
). decode ( 'ascii' )
843 _config_params
= [ '_consoleKeyB64' , '_consolePort' , '_testServerPort' ]
844 _config_template
= """
845 pc = newPacketCache(100, {maxTTL=86400, minTTL=1})
846 getPool(""):setCache(pc)
848 controlSocket("127.0.0.1: %d ")
849 newServer{address="127.0.0.1: %d "}
851 def testCacheExpunge ( self
):
858 name
= 'expunge.cache.tests.powerdns.com.'
859 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
860 response
= dns
. message
. make_response ( query
)
861 rrset
= dns
. rrset
. from_text ( name
,
866 response
. answer
. append ( rrset
)
869 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
870 self
. assertTrue ( receivedQuery
)
871 self
. assertTrue ( receivedResponse
)
872 receivedQuery
. id = query
. id
873 self
. assertEquals ( query
, receivedQuery
)
874 self
. assertEquals ( response
, receivedResponse
)
877 # next queries should hit the cache
878 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
879 self
. assertEquals ( receivedResponse
, response
)
881 # remove cached entries
882 self
. sendConsoleCommand ( "getPool( \"\" ):getCache():expunge(0)" )
885 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
886 self
. assertTrue ( receivedQuery
)
887 self
. assertTrue ( receivedResponse
)
888 receivedQuery
. id = query
. id
889 self
. assertEquals ( query
, receivedQuery
)
890 self
. assertEquals ( response
, receivedResponse
)
893 # next queries should hit the cache again
894 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
895 self
. assertEquals ( receivedResponse
, response
)
898 for key
in self
._ responsesCounter
:
899 total
+= self
._ responsesCounter
[ key
]
901 self
. assertEquals ( total
, misses
)
903 def testCacheExpungeByName ( self
):
905 Cache: Expunge by name
910 name
= 'expungebyname.cache.tests.powerdns.com.'
911 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
912 response
= dns
. message
. make_response ( query
)
913 rrset
= dns
. rrset
. from_text ( name
,
918 response
. answer
. append ( rrset
)
920 name2
= 'expungebynameother.cache.tests.powerdns.com.'
921 query2
= dns
. message
. make_query ( name2
, 'A' , 'IN' )
922 response2
= dns
. message
. make_response ( query2
)
923 rrset2
= dns
. rrset
. from_text ( name2
,
928 response2
. answer
. append ( rrset2
)
931 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
932 self
. assertTrue ( receivedQuery
)
933 self
. assertTrue ( receivedResponse
)
934 receivedQuery
. id = query
. id
935 self
. assertEquals ( query
, receivedQuery
)
936 self
. assertEquals ( response
, receivedResponse
)
939 # next queries should hit the cache
940 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
941 self
. assertEquals ( receivedResponse
, response
)
943 # cache another entry
944 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query2
, response2
)
945 self
. assertTrue ( receivedQuery
)
946 self
. assertTrue ( receivedResponse
)
947 receivedQuery
. id = query2
. id
948 self
. assertEquals ( query2
, receivedQuery
)
949 self
. assertEquals ( response2
, receivedResponse
)
952 # queries for name and name 2 should hit the cache
953 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
954 self
. assertEquals ( receivedResponse
, response
)
956 ( _
, receivedResponse
) = self
. sendUDPQuery ( query2
, response
= None , useQueue
= False )
957 self
. assertEquals ( receivedResponse
, response2
)
959 # remove cached entries from name
960 self
. sendConsoleCommand ( "getPool( \"\" ):getCache():expungeByName(newDNSName( \" " + name
+ " \" ))" )
963 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
964 self
. assertTrue ( receivedQuery
)
965 self
. assertTrue ( receivedResponse
)
966 receivedQuery
. id = query
. id
967 self
. assertEquals ( query
, receivedQuery
)
968 self
. assertEquals ( response
, receivedResponse
)
971 # next queries for name should hit the cache again
972 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
973 self
. assertEquals ( receivedResponse
, response
)
975 # queries for name2 should still hit the cache
976 ( _
, receivedResponse
) = self
. sendUDPQuery ( query2
, response
= None , useQueue
= False )
977 self
. assertEquals ( receivedResponse
, response2
)
980 for key
in self
._ responsesCounter
:
981 total
+= self
._ responsesCounter
[ key
]
983 self
. assertEquals ( total
, misses
)
985 def testCacheExpungeByNameAndType ( self
):
987 Cache: Expunge by name and type
992 name
= 'expungebynameandtype.cache.tests.powerdns.com.'
993 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
994 response
= dns
. message
. make_response ( query
)
995 rrset
= dns
. rrset
. from_text ( name
,
1000 response
. answer
. append ( rrset
)
1002 query2
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
1003 response2
= dns
. message
. make_response ( query2
)
1004 rrset2
= dns
. rrset
. from_text ( name
,
1009 response2
. answer
. append ( rrset2
)
1012 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1013 self
. assertTrue ( receivedQuery
)
1014 self
. assertTrue ( receivedResponse
)
1015 receivedQuery
. id = query
. id
1016 self
. assertEquals ( query
, receivedQuery
)
1017 self
. assertEquals ( response
, receivedResponse
)
1020 # next queries should hit the cache
1021 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1022 self
. assertEquals ( receivedResponse
, response
)
1024 # cache another entry
1025 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query2
, response2
)
1026 self
. assertTrue ( receivedQuery
)
1027 self
. assertTrue ( receivedResponse
)
1028 receivedQuery
. id = query2
. id
1029 self
. assertEquals ( query2
, receivedQuery
)
1030 self
. assertEquals ( response2
, receivedResponse
)
1033 # queries for name A and AAAA should hit the cache
1034 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1035 self
. assertEquals ( receivedResponse
, response
)
1037 ( _
, receivedResponse
) = self
. sendUDPQuery ( query2
, response
= None , useQueue
= False )
1038 self
. assertEquals ( receivedResponse
, response2
)
1040 # remove cached entries from name A
1041 self
. sendConsoleCommand ( "getPool( \"\" ):getCache():expungeByName(newDNSName( \" " + name
+ " \" ), DNSQType.A)" )
1044 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1045 self
. assertTrue ( receivedQuery
)
1046 self
. assertTrue ( receivedResponse
)
1047 receivedQuery
. id = query
. id
1048 self
. assertEquals ( query
, receivedQuery
)
1049 self
. assertEquals ( response
, receivedResponse
)
1052 # next queries for name A should hit the cache again
1053 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1054 self
. assertEquals ( receivedResponse
, response
)
1056 # queries for name AAAA should still hit the cache
1057 ( _
, receivedResponse
) = self
. sendUDPQuery ( query2
, response
= None , useQueue
= False )
1058 self
. assertEquals ( receivedResponse
, response2
)
1061 for key
in self
._ responsesCounter
:
1062 total
+= self
._ responsesCounter
[ key
]
1063 self
. assertEquals ( total
, misses
)
1065 def testCacheExpungeByNameAndSuffix ( self
):
1067 Cache: Expunge by name
1072 name
= 'expungebyname.suffix.cache.tests.powerdns.com.'
1073 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
1074 response
= dns
. message
. make_response ( query
)
1075 rrset
= dns
. rrset
. from_text ( name
,
1080 response
. answer
. append ( rrset
)
1082 name2
= 'expungebyname.suffixother.cache.tests.powerdns.com.'
1083 query2
= dns
. message
. make_query ( name2
, 'A' , 'IN' )
1084 response2
= dns
. message
. make_response ( query2
)
1085 rrset2
= dns
. rrset
. from_text ( name2
,
1090 response2
. answer
. append ( rrset2
)
1093 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1094 self
. assertTrue ( receivedQuery
)
1095 self
. assertTrue ( receivedResponse
)
1096 receivedQuery
. id = query
. id
1097 self
. assertEquals ( query
, receivedQuery
)
1098 self
. assertEquals ( response
, receivedResponse
)
1101 # next queries should hit the cache
1102 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1103 self
. assertEquals ( receivedResponse
, response
)
1105 # cache another entry
1106 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query2
, response2
)
1107 self
. assertTrue ( receivedQuery
)
1108 self
. assertTrue ( receivedResponse
)
1109 receivedQuery
. id = query2
. id
1110 self
. assertEquals ( query2
, receivedQuery
)
1111 self
. assertEquals ( response2
, receivedResponse
)
1114 # queries for name and name 2 should hit the cache
1115 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1116 self
. assertEquals ( receivedResponse
, response
)
1118 ( _
, receivedResponse
) = self
. sendUDPQuery ( query2
, response
= None , useQueue
= False )
1119 self
. assertEquals ( receivedResponse
, response2
)
1121 # remove cached entries from name
1122 self
. sendConsoleCommand ( "getPool( \"\" ):getCache():expungeByName(newDNSName( \" suffix.cache.tests.powerdns.com. \" ), DNSQType.ANY, true)" )
1125 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1126 self
. assertTrue ( receivedQuery
)
1127 self
. assertTrue ( receivedResponse
)
1128 receivedQuery
. id = query
. id
1129 self
. assertEquals ( query
, receivedQuery
)
1130 self
. assertEquals ( response
, receivedResponse
)
1133 # next queries for name should hit the cache again
1134 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1135 self
. assertEquals ( receivedResponse
, response
)
1137 # queries for name2 should still hit the cache
1138 ( _
, receivedResponse
) = self
. sendUDPQuery ( query2
, response
= None , useQueue
= False )
1139 self
. assertEquals ( receivedResponse
, response2
)
1142 for key
in self
._ responsesCounter
:
1143 total
+= self
._ responsesCounter
[ key
]
1145 self
. assertEquals ( total
, misses
)
1147 def testCacheExpungeByNameAndTypeAndSuffix ( self
):
1149 Cache: Expunge by name and type
1154 name
= 'expungebynameandtype.suffixtype.cache.tests.powerdns.com.'
1155 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
1156 response
= dns
. message
. make_response ( query
)
1157 rrset
= dns
. rrset
. from_text ( name
,
1162 response
. answer
. append ( rrset
)
1164 query2
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
1165 response2
= dns
. message
. make_response ( query2
)
1166 rrset2
= dns
. rrset
. from_text ( name
,
1171 response2
. answer
. append ( rrset2
)
1174 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1175 self
. assertTrue ( receivedQuery
)
1176 self
. assertTrue ( receivedResponse
)
1177 receivedQuery
. id = query
. id
1178 self
. assertEquals ( query
, receivedQuery
)
1179 self
. assertEquals ( response
, receivedResponse
)
1182 # next queries should hit the cache
1183 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1184 self
. assertEquals ( receivedResponse
, response
)
1186 # cache another entry
1187 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query2
, response2
)
1188 self
. assertTrue ( receivedQuery
)
1189 self
. assertTrue ( receivedResponse
)
1190 receivedQuery
. id = query2
. id
1191 self
. assertEquals ( query2
, receivedQuery
)
1192 self
. assertEquals ( response2
, receivedResponse
)
1195 # queries for name A and AAAA should hit the cache
1196 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1197 self
. assertEquals ( receivedResponse
, response
)
1199 ( _
, receivedResponse
) = self
. sendUDPQuery ( query2
, response
= None , useQueue
= False )
1200 self
. assertEquals ( receivedResponse
, response2
)
1202 # remove cached entries from name A
1203 self
. sendConsoleCommand ( "getPool( \"\" ):getCache():expungeByName(newDNSName( \" suffixtype.cache.tests.powerdns.com. \" ), DNSQType.A, true)" )
1206 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1207 self
. assertTrue ( receivedQuery
)
1208 self
. assertTrue ( receivedResponse
)
1209 receivedQuery
. id = query
. id
1210 self
. assertEquals ( query
, receivedQuery
)
1211 self
. assertEquals ( response
, receivedResponse
)
1214 # next queries for name A should hit the cache again
1215 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1216 self
. assertEquals ( receivedResponse
, response
)
1218 # queries for name AAAA should still hit the cache
1219 ( _
, receivedResponse
) = self
. sendUDPQuery ( query2
, response
= None , useQueue
= False )
1220 self
. assertEquals ( receivedResponse
, response2
)
1223 for key
in self
._ responsesCounter
:
1224 total
+= self
._ responsesCounter
[ key
]
1225 self
. assertEquals ( total
, misses
)
1227 class TestCachingTTL ( DNSDistTest
):
1229 _maxCacheTTL
= 86400
1231 _config_params
= [ '_maxCacheTTL' , '_minCacheTTL' , '_testServerPort' ]
1232 _config_template
= """
1233 pc = newPacketCache(1000, {maxTTL= %d , minTTL= %d })
1234 getPool(""):setCache(pc)
1235 newServer{address="127.0.0.1: %d "}
1237 def testCacheShortTTL ( self
):
1239 Cache: Entries with a TTL shorter than minTTL
1244 name
= 'ttltooshort.cache.tests.powerdns.com.'
1245 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
1246 response
= dns
. message
. make_response ( query
)
1247 rrset
= dns
. rrset
. from_text ( name
,
1252 response
. answer
. append ( rrset
)
1255 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1256 self
. assertTrue ( receivedQuery
)
1257 self
. assertTrue ( receivedResponse
)
1258 receivedQuery
. id = query
. id
1259 self
. assertEquals ( query
, receivedQuery
)
1260 self
. assertEquals ( response
, receivedResponse
)
1261 for an
in receivedResponse
. answer
:
1262 self
. assertEquals ( an
. ttl
, ttl
)
1265 # We should not have been cached
1266 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1267 self
. assertTrue ( receivedQuery
)
1268 self
. assertTrue ( receivedResponse
)
1269 receivedQuery
. id = query
. id
1270 self
. assertEquals ( query
, receivedQuery
)
1271 self
. assertEquals ( response
, receivedResponse
)
1272 for an
in receivedResponse
. answer
:
1273 self
. assertEquals ( an
. ttl
, ttl
)
1277 for key
in self
._ responsesCounter
:
1278 total
+= self
._ responsesCounter
[ key
]
1280 self
. assertEquals ( total
, misses
)
1282 def testCacheNXWithNoRR ( self
):
1284 Cache: NX with no RR
1288 name
= 'nxwithnorr.cache.tests.powerdns.com.'
1289 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
1290 response
= dns
. message
. make_response ( query
)
1291 response
. set_rcode ( dns
. rcode
. NXDOMAIN
)
1294 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1295 self
. assertTrue ( receivedQuery
)
1296 self
. assertTrue ( receivedResponse
)
1297 receivedQuery
. id = query
. id
1298 self
. assertEquals ( query
, receivedQuery
)
1299 self
. assertEquals ( response
, receivedResponse
)
1302 # We should not have been cached
1303 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1304 self
. assertTrue ( receivedQuery
)
1305 self
. assertTrue ( receivedResponse
)
1306 receivedQuery
. id = query
. id
1307 self
. assertEquals ( query
, receivedQuery
)
1308 self
. assertEquals ( response
, receivedResponse
)
1312 for key
in self
._ responsesCounter
:
1313 total
+= self
._ responsesCounter
[ key
]
1315 self
. assertEquals ( total
, misses
)
1317 class TestCachingLongTTL ( DNSDistTest
):
1320 _config_params
= [ '_maxCacheTTL' , '_testServerPort' ]
1321 _config_template
= """
1322 pc = newPacketCache(1000, {maxTTL= %d })
1323 getPool(""):setCache(pc)
1324 newServer{address="127.0.0.1: %d "}
1326 def testCacheLongTTL ( self
):
1328 Cache: Entries with a longer TTL than the maximum
1333 name
= 'longttl.cache.tests.powerdns.com.'
1334 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
1335 response
= dns
. message
. make_response ( query
)
1336 rrset
= dns
. rrset
. from_text ( name
,
1341 response
. answer
. append ( rrset
)
1344 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1345 self
. assertTrue ( receivedQuery
)
1346 self
. assertTrue ( receivedResponse
)
1347 receivedQuery
. id = query
. id
1348 self
. assertEquals ( query
, receivedQuery
)
1349 self
. assertEquals ( response
, receivedResponse
)
1350 for an
in receivedResponse
. answer
:
1351 self
. assertEquals ( an
. ttl
, ttl
)
1354 # next queries should hit the cache
1355 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1356 self
. assertEquals ( receivedResponse
, response
)
1357 for an
in receivedResponse
. answer
:
1358 self
. assertTrue ( an
. ttl
<= ttl
)
1360 time
. sleep ( self
._ maxCacheTTL
+ 1 )
1362 # we should not have cached for longer than max cache
1363 # so it should be a miss
1364 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1365 self
. assertTrue ( receivedQuery
)
1366 self
. assertTrue ( receivedResponse
)
1367 receivedQuery
. id = query
. id
1368 self
. assertEquals ( query
, receivedQuery
)
1369 self
. assertEquals ( response
, receivedResponse
)
1370 for an
in receivedResponse
. answer
:
1371 self
. assertEquals ( an
. ttl
, ttl
)
1375 for key
in self
._ responsesCounter
:
1376 total
+= self
._ responsesCounter
[ key
]
1378 self
. assertEquals ( total
, misses
)
1380 class TestCachingFailureTTL ( DNSDistTest
):
1382 _failureCacheTTL
= 2
1383 _config_params
= [ '_failureCacheTTL' , '_testServerPort' ]
1384 _config_template
= """
1385 pc = newPacketCache(1000, {maxTTL=86400, minTTL=0, temporaryFailureTTL= %d , staleTTL=60})
1386 getPool(""):setCache(pc)
1387 newServer{address="127.0.0.1: %d "}
1389 def testCacheServFailTTL ( self
):
1395 name
= 'servfail.failure.cache.tests.powerdns.com.'
1396 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
1397 response
= dns
. message
. make_response ( query
)
1398 response
. set_rcode ( dns
. rcode
. SERVFAIL
)
1401 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1402 self
. assertTrue ( receivedQuery
)
1403 self
. assertTrue ( receivedResponse
)
1404 receivedQuery
. id = query
. id
1405 self
. assertEquals ( query
, receivedQuery
)
1406 self
. assertEquals ( response
, receivedResponse
)
1409 # next queries should hit the cache
1410 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1411 self
. assertEquals ( receivedResponse
, response
)
1413 time
. sleep ( self
._ failureCacheTTL
+ 1 )
1415 # we should not have cached for longer than failure cache
1416 # so it should be a miss
1417 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1418 self
. assertTrue ( receivedQuery
)
1419 self
. assertTrue ( receivedResponse
)
1420 receivedQuery
. id = query
. id
1421 self
. assertEquals ( query
, receivedQuery
)
1422 self
. assertEquals ( response
, receivedResponse
)
1426 for key
in self
._ responsesCounter
:
1427 total
+= self
._ responsesCounter
[ key
]
1429 self
. assertEquals ( total
, misses
)
1431 def testCacheRefusedTTL ( self
):
1437 name
= 'refused.failure.cache.tests.powerdns.com.'
1438 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
1439 response
= dns
. message
. make_response ( query
)
1440 response
. set_rcode ( dns
. rcode
. REFUSED
)
1443 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1444 self
. assertTrue ( receivedQuery
)
1445 self
. assertTrue ( receivedResponse
)
1446 receivedQuery
. id = query
. id
1447 self
. assertEquals ( query
, receivedQuery
)
1448 self
. assertEquals ( response
, receivedResponse
)
1451 # next queries should hit the cache
1452 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1453 self
. assertEquals ( receivedResponse
, response
)
1455 time
. sleep ( self
._ failureCacheTTL
+ 1 )
1457 # we should not have cached for longer than failure cache
1458 # so it should be a miss
1459 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1460 self
. assertTrue ( receivedQuery
)
1461 self
. assertTrue ( receivedResponse
)
1462 receivedQuery
. id = query
. id
1463 self
. assertEquals ( query
, receivedQuery
)
1464 self
. assertEquals ( response
, receivedResponse
)
1468 for key
in self
._ responsesCounter
:
1469 total
+= self
._ responsesCounter
[ key
]
1471 self
. assertEquals ( total
, misses
)
1473 def testCacheHeaderOnlyRefusedTTL ( self
):
1475 Cache: Header-Only Refused TTL
1479 name
= 'header-only-refused.failure.cache.tests.powerdns.com.'
1480 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
1481 response
= dns
. message
. make_response ( query
)
1482 response
. set_rcode ( dns
. rcode
. REFUSED
)
1483 response
. question
= []
1486 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1487 self
. assertTrue ( receivedQuery
)
1488 self
. assertTrue ( receivedResponse
)
1489 receivedQuery
. id = query
. id
1490 self
. assertEquals ( query
, receivedQuery
)
1491 self
. assertEquals ( response
, receivedResponse
)
1494 # next queries should hit the cache
1495 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1496 self
. assertEquals ( receivedResponse
, response
)
1498 time
. sleep ( self
._ failureCacheTTL
+ 1 )
1500 # we should not have cached for longer than failure cache
1501 # so it should be a miss
1502 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1503 self
. assertTrue ( receivedQuery
)
1504 self
. assertTrue ( receivedResponse
)
1505 receivedQuery
. id = query
. id
1506 self
. assertEquals ( query
, receivedQuery
)
1507 self
. assertEquals ( response
, receivedResponse
)
1511 for key
in self
._ responsesCounter
:
1512 total
+= self
._ responsesCounter
[ key
]
1514 self
. assertEquals ( total
, misses
)
1516 class TestCachingNegativeTTL ( DNSDistTest
):
1519 _config_params
= [ '_negCacheTTL' , '_testServerPort' ]
1520 _config_template
= """
1521 pc = newPacketCache(1000, {maxTTL=86400, minTTL=0, temporaryFailureTTL=60, staleTTL=60, dontAge=false, numberOfShards=1, deferrableInsertLock=true, maxNegativeTTL= %d })
1522 getPool(""):setCache(pc)
1523 newServer{address="127.0.0.1: %d "}
1526 def testCacheNegativeTTLNXDomain ( self
):
1528 Cache: Negative TTL on NXDOMAIN
1532 name
= 'nxdomain.negativettl.cache.tests.powerdns.com.'
1533 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
1534 response
= dns
. message
. make_response ( query
)
1535 response
. set_rcode ( dns
. rcode
. NXDOMAIN
)
1536 soa
= dns
. rrset
. from_text ( name
,
1540 'ns.' + name
+ ' hostmaster.' + name
+ ' 1 3600 3600 3600 60' )
1541 response
. authority
. append ( soa
)
1544 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1545 self
. assertTrue ( receivedQuery
)
1546 self
. assertTrue ( receivedResponse
)
1547 receivedQuery
. id = query
. id
1548 self
. assertEquals ( query
, receivedQuery
)
1549 self
. assertEquals ( response
, receivedResponse
)
1552 # next queries should hit the cache
1553 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1554 self
. assertEquals ( receivedResponse
, response
)
1556 time
. sleep ( self
._ negCacheTTL
+ 1 )
1558 # we should not have cached for longer than the negative TTL
1559 # so it should be a miss
1560 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1561 self
. assertTrue ( receivedQuery
)
1562 self
. assertTrue ( receivedResponse
)
1563 receivedQuery
. id = query
. id
1564 self
. assertEquals ( query
, receivedQuery
)
1565 self
. assertEquals ( response
, receivedResponse
)
1569 for key
in self
._ responsesCounter
:
1570 total
+= self
._ responsesCounter
[ key
]
1572 self
. assertEquals ( total
, misses
)
1574 def testCacheNegativeTTLNoData ( self
):
1576 Cache: Negative TTL on NoData
1580 name
= 'nodata.negativettl.cache.tests.powerdns.com.'
1581 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
1582 response
= dns
. message
. make_response ( query
)
1583 response
. set_rcode ( dns
. rcode
. NOERROR
)
1584 soa
= dns
. rrset
. from_text ( name
,
1588 'ns.' + name
+ ' hostmaster.' + name
+ ' 1 3600 3600 3600 60' )
1589 response
. authority
. append ( soa
)
1592 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1593 self
. assertTrue ( receivedQuery
)
1594 self
. assertTrue ( receivedResponse
)
1595 receivedQuery
. id = query
. id
1596 self
. assertEquals ( query
, receivedQuery
)
1597 self
. assertEquals ( response
, receivedResponse
)
1600 # next queries should hit the cache
1601 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1602 self
. assertEquals ( receivedResponse
, response
)
1604 time
. sleep ( self
._ negCacheTTL
+ 1 )
1606 # we should not have cached for longer than the negativel TTL
1607 # so it should be a miss
1608 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1609 self
. assertTrue ( receivedQuery
)
1610 self
. assertTrue ( receivedResponse
)
1611 receivedQuery
. id = query
. id
1612 self
. assertEquals ( query
, receivedQuery
)
1613 self
. assertEquals ( response
, receivedResponse
)
1617 for key
in self
._ responsesCounter
:
1618 total
+= self
._ responsesCounter
[ key
]
1620 self
. assertEquals ( total
, misses
)
1622 class TestCachingDontAge ( DNSDistTest
):
1624 _config_template
= """
1625 pc = newPacketCache(100, {maxTTL=86400, minTTL=0, temporaryFailureTTL=60, staleTTL=60, dontAge=true})
1626 getPool(""):setCache(pc)
1627 newServer{address="127.0.0.1: %d "}
1629 def testCacheDoesntDecreaseTTL ( self
):
1631 Cache: Cache doesn't decrease TTL with 'don't age' set
1633 dnsdist is configured to cache entries but without aging the TTL,
1634 we are sending one request (cache miss) and verify that the cache
1635 hits don't have a decreasing TTL.
1639 name
= 'cachedoesntdecreasettl.cache-dont-age.tests.powerdns.com.'
1640 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
1641 response
= dns
. message
. make_response ( query
)
1642 rrset
= dns
. rrset
. from_text ( name
,
1647 response
. answer
. append ( rrset
)
1649 # first query to fill the cache
1650 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1651 self
. assertTrue ( receivedQuery
)
1652 self
. assertTrue ( receivedResponse
)
1653 receivedQuery
. id = query
. id
1654 self
. assertEquals ( query
, receivedQuery
)
1655 self
. assertEquals ( receivedResponse
, response
)
1658 # next queries should hit the cache
1659 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1660 self
. assertEquals ( receivedResponse
, response
)
1661 for an
in receivedResponse
. answer
:
1662 self
. assertTrue ( an
. ttl
== ttl
)
1664 # now we wait a bit for the TTL to decrease
1667 # next queries should hit the cache
1668 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1669 self
. assertEquals ( receivedResponse
, response
)
1670 for an
in receivedResponse
. answer
:
1671 self
. assertTrue ( an
. ttl
== ttl
)
1674 for key
in self
._ responsesCounter
:
1675 total
+= self
._ responsesCounter
[ key
]
1677 self
. assertEquals ( total
, misses
)
1679 class TestCachingECSWithoutPoolECS ( DNSDistTest
):
1681 _consoleKey
= DNSDistTest
. generateConsoleKey ()
1682 _consoleKeyB64
= base64
. b64encode ( _consoleKey
). decode ( 'ascii' )
1683 _config_params
= [ '_consoleKeyB64' , '_consolePort' , '_testServerPort' ]
1684 _config_template
= """
1685 pc = newPacketCache(100, {maxTTL=86400, minTTL=1})
1686 getPool(""):setCache(pc)
1688 controlSocket("127.0.0.1: %d ")
1689 newServer{address="127.0.0.1: %d ", useClientSubnet=true}
1692 def testCached ( self
):
1694 Cache: Cached entry with ECS is a miss when no backend are available
1697 name
= 'cached.cache-ecs-without-pool-ecs.tests.powerdns.com.'
1698 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
1699 response
= dns
. message
. make_response ( query
)
1700 rrset
= dns
. rrset
. from_text ( name
,
1705 response
. answer
. append ( rrset
)
1707 # first query to fill the cache
1708 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
1709 sender
= getattr ( self
, method
)
1710 ( receivedQuery
, receivedResponse
) = sender ( query
, response
)
1711 self
. assertTrue ( receivedQuery
)
1712 self
. assertTrue ( receivedResponse
)
1713 receivedQuery
. id = query
. id
1714 self
. assertEquals ( query
, receivedQuery
)
1715 self
. assertEquals ( receivedResponse
, response
)
1717 # next queries should hit the cache
1718 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
1719 sender
= getattr ( self
, method
)
1720 ( _
, receivedResponse
) = sender ( query
, response
= None , useQueue
= False )
1721 self
. assertEquals ( receivedResponse
, response
)
1723 # we mark the backend as down
1724 self
. sendConsoleCommand ( "getServer(0):setDown()" )
1726 # we should NOT get a cached entry since it has ECS and we haven't asked the pool
1727 # to add ECS when no backend is up
1728 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
1729 sender
= getattr ( self
, method
)
1730 ( _
, receivedResponse
) = sender ( query
, response
= None , useQueue
= False )
1731 self
. assertEquals ( receivedResponse
, None )
1733 class TestCachingECSWithPoolECS ( DNSDistTest
):
1735 _consoleKey
= DNSDistTest
. generateConsoleKey ()
1736 _consoleKeyB64
= base64
. b64encode ( _consoleKey
). decode ( 'ascii' )
1737 _config_params
= [ '_consoleKeyB64' , '_consolePort' , '_testServerPort' ]
1738 _config_template
= """
1739 pc = newPacketCache(100, {maxTTL=86400, minTTL=1})
1740 getPool(""):setCache(pc)
1741 getPool(""):setECS(true)
1743 controlSocket("127.0.0.1: %d ")
1744 newServer{address="127.0.0.1: %d ", useClientSubnet=true}
1747 def testCached ( self
):
1749 Cache: Cached entry with ECS is a hit when no backend are available
1752 name
= 'cached.cache-ecs-with-pool-ecs.tests.powerdns.com.'
1753 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
1754 response
= dns
. message
. make_response ( query
)
1755 rrset
= dns
. rrset
. from_text ( name
,
1760 response
. answer
. append ( rrset
)
1762 # first query to fill the cache
1763 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
1764 sender
= getattr ( self
, method
)
1765 ( receivedQuery
, receivedResponse
) = sender ( query
, response
)
1766 self
. assertTrue ( receivedQuery
)
1767 self
. assertTrue ( receivedResponse
)
1768 receivedQuery
. id = query
. id
1769 self
. assertEquals ( query
, receivedQuery
)
1770 self
. assertEquals ( receivedResponse
, response
)
1772 # next queries should hit the cache
1773 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
1774 sender
= getattr ( self
, method
)
1775 ( _
, receivedResponse
) = sender ( query
, response
= None , useQueue
= False )
1776 self
. assertEquals ( receivedResponse
, response
)
1778 # we mark the backend as down
1779 self
. sendConsoleCommand ( "getServer(0):setDown()" )
1781 # we should STILL get a cached entry since it has ECS and we have asked the pool
1782 # to add ECS when no backend is up
1783 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
1784 sender
= getattr ( self
, method
)
1785 ( _
, receivedResponse
) = sender ( query
, response
= None , useQueue
= False )
1786 self
. assertEquals ( receivedResponse
, response
)
1788 class TestCachingCollisionNoECSParsing ( DNSDistTest
):
1790 _config_template
= """
1791 pc = newPacketCache(100, {maxTTL=86400, minTTL=1})
1792 getPool(""):setCache(pc)
1793 newServer{address="127.0.0.1: %d "}
1796 def testCacheCollisionNoECSParsing ( self
):
1798 Cache: Collision with no ECS parsing
1800 name
= 'collision-no-ecs-parsing.cache.tests.powerdns.com.'
1801 ecso
= clientsubnetoption
. ClientSubnetOption ( '10.0.188.3' , 32 )
1802 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' , use_edns
= True , options
=[ ecso
], payload
= 512 )
1803 query
. flags
= dns
. flags
. RD
1804 response
= dns
. message
. make_response ( query
)
1805 rrset
= dns
. rrset
. from_text ( name
,
1810 response
. answer
. append ( rrset
)
1812 # first query should to fill the cache
1813 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1814 self
. assertTrue ( receivedQuery
)
1815 self
. assertTrue ( receivedResponse
)
1816 receivedQuery
. id = query
. id
1817 self
. assertEquals ( query
, receivedQuery
)
1818 self
. assertEquals ( receivedResponse
, response
)
1820 # second query will hash to the same key, triggering a collision which
1821 # will not be detected because the qname, qtype, qclass and flags will
1822 # match and EDNS Client Subnet parsing has not been enabled
1823 ecso2
= clientsubnetoption
. ClientSubnetOption ( '10.0.192.138' , 32 )
1824 query2
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' , use_edns
= True , options
=[ ecso2
], payload
= 512 )
1825 query2
. flags
= dns
. flags
. RD
1826 ( _
, receivedResponse
) = self
. sendUDPQuery ( query2
, response
= None , useQueue
= False )
1827 receivedResponse
. id = response
. id
1828 self
. assertEquals ( receivedResponse
, response
)
1830 class TestCachingCollisionWithECSParsing ( DNSDistTest
):
1832 _config_template
= """
1833 pc = newPacketCache(100, {maxTTL=86400, minTTL=1, temporaryFailureTTL=60, staleTTL=60, dontAge=false, numberOfShards=1, deferrableInsertLock=true, maxNegativeTTL=3600, parseECS=true})
1834 getPool(""):setCache(pc)
1835 newServer{address="127.0.0.1: %d "}
1838 def testCacheCollisionWithECSParsing ( self
):
1840 Cache: Collision with ECS parsing
1842 name
= 'collision-with-ecs-parsing.cache.tests.powerdns.com.'
1843 ecso
= clientsubnetoption
. ClientSubnetOption ( '10.0.115.61' , 32 )
1844 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' , use_edns
= True , options
=[ ecso
], payload
= 512 )
1845 query
. flags
= dns
. flags
. RD
1846 response
= dns
. message
. make_response ( query
)
1847 rrset
= dns
. rrset
. from_text ( name
,
1852 response
. answer
. append ( rrset
)
1854 # first query should to fill the cache
1855 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1856 self
. assertTrue ( receivedQuery
)
1857 self
. assertTrue ( receivedResponse
)
1858 receivedQuery
. id = query
. id
1859 self
. assertEquals ( query
, receivedQuery
)
1860 self
. assertEquals ( receivedResponse
, response
)
1862 # second query will hash to the same key, triggering a collision which
1863 # _will_ be detected this time because the qname, qtype, qclass and flags will
1864 # match but EDNS Client Subnet parsing is now enabled and will detect the issue
1865 ecso2
= clientsubnetoption
. ClientSubnetOption ( '10.0.143.21' , 32 )
1866 query2
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' , use_edns
= True , options
=[ ecso2
], payload
= 512 )
1867 query2
. flags
= dns
. flags
. RD
1868 response2
= dns
. message
. make_response ( query2
)
1869 rrset
= dns
. rrset
. from_text ( name
,
1874 response2
. answer
. append ( rrset
)
1875 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query2
, response2
)
1876 self
. assertEquals ( receivedResponse
, response2
)
1878 class TestCachingScopeZero ( DNSDistTest
):
1880 _config_template
= """
1881 -- Be careful to enable ECS parsing in the packet cache, otherwise scope zero is disabled
1882 pc = newPacketCache(100, {maxTTL=86400, minTTL=1, temporaryFailureTTL=60, staleTTL=60, dontAge=false, numberOfShards=1, deferrableInsertLock=true, maxNegativeTTL=3600, parseECS=true})
1883 getPool(""):setCache(pc)
1884 newServer{address="127.0.0.1: %d ", useClientSubnet=true}
1885 -- to simulate a second client coming from a different IP address,
1886 -- we will force the ECS value added to the query if RD is set (note that we need
1887 -- to unset it using rules before the first cache lookup)
1888 addAction(RDRule(), SetECSAction("192.0.2.1/32"))
1889 addAction(RDRule(), NoRecurseAction())
1892 def testScopeZero ( self
):
1894 Cache: Test the scope-zero feature, backend returns a scope of zero
1897 name
= 'scope-zero.cache.tests.powerdns.com.'
1898 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
1899 query
. flags
&= ~dns
. flags
. RD
1900 ecso
= clientsubnetoption
. ClientSubnetOption ( '127.0.0.0' , 24 )
1901 expectedQuery
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' , use_edns
= True , options
=[ ecso
], payload
= 512 )
1902 expectedQuery
. flags
&= ~dns
. flags
. RD
1903 ecsoResponse
= clientsubnetoption
. ClientSubnetOption ( '127.0.0.1' , 24 , 0 )
1904 expectedResponse
= dns
. message
. make_response ( query
)
1905 scopedResponse
= dns
. message
. make_response ( query
)
1906 scopedResponse
. use_edns ( edns
= True , payload
= 4096 , options
=[ ecsoResponse
])
1907 rrset
= dns
. rrset
. from_text ( name
,
1912 scopedResponse
. answer
. append ( rrset
)
1913 expectedResponse
. answer
. append ( rrset
)
1915 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
1916 sender
= getattr ( self
, method
)
1917 ( receivedQuery
, receivedResponse
) = sender ( query
, scopedResponse
)
1918 receivedQuery
. id = expectedQuery
. id
1919 self
. checkMessageEDNSWithECS ( expectedQuery
, receivedQuery
)
1920 self
. checkMessageNoEDNS ( receivedResponse
, expectedResponse
)
1922 # next query should hit the cache, nothing special about that
1923 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
1924 sender
= getattr ( self
, method
)
1925 ( _
, receivedResponse
) = sender ( query
, response
= None , useQueue
= False )
1926 self
. checkMessageNoEDNS ( receivedResponse
, expectedResponse
)
1928 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
1929 query
. flags
&= dns
. flags
. RD
1930 # next query FROM A DIFFERENT CLIENT since RD is now set should STILL hit the cache
1931 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
1932 sender
= getattr ( self
, method
)
1933 ( _
, receivedResponse
) = sender ( query
, response
= None , useQueue
= False )
1934 receivedResponse
. id = expectedResponse
. id
1935 self
. checkMessageNoEDNS ( receivedResponse
, expectedResponse
)
1937 name
= 'scope-zero-with-ecs.cache.tests.powerdns.com.'
1938 ecso
= clientsubnetoption
. ClientSubnetOption ( '127.0.0.1' , 24 )
1939 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' , use_edns
= True , options
=[ ecso
], payload
= 512 )
1940 query
. flags
&= ~dns
. flags
. RD
1941 expectedQuery
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' , use_edns
= True , options
=[ ecso
], payload
= 512 )
1942 expectedQuery
. flags
&= ~dns
. flags
. RD
1943 expectedResponse
= dns
. message
. make_response ( query
)
1944 expectedResponse
. use_edns ( edns
= True , payload
= 4096 , options
=[ ecsoResponse
])
1945 expectedResponse
. answer
. append ( rrset
)
1946 scopedResponse
= dns
. message
. make_response ( query
)
1947 scopedResponse
. use_edns ( edns
= True , payload
= 4096 , options
=[ ecsoResponse
])
1948 scopedResponse
. answer
. append ( rrset
)
1949 # this query has ECS, it should NOT be able to use the scope-zero cached entry since the hash will be
1951 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
1952 sender
= getattr ( self
, method
)
1953 ( receivedQuery
, receivedResponse
) = sender ( query
, scopedResponse
)
1954 receivedQuery
. id = expectedQuery
. id
1955 self
. checkMessageEDNSWithECS ( expectedQuery
, receivedQuery
)
1956 self
. checkMessageEDNSWithECS ( receivedResponse
, expectedResponse
)
1958 # it should still have been cached, though, so the next query should be a hit
1959 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
1960 sender
= getattr ( self
, method
)
1961 ( _
, receivedResponse
) = sender ( query
, response
= None , useQueue
= False )
1962 self
. checkMessageEDNSWithECS ( receivedResponse
, expectedResponse
)
1964 def testScopeNotZero ( self
):
1966 Cache: Test the scope-zero feature, backend returns a scope of non-zero
1969 name
= 'scope-not-zero.cache.tests.powerdns.com.'
1970 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
1971 query
. flags
&= ~dns
. flags
. RD
1972 ecso
= clientsubnetoption
. ClientSubnetOption ( '127.0.0.0' , 24 )
1973 expectedQuery
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' , use_edns
= True , options
=[ ecso
], payload
= 512 )
1974 expectedQuery
. flags
&= ~dns
. flags
. RD
1975 ecso2
= clientsubnetoption
. ClientSubnetOption ( '192.0.2.1' , 32 )
1976 expectedQuery2
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' , use_edns
= True , options
=[ ecso2
], payload
= 512 )
1977 expectedQuery2
. flags
&= ~dns
. flags
. RD
1978 ecsoResponse
= clientsubnetoption
. ClientSubnetOption ( '127.0.0.1' , 24 , 24 )
1979 ecsoResponse2
= clientsubnetoption
. ClientSubnetOption ( '192.0.2.1' , 32 , 24 )
1980 rrset
= dns
. rrset
. from_text ( name
,
1985 expectedResponse
= dns
. message
. make_response ( query
)
1986 expectedResponse
. answer
. append ( rrset
)
1987 scopedResponse
= dns
. message
. make_response ( query
)
1988 scopedResponse
. use_edns ( edns
= True , payload
= 4096 , options
=[ ecsoResponse
])
1989 scopedResponse
. answer
. append ( rrset
)
1990 scopedResponse2
= dns
. message
. make_response ( query
)
1991 scopedResponse2
. use_edns ( edns
= True , payload
= 4096 , options
=[ ecsoResponse2
])
1992 scopedResponse2
. answer
. append ( rrset
)
1994 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
1995 sender
= getattr ( self
, method
)
1996 ( receivedQuery
, receivedResponse
) = sender ( query
, scopedResponse
)
1997 receivedQuery
. id = expectedQuery
. id
1998 self
. checkMessageEDNSWithECS ( expectedQuery
, receivedQuery
)
1999 self
. checkMessageNoEDNS ( receivedResponse
, expectedResponse
)
2001 # next query should hit the cache, nothing special about that
2002 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
2003 sender
= getattr ( self
, method
)
2004 ( _
, receivedResponse
) = sender ( query
, response
= None , useQueue
= False )
2005 self
. checkMessageNoEDNS ( receivedResponse
, expectedResponse
)
2007 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
2008 query
. flags
&= dns
. flags
. RD
2009 expectedResponse
= dns
. message
. make_response ( query
)
2010 expectedResponse
. answer
. append ( rrset
)
2011 # next query FROM A DIFFERENT CLIENT since RD is now set should NOT hit the cache
2012 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
2013 sender
= getattr ( self
, method
)
2014 ( receivedQuery
, receivedResponse
) = sender ( query
, scopedResponse2
)
2015 receivedQuery
. id = expectedQuery2
. id
2016 self
. checkMessageEDNSWithECS ( expectedQuery2
, receivedQuery
)
2017 self
. checkMessageNoEDNS ( receivedResponse
, expectedResponse
)
2019 def testNoECS ( self
):
2021 Cache: Test the scope-zero feature, backend returns no ECS at all
2024 name
= 'scope-zero-no-ecs.cache.tests.powerdns.com.'
2025 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
2026 query
. flags
&= ~dns
. flags
. RD
2027 ecso
= clientsubnetoption
. ClientSubnetOption ( '127.0.0.0' , 24 )
2028 expectedQuery
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' , use_edns
= True , options
=[ ecso
], payload
= 512 )
2029 expectedQuery
. flags
&= ~dns
. flags
. RD
2030 ecso2
= clientsubnetoption
. ClientSubnetOption ( '192.0.2.1' , 32 )
2031 expectedQuery2
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' , use_edns
= True , options
=[ ecso2
], payload
= 512 )
2032 expectedQuery2
. flags
&= ~dns
. flags
. RD
2033 rrset
= dns
. rrset
. from_text ( name
,
2038 response
= dns
. message
. make_response ( query
)
2039 response
. answer
. append ( rrset
)
2041 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
2042 sender
= getattr ( self
, method
)
2043 ( receivedQuery
, receivedResponse
) = sender ( query
, response
)
2044 receivedQuery
. id = expectedQuery
. id
2045 self
. checkMessageEDNSWithECS ( expectedQuery
, receivedQuery
)
2046 self
. checkMessageNoEDNS ( receivedResponse
, response
)
2048 # next query should hit the cache, nothing special about that
2049 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
2050 sender
= getattr ( self
, method
)
2051 ( _
, receivedResponse
) = sender ( query
, response
= None , useQueue
= False )
2052 self
. checkMessageNoEDNS ( receivedResponse
, response
)
2054 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
2055 query
. flags
&= dns
. flags
. RD
2056 response
= dns
. message
. make_response ( query
)
2057 response
. answer
. append ( rrset
)
2058 # next query FROM A DIFFERENT CLIENT since RD is now set should NOT hit the cache
2059 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
2060 sender
= getattr ( self
, method
)
2061 ( receivedQuery
, receivedResponse
) = sender ( query
, response
)
2062 receivedQuery
. id = expectedQuery2
. id
2063 self
. checkMessageEDNSWithECS ( expectedQuery2
, receivedQuery
)
2064 self
. checkMessageNoEDNS ( receivedResponse
, response
)
2066 class TestCachingScopeZeroButNoSubnetcheck ( DNSDistTest
):
2068 _config_template
= """
2069 -- We disable ECS parsing in the packet cache, meaning scope zero is disabled
2070 pc = newPacketCache(100, {maxTTL=86400, minTTL=1, temporaryFailureTTL=60, staleTTL=60, dontAge=false, numberOfShards=1, deferrableInsertLock=true, maxNegativeTTL=3600, parseECS=false})
2071 getPool(""):setCache(pc)
2072 newServer{address="127.0.0.1: %d ", useClientSubnet=true}
2073 -- to simulate a second client coming from a different IP address,
2074 -- we will force the ECS value added to the query if RD is set (note that we need
2075 -- to unset it using rules before the first cache lookup)
2076 addAction(RDRule(), SetECSAction("192.0.2.1/32"))
2077 addAction(RDRule(), NoRecurseAction())
2080 def testScopeZero ( self
):
2082 Cache: Test that the scope-zero feature is disabled when ECS parsing is not enabled in the cache
2085 name
= 'scope-zero-no-subnet.cache.tests.powerdns.com.'
2086 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
2087 query
. flags
&= ~dns
. flags
. RD
2088 ecso
= clientsubnetoption
. ClientSubnetOption ( '127.0.0.0' , 24 )
2089 expectedQuery
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' , use_edns
= True , options
=[ ecso
], payload
= 512 )
2090 expectedQuery
. flags
&= ~dns
. flags
. RD
2091 ecso2
= clientsubnetoption
. ClientSubnetOption ( '192.0.2.1' , 32 )
2092 expectedQuery2
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' , use_edns
= True , options
=[ ecso2
], payload
= 512 )
2093 expectedQuery2
. flags
&= ~dns
. flags
. RD
2094 ecsoResponse
= clientsubnetoption
. ClientSubnetOption ( '127.0.0.1' , 24 , 0 )
2095 expectedResponse
= dns
. message
. make_response ( query
)
2096 scopedResponse
= dns
. message
. make_response ( query
)
2097 scopedResponse
. use_edns ( edns
= True , payload
= 4096 , options
=[ ecsoResponse
])
2098 rrset
= dns
. rrset
. from_text ( name
,
2103 scopedResponse
. answer
. append ( rrset
)
2104 expectedResponse
. answer
. append ( rrset
)
2106 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
2107 sender
= getattr ( self
, method
)
2108 ( receivedQuery
, receivedResponse
) = sender ( query
, scopedResponse
)
2109 receivedQuery
. id = expectedQuery
. id
2110 self
. checkMessageEDNSWithECS ( expectedQuery
, receivedQuery
)
2111 self
. checkMessageNoEDNS ( receivedResponse
, expectedResponse
)
2113 # next query should hit the cache, nothing special about that
2114 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
2115 sender
= getattr ( self
, method
)
2116 ( _
, receivedResponse
) = sender ( query
, response
= None , useQueue
= False )
2117 self
. checkMessageNoEDNS ( receivedResponse
, expectedResponse
)
2119 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
2120 query
. flags
&= dns
. flags
. RD
2121 response
= dns
. message
. make_response ( query
)
2122 response
. answer
. append ( rrset
)
2123 # next query FROM A DIFFERENT CLIENT since RD is now set should NOT hit the cache
2124 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
2125 sender
= getattr ( self
, method
)
2126 ( receivedQuery
, receivedResponse
) = sender ( query
, response
)
2127 receivedQuery
. id = expectedQuery2
. id
2128 self
. checkMessageEDNSWithECS ( expectedQuery2
, receivedQuery
)
2129 self
. checkMessageNoEDNS ( receivedResponse
, response
)