* [RFC PATCH 0/5] netdev: show a process of packets
@ 2010-06-08 5:25 Koki Sanagi
2010-06-08 5:27 ` [RFC PATCH 1/5] irq: add tracepoint to softirq_raise Koki Sanagi
` (4 more replies)
0 siblings, 5 replies; 6+ messages in thread
From: Koki Sanagi @ 2010-06-08 5:25 UTC (permalink / raw)
To: netdev; +Cc: davem, kaneshige.kenji, izumi.taku
These patch-set adds tracepoints to show us a process of packets.
Using these tracepoints and existing points, we can get the time when
packet passes through some points in transmit or receive sequence.
For example, this is an output of perf script which is attached by patch 5/5.
79074.756672832sec cpu=1
irq_entry(+0.000000msec,irq=77:eth3)
|------------softirq_raise(+0.001277msec)
irq_exit (+0.002278msec) |
|
softirq_entry(+0.003562msec)
|
|---netif_receive_skb(+0.006279msec,len=100)
| |
| skb_copy_datagram_iovec(+0.038778msec, 2285:sshd)
|
napi_poll_exit(+0.017160msec, eth3)
|
softirq_exit(+0.018248msec)
The above is a receive side. Like this, it can show receive sequence from
interrupt(irq_entry) to application(skb_copy_datagram_iovec). There are 8
tracepoints in this side. All events except for skb_copy_datagram_iovec can be
associated with each other by CPU number. skb_copy_datagram_iovec can be
associated with netif_receive_skb by skbaddr.
This script shows one NET_RX softirq and events related to it. All relative
time bases on first irq_entry which raise NET_RX softirq.
dev len dev_queue_xmit|----------|dev_hard_start_xmit|-----|free_skb
| | |
eth3 114 79044.417123332sec 0.005242msec 0.103843msec
eth3 114 79044.580090422sec 0.002306msec 0.103632msec
eth3 114 79044.719078251sec 0.002288msec 0.104093msec
The above is a transmit side. There are three tracepoints in this side.
Point1 is before putting a packet to Qdisc. point2 is after ndo_start_xmit in
dev_hard_start_xmit. It indicates finishing putting a packet to driver.
point3 is in consume_skb and dev_kfree_skb_irq. It indicates freeing a
transmitted packet.
Values of this script are, from left, device name, length of a packet, a time of
point1, an interval time between point1 and point2 and an interval time between
point2 and point3.
These times are useful to analyze a performance or to detect a point where
packet delays. For example,
- NET_RX softirq calling is late.
- Application is late to take a packet.
- It takes much time to put a transmitting packet to driver
(It may be caused by packed queue)
And also, these tracepoint help us to investigate a network driver's trouble
from memory dump because ftrace records it to memory. And ftrace is so light
even if always trace on. So, in a case investigating a problem which doesn't
reproduce, it is useful.
Thanks,
Koki Sanagi.
^ permalink raw reply [flat|nested] 6+ messages in thread
* [RFC PATCH 1/5] irq: add tracepoint to softirq_raise
2010-06-08 5:25 [RFC PATCH 0/5] netdev: show a process of packets Koki Sanagi
@ 2010-06-08 5:27 ` Koki Sanagi
2010-06-08 5:28 ` [RFC PATCH 2/5] napi: convert trace_napi_poll to TRACE_EVENT Koki Sanagi
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Koki Sanagi @ 2010-06-08 5:27 UTC (permalink / raw)
To: netdev; +Cc: davem, kaneshige.kenji, izumi.taku, laijs
This patch adds tracepoint to softirq_raise.
This is a same patch Lai Jiangshan submitted.
http://marc.info/?l=linux-kernel&m=126026122728732&w=2
Signed-off-by: Koki Sanagi <sanagi.koki@jp.fujitsu.com>
---
include/linux/interrupt.h | 8 +++++++-
include/trace/events/irq.h | 34 +++++++++++++++++++++++++++++++---
2 files changed, 38 insertions(+), 4 deletions(-)
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index c233113..1cb5726 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -18,6 +18,7 @@
#include <asm/atomic.h>
#include <asm/ptrace.h>
#include <asm/system.h>
+#include <trace/events/irq.h>
/*
* These correspond to the IORESOURCE_IRQ_* defines in
@@ -402,7 +403,12 @@ asmlinkage void do_softirq(void);
asmlinkage void __do_softirq(void);
extern void open_softirq(int nr, void (*action)(struct softirq_action *));
extern void softirq_init(void);
-#define __raise_softirq_irqoff(nr) do { or_softirq_pending(1UL << (nr)); } while (0)
+static inline void __raise_softirq_irqoff(unsigned int nr)
+{
+ trace_softirq_raise(nr);
+ or_softirq_pending(1UL << nr);
+}
+
extern void raise_softirq_irqoff(unsigned int nr);
extern void raise_softirq(unsigned int nr);
extern void wakeup_softirqd(void);
diff --git a/include/trace/events/irq.h b/include/trace/events/irq.h
index 0e4cfb6..7cb7435 100644
--- a/include/trace/events/irq.h
+++ b/include/trace/events/irq.h
@@ -5,7 +5,9 @@
#define _TRACE_IRQ_H
#include <linux/tracepoint.h>
-#include <linux/interrupt.h>
+
+struct irqaction;
+struct softirq_action;
#define softirq_name(sirq) { sirq##_SOFTIRQ, #sirq }
#define show_softirq_name(val) \
@@ -82,6 +84,32 @@ TRACE_EVENT(irq_handler_exit,
__entry->irq, __entry->ret ? "handled" : "unhandled")
);
+/**
+ * softirq_raise - called immediately when a softirq is raised
+ * @nr: softirq vector number
+ *
+ * Tracepoint for tracing when softirq action is raised.
+ * Also, when used in combination with the softirq_entry tracepoint
+ * we can determine the softirq raise latency.
+ */
+TRACE_EVENT(softirq_raise,
+
+ TP_PROTO(unsigned int nr),
+
+ TP_ARGS(nr),
+
+ TP_STRUCT__entry(
+ __field( unsigned int, vec )
+ ),
+
+ TP_fast_assign(
+ __entry->vec = nr;
+ ),
+
+ TP_printk("vec=%d [action=%s]", __entry->vec,
+ show_softirq_name(__entry->vec))
+);
+
DECLARE_EVENT_CLASS(softirq,
TP_PROTO(struct softirq_action *h, struct softirq_action *vec),
@@ -89,11 +117,11 @@ DECLARE_EVENT_CLASS(softirq,
TP_ARGS(h, vec),
TP_STRUCT__entry(
- __field( int, vec )
+ __field( unsigned int, vec )
),
TP_fast_assign(
- __entry->vec = (int)(h - vec);
+ __entry->vec = (unsigned int)(h - vec);
),
TP_printk("vec=%d [action=%s]", __entry->vec,
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [RFC PATCH 2/5] napi: convert trace_napi_poll to TRACE_EVENT
2010-06-08 5:25 [RFC PATCH 0/5] netdev: show a process of packets Koki Sanagi
2010-06-08 5:27 ` [RFC PATCH 1/5] irq: add tracepoint to softirq_raise Koki Sanagi
@ 2010-06-08 5:28 ` Koki Sanagi
2010-06-08 5:30 ` [RFC PATCH 3/5] netdev: add tracepoints to netdev layer Koki Sanagi
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Koki Sanagi @ 2010-06-08 5:28 UTC (permalink / raw)
To: netdev; +Cc: davem, kaneshige.kenji, izumi.taku, nhorman
This patch converts trace_napi_poll from DECLARE_EVENT to TRACE_EVENT.
This is a same patch Neil Horman submitted.
http://marc.info/?l=linux-kernel&m=125978157926853&w=2
Signed-off-by: Koki Sanagi <sanagi.koki@jp.fujitsu.com>
---
include/trace/events/napi.h | 23 +++++++++++++++++++++--
1 files changed, 21 insertions(+), 2 deletions(-)
diff --git a/include/trace/events/napi.h b/include/trace/events/napi.h
index 188deca..512a057 100644
--- a/include/trace/events/napi.h
+++ b/include/trace/events/napi.h
@@ -6,10 +6,29 @@
#include <linux/netdevice.h>
#include <linux/tracepoint.h>
+#include <linux/ftrace.h>
+
+#define NO_DEV "(no_device)"
+
+TRACE_EVENT(napi_poll,
-DECLARE_TRACE(napi_poll,
TP_PROTO(struct napi_struct *napi),
- TP_ARGS(napi));
+
+ TP_ARGS(napi),
+
+ TP_STRUCT__entry(
+ __field( struct napi_struct *, napi)
+ __string( dev_name, napi->dev ? napi->dev->name : NO_DEV)
+ ),
+
+ TP_fast_assign(
+ __entry->napi = napi;
+ __assign_str(dev_name, napi->dev ? napi->dev->name : NO_DEV);
+ ),
+
+ TP_printk("napi poll on napi struct %p for device %s",
+ __entry->napi, __get_str(dev_name))
+);
#endif /* _TRACE_NAPI_H_ */
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [RFC PATCH 3/5] netdev: add tracepoints to netdev layer
2010-06-08 5:25 [RFC PATCH 0/5] netdev: show a process of packets Koki Sanagi
2010-06-08 5:27 ` [RFC PATCH 1/5] irq: add tracepoint to softirq_raise Koki Sanagi
2010-06-08 5:28 ` [RFC PATCH 2/5] napi: convert trace_napi_poll to TRACE_EVENT Koki Sanagi
@ 2010-06-08 5:30 ` Koki Sanagi
2010-06-08 5:30 ` [RFC PATCH 4/5] skb: add tracepoints to freeing skb Koki Sanagi
2010-06-08 5:31 ` [RFC PATCH 5/5] perf:add a script shows a process of packet Koki Sanagi
4 siblings, 0 replies; 6+ messages in thread
From: Koki Sanagi @ 2010-06-08 5:30 UTC (permalink / raw)
To: netdev; +Cc: davem, kaneshige.kenji, izumi.taku
This patch adds tracepoint to dev_queue_xmit, dev_hard_start_xmit and
netif_receive_skb.
Signed-off-by: Koki Sanagi <sanagi.koki@jp.fujitsu.com>
---
include/trace/events/net.h | 84 ++++++++++++++++++++++++++++++++++++++++++++
net/core/dev.c | 5 +++
net/core/net-traces.c | 1 +
3 files changed, 90 insertions(+), 0 deletions(-)
diff --git a/include/trace/events/net.h b/include/trace/events/net.h
new file mode 100644
index 0000000..4f82fb5
--- /dev/null
+++ b/include/trace/events/net.h
@@ -0,0 +1,84 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM net
+
+#if !defined(_TRACE_NET_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_NET_H
+
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/tracepoint.h>
+
+#define NO_DEV "(no_device)"
+
+TRACE_EVENT(net_dev_xmit,
+
+ TP_PROTO(struct sk_buff *skb,
+ int rc),
+
+ TP_ARGS(skb, rc),
+
+ TP_STRUCT__entry(
+ __field( void *, skbaddr )
+ __field( unsigned int, len )
+ __field( int, rc )
+ __string( name, skb->dev->name )
+ ),
+
+ TP_fast_assign(
+ __entry->skbaddr = skb;
+ __entry->len = skb->len;
+ __entry->rc = rc;
+ __assign_str(name, skb->dev->name);
+ ),
+
+ TP_printk("dev=%s skbaddr=%p len=%u rc=%d",
+ __get_str(name), __entry->skbaddr, __entry->len, __entry->rc)
+);
+
+TRACE_EVENT(net_dev_queue,
+
+ TP_PROTO(struct sk_buff *skb),
+
+ TP_ARGS(skb),
+
+ TP_STRUCT__entry(
+ __field( void *, skbaddr )
+ __field( unsigned int, len )
+ __string( name, skb->dev->name )
+ ),
+
+ TP_fast_assign(
+ __entry->skbaddr = skb;
+ __entry->len = skb->len;
+ __assign_str(name, skb->dev->name);
+ ),
+
+ TP_printk("dev=%s skbaddr=%p len=%u",
+ __get_str(name), __entry->skbaddr, __entry->len)
+);
+
+TRACE_EVENT(net_dev_receive,
+
+ TP_PROTO(struct sk_buff *skb),
+
+ TP_ARGS(skb),
+
+ TP_STRUCT__entry(
+ __field( void *, skbaddr )
+ __field( unsigned int, len )
+ __string( name, skb->dev->name )
+ ),
+
+ TP_fast_assign(
+ __entry->skbaddr = skb;
+ __entry->len = skb->len;
+ __assign_str(name, skb->dev->name);
+ ),
+
+ TP_printk("dev=%s skbaddr=%p len=%u",
+ __get_str(name), __entry->skbaddr, __entry->len)
+);
+#endif /* _TRACE_NET_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/net/core/dev.c b/net/core/dev.c
index ec01a59..f7c731b 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -130,6 +130,7 @@
#include <linux/jhash.h>
#include <linux/random.h>
#include <trace/events/napi.h>
+#include <trace/events/net.h>
#include <linux/pci.h>
#include "net-sysfs.h"
@@ -1926,6 +1927,7 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
}
rc = ops->ndo_start_xmit(skb, dev);
+ trace_net_dev_xmit(skb, rc);
if (rc == NETDEV_TX_OK)
txq_trans_update(txq);
return rc;
@@ -1946,6 +1948,7 @@ gso:
skb_dst_drop(nskb);
rc = ops->ndo_start_xmit(nskb, dev);
+ trace_net_dev_xmit(nskb, rc);
if (unlikely(rc != NETDEV_TX_OK)) {
if (rc & ~NETDEV_TX_MASK)
goto out_kfree_gso_skb;
@@ -2159,6 +2162,7 @@ int dev_queue_xmit(struct sk_buff *skb)
}
gso:
+ trace_net_dev_queue(skb);
/* Disable soft irqs for various locks below. Also
* stops preemption for RCU.
*/
@@ -2934,6 +2938,7 @@ int netif_receive_skb(struct sk_buff *skb)
if (netdev_tstamp_prequeue)
net_timestamp_check(skb);
+ trace_net_dev_receive(skb);
#ifdef CONFIG_RPS
{
struct rps_dev_flow voidflow, *rflow = &voidflow;
diff --git a/net/core/net-traces.c b/net/core/net-traces.c
index afa6380..7f1bb2a 100644
--- a/net/core/net-traces.c
+++ b/net/core/net-traces.c
@@ -26,6 +26,7 @@
#define CREATE_TRACE_POINTS
#include <trace/events/skb.h>
+#include <trace/events/net.h>
#include <trace/events/napi.h>
EXPORT_TRACEPOINT_SYMBOL_GPL(kfree_skb);
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [RFC PATCH 4/5] skb: add tracepoints to freeing skb
2010-06-08 5:25 [RFC PATCH 0/5] netdev: show a process of packets Koki Sanagi
` (2 preceding siblings ...)
2010-06-08 5:30 ` [RFC PATCH 3/5] netdev: add tracepoints to netdev layer Koki Sanagi
@ 2010-06-08 5:30 ` Koki Sanagi
2010-06-08 5:31 ` [RFC PATCH 5/5] perf:add a script shows a process of packet Koki Sanagi
4 siblings, 0 replies; 6+ messages in thread
From: Koki Sanagi @ 2010-06-08 5:30 UTC (permalink / raw)
To: netdev; +Cc: davem, kaneshige.kenji, izumi.taku
This patch adds tracepoint to consume_skb and dev_kfree_skb_irq.
Signed-off-by: Koki Sanagi <sanagi.koki@jp.fujitsu.com>
---
include/trace/events/skb.h | 36 ++++++++++++++++++++++++++++++++++++
net/core/dev.c | 2 ++
net/core/skbuff.c | 1 +
3 files changed, 39 insertions(+), 0 deletions(-)
diff --git a/include/trace/events/skb.h b/include/trace/events/skb.h
index 4b2be6d..6ab5b34 100644
--- a/include/trace/events/skb.h
+++ b/include/trace/events/skb.h
@@ -35,6 +35,42 @@ TRACE_EVENT(kfree_skb,
__entry->skbaddr, __entry->protocol, __entry->location)
);
+TRACE_EVENT(consume_skb,
+
+ TP_PROTO(struct sk_buff *skb),
+
+ TP_ARGS(skb),
+
+ TP_STRUCT__entry(
+ __field( void *, skbaddr )
+ ),
+
+ TP_fast_assign(
+ __entry->skbaddr = skb;
+ ),
+
+ TP_printk("skbaddr=%p",
+ __entry->skbaddr)
+);
+
+TRACE_EVENT(dev_kfree_skb_irq,
+
+ TP_PROTO(struct sk_buff *skb),
+
+ TP_ARGS(skb),
+
+ TP_STRUCT__entry(
+ __field( void *, skbaddr )
+ ),
+
+ TP_fast_assign(
+ __entry->skbaddr = skb;
+ ),
+
+ TP_printk("skbaddr=%p",
+ __entry->skbaddr)
+);
+
TRACE_EVENT(skb_copy_datagram_iovec,
TP_PROTO(const struct sk_buff *skb, int len),
diff --git a/net/core/dev.c b/net/core/dev.c
index f7c731b..e0093c4 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -131,6 +131,7 @@
#include <linux/random.h>
#include <trace/events/napi.h>
#include <trace/events/net.h>
+#include <trace/events/skb.h>
#include <linux/pci.h>
#include "net-sysfs.h"
@@ -1584,6 +1585,7 @@ void dev_kfree_skb_irq(struct sk_buff *skb)
struct softnet_data *sd;
unsigned long flags;
+ trace_dev_kfree_skb_irq(skb);
local_irq_save(flags);
sd = &__get_cpu_var(softnet_data);
skb->next = sd->completion_queue;
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 4e7ac09..008c019 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -466,6 +466,7 @@ void consume_skb(struct sk_buff *skb)
smp_rmb();
else if (likely(!atomic_dec_and_test(&skb->users)))
return;
+ trace_consume_skb(skb);
__kfree_skb(skb);
}
EXPORT_SYMBOL(consume_skb);
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [RFC PATCH 5/5] perf:add a script shows a process of packet
2010-06-08 5:25 [RFC PATCH 0/5] netdev: show a process of packets Koki Sanagi
` (3 preceding siblings ...)
2010-06-08 5:30 ` [RFC PATCH 4/5] skb: add tracepoints to freeing skb Koki Sanagi
@ 2010-06-08 5:31 ` Koki Sanagi
4 siblings, 0 replies; 6+ messages in thread
From: Koki Sanagi @ 2010-06-08 5:31 UTC (permalink / raw)
To: netdev; +Cc: davem, kaneshige.kenji, izumi.taku
This perf script show a time-chart of process of packet.
If you want to use it, install perf and
#perf trace record netdev-times
And if you want a result,
#perf trace report netdev-times
Signed-off-by: Koki Sanagi <sanagi.koki@jp.fujitsu.com>
---
tools/perf/scripts/python/bin/netdev-times-record | 7 +
tools/perf/scripts/python/bin/netdev-times-report | 10 +
tools/perf/scripts/python/netdev-times.py | 451 +++++++++++++++++++++
3 files changed, 468 insertions(+), 0 deletions(-)
diff --git a/tools/perf/scripts/python/bin/netdev-times-record b/tools/perf/scripts/python/bin/netdev-times-record
new file mode 100644
index 0000000..c6a54fd
--- /dev/null
+++ b/tools/perf/scripts/python/bin/netdev-times-record
@@ -0,0 +1,7 @@
+#!/bin/bash
+perf record -c 1 -f -R -a -e net:net_dev_xmit -e net:net_dev_queue \
+ -e net:net_dev_receive -e skb:consume_skb \
+ -e skb:dev_kfree_skb_irq -e napi:napi_poll \
+ -e irq:irq_handler_entry -e irq:irq_handler_exit \
+ -e irq:softirq_entry -e irq:softirq_exit \
+ -e irq:softirq_raise -e skb:skb_copy_datagram_iovec
diff --git a/tools/perf/scripts/python/bin/netdev-times-report b/tools/perf/scripts/python/bin/netdev-times-report
new file mode 100644
index 0000000..5d24c3d
--- /dev/null
+++ b/tools/perf/scripts/python/bin/netdev-times-report
@@ -0,0 +1,10 @@
+#!/bin/bash
+# description: displayi a process of packet and processing time
+# args: [comm]
+if [ $# -gt 0 ] ; then
+ if ! expr match "$1" "-" > /dev/null ; then
+ comm=$1
+ shift
+ fi
+fi
+perf trace $@ -s ~/libexec/perf-core/scripts/python/netdev-times.py $comm
diff --git a/tools/perf/scripts/python/netdev-times.py b/tools/perf/scripts/python/netdev-times.py
new file mode 100644
index 0000000..e7b47c7
--- /dev/null
+++ b/tools/perf/scripts/python/netdev-times.py
@@ -0,0 +1,451 @@
+# Display process of packets and processed time.
+# It helps you to investigate networking.
+
+import os
+import sys
+
+sys.path.append(os.environ['PERF_EXEC_PATH'] + \
+ '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
+
+from perf_trace_context import *
+from Core import *
+from Util import *
+
+all_event_list = []; # insert all tracepoint event related with this script
+irq_dic = {}; # key is cpu and value is a list which stacks irqs
+ # which raise NET_RX softirq
+net_rx_dic = {}; # key is cpu and value include time of NET_RX softirq-entry
+ # and a list which stacks receive
+receive_hunk_list = []; # a list which include a sequence of receive events
+receive_skb_list = []; # received packet list for matching
+ # skb_copy_datagram_iovec
+
+queue_list = []; # list of packets which pass through dev_queue_xmit
+xmit_list = []; # list of packets which pass through dev_hard_start_xmit
+free_list = []; # list of packets which is freed
+# Calculate a time interval(msec) from src(nsec) to dst(nsec)
+def diff_msec(src, dst):
+ return (dst - src) / 1000000.0
+
+# Display a process of transmitting a packet
+def print_transmit(hunk):
+ print "%7s %5d %6d.%09dsec %12.6fmsec %12.6fmsec" % \
+ (hunk['dev'], hunk['len'],
+ nsecs_secs(hunk['queue_t']),
+ nsecs_nsecs(hunk['queue_t']),
+ diff_msec(hunk['queue_t'], hunk['xmit_t']),
+ diff_msec(hunk['xmit_t'], hunk['free_t']))
+
+# Display a process of received packets and interrputs associated with
+# a NET_RX softirq
+def print_receive(hunk):
+ if 'irq_list' not in hunk.keys() \
+ or len(hunk['irq_list']) == 0:
+ return
+ irq_list = hunk['irq_list']
+ cpu = irq_list[0]['cpu']
+ base_t = irq_list[0]['irq_ent_t']
+ print "%d.%09dsec cpu=%d" % \
+ (nsecs_secs(base_t), nsecs_nsecs(base_t), cpu)
+ for i in range(len(irq_list)):
+ print "irq_entry(+%fmsec,irq=%d:%s)" % \
+ (diff_msec(base_t, irq_list[i]['irq_ent_t']),
+ irq_list[i]['irq'], irq_list[i]['name'])
+
+ print " |------------" \
+ "softirq_raise(+%fmsec)" % \
+ diff_msec(base_t, irq_list[i]['sirq_raise_t'])
+
+ print "irq_exit (+%fmsec) |" % \
+ diff_msec(base_t, irq_list[i]['irq_ext_t'])
+
+ print " |"
+
+ if 'sirq_ent_t' not in hunk.keys():
+ print 'maybe softirq_entry is dropped'
+ return
+ print " " \
+ "softirq_entry(+%fmsec)\n" \
+ " " \
+ " |" % \
+ diff_msec(base_t, hunk['sirq_ent_t'])
+ event_list = hunk['event_list']
+ for i in range(len(event_list)):
+ event = event_list[i]
+ if event['event_name'] == 'napi_poll':
+ print " " \
+ "napi_poll_exit(+%fmsec, %s)" % \
+ (diff_msec(base_t, event['event_t']), event['dev'])
+ print " " \
+ " |"
+ elif 'comm' in event.keys():
+ print " " \
+ " |---netif_receive_skb" \
+ "(+%fmsec,len=%d)\n" \
+ " " \
+ " | |\n" \
+ " " \
+ " | skb_copy_datagram_iovec" \
+ "(+%fmsec, %d:%s)\n" \
+ " " \
+ " |" % \
+ (diff_msec(base_t, event['event_t']),
+ event['len'],
+ diff_msec(base_t, event['comm_t']),
+ event['pid'], event['comm'])
+ else:
+ print " " \
+ " |---netif_receive_skb" \
+ "(+%fmsec,len=%d)\n" \
+ " " \
+ " |" % \
+ (diff_msec(base_t, event['event_t']),
+ event['len'])
+
+ print " " \
+ "softirq_exit(+%fmsec)\n" % \
+ diff_msec(base_t, hunk['sirq_ext_t'])
+
+def trace_end():
+ # order all events in time
+ all_event_list.sort(lambda a,b :cmp(a['time'], b['time']))
+ # process all events
+ for i in range(len(all_event_list)):
+ event = all_event_list[i]
+ event_name = event['event_name']
+ if event_name == 'irq__softirq_exit':
+ handle_irq_softirq_exit(event['event_name'],
+ event['context'], event['common_cpu'],
+ event['common_pid'], event['common_comm'],
+ event['time'], event['vec'])
+ elif event_name == 'irq__softirq_entry':
+ handle_irq_softirq_entry(event['event_name'],
+ event['context'], event['common_cpu'],
+ event['common_pid'], event['common_comm'],
+ event['time'],event['vec'])
+ elif event_name == 'irq__softirq_raise':
+ handle_irq_softirq_raise(event['event_name'],
+ event['context'], event['common_cpu'],
+ event['common_pid'], event['common_comm'],
+ event['time'], event['vec'])
+ elif event_name == 'irq__irq_handler_entry':
+ handle_irq_handler_entry(event['event_name'],
+ event['context'], event['common_cpu'],
+ event['common_pid'], event['common_comm'],
+ event['time'], event['irq'], event['name'])
+ elif event_name == 'irq__irq_handler_exit':
+ handle_irq_handler_exit(event['event_name'],
+ event['context'], event['common_cpu'],
+ event['common_pid'], event['common_comm'],
+ event['time'], event['irq'], event['ret'])
+ elif event_name == 'napi__napi_poll':
+ handle_napi_poll(event['event_name'],
+ event['context'], event['common_cpu'],
+ event['common_pid'], event['common_comm'],
+ event['time'], event['napi'],
+ event['dev_name'])
+ elif event_name == 'net__net_dev_receive':
+ handle_net_dev_receive(event['event_name'],
+ event['context'], event['common_cpu'],
+ event['common_pid'], event['common_comm'],
+ event['time'], event['skbaddr'],
+ event['skblen'], event['name'])
+ elif event_name == 'skb__skb_copy_datagram_iovec':
+ handle_skb_copy_datagram_iovec(event['event_name'],
+ event['context'], event['common_cpu'],
+ event['common_pid'], event['common_comm'],
+ event['time'], event['skbaddr'],
+ event['skblen'])
+ elif event_name == 'net__net_dev_queue':
+ handle_net_dev_queue(event['event_name'],
+ event['context'], event['common_cpu'],
+ event['common_pid'], event['common_comm'],
+ event['time'], event['skbaddr'],
+ event['skblen'], event['name'])
+ elif event_name == 'net__net_dev_xmit':
+ handle_net_dev_xmit(event['event_name'],
+ event['context'], event['common_cpu'],
+ event['common_pid'], event['common_comm'],
+ event['time'], event['skbaddr'],
+ event['skblen'], event['rc'], event['name'])
+ elif event_name == 'skb__dev_kfree_skb_irq':
+ handle_dev_kfree_skb_irq(event['event_name'],
+ event['context'], event['common_cpu'],
+ event['common_pid'], event['common_comm'],
+ event['time'], event['skbaddr'])
+ elif event_name == 'skb__consume_skb':
+ handle_consume_skb(event['event_name'],
+ event['context'], event['common_cpu'],
+ event['common_pid'], event['common_comm'],
+ event['time'], event['skbaddr'])
+ # display receive hunks
+ for i in range(len(receive_hunk_list)):
+ print_receive(receive_hunk_list[i])
+ # display transmit hunks
+ print " dev len dev_queue_xmit|----------|" \
+ "dev_hard_start_xmit|-----|free_skb"
+ print " | |" \
+ " |"
+ for i in range(len(free_list)):
+ print_transmit(free_list[i])
+
+def irq__softirq_exit(event_name, context, common_cpu,
+ common_secs, common_nsecs, common_pid, common_comm,
+ vec):
+ if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX":
+ return
+ event_data = {'event_name':event_name, 'context':context,
+ 'common_cpu':common_cpu, 'common_pid':common_pid,
+ 'common_comm':common_comm,'time':nsecs(common_secs,
+ common_nsecs),
+ 'vec':vec}
+ all_event_list.append(event_data)
+
+def handle_irq_softirq_exit(event_name, context, common_cpu,
+ common_pid, common_comm, time,
+ vec):
+ rec_data = {'sirq_ext_t':time}
+ if common_cpu in irq_dic.keys():
+ rec_data.update({'irq_list':irq_dic[common_cpu]})
+ del irq_dic[common_cpu]
+ if common_cpu in net_rx_dic.keys():
+ rec_data.update({
+ 'event_list':net_rx_dic[common_cpu]['event_list'],
+ 'sirq_ent_t':net_rx_dic[common_cpu]['sirq_ent_t']})
+ del net_rx_dic[common_cpu]
+ # merge information realted to a NET_RX softirq
+ receive_hunk_list.append(rec_data)
+
+def irq__softirq_entry(event_name, context, common_cpu,
+ common_secs, common_nsecs, common_pid, common_comm,
+ vec):
+ if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX":
+ return
+ event_data = {'event_name':event_name, 'context':context,
+ 'common_cpu':common_cpu, 'common_pid':common_pid,
+ 'common_comm':common_comm,'time':nsecs(common_secs,
+ common_nsecs),
+ 'vec':vec}
+ all_event_list.append(event_data)
+
+def handle_irq_softirq_entry(event_name, context, common_cpu,
+ common_pid, common_comm, time,
+ vec):
+ net_rx_dic[common_cpu] = {'event_list':[],
+ 'sirq_ent_t':time}
+
+def irq__softirq_raise(event_name, context, common_cpu,
+ common_secs, common_nsecs, common_pid, common_comm,
+ vec):
+ if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX":
+ return
+ event_data = {'event_name':event_name, 'context':context,
+ 'common_cpu':common_cpu, 'common_pid':common_pid,
+ 'common_comm':common_comm,'time':nsecs(common_secs,
+ common_nsecs),
+ 'vec':vec}
+ all_event_list.append(event_data)
+
+def handle_irq_softirq_raise(event_name, context, common_cpu,
+ common_pid, common_comm, time,
+ vec):
+ if common_cpu not in irq_dic.keys() \
+ or len(irq_dic[common_cpu]) == 0:
+ return
+ irq = irq_dic[common_cpu].pop()
+ # put a time to prev irq on the same cpu
+ irq.update({'sirq_raise_t':time})
+ irq_dic[common_cpu].append(irq)
+
+def irq__irq_handler_entry(event_name, context, common_cpu,
+ common_secs, common_nsecs, common_pid, common_comm,
+ irq, name):
+ event_data = {'event_name':event_name, 'context':context,
+ 'common_cpu':common_cpu, 'common_pid':common_pid,
+ 'common_comm':common_comm,'time':nsecs(common_secs,
+ common_nsecs),
+ 'irq':irq, 'name':name}
+ all_event_list.append(event_data)
+
+def handle_irq_handler_entry(event_name, context, common_cpu,
+ common_pid, common_comm, time,
+ irq, name):
+ if common_cpu not in irq_dic.keys():
+ irq_dic[common_cpu] = []
+ irq_record = {'irq':irq,
+ 'name':name,
+ 'cpu':common_cpu,
+ 'irq_ent_t':time}
+ irq_dic[common_cpu].append(irq_record)
+
+def irq__irq_handler_exit(event_name, context, common_cpu,
+ common_secs, common_nsecs, common_pid, common_comm,
+ irq, ret):
+ event_data = {'event_name':event_name, 'context':context,
+ 'common_cpu':common_cpu, 'common_pid':common_pid,
+ 'common_comm':common_comm,'time':nsecs(common_secs,
+ common_nsecs),
+ 'irq':irq, 'ret':ret}
+ all_event_list.append(event_data)
+
+def handle_irq_handler_exit(event_name, context, common_cpu,
+ common_pid, common_comm, time,
+ irq, ret):
+ if common_cpu not in irq_dic.keys():
+ return
+ irq_record = irq_dic[common_cpu].pop()
+ irq_record.update({'irq_ext_t':time})
+ # if an irq doesn't include NET_RX softirq, drop.
+ if 'sirq_raise_t' in irq_record.keys():
+ irq_dic[common_cpu].append(irq_record)
+
+def napi__napi_poll(event_name, context, common_cpu,
+ common_secs, common_nsecs, common_pid, common_comm,
+ napi, dev_name):
+ event_data = {'event_name':event_name, 'context':context,
+ 'common_cpu':common_cpu, 'common_pid':common_pid,
+ 'common_comm':common_comm,'time':nsecs(common_secs,
+ common_nsecs),
+ 'napi':napi, 'dev_name':dev_name}
+ all_event_list.append(event_data)
+
+def handle_napi_poll(event_name, context, common_cpu,
+ common_pid, common_comm, time,
+ napi, dev_name):
+ if common_cpu in net_rx_dic.keys():
+ event_list = net_rx_dic[common_cpu]['event_list']
+ rec_data = {'event_name':'napi_poll',
+ 'dev':dev_name,
+ 'event_t':time}
+ event_list.append(rec_data)
+
+def net__net_dev_receive(event_name, context, common_cpu,
+ common_secs, common_nsecs, common_pid, common_comm,
+ skbaddr,skblen, name):
+ event_data = {'event_name':event_name, 'context':context,
+ 'common_cpu':common_cpu, 'common_pid':common_pid,
+ 'common_comm':common_comm,'time':nsecs(common_secs,
+ common_nsecs),
+ 'skbaddr':skbaddr, 'skblen':skblen, 'name':name}
+ all_event_list.append(event_data)
+
+def handle_net_dev_receive(event_name, context, common_cpu,
+ ccommon_pid, common_comm, time,
+ skbaddr, skblen, name):
+ if common_cpu in net_rx_dic.keys():
+ rec_data = {'event_name':'netif_receive_skb',
+ 'event_t':time,
+ 'skbaddr':skbaddr,
+ 'len':skblen}
+ event_list = net_rx_dic[common_cpu]['event_list']
+ event_list.append(rec_data)
+ receive_skb_list.insert(0, rec_data)
+
+def skb__skb_copy_datagram_iovec(event_name, context, common_cpu,
+ common_secs, common_nsecs, common_pid, common_comm,
+ skbaddr, skblen):
+ event_data = {'event_name':event_name, 'context':context,
+ 'common_cpu':common_cpu, 'common_pid':common_pid,
+ 'common_comm':common_comm,'time':nsecs(common_secs,
+ common_nsecs),
+ 'skbaddr':skbaddr, 'skblen':skblen}
+ all_event_list.append(event_data)
+
+def handle_skb_copy_datagram_iovec(event_name, context, common_cpu,
+ common_pid, common_comm, time,
+ skbaddr, skblen):
+ for i in range(len(receive_skb_list)):
+ rec_data = receive_skb_list[i]
+ if skbaddr == rec_data['skbaddr'] and \
+ 'comm' not in rec_data.keys():
+ rec_data.update({'comm':common_comm,
+ 'pid':common_pid,
+ 'comm_t':time})
+ del receive_skb_list[i]
+ break
+
+def net__net_dev_queue(event_name, context, common_cpu,
+ common_secs, common_nsecs, common_pid, common_comm,
+ skbaddr, skblen, name):
+ event_data = {'event_name':event_name, 'context':context,
+ 'common_cpu':common_cpu, 'common_pid':common_pid,
+ 'common_comm':common_comm,'time':nsecs(common_secs,
+ common_nsecs),
+ 'skbaddr':skbaddr, 'skblen':skblen, 'name':name}
+ all_event_list.append(event_data)
+
+def handle_net_dev_queue(event_name, context, common_cpu,
+ common_pid, common_comm, time,
+ skbaddr, skblen, name):
+ skb = {'dev':name,
+ 'skbaddr':skbaddr,
+ 'len':skblen,
+ 'queue_t':time}
+ xmit_list.insert(0, skb)
+
+def net__net_dev_xmit(event_name, context, common_cpu,
+ common_secs, common_nsecs, common_pid, common_comm,
+ skbaddr, skblen, rc, name):
+ event_data = {'event_name':event_name, 'context':context,
+ 'common_cpu':common_cpu, 'common_pid':common_pid,
+ 'common_comm':common_comm,'time':nsecs(common_secs,
+ common_nsecs),
+ 'skbaddr':skbaddr, 'skblen':skblen, 'rc':rc, 'name':name}
+ all_event_list.append(event_data)
+
+def handle_net_dev_xmit(event_name, context, common_cpu,
+ common_pid, common_comm, time,
+ skbaddr, skblen, rc, name):
+ if rc == 0: # NETDEV_TX_OK
+ for i in range(len(xmit_list)):
+ skb = xmit_list[i]
+ if skb['skbaddr'] == skbaddr:
+ skb['xmit_t'] = time
+ queue_list.insert(0, skb)
+ del xmit_list[i]
+ break
+
+def free_skb(event_name, context, common_cpu,
+ common_pid, common_comm, time,
+ skbaddr):
+ for i in range(len(queue_list)):
+ skb = queue_list[i]
+ if skb['skbaddr'] ==skbaddr:
+ skb['free_t'] = time
+ free_list.append(skb)
+ del queue_list[i]
+ break
+
+def skb__dev_kfree_skb_irq(event_name, context, common_cpu,
+ common_secs, common_nsecs, common_pid, common_comm,
+ skbaddr):
+ event_data = {'event_name':event_name, 'context':context,
+ 'common_cpu':common_cpu, 'common_pid':common_pid,
+ 'common_comm':common_comm,'time':nsecs(common_secs,
+ common_nsecs),
+ 'skbaddr':skbaddr}
+ all_event_list.append(event_data)
+
+def handle_dev_kfree_skb_irq(event_name, context, common_cpu,
+ common_pid, common_comm, time,
+ skbaddr):
+ free_skb(event_name, context, common_cpu,
+ common_pid, common_comm, time,
+ skbaddr)
+
+def skb__consume_skb(event_name, context, common_cpu,
+ common_secs, common_nsecs, common_pid, common_comm,
+ skbaddr):
+ event_data = {'event_name':event_name, 'context':context,
+ 'common_cpu':common_cpu, 'common_pid':common_pid,
+ 'common_comm':common_comm,'time':nsecs(common_secs,
+ common_nsecs),
+ 'skbaddr':skbaddr}
+ all_event_list.append(event_data)
+
+def handle_consume_skb(event_name, context, common_cpu,
+ common_pid, common_comm, time,
+ skbaddr):
+ free_skb(event_name, context, common_cpu,
+ common_pid, common_comm, time,
+ skbaddr)
^ permalink raw reply related [flat|nested] 6+ messages in thread
end of thread, other threads:[~2010-06-08 5:31 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-06-08 5:25 [RFC PATCH 0/5] netdev: show a process of packets Koki Sanagi
2010-06-08 5:27 ` [RFC PATCH 1/5] irq: add tracepoint to softirq_raise Koki Sanagi
2010-06-08 5:28 ` [RFC PATCH 2/5] napi: convert trace_napi_poll to TRACE_EVENT Koki Sanagi
2010-06-08 5:30 ` [RFC PATCH 3/5] netdev: add tracepoints to netdev layer Koki Sanagi
2010-06-08 5:30 ` [RFC PATCH 4/5] skb: add tracepoints to freeing skb Koki Sanagi
2010-06-08 5:31 ` [RFC PATCH 5/5] perf:add a script shows a process of packet Koki Sanagi
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).