]>
git.ipfire.org Git - thirdparty/pdns.git/blob - regression-tests.dnsdist/test_TCPKeepAlive.py
5 from dnsdisttests
import DNSDistTest
, range
7 class TestTCPKeepAlive(DNSDistTest
):
9 These tests make sure that dnsdist keeps the TCP connection alive
10 in various cases, like cache hits, self-generated answer, and
11 that it doesn't in error cases (Drop, invalid queries...)
15 _maxTCPQueriesPerConn
= 99
16 _maxTCPConnsPerClient
= 3
17 _maxTCPConnDuration
= 99
18 _config_template
= """
19 newServer{address="127.0.0.1:%s"}
21 setMaxTCPQueriesPerConnection(%s)
22 setMaxTCPConnectionsPerClient(%s)
23 setMaxTCPConnectionDuration(%s)
24 pc = newPacketCache(100, 86400, 1)
25 getPool(""):setCache(pc)
26 addAction("refused.tcpka.tests.powerdns.com.", RCodeAction(dnsdist.REFUSED))
27 addAction("dropped.tcpka.tests.powerdns.com.", DropAction())
28 addResponseAction("dropped-response.tcpka.tests.powerdns.com.", DropResponseAction())
29 -- create the pool named "nosuchpool"
31 addAction("nodownstream-servfail.tcpka.tests.powerdns.com.", PoolAction("nosuchpool"))
32 setServFailWhenNoServer(true)
34 _config_params
= ['_testServerPort', '_tcpIdleTimeout', '_maxTCPQueriesPerConn', '_maxTCPConnsPerClient', '_maxTCPConnDuration']
36 def testTCPKaSelfGenerated(self
):
38 TCP KeepAlive: Self-generated answer
40 name
= 'refused.tcpka.tests.powerdns.com.'
41 query
= dns
.message
.make_query(name
, 'A', 'IN')
42 expectedResponse
= dns
.message
.make_response(query
)
43 expectedResponse
.set_rcode(dns
.rcode
.REFUSED
)
45 conn
= self
.openTCPConnection()
50 self
.sendTCPQueryOverConnection(conn
, query
)
51 response
= self
.recvTCPResponseOverConnection(conn
)
54 self
.assertEquals(expectedResponse
, response
)
60 self
.assertEqual(count
, 5)
62 def testTCPKaCacheHit(self
):
64 TCP KeepAlive: Cache Hit
66 name
= 'cachehit.tcpka.tests.powerdns.com.'
67 query
= dns
.message
.make_query(name
, 'A', 'IN')
68 expectedResponse
= dns
.message
.make_response(query
)
69 rrset
= dns
.rrset
.from_text(name
,
74 expectedResponse
.answer
.append(rrset
)
76 # first query to fill the cache
77 (receivedQuery
, receivedResponse
) = self
.sendTCPQuery(query
, expectedResponse
)
78 self
.assertTrue(receivedQuery
)
79 self
.assertTrue(receivedResponse
)
80 receivedQuery
.id = query
.id
81 self
.assertEquals(query
, receivedQuery
)
82 self
.assertEquals(receivedResponse
, expectedResponse
)
84 conn
= self
.openTCPConnection()
89 self
.sendTCPQueryOverConnection(conn
, query
)
90 response
= self
.recvTCPResponseOverConnection(conn
)
93 self
.assertEquals(expectedResponse
, response
)
99 self
.assertEqual(count
, 5)
101 def testTCPKaNoDownstreamServFail(self
):
103 TCP KeepAlive: No downstream ServFail
105 The query is routed to a pool that has no server,
106 and dnsdist is configured to send a ServFail when
107 that happens. We should keep the TCP connection open.
109 name
= 'nodownstream-servfail.tcpka.tests.powerdns.com.'
110 query
= dns
.message
.make_query(name
, 'A', 'IN')
111 expectedResponse
= dns
.message
.make_response(query
)
112 expectedResponse
.set_rcode(dns
.rcode
.SERVFAIL
)
114 conn
= self
.openTCPConnection()
119 self
.sendTCPQueryOverConnection(conn
, query
)
120 response
= self
.recvTCPResponseOverConnection(conn
)
123 self
.assertEquals(expectedResponse
, response
)
129 self
.assertEqual(count
, 5)
131 def testTCPKaQRBitSet(self
):
133 TCP KeepAlive: QR bit set in question
135 name
= 'qrset.tcpka.tests.powerdns.com.'
136 query
= dns
.message
.make_query(name
, 'A', 'IN')
137 query
.flags |
= dns
.flags
.QR
139 conn
= self
.openTCPConnection()
144 self
.sendTCPQueryOverConnection(conn
, query
)
145 response
= self
.recvTCPResponseOverConnection(conn
)
153 self
.assertEqual(count
, 0)
155 def testTCPKaDrop(self
):
159 name
= 'dropped.tcpka.tests.powerdns.com.'
160 query
= dns
.message
.make_query(name
, 'A', 'IN')
161 query
.flags |
= dns
.flags
.QR
163 conn
= self
.openTCPConnection()
168 self
.sendTCPQueryOverConnection(conn
, query
)
169 response
= self
.recvTCPResponseOverConnection(conn
)
177 self
.assertEqual(count
, 0)
179 def testTCPKaDropResponse(self
):
181 TCP KeepAlive: Drop Response
183 name
= 'dropped-response.tcpka.tests.powerdns.com.'
184 query
= dns
.message
.make_query(name
, 'A', 'IN')
186 conn
= self
.openTCPConnection()
191 self
.sendTCPQueryOverConnection(conn
, query
)
192 response
= self
.recvTCPResponseOverConnection(conn
)
200 self
.assertEqual(count
, 0)
202 class TestTCPKeepAliveNoDownstreamDrop(DNSDistTest
):
204 This test makes sure that dnsdist drops the TCP connection
205 if no downstream server is available and setServFailWhenNoServer()
210 _maxTCPQueriesPerConn
= 99
211 _maxTCPConnsPerClient
= 3
212 _maxTCPConnDuration
= 99
213 _config_template
= """
214 newServer{address="127.0.0.1:%s"}
215 setTCPRecvTimeout(%s)
216 setMaxTCPQueriesPerConnection(%s)
217 setMaxTCPConnectionsPerClient(%s)
218 setMaxTCPConnectionDuration(%s)
219 -- create the pool named "nosuchpool"
220 getPool("nosuchpool")
221 addAction("nodownstream-drop.tcpka.tests.powerdns.com.", PoolAction("nosuchpool"))
223 _config_params
= ['_testServerPort', '_tcpIdleTimeout', '_maxTCPQueriesPerConn', '_maxTCPConnsPerClient', '_maxTCPConnDuration']
225 def testTCPKaNoDownstreamDrop(self
):
227 TCP KeepAlive: No downstream Drop
229 The query is routed to a pool that has no server,
230 and dnsdist is configured to drop the query when
231 that happens. We should close the TCP connection right away.
233 name
= 'nodownstream-drop.tcpka.tests.powerdns.com.'
234 query
= dns
.message
.make_query(name
, 'A', 'IN')
236 conn
= self
.openTCPConnection()
241 self
.sendTCPQueryOverConnection(conn
, query
)
242 response
= self
.recvTCPResponseOverConnection(conn
)
250 self
.assertEqual(count
, 0)