qdisc: add tracepoint qdisc:qdisc_dequeue for dequeued SKBs
authorJesper Dangaard Brouer <brouer@redhat.com>
Tue, 15 Aug 2017 19:11:03 +0000 (21:11 +0200)
committerDavid S. Miller <davem@davemloft.net>
Wed, 16 Aug 2017 21:10:10 +0000 (14:10 -0700)
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>
include/trace/events/qdisc.h [new file with mode: 0644]
net/core/net-traces.c
net/sched/sch_generic.c

diff --git a/include/trace/events/qdisc.h b/include/trace/events/qdisc.h
new file mode 100644 (file)
index 0000000..60d0d8b
--- /dev/null
@@ -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>
index 92da5e4ceb4f42105ca3d1a436eb8df99bfd3eaf..4f1468ccd056e161296740f477d9f9e92eca03e4 100644 (file)
@@ -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);
index 57ba406f1437323a4ba172d52f14a8b687b86708..c6b89a34e8d2e8eecc7ad6d21950bd84335443a0 100644 (file)
@@ -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;
 }