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
This commit is contained in:
Poddar, Siddarth 2018-01-22 17:24:15 +05:30 committed by nshrivas
parent 465330e047
commit 31797fa6a8
11 changed files with 1091 additions and 59 deletions

View File

@ -590,7 +590,13 @@ bool cds_is_group_addr(uint8_t *mac_addr)
return false;
}
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);

View File

@ -2776,22 +2776,18 @@ cds_print_htc_credit_history(uint32_t count, qdf_abstract_print *print,
}
#endif
/**
* cds_get_arp_stats_gw_ip() - get arp stats track IP
*
* Return: ARP stats IP to track
*/
uint32_t cds_get_arp_stats_gw_ip(void)
uint32_t cds_get_arp_stats_gw_ip(void *context)
{
struct hdd_context *hdd_ctx;
struct hdd_adapter *adapter = (struct hdd_adapter *)context;
hdd_ctx = (struct hdd_context *) (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;
}
/**

View File

@ -631,15 +631,21 @@ static inline void ol_tx_timestamp(ol_txrx_pdev_handle pdev,
/**
* 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)
@ -703,7 +709,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) {

View File

@ -307,6 +307,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 */
@ -464,6 +467,19 @@ struct hdd_pmf_stats {
};
#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;
@ -478,14 +494,87 @@ struct hdd_arp_stats_s {
};
/**
* struct hdd_stats - per-adapter statistics
* @summary_stat: Summary stats reported by firmware
* @class_a_stat: "Class A" stats reported by firmware
* @class_d_stat: "Class D" stats reported by firmware
* @per_chain_rssi_stats: Per-chain RSSI stats
* @tx_rx_stats: Tx & Rx stats
* @hdd_pmf_stats: Protected Management Frame stats
* 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;
};
struct hdd_stats {
tCsrSummaryStatsInfo summary_stat;
tCsrGlobalClassAStatsInfo class_a_stat;
@ -493,6 +582,9 @@ struct hdd_stats {
struct csr_per_chain_rssi_stats_info per_chain_rssi_stats;
struct hdd_tx_rx_stats tx_rx_stats;
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
struct hdd_pmf_stats hdd_pmf_stats;
#endif
@ -1211,6 +1303,13 @@ struct hdd_adapter {
bool con_status;
bool dad;
uint8_t active_ac;
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;
uint32_t mon_chan;
uint32_t mon_bandwidth;

View File

@ -65,6 +65,18 @@ QDF_STATUS hdd_rx_packet_cbk(void *context, qdf_nbuf_t rxBuf);
QDF_STATUS hdd_get_peer_sta_id(struct hdd_station_ctx *sta_ctx,
struct qdf_mac_addr *peer_mac_addr,
uint8_t *sta_id);
/**
* 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_tx_queue_cb() - Disable/Enable the Transmit Queues

View File

@ -1985,6 +1985,7 @@ QDF_STATUS hdd_roam_register_sta(struct hdd_adapter *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;
adapter->txrx_vdev = (void *)cdp_get_vdev_from_vdev_id(soc,
(struct cdp_pdev *)pdev,
@ -3826,6 +3827,7 @@ QDF_STATUS hdd_roam_register_tdlssta(struct hdd_adapter *adapter,
(struct cdp_pdev *)pdev, adapter->session_id),
adapter, &txrx_ops);
adapter->tx_fn = txrx_ops.tx.tx;
txrx_ops.rx.stats_rx = hdd_tx_rx_collect_connectivity_stats_info;
/* Register the Station with TL... */
qdf_status = cdp_peer_register(soc,

View File

@ -12409,9 +12409,266 @@ static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
return ret;
}
/*
* define short names for the global vendor params
* used by wlan_hdd_cfg80211_setarp_stats_cmd()
*/
#define STATS_SET_INVALID \
QCA_ATTR_NUD_STATS_SET_INVALID
#define STATS_SET_START \
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
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(
struct hdd_adapter *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 (wlan_cfg80211_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;
}
void hdd_update_cca_info_cb(void *context, uint32_t congestion,
uint32_t vdev_id)
uint32_t vdev_id)
{
struct hdd_context *hdd_ctx = (struct hdd_context *)context;
int status;
@ -12556,25 +12813,6 @@ static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
return ret;
}
/*
* define short names for the global vendor params
* used by wlan_hdd_cfg80211_setarp_stats_cmd()
*/
#define STATS_SET_INVALID \
QCA_ATTR_NUD_STATS_SET_INVALID
#define STATS_SET_START \
QCA_ATTR_NUD_STATS_SET_START
#define STATS_GW_IPV4 \
QCA_ATTR_NUD_STATS_GW_IPV4
#define STATS_SET_MAX \
QCA_ATTR_NUD_STATS_SET_MAX
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 },
};
/**
* __wlan_hdd_cfg80211_set_nud_stats() - set arp stats command to firmware
* @wiphy: pointer to wireless wiphy structure.
@ -12595,7 +12833,7 @@ static int __wlan_hdd_cfg80211_set_nud_stats(struct wiphy *wiphy,
struct net_device *dev = wdev->netdev;
struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
struct hdd_context *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;
hdd_enter();
@ -12623,25 +12861,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)
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->session_id;
if (QDF_STATUS_SUCCESS !=
@ -12712,9 +12990,45 @@ static int wlan_hdd_cfg80211_set_nud_stats(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 },
@ -12727,8 +13041,278 @@ 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(struct hdd_adapter *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(struct hdd_adapter *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(struct hdd_adapter *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(
struct hdd_adapter *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.
@ -12753,6 +13337,7 @@ static int __wlan_hdd_cfg80211_get_nud_stats(struct wiphy *wiphy,
struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
struct get_arp_stats_params arp_stats_params;
void *soc = cds_get_context(QDF_MODULE_ID_SOC);
uint32_t pkt_type_bitmap;
struct sk_buff *skb;
hdd_enter();
@ -12834,7 +13419,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;
}

View File

@ -37,6 +37,7 @@
#include <wlan_cfg80211_scan.h>
#include <wlan_cfg80211.h>
#include <wlan_cfg80211_tdls.h>
#include <qca_vendor.h>
struct hdd_context;
@ -227,6 +228,24 @@ struct cfg80211_bss *
wlan_hdd_cfg80211_update_bss_db(struct hdd_adapter *adapter,
struct csr_roam_info *roam_info);
#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
int wlan_hdd_cfg80211_pmksa_candidate_notify(struct hdd_adapter *adapter,
struct csr_roam_info *roam_info,
int index, bool preauth);

View File

@ -10763,6 +10763,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_info("rsp->tcp_ack_recvd :%x", rsp->tcp_ack_recvd);
hdd_info("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);

View File

@ -266,6 +266,7 @@ static int hdd_ocb_register_sta(struct hdd_adapter *adapter)
(struct cdp_vdev *)cdp_get_vdev_from_vdev_id(soc,
(struct cdp_pdev *)pdev, adapter->session_id),
adapter, &txrx_ops);
txrx_ops.rx.stats_rx = hdd_tx_rx_collect_connectivity_stats_info;
adapter->tx_fn = txrx_ops.tx.tx;
qdf_status = cdp_peer_register(soc,

View File

@ -63,6 +63,7 @@
#include <cdp_txrx_misc.h>
#include "wlan_hdd_rx_monitor.h"
#include "wlan_hdd_power.h"
#include "wlan_hdd_cfg80211.h"
#include <wlan_hdd_tsf.h>
#ifdef QCA_LL_TX_FLOW_CONTROL_V2
@ -548,6 +549,263 @@ static inline bool hdd_is_tx_allowed(struct sk_buff *skb, uint8_t peer_id)
FL("Invalid peer state for Tx: %d"), peer_state);
return false;
}
/**
* 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,
struct hdd_adapter *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;
struct hdd_adapter *adapter = NULL;
adapter = (struct hdd_adapter *)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
@ -573,6 +831,7 @@ static int __hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
struct hdd_station_ctx *sta_ctx = &adapter->session.station;
struct qdf_mac_addr *mac_addr;
bool pkt_proto_logged = false;
uint8_t pkt_type = 0;
#ifdef QCA_PKT_PROTO_TRACE
uint8_t proto_type = 0;
#endif
@ -607,6 +866,10 @@ static int __hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
"%s : ARP packet", __func__);
}
}
/* track connectivity stats */
if (adapter->pkt_type_bitmap)
hdd_tx_rx_collect_connectivity_stats_info(skb, adapter,
PKT_TYPE_REQ, &pkt_type);
if (cds_is_driver_recovering()) {
QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_WARN,
@ -828,6 +1091,11 @@ drop_pkt_accounting:
"%s : ARP packet dropped", __func__);
}
/* track connectivity stats */
if (adapter->pkt_type_bitmap)
hdd_tx_rx_collect_connectivity_stats_info(skb, adapter,
PKT_TYPE_TX_DROPPED, &pkt_type);
return NETDEV_TX_OK;
}
@ -1240,6 +1508,7 @@ QDF_STATUS hdd_rx_packet_cbk(void *context, qdf_nbuf_t rxBuf)
unsigned int cpu_index;
struct qdf_mac_addr *mac_addr;
bool wake_lock = false;
uint8_t pkt_type = 0;
bool proto_pkt_logged = false;
bool track_arp = false;
@ -1292,6 +1561,10 @@ QDF_STATUS hdd_rx_packet_cbk(void *context, qdf_nbuf_t rxBuf)
track_arp = true;
}
}
/* track connectivity stats */
if (adapter->pkt_type_bitmap)
hdd_tx_rx_collect_connectivity_stats_info(skb, adapter,
PKT_TYPE_RSP, &pkt_type);
sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
if ((sta_ctx->conn_info.proxyARPService) &&
@ -1396,19 +1669,35 @@ QDF_STATUS hdd_rx_packet_cbk(void *context, qdf_nbuf_t rxBuf)
if (track_arp)
++adapter->hdd_stats.hdd_arp_stats.
rx_delivered;
/* track connectivity stats */
if (adapter->pkt_type_bitmap)
hdd_tx_rx_collect_connectivity_stats_info(
skb, adapter,
PKT_TYPE_RX_DELIVERED,
&pkt_type);
} else {
++adapter->hdd_stats.tx_rx_stats.
rx_refused[cpu_index];
if (track_arp)
++adapter->hdd_stats.hdd_arp_stats.
rx_refused;
/* track connectivity stats */
if (adapter->pkt_type_bitmap)
hdd_tx_rx_collect_connectivity_stats_info(
skb, adapter,
PKT_TYPE_RX_REFUSED, &pkt_type);
}
} else {
++adapter->hdd_stats.tx_rx_stats.
rx_delivered[cpu_index];
if (track_arp)
++adapter->hdd_stats.hdd_arp_stats.
rx_delivered;
rx_delivered;
/* track connectivity stats */
if (adapter->pkt_type_bitmap)
hdd_tx_rx_collect_connectivity_stats_info(
skb, adapter,
PKT_TYPE_RX_DELIVERED, &pkt_type);
}
}