1 # wmediumd sanity checks
2 # Copyright (c) 2015, Intel Deutschland GmbH
4 # This software may be distributed under the terms of the BSD license.
5 # See README for more details.
7 import tempfile
, os
, subprocess
, errno
, hwsim_utils
, time
8 from utils
import HwsimSkip
9 from wpasupplicant
import WpaSupplicant
10 from tshark
import run_tshark
11 from test_ap_open
import _test_ap_open
12 from test_wpas_mesh
import check_mesh_support
, check_mesh_group_added
13 from test_wpas_mesh
import check_mesh_peer_connected
, add_open_mesh_network
14 from test_wpas_mesh
import check_mesh_group_removed
32 ids = ["%s", "%s", "%s"]
50 ids = ["%s", "%s", "%s", "%s", "%s"]
67 def get_wmediumd_version():
68 if len(LocalVariables
.revs
) > 0:
69 return LocalVariables
.revs
72 verstr
= subprocess
.check_output(['wmediumd', '-V']).decode()
74 if e
.errno
== errno
.ENOENT
:
75 raise HwsimSkip('wmediumd not available')
78 vernum
= verstr
.split(' ')[1][1:]
79 LocalVariables
.revs
= vernum
.split('.')
80 for i
in range(0, len(LocalVariables
.revs
)):
81 LocalVariables
.revs
[i
] = int(LocalVariables
.revs
[i
])
82 while len(LocalVariables
.revs
) < 3:
83 LocalVariables
.revs
+= [0]
85 return LocalVariables
.revs
87 def require_wmediumd_version(major
, minor
, patch
):
88 revs
= get_wmediumd_version()
89 if revs
[0] < major
or revs
[1] < minor
or revs
[2] < patch
:
90 raise HwsimSkip('wmediumd v%s.%s.%s is too old for this test' %
91 (revs
[0], revs
[1], revs
[2]))
93 def output_wmediumd_log(p
, params
, data
):
94 log_file
= open(os
.path
.abspath(os
.path
.join(params
['logdir'],
95 'wmediumd.log')), 'a')
99 def start_wmediumd(fn
, params
):
101 p
= subprocess
.Popen(['wmediumd', '-c', fn
],
102 stdout
=subprocess
.PIPE
,
103 stderr
=subprocess
.STDOUT
)
105 if e
.errno
== errno
.ENOENT
:
106 raise HwsimSkip('wmediumd not available')
111 line
= p
.stdout
.readline().decode()
113 output_wmediumd_log(p
, params
, logs
)
114 raise Exception('wmediumd was terminated unexpectedly')
115 if line
.find('REGISTER SENT!') > -1:
120 def stop_wmediumd(p
, params
):
123 stdoutdata
, stderrdata
= p
.communicate()
124 output_wmediumd_log(p
, params
, stdoutdata
.decode())
126 def test_wmediumd_simple(dev
, apdev
, params
):
127 """test a simple wmediumd configuration"""
128 fd
, fn
= tempfile
.mkstemp()
130 f
= os
.fdopen(fd
, 'w')
131 f
.write(CFG
% (apdev
[0]['bssid'], dev
[0].own_addr()))
133 p
= start_wmediumd(fn
, params
)
135 _test_ap_open(dev
, apdev
)
137 stop_wmediumd(p
, params
)
138 # test that releasing hwsim works correctly
139 _test_ap_open(dev
, apdev
)
143 def test_wmediumd_path_simple(dev
, apdev
, params
):
144 """test a mesh path"""
145 # 0 and 1 is connected
146 # 0 and 2 is connected
147 # 1 and 2 is not connected
151 # This tests if 1 and 2 can communicate each other via 0.
152 require_wmediumd_version(0, 3, 1)
153 fd
, fn
= tempfile
.mkstemp()
155 f
= os
.fdopen(fd
, 'w')
156 f
.write(CFG2
% (dev
[0].own_addr(), dev
[1].own_addr(),
159 p
= start_wmediumd(fn
, params
)
161 _test_wmediumd_path_simple(dev
, apdev
)
163 stop_wmediumd(p
, params
)
167 def _test_wmediumd_path_simple(dev
, apdev
):
168 for i
in range(0, 3):
169 check_mesh_support(dev
[i
])
170 add_open_mesh_network(dev
[i
], freq
="2462", basic_rates
="60 120 240")
172 # Check for mesh joined
173 for i
in range(0, 3):
174 check_mesh_group_added(dev
[i
])
176 state
= dev
[i
].get_status_field("wpa_state")
177 if state
!= "COMPLETED":
178 raise Exception("Unexpected wpa_state on dev" + str(i
) + ": " + state
)
180 mode
= dev
[i
].get_status_field("mode")
182 raise Exception("Unexpected mode: " + mode
)
184 # Check for peer connected
185 check_mesh_peer_connected(dev
[0])
186 check_mesh_peer_connected(dev
[0])
187 check_mesh_peer_connected(dev
[1])
188 check_mesh_peer_connected(dev
[2])
190 # Test connectivity 1->2 and 2->1
191 hwsim_utils
.test_connectivity(dev
[1], dev
[2])
193 # Check mpath table on 0
194 res
, data
= dev
[0].cmd_execute(['iw', dev
[0].ifname
, 'mpath', 'dump'])
196 raise Exception("iw command failed on dev0")
197 if data
.find(dev
[1].own_addr() + ' ' + dev
[1].own_addr()) == -1 or \
198 data
.find(dev
[2].own_addr() + ' ' + dev
[2].own_addr()) == -1:
199 raise Exception("mpath not found on dev0:\n" + data
)
200 if data
.find(dev
[0].own_addr()) > -1:
201 raise Exception("invalid mpath found on dev0:\n" + data
)
203 # Check mpath table on 1
204 res
, data
= dev
[1].cmd_execute(['iw', dev
[1].ifname
, 'mpath', 'dump'])
206 raise Exception("iw command failed on dev1")
207 if data
.find(dev
[0].own_addr() + ' ' + dev
[0].own_addr()) == -1 or \
208 data
.find(dev
[2].own_addr() + ' ' + dev
[0].own_addr()) == -1:
209 raise Exception("mpath not found on dev1:\n" + data
)
210 if data
.find(dev
[2].own_addr() + ' ' + dev
[2].own_addr()) > -1 or \
211 data
.find(dev
[1].own_addr()) > -1:
212 raise Exception("invalid mpath found on dev1:\n" + data
)
214 # Check mpath table on 2
215 res
, data
= dev
[2].cmd_execute(['iw', dev
[2].ifname
, 'mpath', 'dump'])
217 raise Exception("iw command failed on dev2")
218 if data
.find(dev
[0].own_addr() + ' ' + dev
[0].own_addr()) == -1 or \
219 data
.find(dev
[1].own_addr() + ' ' + dev
[0].own_addr()) == -1:
220 raise Exception("mpath not found on dev2:\n" + data
)
221 if data
.find(dev
[1].own_addr() + ' ' + dev
[1].own_addr()) > -1 or \
222 data
.find(dev
[2].own_addr()) > -1:
223 raise Exception("invalid mpath found on dev2:\n" + data
)
226 for i
in range(0, 3):
227 dev
[i
].mesh_group_remove()
228 check_mesh_group_removed(dev
[i
])
229 dev
[i
].dump_monitor()
231 def test_wmediumd_path_ttl(dev
, apdev
, params
):
232 """Mesh path request TTL"""
233 # 0 --- 1 --- 2 --- 3 --- 4
234 # Test the TTL of mesh path request.
235 # If the TTL is shorter than path, the mesh path request should be dropped.
236 require_wmediumd_version(0, 3, 1)
239 for i
in range(0, 3):
240 local_dev
.append(dev
[i
])
242 for i
in range(5, 7):
243 wpas
= WpaSupplicant(global_iface
='/tmp/wpas-wlan5')
244 wpas
.interface_add("wlan" + str(i
))
245 check_mesh_support(wpas
)
246 temp_dev
= wpas
.request("MESH_INTERFACE_ADD ifname=mesh" + str(i
))
247 if "FAIL" in temp_dev
:
248 raise Exception("MESH_INTERFACE_ADD failed")
249 local_dev
.append(WpaSupplicant(ifname
=temp_dev
))
251 fd
, fn
= tempfile
.mkstemp()
253 f
= os
.fdopen(fd
, 'w')
254 f
.write(CFG3
% (local_dev
[0].own_addr(), local_dev
[1].own_addr(),
255 local_dev
[2].own_addr(), local_dev
[3].own_addr(),
256 local_dev
[4].own_addr()))
258 p
= start_wmediumd(fn
, params
)
260 _test_wmediumd_path_ttl(local_dev
, True)
261 _test_wmediumd_path_ttl(local_dev
, False)
263 stop_wmediumd(p
, params
)
266 for i
in range(5, 7):
267 wpas
.interface_remove("wlan" + str(i
))
269 def _test_wmediumd_path_ttl(dev
, ok
):
270 for i
in range(0, 5):
271 check_mesh_support(dev
[i
])
272 add_open_mesh_network(dev
[i
], freq
="2462", basic_rates
="60 120 240")
274 # Check for mesh joined
275 for i
in range(0, 5):
276 check_mesh_group_added(dev
[i
])
278 state
= dev
[i
].get_status_field("wpa_state")
279 if state
!= "COMPLETED":
280 raise Exception("Unexpected wpa_state on dev" + str(i
) + ": " + state
)
282 mode
= dev
[i
].get_status_field("mode")
284 raise Exception("Unexpected mode: " + mode
)
286 # set mesh path request ttl
287 subprocess
.check_call(["iw", "dev", dev
[0].ifname
, "set", "mesh_param",
288 "mesh_element_ttl=" + ("4" if ok
else "3")])
290 # Check for peer connected
291 for i
in range(0, 5):
292 check_mesh_peer_connected(dev
[i
])
293 for i
in range(1, 4):
294 check_mesh_peer_connected(dev
[i
])
296 # Test connectivity 0->4 and 0->4
297 hwsim_utils
.test_connectivity(dev
[0], dev
[4], success_expected
=ok
)
299 # Check mpath table on 0
300 res
, data
= dev
[0].cmd_execute(['iw', dev
[0].ifname
, 'mpath', 'dump'])
302 raise Exception("iw command failed on dev0")
304 if data
.find(dev
[1].own_addr() + ' ' + dev
[1].own_addr()) == -1 or \
305 data
.find(dev
[4].own_addr() + ' ' + dev
[1].own_addr()) == -1:
306 raise Exception("mpath not found on dev0:\n" + data
)
308 if data
.find(dev
[1].own_addr() + ' ' + dev
[1].own_addr()) == -1 or \
309 data
.find(dev
[4].own_addr() + ' 00:00:00:00:00:00') == -1:
310 raise Exception("mpath not found on dev0:\n" + data
)
311 if data
.find(dev
[0].own_addr()) > -1 or \
312 data
.find(dev
[2].own_addr()) > -1 or \
313 data
.find(dev
[3].own_addr()) > -1:
314 raise Exception("invalid mpath found on dev0:\n" + data
)
317 for i
in range(0, 3):
318 dev
[i
].mesh_group_remove()
319 check_mesh_group_removed(dev
[i
])
320 dev
[i
].dump_monitor()
322 def test_wmediumd_path_rann(dev
, apdev
, params
):
323 """Mesh path with RANN"""
324 # 0 and 1 is connected
325 # 0 and 2 is connected
326 # 1 and 2 is not connected
327 # 2 is mesh root and RANN enabled
331 # This tests if 1 and 2 can communicate each other via 0.
332 require_wmediumd_version(0, 3, 1)
333 fd
, fn
= tempfile
.mkstemp()
335 f
= os
.fdopen(fd
, 'w')
336 f
.write(CFG2
% (dev
[0].own_addr(), dev
[1].own_addr(),
339 p
= start_wmediumd(fn
, params
)
341 _test_wmediumd_path_rann(dev
, apdev
)
343 stop_wmediumd(p
, params
)
347 capfile
= os
.path
.join(params
['logdir'], "hwsim0.pcapng")
349 # check Root STA address in root announcement element
350 filt
= "wlan.fc.type_subtype == 0x000d && " + \
351 "wlan_mgt.fixed.mesh_action == 0x01 && " + \
352 "wlan_mgt.tag.number == 126"
353 out
= run_tshark(capfile
, filt
, ["wlan.rann.root_sta"])
355 raise Exception("No captured data found\n")
356 if out
.find(dev
[2].own_addr()) == -1 or \
357 out
.find(dev
[0].own_addr()) > -1 or \
358 out
.find(dev
[1].own_addr()) > -1:
359 raise Exception("RANN should be sent by dev2 only:\n" + out
)
361 # check RANN interval is in range
362 filt
= "wlan.sa == 02:00:00:00:02:00 && " + \
363 "wlan.fc.type_subtype == 0x000d && " + \
364 "wlan_mgt.fixed.mesh_action == 0x01 && " + \
365 "wlan_mgt.tag.number == 126"
366 out
= run_tshark(capfile
, filt
, ["frame.time_relative"])
368 raise Exception("No captured data found\n")
369 lines
= out
.splitlines()
370 prev
= float(lines
[len(lines
) - 1])
371 for i
in reversed(list(range(1, len(lines
) - 1))):
372 now
= float(lines
[i
])
373 if prev
- now
< 1.0 or 3.0 < prev
- now
:
374 raise Exception("RANN interval " + str(prev
- now
) +
375 "(sec) should be close to 2.0(sec)\n")
378 # check no one uses broadcast path request
379 filt
= "wlan.da == ff:ff:ff:ff:ff:ff && " + \
380 "wlan.fc.type_subtype == 0x000d && " + \
381 "wlan_mgt.fixed.mesh_action == 0x01 && " + \
382 "wlan_mgt.tag.number == 130"
383 out
= run_tshark(capfile
, filt
, ["wlan.sa", "wlan.da"])
385 raise Exception("No captured data found\n")
387 raise Exception("invalid broadcast path requests\n" + out
)
389 def _test_wmediumd_path_rann(dev
, apdev
):
390 for i
in range(0, 3):
391 check_mesh_support(dev
[i
])
392 add_open_mesh_network(dev
[i
], freq
="2462", basic_rates
="60 120 240")
394 # Check for mesh joined
395 for i
in range(0, 3):
396 check_mesh_group_added(dev
[i
])
398 state
= dev
[i
].get_status_field("wpa_state")
399 if state
!= "COMPLETED":
400 raise Exception("Unexpected wpa_state on dev" + str(i
) + ": " + state
)
402 mode
= dev
[i
].get_status_field("mode")
404 raise Exception("Unexpected mode: " + mode
)
406 # set node 2 as RANN supported root
407 subprocess
.check_call(["iw", "dev", dev
[0].ifname
, "set", "mesh_param",
408 "mesh_hwmp_rootmode=0"])
409 subprocess
.check_call(["iw", "dev", dev
[1].ifname
, "set", "mesh_param",
410 "mesh_hwmp_rootmode=0"])
411 subprocess
.check_call(["iw", "dev", dev
[2].ifname
, "set", "mesh_param",
412 "mesh_hwmp_rootmode=4"])
413 subprocess
.check_call(["iw", "dev", dev
[2].ifname
, "set", "mesh_param",
414 "mesh_hwmp_rann_interval=2000"])
416 # Check for peer connected
417 check_mesh_peer_connected(dev
[0])
418 check_mesh_peer_connected(dev
[0])
419 check_mesh_peer_connected(dev
[1])
420 check_mesh_peer_connected(dev
[2])
422 # Wait for RANN frame
425 # Test connectivity 1->2 and 2->1
426 hwsim_utils
.test_connectivity(dev
[1], dev
[2])
428 # Check mpath table on 0
429 res
, data
= dev
[0].cmd_execute(['iw', dev
[0].ifname
, 'mpath', 'dump'])
431 raise Exception("iw command failed on dev0")
432 if data
.find(dev
[1].own_addr() + ' ' + dev
[1].own_addr()) == -1 or \
433 data
.find(dev
[2].own_addr() + ' ' + dev
[2].own_addr()) == -1:
434 raise Exception("mpath not found on dev0:\n" + data
)
435 if data
.find(dev
[0].own_addr()) > -1:
436 raise Exception("invalid mpath found on dev0:\n" + data
)
438 # Check mpath table on 1
439 res
, data
= dev
[1].cmd_execute(['iw', dev
[1].ifname
, 'mpath', 'dump'])
441 raise Exception("iw command failed on dev1")
442 if data
.find(dev
[0].own_addr() + ' ' + dev
[0].own_addr()) == -1 or \
443 data
.find(dev
[2].own_addr() + ' ' + dev
[0].own_addr()) == -1:
444 raise Exception("mpath not found on dev1:\n" + data
)
445 if data
.find(dev
[2].own_addr() + ' ' + dev
[2].own_addr()) > -1 or \
446 data
.find(dev
[1].own_addr()) > -1:
447 raise Exception("invalid mpath found on dev1:\n" + data
)
449 # Check mpath table on 2
450 res
, data
= dev
[2].cmd_execute(['iw', dev
[2].ifname
, 'mpath', 'dump'])
452 raise Exception("iw command failed on dev2")
453 if data
.find(dev
[0].own_addr() + ' ' + dev
[0].own_addr()) == -1 or \
454 data
.find(dev
[1].own_addr() + ' ' + dev
[0].own_addr()) == -1:
455 raise Exception("mpath not found on dev2:\n" + data
)
456 if data
.find(dev
[1].own_addr() + ' ' + dev
[1].own_addr()) > -1 or \
457 data
.find(dev
[2].own_addr()) > -1:
458 raise Exception("invalid mpath found on dev2:\n" + data
)
461 for i
in range(0, 3):
462 dev
[i
].mesh_group_remove()
463 check_mesh_group_removed(dev
[i
])
464 dev
[i
].dump_monitor()