qcacmn: Add new feature to support protocol tags

With this feature, using appropriate commands, link layer, network layer,
transport layer and some of the application protocols can be tagged with
the user provided tag values for easier identification of protocols. The
supported protocols today are as follows.

ARP, DHCPv4, DHCPv6, DNS over TCP (v4), DNS over TCP (v6), DNS over UDP
(v4), DNS over UDP (v6), ICMPv4, ICMPv6, TCPv4, TCPv6, UDPv4,
UDPv6, IPv4, IPv6, EAP.

Receive packets are tagged by hardware. Tags are applied after the first
matching rule. Hence it is recommended that the rules are
programmed in such a way that tags are configured from application layer
to data link layer to get expected results.

Change-Id: Ibdc2bd2b78234f482074955e89fb93f05988eaca
This commit is contained in:
Karunakar Dasineni 2019-03-19 23:04:59 -07:00 • committed by nshrivas
commit 142f9baf47
20 changed files with 631 additions and 12 deletions

View file

@ -26,6 +26,7 @@
#define _CDP_TXRX_CTRL_H_
#include "cdp_txrx_handle.h"
#include "cdp_txrx_cmn_struct.h"
#include "cdp_txrx_cmn.h"
#include "cdp_txrx_ops.h"
static inline int cdp_is_target_ar900b
@ -702,6 +703,67 @@ cdp_get_pldev(ol_txrx_soc_handle soc,
return soc->ops->ctrl_ops->txrx_get_pldev(pdev);
}
#ifdef WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG
/**
* cdp_update_pdev_rx_protocol_tag() - wrapper function to set the protocol
* tag in CDP layer from cfg layer
* @soc: SOC TXRX handle
* @pdev: CDP pdev pointer
* @protocol_mask: Bitmap for protocol for which tagging is enabled
* @protocol_type: Protocol type for which the tag should be update
* @tag: Actual tag value for the given prototype
* Return: Returns QDF_STATUS_SUCCESS/FAILURE
*/
static inline QDF_STATUS
cdp_update_pdev_rx_protocol_tag(ol_txrx_soc_handle soc,
struct cdp_pdev *pdev, uint32_t protocol_mask,
uint16_t protocol_type, uint16_t tag)
{
if (!soc || !soc->ops) {
dp_err("Invalid SOC instance");
QDF_BUG(0);
return QDF_STATUS_E_FAILURE;
}
if (!soc->ops->ctrl_ops ||
!soc->ops->ctrl_ops->txrx_update_pdev_rx_protocol_tag)
return QDF_STATUS_E_FAILURE;
return soc->ops->ctrl_ops->txrx_update_pdev_rx_protocol_tag
(pdev, protocol_mask, protocol_type, tag);
}
#ifdef WLAN_SUPPORT_RX_TAG_STATISTICS
/**
* cdp_dump_pdev_rx_protocol_tag_stats() - wrapper function to dump the protocol
tag statistics for given or all protocols
* @soc: SOC TXRX handle
* @pdev: CDP pdev pointer
* @protocol_type: Protocol type for which the tag should be update
* Return: Returns QDF_STATUS_SUCCESS/FAILURE
*/
static inline QDF_STATUS
cdp_dump_pdev_rx_protocol_tag_stats(ol_txrx_soc_handle soc,
struct cdp_pdev *pdev,
uint16_t protocol_type)
{
if (!soc || !soc->ops) {
dp_err("Invalid SOC instance");
QDF_BUG(0);
return QDF_STATUS_E_FAILURE;
}
if (!soc->ops->ctrl_ops ||
!soc->ops->ctrl_ops->txrx_dump_pdev_rx_protocol_tag_stats)
return QDF_STATUS_E_FAILURE;
soc->ops->ctrl_ops->txrx_dump_pdev_rx_protocol_tag_stats(pdev,
protocol_type);
return QDF_STATUS_SUCCESS;
}
#endif /* WLAN_SUPPORT_RX_TAG_STATISTICS */
#endif /* WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG */
#ifdef ATH_SUPPORT_NAC_RSSI
/**
* cdp_vdev_config_for_nac_rssi(): To invoke dp callback for nac rssi config

View file

@ -649,6 +649,17 @@ struct cdp_ctrl_ops {
*txrx_pdev_handle, char *macaddr, uint8_t enb_dsb);
void (*calculate_delay_stats)(struct cdp_vdev *vdev, qdf_nbuf_t nbuf);
#ifdef WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG
QDF_STATUS (*txrx_update_pdev_rx_protocol_tag)(
struct cdp_pdev *txrx_pdev_handle,
uint32_t protocol_mask, uint16_t protocol_type,
uint16_t tag);
#ifdef WLAN_SUPPORT_RX_TAG_STATISTICS
void (*txrx_dump_pdev_rx_protocol_tag_stats)(
struct cdp_pdev *txrx_pdev_handle,
uint16_t protocol_type);
#endif /* WLAN_SUPPORT_RX_TAG_STATISTICS */
#endif /* WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG */
};
struct cdp_me_ops {

View file

@ -1138,6 +1138,27 @@ struct cdp_htt_rx_pdev_stats {
struct cdp_htt_rx_pdev_fw_stats_phy_err_tlv fw_stats_phy_err_tlv;
};
#ifdef WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG
/* Since protocol type enumeration value is passed as CCE metadata
* to firmware, add a constant offset before passing it to firmware
*/
#define RX_PROTOCOL_TAG_START_OFFSET 128
/* This should align with packet type enumerations in ieee80211_ioctl.h
* and wmi_unified_param.h files
*/
#define RX_PROTOCOL_TAG_MAX 24
/* Macro that should be used to dump the statistics counter for all
* protocol types
*/
#define RX_PROTOCOL_TAG_ALL 0xff
#ifdef WLAN_SUPPORT_RX_TAG_STATISTICS
struct cdp_pdev_rx_protocol_tag_stats {
uint32_t tag_ctr;
};
#endif /* WLAN_SUPPORT_RX_TAG_STATISTICS */
#endif /* WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG */
/* struct cdp_pdev_stats - pdev stats
* @msdu_not_done: packets dropped because msdu done bit not set
* @mec:Multicast Echo check
@ -1213,6 +1234,12 @@ struct cdp_pdev_stats {
/* Received wdi messages from fw */
uint32_t wdi_event[CDP_WDI_NUM_EVENTS];
struct cdp_tid_stats tid_stats;
#if defined(WLAN_SUPPORT_RX_TAG_STATISTICS) && \
defined(WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG)
struct cdp_pdev_rx_protocol_tag_stats
rx_protocol_tag_stats[RX_PROTOCOL_TAG_MAX];
#endif /* WLAN_SUPPORT_RX_TAG_STATISTICS */
};
#ifndef BIG_ENDIAN_HOST

View file

@ -9525,6 +9525,90 @@ dp_enable_peer_based_pktlog(
return QDF_STATUS_SUCCESS;
}
#ifdef WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG
/**
* dp_update_pdev_rx_protocol_tag - Add/remove a protocol tag that should be
* applied to the desired protocol type packets
* @txrx_pdev_handle: cdp_pdev handle
* @enable_rx_protocol_tag - bitmask that indicates what protocol types
* are enabled for tagging. zero indicates disable feature, non-zero indicates
* enable feature
* @protocol_type: new protocol type for which the tag is being added
* @tag: user configured tag for the new protocol
*
* Return: QDF_STATUS
*/
static QDF_STATUS
dp_update_pdev_rx_protocol_tag(struct cdp_pdev *pdev_handle,
uint32_t enable_rx_protocol_tag,
uint16_t protocol_type,
uint16_t tag)
{
struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle;
/*
* dynamically enable/disable tagging based on enable_rx_protocol_tag
* flag.
*/
if (enable_rx_protocol_tag) {
/* Tagging for one or more protocols has been set by user */
pdev->rx_protocol_tagging_enabled = true;
} else {
/*
* No protocols being tagged, disable feature till next add
* operation
*/
pdev->rx_protocol_tagging_enabled = false;
}
if (tag == 0) {
/*
* In case of tag deletion, clear the stats for given
* protocol type.
*/
DP_STATS_UPD(pdev,
rx_protocol_tag_stats[protocol_type].tag_ctr, 0);
}
pdev->rx_proto_tag_map[protocol_type].tag = tag;
return QDF_STATUS_SUCCESS;
}
#ifdef WLAN_SUPPORT_RX_TAG_STATISTICS
static void
dp_dump_pdev_rx_protocol_tag_stats(struct cdp_pdev *pdev_handle,
uint16_t protocol_type)
{
struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle;
if (protocol_type != RX_PROTOCOL_TAG_ALL &&
protocol_type >= RX_PROTOCOL_TAG_MAX) {
DP_PRINT_STATS("%s : Invalid protocol type : %u\n",
__func__, protocol_type);
return;
}
if (protocol_type == RX_PROTOCOL_TAG_ALL) {
uint8_t protocol_index = 0;
for (protocol_index = 0; protocol_index < RX_PROTOCOL_TAG_MAX;
protocol_index++) {
DP_PRINT_STATS("PROTO: %d, TAG: %u COUNT = %u\n",
protocol_index,
pdev->rx_proto_tag_map[protocol_index].tag,
pdev->stats.
rx_protocol_tag_stats[protocol_index].tag_ctr);
}
} else {
DP_PRINT_STATS("PROTO: %d, TAG: %u COUNT = %u\n",
protocol_type,
pdev->rx_proto_tag_map[protocol_type].tag,
pdev->stats.rx_protocol_tag_stats[protocol_type].tag_ctr);
}
}
#endif /* WLAN_SUPPORT_RX_TAG_STATISTICS */
#endif /* WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG */
static QDF_STATUS dp_peer_map_attach_wifi3(struct cdp_soc_t *soc_hdl,
uint32_t max_peers,
uint32_t max_ast_index,
@ -9973,6 +10057,13 @@ static struct cdp_ctrl_ops dp_ops_ctrl = {
.txrx_get_vdev_param = dp_get_vdev_param,
.enable_peer_based_pktlog = dp_enable_peer_based_pktlog,
.calculate_delay_stats = dp_calculate_delay_stats,
#ifdef WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG
.txrx_update_pdev_rx_protocol_tag = dp_update_pdev_rx_protocol_tag,
#ifdef WLAN_SUPPORT_RX_TAG_STATISTICS
.txrx_dump_pdev_rx_protocol_tag_stats =
dp_dump_pdev_rx_protocol_tag_stats,
#endif /* WLAN_SUPPORT_RX_TAG_STATISTICS */
#endif /* WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG */
};
static struct cdp_me_ops dp_ops_me = {

View file

@ -1856,6 +1856,9 @@ done:
dp_set_rx_queue(nbuf, ring_id);
/* Update the protocol tag in SKB based on CCE metadata */
dp_rx_update_protocol_tag(soc, vdev, nbuf, rx_tlv_hdr, true);
/*
* HW structures call this L3 header padding --
* even though this is actually the offset from

View file

@ -929,6 +929,181 @@ static inline bool check_qwrap_multicast_loopback(struct dp_vdev *vdev,
}
#endif
#if defined(WLAN_SUPPORT_RX_TAG_STATISTICS) && \
defined(WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG)
/*
* dp_rx_update_rx_protocol_tag_stats() - Increments the protocol tag stats
* for the given protocol type
*
* @soc: core txrx main context
* @pdev: TXRX pdev context for which the stats should be incremented
* @protocol_index: Protocol index for which the stats should be incremented
* Return: void
*/
static inline void dp_rx_update_rx_protocol_tag_stats(struct dp_pdev *pdev,
uint16_t protocol_index)
{
DP_STATS_INC(pdev, rx_protocol_tag_stats[protocol_index].tag_ctr, 1);
}
#else
static inline void dp_rx_update_rx_protocol_tag_stats(struct dp_pdev *pdev,
uint16_t protocol_index)
{
}
#endif /* WLAN_SUPPORT_RX_TAG_STATISTICS */
/*
* dp_rx_update_protocol_tag() - Reads CCE metadata from the RX MSDU end TLV
* and set the corresponding tag in QDF packet
*
* @soc : core txrx main context
* @vdev : vdev on which the packet is received
* @nbuf : QDF packet buffer on which the protocol tag should be set
* @rx_tlv_hdr : base address where the RX TLVs starts
* @update_stats : Flag to indicate whether to update stats or not
* Return : void
*/
#ifdef WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG
static inline void
dp_rx_update_protocol_tag(struct dp_soc *soc, struct dp_vdev *vdev,
qdf_nbuf_t nbuf, uint8_t *rx_tlv_hdr,
bool update_stats)
{
uint16_t cce_metadata = RX_PROTOCOL_TAG_START_OFFSET;
bool cce_match = false;
struct dp_pdev *pdev = vdev->pdev;
uint16_t protocol_tag = 0;
if (qdf_unlikely(pdev->rx_protocol_tagging_enabled)) {
/*
* In case of raw frames, rx_attention and rx_msdu_end tlv
* may be stale or invalid. Do not tag such frames.
* Default decap_type is set to ethernet for monitor vdev,
* therefore, cannot check decap_type for monitor mode.
* We will call this only for eth frames from dp_rx_mon_dest.c.
*/
if (qdf_unlikely((pdev->monitor_vdev &&
pdev->monitor_vdev == vdev) ||
(vdev->rx_decap_type == htt_cmn_pkt_type_ethernet))) {
/*
* Check whether HW has filled in the CCE metadata in
* this packet, if not filled, just return
*/
if (qdf_unlikely(
hal_rx_msdu_cce_match_get(rx_tlv_hdr))) {
cce_match = true;
/* Get the cce_metadata from RX MSDU TLV */
cce_metadata =
(hal_rx_msdu_cce_metadata_get(rx_tlv_hdr) &
RX_MSDU_END_16_CCE_METADATA_MASK);
/*
* Received CCE metadata should be within the
* valid limits
*/
qdf_assert_always((cce_metadata >=
RX_PROTOCOL_TAG_START_OFFSET) &&
(cce_metadata <
(RX_PROTOCOL_TAG_START_OFFSET +
RX_PROTOCOL_TAG_MAX)));
/*
* The CCE metadata received is just the
* packet_type + RX_PROTOCOL_TAG_START_OFFSET
*/
cce_metadata -= RX_PROTOCOL_TAG_START_OFFSET;
/*
* Update the QDF packet with the user-specified
* tag/metadata by looking up tag value for
* received protocol type.
*/
protocol_tag =
pdev->rx_proto_tag_map[cce_metadata].tag;
qdf_nbuf_set_rx_protocol_tag(nbuf,
protocol_tag);
if (qdf_unlikely(update_stats))
dp_rx_update_rx_protocol_tag_stats(
pdev, cce_metadata);
}
}
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_LOW,
"Seq:%u decap:%u CCE Match:%d ProtoID:%u Tag:%u US:%d",
hal_rx_get_rx_sequence(rx_tlv_hdr),
vdev->rx_decap_type, cce_match, cce_metadata,
protocol_tag, update_stats);
}
}
#else
static inline void
dp_rx_update_protocol_tag(struct dp_soc *soc, struct dp_vdev *vdev,
qdf_nbuf_t nbuf, uint8_t *rx_tlv_hdr,
bool update_stats)
{
/* Stub API */
}
#endif /* WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG */
/*
* dp_rx_mon_update_protocol_tag() - Performs necessary checks for monitor mode
* and then tags appropriate packets
* @soc : core txrx main context
* @vdev : pdev on which packet is received
* @msdu : QDF packet buffer on which the protocol tag should be set
* @rx_desc : base address where the RX TLVs start
* Return : void
*/
#ifdef WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG
static inline
void dp_rx_mon_update_protocol_tag(struct dp_soc *soc, struct dp_pdev *dp_pdev,
qdf_nbuf_t msdu, void *rx_desc)
{
/*
* Update the protocol tag in SKB for packets received on BSS.
* Do not update tag stats since it would double actual received count
*/
if (qdf_unlikely(dp_pdev->rx_protocol_tagging_enabled &&
dp_pdev->monitor_vdev &&
(1 == dp_pdev->ppdu_info.rx_status.rxpcu_filter_pass)
)) {
uint32_t msdu_ppdu_id =
HAL_RX_HW_DESC_GET_PPDUID_GET(rx_desc);
if (msdu_ppdu_id !=
dp_pdev->ppdu_info.com_info.ppdu_id) {
QDF_TRACE(
QDF_MODULE_ID_DP,
QDF_TRACE_LEVEL_ERROR,
"msdu_ppdu_id=%x,com_info.ppdu_id=%x",
msdu_ppdu_id,
dp_pdev->ppdu_info.com_info.ppdu_id);
} else {
struct mon_rx_status *pmon_rx_status;
pmon_rx_status =
&dp_pdev->ppdu_info.rx_status;
if (pmon_rx_status->
frame_control_info_valid &&
((pmon_rx_status->frame_control &
IEEE80211_FC0_TYPE_MASK) ==
IEEE80211_FC0_TYPE_DATA)) {
dp_rx_update_protocol_tag(
soc,
dp_pdev->monitor_vdev,
msdu,
rx_desc, false);
}
}
}
}
#else
static inline
void dp_rx_mon_update_protocol_tag(struct dp_soc *soc, struct dp_pdev *dp_pdev,
qdf_nbuf_t msdu, void *rx_desc)
{
/* Stub API */
}
#endif /* WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG */
/*
* dp_rx_buffers_replenish() - replenish rxdma ring with rx nbufs
* called during dp rx initialization

View file

@ -816,6 +816,13 @@ dp_rx_null_q_desc_handle(struct dp_soc *soc, qdf_nbuf_t nbuf,
DP_STATS_INC_PKT(peer, rx.to_stack, 1,
qdf_nbuf_len(nbuf));
/*
* Update the protocol tag in SKB based on
* CCE metadata
*/
dp_rx_update_protocol_tag(soc, vdev, nbuf,
rx_tlv_hdr, true);
if (qdf_unlikely(hal_rx_msdu_end_da_is_mcbc_get(
rx_tlv_hdr) &&
(vdev->rx_decap_type ==
@ -992,6 +999,9 @@ process_rx:
if (qdf_unlikely(vdev->rx_decap_type == htt_cmn_pkt_type_raw)) {
dp_rx_deliver_raw(vdev, nbuf, peer);
} else {
/* Update the protocol tag in SKB based on CCE metadata */
dp_rx_update_protocol_tag(soc, vdev, nbuf,
rx_tlv_hdr, true);
DP_STATS_INC(peer, rx.to_stack.num, 1);
vdev->osif_rx(vdev->osif_vdev, nbuf);
}

View file

@ -352,9 +352,8 @@ dp_rx_mon_mpdu_pop(struct dp_soc *soc, uint32_t mac_id,
QDF_TRACE(QDF_MODULE_ID_DP,
QDF_TRACE_LEVEL_DEBUG,
"[%s] i=%d, ppdu_id=%x, num_msdus = %u\n",
__func__, i, *ppdu_id,
num_msdus);
"[%s] i=%d, ppdu_id=%x, num_msdus = %u",
__func__, i, *ppdu_id, num_msdus);
if (is_first_msdu) {
if (!HAL_RX_HW_DESC_MPDU_VALID(
@ -742,6 +741,9 @@ qdf_nbuf_t dp_rx_mon_restitch_mpdu_from_msdus(struct dp_soc *soc,
is_first_frag = 0;
}
/* Update protocol tag for MSDU */
dp_rx_mon_update_protocol_tag(soc, dp_pdev, msdu_orig, rx_desc);
dest = qdf_nbuf_put_tail(prev_buf,
msdu_llc_len + amsdu_pad);

View file

@ -1134,6 +1134,13 @@ struct ppdu_info {
TAILQ_ENTRY(ppdu_info) ppdu_info_list_elem;
};
#ifdef WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG
struct rx_protocol_tag_map {
/* This is the user configured tag for the said protocol type */
uint16_t tag;
};
#endif /* WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG */
/* PDEV level structure for data path */
struct dp_pdev {
/**
@ -1430,6 +1437,19 @@ struct dp_pdev {
/* unique cookie required for peer session */
uint32_t next_peer_cookie;
#ifdef WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG
/*
* Run time enabled when the first protocol tag is added,
* run time disabled when the last protocol tag is deleted
*/
bool rx_protocol_tagging_enabled;
/*
* The protocol type is used as array index to save
* user provided tag info
*/
struct rx_protocol_tag_map rx_proto_tag_map[RX_PROTOCOL_TAG_MAX];
#endif /* WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG */
};
struct dp_peer;