758 lines
31 KiB
Python
758 lines
31 KiB
Python
#
|
|
# Copyright 2019 - The Android Open Source Project
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
import random
|
|
import re
|
|
import time
|
|
from acts import asserts
|
|
from acts import base_test
|
|
from acts.test_decorators import test_tracker_info
|
|
from acts_contrib.test_utils.net import connectivity_test_utils as cutils
|
|
from acts_contrib.test_utils.net import net_test_utils as nutils
|
|
from acts_contrib.test_utils.net import socket_test_utils as sutils
|
|
from acts_contrib.test_utils.net.net_test_utils import start_tcpdump
|
|
from acts_contrib.test_utils.net.net_test_utils import stop_tcpdump
|
|
from acts_contrib.test_utils.wifi import wifi_test_utils as wutils
|
|
from scapy.all import rdpcap
|
|
from scapy.all import Scapy_Exception
|
|
from scapy.all import TCP
|
|
from scapy.all import UDP
|
|
|
|
|
|
ACK = "A"
|
|
DROPPED_IPV4_KA_ACK = "DROPPED_IPV4_KEEPALIVE_ACK"
|
|
MIN_TEST_KA_INTERVAL = 10
|
|
# max keepalive interval is kept to 60 for test purposes
|
|
MAX_TEST_KA_INTERVAL = 60
|
|
# sleep time to test keepalives. this is set to a prime number to prevent
|
|
# race conditions and as a result flaky tests.
|
|
# Ex: if keepalive is started with 42s time interval, we expect 4 keepalives
|
|
# after 181s.
|
|
SLEEP_TIME = 181
|
|
STRESS_COUNT = 5
|
|
SUPPORTED_KERNEL_VERSION = 4.8
|
|
TCP_SERVER_PORT = 853
|
|
UDP_SERVER_PORT = 4500
|
|
|
|
|
|
class SocketKeepaliveTest(base_test.BaseTestClass):
|
|
"""Tests for Socket keepalive."""
|
|
|
|
def __init__(self, controllers):
|
|
"""List and order of tests to run."""
|
|
base_test.BaseTestClass.__init__(self, controllers)
|
|
self.tests = (
|
|
"test_tcp_socket_keepalive_start_stop_wifi",
|
|
"test_natt_socket_keepalive_start_stop_wifi",
|
|
"test_tcp_socket_keepalive_error_client_socket_close_wifi",
|
|
"test_tcp_socket_keepalive_over_max_keepalive_limit_wifi",
|
|
"test_tcp_socket_keepalive_invalid_interval",
|
|
"test_natt_socket_keepalive_invalid_interval",
|
|
"test_tcp_socket_keepalive_start_stop_multiple_keepalives_wifi",
|
|
"test_tcp_socket_keepalive_start_stop_stress_wifi",
|
|
"test_tcp_socket_keepalive_on_data_received_wifi",
|
|
"test_natt_socket_keepalive_start_stop_lte",)
|
|
|
|
def setup_class(self):
|
|
"""Setup devices for tests and unpack params."""
|
|
|
|
self.dut = self.android_devices[1]
|
|
# remote_server_2 is the host machine to test OnDataCallback and Error
|
|
# callbacks. The server program sends data to the DUT while keepalive
|
|
# is enabled. It also closes the server socket to verify Error callback
|
|
# 'test_tcp_socket_keepalive_on_data_received_wifi' requires this.
|
|
# remote_server is the host machine to test all other test cases.
|
|
# This host listens, accepts connections and verifies the keepalive
|
|
# intervals.
|
|
req_params = ("wifi_network", "remote_server", "remote_server_2")
|
|
self.unpack_userparams(req_params)
|
|
nutils.verify_lte_data_and_tethering_supported(self.dut)
|
|
self.max_ka_net = self.dut.droid.getSupportedKeepalivesForNetwork()
|
|
self.log.info("Max Keepalives for mobile network: %s" % self.max_ka_net)
|
|
wutils.start_wifi_connection_scan_and_ensure_network_found(
|
|
self.dut, self.wifi_network["SSID"])
|
|
wutils.wifi_connect(self.dut, self.wifi_network)
|
|
self.max_ka_wifi = self.dut.droid.getSupportedKeepalivesForNetwork()
|
|
self.log.info("Max Keepalives on wifi network: %s" % self.max_ka_wifi)
|
|
self.kernel_version = self._get_kernel_version(self.dut)
|
|
self.log.info("Kernel version: %s" % self.kernel_version)
|
|
|
|
self.host_ip = self.remote_server["ip_addr"]
|
|
self.tcpdump_pid = None
|
|
self.tcp_sockets = []
|
|
self.socket_keepalives = []
|
|
self.gce_tcpdump_pid = None
|
|
self.udp_encap = None
|
|
|
|
def setup_test(self):
|
|
asserts.skip_if(
|
|
self.test_name.startswith("test_tcp") and \
|
|
self.kernel_version < SUPPORTED_KERNEL_VERSION,
|
|
"TCP Keepalive is not supported on kernel %s. Need at least %s" %
|
|
(self.kernel_version, SUPPORTED_KERNEL_VERSION))
|
|
|
|
if self.test_name.endswith("_lte"):
|
|
wutils.wifi_toggle_state(self.dut, False)
|
|
time.sleep(3)
|
|
link_prop = self.dut.droid.connectivityGetActiveLinkProperties()
|
|
iface = link_prop["InterfaceName"]
|
|
self.log.info("Iface: %s" % iface)
|
|
self.dut_ip = self.dut.droid.connectivityGetIPv4Addresses(iface)[0]
|
|
self.tcpdump_pid = start_tcpdump(self.dut, self.test_name)
|
|
|
|
def teardown_test(self):
|
|
if self.tcpdump_pid:
|
|
stop_tcpdump(self.dut, self.tcpdump_pid, self.test_name)
|
|
self.tcpdump_pid = None
|
|
if self.gce_tcpdump_pid:
|
|
host = self.remote_server
|
|
if "_on_data_" in self.test_name:
|
|
host = self.remote_server_2
|
|
nutils.stop_tcpdump_gce_server(
|
|
self.dut, self.gce_tcpdump_pid, None, host)
|
|
self.gce_tcpdump_pid = None
|
|
for ska in self.socket_keepalives:
|
|
cutils.stop_socket_keepalive(self.dut, ska)
|
|
self.socket_keepalives = []
|
|
for sock in self.tcp_sockets:
|
|
sutils.shutdown_socket(self.dut, sock)
|
|
self.tcp_sockets = []
|
|
if self.udp_encap:
|
|
self.dut.droid.ipSecCloseUdpEncapsulationSocket(self.udp_encap)
|
|
self.udp_encap = None
|
|
wutils.wifi_toggle_state(self.dut, True)
|
|
|
|
def teardown_class(self):
|
|
wutils.reset_wifi(self.dut)
|
|
|
|
def on_fail(self, test_name, begin_time):
|
|
self.dut.take_bug_report(test_name, begin_time)
|
|
|
|
### Helper functions
|
|
|
|
def _get_kernel_version(self, ad):
|
|
"""Get the kernel version on the device.
|
|
|
|
Args:
|
|
ad: android device object.
|
|
|
|
Returns:
|
|
Kernel version on the device.
|
|
"""
|
|
cmd_out = ad.adb.shell("cat /proc/version")
|
|
pattern_match = re.findall(r"^Linux version \d.\d", cmd_out)
|
|
return float(pattern_match[0].split()[-1]) if pattern_match else None
|
|
|
|
def _verify_tcp_keepalives(self,
|
|
pcap,
|
|
interval,
|
|
cport,
|
|
beg,
|
|
end,
|
|
expected_ka_count,
|
|
verify_ka_interval=True):
|
|
"""Verify TCP keepalives received by host.
|
|
|
|
Args:
|
|
pcap: tcpdump file from host.
|
|
interval: keepalive time interval.
|
|
cport: client port after NAT on the host.
|
|
beg: beginning time for keepalives.
|
|
end: end time for keepalives.
|
|
expected_ka_count: expected no. of KA packets.
|
|
verify_ka_interval: if true, verify the keepalive time interval.
|
|
|
|
Returns:
|
|
True/False if keepalives are successful.
|
|
"""
|
|
try:
|
|
packets = rdpcap(pcap)
|
|
except Scapy_Exception:
|
|
asserts.fail("Not a valid pcap file")
|
|
|
|
seq = None
|
|
time_stamps = []
|
|
for pkt in packets:
|
|
if pkt.time < beg:
|
|
continue
|
|
if pkt.time > end:
|
|
break
|
|
if TCP in pkt and pkt[TCP].dport == TCP_SERVER_PORT and \
|
|
pkt[TCP].sport == cport and pkt[TCP].flags == ACK and \
|
|
not seq or pkt[TCP].seq == seq:
|
|
|
|
seq = pkt[TCP].seq
|
|
time_stamps.append(pkt.time)
|
|
|
|
self.log.info("KA count: %s, expected %s" % (len(time_stamps),
|
|
expected_ka_count))
|
|
if len(time_stamps) != expected_ka_count:
|
|
return False
|
|
if not verify_ka_interval:
|
|
return True
|
|
return self._verify_keepalive_interval(time_stamps, interval)
|
|
|
|
def _verify_natt_keepalives(self,
|
|
pcap,
|
|
interval,
|
|
beg,
|
|
end,
|
|
expected_ka_count):
|
|
"""Verify Natt keepalives received by host.
|
|
|
|
Args:
|
|
pcap: tcpdump file from host.
|
|
interval: expected time difference between keepalives.
|
|
beg: beginning time for keepalives.
|
|
end: end time for keepalives.
|
|
expected_ka_count: expected keepalive count.
|
|
|
|
Returns:
|
|
True/False if keepalives are successful.
|
|
"""
|
|
try:
|
|
packets = rdpcap(pcap)
|
|
except Scapy_Exception:
|
|
asserts.fail("Not a valid pcap file")
|
|
|
|
ka_dict = {}
|
|
for pkt in packets:
|
|
if pkt.time < beg:
|
|
continue
|
|
if pkt.time > end:
|
|
break
|
|
if UDP in pkt and pkt[UDP].dport == UDP_SERVER_PORT:
|
|
if pkt[UDP].sport not in ka_dict:
|
|
ka_dict[pkt[UDP].sport] = [float(pkt.time)]
|
|
else:
|
|
ka_dict[pkt[UDP].sport].append(float(pkt.time))
|
|
|
|
for sport in ka_dict:
|
|
self.log.info("Source port: %s" % sport)
|
|
self.log.info("KA count: %s, expected: %s" % (len(ka_dict[sport]),
|
|
expected_ka_count))
|
|
if len(ka_dict[sport]) == expected_ka_count and \
|
|
self._verify_keepalive_interval(ka_dict[sport], interval):
|
|
return True
|
|
self.log.error("Keepalive time interval verification failed")
|
|
return False
|
|
|
|
def _verify_keepalive_interval(self, time_stamps, interval):
|
|
"""Verify time difference between keepalive packets.
|
|
|
|
Args:
|
|
time_stamps: List of timestamps of each keepalive.
|
|
interval: Expected time difference.
|
|
|
|
Returns:
|
|
True if Keepalive interval matches with expected value.
|
|
"""
|
|
i = 0
|
|
for t in time_stamps:
|
|
if i == 0:
|
|
prev = t
|
|
i += 1
|
|
continue
|
|
diff = int(round(t - prev))
|
|
self.log.info("KA interval: %s, expected: %s" % (diff, interval))
|
|
if diff != interval:
|
|
return False
|
|
prev = t
|
|
i += 1
|
|
return True
|
|
|
|
def _get_expected_ka_count(self, elapsed_time, ka_time_interval):
|
|
"""Get expected keepalive count.
|
|
|
|
Args:
|
|
elapsed_time: time in seconds within which to count the keepalives.
|
|
ka_time_interval: time interval between keepalives.
|
|
|
|
Returns:
|
|
no. of keepalives.
|
|
"""
|
|
return int(elapsed_time/ka_time_interval)
|
|
|
|
def _get_client_port_and_time_interval(self):
|
|
"""Generate a random tcp port and keepalive time interval.
|
|
|
|
Returns:
|
|
client_port and keepalive time interval.
|
|
"""
|
|
# (TODO: @gmoturu) Change this to autobind instead of generating a port.
|
|
client_port = random.randint(8000, 9000)
|
|
time_interval = random.randint(MIN_TEST_KA_INTERVAL,
|
|
MAX_TEST_KA_INTERVAL)
|
|
self.log.info("Socket Keepalive time interval: %s" % time_interval)
|
|
return client_port, time_interval
|
|
|
|
def _open_tcp_socket_and_connect(self, client_port, server_ip=None):
|
|
"""Open a TCP socket and connect to server for keepalive testing.
|
|
|
|
Args:
|
|
client_port: port to open tcp socket on.
|
|
server_ip: IP addr of remote server.
|
|
|
|
Returns:
|
|
socket object and client port seen by server.
|
|
"""
|
|
if not server_ip:
|
|
server_ip = self.host_ip
|
|
sock = self.dut.droid.openTcpSocket(server_ip,
|
|
TCP_SERVER_PORT,
|
|
self.dut_ip,
|
|
client_port)
|
|
asserts.assert_true(sock, "Failed to open TCP socket")
|
|
self.log.info("Socket key: %s" % sock)
|
|
self.tcp_sockets.append(sock)
|
|
cport_server = self.dut.droid.tcpSocketRecv(sock)
|
|
asserts.assert_true(cport_server, "Received null message from server")
|
|
self.log.info("Client port after NAT on host: %s" % cport_server)
|
|
return sock, cport_server
|
|
|
|
def _start_tcp_keepalive(self, sock, time_interval, expect_ka_start=True):
|
|
"""Start TCP keepalive.
|
|
|
|
Args:
|
|
sock: TCP socket object.
|
|
time_interval: keepalive time interval.
|
|
expect_ka_start: if True, KA should Start, else Error outcome.
|
|
|
|
Returns:
|
|
key of socket keepalive object.
|
|
"""
|
|
ska_key = cutils.start_tcp_socket_keepalive(self.dut,
|
|
sock,
|
|
time_interval)
|
|
|
|
if not expect_ka_start:
|
|
asserts.assert_false(ska_key,
|
|
"Expected starting socket keepalive to fail")
|
|
return None
|
|
|
|
asserts.assert_true(ska_key, "Failed to start socket keepalive")
|
|
self.socket_keepalives.append(ska_key)
|
|
return ska_key
|
|
|
|
def _get_dropped_keepalive_acks(self, ack=DROPPED_IPV4_KA_ACK):
|
|
"""Get dropped keepalive acks from dumpsys output.
|
|
|
|
Args:
|
|
ack: Type of keepalive ack to check.
|
|
|
|
Returns:
|
|
Number of dropped acks.
|
|
"""
|
|
dropped_acks = self.dut.adb.shell(
|
|
"dumpsys network_stack | grep '%s'" % ack)
|
|
dropped_acks = dropped_acks.rstrip()
|
|
self.log.info("Dropped keepalive acks: %s" % dropped_acks)
|
|
return 0 if not dropped_acks else int(dropped_acks.split(":")[-1])
|
|
|
|
def _test_socket_keepalive_start_stop(self):
|
|
"""Test NATT and TCP socket keepalives for wifi and mobile networks."""
|
|
tcp_keepalive = True if "_tcp_" in self.test_name else False
|
|
ad = self.dut
|
|
port = TCP_SERVER_PORT if tcp_keepalive else UDP_SERVER_PORT
|
|
self.log.info("Client IP: %s" % self.dut_ip)
|
|
self.log.info("Server IP: %s" % self.host_ip)
|
|
|
|
# start tcpdump on the server
|
|
self.gce_tcpdump_pid, pcap_path = nutils.start_tcpdump_gce_server(
|
|
ad, self.test_name, port, self.remote_server)
|
|
|
|
# start keepalive
|
|
client_port, time_interval = self._get_client_port_and_time_interval()
|
|
ska_key = None
|
|
if tcp_keepalive:
|
|
self.log.info("Client port: %s" % client_port)
|
|
self.log.info("Server port: %s" % TCP_SERVER_PORT)
|
|
sock, cport_server = self._open_tcp_socket_and_connect(client_port)
|
|
ska_key = self._start_tcp_keepalive(sock, time_interval)
|
|
else:
|
|
self.log.info("UDP encap port on server: %s" % UDP_SERVER_PORT)
|
|
self.udp_encap = self.dut.droid.ipSecOpenUdpEncapsulationSocket()
|
|
ska_key = cutils.start_natt_socket_keepalive(self.dut,
|
|
self.udp_encap,
|
|
self.dut_ip,
|
|
self.host_ip,
|
|
time_interval)
|
|
self.socket_keepalives.append(ska_key)
|
|
asserts.assert_true(ska_key, "Failed to start socket keepalive")
|
|
|
|
# sleep for sometime to verify keepalives
|
|
beg_time = time.time()
|
|
self.log.info("Sleeping for %s seconds" % SLEEP_TIME)
|
|
time.sleep(SLEEP_TIME)
|
|
end_time = time.time()
|
|
|
|
# stop tcpdump
|
|
pcap_file = nutils.stop_tcpdump_gce_server(
|
|
ad, self.gce_tcpdump_pid, pcap_path, self.remote_server)
|
|
self.gce_tcpdump_pid = None
|
|
|
|
# verify keepalives
|
|
expected_ka_count = self._get_expected_ka_count(end_time-beg_time,
|
|
time_interval)
|
|
|
|
if tcp_keepalive:
|
|
result = self._verify_tcp_keepalives(
|
|
pcap_file, time_interval, int(cport_server), beg_time, end_time,
|
|
expected_ka_count)
|
|
else:
|
|
result = self._verify_natt_keepalives(
|
|
pcap_file, time_interval, beg_time, end_time, expected_ka_count)
|
|
asserts.assert_true(result, "Keepalive verification failed")
|
|
|
|
### Tests begin
|
|
|
|
@test_tracker_info(uuid="537e13ef-2366-40a3-86d4-596266d21eda")
|
|
def test_tcp_socket_keepalive_start_stop_wifi(self):
|
|
"""Test TCP keepalive for onStart and onStop callbacks.
|
|
|
|
Steps:
|
|
1. Open a TCP socket on DUT and connect to server.
|
|
2. Start TCP keepalive and verify onStarted callback is received.
|
|
3. Verify that server received the keepalives.
|
|
4. Stop TCP keepalive and verify onStopped callback is received.
|
|
"""
|
|
self._test_socket_keepalive_start_stop()
|
|
|
|
@test_tracker_info(uuid="8f23f3a0-7b65-4b5c-bc91-5decaddb7c9c")
|
|
def test_tcp_socket_keepalive_on_data_received_wifi(self):
|
|
"""Test Error callback for tcp socket keepalive.
|
|
|
|
Steps:
|
|
1. Open a TCP socket on DUT and connect ot server on port 853.
|
|
2. Start TCP keepalive and verify on Start callback.
|
|
3. Send message from server and verify OnDataReceived Callback.
|
|
4. Send data and recv data from server.
|
|
5. Start keeaplive again and verify server receives them.
|
|
"""
|
|
# start tcpdump on the server
|
|
host = self.remote_server_2
|
|
host_ip = host["ip_addr"]
|
|
tcpdump_pid, pcap_path = nutils.start_tcpdump_gce_server(
|
|
self.dut, self.test_name, TCP_SERVER_PORT, host)
|
|
|
|
# open socket, connect to server, start keepalive
|
|
time_interval = 11
|
|
sleep_time = 37
|
|
keepalive_count = 3
|
|
self.log.info("Client IP: %s" % self.dut_ip)
|
|
self.log.info("Server IP: %s" % host_ip)
|
|
client_port = random.randint(8000, 9000)
|
|
self.log.info("Client port: %s" % client_port)
|
|
sock, cport_server = self._open_tcp_socket_and_connect(client_port,
|
|
host_ip)
|
|
ska_key = self._start_tcp_keepalive(sock, time_interval)
|
|
|
|
# wait for data to be received from server
|
|
begin_time = time.time()
|
|
self.log.info("Sleeping for %s seconds" % sleep_time)
|
|
time.sleep(sleep_time)
|
|
recv_msg = self.dut.droid.tcpSocketRecv(sock)
|
|
self.log.info("Received message: %s" % recv_msg)
|
|
|
|
# verify onDataReceived callback
|
|
status = cutils.socket_keepalive_data_received(self.dut, ska_key)
|
|
asserts.assert_true(status, "Failed to receive onDataReceived callback")
|
|
self.socket_keepalives = []
|
|
|
|
# wait for some time before starting keepalives
|
|
self.log.info("Sleeping for %s seconds" % sleep_time)
|
|
time.sleep(sleep_time)
|
|
|
|
# re-start keepalives and sleep for sometime to verify keepalives
|
|
ska_key = self._start_tcp_keepalive(sock, time_interval)
|
|
self.log.info("Sleeping for %s seconds" % sleep_time)
|
|
time.sleep(sleep_time)
|
|
end_time = time.time()
|
|
dropped_acks = self._get_dropped_keepalive_acks()
|
|
|
|
# expected ka count here is not based on beg_time and end_time as we
|
|
# wait some time before re-starting keepalives after OnDataReceived
|
|
# callback. the elapsed time will be sleep_time * 2. the extra keepalive
|
|
# accounts for the one sent by kernel. b/132924144 for reference.
|
|
expected_ka_count = 1+self._get_expected_ka_count(sleep_time*2,
|
|
time_interval)
|
|
|
|
# stop tcpdump
|
|
pcap_file = nutils.stop_tcpdump_gce_server(
|
|
self.dut, tcpdump_pid, pcap_path, host)
|
|
|
|
# server closes socket - verify error callback
|
|
time.sleep(60)
|
|
status = cutils.socket_keepalive_error(self.dut, ska_key)
|
|
asserts.assert_true(status, "Failed to receive onError callback")
|
|
self.socket_keepalives = []
|
|
self.tcp_sockets = []
|
|
|
|
# verify keepalives
|
|
result = self._verify_tcp_keepalives(pcap_file,
|
|
time_interval,
|
|
int(cport_server),
|
|
begin_time,
|
|
end_time,
|
|
expected_ka_count,
|
|
False)
|
|
asserts.assert_true(result and keepalive_count == dropped_acks,
|
|
"Keepalive verification failed")
|
|
asserts.assert_true(result, "Keepalive verification failed")
|
|
|
|
@test_tracker_info(uuid="c02bcc1c-f86b-4905-973a-b4200a2b86c1")
|
|
def test_tcp_socket_keepalive_start_stop_multiple_keepalives_wifi(self):
|
|
"""Test TCP keepalive for onStart and onStop callbacks.
|
|
|
|
Steps:
|
|
1. Open 3 TCP socket on DUT and connect to server.
|
|
2. Start TCP keepalive and verify onStarted callback is received.
|
|
3. Verify that server received the keepalives.
|
|
4. Stop TCP keepalive and verify onStopped callback is received.
|
|
"""
|
|
# start tcpdump on the server
|
|
tcpdump_pid, pcap_path = nutils.start_tcpdump_gce_server(
|
|
self.dut, self.test_name, TCP_SERVER_PORT, self.remote_server)
|
|
|
|
# open 3 sockets and start keepalives
|
|
interval_list = []
|
|
cport_list = []
|
|
cport_server_list = []
|
|
self.log.info("Client IP: %s" % self.dut_ip)
|
|
self.log.info("Server IP: %s" % self.host_ip)
|
|
for _ in range(self.max_ka_wifi):
|
|
cport, interval = self._get_client_port_and_time_interval()
|
|
cport_list.append(cport)
|
|
interval_list.append(interval)
|
|
|
|
for _ in range(self.max_ka_wifi):
|
|
sock, cport_server = self._open_tcp_socket_and_connect(
|
|
cport_list[_])
|
|
self._start_tcp_keepalive(sock, interval_list[_])
|
|
cport_server_list.append(cport_server)
|
|
|
|
# sleep for sometime to verify keepalives
|
|
begin_time = time.time()
|
|
self.log.info("Sleeping for %s seconds" % SLEEP_TIME)
|
|
time.sleep(SLEEP_TIME)
|
|
end_time = time.time()
|
|
dropped_acks = self._get_dropped_keepalive_acks()
|
|
|
|
# stop tcpdump
|
|
pcap_file = nutils.stop_tcpdump_gce_server(
|
|
self.dut, tcpdump_pid, pcap_path, self.remote_server)
|
|
|
|
# verify keepalives
|
|
total_dropped_acks = 0
|
|
for _ in range(self.max_ka_wifi):
|
|
total_dropped_acks += int(SLEEP_TIME/interval_list[_])
|
|
expected_ka_count = self._get_expected_ka_count(end_time-begin_time,
|
|
interval_list[_])
|
|
result = self._verify_tcp_keepalives(pcap_file,
|
|
interval_list[_],
|
|
int(cport_server_list[_]),
|
|
begin_time,
|
|
end_time,
|
|
expected_ka_count)
|
|
asserts.assert_true(result, "Keepalive verification failed")
|
|
|
|
@test_tracker_info(uuid="64374896-7a04-4a5b-b27c-e27b5f0e7159")
|
|
def test_tcp_socket_keepalive_start_stop_stress_wifi(self):
|
|
"""Test TCP keepalive for onStart and onStop callbacks.
|
|
|
|
Steps:
|
|
1. Open 3 TCP socket on DUT and connect to server.
|
|
2. Start TCP keepalive and verify onStarted callback is received.
|
|
3. Verify that server received the keepalives.
|
|
4. Stop TCP keepalive and verify onStopped callback is received.
|
|
5. Repeat steps 1-4 few times.
|
|
"""
|
|
# open 3 sockets
|
|
interval_list = []
|
|
cport_server_list = []
|
|
sock_list = []
|
|
|
|
self.log.info("Client IP: %s" % self.dut_ip)
|
|
self.log.info("Server IP: %s" % self.host_ip)
|
|
for _ in range(self.max_ka_wifi):
|
|
client_port = random.randint(8000, 9000)
|
|
self.log.info("Client port: %s" % client_port)
|
|
sock, cport_server = self._open_tcp_socket_and_connect(client_port)
|
|
sock_list.append(sock)
|
|
cport_server_list.append(cport_server)
|
|
|
|
for _ in range(STRESS_COUNT):
|
|
|
|
# start tcpdump on the server
|
|
tcpdump_pid, pcap_path = nutils.start_tcpdump_gce_server(
|
|
self.dut, self.test_name, TCP_SERVER_PORT, self.remote_server)
|
|
|
|
# start keepalives on sockets
|
|
for _ in range(self.max_ka_wifi):
|
|
time_interval = random.randint(MIN_TEST_KA_INTERVAL,
|
|
MAX_TEST_KA_INTERVAL)
|
|
self.log.info("TCP socket Keepalive time interval: %s" %
|
|
time_interval)
|
|
interval_list.append(time_interval)
|
|
self._start_tcp_keepalive(sock_list[_], interval_list[_])
|
|
|
|
# sleep for sometime to verify keepalives
|
|
begin_time = time.time()
|
|
self.log.info("Sleeping for %s seconds" % SLEEP_TIME)
|
|
time.sleep(SLEEP_TIME)
|
|
end_time = time.time()
|
|
dropped_acks = self._get_dropped_keepalive_acks()
|
|
|
|
# stop keepalives
|
|
for ska in self.socket_keepalives:
|
|
self.log.info("Stopping keepalive %s" % ska)
|
|
cutils.stop_socket_keepalive(self.dut, ska)
|
|
self.socket_keepalives = []
|
|
|
|
# stop tcpdump
|
|
pcap_file = nutils.stop_tcpdump_gce_server(
|
|
self.dut, tcpdump_pid, pcap_path, self.remote_server)
|
|
|
|
# verify keepalives
|
|
total_dropped_acks = 0
|
|
for _ in range(self.max_ka_wifi):
|
|
total_dropped_acks += int(SLEEP_TIME/interval_list[_])
|
|
expected_ka_count = self._get_expected_ka_count(
|
|
end_time-begin_time, interval_list[_])
|
|
result = self._verify_tcp_keepalives(pcap_file,
|
|
interval_list[_],
|
|
int(cport_server_list[_]),
|
|
begin_time,
|
|
end_time,
|
|
expected_ka_count)
|
|
asserts.assert_true(result, "Keepalive verification failed")
|
|
|
|
interval_list = []
|
|
|
|
@test_tracker_info(uuid="de3970c1-23d1-4d52-b3c9-4a2f1e53e7f6")
|
|
def test_tcp_socket_keepalive_error_client_socket_close_wifi(self):
|
|
"""Test Error callback for tcp socket keepalive.
|
|
|
|
Steps:
|
|
1. Open a TCP socket on DUT and connect to server on port 853.
|
|
2. Start TCP keepalive and verify on Start callback.
|
|
3. Wait for some time and shutdown the client socket.
|
|
4. Verify on Error callback is received.
|
|
"""
|
|
# open socket, connect to server, start keepalive
|
|
client_port, time_interval = self._get_client_port_and_time_interval()
|
|
sock, _ = self._open_tcp_socket_and_connect(client_port)
|
|
ska_key = self._start_tcp_keepalive(sock, time_interval)
|
|
|
|
# wait for atleast 1 keepalive
|
|
self.log.info("Sleeping for %s seconds" % (time_interval+1))
|
|
time.sleep(time_interval+1)
|
|
|
|
# shutdown client socket
|
|
sutils.shutdown_socket(self.dut, sock)
|
|
self.tcp_sockets.remove(sock)
|
|
self.socket_keepalives = []
|
|
|
|
# verify Error callback received
|
|
result = cutils.socket_keepalive_error(self.dut, ska_key)
|
|
asserts.assert_true(result, "Failed to receive error callback")
|
|
|
|
@test_tracker_info(uuid="7c902e51-725a-41f1-aebc-8528197c450c")
|
|
def test_tcp_socket_keepalive_over_max_keepalive_limit_wifi(self):
|
|
"""Test TCP socket keepalive over max keepalive limit.
|
|
|
|
Steps:
|
|
1. Start 4 TCP socket keepalives.
|
|
2. 3 Should be successful and 4th should fail with Error.
|
|
"""
|
|
# open sockets and connect to server
|
|
max_ka_net = self.dut.droid.getSupportedKeepalivesForNetwork()
|
|
self.log.info("Max Keepalives supported: %s" % max_ka_net)
|
|
state = True
|
|
for _ in range(1, max_ka_net+1):
|
|
cport, interval = self._get_client_port_and_time_interval()
|
|
sock, _ = self._open_tcp_socket_and_connect(cport)
|
|
if _ == max_ka_net:
|
|
state = False
|
|
self._start_tcp_keepalive(sock, interval, state)
|
|
|
|
@test_tracker_info(uuid="308004c5-8e40-4e8b-9408-4a90e85a2261")
|
|
def test_tcp_socket_keepalive_invalid_interval(self):
|
|
"""Test TCP socket keepalive with invalid interval.
|
|
|
|
Steps:
|
|
1. Start TCP socket keepalive with time interval <10 seconds.
|
|
2. Verify Error callback is received.
|
|
"""
|
|
# keepalive time interval, client port
|
|
client_port = random.randint(8000, 9000)
|
|
time_interval = random.randint(1, 9)
|
|
self.log.info("Client port: %s" % client_port)
|
|
self.log.info("Server port: %s" % TCP_SERVER_PORT)
|
|
|
|
# open tcp socket
|
|
sock, _ = self._open_tcp_socket_and_connect(client_port)
|
|
|
|
# start TCP socket keepalive
|
|
self.log.info("TCP socket Keepalive time interval: %s" % time_interval)
|
|
self._start_tcp_keepalive(sock, time_interval, False)
|
|
|
|
@test_tracker_info(uuid="c9012da2-656f-44ef-bad6-26892335d4bd")
|
|
def test_natt_socket_keepalive_start_stop_wifi(self):
|
|
"""Test Natt socket keepalive for onStart and onStop callbacks.
|
|
|
|
Steps:
|
|
1. Open a UDP encap socket on DUT.
|
|
2. Start Natt socket keepalive.
|
|
3. Verify that server received the keepalives.
|
|
4. Stop keepalive and verify onStopped callback is received.
|
|
"""
|
|
self._test_socket_keepalive_start_stop()
|
|
|
|
@test_tracker_info(uuid="646bfd5d-936f-4069-8dea-fdd02582550d")
|
|
def test_natt_socket_keepalive_start_stop_lte(self):
|
|
"""Test Natt socket keepalive for onStart and onStop callbacks.
|
|
|
|
Steps:
|
|
1. Open a UDP encap socket on DUT.
|
|
2. Start Natt socket keepalive.
|
|
3. Verify that server received the keepalives.
|
|
4. Stop keepalive and verify onStopped callback is received.
|
|
"""
|
|
self._test_socket_keepalive_start_stop()
|
|
|
|
@test_tracker_info(uuid="8ab20733-4a9e-4e4d-a46f-4d32a9f221c5")
|
|
def test_natt_socket_keepalive_invalid_interval(self):
|
|
"""Test invalid natt socket keepalive time interval.
|
|
|
|
Steps:
|
|
1. Start NATT socket keepalive with time interval <10 seconds.
|
|
2. Verify Error callback is recevied.
|
|
"""
|
|
# keepalive time interval, client port
|
|
time_interval = random.randint(1, 9)
|
|
self.log.info("Natt socket keepalive time interval: %s" % time_interval)
|
|
self.log.info("UDP encap port on server: %s" % UDP_SERVER_PORT)
|
|
|
|
# open udp encap socket
|
|
self.udp_encap = self.dut.droid.ipSecOpenUdpEncapsulationSocket()
|
|
|
|
# start Natt socket keepalive
|
|
ska_key = cutils.start_natt_socket_keepalive(
|
|
self.dut, self.udp_encap, self.dut_ip, self.host_ip, time_interval)
|
|
asserts.assert_true(not ska_key, "Failed to receive error callback")
|
|
|
|
### Tests End
|