diff options
| author | Yun Park <yunp@codeaurora.org> | 2018-05-29 17:03:31 -0700 |
|---|---|---|
| committer | nshrivas <nshrivas@codeaurora.org> | 2018-06-01 19:54:34 -0700 |
| commit | 9282f6487e28792e0cfbf78eb29c4db0b39136ed (patch) | |
| tree | 8b3a38fb9ed2e62506854e7c27bb918fe1ae7a7a | |
| parent | b03fcef355297c58ef7df489204e2c9926cb4c20 (diff) | |
qcacld-3.0: Indications of DHCP START/STOP indication SAP/P2P GO
The Data Path in the WLAN host driver needs to be sending DHCP START/
STOP indications to FW during DHCP based IP address acquisition phase
in the SAP mode.
For this, DP needs to be inspecting the Tx/Rx frame, and sending the
notification to the FW through WMI message.
Change-Id: Iad6308980a7158516f341b97f3baffab1e4c4bc3
CRs-Fixed: 2114816
| -rw-r--r-- | core/hdd/inc/wlan_hdd_main.h | 29 | ||||
| -rw-r--r-- | core/hdd/inc/wlan_hdd_softap_tx_rx.h | 25 | ||||
| -rw-r--r-- | core/hdd/src/wlan_hdd_hostapd.c | 12 | ||||
| -rw-r--r-- | core/hdd/src/wlan_hdd_ipa.c | 11 | ||||
| -rw-r--r-- | core/hdd/src/wlan_hdd_softap_tx_rx.c | 113 | ||||
| -rw-r--r-- | core/wma/inc/wma_api.h | 11 | ||||
| -rw-r--r-- | core/wma/src/wma_features.c | 41 |
7 files changed, 241 insertions, 1 deletions
diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 22ad6fd0a490..fada4546d886 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -973,6 +973,33 @@ enum bss_stop_reason { }; /** + * struct dhcp_phase - Per Peer DHCP Phases + * @DHCP_PHASE_ACK: upon receiving DHCP_ACK/NAK message in REQUEST phase or + * DHCP_DELINE message in OFFER phase + * @DHCP_PHASE_DISCOVER: upon receiving DHCP_DISCOVER message in ACK phase + * @DHCP_PHASE_OFFER: upon receiving DHCP_OFFER message in DISCOVER phase + * @DHCP_PHASE_REQUEST: upon receiving DHCP_REQUEST message in OFFER phase or + * ACK phase (Renewal process) + */ +enum dhcp_phase { + DHCP_PHASE_ACK, + DHCP_PHASE_DISCOVER, + DHCP_PHASE_OFFER, + DHCP_PHASE_REQUEST +}; + +/** + * struct dhcp_nego_status - Per Peer DHCP Negotiation Status + * @DHCP_NEGO_STOP: when the peer is in ACK phase or client disassociated + * @DHCP_NEGO_IN_PROGRESS: when the peer is in DISCOVER or REQUEST + * (Renewal process) phase + */ +enum dhcp_nego_status { + DHCP_NEGO_STOP, + DHCP_NEGO_IN_PROGRESS +}; + +/** * typedef struct hdd_station_info_t - Per station structure kept in HDD for * multiple station support for SoftAP * @isUsed: The station entry is used or not @@ -1053,6 +1080,8 @@ typedef struct { struct ieee80211_vht_cap vht_caps; uint32_t reason_code; int8_t rssi; + enum dhcp_phase dhcp_phase; + enum dhcp_nego_status dhcp_nego_status; } hdd_station_info_t; /** diff --git a/core/hdd/inc/wlan_hdd_softap_tx_rx.h b/core/hdd/inc/wlan_hdd_softap_tx_rx.h index 73e2cab90f59..66a8e323d11e 100644 --- a/core/hdd/inc/wlan_hdd_softap_tx_rx.h +++ b/core/hdd/inc/wlan_hdd_softap_tx_rx.h @@ -80,4 +80,29 @@ void hdd_softap_tx_resume_cb(void *adapter_context, bool tx_resume) } #endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */ +/** + * hdd_post_dhcp_ind() - Send DHCP START/STOP indication to FW + * @adapter: pointer to hdd adapter + * @sta_id: peer station ID + * @type: WMA message type + * + * Return: None + */ +QDF_STATUS hdd_post_dhcp_ind(hdd_adapter_t *adapter, + uint8_t sta_id, uint16_t type); + +/** + * hdd_dhcp_indication() - Send DHCP START/STOP indication to FW + * @adapter: pointer to hdd adapter + * @sta_id: peer station ID + * @skb: pointer to OS packet (sk_buff) + * @dir: direction + * + * Return: None + */ +void hdd_dhcp_indication(hdd_adapter_t *adapter, + uint8_t sta_id, + struct sk_buff *skb, + enum qdf_proto_dir dir); + #endif /* end #if !defined(WLAN_HDD_SOFTAP_TX_RX_H) */ diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index b8367e5237cf..049ab1f39a4a 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -1482,6 +1482,10 @@ static void hdd_fill_station_info(hdd_adapter_t *pHostapdAdapter, hdd_copy_ht_caps(&stainfo->ht_caps, &event->ht_caps); } + /* Initialize DHCP info */ + stainfo->dhcp_phase = DHCP_PHASE_ACK; + stainfo->dhcp_nego_status = DHCP_NEGO_STOP; + while (i < WLAN_MAX_STA_COUNT) { if (!qdf_mem_cmp(pHostapdAdapter-> cache_sta_info[i].macAddrSTA.bytes, @@ -2241,6 +2245,14 @@ QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent, pHostapdAdapter->sessionId, QDF_PROTO_TYPE_MGMT, QDF_PROTO_MGMT_DISASSOC)); + /* Send DHCP STOP indication to FW */ + stainfo->dhcp_phase = DHCP_PHASE_ACK; + if ((stainfo->dhcp_nego_status == + DHCP_NEGO_IN_PROGRESS)) + hdd_post_dhcp_ind(pHostapdAdapter, staId, + WMA_DHCP_STOP_IND); + stainfo->dhcp_nego_status = DHCP_NEGO_STOP; + hdd_softap_deregister_sta(pHostapdAdapter, staId); pHddApCtx->bApActive = false; diff --git a/core/hdd/src/wlan_hdd_ipa.c b/core/hdd/src/wlan_hdd_ipa.c index 3101624eb47e..e805c4875c58 100644 --- a/core/hdd/src/wlan_hdd_ipa.c +++ b/core/hdd/src/wlan_hdd_ipa.c @@ -5488,6 +5488,8 @@ static void hdd_ipa_send_skb_to_network(qdf_nbuf_t skb, struct hdd_ipa_priv *hdd_ipa = ghdd_ipa; unsigned int cpu_index; uint32_t enabled; + struct qdf_mac_addr src_mac; + uint8_t staid; if (hdd_validate_adapter(adapter)) { HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "Invalid adapter: 0x%pK", @@ -5511,6 +5513,15 @@ static void hdd_ipa_send_skb_to_network(qdf_nbuf_t skb, if (!enabled) hdd_ipa_set_wake_up_idle(true); + if (adapter->device_mode == QDF_SAP_MODE) { + /* Send DHCP Indication to FW */ + qdf_mem_copy(&src_mac, skb->data + QDF_NBUF_SRC_MAC_OFFSET, + sizeof(src_mac)); + if (QDF_STATUS_SUCCESS == + hdd_softap_get_sta_id(adapter, &src_mac, &staid)) + hdd_dhcp_indication(adapter, staid, skb, QDF_RX); + } + skb->destructor = hdd_ipa_uc_rt_debug_destructor; skb->dev = adapter->dev; skb->protocol = eth_type_trans(skb, skb->dev); diff --git a/core/hdd/src/wlan_hdd_softap_tx_rx.c b/core/hdd/src/wlan_hdd_softap_tx_rx.c index af9affcda87c..69cfb7d565b5 100644 --- a/core/hdd/src/wlan_hdd_softap_tx_rx.c +++ b/core/hdd/src/wlan_hdd_softap_tx_rx.c @@ -34,6 +34,7 @@ #include <cds_utils.h> #include <wlan_hdd_regulatory.h> #include <wlan_hdd_ipa.h> +#include "wma_types.h" /* Preprocessor definitions and constants */ #undef QCA_HDD_SAP_DUMP_SK_BUFF @@ -254,6 +255,112 @@ static inline struct sk_buff *hdd_skb_orphan(hdd_adapter_t *pAdapter, #endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */ /** + * hdd_post_dhcp_ind() - Send DHCP START/STOP indication to FW + * @adapter: pointer to hdd adapter + * @sta_id: peer station ID + * @type: WMA message type + * + * Return: None + */ +QDF_STATUS hdd_post_dhcp_ind(hdd_adapter_t *adapter, + uint8_t sta_id, uint16_t type) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + + hdd_debug("Post DHCP indication,sta_id=%d, type=%d", sta_id, type); + + if (!adapter) { + hdd_err("NULL adapter"); + return QDF_STATUS_E_FAILURE; + } + + status = wma_send_dhcp_ind(type, + adapter->device_mode, + adapter->macAddressCurrent.bytes, + adapter->aStaInfo[sta_id].macAddrSTA.bytes); + if (!QDF_IS_STATUS_SUCCESS(status)) + QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR, + "%s: Post DHCP Ind MSG fail", __func__); + + return status; +} + +/** + * hdd_dhcp_indication() - Send DHCP START/STOP indication to FW + * @adapter: pointer to hdd adapter + * @sta_id: peer station ID + * @skb: pointer to OS packet (sk_buff) + * @dir: direction + * + * Return: None + */ +void hdd_dhcp_indication(hdd_adapter_t *adapter, + uint8_t sta_id, + struct sk_buff *skb, + enum qdf_proto_dir dir) +{ + enum qdf_proto_subtype subtype = QDF_PROTO_INVALID; + hdd_station_info_t *hdd_sta_info; + + hdd_debug("adapter=%p, sta_id=%d, dir=%d", adapter, sta_id, dir); + + if ((adapter->device_mode == QDF_SAP_MODE) && + ((dir == QDF_TX && QDF_NBUF_CB_PACKET_TYPE_DHCP == + QDF_NBUF_CB_GET_PACKET_TYPE(skb)) || + (dir == QDF_RX && qdf_nbuf_is_ipv4_dhcp_pkt(skb) == true))) { + + subtype = qdf_nbuf_get_dhcp_subtype(skb); + hdd_sta_info = &adapter->aStaInfo[sta_id]; + + hdd_debug("ENTER: type=%d, phase=%d, nego_status=%d", + subtype, + hdd_sta_info->dhcp_phase, + hdd_sta_info->dhcp_nego_status); + + switch (subtype) { + case QDF_PROTO_DHCP_DISCOVER: + if (dir != QDF_RX) + break; + if (hdd_sta_info->dhcp_nego_status == DHCP_NEGO_STOP) + hdd_post_dhcp_ind(adapter, sta_id, + WMA_DHCP_START_IND); + hdd_sta_info->dhcp_phase = DHCP_PHASE_DISCOVER; + hdd_sta_info->dhcp_nego_status = DHCP_NEGO_IN_PROGRESS; + break; + case QDF_PROTO_DHCP_OFFER: + hdd_sta_info->dhcp_phase = DHCP_PHASE_OFFER; + break; + case QDF_PROTO_DHCP_REQUEST: + if (dir != QDF_RX) + break; + if (hdd_sta_info->dhcp_nego_status == DHCP_NEGO_STOP) + hdd_post_dhcp_ind(adapter, sta_id, + WMA_DHCP_START_IND); + hdd_sta_info->dhcp_nego_status = DHCP_NEGO_IN_PROGRESS; + case QDF_PROTO_DHCP_DECLINE: + if (dir == QDF_RX) + hdd_sta_info->dhcp_phase = DHCP_PHASE_REQUEST; + break; + case QDF_PROTO_DHCP_ACK: + case QDF_PROTO_DHCP_NACK: + hdd_sta_info->dhcp_phase = DHCP_PHASE_ACK; + if ((hdd_sta_info->dhcp_nego_status == + DHCP_NEGO_IN_PROGRESS)) + hdd_post_dhcp_ind(adapter, sta_id, + WMA_DHCP_STOP_IND); + hdd_sta_info->dhcp_nego_status = DHCP_NEGO_STOP; + break; + default: + break; + } + + hdd_debug("EXIT: phase=%d, nego_status=%d", + hdd_sta_info->dhcp_phase, + hdd_sta_info->dhcp_nego_status); + } +} + +/** * __hdd_softap_hard_start_xmit() - Transmit a frame * @skb: pointer to OS packet (sk_buff) * @dev: pointer to network device @@ -415,6 +522,9 @@ static netdev_tx_t __hdd_softap_hard_start_xmit(struct sk_buff *skb, } pAdapter->aStaInfo[STAId].last_tx_rx_ts = qdf_system_ticks(); + if (STAId != pHddApCtx->uBCStaId) + hdd_dhcp_indication(pAdapter, STAId, skb, QDF_TX); + hdd_event_eapol_log(skb, QDF_TX); QDF_NBUF_CB_TX_PACKET_TRACK(skb) = QDF_NBUF_TX_PKT_DATA_TRACK; QDF_NBUF_UPDATE_TX_PKT_COUNT(skb, QDF_NBUF_TX_PKT_HDD); @@ -709,7 +819,6 @@ QDF_STATUS hdd_softap_rx_packet_cbk(void *context, qdf_nbuf_t rxBuf) skb->dev = pAdapter->dev; if (unlikely(skb->dev == NULL)) { - QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_ERROR, "%s: ERROR!!Invalid netdevice", __func__); return QDF_STATUS_E_FAILURE; @@ -731,6 +840,8 @@ QDF_STATUS hdd_softap_rx_packet_cbk(void *context, qdf_nbuf_t rxBuf) } } + hdd_dhcp_indication(pAdapter, staid, skb, QDF_RX); + hdd_event_eapol_log(skb, QDF_RX); qdf_dp_trace_log_pkt(pAdapter->sessionId, skb, QDF_RX); DPTRACE(qdf_dp_trace(skb, diff --git a/core/wma/inc/wma_api.h b/core/wma/inc/wma_api.h index 43d99abe1093..2de08c97638f 100644 --- a/core/wma/inc/wma_api.h +++ b/core/wma/inc/wma_api.h @@ -572,4 +572,15 @@ bool wma_dual_beacon_on_single_mac_mcc_capable(void); */ void wma_cleanup_vdev_resp_and_hold_req(void *priv); +/** + * wma_send_dhcp_ind() - Send DHCP Start/Stop Indication to FW. + * @type - WMA message type. + * @device_mode - mode(AP, SAP etc) of the device. + * @mac_addr - MAC address of the adapter. + * @sta_mac_addr - MAC address of the peer station. + * + * Return: QDF_STATUS. + */ +QDF_STATUS wma_send_dhcp_ind(uint16_t type, uint8_t device_mode, + uint8_t *mac_addr, uint8_t *sta_mac_addr); #endif diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index 043ae5ad0cbd..3c8382311546 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -11530,3 +11530,44 @@ bool wma_dual_beacon_on_single_mac_mcc_capable(void) return false; } } + +/** + * wma_send_dhcp_ind() - Send DHCP Start/Stop Indication to FW. + * @type - WMA message type. + * @device_mode - mode(AP, SAP etc) of the device. + * @mac_addr - MAC address of the adapter. + * @sta_mac_addr - MAC address of the peer station. + * + * Return: QDF_STATUS. + */ +QDF_STATUS wma_send_dhcp_ind(uint16_t type, uint8_t device_mode, + uint8_t *mac_addr, uint8_t *peer_mac_addr) +{ + QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; + tAniDHCPInd *msg; + + msg = (tAniDHCPInd *) qdf_mem_malloc(sizeof(tAniDHCPInd)); + if (NULL == msg) { + QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR, + "%s: Not able to allocate memory for dhcp ind", + __func__); + return QDF_STATUS_E_NOMEM; + } + msg->msgType = type; + msg->msgLen = (uint16_t) sizeof(tAniDHCPInd); + msg->device_mode = device_mode; + qdf_mem_copy(msg->adapterMacAddr.bytes, mac_addr, QDF_MAC_ADDR_SIZE); + qdf_mem_copy(msg->peerMacAddr.bytes, peer_mac_addr, QDF_MAC_ADDR_SIZE); + + qdf_status = wma_process_dhcp_ind(cds_get_context(QDF_MODULE_ID_WMA), + (tAniDHCPInd *)msg); + if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { + QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR, + "%s: Failed to send DHCP indication", __func__); + qdf_status = QDF_STATUS_E_FAILURE; + } + + qdf_mem_free(msg); + + return qdf_status; +} |
