1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
|
# SPDX-License-Identifier: GPL-3.0-or-later
"""Test opening as many connections as possible.
Due to resource-intensity of this test, it's filename doesn't contain
"test" on purpose, so it doesn't automatically get picked up by pytest
(to allow easy parallel testing).
To execute this test, pass the filename of this file to pytest directly.
Also, make sure not to use parallel execution (-n).
"""
import resource
import time
import pytest
from kresd import Kresd
import utils
MAX_SOCKETS = 10000 # upper bound of how many connections to open
MAX_ITERATIONS = 10 # number of iterations to run the test
# we can't use softlimit itself since kresd already has open sockets,
# so use lesser value
RESERVED_NOFILE = 40 # 40 is empirical value
@pytest.mark.parametrize('sock_func_name', [
'ip_tcp_socket',
'ip6_tcp_socket',
'ip_tls_socket',
'ip6_tls_socket',
])
def test_conn_flood(tmpdir, sock_func_name):
def create_sockets(make_sock, nsockets):
sockets = []
next_ping = time.time() + 4 # less than tcp idle timeout / 2
while True:
additional_sockets = 0
while time.time() < next_ping:
nsock_to_init = min(100, nsockets - len(sockets))
if not nsock_to_init:
return sockets
sockets.extend([make_sock() for _ in range(nsock_to_init)])
additional_sockets += nsock_to_init
# large number of connections can take a lot of time to open
# send some valid data to avoid TCP idle timeout for already open sockets
next_ping = time.time() + 4
for s in sockets:
utils.ping_alive(s)
# break when no more than 20% additional sockets are created
if additional_sockets / len(sockets) < 0.2:
return sockets
max_num_of_open_files = resource.getrlimit(resource.RLIMIT_NOFILE)[0] - RESERVED_NOFILE
nsockets = min(max_num_of_open_files, MAX_SOCKETS)
# create kresd instance with verbose=False
ip = '127.0.0.1'
ip6 = '::1'
with Kresd(tmpdir, ip=ip, ip6=ip6, verbose=False) as kresd:
make_sock = getattr(kresd, sock_func_name) # function for creating sockets
sockets = create_sockets(make_sock, nsockets)
print("\nEstablished {} connections".format(len(sockets)))
print("Start sending data")
for i in range(MAX_ITERATIONS):
for s in sockets:
utils.ping_alive(s)
print("Iteration {} done...".format(i))
print("Close connections")
for s in sockets:
s.close()
# check in kresd is alive
print("Check upstream is still alive")
sock = make_sock()
utils.ping_alive(sock)
print("OK!")
|