diff --git a/tests/remote/utils.py b/tests/remote/utils.py
new file mode 100644
index 0000000..ffdffcc
--- /dev/null
+++ b/tests/remote/utils.py
@@ -0,0 +1,314 @@
+import time
+import wpaspy
+
+def get_device(devices, name=None, flags=None):
+    if name is None and flags is None:
+        return devices[0]
+    for device in devices:
+        if device['name'] == name:
+            return device
+    for device in devices:
+        try:
+            device_flags = device['flags']
+            if device_flags.find(flags) != -1:
+                return device
+        except:
+            pass
+    return None
+
+def get_dut(duts, name=None):
+    if name is None:
+        return duts[0]
+    for dut in duts:
+        if dut['name'] == name:
+            return dut
+    return None
+
+def run_hostapd(dev, setup_params):
+    log_file = None
+    host = wpaspy.Host(host = dev['hostname'],
+                       ifname = dev['ifname'],
+                       port = dev['port'],
+                       name = dev['name'])
+    try:
+        setup_hw = setup_params['setup_hw']
+        host.execute(setup_hw + " -I " + dev['ifname'])
+    except:
+        pass
+
+    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 = ""
+
+    status, buf = host.execute(setup_params['hostapd'] + " -B -ddt -g udp:" + host.port + log)
+    if status != 0:
+        raise Exception("Could not run hostapd: " + buf)
+
+    return host, log_file
+
+def run_wpasupplicant(dev, setup_params):
+    log_file = None
+    host = wpaspy.Host(host = dev['hostname'],
+                       ifname = dev['ifname'],
+                       port = dev['port'],
+                       name = dev['name'])
+    try:
+        setup_hw = setup_params['setup_hw']
+        host.execute(setup_hw + " -I " + dev['ifname'])
+    except:
+        pass
+
+    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 = ""
+
+    status, buf = host.execute(setup_params['wpa_supplicant'] + " -B -g udp:" + host.port + log)
+    if status != 0:
+        raise Exception("Could not run wpa_supplicant: " + buf)
+
+    return host, log_file
+
+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 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 ping_run(host, ip, result, ifname=None, addr_type="ipv4", deadline="5"):
+    ping = "ping"
+    if ifname is None:
+       ifname = host.ifname
+    if addr_type is "ipv6":
+        ping = "ping6"
+    ping = ping + " -w 5" + " -I " + ifname + " " + ip
+
+    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 check_connectivity(a, b, addr_type = "ipv4", deadline="5"):
+    addr_a = get_ip(a, addr_type)
+    addr_b = get_ip(b, addr_type)
+
+    if addr_type == "ipv4":
+        ping = "ping"
+    else:
+        ping = "ping6"
+
+    status, buf = a.execute(ping + " -w " + deadline + " -I " + a.ifname + " " + addr_b)
+    if status != 0:
+        raise Exception("ping " + a.ifname + " >> " + b.ifname)
+
+    a_b = get_ping_packet_loss(buf)
+
+    status, buf = b.execute(ping + " -w " + deadline + " -I " + b.ifname + " " + addr_a)
+    if status != 0:
+        raise Exception("ping " + b.ifname + " >> " + 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
+
+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 = "-S 0x00"
+    elif qos == "bk":
+        qos_param = "-S 0x20"
+    elif qos == "vi":
+        qos_param = "-S 0xA0"
+    elif qos == "vo":
+        qos_param = "-S 0xE0"
+    else:
+        qos_param = "-S 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 is not "iperf3":
+            iperf_server = iperf_server + " -u"
+        iperf_client = iperf_client + " -u -b " + bw
+
+    qos_param = ac_to_iperf_ac(qos)
+    iperf_client = iperf_client + " " + qos_param
+
+    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 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
