Prechádzať zdrojové kódy

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
Sravan Kumar Kairam 8 rokov pred
rodič
commit
c1ae71c4cd

+ 4 - 1
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 */

+ 68 - 0
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++;
+}

+ 26 - 0
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)

+ 3 - 3
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;
 };
 
 /**

+ 5 - 3
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;
 }

+ 0 - 2
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;
 

+ 52 - 5
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;
 		}
 	}