]>
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 -- maxTTL=86400, minTTL=1
12 pc = newPacketCache(100, 86400, 1)
13 getPool(""):setCache(pc)
14 addAction(makeRule("nocache.cache.tests.powerdns.com."), SkipCacheAction())
15 function skipViaLua(dq)
17 return DNSAction.None, ""
19 addAction("nocachevialua.cache.tests.powerdns.com.", LuaAction(skipViaLua))
20 newServer{address="127.0.0.1: %d "}
25 Cache: Served from cache
27 dnsdist is configured to cache entries, we are sending several
28 identical requests and checking that the backend only receive
32 name
= 'cached.cache.tests.powerdns.com.'
33 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
34 response
= dns
. message
. make_response ( query
)
35 rrset
= dns
. rrset
. from_text ( name
,
40 response
. answer
. append ( rrset
)
42 # first query to fill the cache
43 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
44 self
. assertTrue ( receivedQuery
)
45 self
. assertTrue ( receivedResponse
)
46 receivedQuery
. id = query
. id
47 self
. assertEquals ( query
, receivedQuery
)
48 self
. assertEquals ( receivedResponse
, response
)
50 for _
in range ( numberOfQueries
):
51 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
52 self
. assertEquals ( receivedResponse
, response
)
55 for key
in self
._ responsesCounter
:
56 total
+= self
._ responsesCounter
[ key
]
57 TestCaching
._ responsesCounter
[ key
] = 0
59 self
. assertEquals ( total
, 1 )
61 # TCP should not be cached
62 # first query to fill the cache
63 ( receivedQuery
, receivedResponse
) = self
. sendTCPQuery ( query
, response
)
64 self
. assertTrue ( receivedQuery
)
65 self
. assertTrue ( receivedResponse
)
66 receivedQuery
. id = query
. id
67 self
. assertEquals ( query
, receivedQuery
)
68 self
. assertEquals ( receivedResponse
, response
)
70 for _
in range ( numberOfQueries
):
71 ( _
, receivedResponse
) = self
. sendTCPQuery ( query
, response
= None , useQueue
= False )
72 self
. assertEquals ( receivedResponse
, response
)
75 for key
in self
._ responsesCounter
:
76 total
+= self
._ responsesCounter
[ key
]
77 TestCaching
._ responsesCounter
[ key
] = 0
79 self
. assertEquals ( total
, 1 )
81 def testDOCached ( self
):
83 Cache: Served from cache, query has DO bit set
85 dnsdist is configured to cache entries, we are sending several
86 identical requests and checking that the backend only receive
90 name
= 'cached-do.cache.tests.powerdns.com.'
91 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' , use_edns
= True , payload
= 4096 , want_dnssec
= True )
92 response
= dns
. message
. make_response ( query
)
93 rrset
= dns
. rrset
. from_text ( name
,
98 response
. answer
. append ( rrset
)
100 # first query to fill the cache
101 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
102 self
. assertTrue ( receivedQuery
)
103 self
. assertTrue ( receivedResponse
)
104 receivedQuery
. id = query
. id
105 self
. assertEquals ( query
, receivedQuery
)
106 self
. assertEquals ( receivedResponse
, response
)
108 for _
in range ( numberOfQueries
):
109 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
110 self
. assertEquals ( receivedResponse
, response
)
113 for key
in self
._ responsesCounter
:
114 total
+= self
._ responsesCounter
[ key
]
115 TestCaching
._ responsesCounter
[ key
] = 0
117 self
. assertEquals ( total
, 1 )
119 # TCP should not be cached
120 # first query to fill the cache
121 ( receivedQuery
, receivedResponse
) = self
. sendTCPQuery ( query
, response
)
122 self
. assertTrue ( receivedQuery
)
123 self
. assertTrue ( receivedResponse
)
124 receivedQuery
. id = query
. id
125 self
. assertEquals ( query
, receivedQuery
)
126 self
. assertEquals ( receivedResponse
, response
)
128 for _
in range ( numberOfQueries
):
129 ( _
, receivedResponse
) = self
. sendTCPQuery ( query
, response
= None , useQueue
= False )
130 self
. assertEquals ( receivedResponse
, response
)
133 for key
in self
._ responsesCounter
:
134 total
+= self
._ responsesCounter
[ key
]
135 TestCaching
._ responsesCounter
[ key
] = 0
137 self
. assertEquals ( total
, 1 )
139 def testSkipCache ( self
):
141 Cache: SkipCacheAction
143 dnsdist is configured to not cache entries for nocache.cache.tests.powerdns.com.
144 we are sending several requests and checking that the backend get them all.
146 name
= 'nocache.cache.tests.powerdns.com.'
148 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
149 response
= dns
. message
. make_response ( query
)
150 rrset
= dns
. rrset
. from_text ( name
,
155 response
. answer
. append ( rrset
)
157 for _
in range ( numberOfQueries
):
158 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
159 self
. assertTrue ( receivedQuery
)
160 self
. assertTrue ( receivedResponse
)
161 receivedQuery
. id = query
. id
162 self
. assertEquals ( query
, receivedQuery
)
163 self
. assertEquals ( receivedResponse
, response
)
165 ( receivedQuery
, receivedResponse
) = self
. sendTCPQuery ( query
, response
)
166 self
. assertTrue ( receivedQuery
)
167 self
. assertTrue ( receivedResponse
)
168 receivedQuery
. id = query
. id
169 self
. assertEquals ( query
, receivedQuery
)
170 self
. assertEquals ( receivedResponse
, response
)
172 for key
in self
._ responsesCounter
:
173 value
= self
._ responsesCounter
[ key
]
174 self
. assertEquals ( value
, numberOfQueries
)
176 def testSkipCacheViaLua ( self
):
178 Cache: SkipCache via Lua
180 dnsdist is configured to not cache entries for nocachevialua.cache.tests.powerdns.com.
181 we are sending several requests and checking that the backend get them all.
183 name
= 'nocachevialua.cache.tests.powerdns.com.'
185 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
186 response
= dns
. message
. make_response ( query
)
187 rrset
= dns
. rrset
. from_text ( name
,
192 response
. answer
. append ( rrset
)
194 for _
in range ( numberOfQueries
):
195 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
196 self
. assertTrue ( receivedQuery
)
197 self
. assertTrue ( receivedResponse
)
198 receivedQuery
. id = query
. id
199 self
. assertEquals ( query
, receivedQuery
)
200 self
. assertEquals ( receivedResponse
, response
)
202 ( receivedQuery
, receivedResponse
) = self
. sendTCPQuery ( query
, response
)
203 self
. assertTrue ( receivedQuery
)
204 self
. assertTrue ( receivedResponse
)
205 receivedQuery
. id = query
. id
206 self
. assertEquals ( query
, receivedQuery
)
207 self
. assertEquals ( receivedResponse
, response
)
209 for key
in self
._ responsesCounter
:
210 value
= self
._ responsesCounter
[ key
]
211 self
. assertEquals ( value
, numberOfQueries
)
213 def testCacheExpiration ( self
):
215 Cache: Cache expiration
217 dnsdist is configured to cache entries, we are sending one request
218 (cache miss) with a very short TTL, checking that the next requests
219 are cached. Then we wait for the TTL to expire, check that the
220 next request is a miss but the following one a hit.
224 name
= 'cacheexpiration.cache.tests.powerdns.com.'
225 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
226 response
= dns
. message
. make_response ( query
)
227 rrset
= dns
. rrset
. from_text ( name
,
232 response
. answer
. append ( rrset
)
234 # first query to fill the cache
235 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
236 self
. assertTrue ( receivedQuery
)
237 self
. assertTrue ( receivedResponse
)
238 receivedQuery
. id = query
. id
239 self
. assertEquals ( query
, receivedQuery
)
240 self
. assertEquals ( receivedResponse
, response
)
243 # next queries should hit the cache
244 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
245 self
. assertEquals ( receivedResponse
, response
)
247 # now we wait a bit for the cache entry to expire
250 # next query should be a miss, fill the cache again
251 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
252 self
. assertTrue ( receivedQuery
)
253 self
. assertTrue ( receivedResponse
)
254 receivedQuery
. id = query
. id
255 self
. assertEquals ( query
, receivedQuery
)
256 self
. assertEquals ( receivedResponse
, response
)
259 # following queries should hit the cache again
260 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
261 self
. assertEquals ( receivedResponse
, response
)
264 for key
in self
._ responsesCounter
:
265 total
+= self
._ responsesCounter
[ key
]
267 self
. assertEquals ( total
, misses
)
269 def testCacheExpirationDifferentSets ( self
):
271 Cache: Cache expiration with different sets
273 dnsdist is configured to cache entries, we are sending one request
274 (cache miss) whose response has a long and a very short TTL,
275 checking that the next requests are cached. Then we wait for the
276 short TTL to expire, check that the
277 next request is a miss but the following one a hit.
281 name
= 'cacheexpirationdifferentsets.cache.tests.powerdns.com.'
282 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
283 response
= dns
. message
. make_response ( query
)
284 rrset
= dns
. rrset
. from_text ( name
,
288 'cname.cacheexpirationdifferentsets.cache.tests.powerdns.com.' )
289 response
. answer
. append ( rrset
)
290 rrset
= dns
. rrset
. from_text ( 'cname.cacheexpirationdifferentsets.cache.tests.powerdns.com.' ,
295 response
. additional
. append ( rrset
)
297 # first query to fill the cache
298 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
299 self
. assertTrue ( receivedQuery
)
300 self
. assertTrue ( receivedResponse
)
301 receivedQuery
. id = query
. id
302 self
. assertEquals ( query
, receivedQuery
)
303 self
. assertEquals ( receivedResponse
, response
)
306 # next queries should hit the cache
307 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
308 self
. assertEquals ( receivedResponse
, response
)
310 # now we wait a bit for the cache entry to expire
313 # next query should be a miss, fill the cache again
314 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
315 self
. assertTrue ( receivedQuery
)
316 self
. assertTrue ( receivedResponse
)
317 receivedQuery
. id = query
. id
318 self
. assertEquals ( query
, receivedQuery
)
319 self
. assertEquals ( receivedResponse
, response
)
322 # following queries should hit the cache again
323 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
324 self
. assertEquals ( receivedResponse
, response
)
327 for key
in self
._ responsesCounter
:
328 total
+= self
._ responsesCounter
[ key
]
330 self
. assertEquals ( total
, misses
)
332 def testCacheDecreaseTTL ( self
):
334 Cache: Cache decreases TTL
336 dnsdist is configured to cache entries, we are sending one request
337 (cache miss) and verify that the cache hits have a decreasing TTL.
341 name
= 'cachedecreasettl.cache.tests.powerdns.com.'
342 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
343 response
= dns
. message
. make_response ( query
)
344 rrset
= dns
. rrset
. from_text ( name
,
349 response
. answer
. append ( rrset
)
351 # first query to fill the cache
352 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
353 self
. assertTrue ( receivedQuery
)
354 self
. assertTrue ( receivedResponse
)
355 receivedQuery
. id = query
. id
356 self
. assertEquals ( query
, receivedQuery
)
357 self
. assertEquals ( receivedResponse
, response
)
360 # next queries should hit the cache
361 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
362 self
. assertEquals ( receivedResponse
, response
)
363 for an
in receivedResponse
. answer
:
364 self
. assertTrue ( an
. ttl
<= ttl
)
366 # now we wait a bit for the TTL to decrease
369 # next queries should hit the cache
370 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
371 self
. assertEquals ( receivedResponse
, response
)
372 for an
in receivedResponse
. answer
:
373 self
. assertTrue ( an
. ttl
< ttl
)
376 for key
in self
._ responsesCounter
:
377 total
+= self
._ responsesCounter
[ key
]
379 self
. assertEquals ( total
, misses
)
381 def testCacheDifferentCase ( self
):
383 Cache: Cache matches different case
385 dnsdist is configured to cache entries, we are sending one request
386 (cache miss) and verify that the same one with a different case
390 name
= 'cachedifferentcase.cache.tests.powerdns.com.'
391 differentCaseName
= 'CacheDifferentCASE.cache.tests.powerdns.com.'
392 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
393 differentCaseQuery
= dns
. message
. make_query ( differentCaseName
, 'AAAA' , 'IN' )
394 response
= dns
. message
. make_response ( query
)
395 differentCaseResponse
= dns
. message
. make_response ( differentCaseQuery
)
396 rrset
= dns
. rrset
. from_text ( name
,
401 response
. answer
. append ( rrset
)
402 differentCaseResponse
. answer
. append ( rrset
)
404 # first query to fill the cache
405 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
406 self
. assertTrue ( receivedQuery
)
407 self
. assertTrue ( receivedResponse
)
408 receivedQuery
. id = query
. id
409 self
. assertEquals ( query
, receivedQuery
)
410 self
. assertEquals ( receivedResponse
, response
)
412 # different case query should still hit the cache
413 ( _
, receivedResponse
) = self
. sendUDPQuery ( differentCaseQuery
, response
= None , useQueue
= False )
414 self
. assertEquals ( receivedResponse
, differentCaseResponse
)
417 class TestTempFailureCacheTTLAction ( DNSDistTest
):
419 _config_template
= """
420 -- maxTTL=86400, minTTL=1
421 pc = newPacketCache(100, 86400, 1)
422 getPool(""):setCache(pc)
423 addAction("servfail.cache.tests.powerdns.com.", TempFailureCacheTTLAction(1))
424 newServer{address="127.0.0.1: %d "}
427 def testTempFailureCacheTTLAction ( self
):
429 Cache: When a TempFailure TTL is set, it should be honored
431 dnsdist is configured to cache packets, plus a specific qname is
432 set up with a lower TempFailure Cache TTL. we are sending one request
433 (cache miss) and verify that the cache is hit for the following query,
434 but the TTL then expires before the larger "good" packetcache TTL.
436 name
= 'servfail.cache.tests.powerdns.com.'
437 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
438 response
= dns
. message
. make_response ( query
)
439 response
. set_rcode ( dns
. rcode
. SERVFAIL
)
441 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
442 self
. assertTrue ( receivedQuery
)
443 self
. assertTrue ( receivedResponse
)
444 receivedQuery
. id = query
. id
445 self
. assertEquals ( query
, receivedQuery
)
446 self
. assertEquals ( receivedResponse
, response
)
448 # next query should hit the cache
449 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
450 self
. assertFalse ( receivedQuery
)
451 self
. assertTrue ( receivedResponse
)
452 self
. assertEquals ( receivedResponse
, response
)
454 # now we wait a bit for the Failure-Cache TTL to expire
457 # next query should NOT hit the cache
458 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
459 self
. assertTrue ( receivedQuery
)
460 self
. assertTrue ( receivedResponse
)
461 self
. assertEquals ( receivedResponse
, response
)
464 class TestCachingWithExistingEDNS ( DNSDistTest
):
466 _config_template
= """
467 -- maxTTL=86400, minTTL=1
468 pc = newPacketCache(5, 86400, 1)
469 getPool(""):setCache(pc)
470 newServer{address="127.0.0.1: %d "}
472 def testCacheWithEDNS ( self
):
474 Cache: Cache should not match different EDNS value
476 dnsdist is configured to cache entries, we are sending one request
477 (cache miss) and verify that the same one with a different EDNS UDP
478 Payload size is not served from the cache.
481 name
= 'cachedifferentedns.cache.tests.powerdns.com.'
482 query
= dns
. message
. make_query ( name
, 'A' , 'IN' , use_edns
= True , payload
= 512 )
483 response
= dns
. message
. make_response ( query
)
484 rrset
= dns
. rrset
. from_text ( name
,
489 response
. answer
. append ( rrset
)
491 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
492 self
. assertTrue ( receivedQuery
)
493 self
. assertTrue ( receivedResponse
)
494 receivedQuery
. id = query
. id
495 self
. assertEquals ( query
, receivedQuery
)
496 self
. assertEquals ( response
, receivedResponse
)
499 query
= dns
. message
. make_query ( name
, 'A' , 'IN' , use_edns
= True , payload
= 4096 )
500 response
= dns
. message
. make_response ( query
)
501 rrset
= dns
. rrset
. from_text ( name
,
506 response
. answer
. append ( rrset
)
508 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
509 self
. assertTrue ( receivedQuery
)
510 self
. assertTrue ( receivedResponse
)
511 receivedQuery
. id = query
. id
512 self
. assertEquals ( query
, receivedQuery
)
513 self
. assertEquals ( response
, receivedResponse
)
517 for key
in self
._ responsesCounter
:
518 total
+= self
._ responsesCounter
[ key
]
520 self
. assertEquals ( total
, misses
)
522 class TestCachingCacheFull ( DNSDistTest
):
524 _config_template
= """
525 -- maxTTL=86400, minTTL=1
526 pc = newPacketCache(1, 86400, 1)
527 getPool(""):setCache(pc)
528 newServer{address="127.0.0.1: %d "}
530 def testCacheFull ( self
):
532 Cache: No new entries are cached when the cache is full
536 name
= 'cachenotfullyet.cache.tests.powerdns.com.'
537 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
538 response
= dns
. message
. make_response ( query
)
539 rrset
= dns
. rrset
. from_text ( name
,
544 response
. answer
. append ( rrset
)
547 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
548 self
. assertTrue ( receivedQuery
)
549 self
. assertTrue ( receivedResponse
)
550 receivedQuery
. id = query
. id
551 self
. assertEquals ( query
, receivedQuery
)
552 self
. assertEquals ( response
, receivedResponse
)
555 # next queries should hit the cache
556 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
557 self
. assertEquals ( receivedResponse
, response
)
559 # ok, now the cache is full, send another query
560 name
= 'cachefull.cache.tests.powerdns.com.'
561 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
562 response
= dns
. message
. make_response ( query
)
563 rrset
= dns
. rrset
. from_text ( name
,
568 response
. answer
. append ( rrset
)
571 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
572 self
. assertTrue ( receivedQuery
)
573 self
. assertTrue ( receivedResponse
)
574 receivedQuery
. id = query
. id
575 self
. assertEquals ( query
, receivedQuery
)
576 self
. assertEquals ( response
, receivedResponse
)
579 # next queries should NOT hit the cache
580 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
581 self
. assertTrue ( receivedQuery
)
582 self
. assertTrue ( receivedResponse
)
583 receivedQuery
. id = query
. id
584 self
. assertEquals ( query
, receivedQuery
)
585 self
. assertEquals ( response
, receivedResponse
)
589 for key
in self
._ responsesCounter
:
590 total
+= self
._ responsesCounter
[ key
]
592 self
. assertEquals ( total
, misses
)
594 class TestCachingNoStale ( DNSDistTest
):
596 _consoleKey
= DNSDistTest
. generateConsoleKey ()
597 _consoleKeyB64
= base64
. b64encode ( _consoleKey
). decode ( 'ascii' )
598 _config_params
= [ '_consoleKeyB64' , '_consolePort' , '_testServerPort' ]
599 _config_template
= """
600 -- maxTTL=86400, minTTL=1
601 pc = newPacketCache(100, 86400, 1)
602 getPool(""):setCache(pc)
604 controlSocket("127.0.0.1: %d ")
605 newServer{address="127.0.0.1: %d "}
607 def testCacheNoStale ( self
):
609 Cache: Cache entry, set backend down, we should not get a stale entry
613 name
= 'nostale.cache.tests.powerdns.com.'
614 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
615 response
= dns
. message
. make_response ( query
)
616 rrset
= dns
. rrset
. from_text ( name
,
621 response
. answer
. append ( rrset
)
624 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
625 self
. assertTrue ( receivedQuery
)
626 self
. assertTrue ( receivedResponse
)
627 receivedQuery
. id = query
. id
628 self
. assertEquals ( query
, receivedQuery
)
629 self
. assertEquals ( response
, receivedResponse
)
631 # next queries should hit the cache
632 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
633 self
. assertEquals ( receivedResponse
, response
)
635 # ok, we mark the backend as down
636 self
. sendConsoleCommand ( "getServer(0):setDown()" )
637 # and we wait for the entry to expire
640 # we should NOT get a cached, stale, entry
641 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
642 self
. assertEquals ( receivedResponse
, None )
645 class TestCachingStale ( DNSDistTest
):
647 _consoleKey
= DNSDistTest
. generateConsoleKey ()
648 _consoleKeyB64
= base64
. b64encode ( _consoleKey
). decode ( 'ascii' )
650 _config_params
= [ '_staleCacheTTL' , '_consoleKeyB64' , '_consolePort' , '_testServerPort' ]
651 _config_template
= """
652 -- maxTTL=86400, minTTL=1, temporaryFailureTTL=0, staleTTL=XX
653 pc = newPacketCache(100, 86400, 1, 0, %d )
654 getPool(""):setCache(pc)
655 setStaleCacheEntriesTTL(600)
657 controlSocket("127.0.0.1: %d ")
658 newServer{address="127.0.0.1: %d "}
660 def testCacheStale ( self
):
662 Cache: Cache entry, set backend down, get stale entry
667 name
= 'stale.cache.tests.powerdns.com.'
668 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
669 response
= dns
. message
. make_response ( query
)
670 rrset
= dns
. rrset
. from_text ( name
,
675 response
. answer
. append ( rrset
)
678 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
679 self
. assertTrue ( receivedQuery
)
680 self
. assertTrue ( receivedResponse
)
681 receivedQuery
. id = query
. id
682 self
. assertEquals ( query
, receivedQuery
)
683 self
. assertEquals ( response
, receivedResponse
)
686 # next queries should hit the cache
687 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
688 self
. assertEquals ( receivedResponse
, response
)
690 # ok, we mark the backend as down
691 self
. sendConsoleCommand ( "getServer(0):setDown()" )
692 # and we wait for the entry to expire
695 # we should get a cached, stale, entry
696 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
697 self
. assertEquals ( receivedResponse
, response
)
698 for an
in receivedResponse
. answer
:
699 self
. assertEquals ( an
. ttl
, self
._ staleCacheTTL
)
702 for key
in self
._ responsesCounter
:
703 total
+= self
._ responsesCounter
[ key
]
705 self
. assertEquals ( total
, misses
)
707 class TestCachingStaleExpunged ( DNSDistTest
):
709 _consoleKey
= DNSDistTest
. generateConsoleKey ()
710 _consoleKeyB64
= base64
. b64encode ( _consoleKey
). decode ( 'ascii' )
712 _config_params
= [ '_staleCacheTTL' , '_consoleKeyB64' , '_consolePort' , '_testServerPort' ]
713 _config_template
= """
714 -- maxTTL=86400, minTTL=1, temporaryFailureTTL=0, staleTTL=XX
715 pc = newPacketCache(100, 86400, 1, 0, %d )
716 getPool(""):setCache(pc)
717 setStaleCacheEntriesTTL(600)
718 -- try to remove all expired entries
719 setCacheCleaningPercentage(100)
720 -- clean the cache every second
721 setCacheCleaningDelay(1)
723 controlSocket("127.0.0.1: %d ")
724 newServer{address="127.0.0.1: %d "}
726 def testCacheStale ( self
):
728 Cache: Cache entry, set backend down, wait for the cache cleaning to run and remove the entry, get no entry
733 name
= 'stale-but-expunged.cache.tests.powerdns.com.'
734 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
735 response
= dns
. message
. make_response ( query
)
736 rrset
= dns
. rrset
. from_text ( name
,
741 response
. answer
. append ( rrset
)
744 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
745 self
. assertTrue ( receivedQuery
)
746 self
. assertTrue ( receivedResponse
)
747 receivedQuery
. id = query
. id
748 self
. assertEquals ( query
, receivedQuery
)
749 self
. assertEquals ( response
, receivedResponse
)
751 self
. assertEquals ( int ( self
. sendConsoleCommand ( "getPool( \"\" ):getCache():getStats()[ \" misses \" ]" ). strip ( " \n " )), misses
+ drops
)
753 # next queries should hit the cache
754 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
755 self
. assertEquals ( receivedResponse
, response
)
756 # the cache should have one entry
757 self
. assertEquals ( int ( self
. sendConsoleCommand ( "getPool( \"\" ):getCache():getStats()[ \" entries \" ]" ). strip ( " \n " )), 1 )
758 self
. assertEquals ( int ( self
. sendConsoleCommand ( "getPool( \"\" ):getCache():getStats()[ \" hits \" ]" ). strip ( " \n " )), 1 )
760 # ok, we mark the backend as down
761 self
. sendConsoleCommand ( "getServer(0):setDown()" )
762 # and we wait for the entry to expire
764 # wait a bit more to be sure that the cache cleaning algo has been run
766 # the cache should be empty now
767 self
. assertEquals ( int ( self
. sendConsoleCommand ( "getPool( \"\" ):getCache():getStats()[ \" entries \" ]" ). strip ( " \n " )), 0 )
769 # we should get a DROP (backend is down, nothing in the cache anymore)
770 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
771 self
. assertEquals ( receivedResponse
, None )
774 self
. assertEquals ( int ( self
. sendConsoleCommand ( "getPool( \"\" ):getCache():getStats()[ \" misses \" ]" ). strip ( " \n " )), misses
+ drops
)
775 self
. assertEquals ( int ( self
. sendConsoleCommand ( "getPool( \"\" ):getCache():getStats()[ \" hits \" ]" ). strip ( " \n " )), 1 )
778 for key
in self
._ responsesCounter
:
779 total
+= self
._ responsesCounter
[ key
]
781 self
. assertEquals ( total
, misses
)
783 class TestCachingStaleExpungePrevented ( DNSDistTest
):
785 _consoleKey
= DNSDistTest
. generateConsoleKey ()
786 _consoleKeyB64
= base64
. b64encode ( _consoleKey
). decode ( 'ascii' )
787 _config_params
= [ '_consoleKeyB64' , '_consolePort' , '_testServerPort' ]
788 _config_template
= """
789 -- maxTTL=86400, minTTL=1, temporaryFailureTTL=0, staleTTL=60, dontAge=false, numberOfShards=1, deferrableInsertLock=true, maxNegativeTTL=3600, ecsParsing=false, keepStaleData=true
790 pc = newPacketCache(100, 86400, 1, 0, 60, false, 1, true, 3600, false, { keepStaleData=true})
791 getPool(""):setCache(pc)
792 setStaleCacheEntriesTTL(600)
793 -- try to remove all expired entries
794 setCacheCleaningPercentage(100)
795 -- clean the cache every second
796 setCacheCleaningDelay(1)
798 controlSocket("127.0.0.1: %d ")
799 newServer{address="127.0.0.1: %d "}
801 def testCacheStale ( self
):
803 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
807 name
= 'stale-not-expunged.cache.tests.powerdns.com.'
808 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
809 response
= dns
. message
. make_response ( query
)
810 rrset
= dns
. rrset
. from_text ( name
,
815 response
. answer
. append ( rrset
)
818 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
819 self
. assertTrue ( receivedQuery
)
820 self
. assertTrue ( receivedResponse
)
821 receivedQuery
. id = query
. id
822 self
. assertEquals ( query
, receivedQuery
)
823 self
. assertEquals ( response
, receivedResponse
)
825 self
. assertEquals ( int ( self
. sendConsoleCommand ( "getPool( \"\" ):getCache():getStats()[ \" misses \" ]" ). strip ( " \n " )), 1 )
827 # next queries should hit the cache
828 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
829 self
. assertEquals ( receivedResponse
, response
)
830 # the cache should have one entry
831 self
. assertEquals ( int ( self
. sendConsoleCommand ( "getPool( \"\" ):getCache():getStats()[ \" entries \" ]" ). strip ( " \n " )), 1 )
832 self
. assertEquals ( int ( self
. sendConsoleCommand ( "getPool( \"\" ):getCache():getStats()[ \" hits \" ]" ). strip ( " \n " )), 1 )
834 # ok, we mark the backend as down
835 self
. sendConsoleCommand ( "getServer(0):setDown()" )
836 # and we wait for the entry to expire
838 # wait a bit more to be sure that the cache cleaning algo has been run
840 # the cache should NOT be empty because the removal of the expired entry should have been prevented
841 # since all backends for this pool are down
842 self
. assertEquals ( int ( self
. sendConsoleCommand ( "getPool( \"\" ):getCache():getStats()[ \" entries \" ]" ). strip ( " \n " )), 1 )
844 # we should get a HIT
845 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
846 self
. assertEquals ( receivedResponse
, response
)
848 self
. assertEquals ( int ( self
. sendConsoleCommand ( "getPool( \"\" ):getCache():getStats()[ \" misses \" ]" ). strip ( " \n " )), 1 )
849 self
. assertEquals ( int ( self
. sendConsoleCommand ( "getPool( \"\" ):getCache():getStats()[ \" hits \" ]" ). strip ( " \n " )), 2 )
852 for key
in self
._ responsesCounter
:
853 total
+= self
._ responsesCounter
[ key
]
855 self
. assertEquals ( total
, misses
)
857 class TestCacheManagement ( DNSDistTest
):
859 _consoleKey
= DNSDistTest
. generateConsoleKey ()
860 _consoleKeyB64
= base64
. b64encode ( _consoleKey
). decode ( 'ascii' )
861 _config_params
= [ '_consoleKeyB64' , '_consolePort' , '_testServerPort' ]
862 _config_template
= """
863 -- maxTTL=86400, minTTL=1
864 pc = newPacketCache(100, 86400, 1)
865 getPool(""):setCache(pc)
867 controlSocket("127.0.0.1: %d ")
868 newServer{address="127.0.0.1: %d "}
870 def testCacheExpunge ( self
):
877 name
= 'expunge.cache.tests.powerdns.com.'
878 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
879 response
= dns
. message
. make_response ( query
)
880 rrset
= dns
. rrset
. from_text ( name
,
885 response
. answer
. append ( rrset
)
888 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
889 self
. assertTrue ( receivedQuery
)
890 self
. assertTrue ( receivedResponse
)
891 receivedQuery
. id = query
. id
892 self
. assertEquals ( query
, receivedQuery
)
893 self
. assertEquals ( response
, receivedResponse
)
896 # next queries should hit the cache
897 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
898 self
. assertEquals ( receivedResponse
, response
)
900 # remove cached entries
901 self
. sendConsoleCommand ( "getPool( \"\" ):getCache():expunge(0)" )
904 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
905 self
. assertTrue ( receivedQuery
)
906 self
. assertTrue ( receivedResponse
)
907 receivedQuery
. id = query
. id
908 self
. assertEquals ( query
, receivedQuery
)
909 self
. assertEquals ( response
, receivedResponse
)
912 # next queries should hit the cache again
913 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
914 self
. assertEquals ( receivedResponse
, response
)
917 for key
in self
._ responsesCounter
:
918 total
+= self
._ responsesCounter
[ key
]
920 self
. assertEquals ( total
, misses
)
922 def testCacheExpungeByName ( self
):
924 Cache: Expunge by name
929 name
= 'expungebyname.cache.tests.powerdns.com.'
930 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
931 response
= dns
. message
. make_response ( query
)
932 rrset
= dns
. rrset
. from_text ( name
,
937 response
. answer
. append ( rrset
)
939 name2
= 'expungebynameother.cache.tests.powerdns.com.'
940 query2
= dns
. message
. make_query ( name2
, 'A' , 'IN' )
941 response2
= dns
. message
. make_response ( query2
)
942 rrset2
= dns
. rrset
. from_text ( name2
,
947 response2
. answer
. append ( rrset2
)
950 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
951 self
. assertTrue ( receivedQuery
)
952 self
. assertTrue ( receivedResponse
)
953 receivedQuery
. id = query
. id
954 self
. assertEquals ( query
, receivedQuery
)
955 self
. assertEquals ( response
, receivedResponse
)
958 # next queries should hit the cache
959 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
960 self
. assertEquals ( receivedResponse
, response
)
962 # cache another entry
963 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query2
, response2
)
964 self
. assertTrue ( receivedQuery
)
965 self
. assertTrue ( receivedResponse
)
966 receivedQuery
. id = query2
. id
967 self
. assertEquals ( query2
, receivedQuery
)
968 self
. assertEquals ( response2
, receivedResponse
)
971 # queries for name and name 2 should hit the cache
972 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
973 self
. assertEquals ( receivedResponse
, response
)
975 ( _
, receivedResponse
) = self
. sendUDPQuery ( query2
, response
= None , useQueue
= False )
976 self
. assertEquals ( receivedResponse
, response2
)
978 # remove cached entries from name
979 self
. sendConsoleCommand ( "getPool( \"\" ):getCache():expungeByName(newDNSName( \" " + name
+ " \" ))" )
982 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
983 self
. assertTrue ( receivedQuery
)
984 self
. assertTrue ( receivedResponse
)
985 receivedQuery
. id = query
. id
986 self
. assertEquals ( query
, receivedQuery
)
987 self
. assertEquals ( response
, receivedResponse
)
990 # next queries for name should hit the cache again
991 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
992 self
. assertEquals ( receivedResponse
, response
)
994 # queries for name2 should still hit the cache
995 ( _
, receivedResponse
) = self
. sendUDPQuery ( query2
, response
= None , useQueue
= False )
996 self
. assertEquals ( receivedResponse
, response2
)
999 for key
in self
._ responsesCounter
:
1000 total
+= self
._ responsesCounter
[ key
]
1002 self
. assertEquals ( total
, misses
)
1004 def testCacheExpungeByNameAndType ( self
):
1006 Cache: Expunge by name and type
1011 name
= 'expungebynameandtype.cache.tests.powerdns.com.'
1012 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
1013 response
= dns
. message
. make_response ( query
)
1014 rrset
= dns
. rrset
. from_text ( name
,
1019 response
. answer
. append ( rrset
)
1021 query2
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
1022 response2
= dns
. message
. make_response ( query2
)
1023 rrset2
= dns
. rrset
. from_text ( name
,
1028 response2
. answer
. append ( rrset2
)
1031 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1032 self
. assertTrue ( receivedQuery
)
1033 self
. assertTrue ( receivedResponse
)
1034 receivedQuery
. id = query
. id
1035 self
. assertEquals ( query
, receivedQuery
)
1036 self
. assertEquals ( response
, receivedResponse
)
1039 # next queries should hit the cache
1040 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1041 self
. assertEquals ( receivedResponse
, response
)
1043 # cache another entry
1044 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query2
, response2
)
1045 self
. assertTrue ( receivedQuery
)
1046 self
. assertTrue ( receivedResponse
)
1047 receivedQuery
. id = query2
. id
1048 self
. assertEquals ( query2
, receivedQuery
)
1049 self
. assertEquals ( response2
, receivedResponse
)
1052 # queries for name A and AAAA should hit the cache
1053 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1054 self
. assertEquals ( receivedResponse
, response
)
1056 ( _
, receivedResponse
) = self
. sendUDPQuery ( query2
, response
= None , useQueue
= False )
1057 self
. assertEquals ( receivedResponse
, response2
)
1059 # remove cached entries from name A
1060 self
. sendConsoleCommand ( "getPool( \"\" ):getCache():expungeByName(newDNSName( \" " + name
+ " \" ), dnsdist.A)" )
1063 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1064 self
. assertTrue ( receivedQuery
)
1065 self
. assertTrue ( receivedResponse
)
1066 receivedQuery
. id = query
. id
1067 self
. assertEquals ( query
, receivedQuery
)
1068 self
. assertEquals ( response
, receivedResponse
)
1071 # next queries for name A should hit the cache again
1072 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1073 self
. assertEquals ( receivedResponse
, response
)
1075 # queries for name AAAA should still hit the cache
1076 ( _
, receivedResponse
) = self
. sendUDPQuery ( query2
, response
= None , useQueue
= False )
1077 self
. assertEquals ( receivedResponse
, response2
)
1080 for key
in self
._ responsesCounter
:
1081 total
+= self
._ responsesCounter
[ key
]
1082 self
. assertEquals ( total
, misses
)
1084 def testCacheExpungeByNameAndSuffix ( self
):
1086 Cache: Expunge by name
1091 name
= 'expungebyname.suffix.cache.tests.powerdns.com.'
1092 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
1093 response
= dns
. message
. make_response ( query
)
1094 rrset
= dns
. rrset
. from_text ( name
,
1099 response
. answer
. append ( rrset
)
1101 name2
= 'expungebyname.suffixother.cache.tests.powerdns.com.'
1102 query2
= dns
. message
. make_query ( name2
, 'A' , 'IN' )
1103 response2
= dns
. message
. make_response ( query2
)
1104 rrset2
= dns
. rrset
. from_text ( name2
,
1109 response2
. answer
. append ( rrset2
)
1112 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1113 self
. assertTrue ( receivedQuery
)
1114 self
. assertTrue ( receivedResponse
)
1115 receivedQuery
. id = query
. id
1116 self
. assertEquals ( query
, receivedQuery
)
1117 self
. assertEquals ( response
, receivedResponse
)
1120 # next queries should hit the cache
1121 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1122 self
. assertEquals ( receivedResponse
, response
)
1124 # cache another entry
1125 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query2
, response2
)
1126 self
. assertTrue ( receivedQuery
)
1127 self
. assertTrue ( receivedResponse
)
1128 receivedQuery
. id = query2
. id
1129 self
. assertEquals ( query2
, receivedQuery
)
1130 self
. assertEquals ( response2
, receivedResponse
)
1133 # queries for name and name 2 should hit the cache
1134 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1135 self
. assertEquals ( receivedResponse
, response
)
1137 ( _
, receivedResponse
) = self
. sendUDPQuery ( query2
, response
= None , useQueue
= False )
1138 self
. assertEquals ( receivedResponse
, response2
)
1140 # remove cached entries from name
1141 self
. sendConsoleCommand ( "getPool( \"\" ):getCache():expungeByName(newDNSName( \" suffix.cache.tests.powerdns.com. \" ), dnsdist.ANY, true)" )
1144 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1145 self
. assertTrue ( receivedQuery
)
1146 self
. assertTrue ( receivedResponse
)
1147 receivedQuery
. id = query
. id
1148 self
. assertEquals ( query
, receivedQuery
)
1149 self
. assertEquals ( response
, receivedResponse
)
1152 # next queries for name should hit the cache again
1153 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1154 self
. assertEquals ( receivedResponse
, response
)
1156 # queries for name2 should still hit the cache
1157 ( _
, receivedResponse
) = self
. sendUDPQuery ( query2
, response
= None , useQueue
= False )
1158 self
. assertEquals ( receivedResponse
, response2
)
1161 for key
in self
._ responsesCounter
:
1162 total
+= self
._ responsesCounter
[ key
]
1164 self
. assertEquals ( total
, misses
)
1166 def testCacheExpungeByNameAndTypeAndSuffix ( self
):
1168 Cache: Expunge by name and type
1173 name
= 'expungebynameandtype.suffixtype.cache.tests.powerdns.com.'
1174 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
1175 response
= dns
. message
. make_response ( query
)
1176 rrset
= dns
. rrset
. from_text ( name
,
1181 response
. answer
. append ( rrset
)
1183 query2
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
1184 response2
= dns
. message
. make_response ( query2
)
1185 rrset2
= dns
. rrset
. from_text ( name
,
1190 response2
. answer
. append ( rrset2
)
1193 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1194 self
. assertTrue ( receivedQuery
)
1195 self
. assertTrue ( receivedResponse
)
1196 receivedQuery
. id = query
. id
1197 self
. assertEquals ( query
, receivedQuery
)
1198 self
. assertEquals ( response
, receivedResponse
)
1201 # next queries should hit the cache
1202 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1203 self
. assertEquals ( receivedResponse
, response
)
1205 # cache another entry
1206 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query2
, response2
)
1207 self
. assertTrue ( receivedQuery
)
1208 self
. assertTrue ( receivedResponse
)
1209 receivedQuery
. id = query2
. id
1210 self
. assertEquals ( query2
, receivedQuery
)
1211 self
. assertEquals ( response2
, receivedResponse
)
1214 # queries for name A and AAAA should hit the cache
1215 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1216 self
. assertEquals ( receivedResponse
, response
)
1218 ( _
, receivedResponse
) = self
. sendUDPQuery ( query2
, response
= None , useQueue
= False )
1219 self
. assertEquals ( receivedResponse
, response2
)
1221 # remove cached entries from name A
1222 self
. sendConsoleCommand ( "getPool( \"\" ):getCache():expungeByName(newDNSName( \" suffixtype.cache.tests.powerdns.com. \" ), dnsdist.A, true)" )
1225 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1226 self
. assertTrue ( receivedQuery
)
1227 self
. assertTrue ( receivedResponse
)
1228 receivedQuery
. id = query
. id
1229 self
. assertEquals ( query
, receivedQuery
)
1230 self
. assertEquals ( response
, receivedResponse
)
1233 # next queries for name A should hit the cache again
1234 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1235 self
. assertEquals ( receivedResponse
, response
)
1237 # queries for name AAAA should still hit the cache
1238 ( _
, receivedResponse
) = self
. sendUDPQuery ( query2
, response
= None , useQueue
= False )
1239 self
. assertEquals ( receivedResponse
, response2
)
1242 for key
in self
._ responsesCounter
:
1243 total
+= self
._ responsesCounter
[ key
]
1244 self
. assertEquals ( total
, misses
)
1246 class TestCachingTTL ( DNSDistTest
):
1248 _maxCacheTTL
= 86400
1250 _config_params
= [ '_maxCacheTTL' , '_minCacheTTL' , '_testServerPort' ]
1251 _config_template
= """
1252 -- maxTTL=XX, minTTL=XX
1253 pc = newPacketCache(1000, %d , %d )
1254 getPool(""):setCache(pc)
1255 newServer{address="127.0.0.1: %d "}
1257 def testCacheShortTTL ( self
):
1259 Cache: Entries with a TTL shorter than minTTL
1264 name
= 'ttltooshort.cache.tests.powerdns.com.'
1265 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
1266 response
= dns
. message
. make_response ( query
)
1267 rrset
= dns
. rrset
. from_text ( name
,
1272 response
. answer
. append ( rrset
)
1275 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1276 self
. assertTrue ( receivedQuery
)
1277 self
. assertTrue ( receivedResponse
)
1278 receivedQuery
. id = query
. id
1279 self
. assertEquals ( query
, receivedQuery
)
1280 self
. assertEquals ( response
, receivedResponse
)
1281 for an
in receivedResponse
. answer
:
1282 self
. assertEquals ( an
. ttl
, ttl
)
1285 # We should not have been cached
1286 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1287 self
. assertTrue ( receivedQuery
)
1288 self
. assertTrue ( receivedResponse
)
1289 receivedQuery
. id = query
. id
1290 self
. assertEquals ( query
, receivedQuery
)
1291 self
. assertEquals ( response
, receivedResponse
)
1292 for an
in receivedResponse
. answer
:
1293 self
. assertEquals ( an
. ttl
, ttl
)
1297 for key
in self
._ responsesCounter
:
1298 total
+= self
._ responsesCounter
[ key
]
1300 self
. assertEquals ( total
, misses
)
1302 def testCacheNXWithNoRR ( self
):
1304 Cache: NX with no RR
1308 name
= 'nxwithnorr.cache.tests.powerdns.com.'
1309 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
1310 response
= dns
. message
. make_response ( query
)
1311 response
. set_rcode ( dns
. rcode
. NXDOMAIN
)
1314 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1315 self
. assertTrue ( receivedQuery
)
1316 self
. assertTrue ( receivedResponse
)
1317 receivedQuery
. id = query
. id
1318 self
. assertEquals ( query
, receivedQuery
)
1319 self
. assertEquals ( response
, receivedResponse
)
1322 # We should not have been cached
1323 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1324 self
. assertTrue ( receivedQuery
)
1325 self
. assertTrue ( receivedResponse
)
1326 receivedQuery
. id = query
. id
1327 self
. assertEquals ( query
, receivedQuery
)
1328 self
. assertEquals ( response
, receivedResponse
)
1332 for key
in self
._ responsesCounter
:
1333 total
+= self
._ responsesCounter
[ key
]
1335 self
. assertEquals ( total
, misses
)
1337 class TestCachingLongTTL ( DNSDistTest
):
1340 _config_params
= [ '_maxCacheTTL' , '_testServerPort' ]
1341 _config_template
= """
1343 pc = newPacketCache(1000, %d )
1344 getPool(""):setCache(pc)
1345 newServer{address="127.0.0.1: %d "}
1347 def testCacheLongTTL ( self
):
1349 Cache: Entries with a longer TTL than the maximum
1354 name
= 'longttl.cache.tests.powerdns.com.'
1355 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
1356 response
= dns
. message
. make_response ( query
)
1357 rrset
= dns
. rrset
. from_text ( name
,
1362 response
. answer
. append ( rrset
)
1365 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1366 self
. assertTrue ( receivedQuery
)
1367 self
. assertTrue ( receivedResponse
)
1368 receivedQuery
. id = query
. id
1369 self
. assertEquals ( query
, receivedQuery
)
1370 self
. assertEquals ( response
, receivedResponse
)
1371 for an
in receivedResponse
. answer
:
1372 self
. assertEquals ( an
. ttl
, ttl
)
1375 # next queries should hit the cache
1376 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1377 self
. assertEquals ( receivedResponse
, response
)
1378 for an
in receivedResponse
. answer
:
1379 self
. assertTrue ( an
. ttl
<= ttl
)
1381 time
. sleep ( self
._ maxCacheTTL
+ 1 )
1383 # we should not have cached for longer than max cache
1384 # so it should be a miss
1385 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1386 self
. assertTrue ( receivedQuery
)
1387 self
. assertTrue ( receivedResponse
)
1388 receivedQuery
. id = query
. id
1389 self
. assertEquals ( query
, receivedQuery
)
1390 self
. assertEquals ( response
, receivedResponse
)
1391 for an
in receivedResponse
. answer
:
1392 self
. assertEquals ( an
. ttl
, ttl
)
1396 for key
in self
._ responsesCounter
:
1397 total
+= self
._ responsesCounter
[ key
]
1399 self
. assertEquals ( total
, misses
)
1401 class TestCachingFailureTTL ( DNSDistTest
):
1403 _failureCacheTTL
= 2
1404 _config_params
= [ '_failureCacheTTL' , '_testServerPort' ]
1405 _config_template
= """
1406 -- maxTTL=86400, minTTL=0, temporaryFailureTTL=XX, staleTTL=60
1407 pc = newPacketCache(1000, 86400, 0, %d , 60)
1408 getPool(""):setCache(pc)
1409 newServer{address="127.0.0.1: %d "}
1411 def testCacheServFailTTL ( self
):
1417 name
= 'servfail.failure.cache.tests.powerdns.com.'
1418 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
1419 response
= dns
. message
. make_response ( query
)
1420 response
. set_rcode ( dns
. rcode
. SERVFAIL
)
1423 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1424 self
. assertTrue ( receivedQuery
)
1425 self
. assertTrue ( receivedResponse
)
1426 receivedQuery
. id = query
. id
1427 self
. assertEquals ( query
, receivedQuery
)
1428 self
. assertEquals ( response
, receivedResponse
)
1431 # next queries should hit the cache
1432 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1433 self
. assertEquals ( receivedResponse
, response
)
1435 time
. sleep ( self
._ failureCacheTTL
+ 1 )
1437 # we should not have cached for longer than failure cache
1438 # so it should be a miss
1439 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1440 self
. assertTrue ( receivedQuery
)
1441 self
. assertTrue ( receivedResponse
)
1442 receivedQuery
. id = query
. id
1443 self
. assertEquals ( query
, receivedQuery
)
1444 self
. assertEquals ( response
, receivedResponse
)
1448 for key
in self
._ responsesCounter
:
1449 total
+= self
._ responsesCounter
[ key
]
1451 self
. assertEquals ( total
, misses
)
1453 def testCacheRefusedTTL ( self
):
1459 name
= 'refused.failure.cache.tests.powerdns.com.'
1460 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
1461 response
= dns
. message
. make_response ( query
)
1462 response
. set_rcode ( dns
. rcode
. REFUSED
)
1465 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1466 self
. assertTrue ( receivedQuery
)
1467 self
. assertTrue ( receivedResponse
)
1468 receivedQuery
. id = query
. id
1469 self
. assertEquals ( query
, receivedQuery
)
1470 self
. assertEquals ( response
, receivedResponse
)
1473 # next queries should hit the cache
1474 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1475 self
. assertEquals ( receivedResponse
, response
)
1477 time
. sleep ( self
._ failureCacheTTL
+ 1 )
1479 # we should not have cached for longer than failure cache
1480 # so it should be a miss
1481 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1482 self
. assertTrue ( receivedQuery
)
1483 self
. assertTrue ( receivedResponse
)
1484 receivedQuery
. id = query
. id
1485 self
. assertEquals ( query
, receivedQuery
)
1486 self
. assertEquals ( response
, receivedResponse
)
1490 for key
in self
._ responsesCounter
:
1491 total
+= self
._ responsesCounter
[ key
]
1493 self
. assertEquals ( total
, misses
)
1495 def testCacheHeaderOnlyRefusedTTL ( self
):
1497 Cache: Header-Only Refused TTL
1501 name
= 'header-only-refused.failure.cache.tests.powerdns.com.'
1502 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
1503 response
= dns
. message
. make_response ( query
)
1504 response
. set_rcode ( dns
. rcode
. REFUSED
)
1505 response
. question
= []
1508 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1509 self
. assertTrue ( receivedQuery
)
1510 self
. assertTrue ( receivedResponse
)
1511 receivedQuery
. id = query
. id
1512 self
. assertEquals ( query
, receivedQuery
)
1513 self
. assertEquals ( response
, receivedResponse
)
1516 # next queries should hit the cache
1517 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1518 self
. assertEquals ( receivedResponse
, response
)
1520 time
. sleep ( self
._ failureCacheTTL
+ 1 )
1522 # we should not have cached for longer than failure cache
1523 # so it should be a miss
1524 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1525 self
. assertTrue ( receivedQuery
)
1526 self
. assertTrue ( receivedResponse
)
1527 receivedQuery
. id = query
. id
1528 self
. assertEquals ( query
, receivedQuery
)
1529 self
. assertEquals ( response
, receivedResponse
)
1533 for key
in self
._ responsesCounter
:
1534 total
+= self
._ responsesCounter
[ key
]
1536 self
. assertEquals ( total
, misses
)
1538 class TestCachingNegativeTTL ( DNSDistTest
):
1541 _config_params
= [ '_negCacheTTL' , '_testServerPort' ]
1542 _config_template
= """
1543 -- maxTTL=86400, minTTL=0, temporaryFailureTTL=60, staleTTL=60, dontAge=false, numberOfShards=1, deferrableInsertLock=true, maxNegativeTTL=XX
1544 pc = newPacketCache(1000, 86400, 0, 60, 60, false, 1, true, %d )
1545 getPool(""):setCache(pc)
1546 newServer{address="127.0.0.1: %d "}
1549 def testCacheNegativeTTLNXDomain ( self
):
1551 Cache: Negative TTL on NXDOMAIN
1555 name
= 'nxdomain.negativettl.cache.tests.powerdns.com.'
1556 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
1557 response
= dns
. message
. make_response ( query
)
1558 response
. set_rcode ( dns
. rcode
. NXDOMAIN
)
1559 soa
= dns
. rrset
. from_text ( name
,
1563 'ns.' + name
+ ' hostmaster.' + name
+ ' 1 3600 3600 3600 60' )
1564 response
. authority
. append ( soa
)
1567 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1568 self
. assertTrue ( receivedQuery
)
1569 self
. assertTrue ( receivedResponse
)
1570 receivedQuery
. id = query
. id
1571 self
. assertEquals ( query
, receivedQuery
)
1572 self
. assertEquals ( response
, receivedResponse
)
1575 # next queries should hit the cache
1576 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1577 self
. assertEquals ( receivedResponse
, response
)
1579 time
. sleep ( self
._ negCacheTTL
+ 1 )
1581 # we should not have cached for longer than the negativel TTL
1582 # so it should be a miss
1583 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1584 self
. assertTrue ( receivedQuery
)
1585 self
. assertTrue ( receivedResponse
)
1586 receivedQuery
. id = query
. id
1587 self
. assertEquals ( query
, receivedQuery
)
1588 self
. assertEquals ( response
, receivedResponse
)
1592 for key
in self
._ responsesCounter
:
1593 total
+= self
._ responsesCounter
[ key
]
1595 self
. assertEquals ( total
, misses
)
1597 def testCacheNegativeTTLNoData ( self
):
1599 Cache: Negative TTL on NoData
1603 name
= 'nodata.negativettl.cache.tests.powerdns.com.'
1604 query
= dns
. message
. make_query ( name
, 'A' , 'IN' )
1605 response
= dns
. message
. make_response ( query
)
1606 response
. set_rcode ( dns
. rcode
. NOERROR
)
1607 soa
= dns
. rrset
. from_text ( name
,
1611 'ns.' + name
+ ' hostmaster.' + name
+ ' 1 3600 3600 3600 60' )
1612 response
. authority
. append ( soa
)
1615 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1616 self
. assertTrue ( receivedQuery
)
1617 self
. assertTrue ( receivedResponse
)
1618 receivedQuery
. id = query
. id
1619 self
. assertEquals ( query
, receivedQuery
)
1620 self
. assertEquals ( response
, receivedResponse
)
1623 # next queries should hit the cache
1624 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1625 self
. assertEquals ( receivedResponse
, response
)
1627 time
. sleep ( self
._ negCacheTTL
+ 1 )
1629 # we should not have cached for longer than the negativel TTL
1630 # so it should be a miss
1631 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1632 self
. assertTrue ( receivedQuery
)
1633 self
. assertTrue ( receivedResponse
)
1634 receivedQuery
. id = query
. id
1635 self
. assertEquals ( query
, receivedQuery
)
1636 self
. assertEquals ( response
, receivedResponse
)
1640 for key
in self
._ responsesCounter
:
1641 total
+= self
._ responsesCounter
[ key
]
1643 self
. assertEquals ( total
, misses
)
1645 class TestCachingDontAge ( DNSDistTest
):
1647 _config_template
= """
1648 -- maxTTL=86400, minTTL=0, temporaryFailureTTL=60, staleTTL=60, dontAge=true
1649 pc = newPacketCache(100, 86400, 0, 60, 60, true)
1650 getPool(""):setCache(pc)
1651 newServer{address="127.0.0.1: %d "}
1653 def testCacheDoesntDecreaseTTL ( self
):
1655 Cache: Cache doesn't decrease TTL with 'don't age' set
1657 dnsdist is configured to cache entries but without aging the TTL,
1658 we are sending one request (cache miss) and verify that the cache
1659 hits don't have a decreasing TTL.
1663 name
= 'cachedoesntdecreasettl.cache-dont-age.tests.powerdns.com.'
1664 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
1665 response
= dns
. message
. make_response ( query
)
1666 rrset
= dns
. rrset
. from_text ( name
,
1671 response
. answer
. append ( rrset
)
1673 # first query to fill the cache
1674 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1675 self
. assertTrue ( receivedQuery
)
1676 self
. assertTrue ( receivedResponse
)
1677 receivedQuery
. id = query
. id
1678 self
. assertEquals ( query
, receivedQuery
)
1679 self
. assertEquals ( receivedResponse
, response
)
1682 # next queries should hit the cache
1683 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1684 self
. assertEquals ( receivedResponse
, response
)
1685 for an
in receivedResponse
. answer
:
1686 self
. assertTrue ( an
. ttl
== ttl
)
1688 # now we wait a bit for the TTL to decrease
1691 # next queries should hit the cache
1692 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1693 self
. assertEquals ( receivedResponse
, response
)
1694 for an
in receivedResponse
. answer
:
1695 self
. assertTrue ( an
. ttl
== ttl
)
1698 for key
in self
._ responsesCounter
:
1699 total
+= self
._ responsesCounter
[ key
]
1701 self
. assertEquals ( total
, misses
)
1703 class TestCachingECSWithoutPoolECS ( DNSDistTest
):
1705 _consoleKey
= DNSDistTest
. generateConsoleKey ()
1706 _consoleKeyB64
= base64
. b64encode ( _consoleKey
). decode ( 'ascii' )
1707 _config_params
= [ '_consoleKeyB64' , '_consolePort' , '_testServerPort' ]
1708 _config_template
= """
1709 -- maxTTL=86400, minTTL=1
1710 pc = newPacketCache(100, 86400, 1)
1711 getPool(""):setCache(pc)
1713 controlSocket("127.0.0.1: %d ")
1714 newServer{address="127.0.0.1: %d ", useClientSubnet=true}
1717 def testCached ( self
):
1719 Cache: Cached entry with ECS is a miss when no backend are available
1722 name
= 'cached.cache-ecs-without-pool-ecs.tests.powerdns.com.'
1723 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
1724 response
= dns
. message
. make_response ( query
)
1725 rrset
= dns
. rrset
. from_text ( name
,
1730 response
. answer
. append ( rrset
)
1732 # first query to fill the cache
1733 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1734 self
. assertTrue ( receivedQuery
)
1735 self
. assertTrue ( receivedResponse
)
1736 receivedQuery
. id = query
. id
1737 self
. assertEquals ( query
, receivedQuery
)
1738 self
. assertEquals ( receivedResponse
, response
)
1739 ( receivedQuery
, receivedResponse
) = self
. sendTCPQuery ( query
, response
)
1740 self
. assertTrue ( receivedQuery
)
1741 self
. assertTrue ( receivedResponse
)
1742 receivedQuery
. id = query
. id
1743 self
. assertEquals ( query
, receivedQuery
)
1744 self
. assertEquals ( receivedResponse
, response
)
1746 # next queries should hit the cache
1747 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1748 self
. assertEquals ( receivedResponse
, response
)
1751 ( _
, receivedResponse
) = self
. sendTCPQuery ( query
, response
= None , useQueue
= False )
1752 self
. assertEquals ( receivedResponse
, response
)
1754 # we mark the backend as down
1755 self
. sendConsoleCommand ( "getServer(0):setDown()" )
1757 # we should NOT get a cached entry since it has ECS and we haven't asked the pool
1758 # to add ECS when no backend is up
1759 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1760 self
. assertEquals ( receivedResponse
, None )
1763 ( _
, receivedResponse
) = self
. sendTCPQuery ( query
, response
= None , useQueue
= False )
1764 self
. assertEquals ( receivedResponse
, None )
1766 class TestCachingECSWithPoolECS ( DNSDistTest
):
1768 _consoleKey
= DNSDistTest
. generateConsoleKey ()
1769 _consoleKeyB64
= base64
. b64encode ( _consoleKey
). decode ( 'ascii' )
1770 _config_params
= [ '_consoleKeyB64' , '_consolePort' , '_testServerPort' ]
1771 _config_template
= """
1772 -- maxTTL=86400, minTTL=1
1773 pc = newPacketCache(100, 86400, 1)
1774 getPool(""):setCache(pc)
1775 getPool(""):setECS(true)
1777 controlSocket("127.0.0.1: %d ")
1778 newServer{address="127.0.0.1: %d ", useClientSubnet=true}
1781 def testCached ( self
):
1783 Cache: Cached entry with ECS is a hit when no backend are available
1786 name
= 'cached.cache-ecs-with-pool-ecs.tests.powerdns.com.'
1787 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
1788 response
= dns
. message
. make_response ( query
)
1789 rrset
= dns
. rrset
. from_text ( name
,
1794 response
. answer
. append ( rrset
)
1796 # first query to fill the cache
1797 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1798 self
. assertTrue ( receivedQuery
)
1799 self
. assertTrue ( receivedResponse
)
1800 receivedQuery
. id = query
. id
1801 self
. assertEquals ( query
, receivedQuery
)
1802 self
. assertEquals ( receivedResponse
, response
)
1803 ( receivedQuery
, receivedResponse
) = self
. sendTCPQuery ( query
, response
)
1804 self
. assertTrue ( receivedQuery
)
1805 self
. assertTrue ( receivedResponse
)
1806 receivedQuery
. id = query
. id
1807 self
. assertEquals ( query
, receivedQuery
)
1808 self
. assertEquals ( receivedResponse
, response
)
1810 # next queries should hit the cache
1811 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1812 self
. assertEquals ( receivedResponse
, response
)
1815 ( _
, receivedResponse
) = self
. sendTCPQuery ( query
, response
= None , useQueue
= False )
1816 self
. assertEquals ( receivedResponse
, response
)
1818 # we mark the backend as down
1819 self
. sendConsoleCommand ( "getServer(0):setDown()" )
1821 # we should STILL get a cached entry since it has ECS and we have asked the pool
1822 # to add ECS when no backend is up
1823 ( _
, receivedResponse
) = self
. sendUDPQuery ( query
, response
= None , useQueue
= False )
1824 self
. assertEquals ( receivedResponse
, response
)
1827 ( _
, receivedResponse
) = self
. sendTCPQuery ( query
, response
= None , useQueue
= False )
1828 self
. assertEquals ( receivedResponse
, response
)
1830 class TestCachingCollisionNoECSParsing ( DNSDistTest
):
1832 _config_template
= """
1833 -- maxTTL=86400, minTTL=1
1834 pc = newPacketCache(100, 86400, 1)
1835 getPool(""):setCache(pc)
1836 newServer{address="127.0.0.1: %d "}
1839 def testCacheCollisionNoECSParsing ( self
):
1841 Cache: Collision with no ECS parsing
1843 name
= 'collision-no-ecs-parsing.cache.tests.powerdns.com.'
1844 ecso
= clientsubnetoption
. ClientSubnetOption ( '10.0.188.3' , 32 )
1845 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' , use_edns
= True , options
=[ ecso
], payload
= 512 )
1846 query
. flags
= dns
. flags
. RD
1847 response
= dns
. message
. make_response ( query
)
1848 rrset
= dns
. rrset
. from_text ( name
,
1853 response
. answer
. append ( rrset
)
1855 # first query should to fill the cache
1856 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1857 self
. assertTrue ( receivedQuery
)
1858 self
. assertTrue ( receivedResponse
)
1859 receivedQuery
. id = query
. id
1860 self
. assertEquals ( query
, receivedQuery
)
1861 self
. assertEquals ( receivedResponse
, response
)
1863 # second query will hash to the same key, triggering a collision which
1864 # will not be detected because the qname, qtype, qclass and flags will
1865 # match and EDNS Client Subnet parsing has not been enabled
1866 ecso2
= clientsubnetoption
. ClientSubnetOption ( '10.0.192.138' , 32 )
1867 query2
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' , use_edns
= True , options
=[ ecso2
], payload
= 512 )
1868 query2
. flags
= dns
. flags
. RD
1869 ( _
, receivedResponse
) = self
. sendUDPQuery ( query2
, response
= None , useQueue
= False )
1870 receivedResponse
. id = response
. id
1871 self
. assertEquals ( receivedResponse
, response
)
1873 class TestCachingCollisionWithECSParsing ( DNSDistTest
):
1875 _config_template
= """
1876 -- maxTTL=86400, minTTL=1, temporaryFailureTTL=60, staleTTL=60, dontAge=false, numberOfShards=1, deferrableInsertLock=true, maxNegativeTTL=3600, parseECS=true
1877 pc = newPacketCache(100, 86400, 1, 60, 60, false, 1, true, 3600, true)
1878 getPool(""):setCache(pc)
1879 newServer{address="127.0.0.1: %d "}
1882 def testCacheCollisionWithECSParsing ( self
):
1884 Cache: Collision with ECS parsing
1886 name
= 'collision-with-ecs-parsing.cache.tests.powerdns.com.'
1887 ecso
= clientsubnetoption
. ClientSubnetOption ( '10.0.115.61' , 32 )
1888 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' , use_edns
= True , options
=[ ecso
], payload
= 512 )
1889 query
. flags
= dns
. flags
. RD
1890 response
= dns
. message
. make_response ( query
)
1891 rrset
= dns
. rrset
. from_text ( name
,
1896 response
. answer
. append ( rrset
)
1898 # first query should to fill the cache
1899 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query
, response
)
1900 self
. assertTrue ( receivedQuery
)
1901 self
. assertTrue ( receivedResponse
)
1902 receivedQuery
. id = query
. id
1903 self
. assertEquals ( query
, receivedQuery
)
1904 self
. assertEquals ( receivedResponse
, response
)
1906 # second query will hash to the same key, triggering a collision which
1907 # _will_ be detected this time because the qname, qtype, qclass and flags will
1908 # match but EDNS Client Subnet parsing is now enabled and will detect the issue
1909 ecso2
= clientsubnetoption
. ClientSubnetOption ( '10.0.143.21' , 32 )
1910 query2
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' , use_edns
= True , options
=[ ecso2
], payload
= 512 )
1911 query2
. flags
= dns
. flags
. RD
1912 response2
= dns
. message
. make_response ( query2
)
1913 rrset
= dns
. rrset
. from_text ( name
,
1918 response2
. answer
. append ( rrset
)
1919 ( receivedQuery
, receivedResponse
) = self
. sendUDPQuery ( query2
, response2
)
1920 self
. assertEquals ( receivedResponse
, response2
)
1922 class TestCachingScopeZero ( DNSDistTest
):
1924 _config_template
= """
1925 -- Be careful to enable ECS parsing in the packet cache, otherwise scope zero is disabled
1926 pc = newPacketCache(100, 86400, 1, 60, 60, false, 1, true, 3600, true)
1927 getPool(""):setCache(pc)
1928 newServer{address="127.0.0.1: %d ", useClientSubnet=true}
1929 -- to simulate a second client coming from a different IP address,
1930 -- we will force the ECS value added to the query if RD is set (note that we need
1931 -- to unset it using rules before the first cache lookup)
1932 addAction(RDRule(), SetECSAction("192.0.2.1/32"))
1933 addAction(RDRule(), NoRecurseAction())
1936 def testScopeZero ( self
):
1938 Cache: Test the scope-zero feature, backend returns a scope of zero
1941 name
= 'scope-zero.cache.tests.powerdns.com.'
1942 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
1943 query
. flags
&= ~dns
. flags
. RD
1944 ecso
= clientsubnetoption
. ClientSubnetOption ( '127.0.0.0' , 24 )
1945 expectedQuery
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' , use_edns
= True , options
=[ ecso
], payload
= 512 )
1946 expectedQuery
. flags
&= ~dns
. flags
. RD
1947 ecsoResponse
= clientsubnetoption
. ClientSubnetOption ( '127.0.0.1' , 24 , 0 )
1948 expectedResponse
= dns
. message
. make_response ( query
)
1949 scopedResponse
= dns
. message
. make_response ( query
)
1950 scopedResponse
. use_edns ( edns
= True , payload
= 4096 , options
=[ ecsoResponse
])
1951 rrset
= dns
. rrset
. from_text ( name
,
1956 scopedResponse
. answer
. append ( rrset
)
1957 expectedResponse
. answer
. append ( rrset
)
1959 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
1960 sender
= getattr ( self
, method
)
1961 ( receivedQuery
, receivedResponse
) = sender ( query
, scopedResponse
)
1962 receivedQuery
. id = expectedQuery
. id
1963 self
. checkMessageEDNSWithECS ( expectedQuery
, receivedQuery
)
1964 self
. checkMessageNoEDNS ( receivedResponse
, expectedResponse
)
1966 # next query should hit the cache, nothing special about that
1967 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
1968 sender
= getattr ( self
, method
)
1969 ( _
, receivedResponse
) = sender ( query
, response
= None , useQueue
= False )
1970 self
. checkMessageNoEDNS ( receivedResponse
, expectedResponse
)
1972 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
1973 query
. flags
&= dns
. flags
. RD
1974 # next query FROM A DIFFERENT CLIENT since RD is now set should STILL hit the cache
1975 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
1976 sender
= getattr ( self
, method
)
1977 ( _
, receivedResponse
) = sender ( query
, response
= None , useQueue
= False )
1978 receivedResponse
. id = expectedResponse
. id
1979 self
. checkMessageNoEDNS ( receivedResponse
, expectedResponse
)
1981 name
= 'scope-zero-with-ecs.cache.tests.powerdns.com.'
1982 ecso
= clientsubnetoption
. ClientSubnetOption ( '127.0.0.1' , 24 )
1983 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' , use_edns
= True , options
=[ ecso
], payload
= 512 )
1984 query
. flags
&= ~dns
. flags
. RD
1985 expectedQuery
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' , use_edns
= True , options
=[ ecso
], payload
= 512 )
1986 expectedQuery
. flags
&= ~dns
. flags
. RD
1987 expectedResponse
= dns
. message
. make_response ( query
)
1988 expectedResponse
. use_edns ( edns
= True , payload
= 4096 , options
=[ ecsoResponse
])
1989 expectedResponse
. answer
. append ( rrset
)
1990 scopedResponse
= dns
. message
. make_response ( query
)
1991 scopedResponse
. use_edns ( edns
= True , payload
= 4096 , options
=[ ecsoResponse
])
1992 scopedResponse
. answer
. append ( rrset
)
1993 # this query has ECS, it should NOT be able to use the scope-zero cached entry since the hash will be
1995 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
1996 sender
= getattr ( self
, method
)
1997 ( receivedQuery
, receivedResponse
) = sender ( query
, scopedResponse
)
1998 receivedQuery
. id = expectedQuery
. id
1999 self
. checkMessageEDNSWithECS ( expectedQuery
, receivedQuery
)
2000 self
. checkMessageEDNSWithECS ( receivedResponse
, expectedResponse
)
2002 # it should still have been cached, though, so the next query should be a hit
2003 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
2004 sender
= getattr ( self
, method
)
2005 ( _
, receivedResponse
) = sender ( query
, response
= None , useQueue
= False )
2006 self
. checkMessageEDNSWithECS ( receivedResponse
, expectedResponse
)
2008 def testScopeNotZero ( self
):
2010 Cache: Test the scope-zero feature, backend returns a scope of non-zero
2013 name
= 'scope-not-zero.cache.tests.powerdns.com.'
2014 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
2015 query
. flags
&= ~dns
. flags
. RD
2016 ecso
= clientsubnetoption
. ClientSubnetOption ( '127.0.0.0' , 24 )
2017 expectedQuery
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' , use_edns
= True , options
=[ ecso
], payload
= 512 )
2018 expectedQuery
. flags
&= ~dns
. flags
. RD
2019 ecso2
= clientsubnetoption
. ClientSubnetOption ( '192.0.2.1' , 32 )
2020 expectedQuery2
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' , use_edns
= True , options
=[ ecso2
], payload
= 512 )
2021 expectedQuery2
. flags
&= ~dns
. flags
. RD
2022 ecsoResponse
= clientsubnetoption
. ClientSubnetOption ( '127.0.0.1' , 24 , 24 )
2023 ecsoResponse2
= clientsubnetoption
. ClientSubnetOption ( '192.0.2.1' , 32 , 24 )
2024 rrset
= dns
. rrset
. from_text ( name
,
2029 expectedResponse
= dns
. message
. make_response ( query
)
2030 expectedResponse
. answer
. append ( rrset
)
2031 scopedResponse
= dns
. message
. make_response ( query
)
2032 scopedResponse
. use_edns ( edns
= True , payload
= 4096 , options
=[ ecsoResponse
])
2033 scopedResponse
. answer
. append ( rrset
)
2034 scopedResponse2
= dns
. message
. make_response ( query
)
2035 scopedResponse2
. use_edns ( edns
= True , payload
= 4096 , options
=[ ecsoResponse2
])
2036 scopedResponse2
. answer
. append ( rrset
)
2038 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
2039 sender
= getattr ( self
, method
)
2040 ( receivedQuery
, receivedResponse
) = sender ( query
, scopedResponse
)
2041 receivedQuery
. id = expectedQuery
. id
2042 self
. checkMessageEDNSWithECS ( expectedQuery
, receivedQuery
)
2043 self
. checkMessageNoEDNS ( receivedResponse
, expectedResponse
)
2045 # next query should hit the cache, nothing special about that
2046 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
2047 sender
= getattr ( self
, method
)
2048 ( _
, receivedResponse
) = sender ( query
, response
= None , useQueue
= False )
2049 self
. checkMessageNoEDNS ( receivedResponse
, expectedResponse
)
2051 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
2052 query
. flags
&= dns
. flags
. RD
2053 expectedResponse
= dns
. message
. make_response ( query
)
2054 expectedResponse
. answer
. append ( rrset
)
2055 # next query FROM A DIFFERENT CLIENT since RD is now set should NOT hit the cache
2056 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
2057 sender
= getattr ( self
, method
)
2058 ( receivedQuery
, receivedResponse
) = sender ( query
, scopedResponse2
)
2059 receivedQuery
. id = expectedQuery2
. id
2060 self
. checkMessageEDNSWithECS ( expectedQuery2
, receivedQuery
)
2061 self
. checkMessageNoEDNS ( receivedResponse
, expectedResponse
)
2063 def testNoECS ( self
):
2065 Cache: Test the scope-zero feature, backend returns no ECS at all
2068 name
= 'scope-zero-no-ecs.cache.tests.powerdns.com.'
2069 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
2070 query
. flags
&= ~dns
. flags
. RD
2071 ecso
= clientsubnetoption
. ClientSubnetOption ( '127.0.0.0' , 24 )
2072 expectedQuery
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' , use_edns
= True , options
=[ ecso
], payload
= 512 )
2073 expectedQuery
. flags
&= ~dns
. flags
. RD
2074 ecso2
= clientsubnetoption
. ClientSubnetOption ( '192.0.2.1' , 32 )
2075 expectedQuery2
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' , use_edns
= True , options
=[ ecso2
], payload
= 512 )
2076 expectedQuery2
. flags
&= ~dns
. flags
. RD
2077 rrset
= dns
. rrset
. from_text ( name
,
2082 response
= dns
. message
. make_response ( query
)
2083 response
. answer
. append ( rrset
)
2085 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
2086 sender
= getattr ( self
, method
)
2087 ( receivedQuery
, receivedResponse
) = sender ( query
, response
)
2088 receivedQuery
. id = expectedQuery
. id
2089 self
. checkMessageEDNSWithECS ( expectedQuery
, receivedQuery
)
2090 self
. checkMessageNoEDNS ( receivedResponse
, response
)
2092 # next query should hit the cache, nothing special about that
2093 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
2094 sender
= getattr ( self
, method
)
2095 ( _
, receivedResponse
) = sender ( query
, response
= None , useQueue
= False )
2096 self
. checkMessageNoEDNS ( receivedResponse
, response
)
2098 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
2099 query
. flags
&= dns
. flags
. RD
2100 response
= dns
. message
. make_response ( query
)
2101 response
. answer
. append ( rrset
)
2102 # next query FROM A DIFFERENT CLIENT since RD is now set should NOT hit the cache
2103 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
2104 sender
= getattr ( self
, method
)
2105 ( receivedQuery
, receivedResponse
) = sender ( query
, response
)
2106 receivedQuery
. id = expectedQuery2
. id
2107 self
. checkMessageEDNSWithECS ( expectedQuery2
, receivedQuery
)
2108 self
. checkMessageNoEDNS ( receivedResponse
, response
)
2110 class TestCachingScopeZeroButNoSubnetcheck ( DNSDistTest
):
2112 _config_template
= """
2113 -- We disable ECS parsing in the packet cache, meaning scope zero is disabled
2114 pc = newPacketCache(100, 86400, 1, 60, 60, false, 1, true, 3600, false)
2115 getPool(""):setCache(pc)
2116 newServer{address="127.0.0.1: %d ", useClientSubnet=true}
2117 -- to simulate a second client coming from a different IP address,
2118 -- we will force the ECS value added to the query if RD is set (note that we need
2119 -- to unset it using rules before the first cache lookup)
2120 addAction(RDRule(), SetECSAction("192.0.2.1/32"))
2121 addAction(RDRule(), NoRecurseAction())
2124 def testScopeZero ( self
):
2126 Cache: Test that the scope-zero feature is disabled when ECS parsing is not enabled in the cache
2129 name
= 'scope-zero-no-subnet.cache.tests.powerdns.com.'
2130 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
2131 query
. flags
&= ~dns
. flags
. RD
2132 ecso
= clientsubnetoption
. ClientSubnetOption ( '127.0.0.0' , 24 )
2133 expectedQuery
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' , use_edns
= True , options
=[ ecso
], payload
= 512 )
2134 expectedQuery
. flags
&= ~dns
. flags
. RD
2135 ecso2
= clientsubnetoption
. ClientSubnetOption ( '192.0.2.1' , 32 )
2136 expectedQuery2
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' , use_edns
= True , options
=[ ecso2
], payload
= 512 )
2137 expectedQuery2
. flags
&= ~dns
. flags
. RD
2138 ecsoResponse
= clientsubnetoption
. ClientSubnetOption ( '127.0.0.1' , 24 , 0 )
2139 expectedResponse
= dns
. message
. make_response ( query
)
2140 scopedResponse
= dns
. message
. make_response ( query
)
2141 scopedResponse
. use_edns ( edns
= True , payload
= 4096 , options
=[ ecsoResponse
])
2142 rrset
= dns
. rrset
. from_text ( name
,
2147 scopedResponse
. answer
. append ( rrset
)
2148 expectedResponse
. answer
. append ( rrset
)
2150 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
2151 sender
= getattr ( self
, method
)
2152 ( receivedQuery
, receivedResponse
) = sender ( query
, scopedResponse
)
2153 receivedQuery
. id = expectedQuery
. id
2154 self
. checkMessageEDNSWithECS ( expectedQuery
, receivedQuery
)
2155 self
. checkMessageNoEDNS ( receivedResponse
, expectedResponse
)
2157 # next query should hit the cache, nothing special about that
2158 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
2159 sender
= getattr ( self
, method
)
2160 ( _
, receivedResponse
) = sender ( query
, response
= None , useQueue
= False )
2161 self
. checkMessageNoEDNS ( receivedResponse
, expectedResponse
)
2163 query
= dns
. message
. make_query ( name
, 'AAAA' , 'IN' )
2164 query
. flags
&= dns
. flags
. RD
2165 response
= dns
. message
. make_response ( query
)
2166 response
. answer
. append ( rrset
)
2167 # next query FROM A DIFFERENT CLIENT since RD is now set should NOT hit the cache
2168 for method
in ( "sendUDPQuery" , "sendTCPQuery" ):
2169 sender
= getattr ( self
, method
)
2170 ( receivedQuery
, receivedResponse
) = sender ( query
, response
)
2171 receivedQuery
. id = expectedQuery2
. id
2172 self
. checkMessageEDNSWithECS ( expectedQuery2
, receivedQuery
)
2173 self
. checkMessageNoEDNS ( receivedResponse
, response
)