From e9a034ded21e83c622f0df9f39cb3f79b092d248 Mon Sep 17 00:00:00 2001 From: mukul sharma Date: Fri, 4 Sep 2015 17:02:01 +0530 Subject: [PATCH] qcacld-3.0: Add support for 11w offload feature This change Adds 11w offload feature, This change includes: 1. SA Query time out Kickout reason handling 2. Add a new service bit map for 11w offload and cache it to pMAc 3. Error logging in following unexpected case a) Unprotected deauth / diasssoc from peer AP, b) reception of SA query action frame in SAP / STA vde mode 4. Configure sta sa query related parameters as a part of sta vdev attach 5. Trim mmie for pmf bcast/mcast mgmt frames Change-Id: If119e9a79185552e163834f7c6c3a14288fe2761 CRs-Fixed: 931630 --- core/mac/inc/ani_global.h | 1 + .../mac/src/pe/lim/lim_process_action_frame.c | 8 + .../mac/src/pe/lim/lim_process_deauth_frame.c | 12 ++ .../src/pe/lim/lim_process_disassoc_frame.c | 12 ++ core/sme/src/common/sme_api.c | 3 + core/wma/inc/wma_internal.h | 5 + core/wma/inc/wma_tgt_cfg.h | 1 + core/wma/src/wma_dev_if.c | 7 + core/wma/src/wma_main.c | 4 + core/wma/src/wma_mgmt.c | 145 +++++++++++++++--- 10 files changed, 173 insertions(+), 25 deletions(-) diff --git a/core/mac/inc/ani_global.h b/core/mac/inc/ani_global.h index e4e7bbdefcdc..1c98232e7e81 100644 --- a/core/mac/inc/ani_global.h +++ b/core/mac/inc/ani_global.h @@ -1021,6 +1021,7 @@ typedef struct sAniSirGlobal { void *readyToSuspendContext; uint8_t lteCoexAntShare; uint8_t beacon_offload; + bool pmf_offload; uint32_t fEnableDebugLog; uint16_t mgmtSeqNum; bool enable5gEBT; diff --git a/core/mac/src/pe/lim/lim_process_action_frame.c b/core/mac/src/pe/lim/lim_process_action_frame.c index 15d039276b4d..a7b1b88a5d64 100644 --- a/core/mac/src/pe/lim/lim_process_action_frame.c +++ b/core/mac/src/pe/lim/lim_process_action_frame.c @@ -1534,6 +1534,14 @@ static void __lim_process_sa_query_request_action_frame(tpAniSirGlobal pMac, if (pHdr->fc.wep == 0) return; + /* 11w offload is enabled then firmware should not fwd this frame */ + if (pMac->pmf_offload) { + lim_log(pMac, LOGE, + FL("11w offload is enabled, SA Query request is not expected ") + ); + return; + } + /*Extract 11w trsansId from SA query request action frame In SA query response action frame we will send same transId In SA query request action frame: diff --git a/core/mac/src/pe/lim/lim_process_deauth_frame.c b/core/mac/src/pe/lim/lim_process_deauth_frame.c index e64058d28342..2cca55d9f6bd 100644 --- a/core/mac/src/pe/lim/lim_process_deauth_frame.c +++ b/core/mac/src/pe/lim/lim_process_deauth_frame.c @@ -138,6 +138,18 @@ lim_process_deauth_frame(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo, (pMac, LOGE, FL("received an unprotected deauth from AP")); ) + + /* + * When 11w offload is enabled then + * firmware should not fwd this frame + */ + if (LIM_IS_STA_ROLE(psessionEntry) && pMac->pmf_offload) { + lim_log(pMac, LOGE, + FL("11w offload is enable,unprotected deauth is not expected") + ); + return; + } + /* If the frame received is unprotected, forward it to the supplicant to initiate */ /* an SA query */ frameLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); diff --git a/core/mac/src/pe/lim/lim_process_disassoc_frame.c b/core/mac/src/pe/lim/lim_process_disassoc_frame.c index 33a1c089d232..70a9a8d86c72 100644 --- a/core/mac/src/pe/lim/lim_process_disassoc_frame.c +++ b/core/mac/src/pe/lim/lim_process_disassoc_frame.c @@ -134,6 +134,18 @@ lim_process_disassoc_frame(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo, (pMac, LOGE, FL("received an unprotected disassoc from AP")); ) + + /* + * When 11w offload is enabled then + * firmware should not fwd this frame + */ + if (LIM_IS_STA_ROLE(psessionEntry) && pMac->pmf_offload) { + lim_log(pMac, LOGE, + FL("11w offload is enable,unprotected disassoc is not expected") + ); + return; + } + /* If the frame received is unprotected, forward it to the supplicant to initiate */ /* an SA query */ frameLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index baf6afd3c260..4cfe7d661154 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -14870,6 +14870,9 @@ void sme_update_tgt_services(tHalHandle hal, struct wma_tgt_services *cfg) mac_ctx->lteCoexAntShare = cfg->lte_coex_ant_share; mac_ctx->beacon_offload = cfg->beacon_offload; + mac_ctx->pmf_offload = cfg->pmf_offload; + CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_INFO, + FL("mac_ctx->pmf_offload: %d"), mac_ctx->pmf_offload); return; } diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h index d927a7613984..d204979b4e0c 100644 --- a/core/wma/inc/wma_internal.h +++ b/core/wma/inc/wma_internal.h @@ -44,6 +44,9 @@ WMI_SCAN_EVENT_DEQUEUED) /* default value */ #define DEFAULT_INFRA_STA_KEEP_ALIVE_PERIOD 20 +#define DEFAULT_STA_SA_QUERY_MAX_RETRIES_COUNT (5) +#define DEFAULT_STA_SA_QUERY_RETRY_INTERVAL (200) + /* pdev vdev and peer stats*/ #define FW_PDEV_STATS_SET 0x1 #define FW_VDEV_STATS_SET 0x2 @@ -569,6 +572,8 @@ int wma_unified_bcntx_status_event_handler(void *handle, uint8_t *cmd_param_info, uint32_t len); +void wma_set_sta_sa_query_param(tp_wma_handle wma, + uint8_t vdev_id); void wma_set_sta_keep_alive(tp_wma_handle wma, uint8_t vdev_id, uint32_t method, uint32_t timeperiod, diff --git a/core/wma/inc/wma_tgt_cfg.h b/core/wma/inc/wma_tgt_cfg.h index eab91f69a892..5efa9545d822 100644 --- a/core/wma/inc/wma_tgt_cfg.h +++ b/core/wma/inc/wma_tgt_cfg.h @@ -56,6 +56,7 @@ struct wma_tgt_services { bool pno_offload; #endif /* FEATURE_WLAN_SCAN_PNO */ bool beacon_offload; + bool pmf_offload; uint32_t lte_coex_ant_share; #ifdef FEATURE_WLAN_TDLS bool en_tdls; diff --git a/core/wma/src/wma_dev_if.c b/core/wma/src/wma_dev_if.c index e847cced08cb..b15eb9a32560 100644 --- a/core/wma/src/wma_dev_if.c +++ b/core/wma/src/wma_dev_if.c @@ -1762,6 +1762,13 @@ ol_txrx_vdev_handle wma_vdev_attach(tp_wma_handle wma_handle, self_sta_req->session_id, SIR_KEEP_ALIVE_NULL_PKT, cfg_val, NULL, NULL, NULL); + + /* offload STA SA query related params to fwr */ + if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap, + WMI_SERVICE_STA_PMF_OFFLOAD)) { + wma_set_sta_sa_query_param(wma_handle, + self_sta_req->session_id); + } break; } diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 9f4c36117018..319e076a975f 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -3258,6 +3258,9 @@ static inline void wma_update_target_services(tp_wma_handle wh, if (WMI_SERVICE_IS_ENABLED (wh->wmi_service_bitmap, WMI_SERVICE_BEACON_OFFLOAD)) cfg->beacon_offload = true; + if (WMI_SERVICE_IS_ENABLED + (wh->wmi_service_bitmap, WMI_SERVICE_STA_PMF_OFFLOAD)) + cfg->pmf_offload = true; #ifdef WLAN_FEATURE_ROAM_OFFLOAD /* Enable Roam Offload */ cfg->en_roam_offload = WMI_SERVICE_IS_ENABLED(wh->wmi_service_bitmap, @@ -3385,6 +3388,7 @@ static void wma_update_hdd_cfg(tp_wma_handle wma_handle) struct wma_tgt_cfg tgt_cfg; void *hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD); + cdf_mem_zero(&tgt_cfg, sizeof(struct wma_tgt_cfg)); tgt_cfg.reg_domain = wma_handle->reg_cap.eeprom_rd; tgt_cfg.eeprom_rd_ext = wma_handle->reg_cap.eeprom_rd_ext; diff --git a/core/wma/src/wma_mgmt.c b/core/wma/src/wma_mgmt.c index b85b51a9faef..89a9e728cb55 100644 --- a/core/wma/src/wma_mgmt.c +++ b/core/wma/src/wma_mgmt.c @@ -419,6 +419,8 @@ int wma_peer_sta_kickout_event_handler(void *handle, u8 *event, u32 len) break; case WMI_PEER_STA_KICKOUT_REASON_INACTIVITY: + /* Handle SA query kickout is same as inactivity kickout */ + case WMI_PEER_STA_KICKOUT_REASON_SA_QUERY_TIMEOUT: default: break; } @@ -594,6 +596,69 @@ void wma_set_sap_keepalive(tp_wma_handle wma, uint8_t vdev_id) min_inactive_time, max_inactive_time, max_unresponsive_time); } +/** + * wma_set_sta_sa_query_param() - set sta sa query parameters + * @wma: wma handle + * @vdev_id: vdev id + + * This function sets sta query related parameters in fw. + * + * Return: none + */ + +void wma_set_sta_sa_query_param(tp_wma_handle wma, + uint8_t vdev_id) +{ + struct sAniSirGlobal *mac = cds_get_context(CDF_MODULE_ID_PE); + uint32_t max_retries, retry_interval; + wmi_buf_t buf; + WMI_PMF_OFFLOAD_SET_SA_QUERY_CMD_fixed_param *cmd; + int len; + + WMA_LOGD(FL("Enter:")); + len = sizeof(*cmd); + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE(FL("wmi_buf_alloc failed")); + return; + } + + cmd = (WMI_PMF_OFFLOAD_SET_SA_QUERY_CMD_fixed_param *)wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_WMI_PMF_OFFLOAD_SET_SA_QUERY_CMD_fixed_param, + WMITLV_GET_STRUCT_TLVLEN + (WMI_PMF_OFFLOAD_SET_SA_QUERY_CMD_fixed_param)); + + if (wlan_cfg_get_int + (mac, WNI_CFG_PMF_SA_QUERY_MAX_RETRIES, + &max_retries) != eSIR_SUCCESS) { + max_retries = DEFAULT_STA_SA_QUERY_MAX_RETRIES_COUNT; + WMA_LOGE(FL("Failed to get value for WNI_CFG_PMF_SA_QUERY_MAX_RETRIES")); + } + if (wlan_cfg_get_int + (mac, WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL, + &retry_interval) != eSIR_SUCCESS) { + retry_interval = DEFAULT_STA_SA_QUERY_RETRY_INTERVAL; + WMA_LOGE(FL("Failed to get value for WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL")); + } + + cmd->vdev_id = vdev_id; + cmd->sa_query_max_retry_count = max_retries; + cmd->sa_query_retry_interval = retry_interval; + + WMA_LOGD(FL("STA sa query: vdev_id:%d interval:%u retry count:%d"), + vdev_id, retry_interval, max_retries); + + if (wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_PMF_OFFLOAD_SET_SA_QUERY_CMDID)) { + WMA_LOGE(FL("Failed to offload STA SA Query")); + cdf_nbuf_free(buf); + } + + WMA_LOGD(FL("Exit :")); + return; +} + /** * wma_set_sta_keep_alive() - set sta keep alive parameters * @wma: wma handle @@ -2914,6 +2979,56 @@ wma_is_ccmp_pn_replay_attack(void *cds_ctx, struct ieee80211_frame *wh, return false; } +/** + * wma_process_bip() - process mmie in rmf frame + * @wma_handle: wma handle + * @iface: txrx node + * @wh: 80211 frame + * @wbuf: Buffer + * + * Return: 0 for success or error code + */ + +static +int wma_process_bip(tp_wma_handle wma_handle, + struct wma_txrx_node *iface, + struct ieee80211_frame *wh, + cdf_nbuf_t wbuf +) +{ + uint16_t key_id; + uint8_t *efrm; + + efrm = cdf_nbuf_data(wbuf) + cdf_nbuf_len(wbuf); + key_id = (uint16_t)*(efrm - cds_get_mmie_size() + 2); + + if (!((key_id == WMA_IGTK_KEY_INDEX_4) + || (key_id == WMA_IGTK_KEY_INDEX_5))) { + WMA_LOGE(FL("Invalid KeyID(%d) dropping the frame"), key_id); + return -EINVAL; + } + if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap, + WMI_SERVICE_STA_PMF_OFFLOAD)) { + /* + * if 11w offload is enabled then mmie validation is performed + * in firmware, host just need to trim the mmie. + */ + cdf_nbuf_trim_tail(wbuf, cds_get_mmie_size()); + } else { + if (cds_is_mmie_valid(iface->key.key, + iface->key.key_id[key_id - WMA_IGTK_KEY_INDEX_4].ipn, + (uint8_t *) wh, efrm)) { + WMA_LOGE(FL("Protected BC/MC frame MMIE validation successful")); + /* Remove MMIE */ + cdf_nbuf_trim_tail(wbuf, cds_get_mmie_size()); + } else { + WMA_LOGE(FL("BC/MC MIC error or MMIE not present, dropping the frame")); + return -EINVAL; + } + } + return 0; +} + /** * wma_process_rmf_frame() - process rmf frame * @wma_handle: wma handle @@ -2931,8 +3046,7 @@ int wma_process_rmf_frame(tp_wma_handle wma_handle, cds_pkt_t *rx_pkt, cdf_nbuf_t wbuf) { - uint8_t *efrm, *orig_hdr; - uint16_t key_id; + uint8_t *orig_hdr; uint8_t *ccmp; if ((wh)->i_fc[1] & IEEE80211_FC1_WEP) { @@ -2979,29 +3093,10 @@ int wma_process_rmf_frame(tp_wma_handle wma_handle, } else { if (IEEE80211_IS_BROADCAST(wh->i_addr1) || IEEE80211_IS_MULTICAST(wh->i_addr1)) { - efrm = cdf_nbuf_data(wbuf) + - cdf_nbuf_len(wbuf); - - key_id = (uint16_t)*(efrm - cds_get_mmie_size() + 2); - if (!((key_id == WMA_IGTK_KEY_INDEX_4) - || (key_id == WMA_IGTK_KEY_INDEX_5))) { - WMA_LOGE("Invalid KeyID(%d) dropping the frame", key_id); - cds_pkt_return_packet(rx_pkt); - return -EINVAL; - } - - if (cds_is_mmie_valid(iface->key.key, - iface->key.key_id[key_id - WMA_IGTK_KEY_INDEX_4].ipn, - (uint8_t *) wh, efrm)) { - WMA_LOGE("Protected BC/MC frame MMIE validation successful"); - /* Remove MMIE */ - cdf_nbuf_trim_tail(wbuf, - cds_get_mmie_size()); - } else { - WMA_LOGE("BC/MC MIC error or MMIE not present, dropping the frame"); - cds_pkt_return_packet(rx_pkt); - return -EINVAL; - } + if (0 != wma_process_bip(wma_handle, iface, wh, wbuf)) { + cds_pkt_return_packet(rx_pkt); + return -EINVAL; + } } else { WMA_LOGE("Rx unprotected unicast mgmt frame"); rx_pkt->pkt_meta.dpuFeedback =