luaCtx.registerFunction("toString", &ServerPolicy::toString);
luaCtx.registerFunction("__tostring", &ServerPolicy::toString);
- static const std::array<ServerPolicy, 6> policies = {
- ServerPolicy{"firstAvailable", firstAvailable, false},
- ServerPolicy{"roundrobin", roundrobin, false},
- ServerPolicy{"wrandom", wrandom, false},
- ServerPolicy{"whashed", whashed, false},
- ServerPolicy{"chashed", chashed, false},
- ServerPolicy{"leastOutstanding", leastOutstanding, false}
+ const std::array<std::shared_ptr<ServerPolicy>, 6> policies = {
+ std::make_shared<ServerPolicy>("firstAvailable", firstAvailable, false),
+ std::make_shared<ServerPolicy>("roundrobin", roundrobin, false),
+ std::make_shared<ServerPolicy>("wrandom", wrandom, false),
+ std::make_shared<ServerPolicy>("whashed", whashed, false),
+ std::make_shared<ServerPolicy>("chashed", chashed, false),
+ std::make_shared<ServerPolicy>("leastOutstanding", leastOutstanding, false)
};
for (const auto& policy : policies) {
- luaCtx.writeVariable(policy.d_name, &policy);
+ luaCtx.writeVariable(policy->d_name, policy);
}
#endif /* DISABLE_POLICIES_BINDINGS */
(_, receivedResponse) = self.sendTCPQuery(query, response=None, useQueue=False)
self.assertEqual(receivedResponse, None)
+class RoundRobinTest(object):
+ def doTestRR(self, name):
+ """
+ Routing: Round Robin
+
+ Send 10 A queries to the requested name,
+ check that dnsdist routes half of it to each backend.
+ """
+ numberOfQueries = 10
+ name = name
+ 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)
+
+ # the round robin counter is shared for UDP and TCP,
+ # so we need to do UDP then TCP to have a clean count
+ for _ in range(numberOfQueries):
+ (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
+ receivedQuery.id = query.id
+ self.assertEqual(query, receivedQuery)
+ self.assertEqual(response, receivedResponse)
-class TestRoutingRoundRobinLB(DNSDistTest):
+ for _ in range(numberOfQueries):
+ (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
+ receivedQuery.id = query.id
+ self.assertEqual(query, receivedQuery)
+ self.assertEqual(response, receivedResponse)
+
+ for key in self._responsesCounter:
+ value = self._responsesCounter[key]
+ self.assertEqual(value, numberOfQueries / 2)
+
+class TestRoutingRoundRobinLB(RoundRobinTest, DNSDistTest):
_testServer2Port = pickAvailablePort()
_config_params = ['_testServerPort', '_testServer2Port']
Send 10 A queries to "rr.routing.tests.powerdns.com.",
check that dnsdist routes half of it to each backend.
"""
- numberOfQueries = 10
- name = 'rr.routing.tests.powerdns.com.'
- 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)
+ self.doTestRR('rr.routing.tests.powerdns.com.')
- # the round robin counter is shared for UDP and TCP,
- # so we need to do UDP then TCP to have a clean count
- for _ in range(numberOfQueries):
- (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
- receivedQuery.id = query.id
- self.assertEqual(query, receivedQuery)
- self.assertEqual(response, receivedResponse)
+class TestRoutingRoundRobinLBViaPool(RoundRobinTest, DNSDistTest):
- for _ in range(numberOfQueries):
- (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
- receivedQuery.id = query.id
- self.assertEqual(query, receivedQuery)
- self.assertEqual(response, receivedResponse)
+ _testServer2Port = pickAvailablePort()
+ _config_params = ['_testServerPort', '_testServer2Port']
+ _config_template = """
+ s1 = newServer{address="127.0.0.1:%d"}
+ s1:setUp()
+ s2 = newServer{address="127.0.0.1:%d"}
+ s2:setUp()
+ setPoolServerPolicy(roundrobin, '')
+ """
- for key in self._responsesCounter:
- value = self._responsesCounter[key]
- self.assertEqual(value, numberOfQueries / 2)
+ @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 testRR(self):
+ """
+ Routing: Round Robin (pool)
+
+ Send 10 A queries to "rr-pool.routing.tests.powerdns.com.",
+ check that dnsdist routes half of it to each backend.
+ """
+ self.doTestRR('rr-pool.routing.tests.powerdns.com.')
class TestRoutingRoundRobinLBOneDown(DNSDistTest):
(_, receivedResponse) = sender(query, response=None, useQueue=False)
self.assertEqual(receivedResponse, None)
-class TestRoutingLuaFFIPerThreadRoundRobinLB(DNSDistTest):
+class TestRoutingLuaFFIPerThreadRoundRobinLB(RoundRobinTest, DNSDistTest):
_testServer2Port = pickAvailablePort()
_config_params = ['_testServerPort', '_testServer2Port']
def testRR(self):
"""
- Routing: Round Robin
-
- Send 10 A queries to "rr.routing.tests.powerdns.com.",
- check that dnsdist routes half of it to each backend.
+ Routing: Round Robin (LuaFFI)
"""
- numberOfQueries = 10
- name = 'rr.routing.tests.powerdns.com.'
- 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)
+ self.doTestRR('rr-luaffi.routing.tests.powerdns.com.')
- # the round robin counter is shared for UDP and TCP,
- # so we need to do UDP then TCP to have a clean count
- for _ in range(numberOfQueries):
- (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
- receivedQuery.id = query.id
- self.assertEqual(query, receivedQuery)
- self.assertEqual(response, receivedResponse)
+class TestRoutingCustomLuaRoundRobinLB(RoundRobinTest, DNSDistTest):
- for _ in range(numberOfQueries):
- (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
- receivedQuery.id = query.id
- self.assertEqual(query, receivedQuery)
- self.assertEqual(response, receivedResponse)
+ _testServer2Port = pickAvailablePort()
+ _config_params = ['_testServerPort', '_testServer2Port']
+ _config_template = """
+ -- otherwise we start too many TCP workers, and as each thread
+ -- uses it own counter this makes the TCP queries distribution hard to predict
+ setMaxTCPClientThreads(1)
- for key in self._responsesCounter:
- value = self._responsesCounter[key]
- self.assertEqual(value, numberOfQueries / 2)
+ local counter = 0
+ function luaroundrobin(servers_list, dq)
+ counter = counter + 1
+ return servers_list[(counter %% #servers_list)+1]
+ end
+ setServerPolicy(newServerPolicy("custom lua round robin policy", luaroundrobin))
+
+ s1 = newServer{address="127.0.0.1:%s"}
+ s1:setUp()
+ s2 = newServer{address="127.0.0.1:%s"}
+ 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 testRR(self):
+ """
+ Routing: Round Robin (Lua)
+ """
+ self.doTestRR('rr-lua.routing.tests.powerdns.com.')
class TestRoutingOrder(DNSDistTest):