Path: blob/master/tools/perf/scripts/python/netdev-times.py
10823 views
# Display a process of packets and processed time.1# It helps us to investigate networking or network device.2#3# options4# tx: show only tx chart5# rx: show only rx chart6# dev=: show only thing related to specified device7# debug: work with debug mode. It shows buffer status.89import os10import sys1112sys.path.append(os.environ['PERF_EXEC_PATH'] + \13'/scripts/python/Perf-Trace-Util/lib/Perf/Trace')1415from perf_trace_context import *16from Core import *17from Util import *1819all_event_list = []; # insert all tracepoint event related with this script20irq_dic = {}; # key is cpu and value is a list which stacks irqs21# which raise NET_RX softirq22net_rx_dic = {}; # key is cpu and value include time of NET_RX softirq-entry23# and a list which stacks receive24receive_hunk_list = []; # a list which include a sequence of receive events25rx_skb_list = []; # received packet list for matching26# skb_copy_datagram_iovec2728buffer_budget = 65536; # the budget of rx_skb_list, tx_queue_list and29# tx_xmit_list30of_count_rx_skb_list = 0; # overflow count3132tx_queue_list = []; # list of packets which pass through dev_queue_xmit33of_count_tx_queue_list = 0; # overflow count3435tx_xmit_list = []; # list of packets which pass through dev_hard_start_xmit36of_count_tx_xmit_list = 0; # overflow count3738tx_free_list = []; # list of packets which is freed3940# options41show_tx = 0;42show_rx = 0;43dev = 0; # store a name of device specified by option "dev="44debug = 0;4546# indices of event_info tuple47EINFO_IDX_NAME= 048EINFO_IDX_CONTEXT=149EINFO_IDX_CPU= 250EINFO_IDX_TIME= 351EINFO_IDX_PID= 452EINFO_IDX_COMM= 55354# Calculate a time interval(msec) from src(nsec) to dst(nsec)55def diff_msec(src, dst):56return (dst - src) / 1000000.05758# Display a process of transmitting a packet59def print_transmit(hunk):60if dev != 0 and hunk['dev'].find(dev) < 0:61return62print "%7s %5d %6d.%06dsec %12.3fmsec %12.3fmsec" % \63(hunk['dev'], hunk['len'],64nsecs_secs(hunk['queue_t']),65nsecs_nsecs(hunk['queue_t'])/1000,66diff_msec(hunk['queue_t'], hunk['xmit_t']),67diff_msec(hunk['xmit_t'], hunk['free_t']))6869# Format for displaying rx packet processing70PF_IRQ_ENTRY= " irq_entry(+%.3fmsec irq=%d:%s)"71PF_SOFT_ENTRY=" softirq_entry(+%.3fmsec)"72PF_NAPI_POLL= " napi_poll_exit(+%.3fmsec %s)"73PF_JOINT= " |"74PF_WJOINT= " | |"75PF_NET_RECV= " |---netif_receive_skb(+%.3fmsec skb=%x len=%d)"76PF_NET_RX= " |---netif_rx(+%.3fmsec skb=%x)"77PF_CPY_DGRAM= " | skb_copy_datagram_iovec(+%.3fmsec %d:%s)"78PF_KFREE_SKB= " | kfree_skb(+%.3fmsec location=%x)"79PF_CONS_SKB= " | consume_skb(+%.3fmsec)"8081# Display a process of received packets and interrputs associated with82# a NET_RX softirq83def print_receive(hunk):84show_hunk = 085irq_list = hunk['irq_list']86cpu = irq_list[0]['cpu']87base_t = irq_list[0]['irq_ent_t']88# check if this hunk should be showed89if dev != 0:90for i in range(len(irq_list)):91if irq_list[i]['name'].find(dev) >= 0:92show_hunk = 193break94else:95show_hunk = 196if show_hunk == 0:97return9899print "%d.%06dsec cpu=%d" % \100(nsecs_secs(base_t), nsecs_nsecs(base_t)/1000, cpu)101for i in range(len(irq_list)):102print PF_IRQ_ENTRY % \103(diff_msec(base_t, irq_list[i]['irq_ent_t']),104irq_list[i]['irq'], irq_list[i]['name'])105print PF_JOINT106irq_event_list = irq_list[i]['event_list']107for j in range(len(irq_event_list)):108irq_event = irq_event_list[j]109if irq_event['event'] == 'netif_rx':110print PF_NET_RX % \111(diff_msec(base_t, irq_event['time']),112irq_event['skbaddr'])113print PF_JOINT114print PF_SOFT_ENTRY % \115diff_msec(base_t, hunk['sirq_ent_t'])116print PF_JOINT117event_list = hunk['event_list']118for i in range(len(event_list)):119event = event_list[i]120if event['event_name'] == 'napi_poll':121print PF_NAPI_POLL % \122(diff_msec(base_t, event['event_t']), event['dev'])123if i == len(event_list) - 1:124print ""125else:126print PF_JOINT127else:128print PF_NET_RECV % \129(diff_msec(base_t, event['event_t']), event['skbaddr'],130event['len'])131if 'comm' in event.keys():132print PF_WJOINT133print PF_CPY_DGRAM % \134(diff_msec(base_t, event['comm_t']),135event['pid'], event['comm'])136elif 'handle' in event.keys():137print PF_WJOINT138if event['handle'] == "kfree_skb":139print PF_KFREE_SKB % \140(diff_msec(base_t,141event['comm_t']),142event['location'])143elif event['handle'] == "consume_skb":144print PF_CONS_SKB % \145diff_msec(base_t,146event['comm_t'])147print PF_JOINT148149def trace_begin():150global show_tx151global show_rx152global dev153global debug154155for i in range(len(sys.argv)):156if i == 0:157continue158arg = sys.argv[i]159if arg == 'tx':160show_tx = 1161elif arg =='rx':162show_rx = 1163elif arg.find('dev=',0, 4) >= 0:164dev = arg[4:]165elif arg == 'debug':166debug = 1167if show_tx == 0 and show_rx == 0:168show_tx = 1169show_rx = 1170171def trace_end():172# order all events in time173all_event_list.sort(lambda a,b :cmp(a[EINFO_IDX_TIME],174b[EINFO_IDX_TIME]))175# process all events176for i in range(len(all_event_list)):177event_info = all_event_list[i]178name = event_info[EINFO_IDX_NAME]179if name == 'irq__softirq_exit':180handle_irq_softirq_exit(event_info)181elif name == 'irq__softirq_entry':182handle_irq_softirq_entry(event_info)183elif name == 'irq__softirq_raise':184handle_irq_softirq_raise(event_info)185elif name == 'irq__irq_handler_entry':186handle_irq_handler_entry(event_info)187elif name == 'irq__irq_handler_exit':188handle_irq_handler_exit(event_info)189elif name == 'napi__napi_poll':190handle_napi_poll(event_info)191elif name == 'net__netif_receive_skb':192handle_netif_receive_skb(event_info)193elif name == 'net__netif_rx':194handle_netif_rx(event_info)195elif name == 'skb__skb_copy_datagram_iovec':196handle_skb_copy_datagram_iovec(event_info)197elif name == 'net__net_dev_queue':198handle_net_dev_queue(event_info)199elif name == 'net__net_dev_xmit':200handle_net_dev_xmit(event_info)201elif name == 'skb__kfree_skb':202handle_kfree_skb(event_info)203elif name == 'skb__consume_skb':204handle_consume_skb(event_info)205# display receive hunks206if show_rx:207for i in range(len(receive_hunk_list)):208print_receive(receive_hunk_list[i])209# display transmit hunks210if show_tx:211print " dev len Qdisc " \212" netdevice free"213for i in range(len(tx_free_list)):214print_transmit(tx_free_list[i])215if debug:216print "debug buffer status"217print "----------------------------"218print "xmit Qdisc:remain:%d overflow:%d" % \219(len(tx_queue_list), of_count_tx_queue_list)220print "xmit netdevice:remain:%d overflow:%d" % \221(len(tx_xmit_list), of_count_tx_xmit_list)222print "receive:remain:%d overflow:%d" % \223(len(rx_skb_list), of_count_rx_skb_list)224225# called from perf, when it finds a correspoinding event226def irq__softirq_entry(name, context, cpu, sec, nsec, pid, comm, vec):227if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX":228return229event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec)230all_event_list.append(event_info)231232def irq__softirq_exit(name, context, cpu, sec, nsec, pid, comm, vec):233if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX":234return235event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec)236all_event_list.append(event_info)237238def irq__softirq_raise(name, context, cpu, sec, nsec, pid, comm, vec):239if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX":240return241event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec)242all_event_list.append(event_info)243244def irq__irq_handler_entry(name, context, cpu, sec, nsec, pid, comm,245irq, irq_name):246event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,247irq, irq_name)248all_event_list.append(event_info)249250def irq__irq_handler_exit(name, context, cpu, sec, nsec, pid, comm, irq, ret):251event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, irq, ret)252all_event_list.append(event_info)253254def napi__napi_poll(name, context, cpu, sec, nsec, pid, comm, napi, dev_name):255event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,256napi, dev_name)257all_event_list.append(event_info)258259def net__netif_receive_skb(name, context, cpu, sec, nsec, pid, comm, skbaddr,260skblen, dev_name):261event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,262skbaddr, skblen, dev_name)263all_event_list.append(event_info)264265def net__netif_rx(name, context, cpu, sec, nsec, pid, comm, skbaddr,266skblen, dev_name):267event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,268skbaddr, skblen, dev_name)269all_event_list.append(event_info)270271def net__net_dev_queue(name, context, cpu, sec, nsec, pid, comm,272skbaddr, skblen, dev_name):273event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,274skbaddr, skblen, dev_name)275all_event_list.append(event_info)276277def net__net_dev_xmit(name, context, cpu, sec, nsec, pid, comm,278skbaddr, skblen, rc, dev_name):279event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,280skbaddr, skblen, rc ,dev_name)281all_event_list.append(event_info)282283def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm,284skbaddr, protocol, location):285event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,286skbaddr, protocol, location)287all_event_list.append(event_info)288289def skb__consume_skb(name, context, cpu, sec, nsec, pid, comm, skbaddr):290event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,291skbaddr)292all_event_list.append(event_info)293294def skb__skb_copy_datagram_iovec(name, context, cpu, sec, nsec, pid, comm,295skbaddr, skblen):296event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,297skbaddr, skblen)298all_event_list.append(event_info)299300def handle_irq_handler_entry(event_info):301(name, context, cpu, time, pid, comm, irq, irq_name) = event_info302if cpu not in irq_dic.keys():303irq_dic[cpu] = []304irq_record = {'irq':irq, 'name':irq_name, 'cpu':cpu, 'irq_ent_t':time}305irq_dic[cpu].append(irq_record)306307def handle_irq_handler_exit(event_info):308(name, context, cpu, time, pid, comm, irq, ret) = event_info309if cpu not in irq_dic.keys():310return311irq_record = irq_dic[cpu].pop()312if irq != irq_record['irq']:313return314irq_record.update({'irq_ext_t':time})315# if an irq doesn't include NET_RX softirq, drop.316if 'event_list' in irq_record.keys():317irq_dic[cpu].append(irq_record)318319def handle_irq_softirq_raise(event_info):320(name, context, cpu, time, pid, comm, vec) = event_info321if cpu not in irq_dic.keys() \322or len(irq_dic[cpu]) == 0:323return324irq_record = irq_dic[cpu].pop()325if 'event_list' in irq_record.keys():326irq_event_list = irq_record['event_list']327else:328irq_event_list = []329irq_event_list.append({'time':time, 'event':'sirq_raise'})330irq_record.update({'event_list':irq_event_list})331irq_dic[cpu].append(irq_record)332333def handle_irq_softirq_entry(event_info):334(name, context, cpu, time, pid, comm, vec) = event_info335net_rx_dic[cpu] = {'sirq_ent_t':time, 'event_list':[]}336337def handle_irq_softirq_exit(event_info):338(name, context, cpu, time, pid, comm, vec) = event_info339irq_list = []340event_list = 0341if cpu in irq_dic.keys():342irq_list = irq_dic[cpu]343del irq_dic[cpu]344if cpu in net_rx_dic.keys():345sirq_ent_t = net_rx_dic[cpu]['sirq_ent_t']346event_list = net_rx_dic[cpu]['event_list']347del net_rx_dic[cpu]348if irq_list == [] or event_list == 0:349return350rec_data = {'sirq_ent_t':sirq_ent_t, 'sirq_ext_t':time,351'irq_list':irq_list, 'event_list':event_list}352# merge information realted to a NET_RX softirq353receive_hunk_list.append(rec_data)354355def handle_napi_poll(event_info):356(name, context, cpu, time, pid, comm, napi, dev_name) = event_info357if cpu in net_rx_dic.keys():358event_list = net_rx_dic[cpu]['event_list']359rec_data = {'event_name':'napi_poll',360'dev':dev_name, 'event_t':time}361event_list.append(rec_data)362363def handle_netif_rx(event_info):364(name, context, cpu, time, pid, comm,365skbaddr, skblen, dev_name) = event_info366if cpu not in irq_dic.keys() \367or len(irq_dic[cpu]) == 0:368return369irq_record = irq_dic[cpu].pop()370if 'event_list' in irq_record.keys():371irq_event_list = irq_record['event_list']372else:373irq_event_list = []374irq_event_list.append({'time':time, 'event':'netif_rx',375'skbaddr':skbaddr, 'skblen':skblen, 'dev_name':dev_name})376irq_record.update({'event_list':irq_event_list})377irq_dic[cpu].append(irq_record)378379def handle_netif_receive_skb(event_info):380global of_count_rx_skb_list381382(name, context, cpu, time, pid, comm,383skbaddr, skblen, dev_name) = event_info384if cpu in net_rx_dic.keys():385rec_data = {'event_name':'netif_receive_skb',386'event_t':time, 'skbaddr':skbaddr, 'len':skblen}387event_list = net_rx_dic[cpu]['event_list']388event_list.append(rec_data)389rx_skb_list.insert(0, rec_data)390if len(rx_skb_list) > buffer_budget:391rx_skb_list.pop()392of_count_rx_skb_list += 1393394def handle_net_dev_queue(event_info):395global of_count_tx_queue_list396397(name, context, cpu, time, pid, comm,398skbaddr, skblen, dev_name) = event_info399skb = {'dev':dev_name, 'skbaddr':skbaddr, 'len':skblen, 'queue_t':time}400tx_queue_list.insert(0, skb)401if len(tx_queue_list) > buffer_budget:402tx_queue_list.pop()403of_count_tx_queue_list += 1404405def handle_net_dev_xmit(event_info):406global of_count_tx_xmit_list407408(name, context, cpu, time, pid, comm,409skbaddr, skblen, rc, dev_name) = event_info410if rc == 0: # NETDEV_TX_OK411for i in range(len(tx_queue_list)):412skb = tx_queue_list[i]413if skb['skbaddr'] == skbaddr:414skb['xmit_t'] = time415tx_xmit_list.insert(0, skb)416del tx_queue_list[i]417if len(tx_xmit_list) > buffer_budget:418tx_xmit_list.pop()419of_count_tx_xmit_list += 1420return421422def handle_kfree_skb(event_info):423(name, context, cpu, time, pid, comm,424skbaddr, protocol, location) = event_info425for i in range(len(tx_queue_list)):426skb = tx_queue_list[i]427if skb['skbaddr'] == skbaddr:428del tx_queue_list[i]429return430for i in range(len(tx_xmit_list)):431skb = tx_xmit_list[i]432if skb['skbaddr'] == skbaddr:433skb['free_t'] = time434tx_free_list.append(skb)435del tx_xmit_list[i]436return437for i in range(len(rx_skb_list)):438rec_data = rx_skb_list[i]439if rec_data['skbaddr'] == skbaddr:440rec_data.update({'handle':"kfree_skb",441'comm':comm, 'pid':pid, 'comm_t':time})442del rx_skb_list[i]443return444445def handle_consume_skb(event_info):446(name, context, cpu, time, pid, comm, skbaddr) = event_info447for i in range(len(tx_xmit_list)):448skb = tx_xmit_list[i]449if skb['skbaddr'] == skbaddr:450skb['free_t'] = time451tx_free_list.append(skb)452del tx_xmit_list[i]453return454455def handle_skb_copy_datagram_iovec(event_info):456(name, context, cpu, time, pid, comm, skbaddr, skblen) = event_info457for i in range(len(rx_skb_list)):458rec_data = rx_skb_list[i]459if skbaddr == rec_data['skbaddr']:460rec_data.update({'handle':"skb_copy_datagram_iovec",461'comm':comm, 'pid':pid, 'comm_t':time})462del rx_skb_list[i]463return464465466