diff options
| author | Poddar, Siddarth <siddpodd@codeaurora.org> | 2018-01-08 20:38:43 +0530 |
|---|---|---|
| committer | Poddar, Siddarth <siddpodd@codeaurora.org> | 2018-01-13 12:01:02 +0530 |
| commit | 6259925fd8bf35e802a844752fbf53b057d0a679 (patch) | |
| tree | 448b256076dea03cabff25754a379823a2cb443f | |
| parent | febc5230fecf53d81b2d3ba65e3f650bc32af94b (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.h | 10 | ||||
| -rw-r--r-- | core/cds/src/cds_api.c | 18 | ||||
| -rw-r--r-- | core/dp/txrx/ol_tx_send.c | 16 | ||||
| -rw-r--r-- | core/hdd/inc/wlan_hdd_main.h | 109 | ||||
| -rw-r--r-- | core/hdd/inc/wlan_hdd_tx_rx.h | 15 | ||||
| -rw-r--r-- | core/hdd/src/wlan_hdd_assoc.c | 2 | ||||
| -rw-r--r-- | core/hdd/src/wlan_hdd_cfg80211.c | 620 | ||||
| -rw-r--r-- | core/hdd/src/wlan_hdd_cfg80211.h | 21 | ||||
| -rw-r--r-- | core/hdd/src/wlan_hdd_main.c | 9 | ||||
| -rw-r--r-- | core/hdd/src/wlan_hdd_ocb.c | 3 | ||||
| -rw-r--r-- | core/hdd/src/wlan_hdd_tx_rx.c | 288 | ||||
| -rw-r--r-- | uapi/linux/qca_vendor.h | 114 |
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, |
