diff options
| author | Himanshu Agarwal <himanaga@qti.qualcomm.com> | 2016-05-23 16:09:52 +0530 |
|---|---|---|
| committer | Anjaneedevi Kapparapu <akappa@codeaurora.org> | 2016-05-26 15:34:38 +0530 |
| commit | e5790efd919c15cab528ee441bc262a60872c2d4 (patch) | |
| tree | 2395a60e3ad2a84b90b6771234b459d3c3a2fa73 | |
| parent | 4235b981b6548deef493e728f323d22c0402085e (diff) | |
qcacld-2.0: Dump header info for first data packet after WOW wakeup
Dump the information such as source MAC address, destination
MAC address, sequence number, packet type, subtype and other
important information for the first data packet after WOW wakeup.
Change-Id: I3c83991f56be34412f3f10adf58bd991ecb536ca
CRs-Fixed: 1019037
| -rw-r--r-- | CORE/SERVICES/WMA/wma.c | 307 | ||||
| -rw-r--r-- | CORE/SERVICES/WMA/wma.h | 15 |
2 files changed, 316 insertions, 6 deletions
diff --git a/CORE/SERVICES/WMA/wma.c b/CORE/SERVICES/WMA/wma.c index 6d6aaae36d15..f2540f77c160 100644 --- a/CORE/SERVICES/WMA/wma.c +++ b/CORE/SERVICES/WMA/wma.c @@ -20940,6 +20940,288 @@ exit_handler: wma_beacon_miss_handler(wma, wake_info->vdev_id, 0); } +/** + * wma_pkt_proto_subtype_to_string() - to convert proto subtype + * of data packet to string. + * @proto_subtype: proto subtype for data packet + * + * This function returns the string for the proto subtype of + * data packet. + * + * Return: string for proto subtype for data packet + */ +const char * +wma_pkt_proto_subtype_to_string(enum adf_proto_subtype proto_subtype) +{ + switch (proto_subtype) { + case ADF_PROTO_EAPOL_M1: + return "EAPOL M1"; + case ADF_PROTO_EAPOL_M2: + return "EAPOL M2"; + case ADF_PROTO_EAPOL_M3: + return "EAPOL M3"; + case ADF_PROTO_EAPOL_M4: + return "EAPOL M4"; + case ADF_PROTO_DHCP_DISCOVER: + return "DHCP DISCOVER"; + case ADF_PROTO_DHCP_REQUEST: + return "DHCP REQUEST"; + case ADF_PROTO_DHCP_OFFER: + return "DHCP OFFER"; + case ADF_PROTO_DHCP_ACK: + return "DHCP ACK"; + case ADF_PROTO_DHCP_NACK: + return "DHCP NACK"; + case ADF_PROTO_DHCP_RELEASE: + return "DHCP RELEASE"; + case ADF_PROTO_DHCP_INFORM: + return "DHCP INFORM"; + case ADF_PROTO_DHCP_DECLINE: + return "DHCP DECLINE"; + case ADF_PROTO_ARP_REQ: + return "ARP REQUEST"; + case ADF_PROTO_ARP_RES: + return "ARP RESPONSE"; + case ADF_PROTO_ICMP_REQ: + return "ICMP REQUEST"; + case ADF_PROTO_ICMP_RES: + return "ICMP RESPONSE"; + case ADF_PROTO_ICMPV6_REQ: + return "ICMPV6 REQUEST"; + case ADF_PROTO_ICMPV6_RES: + return "ICMPV6 RESPONSE"; + case ADF_PROTO_IPV4_UDP: + return "IPV4 UDP Packet"; + case ADF_PROTO_IPV4_TCP: + return "IPV4 TCP Packet"; + case ADF_PROTO_IPV6_UDP: + return "IPV6 UDP Packet"; + case ADF_PROTO_IPV6_TCP: + return "IPV6 TCP Packet"; + default: + return "Invalid Packet"; + } +} + +/** + * wma_wow_get_pkt_proto_subtype() - get the proto subtype + * of the packet. + * @data: Pointer to data buffer + * @len: length of the data buffer + * + * This function gives the proto subtype of the packet. + * + * Return: proto subtype of the packet. + */ +static enum adf_proto_subtype +wma_wow_get_pkt_proto_subtype(uint8_t *data, + uint32_t len) +{ + if (len >= WMA_IS_DHCP_GET_MIN_LEN) { + if (adf_nbuf_data_is_dhcp_pkt(data) == A_STATUS_OK) { + if (len >= WMA_DHCP_SUBTYPE_GET_MIN_LEN) + return adf_nbuf_data_get_dhcp_subtype(data); + VOS_TRACE(VOS_MODULE_ID_WDA, + VOS_TRACE_LEVEL_ERROR, "DHCP Packet"); + return ADF_PROTO_INVALID; + } + } + if (len >= WMA_IS_EAPOL_GET_MIN_LEN) { + if (adf_nbuf_data_is_eapol_pkt(data) == A_STATUS_OK) { + if (len >= WMA_EAPOL_SUBTYPE_GET_MIN_LEN) + return adf_nbuf_data_get_eapol_subtype(data); + VOS_TRACE(VOS_MODULE_ID_WDA, + VOS_TRACE_LEVEL_ERROR, "EAPOL Packet"); + return ADF_PROTO_INVALID; + } + } + if (len >= WMA_IS_ARP_GET_MIN_LEN) { + if (adf_nbuf_data_is_ipv4_arp_pkt(data)) { + if (len >= WMA_ARP_SUBTYPE_GET_MIN_LEN) + return adf_nbuf_data_get_arp_subtype(data); + VOS_TRACE(VOS_MODULE_ID_WDA, + VOS_TRACE_LEVEL_ERROR, "ARP Packet"); + return ADF_PROTO_INVALID; + } + } + if (len >= WMA_IPV4_PROTO_GET_MIN_LEN) { + if (adf_nbuf_data_is_icmp_pkt(data)) { + if (len >= WMA_ICMP_SUBTYPE_GET_MIN_LEN) + return adf_nbuf_data_get_icmp_subtype(data); + VOS_TRACE(VOS_MODULE_ID_WDA, + VOS_TRACE_LEVEL_ERROR, "ICMP Packet"); + return ADF_PROTO_INVALID; + } else if (adf_nbuf_data_is_ipv4_udp_pkt(data)) { + return ADF_PROTO_IPV4_UDP; + } else if (adf_nbuf_data_is_ipv4_tcp_pkt(data)) { + return ADF_PROTO_IPV4_TCP; + } + } + if (len >= WMA_IPV6_PROTO_GET_MIN_LEN) { + if (adf_nbuf_data_is_icmpv6_pkt(data)) { + if (len >= WMA_ICMPV6_SUBTYPE_GET_MIN_LEN) + return adf_nbuf_data_get_icmpv6_subtype(data); + VOS_TRACE(VOS_MODULE_ID_WDA, + VOS_TRACE_LEVEL_ERROR, "ICMPV6 Packet"); + return ADF_PROTO_INVALID; + } else if (adf_nbuf_data_is_ipv6_udp_pkt(data)) { + return ADF_PROTO_IPV6_UDP; + } else if (adf_nbuf_data_is_ipv6_tcp_pkt(data)) { + return ADF_PROTO_IPV6_TCP; + } + } + + return ADF_PROTO_INVALID; +} + +/** + * wma_wow_parse_data_pkt_buffer() - API to parse data buffer for data + * packet that resulted in WOW wakeup. + * @data: Pointer to data buffer + * @buf_len: data buffer length + * + * This function parses the data buffer received (first few bytes of + * skb->data) to get informaton like src mac addr, dst mac addr, packet + * len, seq_num, etc. + * + * Return: void + */ +static void wma_wow_parse_data_pkt_buffer(uint8_t *data, + uint32_t buf_len) +{ + enum adf_proto_subtype proto_subtype; + uint16_t pkt_len, key_len, seq_num; + uint32_t transaction_id, tcp_seq_num; + + WMA_LOGD("wow_buf_pkt_len: %d", buf_len); + if (buf_len >= ADF_NBUF_TRAC_ETH_TYPE_OFFSET) + WMA_LOGE("Src_mac: " MAC_ADDRESS_STR " Dst_mac: " MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(data), + MAC_ADDR_ARRAY(data + ADF_NBUF_SRC_MAC_OFFSET)); + else + goto end; + + proto_subtype = wma_wow_get_pkt_proto_subtype(data, buf_len); + switch (proto_subtype) { + case ADF_PROTO_EAPOL_M1: + case ADF_PROTO_EAPOL_M2: + case ADF_PROTO_EAPOL_M3: + case ADF_PROTO_EAPOL_M4: + WMA_LOGE("WOW Wakeup: %s rcvd", + wma_pkt_proto_subtype_to_string(proto_subtype)); + if (buf_len >= WMA_EAPOL_INFO_GET_MIN_LEN) { + pkt_len = (uint16_t)(*(uint16_t *)(data + + EAPOL_PKT_LEN_OFFSET)); + key_len = (uint16_t)(*(uint16_t *)(data + + EAPOL_KEY_LEN_OFFSET)); + WMA_LOGE("Pkt_len: %d, Key_len: %d", + adf_os_cpu_to_be16(pkt_len), + adf_os_cpu_to_be16(key_len)); + } + break; + + case ADF_PROTO_DHCP_DISCOVER: + case ADF_PROTO_DHCP_REQUEST: + case ADF_PROTO_DHCP_OFFER: + case ADF_PROTO_DHCP_ACK: + case ADF_PROTO_DHCP_NACK: + case ADF_PROTO_DHCP_RELEASE: + case ADF_PROTO_DHCP_INFORM: + case ADF_PROTO_DHCP_DECLINE: + WMA_LOGE("WOW Wakeup: %s rcvd", + wma_pkt_proto_subtype_to_string(proto_subtype)); + if (buf_len >= WMA_DHCP_INFO_GET_MIN_LEN) { + pkt_len = (uint16_t)(*(uint16_t *)(data + + DHCP_PKT_LEN_OFFSET)); + transaction_id = (uint32_t)(*(uint32_t *)(data + + DHCP_TRANSACTION_ID_OFFSET)); + WMA_LOGE("Pkt_len: %d, Transaction_id: %d", + adf_os_cpu_to_be16(pkt_len), + adf_os_cpu_to_be32(transaction_id)); + } + break; + + case ADF_PROTO_ARP_REQ: + case ADF_PROTO_ARP_RES: + WMA_LOGE("WOW Wakeup: %s rcvd", + wma_pkt_proto_subtype_to_string(proto_subtype)); + break; + + case ADF_PROTO_ICMP_REQ: + case ADF_PROTO_ICMP_RES: + WMA_LOGE("WOW Wakeup: %s rcvd", + wma_pkt_proto_subtype_to_string(proto_subtype)); + if (buf_len >= WMA_IPV4_PKT_INFO_GET_MIN_LEN) { + pkt_len = (uint16_t)(*(uint16_t *)(data + + IPV4_PKT_LEN_OFFSET)); + seq_num = (uint16_t)(*(uint16_t *)(data + + ICMP_SEQ_NUM_OFFSET)); + WMA_LOGE("Pkt_len: %d, Seq_num: %d", + adf_os_cpu_to_be16(pkt_len), + adf_os_cpu_to_be16(seq_num)); + } + break; + + case ADF_PROTO_ICMPV6_REQ: + case ADF_PROTO_ICMPV6_RES: + WMA_LOGE("WOW Wakeup: %s rcvd", + wma_pkt_proto_subtype_to_string(proto_subtype)); + if (buf_len >= WMA_IPV6_PKT_INFO_GET_MIN_LEN) { + pkt_len = (uint16_t)(*(uint16_t *)(data + + IPV6_PKT_LEN_OFFSET)); + seq_num = (uint16_t)(*(uint16_t *)(data + + ICMPV6_SEQ_NUM_OFFSET)); + WMA_LOGE("Pkt_len: %d, Seq_num: %d", + adf_os_cpu_to_be16(pkt_len), + adf_os_cpu_to_be16(seq_num)); + } + break; + + case ADF_PROTO_IPV4_UDP: + case ADF_PROTO_IPV4_TCP: + WMA_LOGE("WOW Wakeup: %s rcvd", + wma_pkt_proto_subtype_to_string(proto_subtype)); + if (buf_len >= WMA_IPV4_PKT_INFO_GET_MIN_LEN) { + pkt_len = (uint16_t)(*(uint16_t *)(data + + IPV4_PKT_LEN_OFFSET)); + WMA_LOGE("Pkt_len: %d", + adf_os_cpu_to_be16(pkt_len)); + if (proto_subtype == ADF_PROTO_IPV4_TCP) { + tcp_seq_num = (uint32_t)(*(uint32_t *)(data + + IPV4_TCP_SEQ_NUM_OFFSET)); + WMA_LOGE("TCP_seq_num: %d", + adf_os_cpu_to_be32(tcp_seq_num)); + } + } + break; + + case ADF_PROTO_IPV6_UDP: + case ADF_PROTO_IPV6_TCP: + WMA_LOGE("WOW Wakeup: %s rcvd", + wma_pkt_proto_subtype_to_string(proto_subtype)); + if (buf_len >= WMA_IPV6_PKT_INFO_GET_MIN_LEN) { + pkt_len = (uint16_t)(*(uint16_t *)(data + + IPV6_PKT_LEN_OFFSET)); + WMA_LOGE("Pkt_len: %d", + adf_os_cpu_to_be16(pkt_len)); + if (proto_subtype == ADF_PROTO_IPV6_TCP) { + tcp_seq_num = (uint32_t)(*(uint32_t *)(data + + IPV6_TCP_SEQ_NUM_OFFSET)); + WMA_LOGE("TCP_seq_num: %d", + adf_os_cpu_to_be32(tcp_seq_num)); + } + } + break; + + default: +end: + WMA_LOGE("wow_buf_pkt_len: %d", buf_len); + WMA_LOGE("Invalid Packet Type or Smaller WOW packet buffer than expected"); + break; + } +} + + /* * Handler to catch wow wakeup host event. This event will have * reason why the firmware has woken the host. @@ -21073,12 +21355,25 @@ static int wma_wow_wakeup_host_event(void *handle, u_int8_t *event, /* First 4-bytes of wow_packet_buffer is the length */ vos_mem_copy((u_int8_t *) &wow_buf_pkt_len, param_buf->wow_packet_buffer, 4); - wma_wow_wake_up_stats(wma, - param_buf->wow_packet_buffer + 4, wow_buf_pkt_len, - WOW_REASON_PATTERN_MATCH_FOUND); - vos_trace_hex_dump(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_DEBUG, - param_buf->wow_packet_buffer + 4, - wow_buf_pkt_len); + if (wow_buf_pkt_len) { + uint8_t *data; + + wma_wow_wake_up_stats(wma, + param_buf->wow_packet_buffer + 4, + wow_buf_pkt_len, + WOW_REASON_PATTERN_MATCH_FOUND); + vos_trace_hex_dump(VOS_MODULE_ID_WDA, + VOS_TRACE_LEVEL_DEBUG, + param_buf->wow_packet_buffer + 4, + wow_buf_pkt_len); + + data = (uint8_t *) + (param_buf->wow_packet_buffer + 4); + wma_wow_parse_data_pkt_buffer(data, + wow_buf_pkt_len); + } else { + WMA_LOGE("wow packet buffer is empty"); + } } else { WMA_LOGE("No wow packet buffer present"); } diff --git a/CORE/SERVICES/WMA/wma.h b/CORE/SERVICES/WMA/wma.h index 7d3e0bcfd624..34e4c99f9368 100644 --- a/CORE/SERVICES/WMA/wma.h +++ b/CORE/SERVICES/WMA/wma.h @@ -182,6 +182,21 @@ #define WMA_MCAST_IPV6_MAC_ADDR (0x33) #define WMA_ICMP_PROTOCOL (0x01) +#define WMA_IS_EAPOL_GET_MIN_LEN 14 +#define WMA_EAPOL_SUBTYPE_GET_MIN_LEN 21 +#define WMA_EAPOL_INFO_GET_MIN_LEN 23 +#define WMA_IS_DHCP_GET_MIN_LEN 38 +#define WMA_DHCP_SUBTYPE_GET_MIN_LEN 0x11D +#define WMA_DHCP_INFO_GET_MIN_LEN 50 +#define WMA_IS_ARP_GET_MIN_LEN 14 +#define WMA_ARP_SUBTYPE_GET_MIN_LEN 22 +#define WMA_IPV4_PROTO_GET_MIN_LEN 24 +#define WMA_IPV4_PKT_INFO_GET_MIN_LEN 42 +#define WMA_ICMP_SUBTYPE_GET_MIN_LEN 35 +#define WMA_IPV6_PROTO_GET_MIN_LEN 21 +#define WMA_IPV6_PKT_INFO_GET_MIN_LEN 62 +#define WMA_ICMPV6_SUBTYPE_GET_MIN_LEN 55 + typedef struct probeTime_dwellTime { u_int8_t dwell_time; u_int8_t probe_time; |
