forked from Minki/linux
qdisc: add tracepoint qdisc:qdisc_dequeue for dequeued SKBs
The main purpose of this tracepoint is to monitor bulk dequeue in the network qdisc layer, as it cannot be deducted from the existing qdisc stats. The txq_state can be used for determining the reason for zero packet dequeues, see enum netdev_queue_state_t. Notice all packets doesn't necessary activate this tracepoint. As qdiscs with flag TCQ_F_CAN_BYPASS, can directly invoke sch_direct_xmit() when qdisc_qlen is zero. Remember that perf record supports filters like: perf record -e qdisc:qdisc_dequeue \ --filter 'ifindex == 4 && (packets > 1 || txq_state > 0)' Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
7440cccee0
commit
e543002f77
50
include/trace/events/qdisc.h
Normal file
50
include/trace/events/qdisc.h
Normal file
@ -0,0 +1,50 @@
|
||||
#undef TRACE_SYSTEM
|
||||
#define TRACE_SYSTEM qdisc
|
||||
|
||||
#if !defined(_TRACE_QDISC_H) || defined(TRACE_HEADER_MULTI_READ)
|
||||
#define _TRACE_QDISC_H_
|
||||
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/tracepoint.h>
|
||||
#include <linux/ftrace.h>
|
||||
|
||||
TRACE_EVENT(qdisc_dequeue,
|
||||
|
||||
TP_PROTO(struct Qdisc *qdisc, const struct netdev_queue *txq,
|
||||
int packets, struct sk_buff *skb),
|
||||
|
||||
TP_ARGS(qdisc, txq, packets, skb),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field( struct Qdisc *, qdisc )
|
||||
__field(const struct netdev_queue *, txq )
|
||||
__field( int, packets )
|
||||
__field( void *, skbaddr )
|
||||
__field( int, ifindex )
|
||||
__field( u32, handle )
|
||||
__field( u32, parent )
|
||||
__field( unsigned long, txq_state)
|
||||
),
|
||||
|
||||
/* skb==NULL indicate packets dequeued was 0, even when packets==1 */
|
||||
TP_fast_assign(
|
||||
__entry->qdisc = qdisc;
|
||||
__entry->txq = txq;
|
||||
__entry->packets = skb ? packets : 0;
|
||||
__entry->skbaddr = skb;
|
||||
__entry->ifindex = txq->dev ? txq->dev->ifindex : 0;
|
||||
__entry->handle = qdisc->handle;
|
||||
__entry->parent = qdisc->parent;
|
||||
__entry->txq_state = txq->state;
|
||||
),
|
||||
|
||||
TP_printk("dequeue ifindex=%d qdisc handle=0x%X parent=0x%X txq_state=0x%lX packets=%d skbaddr=%p",
|
||||
__entry->ifindex, __entry->handle, __entry->parent,
|
||||
__entry->txq_state, __entry->packets, __entry->skbaddr )
|
||||
);
|
||||
|
||||
#endif /* _TRACE_QDISC_H_ */
|
||||
|
||||
/* This part must be outside protection */
|
||||
#include <trace/define_trace.h>
|
@ -32,6 +32,7 @@
|
||||
#include <trace/events/sock.h>
|
||||
#include <trace/events/udp.h>
|
||||
#include <trace/events/fib.h>
|
||||
#include <trace/events/qdisc.h>
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
#include <trace/events/fib6.h>
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(fib6_table_lookup);
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <net/sch_generic.h>
|
||||
#include <net/pkt_sched.h>
|
||||
#include <net/dst.h>
|
||||
#include <trace/events/qdisc.h>
|
||||
|
||||
/* Qdisc to use by default */
|
||||
const struct Qdisc_ops *default_qdisc_ops = &pfifo_fast_ops;
|
||||
@ -126,7 +127,7 @@ static struct sk_buff *dequeue_skb(struct Qdisc *q, bool *validate,
|
||||
q->q.qlen--;
|
||||
} else
|
||||
skb = NULL;
|
||||
return skb;
|
||||
goto trace;
|
||||
}
|
||||
*validate = true;
|
||||
skb = q->skb_bad_txq;
|
||||
@ -139,7 +140,8 @@ static struct sk_buff *dequeue_skb(struct Qdisc *q, bool *validate,
|
||||
q->q.qlen--;
|
||||
goto bulk;
|
||||
}
|
||||
return NULL;
|
||||
skb = NULL;
|
||||
goto trace;
|
||||
}
|
||||
if (!(q->flags & TCQ_F_ONETXQUEUE) ||
|
||||
!netif_xmit_frozen_or_stopped(txq))
|
||||
@ -151,6 +153,8 @@ bulk:
|
||||
else
|
||||
try_bulk_dequeue_skb_slow(q, skb, packets);
|
||||
}
|
||||
trace:
|
||||
trace_qdisc_dequeue(q, txq, *packets, skb);
|
||||
return skb;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user