Просмотр исходного кода

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
mukul sharma 9 лет назад
Родитель
Сommit
e9a034ded2

+ 1 - 0
core/mac/inc/ani_global.h

@@ -1021,6 +1021,7 @@ typedef struct sAniSirGlobal {
 	void *readyToSuspendContext;
 	void *readyToSuspendContext;
 	uint8_t lteCoexAntShare;
 	uint8_t lteCoexAntShare;
 	uint8_t beacon_offload;
 	uint8_t beacon_offload;
+	bool pmf_offload;
 	uint32_t fEnableDebugLog;
 	uint32_t fEnableDebugLog;
 	uint16_t mgmtSeqNum;
 	uint16_t mgmtSeqNum;
 	bool enable5gEBT;
 	bool enable5gEBT;

+ 8 - 0
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)
 	if (pHdr->fc.wep == 0)
 		return;
 		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
 	/*Extract 11w trsansId from SA query request action frame
 	   In SA query response action frame we will send same transId
 	   In SA query response action frame we will send same transId
 	   In SA query request action frame:
 	   In SA query request action frame:

+ 12 - 0
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,
 			       (pMac, LOGE,
 			       FL("received an unprotected deauth from AP"));
 			       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 */
 		/* If the frame received is unprotected, forward it to the supplicant to initiate */
 		/* an SA query */
 		/* an SA query */
 		frameLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
 		frameLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);

+ 12 - 0
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,
 			       (pMac, LOGE,
 			       FL("received an unprotected disassoc from AP"));
 			       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 */
 		/* If the frame received is unprotected, forward it to the supplicant to initiate */
 		/* an SA query */
 		/* an SA query */
 		frameLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
 		frameLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);

+ 3 - 0
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->lteCoexAntShare = cfg->lte_coex_ant_share;
 	mac_ctx->beacon_offload = cfg->beacon_offload;
 	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;
 	return;
 }
 }

+ 5 - 0
core/wma/inc/wma_internal.h

@@ -44,6 +44,9 @@
 				WMI_SCAN_EVENT_DEQUEUED)
 				WMI_SCAN_EVENT_DEQUEUED)
 /* default value */
 /* default value */
 #define DEFAULT_INFRA_STA_KEEP_ALIVE_PERIOD  20
 #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*/
 /* pdev vdev and peer stats*/
 #define FW_PDEV_STATS_SET 0x1
 #define FW_PDEV_STATS_SET 0x1
 #define FW_VDEV_STATS_SET 0x2
 #define FW_VDEV_STATS_SET 0x2
@@ -569,6 +572,8 @@ int wma_unified_bcntx_status_event_handler(void *handle,
 					   uint8_t *cmd_param_info,
 					   uint8_t *cmd_param_info,
 					   uint32_t len);
 					   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,
 void wma_set_sta_keep_alive(tp_wma_handle wma, uint8_t vdev_id,
 				   uint32_t method, uint32_t timeperiod,
 				   uint32_t method, uint32_t timeperiod,

+ 1 - 0
core/wma/inc/wma_tgt_cfg.h

@@ -56,6 +56,7 @@ struct wma_tgt_services {
 	bool pno_offload;
 	bool pno_offload;
 #endif /* FEATURE_WLAN_SCAN_PNO */
 #endif /* FEATURE_WLAN_SCAN_PNO */
 	bool beacon_offload;
 	bool beacon_offload;
+	bool pmf_offload;
 	uint32_t lte_coex_ant_share;
 	uint32_t lte_coex_ant_share;
 #ifdef FEATURE_WLAN_TDLS
 #ifdef FEATURE_WLAN_TDLS
 	bool en_tdls;
 	bool en_tdls;

+ 7 - 0
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,
 				       self_sta_req->session_id,
 				       SIR_KEEP_ALIVE_NULL_PKT,
 				       SIR_KEEP_ALIVE_NULL_PKT,
 				       cfg_val, NULL, NULL, NULL);
 				       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;
 		break;
 	}
 	}
 
 

+ 4 - 0
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
 	if (WMI_SERVICE_IS_ENABLED
 		    (wh->wmi_service_bitmap, WMI_SERVICE_BEACON_OFFLOAD))
 		    (wh->wmi_service_bitmap, WMI_SERVICE_BEACON_OFFLOAD))
 		cfg->beacon_offload = true;
 		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
 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
 	/* Enable Roam Offload */
 	/* Enable Roam Offload */
 	cfg->en_roam_offload = WMI_SERVICE_IS_ENABLED(wh->wmi_service_bitmap,
 	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;
 	struct wma_tgt_cfg tgt_cfg;
 	void *hdd_ctx = cds_get_context(CDF_MODULE_ID_HDD);
 	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.reg_domain = wma_handle->reg_cap.eeprom_rd;
 	tgt_cfg.eeprom_rd_ext = wma_handle->reg_cap.eeprom_rd_ext;
 	tgt_cfg.eeprom_rd_ext = wma_handle->reg_cap.eeprom_rd_ext;
 
 

+ 120 - 25
core/wma/src/wma_mgmt.c

@@ -419,6 +419,8 @@ int wma_peer_sta_kickout_event_handler(void *handle, u8 *event, u32 len)
 		break;
 		break;
 
 
 	case WMI_PEER_STA_KICKOUT_REASON_INACTIVITY:
 	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:
 	default:
 		break;
 		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);
 		 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_set_sta_keep_alive() - set sta keep alive parameters
  * @wma: wma handle
  * @wma: wma handle
@@ -2914,6 +2979,56 @@ wma_is_ccmp_pn_replay_attack(void *cds_ctx, struct ieee80211_frame *wh,
 	return false;
 	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_process_rmf_frame() - process rmf frame
  * @wma_handle: wma handle
  * @wma_handle: wma handle
@@ -2931,8 +3046,7 @@ int wma_process_rmf_frame(tp_wma_handle wma_handle,
 	cds_pkt_t *rx_pkt,
 	cds_pkt_t *rx_pkt,
 	cdf_nbuf_t wbuf)
 	cdf_nbuf_t wbuf)
 {
 {
-	uint8_t *efrm, *orig_hdr;
-	uint16_t key_id;
+	uint8_t *orig_hdr;
 	uint8_t *ccmp;
 	uint8_t *ccmp;
 
 
 	if ((wh)->i_fc[1] & IEEE80211_FC1_WEP) {
 	if ((wh)->i_fc[1] & IEEE80211_FC1_WEP) {
@@ -2979,29 +3093,10 @@ int wma_process_rmf_frame(tp_wma_handle wma_handle,
 	} else {
 	} else {
 		if (IEEE80211_IS_BROADCAST(wh->i_addr1) ||
 		if (IEEE80211_IS_BROADCAST(wh->i_addr1) ||
 		    IEEE80211_IS_MULTICAST(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 {
 		} else {
 			WMA_LOGE("Rx unprotected unicast mgmt frame");
 			WMA_LOGE("Rx unprotected unicast mgmt frame");
 			rx_pkt->pkt_meta.dpuFeedback =
 			rx_pkt->pkt_meta.dpuFeedback =