tests: Autonomous GO random channel selection
[mech_eap.git] / tests / hwsim / test_p2p_channel.py
1 # P2P channel selection test cases
2 # Copyright (c) 2014, Jouni Malinen <j@w1.fi>
3 #
4 # This software may be distributed under the terms of the BSD license.
5 # See README for more details.
6
7 import logging
8 logger = logging.getLogger()
9 import os
10 import subprocess
11 import time
12
13 import hostapd
14 import hwsim_utils
15 from test_p2p_grpform import go_neg_pin_authorized
16 from test_p2p_grpform import check_grpform_results
17 from test_p2p_grpform import remove_group
18 from test_p2p_grpform import go_neg_pbc
19 from test_p2p_autogo import autogo
20
21 def set_country(country):
22     subprocess.call(['sudo', 'iw', 'reg', 'set', country])
23     time.sleep(0.1)
24
25 def test_p2p_channel_5ghz(dev):
26     """P2P group formation with 5 GHz preference"""
27     try:
28         set_country("US")
29         [i_res, r_res] = go_neg_pin_authorized(i_dev=dev[0], i_intent=15,
30                                                r_dev=dev[1], r_intent=0,
31                                                test_data=False)
32         check_grpform_results(i_res, r_res)
33         freq = int(i_res['freq'])
34         if freq < 5000:
35             raise Exception("Unexpected channel %d MHz - did not follow 5 GHz preference" % freq)
36         remove_group(dev[0], dev[1])
37     finally:
38         set_country("00")
39
40 def test_p2p_channel_5ghz_no_vht(dev):
41     """P2P group formation with 5 GHz preference when VHT channels are disallowed"""
42     try:
43         set_country("US")
44         dev[0].request("P2P_SET disallow_freq 5180-5240")
45         [i_res, r_res] = go_neg_pin_authorized(i_dev=dev[0], i_intent=15,
46                                                r_dev=dev[1], r_intent=0,
47                                                test_data=False)
48         check_grpform_results(i_res, r_res)
49         freq = int(i_res['freq'])
50         if freq < 5000:
51             raise Exception("Unexpected channel %d MHz - did not follow 5 GHz preference" % freq)
52         remove_group(dev[0], dev[1])
53     finally:
54         set_country("00")
55         dev[0].request("P2P_SET disallow_freq ")
56
57 def test_p2p_channel_random_social(dev):
58     """P2P group formation with 5 GHz preference but all 5 GHz channels disabled"""
59     try:
60         set_country("US")
61         dev[0].request("SET p2p_oper_channel 11")
62         dev[0].request("P2P_SET disallow_freq 5000-6000,2462")
63         [i_res, r_res] = go_neg_pin_authorized(i_dev=dev[0], i_intent=15,
64                                                r_dev=dev[1], r_intent=0,
65                                                test_data=False)
66         check_grpform_results(i_res, r_res)
67         freq = int(i_res['freq'])
68         if freq not in [ 2412, 2437, 2462 ]:
69             raise Exception("Unexpected channel %d MHz - did not pick random social channel" % freq)
70         remove_group(dev[0], dev[1])
71     finally:
72         set_country("00")
73         dev[0].request("P2P_SET disallow_freq ")
74
75 def test_p2p_channel_random(dev):
76     """P2P group formation with 5 GHz preference but all 5 GHz channels and all social channels disabled"""
77     try:
78         set_country("US")
79         dev[0].request("SET p2p_oper_channel 11")
80         dev[0].request("P2P_SET disallow_freq 5000-6000,2412,2437,2462")
81         [i_res, r_res] = go_neg_pin_authorized(i_dev=dev[0], i_intent=15,
82                                                r_dev=dev[1], r_intent=0,
83                                                test_data=False)
84         check_grpform_results(i_res, r_res)
85         freq = int(i_res['freq'])
86         if freq > 2500 or freq in [ 2412, 2437, 2462 ]:
87             raise Exception("Unexpected channel %d MHz" % freq)
88         remove_group(dev[0], dev[1])
89     finally:
90         set_country("00")
91         dev[0].request("P2P_SET disallow_freq ")
92
93 def test_p2p_channel_random_social_with_op_class_change(dev, apdev, params):
94     """P2P group formation using random social channel with oper class change needed"""
95     try:
96         set_country("US")
97         logger.info("Start group on 5 GHz")
98         [i_res, r_res] = go_neg_pin_authorized(i_dev=dev[0], i_intent=15,
99                                                r_dev=dev[1], r_intent=0,
100                                                test_data=False)
101         check_grpform_results(i_res, r_res)
102         freq = int(i_res['freq'])
103         if freq < 5000:
104             raise Exception("Unexpected channel %d MHz - did not pick 5 GHz preference" % freq)
105         remove_group(dev[0], dev[1])
106
107         logger.info("Disable 5 GHz and try to re-start group based on 5 GHz preference")
108         dev[0].request("SET p2p_oper_reg_class 115")
109         dev[0].request("SET p2p_oper_channel 36")
110         dev[0].request("P2P_SET disallow_freq 5000-6000")
111         [i_res, r_res] = go_neg_pin_authorized(i_dev=dev[0], i_intent=15,
112                                                r_dev=dev[1], r_intent=0,
113                                                test_data=False)
114         check_grpform_results(i_res, r_res)
115         freq = int(i_res['freq'])
116         if freq not in [ 2412, 2437, 2462 ]:
117             raise Exception("Unexpected channel %d MHz - did not pick random social channel" % freq)
118         remove_group(dev[0], dev[1])
119
120         try:
121             arg = [ "tshark",
122                     "-r", os.path.join(params['logdir'], "hwsim0.pcapng"),
123                     "-R", "wifi_p2p.public_action.subtype == 0",
124                     "-V" ]
125             cmd = subprocess.Popen(arg, stdout=subprocess.PIPE,
126                                    stderr=open('/dev/null', 'w'))
127         except Exception, e:
128             logger.info("Could run run tshark check: " + str(e))
129             cmd = None
130             pass
131
132         if cmd:
133             last = None
134             for l in cmd.stdout.read().splitlines():
135                 if "Operating Channel:" not in l:
136                     continue
137                 last = l
138             if last is None:
139                 raise Exception("Could not find GO Negotiation Request")
140             if "Operating Class 81" not in last:
141                 raise Exception("Unexpected operating class: " + last.strip())
142     finally:
143         set_country("00")
144         dev[0].request("P2P_SET disallow_freq ")
145         dev[0].request("SET p2p_oper_reg_class 81")
146         dev[0].request("SET p2p_oper_channel 11")
147
148 def test_p2p_channel_avoid(dev):
149     """P2P and avoid frequencies driver event"""
150     try:
151         set_country("US")
152         if "OK" not in dev[0].request("DRIVER_EVENT AVOID_FREQUENCIES 5000-6000,2412,2437,2462"):
153             raise Exception("Could not simulate driver event")
154         ev = dev[0].wait_event(["CTRL-EVENT-AVOID-FREQ"], timeout=10)
155         if ev is None:
156             raise Exception("No CTRL-EVENT-AVOID-FREQ event")
157         [i_res, r_res] = go_neg_pin_authorized(i_dev=dev[0], i_intent=15,
158                                                r_dev=dev[1], r_intent=0,
159                                                test_data=False)
160         check_grpform_results(i_res, r_res)
161         freq = int(i_res['freq'])
162         if freq > 2500 or freq in [ 2412, 2437, 2462 ]:
163             raise Exception("Unexpected channel %d MHz" % freq)
164
165         if "OK" not in dev[0].request("DRIVER_EVENT AVOID_FREQUENCIES"):
166             raise Exception("Could not simulate driver event(2)")
167         ev = dev[0].wait_event(["CTRL-EVENT-AVOID-FREQ"], timeout=10)
168         if ev is None:
169             raise Exception("No CTRL-EVENT-AVOID-FREQ event")
170         ev = dev[0].wait_event(["P2P-REMOVE-AND-REFORM-GROUP"], timeout=1)
171         if ev is not None:
172             raise Exception("Unexpected P2P-REMOVE-AND-REFORM-GROUP event")
173
174         if "OK" not in dev[0].request("DRIVER_EVENT AVOID_FREQUENCIES " + str(freq)):
175             raise Exception("Could not simulate driver event(3)")
176         ev = dev[0].wait_event(["CTRL-EVENT-AVOID-FREQ"], timeout=10)
177         if ev is None:
178             raise Exception("No CTRL-EVENT-AVOID-FREQ event")
179         ev = dev[0].wait_event(["P2P-REMOVE-AND-REFORM-GROUP"], timeout=10)
180         if ev is None:
181             raise Exception("No P2P-REMOVE-AND-REFORM-GROUP event")
182     finally:
183         set_country("00")
184         dev[0].request("DRIVER_EVENT AVOID_FREQUENCIES")
185
186 def test_autogo_following_bss(dev, apdev):
187     """P2P autonomous GO operate on the same channel as station interface"""
188     if dev[0].get_mcc() > 1:
189         logger.info("test mode: MCC")
190
191     dev[0].request("SET p2p_no_group_iface 0")
192
193     channels = { 3 : "2422", 5 : "2432", 9 : "2452" }
194     for key in channels:
195         hostapd.add_ap(apdev[0]['ifname'], { "ssid" : 'ap-test',
196                                              "channel" : str(key) })
197         dev[0].connect("ap-test", key_mgmt="NONE",
198                        scan_freq=str(channels[key]))
199         res_go = autogo(dev[0])
200         if res_go['freq'] != channels[key]:
201             raise Exception("Group operation channel is not the same as on connected station interface")
202         hwsim_utils.test_connectivity(dev[0].ifname, apdev[0]['ifname'])
203         dev[0].remove_group(res_go['ifname'])
204
205 def test_go_neg_with_bss_connected(dev, apdev):
206     """P2P channel selection: GO negotiation when station interface is connected"""
207
208     dev[0].request("SET p2p_no_group_iface 0")
209
210     hostapd.add_ap(apdev[0]['ifname'], { "ssid": 'bss-2.4ghz', "channel": '5' })
211     dev[0].connect("bss-2.4ghz", key_mgmt="NONE", scan_freq="2432")
212     #dev[0] as GO
213     [i_res, r_res] = go_neg_pbc(i_dev=dev[0], i_intent=10, r_dev=dev[1],
214                                 r_intent=1)
215     check_grpform_results(i_res, r_res)
216     if i_res['role'] != "GO":
217        raise Exception("GO not selected according to go_intent")
218     if i_res['freq'] != "2432":
219        raise Exception("Group formed on a different frequency than BSS")
220     hwsim_utils.test_connectivity(dev[0].ifname, apdev[0]['ifname'])
221     dev[0].remove_group(i_res['ifname'])
222
223     if dev[0].get_mcc() > 1:
224         logger.info("Skip as-client case due to MCC being enabled")
225         return;
226
227     #dev[0] as client
228     [i_res2, r_res2] = go_neg_pbc(i_dev=dev[0], i_intent=1, r_dev=dev[1],
229                                   r_intent=10)
230     check_grpform_results(i_res2, r_res2)
231     if i_res2['role'] != "client":
232        raise Exception("GO not selected according to go_intent")
233     if i_res2['freq'] != "2432":
234        raise Exception("Group formed on a different frequency than BSS")
235     hwsim_utils.test_connectivity(dev[0].ifname, apdev[0]['ifname'])
236
237 def test_autogo_with_bss_on_disallowed_chan(dev, apdev):
238     """P2P channel selection: Autonomous GO with BSS on a disallowed channel"""
239
240     dev[0].request("SET p2p_no_group_iface 0")
241
242     if dev[0].get_mcc() < 2:
243        logger.info("Skipping test because driver does not support MCC")
244        return "skip"
245     try:
246         hostapd.add_ap(apdev[0]['ifname'], { "ssid": 'bss-2.4ghz',
247                                              "channel": '1' })
248         dev[0].request("P2P_SET disallow_freq 2412")
249         dev[0].connect("bss-2.4ghz", key_mgmt="NONE", scan_freq="2412")
250         res = autogo(dev[0])
251         if res['freq'] == "2412":
252            raise Exception("GO set on a disallowed channel")
253         hwsim_utils.test_connectivity(dev[0].ifname, apdev[0]['ifname'])
254     finally:
255         dev[0].request("P2P_SET disallow_freq ")
256
257 def test_go_neg_with_bss_on_disallowed_chan(dev, apdev):
258     """P2P channel selection: GO negotiation with station interface on a disallowed channel"""
259
260     dev[0].request("SET p2p_no_group_iface 0")
261
262     if dev[0].get_mcc() < 2:
263        logger.info("Skipping test because driver does not support MCC")
264        return "skip"
265     try:
266         hostapd.add_ap(apdev[0]['ifname'], { "ssid": 'bss-2.4ghz', "channel": '1' })
267         dev[0].connect("bss-2.4ghz", key_mgmt="NONE", scan_freq="2412")
268         dev[0].request("P2P_SET disallow_freq 2412")
269
270         #dev[0] as GO
271         [i_res, r_res] = go_neg_pbc(i_dev=dev[0], i_intent=10, r_dev=dev[1],
272                                     r_intent=1)
273         check_grpform_results(i_res, r_res)
274         if i_res['role'] != "GO":
275            raise Exception("GO not selected according to go_intent")
276         if i_res['freq'] == "2412":
277            raise Exception("Group formed on a disallowed channel")
278         hwsim_utils.test_connectivity(dev[0].ifname, apdev[0]['ifname'])
279         dev[0].remove_group(i_res['ifname'])
280
281         #dev[0] as client
282         [i_res2, r_res2] = go_neg_pbc(i_dev=dev[0], i_intent=1, r_dev=dev[1],
283                                       r_intent=10)
284         check_grpform_results(i_res2, r_res2)
285         if i_res2['role'] != "client":
286            raise Exception("GO not selected according to go_intent")
287         if i_res2['freq'] == "2412":
288            raise Exception("Group formed on a disallowed channel")
289         hwsim_utils.test_connectivity(dev[0].ifname, apdev[0]['ifname'])
290     finally:
291         dev[0].request("P2P_SET disallow_freq ")
292
293 def test_autogo_force_diff_channel(dev, apdev):
294     """P2P autonomous GO and station interface operate on different channels"""
295     if dev[0].get_mcc() < 2:
296         logger.info("Skiping test because the driver doesn't support MCC")
297         return "skip"
298
299     dev[0].request("SET p2p_no_group_iface 0")
300
301     hostapd.add_ap(apdev[0]['ifname'], {"ssid" : 'ap-test', "channel" : '1'})
302     dev[0].connect("ap-test", key_mgmt = "NONE", scan_freq = "2412")
303     channels = { 2 : 2417, 5 : 2432, 9 : 2452 }
304     for key in channels:
305         res_go = autogo(dev[0], channels[key])
306         hwsim_utils.test_connectivity(dev[0].ifname, apdev[0]['ifname'])
307         if int(res_go['freq']) == 2412:
308             raise Exception("Group operation channel is: 2412 excepted: " + res_go['freq'])
309         dev[0].remove_group(res_go['ifname'])
310
311 def test_go_neg_forced_freq_diff_than_bss_freq(dev, apdev):
312     """P2P channel selection: GO negotiation with forced freq different than station interface"""
313     if dev[0].get_mcc() < 2:
314        logger.info("Skipping test because driver does not support MCC")
315        return "skip"
316
317     dev[0].request("SET p2p_no_group_iface 0")
318
319     hostapd.add_ap(apdev[0]['ifname'], { "country_code": 'US',
320                                          "ssid": 'bss-5ghz', "hw_mode": 'a',
321                                          "channel": '40' })
322     dev[0].connect("bss-5ghz", key_mgmt="NONE", scan_freq="5200")
323
324     # GO and peer force the same freq, different than BSS freq,
325     # dev[0] to become GO
326     [i_res, r_res] = go_neg_pbc(i_dev=dev[1], i_intent=1, i_freq=5180,
327                                 r_dev=dev[0], r_intent=14, r_freq=5180)
328     check_grpform_results(i_res, r_res)
329     if i_res['freq'] != "5180":
330        raise Exception("P2P group formed on unexpected frequency: " + i_res['freq'])
331     if r_res['role'] != "GO":
332        raise Exception("GO not selected according to go_intent")
333     hwsim_utils.test_connectivity(dev[0].ifname, apdev[0]['ifname'])
334     dev[0].remove_group(r_res['ifname'])
335
336     # GO and peer force the same freq, different than BSS freq, dev[0] to
337     # become client
338     [i_res2, r_res2] = go_neg_pbc(i_dev=dev[1], i_intent=14, i_freq=2422,
339                                   r_dev=dev[0], r_intent=1, r_freq=2422)
340     check_grpform_results(i_res2, r_res2)
341     if i_res2['freq'] != "2422":
342        raise Exception("P2P group formed on unexpected frequency: " + i_res2['freq'])
343     if r_res2['role'] != "client":
344        raise Exception("GO not selected according to go_intent")
345     hwsim_utils.test_connectivity(dev[0].ifname, apdev[0]['ifname'])
346
347 def test_go_pref_chan_bss_on_diff_chan(dev, apdev):
348     """P2P channel selection: Station on different channel than GO configured pref channel"""
349
350     dev[0].request("SET p2p_no_group_iface 0")
351
352     try:
353         hostapd.add_ap(apdev[0]['ifname'], { "ssid": 'bss-2.4ghz',
354                                              "channel": '1' })
355         dev[0].request("SET p2p_pref_chan 81:2")
356         dev[0].connect("bss-2.4ghz", key_mgmt="NONE", scan_freq="2412")
357         res = autogo(dev[0])
358         if res['freq'] != "2412":
359            raise Exception("GO channel did not follow BSS")
360         hwsim_utils.test_connectivity(dev[0].ifname, apdev[0]['ifname'])
361     finally:
362         dev[0].request("SET p2p_pref_chan ")
363
364 def test_go_pref_chan_bss_on_disallowed_chan(dev, apdev):
365     """P2P channel selection: Station interface on different channel than GO configured pref channel, and station channel is disallowed"""
366     if dev[0].get_mcc() < 2:
367        logger.info("Skipping test because driver does not support MCC")
368        return "skip"
369
370     dev[0].request("SET p2p_no_group_iface 0")
371
372     try:
373         hostapd.add_ap(apdev[0]['ifname'], { "ssid": 'bss-2.4ghz',
374                                              "channel": '1' })
375         dev[0].request("P2P_SET disallow_freq 2412")
376         dev[0].request("SET p2p_pref_chan 81:2")
377         dev[0].connect("bss-2.4ghz", key_mgmt="NONE", scan_freq="2412")
378         res2 = autogo(dev[0])
379         if res2['freq'] != "2417":
380            raise Exception("GO channel did not follow pref_chan configuration")
381         hwsim_utils.test_connectivity(dev[0].ifname, apdev[0]['ifname'])
382     finally:
383         dev[0].request("P2P_SET disallow_freq ")
384         dev[0].request("SET p2p_pref_chan ")
385
386 def test_no_go_freq(dev, apdev):
387     """P2P channel selection: no GO freq"""
388     try:
389        dev[0].request("SET p2p_no_go_freq 2412")
390        # dev[0] as client, channel 1 is ok
391        [i_res, r_res] = go_neg_pbc(i_dev=dev[0], i_intent=1,
392                                    r_dev=dev[1], r_intent=14, r_freq=2412)
393        check_grpform_results(i_res, r_res)
394        if i_res['freq'] != "2412":
395           raise Exception("P2P group not formed on forced freq")
396
397        dev[1].remove_group(r_res['ifname'])
398        fail = False
399        # dev[0] as GO, channel 1 is not allowed
400        try:
401           dev[0].request("SET p2p_no_go_freq 2412")
402           [i_res2, r_res2] = go_neg_pbc(i_dev=dev[0], i_intent=14,
403                                         r_dev=dev[1], r_intent=1, r_freq=2412)
404           check_grpform_results(i_res2, r_res2)
405           fail = True
406        except:
407            pass
408        if fail:
409            raise Exception("GO set on a disallowed freq")
410     finally:
411        dev[0].request("SET p2p_no_go_freq ")
412
413 def test_go_neg_peers_force_diff_freq(dev, apdev):
414     try:
415        [i_res2, r_res2] = go_neg_pbc(i_dev=dev[0], i_intent=14, i_freq=5180,
416                                      r_dev=dev[1], r_intent=0, r_freq=5200)
417     except Exception, e:
418         return
419     raise Exception("Unexpected group formation success")
420
421 def test_autogo_random_channel(dev, apdev):
422     """P2P channel selection: GO instantiated on random channel 1, 6, 11"""
423     freqs = []
424     go_freqs = ["2412", "2437", "2462"]
425     for i in range(0, 20):
426         result = autogo(dev[0])
427         if result['freq'] not in go_freqs:
428            raise Exception("Unexpected frequency selected: " + result['freq'])
429         if result['freq'] not in freqs:
430             freqs.append(result['freq'])
431         if len(freqs) == 3:
432             break
433         dev[0].remove_group(result['ifname'])
434     if i == 20:
435        raise Exception("GO created 20 times and not all social channels were selected. freqs not selected: " + str(list(set(go_freqs) - set(freqs))))