[lttng-dev] [RFC-PATCH] Add packet details to net_* tracepoints
Geneviève Bastien
gbastien+lttng at versatic.net
Fri Mar 15 12:55:32 EDT 2013
This patch adds some packet header details to the net_*
tracepoints: the network header and transport header
if it is tcp.
Signed-off-by: Geneviève Bastien <gbastien+lttng at versatic.net>
---
instrumentation/events/lttng-module/net.h | 96 +++++++++++++++++++++++++++++--
1 file changed, 91 insertions(+), 5 deletions(-)
diff --git a/instrumentation/events/lttng-module/net.h b/instrumentation/events/lttng-module/net.h
index e552cf7..5830160 100644
--- a/instrumentation/events/lttng-module/net.h
+++ b/instrumentation/events/lttng-module/net.h
@@ -7,9 +7,50 @@
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/ipv6.h>
#include <linux/tracepoint.h>
#include <linux/version.h>
+#ifndef _TRACE_NET_DEF_
+#define _TRACE_NET_DEF_
+
+static inline unsigned int __get_network_header_len(struct sk_buff *skb)
+{
+ if (skb_network_header(skb) == skb->head) {
+ /* Is the network header initialized */
+ return 0;
+ } else if (skb->transport_header > skb->network_header) {
+ /* is the transport header initialized */
+ return skb->transport_header - skb->network_header;
+ } else { /* Don't know where to stop */
+ return 0;
+ }
+}
+
+static inline unsigned int __get_transport_header_len(struct sk_buff *skb)
+{
+ if (skb_network_header(skb) == skb->head) {
+ /* Is the network header initialized */
+ return 0;
+ } else if (skb->transport_header <= skb->network_header) {
+ /* is the transport header initialized */
+ return 0;
+ } else if (
+ ((ip_hdr(skb)->version == 4)
+ && (ip_hdr(skb)->protocol == 6)) ||
+ ((ipv6_hdr(skb)->version == 6) &&
+ (ipv6_hdr(skb)->nexthdr == 6))) {
+ /* tcp over ipv4 or ipv6 */
+ return sizeof(struct tcphdr);
+ } else {
+ /* Other protocol */
+ return 0;
+ }
+}
+
+#endif /* _TRACE_NET_DEF_ */
+
TRACE_EVENT(net_dev_xmit,
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,40))
@@ -57,6 +98,27 @@ TRACE_EVENT(net_dev_xmit,
__get_str(name), __entry->skbaddr, __entry->len, __entry->rc)
)
+/*
+ * This has to be safe: we need as much information from the headers as
+ * possible, but these tracepoints are early after the skb reception and
+ * just before sending, so we do not have yet full skb information.
+ * We will need to do some packet treatment to be able to get all the info we
+ * need.
+ *
+ * At this point, sometimes the network header (nh) and/or transport header
+ * (th) is not initialized. And we do not know the length of those headers.
+ *
+ * The idea is to copy header only if we know where it starts and where it
+ * ends.
+ *
+ * For nh, we copy th-nh bytes, if both th and nh are initialized.
+ *
+ * For th, we never know its length, so we copy it only if we know where to
+ * start and if it's a tcp header. To know that, we check the first bits of
+ * nh (assuming it's a ip header) whether it's v4 or v6 and depending on the
+ * ip version, check the transport protocol. If it's tcp (6), then we know
+ * the th is a (struct tcphdr)
+ */
DECLARE_EVENT_CLASS(net_dev_template,
TP_PROTO(struct sk_buff *skb),
@@ -64,19 +126,43 @@ DECLARE_EVENT_CLASS(net_dev_template,
TP_ARGS(skb),
TP_STRUCT__entry(
- __field( void *, skbaddr )
- __field( unsigned int, len )
- __string( name, skb->dev->name )
+ __field_hex(void *, skbaddr)
+ __field(unsigned int, len)
+ __string(name, skb->dev->name)
+ __field_network_hex(uint32_t, saddr)
+ __field(unsigned char*, mh)
+ __field(unsigned char*, nh)
+ __field(unsigned char*, th)
+ __field(unsigned char*, tail)
+ __field(unsigned char*, end)
+ __field(unsigned char*, head)
+ __field(unsigned char*, data)
+ __dynamic_array_hex(unsigned char, nhdata,
+ __get_network_header_len(skb))
+ __dynamic_array_hex(unsigned char, thdata,
+ __get_transport_header_len(skb))
),
TP_fast_assign(
tp_assign(skbaddr, skb)
tp_assign(len, skb->len)
tp_strcpy(name, skb->dev->name)
+ tp_assign(saddr, ip_hdr(skb)->saddr)
+ tp_assign(mh, skb->mac_header)
+ tp_assign(nh, skb->network_header)
+ tp_assign(th, skb->transport_header)
+ tp_assign(tail, skb->tail)
+ tp_assign(end, skb->end)
+ tp_assign(head, skb->head)
+ tp_assign(data, skb->data)
+ tp_memcpy_dyn(nhdata, skb_network_header(skb))
+ tp_memcpy_dyn(thdata, skb_transport_header(skb))
),
- TP_printk("dev=%s skbaddr=%p len=%u",
- __get_str(name), __entry->skbaddr, __entry->len)
+ TP_printk("dev=%s skbaddr=%x len=%u saddr=%x %x %x %x %x %x %x %x",
+ __get_str(name), __entry->skbaddr, __entry->len, __entry->saddr,
+ __entry->th, __entry->nh, __entry->mh, __entry->tail,
+ __entry->end, __entry->head, __entry->data)
)
DEFINE_EVENT(net_dev_template, net_dev_queue,
--
1.8.1.5
More information about the lttng-dev
mailing list