summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPoddar, Siddarth <siddpodd@codeaurora.org>2018-01-08 20:38:43 +0530
committerPoddar, Siddarth <siddpodd@codeaurora.org>2018-01-13 12:01:02 +0530
commit6259925fd8bf35e802a844752fbf53b057d0a679 (patch)
tree448b256076dea03cabff25754a379823a2cb443f
parentfebc5230fecf53d81b2d3ba65e3f650bc32af94b (diff)
qcacld-3.0: Extend debug stats
Extend to collect connectivity check stats other than ARP such as DNS, TCP SYN/SYN-ACK/ACK, and Ipv4. Add extra attributes in existing vendor command(set/reset and get NUD debug stats) for above connectvitiy stats. CRs-Fixed: 2161889 Change-Id: I037c4ec29b181a0b3117ae2abbc7a2229b373ac2
-rw-r--r--core/cds/inc/cds_api.h10
-rw-r--r--core/cds/src/cds_api.c18
-rw-r--r--core/dp/txrx/ol_tx_send.c16
-rw-r--r--core/hdd/inc/wlan_hdd_main.h109
-rw-r--r--core/hdd/inc/wlan_hdd_tx_rx.h15
-rw-r--r--core/hdd/src/wlan_hdd_assoc.c2
-rw-r--r--core/hdd/src/wlan_hdd_cfg80211.c620
-rw-r--r--core/hdd/src/wlan_hdd_cfg80211.h21
-rw-r--r--core/hdd/src/wlan_hdd_main.c9
-rw-r--r--core/hdd/src/wlan_hdd_ocb.c3
-rw-r--r--core/hdd/src/wlan_hdd_tx_rx.c288
-rw-r--r--uapi/linux/qca_vendor.h114
12 files changed, 1186 insertions, 39 deletions
diff --git a/core/cds/inc/cds_api.h b/core/cds/inc/cds_api.h
index 40eb34e59475..e7f740bd4488 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.
*
@@ -511,7 +511,13 @@ void cds_pkt_stats_to_logger_thread(void *pl_hdr, void *pkt_dump, void *data);
QDF_STATUS cds_register_dp_cb(struct cds_dp_cbacks *dp_cbs);
QDF_STATUS cds_deregister_dp_cb(void);
-uint32_t cds_get_arp_stats_gw_ip(void);
+/**
+ * cds_get_arp_stats_gw_ip() - get arp stats track IP
+ * @context: osif dev
+ *
+ * Return: ARP stats IP to track.
+ */
+uint32_t cds_get_arp_stats_gw_ip(void *context);
void cds_incr_arp_stats_tx_tgt_delivered(void);
void cds_incr_arp_stats_tx_tgt_acked(void);
diff --git a/core/cds/src/cds_api.c b/core/cds/src/cds_api.c
index a0b173bd57cd..1b8d154e5e26 100644
--- a/core/cds/src/cds_api.c
+++ b/core/cds/src/cds_api.c
@@ -2764,22 +2764,18 @@ QDF_STATUS cds_deregister_dp_cb(void)
return QDF_STATUS_SUCCESS;
}
-/**
- * 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)
+uint32_t cds_get_arp_stats_gw_ip(void *context)
{
- hdd_context_t *hdd_ctx;
+ hdd_adapter_t *adapter = (hdd_adapter_t *)context;
- hdd_ctx = (hdd_context_t *) (gp_cds_context->pHDDContext);
- if (!hdd_ctx) {
- cds_err("Hdd Context is Null");
+ if (unlikely(adapter->magic != WLAN_HDD_ADAPTER_MAGIC)) {
+ QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_ERROR,
+ "Magic cookie(%x) for adapter sanity verification is invalid",
+ adapter->magic);
return 0;
}
- return hdd_ctx->track_arp_ip;
+ return adapter->track_arp_ip;
}
/**
diff --git a/core/dp/txrx/ol_tx_send.c b/core/dp/txrx/ol_tx_send.c
index ec3eb1a2568e..071f5a9bfa7c 100644
--- a/core/dp/txrx/ol_tx_send.c
+++ b/core/dp/txrx/ol_tx_send.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -545,15 +545,21 @@ void ol_tx_credit_completion_handler(ol_txrx_pdev_handle pdev, int credits)
/**
* ol_tx_update_arp_stats() - update ARP packet TX stats
+ * @tx_desc: tx desc
* @netbuf: buffer
+ * @status: htt status
*
*
* Return: none
*/
-static void ol_tx_update_arp_stats(qdf_nbuf_t netbuf,
- enum htt_tx_status status)
+static void ol_tx_update_arp_stats(struct ol_tx_desc_t *tx_desc,
+ qdf_nbuf_t netbuf,
+ enum htt_tx_status status)
{
- uint32_t tgt_ip = cds_get_arp_stats_gw_ip();
+ uint32_t tgt_ip;
+
+ qdf_assert(tx_desc);
+ tgt_ip = cds_get_arp_stats_gw_ip(tx_desc->vdev->osif_dev);
if (tgt_ip == qdf_nbuf_get_arp_tgt_ip(netbuf)) {
if (status != htt_tx_status_download_fail)
@@ -670,7 +676,7 @@ ol_tx_completion_handler(ol_txrx_pdev_handle pdev,
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);
+ ol_tx_update_arp_stats(tx_desc, netbuf, status);
}
if (tx_desc->pkt_type != OL_TX_FRM_TSO) {
diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h
index 16e3fdb65f98..56a89dc684e2 100644
--- a/core/hdd/inc/wlan_hdd_main.h
+++ b/core/hdd/inc/wlan_hdd_main.h
@@ -291,6 +291,9 @@
#endif
#define MAX_USER_COMMAND_SIZE 4096
+#define DNS_DOMAIN_NAME_MAX_LEN 255
+#define ICMPv6_ADDR_LEN 16
+
#define HDD_MIN_TX_POWER (-100) /* minimum tx power */
#define HDD_MAX_TX_POWER (+100) /* maximum tx power */
@@ -518,6 +521,19 @@ typedef struct hdd_pmf_stats_s {
} hdd_pmf_stats_t;
#endif
+/**
+ * struct hdd_arp_stats_s - arp debug stats count
+ * @tx_arp_req_count: no. of arp req received from network stack
+ * @rx_arp_rsp_count: no. of arp res received from FW
+ * @tx_dropped: no. of arp req dropped at hdd layer
+ * @rx_dropped: no. of arp res dropped
+ * @rx_delivered: no. of arp res delivered to network stack
+ * @rx_refused: no of arp rsp refused (not delivered) to network stack
+ * @tx_host_fw_sent: no of arp req sent by FW OTA
+ * @rx_host_drop_reorder: no of arp res dropped by host
+ * @rx_fw_cnt: no of arp res received by FW
+ * @tx_ack_cnt: no of arp req acked by FW
+ */
struct hdd_arp_stats_s {
uint16_t tx_arp_req_count;
uint16_t rx_arp_rsp_count;
@@ -531,6 +547,88 @@ struct hdd_arp_stats_s {
uint16_t tx_ack_cnt;
};
+/**
+ * struct hdd_dns_stats_s - dns debug stats count
+ * @tx_dns_req_count: no. of dns query received from network stack
+ * @rx_dns_rsp_count: no. of dns res received from FW
+ * @tx_dropped: no. of dns query dropped at hdd layer
+ * @rx_delivered: no. of dns res delivered to network stack
+ * @rx_refused: no of dns res refused (not delivered) to network stack
+ * @tx_host_fw_sent: no of dns query sent by FW OTA
+ * @rx_host_drop: no of dns res dropped by host
+ * @tx_ack_cnt: no of dns req acked by FW
+ */
+struct hdd_dns_stats_s {
+ uint16_t tx_dns_req_count;
+ uint16_t rx_dns_rsp_count;
+ uint16_t tx_dropped;
+ uint16_t rx_delivered;
+ uint16_t rx_refused;
+ uint16_t tx_host_fw_sent;
+ uint16_t rx_host_drop;
+ uint16_t tx_ack_cnt;
+};
+
+/**
+ * struct hdd_tcp_stats_s - tcp debug stats count
+ * @tx_tcp_syn_count: no. of tcp syn received from network stack
+ * @@tx_tcp_ack_count: no. of tcp ack received from network stack
+ * @rx_tcp_syn_ack_count: no. of tcp syn ack received from FW
+ * @tx_tcp_syn_dropped: no. of tcp syn dropped at hdd layer
+ * @tx_tcp_ack_dropped: no. of tcp ack dropped at hdd layer
+ * @rx_delivered: no. of tcp syn ack delivered to network stack
+ * @rx_refused: no of tcp syn ack refused (not delivered) to network stack
+ * @tx_tcp_syn_host_fw_sent: no of tcp syn sent by FW OTA
+ * @@tx_tcp_ack_host_fw_sent: no of tcp ack sent by FW OTA
+ * @rx_host_drop: no of tcp syn ack dropped by host
+ * @tx_tcp_syn_ack_cnt: no of tcp syn acked by FW
+ * @tx_tcp_syn_ack_cnt: no of tcp ack acked by FW
+ * @is_tcp_syn_ack_rcv: flag to check tcp syn ack received or not
+ * @is_tcp_ack_sent: flag to check tcp ack sent or not
+ */
+struct hdd_tcp_stats_s {
+ uint16_t tx_tcp_syn_count;
+ uint16_t tx_tcp_ack_count;
+ uint16_t rx_tcp_syn_ack_count;
+ uint16_t tx_tcp_syn_dropped;
+ uint16_t tx_tcp_ack_dropped;
+ uint16_t rx_delivered;
+ uint16_t rx_refused;
+ uint16_t tx_tcp_syn_host_fw_sent;
+ uint16_t tx_tcp_ack_host_fw_sent;
+ uint16_t rx_host_drop;
+ uint16_t rx_fw_cnt;
+ uint16_t tx_tcp_syn_ack_cnt;
+ uint16_t tx_tcp_ack_ack_cnt;
+ bool is_tcp_syn_ack_rcv;
+ bool is_tcp_ack_sent;
+
+};
+
+/**
+ * struct hdd_icmpv4_stats_s - icmpv4 debug stats count
+ * @tx_icmpv4_req_count: no. of icmpv4 req received from network stack
+ * @rx_icmpv4_rsp_count: no. of icmpv4 res received from FW
+ * @tx_dropped: no. of icmpv4 req dropped at hdd layer
+ * @rx_delivered: no. of icmpv4 res delivered to network stack
+ * @rx_refused: no of icmpv4 res refused (not delivered) to network stack
+ * @tx_host_fw_sent: no of icmpv4 req sent by FW OTA
+ * @rx_host_drop: no of icmpv4 res dropped by host
+ * @rx_fw_cnt: no of icmpv4 res received by FW
+ * @tx_ack_cnt: no of icmpv4 req acked by FW
+ */
+struct hdd_icmpv4_stats_s {
+ uint16_t tx_icmpv4_req_count;
+ uint16_t rx_icmpv4_rsp_count;
+ uint16_t tx_dropped;
+ uint16_t rx_delivered;
+ uint16_t rx_refused;
+ uint16_t tx_host_fw_sent;
+ uint16_t rx_host_drop;
+ uint16_t rx_fw_cnt;
+ uint16_t tx_ack_cnt;
+};
+
typedef struct hdd_stats_s {
tCsrSummaryStatsInfo summary_stat;
tCsrGlobalClassAStatsInfo ClassA_stat;
@@ -538,6 +636,9 @@ typedef struct hdd_stats_s {
struct csr_per_chain_rssi_stats_info per_chain_rssi_stats;
hdd_tx_rx_stats_t hddTxRxStats;
struct hdd_arp_stats_s hdd_arp_stats;
+ struct hdd_dns_stats_s hdd_dns_stats;
+ struct hdd_tcp_stats_s hdd_tcp_stats;
+ struct hdd_icmpv4_stats_s hdd_icmpv4_stats;
#ifdef WLAN_FEATURE_11W
hdd_pmf_stats_t hddPmfStats;
#endif
@@ -1450,6 +1551,13 @@ struct hdd_adapter_s {
struct lfr_firmware_status lfr_fw_status;
bool con_status;
bool dad;
+ uint32_t pkt_type_bitmap;
+ uint32_t track_arp_ip;
+ uint8_t dns_payload[256];
+ uint32_t track_dns_domain_len;
+ uint32_t track_src_port;
+ uint32_t track_dest_port;
+ uint32_t track_dest_ipv4;
/* random address management for management action frames */
spinlock_t random_mac_lock;
struct action_frame_random_mac random_mac[MAX_RANDOM_MAC_ADDRS];
@@ -2023,7 +2131,6 @@ struct hdd_context_s {
uint32_t no_of_probe_req_ouis;
uint32_t *probe_req_voui;
struct hdd_nud_stats_context nud_stats_context;
- uint32_t track_arp_ip;
uint8_t bt_a2dp_active:1;
uint8_t bt_vo_active:1;
#ifdef FEATURE_SPECTRAL_SCAN
diff --git a/core/hdd/inc/wlan_hdd_tx_rx.h b/core/hdd/inc/wlan_hdd_tx_rx.h
index 2fdd9ce8a5de..95a3df7a7407 100644
--- a/core/hdd/inc/wlan_hdd_tx_rx.h
+++ b/core/hdd/inc/wlan_hdd_tx_rx.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -62,6 +62,19 @@ QDF_STATUS hdd_deinit_tx_rx(hdd_adapter_t *pAdapter);
QDF_STATUS hdd_rx_packet_cbk(void *context, qdf_nbuf_t rxBuf);
/**
+ * hdd_tx_rx_collect_connectivity_stats_info() - collect connectivity stats
+ * @skb: pointer to skb data
+ * @adapter: pointer to vdev apdapter
+ * @action: action done on pkt.
+ * @pkt_type: data pkt type
+ *
+ * Return: None
+ */
+void hdd_tx_rx_collect_connectivity_stats_info(struct sk_buff *skb,
+ void *adapter, enum connectivity_stats_pkt_status action,
+ uint8_t *pkt_type);
+
+/**
* hdd_rx_ol_init() - Initialize Rx mode(LRO or GRO) method
* @hdd_ctx: pointer to HDD Station Context
*
diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c
index a49b0955eb3e..9367c19e3a3b 100644
--- a/core/hdd/src/wlan_hdd_assoc.c
+++ b/core/hdd/src/wlan_hdd_assoc.c
@@ -1881,6 +1881,7 @@ QDF_STATUS hdd_roam_register_sta(hdd_adapter_t *pAdapter,
/* Register the vdev transmit and receive functions */
qdf_mem_zero(&txrx_ops, sizeof(txrx_ops));
txrx_ops.rx.rx = hdd_rx_packet_cbk;
+ txrx_ops.rx.stats_rx = hdd_tx_rx_collect_connectivity_stats_info;
ol_txrx_vdev_register(
ol_txrx_get_vdev_from_vdev_id(pAdapter->sessionId),
pAdapter, &txrx_ops);
@@ -3665,6 +3666,7 @@ QDF_STATUS hdd_roam_register_tdlssta(hdd_adapter_t *pAdapter,
/* Register the vdev transmit and receive functions */
qdf_mem_zero(&txrx_ops, sizeof(txrx_ops));
txrx_ops.rx.rx = hdd_rx_packet_cbk;
+ txrx_ops.rx.stats_rx = hdd_tx_rx_collect_connectivity_stats_info;
ol_txrx_vdev_register(
ol_txrx_get_vdev_from_vdev_id(pAdapter->sessionId),
pAdapter, &txrx_ops);
diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c
index edf3d6eaa0fd..deaa28ddbdcb 100644
--- a/core/hdd/src/wlan_hdd_cfg80211.c
+++ b/core/hdd/src/wlan_hdd_cfg80211.c
@@ -10778,6 +10778,8 @@ static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
QCA_ATTR_NUD_STATS_SET_START
#define STATS_GW_IPV4 \
QCA_ATTR_NUD_STATS_GW_IPV4
+#define STATS_SET_DATA_PKT_INFO \
+ QCA_ATTR_NUD_STATS_SET_DATA_PKT_INFO
#define STATS_SET_MAX \
QCA_ATTR_NUD_STATS_SET_MAX
@@ -10785,8 +10787,245 @@ const struct nla_policy
qca_wlan_vendor_set_nud_stats[STATS_SET_MAX + 1] = {
[STATS_SET_START] = {.type = NLA_FLAG },
[STATS_GW_IPV4] = {.type = NLA_U32 },
+ [STATS_SET_DATA_PKT_INFO] = {.type = NLA_U32 },
};
+/* define short names for the global vendor params */
+#define CONNECTIVITY_STATS_SET_INVALID \
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_SET_INVALID
+#define STATS_PKT_INFO_TYPE \
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_STATS_PKT_INFO_TYPE
+#define STATS_DNS_DOMAIN_NAME \
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_DNS_DOMAIN_NAME
+#define STATS_SRC_PORT \
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_SRC_PORT
+#define STATS_DEST_PORT \
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_PORT
+#define STATS_DEST_IPV4 \
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_IPV4
+#define STATS_DEST_IPV6 \
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_IPV6
+#define CONNECTIVITY_STATS_SET_MAX \
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_SET_MAX
+
+const struct nla_policy
+qca_wlan_vendor_set_connectivity_check_stats[CONNECTIVITY_STATS_SET_MAX + 1] = {
+ [STATS_PKT_INFO_TYPE] = {.type = NLA_U32 },
+ [STATS_DNS_DOMAIN_NAME] = {.type = NLA_BINARY,
+ .len = DNS_DOMAIN_NAME_MAX_LEN },
+ [STATS_SRC_PORT] = {.type = NLA_U32 },
+ [STATS_DEST_PORT] = {.type = NLA_U32 },
+ [STATS_DEST_IPV4] = {.type = NLA_U32 },
+ [STATS_DEST_IPV6] = {.type = NLA_BINARY,
+ .len = ICMPv6_ADDR_LEN },
+};
+
+/**
+ * hdd_dns_unmake_name_query() - Convert an uncompressed DNS name to a
+ * NUL-terminated string
+ * @name: DNS name
+ *
+ * Return: Produce a printable version of a DNS name.
+ */
+static inline uint8_t *hdd_dns_unmake_name_query(uint8_t *name)
+{
+ uint8_t *p;
+ unsigned int len;
+
+ p = name;
+ while ((len = *p)) {
+ *(p++) = '.';
+ p += len;
+ }
+
+ return name + 1;
+}
+
+/**
+ * hdd_dns_make_name_query() - Convert a standard NUL-terminated string
+ * to DNS name
+ * @string: Name as a NUL-terminated string
+ * @buf: Buffer in which to place DNS name
+ *
+ * DNS names consist of "<length>element" pairs.
+ *
+ * Return: Byte following constructed DNS name
+ */
+static uint8_t *hdd_dns_make_name_query(const uint8_t *string, uint8_t *buf)
+{
+ uint8_t *length_byte = buf++;
+ uint8_t c;
+
+ while ((c = *(string++))) {
+ if (c == '.') {
+ *length_byte = buf - length_byte - 1;
+ length_byte = buf;
+ }
+ *(buf++) = c;
+ }
+ *length_byte = buf - length_byte - 1;
+ *(buf++) = '\0';
+ return buf;
+}
+
+/**
+ * hdd_set_clear_connectivity_check_stats_info() - set/clear stats info
+ * @adapter: Pointer to hdd adapter
+ * @arp_stats_params: arp stats structure to be sent to FW
+ * @tb: nl attribute
+ * @is_set_stats: set/clear stats
+ *
+ *
+ * Return: 0 on success, negative errno on failure
+ */
+static int hdd_set_clear_connectivity_check_stats_info(
+ hdd_adapter_t *adapter,
+ struct set_arp_stats_params *arp_stats_params,
+ struct nlattr **tb, bool is_set_stats)
+{
+ struct nlattr *tb2[CONNECTIVITY_STATS_SET_MAX + 1];
+ struct nlattr *curr_attr = NULL;
+ int err = 0;
+ uint32_t pkt_bitmap;
+ int rem;
+
+ /* Clear All Stats command has come */
+ if (!is_set_stats) {
+ arp_stats_params->pkt_type_bitmap = adapter->pkt_type_bitmap;
+ /* DNS tracking is not supported in FW. */
+ arp_stats_params->pkt_type_bitmap &=
+ ~CONNECTIVITY_CHECK_SET_DNS;
+ arp_stats_params->flag = false;
+ arp_stats_params->pkt_type = WLAN_NUD_STATS_ARP_PKT_TYPE;
+ qdf_mem_zero(&adapter->hdd_stats.hdd_arp_stats,
+ sizeof(adapter->hdd_stats.hdd_arp_stats));
+ qdf_mem_zero(&adapter->hdd_stats.hdd_dns_stats,
+ sizeof(adapter->hdd_stats.hdd_dns_stats));
+ qdf_mem_zero(&adapter->hdd_stats.hdd_tcp_stats,
+ sizeof(adapter->hdd_stats.hdd_tcp_stats));
+ qdf_mem_zero(&adapter->hdd_stats.hdd_icmpv4_stats,
+ sizeof(adapter->hdd_stats.hdd_icmpv4_stats));
+ adapter->track_arp_ip = 0;
+ qdf_mem_zero(adapter->dns_payload,
+ adapter->track_dns_domain_len);
+ adapter->track_dns_domain_len = 0;
+ adapter->track_src_port = 0;
+ adapter->track_dest_port = 0;
+ adapter->track_dest_ipv4 = 0;
+ adapter->pkt_type_bitmap = 0;
+ goto end;
+ }
+
+ /* Set NUD command for start tracking is received. */
+ nla_for_each_nested(curr_attr,
+ tb[STATS_SET_DATA_PKT_INFO],
+ rem) {
+
+ if (hdd_nla_parse(tb2,
+ CONNECTIVITY_STATS_SET_MAX,
+ nla_data(curr_attr), nla_len(curr_attr),
+ qca_wlan_vendor_set_connectivity_check_stats)) {
+ hdd_err("nla_parse failed");
+ err = -EINVAL;
+ goto end;
+ }
+
+ if (tb2[STATS_PKT_INFO_TYPE]) {
+ pkt_bitmap = nla_get_u32(tb2[STATS_PKT_INFO_TYPE]);
+ if (!pkt_bitmap) {
+ hdd_err("pkt tracking bitmap is empty");
+ err = -EINVAL;
+ goto end;
+ }
+ arp_stats_params->pkt_type_bitmap = pkt_bitmap;
+ arp_stats_params->flag = true;
+ adapter->pkt_type_bitmap |=
+ arp_stats_params->pkt_type_bitmap;
+
+ if (pkt_bitmap & CONNECTIVITY_CHECK_SET_ARP) {
+ if (!tb[STATS_GW_IPV4]) {
+ hdd_err("GW ipv4 address is not present");
+ err = -EINVAL;
+ goto end;
+ }
+ arp_stats_params->ip_addr =
+ nla_get_u32(tb[STATS_GW_IPV4]);
+ arp_stats_params->pkt_type =
+ WLAN_NUD_STATS_ARP_PKT_TYPE;
+ adapter->track_arp_ip =
+ arp_stats_params->ip_addr;
+ qdf_mem_zero(&adapter->hdd_stats.hdd_arp_stats,
+ sizeof(adapter->hdd_stats.
+ hdd_arp_stats));
+ }
+
+ if (pkt_bitmap & CONNECTIVITY_CHECK_SET_DNS) {
+ uint8_t *domain_name;
+
+ if (!tb2[STATS_DNS_DOMAIN_NAME]) {
+ hdd_err("DNS domain id is not present");
+ err = -EINVAL;
+ goto end;
+ }
+ domain_name =
+ nla_data(tb2[STATS_DNS_DOMAIN_NAME]);
+ adapter->track_dns_domain_len =
+ nla_len(tb2[STATS_DNS_DOMAIN_NAME]);
+ hdd_dns_make_name_query(domain_name,
+ adapter->dns_payload);
+ /* DNS tracking is not supported in FW. */
+ arp_stats_params->pkt_type_bitmap &=
+ ~CONNECTIVITY_CHECK_SET_DNS;
+ qdf_mem_zero(&adapter->hdd_stats.hdd_dns_stats,
+ sizeof(adapter->hdd_stats.
+ hdd_dns_stats));
+ }
+
+ if (pkt_bitmap & CONNECTIVITY_CHECK_SET_TCP_HANDSHAKE) {
+ if (!tb2[STATS_SRC_PORT] ||
+ !tb2[STATS_DEST_PORT]) {
+ hdd_err("Source/Dest port is not present");
+ err = -EINVAL;
+ goto end;
+ }
+ arp_stats_params->tcp_src_port =
+ nla_get_u32(tb2[STATS_SRC_PORT]);
+ arp_stats_params->tcp_dst_port =
+ nla_get_u32(tb2[STATS_DEST_PORT]);
+ adapter->track_src_port =
+ arp_stats_params->tcp_src_port;
+ adapter->track_dest_port =
+ arp_stats_params->tcp_dst_port;
+ qdf_mem_zero(&adapter->hdd_stats.hdd_tcp_stats,
+ sizeof(adapter->hdd_stats.
+ hdd_tcp_stats));
+ }
+
+ if (pkt_bitmap & CONNECTIVITY_CHECK_SET_ICMPV4) {
+ if (!tb2[STATS_DEST_IPV4]) {
+ hdd_err("destination ipv4 address to track ping packets is not present");
+ err = -EINVAL;
+ goto end;
+ }
+ arp_stats_params->icmp_ipv4 =
+ nla_get_u32(tb2[STATS_DEST_IPV4]);
+ adapter->track_dest_ipv4 =
+ arp_stats_params->icmp_ipv4;
+ qdf_mem_zero(&adapter->hdd_stats.hdd_tcp_stats,
+ sizeof(adapter->hdd_stats.
+ hdd_tcp_stats));
+ }
+ } else {
+ hdd_err("stats list empty");
+ err = -EINVAL;
+ goto end;
+ }
+ }
+
+end:
+ return err;
+}
+
/**
* hdd_post_get_chain_rssi_rsp - send rsp to user space
* @hdd_ctx: Pointer to hdd context
@@ -10976,7 +11215,7 @@ static int __wlan_hdd_cfg80211_set_nud_stats(struct wiphy *wiphy,
struct net_device *dev = wdev->netdev;
hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
- struct set_arp_stats_params arp_stats_params;
+ struct set_arp_stats_params arp_stats_params = {0};
int err = 0;
ENTER();
@@ -11004,25 +11243,65 @@ static int __wlan_hdd_cfg80211_set_nud_stats(struct wiphy *wiphy,
}
if (tb[STATS_SET_START]) {
- if (!tb[STATS_GW_IPV4]) {
- QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
- "%s STATS_SET_START CMD", __func__);
- return -EINVAL;
+ /* tracking is enabled for stats other than arp. */
+ if (tb[STATS_SET_DATA_PKT_INFO]) {
+ err = hdd_set_clear_connectivity_check_stats_info(
+ adapter,
+ &arp_stats_params, tb, true);
+ if (err)
+ return -EINVAL;
+
+ /*
+ * if only tracking dns, then don't send
+ * wmi command to FW.
+ */
+ if (!arp_stats_params.pkt_type_bitmap)
+ return err;
+ } else {
+ if (!tb[STATS_GW_IPV4]) {
+ QDF_TRACE(QDF_MODULE_ID_HDD,
+ QDF_TRACE_LEVEL_ERROR,
+ "%s STATS_SET_START CMD", __func__);
+ return -EINVAL;
+ }
+ arp_stats_params.flag = true;
+ arp_stats_params.ip_addr =
+ nla_get_u32(tb[STATS_GW_IPV4]);
+ adapter->track_arp_ip = arp_stats_params.ip_addr;
+
+ qdf_mem_zero(&adapter->hdd_stats.hdd_arp_stats,
+ sizeof(adapter->hdd_stats.hdd_arp_stats));
+
+ arp_stats_params.pkt_type = WLAN_NUD_STATS_ARP_PKT_TYPE;
}
- 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;
+ /* clear tracking stats of other data types as well*/
+ if (adapter->pkt_type_bitmap) {
+ err = hdd_set_clear_connectivity_check_stats_info(
+ adapter,
+ &arp_stats_params, tb, false);
+ if (err)
+ return -EINVAL;
+
+ /*
+ * if only tracking dns, then don't send
+ * wmi command to FW.
+ */
+ if (!arp_stats_params.pkt_type_bitmap)
+ return err;
+ } else {
+ arp_stats_params.flag = false;
+ qdf_mem_zero(&adapter->hdd_stats.hdd_arp_stats,
+ sizeof(adapter->hdd_stats.hdd_arp_stats));
+ arp_stats_params.pkt_type = WLAN_NUD_STATS_ARP_PKT_TYPE;
+ }
}
+
if (arp_stats_params.flag) {
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
"%s STATS_SET_START Cleared!!", __func__);
}
- qdf_mem_zero(&adapter->hdd_stats.hdd_arp_stats,
- sizeof(adapter->hdd_stats.hdd_arp_stats));
- arp_stats_params.pkt_type = WLAN_NUD_STATS_ARP_PKT_TYPE;
arp_stats_params.vdev_id = adapter->sessionId;
if (QDF_STATUS_SUCCESS !=
@@ -11179,9 +11458,45 @@ static int wlan_hdd_cfg80211_set_limit_offchan_param(struct wiphy *wiphy,
QCA_ATTR_NUD_STATS_AP_LINK_ACTIVE
#define AP_LINK_DAD \
QCA_ATTR_NUD_STATS_IS_DAD
+#define DATA_PKT_STATS \
+ QCA_ATTR_NUD_STATS_DATA_PKT_STATS
#define STATS_GET_MAX \
QCA_ATTR_NUD_STATS_GET_MAX
+#define CHECK_STATS_INVALID \
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_INVALID
+#define CHECK_STATS_PKT_TYPE \
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_TYPE
+#define CHECK_STATS_PKT_DNS_DOMAIN_NAME \
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DNS_DOMAIN_NAME
+#define CHECK_STATS_PKT_SRC_PORT \
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_SRC_PORT
+#define CHECK_STATS_PKT_DEST_PORT \
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_PORT
+#define CHECK_STATS_PKT_DEST_IPV4 \
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_IPV4
+#define CHECK_STATS_PKT_DEST_IPV6 \
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_IPV6
+#define CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV \
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV
+#define CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC \
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC
+#define CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC \
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC
+#define CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS \
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS
+#define CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC \
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC
+#define CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC \
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC
+#define CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV \
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV
+#define CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP \
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP
+#define CHECK_DATA_STATS_MAX \
+ QCA_ATTR_CONNECTIVITY_CHECK_DATA_STATS_MAX
+
+
const struct nla_policy
qca_wlan_vendor_get_nud_stats[STATS_GET_MAX + 1] = {
[COUNT_FROM_NETDEV] = {.type = NLA_U16 },
@@ -11194,9 +11509,279 @@ qca_wlan_vendor_get_nud_stats[STATS_GET_MAX + 1] = {
[RSP_COUNT_OUT_OF_ORDER_DROP] = {.type = NLA_U16 },
[AP_LINK_ACTIVE] = {.type = NLA_FLAG },
[AP_LINK_DAD] = {.type = NLA_FLAG },
+ [DATA_PKT_STATS] = {.type = NLA_U16 },
};
/**
+ * hdd_populate_dns_stats_info() - send dns stats info to network stack
+ * @adapter: pointer to adapter context
+ * @skb: pointer to skb
+ *
+ *
+ * Return: An error code or 0 on success.
+ */
+static int hdd_populate_dns_stats_info(hdd_adapter_t *adapter,
+ struct sk_buff *skb)
+{
+ uint8_t *dns_query;
+
+ dns_query = qdf_mem_malloc(adapter->track_dns_domain_len + 1);
+ if (!dns_query) {
+ QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
+ "%s: mem alloc fail.", __func__);
+ return -EINVAL;
+ }
+
+ qdf_mem_copy(dns_query, adapter->dns_payload,
+ adapter->track_dns_domain_len);
+
+ if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
+ CONNECTIVITY_CHECK_SET_DNS) ||
+ nla_put(skb, CHECK_STATS_PKT_DNS_DOMAIN_NAME,
+ adapter->track_dns_domain_len,
+ hdd_dns_unmake_name_query(dns_query)) ||
+ nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV,
+ adapter->hdd_stats.hdd_dns_stats.tx_dns_req_count) ||
+ nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC,
+ adapter->hdd_stats.hdd_dns_stats.tx_host_fw_sent) ||
+ nla_put_u16(skb, CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC,
+ adapter->hdd_stats.hdd_dns_stats.tx_host_fw_sent) ||
+ nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS,
+ adapter->hdd_stats.hdd_dns_stats.tx_ack_cnt) ||
+ nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC,
+ adapter->hdd_stats.hdd_dns_stats.rx_dns_rsp_count) ||
+ nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV,
+ adapter->hdd_stats.hdd_dns_stats.rx_delivered) ||
+ nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP,
+ adapter->hdd_stats.hdd_dns_stats.rx_host_drop)) {
+ hdd_err("nla put fail");
+ qdf_mem_free(dns_query);
+ kfree_skb(skb);
+ return -EINVAL;
+ }
+ qdf_mem_free(dns_query);
+ return 0;
+}
+
+/**
+ * hdd_populate_tcp_stats_info() - send tcp stats info to network stack
+ * @adapter: pointer to adapter context
+ * @skb: pointer to skb
+ * @pkt_type: tcp pkt type
+ *
+ * Return: An error code or 0 on success.
+ */
+static int hdd_populate_tcp_stats_info(hdd_adapter_t *adapter,
+ struct sk_buff *skb,
+ uint8_t pkt_type)
+{
+ switch (pkt_type) {
+ case CONNECTIVITY_CHECK_SET_TCP_SYN:
+ /* Fill info for tcp syn packets (tx packet) */
+ if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
+ CONNECTIVITY_CHECK_SET_TCP_SYN) ||
+ nla_put_u16(skb, CHECK_STATS_PKT_SRC_PORT,
+ adapter->track_src_port) ||
+ nla_put_u16(skb, CHECK_STATS_PKT_DEST_PORT,
+ adapter->track_dest_port) ||
+ nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV,
+ adapter->hdd_stats.hdd_tcp_stats.tx_tcp_syn_count) ||
+ nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC,
+ adapter->hdd_stats.hdd_tcp_stats.
+ tx_tcp_syn_host_fw_sent) ||
+ nla_put_u16(skb, CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC,
+ adapter->hdd_stats.hdd_tcp_stats.
+ tx_tcp_syn_host_fw_sent) ||
+ nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS,
+ adapter->hdd_stats.hdd_tcp_stats.tx_tcp_syn_ack_cnt)) {
+ hdd_err("nla put fail");
+ kfree_skb(skb);
+ return -EINVAL;
+ }
+ break;
+ case CONNECTIVITY_CHECK_SET_TCP_SYN_ACK:
+ /* Fill info for tcp syn-ack packets (rx packet) */
+ if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
+ CONNECTIVITY_CHECK_SET_TCP_SYN_ACK) ||
+ nla_put_u16(skb, CHECK_STATS_PKT_SRC_PORT,
+ adapter->track_src_port) ||
+ nla_put_u16(skb, CHECK_STATS_PKT_DEST_PORT,
+ adapter->track_dest_port) ||
+ nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC,
+ adapter->hdd_stats.hdd_tcp_stats.rx_fw_cnt) ||
+ nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC,
+ adapter->hdd_stats.hdd_tcp_stats.
+ rx_tcp_syn_ack_count) ||
+ nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV,
+ adapter->hdd_stats.hdd_tcp_stats.rx_delivered) ||
+ nla_put_u16(skb,
+ CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP,
+ adapter->hdd_stats.hdd_tcp_stats.rx_host_drop)) {
+ hdd_err("nla put fail");
+ kfree_skb(skb);
+ return -EINVAL;
+ }
+ break;
+ case CONNECTIVITY_CHECK_SET_TCP_ACK:
+ /* Fill info for tcp ack packets (tx packet) */
+ if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
+ CONNECTIVITY_CHECK_SET_TCP_ACK) ||
+ nla_put_u16(skb, CHECK_STATS_PKT_SRC_PORT,
+ adapter->track_src_port) ||
+ nla_put_u16(skb, CHECK_STATS_PKT_DEST_PORT,
+ adapter->track_dest_port) ||
+ nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV,
+ adapter->hdd_stats.hdd_tcp_stats.tx_tcp_ack_count) ||
+ nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC,
+ adapter->hdd_stats.hdd_tcp_stats.
+ tx_tcp_ack_host_fw_sent) ||
+ nla_put_u16(skb, CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC,
+ adapter->hdd_stats.hdd_tcp_stats.
+ tx_tcp_ack_host_fw_sent) ||
+ nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS,
+ adapter->hdd_stats.hdd_tcp_stats.tx_tcp_ack_ack_cnt)) {
+ hdd_err("nla put fail");
+ kfree_skb(skb);
+ return -EINVAL;
+ }
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+/**
+ * hdd_populate_icmpv4_stats_info() - send icmpv4 stats info to network stack
+ * @adapter: pointer to adapter context
+ * @skb: pointer to skb
+ *
+ *
+ * Return: An error code or 0 on success.
+ */
+static int hdd_populate_icmpv4_stats_info(hdd_adapter_t *adapter,
+ struct sk_buff *skb)
+{
+ if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
+ CONNECTIVITY_CHECK_SET_ICMPV4) ||
+ nla_put_u32(skb, CHECK_STATS_PKT_DEST_IPV4,
+ adapter->track_dest_ipv4) ||
+ nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV,
+ adapter->hdd_stats.hdd_icmpv4_stats.tx_icmpv4_req_count) ||
+ nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC,
+ adapter->hdd_stats.hdd_icmpv4_stats.tx_host_fw_sent) ||
+ nla_put_u16(skb, CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC,
+ adapter->hdd_stats.hdd_icmpv4_stats.tx_host_fw_sent) ||
+ nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS,
+ adapter->hdd_stats.hdd_icmpv4_stats.tx_ack_cnt) ||
+ nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC,
+ adapter->hdd_stats.hdd_icmpv4_stats.rx_fw_cnt) ||
+ nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC,
+ adapter->hdd_stats.hdd_icmpv4_stats.rx_icmpv4_rsp_count) ||
+ nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV,
+ adapter->hdd_stats.hdd_icmpv4_stats.rx_delivered) ||
+ nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP,
+ adapter->hdd_stats.hdd_icmpv4_stats.rx_host_drop)) {
+ hdd_err("nla put fail");
+ kfree_skb(skb);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+/**
+ * hdd_populate_connectivity_check_stats_info() - send connectivity stats info
+ * to network stack
+ * @adapter: pointer to adapter context
+ * @skb: pointer to skb
+ *
+ *
+ * Return: An error code or 0 on success.
+ */
+
+static int hdd_populate_connectivity_check_stats_info(
+ hdd_adapter_t *adapter, struct sk_buff *skb)
+{
+ struct nlattr *connect_stats, *connect_info;
+ uint32_t count = 0;
+
+ connect_stats = nla_nest_start(skb, DATA_PKT_STATS);
+ if (connect_stats == NULL) {
+ hdd_err("nla_nest_start failed");
+ return -EINVAL;
+ }
+
+ if (adapter->pkt_type_bitmap & CONNECTIVITY_CHECK_SET_DNS) {
+ connect_info = nla_nest_start(skb, count);
+ if (connect_info == NULL) {
+ hdd_err("nla_nest_start failed count %u", count);
+ return -EINVAL;
+ }
+
+ if (hdd_populate_dns_stats_info(adapter, skb))
+ goto put_attr_fail;
+ nla_nest_end(skb, connect_info);
+ count++;
+ }
+
+ if (adapter->pkt_type_bitmap & CONNECTIVITY_CHECK_SET_TCP_HANDSHAKE) {
+ connect_info = nla_nest_start(skb, count);
+ if (connect_info == NULL) {
+ hdd_err("nla_nest_start failed count %u", count);
+ return -EINVAL;
+ }
+ if (hdd_populate_tcp_stats_info(adapter, skb,
+ CONNECTIVITY_CHECK_SET_TCP_SYN))
+ goto put_attr_fail;
+ nla_nest_end(skb, connect_info);
+ count++;
+
+ connect_info = nla_nest_start(skb, count);
+ if (connect_info == NULL) {
+ hdd_err("nla_nest_start failed count %u", count);
+ return -EINVAL;
+ }
+ if (hdd_populate_tcp_stats_info(adapter, skb,
+ CONNECTIVITY_CHECK_SET_TCP_SYN_ACK))
+ goto put_attr_fail;
+ nla_nest_end(skb, connect_info);
+ count++;
+
+ connect_info = nla_nest_start(skb, count);
+ if (connect_info == NULL) {
+ hdd_err("nla_nest_start failed count %u", count);
+ return -EINVAL;
+ }
+ if (hdd_populate_tcp_stats_info(adapter, skb,
+ CONNECTIVITY_CHECK_SET_TCP_ACK))
+ goto put_attr_fail;
+ nla_nest_end(skb, connect_info);
+ count++;
+ }
+
+ if (adapter->pkt_type_bitmap & CONNECTIVITY_CHECK_SET_ICMPV4) {
+ connect_info = nla_nest_start(skb, count);
+ if (connect_info == NULL) {
+ hdd_err("nla_nest_start failed count %u", count);
+ return -EINVAL;
+ }
+
+ if (hdd_populate_icmpv4_stats_info(adapter, skb))
+ goto put_attr_fail;
+ nla_nest_end(skb, connect_info);
+ count++;
+ }
+
+ nla_nest_end(skb, connect_stats);
+ return 0;
+
+put_attr_fail:
+ hdd_err("QCA_WLAN_VENDOR_ATTR put fail. count %u", count);
+ return -EINVAL;
+}
+
+
+/**
* __wlan_hdd_cfg80211_get_nud_stats() - get arp stats command to firmware
* @wiphy: pointer to wireless wiphy structure.
* @wdev: pointer to wireless_dev structure.
@@ -11219,6 +11804,7 @@ static int __wlan_hdd_cfg80211_get_nud_stats(struct wiphy *wiphy,
hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
struct get_arp_stats_params arp_stats_params;
+ uint32_t pkt_type_bitmap;
struct sk_buff *skb;
ENTER();
@@ -11300,7 +11886,15 @@ 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;
+ pkt_type_bitmap = adapter->pkt_type_bitmap;
+ /* ARP tracking is done above. */
+ pkt_type_bitmap &= ~CONNECTIVITY_CHECK_SET_ARP;
+
+ if (pkt_type_bitmap) {
+ if (hdd_populate_connectivity_check_stats_info(adapter, skb))
+ return -EINVAL;
+ }
+
cfg80211_vendor_cmd_reply(skb);
return err;
}
diff --git a/core/hdd/src/wlan_hdd_cfg80211.h b/core/hdd/src/wlan_hdd_cfg80211.h
index acf9298e1c6d..7f16d5157d21 100644
--- a/core/hdd/src/wlan_hdd_cfg80211.h
+++ b/core/hdd/src/wlan_hdd_cfg80211.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -300,6 +300,25 @@ typedef struct sHddAvoidFreqList {
*/
bool hdd_is_ie_valid(const uint8_t *ie, size_t ie_len);
+
+#define CONNECTIVITY_CHECK_SET_ARP \
+ QCA_WLAN_VENDOR_CONNECTIVITY_CHECK_SET_ARP
+#define CONNECTIVITY_CHECK_SET_DNS \
+ QCA_WLAN_VENDOR_CONNECTIVITY_CHECK_SET_DNS
+#define CONNECTIVITY_CHECK_SET_TCP_HANDSHAKE \
+ QCA_WLAN_VENDOR_CONNECTIVITY_CHECK_SET_TCP_HANDSHAKE
+#define CONNECTIVITY_CHECK_SET_ICMPV4 \
+ QCA_WLAN_VENDOR_CONNECTIVITY_CHECK_SET_ICMPV4
+#define CONNECTIVITY_CHECK_SET_ICMPV6 \
+ QCA_WLAN_VENDOR_CONNECTIVITY_CHECK_SET_ICMPV6
+#define CONNECTIVITY_CHECK_SET_TCP_SYN \
+ QCA_WLAN_VENDOR_CONNECTIVITY_CHECK_SET_TCP_SYN
+#define CONNECTIVITY_CHECK_SET_TCP_SYN_ACK \
+ QCA_WLAN_VENDOR_CONNECTIVITY_CHECK_SET_TCP_SYN_ACK
+#define CONNECTIVITY_CHECK_SET_TCP_ACK \
+ QCA_WLAN_VENDOR_CONNECTIVITY_CHECK_SET_TCP_ACK
+
+
struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
tCsrRoamInfo *pRoamInfo);
diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c
index 1313c5ae2959..56539299a400 100644
--- a/core/hdd/src/wlan_hdd_main.c
+++ b/core/hdd/src/wlan_hdd_main.c
@@ -10752,6 +10752,15 @@ static void hdd_get_nud_stats_cb(void *data, struct rsp_stats *rsp)
adapter->dad |= rsp->dad_detected;
adapter->con_status = rsp->connect_status;
+ /* Flag true indicates connectivity check stats present. */
+ if (rsp->connect_stats_present) {
+ hdd_notice("rsp->tcp_ack_recvd :%x", rsp->tcp_ack_recvd);
+ hdd_notice("rsp->icmpv4_rsp_recvd :%x", rsp->icmpv4_rsp_recvd);
+ adapter->hdd_stats.hdd_tcp_stats.rx_fw_cnt = rsp->tcp_ack_recvd;
+ adapter->hdd_stats.hdd_icmpv4_stats.rx_fw_cnt =
+ rsp->icmpv4_rsp_recvd;
+ }
+
spin_lock(&hdd_context_lock);
context = &hdd_ctx->nud_stats_context;
complete(&context->response_event);
diff --git a/core/hdd/src/wlan_hdd_ocb.c b/core/hdd/src/wlan_hdd_ocb.c
index 80ef8ffb97d8..a613d10b456e 100644
--- a/core/hdd/src/wlan_hdd_ocb.c
+++ b/core/hdd/src/wlan_hdd_ocb.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -266,6 +266,7 @@ static int hdd_ocb_register_sta(hdd_adapter_t *adapter)
/* Register the vdev transmit and receive functions */
qdf_mem_zero(&txrx_ops, sizeof(txrx_ops));
txrx_ops.rx.rx = hdd_rx_packet_cbk;
+ txrx_ops.rx.stats_rx = hdd_tx_rx_collect_connectivity_stats_info;
ol_txrx_vdev_register(
ol_txrx_get_vdev_from_vdev_id(adapter->sessionId),
adapter, &txrx_ops);
diff --git a/core/hdd/src/wlan_hdd_tx_rx.c b/core/hdd/src/wlan_hdd_tx_rx.c
index e70bb34f1cba..93e2fad23b7b 100644
--- a/core/hdd/src/wlan_hdd_tx_rx.c
+++ b/core/hdd/src/wlan_hdd_tx_rx.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -506,6 +506,261 @@ static void hdd_get_transmit_sta_id(hdd_adapter_t *adapter,
}
/**
+ * hdd_tx_rx_is_dns_domain_name_match() - function to check whether dns
+ * domain name in the received skb matches with the tracking dns domain
+ * name or not
+ *
+ * @skb: pointer to skb
+ * @adapter: pointer to adapter
+ *
+ * Returns: true if matches else false
+ */
+static bool hdd_tx_rx_is_dns_domain_name_match(struct sk_buff *skb,
+ hdd_adapter_t *adapter)
+{
+ uint8_t *domain_name;
+
+ if (adapter->track_dns_domain_len == 0)
+ return false;
+
+ domain_name = qdf_nbuf_get_dns_domain_name(skb,
+ adapter->track_dns_domain_len);
+ if (strncmp(domain_name, adapter->dns_payload,
+ adapter->track_dns_domain_len) == 0)
+ return true;
+ else
+ return false;
+}
+
+void hdd_tx_rx_collect_connectivity_stats_info(struct sk_buff *skb,
+ void *context,
+ enum connectivity_stats_pkt_status action,
+ uint8_t *pkt_type)
+{
+ uint32_t pkt_type_bitmap;
+ hdd_adapter_t *adapter = NULL;
+
+ adapter = (hdd_adapter_t *)context;
+ if (unlikely(adapter->magic != WLAN_HDD_ADAPTER_MAGIC)) {
+ QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_ERROR,
+ "Magic cookie(%x) for adapter sanity verification is invalid",
+ adapter->magic);
+ return;
+ }
+
+ /* ARP tracking is done already. */
+ pkt_type_bitmap = adapter->pkt_type_bitmap;
+ pkt_type_bitmap &= ~CONNECTIVITY_CHECK_SET_ARP;
+
+ if (!pkt_type_bitmap)
+ return;
+
+ switch (action) {
+ case PKT_TYPE_REQ:
+ case PKT_TYPE_TX_HOST_FW_SENT:
+ if (qdf_nbuf_is_icmp_pkt(skb)) {
+ if (qdf_nbuf_data_is_icmpv4_req(skb) &&
+ (adapter->track_dest_ipv4 ==
+ qdf_nbuf_get_icmpv4_tgt_ip(skb))) {
+ *pkt_type = CONNECTIVITY_CHECK_SET_ICMPV4;
+ if (action == PKT_TYPE_REQ) {
+ ++adapter->hdd_stats.hdd_icmpv4_stats.
+ tx_icmpv4_req_count;
+ QDF_TRACE(QDF_MODULE_ID_HDD_DATA,
+ QDF_TRACE_LEVEL_INFO_HIGH,
+ "%s : ICMPv4 Req packet", __func__);
+ } else
+ /* host receives tx completion */
+ ++adapter->hdd_stats.hdd_icmpv4_stats.
+ tx_host_fw_sent;
+ }
+ } else if (qdf_nbuf_is_ipv4_tcp_pkt(skb)) {
+ if (qdf_nbuf_data_is_tcp_syn(skb) &&
+ (adapter->track_dest_port ==
+ qdf_nbuf_data_get_tcp_dst_port(skb))) {
+ *pkt_type = CONNECTIVITY_CHECK_SET_TCP_SYN;
+ if (action == PKT_TYPE_REQ) {
+ ++adapter->hdd_stats.hdd_tcp_stats.
+ tx_tcp_syn_count;
+ QDF_TRACE(QDF_MODULE_ID_HDD_DATA,
+ QDF_TRACE_LEVEL_INFO_HIGH,
+ "%s : TCP Syn packet", __func__);
+ } else
+ /* host receives tx completion */
+ ++adapter->hdd_stats.hdd_tcp_stats.
+ tx_tcp_syn_host_fw_sent;
+ } else if ((adapter->hdd_stats.hdd_tcp_stats.
+ is_tcp_syn_ack_rcv || adapter->hdd_stats.
+ hdd_tcp_stats.is_tcp_ack_sent) &&
+ qdf_nbuf_data_is_tcp_ack(skb) &&
+ (adapter->track_dest_port ==
+ qdf_nbuf_data_get_tcp_dst_port(skb))) {
+ *pkt_type = CONNECTIVITY_CHECK_SET_TCP_ACK;
+ if (action == PKT_TYPE_REQ &&
+ adapter->hdd_stats.hdd_tcp_stats.
+ is_tcp_syn_ack_rcv) {
+ ++adapter->hdd_stats.hdd_tcp_stats.
+ tx_tcp_ack_count;
+ adapter->hdd_stats.hdd_tcp_stats.
+ is_tcp_syn_ack_rcv = false;
+ adapter->hdd_stats.hdd_tcp_stats.
+ is_tcp_ack_sent = true;
+ QDF_TRACE(QDF_MODULE_ID_HDD_DATA,
+ QDF_TRACE_LEVEL_INFO_HIGH,
+ "%s : TCP Ack packet", __func__);
+ } else if (action == PKT_TYPE_TX_HOST_FW_SENT &&
+ adapter->hdd_stats.hdd_tcp_stats.
+ is_tcp_ack_sent) {
+ /* host receives tx completion */
+ ++adapter->hdd_stats.hdd_tcp_stats.
+ tx_tcp_ack_host_fw_sent;
+ adapter->hdd_stats.hdd_tcp_stats.
+ is_tcp_ack_sent = false;
+ }
+ }
+ } else if (qdf_nbuf_is_ipv4_udp_pkt(skb)) {
+ if (qdf_nbuf_data_is_dns_query(skb) &&
+ hdd_tx_rx_is_dns_domain_name_match(skb, adapter)) {
+ *pkt_type = CONNECTIVITY_CHECK_SET_DNS;
+ if (action == PKT_TYPE_REQ) {
+ ++adapter->hdd_stats.hdd_dns_stats.
+ tx_dns_req_count;
+ QDF_TRACE(QDF_MODULE_ID_HDD_DATA,
+ QDF_TRACE_LEVEL_INFO_HIGH,
+ "%s : DNS query packet", __func__);
+ } else
+ /* host receives tx completion */
+ ++adapter->hdd_stats.hdd_dns_stats.
+ tx_host_fw_sent;
+ }
+ }
+ break;
+
+ case PKT_TYPE_RSP:
+ if (qdf_nbuf_is_icmp_pkt(skb)) {
+ if (qdf_nbuf_data_is_icmpv4_rsp(skb) &&
+ (adapter->track_dest_ipv4 ==
+ qdf_nbuf_get_icmpv4_src_ip(skb))) {
+ ++adapter->hdd_stats.hdd_icmpv4_stats.
+ rx_icmpv4_rsp_count;
+ *pkt_type =
+ CONNECTIVITY_CHECK_SET_ICMPV4;
+ QDF_TRACE(QDF_MODULE_ID_HDD_DATA,
+ QDF_TRACE_LEVEL_INFO_HIGH,
+ "%s : ICMPv4 Res packet", __func__);
+ }
+ } else if (qdf_nbuf_is_ipv4_tcp_pkt(skb)) {
+ if (qdf_nbuf_data_is_tcp_syn_ack(skb) &&
+ (adapter->track_dest_port ==
+ qdf_nbuf_data_get_tcp_src_port(skb))) {
+ ++adapter->hdd_stats.hdd_tcp_stats.
+ rx_tcp_syn_ack_count;
+ adapter->hdd_stats.hdd_tcp_stats.
+ is_tcp_syn_ack_rcv = true;
+ *pkt_type =
+ CONNECTIVITY_CHECK_SET_TCP_SYN_ACK;
+ QDF_TRACE(QDF_MODULE_ID_HDD_DATA,
+ QDF_TRACE_LEVEL_INFO_HIGH,
+ "%s : TCP Syn ack packet", __func__);
+ }
+ } else if (qdf_nbuf_is_ipv4_udp_pkt(skb)) {
+ if (qdf_nbuf_data_is_dns_response(skb) &&
+ hdd_tx_rx_is_dns_domain_name_match(skb, adapter)) {
+ ++adapter->hdd_stats.hdd_dns_stats.
+ rx_dns_rsp_count;
+ *pkt_type = CONNECTIVITY_CHECK_SET_DNS;
+ QDF_TRACE(QDF_MODULE_ID_HDD_DATA,
+ QDF_TRACE_LEVEL_INFO_HIGH,
+ "%s : DNS response packet", __func__);
+ }
+ }
+ break;
+
+ case PKT_TYPE_TX_DROPPED:
+ switch (*pkt_type) {
+ case CONNECTIVITY_CHECK_SET_ICMPV4:
+ ++adapter->hdd_stats.hdd_icmpv4_stats.tx_dropped;
+ QDF_TRACE(QDF_MODULE_ID_HDD_DATA,
+ QDF_TRACE_LEVEL_INFO_HIGH,
+ "%s : ICMPv4 Req packet dropped", __func__);
+ break;
+ case CONNECTIVITY_CHECK_SET_TCP_SYN:
+ ++adapter->hdd_stats.hdd_tcp_stats.tx_tcp_syn_dropped;
+ QDF_TRACE(QDF_MODULE_ID_HDD_DATA,
+ QDF_TRACE_LEVEL_INFO_HIGH,
+ "%s : TCP syn packet dropped", __func__);
+ break;
+ case CONNECTIVITY_CHECK_SET_TCP_ACK:
+ ++adapter->hdd_stats.hdd_tcp_stats.tx_tcp_ack_dropped;
+ QDF_TRACE(QDF_MODULE_ID_HDD_DATA,
+ QDF_TRACE_LEVEL_INFO_HIGH,
+ "%s : TCP ack packet dropped", __func__);
+ break;
+ case CONNECTIVITY_CHECK_SET_DNS:
+ ++adapter->hdd_stats.hdd_dns_stats.tx_dropped;
+ QDF_TRACE(QDF_MODULE_ID_HDD_DATA,
+ QDF_TRACE_LEVEL_INFO_HIGH,
+ "%s : DNS query packet dropped", __func__);
+ break;
+ default:
+ break;
+ }
+ break;
+ case PKT_TYPE_RX_DELIVERED:
+ switch (*pkt_type) {
+ case CONNECTIVITY_CHECK_SET_ICMPV4:
+ ++adapter->hdd_stats.hdd_icmpv4_stats.rx_delivered;
+ break;
+ case CONNECTIVITY_CHECK_SET_TCP_SYN_ACK:
+ ++adapter->hdd_stats.hdd_tcp_stats.rx_delivered;
+ break;
+ case CONNECTIVITY_CHECK_SET_DNS:
+ ++adapter->hdd_stats.hdd_dns_stats.rx_delivered;
+ break;
+ default:
+ break;
+ }
+ break;
+ case PKT_TYPE_RX_REFUSED:
+ switch (*pkt_type) {
+ case CONNECTIVITY_CHECK_SET_ICMPV4:
+ ++adapter->hdd_stats.hdd_icmpv4_stats.rx_refused;
+ break;
+ case CONNECTIVITY_CHECK_SET_TCP_SYN_ACK:
+ ++adapter->hdd_stats.hdd_tcp_stats.rx_refused;
+ break;
+ case CONNECTIVITY_CHECK_SET_DNS:
+ ++adapter->hdd_stats.hdd_dns_stats.rx_refused;
+ break;
+ default:
+ break;
+ }
+ break;
+ case PKT_TYPE_TX_ACK_CNT:
+ switch (*pkt_type) {
+ case CONNECTIVITY_CHECK_SET_ICMPV4:
+ ++adapter->hdd_stats.hdd_icmpv4_stats.tx_ack_cnt;
+ break;
+ case CONNECTIVITY_CHECK_SET_TCP_SYN:
+ ++adapter->hdd_stats.hdd_tcp_stats.tx_tcp_syn_ack_cnt;
+ break;
+ case CONNECTIVITY_CHECK_SET_TCP_ACK:
+ ++adapter->hdd_stats.hdd_tcp_stats.tx_tcp_ack_ack_cnt;
+ break;
+ case CONNECTIVITY_CHECK_SET_DNS:
+ ++adapter->hdd_stats.hdd_dns_stats.tx_ack_cnt;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+
+/**
* __hdd_hard_start_xmit() - Transmit a frame
* @skb: pointer to OS packet (sk_buff)
* @dev: pointer to network device
@@ -526,8 +781,11 @@ static int __hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
bool granted;
uint8_t STAId;
+#ifdef QCA_PKT_PROTO_TRACE
hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
+#endif
hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
+ uint8_t pkt_type = 0;
bool pkt_proto_logged = false;
#ifdef QCA_PKT_PROTO_TRACE
uint8_t proto_type = 0;
@@ -550,13 +808,17 @@ static int __hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
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))) {
+ (pAdapter->track_arp_ip == qdf_nbuf_get_arp_tgt_ip(skb))) {
++pAdapter->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__);
}
}
+ /* track connectivity stats */
+ if (pAdapter->pkt_type_bitmap)
+ hdd_tx_rx_collect_connectivity_stats_info(skb, pAdapter,
+ PKT_TYPE_REQ, &pkt_type);
if (cds_is_driver_recovering() || cds_is_driver_in_bad_state()) {
QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_INFO_HIGH,
@@ -775,6 +1037,11 @@ drop_pkt_accounting:
"%s : ARP packet dropped", __func__);
}
+ /* track connectivity stats */
+ if (pAdapter->pkt_type_bitmap)
+ hdd_tx_rx_collect_connectivity_stats_info(skb, pAdapter,
+ PKT_TYPE_TX_DROPPED, &pkt_type);
+
return NETDEV_TX_OK;
}
@@ -1539,6 +1806,7 @@ QDF_STATUS hdd_rx_packet_cbk(void *context, qdf_nbuf_t rxBuf)
bool wake_lock = false;
bool is_arp = false;
bool track_arp = false;
+ uint8_t pkt_type = 0;
bool proto_pkt_logged = false;
/* Sanity check on inputs */
@@ -1570,7 +1838,7 @@ QDF_STATUS hdd_rx_packet_cbk(void *context, qdf_nbuf_t rxBuf)
if (QDF_NBUF_CB_PACKET_TYPE_ARP == QDF_NBUF_CB_GET_PACKET_TYPE(skb)) {
is_arp = true;
if (qdf_nbuf_data_is_arp_rsp(skb) &&
- (pHddCtx->track_arp_ip == qdf_nbuf_get_arp_src_ip(skb))) {
+ (pAdapter->track_arp_ip == qdf_nbuf_get_arp_src_ip(skb))) {
++pAdapter->hdd_stats.hdd_arp_stats.rx_arp_rsp_count;
QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_DEBUG,
"%s: ARP packet received", __func__);
@@ -1578,6 +1846,11 @@ QDF_STATUS hdd_rx_packet_cbk(void *context, qdf_nbuf_t rxBuf)
}
}
+ /* track connectivity stats */
+ if (pAdapter->pkt_type_bitmap)
+ hdd_tx_rx_collect_connectivity_stats_info(skb, pAdapter,
+ PKT_TYPE_RSP, &pkt_type);
+
pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
if ((pHddStaCtx->conn_info.proxyARPService) &&
cfg80211_is_gratuitous_arp_unsolicited_na(skb)) {
@@ -1676,12 +1949,21 @@ QDF_STATUS hdd_rx_packet_cbk(void *context, qdf_nbuf_t rxBuf)
if (track_arp)
++pAdapter->hdd_stats.hdd_arp_stats.
rx_delivered;
+ /* track connectivity stats */
+ if (pAdapter->pkt_type_bitmap)
+ hdd_tx_rx_collect_connectivity_stats_info(skb, pAdapter,
+ PKT_TYPE_RX_DELIVERED, &pkt_type);
} else {
++pAdapter->hdd_stats.hddTxRxStats.
rxRefused[cpu_index];
if (track_arp)
++pAdapter->hdd_stats.hdd_arp_stats.
rx_refused;
+ /* track connectivity stats */
+ if (pAdapter->pkt_type_bitmap)
+ hdd_tx_rx_collect_connectivity_stats_info(
+ skb, pAdapter,
+ PKT_TYPE_RX_REFUSED, &pkt_type);
}
return QDF_STATUS_SUCCESS;
diff --git a/uapi/linux/qca_vendor.h b/uapi/linux/qca_vendor.h
index 5bef49f6862a..ec460be881c3 100644
--- a/uapi/linux/qca_vendor.h
+++ b/uapi/linux/qca_vendor.h
@@ -2539,7 +2539,14 @@ enum qca_attr_nud_stats_set {
QCA_ATTR_NUD_STATS_SET_START = 1,
/* IPv4 address of the default gateway (in network byte order) */
QCA_ATTR_NUD_STATS_GW_IPV4 = 2,
-
+ /*
+ * Represents the data packet type to be monitored.
+ * Host driver tracks the stats corresponding to each data frame
+ * represented by these flags.
+ * These data packets are represented by
+ * enum qca_wlan_vendor_nud_stats_set_data_pkt_info.
+ */
+ QCA_ATTR_NUD_STATS_SET_DATA_PKT_INFO = 3,
/* keep last */
QCA_ATTR_NUD_STATS_SET_LAST,
QCA_ATTR_NUD_STATS_SET_MAX =
@@ -2547,6 +2554,105 @@ enum qca_attr_nud_stats_set {
};
/**
+ * enum qca_attr_connectivity_check_stats_set - attribute to vendor subcmd
+ * QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_SET. This carry the requisite
+ * information to start / stop the NUD stats collection.
+ * @QCA_ATTR_CONNECTIVITY_CHECK_STATS_STATS_PKT_INFO_TYPE: set pkt info stats
+ * Bitmap to Flag to Start / Stop the NUD stats collection
+ * Start - If included , Stop - If not included
+ * @QCA_ATTR_CONNECTIVITY_CHECK_STATS_DNS_DOMAIN_NAME: set gatway ipv4 address
+ * IPv4 address of Default Gateway (in network byte order)
+ * QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_SET. This carry the requisite
+ * information to start / stop the NUD stats collection.
+ * @QCA_ATTR_CONNECTIVITY_CHECK_STATS_SRC_PORT: set nud debug stats
+ * Flag to Start / Stop the NUD stats collection
+ * Start - If included , Stop - If not included
+ * @QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_PORT: set gatway ipv4 address
+ * IPv4 address of Default Gateway (in network byte order)
+ * QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_SET. This carry the requisite
+ * information to start / stop the NUD stats collection.
+ * @QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_IPV4: set nud debug stats
+ * Flag to Start / Stop the NUD stats collection
+ * Start - If included , Stop - If not included
+ * @QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_IPV6: set gatway ipv4 address
+ * IPv4 address of Default Gateway (in network byte order)
+ */
+enum qca_attr_connectivity_check_stats_set {
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_SET_INVALID = 0,
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_STATS_PKT_INFO_TYPE = 1,
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_DNS_DOMAIN_NAME = 2,
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_SRC_PORT = 3,
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_PORT = 4,
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_IPV4 = 5,
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_IPV6 = 6,
+ /* keep last */
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_SET_LAST,
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_SET_MAX =
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_SET_LAST - 1,
+};
+
+/**
+ * qca_wlan_vendor_nud_stats_data_pkt_flags: Flag representing the various
+ * data types for which the stats have to get collected.
+ */
+enum qca_wlan_vendor_connectivity_check_pkt_flags {
+ QCA_WLAN_VENDOR_CONNECTIVITY_CHECK_SET_ARP = 1 << 0,
+ QCA_WLAN_VENDOR_CONNECTIVITY_CHECK_SET_DNS = 1 << 1,
+ QCA_WLAN_VENDOR_CONNECTIVITY_CHECK_SET_TCP_HANDSHAKE = 1 << 2,
+ QCA_WLAN_VENDOR_CONNECTIVITY_CHECK_SET_ICMPV4 = 1 << 3,
+ QCA_WLAN_VENDOR_CONNECTIVITY_CHECK_SET_ICMPV6 = 1 << 4,
+ /* Used by QCA_ATTR_NUD_STATS_PKT_TYPE only in nud stats get
+ * to represent the stats of respective data type.
+ */
+ QCA_WLAN_VENDOR_CONNECTIVITY_CHECK_SET_TCP_SYN = 1 << 5,
+ QCA_WLAN_VENDOR_CONNECTIVITY_CHECK_SET_TCP_SYN_ACK = 1 << 6,
+ QCA_WLAN_VENDOR_CONNECTIVITY_CHECK_SET_TCP_ACK = 1 << 7,
+};
+
+enum qca_attr_connectivity_check_stats {
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_INVALID = 0,
+ /* Data packet type for which the stats are collected.
+ * Represented by enum qca_wlan_vendor_nud_stats_data_pkt_flags
+ */
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_TYPE = 1,
+ /* ID corresponding to the DNS frame for which the respective DNS stats
+ * are monitored (u32).
+ */
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DNS_DOMAIN_NAME = 2,
+ /* source / destination port on which the respective proto stats are
+ * collected (u32).
+ */
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_SRC_PORT = 3,
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_PORT = 4,
+ /* IPv4/IPv6 address for which the destined data packets are
+ * monitored. (in network byte order)
+ */
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_IPV4 = 5,
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_IPV6 = 6,
+ /* Data packet Request count received from netdev */
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV = 7,
+ /* Data packet Request count sent to lower MAC from upper MAC */
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC = 8,
+ /* Data packet Request count received by lower MAC from upper MAC */
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC = 9,
+ /* Data packet Request count successfully transmitted by the device */
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS = 10,
+ /* Data packet Response count received by lower MAC */
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC = 11,
+ /* Data packet Response count received by upper MAC */
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC = 12,
+ /* Data packet Response count delivered to netdev */
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV = 13,
+ /* Data Packet Response count that are dropped out of order */
+ QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP = 14,
+
+ /* keep last */
+ QCA_ATTR_CONNECTIVITY_CHECK_DATA_STATS_LAST,
+ QCA_ATTR_CONNECTIVITY_CHECK_DATA_STATS_MAX =
+ QCA_ATTR_CONNECTIVITY_CHECK_DATA_STATS_LAST - 1,
+};
+
+/**
* qca_attr_nud_stats_get: Attributes to vendor subcmd
* QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET. This carries the requisite
* NUD statistics collected when queried.
@@ -2579,6 +2685,12 @@ enum qca_attr_nud_stats_get {
* Yes - If detected, No - If not detected.
*/
QCA_ATTR_NUD_STATS_IS_DAD = 10,
+ /*
+ * List of Data types for which the stats are requested.
+ * This list does not carry ARP stats as they are done by the
+ * above attributes. Represented by enum qca_attr_nud_data_stats.
+ */
+ QCA_ATTR_NUD_STATS_DATA_PKT_STATS = 11,
/* keep last */
QCA_ATTR_NUD_STATS_GET_LAST,