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

Subscribe for Tx data wdi event and process Tx data packets
and post into mon thread for packet capture mode

Change-Id: Id4c231ce8f32c45f579289b37cb810581c6ab31b
CRs-Fixed: 2845593
This commit is contained in:
Vulupala Shashank Reddy 2020-11-19 11:55:49 +05:30 • committed by snandini
commit dbc0189477
4 changed files with 425 additions and 7 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 The Linux Foundation. All rights reserved.
* Copyright (c) 2020-2021 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
@ -29,7 +29,9 @@
#include "cdp_txrx_cmn_struct.h"
#include <qdf_nbuf.h>
#ifndef WLAN_FEATURE_PKT_CAPTURE_LITHIUM
#include <htt_internal.h>
#endif
/**
* pkt_capture_data_process_type - data pkt types to process
@ -70,7 +72,7 @@ void pkt_capture_datapkt_process(
qdf_nbuf_t mon_buf_list,
enum pkt_capture_data_process_type type,
uint8_t tid, uint8_t status, bool pktformat,
uint8_t *bssid, htt_pdev_handle pdev,
uint8_t *bssid, void *pdev,
uint8_t tx_retry_cnt);
/**
* pkt_capture_msdu_process_pkts() - process data rx pkts

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 The Linux Foundation. All rights reserved.
* Copyright (c) 2020-2021 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
@ -31,6 +31,9 @@
#include "wlan_pkt_capture_priv.h"
#include "wlan_pkt_capture_objmgr.h"
#include "wlan_objmgr_vdev_obj.h"
#ifdef WLAN_FEATURE_PKT_CAPTURE_LITHIUM
#include "cdp_txrx_stats_struct.h"
#endif
#define pkt_capture_log(level, args...) \
QDF_TRACE(QDF_MODULE_ID_PKT_CAPTURE, level, ## args)
@ -198,4 +201,26 @@ void pkt_capture_record_channel(struct wlan_objmgr_vdev *vdev);
void pkt_capture_mon(struct pkt_capture_cb_context *cb_ctx, qdf_nbuf_t msdu,
struct wlan_objmgr_vdev *vdev, uint16_t ch_freq);
#ifdef WLAN_FEATURE_PKT_CAPTURE_LITHIUM
/**
* pkt_capture_get_pktcap_mode_lithium - Get packet capture mode
*
* Return: enum pkt_capture_mode
*/
enum pkt_capture_mode
pkt_capture_get_pktcap_mode_lithium(void);
/**
* pkt_capture_callback() - callback function for dp wdi events
* @soc: dp_soc handle
* @event: wdi event
* @log_data: nbuf data
* @vdev_id: vdev id
* @status: status
*
* Return: None
*/
void pkt_capture_callback(void *soc, enum WDI_EVENT event, void *log_data,
u_int16_t vdev_id, uint32_t status);
#endif
#endif /* end of _WLAN_PKT_CAPTURE_MAIN_H_ */

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 The Linux Foundation. All rights reserved.
* Copyright (c) 2020-2021 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
@ -155,7 +155,7 @@ static void pkt_capture_tx_get_phy_info(
uint8_t preamble = 0;
uint8_t preamble_type = pktcapture_hdr->preamble;
uint8_t mcs = 0, bw = 0;
uint16_t vht_flags = 0, ht_flags = 0;
uint16_t vht_flags = 0, ht_flags = 0, he_flags = 0;
switch (preamble_type) {
case 0x0:
@ -180,10 +180,18 @@ static void pkt_capture_tx_get_phy_info(
mcs = pktcapture_hdr->mcs;
/* fallthrough */
break;
case 0x4:
he_flags = 1;
default:
break;
}
if (preamble == 0)
tx_status->ofdm_flag = 1;
else if (preamble == 1)
tx_status->cck_flag = 1;
tx_status->mcs = mcs;
tx_status->bw = bw;
tx_status->nr_ant = pktcapture_hdr->nss;
@ -194,6 +202,7 @@ static void pkt_capture_tx_get_phy_info(
tx_status->vht_flag_values3[0] = mcs << 0x4 | (pktcapture_hdr->nss + 1);
tx_status->ht_flags = ht_flags;
tx_status->vht_flags = vht_flags;
tx_status->he_flags = he_flags;
tx_status->rtap_flags |= ((preamble == 1) ? BIT(1) : 0);
if (bw == 0)
tx_status->vht_flag_values2 = 0;
@ -203,6 +212,7 @@ static void pkt_capture_tx_get_phy_info(
tx_status->vht_flag_values2 = 4;
}
#ifndef WLAN_FEATURE_PKT_CAPTURE_LITHIUM
/**
* pkt_capture_update_tx_status() - tx status for tx packets, for
* pkt capture mode(normal tx + offloaded tx) to prepare radiotap header
@ -237,6 +247,23 @@ pkt_capture_update_tx_status(
tx_status->tx_retry_cnt = pktcapture_hdr->tx_retry_cnt;
tx_status->add_rtap_ext = true;
}
#else
static void
pkt_capture_update_tx_status(
void *pdev,
struct mon_rx_status *tx_status,
struct pkt_capture_tx_hdr_elem_t *pktcapture_hdr)
{
pkt_capture_tx_get_phy_info(pktcapture_hdr, tx_status);
tx_status->tsft = (u_int64_t)(pktcapture_hdr->timestamp);
tx_status->ant_signal_db = pktcapture_hdr->rssi_comb;
tx_status->rssi_comb = pktcapture_hdr->rssi_comb;
tx_status->tx_status = pktcapture_hdr->status;
tx_status->tx_retry_cnt = pktcapture_hdr->tx_retry_cnt;
tx_status->add_rtap_ext = true;
}
#endif
/**
* pkt_capture_rx_convert8023to80211() - convert 802.3 packet to 802.11
@ -532,6 +559,7 @@ free_buf:
drop_count = pkt_capture_drop_nbuf_list(buf_list);
}
#ifndef WLAN_FEATURE_PKT_CAPTURE_LITHIUM
/**
* pkt_capture_tx_data_cb() - process data tx and rx packets
* for pkt capture mode. (normal tx/rx + offloaded tx/rx)
@ -703,13 +731,211 @@ pkt_capture_tx_data_cb(
free_buf:
drop_count = pkt_capture_drop_nbuf_list(nbuf_list);
}
#else
/**
* pkt_capture_get_vdev_bss_peer_mac_addr() - API to get bss peer mac address
* @vdev: objmgr vdev
* @bss_peer_mac_address: bss peer mac address
*.
* Helper function to get bss peer mac address
*
* Return: if success pmo vdev ctx else NULL
*/
static QDF_STATUS pkt_capture_get_vdev_bss_peer_mac_addr(
struct wlan_objmgr_vdev *vdev,
struct qdf_mac_addr *bss_peer_mac_address)
{
struct wlan_objmgr_peer *peer;
if (!vdev) {
qdf_print("vdev is null");
return QDF_STATUS_E_INVAL;
}
peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_PKT_CAPTURE_ID);
if (!peer) {
qdf_print("peer is null");
return QDF_STATUS_E_INVAL;
}
wlan_peer_obj_lock(peer);
qdf_mem_copy(bss_peer_mac_address->bytes, wlan_peer_get_macaddr(peer),
QDF_MAC_ADDR_SIZE);
wlan_peer_obj_unlock(peer);
wlan_objmgr_peer_release_ref(peer, WLAN_PKT_CAPTURE_ID);
return QDF_STATUS_SUCCESS;
}
static void
pkt_capture_tx_data_cb(
void *context, void *ppdev, void *nbuf_list, uint8_t vdev_id,
uint8_t tid, uint16_t status, bool pkt_format,
uint8_t *bssid, uint8_t tx_retry_cnt)
{
qdf_nbuf_t msdu, next_buf;
struct pkt_capture_vdev_priv *vdev_priv;
struct wlan_objmgr_vdev *vdev = context;
struct pkt_capture_cb_context *cb_ctx;
uint8_t drop_count;
struct htt_tx_data_hdr_information *cmpl_desc = NULL;
struct pkt_capture_tx_hdr_elem_t pktcapture_hdr = {0};
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 ether_type;
uint32_t headroom;
uint16_t seq_no, fc_ctrl;
struct mon_rx_status tx_status = {0};
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 };
struct qdf_mac_addr bss_peer_mac_address;
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 = nbuf_list;
while (msdu) {
next_buf = qdf_nbuf_queue_next(msdu);
qdf_nbuf_set_next(msdu, NULL); /* Add NULL terminator */
cmpl_desc = (struct htt_tx_data_hdr_information *)
(qdf_nbuf_data(msdu));
pktcapture_hdr.timestamp = cmpl_desc->phy_timestamp_l32;
pktcapture_hdr.preamble = cmpl_desc->preamble;
pktcapture_hdr.mcs = cmpl_desc->mcs;
pktcapture_hdr.bw = cmpl_desc->bw;
pktcapture_hdr.nss = cmpl_desc->nss;
pktcapture_hdr.rssi_comb = cmpl_desc->rssi;
pktcapture_hdr.rate = cmpl_desc->rate;
pktcapture_hdr.stbc = cmpl_desc->stbc;
pktcapture_hdr.sgi = cmpl_desc->sgi;
pktcapture_hdr.ldpc = cmpl_desc->ldpc;
pktcapture_hdr.beamformed = cmpl_desc->beamformed;
pktcapture_hdr.status = status;
pktcapture_hdr.tx_retry_cnt = tx_retry_cnt;
qdf_nbuf_pull_head(
msdu,
sizeof(struct htt_tx_data_hdr_information));
if (pkt_format == TXRX_PKTCAPTURE_PKT_FORMAT_8023) {
eth_hdr = (struct ethernet_hdr_t *)qdf_nbuf_data(msdu);
hdsize = sizeof(struct ethernet_hdr_t);
wh = (struct ieee80211_frame *)localbuf;
*(uint16_t *)wh->i_dur = 0;
new_hdsize = 0;
pkt_capture_get_vdev_bss_peer_mac_addr(
vdev,
&bss_peer_mac_address);
qdf_mem_copy(bssid, bss_peer_mac_address.bytes,
QDF_MAC_ADDR_SIZE);
if (vdev_id == HTT_INVALID_VDEV)
qdf_mem_copy(bssid, eth_hdr->dest_addr,
QDF_MAC_ADDR_SIZE);
/* BSSID , SA , DA */
qdf_mem_copy(wh->i_addr1, bssid,
QDF_MAC_ADDR_SIZE);
qdf_mem_copy(wh->i_addr2, eth_hdr->src_addr,
QDF_MAC_ADDR_SIZE);
qdf_mem_copy(wh->i_addr3, eth_hdr->dest_addr,
QDF_MAC_ADDR_SIZE);
seq_no = cmpl_desc->seqno;
seq_no = (seq_no << IEEE80211_SEQ_SEQ_SHIFT) &
IEEE80211_SEQ_SEQ_MASK;
fc_ctrl = cmpl_desc->framectrl;
qdf_mem_copy(wh->i_fc, &fc_ctrl, sizeof(fc_ctrl));
qdf_mem_copy(wh->i_seq, &seq_no, sizeof(seq_no));
wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
new_hdsize = sizeof(struct ieee80211_frame);
if (wh->i_fc[0] & QDF_IEEE80211_FC0_SUBTYPE_QOS) {
qos_cntl = (struct ieee80211_qoscntl *)
(localbuf + new_hdsize);
qos_cntl->i_qos[0] =
(tid & IEEE80211_QOS_TID);
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);
}
pkt_capture_update_tx_status(
ppdev,
&tx_status,
&pktcapture_hdr);
/*
* Calculate the headroom and adjust head
* to prepare radiotap header.
*/
headroom = qdf_nbuf_headroom(msdu);
qdf_nbuf_update_radiotap(&tx_status, msdu, headroom);
pkt_capture_mon(cb_ctx, msdu, vdev, 0);
msdu = next_buf;
}
return;
free_buf:
drop_count = pkt_capture_drop_nbuf_list(nbuf_list);
}
#endif
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 *bssid, void *pdev,
uint8_t tx_retry_cnt)
{
uint8_t drop_count;

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 The Linux Foundation. All rights reserved.
* Copyright (c) 2020-2021 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
@ -21,6 +21,9 @@
* internally in pkt_capture component only.
*/
#ifdef WLAN_FEATURE_PKT_CAPTURE_LITHIUM
#include <dp_types.h>
#endif
#include "wlan_pkt_capture_main.h"
#include "cfg_ucfg_api.h"
#include "wlan_pkt_capture_mon_thread.h"
@ -31,6 +34,166 @@
static struct wlan_objmgr_vdev *gp_pkt_capture_vdev;
#ifdef WLAN_FEATURE_PKT_CAPTURE_LITHIUM
wdi_event_subscribe PKT_CAPTURE_TX_SUBSCRIBER;
/**
* pkt_capture_wdi_event_subscribe() - Subscribe pkt capture callbacks
* @psoc: pointer to psoc object
*
* Return: None
*/
static void pkt_capture_wdi_event_subscribe(struct wlan_objmgr_psoc *psoc)
{
void *soc = cds_get_context(QDF_MODULE_ID_SOC);
uint8_t pdev_id = WMI_PDEV_ID_SOC;
PKT_CAPTURE_TX_SUBSCRIBER.callback =
pkt_capture_callback;
PKT_CAPTURE_TX_SUBSCRIBER.context = wlan_psoc_get_dp_handle(psoc);
cdp_wdi_event_sub(soc, pdev_id, &PKT_CAPTURE_TX_SUBSCRIBER,
WDI_EVENT_PKT_CAPTURE_TX_DATA);
}
/**
* pkt_capture_wdi_event_unsubscribe() - Unsubscribe pkt capture callbacks
* @psoc: pointer to psoc object
*
* Return: None
*/
static void pkt_capture_wdi_event_unsubscribe(struct wlan_objmgr_psoc *psoc)
{
void *soc = cds_get_context(QDF_MODULE_ID_SOC);
uint8_t pdev_id = WMI_PDEV_ID_SOC;
cdp_wdi_event_unsub(soc, pdev_id, &PKT_CAPTURE_TX_SUBSCRIBER,
WDI_EVENT_PKT_CAPTURE_TX_DATA);
}
enum pkt_capture_mode
pkt_capture_get_pktcap_mode_lithium()
{
enum pkt_capture_mode mode = PACKET_CAPTURE_MODE_DISABLE;
struct pkt_capture_vdev_priv *vdev_priv;
struct wlan_objmgr_vdev *vdev;
vdev = pkt_capture_get_vdev();
if (!vdev)
return PACKET_CAPTURE_MODE_DISABLE;
vdev_priv = pkt_capture_vdev_get_priv(vdev);
if (!vdev_priv)
pkt_capture_err("vdev_priv is NULL");
else
mode = vdev_priv->cb_ctx->pkt_capture_mode;
return mode;
}
void pkt_capture_callback(void *soc, enum WDI_EVENT event, void *log_data,
u_int16_t vdev_id, uint32_t status)
{
uint8_t bssid[QDF_MAC_ADDR_SIZE];
uint8_t tid = 0, tx_retry_cnt = 0;
struct htt_tx_data_hdr_information cmpl_desc;
struct htt_tx_data_hdr_information *ptr_cmpl_desc;
struct hal_tx_completion_status ppdu_hdr = {0};
uint32_t txcap_hdr_size = sizeof(struct htt_tx_data_hdr_information);
struct dp_soc *psoc = soc;
switch (event) {
case WDI_EVENT_PKT_CAPTURE_TX_DATA:
{
struct dp_tx_desc_s *desc = log_data;
qdf_nbuf_t netbuf;
int nbuf_len;
hal_tx_comp_get_status(&desc->comp, &ppdu_hdr, psoc->hal_soc);
if (!(pkt_capture_get_pktcap_mode_lithium() &
PKT_CAPTURE_MODE_DATA_ONLY)) {
return;
}
cmpl_desc.phy_timestamp_l32 = ppdu_hdr.tsf;
cmpl_desc.preamble = ppdu_hdr.pkt_type;
cmpl_desc.mcs = ppdu_hdr.mcs;
cmpl_desc.bw = ppdu_hdr.bw;
/* nss is not updated */
cmpl_desc.nss = 0;
cmpl_desc.rssi = ppdu_hdr.ack_frame_rssi;
/* rate is not updated */
cmpl_desc.rate = 0;
cmpl_desc.stbc = ppdu_hdr.stbc;
cmpl_desc.sgi = ppdu_hdr.sgi;
cmpl_desc.ldpc = ppdu_hdr.ldpc;
/* beamformed is not updated */
cmpl_desc.beamformed = 0;
cmpl_desc.framectrl = 0x0008;
cmpl_desc.tx_retry_cnt = ppdu_hdr.transmit_cnt;
tid = ppdu_hdr.tid;
status = ppdu_hdr.status;
tx_retry_cnt = ppdu_hdr.transmit_cnt;
nbuf_len = qdf_nbuf_len(desc->nbuf);
netbuf = qdf_nbuf_alloc(NULL,
roundup(nbuf_len + RESERVE_BYTES, 4),
RESERVE_BYTES, 4, false);
if (!netbuf)
return;
qdf_nbuf_put_tail(netbuf, nbuf_len);
qdf_mem_copy(qdf_nbuf_data(netbuf),
qdf_nbuf_data(desc->nbuf), nbuf_len);
if (qdf_unlikely(qdf_nbuf_headroom(netbuf) < txcap_hdr_size)) {
netbuf = qdf_nbuf_realloc_headroom(netbuf,
txcap_hdr_size);
if (!netbuf) {
QDF_TRACE(QDF_MODULE_ID_PKT_CAPTURE,
QDF_TRACE_LEVEL_ERROR,
FL("No headroom"));
return;
}
}
if (!qdf_nbuf_push_head(netbuf, txcap_hdr_size)) {
QDF_TRACE(QDF_MODULE_ID_PKT_CAPTURE,
QDF_TRACE_LEVEL_ERROR, FL("No headroom"));
qdf_nbuf_free(netbuf);
return;
}
ptr_cmpl_desc =
(struct htt_tx_data_hdr_information *)qdf_nbuf_data(netbuf);
qdf_mem_copy(ptr_cmpl_desc, &cmpl_desc, txcap_hdr_size);
pkt_capture_datapkt_process(
vdev_id, netbuf, TXRX_PROCESS_TYPE_DATA_TX_COMPL,
tid, status, TXRX_PKTCAPTURE_PKT_FORMAT_8023,
bssid, NULL, tx_retry_cnt);
break;
}
default:
break;
}
}
#else
static void pkt_capture_wdi_event_subscribe(struct wlan_objmgr_psoc *psoc)
{
}
static void pkt_capture_wdi_event_unsubscribe(struct wlan_objmgr_psoc *psoc)
{
}
#endif
struct wlan_objmgr_vdev *pkt_capture_get_vdev()
{
return gp_pkt_capture_vdev;
@ -92,6 +255,7 @@ pkt_capture_register_callbacks(struct wlan_objmgr_vdev *vdev,
target_if_pkt_capture_register_tx_ops(&vdev_priv->tx_ops);
target_if_pkt_capture_register_rx_ops(&vdev_priv->rx_ops);
pkt_capture_wdi_event_subscribe(psoc);
pkt_capture_record_channel(vdev);
status = tgt_pkt_capture_register_ev_handler(vdev);
@ -169,6 +333,7 @@ QDF_STATUS pkt_capture_deregister_callbacks(struct wlan_objmgr_vdev *vdev)
wait_for_completion(&vdev_priv->mon_ctx->mon_register_event);
pkt_capture_drop_monpkt(vdev_priv->mon_ctx);
pkt_capture_wdi_event_unsubscribe(psoc);
status = tgt_pkt_capture_unregister_ev_handler(vdev);
if (QDF_IS_STATUS_ERROR(status))
pkt_capture_err("Unable to unregister event handlers");