/* 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 INVALID_RATE_CODE 0xff

/* Based on pkt log V2, this type of event will triggered */
#define PKTLOG_TYPE_PKT_SW_EVENT    10
#define PKTLOG_TYPE_RX_STATBUF      22   //Full Rx pktlog stats
#define PKTLOG_TYPE_LITE_T2H        23   //PPDU Level Tx pktlog stats
#define PKTLOG_TYPE_LITE_RX         24   //PPDU Level Rx pktlog stats


#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

/* Depend on packet log version V2 this
 * offset are define, for more info need to
 * check from firmware side.
 */
#define TX_SUCCESS_TMS_OFFSET 56
#define LINK_LAYER_TX_SQN_OFFSET 66
#define RATE_CODE_OFFSET 68
#define TX_STATUS_OFFSET 70
#define TX_RSSI_OFFSET 71
#define NO_RETRIES_OFFSET 75
#define EXT_FLAGS_OFFSET 76
#define BMAP_FAILED_OFFSET 84
#define BMAP_ENQUEUED_OFFSET 92
#define FRAME_CTRL_OFFSET 216
#define QOS_CTRL_OFFSET 218

/* MAX HT/VHT mcs index */
#define MAX_VHT_MCS_IDX 10
#define MAX_HT_MCS_IDX 8

/* MAX CCK/OFDM rate index */
#define MAX_CCK_MCS_IDX 4
#define MAX_OFDM_MCS_IDX 8

/* 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        : 8; //[7:0]
    u16 mac_id          : 8; //[15:8]
    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));

/* structure implemented w.r.t PKT_LOG_V2 Version */
struct rx_msdu_start_v1 {
    u32 reserved1[2];
    u32 reserved2                       :  8; //[7:0]
    u32 decap_format                    :  2; //[9:8]
    u32 reserved3                       : 22; //[31:10]
    u32 reserved4[2];
} __attribute__((packed));

struct rx_msdu_end_v1 {
    u32 reserved1[4];
    u32 reserved2                       : 15; //[14:0]
    u32 last_msdu                       :  1; //[15]
    u32 reserved3                       : 16; //[31:16]
    u32 reserved4[9];
} __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));

struct rx_ppdu_end_V1 {
    u32 reserved1[18];
    u32 wb_timestamp_lower_32;
    u32 reserved2[18];
} __attribute__((packed));

#define MAX_MSDUS_PER_MPDU 3
#define MAX_RXMPDUS_PER_AMPDU 64
#define RX_HTT_HDR_STATUS_LEN 64
/* RX Data length is 256 for PKT_LOG_V2 Version */
#define RX_HTT_HDR_STATUS_LEN_V1 256

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;

/* structure implemented w.r.t PKT_LOG_V2 Version */
typedef struct {
    struct rx_attention attention;
    u32 reserved1[2];
    struct rx_mpdu_start    mpdu_start;
    struct rx_msdu_start_v1 msdu_start;
    struct rx_msdu_end_v1   msdu_end;
    struct rx_mpdu_end      mpdu_end;
    struct rx_ppdu_start    ppdu_start;
    struct rx_ppdu_end_V1    ppdu_end;
    char rx_hdr_status[RX_HTT_HDR_STATUS_LEN_V1];
}__attribute__((packed)) rb_pkt_stats_t_v1;
/************************************************************/

/*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.
 */

/* PKT_LOG_V2 Base strcuture used to parse buffer */
typedef struct {
    u16 frm_ctrl;
    u8  tx_ok;
    u16 qos_ctrl;
    u64 bmap_failed;
    u64 bmap_enqueued;
} __attribute__((packed)) node_pkt_stats;

typedef u8 A_RATECODE;

/* Rate Code as per PKT_LOG_V2 Version */
typedef struct {
    A_RATECODE rateCode;
    u8 flags;
} RATE_CODE;

/* bandwidht type*/
typedef enum {
    BW_20MHZ,
    BW_40MHZ,
    BW_80MHZ,
    BW_160MHZ,
} bandwidth;

/* Preamble type*/
typedef enum {
    WIFI_HW_RATECODE_PREAM_OFDM = 0,
    WIFI_HW_RATECODE_PREAM_CCK  = 1,
    WIFI_HW_RATECODE_PREAM_HT   = 2,
    WIFI_HW_RATECODE_PREAM_VHT  = 3,
    WIFI_HW_RATECODE_PREAM_COUNT,
} WIFI_HW_RATECODE_PREAM_TYPE;

/**
 * struct index_data_rate_type - non vht data rate type
 * @rate_index: cck  rate index
 * @cck_rate: CCK supported rate table
 */
struct index_data_rate_cck_type {
    uint8_t  rate_index;
    uint16_t cck_rate[2];
};

/**
 * struct index_data_rate_type - non vht data rate type
 * @rate_index: ofdm  rate index
 * @ofdm__rate: OFDM supported rate table
 */
struct index_data_rate_ofdm_type {
    uint8_t  rate_index;
    uint16_t ofdm_rate[2];
};

/*Below CCK/OFDM table refer from firmware Arch */
/* Rate Table Based on CCK */
static struct index_data_rate_cck_type cck_mcs_nss1[] = {
    /*RC     LKbps   SKbps */
    {0x40,  {11000,  11000} },
    {0x41,  {5500,   5500} },
    {0x42,  {2000,   2000} },
    {0x43,  {1000,   1000} }
};

/* Rate Table Based on OFDM */
static struct index_data_rate_ofdm_type ofdm_mcs_nss1[] = {
    /*RC     LKbps   SKbps */
    {0x00,  {48000,  48000} },
    {0x01,  {34000,  24000} },
    {0x02,  {12000,  12000} },
    {0x03,  {6000,   6000} },
    {0x04,  {54000,  54000} },
    {0x05,  {36000,  36000} },
    {0x06,  {18000,  18000} },
    {0x07,  {9000,   9000} }
};

/**
 * struct index_data_rate_type - non vht data rate type
 * @mcs_index: mcs rate index
 * @ht20_rate: HT20 supported rate table
 * @ht40_rate: HT40 supported rate table
 */
struct index_data_rate_type {
    uint8_t  mcs_index;
    uint16_t ht20_rate[2];
    uint16_t ht40_rate[2];
};

/**
 * struct index_vht_data_rate_type - vht data rate type
 * @mcs_index: mcs rate index
 * @ht20_rate: VHT20 supported rate table
 * @ht40_rate: VHT40 supported rate table
 * @ht80_rate: VHT80 supported rate table
 */
struct index_vht_data_rate_type {
    uint8_t mcs_index;
    uint16_t ht20_rate[2];
    uint16_t ht40_rate[2];
    uint16_t ht80_rate[2];
};

/*Below HT/VHT table refer from Host Driver
 * MCS Based rate table
 * HT MCS parameters with Nss = 1
 */
static struct index_data_rate_type mcs_nss1[] = {
    /* MCS L20  S20   L40   S40 */
    {0,  {65,  72},  {135,  150 } },
    {1,  {130, 144}, {270,  300 } },
    {2,  {195, 217}, {405,  450 } },
    {3,  {260, 289}, {540,  600 } },
    {4,  {390, 433}, {815,  900 } },
    {5,  {520, 578}, {1080, 1200} },
    {6,  {585, 650}, {1215, 1350} },
    {7,  {650, 722}, {1350, 1500} }
};

/* HT MCS parameters with Nss = 2 */
static struct index_data_rate_type mcs_nss2[] = {
    /* MCS L20  S20    L40   S40 */
    {0,  {130,  144},  {270,  300 } },
    {1,  {260,  289},  {540,  600 } },
    {2,  {390,  433},  {810,  900 } },
    {3,  {520,  578},  {1080, 1200} },
    {4,  {780,  867},  {1620, 1800} },
    {5,  {1040, 1156}, {2160, 2400} },
    {6,  {1170, 1300}, {2430, 2700} },
    {7,  {1300, 1440}, {2700, 3000} }
};

/* MCS Based VHT rate table
 * MCS parameters with Nss = 1
 */
static struct index_vht_data_rate_type vht_mcs_nss1[] = {
    /* MCS L20  S20    L40   S40    L80   S80 */
    {0,  {65,   72 }, {135,  150},  {293,  325} },
    {1,  {130,  144}, {270,  300},  {585,  650} },
    {2,  {195,  217}, {405,  450},  {878,  975} },
    {3,  {260,  289}, {540,  600},  {1170, 1300} },
    {4,  {390,  433}, {810,  900},  {1755, 1950} },
    {5,  {520,  578}, {1080, 1200}, {2340, 2600} },
    {6,  {585,  650}, {1215, 1350}, {2633, 2925} },
    {7,  {650,  722}, {1350, 1500}, {2925, 3250} },
    {8,  {780,  867}, {1620, 1800}, {3510, 3900} },
    {9,  {865,  960}, {1800, 2000}, {3900, 4333} }
};

/*MCS parameters with Nss = 2*/
static struct index_vht_data_rate_type vht_mcs_nss2[] = {
    /* MCS L20  S20    L40    S40    L80    S80 */
    {0,  {130,  144},  {270,  300},  { 585,  650} },
    {1,  {260,  289},  {540,  600},  {1170, 1300} },
    {2,  {390,  433},  {810,  900},  {1755, 1950} },
    {3,  {520,  578},  {1080, 1200}, {2340, 2600} },
    {4,  {780,  867},  {1620, 1800}, {3510, 3900} },
    {5,  {1040, 1156}, {2160, 2400}, {4680, 5200} },
    {6,  {1170, 1300}, {2430, 2700}, {5265, 5850} },
    {7,  {1300, 1444}, {2700, 3000}, {5850, 6500} },
    {8,  {1560, 1733}, {3240, 3600}, {7020, 7800} },
    {9,  {1730, 1920}, {3600, 4000}, {7800, 8667} }
};
/*********************************************************/

#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
