summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYun Park <yunp@codeaurora.org>2018-05-29 17:03:31 -0700
committernshrivas <nshrivas@codeaurora.org>2018-06-01 19:54:34 -0700
commit9282f6487e28792e0cfbf78eb29c4db0b39136ed (patch)
tree8b3a38fb9ed2e62506854e7c27bb918fe1ae7a7a
parentb03fcef355297c58ef7df489204e2c9926cb4c20 (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.h29
-rw-r--r--core/hdd/inc/wlan_hdd_softap_tx_rx.h25
-rw-r--r--core/hdd/src/wlan_hdd_hostapd.c12
-rw-r--r--core/hdd/src/wlan_hdd_ipa.c11
-rw-r--r--core/hdd/src/wlan_hdd_softap_tx_rx.c113
-rw-r--r--core/wma/inc/wma_api.h11
-rw-r--r--core/wma/src/wma_features.c41
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;
+}