blob: e01da3b6873dd4910041ae58c05b6bc964e8f6c0 [file] [log] [blame]
/* 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