這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
1 P2P GO Client協商流程
協商流程
P2P GO/Client的協商流程只需要簡單的幾步,如:
P2P串連發起端:指在P2P串連過程中主動發起P2P串連的機子,用A表示;
P2P串連接受端:指在P2P串連過程中接受P2P串連的機子,用B表示;
圖1 P2P GO/Client協商流程
如所示:
1、 首先A在P2P串連初始化準備完成後,發送一個“GO Negotiation Request”給B;
2、 而這時候,B並沒有準備好,這時B先儲存下A的協商資訊,然後發送一個“GO Negotiation Response”給A,該response包含有B的協商資訊,但在該response中,B把狀態state設定為P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE,表示當前P2P串連不可用;
3、 A在接收到該response後,儲存B的協商資訊,切換到Listen state,等待B的P2P串連初始化完成,並等待B發送“GO Negotiation Request”。所以第一次的協商並沒有確定任何東西,主要用來通知B,A需要與B進行P2P串連;
4、 B在發送“GO Negotiation Response”後,進行P2P串連初始化,B在P2P串連初始化完成後,就發送一個“GO Negotiation Request”給A;
5、 而A在收到B的Request後,根據該Request的協商資訊,就可以確定自己在P2P串連時的角色了。這時A發送一個“GO Negotiation Response”給B,在該Response中,state為P2P_SC_SUCCESS,表示可以進行P2P串連;
6、 B在收到A的Response後,也可以確定自己在P2P串連時的角色了;
7、 最後B發送一個“GO Negotiation Confirm”給A,該Confirm作用之一是作為協商的確認,同時確定了後面P2P串連所使用的通道;
在P2P GO/Client協商完成後,作為GO角色的裝置後面就把自己切換到AP模式,而作為Client角色的裝置就去串連GO的AP。
協商時Request/Response內容
Request的部內容:
* Dialog Token: 1
Parsing WPS IE
Device Password ID: 4
Parsing P2P IE
Attribute 2 length 2
* Device Capability 21 Group Capability 2a
Attribute 4 length 1
* GO Intent: Intent 6 Tie breaker 0
Attribute 5 length 2
* Configuration Timeout
Attribute 6 length 5
* Listen Channel: Country XX(0x04) Regulatory Class 81 Channel Number 6
Attribute 9 length 6
* Intended P2P Interface Address: 96:bd:db:15:b9:38
Attribute 11 length 16
* Channel List: Country String ‘XX(0x04)’
Attribute 13 length 33
* Device Info: addr 96:bd:db:15:b9:38 primary device type 10-0050F204-5 device name ‘Android_dd11’ config methods 0x80
Attribute 17 length 5
* Operating Channel: Country XX(0x04) Regulatory Class 81 Channel Number 11 Peer country - hexdump(len=3): 58 58 04
其中* GO Intent: Intent 6 Tie breaker 0就是用於確定GO/Client角色的。
Response的部分內容:
* Dialog Token: 2
Parsing WPS IE
Device Password ID: 0
Parsing P2P IE
Attribute 0 length 1
* Status: 1
Attribute 2 length 2
* Device Capability 21 Group Capability 00
Attribute 4 length 1
* GO Intent: Intent 6 Tie breaker 0
Attribute 5 length 2
* Configuration Timeout
Attribute 17 length 5
* Operating Channel: Country XX(0x04) Regulatory Class 81 Channel Number 11
Attribute 9 length 6
* Intended P2P Interface Address: 96:bd:db:15:b9:38
Attribute 11 length 16
* Channel List: Country String ‘XX(0x04)’
Attribute 13 length 33
* Device Info: addr 96:bd:db:15:b9:38 primary device type 10-0050F204-5 device name ‘Android_dd11’ config methods 0x188
Confirm的部分內容:
* Dialog Token: 1
Parsing P2P IE
Attribute 0 length 1
* Status: 0
Attribute 2 length 2
* Device Capability 21 Group Capability 00
Attribute 17 length 5
* Operating Channel: Country XX(0x04) Regulatory Class 81 Channel Number 11
Attribute 11 length 16
* Channel List: Country String ‘XX(0x04)’
P2P串連時的P2P命令
P2P串連發起端命令:
p2p-dev-wlan0: Control interface command ‘P2P_FIND 120’
p2p-dev-wlan0: Control interface command ‘P2P_STOP_FIND’
p2p-dev-wlan0: Control interface command ‘P2P_PEER 96:bd:db:15:b9:38’
p2p-dev-wlan0: Control interface command ‘P2P_PEER 96:bd:db:15:b9:38’
p2p-dev-wlan0: Control interface command ‘P2P_PROV_DISC 96:bd:db:15:b9:38 pbc’
p2p-dev-wlan0: Control interface command ‘P2P_PEER 96:bd:db:15:b9:38’
p2p-dev-wlan0: Control interface command ‘P2P_CONNECT 96:bd:db:15:b9:38 pbc persistent go_intent=6 ’
p2p-dev-wlan0: Control interface command ‘LIST_NETWORKS’
p2p-dev-wlan0: Control interface command ‘GET_NETWORK 0 mode’
p2p-wlan0-1: Control interface command ‘SET p2p_group_idle 10’
p2p-wlan0-1: Control interface command ‘SET p2p_group_idle 0’
不同廠家實現P2P wlan口的方式不一樣,這隻是一種實現方式,其中p2p-dev-wlan0為虛擬網口,在P2P掃描、協商階段都是使用該網口,p2p-wlan0-1核心實際註冊的網口,實際P2P的串連就是使用該網口,p2p-wlan0-1網口在接收到P2P_CONNECT命令時才建立,該廠家p2p-wlan0-1網口的建立是由supplicant層通過nl80211 driver的wpa_driver_nl80211_if_add函數調用核心進行建立,最終調用到wifi驅動的wl_cfg80211_add_virtual_iface進行網口的建立,該函數雖然看起來只是增加虛擬網口,但也是可以建立實際的網口的,p2p-dev-wlan0(虛擬網口)與p2p-wlan0-1(實際網口)都是由該函數建立的。在這裡整個協商過程是在收到P2P_CONNECT命令後才開始的。
P2P串連發起端命令:
p2p-dev-wlan0: Control interface command ‘P2P_FIND 120’
p2p-dev-wlan0: Control interface command ‘P2P_STOP_FIND’
p2p-dev-wlan0: Control interface command ‘P2P_PEER 96:bd:db:15:b9:38’
p2p-dev-wlan0: Control interface command ‘P2P_CONNECT 96:bd:db:15:b9:38 pbc persistent go_intent=6 ’
p2p-dev-wlan0: Control interface command ‘LIST_NETWORKS’
p2p-dev-wlan0: Control interface command ‘GET_NETWORK 0 mode’
p2p-wlan0-6: Control interface command ‘SET p2p_group_idle 10’
在P2P串連接受端,當上層確認允許P2P串連時,先P2P_STOP_FIND,再往下發送P2P_PEER、P2P_CONNECT,這是就會建立實際的P2P串連網口p2p-wlan0-6,然後就是發送一個“GO Negotiation Request”。
2 已儲存群組時的協商過程
在P2P串連完成後,若P2P串連斷開後,再發起P2P串連,並不一定都需要P2P GO/Client的協商過程,這依賴雙方是否都儲存有P2P串連資訊。下面先介紹P2P串連後儲存的資訊,作為GO或Client時,儲存的資訊並不相同。
作為GO時儲存的資訊如下:
network={
ssid=”DIRECT-ZT-Android_7ab3”
bssid=6e:fa:a7:dc:14:d6
psk=”zT32EqmT”
proto=RSN
key_mgmt=WPA-PSK
pairwise=CCMP
auth_alg=OPEN
mode=3
disabled=2
p2p_client_list=96:bd:db:15:b9:38
}
ssid:GO的名稱;
bssid:GO自己的mac地址;
psk:GO的密碼;
p2p_client_list:所串連的Client的mac地址;
作為Client時儲存的資訊如下:
network={
ssid=”DIRECT-H0-Android_dd11”
bssid=96:bd:db:15:b9:38
psk=03e45fa923d8fbaf58920fdb484487bf19a98090d23278c72e326bfea44a9b50
proto=RSN
key_mgmt=WPA-PSK
pairwise=CCMP
auth_alg=OPEN
disabled=2
}
ssid:所串連GO的名稱;
bssid:所串連GO的mac地址;
psk:所串連GO的密碼,已加密;
不同情況下的P2P串連差異
1、 裝置雙方都沒有儲存有P2P串連資訊
該情況就走第一節介紹的協商過程。
2、 裝置雙方都儲存有P2P串連資訊
這種情況下,由於雙方都儲存有P2P串連資訊,就根據上次P2P串連的資訊串連就可以了,也就是上次是做GO的,還是做GO,做Client的也一樣,同時GO的名稱,mac地址,密碼,Client mac地址都是知道的,所以不需要再協商了,
只要GO/Client任意一端發起串連就可以了,但這次就不需要發送P2P_CONNECT命令了,只要發送P2P_INVITE命令就可以了,命令如下:
p2p-dev-wlan0: Control interface command ‘P2P_INVITE persistent=0 peer=96:bd:db:15:b9:38’
3、 發起端沒有儲存P2P串連資訊,接受端儲存有P2P串連資訊
由於發起端沒有儲存P2P串連資訊,也沒有選擇了,也是走第一節介紹的協商過程。
4、 發起端儲存有P2P串連資訊,接受端沒有儲存P2P串連資訊
由於發起端儲存有P2P串連資訊,所以發起端先發送P2P_INVITE,但由於接受端沒有儲存有P2P串連資訊,這次的P2P_INVITE以失敗告終,後面就是走第一節介紹的協商過程了。整個命令過程如下:
p2p-dev-wlan0: Control interface command ‘P2P_FIND 120’
p2p-dev-wlan0: Control interface command ‘P2P_STOP_FIND’
p2p-dev-wlan0: Control interface command ‘P2P_PEER 96:bd:db:15:b9:38’
p2p-dev-wlan0: Control interface command ‘P2P_PEER 96:bd:db:15:b9:38’
p2p-dev-wlan0: Control interface command ‘P2P_INVITE persistent=0 peer=96:bd:db:15:b9:38’
p2p-dev-wlan0: Control interface command ‘GET_NETWORK 0 p2p_client_list’
p2p-dev-wlan0: Control interface command ‘REMOVE_NETWORK 0’
p2p-dev-wlan0: Control interface command ‘P2P_PEER 96:bd:db:15:b9:38’
p2p-dev-wlan0: Control interface command ‘P2P_CONNECT 96:bd:db:15:b9:38 pbc persistent go_intent=6 ’
p2p-dev-wlan0: Control interface command ‘LIST_NETWORKS’
p2p-dev-wlan0: Control interface command ‘GET_NETWORK 0 mode’
p2p-wlan0-13: Control interface command ‘SET p2p_group_idle 10’
3 GO Client角色的協商過程
協商參數
協商過程中,GO、Client角色由兩個參數確定:
Intent:作為GO的優先順序;
breaker:在Intent相同是,用於判定誰做GO;
Intent的取值範圍為:0~1(#define P2P_MAX_GO_INTENT 15)
該Intent初始化時為0,在每次P2P_CONNECT時,由上層傳下來,android系統下,java層預設為6,該定義在:
/frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiNative.java
private static final int DEFAULT_GROUP_OWNER_INTENT = 6;
在協商時,誰的Intent值大,誰就作為GO;如果一端指定Intent值為15(P2P_MAX_GO_INTENT)那這端是GO,如果兩端都指定Intent為15,那這次的協商就會失敗。在協商兩端的值都不為15,並且值相等的情況下,就要breaker的值進行判定誰做GO了。
breaker的值只有0或1,該值在初始化時採用隨機產生:
if (os_get_random(&p2p->next_tie_breaker, 1) < 0)
p2p->next_tie_breaker = 0;
p2p->next_tie_breaker &= 0x01;
dev->tie_breaker = p2p->next_tie_breaker;
p2p->next_tie_breaker = !p2p->next_tie_breaker;
breaker值在每次發起P2P_CONNECT時都取反一次,這樣做的目的是在雙方的Intent值相同的情況下,多次協商時,雙方都有機會做GO。並且在發送Request時才填入自己的breaker值,在回應Response時,是把對方的breaker值取反後作為breaker值發送。
在協商流程中,由第二次Request/Response的Intent、breaker值決定誰做GO,這是誰的Intent(非15的情況下)值大誰就做GO,當Intent值相同時,這時由發送Request端的breaker值確定誰做GO,當發送Request端的breaker的值為1時,發送Request端作為GO,反之則作為Client。接收Request端的就剛好相反。
參數在協商階段的作用
這裡結合圖1進行說明:
1、 A發送Request給B,該Request包含A的Intent、breaker值;
2、 B收到Request後,由於B還沒準備好,回應一個Response給A,該Response中包含B的Intent值,同時把A的breaker值取反作為breaker填入Response中。在wifi開啟的首次接受P2P串連時,由於B上層還沒有調用過P2P_CONNECT,這時的Intent值為0,但這次的Intent值不影響最後的GO、Client判定;
3、 上面個這個回合的Request/Response不做GO、Client判定;
4、 B發送Request給A,該Request包含A的Intent、breaker值;
5、 A收到Request後,回應一個Response給B,該Response中包含A的Intent值,同時把B的breaker值取反作為breaker填入Response中;
6、 在這回合的Request/Response中,就決定了誰做GO,誰的Intent(非15的情況下)值大誰就做GO,在Intent相同的情況下,若B的breaker值為1,則B做GO,若B的breaker值為0,則B做Client,A的角色則剛好與B相反;
可以看到,最終的GO、Client角色是在第二回合的Request/Response中決定的。