diff options
| author | Himanshu Agarwal <himanaga@codeaurora.org> | 2016-07-20 18:11:03 +0530 |
|---|---|---|
| committer | qcabuildsw <qcabuildsw@localhost> | 2016-08-17 17:06:31 -0700 |
| commit | 82de9040ddc7cfa034f114de9c0ea7e99afe476b (patch) | |
| tree | 4e2d3bde64947dd8f29e2770e0e28f7c10fb03b5 | |
| parent | 5e74bb81d50ddfc819f37927960f89315f6e4f95 (diff) | |
qcacld-3.0: Dump header info for first data packet after WOW wakeup
Propagation from qcacld-2.0 to qcacld-3.0.
Dump some 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/wma/inc/wma.h | 14 | ||||
| -rw-r--r-- | core/wma/src/wma_features.c | 308 |
2 files changed, 314 insertions, 8 deletions
diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h index 3e1d6115d7ed..74f029fa93a7 100644 --- a/core/wma/inc/wma.h +++ b/core/wma/inc/wma.h @@ -166,6 +166,20 @@ #define WMA_MCAST_IPV4_MAC_ADDR (0x01) #define WMA_MCAST_IPV6_MAC_ADDR (0x33) +#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 /* Roaming default values * All time and period values are in milliseconds. diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index 0803b8c4ce03..2b87fd7fee89 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -2617,6 +2617,287 @@ static bool tlv_check_required(int32_t reason) } /** + * 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 qdf_proto_subtype proto_subtype) +{ + switch (proto_subtype) { + case QDF_PROTO_EAPOL_M1: + return "EAPOL M1"; + case QDF_PROTO_EAPOL_M2: + return "EAPOL M2"; + case QDF_PROTO_EAPOL_M3: + return "EAPOL M3"; + case QDF_PROTO_EAPOL_M4: + return "EAPOL M4"; + case QDF_PROTO_DHCP_DISCOVER: + return "DHCP DISCOVER"; + case QDF_PROTO_DHCP_REQUEST: + return "DHCP REQUEST"; + case QDF_PROTO_DHCP_OFFER: + return "DHCP OFFER"; + case QDF_PROTO_DHCP_ACK: + return "DHCP ACK"; + case QDF_PROTO_DHCP_NACK: + return "DHCP NACK"; + case QDF_PROTO_DHCP_RELEASE: + return "DHCP RELEASE"; + case QDF_PROTO_DHCP_INFORM: + return "DHCP INFORM"; + case QDF_PROTO_DHCP_DECLINE: + return "DHCP DECLINE"; + case QDF_PROTO_ARP_REQ: + return "ARP REQUEST"; + case QDF_PROTO_ARP_RES: + return "ARP RESPONSE"; + case QDF_PROTO_ICMP_REQ: + return "ICMP REQUEST"; + case QDF_PROTO_ICMP_RES: + return "ICMP RESPONSE"; + case QDF_PROTO_ICMPV6_REQ: + return "ICMPV6 REQUEST"; + case QDF_PROTO_ICMPV6_RES: + return "ICMPV6 RESPONSE"; + case QDF_PROTO_IPV4_UDP: + return "IPV4 UDP Packet"; + case QDF_PROTO_IPV4_TCP: + return "IPV4 TCP Packet"; + case QDF_PROTO_IPV6_UDP: + return "IPV6 UDP Packet"; + case QDF_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 qdf_proto_subtype +wma_wow_get_pkt_proto_subtype(uint8_t *data, + uint32_t len) +{ + if (len >= WMA_IS_DHCP_GET_MIN_LEN) { + if (qdf_nbuf_data_is_ipv4_dhcp_pkt(data)) { + if (len >= WMA_DHCP_SUBTYPE_GET_MIN_LEN) + return qdf_nbuf_data_get_dhcp_subtype(data); + QDF_TRACE(QDF_MODULE_ID_WMA, + QDF_TRACE_LEVEL_ERROR, "DHCP Packet"); + return QDF_PROTO_INVALID; + } + } + if (len >= WMA_IS_EAPOL_GET_MIN_LEN) { + if (qdf_nbuf_data_is_ipv4_eapol_pkt(data)) { + if (len >= WMA_EAPOL_SUBTYPE_GET_MIN_LEN) + return qdf_nbuf_data_get_eapol_subtype(data); + QDF_TRACE(QDF_MODULE_ID_WMA, + QDF_TRACE_LEVEL_ERROR, "EAPOL Packet"); + return QDF_PROTO_INVALID; + } + } + if (len >= WMA_IS_ARP_GET_MIN_LEN) { + if (qdf_nbuf_data_is_ipv4_arp_pkt(data)) { + if (len >= WMA_ARP_SUBTYPE_GET_MIN_LEN) + return qdf_nbuf_data_get_arp_subtype(data); + QDF_TRACE(QDF_MODULE_ID_WMA, + QDF_TRACE_LEVEL_ERROR, "ARP Packet"); + return QDF_PROTO_INVALID; + } + } + if (len >= WMA_IPV4_PROTO_GET_MIN_LEN) { + if (qdf_nbuf_data_is_icmp_pkt(data)) { + if (len >= WMA_ICMP_SUBTYPE_GET_MIN_LEN) + return qdf_nbuf_data_get_icmp_subtype(data); + QDF_TRACE(QDF_MODULE_ID_WMA, + QDF_TRACE_LEVEL_ERROR, "ICMP Packet"); + return QDF_PROTO_INVALID; + } else if (qdf_nbuf_data_is_ipv4_udp_pkt(data)) { + return QDF_PROTO_IPV4_UDP; + } else if (qdf_nbuf_data_is_ipv4_tcp_pkt(data)) { + return QDF_PROTO_IPV4_TCP; + } + } + if (len >= WMA_IPV6_PROTO_GET_MIN_LEN) { + if (qdf_nbuf_data_is_icmpv6_pkt(data)) { + if (len >= WMA_ICMPV6_SUBTYPE_GET_MIN_LEN) + return qdf_nbuf_data_get_icmpv6_subtype(data); + QDF_TRACE(QDF_MODULE_ID_WMA, + QDF_TRACE_LEVEL_ERROR, "ICMPV6 Packet"); + return QDF_PROTO_INVALID; + } else if (qdf_nbuf_data_is_ipv6_udp_pkt(data)) { + return QDF_PROTO_IPV6_UDP; + } else if (qdf_nbuf_data_is_ipv6_tcp_pkt(data)) { + return QDF_PROTO_IPV6_TCP; + } + } + + return QDF_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 qdf_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 >= QDF_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 + QDF_NBUF_SRC_MAC_OFFSET)); + else + goto end; + + proto_subtype = wma_wow_get_pkt_proto_subtype(data, buf_len); + switch (proto_subtype) { + case QDF_PROTO_EAPOL_M1: + case QDF_PROTO_EAPOL_M2: + case QDF_PROTO_EAPOL_M3: + case QDF_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", + ani_cpu_to_be16(pkt_len), + ani_cpu_to_be16(key_len)); + } + break; + + case QDF_PROTO_DHCP_DISCOVER: + case QDF_PROTO_DHCP_REQUEST: + case QDF_PROTO_DHCP_OFFER: + case QDF_PROTO_DHCP_ACK: + case QDF_PROTO_DHCP_NACK: + case QDF_PROTO_DHCP_RELEASE: + case QDF_PROTO_DHCP_INFORM: + case QDF_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", + ani_cpu_to_be16(pkt_len), + ani_cpu_to_be16(transaction_id)); + } + break; + + case QDF_PROTO_ARP_REQ: + case QDF_PROTO_ARP_RES: + WMA_LOGE("WOW Wakeup: %s rcvd", + wma_pkt_proto_subtype_to_string(proto_subtype)); + break; + + case QDF_PROTO_ICMP_REQ: + case QDF_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", + ani_cpu_to_be16(pkt_len), + ani_cpu_to_be16(seq_num)); + } + break; + + case QDF_PROTO_ICMPV6_REQ: + case QDF_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", + ani_cpu_to_be16(pkt_len), + ani_cpu_to_be16(seq_num)); + } + break; + + case QDF_PROTO_IPV4_UDP: + case QDF_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", + ani_cpu_to_be16(pkt_len)); + if (proto_subtype == QDF_PROTO_IPV4_TCP) { + tcp_seq_num = (uint32_t)(*(uint32_t *)(data + + IPV4_TCP_SEQ_NUM_OFFSET)); + WMA_LOGE("TCP_seq_num: %d", + ani_cpu_to_be16(tcp_seq_num)); + } + } + break; + + case QDF_PROTO_IPV6_UDP: + case QDF_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", + ani_cpu_to_be16(pkt_len)); + if (proto_subtype == QDF_PROTO_IPV6_TCP) { + tcp_seq_num = (uint32_t)(*(uint32_t *)(data + + IPV6_TCP_SEQ_NUM_OFFSET)); + WMA_LOGE("TCP_seq_num: %d", + ani_cpu_to_be16(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; + } +} + +/** * wma_wow_wakeup_host_event() - wakeup host event handler * @handle: wma handle * @event: event data @@ -2764,14 +3045,25 @@ int wma_wow_wakeup_host_event(void *handle, uint8_t *event, /* First 4-bytes of wow_packet_buffer is the length */ qdf_mem_copy((uint8_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); - qdf_trace_hex_dump(QDF_MODULE_ID_WMA, - QDF_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); + qdf_trace_hex_dump(QDF_MODULE_ID_WMA, + QDF_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"); } |
