/* Copyright (c) 2015, The Linux Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of The Linux Foundation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _PKT_STATS_H_ #define _PKT_STATS_H_ /* Types of packet log events. * Tx stats will be sent from driver with the help of multiple events. * Need to parse the events PKTLOG_TYPE_TX_CTRL and PKTLOG_TYPE_TX_STAT * as of now for the required stats. Rest of the events can ignored. */ #define PKTLOG_TYPE_TX_CTRL 1 #define PKTLOG_TYPE_TX_STAT 2 #define PKTLOG_TYPE_TX_MSDU_ID 3 #define PKTLOG_TYPE_TX_FRM_HDR 4 /* Rx stats will be sent from driver with event ID- PKTLOG_TYPE_RX_STAT */ #define PKTLOG_TYPE_RX_STAT 5 #define PKTLOG_TYPE_RC_FIND 6 #define PKTLOG_TYPE_RC_UPDATE 7 #define PKTLOG_TYPE_TX_VIRT_ADDR 8 #define PKTLOG_TYPE_PKT_STATS 9 #define PKTLOG_TYPE_PKT_DUMP 10 #define PKTLOG_TYPE_MAX 11 #define BW_OFFSET 8 #define INVALID_RSSI 255 #define PKT_INFO_FLG_TX_LOCAL_S 0x1 #define PKT_INFO_FLG_RX_HOST_RXD 0x2 #define PKT_INFO_FLG_TX_REMOTE_S 0x4 #define PKT_INFO_FLG_RX_LOCAL_S 0x8 #define PKT_INFO_FLG_RX_REMOTE_S 0x10 #define PKT_INFO_FLG_RX_LOCAL_DISCARD_S 0x20 #define PKT_INFO_FLG_RX_REMOTE_DISCARD_S 0x40 #define PKT_INFO_FLG_RX_REORDER_STORE_S 0x80 #define PKT_INFO_FLG_RX_REORDER_DROP_S 0x100 #define PKT_INFO_FLG_RX_PEER_INFO_S 0x200 #define PKT_INFO_FLG_UNKNOWN_S 0x400 /* MASK value of flags based on RX_STAT content. * These are the events that carry Rx decriptor */ #define PKT_INFO_FLG_RX_RXDESC_MASK \ (PKT_INFO_FLG_RX_HOST_RXD | \ PKT_INFO_FLG_RX_LOCAL_S | \ PKT_INFO_FLG_RX_REMOTE_S | \ PKT_INFO_FLG_RX_LOCAL_DISCARD_S | \ PKT_INFO_FLG_RX_REMOTE_DISCARD_S) /* Format of the packet stats event*/ typedef struct { u16 flags; u16 missed_cnt; u16 log_type; u16 size; u32 timestamp; } __attribute__((packed)) wh_pktlog_hdr_t; /*Rx stats specific structures. */ struct rx_attention { u32 first_mpdu : 1; //[0] u32 last_mpdu : 1; //[1] u32 reserved1 : 6; //[7:2] u32 mgmt_type : 1; //[8] u32 ctrl_type : 1; //[9] u32 reserved2 : 6; //[15:10] u32 overflow_err : 1; //[16] u32 msdu_length_err : 1; //[17] u32 tcp_udp_chksum_fail : 1; //[18] u32 ip_chksum_fail : 1; //[19] u32 reserved3 : 7; //[26:20] u32 mpdu_length_err : 1; //[27] u32 tkip_mic_err : 1; //[28] u32 decrypt_err : 1; //[29] u32 fcs_err : 1; //[30] u32 msdu_done : 1; //[31] } __attribute__((packed)); struct rx_mpdu_start { u32 reserved1 : 13; //[12:0] u32 encrypted : 1; //[13] u32 retry : 1; //[14] u32 reserved2 : 1; //[15] u32 seq_num : 12; //[27:16] u32 reserved3 : 4; //[31:28] u32 reserved4; u32 reserved5 : 28; //[27:0] u32 tid : 4; //[31:28] } __attribute__((packed)); /*Indicates the decap-format of the packet*/ enum { RAW=0, // RAW: No decapsulation NATIVEWIFI, ETHERNET2, // (DIX) ETHERNET // (SNAP/LLC) }; struct rx_msdu_start { u32 reserved1[2]; u32 reserved2 : 8; //[7:0] u32 decap_format : 2; //[9:8] u32 reserved3 : 22; //[31:10] } __attribute__((packed)); struct rx_msdu_end { u32 reserved1[4]; u32 reserved2 : 15; u32 last_msdu : 1; //[15] u32 reserved3 : 16; //[31:16] } __attribute__((packed)); struct rx_mpdu_end { u32 reserved1 : 13; //[12:0] u32 overflow_err : 1; //[13] u32 last_mpdu : 1; //[14] u32 post_delim_err : 1; //[15] u32 reserved2 : 12; //[27:16] u32 mpdu_length_err : 1; //[28] u32 tkip_mic_err : 1; //[29] u32 decrypt_err : 1; //[30] u32 fcs_err : 1; //[31] } __attribute__((packed)); #define PREAMBLE_L_SIG_RATE 0x04 #define PREAMBLE_VHT_SIG_A_1 0x08 #define PREAMBLE_VHT_SIG_A_2 0x0c /* Wifi Logger preamble */ #define WL_PREAMBLE_CCK 0 #define WL_PREAMBLE_OFDM 1 #define WL_PREAMBLE_HT 2 #define WL_PREAMBLE_VHT 3 #define BITMASK(x) ((1<<(x)) - 1 ) #define MAX_BA_WINDOW_SIZE 64 #define SEQ_NUM_RANGE 4096 #define BITMAP_VAR_SIZE 32 /* Contains MCS related stats */ struct rx_ppdu_start { u32 reserved1[4]; u32 rssi_comb : 8; //[7:0] u32 reserved2 : 24; //[31:8] u32 l_sig_rate : 4; //[3:0] u32 l_sig_rate_select : 1; //[4] u32 reserved3 : 19; //[23:5] u32 preamble_type : 8; //[31:24] u32 ht_sig_vht_sig_a_1 : 24; //[23:0] u32 reserved4 : 8; //[31:24] u32 ht_sig_vht_sig_a_2 : 24; //[23:0] u32 reserved5 : 8; //[31:25] u32 reserved6[2]; } __attribute__((packed)); struct rx_ppdu_end { u32 reserved1[16]; u32 tsf_timestamp; u32 reserved2[5]; } __attribute__((packed)); #define MAX_MSDUS_PER_MPDU 3 #define MAX_RXMPDUS_PER_AMPDU 64 #define RX_HTT_HDR_STATUS_LEN 64 typedef struct { struct rx_attention attention; u32 reserved1; struct rx_mpdu_start mpdu_start; struct rx_msdu_start msdu_start; struct rx_msdu_end msdu_end; struct rx_mpdu_end mpdu_end; struct rx_ppdu_start ppdu_start; struct rx_ppdu_end ppdu_end; char rx_hdr_status[RX_HTT_HDR_STATUS_LEN]; }__attribute__((packed)) rb_pkt_stats_t; /*Tx stats specific structures. */ struct ppdu_status { u32 ba_start_seq_num : 12; //[11:0] u32 reserved1 : 3; //[14:12] u32 ba_status : 1; //[15] u32 reserved2 : 15; //[30:16] u32 tx_ok : 1; //[31] u32 ba_bitmap_31_0 : 32; //[31:0] u32 ba_bitmap_63_32 : 32; //[31:0] u32 reserved3[8]; u32 ack_rssi_ave : 8; //[7:0] u32 reserved4 : 16; //[23:8] u32 total_tries : 5; //[28:24] u32 reserved5 : 3; //[31:29] u32 reserved6[4]; } __attribute__((packed)); /*Contains tx timestamp*/ struct try_status { u32 timestamp : 23; //[22:0] u32 reserved1 : 1; //[23] u32 series : 1; //[24] u32 reserved2 : 3; //[27:25] u32 packet_bw : 2; //[29:28] u32 reserved3 : 1; //[30] u32 tx_packet : 1; //[31] } __attribute__((packed)); struct try_list { struct try_status try_st[16]; } __attribute__((packed)); struct tx_ppdu_end { struct try_list try_list; struct ppdu_status stat; } __attribute__((packed)); /*Tx MCS and data rate ralated stats */ struct series_bw { u32 reserved1 : 28; //[27:0] u32 short_gi : 1; //[28] u32 reserved2 : 3; //[31:29] u32 reserved3 : 24; //[23:21] u32 rate : 4; //[27:24] u32 nss : 2; //[29:28] u32 preamble_type : 2; //[31:30] u32 reserved4[2]; } __attribute__((packed)); enum tx_bw { BW_20_MHZ, BW_40_MHZ, BW_80_MHZ, BW_160_MHZ }; #define DATA_PROTECTED 14 struct tx_ppdu_start { u32 reserved1[2]; u32 start_seq_num : 12; //[11:0] u32 reserved2 : 20; //[31:12] u32 seqnum_bitmap_31_0 : 32; //[31:0] u32 seqnum_bitmap_63_32 : 32; //[31:0] u32 reserved3[8]; u32 reserved4 : 15; //[14:0] u32 ampdu : 1; //[15] u32 no_ack : 1; //[16] u32 reserved5 : 15; //[31:17] u32 reserved6 : 16; //[15:0] u32 frame_control : 16; //[31:16] u32 reserved7 : 16; //[23:21] u32 qos_ctl : 16; //[31:16] u32 reserved8[4]; u32 reserved9 : 24; //[23:21] u32 valid_s0_bw20 : 1; //[24] u32 valid_s0_bw40 : 1; //[25] u32 valid_s0_bw80 : 1; //[26] u32 valid_s0_bw160 : 1; //[27] u32 valid_s1_bw20 : 1; //[28] u32 valid_s1_bw40 : 1; //[29] u32 valid_s1_bw80 : 1; //[30] u32 valid_s1_bw160 : 1; //[31] struct series_bw s0_bw20; struct series_bw s0_bw40; struct series_bw s0_bw80; struct series_bw s0_bw160; struct series_bw s1_bw20; struct series_bw s1_bw40; struct series_bw s1_bw80; struct series_bw s1_bw160; u32 reserved10[3]; } __attribute__((packed)); #define PKTLOG_MAX_TXCTL_WORDS 57 /* +2 words for bitmap */ typedef struct { u32 reserved1[3]; union { u32 txdesc_ctl[PKTLOG_MAX_TXCTL_WORDS]; struct tx_ppdu_start ppdu_start; }u; } __attribute__((packed)) wh_pktlog_txctl; /* Required stats are spread across multiple * events(PKTLOG_TYPE_TX_CTRL and PKTLOG_TYPE_TX_STAT here). * Need to aggregate the stats collected in each event and write to the * ring buffer only after receiving all the expected stats. * Need to preserve the stats in hal_info till then and use tx_stats_events * flag to track the events. * prev_seq_no: Can used to track the events that come from driver and identify * if any event is missed. */ #define RING_BUF_ENTRY_SIZE 512 #define PKT_STATS_BUF_SIZE 128 struct pkt_stats_s { u8 tx_stats_events; /* TODO: Need to handle the case if size of the stats are more * than 512 bytes. Currently, the tx size is 34 bytes and ring buffer entry * size is 12 bytes. */ u8 tx_stats[PKT_STATS_BUF_SIZE]; u8 num_msdu; u16 start_seq_num; u16 ba_seq_num; u32 ba_bitmap_31_0; u32 ba_bitmap_63_32; u32 tx_seqnum_bitmap_31_0; u32 tx_seqnum_bitmap_63_32; u32 shifted_bitmap_31_0; u32 shifted_bitmap_63_32; bool isBlockAck; u8 tx_bandwidth; u8 series; }; typedef union { struct { u16 rate : 4; u16 nss : 2; u16 preamble : 2; u16 bw : 2; u16 short_gi : 1; u16 reserved : 5; } mcs_s; u16 mcs; } MCS; typedef struct { MCS RxMCS; u16 last_transmit_rate; u16 rssi; u32 timestamp; u8 tid; } rx_aggr_stats; typedef struct drv_msg_s { u16 length; u16 event_type; u32 timestamp_low; u32 timestamp_high; union { struct { u32 version; u32 msg_seq_no; u32 payload_len; u8 payload[0]; } __attribute__((packed)) pkt_stats_event; } u; } __attribute__((packed)) drv_msg_t; typedef enum { START_MONITOR = 1, STOP_MONITOR, TX_MGMT_PKT, TX_DATA_PKT, RX_MGMT_PKT, RX_DATA_PKT, } pktdump_event_type; typedef struct { u8 status; u8 type; u32 driver_ts; u16 fw_ts; } __attribute__((packed)) pktdump_hdr; typedef struct { frame_type payload_type; u32 driver_timestamp_usec; u32 firmware_timestamp_usec; size_t frame_len; char *frame_content; } frame_info_i; typedef struct { // Prefix of MD5 hash of |frame_inf.frame_content|. If frame // content is not provided, prefix of MD5 hash over the same data // that would be in frame_content, if frame content were provided. char md5_prefix[MD5_PREFIX_LEN]; // Prefix of MD5 hash of packet bytes wifi_tx_packet_fate fate; frame_info_i frame_inf; } wifi_tx_report_i; typedef struct { // Prefix of MD5 hash of |frame_inf.frame_content|. If frame // content is not provided, prefix of MD5 hash over the same data // that would be in frame_content, if frame content were provided. char md5_prefix[MD5_PREFIX_LEN]; wifi_rx_packet_fate fate; frame_info_i frame_inf; } wifi_rx_report_i; typedef struct { wifi_tx_report_i tx_fate_stats[MAX_FATE_LOG_LEN]; size_t n_tx_stats_collected; wifi_rx_report_i rx_fate_stats[MAX_FATE_LOG_LEN]; size_t n_rx_stats_collected; } packet_fate_monitor_info; #endif