From bbc4de06d7a1922353b244ff808c966ed6e9938e Mon Sep 17 00:00:00 2001 From: Adil Saeed Musthafa Date: Thu, 12 Dec 2019 14:34:44 -0800 Subject: [PATCH] qcacmn: per-peer protocol count tracking Maintain packet counters for each peer based on protocol. Following 3 protocols are supported * ICMP (IPv4) * ARP (IPv4) * EAP Change-Id: I56dd9bbedd7b6698b7d155a524b242e8cabd76c3 CRs-Fixed: 2604877 --- dp/inc/cdp_txrx_ctrl.h | 174 +++++++++++++++++++++++++++++++++ dp/inc/cdp_txrx_ops.h | 47 ++++++++- dp/inc/cdp_txrx_stats_struct.h | 34 +++++++ dp/wifi3.0/dp_internal.h | 42 ++++++++ dp/wifi3.0/dp_main.c | 62 ++++++++++++ dp/wifi3.0/dp_rx.c | 25 +++++ dp/wifi3.0/dp_rx_err.c | 2 + dp/wifi3.0/dp_stats.c | 112 +++++++++++++++++++++ dp/wifi3.0/dp_tx.c | 26 +++++ dp/wifi3.0/dp_types.h | 15 +++ 10 files changed, 538 insertions(+), 1 deletion(-) diff --git a/dp/inc/cdp_txrx_ctrl.h b/dp/inc/cdp_txrx_ctrl.h index 4ee13bf8a0..5c874f91b1 100644 --- a/dp/inc/cdp_txrx_ctrl.h +++ b/dp/inc/cdp_txrx_ctrl.h @@ -284,6 +284,144 @@ cdp_txrx_get_psoc_param(ol_txrx_soc_handle soc, return soc->ops->ctrl_ops->txrx_get_psoc_param(soc, type, val); } +#ifdef VDEV_PEER_PROTOCOL_COUNT +/** + * cdp_set_vdev_peer_protocol_count() - set per-peer protocol count tracking + * + * @soc - pointer to the soc + * @vdev - the data virtual device object + * @enable - enable per-peer protocol count + * + * Set per-peer protocol count feature enable + * + * Return: void + */ +static inline +void cdp_set_vdev_peer_protocol_count(ol_txrx_soc_handle soc, int8_t vdev_id, + bool enable) +{ + if (!soc || !soc->ops) { + QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, + "%s: Invalid Instance:", __func__); + QDF_BUG(0); + return; + } + + if (!soc->ops->ctrl_ops || + !soc->ops->ctrl_ops->txrx_enable_peer_protocol_count) + return; + + soc->ops->ctrl_ops->txrx_enable_peer_protocol_count(soc, vdev_id, + enable); +} + +/** + * cdp_set_vdev_peer_protocol_drop_mask() - set per-peer protocol drop mask + * + * @soc - pointer to the soc + * @vdev - the data virtual device object + * @drop_mask - drop_mask + * + * Set per-peer protocol drop_mask + * + * Return - void + */ +static inline +void cdp_set_vdev_peer_protocol_drop_mask(ol_txrx_soc_handle soc, + int8_t vdev_id, int drop_mask) +{ + if (!soc || !soc->ops) { + QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, + "%s: Invalid Instance:", __func__); + QDF_BUG(0); + return; + } + + if (!soc->ops->ctrl_ops || + !soc->ops->ctrl_ops->txrx_set_peer_protocol_drop_mask) + return; + + soc->ops->ctrl_ops->txrx_set_peer_protocol_drop_mask(soc, vdev_id, + drop_mask); +} + +/** + * cdp_is_vdev_peer_protocol_count_enabled() - whether peer-protocol tracking + * enabled + * + * @soc - pointer to the soc + * @vdev - the data virtual device object + * + * Get whether peer protocol count feature enabled or not + * + * Return: whether feature enabled or not + */ +static inline +int cdp_is_vdev_peer_protocol_count_enabled(ol_txrx_soc_handle soc, + int8_t vdev_id) +{ + 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->txrx_is_peer_protocol_count_enabled) + return 0; + + return soc->ops->ctrl_ops->txrx_is_peer_protocol_count_enabled(soc, + vdev_id); +} + +/** + * cdp_get_peer_protocol_drop_mask() - get per-peer protocol count drop-mask + * + * @soc - pointer to the soc + * @vdev - the data virtual device object + * + * Get peer-protocol-count drop-mask + * + * Return: peer-protocol-count drop-mask + */ +static inline +int cdp_get_peer_protocol_drop_mask(ol_txrx_soc_handle soc, int8_t vdev_id) +{ + 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->txrx_get_peer_protocol_drop_mask) + return 0; + + return soc->ops->ctrl_ops->txrx_get_peer_protocol_drop_mask(soc, + vdev_id); +} + +/* + * Rx-Ingress and Tx-Egress are in the lower level DP layer + * Rx-Egress and Tx-ingress are handled in osif layer for DP + * So + * Rx-Ingress and Tx-Egress definitions are in DP layer + * Rx-Egress and Tx-ingress mask definitions are here below + */ +#define VDEV_PEER_PROTOCOL_RX_INGRESS_MASK 1 +#define VDEV_PEER_PROTOCOL_TX_INGRESS_MASK 2 +#define VDEV_PEER_PROTOCOL_RX_EGRESS_MASK 4 +#define VDEV_PEER_PROTOCOL_TX_EGRESS_MASK 8 + +#else +#define cdp_set_vdev_peer_protocol_count(soc, vdev_id, enable) +#define cdp_set_vdev_peer_protocol_drop_mask(soc, vdev_id, drop_mask) +#define cdp_is_vdev_peer_protocol_count_enabled(soc, vdev_id) 0 +#define cdp_get_peer_protocol_drop_mask(soc, vdev_id) 0 +#endif + /** * cdp_txrx_set_pdev_param() - set pdev parameter * @soc: opaque soc handle @@ -425,6 +563,42 @@ static inline QDF_STATUS cdp_txrx_get_pdev_param(ol_txrx_soc_handle soc, (soc, pdev_id, type, value); } +/** + * cdp_txrx_peer_protocol_cnt() - set peer protocol count + * @soc: opaque soc handle + * @vdev: opaque vdev handle + * @nbuf: data packet + * @is_egress: whether egress or ingress + * @is_rx: whether tx or rx + * + * Return: void + */ +#ifdef VDEV_PEER_PROTOCOL_COUNT +static inline void +cdp_txrx_peer_protocol_cnt(ol_txrx_soc_handle soc, + int8_t vdev_id, + qdf_nbuf_t nbuf, + enum vdev_peer_protocol_enter_exit is_egress, + enum vdev_peer_protocol_tx_rx is_rx) +{ + if (!soc || !soc->ops) { + QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, + "%s: Invalid Instance:", __func__); + QDF_BUG(0); + return; + } + + if (!soc->ops->ctrl_ops || + !soc->ops->ctrl_ops->txrx_peer_protocol_cnt) + return; + + soc->ops->ctrl_ops->txrx_peer_protocol_cnt(soc, vdev_id, nbuf, + is_egress, is_rx); +} +#else +#define cdp_txrx_peer_protocol_cnt(soc, vdev_id, nbuf, is_egress, is_rx) +#endif + /** * cdp_enable_peer_based_pktlog()- Set flag in peer structure * diff --git a/dp/inc/cdp_txrx_ops.h b/dp/inc/cdp_txrx_ops.h index d2d018fc7d..f193401973 100644 --- a/dp/inc/cdp_txrx_ops.h +++ b/dp/inc/cdp_txrx_ops.h @@ -57,6 +57,31 @@ enum cdp_nac_param_cmd { /* IEEE80211_NAC_PARAM_LIST */ CDP_NAC_PARAM_LIST, }; + +/** + * enum vdev_peer_protocol_enter_exit - whether ingress or egress + * @CDP_VDEV_PEER_PROTOCOL_IS_INGRESS: ingress + * @CDP_VDEV_PEER_PROTOCOL_IS_EGRESS: egress + * + * whether ingress or egress + */ +enum vdev_peer_protocol_enter_exit { + CDP_VDEV_PEER_PROTOCOL_IS_INGRESS, + CDP_VDEV_PEER_PROTOCOL_IS_EGRESS +}; + +/** + * enum vdev_peer_protocol_tx_rx - whether tx or rx + * @CDP_VDEV_PEER_PROTOCOL_IS_TX: tx + * @CDP_VDEV_PEER_PROTOCOL_IS_RX: rx + * + * whether tx or rx + */ +enum vdev_peer_protocol_tx_rx { + CDP_VDEV_PEER_PROTOCOL_IS_TX, + CDP_VDEV_PEER_PROTOCOL_IS_RX +}; + /****************************************************************************** * * Control Interface (A Interface) @@ -617,7 +642,13 @@ struct cdp_ctrl_ops { cdp_config_param_type *val); void * (*txrx_get_pldev)(struct cdp_soc_t *soc, uint8_t pdev_id); - +#ifdef VDEV_PEER_PROTOCOL_COUNT + void (*txrx_peer_protocol_cnt)(struct cdp_soc_t *soc, + int8_t vdev_id, + qdf_nbuf_t nbuf, + bool is_egress, + bool is_rx); +#endif #ifdef ATH_SUPPORT_NAC_RSSI QDF_STATUS (*txrx_vdev_config_for_nac_rssi)(struct cdp_soc_t *cdp_soc, uint8_t vdev_id, @@ -684,6 +715,20 @@ struct cdp_ctrl_ops { QDF_STATUS (*txrx_get_psoc_param)(ol_txrx_soc_handle soc, enum cdp_psoc_param_type type, cdp_config_param_type *val); +#ifdef VDEV_PEER_PROTOCOL_COUNT + /* + * Enable per-peer protocol counters + */ + void (*txrx_enable_peer_protocol_count)(struct cdp_soc_t *soc, + int8_t vdev_id, bool enable); + void (*txrx_set_peer_protocol_drop_mask)(struct cdp_soc_t *soc, + int8_t vdev_id, int mask); + int (*txrx_is_peer_protocol_count_enabled)(struct cdp_soc_t *soc, + int8_t vdev_id); + int (*txrx_get_peer_protocol_drop_mask)(struct cdp_soc_t *soc, + int8_t vdev_id); + +#endif }; struct cdp_me_ops { diff --git a/dp/inc/cdp_txrx_stats_struct.h b/dp/inc/cdp_txrx_stats_struct.h index 9f32f8cd6d..c1d5b81ba0 100644 --- a/dp/inc/cdp_txrx_stats_struct.h +++ b/dp/inc/cdp_txrx_stats_struct.h @@ -667,6 +667,32 @@ typedef union cdp_peer_stats_buf { uint32_t rx_avg_rssi; } cdp_peer_stats_param_t; /* Max union size 16 bytes */ +/** + * enum cdp_protocol_trace - Protocols supported by per-peer protocol trace + * @CDP_TRACE_ICMP: ICMP packets + * @CDP_TRACE_EAP: EAPOL packets + * @CDP_TRACE_ARP: ARP packets + * + * Enumeration of all protocols supported by per-peer protocol trace feature + */ +enum cdp_protocol_trace { + CDP_TRACE_ICMP, + CDP_TRACE_EAP, + CDP_TRACE_ARP, + CDP_TRACE_MAX +}; + +/** + * struct protocol_trace_count - type of count on per-peer protocol trace + * @egress_cnt: how many packets go out of host driver + * @ingress_cnt: how many packets come into the host driver + * + * Type of count on per-peer protocol trace + */ +struct protocol_trace_count { + uint16_t egress_cnt; + uint16_t ingress_cnt; +}; /* struct cdp_tx_stats - tx stats * @cdp_pkt_info comp_pkt: Pkt Info for which completions were received * @cdp_pkt_info ucast: Unicast Packet Count @@ -675,6 +701,7 @@ typedef union cdp_peer_stats_buf { * @cdp_pkt_info nawds_mcast: NAWDS Multicast Packet Count * @cdp_pkt_info tx_success: Successful Tx Packets * @nawds_mcast_drop: NAWDS Multicast Drop Count + * @protocol_trace_cnt: per-peer protocol counter * @tx_failed: Total Tx failure * @ofdma: Total Packets as ofdma * @stbc: Packets in STBC @@ -749,6 +776,9 @@ struct cdp_tx_stats { struct cdp_pkt_info mcast; struct cdp_pkt_info bcast; struct cdp_pkt_info nawds_mcast; +#ifdef VDEV_PEER_PROTOCOL_COUNT + struct protocol_trace_count protocol_trace_cnt[CDP_TRACE_MAX]; +#endif struct cdp_pkt_info tx_success; uint32_t nawds_mcast_drop; uint32_t tx_failed; @@ -842,6 +872,7 @@ struct cdp_tx_stats { * @pkts: Intra BSS packets received * @fail: Intra BSS packets failed * @mdns_no_fwd: Intra BSS MDNS packets not forwarded + * @protocol_trace_cnt: per-peer protocol counters * @mic_err: Rx MIC errors CCMP * @decrypt_err: Rx Decryption Errors CRC * @fcserr: rx MIC check failed (CCMP) @@ -905,6 +936,9 @@ struct cdp_rx_stats { struct cdp_pkt_info fail; uint32_t mdns_no_fwd; } intra_bss; +#ifdef VDEV_PEER_PROTOCOL_COUNT + struct protocol_trace_count protocol_trace_cnt[CDP_TRACE_MAX]; +#endif struct { uint32_t mic_err; diff --git a/dp/wifi3.0/dp_internal.h b/dp/wifi3.0/dp_internal.h index b508aa8fd6..f6266ab03c 100644 --- a/dp/wifi3.0/dp_internal.h +++ b/dp/wifi3.0/dp_internal.h @@ -1599,6 +1599,48 @@ static inline QDF_STATUS dp_peer_stats_notify(struct dp_pdev *pdev, } #endif /* CONFIG_WIN */ + +#ifdef VDEV_PEER_PROTOCOL_COUNT +/** + * dp_vdev_peer_stats_update_protocol_cnt() - update per-peer protocol counters + * @vdev: VDEV DP object + * @nbuf: data packet + * @peer: Peer DP object + * @is_egress: whether egress or ingress + * @is_rx: whether rx or tx + * + * This function updates the per-peer protocol counters + * Return: void + */ +void dp_vdev_peer_stats_update_protocol_cnt(struct dp_vdev *vdev, + qdf_nbuf_t nbuf, + struct dp_peer *peer, + bool is_egress, + bool is_rx); + +/** + * dp_vdev_peer_stats_update_protocol_cnt() - update per-peer protocol counters + * @soc: SOC DP object + * @vdev_id: vdev_id + * @nbuf: data packet + * @is_egress: whether egress or ingress + * @is_rx: whether rx or tx + * + * This function updates the per-peer protocol counters + * Return: void + */ + +void dp_peer_stats_update_protocol_cnt(struct cdp_soc_t *soc, + int8_t vdev_id, + qdf_nbuf_t nbuf, + bool is_egress, + bool is_rx); + +#else +#define dp_vdev_peer_stats_update_protocol_cnt(vdev, nbuf, peer, \ + is_egress, is_rx) +#endif + #ifdef QCA_LL_TX_FLOW_CONTROL_V2 void dp_tx_dump_flow_pool_info(struct cdp_soc_t *soc_hdl); int dp_tx_delete_flow_pool(struct dp_soc *soc, struct dp_tx_desc_pool_s *pool, diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index fa8738217a..462899eca1 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -6967,6 +6967,57 @@ void dp_peer_set_mesh_rx_filter(struct cdp_vdev *vdev_hdl, uint32_t val) } #endif +#ifdef VDEV_PEER_PROTOCOL_COUNT +static void dp_enable_vdev_peer_protocol_count(struct cdp_soc_t *soc, + int8_t vdev_id, + bool enable) +{ + struct dp_vdev *vdev; + + vdev = dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, + vdev_id); + dp_info("enable %d vdev_id %d", enable, vdev_id); + vdev->peer_protocol_count_track = enable; +} + +static void dp_enable_vdev_peer_protocol_drop_mask(struct cdp_soc_t *soc, + int8_t vdev_id, + int drop_mask) +{ + struct dp_vdev *vdev; + + vdev = dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, + vdev_id); + dp_info("drop_mask %d vdev_id %d", drop_mask, vdev_id); + vdev->peer_protocol_count_dropmask = drop_mask; +} + +static int dp_is_vdev_peer_protocol_count_enabled(struct cdp_soc_t *soc, + int8_t vdev_id) +{ + struct dp_vdev *vdev; + + vdev = dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, + vdev_id); + dp_info("enable %d vdev_id %d", vdev->peer_protocol_count_track, + vdev_id); + return vdev->peer_protocol_count_track; +} + +static int dp_get_vdev_peer_protocol_drop_mask(struct cdp_soc_t *soc, + int8_t vdev_id) +{ + struct dp_vdev *vdev; + + vdev = dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, + vdev_id); + dp_info("drop_mask %d vdev_id %d", vdev->peer_protocol_count_dropmask, + vdev_id); + return vdev->peer_protocol_count_dropmask; +} + +#endif + bool dp_check_pdev_exists(struct dp_soc *soc, struct dp_pdev *data) { uint8_t pdev_count; @@ -9902,6 +9953,14 @@ static struct cdp_cmn_ops dp_ops_cmn = { static struct cdp_ctrl_ops dp_ops_ctrl = { .txrx_peer_authorize = dp_peer_authorize, +#ifdef VDEV_PEER_PROTOCOL_COUNT + .txrx_enable_peer_protocol_count = dp_enable_vdev_peer_protocol_count, + .txrx_set_peer_protocol_drop_mask = + dp_enable_vdev_peer_protocol_drop_mask, + .txrx_is_peer_protocol_count_enabled = + dp_is_vdev_peer_protocol_count_enabled, + .txrx_get_peer_protocol_drop_mask = dp_get_vdev_peer_protocol_drop_mask, +#endif .txrx_set_vdev_param = dp_set_vdev_param, .txrx_set_psoc_param = dp_set_psoc_param, .txrx_get_psoc_param = dp_get_psoc_param, @@ -9921,6 +9980,9 @@ static struct cdp_ctrl_ops dp_ops_ctrl = { .txrx_get_pdev_param = dp_get_pdev_param, .txrx_set_peer_param = dp_set_peer_param, .txrx_get_peer_param = dp_get_peer_param, +#ifdef VDEV_PEER_PROTOCOL_COUNT + .txrx_peer_protocol_cnt = dp_peer_stats_update_protocol_cnt, +#endif #ifdef ATH_SUPPORT_NAC_RSSI .txrx_vdev_config_for_nac_rssi = dp_config_for_nac_rssi, .txrx_vdev_get_neighbour_rssi = dp_vdev_get_neighbour_rssi, diff --git a/dp/wifi3.0/dp_rx.c b/dp/wifi3.0/dp_rx.c index a1a65d1610..10dd09d52a 100644 --- a/dp/wifi3.0/dp_rx.c +++ b/dp/wifi3.0/dp_rx.c @@ -1379,6 +1379,30 @@ static inline void dp_rx_cksum_offload(struct dp_pdev *pdev, } } +#ifdef VDEV_PEER_PROTOCOL_COUNT +#define dp_rx_msdu_stats_update_prot_cnts(vdev_hdl, nbuf, peer) \ +{ \ + qdf_nbuf_t nbuf_local; \ + struct dp_peer *peer_local; \ + struct dp_vdev *vdev_local = vdev_hdl; \ + do { \ + if (qdf_likely(!((vdev_local)->peer_protocol_count_track))) \ + break; \ + nbuf_local = nbuf; \ + peer_local = peer; \ + if (qdf_unlikely(qdf_nbuf_is_frag((nbuf_local)))) \ + break; \ + else if (qdf_unlikely(qdf_nbuf_is_raw_frame((nbuf_local)))) \ + break; \ + dp_vdev_peer_stats_update_protocol_cnt((vdev_local), \ + (nbuf_local), \ + (peer_local), 0, 1); \ + } while (0); \ +} +#else +#define dp_rx_msdu_stats_update_prot_cnts(vdev_hdl, nbuf, peer) +#endif + /** * dp_rx_msdu_stats_update() - update per msdu stats. * @soc: core txrx main context @@ -1404,6 +1428,7 @@ static void dp_rx_msdu_stats_update(struct dp_soc *soc, qdf_ether_header_t *eh; uint16_t msdu_len = QDF_NBUF_CB_RX_PKT_LEN(nbuf); + dp_rx_msdu_stats_update_prot_cnts(vdev, nbuf, peer); is_not_amsdu = qdf_nbuf_is_rx_chfrag_start(nbuf) & qdf_nbuf_is_rx_chfrag_end(nbuf); diff --git a/dp/wifi3.0/dp_rx_err.c b/dp/wifi3.0/dp_rx_err.c index 2f2b373700..2ae41a0303 100644 --- a/dp/wifi3.0/dp_rx_err.c +++ b/dp/wifi3.0/dp_rx_err.c @@ -821,6 +821,8 @@ dp_rx_null_q_desc_handle(struct dp_soc *soc, qdf_nbuf_t nbuf, else qdf_nbuf_pull_head(nbuf, (l2_hdr_offset + RX_PKT_TLVS_LEN)); + dp_vdev_peer_stats_update_protocol_cnt(vdev, nbuf, NULL, 0, 1); + if (dp_rx_mcast_echo_check(soc, peer, rx_tlv_hdr, nbuf)) { /* this is a looped back MCBC pkt, drop it */ DP_STATS_INC_PKT(peer, rx.mec_drop, 1, qdf_nbuf_len(nbuf)); diff --git a/dp/wifi3.0/dp_stats.c b/dp/wifi3.0/dp_stats.c index c9f62dfbcb..25a1d71105 100644 --- a/dp/wifi3.0/dp_stats.c +++ b/dp/wifi3.0/dp_stats.c @@ -4041,6 +4041,118 @@ void dp_htt_stats_copy_tag(struct dp_pdev *pdev, uint8_t tag_type, uint32_t *tag qdf_mem_copy(dest_ptr, tag_buf, size); } +#ifdef VDEV_PEER_PROTOCOL_COUNT +#ifdef VDEV_PEER_PROTOCOL_COUNT_TESTING +static QDF_STATUS dp_peer_stats_update_protocol_test_cnt(struct dp_vdev *vdev, + bool is_egress, + bool is_rx) +{ + int mask; + + if (is_egress) + if (is_rx) + mask = VDEV_PEER_PROTOCOL_RX_EGRESS_MASK; + else + mask = VDEV_PEER_PROTOCOL_TX_EGRESS_MASK; + else + if (is_rx) + mask = VDEV_PEER_PROTOCOL_RX_INGRESS_MASK; + else + mask = VDEV_PEER_PROTOCOL_TX_INGRESS_MASK; + + if (qdf_unlikely(vdev->peer_protocol_count_dropmask & mask)) { + dp_info("drop mask set %x", vdev->peer_protocol_count_dropmask); + return QDF_STATUS_SUCCESS; + } + return QDF_STATUS_E_FAILURE; +} + +#else +static QDF_STATUS dp_peer_stats_update_protocol_test_cnt(struct dp_vdev *vdev, + bool is_egress, + bool is_rx) +{ + return QDF_STATUS_E_FAILURE; +} +#endif + +void dp_vdev_peer_stats_update_protocol_cnt(struct dp_vdev *vdev, + qdf_nbuf_t nbuf, + struct dp_peer *peer, + bool is_egress, + bool is_rx) +{ + struct cdp_peer_stats *peer_stats; + struct protocol_trace_count *protocol_trace_cnt; + enum cdp_protocol_trace prot; + struct dp_soc *soc; + struct ether_header *eh; + char *mac; + bool new_peer_ref = false; + + if (qdf_likely(!vdev->peer_protocol_count_track)) + return; + if (qdf_unlikely(dp_peer_stats_update_protocol_test_cnt(vdev, + is_egress, + is_rx) == + QDF_STATUS_SUCCESS)) + return; + + soc = vdev->pdev->soc; + eh = (struct ether_header *)qdf_nbuf_data(nbuf); + if (is_rx) + mac = eh->ether_shost; + else + mac = eh->ether_dhost; + + if (!peer) { + peer = dp_peer_find_hash_find(soc, mac, 0, vdev->vdev_id); + new_peer_ref = true; + if (!peer) + return; + } + peer_stats = &peer->stats; + + if (qdf_nbuf_is_icmp_pkt(nbuf) == true) + prot = CDP_TRACE_ICMP; + else if (qdf_nbuf_is_ipv4_arp_pkt(nbuf) == true) + prot = CDP_TRACE_ARP; + else if (qdf_nbuf_is_ipv4_eapol_pkt(nbuf) == true) + prot = CDP_TRACE_EAP; + else + goto dp_vdev_peer_stats_update_protocol_cnt_free_peer; + + if (is_rx) + protocol_trace_cnt = peer_stats->rx.protocol_trace_cnt; + else + protocol_trace_cnt = peer_stats->tx.protocol_trace_cnt; + + if (is_egress) + protocol_trace_cnt[prot].egress_cnt++; + else + protocol_trace_cnt[prot].ingress_cnt++; +dp_vdev_peer_stats_update_protocol_cnt_free_peer: + if (new_peer_ref) + dp_peer_unref_delete(peer); +} + +void dp_peer_stats_update_protocol_cnt(struct cdp_soc_t *soc, + int8_t vdev_id, + qdf_nbuf_t nbuf, + bool is_egress, + bool is_rx) +{ + struct dp_vdev *vdev; + + vdev = dp_get_vdev_from_soc_vdev_id_wifi3((struct dp_soc *)soc, + vdev_id); + if (qdf_likely(!vdev->peer_protocol_count_track)) + return; + dp_vdev_peer_stats_update_protocol_cnt(vdev, nbuf, NULL, is_egress, + is_rx); +} +#endif + QDF_STATUS dp_peer_stats_notify(struct dp_pdev *dp_pdev, struct dp_peer *peer) { struct cdp_interface_peer_stats peer_stats_intf; diff --git a/dp/wifi3.0/dp_tx.c b/dp/wifi3.0/dp_tx.c index a185815510..fe8c0a440c 100644 --- a/dp/wifi3.0/dp_tx.c +++ b/dp/wifi3.0/dp_tx.c @@ -1070,6 +1070,31 @@ static void dp_tx_raw_prepare_unset(struct dp_soc *soc, } while (cur_nbuf); } +#ifdef VDEV_PEER_PROTOCOL_COUNT +#define dp_vdev_peer_stats_update_protocol_cnt_tx(vdev_hdl, nbuf) \ +{ \ + qdf_nbuf_t nbuf_local; \ + struct dp_vdev *vdev_local = vdev_hdl; \ + do { \ + if (qdf_likely(!((vdev_local)->peer_protocol_count_track))) \ + break; \ + nbuf_local = nbuf; \ + if (qdf_unlikely(((vdev_local)->tx_encap_type) == \ + htt_cmn_pkt_type_raw)) \ + break; \ + else if (qdf_unlikely(qdf_nbuf_is_nonlinear((nbuf_local)))) \ + break; \ + else if (qdf_nbuf_is_tso((nbuf_local))) \ + break; \ + dp_vdev_peer_stats_update_protocol_cnt((vdev_local), \ + (nbuf_local), \ + NULL, 1, 0); \ + } while (0); \ +} +#else +#define dp_vdev_peer_stats_update_protocol_cnt_tx(vdev_hdl, skb) +#endif + /** * dp_tx_hw_enqueue() - Enqueue to TCL HW for transmit * @soc: DP Soc Handle @@ -1181,6 +1206,7 @@ static QDF_STATUS dp_tx_hw_enqueue(struct dp_soc *soc, struct dp_vdev *vdev, } tx_desc->flags |= DP_TX_DESC_FLAG_QUEUED_TX; + dp_vdev_peer_stats_update_protocol_cnt_tx(vdev, tx_desc->nbuf); hal_tx_desc_sync(hal_tx_desc_cached, hal_tx_desc); DP_STATS_INC_PKT(vdev, tx_i.processed, 1, length); diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index 90f446e889..4983b7826b 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -1970,6 +1970,21 @@ struct dp_vdev { #endif /* Extended data path handle */ struct cdp_ext_vdev *vdev_dp_ext_handle; +#ifdef VDEV_PEER_PROTOCOL_COUNT + /* + * Rx-Ingress and Tx-Egress are in the lower level DP layer + * Rx-Egress and Tx-ingress are handled in osif layer for DP + * So + * Rx-Egress and Tx-ingress mask definitions are in OSIF layer + * Rx-Ingress and Tx-Egress definitions are here below + */ +#define VDEV_PEER_PROTOCOL_RX_INGRESS_MASK 1 +#define VDEV_PEER_PROTOCOL_TX_INGRESS_MASK 2 +#define VDEV_PEER_PROTOCOL_RX_EGRESS_MASK 4 +#define VDEV_PEER_PROTOCOL_TX_EGRESS_MASK 8 + bool peer_protocol_count_track; + int peer_protocol_count_dropmask; +#endif };