mirror of
https://github.com/qca/qca-swiss-army-knife.git
synced 2025-12-10 07:44:42 +01:00
ath10k_htt_rx_desc has QCA988X,QCA99X0 and QCA6174 packet information. ath10k_htt_rx_desc has QCA99X0 relted structures at various offsets. The current script has not taken care of QCA99X0 changes. This modification has fix for QCA988X chipsets. We will fix this script for all the supported chipsets later by sending one more trcing attribute from the driver.
319 lines
9.5 KiB
Python
319 lines
9.5 KiB
Python
#
|
|
# Copyright (c) 2014 Qualcomm Atheros, Inc.
|
|
#
|
|
# Permission to use, copy, modify, and/or distribute this software for any
|
|
# purpose with or without fee is hereby granted, provided that the above
|
|
# copyright notice and this permission notice appear in all copies.
|
|
#
|
|
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
#
|
|
# trace-cmd pktlog plugin for ath10k, QCA Linux wireless driver
|
|
#
|
|
# TODO:
|
|
#
|
|
# o create class for struct ieee80211_hdr each packet headers with
|
|
# pack() and unpack() methods
|
|
|
|
import struct
|
|
import binascii
|
|
|
|
DEBUG = 1
|
|
|
|
CUR_PKTLOG_VER = 10010
|
|
PKTLOG_MAGIC_NUM = 7735225
|
|
|
|
IEEE80211_FCTL_TODS = 0x0100
|
|
IEEE80211_FCTL_FROMDS = 0x0200
|
|
TARGET_NUM_MSDU_DESC = (1024 + 400)
|
|
MAX_PKT_INFO_MSDU_ID = 192
|
|
PKTLOG_MAX_TXCTL_WORDS = 57
|
|
|
|
ATH10K_PKTLOG_TYPE_TX_CTRL = 1
|
|
ATH10K_PKTLOG_TYPE_TX_STAT = 2
|
|
ATH10K_PKTLOG_TYPE_TX_MSDU_ID = 3
|
|
ATH10K_PKTLOG_TYPE_TX_FRM_HDR = 4
|
|
ATH10K_PKTLOG_TYPE_RX_STAT = 5
|
|
ATH10K_PKTLOG_TYPE_RC_FIND = 6
|
|
ATH10K_PKTLOG_TYPE_RC_UPDATE = 7
|
|
ATH10K_PKTLOG_TYPE_TX_VIRT_ADDR = 8
|
|
ATH10K_PKTLOG_TYPE_DBG_PRINT = 9
|
|
|
|
ATH10K_PKTLOG_FLG_TYPE_LOCAL_S = 0
|
|
ATH10K_PKTLOG_FLG_TYPE_REMOTE_S = 1
|
|
ATH10K_PKTLOG_FLG_TYPE_CLONE_S = 2
|
|
ATH10K_PKTLOG_FLG_TYPE_UNKNOWN_S = 3
|
|
|
|
# sizeof(ath10k_pktlog_txctl) = 12 + 4 * 57
|
|
ATH10K_PKTLOG_TXCTL_LEN = 240
|
|
|
|
msdu_len_tbl = {}
|
|
output_file = None
|
|
frm_hdr = None
|
|
|
|
def dbg(msg):
|
|
if DEBUG == 0:
|
|
return
|
|
|
|
print msg
|
|
|
|
def hexdump(buf, prefix=None):
|
|
s = binascii.b2a_hex(buf)
|
|
s_len = len(s)
|
|
result = ""
|
|
|
|
if prefix == None:
|
|
prefix = ""
|
|
|
|
for i in range(s_len / 2):
|
|
if i % 16 == 0:
|
|
result = result + ("%s%04x: " % (prefix, i))
|
|
|
|
result = result + (s[2*i] + s[2*i+1] + " ")
|
|
|
|
if (i + 1) % 16 == 0:
|
|
result = result + "\n"
|
|
|
|
# FIXME: if len(s) % 16 == 0 there's an extra \n in the end
|
|
|
|
return result
|
|
|
|
# struct ath10k_pktlog_hdr {
|
|
# unsigned short flags;
|
|
# unsigned short missed_cnt;
|
|
# unsigned short log_type;
|
|
# unsigned short size;
|
|
# unsigned int timestamp;
|
|
# unsigned char payload[0];
|
|
# } __attribute__((__packed__));
|
|
class Ath10kPktlogHdr:
|
|
# 2 + 2 + 2 + 2 + 4 = 12
|
|
hdr_len = 12
|
|
struct_fmt = '<HHHHI'
|
|
|
|
def unpack(self, buf, offset=0):
|
|
(self.flags, self.missed_cnt, self.log_type,
|
|
self.size, self.timestamp) = struct.unpack_from(self.struct_fmt, buf, 0)
|
|
|
|
payload_len = len(buf) - self.hdr_len
|
|
if payload_len != self.size:
|
|
raise Exception('Payload length invalid: %d != %d' %
|
|
(payload_len, self.size))
|
|
|
|
self.payload = buf[self.hdr_len:]
|
|
|
|
# excludes payload, you have to write that separately!
|
|
def pack(self):
|
|
return struct.pack(self.struct_fmt,
|
|
self.flags,
|
|
self.missed_cnt,
|
|
self.log_type,
|
|
self.size,
|
|
self.timestamp)
|
|
|
|
def __str__(self):
|
|
return 'flags %04x miss %d log_type %d size %d timestamp %d\n' % \
|
|
(self.flags, self.missed_cnt, self.log_type, self.size, self.timestamp)
|
|
|
|
def __init__(self):
|
|
self.flags = 0
|
|
self.missed_cnt = 0
|
|
self.log_type = 0
|
|
self.size = 0
|
|
self.timestamp = 0
|
|
self.payload = []
|
|
|
|
def output_open():
|
|
global output_file
|
|
|
|
# apparently no way to close the file as the python plugin doesn't
|
|
# have unregister() callback
|
|
output_file = open('pktlog.dat', 'wb')
|
|
|
|
buf = struct.pack('II', PKTLOG_MAGIC_NUM, CUR_PKTLOG_VER)
|
|
output_write(buf)
|
|
|
|
def output_write(buf):
|
|
global output_file
|
|
|
|
output_file.write(buf)
|
|
|
|
def pktlog_tx_frm_hdr(frame):
|
|
global frm_hdr
|
|
|
|
try:
|
|
# struct ieee80211_hdr
|
|
(frame_control, duration_id, addr1a, addr1b, addr1c, addr2a, addr2b, addr2c, addr3a, addr3b, addr3c, seq_ctrl) = struct.unpack_from('<HHI2BI2BI2BH', frame, 0)
|
|
except struct.error as e:
|
|
dbg('failed to parse struct ieee80211_hdr: %s' % (e))
|
|
return
|
|
|
|
if frame_control & IEEE80211_FCTL_TODS:
|
|
bssid_tail = (addr1b << 8) | addr1c
|
|
sa_tail = (addr2b << 8) | addr2c
|
|
da_tail = (addr3b << 8) | addr3c
|
|
elif frame_control & IEEE80211_FCTL_FROMDS:
|
|
bssid_tail = (addr2b << 8) | addr2c
|
|
sa_tail = (addr3b << 8) | addr3c
|
|
da_tail = (addr1b << 8) | addr1c
|
|
else:
|
|
bssid_tail = (addr3b << 8) | addr3c
|
|
sa_tail = (addr2b << 8) | addr2c
|
|
da_tail = (addr1b << 8) | addr1c
|
|
|
|
resvd = 0
|
|
|
|
frm_hdr = struct.pack('HHHHHH', frame_control, seq_ctrl, bssid_tail,
|
|
sa_tail, da_tail, resvd)
|
|
dbg('frm_hdr %d B' % len(frm_hdr))
|
|
|
|
def pktlog_tx_ctrl(buf):
|
|
global frm_hdr
|
|
|
|
hdr = Ath10kPktlogHdr()
|
|
hdr.unpack(buf)
|
|
hdr.size = ATH10K_PKTLOG_TXCTL_LEN
|
|
|
|
output_write(hdr.pack())
|
|
|
|
# write struct ath10k_pktlog_frame
|
|
if frm_hdr:
|
|
output_write(frm_hdr)
|
|
else:
|
|
tmp = struct.pack('HHHHHH', 0, 0, 0, 0, 0, 0)
|
|
output_write(tmp)
|
|
|
|
# write unsigned int txdesc_ctl[PKTLOG_MAX_TXCTL_WORDS]
|
|
# FIXME: check that length is correct
|
|
output_write(buf[12:])
|
|
|
|
def pktlog_tx_msdu_id(buf):
|
|
global msdu_len_tbl
|
|
|
|
hdr = Ath10kPktlogHdr()
|
|
hdr.unpack(buf)
|
|
hdr.size = 4 + (192 / 8) + 2 * 192
|
|
|
|
# write struct ath10k_pktlog_hdr
|
|
output_write(hdr.pack())
|
|
|
|
# parse struct msdu_id_info
|
|
# hdr (12) + num_msdu (4) + bound_bmap (24) = 40
|
|
msdu_info = hdr.payload[0:28]
|
|
id = hdr.payload[28:]
|
|
num_msdu, = struct.unpack_from('I', msdu_info)
|
|
output_write(msdu_info)
|
|
|
|
for i in range(MAX_PKT_INFO_MSDU_ID):
|
|
if len(id) >= 2:
|
|
msdu_id, = struct.unpack_from('<H', id);
|
|
id = id[2:]
|
|
if msdu_id not in msdu_len_tbl:
|
|
dbg('msdu_id %d not found from msdu_len_tbl' % (msdu_id))
|
|
msdu_len = 0
|
|
else:
|
|
msdu_len = msdu_len_tbl[msdu_id]
|
|
else:
|
|
msdu_len = 0
|
|
output_write(struct.pack('H', msdu_len))
|
|
|
|
def ath10k_htt_pktlog_handler(pevent, trace_seq, event):
|
|
buf = event['pktlog'].data
|
|
offset = 0
|
|
|
|
hdr = Ath10kPktlogHdr()
|
|
hdr.unpack(buf, offset)
|
|
offset = offset + hdr.hdr_len
|
|
|
|
trace_seq.puts('%s\n' % (hdr))
|
|
|
|
if hdr.log_type == ATH10K_PKTLOG_TYPE_TX_FRM_HDR:
|
|
pktlog_tx_frm_hdr(buf[Ath10kPktlogHdr.hdr_len:])
|
|
elif hdr.log_type == ATH10K_PKTLOG_TYPE_TX_CTRL:
|
|
pktlog_tx_ctrl(buf)
|
|
elif hdr.log_type == ATH10K_PKTLOG_TYPE_TX_MSDU_ID:
|
|
pktlog_tx_msdu_id(buf)
|
|
elif hdr.log_type == ATH10K_PKTLOG_TYPE_TX_STAT or \
|
|
hdr.log_type == ATH10K_PKTLOG_TYPE_RX_STAT or \
|
|
hdr.log_type == ATH10K_PKTLOG_TYPE_RC_FIND or \
|
|
hdr.log_type == ATH10K_PKTLOG_TYPE_RC_UPDATE:
|
|
output_write(buf[0 : offset + hdr.size])
|
|
else:
|
|
pass
|
|
|
|
def ath10k_htt_rx_desc_handler(pevent, trace_seq, event):
|
|
rxdesc = event['rxdesc'].data
|
|
|
|
trace_seq.puts('len %d\n' % (len(rxdesc)))
|
|
|
|
hdr = Ath10kPktlogHdr()
|
|
hdr.flags = (1 << ATH10K_PKTLOG_FLG_TYPE_REMOTE_S)
|
|
hdr.missed_cnt = 0
|
|
hdr.log_type = ATH10K_PKTLOG_TYPE_RX_STAT
|
|
#TODO Fix this according to board type
|
|
#hdr.size = len(rxdesc)
|
|
hdr.size = 248
|
|
|
|
output_write(hdr.pack())
|
|
#output_write(rxdesc)
|
|
#This change is required for QCA988X chip sets
|
|
#We are skipping QCA99X0 data here
|
|
output_write(rxdesc[0 : 32])
|
|
output_write(rxdesc[36 : 56])
|
|
output_write(rxdesc[76 : 208])
|
|
output_write(rxdesc[228 : ])
|
|
|
|
def ath10k_htt_tx_handler(pevent, trace_seq, event):
|
|
global msdu_len_tbl
|
|
msdu_id = long(event['msdu_id'])
|
|
msdu_len = long(event['msdu_len'])
|
|
|
|
trace_seq.puts('msdu_id %d msdu_len %d\n' % (msdu_id, msdu_len))
|
|
|
|
if msdu_id > TARGET_NUM_MSDU_DESC:
|
|
dbg('Invalid msdu_id in tx: %d' % (msdu_id))
|
|
return
|
|
|
|
msdu_len_tbl[msdu_id] = msdu_len
|
|
|
|
def ath10k_txrx_tx_unref_handler(pevent, trace_seq, event):
|
|
global msdu_len_tbl
|
|
msdu_id = long(event['msdu_id'])
|
|
|
|
trace_seq.puts('msdu_id %d\n' % (msdu_id))
|
|
|
|
if msdu_id > TARGET_NUM_MSDU_DESC:
|
|
dbg('Invalid msdu_id from unref: %d' % (msdu_id))
|
|
return
|
|
|
|
msdu_len_tbl[msdu_id] = 0
|
|
|
|
def ath10k_tx_hdr_handler(pevent, trace_seq, event):
|
|
buf = event['data'].data
|
|
|
|
pktlog_tx_frm_hdr(buf[0:])
|
|
|
|
def register(pevent):
|
|
|
|
output_open()
|
|
|
|
pevent.register_event_handler("ath10k", "ath10k_htt_pktlog",
|
|
lambda *args:
|
|
ath10k_htt_pktlog_handler(pevent, *args))
|
|
pevent.register_event_handler("ath10k", "ath10k_htt_rx_desc",
|
|
lambda *args:
|
|
ath10k_htt_rx_desc_handler(pevent, *args))
|
|
pevent.register_event_handler("ath10k", "ath10k_htt_tx",
|
|
lambda *args:
|
|
ath10k_htt_tx_handler(pevent, *args))
|
|
pevent.register_event_handler("ath10k", "ath10k_txrx_tx_unref",
|
|
lambda *args:
|
|
ath10k_txrx_tx_unref_handler(pevent, *args))
|
|
pevent.register_event_handler("ath10k", "ath10k_tx_hdr",
|
|
lambda *args:
|
|
ath10k_tx_hdr_handler(pevent, *args))
|