152cff6ba6
The option of handling upper layer P2P management operations within the driver/firmware was originally planned to be used with wpa_supplicant, but this has not really happened and there is no clear sign of this being needed in the near term either. This functionality has not been completed and it is certainly not being kept up-to-date or tested. As such, it is best to remove it for now and if this or something similar is needed in the future, it can be brought back once a clear need for it has been demonstrated first. Signed-hostap: Jouni Malinen <j@w1.fi>
474 lines
20 KiB
Text
474 lines
20 KiB
Text
/**
|
|
\page p2p Wi-Fi Direct - P2P module
|
|
|
|
Wi-Fi Direct functionality is implemented any many levels in the WLAN
|
|
stack from low-level driver operations to high-level GUI design. This
|
|
document covers the parts that can be user by %wpa_supplicant. However,
|
|
it should be noted that alternative designs are also possible, so some
|
|
of the functionality may reside in other components in the system.
|
|
|
|
The driver (or WLAN firmware/hardware) is expected to handle low-level
|
|
operations related to P2P Power Management and channel scheduling. In
|
|
addition, support for virtual network interface and data frame
|
|
processing is done inside the driver. Configuration for these
|
|
low-level operations is defined in the driver interface:
|
|
src/drivers/driver.h. This defines both the commands and events used to
|
|
interact with the driver.
|
|
|
|
P2P module implements higher layer functionality for management P2P
|
|
groups. It takes care of Device Discovery, Service Discovery, Group
|
|
Owner Negotiation, P2P Invitation. In addition, it maintains
|
|
information about neighboring P2P Devices. This module could be used
|
|
in designs that do not use %wpa_supplicant and it could also reside
|
|
inside the driver/firmware component. P2P module API is defined in
|
|
src/p2p/p2p.h.
|
|
|
|
Provisioning step of Group Formation is implemented using WPS
|
|
(src/wps/wps.h).
|
|
|
|
%wpa_supplicant includes code in interact with both the P2P module
|
|
(wpa_supplicant/p2p_supplicant.c) and WPS
|
|
(wpa_supplicant/wps_supplicant.c). The driver operations are passed
|
|
through these files, i.e., core P2P or WPS code does not interact
|
|
directly with the driver interface.
|
|
|
|
|
|
\section p2p_arch P2P architecture
|
|
|
|
P2P functionality affects many areas of the system architecture. This
|
|
section shows couple of examples on the location of main P2P
|
|
components. In the diagrams below, green arrows are used to show
|
|
communication paths from the P2P module to upper layer management
|
|
functionality and all the way to a GUI that user could use to manage
|
|
P2P connections. Blue arrows show the path taken for lower layer
|
|
operations. Glue code is used to bind the P2P module API to the rest
|
|
of the system to provide access both towards upper and lower layer
|
|
functionality.
|
|
|
|
\subsection p2p_arch_mac80211 P2P architecture with Linux/mac80211/ath9k
|
|
|
|
An architecture where the P2P module resides inside the
|
|
%wpa_supplicant process is used with Linux mac80211-based drivers,
|
|
e.g., ath9k. The following diagram shows the main components related
|
|
to P2P functionality in such an architecture.
|
|
|
|
\image html p2p_arch.png "P2P module within wpa_supplicant"
|
|
\image latex p2p_arch.eps "P2P module within wpa_supplicant" width=15cm
|
|
|
|
\subsection p2p_arch_umac P2P architecture with UMAC
|
|
|
|
The following diagram shows the main components related to P2P
|
|
functionality in an architecture where the P2P module resides inside
|
|
the kernel IEEE 802.11 stack (UMAC in the figure).
|
|
|
|
\image html p2p_arch2.png "P2P module in kernel
|
|
\image latex p2p_arch2.eps "P2P module in kernel" width=15cm
|
|
|
|
|
|
\section p2p_module P2P module
|
|
|
|
P2P module manages discovery and group formation with a single state
|
|
machine, i.e., only a single operation per device can be in progress
|
|
at any given time. The following diagram describes the P2P state
|
|
machine. For clarity, it does not include state transitions on
|
|
operation timeouts to the IDLE state. The states that are marked with
|
|
dotted ellipse are listed for clarity to describe the protocol
|
|
functionality for Device Discovery phase, but are not used in the
|
|
implementation (the SEARCH state is used to manage the initial Scan
|
|
and the alternating Listen and Search states within Find).
|
|
|
|
\image html p2p_sm.png "P2P module state machine"
|
|
\image latex p2p_sm.eps "P2P module state machine" width=15cm
|
|
|
|
\subsection p2p_module_api P2P module API
|
|
|
|
P2P module API is defined in src/p2p/p2p.h. The API consists of
|
|
functions for requesting operations and for providing event
|
|
notifications. Similar set of callback functions are configured with
|
|
struct p2p_config to provide callback functions that P2P module can
|
|
use to request operations and to provide event notifications. In
|
|
addition, there are number of generic helper functions that can be
|
|
used for P2P related operations.
|
|
|
|
These are the main functions for an upper layer management entity to
|
|
request P2P operations:
|
|
- p2p_find()
|
|
- p2p_stop_find()
|
|
- p2p_listen()
|
|
- p2p_connect()
|
|
- p2p_reject()
|
|
- p2p_prov_disc_req()
|
|
- p2p_sd_request()
|
|
- p2p_sd_cancel_request()
|
|
- p2p_sd_response()
|
|
- p2p_sd_service_update()
|
|
- p2p_invite()
|
|
|
|
These are the main callback functions for P2P module to provide event
|
|
notifications to the upper layer management entity:
|
|
|
|
- p2p_config::dev_found()
|
|
- p2p_config::go_neg_req_rx()
|
|
- p2p_config::go_neg_completed()
|
|
- p2p_config::sd_request()
|
|
- p2p_config::sd_response()
|
|
- p2p_config::prov_disc_req()
|
|
- p2p_config::prov_disc_resp()
|
|
- p2p_config::invitation_process()
|
|
- p2p_config::invitation_received()
|
|
- p2p_config::invitation_result()
|
|
|
|
The P2P module uses following functions to request lower layer driver
|
|
operations:
|
|
|
|
- p2p_config::p2p_scan()
|
|
- p2p_config::send_probe_resp()
|
|
- p2p_config::send_action()
|
|
- p2p_config::send_action_done()
|
|
- p2p_config::start_listen()
|
|
- p2p_config::stop_listen()
|
|
|
|
Events from lower layer driver operations are delivered to the P2P
|
|
module with following functions:
|
|
|
|
- p2p_probe_req_rx()
|
|
- p2p_rx_action()
|
|
- p2p_scan_res_handler()
|
|
- p2p_scan_res_handled()
|
|
- p2p_send_action_cb()
|
|
- p2p_listen_cb()
|
|
|
|
In addition to the per-device state, the P2P module maintains
|
|
per-group state for group owners. This is initialized with a call to
|
|
p2p_group_init() when a group is created and deinitialized with
|
|
p2p_group_deinit(). The upper layer GO management entity uses
|
|
following functions to interact with the P2P per-group state:
|
|
|
|
- p2p_group_notif_assoc()
|
|
- p2p_group_notif_disassoc()
|
|
- p2p_group_notif_formation_done()
|
|
- p2p_group_match_dev_type()
|
|
|
|
The P2P module will use following callback function to update P2P IE
|
|
for GO Beacon and Probe Response frames:
|
|
|
|
- p2p_group_config::ie_update()
|
|
|
|
|
|
\section p2p_driver P2P driver operations (low-level interface)
|
|
|
|
The following driver wrapper functions are needed for P2P in addition
|
|
to the standard station/AP mode operations when the P2P module resides
|
|
within %wpa_supplicant:
|
|
- wpa_driver_ops::if_add()
|
|
- wpa_driver_ops::if_remove()
|
|
- wpa_driver_ops::alloc_interface_addr()
|
|
- wpa_driver_ops::release_interface_addr()
|
|
- wpa_driver_ops::remain_on_channel()
|
|
- wpa_driver_ops::cancel_remain_on_channel()
|
|
- wpa_driver_ops::send_action()
|
|
- wpa_driver_ops::probe_req_report()
|
|
- wpa_driver_ops::disable_11b_rates()
|
|
|
|
The following driver wrapper events are needed for P2P in addition to
|
|
the standard station/AP mode events when the P2P module resides within
|
|
%wpa_supplicant:
|
|
- wpa_event_type::EVENT_RX_ACTION
|
|
- wpa_event_type::EVENT_REMAIN_ON_CHANNEL
|
|
- wpa_event_type::EVENT_CANCEL_REMAIN_ON_CHANNEL
|
|
- wpa_event_type::EVENT_RX_PROBE_REQ
|
|
|
|
|
|
\section p2p_go_neg P2P device discovery and group formation
|
|
|
|
This section shows an example sequence of operations that can be used
|
|
to implement P2P device discovery and group formation. The function
|
|
calls are described based on the P2P module API. The exact design for
|
|
the glue code outside the P2P module depends on the architecture used
|
|
in the system.
|
|
|
|
An upper layer management entity starts P2P device discovery by
|
|
calling p2p_find(). The P2P module start the discovery by requesting a
|
|
full scan to be completed by calling p2p_config::p2p_scan(). Results
|
|
from the scan will be reported by calling p2p_scan_res_handler() and
|
|
after last result, the scan result processing is terminated with a
|
|
call to p2p_scan_res_handled(). The P2P peers that are found during
|
|
the full scan are reported with the p2p_config::dev_found() callback.
|
|
|
|
After the full scan, P2P module start alternating between Listen and
|
|
Search states until the device discovery operation times out or
|
|
terminated, e.g., with a call to p2p_stop_find().
|
|
|
|
When going into the Listen state, the P2P module requests the driver
|
|
to be configured to be awake on the listen channel with a call to
|
|
p2p_config::start_listen(). The glue code using the P2P module may
|
|
implement this, e.g., by using remain-on-channel low-level driver
|
|
functionality for off-channel operation. Once the driver is available
|
|
on the requested channel, notification of this is delivered by calling
|
|
p2p_listen_cb(). The Probe Request frames that are received during the
|
|
Listen period are delivered to the P2P module by calling
|
|
p2p_config::p2p_probe_req_rx() and P2P module request a response to
|
|
these to be sent by using p2p_config::send_probe_resp() callback
|
|
function. If a group owner negotiation from another P2P device is
|
|
received during the device discovery phase, that is indicated to the
|
|
upper layer code with the p2p_config::go_neg_req_tx() callback.
|
|
|
|
The Search state is implemented by using the normal scan interface,
|
|
i.e., the P2P module will call p2p_config::p2p_scan() just like in the
|
|
full scan phase described. Similarly, scan results from the search
|
|
operation will be delivered to the P2P module using the
|
|
p2p_scan_res_handler() and p2p_scan_res_handled() functions.
|
|
|
|
Once the upper layer management entity has found a peer with which it
|
|
wants to connect by forming a new group, it initiates group owner
|
|
negotiation by calling p2p_connect(). Before doing this, the upper
|
|
layer code is responsible for asking the user to provide the PIN to be
|
|
used during the provisioning step with the peer or the push button
|
|
press for PBC mode. The glue code will need to figure out the intended
|
|
interface address for the group before group owner negotiation can be
|
|
started.
|
|
|
|
Optional Provision Discovery mechanism can be used to request the peer
|
|
to display a PIN for the local device to enter (and vice versa). Upper
|
|
layer management entity can request the specific mechanism by calling
|
|
p2p_prov_disc_req(). The response to this will be reported with the
|
|
p2p_config::prov_disc_resp() callback. If the peer device started
|
|
Provision Discovery, an accepted request will be reported with the
|
|
p2p_config::prov_disc_req() callback. The P2P module will
|
|
automatically accept the Provision Discovery for display and keypad
|
|
methods, but it is up to the upper layer manegement entity to actually
|
|
generate the PIN and to configure it with following p2p_connect() call
|
|
to actually authorize the connection.
|
|
|
|
The P2P module will use p2p_config::send_action() callback to request
|
|
lower layer code to transmit an Action frame during group owner
|
|
negotiation. p2p_send_action_cb() is used to report the result of
|
|
transmission. If the peer is not reachable, the P2P module will try to
|
|
find it by alternating between Action frame send and Listen
|
|
states. The Listen state for this phase will be used similarly to the
|
|
Listen state during device discovery as described above.
|
|
|
|
Once the group owner negotiation has been completed, its results will
|
|
be reported with the p2p_config::go_neg_completed() callback. The
|
|
upper layer management code or the glue code using the P2P module API
|
|
is responsible for creating a new group interface and starting
|
|
provisioning step at this point by configuring WPS Registrar or
|
|
Enrollee functionality based on the reported group owner negotiation
|
|
results. The upper layer code is also responsible for timing out WPS
|
|
provisioning if it cannot be completed in 15 seconds.
|
|
|
|
Successful completion of the WPS provisioning is reported with a call
|
|
to p2p_wps_success_cb(). The P2P module will clear its group formation
|
|
state at this point and allows new group formation attempts to be
|
|
started. The upper layer management code is responsible for configuring
|
|
the GO to accept associations from devices and the client to connect to
|
|
the GO with the provisioned credentials. GO is also responsible for
|
|
calling p2p_group_notif_formation_done() as described below.
|
|
|
|
If the WPS provisioning step fails or times out, this is reported with
|
|
a call to p2p_group_formation_failed(). The P2P module will clear its
|
|
group formation state at this point and allows new group formation
|
|
attempts to be started. The upper layer management code is responsible
|
|
for removing the group interface for the failed group.
|
|
|
|
|
|
\section p2p_sd P2P service discovery
|
|
|
|
P2P protocol includes service discovery functionality that can be used
|
|
to discover which services are provided by the peers before forming a
|
|
group. This leverages the Generic Advertisement Service (GAS) protocol
|
|
from IEEE 802.11u and P2P vendor-specific contents inside the Native
|
|
GAS messages.
|
|
|
|
The P2P module takes care of GAS encapsulation, fragmentation, and
|
|
actual transmission and reception of the Action frames needed for
|
|
service discovery. The user of the P2P module is responsible for
|
|
providing P2P specific Service Request TLV(s) for queries and Service
|
|
Response TLV(s) for responses.
|
|
|
|
\subsection p2p_sd_query Quering services of peers
|
|
|
|
Service discovery is implemented by processing pending queries as a
|
|
part of the device discovery phase. p2p_sd_request() function is used
|
|
to schedule service discovery queries to a specific peer or to all
|
|
discovered peers. p2p_sd_cancel_request() can be used to cancel a
|
|
scheduled query. Queries that are specific to a single peer will be
|
|
removed automatically after the response has been received.
|
|
|
|
After the service discovery queries have been queued, device discovery
|
|
is started with a call to p2p_find(). The pending service discovery
|
|
queries are then sent whenever a peer is discovered during the find
|
|
operation. Responses to the queries will be reported with the
|
|
p2p_config::sd_response() callback.
|
|
|
|
\subsection p2p_sd_response Replying to service discovery queries from peers
|
|
|
|
The received service discovery requests will be indicated with the
|
|
p2p_config::sd_request() callback. The response to the query is sent
|
|
by calling p2p_sd_response().
|
|
|
|
\subsection p2p_sd_indicator Service update indicator
|
|
|
|
P2P service discovery provides a mechanism to notify peers about
|
|
changes in available services. This works by incrementing Service
|
|
Update Indicator value whenever there is a change in the
|
|
services. This value is included in all SD request and response
|
|
frames. The value received from the peers will be included in the
|
|
p2p_config::sd_request() and p2p_config::sd_response() callbacks. The
|
|
value to be sent to the peers is incremented with a call to
|
|
p2p_sd_service_update() whenever availibility of the local services
|
|
changes.
|
|
|
|
|
|
\section p2p_go P2P group owner
|
|
|
|
This section describes how P2P module can be used for managing
|
|
per-group information in a group owner. The function calls are
|
|
described based on the P2P module API. The exact design for the glue
|
|
code outside the P2P module depends on the architecture used in the
|
|
system.
|
|
|
|
When a P2P group interface is created in group owner role, per-group
|
|
data is initialized with p2p_group_init(). This call provides a
|
|
pointer to the per-device P2P module context and configures the
|
|
per-group operation. The configured p2p_group_config::ie_update()
|
|
callback is used to set the initial P2P IE for Beacon and Probe
|
|
Response frames in the group owner. The AP mode implementation may use
|
|
this information to add IEs into the frames.
|
|
|
|
Once the group formation has been completed (or if it is skipped in
|
|
case of manual group setup), p2p_group_notif_formation_done() is
|
|
called. This will allow the P2P module to update the P2P IE for
|
|
Beacon and Probe Response frames.
|
|
|
|
The SME/MLME code that managements IEEE 802.11 association processing
|
|
needs to inform P2P module whenever a P2P client associates or
|
|
disassociates with the group. This is done by calling
|
|
p2p_group_notif_assoc() and p2p_group_notif_disassoc(). The P2P module
|
|
manages a list of group members and updates the P2P Group Information
|
|
subelement in the P2P IE based on the information from the P2P
|
|
clients. The p2p_group_config::ie_update() callback is used whenever
|
|
the P2P IE in Probe Response frames needs to be changed.
|
|
|
|
The SME/MLME code that takes care of replying to Probe Request frames
|
|
can use p2p_group_match_dev_type() to check whether the Probe Request
|
|
frame request a reply only from groups that include a specific device
|
|
type in one of the clients or GO. A match will be reported if the
|
|
Probe Request does not request a specific device type, so this
|
|
function can be used to filter or received Probe Request frames and
|
|
only the ones that result in non-zero return value need to be replied.
|
|
|
|
When the P2P group interface for GO role is removed,
|
|
p2p_group_deinit() is used to deinitialize the per-group P2P module
|
|
state.
|
|
|
|
|
|
\section p2p_ctrl_iface P2P control interface
|
|
|
|
%wpa_supplicant \ref ctrl_iface_page "control interface" can be used
|
|
to manage P2P functionality from an external program (e.g., a GUI or a
|
|
system configuration manager). This interface can be used directly
|
|
through the control interface backend mechanism (e.g., local domain
|
|
sockets on Linux) or with help of wpa_cli (e.g., from a script).
|
|
|
|
The following P2P-related commands are available:
|
|
- \ref ctrl_iface_P2P_FIND P2P_FIND
|
|
- \ref ctrl_iface_P2P_STOP_FIND P2P_STOP_FIND
|
|
- \ref ctrl_iface_P2P_CONNECT P2P_CONNECT
|
|
- \ref ctrl_iface_P2P_LISTEN P2P_LISTEN
|
|
- \ref ctrl_iface_P2P_GROUP_REMOVE P2P_GROUP_REMOVE
|
|
- \ref ctrl_iface_P2P_GROUP_ADD P2P_GROUP_ADD
|
|
- \ref ctrl_iface_P2P_PROV_DISC P2P_PROV_DISC
|
|
- \ref ctrl_iface_P2P_SERV_DISC_REQ P2P_SERV_DISC_REQ
|
|
- \ref ctrl_iface_P2P_SERV_DISC_CANCEL_REQ P2P_SERV_DISC_CANCEL_REQ
|
|
- \ref ctrl_iface_P2P_SERV_DISC_RESP P2P_SERV_DISC_RESP
|
|
- \ref ctrl_iface_P2P_SERVICE_UPDATE P2P_SERVICE_UPDATE
|
|
- \ref ctrl_iface_P2P_SERV_DISC_EXTERNAL P2P_SERV_DISC_EXTERNAL
|
|
- \ref ctrl_iface_P2P_REJECT P2P_REJECT
|
|
- \ref ctrl_iface_P2P_INVITE P2P_INVITE
|
|
|
|
The following P2P-related events are used:
|
|
- \ref ctrl_iface_event_P2P_EVENT_DEVICE_FOUND P2P-DEVICE-FOUND
|
|
- \ref ctrl_iface_event_P2P_EVENT_GO_NEG_REQUEST P2P-GO-NEG-REQUEST
|
|
- \ref ctrl_iface_event_P2P_EVENT_GO_NEG_SUCCESS P2P-GO-NEG-SUCCESS
|
|
- \ref ctrl_iface_event_P2P_EVENT_GO_NEG_FAILURE P2P-GO-NEG-FAILURE
|
|
- \ref ctrl_iface_event_P2P_EVENT_GROUP_FORMATION_SUCCESS P2P-GROUP-FORMATION-SUCCESS
|
|
- \ref ctrl_iface_event_P2P_EVENT_GROUP_FORMATION_FAILURE P2P-GROUP-FORMATION-FAILURE
|
|
- \ref ctrl_iface_event_P2P_EVENT_GROUP_STARTED P2P-GROUP-STARTED
|
|
- \ref ctrl_iface_event_P2P_EVENT_GROUP_REMOVED P2P-GROUP-REMOVED
|
|
- \ref ctrl_iface_event_P2P_EVENT_PROV_DISC_SHOW_PIN P2P-PROV-DISC-SHOW-PIN
|
|
- \ref ctrl_iface_event_P2P_EVENT_PROV_DISC_ENTER_PIN P2P-PROV-DISC-ENTER-PIN
|
|
- \ref ctrl_iface_event_P2P_EVENT_SERV_DISC_REQ P2P-SERV-DISC-REQ
|
|
- \ref ctrl_iface_event_P2P_EVENT_SERV_DISC_RESP P2P-SERV-DISC-RESP
|
|
- \ref ctrl_iface_event_P2P_EVENT_INVITATION_RECEIVED P2P-INVITATION-RECEIVED
|
|
- \ref ctrl_iface_event_P2P_EVENT_INVITATION_RESULT P2P-INVITATION-RESULT
|
|
|
|
|
|
\subsection p2p_wpa_gui GUI example (wpa_gui)
|
|
|
|
wpa_gui has an example implementation of a GUI that could be used to
|
|
manage P2P operations. The P2P related functionality is contained
|
|
mostly in wpa_supplicant/wpa_gui-qt4/peers.cpp and it shows how the
|
|
control interface commands and events can be used.
|
|
|
|
|
|
\subsection p2p_wpa_cli wpa_cli example
|
|
|
|
wpa_cli can be used to control %wpa_supplicant in interactive
|
|
mode. The following sessions show examples of commands used for
|
|
device discovery and group formation. The lines starting with "> " are
|
|
commands from the user (followed by command result indication) and
|
|
lines starting with "<2>" are event messages from %wpa_supplicant.
|
|
|
|
P2P device "Wireless Client":
|
|
|
|
\verbatim
|
|
> p2p_find
|
|
OK
|
|
> <2>P2P-DEVICE-FOUND 02:40:61:c2:f3:b7 p2p_dev_addr=02:40:61:c2:f3:b7
|
|
pri_dev_type=1-0050F204-1 name='Wireless Client 2' config_methods=0x18c
|
|
dev_capab=0x1 group_capab=0x0
|
|
<2>P2P-GO-NEG-REQUEST 02:40:61:c2:f3:b7
|
|
<2>P2P-GO-NEG-REQUEST 02:40:61:c2:f3:b7
|
|
> p2p_connect 02:40:61:c2:f3:b7 pbc
|
|
OK
|
|
<2>P2P-GO-NEG-SUCCESS
|
|
<2>P2P-GROUP-FORMATION-SUCCESS
|
|
<2>P2P-GROUP-STARTED sta0-p2p-0 client DIRECT-vM
|
|
> interface
|
|
Available interfaces:
|
|
sta0-p2p-0
|
|
sta0
|
|
> p2p_group_remove sta0-p2p-0
|
|
<2>P2P-GROUP-REMOVED sta0-p2p-0 client
|
|
OK
|
|
> term
|
|
OK
|
|
\endverbatim
|
|
|
|
|
|
P2P device "Wireless Client2" (which ended up operating in GO role):
|
|
|
|
\verbatim
|
|
> p2p_find
|
|
OK
|
|
<2>P2P-DEVICE-FOUND 02:f0:bc:44:87:62 p2p_dev_addr=02:f0:bc:44:87:62
|
|
pri_dev_type=1-0050F204-1 name='Wireless Client' config_methods=0x18c
|
|
dev_capab=0x1 group_capab=0x0
|
|
> p2p_connect 02:f0:bc:44:87:62 pbc
|
|
OK
|
|
<2>P2P-GO-NEG-SUCCESS
|
|
<2>P2P-GROUP-FORMATION-SUCCESS
|
|
<2>P2P-GROUP-STARTED sta1-p2p-0 GO DIRECT-vM
|
|
> interface
|
|
Available interfaces:
|
|
sta1-p2p-0
|
|
sta1
|
|
> p2p_group_remove sta1-p2p-0
|
|
<2>P2P-GROUP-REMOVED sta1-p2p-0 GO
|
|
OK
|
|
> term
|
|
OK
|
|
\endverbatim
|
|
|
|
*/
|