[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