]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: Add a regression test for Dynamic rules SetTag action
authorRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 7 May 2024 13:24:34 +0000 (15:24 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Thu, 16 May 2024 09:10:32 +0000 (11:10 +0200)
regression-tests.dnsdist/test_DynBlocksRatio.py

index 72d90bb8e9cda283f4f25e9e3d128f769b64012c..d239a3ad3d2d170830becf21f4a5d038e94a7a9a 100644 (file)
@@ -55,3 +55,90 @@ class TestDynBlockGroupCacheMissRatio(DynBlocksTest):
         """
         name = 'cachemissratio.group.dynblocks.tests.powerdns.com.'
         self.doTestCacheMissRatio(name, 3, 17)
+
+class TestDynBlockGroupCacheMissRatioSetTag(DynBlocksTest):
+
+    # we need this period to be quite long because we request the valid
+    # queries to be still looked at to reach the 20 queries count!
+    _dynBlockPeriod = 6
+    _config_params = ['_dynBlockPeriod', '_dynBlockDuration', '_testServerPort']
+    _config_template = """
+    local dbr = dynBlockRulesGroup()
+    dbr:setCacheMissRatio(0.8, %d, "Exceeded cache miss ratio", %d, 20, 0.0, DNSAction.SetTag, 0.0, { tagName='dyn-miss-ratio', tagValue='hit' })
+
+    -- on a cache miss, and if the cache miss ratio threshold was exceeded, send a REFUSED response
+    addCacheMissAction(TagRule('dyn-miss-ratio', 'hit'), RCodeAction(DNSRCode.REFUSED))
+
+    function maintenance()
+           dbr:apply()
+    end
+
+    newServer{address="127.0.0.1:%s"}
+    local pc = newPacketCache(1000, {maxTTL=86400, minTTL=1})
+    getPool(""):setCache(pc)
+    """
+
+    def testDynBlocksCacheMissRatio(self):
+        """
+        Dyn Blocks (group): Cache miss ratio with SetTag
+        """
+        name = 'cachemissratio-settag.group.dynblocks.tests.powerdns.com.'
+        rrset = dns.rrset.from_text(name,
+                                    60,
+                                    dns.rdataclass.IN,
+                                    dns.rdatatype.A,
+                                    '192.0.2.1')
+
+        cacheHits = 3
+        cacheMisses = 17
+        for idx in range(cacheMisses):
+            query = dns.message.make_query(str(idx) + '.' + name, 'A', 'IN')
+            response = dns.message.make_response(query)
+            response.answer.append(rrset)
+            (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
+            if receivedQuery:
+                receivedQuery.id = query.id
+                self.assertEqual(query, receivedQuery)
+                self.assertEqual(response, receivedResponse)
+            else:
+                # the query has not reached the responder,
+                # let's clear the response queue
+                self.clearToResponderQueue()
+
+        query = dns.message.make_query('0.' + name, 'A', 'IN')
+        response = dns.message.make_response(query)
+        response.answer.append(rrset)
+        for _ in range(cacheHits):
+            (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False)
+
+        waitForMaintenanceToRun()
+
+        # we should now get REFUSED for cache misses for up to self._dynBlockDuration + self._dynBlockPeriod
+
+        # cache miss
+        query = dns.message.make_query(str(cacheMisses + 1) + '.' + name, 'A', 'IN')
+        # dnsdist sets RA = RD for TC responses
+        query.flags &= ~dns.flags.RD
+        expectedResponse = dns.message.make_response(query)
+        expectedResponse.set_rcode(dns.rcode.REFUSED)
+        (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False, timeout=0.5)
+        self.assertEqual(receivedResponse, expectedResponse)
+
+        # but a cache hit should be OK
+        query = dns.message.make_query('0.' + name, 'A', 'IN')
+        expectedResponse = dns.message.make_response(query)
+        expectedResponse.answer.append(rrset)
+        (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False, timeout=0.5)
+        self.assertEqual(receivedResponse, expectedResponse)
+
+        # wait until we are not blocked anymore
+        time.sleep(self._dynBlockDuration + self._dynBlockPeriod)
+
+        # this one should succeed
+        query = dns.message.make_query(str(cacheMisses + 2) + '.' + name, 'A', 'IN')
+        response = dns.message.make_response(query)
+        response.answer.append(rrset)
+        (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
+        receivedQuery.id = query.id
+        self.assertEqual(query, receivedQuery)
+        self.assertEqual(response, receivedResponse)