diff --git a/tests/hwsim/test_wmediumd.py b/tests/hwsim/test_wmediumd.py index 8aeacbb9a..d07d5aca2 100644 --- a/tests/hwsim/test_wmediumd.py +++ b/tests/hwsim/test_wmediumd.py @@ -4,9 +4,10 @@ # This software may be distributed under the terms of the BSD license. # See README for more details. -import tempfile, os, subprocess, errno, hwsim_utils +import tempfile, os, subprocess, errno, hwsim_utils, time from utils import HwsimSkip from wpasupplicant import WpaSupplicant +from tshark import run_tshark from test_ap_open import _test_ap_open from test_wpas_mesh import check_mesh_support, check_mesh_group_added from test_wpas_mesh import check_mesh_peer_connected, add_open_mesh_network @@ -317,3 +318,147 @@ def _test_wmediumd_path_ttl(dev, ok): dev[i].mesh_group_remove() check_mesh_group_removed(dev[i]) dev[i].dump_monitor() + +def test_wmediumd_path_rann(dev, apdev, params): + """Mesh path with RANN""" + # 0 and 1 is connected + # 0 and 2 is connected + # 1 and 2 is not connected + # 2 is mesh root and RANN enabled + # 1 --- 0 --- 2 + # | | + # +-----X-----+ + # This tests if 1 and 2 can communicate each other via 0. + require_wmediumd_version(0, 3, 1) + fd, fn = tempfile.mkstemp() + try: + f = os.fdopen(fd, 'w') + f.write(CFG2 % (dev[0].own_addr(), dev[1].own_addr(), + dev[2].own_addr())) + f.close() + p = start_wmediumd(fn, params) + try: + _test_wmediumd_path_rann(dev, apdev) + finally: + stop_wmediumd(p, params) + finally: + os.unlink(fn) + + capfile = os.path.join(params['logdir'], "hwsim0.pcapng") + + # check Root STA address in root announcement element + filt = "wlan.fc.type_subtype == 0x000d && " + \ + "wlan_mgt.fixed.mesh_action == 0x01 && " + \ + "wlan_mgt.tag.number == 126" + out = run_tshark(capfile, filt, [ "wlan.rann.root_sta" ]) + if out is None: + raise Exception("No captured data found\n") + if out.find(dev[2].own_addr()) == -1 or \ + out.find(dev[0].own_addr()) > -1 or \ + out.find(dev[1].own_addr()) > -1: + raise Exception("RANN should be sent by dev2 only:\n" + out) + + # check RANN interval is in range + filt = "wlan.sa == 02:00:00:00:02:00 && " + \ + "wlan.fc.type_subtype == 0x000d && " + \ + "wlan_mgt.fixed.mesh_action == 0x01 && " + \ + "wlan_mgt.tag.number == 126" + out = run_tshark(capfile, filt, [ "frame.time_relative" ]) + if out is None: + raise Exception("No captured data found\n") + lines = out.splitlines() + prev = float(lines[len(lines) - 1]) + for i in reversed(range(1, len(lines) - 1)): + now = float(lines[i]) + if prev - now < 1.0 or 3.0 < prev - now: + raise Exception("RANN interval " + str(prev - now) + + "(sec) should be close to 2.0(sec)\n") + prev = now + + # check no one uses broadcast path request + filt = "wlan.da == ff:ff:ff:ff:ff:ff && " + \ + "wlan.fc.type_subtype == 0x000d && " + \ + "wlan_mgt.fixed.mesh_action == 0x01 && " + \ + "wlan_mgt.tag.number == 130" + out = run_tshark(capfile, filt, [ "wlan.sa", "wlan.da" ]) + if out is None: + raise Exception("No captured data found\n") + if len(out) > 0: + raise Exception("invalid broadcast path requests\n" + out) + +def _test_wmediumd_path_rann(dev, apdev): + for i in range(0, 3): + check_mesh_support(dev[i]) + add_open_mesh_network(dev[i], freq="2462", basic_rates="60 120 240") + + # Check for mesh joined + for i in range(0, 3): + check_mesh_group_added(dev[i]) + + state = dev[i].get_status_field("wpa_state") + if state != "COMPLETED": + raise Exception("Unexpected wpa_state on dev" + str(i) + ": " + state) + + mode = dev[i].get_status_field("mode") + if mode != "mesh": + raise Exception("Unexpected mode: " + mode) + + # set node 2 as RANN supported root + subprocess.check_call(["iw", "dev", dev[0].ifname, "set", "mesh_param", + "mesh_hwmp_rootmode=0"]) + subprocess.check_call(["iw", "dev", dev[1].ifname, "set", "mesh_param", + "mesh_hwmp_rootmode=0"]) + subprocess.check_call(["iw", "dev", dev[2].ifname, "set", "mesh_param", + "mesh_hwmp_rootmode=4"]) + subprocess.check_call(["iw", "dev", dev[2].ifname, "set", "mesh_param", + "mesh_hwmp_rann_interval=2000"]) + + # Check for peer connected + check_mesh_peer_connected(dev[0]) + check_mesh_peer_connected(dev[0]) + check_mesh_peer_connected(dev[1]) + check_mesh_peer_connected(dev[2]) + + # Wait for RANN frame + time.sleep(10) + + # Test connectivity 1->2 and 2->1 + hwsim_utils.test_connectivity(dev[1], dev[2]) + + # Check mpath table on 0 + res, data = dev[0].cmd_execute(['iw', dev[0].ifname, 'mpath', 'dump']) + if res != 0: + raise Exception("iw command failed on dev0") + if data.find(dev[1].own_addr() + ' ' + dev[1].own_addr()) == -1 or \ + data.find(dev[2].own_addr() + ' ' + dev[2].own_addr()) == -1: + raise Exception("mpath not found on dev0:\n" + data) + if data.find(dev[0].own_addr()) > -1: + raise Exception("invalid mpath found on dev0:\n" + data) + + # Check mpath table on 1 + res, data = dev[1].cmd_execute(['iw', dev[1].ifname, 'mpath', 'dump']) + if res != 0: + raise Exception("iw command failed on dev1") + if data.find(dev[0].own_addr() + ' ' + dev[0].own_addr()) == -1 or \ + data.find(dev[2].own_addr() + ' ' + dev[0].own_addr()) == -1: + raise Exception("mpath not found on dev1:\n" + data) + if data.find(dev[2].own_addr() + ' ' + dev[2].own_addr()) > -1 or \ + data.find(dev[1].own_addr()) > -1: + raise Exception("invalid mpath found on dev1:\n" + data) + + # Check mpath table on 2 + res, data = dev[2].cmd_execute(['iw', dev[2].ifname, 'mpath', 'dump']) + if res != 0: + raise Exception("iw command failed on dev2") + if data.find(dev[0].own_addr() + ' ' + dev[0].own_addr()) == -1 or \ + data.find(dev[1].own_addr() + ' ' + dev[0].own_addr()) == -1: + raise Exception("mpath not found on dev2:\n" + data) + if data.find(dev[1].own_addr() + ' ' + dev[1].own_addr()) > -1 or \ + data.find(dev[2].own_addr()) > -1: + raise Exception("invalid mpath found on dev2:\n" + data) + + # remove mesh groups + for i in range(0, 3): + dev[i].mesh_group_remove() + check_mesh_group_removed(dev[i]) + dev[i].dump_monitor()