소스 검색

qcacld-3.0: Process Rx data packet for pkt capture mode

Process Rx data packets and post to the mon thread for
packet capture mode

Change-Id: Id8ae54677615c27d61c6def1a521c509f602863b
CRs-Fixed: 2618941
Vulupala Shashank Reddy 5 년 전
부모
커밋
a2deef8c83

+ 1 - 0
Kbuild

@@ -1053,6 +1053,7 @@ PKT_CAPTURE_OBJS := $(PKT_CAPTURE_DIR)/core/src/wlan_pkt_capture_main.o \
 		$(PKT_CAPTURE_DIR)/core/src/wlan_pkt_capture_mon_thread.o \
 		$(PKT_CAPTURE_DIR)/dispatcher/src/wlan_pkt_capture_ucfg_api.o \
 		$(PKT_CAPTURE_DIR)/core/src/wlan_pkt_capture_mgmt_txrx.o \
+		$(PKT_CAPTURE_DIR)/core/src/wlan_pkt_capture_data_txrx.o \
 		$(PKT_CAPTURE_DIR)/dispatcher/src/wlan_pkt_capture_ucfg_api.o \
 		$(PKT_CAPTURE_TARGET_IF_DIR)/src/target_if_pkt_capture.o
 endif

+ 101 - 0
components/pkt_capture/core/inc/wlan_pkt_capture_data_txrx.h

@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2020 The Linux Foundation. All rights reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * DOC: Declare private API which shall be used internally only
+ * in pkt_capture component. This file shall include prototypes of
+ * pkt_capture data tx and data rx.
+ *
+ * Note: This API should be never accessed out of pkt_capture component.
+ */
+
+#ifndef _WLAN_PKT_CAPTURE_DATA_TXRX_H_
+#define _WLAN_PKT_CAPTURE_DATA_TXRX_H_
+
+#include "cdp_txrx_cmn_struct.h"
+#include <ol_txrx_types.h>
+#include <qdf_nbuf.h>
+
+/**
+ * pkt_capture_data_process_type - data pkt types to process
+ * for packet capture mode
+ * @TXRX_PROCESS_TYPE_DATA_RX: process RX packets (normal rx + offloaded rx)
+ * @TXRX_PROCESS_TYPE_DATA_TX: process TX packets (ofloaded tx)
+ * @TXRX_PROCESS_TYPE_DATA_TX_COMPL: process TX compl packets (normal tx)
+ */
+enum pkt_capture_data_process_type {
+	TXRX_PROCESS_TYPE_DATA_RX,
+	TXRX_PROCESS_TYPE_DATA_TX,
+	TXRX_PROCESS_TYPE_DATA_TX_COMPL,
+};
+
+#define TXRX_PKTCAPTURE_PKT_FORMAT_8023    0
+#define TXRX_PKTCAPTURE_PKT_FORMAT_80211   1
+
+/**
+ * pkt_capture_datapkt_process() - process data tx and rx packets
+ * for pkt capture mode. (normal tx/rx + offloaded tx/rx)
+ * @vdev_id: vdev id for which packet is captured
+ * @mon_buf_list: netbuf list
+ * @type: data process type
+ * @tid:  tid number
+ * @status: Tx status
+ * @pkt_format: Frame format
+ * @bssid: bssid
+ * @pdev: pdev handle
+ *
+ * Return: none
+ */
+void pkt_capture_datapkt_process(
+			uint8_t vdev_id,
+			qdf_nbuf_t mon_buf_list,
+			enum pkt_capture_data_process_type type,
+			uint8_t tid, uint8_t status, bool pkt_format,
+			uint8_t *bssid, htt_pdev_handle pdev);
+/**
+ * pkt_capture_msdu_process_pkts() - process data rx pkts
+ * @bssid: bssid
+ * @head_msdu: pointer to head msdu
+ * @vdev_id: vdev_id
+ * @pdev: pdev handle
+ *
+ * Return: none
+ */
+void pkt_capture_msdu_process_pkts(
+			uint8_t *bssid,
+			qdf_nbuf_t head_msdu,
+			uint8_t vdev_id,
+			htt_pdev_handle pdev);
+
+/**
+ * pkt_capture_rx_in_order_drop_offload_pkt() - drop offload packets
+ * @head_msdu: pointer to head msdu
+ *
+ * Return: none
+ */
+void pkt_capture_rx_in_order_drop_offload_pkt(qdf_nbuf_t head_msdu);
+
+/**
+ * pkt_capture_rx_in_order_offloaded_pkt() - check offloaded data pkt or not
+ * @rx_ind_msg: rx_ind_msg
+ *
+ * Return: false, if it is not offload pkt
+ *         true, if it is offload pkt
+ */
+bool pkt_capture_rx_in_order_offloaded_pkt(qdf_nbuf_t rx_ind_msg);
+#endif /* End  of _WLAN_PKT_CAPTURE_DATA_TXRX_H_ */

+ 8 - 0
components/pkt_capture/core/inc/wlan_pkt_capture_main.h

@@ -30,6 +30,7 @@
 #include <qdf_types.h>
 #include "wlan_pkt_capture_priv.h"
 #include "wlan_pkt_capture_objmgr.h"
+#include "wlan_objmgr_vdev_obj.h"
 
 #define pkt_capture_log(level, args...) \
 	QDF_TRACE(QDF_MODULE_ID_PKT_CAPTURE, level, ## args)
@@ -51,6 +52,13 @@
 #define PKT_CAPTURE_ENTER() pkt_capture_debug("enter")
 #define PKT_CAPTURE_EXIT() pkt_capture_debug("exit")
 
+/**
+ * pkt_capture_get_vdev() - Get pkt capture objmgr vdev.
+ *
+ * Return: pkt capture objmgr vdev
+ */
+struct wlan_objmgr_vdev *pkt_capture_get_vdev(void);
+
 /**
  * pkt_capture_vdev_create_notification() - Handler for vdev create notify.
  * @vdev: vdev which is going to be created by objmgr

+ 9 - 3
components/pkt_capture/core/inc/wlan_pkt_capture_mon_thread.h

@@ -38,29 +38,35 @@
 /* timeout in msec to wait for mon thread to suspend */
 #define PKT_CAPTURE_SUSPEND_TIMEOUT 200
 
-typedef void (*pkt_capture_mon_thread_cb)(void *context, void *monpkt,
-					  uint8_t vdev_id, uint8_t tid,
-					  uint8_t status, bool pkt_format);
+typedef void (*pkt_capture_mon_thread_cb)(
+			void *context, void *ppdev, void *monpkt,
+			uint8_t vdev_id, uint8_t tid,
+			uint8_t status, bool pkt_format,
+			uint8_t *bssid);
 
 /*
  * struct pkt_capture_mon_pkt - mon packet wrapper for mon data from TXRX
  * @list: List for storing mon packets
  * @context: Callback context
+ * @pdev: pointer to pdev handle
  * @monpkt: Mon skb
  * @vdev_id: Vdev id to which this packet is destined
  * @tid: Tid of mon packet
  * @status: Tx packet status
  * @pkt_format: Mon packet format, 0 = 802.3 format , 1 = 802.11 format
+ * @bssid: bssid
  * @callback: Mon callback
  */
 struct pkt_capture_mon_pkt {
 	struct list_head list;
 	void *context;
+	void *pdev;
 	void *monpkt;
 	uint8_t vdev_id;
 	uint8_t tid;
 	uint8_t status;
 	bool pkt_format;
+	uint8_t bssid[QDF_MAC_ADDR_SIZE];
 	pkt_capture_mon_thread_cb callback;
 };
 

+ 370 - 0
components/pkt_capture/core/src/wlan_pkt_capture_data_txrx.c

@@ -0,0 +1,370 @@
+/*
+ * Copyright (c) 2020 The Linux Foundation. All rights reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * DOC: Implement various notification handlers which are accessed
+ * internally in pkt_capture component only.
+ */
+
+#include <wlan_pkt_capture_data_txrx.h>
+#include <wlan_pkt_capture_main.h>
+#include <enet.h>
+#include <htt_internal.h>
+
+/**
+ * pkt_capture_rx_convert8023to80211() - convert 802.3 packet to 802.11
+ * format from rx desc
+ * @bssid: bssid
+ * @msdu: netbuf
+ * @desc: rx desc
+ *
+ * Return: none
+ */
+static void
+pkt_capture_rx_convert8023to80211(uint8_t *bssid, qdf_nbuf_t msdu, void *desc)
+{
+	struct ethernet_hdr_t *eth_hdr;
+	struct llc_snap_hdr_t *llc_hdr;
+	struct ieee80211_frame *wh;
+	uint8_t hdsize, new_hdsize;
+	struct ieee80211_qoscntl *qos_cntl;
+	uint16_t seq_no;
+	uint8_t localbuf[sizeof(struct ieee80211_qosframe_htc_addr4) +
+			sizeof(struct llc_snap_hdr_t)];
+	const uint8_t ethernet_II_llc_snap_header_prefix[] = {
+					0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
+	uint16_t ether_type;
+
+	struct htt_host_rx_desc_base *rx_desc = desc;
+
+	eth_hdr = (struct ethernet_hdr_t *)qdf_nbuf_data(msdu);
+	hdsize = sizeof(struct ethernet_hdr_t);
+	wh = (struct ieee80211_frame *)localbuf;
+
+	wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_DATA;
+	*(uint16_t *)wh->i_dur = 0;
+
+	new_hdsize = 0;
+
+	/* DA , BSSID , SA */
+	qdf_mem_copy(wh->i_addr1, eth_hdr->dest_addr,
+		     QDF_MAC_ADDR_SIZE);
+	qdf_mem_copy(wh->i_addr2, bssid,
+		     QDF_MAC_ADDR_SIZE);
+	qdf_mem_copy(wh->i_addr3, eth_hdr->src_addr,
+		     QDF_MAC_ADDR_SIZE);
+
+	wh->i_fc[1] = IEEE80211_FC1_DIR_FROMDS;
+
+	if (rx_desc->attention.more_data)
+		wh->i_fc[1] |= IEEE80211_FC1_MORE_DATA;
+
+	if (rx_desc->attention.power_mgmt)
+		wh->i_fc[1] |= IEEE80211_FC1_PWR_MGT;
+
+	if (rx_desc->attention.fragment)
+		wh->i_fc[1] |= IEEE80211_FC1_MORE_FRAG;
+
+	if (rx_desc->attention.order)
+		wh->i_fc[1] |= IEEE80211_FC1_ORDER;
+
+	if (rx_desc->mpdu_start.retry)
+		wh->i_fc[1] |= IEEE80211_FC1_RETRY;
+
+	seq_no = rx_desc->mpdu_start.seq_num;
+	seq_no = (seq_no << IEEE80211_SEQ_SEQ_SHIFT) & IEEE80211_SEQ_SEQ_MASK;
+	qdf_mem_copy(wh->i_seq, &seq_no, sizeof(seq_no));
+
+	new_hdsize = sizeof(struct ieee80211_frame);
+
+	if (rx_desc->attention.non_qos == 0) {
+		qos_cntl =
+		(struct ieee80211_qoscntl *)(localbuf + new_hdsize);
+		qos_cntl->i_qos[0] =
+		(rx_desc->mpdu_start.tid & IEEE80211_QOS_TID);
+		wh->i_fc[0] |= QDF_IEEE80211_FC0_SUBTYPE_QOS;
+
+		qos_cntl->i_qos[1] = 0;
+		new_hdsize += sizeof(struct ieee80211_qoscntl);
+	}
+
+	/*
+	 * Prepare llc Header
+	 */
+	llc_hdr = (struct llc_snap_hdr_t *)(localbuf + new_hdsize);
+	ether_type = (eth_hdr->ethertype[0] << 8) |
+			(eth_hdr->ethertype[1]);
+	if (ether_type >= ETH_P_802_3_MIN) {
+		qdf_mem_copy(llc_hdr,
+			     ethernet_II_llc_snap_header_prefix,
+			     sizeof
+			     (ethernet_II_llc_snap_header_prefix));
+		if (ether_type == ETHERTYPE_AARP ||
+		    ether_type == ETHERTYPE_IPX) {
+			llc_hdr->org_code[2] =
+				BTEP_SNAP_ORGCODE_2;
+			/* 0xf8; bridge tunnel header */
+		}
+		llc_hdr->ethertype[0] = eth_hdr->ethertype[0];
+		llc_hdr->ethertype[1] = eth_hdr->ethertype[1];
+		new_hdsize += sizeof(struct llc_snap_hdr_t);
+	}
+
+	/*
+	 * Remove 802.3 Header by adjusting the head
+	 */
+	qdf_nbuf_pull_head(msdu, hdsize);
+
+	/*
+	 * Adjust the head and prepare 802.11 Header
+	 */
+	qdf_nbuf_push_head(msdu, new_hdsize);
+	qdf_mem_copy(qdf_nbuf_data(msdu), localbuf, new_hdsize);
+}
+
+void pkt_capture_rx_in_order_drop_offload_pkt(qdf_nbuf_t head_msdu)
+{
+	while (head_msdu) {
+		qdf_nbuf_t msdu = head_msdu;
+
+		head_msdu = qdf_nbuf_next(head_msdu);
+		qdf_nbuf_free(msdu);
+	}
+}
+
+bool pkt_capture_rx_in_order_offloaded_pkt(qdf_nbuf_t rx_ind_msg)
+{
+	uint32_t *msg_word;
+
+	msg_word = (uint32_t *)qdf_nbuf_data(rx_ind_msg);
+
+	/* check if it is for offloaded data pkt */
+	return HTT_RX_IN_ORD_PADDR_IND_PKT_CAPTURE_MODE_IS_MONITOR_SET
+					(*(msg_word + 1));
+}
+
+void pkt_capture_msdu_process_pkts(
+				uint8_t *bssid,
+				qdf_nbuf_t head_msdu,
+				uint8_t vdev_id, htt_pdev_handle pdev)
+{
+	qdf_nbuf_t loop_msdu, pktcapture_msdu;
+	qdf_nbuf_t msdu, prev = NULL;
+
+	pktcapture_msdu = NULL;
+	loop_msdu = head_msdu;
+	while (loop_msdu) {
+		msdu = qdf_nbuf_copy(loop_msdu);
+
+		if (msdu) {
+			qdf_nbuf_push_head(msdu,
+					   HTT_RX_STD_DESC_RESERVATION);
+			qdf_nbuf_set_next(msdu, NULL);
+
+			if (!(pktcapture_msdu)) {
+				pktcapture_msdu = msdu;
+				prev = msdu;
+			} else {
+				qdf_nbuf_set_next(prev, msdu);
+				prev = msdu;
+			}
+		}
+		loop_msdu = qdf_nbuf_next(loop_msdu);
+	}
+
+	if (!pktcapture_msdu)
+		return;
+
+	pkt_capture_datapkt_process(
+			vdev_id, pktcapture_msdu,
+			TXRX_PROCESS_TYPE_DATA_RX, 0, 0,
+			TXRX_PKTCAPTURE_PKT_FORMAT_8023,
+			bssid, pdev);
+}
+
+/**
+ * pkt_capture_rx_data_cb(): callback to process data rx packets
+ * for pkt capture mode. (normal rx + offloaded rx)
+ * @context: objmgr vdev
+ * @ppdev: device handler
+ * @nbuf_list: netbuf list
+ * @vdev_id: vdev id for which packet is captured
+ * @tid:  tid number
+ * @status: Tx status
+ * @pkt_format: Frame format
+ * @bssid: bssid
+ *
+ * Return: none
+ */
+static void
+pkt_capture_rx_data_cb(
+		void *context, void *ppdev, void *nbuf_list,
+		uint8_t vdev_id, uint8_t tid,
+		uint8_t status, bool pkt_format,
+		uint8_t *bssid)
+{
+	struct pkt_capture_vdev_priv *vdev_priv;
+	qdf_nbuf_t buf_list = (qdf_nbuf_t)nbuf_list;
+	struct wlan_objmgr_vdev *vdev = context;
+	htt_pdev_handle pdev = ppdev;
+	struct pkt_capture_cb_context *cb_ctx;
+	qdf_nbuf_t msdu, next_buf;
+	uint8_t drop_count;
+	struct htt_host_rx_desc_base *rx_desc;
+	struct mon_rx_status rx_status = {0};
+	uint32_t headroom;
+	static uint8_t preamble_type;
+	static uint32_t vht_sig_a_1;
+	static uint32_t vht_sig_a_2;
+
+	vdev_priv = pkt_capture_vdev_get_priv(vdev);
+	if (qdf_unlikely(!vdev))
+		goto free_buf;
+
+	cb_ctx = vdev_priv->cb_ctx;
+	if (!cb_ctx || !cb_ctx->mon_cb || !cb_ctx->mon_ctx)
+		goto free_buf;
+
+	msdu = buf_list;
+	while (msdu) {
+		struct ethernet_hdr_t *eth_hdr;
+
+		next_buf = qdf_nbuf_queue_next(msdu);
+		qdf_nbuf_set_next(msdu, NULL);   /* Add NULL terminator */
+
+		rx_desc = htt_rx_desc(msdu);
+
+		/*
+		 * Only the first mpdu has valid preamble type, so use it
+		 * till the last mpdu is reached
+		 */
+		if (rx_desc->attention.first_mpdu) {
+			preamble_type = rx_desc->ppdu_start.preamble_type;
+			if (preamble_type == 8 || preamble_type == 9 ||
+			    preamble_type == 0x0c || preamble_type == 0x0d) {
+				vht_sig_a_1 = VHT_SIG_A_1(rx_desc);
+				vht_sig_a_2 = VHT_SIG_A_2(rx_desc);
+			}
+		} else {
+			rx_desc->ppdu_start.preamble_type = preamble_type;
+			if (preamble_type == 8 || preamble_type == 9 ||
+			    preamble_type == 0x0c || preamble_type == 0x0d) {
+				VHT_SIG_A_1(rx_desc) = vht_sig_a_1;
+				VHT_SIG_A_2(rx_desc) = vht_sig_a_2;
+			}
+		}
+
+		if (rx_desc->attention.last_mpdu) {
+			preamble_type = 0;
+			vht_sig_a_1 = 0;
+			vht_sig_a_2 = 0;
+		}
+
+		qdf_nbuf_pull_head(msdu, HTT_RX_STD_DESC_RESERVATION);
+
+		/*
+		 * Get the channel info and update the rx status
+		 */
+
+		/* need to update this to fill rx_status*/
+		htt_rx_mon_get_rx_status(pdev, rx_desc, &rx_status);
+		rx_status.chan_noise_floor = NORMALIZED_TO_NOISE_FLOOR;
+
+		/* clear IEEE80211_RADIOTAP_F_FCS flag*/
+		rx_status.rtap_flags &= ~(BIT(4));
+		rx_status.rtap_flags &= ~(BIT(2));
+
+		/*
+		 * convert 802.3 header format into 802.11 format
+		 */
+		if (vdev_id == HTT_INVALID_VDEV) {
+			eth_hdr = (struct ethernet_hdr_t *)qdf_nbuf_data(msdu);
+			qdf_mem_copy(bssid, eth_hdr->src_addr,
+				     QDF_MAC_ADDR_SIZE);
+		}
+
+		pkt_capture_rx_convert8023to80211(bssid, msdu, rx_desc);
+
+		/*
+		 * Calculate the headroom and adjust head
+		 * to prepare radiotap header.
+		 */
+		headroom = qdf_nbuf_headroom(msdu);
+		qdf_nbuf_update_radiotap(&rx_status, msdu, headroom);
+
+		if (QDF_STATUS_SUCCESS !=
+		    cb_ctx->mon_cb(cb_ctx->mon_ctx, msdu)) {
+			pkt_capture_err("Frame Rx to HDD failed");
+			qdf_nbuf_free(msdu);
+		}
+		msdu = next_buf;
+	}
+
+	return;
+
+free_buf:
+	drop_count = pkt_capture_drop_nbuf_list(buf_list);
+}
+
+void pkt_capture_datapkt_process(
+		uint8_t vdev_id,
+		qdf_nbuf_t mon_buf_list,
+		enum pkt_capture_data_process_type type,
+		uint8_t tid, uint8_t status, bool pkt_format,
+		uint8_t *bssid, htt_pdev_handle pdev)
+{
+	uint8_t drop_count;
+	struct pkt_capture_mon_pkt *pkt;
+	pkt_capture_mon_thread_cb callback = NULL;
+	struct wlan_objmgr_vdev *vdev;
+
+	vdev = pkt_capture_get_vdev();
+	if (!vdev)
+		goto drop_rx_buf;
+
+	pkt = pkt_capture_alloc_mon_pkt(vdev);
+	if (!pkt)
+		goto drop_rx_buf;
+
+	switch (type) {
+	case TXRX_PROCESS_TYPE_DATA_RX:
+		callback = pkt_capture_rx_data_cb;
+		break;
+	case TXRX_PROCESS_TYPE_DATA_TX:
+		break;
+	case TXRX_PROCESS_TYPE_DATA_TX_COMPL:
+		break;
+	default:
+		return;
+	}
+
+	pkt->callback = callback;
+	pkt->context = (void *)vdev;
+	pkt->pdev = (void *)pdev;
+	pkt->monpkt = (void *)mon_buf_list;
+	pkt->vdev_id = vdev_id;
+	pkt->tid = tid;
+	pkt->status = status;
+	pkt->pkt_format = pkt_format;
+	qdf_mem_copy(pkt->bssid, bssid, QDF_MAC_ADDR_SIZE);
+	pkt_capture_indicate_monpkt(vdev, pkt);
+	return;
+
+drop_rx_buf:
+	drop_count = pkt_capture_drop_nbuf_list(mon_buf_list);
+}

+ 9 - 0
components/pkt_capture/core/src/wlan_pkt_capture_main.c

@@ -27,6 +27,13 @@
 #include "wlan_pkt_capture_mgmt_txrx.h"
 #include "target_if_pkt_capture.h"
 
+static struct wlan_objmgr_vdev *gp_pkt_capture_vdev;
+
+struct wlan_objmgr_vdev *pkt_capture_get_vdev()
+{
+	return gp_pkt_capture_vdev;
+}
+
 enum pkt_capture_mode pkt_capture_get_mode(struct wlan_objmgr_psoc *psoc)
 {
 	struct pkt_psoc_priv *psoc_priv;
@@ -296,6 +303,7 @@ pkt_capture_vdev_create_notification(struct wlan_objmgr_vdev *vdev, void *arg)
 	}
 
 	vdev_priv->vdev = vdev;
+	gp_pkt_capture_vdev = vdev;
 
 	status = pkt_capture_callback_ctx_create(vdev_priv);
 	if (!QDF_IS_STATUS_SUCCESS(status)) {
@@ -366,6 +374,7 @@ pkt_capture_vdev_destroy_notification(struct wlan_objmgr_vdev *vdev, void *arg)
 	pkt_capture_mon_context_destroy(vdev_priv);
 	pkt_capture_callback_ctx_destroy(vdev_priv);
 	qdf_mem_free(vdev_priv);
+	gp_pkt_capture_vdev = NULL;
 	return status;
 }
 

+ 3 - 3
components/pkt_capture/core/src/wlan_pkt_capture_mgmt_txrx.c

@@ -44,9 +44,9 @@
  * Return: none
  */
 static void
-pkt_capture_mgmtpkt_cb(void *context, void *nbuf_list,
+pkt_capture_mgmtpkt_cb(void *context, void *ppdev, void *nbuf_list,
 		       uint8_t vdev_id, uint8_t tid, uint8_t status,
-		       bool pkt_format)
+		       bool pkt_format, uint8_t *bssid)
 {
 	struct pkt_capture_vdev_priv *vdev_priv;
 	struct wlan_objmgr_psoc *psoc = context;
@@ -293,7 +293,7 @@ pkt_capture_mgmt_rx_data_cb(struct wlan_objmgr_psoc *psoc,
 	qdf_nbuf_t nbuf;
 	int buf_len;
 
-	if (!(pkt_capture_get_mode(psoc) & PKT_CAPTURE_MODE_MGMT_ONLY))
+	if (!(pkt_capture_get_pktcap_mode(psoc) & PKT_CAPTURE_MODE_MGMT_ONLY))
 		return QDF_STATUS_E_FAILURE;
 
 	buf_len = qdf_nbuf_len(wbuf);

+ 2 - 2
components/pkt_capture/core/src/wlan_pkt_capture_mon_thread.c

@@ -209,8 +209,8 @@ pkt_capture_process_from_queue(struct pkt_capture_mon_context *mon_ctx)
 		spin_unlock_bh(&mon_ctx->mon_queue_lock);
 		vdev_id = pkt->vdev_id;
 		tid = pkt->tid;
-		pkt->callback(pkt->context, pkt->monpkt, vdev_id,
-			      tid, pkt->status, pkt->pkt_format);
+		pkt->callback(pkt->context, pkt->pdev, pkt->monpkt, vdev_id,
+			      tid, pkt->status, pkt->pkt_format, pkt->bssid);
 		pkt_capture_free_mon_pkt(mon_ctx, pkt);
 		spin_lock_bh(&mon_ctx->mon_queue_lock);
 	}

+ 53 - 0
components/pkt_capture/dispatcher/inc/wlan_pkt_capture_ucfg_api.h

@@ -28,6 +28,8 @@
 #include <qdf_types.h>
 #include "wlan_pkt_capture_objmgr.h"
 #include "wlan_pkt_capture_public_structs.h"
+#include "wlan_pkt_capture_mon_thread.h"
+#include <htt_types.h>
 
 #ifdef WLAN_FEATURE_PKT_CAPTURE
 /**
@@ -155,6 +157,38 @@ ucfg_pkt_capture_mgmt_tx_completion(
  * Return: 0 on success, -EINVAL on failure
  */
 int ucfg_pkt_capture_enable_ops(struct wlan_objmgr_vdev *vdev);
+
+/**
+ * ucfg_pkt_capture_rx_msdu_process() -  process data rx pkts
+ * @bssid: bssid
+ * @head_msdu: pointer to head msdu
+ * @vdev_id: vdev_id
+ * @pdev: pdev handle
+ *
+ * Return: none
+ */
+void ucfg_pkt_capture_rx_msdu_process(
+				uint8_t *bssid,
+				qdf_nbuf_t head_msdu,
+				uint8_t vdev_id, htt_pdev_handle pdev);
+
+/**
+ * ucfg_pkt_capture_rx_offloaded_pkt() - check offloaded data pkt or not
+ * @rx_ind_msg: rx_ind_msg
+ *
+ * Return: 0 not an offload pkt
+ *         1 offload pkt
+ */
+bool ucfg_pkt_capture_rx_offloaded_pkt(qdf_nbuf_t rx_ind_msg);
+
+/**
+ * ucfg_pkt_capture_rx_drop_offload_pkt() - drop offload packets
+ * @head_msdu: pointer to head msdu
+ *
+ * Return: none
+ */
+void ucfg_pkt_capture_rx_drop_offload_pkt(qdf_nbuf_t head_msdu);
+
 #else
 static inline
 QDF_STATUS ucfg_pkt_capture_init(void)
@@ -226,5 +260,24 @@ ucfg_pkt_capture_mgmt_tx_completion(struct wlan_objmgr_pdev *pdev,
 				    struct mgmt_offload_event_params *params)
 {
 }
+
+static inline void
+ucfg_pkt_capture_rx_msdu_process(
+				uint8_t *bssid,
+				qdf_nbuf_t head_msdu,
+				uint8_t vdev_id, htt_pdev_handle pdev)
+{
+}
+
+static inline bool
+ucfg_pkt_capture_rx_offloaded_pkt(qdf_nbuf_t rx_ind_msg)
+{
+	return false;
+}
+
+static inline void
+ucfg_pkt_capture_rx_drop_offload_pkt(qdf_nbuf_t head_msdu)
+{
+}
 #endif /* WLAN_FEATURE_PKT_CAPTURE */
 #endif /* _WLAN_PKT_CAPTURE_UCFG_API_H_ */

+ 20 - 0
components/pkt_capture/dispatcher/src/wlan_pkt_capture_ucfg_api.c

@@ -26,6 +26,7 @@
 #include "wlan_pkt_capture_mon_thread.h"
 #include "wlan_pkt_capture_mgmt_txrx.h"
 #include "target_if_pkt_capture.h"
+#include "wlan_pkt_capture_data_txrx.h"
 
 enum pkt_capture_mode ucfg_pkt_capture_get_mode(struct wlan_objmgr_psoc *psoc)
 {
@@ -271,3 +272,22 @@ int ucfg_pkt_capture_enable_ops(struct wlan_objmgr_vdev *vdev)
 
 	return 0;
 }
+
+void ucfg_pkt_capture_rx_msdu_process(
+				uint8_t *bssid,
+				qdf_nbuf_t head_msdu,
+				uint8_t vdev_id, htt_pdev_handle pdev)
+{
+		pkt_capture_msdu_process_pkts(bssid, head_msdu,
+					      vdev_id, pdev);
+}
+
+bool ucfg_pkt_capture_rx_offloaded_pkt(qdf_nbuf_t rx_ind_msg)
+{
+	return pkt_capture_rx_in_order_offloaded_pkt(rx_ind_msg);
+}
+
+void ucfg_pkt_capture_rx_drop_offload_pkt(qdf_nbuf_t head_msdu)
+{
+	pkt_capture_rx_in_order_drop_offload_pkt(head_msdu);
+}

+ 21 - 1
core/dp/htt/htt_internal.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2014-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011, 2014-2020 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -1119,6 +1119,19 @@ int htt_rx_mon_amsdu_rx_in_order_pop_ll(htt_pdev_handle pdev,
 					qdf_nbuf_t *head_msdu,
 					qdf_nbuf_t *tail_msdu,
 					uint32_t *replenish_cnt);
+
+/**
+ * htt_rx_mon_get_rx_status() - Update information about the rx status,
+ * which is used later for radiotap updation.
+ * @pdev: Pointer to pdev handle
+ * @rx_desc: Pointer to struct htt_host_rx_desc_base
+ * @rx_status: Return variable updated with rx_status
+ *
+ * Return: None
+ */
+void htt_rx_mon_get_rx_status(htt_pdev_handle pdev,
+			      struct htt_host_rx_desc_base *rx_desc,
+			      struct mon_rx_status *rx_status);
 #else
 static inline
 int htt_rx_mon_amsdu_rx_in_order_pop_ll(htt_pdev_handle pdev,
@@ -1129,6 +1142,13 @@ int htt_rx_mon_amsdu_rx_in_order_pop_ll(htt_pdev_handle pdev,
 {
 	return 0;
 }
+
+static inline
+void htt_rx_mon_get_rx_status(htt_pdev_handle pdev,
+			      struct htt_host_rx_desc_base *rx_desc,
+			      struct mon_rx_status *rx_status)
+{
+}
 #endif
 
 #endif /* _HTT_INTERNAL__H_ */

+ 3 - 11
core/dp/htt/htt_monitor_rx.c

@@ -458,17 +458,9 @@ static uint8_t htt_mon_rx_get_rtap_flags(struct htt_host_rx_desc_base *rx_desc)
 	return rtap_flags;
 }
 
-/**
- * htt_rx_mon_get_rx_status() - Update information about the rx status,
- * which is used later for radiotap updation.
- * @rx_desc: Pointer to struct htt_host_rx_desc_base
- * @rx_status: Return variable updated with rx_status
- *
- * Return: None
- */
-static void htt_rx_mon_get_rx_status(htt_pdev_handle pdev,
-				     struct htt_host_rx_desc_base *rx_desc,
-				     struct mon_rx_status *rx_status)
+void htt_rx_mon_get_rx_status(htt_pdev_handle pdev,
+			      struct htt_host_rx_desc_base *rx_desc,
+			      struct mon_rx_status *rx_status)
 {
 	uint16_t channel_flags = 0;
 	struct mon_channel *ch_info = &pdev->mon_ch_info;

+ 47 - 0
core/dp/txrx/ol_rx.c

@@ -56,6 +56,7 @@
 #include <cdp_txrx_handle.h>
 #include <pld_common.h>
 #include <htt_internal.h>
+#include <wlan_pkt_capture_ucfg_api.h>
 
 #ifndef OL_RX_INDICATION_MAX_RECORDS
 #define OL_RX_INDICATION_MAX_RECORDS 2048
@@ -1561,6 +1562,7 @@ ol_rx_in_order_indication_handler(ol_txrx_pdev_handle pdev,
 {
 	struct ol_txrx_vdev_t *vdev = NULL;
 	struct ol_txrx_peer_t *peer = NULL;
+	struct ol_txrx_peer_t *peer_head = NULL;
 	htt_pdev_handle htt_pdev = NULL;
 	int status;
 	qdf_nbuf_t head_msdu = NULL, tail_msdu = NULL;
@@ -1569,6 +1571,14 @@ ol_rx_in_order_indication_handler(ol_txrx_pdev_handle pdev,
 	uint32_t msdu_count;
 	uint8_t pktlog_bit;
 	uint32_t filled = 0;
+	uint8_t bssid[QDF_MAC_ADDR_SIZE];
+	bool offloaded_pkt;
+	struct ol_txrx_soc_t *soc = cds_get_context(QDF_MODULE_ID_SOC);
+
+	if (qdf_unlikely(!soc)) {
+		ol_txrx_err("soc is NULL");
+		return;
+	}
 
 	if (tid >= OL_TXRX_NUM_EXT_TIDS) {
 		ol_txrx_err("invalid tid, %u", tid);
@@ -1632,6 +1642,43 @@ ol_rx_in_order_indication_handler(ol_txrx_pdev_handle pdev,
 	/* rx_opt_proc takes a NULL-terminated list of msdu netbufs */
 	qdf_nbuf_set_next(tail_msdu, NULL);
 
+	/* Packet Capture Mode */
+
+	if ((ucfg_pkt_capture_get_mode((void *)soc->psoc) &
+	      PKT_CAPTURE_MODE_DATA_ONLY)) {
+		offloaded_pkt = ucfg_pkt_capture_rx_offloaded_pkt(rx_ind_msg);
+		if (peer) {
+			vdev = peer->vdev;
+			if (peer->vdev) {
+				qdf_spin_lock_bh(&pdev->peer_ref_mutex);
+				peer_head = TAILQ_FIRST(&vdev->peer_list);
+				qdf_spin_unlock_bh(&pdev->peer_ref_mutex);
+				if (peer_head) {
+					qdf_spin_lock_bh(
+						&peer_head->peer_info_lock);
+					qdf_mem_copy(bssid,
+						     &peer_head->mac_addr.raw,
+						     QDF_MAC_ADDR_SIZE);
+					qdf_spin_unlock_bh(
+						&peer_head->peer_info_lock);
+
+					ucfg_pkt_capture_rx_msdu_process(
+							bssid, head_msdu,
+							peer->vdev->vdev_id,
+							htt_pdev);
+				}
+			}
+		} else if (offloaded_pkt) {
+			ucfg_pkt_capture_rx_msdu_process(
+						bssid, head_msdu,
+						HTT_INVALID_VDEV,
+						htt_pdev);
+
+			ucfg_pkt_capture_rx_drop_offload_pkt(head_msdu);
+			return;
+		}
+	}
+
 	/* Pktlog */
 	ol_rx_send_pktlog_event(pdev, peer, head_msdu, pktlog_bit);
 

+ 36 - 1
core/dp/txrx/ol_rx_defrag.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2020 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -58,6 +58,7 @@
 #include <ol_rx_defrag.h>
 #include <enet.h>
 #include <qdf_time.h>           /* qdf_system_time */
+#include <wlan_pkt_capture_ucfg_api.h>
 
 #define DEFRAG_IEEE80211_ADDR_EQ(a1, a2) \
 	(!qdf_mem_cmp(a1, a2, QDF_MAC_ADDR_SIZE))
@@ -653,7 +654,14 @@ ol_rx_defrag(ol_txrx_pdev_handle pdev,
 	struct ieee80211_frame *wh;
 	uint8_t key[DEFRAG_IEEE80211_KEY_LEN];
 	htt_pdev_handle htt_pdev = pdev->htt_pdev;
+	struct ol_txrx_peer_t *peer_head = NULL;
+	uint8_t bssid[QDF_MAC_ADDR_SIZE];
+	struct ol_txrx_soc_t *soc = cds_get_context(QDF_MODULE_ID_SOC);
 
+	if (qdf_unlikely(!soc)) {
+		ol_txrx_err("soc is NULL");
+		return;
+	}
 	vdev = peer->vdev;
 
 	/* bypass defrag for safe mode */
@@ -770,6 +778,33 @@ ol_rx_defrag(ol_txrx_pdev_handle pdev,
 	if (ol_cfg_frame_type(pdev->ctrl_pdev) == wlan_frm_fmt_802_3)
 		ol_rx_defrag_nwifi_to_8023(pdev, msdu);
 
+	/* Packet Capture Mode */
+
+	if ((ucfg_pkt_capture_get_mode((void *)soc->psoc) &
+	      PKT_CAPTURE_MODE_DATA_ONLY)) {
+		if (peer) {
+			if (peer->vdev) {
+				qdf_spin_lock_bh(&pdev->peer_ref_mutex);
+				peer_head = TAILQ_FIRST(&vdev->peer_list);
+				qdf_spin_unlock_bh(&pdev->peer_ref_mutex);
+				if (peer_head) {
+					qdf_spin_lock_bh(
+						&peer_head->peer_info_lock);
+					qdf_mem_copy(bssid,
+						     &peer_head->mac_addr.raw,
+						     QDF_MAC_ADDR_SIZE);
+					qdf_spin_unlock_bh(
+						&peer_head->peer_info_lock);
+
+					ucfg_pkt_capture_rx_msdu_process(
+								bssid, msdu,
+								vdev->vdev_id,
+								htt_pdev);
+				}
+			}
+		}
+	}
+
 	ol_rx_fwd_check(vdev, peer, tid, msdu);
 }