1# P2P persistent group test cases
2# Copyright (c) 2013-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
7from remotehost import remote_compatible
8import logging
9logger = logging.getLogger()
10import re
11import time
12
13import hwsim_utils
14from p2p_utils import *
15
16@remote_compatible
17def test_persistent_group(dev):
18    """P2P persistent group formation and re-invocation"""
19    form(dev[0], dev[1])
20    invite_from_cli(dev[0], dev[1])
21    invite_from_go(dev[0], dev[1])
22
23    logger.info("Remove group on the client and try to invite from GO")
24    id = None
25    for n in dev[0].list_networks(p2p=True):
26        if "[P2P-PERSISTENT]" in n['flags']:
27            id = n['id']
28            break
29    if id is None:
30        raise Exception("Could not find persistent group entry")
31    clients = dev[0].global_request("GET_NETWORK " + id + " p2p_client_list").rstrip()
32    if dev[1].p2p_dev_addr() not in clients:
33        raise Exception("Peer missing from client list")
34    if "FAIL" not in dev[1].request("SELECT_NETWORK " + str(id)):
35        raise Exception("SELECT_NETWORK succeeded unexpectedly")
36    if "FAIL" not in dev[1].request("SELECT_NETWORK 1234567"):
37        raise Exception("SELECT_NETWORK succeeded unexpectedly(2)")
38    if "FAIL" not in dev[1].request("ENABLE_NETWORK " + str(id)):
39        raise Exception("ENABLE_NETWORK succeeded unexpectedly")
40    if "FAIL" not in dev[1].request("ENABLE_NETWORK 1234567"):
41        raise Exception("ENABLE_NETWORK succeeded unexpectedly(2)")
42    if "FAIL" not in dev[1].request("DISABLE_NETWORK " + str(id)):
43        raise Exception("DISABLE_NETWORK succeeded unexpectedly")
44    if "FAIL" not in dev[1].request("DISABLE_NETWORK 1234567"):
45        raise Exception("DISABLE_NETWORK succeeded unexpectedly(2)")
46    if "FAIL" not in dev[1].request("REMOVE_NETWORK 1234567"):
47        raise Exception("REMOVE_NETWORK succeeded unexpectedly")
48    dev[1].global_request("REMOVE_NETWORK all")
49    if len(dev[1].list_networks(p2p=True)) > 0:
50        raise Exception("Unexpected network block remaining")
51    invite(dev[0], dev[1])
52    ev = dev[0].wait_global_event(["P2P-INVITATION-RESULT"], timeout=10)
53    if ev is None:
54        raise Exception("No invitation result seen")
55    if "status=8" not in ev:
56        raise Exception("Unexpected invitation result: " + ev)
57    clients = dev[0].request("GET_NETWORK " + id + " p2p_client_list").rstrip()
58    if dev[1].p2p_dev_addr() in clients:
59        raise Exception("Peer was still in client list")
60
61@remote_compatible
62def test_persistent_group2(dev):
63    """P2P persistent group formation with reverse roles"""
64    form(dev[0], dev[1], reverse_init=True)
65    invite_from_cli(dev[0], dev[1])
66    invite_from_go(dev[0], dev[1])
67
68@remote_compatible
69def test_persistent_group3(dev):
70    """P2P persistent group formation and re-invocation with empty BSS table"""
71    form(dev[0], dev[1])
72    dev[1].request("BSS_FLUSH 0")
73    invite_from_cli(dev[0], dev[1])
74    dev[1].request("BSS_FLUSH 0")
75    invite_from_go(dev[0], dev[1])
76
77def test_persistent_group_per_sta_psk(dev):
78    """P2P persistent group formation and re-invocation using per-client PSK"""
79    addr0 = dev[0].p2p_dev_addr()
80    addr1 = dev[1].p2p_dev_addr()
81    addr2 = dev[2].p2p_dev_addr()
82    dev[0].global_request("P2P_SET per_sta_psk 1")
83    logger.info("Form a persistent group")
84    [i_res, r_res] = go_neg_pin_authorized_persistent(i_dev=dev[0], i_intent=15,
85                                                      r_dev=dev[1], r_intent=0)
86    if not i_res['persistent'] or not r_res['persistent']:
87        raise Exception("Formed group was not persistent")
88
89    logger.info("Join another client to the group")
90    pin = dev[2].wps_read_pin()
91    dev[0].p2p_go_authorize_client(pin)
92    social = int(i_res['freq']) in [2412, 2437, 2462]
93    c_res = dev[2].p2p_connect_group(addr0, pin, timeout=60, social=social,
94                                     freq=i_res['freq'])
95    if not c_res['persistent']:
96        raise Exception("Joining client did not recognize persistent group")
97    if r_res['psk'] == c_res['psk']:
98        raise Exception("Same PSK assigned for both clients")
99    dev[0].wait_sta(addr=dev[2].p2p_interface_addr(), wait_4way_hs=True)
100    hwsim_utils.test_connectivity_p2p(dev[1], dev[2])
101
102    logger.info("Remove persistent group and re-start it manually")
103    dev[0].remove_group()
104    dev[1].wait_go_ending_session()
105    dev[2].wait_go_ending_session()
106    dev[0].wait_sta_disconnect()
107    dev[0].wait_sta_disconnect()
108    dev[0].dump_monitor()
109    dev[1].dump_monitor()
110    dev[2].dump_monitor()
111
112    for i in range(0, 3):
113        networks = dev[i].list_networks(p2p=True)
114        if len(networks) != 1:
115            raise Exception("Unexpected number of networks")
116        if "[P2P-PERSISTENT]" not in networks[0]['flags']:
117            raise Exception("Not the persistent group data")
118        if i > 0:
119            # speed up testing by avoiding use of the old BSS entry since the
120            # GO may have changed channels
121            dev[i].request("BSS_FLUSH 0")
122            dev[i].scan(freq="2412", only_new=True)
123        if "OK" not in dev[i].global_request("P2P_GROUP_ADD persistent=" + networks[0]['id'] + " freq=2412"):
124            raise Exception("Could not re-start persistent group")
125        ev = dev[i].wait_global_event(["P2P-GROUP-STARTED"], timeout=30)
126        if ev is None:
127            raise Exception("Timeout on group restart")
128        dev[i].group_form_result(ev)
129
130    dev[0].wait_sta()
131    dev[0].wait_sta()
132
133    logger.info("Leave persistent group and rejoin it")
134    dev[2].remove_group()
135    ev = dev[2].wait_global_event(["P2P-GROUP-REMOVED"], timeout=3)
136    if ev is None:
137        raise Exception("Group removal event timed out")
138    dev[0].wait_sta_disconnect(addr=dev[2].p2p_interface_addr())
139    if not dev[2].discover_peer(addr0, social=True):
140        raise Exception("Peer " + addr0 + " not found")
141    dev[2].dump_monitor()
142    peer = dev[2].get_peer(addr0)
143    dev[2].global_request("P2P_GROUP_ADD persistent=" + peer['persistent'] + " freq=2412")
144    ev = dev[2].wait_global_event(["P2P-GROUP-STARTED"], timeout=30)
145    if ev is None:
146        raise Exception("Timeout on group restart (on client)")
147    cli_res = dev[2].group_form_result(ev)
148    if not cli_res['persistent']:
149        raise Exception("Persistent group not restarted as persistent (cli)")
150    dev[0].wait_sta(addr=dev[2].p2p_interface_addr(), wait_4way_hs=True)
151    hwsim_utils.test_connectivity_p2p(dev[1], dev[2])
152
153    logger.info("Remove one of the clients from the group without removing persistent group information for the client")
154    dev[0].global_request("P2P_REMOVE_CLIENT iface=" + dev[2].p2p_interface_addr())
155    dev[2].wait_go_ending_session()
156    dev[0].wait_sta_disconnect(addr=dev[2].p2p_interface_addr())
157
158    logger.info("Try to reconnect after having been removed from group (but persistent group info still present)")
159    if not dev[2].discover_peer(addr0, social=True):
160        raise Exception("Peer " + peer + " not found")
161    dev[2].dump_monitor()
162    peer = dev[2].get_peer(addr0)
163    dev[2].global_request("P2P_GROUP_ADD persistent=" + peer['persistent'] + " freq=2412")
164    ev = dev[2].wait_global_event(["P2P-GROUP-STARTED",
165                                   "WPA: 4-Way Handshake failed"], timeout=30)
166    if ev is None:
167        raise Exception("Timeout on group restart (on client)")
168    if "P2P-GROUP-STARTED" not in ev:
169        raise Exception("Connection failed")
170    dev[0].wait_sta(addr=dev[2].p2p_interface_addr(), wait_4way_hs=True)
171
172    logger.info("Remove one of the clients from the group")
173    dev[0].global_request("P2P_REMOVE_CLIENT " + addr2)
174    dev[0].wait_sta_disconnect(addr=dev[2].p2p_interface_addr())
175    dev[2].wait_go_ending_session()
176
177    logger.info("Try to reconnect after having been removed from group")
178    if not dev[2].discover_peer(addr0, social=True):
179        raise Exception("Peer " + peer + " not found")
180    dev[2].dump_monitor()
181    peer = dev[2].get_peer(addr0)
182    dev[2].global_request("P2P_GROUP_ADD persistent=" + peer['persistent'] + " freq=2412")
183    ev = dev[2].wait_global_event(["P2P-GROUP-STARTED",
184                                   "WPA: 4-Way Handshake failed"], timeout=30)
185    if ev is None:
186        raise Exception("Timeout on group restart (on client)")
187    if "P2P-GROUP-STARTED" in ev:
188        raise Exception("Client managed to connect after being removed")
189
190    logger.info("Remove the remaining client from the group")
191    dev[0].global_request("P2P_REMOVE_CLIENT " + addr1)
192    dev[0].wait_sta_disconnect(addr=dev[1].p2p_interface_addr())
193    dev[1].wait_go_ending_session()
194
195    logger.info("Terminate persistent group")
196    dev[0].remove_group()
197    dev[0].dump_monitor()
198
199    logger.info("Try to re-invoke persistent group from client")
200    dev[0].global_request("SET persistent_reconnect 1")
201    dev[0].p2p_listen()
202    if not dev[1].discover_peer(addr0, social=True):
203        raise Exception("Peer " + peer + " not found")
204    dev[1].dump_monitor()
205    peer = dev[1].get_peer(addr0)
206    dev[1].global_request("P2P_INVITE persistent=" + peer['persistent'] + " peer=" + addr0)
207    ev = dev[0].wait_global_event(["P2P-GROUP-STARTED"], timeout=30)
208    dev[0].group_form_result(ev)
209    ev = dev[1].wait_global_event(["P2P-GROUP-STARTED",
210                                   "WPA: 4-Way Handshake failed"], timeout=30)
211    if ev is None:
212        raise Exception("Timeout on group restart (on client)")
213    if "P2P-GROUP-STARTED" in ev:
214        raise Exception("Client managed to re-invoke after being removed")
215    dev[0].dump_monitor()
216
217    logger.info("Terminate persistent group")
218    dev[0].remove_group()
219    dev[0].dump_monitor()
220
221def test_persistent_group_invite_removed_client(dev):
222    """P2P persistent group client removal and re-invitation"""
223    addr0 = dev[0].p2p_dev_addr()
224    addr1 = dev[1].p2p_dev_addr()
225    dev[0].request("P2P_SET per_sta_psk 1")
226    logger.info("Form a persistent group")
227    [i_res, r_res] = go_neg_pin_authorized_persistent(i_dev=dev[0], i_intent=15,
228                                                      r_dev=dev[1], r_intent=0)
229    if not i_res['persistent'] or not r_res['persistent']:
230        raise Exception("Formed group was not persistent")
231
232    logger.info("Remove client from the group")
233    dev[0].global_request("P2P_REMOVE_CLIENT " + addr1)
234    dev[0].wait_sta_disconnect(dev[1].p2p_interface_addr())
235    dev[1].wait_go_ending_session()
236
237    logger.info("Re-invite the removed client to join the group")
238    dev[1].p2p_listen()
239    if not dev[0].discover_peer(addr1, social=True):
240        raise Exception("Peer " + peer + " not found")
241    dev[0].global_request("P2P_INVITE group=" + dev[0].group_ifname + " peer=" + addr1)
242    ev = dev[1].wait_global_event(["P2P-INVITATION-RECEIVED"], timeout=10)
243    if ev is None:
244        raise Exception("Timeout on invitation")
245    if "sa=" + addr0 + " persistent=" not in ev:
246        raise Exception("Unexpected invitation event")
247    [event, addr, persistent] = ev.split(' ', 2)
248    dev[1].global_request("P2P_GROUP_ADD " + persistent)
249    ev = dev[1].wait_global_event(["P2P-PERSISTENT-PSK-FAIL"], timeout=30)
250    if ev is None:
251        raise Exception("Did not receive PSK failure report")
252    [tmp, id] = ev.split('=', 1)
253    ev = dev[1].wait_global_event(["P2P-GROUP-REMOVED"], timeout=10)
254    if ev is None:
255        raise Exception("Group removal event timed out")
256    if "reason=PSK_FAILURE" not in ev:
257        raise Exception("Unexpected group removal reason")
258    dev[1].global_request("REMOVE_NETWORK " + id)
259
260    logger.info("Re-invite after client removed persistent group info")
261    dev[0].dump_monitor()
262    dev[1].p2p_listen()
263    if not dev[0].discover_peer(addr1, social=True):
264        raise Exception("Peer " + peer + " not found")
265    dev[0].global_request("P2P_INVITE group=" + dev[0].group_ifname + " peer=" + addr1)
266    ev = dev[1].wait_global_event(["P2P-INVITATION-RECEIVED"], timeout=10)
267    if ev is None:
268        raise Exception("Timeout on invitation")
269    if " persistent=" in ev:
270        raise Exception("Unexpected invitation event")
271    pin = dev[1].wps_read_pin()
272    dev[0].p2p_go_authorize_client(pin)
273    c_res = dev[1].p2p_connect_group(addr0, pin, timeout=60, social=True,
274                                     freq=i_res['freq'])
275    if not c_res['persistent']:
276        raise Exception("Joining client did not recognize persistent group")
277    if r_res['psk'] == c_res['psk']:
278        raise Exception("Same PSK assigned on both times")
279    dev[0].wait_sta(addr=dev[1].p2p_interface_addr(), wait_4way_hs=True)
280    hwsim_utils.test_connectivity_p2p(dev[0], dev[1])
281
282    terminate_group(dev[0], dev[1])
283
284@remote_compatible
285def test_persistent_group_channel(dev):
286    """P2P persistent group re-invocation with channel selection"""
287    form(dev[0], dev[1], test_data=False)
288
289    logger.info("Re-invoke persistent group from client with forced channel")
290    invite(dev[1], dev[0], "freq=2427")
291    [go_res, cli_res] = check_result(dev[0], dev[1])
292    if go_res['freq'] != "2427":
293        raise Exception("Persistent group client forced channel not followed")
294    terminate_group(dev[0], dev[1])
295
296    logger.info("Re-invoke persistent group from GO with forced channel")
297    invite(dev[0], dev[1], "freq=2432")
298    [go_res, cli_res] = check_result(dev[0], dev[1])
299    if go_res['freq'] != "2432":
300        raise Exception("Persistent group GO channel preference not followed")
301    terminate_group(dev[0], dev[1])
302
303    logger.info("Re-invoke persistent group from client with channel preference")
304    invite(dev[1], dev[0], "pref=2417")
305    [go_res, cli_res] = check_result(dev[0], dev[1])
306    if go_res['freq'] != "2417":
307        raise Exception("Persistent group client channel preference not followed")
308    terminate_group(dev[0], dev[1])
309
310@remote_compatible
311def test_persistent_group_and_role_change(dev):
312    """P2P persistent group, auto GO in another role, and re-invocation"""
313    form(dev[0], dev[1])
314
315    logger.info("Start and stop autonomous GO on previous P2P client device")
316    dev[1].p2p_start_go()
317    dev[1].remove_group()
318    dev[1].dump_monitor()
319
320    logger.info("Re-invoke the persistent group")
321    invite_from_go(dev[0], dev[1])
322
323def test_persistent_go_client_list(dev):
324    """P2P GO and list of clients in persistent group"""
325    addr0 = dev[0].p2p_dev_addr()
326    addr1 = dev[1].p2p_dev_addr()
327    addr2 = dev[2].p2p_dev_addr()
328
329    res = dev[0].p2p_start_go(persistent=True)
330    id = None
331    for n in dev[0].list_networks(p2p=True):
332        if "[P2P-PERSISTENT]" in n['flags']:
333            id = n['id']
334            break
335    if id is None:
336        raise Exception("Could not find persistent group entry")
337
338    connect_cli(dev[0], dev[1], social=True, freq=res['freq'])
339    clients = dev[0].global_request("GET_NETWORK " + id + " p2p_client_list").rstrip()
340    if clients != addr1:
341        raise Exception("Unexpected p2p_client_list entry(2): " + clients)
342    connect_cli(dev[0], dev[2], social=True, freq=res['freq'])
343    clients = dev[0].global_request("GET_NETWORK " + id + " p2p_client_list").rstrip()
344    if clients != addr2 + " " + addr1:
345        raise Exception("Unexpected p2p_client_list entry(3): " + clients)
346
347    peer = dev[1].get_peer(res['go_dev_addr'])
348    dev[1].remove_group()
349    dev[1].global_request("P2P_GROUP_ADD persistent=" + peer['persistent'])
350    ev = dev[1].wait_global_event(["P2P-GROUP-STARTED"], timeout=30)
351    if ev is None:
352        raise Exception("Timeout on group restart (on client)")
353    dev[1].group_form_result(ev)
354    clients = dev[0].global_request("GET_NETWORK " + id + " p2p_client_list").rstrip()
355    if set(clients.split()) != set((addr1, addr2)):
356        raise Exception("Unexpected p2p_client_list entry(4): " + clients)
357
358    dev[2].remove_group()
359    dev[1].remove_group()
360    dev[0].remove_group()
361
362    clients = dev[0].global_request("GET_NETWORK " + id + " p2p_client_list").rstrip()
363    if clients != addr1 + " " + addr2:
364        raise Exception("Unexpected p2p_client_list entry(5): " + clients)
365
366    dev[1].p2p_listen()
367    dev[2].p2p_listen()
368    dev[0].request("P2P_FLUSH")
369    dev[0].discover_peer(addr1, social=True)
370    peer = dev[0].get_peer(addr1)
371    if 'persistent' not in peer or peer['persistent'] != id:
372        raise Exception("Persistent group client not recognized(1)")
373
374    dev[0].discover_peer(addr2, social=True)
375    peer = dev[0].get_peer(addr2)
376    if 'persistent' not in peer or peer['persistent'] != id:
377        raise Exception("Persistent group client not recognized(2)")
378
379@remote_compatible
380def test_persistent_group_in_grpform(dev):
381    """P2P persistent group parameters re-used in group formation"""
382    addr0 = dev[0].p2p_dev_addr()
383    addr1 = dev[1].p2p_dev_addr()
384    form(dev[0], dev[1])
385    dev[1].p2p_listen()
386    if not dev[0].discover_peer(addr1, social=True):
387        raise Exception("Could not discover peer")
388    peer = dev[0].get_peer(addr1)
389    if "persistent" not in peer:
390        raise Exception("Could not map peer to a persistent group")
391
392    pin = dev[1].wps_read_pin()
393    dev[1].p2p_go_neg_auth(addr0, pin, "display", go_intent=0)
394    i_res = dev[0].p2p_go_neg_init(addr1, pin, "enter", timeout=20,
395                                   go_intent=15,
396                                   persistent_id=peer['persistent'])
397    r_res = dev[1].p2p_go_neg_auth_result()
398    logger.debug("i_res: " + str(i_res))
399    logger.debug("r_res: " + str(r_res))
400
401@remote_compatible
402def test_persistent_group_without_persistent_reconnect(dev):
403    """P2P persistent group re-invocation without persistent reconnect"""
404    form(dev[0], dev[1])
405    dev[0].dump_monitor()
406    dev[1].dump_monitor()
407
408    logger.info("Re-invoke persistent group from client")
409    invite(dev[1], dev[0], persistent_reconnect=False)
410
411    ev = dev[0].wait_global_event(["P2P-INVITATION-RECEIVED"], timeout=15)
412    if ev is None:
413        raise Exception("No invitation request reported")
414    if "persistent=" not in ev:
415        raise Exception("Invalid invitation type reported: " + ev)
416
417    ev2 = dev[1].wait_global_event(["P2P-INVITATION-RESULT"], timeout=15)
418    if ev2 is None:
419        raise Exception("No invitation response reported")
420    if "status=1" not in ev2:
421        raise Exception("Unexpected status: " + ev2)
422    dev[1].p2p_listen()
423
424    exp = r'<.>(P2P-INVITATION-RECEIVED) sa=([0-9a-f:]*) persistent=([0-9]*) freq=([0-9]*)'
425    s = re.split(exp, ev)
426    if len(s) < 5:
427        raise Exception("Could not parse invitation event")
428    sa = s[2]
429    id = s[3]
430    freq = s[4]
431    logger.info("Invalid P2P_INVITE test coverage")
432    if "FAIL" not in dev[0].global_request("P2P_INVITE persistent=" + id + " peer=" + sa + " freq=0"):
433        raise Exception("Invalid P2P_INVITE accepted")
434    if "FAIL" not in dev[0].global_request("P2P_INVITE persistent=" + id + " peer=" + sa + " pref=0"):
435        raise Exception("Invalid P2P_INVITE accepted")
436    logger.info("Re-initiate invitation based on upper layer acceptance")
437    if "OK" not in dev[0].global_request("P2P_INVITE persistent=" + id + " peer=" + sa + " freq=" + freq):
438        raise Exception("Invitation command failed")
439    [go_res, cli_res] = check_result(dev[0], dev[1])
440    if go_res['freq'] != freq:
441        raise Exception("Unexpected channel on GO: {} MHz, expected {} MHz".format(go_res['freq'], freq))
442    if cli_res['freq'] != freq:
443        raise Exception("Unexpected channel on CLI: {} MHz, expected {} MHz".format(cli_res['freq'], freq))
444    terminate_group(dev[0], dev[1])
445    dev[0].dump_monitor()
446    dev[1].dump_monitor()
447
448    logger.info("Re-invoke persistent group from GO")
449    invite(dev[0], dev[1], persistent_reconnect=False)
450
451    ev = dev[1].wait_global_event(["P2P-INVITATION-RECEIVED"], timeout=15)
452    if ev is None:
453        raise Exception("No invitation request reported")
454    if "persistent=" not in ev:
455        raise Exception("Invalid invitation type reported: " + ev)
456
457    ev2 = dev[0].wait_global_event(["P2P-INVITATION-RESULT"], timeout=15)
458    if ev2 is None:
459        raise Exception("No invitation response reported")
460    if "status=1" not in ev2:
461        raise Exception("Unexpected status: " + ev2)
462    dev[0].p2p_listen()
463
464    exp = r'<.>(P2P-INVITATION-RECEIVED) sa=([0-9a-f:]*) persistent=([0-9]*)'
465    s = re.split(exp, ev)
466    if len(s) < 4:
467        raise Exception("Could not parse invitation event")
468    sa = s[2]
469    id = s[3]
470    logger.info("Re-initiate invitation based on upper layer acceptance")
471    if "OK" not in dev[1].global_request("P2P_INVITE persistent=" + id + " peer=" + sa + " freq=" + freq):
472        raise Exception("Invitation command failed")
473    [go_res, cli_res] = check_result(dev[0], dev[1])
474    terminate_group(dev[0], dev[1])
475
476@remote_compatible
477def test_persistent_group_already_running(dev):
478    """P2P persistent group formation and invitation while GO already running"""
479    form(dev[0], dev[1])
480    peer = dev[1].get_peer(dev[0].p2p_dev_addr())
481    listen_freq = peer['listen_freq']
482    dev[0].dump_monitor()
483    dev[1].dump_monitor()
484    networks = dev[0].list_networks(p2p=True)
485    if len(networks) != 1:
486        raise Exception("Unexpected number of networks")
487    if "[P2P-PERSISTENT]" not in networks[0]['flags']:
488        raise Exception("Not the persistent group data")
489    if "OK" not in dev[0].global_request("P2P_GROUP_ADD persistent=" + networks[0]['id'] + " freq=" + listen_freq):
490        raise Exception("Could not state GO")
491    invite_from_cli(dev[0], dev[1])
492
493@remote_compatible
494def test_persistent_group_add_cli_chan(dev):
495    """P2P persistent group formation and re-invocation with p2p_add_cli_chan=1"""
496    try:
497        dev[0].request("SET p2p_add_cli_chan 1")
498        dev[1].request("SET p2p_add_cli_chan 1")
499        form(dev[0], dev[1])
500        dev[1].request("BSS_FLUSH 0")
501        dev[1].scan(freq="2412", only_new=True)
502        dev[1].scan(freq="2437", only_new=True)
503        dev[1].scan(freq="2462", only_new=True)
504        dev[1].request("BSS_FLUSH 0")
505        invite_from_cli(dev[0], dev[1])
506        invite_from_go(dev[0], dev[1])
507    finally:
508        dev[0].request("SET p2p_add_cli_chan 0")
509        dev[1].request("SET p2p_add_cli_chan 0")
510
511@remote_compatible
512def test_persistent_invalid_group_add(dev):
513    """Invalid P2P_GROUP_ADD command"""
514    id = dev[0].add_network()
515    if "FAIL" not in dev[0].global_request("P2P_GROUP_ADD persistent=12345"):
516        raise Exception("Invalid P2P_GROUP_ADD accepted")
517    if "FAIL" not in dev[0].global_request("P2P_GROUP_ADD persistent=%d" % id):
518        raise Exception("Invalid P2P_GROUP_ADD accepted")
519    if "FAIL" not in dev[0].global_request("P2P_GROUP_ADD foo"):
520        raise Exception("Invalid P2P_GROUP_ADD accepted")
521
522def test_persistent_group_missed_inv_resp(dev):
523    """P2P persistent group re-invocation with invitation response getting lost"""
524    form(dev[0], dev[1])
525    addr = dev[1].p2p_dev_addr()
526    dev[1].global_request("SET persistent_reconnect 1")
527    dev[1].p2p_listen()
528    if not dev[0].discover_peer(addr, social=True):
529        raise Exception("Peer " + addr + " not found")
530    dev[0].dump_monitor()
531    peer = dev[0].get_peer(addr)
532    # Drop the first Invitation Response frame
533    if "FAIL" in dev[0].request("SET ext_mgmt_frame_handling 1"):
534        raise Exception("Failed to enable external management frame handling")
535    cmd = "P2P_INVITE persistent=" + peer['persistent'] + " peer=" + addr
536    dev[0].global_request(cmd)
537    rx_msg = dev[0].mgmt_rx()
538    if rx_msg is None:
539        raise Exception("MGMT-RX timeout (no Invitation Response)")
540    time.sleep(2)
541    # Allow following Invitation Response frame to go through
542    if "FAIL" in dev[0].request("SET ext_mgmt_frame_handling 0"):
543        raise Exception("Failed to disable external management frame handling")
544    time.sleep(1)
545    # Force the P2P Client side to be on its Listen channel for retry
546    dev[1].p2p_listen()
547    ev = dev[0].wait_global_event(["P2P-INVITATION-RESULT"], timeout=15)
548    if ev is None:
549        raise Exception("Invitation result timed out")
550    # Allow P2P Client side to continue connection-to-GO attempts
551    dev[1].p2p_stop_find()
552
553    # Verify that group re-invocation goes through
554    ev = dev[1].wait_global_event(["P2P-GROUP-STARTED",
555                                   "P2P-GROUP-FORMATION-FAILURE"],
556                                  timeout=20)
557    if ev is None:
558        raise Exception("Group start event timed out")
559    if "P2P-GROUP-STARTED" not in ev:
560        raise Exception("Group re-invocation failed")
561    dev[0].group_form_result(ev)
562
563    ev = dev[0].wait_global_event(["P2P-GROUP-STARTED"], timeout=5)
564    if ev is None:
565        raise Exception("Group start event timed out on GO")
566    dev[0].group_form_result(ev)
567
568    terminate_group(dev[0], dev[1])
569
570@remote_compatible
571def test_persistent_group_profile_add(dev):
572    """Create a P2P persistent group with ADD_NETWORK"""
573    passphrase = "passphrase here"
574    id = dev[0].p2pdev_add_network()
575    dev[0].p2pdev_set_network_quoted(id, "ssid", "DIRECT-ab")
576    dev[0].p2pdev_set_network_quoted(id, "psk", passphrase)
577    dev[0].p2pdev_set_network(id, "mode", "3")
578    dev[0].p2pdev_set_network(id, "disabled", "2")
579    dev[0].p2p_start_go(persistent=id, freq=2412)
580
581    pin = dev[1].wps_read_pin()
582    dev[0].p2p_go_authorize_client(pin)
583    res = dev[1].p2p_connect_group(dev[0].p2p_dev_addr(), pin, timeout=60,
584                                   social=True, freq=2412)
585    if res['result'] != 'success':
586        raise Exception("Joining the group did not succeed")
587
588    dev[0].remove_group()
589    dev[1].wait_go_ending_session()
590
591@remote_compatible
592def test_persistent_group_cancel_on_cli(dev):
593    """P2P persistent group formation, re-invocation, and cancel"""
594    dev[0].global_request("SET p2p_no_group_iface 0")
595    dev[1].global_request("SET p2p_no_group_iface 0")
596    form(dev[0], dev[1])
597
598    invite_from_go(dev[0], dev[1], terminate=False)
599    if "FAIL" not in dev[1].global_request("P2P_CANCEL"):
600        raise Exception("P2P_CANCEL succeeded unexpectedly on CLI")
601    if "FAIL" not in dev[0].global_request("P2P_CANCEL"):
602        raise Exception("P2P_CANCEL succeeded unexpectedly on GO")
603    terminate_group(dev[0], dev[1])
604
605    invite_from_cli(dev[0], dev[1], terminate=False)
606    if "FAIL" not in dev[1].global_request("P2P_CANCEL"):
607        raise Exception("P2P_CANCEL succeeded unexpectedly on CLI")
608    if "FAIL" not in dev[0].global_request("P2P_CANCEL"):
609        raise Exception("P2P_CANCEL succeeded unexpectedly on GO")
610    terminate_group(dev[0], dev[1])
611
612@remote_compatible
613def test_persistent_group_cancel_on_cli2(dev):
614    """P2P persistent group formation, re-invocation, and cancel (2)"""
615    form(dev[0], dev[1])
616    invite_from_go(dev[0], dev[1], terminate=False)
617    if "FAIL" not in dev[1].global_request("P2P_CANCEL"):
618        raise Exception("P2P_CANCEL succeeded unexpectedly on CLI")
619    if "FAIL" not in dev[0].global_request("P2P_CANCEL"):
620        raise Exception("P2P_CANCEL succeeded unexpectedly on GO")
621    terminate_group(dev[0], dev[1])
622
623    invite_from_cli(dev[0], dev[1], terminate=False)
624    if "FAIL" not in dev[1].global_request("P2P_CANCEL"):
625        raise Exception("P2P_CANCEL succeeded unexpectedly on CLI")
626    if "FAIL" not in dev[0].global_request("P2P_CANCEL"):
627        raise Exception("P2P_CANCEL succeeded unexpectedly on GO")
628    terminate_group(dev[0], dev[1])
629
630@remote_compatible
631def test_persistent_group_cancel_on_cli3(dev):
632    """P2P persistent group formation, re-invocation, and cancel"""
633    dev[0].global_request("SET p2p_no_group_iface 0")
634    dev[1].global_request("SET p2p_no_group_iface 1")
635    dev[1].p2p_ext_listen(30,30)
636    form(dev[0], dev[1])
637
638    invite_from_go(dev[0], dev[1], terminate=False)
639    if "FAIL" not in dev[1].global_request("P2P_CANCEL"):
640        raise Exception("P2P_CANCEL succeeded unexpectedly on CLI")
641    if "FAIL" not in dev[0].global_request("P2P_CANCEL"):
642        raise Exception("P2P_CANCEL succeeded unexpectedly on GO")
643    terminate_group(dev[0], dev[1])
644
645    invite_from_cli(dev[0], dev[1], terminate=False)
646    if "FAIL" not in dev[1].global_request("P2P_CANCEL"):
647        raise Exception("P2P_CANCEL succeeded unexpectedly on CLI")
648    if "FAIL" not in dev[0].global_request("P2P_CANCEL"):
649        raise Exception("P2P_CANCEL succeeded unexpectedly on GO")
650    terminate_group(dev[0], dev[1])
651
652@remote_compatible
653def test_persistent_group_peer_dropped(dev):
654    """P2P persistent group formation and re-invocation with peer having dropped group"""
655    form(dev[0], dev[1], reverse_init=True)
656    invite_from_cli(dev[0], dev[1])
657
658    logger.info("Remove group on the GO and try to invite from the client")
659    dev[0].global_request("REMOVE_NETWORK all")
660    invite(dev[1], dev[0])
661    ev = dev[1].wait_global_event(["P2P-INVITATION-RESULT"], timeout=10)
662    if ev is None:
663        raise Exception("No invitation result seen")
664    if "status=8" not in ev:
665        raise Exception("Unexpected invitation result: " + ev)
666    networks = dev[1].list_networks(p2p=True)
667    if len(networks) > 0:
668        raise Exception("Unexpected network block on client")
669
670    logger.info("Verify that a new group can be formed")
671    form(dev[0], dev[1], reverse_init=True)
672
673@remote_compatible
674def test_persistent_group_peer_dropped2(dev):
675    """P2P persistent group formation and re-invocation with peer having dropped group (2)"""
676    form(dev[0], dev[1])
677    invite_from_go(dev[0], dev[1])
678
679    logger.info("Remove group on the client and try to invite from the GO")
680    dev[1].global_request("REMOVE_NETWORK all")
681    invite(dev[0], dev[1])
682    ev = dev[0].wait_global_event(["P2P-INVITATION-RESULT"], timeout=10)
683    if ev is None:
684        raise Exception("No invitation result seen")
685    if "status=8" not in ev:
686        raise Exception("Unexpected invitation result: " + ev)
687    networks = dev[1].list_networks(p2p=True)
688    if len(networks) > 0:
689        raise Exception("Unexpected network block on client")
690
691    logger.info("Verify that a new group can be formed")
692    form(dev[0], dev[1])
693
694def test_persistent_group_peer_dropped3(dev):
695    """P2P persistent group formation and re-invocation with peer having dropped group (3)"""
696    form(dev[0], dev[1], reverse_init=True)
697    invite_from_cli(dev[0], dev[1])
698
699    logger.info("Remove group on the GO and try to invite from the client")
700    dev[0].global_request("REMOVE_NETWORK all")
701    invite(dev[1], dev[0], use_listen=False)
702    ev = dev[1].wait_global_event(["P2P-INVITATION-RESULT"], timeout=10)
703    if ev is None:
704        raise Exception("No invitation result seen")
705    if "status=8" not in ev:
706        raise Exception("Unexpected invitation result: " + ev)
707    networks = dev[1].list_networks(p2p=True)
708    if len(networks) > 0:
709        raise Exception("Unexpected network block on client")
710
711    time.sleep(0.2)
712    logger.info("Verify that a new group can be formed")
713    form(dev[0], dev[1], reverse_init=True, r_listen=False)
714