19725191aSViacheslav Ovsiienko#!/usr/bin/env python3 29725191aSViacheslav Ovsiienko# SPDX-License-Identifier: BSD-3-Clause 39725191aSViacheslav Ovsiienko# Copyright (c) 2023 NVIDIA Corporation & Affiliates 49725191aSViacheslav Ovsiienko 59725191aSViacheslav Ovsiienko""" 69725191aSViacheslav OvsiienkoAnalyzing the mlx5 PMD datapath tracings 79725191aSViacheslav Ovsiienko""" 89725191aSViacheslav Ovsiienkoimport sys 99725191aSViacheslav Ovsiienkoimport argparse 109725191aSViacheslav Ovsiienkoimport bt2 119725191aSViacheslav Ovsiienko 129725191aSViacheslav OvsiienkoPFX_TX = "pmd.net.mlx5.tx." 139725191aSViacheslav OvsiienkoPFX_TX_LEN = len(PFX_TX) 149725191aSViacheslav Ovsiienko 159725191aSViacheslav Ovsiienko 169725191aSViacheslav Ovsiienkoclass MlxQueue: 179725191aSViacheslav Ovsiienko """Queue container object""" 189725191aSViacheslav Ovsiienko 199725191aSViacheslav Ovsiienko def __init__(self): 209725191aSViacheslav Ovsiienko self.done_burst = [] # completed bursts 219725191aSViacheslav Ovsiienko self.wait_burst = [] # waiting for completion 229725191aSViacheslav Ovsiienko self.pq_id = 0 239725191aSViacheslav Ovsiienko 24*171360dfSViacheslav Ovsiienko def log(self, all): 259725191aSViacheslav Ovsiienko """Log all queue bursts""" 269725191aSViacheslav Ovsiienko for txb in self.done_burst: 279725191aSViacheslav Ovsiienko txb.log() 28*171360dfSViacheslav Ovsiienko if all == True: 29*171360dfSViacheslav Ovsiienko for txb in self.wait_burst: 30*171360dfSViacheslav Ovsiienko txb.log() 319725191aSViacheslav Ovsiienko 329725191aSViacheslav Ovsiienko 339725191aSViacheslav Ovsiienkoclass MlxMbuf: 349725191aSViacheslav Ovsiienko """Packet mbufs container object""" 359725191aSViacheslav Ovsiienko 369725191aSViacheslav Ovsiienko def __init__(self): 379725191aSViacheslav Ovsiienko self.wqe = 0 # wqe id 389725191aSViacheslav Ovsiienko self.ptr = None # first packet mbuf pointer 399725191aSViacheslav Ovsiienko self.len = 0 # packet data length 409725191aSViacheslav Ovsiienko self.nseg = 0 # number of segments 419725191aSViacheslav Ovsiienko 429725191aSViacheslav Ovsiienko def log(self): 439725191aSViacheslav Ovsiienko """Log mbuf""" 449725191aSViacheslav Ovsiienko out_txt = " %X: %u" % (self.ptr, self.len) 459725191aSViacheslav Ovsiienko if self.nseg != 1: 469725191aSViacheslav Ovsiienko out_txt += " (%d segs)" % self.nseg 479725191aSViacheslav Ovsiienko print(out_txt) 489725191aSViacheslav Ovsiienko 499725191aSViacheslav Ovsiienko 509725191aSViacheslav Ovsiienkoclass MlxWqe: 519725191aSViacheslav Ovsiienko """WQE container object""" 529725191aSViacheslav Ovsiienko 539725191aSViacheslav Ovsiienko def __init__(self): 549725191aSViacheslav Ovsiienko self.mbuf = [] # list of mbufs in WQE 559725191aSViacheslav Ovsiienko self.wait_ts = 0 # preceding wait/push timestamp 569725191aSViacheslav Ovsiienko self.comp_ts = 0 # send/recv completion timestamp 579725191aSViacheslav Ovsiienko self.opcode = 0 589725191aSViacheslav Ovsiienko 599725191aSViacheslav Ovsiienko def log(self): 609725191aSViacheslav Ovsiienko """Log WQE""" 619725191aSViacheslav Ovsiienko wqe_id = (self.opcode >> 8) & 0xFFFF 629725191aSViacheslav Ovsiienko wqe_op = self.opcode & 0xFF 639725191aSViacheslav Ovsiienko out_txt = " %04X: " % wqe_id 649725191aSViacheslav Ovsiienko if wqe_op == 0xF: 659725191aSViacheslav Ovsiienko out_txt += "WAIT" 669725191aSViacheslav Ovsiienko elif wqe_op == 0x29: 679725191aSViacheslav Ovsiienko out_txt += "EMPW" 689725191aSViacheslav Ovsiienko elif wqe_op == 0xE: 699725191aSViacheslav Ovsiienko out_txt += "TSO " 709725191aSViacheslav Ovsiienko elif wqe_op == 0xA: 719725191aSViacheslav Ovsiienko out_txt += "SEND" 729725191aSViacheslav Ovsiienko else: 739725191aSViacheslav Ovsiienko out_txt += "0x%02X" % wqe_op 749725191aSViacheslav Ovsiienko if self.comp_ts != 0: 759725191aSViacheslav Ovsiienko out_txt += " (%d, %d)" % (self.wait_ts, self.comp_ts - self.wait_ts) 769725191aSViacheslav Ovsiienko else: 779725191aSViacheslav Ovsiienko out_txt += " (%d)" % self.wait_ts 789725191aSViacheslav Ovsiienko print(out_txt) 799725191aSViacheslav Ovsiienko for mbuf in self.mbuf: 809725191aSViacheslav Ovsiienko mbuf.log() 819725191aSViacheslav Ovsiienko 829725191aSViacheslav Ovsiienko def comp(self, wqe_id, wqe_ts): 839725191aSViacheslav Ovsiienko """Return 0 if WQE in not completedLog WQE""" 849725191aSViacheslav Ovsiienko if self.comp_ts != 0: 859725191aSViacheslav Ovsiienko return 1 869725191aSViacheslav Ovsiienko cur_id = (self.opcode >> 8) & 0xFFFF 879725191aSViacheslav Ovsiienko if cur_id > wqe_id: 889725191aSViacheslav Ovsiienko cur_id -= wqe_id 899725191aSViacheslav Ovsiienko if cur_id <= 0x8000: 909725191aSViacheslav Ovsiienko return 0 919725191aSViacheslav Ovsiienko else: 929725191aSViacheslav Ovsiienko cur_id = wqe_id - cur_id 939725191aSViacheslav Ovsiienko if cur_id >= 0x8000: 949725191aSViacheslav Ovsiienko return 0 959725191aSViacheslav Ovsiienko self.comp_ts = wqe_ts 969725191aSViacheslav Ovsiienko return 1 979725191aSViacheslav Ovsiienko 989725191aSViacheslav Ovsiienko 999725191aSViacheslav Ovsiienkoclass MlxBurst: 1009725191aSViacheslav Ovsiienko """Packet burst container object""" 1019725191aSViacheslav Ovsiienko 1029725191aSViacheslav Ovsiienko def __init__(self): 1039725191aSViacheslav Ovsiienko self.wqes = [] # issued burst WQEs 1049725191aSViacheslav Ovsiienko self.done = 0 # number of sent/recv packets 1059725191aSViacheslav Ovsiienko self.req = 0 # requested number of packets 1069725191aSViacheslav Ovsiienko self.call_ts = 0 # burst routine invocation 1079725191aSViacheslav Ovsiienko self.done_ts = 0 # burst routine done 1089725191aSViacheslav Ovsiienko self.queue = None 1099725191aSViacheslav Ovsiienko 1109725191aSViacheslav Ovsiienko def log(self): 1119725191aSViacheslav Ovsiienko """Log burst""" 1129725191aSViacheslav Ovsiienko port = self.queue.pq_id >> 16 1139725191aSViacheslav Ovsiienko queue = self.queue.pq_id & 0xFFFF 1149725191aSViacheslav Ovsiienko if self.req == 0: 1159725191aSViacheslav Ovsiienko print( 1169725191aSViacheslav Ovsiienko "%u: tx(p=%u, q=%u, %u/%u pkts (incomplete)" 1179725191aSViacheslav Ovsiienko % (self.call_ts, port, queue, self.done, self.req) 1189725191aSViacheslav Ovsiienko ) 1199725191aSViacheslav Ovsiienko else: 1209725191aSViacheslav Ovsiienko print( 1219725191aSViacheslav Ovsiienko "%u: tx(p=%u, q=%u, %u/%u pkts in %u" 1229725191aSViacheslav Ovsiienko % ( 1239725191aSViacheslav Ovsiienko self.call_ts, 1249725191aSViacheslav Ovsiienko port, 1259725191aSViacheslav Ovsiienko queue, 1269725191aSViacheslav Ovsiienko self.done, 1279725191aSViacheslav Ovsiienko self.req, 1289725191aSViacheslav Ovsiienko self.done_ts - self.call_ts, 1299725191aSViacheslav Ovsiienko ) 1309725191aSViacheslav Ovsiienko ) 1319725191aSViacheslav Ovsiienko for wqe in self.wqes: 1329725191aSViacheslav Ovsiienko wqe.log() 1339725191aSViacheslav Ovsiienko 1349725191aSViacheslav Ovsiienko def comp(self, wqe_id, wqe_ts): 1359725191aSViacheslav Ovsiienko """Return 0 if not all of WQEs in burst completed""" 1369725191aSViacheslav Ovsiienko wlen = len(self.wqes) 1379725191aSViacheslav Ovsiienko if wlen == 0: 1389725191aSViacheslav Ovsiienko return 0 1399725191aSViacheslav Ovsiienko for wqe in self.wqes: 1409725191aSViacheslav Ovsiienko if wqe.comp(wqe_id, wqe_ts) == 0: 1419725191aSViacheslav Ovsiienko return 0 1429725191aSViacheslav Ovsiienko return 1 1439725191aSViacheslav Ovsiienko 1449725191aSViacheslav Ovsiienko 1459725191aSViacheslav Ovsiienkoclass MlxTrace: 1469725191aSViacheslav Ovsiienko """Trace representing object""" 1479725191aSViacheslav Ovsiienko 1489725191aSViacheslav Ovsiienko def __init__(self): 1499725191aSViacheslav Ovsiienko self.tx_blst = {} # current Tx bursts per CPU 1509725191aSViacheslav Ovsiienko self.tx_qlst = {} # active Tx queues per port/queue 1519725191aSViacheslav Ovsiienko self.tx_wlst = {} # wait timestamp list per CPU 1529725191aSViacheslav Ovsiienko 153*171360dfSViacheslav Ovsiienko def run(self, msg_it, verbose): 1549725191aSViacheslav Ovsiienko """Run over gathered tracing data and build database""" 1559725191aSViacheslav Ovsiienko for msg in msg_it: 1569725191aSViacheslav Ovsiienko if not isinstance(msg, bt2._EventMessageConst): 1579725191aSViacheslav Ovsiienko continue 1589725191aSViacheslav Ovsiienko event = msg.event 1599725191aSViacheslav Ovsiienko if event.name.startswith(PFX_TX): 160*171360dfSViacheslav Ovsiienko do_tx(msg, self, verbose) 1619725191aSViacheslav Ovsiienko # Handling of other log event cathegories can be added here 162*171360dfSViacheslav Ovsiienko if verbose: 163*171360dfSViacheslav Ovsiienko print("*** End of raw data dump ***") 1649725191aSViacheslav Ovsiienko 165*171360dfSViacheslav Ovsiienko def log(self, all): 1669725191aSViacheslav Ovsiienko """Log gathered trace database""" 1679725191aSViacheslav Ovsiienko for pq_id in self.tx_qlst: 1689725191aSViacheslav Ovsiienko queue = self.tx_qlst.get(pq_id) 169*171360dfSViacheslav Ovsiienko queue.log(all) 1709725191aSViacheslav Ovsiienko 1719725191aSViacheslav Ovsiienko 172*171360dfSViacheslav Ovsiienkodef do_tx_entry(msg, trace, verbose): 1739725191aSViacheslav Ovsiienko """Handle entry Tx busrt""" 1749725191aSViacheslav Ovsiienko event = msg.event 1759725191aSViacheslav Ovsiienko cpu_id = event["cpu_id"] 1769725191aSViacheslav Ovsiienko burst = trace.tx_blst.get(cpu_id) 1779725191aSViacheslav Ovsiienko if burst is not None: 1789725191aSViacheslav Ovsiienko # continue existing burst after WAIT 1799725191aSViacheslav Ovsiienko return 180*171360dfSViacheslav Ovsiienko if verbose > 0: 181*171360dfSViacheslav Ovsiienko print("%u:%X tx_entry(real_time=%u, port_id=%u, queue_id=%u)" % 182*171360dfSViacheslav Ovsiienko (msg.default_clock_snapshot.ns_from_origin, cpu_id, 183*171360dfSViacheslav Ovsiienko event["real_time"], event["port_id"], event["queue_id"])) 1849725191aSViacheslav Ovsiienko # allocate the new burst and append to the queue 1859725191aSViacheslav Ovsiienko burst = MlxBurst() 18602932480STim Martin burst.call_ts = event["real_time"] 18702932480STim Martin if burst.call_ts == 0: 1889725191aSViacheslav Ovsiienko burst.call_ts = msg.default_clock_snapshot.ns_from_origin 1899725191aSViacheslav Ovsiienko trace.tx_blst[cpu_id] = burst 1909725191aSViacheslav Ovsiienko pq_id = event["port_id"] << 16 | event["queue_id"] 1919725191aSViacheslav Ovsiienko queue = trace.tx_qlst.get(pq_id) 1929725191aSViacheslav Ovsiienko if queue is None: 1939725191aSViacheslav Ovsiienko # queue does not exist - allocate the new one 1949725191aSViacheslav Ovsiienko queue = MlxQueue() 1959725191aSViacheslav Ovsiienko queue.pq_id = pq_id 1969725191aSViacheslav Ovsiienko trace.tx_qlst[pq_id] = queue 1979725191aSViacheslav Ovsiienko burst.queue = queue 1989725191aSViacheslav Ovsiienko queue.wait_burst.append(burst) 1999725191aSViacheslav Ovsiienko 2009725191aSViacheslav Ovsiienko 201*171360dfSViacheslav Ovsiienkodef do_tx_exit(msg, trace, verbose): 2029725191aSViacheslav Ovsiienko """Handle exit Tx busrt""" 2039725191aSViacheslav Ovsiienko event = msg.event 2049725191aSViacheslav Ovsiienko cpu_id = event["cpu_id"] 205*171360dfSViacheslav Ovsiienko if verbose > 0: 206*171360dfSViacheslav Ovsiienko print("%u:%X tx_exit(real_time=%u, nb_sent=%u, nb_req=%u)" % 207*171360dfSViacheslav Ovsiienko (msg.default_clock_snapshot.ns_from_origin, cpu_id, 208*171360dfSViacheslav Ovsiienko event["real_time"], event["nb_sent"], event["nb_req"])) 2099725191aSViacheslav Ovsiienko burst = trace.tx_blst.get(cpu_id) 2109725191aSViacheslav Ovsiienko if burst is None: 2119725191aSViacheslav Ovsiienko return 21202932480STim Martin burst.done_ts = event["real_time"] 21302932480STim Martin if burst.done_ts == 0: 2149725191aSViacheslav Ovsiienko burst.done_ts = msg.default_clock_snapshot.ns_from_origin 2159725191aSViacheslav Ovsiienko burst.req = event["nb_req"] 2169725191aSViacheslav Ovsiienko burst.done = event["nb_sent"] 2179725191aSViacheslav Ovsiienko trace.tx_blst.pop(cpu_id) 2189725191aSViacheslav Ovsiienko 2199725191aSViacheslav Ovsiienko 220*171360dfSViacheslav Ovsiienkodef do_tx_wqe(msg, trace, verbose): 2219725191aSViacheslav Ovsiienko """Handle WQE record""" 2229725191aSViacheslav Ovsiienko event = msg.event 2239725191aSViacheslav Ovsiienko cpu_id = event["cpu_id"] 224*171360dfSViacheslav Ovsiienko if verbose > 1: 225*171360dfSViacheslav Ovsiienko print("%u:%X tx_wqe(real_time=%u, opcode=%08X)" % 226*171360dfSViacheslav Ovsiienko (msg.default_clock_snapshot.ns_from_origin, cpu_id, 227*171360dfSViacheslav Ovsiienko event["real_time"], event["opcode"])) 2289725191aSViacheslav Ovsiienko burst = trace.tx_blst.get(cpu_id) 2299725191aSViacheslav Ovsiienko if burst is None: 2309725191aSViacheslav Ovsiienko return 2319725191aSViacheslav Ovsiienko wqe = MlxWqe() 2329725191aSViacheslav Ovsiienko wqe.wait_ts = trace.tx_wlst.get(cpu_id) 2339725191aSViacheslav Ovsiienko if wqe.wait_ts is None: 23402932480STim Martin wqe.wait_ts = event["real_time"] 23502932480STim Martin if wqe.wait_ts == 0: 2369725191aSViacheslav Ovsiienko wqe.wait_ts = msg.default_clock_snapshot.ns_from_origin 2379725191aSViacheslav Ovsiienko wqe.opcode = event["opcode"] 2389725191aSViacheslav Ovsiienko burst.wqes.append(wqe) 2399725191aSViacheslav Ovsiienko 2409725191aSViacheslav Ovsiienko 241*171360dfSViacheslav Ovsiienkodef do_tx_wait(msg, trace, verbose): 2429725191aSViacheslav Ovsiienko """Handle WAIT record""" 2439725191aSViacheslav Ovsiienko event = msg.event 2449725191aSViacheslav Ovsiienko cpu_id = event["cpu_id"] 245*171360dfSViacheslav Ovsiienko if verbose > 1: 246*171360dfSViacheslav Ovsiienko print("%u:%X tx_wait(ts=%u)" % 247*171360dfSViacheslav Ovsiienko (msg.default_clock_snapshot.ns_from_origin, cpu_id, event["ts"])) 2489725191aSViacheslav Ovsiienko trace.tx_wlst[cpu_id] = event["ts"] 2499725191aSViacheslav Ovsiienko 2509725191aSViacheslav Ovsiienko 251*171360dfSViacheslav Ovsiienkodef do_tx_push(msg, trace, verbose): 2529725191aSViacheslav Ovsiienko """Handle WQE push event""" 2539725191aSViacheslav Ovsiienko event = msg.event 2549725191aSViacheslav Ovsiienko cpu_id = event["cpu_id"] 255*171360dfSViacheslav Ovsiienko if verbose > 2: 256*171360dfSViacheslav Ovsiienko print("%u:%X tx_push(mbuf=%X, pkt_len=%u, nb_segs=%u, wqe_id=%04X)" % 257*171360dfSViacheslav Ovsiienko (msg.default_clock_snapshot.ns_from_origin, cpu_id, event["mbuf"], 258*171360dfSViacheslav Ovsiienko event["mbuf_pkt_len"], event["mbuf_nb_segs"], event["wqe_id"])) 2599725191aSViacheslav Ovsiienko burst = trace.tx_blst.get(cpu_id) 2609725191aSViacheslav Ovsiienko if burst is None: 2619725191aSViacheslav Ovsiienko return 2629725191aSViacheslav Ovsiienko if not burst.wqes: 2639725191aSViacheslav Ovsiienko return 2649725191aSViacheslav Ovsiienko wqe = burst.wqes[-1] 2659725191aSViacheslav Ovsiienko mbuf = MlxMbuf() 2669725191aSViacheslav Ovsiienko mbuf.wqe = event["wqe_id"] 2679725191aSViacheslav Ovsiienko mbuf.ptr = event["mbuf"] 2689725191aSViacheslav Ovsiienko mbuf.len = event["mbuf_pkt_len"] 2699725191aSViacheslav Ovsiienko mbuf.nseg = event["mbuf_nb_segs"] 2709725191aSViacheslav Ovsiienko wqe.mbuf.append(mbuf) 2719725191aSViacheslav Ovsiienko 2729725191aSViacheslav Ovsiienko 273*171360dfSViacheslav Ovsiienkodef do_tx_complete(msg, trace, verbose): 2749725191aSViacheslav Ovsiienko """Handle send completion event""" 2759725191aSViacheslav Ovsiienko event = msg.event 2769725191aSViacheslav Ovsiienko pq_id = event["port_id"] << 16 | event["queue_id"] 277*171360dfSViacheslav Ovsiienko if verbose > 1: 278*171360dfSViacheslav Ovsiienko cpu_id = event["cpu_id"] 279*171360dfSViacheslav Ovsiienko print("%u:%X tx_complete(port_id=%u, queue_id=%u, ts=%u, wqe_id=%04X)" % 280*171360dfSViacheslav Ovsiienko (msg.default_clock_snapshot.ns_from_origin, cpu_id, 281*171360dfSViacheslav Ovsiienko event["port_id"], event["queue_id"], event["ts"], event["wqe_id"])) 2829725191aSViacheslav Ovsiienko queue = trace.tx_qlst.get(pq_id) 2839725191aSViacheslav Ovsiienko if queue is None: 2849725191aSViacheslav Ovsiienko return 2859725191aSViacheslav Ovsiienko qlen = len(queue.wait_burst) 2869725191aSViacheslav Ovsiienko if qlen == 0: 2879725191aSViacheslav Ovsiienko return 2889725191aSViacheslav Ovsiienko wqe_id = event["wqe_id"] 2899725191aSViacheslav Ovsiienko wqe_ts = event["ts"] 2909725191aSViacheslav Ovsiienko rmv = 0 2919725191aSViacheslav Ovsiienko while rmv < qlen: 2929725191aSViacheslav Ovsiienko burst = queue.wait_burst[rmv] 2939725191aSViacheslav Ovsiienko if burst.comp(wqe_id, wqe_ts) == 0: 2949725191aSViacheslav Ovsiienko break 2959725191aSViacheslav Ovsiienko rmv += 1 296d6721527SViacheslav Ovsiienko # move completed burst(s) to done list 2979725191aSViacheslav Ovsiienko if rmv != 0: 2989725191aSViacheslav Ovsiienko idx = 0 2999725191aSViacheslav Ovsiienko while idx < rmv: 300d6721527SViacheslav Ovsiienko burst = queue.wait_burst[idx] 3019725191aSViacheslav Ovsiienko queue.done_burst.append(burst) 3029725191aSViacheslav Ovsiienko idx += 1 303d6721527SViacheslav Ovsiienko queue.wait_burst = queue.wait_burst[rmv:] 3049725191aSViacheslav Ovsiienko 3059725191aSViacheslav Ovsiienko 306*171360dfSViacheslav Ovsiienkodef do_tx(msg, trace, verbose): 3079725191aSViacheslav Ovsiienko """Handle Tx related records""" 3089725191aSViacheslav Ovsiienko name = msg.event.name[PFX_TX_LEN:] 3099725191aSViacheslav Ovsiienko if name == "entry": 310*171360dfSViacheslav Ovsiienko do_tx_entry(msg, trace, verbose) 3119725191aSViacheslav Ovsiienko elif name == "exit": 312*171360dfSViacheslav Ovsiienko do_tx_exit(msg, trace, verbose) 3139725191aSViacheslav Ovsiienko elif name == "wqe": 314*171360dfSViacheslav Ovsiienko do_tx_wqe(msg, trace, verbose) 3159725191aSViacheslav Ovsiienko elif name == "wait": 316*171360dfSViacheslav Ovsiienko do_tx_wait(msg, trace, verbose) 3179725191aSViacheslav Ovsiienko elif name == "push": 318*171360dfSViacheslav Ovsiienko do_tx_push(msg, trace, verbose) 3199725191aSViacheslav Ovsiienko elif name == "complete": 320*171360dfSViacheslav Ovsiienko do_tx_complete(msg, trace, verbose) 3219725191aSViacheslav Ovsiienko else: 3229725191aSViacheslav Ovsiienko print("Error: unrecognized Tx event name: %s" % msg.event.name, file=sys.stderr) 3239725191aSViacheslav Ovsiienko raise ValueError() 3249725191aSViacheslav Ovsiienko 3259725191aSViacheslav Ovsiienko 3269725191aSViacheslav Ovsiienkodef main() -> int: 3279725191aSViacheslav Ovsiienko """Script entry point""" 3289725191aSViacheslav Ovsiienko try: 3299725191aSViacheslav Ovsiienko parser = argparse.ArgumentParser() 3309725191aSViacheslav Ovsiienko parser.add_argument("path", nargs=1, type=str, help="input trace folder") 331*171360dfSViacheslav Ovsiienko parser.add_argument("-a", "--all", nargs="?", default=False, const=True, 332*171360dfSViacheslav Ovsiienko help="show all the bursts, including incomplete ones") 333*171360dfSViacheslav Ovsiienko parser.add_argument("-v", "--verbose", type=int, nargs="?", default=0, const=2, 334*171360dfSViacheslav Ovsiienko help="show all the records below specified level") 3359725191aSViacheslav Ovsiienko args = parser.parse_args() 3369725191aSViacheslav Ovsiienko 3379725191aSViacheslav Ovsiienko mlx_tr = MlxTrace() 3389725191aSViacheslav Ovsiienko msg_it = bt2.TraceCollectionMessageIterator(args.path) 339*171360dfSViacheslav Ovsiienko mlx_tr.run(msg_it, args.verbose) 340*171360dfSViacheslav Ovsiienko mlx_tr.log(args.all) 3419725191aSViacheslav Ovsiienko return 0 3429725191aSViacheslav Ovsiienko except ValueError: 3439725191aSViacheslav Ovsiienko return -1 3449725191aSViacheslav Ovsiienko 3459725191aSViacheslav Ovsiienko 3469725191aSViacheslav Ovsiienkoif __name__ == "__main__": 3479725191aSViacheslav Ovsiienko sys.exit(main()) 348