test_wmediumd.py 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. # wmediumd sanity checks
  2. # Copyright (c) 2015, Intel Deutschland GmbH
  3. #
  4. # This software may be distributed under the terms of the BSD license.
  5. # See README for more details.
  6. import tempfile, os, subprocess, errno, hwsim_utils
  7. from utils import HwsimSkip
  8. from wpasupplicant import WpaSupplicant
  9. from test_ap_open import _test_ap_open
  10. from test_wpas_mesh import check_mesh_support, check_mesh_group_added
  11. from test_wpas_mesh import check_mesh_peer_connected, add_open_mesh_network
  12. from test_wpas_mesh import check_mesh_group_removed
  13. class LocalVariables:
  14. revs = []
  15. CFG = """
  16. ifaces :
  17. {
  18. ids = ["%s", "%s" ];
  19. links = (
  20. (0, 1, 30)
  21. );
  22. };
  23. """
  24. CFG2 = """
  25. ifaces :
  26. {
  27. ids = ["%s", "%s", "%s"];
  28. };
  29. model:
  30. {
  31. type = "prob";
  32. links = (
  33. (0, 1, 0.000000),
  34. (0, 2, 0.000000),
  35. (1, 2, 1.000000)
  36. );
  37. };
  38. """
  39. CFG3 = """
  40. ifaces :
  41. {
  42. ids = ["%s", "%s", "%s", "%s", "%s" ];
  43. };
  44. model:
  45. {
  46. type = "prob";
  47. default_prob = 1.0;
  48. links = (
  49. (0, 1, 0.000000),
  50. (1, 2, 0.000000),
  51. (2, 3, 0.000000),
  52. (3, 4, 0.000000)
  53. );
  54. };
  55. """
  56. def get_wmediumd_version():
  57. if len(LocalVariables.revs) > 0:
  58. return LocalVariables.revs;
  59. try:
  60. verstr = subprocess.check_output(['wmediumd', '-V'])
  61. except OSError, e:
  62. if e.errno == errno.ENOENT:
  63. raise HwsimSkip('wmediumd not available')
  64. raise
  65. vernum = verstr.split(' ')[1][1:]
  66. LocalVariables.revs = vernum.split('.')
  67. for i in range(0, len(LocalVariables.revs)):
  68. LocalVariables.revs[i] = int(LocalVariables.revs[i])
  69. while len(LocalVariables.revs) < 3:
  70. LocalVariables.revs += [0]
  71. return LocalVariables.revs;
  72. def require_wmediumd_version(major, minor, patch):
  73. revs = get_wmediumd_version()
  74. if revs[0] < major or revs[1] < minor or revs[2] < patch:
  75. raise HwsimSkip('wmediumd v%s.%s.%s is too old for this test' %
  76. (revs[0], revs[1], revs[2]))
  77. def output_wmediumd_log(p, params, data):
  78. log_file = open(os.path.abspath(os.path.join(params['logdir'],
  79. 'wmediumd.log')), 'a')
  80. log_file.write(data)
  81. log_file.close()
  82. def start_wmediumd(fn, params):
  83. try:
  84. p = subprocess.Popen(['wmediumd', '-c', fn],
  85. stdout=subprocess.PIPE,
  86. stderr=subprocess.STDOUT)
  87. except OSError, e:
  88. if e.errno == errno.ENOENT:
  89. raise HwsimSkip('wmediumd not available')
  90. raise
  91. logs = ''
  92. while True:
  93. line = p.stdout.readline()
  94. if not line:
  95. output_wmediumd_log(p, params, logs)
  96. raise Exception('wmediumd was terminated unexpectedly')
  97. if line.find('REGISTER SENT!') > -1:
  98. break
  99. logs += line
  100. return p
  101. def stop_wmediumd(p, params):
  102. p.terminate()
  103. p.wait()
  104. stdoutdata, stderrdata = p.communicate()
  105. output_wmediumd_log(p, params, stdoutdata)
  106. def test_wmediumd_simple(dev, apdev, params):
  107. """test a simple wmediumd configuration"""
  108. fd, fn = tempfile.mkstemp()
  109. try:
  110. f = os.fdopen(fd, 'w')
  111. f.write(CFG % (apdev[0]['bssid'], dev[0].own_addr()))
  112. f.close()
  113. p = start_wmediumd(fn, params)
  114. try:
  115. _test_ap_open(dev, apdev)
  116. finally:
  117. stop_wmediumd(p, params)
  118. # test that releasing hwsim works correctly
  119. _test_ap_open(dev, apdev)
  120. finally:
  121. os.unlink(fn)
  122. def test_wmediumd_path_simple(dev, apdev, params):
  123. """test a mesh path"""
  124. # 0 and 1 is connected
  125. # 0 and 2 is connected
  126. # 1 and 2 is not connected
  127. # 1 --- 0 --- 2
  128. # | |
  129. # +-----X-----+
  130. # This tests if 1 and 2 can communicate each other via 0.
  131. require_wmediumd_version(0, 3, 1)
  132. fd, fn = tempfile.mkstemp()
  133. try:
  134. f = os.fdopen(fd, 'w')
  135. f.write(CFG2 % (dev[0].own_addr(), dev[1].own_addr(),
  136. dev[2].own_addr()))
  137. f.close()
  138. p = start_wmediumd(fn, params)
  139. try:
  140. _test_wmediumd_path_simple(dev, apdev)
  141. finally:
  142. stop_wmediumd(p, params)
  143. finally:
  144. os.unlink(fn)
  145. def _test_wmediumd_path_simple(dev, apdev):
  146. for i in range(0, 3):
  147. check_mesh_support(dev[i])
  148. add_open_mesh_network(dev[i], freq="2462", basic_rates="60 120 240")
  149. # Check for mesh joined
  150. for i in range(0, 3):
  151. check_mesh_group_added(dev[i])
  152. state = dev[i].get_status_field("wpa_state")
  153. if state != "COMPLETED":
  154. raise Exception("Unexpected wpa_state on dev" + str(i) + ": " + state)
  155. mode = dev[i].get_status_field("mode")
  156. if mode != "mesh":
  157. raise Exception("Unexpected mode: " + mode)
  158. # Check for peer connected
  159. check_mesh_peer_connected(dev[0])
  160. check_mesh_peer_connected(dev[0])
  161. check_mesh_peer_connected(dev[1])
  162. check_mesh_peer_connected(dev[2])
  163. # Test connectivity 1->2 and 2->1
  164. hwsim_utils.test_connectivity(dev[1], dev[2])
  165. # Check mpath table on 0
  166. res, data = dev[0].cmd_execute(['iw', dev[0].ifname, 'mpath', 'dump'])
  167. if res != 0:
  168. raise Exception("iw command failed on dev0")
  169. if data.find(dev[1].own_addr() + ' ' + dev[1].own_addr()) == -1 or \
  170. data.find(dev[2].own_addr() + ' ' + dev[2].own_addr()) == -1:
  171. raise Exception("mpath not found on dev0:\n" + data)
  172. if data.find(dev[0].own_addr()) > -1:
  173. raise Exception("invalid mpath found on dev0:\n" + data)
  174. # Check mpath table on 1
  175. res, data = dev[1].cmd_execute(['iw', dev[1].ifname, 'mpath', 'dump'])
  176. if res != 0:
  177. raise Exception("iw command failed on dev1")
  178. if data.find(dev[0].own_addr() + ' ' + dev[0].own_addr()) == -1 or \
  179. data.find(dev[2].own_addr() + ' ' + dev[0].own_addr()) == -1:
  180. raise Exception("mpath not found on dev1:\n" + data)
  181. if data.find(dev[2].own_addr() + ' ' + dev[2].own_addr()) > -1 or \
  182. data.find(dev[1].own_addr()) > -1:
  183. raise Exception("invalid mpath found on dev1:\n" + data)
  184. # Check mpath table on 2
  185. res, data = dev[2].cmd_execute(['iw', dev[2].ifname, 'mpath', 'dump'])
  186. if res != 0:
  187. raise Exception("iw command failed on dev2")
  188. if data.find(dev[0].own_addr() + ' ' + dev[0].own_addr()) == -1 or \
  189. data.find(dev[1].own_addr() + ' ' + dev[0].own_addr()) == -1:
  190. raise Exception("mpath not found on dev2:\n" + data)
  191. if data.find(dev[1].own_addr() + ' ' + dev[1].own_addr()) > -1 or \
  192. data.find(dev[2].own_addr()) > -1:
  193. raise Exception("invalid mpath found on dev2:\n" + data)
  194. # remove mesh groups
  195. for i in range(0, 3):
  196. dev[i].mesh_group_remove()
  197. check_mesh_group_removed(dev[i])
  198. dev[i].dump_monitor()
  199. def test_wmediumd_path_ttl(dev, apdev, params):
  200. """Mesh path request TTL"""
  201. # 0 --- 1 --- 2 --- 3 --- 4
  202. # Test the TTL of mesh path request.
  203. # If the TTL is shorter than path, the mesh path request should be dropped.
  204. require_wmediumd_version(0, 3, 1)
  205. local_dev = []
  206. for i in range(0, 3):
  207. local_dev.append(dev[i])
  208. for i in range(5, 7):
  209. wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
  210. wpas.interface_add("wlan" + str(i))
  211. check_mesh_support(wpas)
  212. temp_dev = wpas.request("MESH_INTERFACE_ADD ifname=mesh" + str(i))
  213. if "FAIL" in temp_dev:
  214. raise Exception("MESH_INTERFACE_ADD failed")
  215. local_dev.append(WpaSupplicant(ifname=temp_dev))
  216. fd, fn = tempfile.mkstemp()
  217. try:
  218. f = os.fdopen(fd, 'w')
  219. f.write(CFG3 % (local_dev[0].own_addr(), local_dev[1].own_addr(),
  220. local_dev[2].own_addr(), local_dev[3].own_addr(),
  221. local_dev[4].own_addr()))
  222. f.close()
  223. p = start_wmediumd(fn, params)
  224. try:
  225. _test_wmediumd_path_ttl(local_dev, True)
  226. _test_wmediumd_path_ttl(local_dev, False)
  227. finally:
  228. stop_wmediumd(p, params)
  229. finally:
  230. os.unlink(fn)
  231. for i in range(5, 7):
  232. wpas.interface_remove("wlan" + str(i))
  233. def _test_wmediumd_path_ttl(dev, ok):
  234. for i in range(0, 5):
  235. check_mesh_support(dev[i])
  236. add_open_mesh_network(dev[i], freq="2462", basic_rates="60 120 240")
  237. # Check for mesh joined
  238. for i in range(0, 5):
  239. check_mesh_group_added(dev[i])
  240. state = dev[i].get_status_field("wpa_state")
  241. if state != "COMPLETED":
  242. raise Exception("Unexpected wpa_state on dev" + str(i) + ": " + state)
  243. mode = dev[i].get_status_field("mode")
  244. if mode != "mesh":
  245. raise Exception("Unexpected mode: " + mode)
  246. # set mesh path request ttl
  247. subprocess.check_call([ "iw", "dev", dev[0].ifname, "set", "mesh_param",
  248. "mesh_element_ttl=" + ("4" if ok else "3") ])
  249. # Check for peer connected
  250. for i in range(0, 5):
  251. check_mesh_peer_connected(dev[i])
  252. for i in range(1, 4):
  253. check_mesh_peer_connected(dev[i])
  254. # Test connectivity 0->4 and 0->4
  255. hwsim_utils.test_connectivity(dev[0], dev[4], success_expected=ok)
  256. # Check mpath table on 0
  257. res, data = dev[0].cmd_execute(['iw', dev[0].ifname, 'mpath', 'dump'])
  258. if res != 0:
  259. raise Exception("iw command failed on dev0")
  260. if ok:
  261. if data.find(dev[1].own_addr() + ' ' + dev[1].own_addr()) == -1 or \
  262. data.find(dev[4].own_addr() + ' ' + dev[1].own_addr()) == -1:
  263. raise Exception("mpath not found on dev0:\n" + data)
  264. else:
  265. if data.find(dev[1].own_addr() + ' ' + dev[1].own_addr()) == -1 or \
  266. data.find(dev[4].own_addr() + ' 00:00:00:00:00:00') == -1:
  267. raise Exception("mpath not found on dev0:\n" + data)
  268. if data.find(dev[0].own_addr()) > -1 or \
  269. data.find(dev[2].own_addr()) > -1 or \
  270. data.find(dev[3].own_addr()) > -1:
  271. raise Exception("invalid mpath found on dev0:\n" + data)
  272. # remove mesh groups
  273. for i in range(0, 3):
  274. dev[i].mesh_group_remove()
  275. check_mesh_group_removed(dev[i])
  276. dev[i].dump_monitor()