void dnsdist_ffi_dnsresponse_set_max_returned_ttl(dnsdist_ffi_dnsresponse_t* dr, uint32_t max) __attribute__ ((visibility ("default")));
void dnsdist_ffi_dnsresponse_clear_records_type(dnsdist_ffi_dnsresponse_t* dr, uint16_t qtype) __attribute__ ((visibility ("default")));
bool dnsdist_ffi_dnsresponse_rebase(dnsdist_ffi_dnsresponse_t* dr, const char* initialName, size_t initialNameSize) __attribute__ ((visibility ("default")));
+bool dnsdist_ffi_dnsresponse_get_stale_cache_hit(const dnsdist_ffi_dnsresponse_t* dr) __attribute__ ((visibility ("default")));
bool dnsdist_ffi_dnsquestion_set_async(dnsdist_ffi_dnsquestion_t* dq, uint16_t asyncID, uint16_t queryID, uint32_t timeoutMs) __attribute__ ((visibility ("default")));
bool dnsdist_ffi_dnsresponse_set_async(dnsdist_ffi_dnsquestion_t* dq, uint16_t asyncID, uint16_t queryID, uint32_t timeoutMs) __attribute__ ((visibility ("default")));
If the value is really needed while the response is being processed, it is possible to set a tag while the query is processed, as tags will be passed to the response object.
It also has additional methods:
- .. method:: DNSResponse.getSelectedBackend() -> Server
+ .. method:: DNSResponse:getSelectedBackend() -> Server
.. versionadded:: 1.9.0
Get the selected backend :class:`Server` or nil
+ .. method:: DNSResponse:getStaleCacheHit() -> bool
+
+ .. versionadded:: 2.0.0
+
+ Get the indicator of whether the cache lookup hit a stale entry.
+
.. method:: DNSResponse:editTTLs(func)
The function ``func`` is invoked for every entry in the answer, authority and additional section.
TestCacheHitResponses._responsesCounter[key] = 0
self.assertEqual(total, 2)
+
+class TestStaleCacheHitResponses(DNSDistTest):
+
+ _consoleKey = DNSDistTest.generateConsoleKey()
+ _consoleKeyB64 = base64.b64encode(_consoleKey).decode('ascii')
+ _config_params = ['_consoleKeyB64', '_consolePort', '_testServerPort']
+ _config_template = """
+ pc = newPacketCache(100, {maxTTL=86400, minTTL=1})
+ getPool(""):setCache(pc)
+ setStaleCacheEntriesTTL(600)
+ setKey("%s")
+ controlSocket("127.0.0.1:%d")
+ newServer{address="127.0.0.1:%s"}
+ function hitCache(dr) if dr:getStaleCacheHit() then return DNSResponseAction.Drop end return DNSResponseAction.None end
+ addCacheHitResponseAction(SuffixMatchNodeRule("dropstaleentry.cachehitresponses.tests.powerdns.com."), LuaResponseAction(hitCache))
+ """
+
+ def testDroppedWhenStaleCached(self):
+ """
+ CacheHitResponse: Drop when served from the stale cache entry
+ """
+ ttl = 5
+ name = 'dropstaleentry.cachehitresponses.tests.powerdns.com.'
+ query = dns.message.make_query(name, 'AAAA', 'IN')
+ response = dns.message.make_response(query)
+ rrset = dns.rrset.from_text(name,
+ ttl,
+ dns.rdataclass.IN,
+ dns.rdatatype.AAAA,
+ '::1')
+ response.answer.append(rrset)
+
+ # first query to fill the cache
+ (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
+ self.assertTrue(receivedQuery)
+ self.assertTrue(receivedResponse)
+ receivedQuery.id = query.id
+ self.assertEqual(query, receivedQuery)
+ self.assertEqual(receivedResponse, response)
+
+ # mark server down
+ self.sendConsoleCommand("getServer(0):setDown()")
+
+ # next query should hit the cache within ttl
+ (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
+ self.assertEqual(receivedResponse, response)
+
+ time.sleep(ttl + 1)
+
+ # further query should hit stale cache thus dropped
+ (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
+ self.assertEqual(receivedResponse, None)