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
This commit is contained in:
mukul sharma 2015-09-04 17:02:01 +05:30 • committed by Satish Singh
commit e9a034ded2
10 changed files with 173 additions and 25 deletions

View file

@ -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;

View file

@ -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:

View file

@ -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);

View file

@ -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);

View file

@ -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;
}

View file

@ -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,

View file

@ -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;

View file

@ -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;
}

View file

@ -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;

View file

@ -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 =