]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
pipelined test: we no longer have -Tdelay option, use a python proxy that delays...
authorWitold Kręcicki <wpk@isc.org>
Tue, 21 Jan 2020 09:54:38 +0000 (10:54 +0100)
committerWitold Kręcicki <wpk@isc.org>
Wed, 22 Jan 2020 11:16:59 +0000 (12:16 +0100)
bin/tests/system/pipelined/ans5/ans.py [new file with mode: 0644]
bin/tests/system/pipelined/ns1/root.db
bin/tests/system/pipelined/ns2/examplea.db
bin/tests/system/pipelined/ns3/named.args [deleted file]
bin/tests/system/pipelined/prereq.sh [new file with mode: 0644]
util/copyrights

diff --git a/bin/tests/system/pipelined/ans5/ans.py b/bin/tests/system/pipelined/ans5/ans.py
new file mode 100644 (file)
index 0000000..1ebf328
--- /dev/null
@@ -0,0 +1,194 @@
+############################################################################
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+############################################################################
+
+############################################################################
+#
+# This tool acts as a TCP/UDP proxy and delays all incoming packets by 500
+# miliseconds.
+#
+# We use it to check pipelining - a client sents 8 questions over a
+# pipelined connection - that require asking a normal (examplea) and a
+# slow-responding (exampleb) servers:
+# a.examplea
+# a.exampleb
+# b.examplea
+# b.exampleb
+# c.examplea
+# c.exampleb
+# d.examplea
+# d.exampleb
+#
+# If pipelining works properly the answers will be returned out of order
+# with all answers from examplea returned first, and then all answers
+# from exampleb.
+#
+############################################################################
+
+from __future__ import print_function
+
+import datetime
+import os
+import select
+import signal
+import socket
+import sys
+import time
+import threading
+import struct
+
+DELAY = 0.5
+THREADS = []
+
+def log(msg):
+    print(datetime.datetime.now().strftime('%d-%b-%Y %H:%M:%S.%f ') + msg)
+
+
+def sigterm(*_):
+    log('SIGTERM received, shutting down')
+    for thread in THREADS:
+        thread.close()
+        thread.join()
+    os.remove('ans.pid')
+    sys.exit(0)
+
+class TCPDelayer(threading.Thread):
+    """ For a given TCP connection conn we open a connection to (ip, port),
+        and then we delay each incoming packet by DELAY by putting it in a
+        queue.
+        In the pipelined test TCP should not be used, but it's here for
+        completnes.
+    """
+    def __init__(self, conn, ip, port):
+        threading.Thread.__init__(self)
+        self.conn = conn
+        self.cconn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        self.cconn.connect((ip, port))
+        self.queue = []
+        self.running = True
+
+    def close(self):
+        self.running = False
+
+    def run(self):
+        while self.running:
+            curr_timeout = 0.5
+            try:
+                curr_timeout = self.queue[0][0]-time.time()
+            except StopIteration:
+                pass
+            if curr_timeout > 0:
+                if curr_timeout == 0:
+                    curr_timeout = 0.5
+                rfds, _, _ = select.select([self.conn, self.cconn], [], [], curr_timeout)
+                if self.conn in rfds:
+                    data = self.conn.recv(65535)
+                    if not data:
+                        return
+                    self.queue.append((time.time() + DELAY, data))
+                if self.cconn in rfds:
+                    data = self.cconn.recv(65535)
+                    if not data == 0:
+                        return
+                    self.conn.send(data)
+            try:
+                while self.queue[0][0]-time.time() < 0:
+                    _, data = self.queue.pop(0)
+                    self.cconn.send(data)
+            except StopIteration:
+                pass
+
+class UDPDelayer(threading.Thread):
+    """ Every incoming UDP packet is put in a queue for DELAY time, then
+        it's sent to (ip, port). We remember the query id to send the
+        response we get to a proper source, responsed are not delayed.
+    """
+    def __init__(self, usock, ip, port):
+        threading.Thread.__init__(self)
+        self.sock = usock
+        self.csock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+        self.dst = (ip, port)
+        self.queue = []
+        self.qid_mapping = {}
+        self.running = True
+
+    def close(self):
+        self.running = False
+
+    def run(self):
+        while self.running:
+            curr_timeout = 0.5
+            if self.queue:
+                curr_timeout = self.queue[0][0]-time.time()
+            if curr_timeout >= 0:
+                if curr_timeout == 0:
+                    curr_timeout = 0.5
+                rfds, _, _ = select.select([self.sock, self.csock], [], [], curr_timeout)
+                if self.sock in rfds:
+                    data, addr = self.sock.recvfrom(65535)
+                    if not data:
+                        return
+                    self.queue.append((time.time() + DELAY, data))
+                    qid = struct.unpack('>H', data[:2])[0]
+                    log('Received a query from %s, queryid %d' % (str(addr), qid))
+                    self.qid_mapping[qid] = addr
+                if self.csock in rfds:
+                    data, addr = self.csock.recvfrom(65535)
+                    if not data:
+                        return
+                    qid = struct.unpack('>H', data[:2])[0]
+                    dst = self.qid_mapping.get(qid)
+                    if dst is not None:
+                        self.sock.sendto(data, dst)
+                        log('Received a response from %s, queryid %d, sending to %s' % (str(addr), qid, str(dst)))
+            while self.queue and self.queue[0][0]-time.time() < 0:
+                _, data = self.queue.pop(0)
+                qid = struct.unpack('>H', data[:2])[0]
+                log('Sending a query to %s, queryid %d' % (str(self.dst), qid))
+                self.csock.sendto(data, self.dst)
+
+def main():
+    signal.signal(signal.SIGTERM, sigterm)
+    signal.signal(signal.SIGINT, sigterm)
+
+    with open('ans.pid', 'w') as pidfile:
+        print(os.getpid(), file=pidfile)
+
+    listenip = '10.53.0.5'
+    serverip = '10.53.0.2'
+
+    try:
+        port = int(os.environ['PORT'])
+    except KeyError:
+        port = 5300
+
+    log('Listening on %s:%d' % (listenip, port))
+
+    usock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+    usock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+    usock.bind((listenip, port))
+    thread = UDPDelayer(usock, serverip, port)
+    thread.start()
+    THREADS.append(thread)
+
+    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+    sock.bind((listenip, port))
+    sock.listen(1)
+
+    while True:
+        (clientsock, _) = sock.accept()
+        log('Accepted connection from %s' % clientsock)
+        thread = TCPDelayer(clientsock, serverip, port)
+        thread.start()
+        THREADS.append(thread)
+
+if __name__ == '__main__':
+    main()
index 2cddcd234395ed39862820cc62e572a6871184ec..dfa7e8c7fc42e82a4bf7650df1a697ff3ce2cd27 100644 (file)
@@ -19,7 +19,7 @@ $TTL 300
 a.root-servers.nil.    A       10.53.0.1
 
 examplea.              NS      ns2.examplea.
-ns2.examplea.          A       10.53.0.2
+ns2.examplea.          A       10.53.0.5
 
 exampleb.              NS      ns3.exampleb.
 ns3.exampleb.          A       10.53.0.3
index 9f0427e1781abdb1ba809794cba75d2d08d2235a..3522d46eb983b1497a59713dbb0bee263271fc8c 100644 (file)
@@ -17,7 +17,7 @@ examplea              IN SOA  mname1. . (
                                3600       ; minimum (1 hour)
                                )
 examplea.              NS      ns2.examplea.
-ns2.examplea.          A       10.53.0.2
+ns2.examplea.          A       10.53.0.5
 
 $ORIGIN examplea.
 a                      A       10.0.1.1
diff --git a/bin/tests/system/pipelined/ns3/named.args b/bin/tests/system/pipelined/ns3/named.args
deleted file mode 100644 (file)
index bd8140b..0000000
+++ /dev/null
@@ -1 +0,0 @@
--m record,size,mctx -c named.conf -d 99 -D pipelined-ns3 -X named.lock -g -T delay=200
diff --git a/bin/tests/system/pipelined/prereq.sh b/bin/tests/system/pipelined/prereq.sh
new file mode 100644 (file)
index 0000000..81c05c5
--- /dev/null
@@ -0,0 +1,29 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+if test -n "$PYTHON"
+then
+    if $PYTHON -c "import dns" 2> /dev/null
+    then
+        :
+    else
+        echo_i "This test requires the dnspython module." >&2
+        exit 1
+    fi
+else
+    echo_i "This test requires Python and the dnspython module." >&2
+    exit 1
+fi
+
+exit 0
index 12bcf80b2026e1c86e2f2251b89eff855f8bfab2..40ab641f557977d7bbe09d3964e37f93ae50dfc7 100644 (file)
 ./bin/tests/system/pending/ns2/sign.sh         SH      2009,2010,2012,2014,2016,2017,2018,2019,2020
 ./bin/tests/system/pending/setup.sh            SH      2009,2012,2014,2016,2017,2018,2019,2020
 ./bin/tests/system/pending/tests.sh            SH      2009,2010,2012,2015,2016,2018,2019,2020
+./bin/tests/system/pipelined/ans5/ans.py       PYTHON  2020
 ./bin/tests/system/pipelined/clean.sh          SH      2014,2015,2016,2018,2019,2020
 ./bin/tests/system/pipelined/input             X       2014,2015,2018,2019,2020
 ./bin/tests/system/pipelined/inputb            X       2014,2015,2018,2019,2020
-./bin/tests/system/pipelined/ns3/named.args    X       2014,2015,2018,2019,2020
 ./bin/tests/system/pipelined/pipequeries.c     C       2014,2015,2015,2016,2017,2018,2019,2020
+./bin/tests/system/pipelined/prereq.sh         SH      2020
 ./bin/tests/system/pipelined/ref               X       2014,2015,2018,2019,2020
 ./bin/tests/system/pipelined/refb              X       2014,2015,2018,2019,2020
 ./bin/tests/system/pipelined/setup.sh          SH      2014,2015,2016,2017,2018,2019,2020