From: Remi Gacogne Date: Fri, 6 Dec 2024 10:27:13 +0000 (+0100) Subject: dnsdist: Add a regression tests for whashed and chashed X-Git-Tag: rec-5.2.0-rc1~6^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c7557bb12bf597c49bd6998854df88df2e80732e;p=thirdparty%2Fpdns.git dnsdist: Add a regression tests for whashed and chashed --- diff --git a/regression-tests.dnsdist/test_Routing.py b/regression-tests.dnsdist/test_Routing.py index 4ee5e7d570..cabbf21ef9 100644 --- a/regression-tests.dnsdist/test_Routing.py +++ b/regression-tests.dnsdist/test_Routing.py @@ -599,9 +599,9 @@ class TestFirstAvailableQPSPacketCacheHits(DNSDistTest): self.assertEqual(receivedResponse, response) # 4 queries should made it through, 2 UDP and 2 TCP - for k,v in self._responsesCounter.items(): - print(k) - print(v) + #for k,v in self._responsesCounter.items(): + # print(k) + # print(v) if 'UDP Responder' in self._responsesCounter: self.assertEqual(self._responsesCounter['UDP Responder'], 0) @@ -808,6 +808,168 @@ class TestRoutingHighValueWRandom(DNSDistTest): if 'TCP Responder 2' in self._responsesCounter: self.assertEqual(self._responsesCounter['TCP Responder 2'], numberOfQueries - self._responsesCounter['TCP Responder']) +class TestRoutingWHashed(DNSDistTest): + + _testServer2Port = pickAvailablePort() + _config_params = ['_testServerPort', '_testServer2Port'] + _config_template = """ + setServerPolicy(whashed) + setWeightedBalancingFactor(1.5) + -- this is the default, but let's ensure we can reset it to the initial value + setWeightedBalancingFactor(0) + s1 = newServer{address="127.0.0.1:%s", weight=1} + s1:setUp() + s2 = newServer{address="127.0.0.1:%s", weight=1} + s2:setUp() + """ + + @classmethod + def startResponders(cls): + print("Launching responders..") + cls._UDPResponder = threading.Thread(name='UDP Responder', target=cls.UDPResponder, args=[cls._testServerPort, cls._toResponderQueue, cls._fromResponderQueue]) + cls._UDPResponder.daemon = True + cls._UDPResponder.start() + cls._UDPResponder2 = threading.Thread(name='UDP Responder 2', target=cls.UDPResponder, args=[cls._testServer2Port, cls._toResponderQueue, cls._fromResponderQueue]) + cls._UDPResponder2.daemon = True + cls._UDPResponder2.start() + + cls._TCPResponder = threading.Thread(name='TCP Responder', target=cls.TCPResponder, args=[cls._testServerPort, cls._toResponderQueue, cls._fromResponderQueue]) + cls._TCPResponder.daemon = True + cls._TCPResponder.start() + + cls._TCPResponder2 = threading.Thread(name='TCP Responder 2', target=cls.TCPResponder, args=[cls._testServer2Port, cls._toResponderQueue, cls._fromResponderQueue]) + cls._TCPResponder2.daemon = True + cls._TCPResponder2.start() + + def testHashed(self): + """ + Routing: WHashed + + Send 100 A queries to ".whashed.routing.tests.powerdns.com.", + check that dnsdist routes at least 25% to each backend (hashing + will not be perfect, especially with so few datapoints, but still). + """ + numberOfQueries = 100 + suffix = 'whashed.routing.tests.powerdns.com.' + + # the counter is shared for UDP and TCP, + # so we need to do UDP then TCP to have a clean count + for idx in range(numberOfQueries): + name = str(idx) + '.udp.' + suffix + query = dns.message.make_query(name, 'A', 'IN') + response = dns.message.make_response(query) + rrset = dns.rrset.from_text(name, + 60, + dns.rdataclass.IN, + dns.rdatatype.A, + '192.0.2.1') + response.answer.append(rrset) + (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) + receivedQuery.id = query.id + self.assertEqual(query, receivedQuery) + self.assertEqual(response, receivedResponse) + + for idx in range(numberOfQueries): + name = str(idx) + '.tcp.' + suffix + query = dns.message.make_query(name, 'A', 'IN') + response = dns.message.make_response(query) + rrset = dns.rrset.from_text(name, + 60, + dns.rdataclass.IN, + dns.rdatatype.A, + '192.0.2.1') + response.answer.append(rrset) + (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response) + receivedQuery.id = query.id + self.assertEqual(query, receivedQuery) + self.assertEqual(response, receivedResponse) + + self.assertGreater(self._responsesCounter['UDP Responder'], numberOfQueries * 0.25) + self.assertGreater(self._responsesCounter['TCP Responder'], numberOfQueries * 0.25) + self.assertGreater(self._responsesCounter['UDP Responder 2'], numberOfQueries * 0.25) + self.assertGreater(self._responsesCounter['TCP Responder 2'], numberOfQueries * 0.25) + +class TestRoutingCHashed(DNSDistTest): + + _testServer2Port = pickAvailablePort() + _config_params = ['_testServerPort', '_testServer2Port'] + _config_template = """ + setServerPolicy(chashed) + setConsistentHashingBalancingFactor(1.5) + -- this is the default, but let's ensure we can reset it to the initial value + setConsistentHashingBalancingFactor(0) + s1 = newServer{address="127.0.0.1:%s", weight=1000} + s1:setUp() + s2 = newServer{address="127.0.0.1:%s", weight=1000} + s2:setUp() + """ + + @classmethod + def startResponders(cls): + print("Launching responders..") + cls._UDPResponder = threading.Thread(name='UDP Responder', target=cls.UDPResponder, args=[cls._testServerPort, cls._toResponderQueue, cls._fromResponderQueue]) + cls._UDPResponder.daemon = True + cls._UDPResponder.start() + cls._UDPResponder2 = threading.Thread(name='UDP Responder 2', target=cls.UDPResponder, args=[cls._testServer2Port, cls._toResponderQueue, cls._fromResponderQueue]) + cls._UDPResponder2.daemon = True + cls._UDPResponder2.start() + + cls._TCPResponder = threading.Thread(name='TCP Responder', target=cls.TCPResponder, args=[cls._testServerPort, cls._toResponderQueue, cls._fromResponderQueue]) + cls._TCPResponder.daemon = True + cls._TCPResponder.start() + + cls._TCPResponder2 = threading.Thread(name='TCP Responder 2', target=cls.TCPResponder, args=[cls._testServer2Port, cls._toResponderQueue, cls._fromResponderQueue]) + cls._TCPResponder2.daemon = True + cls._TCPResponder2.start() + + def testHashed(self): + """ + Routing: CHashed + + Send 100 A queries to ".chashed.routing.tests.powerdns.com.", + check that dnsdist routes at least 25% to each backend (hashing + will not be perfect, especially with so few datapoints, but still). + """ + numberOfQueries = 100 + suffix = 'chashed.routing.tests.powerdns.com.' + + # the counter is shared for UDP and TCP, + # so we need to do UDP then TCP to have a clean count + for idx in range(numberOfQueries): + name = str(idx) + '.udp.' + suffix + query = dns.message.make_query(name, 'A', 'IN') + response = dns.message.make_response(query) + rrset = dns.rrset.from_text(name, + 60, + dns.rdataclass.IN, + dns.rdatatype.A, + '192.0.2.1') + response.answer.append(rrset) + (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) + receivedQuery.id = query.id + self.assertEqual(query, receivedQuery) + self.assertEqual(response, receivedResponse) + + for idx in range(numberOfQueries): + name = str(idx) + '.tcp.' + suffix + query = dns.message.make_query(name, 'A', 'IN') + response = dns.message.make_response(query) + rrset = dns.rrset.from_text(name, + 60, + dns.rdataclass.IN, + dns.rdatatype.A, + '192.0.2.1') + response.answer.append(rrset) + (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response) + receivedQuery.id = query.id + self.assertEqual(query, receivedQuery) + self.assertEqual(response, receivedResponse) + + self.assertGreater(self._responsesCounter['UDP Responder'], numberOfQueries * 0.25) + self.assertGreater(self._responsesCounter['TCP Responder'], numberOfQueries * 0.25) + self.assertGreater(self._responsesCounter['UDP Responder 2'], numberOfQueries * 0.25) + self.assertGreater(self._responsesCounter['TCP Responder 2'], numberOfQueries * 0.25) + class TestRoutingLuaFFILBNoServer(DNSDistTest): _config_template = """