diff mbox

[v3,4/6] tests/remote: add utils file

Message ID 1461906457-18455-4-git-send-email-janusz.dziedzic@tieto.com
State Accepted
Headers show

Commit Message

Janusz.Dziedzic@tieto.com April 29, 2016, 5:07 a.m. UTC
Add rutils.py for remote tests.

Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
---
 tests/hwsim/remotehost.py    |   1 +
 tests/remote/run-tests.py    |   4 +
 tests/remote/rutils.py       | 543 +++++++++++++++++++++++++++++++++++++++++++
 tests/remote/test_devices.py |  10 +-
 4 files changed, 551 insertions(+), 7 deletions(-)
 create mode 100644 tests/remote/rutils.py
diff mbox

Patch

diff --git a/tests/hwsim/remotehost.py b/tests/hwsim/remotehost.py
index f86e972..5021b92 100644
--- a/tests/hwsim/remotehost.py
+++ b/tests/hwsim/remotehost.py
@@ -36,6 +36,7 @@  class Host():
         self.logs = []
         self.ifname = ifname
         self.port = port
+        self.dev = None
         if self.name == "" and host != None:
             self.name = host
 
diff --git a/tests/remote/run-tests.py b/tests/remote/run-tests.py
index 33ac8e6..c3cb16a 100755
--- a/tests/remote/run-tests.py
+++ b/tests/remote/run-tests.py
@@ -24,6 +24,7 @@  import wpaspy
 import config
 from test_devices import show_devices
 from test_devices import check_devices
+from rutils import TestSkip
 
 def usage():
     print "USAGE: " + sys.argv[0] + " -t devices"
@@ -261,6 +262,9 @@  def main():
         except KeyboardInterrupt:
             put_devices(devices, duts, refs, monitors)
             raise
+        except TestSkip, e:
+            end = datetime.now()
+            logger.warning("SKIP (" + str(e) + ") - " + str((end - start).total_seconds()) + "s")
         except Exception, e:
             end = datetime.now()
             logger.warning("FAILED (" + str(e) + ") - " + str((end - start).total_seconds()) + "s")
diff --git a/tests/remote/rutils.py b/tests/remote/rutils.py
new file mode 100644
index 0000000..98a85be
--- /dev/null
+++ b/tests/remote/rutils.py
@@ -0,0 +1,543 @@ 
+#
+# Utils
+# Copyright (c) 2016, Tieto Corporation
+#
+# This software may be distributed under the terms of the BSD license.
+# See README for more details.
+import time
+from remotehost import Host
+import hostapd
+import config
+
+class TestSkip(Exception):
+    def __init__(self, reason):
+        self.reason = reason
+    def __str__(self):
+        return self.reason
+
+# get host based on name
+def get_host(devices, dev_name):
+    dev = config.get_device(devices, dev_name)
+    host = Host(host = dev['hostname'],
+                ifname = dev['ifname'],
+                port = dev['port'],
+                name = dev['name'])
+    host.dev = dev
+    return host
+
+# run setup_hw - hw specyfic
+def setup_hw(hosts, setup_params):
+    for host in hosts:
+        setup_hw_host(host, setup_params)
+
+def setup_hw_host(host, setup_params):
+    try:
+        setup_hw = setup_params['setup_hw']
+        restart = ""
+        try:
+            if setup_params['restart_device'] == True:
+                restart = " -R "
+        except:
+            pass
+        host.execute([setup_hw, "-I", host.ifname, restart])
+    except:
+        pass
+
+# get traces - hw specyfic
+def trace_start(hosts, setup_params):
+    for host in hosts:
+        trace_start_stop(host, setup_params, start=True)
+
+def trace_stop(hosts, setup_params):
+    for host in hosts:
+        trace_start_stop(host, setup_params, start=False)
+
+def trace_start_stop(host, setup_params, start):
+    if setup_params['trace'] == False:
+        return
+    try:
+        start_trace = setup_params['trace_start']
+        stop_trace = setup_params['trace_stop']
+        if start:
+            cmd = start_trace
+        else:
+            cmd = stop_trace
+        trace_dir = setup_params['log_dir'] + host.ifname + "/remote_traces"
+        host.logs.append(trace_dir + "/*")
+        host.execute([cmd, "-I", host.ifname, "-D", trace_dir])
+    except:
+        pass
+
+# get perf
+def perf_start(hosts, setup_params):
+    for host in hosts:
+        perf_start_stop(host, setup_params, start=True)
+
+def perf_stop(hosts, setup_params):
+    for host in hosts:
+        perf_start_stop(host, setup_params, start=False)
+
+def perf_start_stop(host, setup_params, start):
+    if setup_params['perf'] == False:
+        return
+    try:
+        perf_start = setup_params['perf_start']
+        perf_stop = setup_params['perf_stop']
+        if start:
+            cmd = perf_start
+        else:
+            cmd = perf_stop
+        perf_dir = setup_params['log_dir'] + host.ifname + "/remote_perf"
+        host.logs.append(perf_dir + "/*")
+        host.execute([cmd, "-I", host.ifname, "-D", perf_dir])
+    except:
+        pass
+
+# hostapd/wpa_supplicant helpers
+def run_hostapd(host, setup_params):
+    log_file = None
+    try:
+        tc_name = setup_params['tc_name']
+        log_dir = setup_params['log_dir']
+        log_file = log_dir + tc_name + "_hostapd_" + host.name + "_" + host.ifname + ".log"
+        host.execute(["rm", log_file])
+        log = " -f " + log_file
+    except:
+        log = ""
+
+    if log_file:
+        host.logs.append(log_file)
+    status, buf = host.execute([setup_params['hostapd'], "-B", "-ddt", "-g", "udp:" + host.port, log])
+    if status != 0:
+        raise Exception("Could not run hostapd: " + buf)
+
+def run_wpasupplicant(host, setup_params):
+    log_file = None
+    try:
+        tc_name = setup_params['tc_name']
+        log_dir = setup_params['log_dir']
+        log_file = log_dir + tc_name + "_wpa_supplicant_" + host.name + "_" + host.ifname + ".log"
+        host.execute(["rm", log_file])
+        log = " -f " + log_file
+    except:
+        log = ""
+
+    if log_file:
+        host.logs.append(log_file)
+    status, buf = host.execute([setup_params['wpa_supplicant'], "-B", "-ddt", "-g", "udp:" + host.port, log])
+    if status != 0:
+        raise Exception("Could not run wpa_supplicant: " + buf)
+
+def get_ap_params(channel="1", bw="HT20", country="US", security="open", ht_capab=None, vht_capab=None):
+    ssid = "test_" + channel + "_" + security + "_" + bw
+
+    if bw == "b_only":
+        params = hostapd.b_only_params(channel, ssid, country)
+    elif bw == "g_only":
+        params = hostapd.g_only_params(channel, ssid, country)
+    elif bw == "g_only_wmm":
+        params = hostapd.g_only_params(channel, ssid, country)
+        params['wmm_enabled'] = "1"
+    elif bw == "a_only":
+        params = hostapd.a_only_params(channel, ssid, country)
+    elif bw == "a_only_wmm":
+        params = hostapd.a_only_params(channel, ssid, country)
+        params['wmm_enabled'] = "1"
+    elif bw == "HT20":
+        params = hostapd.ht20_params(channel, ssid, country)
+        if ht_capab:
+            try:
+                params['ht_capab'] = params['ht_capab'] + ht_capab
+            except:
+                params['ht_capab'] = ht_capab
+    elif bw == "HT40+":
+        params = hostapd.ht40_plus_params(channel, ssid, country)
+        if ht_capab:
+            params['ht_capab'] = params['ht_capab'] + ht_capab
+    elif bw == "HT40-":
+        params = hostapd.ht40_minus_params(channel, ssid, country)
+        if ht_capab:
+            params['ht_capab'] = params['ht_capab'] + ht_capab
+    elif bw == "VHT80":
+        params = hostapd.ht40_plus_params(channel, ssid, country)
+        if ht_capab:
+            params['ht_capab'] = params['ht_capab'] + ht_capab
+        if vht_capab:
+            try:
+                params['vht_capab'] = params['vht_capab'] + vht_capab
+            except:
+                params['vht_capab'] = vht_capab
+        params['ieee80211ac'] = "1"
+        params['vht_oper_chwidth'] = "1"
+        params['vht_oper_centr_freq_seg0_idx'] = str(int(channel) + 6)
+    else:
+        params = {}
+
+    # now setup security params
+    if security == "tkip":
+        sec_params = hostapd.wpa_params(passphrase="testtest")
+    elif security == "ccmp":
+        sec_params = hostapd.wpa2_params(passphrase="testtest")
+    elif security == "mixed":
+        sec_params = hostapd.wpa_mixed_params(passphrase="testtest")
+    elif security == "wep":
+        sec_params = { "wep_key0" : "123456789a",
+                       "wep_default_key" : "0",
+                       "auth_algs" : "1"}
+    elif security == "wep_shared":
+        sec_params = { "wep_key0" : "123456789a",
+                       "wep_default_key" : "0",
+                       "auth_algs" : "2" }
+    else:
+        sec_params = {}
+
+    params.update(sec_params)
+
+    return params
+
+# ip helpers
+def get_ipv4(client, ifname=None):
+    if ifname is None:
+        ifname = client.ifname
+    status, buf = client.execute(["ifconfig", ifname])
+    lines = buf.splitlines()
+
+    for line in lines:
+        res = line.find("inet addr:")
+        if res != -1:
+            break
+
+    if res != -1:
+        words = line.split()
+        addr = words[1].split(":")
+        return addr[1]
+
+    return "unknown"
+
+def get_ipv6(client, ifname=None):
+    res = -1
+    if ifname is None:
+        ifname = client.ifname
+    status, buf = client.execute(["ifconfig", ifname])
+    lines = buf.splitlines()
+
+    for line in lines:
+        res = line.find("Scope:Link")
+        if res != -1:
+            break
+
+    if res != -1:
+        words = line.split()
+        if words[0] == "inet6" and words[1] == "addr:":
+            addr_mask = words[2]
+            addr = addr_mask.split("/")
+            return addr[0]
+
+    return "unknown"
+
+def get_ip(client, addr_type="ipv6", iface=None):
+    if addr_type == "ipv6":
+        return get_ipv6(client, iface)
+    elif addr_type == "ipv4":
+        return get_ipv4(client, iface)
+    else:
+        return "unknown addr_type: " + addr_type
+
+def get_ipv4_addr(setup_params, number):
+    try:
+        ipv4_base = setup_params['ipv4_test_net']
+    except:
+        ipv4_base = "172.16.12.0"
+
+    parts = ipv4_base.split('.')
+    ipv4 = parts[0] + "." + parts[1] + "." + parts[2] + "." + str(number)
+
+    return ipv4
+
+def get_mac_addr(host, iface=None):
+    if iface == None:
+        iface = host.ifname
+    status, buf = host.execute(["ifconfig", iface])
+    if status != 0:
+        raise Exception("ifconfig " + iface)
+    words = buf.split()
+    found = 0
+    for word in words:
+        if found == 1:
+            return word
+        if word == "HWaddr":
+            found = 1
+    raise Exception("Could not find HWaddr")
+
+# connectivity/ping helpers
+def get_ping_packet_loss(ping_res):
+    loss_line = ""
+    lines = ping_res.splitlines()
+    for line in lines:
+        if line.find("packet loss") != -1:
+            loss_line = line
+            break;
+
+    if loss_line == "":
+        return "100%"
+
+    sections = loss_line.split(",")
+
+    for section in sections:
+        if section.find("packet loss") != -1:
+            words = section.split()
+            return words[0]
+
+    return "100%"
+
+def ac_to_ping_ac(qos):
+    if qos == "be":
+        qos_param = "0x00"
+    elif qos == "bk":
+        qos_param = "0x20"
+    elif qos == "vi":
+        qos_param = "0xA0"
+    elif qos == "vo":
+        qos_param = "0xE0"
+    else:
+        qos_param = "0x00"
+    return qos_param
+
+def ping_run(host, ip, result, ifname=None, addr_type="ipv4", deadline="5", qos=None):
+    if ifname is None:
+       ifname = host.ifname
+    if addr_type == "ipv6":
+        ping = ["ping6"]
+    else:
+        ping = ["ping"]
+
+    ping = ping + ["-w", deadline, "-I", ifname]
+    if qos:
+        ping = ping + ["-Q", ac_to_ping_ac(qos)]
+    ping = ping + [ip]
+
+    flush_arp_cache(host)
+
+    thread = host.execute_run(ping, result)
+    return thread
+
+def ping_wait(host, thread, timeout=None):
+    host.wait_execute_complete(thread, timeout)
+    if thread.isAlive():
+        raise Exception("ping thread still alive")
+
+def flush_arp_cache(host):
+    host.execute(["ip", "-s", "-s", "neigh", "flush", "all"])
+
+def check_connectivity(a, b, addr_type = "ipv4", deadline="5", qos=None):
+    addr_a = get_ip(a, addr_type)
+    addr_b = get_ip(b, addr_type)
+
+    if addr_type == "ipv4":
+        ping = ["ping"]
+    else:
+        ping = ["ping6"]
+
+    ping_a_b = ping + ["-w", deadline, "-I", a.ifname]
+    ping_b_a = ping + ["-w", deadline, "-I", b.ifname]
+    if qos:
+        ping_a_b = ping_a_b + ["-Q", ac_to_ping_ac(qos)]
+        ping_b_a = ping_b_a + ["-Q", ac_to_ping_ac(qos)]
+    ping_a_b = ping_a_b + [addr_b]
+    ping_b_a = ping_b_a + [addr_a]
+
+    # Clear arp cache
+    flush_arp_cache(a)
+    flush_arp_cache(b)
+
+    status, buf = a.execute(ping_a_b)
+    if status == 2 and ping == "ping6":
+        # tentative possible for a while, try again
+        time.sleep(3)
+        status, buf = a.execute(ping_a_b)
+    if status != 0:
+        raise Exception("ping " + a.name + "/" + a.ifname + " >> " + b.name + "/" + b.ifname)
+
+    a_b = get_ping_packet_loss(buf)
+
+    # Clear arp cache
+    flush_arp_cache(a)
+    flush_arp_cache(b)
+
+    status, buf = b.execute(ping_b_a)
+    if status != 0:
+        raise Exception("ping " + b.name + "/" + b.ifname + " >> " + a.name + "/" + a.ifname)
+
+    b_a = get_ping_packet_loss(buf)
+
+    if int(a_b[:-1]) > 40:
+        raise Exception("Too high packet lost: " + a_b)
+
+    if int(b_a[:-1]) > 40:
+        raise Exception("Too high packet lost: " + b_a)
+
+    return a_b, b_a
+
+
+# iperf helpers
+def get_iperf_speed(iperf_res, pattern="Mbits/sec"):
+    lines = iperf_res.splitlines()
+    sum_line = ""
+    last_line = ""
+    count = 0
+    res = -1
+
+    # first find last SUM line
+    for line in lines:
+        res  = line.find("[SUM]")
+        if res != -1:
+            sum_line = line
+
+    # next check SUM status
+    if sum_line != "":
+        words = sum_line.split()
+        for word in words:
+            res = word.find(pattern)
+            if res != -1:
+                return words[count - 1] + " " + pattern
+            count = count + 1
+
+    # no SUM - one thread - find last line
+    for line in lines:
+        res = line.find(pattern)
+        if res != -1:
+            last_line = line
+
+    if last_line == "":
+        return "0 " + pattern
+
+    count = 0
+    words = last_line.split()
+    for word in words:
+        res = word.find(pattern)
+        if res != -1:
+            return words[count - 1] + " " + pattern
+            break;
+        count = count + 1
+    return "0 " + pattern
+
+def ac_to_iperf_ac(qos):
+    if qos == "be":
+        qos_param = "0x00"
+    elif qos == "bk":
+        qos_param = "0x20"
+    elif qos == "vi":
+        qos_param = "0xA0"
+    elif qos == "vo":
+        qos_param = "0xE0"
+    else:
+        qos_param = "0x00"
+    return qos_param
+
+def iperf_run(server, client, server_ip, client_res, server_res,
+              l4="udp", bw="30M", test_time="30", parallel="5",
+              qos="be", param=" -i 5 ", ifname=None, l3="ipv4",
+              port="5001", iperf="iperf"):
+    if ifname == None:
+        ifname = client.ifname
+
+    if iperf == "iperf":
+        iperf_server = [iperf]
+    elif iperf == "iperf3":
+        iperf_server = [iperf, "-1"]
+
+    if l3 == "ipv4":
+        iperf_client = [iperf, "-c", server_ip, "-p", port]
+        iperf_server = iperf_server + ["-p", port]
+    elif l3 == "ipv6":
+        iperf_client = [iperf, "-V", "-c", server_ip  + "%" + ifname, "-p", port]
+        iperf_server = iperf_server + ["-V", "-p",  port]
+    else:
+        return -1, -1
+
+    iperf_server = iperf_server + ["-s", "-f", "m", param]
+    iperf_client = iperf_client + ["-f", "m", "-t", test_time]
+
+    if parallel != "1":
+        iperf_client = iperf_client + ["-P", parallel]
+
+    if l4 == "udp":
+        if iperf != "iperf3":
+            iperf_server = iperf_server + ["-u"]
+        iperf_client = iperf_client + ["-u", "-b",  bw]
+
+    if qos:
+        iperf_client = iperf_client + ["-Q", ac_to_iperf_ac(qos)]
+
+    flush_arp_cache(server)
+    flush_arp_cache(client)
+
+    server_thread = server.execute_run(iperf_server, server_res)
+    time.sleep(1)
+    client_thread = client.execute_run(iperf_client, client_res)
+
+    return server_thread, client_thread
+
+def iperf_wait(server, client, server_thread, client_thread, timeout=None, iperf="iperf"):
+    client.wait_execute_complete(client_thread, timeout)
+    if client_thread.isAlive():
+        raise Exception("iperf client thread still alive")
+
+    server.wait_execute_complete(server_thread, 5)
+    if server_thread.isAlive():
+        server.execute(["killall", "-s", "INT", iperf])
+        time.sleep(1)
+
+    server.wait_execute_complete(server_thread, 5)
+    if server_thread.isAlive():
+        raise Execption("iperf server thread still alive")
+
+    return
+
+def run_tp_test(server, client, l3="ipv4", iperf="iperf", l4="tcp", test_time="10", parallel="5",
+                qos="be", bw="30M", ifname=None, port="5001"):
+    client_res = []
+    server_res = []
+
+    server_ip = get_ip(server, l3)
+    time.sleep(1)
+    server_thread, client_thread = iperf_run(server, client, server_ip, client_res, server_res,
+                                             l3=l3, iperf=iperf, l4=l4, test_time=test_time,
+                                             parallel=parallel, qos=qos, bw=bw, ifname=ifname,
+                                             port=port)
+    iperf_wait(server, client, server_thread, client_thread, iperf=iperf, timeout=int(test_time) + 10)
+
+    if client_res[0] != 0:
+        raise Exception(iperf + " client: " + client_res[1])
+    if server_res[0] != 0:
+        raise Exception(iperf + " server: " + server_res[1])
+    if client_res[1] is None:
+        raise Exception(iperf + " client result issue")
+    if server_res[1] is None:
+        raise Exception(iperf + " server result issue")
+
+    if iperf == "iperf":
+          result = server_res[1]
+    if iperf == "iperf3":
+          result = client_res[1]
+
+    speed = get_iperf_speed(result)
+    return speed
+
+def get_iperf_bw(bw, parallel, spacial_streams=2):
+    if bw == "b_only":
+        max_tp = 11
+    elif bw == "g_only" or bw == "g_only_wmm" or bw == "a_only" or bw == "a_only_wmm":
+        max_tp = 54
+    elif bw == "HT20":
+        max_tp = 72 * spacial_streams
+    elif bw == "HT40+" or bw == "HT40-":
+        max_tp = 150 * spacial_streams
+    elif bw == "VHT80":
+        max_tp = 433 * spacial_streams
+    else:
+        max_tp = 150
+
+    max_tp = 1.2 * max_tp
+
+    return str(int(max_tp/int(parallel))) + "M"
diff --git a/tests/remote/test_devices.py b/tests/remote/test_devices.py
index 0038924..b84e5fe 100644
--- a/tests/remote/test_devices.py
+++ b/tests/remote/test_devices.py
@@ -16,7 +16,7 @@  import re
 import logging
 logger = logging.getLogger()
 
-import utils
+import rutils
 from remotehost import Host
 from wpasupplicant import WpaSupplicant
 import hostapd
@@ -25,9 +25,7 @@  def show_devices(devices, setup_params):
     """Show/check available devices"""
     print "Devices:"
     for device in devices:
-        dev = config.get_device(devices, device['name'])
-        host = Host(host = dev['hostname'], ifname = dev['ifname'],
-                    port = dev['port'], name = dev['name'])
+        host = rutils.get_host(devices, device['name'])
         # simple check if authorized_keys works correctly
         status, buf = host.execute(["id"])
         if status != 0:
@@ -83,9 +81,7 @@  def show_devices(devices, setup_params):
         print ""
 
 def check_device(devices, setup_params, dev_name, monitor=False):
-    dev = config.get_device(devices, dev_name)
-    host = Host(host = dev['hostname'], ifname = dev['ifname'],
-                port = dev['port'], name = dev['name'])
+    host = rutils.get_host(devices, dev_name)
     # simple check if authorized_keys works correctly
     status, buf = host.execute(["id"])
     if status != 0: