1#!/bin/sh 2# 3# Copyright (C) Internet Systems Consortium, Inc. ("ISC") 4# 5# This Source Code Form is subject to the terms of the Mozilla Public 6# License, v. 2.0. If a copy of the MPL was not distributed with this 7# file, You can obtain one at http://mozilla.org/MPL/2.0/. 8# 9# See the COPYRIGHT file distributed with this work for additional 10# information regarding copyright ownership. 11 12set -e 13 14SYSTEMTESTTOP=.. 15# shellcheck source=../conf.sh 16. "$SYSTEMTESTTOP/conf.sh" 17 18dig_with_opts() { 19 "${DIG}" -p "${PORT}" "$@" 20} 21 22rndccmd() { 23 "${RNDC}" -p "${CONTROLPORT}" -c ../common/rndc.conf -s "$@" 24} 25 26status=0 27n=0 28 29n=$((n + 1)) 30echo_i "initializing TCP statistics ($n)" 31ret=0 32rndccmd 10.53.0.1 stats || ret=1 33rndccmd 10.53.0.2 stats || ret=1 34mv ns1/named.stats ns1/named.stats.test$n 35mv ns2/named.stats ns2/named.stats.test$n 36ntcp10="$(grep "TCP requests received" ns1/named.stats.test$n | tail -1 | awk '{print $1}')" 37ntcp20="$(grep "TCP requests received" ns2/named.stats.test$n | tail -1 | awk '{print $1}')" 38if [ $ret != 0 ]; then echo_i "failed"; fi 39status=$((status + ret)) 40 41n=$((n + 1)) 42echo_i "checking TCP request statistics (resolver) ($n)" 43ret=0 44dig_with_opts @10.53.0.3 txt.example. > dig.out.test$n 45sleep 1 46rndccmd 10.53.0.1 stats || ret=1 47rndccmd 10.53.0.2 stats || ret=1 48mv ns1/named.stats ns1/named.stats.test$n 49mv ns2/named.stats ns2/named.stats.test$n 50ntcp11="$(grep "TCP requests received" ns1/named.stats.test$n | tail -1 | awk '{print $1}')" 51ntcp21="$(grep "TCP requests received" ns2/named.stats.test$n | tail -1 | awk '{print $1}')" 52if [ "$ntcp10" -ge "$ntcp11" ]; then ret=1; fi 53if [ "$ntcp20" -ne "$ntcp21" ]; then ret=1; fi 54if [ $ret != 0 ]; then echo_i "failed"; fi 55status=$((status + ret)) 56 57n=$((n + 1)) 58echo_i "checking TCP request statistics (forwarder) ($n)" 59ret=0 60dig_with_opts @10.53.0.4 txt.example. > dig.out.test$n 61sleep 1 62rndccmd 10.53.0.1 stats || ret=1 63rndccmd 10.53.0.2 stats || ret=1 64mv ns1/named.stats ns1/named.stats.test$n 65mv ns2/named.stats ns2/named.stats.test$n 66ntcp12="$(grep "TCP requests received" ns1/named.stats.test$n | tail -1 | awk '{print $1}')" 67ntcp22="$(grep "TCP requests received" ns2/named.stats.test$n | tail -1 | awk '{print $1}')" 68if [ "$ntcp11" -ne "$ntcp12" ]; then ret=1; fi 69if [ "$ntcp21" -ge "$ntcp22" ];then ret=1; fi 70if [ $ret != 0 ]; then echo_i "failed"; fi 71status=$((status + ret)) 72 73# -------- TCP high-water tests ---------- 74refresh_tcp_stats() { 75 rndccmd 10.53.0.5 status > rndc.out.$n || ret=1 76 TCP_CUR="$(sed -n "s/^tcp clients: \([0-9][0-9]*\).*/\1/p" rndc.out.$n)" 77 TCP_LIMIT="$(sed -n "s/^tcp clients: .*\/\([0-9][0-9]*\)/\1/p" rndc.out.$n)" 78 TCP_HIGH="$(sed -n "s/^TCP high-water: \([0-9][0-9]*\)/\1/p" rndc.out.$n)" 79} 80 81# Send a command to the tool script listening on 10.53.0.6. 82send_command() { 83 nextpart ans6/ans.run > /dev/null 84 echo "$*" | "${PERL}" "${SYSTEMTESTTOP}/send.pl" 10.53.0.6 "${CONTROLPORT}" 85 wait_for_log_peek 10 "result=" ans6/ans.run || ret=1 86 if ! nextpartpeek ans6/ans.run | grep -qF "result=OK"; then 87 return 1 88 fi 89} 90 91# Instructs ans6 to open $1 TCP connections to 10.53.0.5. 92open_connections() { 93 send_command "open" "${1}" 10.53.0.5 "${PORT}" || return 1 94} 95 96# Instructs ans6 to close $1 TCP connections to 10.53.0.5. 97close_connections() { 98 send_command "close" "${1}" || return 1 99} 100 101# Check TCP connections are working normally before opening 102# multiple connections 103n=$((n + 1)) 104echo_i "checking TCP query repsonse ($n)" 105ret=0 106dig_with_opts +tcp @10.53.0.5 txt.example > dig.out.test$n 107grep "status: NXDOMAIN" dig.out.test$n > /dev/null || ret=1 108if [ $ret != 0 ]; then echo_i "failed"; fi 109status=$((status + ret)) 110 111# Check TCP statistics after server startup before using them as a baseline for 112# subsequent checks. 113n=$((n + 1)) 114echo_i "TCP high-water: check initial statistics ($n)" 115ret=0 116refresh_tcp_stats 117assert_int_equal "${TCP_CUR}" 0 "current TCP clients count" || ret=1 118# We compare initial tcp-highwater value with 1 because as part of the 119# system test startup, the script start.pl executes dig to check if target 120# named is running, and that increments tcp-quota by one. 121assert_int_equal "${TCP_HIGH}" 1 "tcp-highwater count" || ret=1 122if [ $ret != 0 ]; then echo_i "failed"; fi 123status=$((status + ret)) 124 125# Ensure the TCP high-water statistic gets updated after some TCP connections 126# are established. 127n=$((n + 1)) 128echo_i "TCP high-water: check value after some TCP connections are established ($n)" 129ret=0 130OLD_TCP_CUR="${TCP_CUR}" 131TCP_ADDED=9 132open_connections "${TCP_ADDED}" || ret=1 133check_stats_added() { 134 refresh_tcp_stats 135 assert_int_equal "${TCP_CUR}" $((OLD_TCP_CUR + TCP_ADDED)) "current TCP clients count" || return 1 136 assert_int_equal "${TCP_HIGH}" $((OLD_TCP_CUR + TCP_ADDED)) "TCP high-water value" || return 1 137} 138retry 2 check_stats_added || ret=1 139if [ $ret != 0 ]; then echo_i "failed"; fi 140status=$((status + ret)) 141 142# Ensure the TCP high-water statistic remains unchanged after some TCP 143# connections are closed. 144n=$((n + 1)) 145echo_i "TCP high-water: check value after some TCP connections are closed ($n)" 146ret=0 147OLD_TCP_CUR="${TCP_CUR}" 148OLD_TCP_HIGH="${TCP_HIGH}" 149TCP_REMOVED=5 150close_connections "${TCP_REMOVED}" || ret=1 151check_stats_removed() { 152 refresh_tcp_stats 153 assert_int_equal "${TCP_CUR}" $((OLD_TCP_CUR - TCP_REMOVED)) "current TCP clients count" || return 1 154 assert_int_equal "${TCP_HIGH}" "${OLD_TCP_HIGH}" "TCP high-water value" || return 1 155} 156retry 2 check_stats_removed || ret=1 157if [ $ret != 0 ]; then echo_i "failed"; fi 158status=$((status + ret)) 159 160# Ensure the TCP high-water statistic never exceeds the configured TCP clients 161# limit. 162n=$((n + 1)) 163echo_i "TCP high-water: ensure tcp-clients is an upper bound ($n)" 164ret=0 165open_connections $((TCP_LIMIT + 1)) || ret=1 166check_stats_limit() { 167 refresh_tcp_stats 168 assert_int_equal "${TCP_CUR}" "${TCP_LIMIT}" "current TCP clients count" || return 1 169 assert_int_equal "${TCP_HIGH}" "${TCP_LIMIT}" "TCP high-water value" || return 1 170} 171retry 2 check_stats_limit || ret=1 172if [ $ret != 0 ]; then echo_i "failed"; fi 173status=$((status + ret)) 174 175# Check TCP connections are working normally before opening 176# multiple connections 177n=$((n + 1)) 178echo_i "checking TCP response recovery ($n)" 179ret=0 180# "0" closes all connections 181close_connections 0 || ret=1 182dig_with_opts +tcp @10.53.0.5 txt.example > dig.out.test$n || ret=1 183grep "status: NXDOMAIN" dig.out.test$n > /dev/null || ret=1 184if [ $ret != 0 ]; then echo_i "failed"; fi 185status=$((status + ret)) 186 187echo_i "exit status: $status" 188[ $status -eq 0 ] || exit 1 189