Browse Source

qcacmn: Add CDP API to set key in data path

1. Add CDP API to set encryption key in datapath.
   Used to perform RX TKIP demic.
2. Fixes to RX TKIP demic function.

Change-Id: Ia14caeb71a320b4746f4303cf6611f1b6e4947ae
CRs-Fixed: 2214749
Pramod Simha 6 năm trước cách đây
mục cha
commit
6e10cb2dd6

+ 22 - 2
dp/inc/cdp_txrx_cmn.h

@@ -270,7 +270,7 @@ cdp_pdev_detach(ol_txrx_soc_handle soc, struct cdp_pdev *pdev, int force)
 
 static inline void *cdp_peer_create
 	(ol_txrx_soc_handle soc, struct cdp_vdev *vdev,
-	uint8_t *peer_mac_addr)
+	uint8_t *peer_mac_addr, void *ol_peer)
 {
 	if (!soc || !soc->ops) {
 		QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG,
@@ -284,7 +284,7 @@ static inline void *cdp_peer_create
 		return NULL;
 
 	return soc->ops->cmn_drv_ops->txrx_peer_create(vdev,
-			peer_mac_addr);
+			peer_mac_addr, ol_peer);
 }
 
 static inline void cdp_peer_setup
@@ -1237,6 +1237,26 @@ static inline int cdp_set_pn_check(ol_txrx_soc_handle soc,
 	return 0;
 }
 
+static inline int cdp_set_key(ol_txrx_soc_handle soc,
+			      struct cdp_peer *peer_handle,
+			      bool is_unicast, uint32_t *key)
+{
+	if (!soc || !soc->ops) {
+		QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG,
+			  "%s: Invalid Instance:", __func__);
+		QDF_BUG(0);
+		return 0;
+	}
+
+	if (!soc->ops->ctrl_ops ||
+	    !soc->ops->ctrl_ops->set_key)
+		return 0;
+
+	soc->ops->ctrl_ops->set_key(peer_handle,
+			is_unicast, key);
+	return 0;
+}
+
 /**
  * cdp_update_config_parameters(): function to propagate configuration
  *                                 parameters to datapath

+ 6 - 1
dp/inc/cdp_txrx_ops.h

@@ -85,7 +85,8 @@ struct cdp_cmn_ops {
 	void (*txrx_pdev_detach)(struct cdp_pdev *pdev, int force);
 
 	void *(*txrx_peer_create)
-		(struct cdp_vdev *vdev, uint8_t *peer_mac_addr);
+		(struct cdp_vdev *vdev, uint8_t *peer_mac_addr,
+		 void *ol_peer);
 
 	void (*txrx_peer_setup)
 		(struct cdp_vdev *vdev_hdl, void *peer_hdl);
@@ -520,6 +521,8 @@ struct cdp_ctrl_ops {
 		enum cdp_nac_param_cmd cmd, char *bssid, char *client_macaddr,
 		uint8_t chan_num);
 #endif
+	void (*set_key)(struct cdp_peer *peer_handle,
+			bool is_unicast, uint32_t *key);
 };
 
 struct cdp_me_ops {
@@ -742,6 +745,8 @@ struct ol_if_ops {
 
 	void (*rx_mic_error)(void *ol_soc_handle,
 			 uint16_t vdev_id, void *wh);
+	bool (*rx_frag_tkip_demic)(void *ol_peer, qdf_nbuf_t nbuf,
+				   uint16_t hdr_space);
 	uint8_t (*freq_to_channel)(void *ol_soc_handle,  uint16_t vdev_id);
 
 	void (*record_act_change)(struct wlan_objmgr_pdev *pdev,

+ 2 - 0
dp/wifi3.0/dp_internal.h

@@ -422,6 +422,8 @@ void dp_set_overload(struct cdp_pdev *pdev_handle, bool overload);
 bool dp_peer_is_inact(void *peer_handle);
 void dp_init_inact_timer(struct dp_soc *soc);
 void dp_free_inact_timer(struct dp_soc *soc);
+void dp_set_michael_key(struct cdp_peer *peer_handle,
+			bool is_unicast, uint32_t *key);
 
 /*
  * dp_get_mac_id_for_pdev() -  Return mac corresponding to pdev for mac

+ 5 - 3
dp/wifi3.0/dp_main.c

@@ -62,7 +62,7 @@ static void dp_pkt_log_con_service(struct cdp_pdev *ppdev, void *scn);
 #endif
 static void dp_pktlogmod_exit(struct dp_pdev *handle);
 static void *dp_peer_create_wifi3(struct cdp_vdev *vdev_handle,
-					uint8_t *peer_mac_addr);
+				uint8_t *peer_mac_addr, void *ol_peer);
 static void dp_peer_delete_wifi3(void *peer_handle, uint32_t bitmap);
 
 #define DP_INTR_POLL_TIMER_MS	10
@@ -3356,7 +3356,7 @@ static struct cdp_vdev *dp_vdev_attach_wifi3(struct cdp_pdev *txrx_pdev,
 
 	if (wlan_op_mode_sta == vdev->opmode)
 		dp_peer_create_wifi3((struct cdp_vdev *)vdev,
-							vdev->mac_addr.raw);
+						vdev->mac_addr.raw, NULL);
 
 	return (struct cdp_vdev *)vdev;
 
@@ -3543,7 +3543,7 @@ static inline void dp_peer_delete_ast_entries(struct dp_soc *soc,
  * Return: DP peeer handle on success, NULL on failure
  */
 static void *dp_peer_create_wifi3(struct cdp_vdev *vdev_handle,
-		uint8_t *peer_mac_addr)
+		uint8_t *peer_mac_addr, void *ol_peer)
 {
 	struct dp_peer *peer;
 	int i;
@@ -3664,6 +3664,7 @@ static void *dp_peer_create_wifi3(struct cdp_vdev *vdev_handle,
 	dp_local_peer_id_alloc(pdev, peer);
 #endif
 	DP_STATS_INIT(peer);
+	peer->ol_peer = ol_peer;
 	return (void *)peer;
 }
 
@@ -7111,6 +7112,7 @@ static struct cdp_ctrl_ops dp_ops_ctrl = {
 #ifdef ATH_SUPPORT_NAC_RSSI
 	.txrx_vdev_config_for_nac_rssi = dp_config_for_nac_rssi,
 #endif
+	.set_key = dp_set_michael_key,
 };
 
 static struct cdp_me_ops dp_ops_me = {

+ 15 - 0
dp/wifi3.0/dp_peer.c

@@ -2378,3 +2378,18 @@ void dp_peer_rxtid_stats(struct dp_peer *peer, void (*dp_stats_cmd_cb),
 	}
 }
 
+void dp_set_michael_key(struct cdp_peer *peer_handle,
+			bool is_unicast, uint32_t *key)
+{
+	struct dp_peer *peer =  (struct dp_peer *)peer_handle;
+	uint8_t sec_index = is_unicast ? 1 : 0;
+
+	if (!peer) {
+		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
+			  "peer not found ");
+		return;
+	}
+
+	qdf_mem_copy(&peer->security[sec_index].michael_key[0],
+		     key, IEEE80211_WEP_MICLEN);
+}

+ 78 - 64
dp/wifi3.0/dp_rx_defrag.c

@@ -97,12 +97,12 @@ static void dp_rx_return_head_frag_desc(struct dp_peer *peer,
 		pdev = peer->vdev->pdev;
 		soc = pdev->soc;
 		dp_rxdma_srng = &pdev->rx_refill_buf_ring;
-		rx_desc_pool = &soc->rx_desc_buf[0];
+		rx_desc_pool = &soc->rx_desc_buf[pdev->pdev_id];
 
 		dp_rx_add_to_free_desc_list(&head, &tail,
 					    peer->rx_tid[tid].head_frag_desc);
 		dp_rx_buffers_replenish(soc, 0, dp_rxdma_srng, rx_desc_pool,
-					1, &head, &tail, HAL_RX_BUF_RBM_SW3_BM);
+					1, &head, &tail);
 	}
 }
 
@@ -412,9 +412,6 @@ static QDF_STATUS dp_rx_defrag_tkip_decap(qdf_nbuf_t msdu, uint16_t hdrlen)
 		return QDF_STATUS_E_DEFRAG_ERROR;
 	}
 
-	qdf_mem_move(orig_hdr + dp_f_tkip.ic_header, orig_hdr, hdrlen);
-
-	qdf_nbuf_pull_head(msdu, dp_f_tkip.ic_header);
 	qdf_nbuf_trim_tail(msdu, dp_f_tkip.ic_trailer);
 
 	return QDF_STATUS_SUCCESS;
@@ -611,6 +608,7 @@ static QDF_STATUS dp_rx_defrag_mic(const uint8_t *key, qdf_nbuf_t wbuf,
 
 	dp_rx_defrag_michdr((struct ieee80211_frame *)(qdf_nbuf_data(wbuf)
 		+ rx_desc_len), hdr);
+
 	l = dp_rx_get_le32(key);
 	r = dp_rx_get_le32(key + 4);
 
@@ -625,8 +623,8 @@ static QDF_STATUS dp_rx_defrag_mic(const uint8_t *key, qdf_nbuf_t wbuf,
 	dp_rx_michael_block(l, r);
 
 	/* first buffer has special handling */
-	data = (uint8_t *) qdf_nbuf_data(wbuf) + rx_desc_len + off;
-	space = qdf_nbuf_len(wbuf) - rx_desc_len - off;
+	data = (uint8_t *)qdf_nbuf_data(wbuf) + off;
+	space = qdf_nbuf_len(wbuf) - off;
 
 	for (;; ) {
 		if (space > data_len)
@@ -653,8 +651,8 @@ static QDF_STATUS dp_rx_defrag_mic(const uint8_t *key, qdf_nbuf_t wbuf,
 			 * Block straddles buffers, split references.
 			 */
 			data_next =
-				(uint8_t *) qdf_nbuf_data(wbuf) + rx_desc_len;
-			if ((qdf_nbuf_len(wbuf) - rx_desc_len) <
+				(uint8_t *)qdf_nbuf_data(wbuf) + off;
+			if ((qdf_nbuf_len(wbuf)) <
 				sizeof(uint32_t) - space) {
 				return QDF_STATUS_E_DEFRAG_ERROR;
 			}
@@ -664,22 +662,19 @@ static QDF_STATUS dp_rx_defrag_mic(const uint8_t *key, qdf_nbuf_t wbuf,
 					data_next[0], data_next[1],
 					data_next[2]);
 				data = data_next + 3;
-				space = (qdf_nbuf_len(wbuf) - rx_desc_len)
-					- 3;
+				space = (qdf_nbuf_len(wbuf) - off) - 3;
 				break;
 			case 2:
 				l ^= dp_rx_get_le32_split(data[0], data[1],
 						    data_next[0], data_next[1]);
 				data = data_next + 2;
-				space = (qdf_nbuf_len(wbuf) - rx_desc_len)
-					- 2;
+				space = (qdf_nbuf_len(wbuf) - off) - 2;
 				break;
 			case 3:
 				l ^= dp_rx_get_le32_split(data[0], data[1],
 					data[2], data_next[0]);
 				data = data_next + 1;
-				space = (qdf_nbuf_len(wbuf) - rx_desc_len)
-					- 1;
+				space = (qdf_nbuf_len(wbuf) - off) - 1;
 				break;
 			}
 			dp_rx_michael_block(l, r);
@@ -688,8 +683,8 @@ static QDF_STATUS dp_rx_defrag_mic(const uint8_t *key, qdf_nbuf_t wbuf,
 			/*
 			 * Setup for next buffer.
 			 */
-			data = (uint8_t *) qdf_nbuf_data(wbuf) + rx_desc_len;
-			space = qdf_nbuf_len(wbuf) - rx_desc_len;
+			data = (uint8_t *)qdf_nbuf_data(wbuf) + off;
+			space = qdf_nbuf_len(wbuf) - off;
 		}
 	}
 	/* Last block and padding (0x5a, 4..7 x 0) */
@@ -729,27 +724,35 @@ static QDF_STATUS dp_rx_defrag_tkip_demic(const uint8_t *key,
 					qdf_nbuf_t msdu, uint16_t hdrlen)
 {
 	QDF_STATUS status;
-	uint32_t pktlen;
+	uint32_t pktlen = 0;
 	uint8_t mic[IEEE80211_WEP_MICLEN];
 	uint8_t mic0[IEEE80211_WEP_MICLEN];
-	int rx_desc_len = sizeof(struct rx_pkt_tlvs);
+	qdf_nbuf_t prev = NULL, next;
+
+	next = msdu;
+	while (next) {
+		pktlen += (qdf_nbuf_len(next) - hdrlen);
+		prev = next;
+		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
+			  "%s pktlen %ld\n", __func__,
+				qdf_nbuf_len(next) - hdrlen);
+		next = qdf_nbuf_next(next);
+	}
 
-	pktlen = qdf_nbuf_len(msdu) - rx_desc_len;
+	qdf_nbuf_copy_bits(prev, qdf_nbuf_len(prev) - dp_f_tkip.ic_miclen,
+			   dp_f_tkip.ic_miclen, (caddr_t)mic0);
+	qdf_nbuf_trim_tail(prev, dp_f_tkip.ic_miclen);
+	pktlen -= dp_f_tkip.ic_miclen;
 
 	status = dp_rx_defrag_mic(key, msdu, hdrlen,
-				pktlen - (hdrlen + dp_f_tkip.ic_miclen), mic);
+				pktlen, mic);
 
 	if (QDF_IS_STATUS_ERROR(status))
 		return status;
 
-	qdf_nbuf_copy_bits(msdu, pktlen - dp_f_tkip.ic_miclen + rx_desc_len,
-				dp_f_tkip.ic_miclen, (caddr_t)mic0);
-
-	if (!qdf_mem_cmp(mic, mic0, dp_f_tkip.ic_miclen))
+	if (qdf_mem_cmp(mic, mic0, dp_f_tkip.ic_miclen))
 		return QDF_STATUS_E_DEFRAG_ERROR;
 
-	qdf_nbuf_trim_tail(msdu, dp_f_tkip.ic_miclen);
-
 	return QDF_STATUS_SUCCESS;
 }
 
@@ -824,11 +827,20 @@ dp_rx_construct_fraglist(struct dp_peer *peer,
  *
  * Return: None
  */
-static void dp_rx_defrag_err(uint8_t vdev_id, uint8_t *peer_mac_addr,
-	int tid, uint32_t tsf32, uint32_t err_type, qdf_nbuf_t rx_frame,
-	uint64_t *pn, uint8_t key_id)
+static void dp_rx_defrag_err(struct dp_vdev *vdev, qdf_nbuf_t nbuf)
 {
-	/* TODO: Who needs to know about the TKIP MIC error */
+	struct ol_if_ops *tops = NULL;
+	struct dp_pdev *pdev = vdev->pdev;
+	int rx_desc_len = sizeof(struct rx_pkt_tlvs);
+	uint8_t *orig_hdr;
+	struct ieee80211_frame *wh;
+
+	orig_hdr = (uint8_t *)(qdf_nbuf_data(nbuf) + rx_desc_len);
+	wh = (struct ieee80211_frame *)orig_hdr;
+
+	tops = pdev->soc->cdp_soc.ol_ops;
+	if (tops->rx_mic_error)
+		tops->rx_mic_error(pdev->osif_pdev, vdev->vdev_id, wh);
 }
 
 
@@ -1117,6 +1129,8 @@ static QDF_STATUS dp_rx_defrag(struct dp_peer *peer, unsigned tid,
 	uint16_t hdr_space;
 	uint8_t key[DEFRAG_IEEE80211_KEY_LEN];
 	struct dp_vdev *vdev = peer->vdev;
+	struct dp_soc *soc = vdev->pdev->soc;
+	uint8_t status = 0;
 
 	hdr_space = dp_rx_defrag_hdrsize(cur);
 	index = hal_rx_msdu_is_wlan_mcast(cur) ?
@@ -1134,14 +1148,8 @@ static QDF_STATUS dp_rx_defrag(struct dp_peer *peer, unsigned tid,
 	cur = frag_list_head;
 
 	QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO,
-			"%s: Security type: %d\n", __func__,
-			peer->security[index].sec_type);
-
-	/* Temporary fix to drop TKIP encrypted packets */
-	if (peer->security[index].sec_type ==
-			htt_sec_type_tkip) {
-		return QDF_STATUS_E_DEFRAG_ERROR;
-	}
+			"%s: index %d Security type: %d\n", __func__,
+			index, peer->security[index].sec_type);
 
 	switch (peer->security[index].sec_type) {
 	case htt_sec_type_tkip:
@@ -1152,9 +1160,6 @@ static QDF_STATUS dp_rx_defrag(struct dp_peer *peer, unsigned tid,
 			tmp_next = qdf_nbuf_next(cur);
 			if (dp_rx_defrag_tkip_decap(cur, hdr_space)) {
 
-				/* TKIP decap failed, discard frags */
-				dp_rx_defrag_frames_free(frag_list_head);
-
 				QDF_TRACE(QDF_MODULE_ID_TXRX,
 					QDF_TRACE_LEVEL_ERROR,
 					"dp_rx_defrag: TKIP decap failed");
@@ -1163,6 +1168,9 @@ static QDF_STATUS dp_rx_defrag(struct dp_peer *peer, unsigned tid,
 			}
 			cur = tmp_next;
 		}
+
+		/* If success, increment header to be stripped later */
+		hdr_space += dp_f_tkip.ic_header;
 		break;
 
 	case htt_sec_type_aes_ccmp:
@@ -1170,9 +1178,6 @@ static QDF_STATUS dp_rx_defrag(struct dp_peer *peer, unsigned tid,
 			tmp_next = qdf_nbuf_next(cur);
 			if (dp_rx_defrag_ccmp_demic(cur, hdr_space)) {
 
-				/* CCMP demic failed, discard frags */
-				dp_rx_defrag_frames_free(frag_list_head);
-
 				QDF_TRACE(QDF_MODULE_ID_TXRX,
 					QDF_TRACE_LEVEL_ERROR,
 					"dp_rx_defrag: CCMP demic failed");
@@ -1181,9 +1186,6 @@ static QDF_STATUS dp_rx_defrag(struct dp_peer *peer, unsigned tid,
 			}
 			if (dp_rx_defrag_ccmp_decap(cur, hdr_space)) {
 
-				/* CCMP decap failed, discard frags */
-				dp_rx_defrag_frames_free(frag_list_head);
-
 				QDF_TRACE(QDF_MODULE_ID_TXRX,
 					QDF_TRACE_LEVEL_ERROR,
 					"dp_rx_defrag: CCMP decap failed");
@@ -1196,6 +1198,7 @@ static QDF_STATUS dp_rx_defrag(struct dp_peer *peer, unsigned tid,
 		/* If success, increment header to be stripped later */
 		hdr_space += dp_f_ccmp.ic_header;
 		break;
+
 	case htt_sec_type_wep40:
 	case htt_sec_type_wep104:
 	case htt_sec_type_wep128:
@@ -1203,9 +1206,6 @@ static QDF_STATUS dp_rx_defrag(struct dp_peer *peer, unsigned tid,
 			tmp_next = qdf_nbuf_next(cur);
 			if (dp_rx_defrag_wep_decap(cur, hdr_space)) {
 
-				/* WEP decap failed, discard frags */
-				dp_rx_defrag_frames_free(frag_list_head);
-
 				QDF_TRACE(QDF_MODULE_ID_TXRX,
 					QDF_TRACE_LEVEL_ERROR,
 					"dp_rx_defrag: WEP decap failed");
@@ -1226,19 +1226,28 @@ static QDF_STATUS dp_rx_defrag(struct dp_peer *peer, unsigned tid,
 	}
 
 	if (tkip_demic) {
-		msdu = frag_list_tail; /* Only last fragment has the MIC */
-
-		qdf_mem_copy(key,
-			peer->security[index].michael_key,
-			sizeof(peer->security[index].michael_key));
-		if (dp_rx_defrag_tkip_demic(key, msdu, hdr_space)) {
-			qdf_nbuf_free(msdu);
-			dp_rx_defrag_err(vdev->vdev_id, peer->mac_addr.raw,
-				tid, 0, QDF_STATUS_E_DEFRAG_ERROR, msdu,
-				NULL, 0);
-			QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
-				"dp_rx_defrag: TKIP demic failed");
-			return QDF_STATUS_E_DEFRAG_ERROR;
+		msdu = frag_list_head;
+		if (soc->cdp_soc.ol_ops->rx_frag_tkip_demic) {
+			status = soc->cdp_soc.ol_ops->rx_frag_tkip_demic(
+				peer->ol_peer, msdu, hdr_space);
+		} else {
+			qdf_mem_copy(key,
+				     &peer->security[index].michael_key[0],
+				IEEE80211_WEP_MICLEN);
+			status = dp_rx_defrag_tkip_demic(key, msdu,
+							 RX_PKT_TLVS_LEN +
+							 hdr_space);
+
+			if (status) {
+				dp_rx_defrag_err(vdev, frag_list_head);
+
+				QDF_TRACE(QDF_MODULE_ID_TXRX,
+					  QDF_TRACE_LEVEL_ERROR,
+					  "%s: TKIP demic failed status %d\n",
+					  __func__, status);
+
+				return QDF_STATUS_E_DEFRAG_ERROR;
+			}
 		}
 	}
 
@@ -1663,6 +1672,7 @@ QDF_STATUS dp_rx_defrag_add_last_frag(struct dp_soc *soc,
 	struct dp_rx_tid *rx_tid = &peer->rx_tid[tid];
 	struct dp_rx_reorder_array_elem *rx_reorder_array_elem;
 	uint8_t all_frag_present;
+	uint32_t msdu_len;
 	QDF_STATUS status;
 
 	rx_reorder_array_elem = peer->rx_tid[tid].array;
@@ -1676,6 +1686,10 @@ QDF_STATUS dp_rx_defrag_add_last_frag(struct dp_soc *soc,
 		goto fail;
 	}
 
+	msdu_len = hal_rx_msdu_start_msdu_len_get(qdf_nbuf_data(nbuf));
+
+	qdf_nbuf_set_pktlen(nbuf, (msdu_len + RX_PKT_TLVS_LEN));
+
 	status = dp_rx_defrag_fraglist_insert(peer, tid,
 					      &rx_reorder_array_elem->head,
 			&rx_reorder_array_elem->tail, nbuf,

+ 3 - 0
dp/wifi3.0/dp_types.h

@@ -1421,6 +1421,9 @@ struct dp_peer {
 	dp_ecm_policy wds_ecm;
 #endif
 	bool delete_in_progress;
+
+	/* Opaque handle to node */
+	void *ol_peer;
 };
 
 #ifdef CONFIG_WIN