diff --git a/doc/.gitignore b/doc/.gitignore index 4ea164e39..28c3fe4e9 100644 --- a/doc/.gitignore +++ b/doc/.gitignore @@ -3,6 +3,12 @@ hostapd.eps hostapd.png html latex +p2p_arch.eps +p2p_arch.png +p2p_arch2.eps +p2p_arch2.png +p2p_sm.eps +p2p_sm.png wpa_supplicant.eps wpa_supplicant.png wpa_supplicant-devel.pdf diff --git a/doc/Makefile b/doc/Makefile index 08a266f76..4e1c1bdf1 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -7,10 +7,16 @@ all: docs fig2dev -L png -m 3 $*.fig | pngtopnm | pnmscale 0.4 | pnmtopng \ > $*.png +%.png: %.dot + dot $*.dot -Tpng -o $*.png + +%.eps: %.dot + dot $*.dot -Tps -o $*.eps + _wpa_supplicant.png: wpa_supplicant.png cp $< $@ -docs-pics: wpa_supplicant.png wpa_supplicant.eps hostapd.png hostapd.eps +docs-pics: wpa_supplicant.png wpa_supplicant.eps hostapd.png hostapd.eps p2p_sm.png p2p_sm.eps p2p_arch.png p2p_arch.eps p2p_arch2.png p2p_arch2.eps docs: docs-pics (cd ..; doxygen doc/doxygen.conf; cd doc) @@ -25,6 +31,9 @@ clean: rm -f wpa_supplicant.eps wpa_supplicant.png rm -f _wpa_supplicant.png rm -f hostapd.eps hostapd.png + rm -f p2p_sm.eps p2p_sm.png + rm -f p2p_arch.eps p2p_arch.png + rm -f p2p_arch2.eps p2p_arch2.png rm -f doxygen.warnings rm -rf html latex rm -f wpa_supplicant-devel.pdf diff --git a/doc/p2p.doxygen b/doc/p2p.doxygen new file mode 100644 index 000000000..6b11e5625 --- /dev/null +++ b/doc/p2p.doxygen @@ -0,0 +1,498 @@ +/** +\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 + +The following driver wrapper functions are needed for P2P in addition +to the standard station/AP mode operations when the P2P module resides +in the driver or firmware: +- 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::disable_11b_rates() +- wpa_driver_ops::p2p_find() +- wpa_driver_ops::p2p_stop_find() +- wpa_driver_ops::p2p_listen() +- wpa_driver_ops::p2p_connect() +- wpa_driver_ops::p2p_reject() +- wpa_driver_ops::wps_success_cb() +- wpa_driver_ops::p2p_group_formation_failed() +- wpa_driver_ops::p2p_set_params() + +The following driver wrapper events are needed for P2P in addition to +the standard station/AP mode events when the P2P module resides in the +driver or firmware: +- wpa_event_type::EVENT_P2P_DEV_FOUND +- wpa_event_type::EVENT_P2P_GO_NEG_REQ_RX +- wpa_event_type::EVENT_P2P_GO_NEG_COMPLETED + + +\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 + +*/ diff --git a/doc/p2p_arch.dot b/doc/p2p_arch.dot new file mode 100644 index 000000000..27ae0e250 --- /dev/null +++ b/doc/p2p_arch.dot @@ -0,0 +1,85 @@ +digraph p2p_arch { + ranksep=.75; + size = "7.5,7.5"; + + edge [dir=none]; + + subgraph cluster_wpa_gui { + label = "wpa_gui"; + + status -> Qt; + scan -> Qt; + network -> Qt; + Qt -> peers; + Qt -> WPS; + Qt -> gui_ctrl; + + gui_ctrl [label="ctrl i/f"]; + } + + subgraph cluster_wpa_supplicant { + label = "wpa_supplicant" + + ctrl_iface [label="ctrl i/f"]; + authenticator [label="Authenticator"]; + supplicant [label="Supplicant"]; + driver_iface [label="driver i/f"]; + p2p_module [label="P2P\nmodule"]; + wps_registrar [label="WPS\nRegistrar"]; + wps_enrollee [label="WPS\nEnrollee"]; + mgmt_entity [label="Management\nentity"]; + + ctrl_iface -> mgmt_entity; + p2p_module -> mgmt_entity; + wps_registrar -> mgmt_entity; + wps_enrollee -> mgmt_entity; + mgmt_entity -> authenticator; + mgmt_entity -> supplicant; + mgmt_entity -> driver_iface; + + { rank = same; mgmt_entity; p2p_module; } + } + + subgraph cluster_wpa_cli { + label = "wpa_cli -a" + + wpa_cli_action; + } + + subgraph cluster_dnsmasq { + label = "dnsmasq" + + dnsmasq; + } + + subgraph cluster_dhclient { + label = "dhclient" + + dhclient; + } + + subgraph cluster_kernel { + label = "Linux kernel" + + cfg80211 -> mac80211; + netdev -> mac80211; + mac80211 -> ath9k; + } + + gui_ctrl -> ctrl_iface; + wpa_cli_action -> ctrl_iface; + + driver_iface -> cfg80211; + + wpa_cli_action -> dnsmasq; + wpa_cli_action -> dhclient; + + dnsmasq -> netdev; + dhclient -> netdev; + + edge [color=blue,dir=both]; + p2p_module -> mgmt_entity -> driver_iface -> cfg80211 -> mac80211 -> ath9k; + + edge [color=green,dir=both]; + peers -> Qt -> gui_ctrl -> ctrl_iface -> mgmt_entity -> p2p_module; +} diff --git a/doc/p2p_arch2.dot b/doc/p2p_arch2.dot new file mode 100644 index 000000000..9c7b4b57a --- /dev/null +++ b/doc/p2p_arch2.dot @@ -0,0 +1,85 @@ +digraph p2p_arch2 { + ranksep=.75; + size = "7.5,7.5"; + + edge [dir=none]; + + subgraph cluster_wpa_gui { + label = "wpa_gui"; + + status -> Qt; + scan -> Qt; + network -> Qt; + Qt -> peers; + Qt -> WPS; + Qt -> gui_ctrl; + + gui_ctrl [label="ctrl i/f"]; + } + + subgraph cluster_wpa_supplicant { + label = "wpa_supplicant" + + ctrl_iface [label="ctrl i/f"]; + authenticator [label="Authenticator"]; + supplicant [label="Supplicant"]; + driver_iface [label="driver i/f"]; + wps_registrar [label="WPS\nRegistrar"]; + wps_enrollee [label="WPS\nEnrollee"]; + mgmt_entity [label="Management\nentity"]; + + ctrl_iface -> mgmt_entity; + wps_registrar -> mgmt_entity; + wps_enrollee -> mgmt_entity; + mgmt_entity -> authenticator; + mgmt_entity -> supplicant; + mgmt_entity -> driver_iface; + } + + subgraph cluster_wpa_cli { + label = "wpa_cli -a" + + wpa_cli_action; + } + + subgraph cluster_dnsmasq { + label = "dnsmasq" + + dnsmasq; + } + + subgraph cluster_dhclient { + label = "dhclient" + + dhclient; + } + + subgraph cluster_kernel { + label = "Kernel" + + ioctl -> umac; + netdev -> umac; + umac -> p2p_module; + p2p_module [label="P2P\nmodule"]; + umac -> driver; + + { rank = same; umac; p2p_module; } + } + + gui_ctrl -> ctrl_iface; + wpa_cli_action -> ctrl_iface; + + driver_iface -> ioctl; + + wpa_cli_action -> dnsmasq; + wpa_cli_action -> dhclient; + + dnsmasq -> netdev; + dhclient -> netdev; + + edge [color=blue,dir=both]; + p2p_module -> umac -> driver; + + edge [color=green,dir=both]; + peers -> Qt -> gui_ctrl -> ctrl_iface -> mgmt_entity -> driver_iface -> ioctl -> umac -> p2p_module; +} diff --git a/doc/p2p_sm.dot b/doc/p2p_sm.dot new file mode 100644 index 000000000..640caefcc --- /dev/null +++ b/doc/p2p_sm.dot @@ -0,0 +1,62 @@ +digraph p2p { + ranksep=.75; + size = "8.5,7.5"; + + start -> IDLE; + start [label="Init",shape=none]; + + /* Discovery: Scan followed by Find(SEARCH,LISTEN) */ + subgraph cluster_0 { + label="Discovery"; + color=lightgrey; + node [color=blue]; + /* SCAN and LISTEN currently not used in the implementation */ + SCAN [style=dotted]; + LISTEN [style=dotted]; + + SCAN -> LISTEN; + LISTEN -> SEARCH -> LISTEN [style=dotted]; + SEARCH -> SD_DURING_FIND [label="Peer SD capab\nand no info", weight=100]; + SD_DURING_FIND -> SEARCH [label="RX SD Resp\nor timeout", weight=100]; + SEARCH -> PROV_DISC_DURING_FIND [label="Prov Disc cmd\nand no Resp", weight=100]; + PROV_DISC_DURING_FIND -> SEARCH [label="RX Prov Disc Resp\nor timeout", weight=100]; + } + + /* Group Formation */ + subgraph cluster_1 { + label="Group Formation"; + color=lightgrey; + node [color=green]; + + CONNECT -> CONNECT_LISTEN [style=dotted,weight=100]; + CONNECT_LISTEN -> CONNECT [style=dotted,weight=100]; + CONNECT -> WAIT_PEER_IDLE [label="RX GO Neg Resp\n(info unavail)"]; + WAIT_PEER_IDLE -> WAIT_PEER_CONNECT [style=dotted,weight=100]; + WAIT_PEER_CONNECT -> WAIT_PEER_IDLE [style=dotted,weight=100]; + + CONNECT -> GO_NEG [label="RX GO Neg Resp\n(success)", weight=10]; + CONNECT_LISTEN -> GO_NEG [label="RX GO Neg Req or\nTX GO Neg Resp"]; + WAIT_PEER_CONNECT -> GO_NEG [label="RX GO Neg Req"]; + GO_NEG -> PROVISIONING [label="TX/RX GO Neg Conf"]; + } + + PROVISIONING -> IDLE [label="WPS\nsuccess"]; + + /* External triggers */ + IDLE -> SCAN [label="Find cmd",weight=20]; + IDLE -> CONNECT [label="Connect cmd",weight=20]; + IDLE -> LISTEN_ONLY [label="Listen cmd"]; + + /* Timeouts */ +/* + edge [color=red]; + WAIT_PEER_IDLE -> IDLE [label="timeout", weight=0]; + WAIT_PEER_CONNECT -> IDLE [label="timeout", weight=0]; + CONNECT -> IDLE [label="timeout", weight=0]; + CONNECT_LISTEN -> IDLE [label="timeout", weight=0]; + GO_NEG -> IDLE [label="timeout", weight=0]; + PROVISIONING -> IDLE [label="timeout", weight=0]; + LISTEN_ONLY -> IDLE [label="timeout", weight=0]; + SEARCH -> IDLE [label="timeout", weight=0]; +*/ +}