]> git.ipfire.org Git - thirdparty/pdns.git/blob - regression-tests.dnsdist/test_TCPLimits.py
Merge pull request #13914 from rgacogne/ddist-fix-xsk-error
[thirdparty/pdns.git] / regression-tests.dnsdist / test_TCPLimits.py
1 #!/usr/bin/env python
2 import struct
3 import time
4 import dns
5 from dnsdisttests import DNSDistTest, pickAvailablePort
6
7 try:
8 range = xrange
9 except NameError:
10 pass
11
12 class TestTCPLimits(DNSDistTest):
13
14 # this test suite uses a different responder port
15 # because it uses a different health check configuration
16 _testServerPort = pickAvailablePort()
17 _answerUnexpected = True
18
19 _tcpIdleTimeout = 2
20 _maxTCPQueriesPerConn = 5
21 _maxTCPConnsPerClient = 3
22 _maxTCPConnDuration = 5
23 _config_template = """
24 newServer{address="127.0.0.1:%s"}
25 setTCPRecvTimeout(%s)
26 setMaxTCPQueriesPerConnection(%s)
27 setMaxTCPConnectionsPerClient(%s)
28 setMaxTCPConnectionDuration(%s)
29 """
30 _config_params = ['_testServerPort', '_tcpIdleTimeout', '_maxTCPQueriesPerConn', '_maxTCPConnsPerClient', '_maxTCPConnDuration']
31 _verboseMode = True
32
33 def testTCPQueriesPerConn(self):
34 """
35 TCP Limits: Maximum number of queries
36 """
37 name = 'maxqueriesperconn.tcp.tests.powerdns.com.'
38 query = dns.message.make_query(name, 'A', 'IN')
39 conn = self.openTCPConnection()
40
41 count = 0
42 for idx in range(self._maxTCPQueriesPerConn):
43 try:
44 self.sendTCPQueryOverConnection(conn, query)
45 response = self.recvTCPResponseOverConnection(conn)
46 self.assertTrue(response)
47 count = count + 1
48 except:
49 pass
50
51 # this one should fail
52 failed = False
53 try:
54 self.sendTCPQueryOverConnection(conn, query)
55 response = self.recvTCPResponseOverConnection(conn)
56 self.assertFalse(response)
57 if not response:
58 failed = True
59 else:
60 count = count + 1
61 except:
62 failed = True
63
64 conn.close()
65 self.assertTrue(failed)
66 self.assertEqual(count, self._maxTCPQueriesPerConn)
67
68 def testTCPConnsPerClient(self):
69 """
70 TCP Limits: Maximum number of conns per client
71 """
72 name = 'maxconnsperclient.tcp.tests.powerdns.com.'
73 query = dns.message.make_query(name, 'A', 'IN')
74 conns = []
75
76 for idx in range(self._maxTCPConnsPerClient + 1):
77 conns.append(self.openTCPConnection())
78
79 count = 0
80 failed = 0
81 for conn in conns:
82 try:
83 self.sendTCPQueryOverConnection(conn, query)
84 response = self.recvTCPResponseOverConnection(conn)
85 if response:
86 count = count + 1
87 else:
88 failed = failed + 1
89 except:
90 failed = failed + 1
91
92 for conn in conns:
93 conn.close()
94
95 # wait a bit to be sure that dnsdist closed the connections
96 # and decremented the counters on its side, otherwise subsequent
97 # connections will be dropped
98 time.sleep(1)
99
100 self.assertEqual(count, self._maxTCPConnsPerClient)
101 self.assertEqual(failed, 1)
102
103 def testTCPDuration(self):
104 """
105 TCP Limits: Maximum duration
106 """
107 name = 'duration.tcp.tests.powerdns.com.'
108
109 start = time.time()
110 conn = self.openTCPConnection()
111 # immediately send the maximum size
112 conn.send(struct.pack("!H", 65535))
113
114 count = 0
115 while count < (self._maxTCPConnDuration * 20):
116 try:
117 # sleeping for only one second keeps us below the
118 # idle timeout (setTCPRecvTimeout())
119 time.sleep(0.1)
120 conn.send(b'A')
121 count = count + 1
122 except Exception as e:
123 print("Exception: %s!" % (e))
124 break
125
126 end = time.time()
127
128 self.assertAlmostEqual(count / 10, self._maxTCPConnDuration, delta=2)
129 self.assertAlmostEqual(end - start, self._maxTCPConnDuration, delta=2)
130
131 conn.close()
132
133 class TestTCPFrontendLimits(DNSDistTest):
134
135 # this test suite uses a different responder port
136 # because it uses a different health check configuration
137 _testServerPort = pickAvailablePort()
138 _answerUnexpected = True
139
140 _skipListeningOnCL = True
141 _tcpIdleTimeout = 2
142 _maxTCPConnsPerFrontend = 10
143 _config_template = """
144 newServer{address="127.0.0.1:%s"}
145 setLocal("%s:%d", {maxConcurrentTCPConnections=%d})
146 """
147 _config_params = ['_testServerPort', '_dnsDistListeningAddr', '_dnsDistPort', '_maxTCPConnsPerFrontend']
148 _verboseMode = True
149
150 def testTCPConnsPerFrontend(self):
151 """
152 TCP Frontend Limits: Maximum number of conns per frontend
153 """
154 name = 'maxconnsperfrontend.tcp.tests.powerdns.com.'
155 query = dns.message.make_query(name, 'A', 'IN')
156 conns = []
157
158 for idx in range(self._maxTCPConnsPerFrontend + 1):
159 conns.append(self.openTCPConnection())
160
161 count = 0
162 failed = 0
163 for conn in conns:
164 try:
165 self.sendTCPQueryOverConnection(conn, query)
166 response = self.recvTCPResponseOverConnection(conn)
167 if response:
168 count = count + 1
169 else:
170 failed = failed + 1
171 except:
172 failed = failed + 1
173
174 for conn in conns:
175 conn.close()
176
177 # wait a bit to be sure that dnsdist closed the connections
178 # and decremented the counters on its side, otherwise subsequent
179 # connections will be dropped
180 time.sleep(1)
181
182 self.assertEqual(count, self._maxTCPConnsPerFrontend)
183 self.assertEqual(failed, 1)