/* 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_PKT_DUMP_V2 11
#define PKTLOG_TYPE_MAX 12
#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
#define PKT_INFO_FLG_PKT_DUMP_V2 0x8000
/* 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;
/* Format of the v2 packet stats event*/
typedef struct {
u16 flags;
u16 missed_cnt;
u16 log_type;
u16 size;
u32 timestamp;
u32 reserved;
} __attribute__((packed)) wh_pktlog_hdr_v2_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