Browse Source

qcacmn: Smart Mesh-NAC filtering in rx data path

Perform software based smart mesh filtering on rx packets indicated
as error packets with invalid peer. All such packets from NAC
sent to umac through monitor interface.

Change-Id: I8e4b40f74088bb8820d6ab6681756835e400d4ef
CRs-Fixed: 2017269
Pratik Gandhi 8 years ago
parent
commit
3da3bc731c
6 changed files with 172 additions and 12 deletions
  1. 60 7
      dp/wifi3.0/dp_rx.c
  2. 33 3
      dp/wifi3.0/dp_rx_err.c
  3. 2 0
      dp/wifi3.0/dp_rx_mon.h
  4. 0 2
      dp/wifi3.0/dp_rx_mon_dest.c
  5. 3 0
      dp/wifi3.0/dp_types.h
  6. 74 0
      dp/wifi3.0/hal_rx.h

+ 60 - 7
dp/wifi3.0/dp_rx.c

@@ -27,6 +27,7 @@
 #include "if_meta_hdr.h"
 #endif
 #include "dp_internal.h"
+#include "dp_rx_mon.h"
 
 /*
  * dp_rx_buffers_replenish() - replenish rxdma ring with rx nbufs
@@ -497,14 +498,56 @@ QDF_STATUS dp_rx_filter_mesh_packets(struct dp_vdev *vdev, qdf_nbuf_t nbuf)
 #endif
 
 #ifdef CONFIG_WIN
+/**
+ * dp_rx_nac_filter(): Function to perform filtering of non-associated
+ * clients
+ * @pdev: DP pdev handle
+ * @rx_pkt_hdr: Rx packet Header
+ *
+ * return: dp_vdev*
+ */
+static
+struct dp_vdev *dp_rx_nac_filter(struct dp_pdev *pdev,
+		uint8_t *rx_pkt_hdr)
+{
+	struct ieee80211_frame *wh;
+	struct dp_neighbour_peer *peer = NULL;
+
+	wh = (struct ieee80211_frame *)rx_pkt_hdr;
+
+	if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) != IEEE80211_FC1_DIR_TODS)
+		return NULL;
+
+	qdf_spin_lock_bh(&pdev->neighbour_peer_mutex);
+	TAILQ_FOREACH(peer, &pdev->neighbour_peers_list,
+				neighbour_peer_list_elem) {
+		if (qdf_mem_cmp(&peer->neighbour_peers_macaddr.raw[0],
+				wh->i_addr2, DP_MAC_ADDR_LEN) == 0) {
+			QDF_TRACE(
+				QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
+				FL("NAC configuration matched for mac-%2x:%2x:%2x:%2x:%2x:%2x"),
+				peer->neighbour_peers_macaddr.raw[0],
+				peer->neighbour_peers_macaddr.raw[1],
+				peer->neighbour_peers_macaddr.raw[2],
+				peer->neighbour_peers_macaddr.raw[3],
+				peer->neighbour_peers_macaddr.raw[4],
+				peer->neighbour_peers_macaddr.raw[5]);
+			return pdev->monitor_vdev;
+		}
+	}
+	qdf_spin_unlock_bh(&pdev->neighbour_peer_mutex);
+
+	return NULL;
+}
+
 /**
  * dp_rx_process_invalid_peer(): Function to pass invalid peer list to umac
  * @soc: DP SOC handle
- * @nbuf: nbuf for which peer is invalid
+ * @mpdu: mpdu for which peer is invalid
  *
  * return: integer type
  */
-uint8_t dp_rx_process_invalid_peer(struct dp_soc *soc, qdf_nbuf_t nbuf)
+uint8_t dp_rx_process_invalid_peer(struct dp_soc *soc, qdf_nbuf_t mpdu)
 {
 	struct dp_invalid_peer_msg msg;
 	struct dp_vdev *vdev = NULL;
@@ -513,7 +556,7 @@ uint8_t dp_rx_process_invalid_peer(struct dp_soc *soc, qdf_nbuf_t nbuf)
 	uint8_t i;
 	uint8_t *rx_pkt_hdr;
 
-	rx_pkt_hdr = qdf_nbuf_data(nbuf);
+	rx_pkt_hdr = hal_rx_pkt_hdr_get(qdf_nbuf_data(mpdu));
 	wh = (struct ieee80211_frame *)rx_pkt_hdr;
 
 	if (!DP_FRAME_IS_DATA(wh)) {
@@ -522,7 +565,7 @@ uint8_t dp_rx_process_invalid_peer(struct dp_soc *soc, qdf_nbuf_t nbuf)
 		return 1;
 	}
 
-	if (qdf_nbuf_len(nbuf) < sizeof(struct ieee80211_frame)) {
+	if (qdf_nbuf_len(mpdu) < sizeof(struct ieee80211_frame)) {
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
 				"Invalid nbuf length");
 		return 1;
@@ -537,6 +580,16 @@ uint8_t dp_rx_process_invalid_peer(struct dp_soc *soc, qdf_nbuf_t nbuf)
 			continue;
 		}
 
+		if (pdev->filter_neighbour_peers) {
+			/* Next Hop scenario not yet handle */
+			vdev = dp_rx_nac_filter(pdev, rx_pkt_hdr);
+			if (vdev) {
+				dp_rx_mon_deliver(soc, i,
+						soc->invalid_peer_head_msdu,
+						soc->invalid_peer_tail_msdu);
+				return 0;
+			}
+		}
 		TAILQ_FOREACH(vdev, &pdev->vdev_list, vdev_list_elem) {
 			if (qdf_mem_cmp(wh->i_addr1, vdev->mac_addr.raw,
 						DP_MAC_ADDR_LEN) == 0) {
@@ -553,7 +606,8 @@ uint8_t dp_rx_process_invalid_peer(struct dp_soc *soc, qdf_nbuf_t nbuf)
 
 out:
 	msg.wh = wh;
-	msg.nbuf = nbuf;
+	qdf_nbuf_pull_head(mpdu, RX_PKT_TLVS_LEN);
+	msg.nbuf = mpdu;
 	msg.vdev_id = vdev->vdev_id;
 	if (pdev->soc->cdp_soc.ol_ops->rx_invalid_peer)
 		return pdev->soc->cdp_soc.ol_ops->rx_invalid_peer(
@@ -562,7 +616,7 @@ out:
 	return 0;
 }
 #else
-uint8_t dp_rx_process_invalid_peer(struct dp_soc *soc, qdf_nbuf_t nbuf)
+uint8_t dp_rx_process_invalid_peer(struct dp_soc *soc, qdf_nbuf_t mpdu)
 {
 	return 0;
 }
@@ -863,7 +917,6 @@ done:
 			 */
 			/* Peer lookup failed */
 			if (!peer && !vdev) {
-
 				dp_rx_process_invalid_peer(soc, nbuf);
 				DP_STATS_INC_PKT(soc, rx.err.rx_invalid_peer, 1,
 						qdf_nbuf_len(nbuf));

+ 33 - 3
dp/wifi3.0/dp_rx_err.c

@@ -199,6 +199,30 @@ dp_rx_2k_jump_handle(struct dp_soc *soc, void *ring_desc,
 				head, tail, quota);
 }
 
+static bool
+dp_rx_chain_msdus(struct dp_soc *soc, qdf_nbuf_t nbuf,
+		struct dp_rx_desc *rx_desc)
+{
+	bool mpdu_done = false;
+
+	if (hal_rx_msdu_end_first_msdu_get(rx_desc->rx_buf_start)) {
+		qdf_nbuf_set_chfrag_start(rx_desc->nbuf, 1);
+		soc->invalid_peer_head_msdu = NULL;
+		soc->invalid_peer_tail_msdu = NULL;
+	}
+
+	if (hal_rx_msdu_end_last_msdu_get(rx_desc->rx_buf_start)) {
+		qdf_nbuf_set_chfrag_end(rx_desc->nbuf, 1);
+		mpdu_done = true;
+	}
+
+	DP_RX_LIST_APPEND(soc->invalid_peer_head_msdu,
+				soc->invalid_peer_tail_msdu,
+				nbuf);
+
+	return mpdu_done;
+}
+
 /**
 * dp_rx_null_q_desc_handle() - Function to handle NULL Queue
 *                              descriptor violation on either a
@@ -271,11 +295,17 @@ dp_rx_null_q_desc_handle(struct dp_soc *soc, struct dp_rx_desc *rx_desc,
 	peer = dp_peer_find_by_id(soc, peer_id);
 
 	if (!peer) {
+		bool mpdu_done = false;
+
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
 		FL("peer is NULL"));
-		qdf_nbuf_pull_head(nbuf, RX_PKT_TLVS_LEN);
-		dp_rx_process_invalid_peer(soc, nbuf);
-		goto fail;
+
+		mpdu_done = dp_rx_chain_msdus(soc, nbuf, rx_desc);
+		if (mpdu_done)
+			dp_rx_process_invalid_peer(soc, nbuf);
+
+		dp_rx_add_to_free_desc_list(head, tail, rx_desc);
+		return rx_bufs_used;
 	}
 
 	vdev = peer->vdev;

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

@@ -46,4 +46,6 @@ QDF_STATUS dp_rx_pdev_mon_status_attach(struct dp_pdev *pdev);
 QDF_STATUS dp_rx_pdev_mon_status_detach(struct dp_pdev *pdev);
 
 uint32_t dp_mon_process(struct dp_soc *soc, uint32_t mac_id, uint32_t quota);
+QDF_STATUS dp_rx_mon_deliver(struct dp_soc *soc, uint32_t mac_id,
+	qdf_nbuf_t head_msdu, qdf_nbuf_t tail_msdu);
 #endif

+ 0 - 2
dp/wifi3.0/dp_rx_mon_dest.c

@@ -609,7 +609,6 @@ void dp_rx_extract_radiotap_info(struct cdp_mon_status *rx_status,
 	/* TODO: rx_mon_status->vht_flag_values1 */
 }
 
-static inline
 QDF_STATUS dp_rx_mon_deliver(struct dp_soc *soc, uint32_t mac_id,
 	qdf_nbuf_t head_msdu, qdf_nbuf_t tail_msdu)
 {
@@ -728,7 +727,6 @@ void dp_rx_mon_dest_process(struct dp_soc *soc, uint32_t mac_id, uint32_t quota)
 						&head_msdu, &tail_msdu,
 						&npackets, &ppdu_id,
 						&head, &tail);
-
 #if 0
 			/* Temporary only handle destination ring */
 			if (ppdu_id != pdev->mon_ppdu_id) {

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

@@ -679,6 +679,9 @@ struct dp_soc {
 
 	/* Obj Mgr SoC */
 	struct wlan_objmgr_psoc *psoc;
+
+	qdf_nbuf_t invalid_peer_head_msdu;
+	qdf_nbuf_t invalid_peer_tail_msdu;
 };
 
 #define MAX_RX_MAC_RINGS 2

+ 74 - 0
dp/wifi3.0/hal_rx.h

@@ -529,6 +529,15 @@ struct rx_pkt_tlvs {
 
 #define RX_PKT_TLVS_LEN		(sizeof(struct rx_pkt_tlvs))
 
+static inline uint8_t
+*hal_rx_pkt_hdr_get(uint8_t *buf)
+{
+	struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf;
+
+	return pkt_tlvs->pkt_hdr_tlv.rx_pkt_hdr;
+
+}
+
 /*
  * Get msdu_done bit from the RX_ATTENTION TLV
  */
@@ -1416,6 +1425,55 @@ hal_rx_msdu_end_da_is_mcbc_get(uint8_t *buf)
 	return da_is_mcbc;
 }
 
+#define HAL_RX_MSDU_END_FIRST_MSDU_GET(_rx_msdu_end)	\
+	(_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end,	\
+		RX_MSDU_END_5_FIRST_MSDU_OFFSET)),	\
+		RX_MSDU_END_5_FIRST_MSDU_MASK,		\
+		RX_MSDU_END_5_FIRST_MSDU_LSB))
+
+ /**
+ * hal_rx_msdu_end_first_msdu_get: API to get first msdu status
+ * from rx_msdu_end TLV
+ *
+ * @ buf: pointer to the start of RX PKT TLV headers
+ * Return: first_msdu
+ */
+static inline uint8_t
+hal_rx_msdu_end_first_msdu_get(uint8_t *buf)
+{
+	struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf;
+	struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end;
+	uint8_t first_msdu;
+
+	first_msdu = HAL_RX_MSDU_END_FIRST_MSDU_GET(msdu_end);
+
+	return first_msdu;
+}
+
+#define HAL_RX_MSDU_END_LAST_MSDU_GET(_rx_msdu_end)	\
+	(_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end,	\
+		RX_MSDU_END_5_LAST_MSDU_OFFSET)),	\
+		RX_MSDU_END_5_LAST_MSDU_MASK,		\
+		RX_MSDU_END_5_LAST_MSDU_LSB))
+
+ /**
+ * hal_rx_msdu_end_last_msdu_get: API to get last msdu status
+ * from rx_msdu_end TLV
+ *
+ * @ buf: pointer to the start of RX PKT TLV headers
+ * Return: last_msdu
+ */
+static inline uint8_t
+hal_rx_msdu_end_last_msdu_get(uint8_t *buf)
+{
+	struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf;
+	struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end;
+	uint8_t last_msdu;
+
+	last_msdu = HAL_RX_MSDU_END_LAST_MSDU_GET(msdu_end);
+
+	return last_msdu;
+}
 /*******************************************************************************
  * RX ERROR APIS
  ******************************************************************************/
@@ -1839,6 +1897,22 @@ enum hal_rx_wbm_rxdma_push_reason {
 	WBM_RELEASE_RING_2_RXDMA_ERROR_CODE_MASK) >>	\
 	WBM_RELEASE_RING_2_RXDMA_ERROR_CODE_LSB)
 
+#define HAL_RX_WBM_FIRST_MSDU_GET(wbm_desc)		\
+	(((*(((uint32_t *) wbm_desc) +			\
+	(WBM_RELEASE_RING_4_FIRST_MSDU_OFFSET >> 2))) & \
+	WBM_RELEASE_RING_4_FIRST_MSDU_MASK) >>		\
+	WBM_RELEASE_RING_4_FIRST_MSDU_LSB)
+
+#define HAL_RX_WBM_LAST_MSDU_GET(wbm_desc)		\
+	(((*(((uint32_t *) wbm_desc) +			\
+	(WBM_RELEASE_RING_4_LAST_MSDU_OFFSET >> 2))) & 	\
+	WBM_RELEASE_RING_4_LAST_MSDU_MASK) >>		\
+	WBM_RELEASE_RING_4_LAST_MSDU_LSB)
+
+#define HAL_RX_WBM_BUF_COOKIE_GET(wbm_desc) \
+	HAL_RX_BUF_COOKIE_GET(&((struct wbm_release_ring *) \
+	wbm_desc)->released_buff_or_desc_addr_info)
+
 #define HAL_RX_WBM_BUF_COOKIE_GET(wbm_desc) \
 	HAL_RX_BUF_COOKIE_GET(&((struct wbm_release_ring *) \
 	wbm_desc)->released_buff_or_desc_addr_info)