From c1ae71c4cd6cfe6253237fdeb91d962aace0c3f0 Mon Sep 17 00:00:00 2001 From: Sravan Kumar Kairam Date: Fri, 24 Feb 2017 12:27:27 +0530 Subject: [PATCH] qcacld-3.0: Add ARP debug stats Change to collect arp packet stats along with existing hdd stats to debug arp packet related issues. Change-Id: Idce70799bd3698dc8a8ecd8cfc8ef7d9bf1f5764 CRs-Fixed: 2019787 --- core/cds/inc/cds_api.h | 5 ++- core/cds/src/cds_api.c | 68 ++++++++++++++++++++++++++++++++ core/dp/txrx/ol_tx_send.c | 26 ++++++++++++ core/hdd/inc/wlan_hdd_main.h | 6 +-- core/hdd/src/wlan_hdd_cfg80211.c | 8 ++-- core/hdd/src/wlan_hdd_main.c | 2 - core/hdd/src/wlan_hdd_tx_rx.c | 57 +++++++++++++++++++++++--- 7 files changed, 158 insertions(+), 14 deletions(-) diff --git a/core/cds/inc/cds_api.h b/core/cds/inc/cds_api.h index a971d431c421..a61234a7d1cc 100644 --- a/core/cds/inc/cds_api.h +++ b/core/cds/inc/cds_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -565,4 +565,7 @@ bool cds_is_group_addr(uint8_t *mac_addr) return false; } +uint32_t cds_get_arp_stats_gw_ip(void); +void cds_incr_arp_stats_tx_tgt_delivered(void); +void cds_incr_arp_stats_tx_tgt_acked(void); #endif /* if !defined __CDS_API_H */ diff --git a/core/cds/src/cds_api.c b/core/cds/src/cds_api.c index d9f44fc731a4..db6d37305961 100644 --- a/core/cds/src/cds_api.c +++ b/core/cds/src/cds_api.c @@ -2769,3 +2769,71 @@ cds_print_htc_credit_history(uint32_t count, qdf_abstract_print *print, print, print_priv); } #endif + +/** + * cds_get_arp_stats_gw_ip() - get arp stats track IP + * + * Return: ARP stats IP to track + */ +uint32_t cds_get_arp_stats_gw_ip(void) +{ + struct hdd_context *hdd_ctx; + + hdd_ctx = (struct hdd_context *) (gp_cds_context->pHDDContext); + if (!hdd_ctx) { + cds_err("Hdd Context is Null"); + return 0; + } + + return hdd_ctx->track_arp_ip; +} + +/** + * cds_incr_arp_stats_tx_tgt_delivered() - increment ARP stats + * + * Return: none + */ +void cds_incr_arp_stats_tx_tgt_delivered(void) +{ + struct hdd_context *hdd_ctx; + struct hdd_adapter *adapter = NULL; + + hdd_ctx = (struct hdd_context *) (gp_cds_context->pHDDContext); + if (!hdd_ctx) { + cds_err("Hdd Context is Null"); + return; + } + + hdd_for_each_adapter(hdd_ctx, adapter) { + if (QDF_STA_MODE == adapter->device_mode) + break; + } + + if (adapter) + adapter->hdd_stats.hdd_arp_stats.tx_host_fw_sent++; +} + +/** + * cds_incr_arp_stats_tx_tgt_acked() - increment ARP stats + * + * Return: none + */ +void cds_incr_arp_stats_tx_tgt_acked(void) +{ + struct hdd_context *hdd_ctx; + struct hdd_adapter *adapter = NULL; + + hdd_ctx = (struct hdd_context *) (gp_cds_context->pHDDContext); + if (!hdd_ctx) { + cds_err("Hdd Context is Null"); + return; + } + + hdd_for_each_adapter(hdd_ctx, adapter) { + if (QDF_STA_MODE == adapter->device_mode) + break; + } + + if (adapter) + adapter->hdd_stats.hdd_arp_stats.tx_ack_cnt++; +} diff --git a/core/dp/txrx/ol_tx_send.c b/core/dp/txrx/ol_tx_send.c index 74d9b8701aa2..eaba41699827 100644 --- a/core/dp/txrx/ol_tx_send.c +++ b/core/dp/txrx/ol_tx_send.c @@ -629,6 +629,26 @@ static inline void ol_tx_timestamp(ol_txrx_pdev_handle pdev, } #endif +/** + * ol_tx_update_arp_stats() - update ARP packet TX stats + * @netbuf: buffer + * + * + * Return: none + */ +static void ol_tx_update_arp_stats(qdf_nbuf_t netbuf, + enum htt_tx_status status) +{ + uint32_t tgt_ip = cds_get_arp_stats_gw_ip(); + + if (tgt_ip == qdf_nbuf_get_arp_tgt_ip(netbuf)) { + if (status != htt_tx_status_download_fail) + cds_incr_arp_stats_tx_tgt_delivered(); + if (status == htt_tx_status_ok) + cds_incr_arp_stats_tx_tgt_acked(); + } +} + /** * WARNING: ol_tx_inspect_handler()'s bahavior is similar to that of * ol_tx_completion_handler(). @@ -680,6 +700,12 @@ ol_tx_completion_handler(ol_txrx_pdev_handle pdev, QDF_NBUF_UPDATE_TX_PKT_COUNT(netbuf, QDF_NBUF_TX_PKT_FREE); + if (QDF_NBUF_CB_GET_PACKET_TYPE(netbuf) == + QDF_NBUF_CB_PACKET_TYPE_ARP) { + if (qdf_nbuf_data_is_arp_req(netbuf)) + ol_tx_update_arp_stats(netbuf, status); + } + if (tx_desc->pkt_type != OL_TX_FRM_TSO) { packetdump_cb = pdev->ol_tx_packetdump_cb; if (packetdump_cb) diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 99cd7358473e..982cc462afed 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -478,15 +478,14 @@ struct hdd_pmf_stats { #endif struct hdd_arp_stats_s { - uint16_t tx_count; - uint16_t rx_count; + uint16_t tx_arp_req_count; + uint16_t rx_arp_rsp_count; uint16_t tx_dropped; uint16_t rx_dropped; uint16_t rx_delivered; uint16_t rx_refused; uint16_t tx_host_fw_sent; uint16_t rx_host_drop_reorder; - uint16_t tx_fw_cnt; uint16_t rx_fw_cnt; uint16_t tx_ack_cnt; }; @@ -1712,6 +1711,7 @@ struct hdd_context { qdf_wake_lock_t monitor_mode_wakelock; bool lte_coex_ant_share; int sscan_pid; + uint32_t track_arp_ip; }; /** diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 6be0a2c83b90..4a8c9e0afbb8 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -12508,6 +12508,7 @@ static int __wlan_hdd_cfg80211_set_nud_stats(struct wiphy *wiphy, } arp_stats_params.flag = true; arp_stats_params.ip_addr = nla_get_u32(tb[STATS_GW_IPV4]); + hdd_ctx->track_arp_ip = arp_stats_params.ip_addr; } else { arp_stats_params.flag = false; } @@ -12686,17 +12687,17 @@ static int __wlan_hdd_cfg80211_get_nud_stats(struct wiphy *wiphy, } if (nla_put_u16(skb, COUNT_FROM_NETDEV, - adapter->hdd_stats.hdd_arp_stats.tx_count) || + adapter->hdd_stats.hdd_arp_stats.tx_arp_req_count) || nla_put_u16(skb, COUNT_TO_LOWER_MAC, adapter->hdd_stats.hdd_arp_stats.tx_host_fw_sent) || nla_put_u16(skb, RX_COUNT_BY_LOWER_MAC, - adapter->hdd_stats.hdd_arp_stats.tx_fw_cnt) || + adapter->hdd_stats.hdd_arp_stats.tx_host_fw_sent) || nla_put_u16(skb, COUNT_TX_SUCCESS, adapter->hdd_stats.hdd_arp_stats.tx_ack_cnt) || nla_put_u16(skb, RSP_RX_COUNT_BY_LOWER_MAC, adapter->hdd_stats.hdd_arp_stats.rx_fw_cnt) || nla_put_u16(skb, RSP_RX_COUNT_BY_UPPER_MAC, - adapter->hdd_stats.hdd_arp_stats.rx_count) || + adapter->hdd_stats.hdd_arp_stats.rx_arp_rsp_count) || nla_put_u16(skb, RSP_COUNT_TO_NETDEV, adapter->hdd_stats.hdd_arp_stats.rx_delivered) || nla_put_u16(skb, RSP_COUNT_OUT_OF_ORDER_DROP, @@ -12711,6 +12712,7 @@ static int __wlan_hdd_cfg80211_get_nud_stats(struct wiphy *wiphy, if (adapter->dad) nla_put_flag(skb, AP_LINK_DAD); + hdd_ctx->track_arp_ip = 0; cfg80211_vendor_cmd_reply(skb); return err; } diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 366ee955e0e6..0b50c04a3bd4 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -10648,9 +10648,7 @@ static void hdd_get_nud_stats_cb(void *data, struct rsp_stats *rsp) hdd_notice("rsp->ba_session_establishment_status :%x", rsp->ba_session_establishment_status); - adapter->hdd_stats.hdd_arp_stats.tx_fw_cnt = rsp->arp_req_enqueue; adapter->hdd_stats.hdd_arp_stats.rx_fw_cnt = rsp->arp_rsp_recvd; - adapter->hdd_stats.hdd_arp_stats.tx_ack_cnt = rsp->arp_req_tx_success; adapter->dad |= rsp->dad_detected; adapter->con_status = rsp->connect_status; diff --git a/core/hdd/src/wlan_hdd_tx_rx.c b/core/hdd/src/wlan_hdd_tx_rx.c index c68771768289..aa929952fa69 100644 --- a/core/hdd/src/wlan_hdd_tx_rx.c +++ b/core/hdd/src/wlan_hdd_tx_rx.c @@ -582,8 +582,9 @@ static int __hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) bool pkt_proto_logged = false; #ifdef QCA_PKT_PROTO_TRACE uint8_t proto_type = 0; +#endif struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); -#endif /* QCA_PKT_PROTO_TRACE */ + bool is_arp; #ifdef QCA_WIFI_FTM if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) { @@ -603,7 +604,22 @@ static int __hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) } wlan_hdd_classify_pkt(skb); - wlan_hdd_latency_opt(adapter, skb); + if (QDF_NBUF_CB_GET_PACKET_TYPE(skb) == QDF_NBUF_CB_PACKET_TYPE_ARP) { + is_arp = true; + if (qdf_nbuf_data_is_arp_req(skb) && + (hdd_ctx->track_arp_ip == qdf_nbuf_get_arp_tgt_ip(skb))) { + ++adapter->hdd_stats.hdd_arp_stats.tx_arp_req_count; + QDF_TRACE(QDF_MODULE_ID_HDD_DATA, + QDF_TRACE_LEVEL_INFO_HIGH, + "%s : ARP packet", __func__); + } + } + + if (cds_is_driver_recovering()) { + QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_WARN, + "Recovery in progress, dropping the packet"); + goto drop_pkt; + } STAId = HDD_WLAN_INVALID_STA_ID; @@ -785,6 +801,7 @@ static int __hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) ++adapter->hdd_stats.tx_rx_stats.tx_dropped_ac[ac]; goto drop_pkt_and_release_skb; } + netif_trans_update(dev); return NETDEV_TX_OK; @@ -812,6 +829,11 @@ drop_pkt_accounting: ++adapter->stats.tx_dropped; ++adapter->hdd_stats.tx_rx_stats.tx_dropped; + if (is_arp) { + ++adapter->hdd_stats.hdd_arp_stats.tx_dropped; + QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_INFO_HIGH, + "%s : ARP packet dropped", __func__); + } return NETDEV_TX_OK; } @@ -1226,6 +1248,7 @@ QDF_STATUS hdd_rx_packet_cbk(void *context, qdf_nbuf_t rxBuf) struct qdf_mac_addr *mac_addr; bool wake_lock = false; bool proto_pkt_logged = false; + bool track_arp = false; /* Sanity check on inputs */ if (unlikely((NULL == context) || (NULL == rxBuf))) { @@ -1262,6 +1285,20 @@ QDF_STATUS hdd_rx_packet_cbk(void *context, qdf_nbuf_t rxBuf) QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_DEBUG, "%s: skb %pK skb->len %d\n", __func__, skb, skb->len); #endif + if (QDF_NBUF_CB_PACKET_TYPE_ARP == + QDF_NBUF_CB_GET_PACKET_TYPE(skb)) { + if (qdf_nbuf_data_is_arp_rsp(skb) && + (hdd_ctx->track_arp_ip == + qdf_nbuf_get_arp_src_ip(skb))) { + ++adapter->hdd_stats.hdd_arp_stats. + rx_arp_rsp_count; + QDF_TRACE(QDF_MODULE_ID_HDD_DATA, + QDF_TRACE_LEVEL_INFO, + "%s: ARP packet received", + __func__); + track_arp = true; + } + } sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); if ((sta_ctx->conn_info.proxyARPService) && @@ -1360,15 +1397,25 @@ QDF_STATUS hdd_rx_packet_cbk(void *context, qdf_nbuf_t rxBuf) else rxstat = netif_rx_ni(skb); - if (NET_RX_SUCCESS == rxstat) + if (NET_RX_SUCCESS == rxstat) { ++adapter->hdd_stats.tx_rx_stats. rx_delivered[cpu_index]; - else + if (track_arp) + ++adapter->hdd_stats.hdd_arp_stats. + rx_delivered; + } else { ++adapter->hdd_stats.tx_rx_stats. rx_refused[cpu_index]; + if (track_arp) + ++adapter->hdd_stats.hdd_arp_stats. + rx_refused; + } } else { ++adapter->hdd_stats.tx_rx_stats. - rx_delivered[cpu_index]; + rx_delivered[cpu_index]; + if (track_arp) + ++adapter->hdd_stats.hdd_arp_stats. + rx_delivered; } }