From 9cf9736a1715a1fec4857fac2784a12596675ce2 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Genevi=C3=A8ve=20Bastien?= Date: Tue, 12 Jul 2016 13:26:14 -0400 Subject: [PATCH] net: Add TCP header data to net_* tracepoints MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This patch adds the transport header variant field in the network types IPv4 and IPv6 using the corresponding next protocol field in both types. It adds the detailed fields of the TCP header. Other transport headers are empty. Example output from babeltrace: [13:21:04.392017771] (+0.000588730) qemulttng0 net_dev_queue: { cpu_id = 1 }, { skbaddr = 0xFFFF88003C8390E8, len = 370, name = "ens3", network_header_type = ( "_ipv4" : container = 1 ), network_header = { ipv4 = { version = 4, ihl = 5, tos = 16, tot_len = 356, id = 0xFA2F, frag_off = 16384, ttl = 64, protocol = ( "_tcp" : container = 6 ), checksum = 0x173C, saddr_padding = { }, saddr = [ [0] = 10, [1] = 0, [2] = 10, [3] = 24 ], daddr_padding = { }, daddr = [ [0] = 10, [1] = 0, [2] = 10, [3] = 1 ], transport_header = { tcp = { source_port = 22, dest_port = 47500, seq = 2784866942, ack_seq = 3750103494, data_offset = 8, reserved = 0, flags = 0x11, window_size = 305, checksum = 0x296F, urg_ptr = 0 } } } } } [13:21:04.429861105] (+0.037671848) qemulttng0 net_dev_queue: { cpu_id = 1 }, { skbaddr = 0xFFFF88003DBFC800, len = 86, name = "ens3", network_header_type = ( "_ipv6" : container = 2 ), network_header = { ipv6 = { version = 6, prio = 0, flow_lbl_padding = { }, flow_lbl = [ [0] = 0x84, [1] = 0x41, [2] = 0x6F ], payload_len = 32, nexthdr = ( "_tcp" : container = 6 ), hop_limit = 64, saddr_padding = { }, saddr = [ [0] = 0xFE80, [1] = 0x0, [2] = 0x0, [3] = 0x0, [4] = 0x5054, [5] = 0xFF, [6] = 0xFE12, [7] = 0x3456 ], daddr_padding = { }, daddr = [ [0] = 0xFE80, [1] = 0x0, [2] = 0x0, [3] = 0x0, [4] = 0x5054, [5] = 0xFF, [6] = 0xFE22, [7] = 0x3344 ], transport_header = { tcp = { source_port = 36972, dest_port = 22, seq = 3750103494, ack_seq = 2784866942, data_offset = 0, reserved = 0, flags = 0x11, window_size = 256, checksum = 0x39F, urg_ptr = 0 } } } } } [13:21:08.195490138] (+3.765629033) qemulttng0 net_if_receive_skb: { cpu_id = 0 }, { skbaddr = 0xFFFF88003C0B8C00, len = 72, name = "ens3", network_header_type = ( "_ipv6" : container = 2 ), network_header = { ipv6 = { version = 6, prio = 0, flow_lbl_padding = { }, flow_lbl = [ [0] = 0x84, [1] = 0xCB, [2] = 0x7F ], payload_len = 32, nexthdr = ( "_unknown" : container = 58 ), hop_limit = 255, saddr_padding = { }, saddr = [ [0] = 0xFE80, [1] = 0x0, [2] = 0x0, [3] = 0x0, [4] = 0x40C, [5] = 0xA9FF, [6] = 0xFEB5, [7] = 0xA75B ], daddr_padding = { }, daddr = [ [0] = 0xFE80, [1] = 0x0, [2] = 0x0, [3] = 0x0, [4] = 0x5054, [5] = 0xFF, [6] = 0xFE12, [7] = 0x3456 ], transport_header = { unknown = { } } } } } Signed-off-by: Geneviève Bastien Signed-off-by: Mathieu Desnoyers --- instrumentation/events/lttng-module/net.h | 169 +++++++++++++++++++++- 1 file changed, 167 insertions(+), 2 deletions(-) diff --git a/instrumentation/events/lttng-module/net.h b/instrumentation/events/lttng-module/net.h index e33959a2..b3b05073 100644 --- a/instrumentation/events/lttng-module/net.h +++ b/instrumentation/events/lttng-module/net.h @@ -29,6 +29,122 @@ static inline unsigned char __has_network_hdr(struct sk_buff *skb) static struct lttng_event_field emptyfields[] = { }; +/* Structures for transport headers. */ + +static struct lttng_event_field tcpfields[] = { + [0] = { + .name = "source_port", + .type = __type_integer(uint16_t, 0, 0, 0, __BIG_ENDIAN, 10, none), + }, + [1] = { + .name = "dest_port", + .type = __type_integer(uint16_t, 0, 0, 0, __BIG_ENDIAN, 10, none), + }, + [2] = { + .name = "seq", + .type = __type_integer(uint32_t, 0, 0, 0, __BIG_ENDIAN, 10, none), + }, + [3] = { + .name = "ack_seq", + .type = __type_integer(uint32_t, 0, 0, 0, __BIG_ENDIAN, 10, none), + }, + [4] = { + .name = "data_offset", + .type = __type_integer(uint8_t, 4, 4, 0, __BIG_ENDIAN, 10, none), + }, + [5] = { + .name = "reserved", + .type = __type_integer(uint8_t, 3, 1, 0, __BIG_ENDIAN, 10, none), + }, + [6] = { + .name = "flags", + .type = __type_integer(uint8_t, 9, 1, 0, __BIG_ENDIAN, 16, none), + }, + [7] = { + .name = "window_size", + .type = __type_integer(uint16_t, 0, 0, 0, __BIG_ENDIAN, 10, none), + }, + [8] = { + .name = "checksum", + .type = __type_integer(uint16_t, 0, 0, 0, __BIG_ENDIAN, 16, none), + }, + [9] = { + .name = "urg_ptr", + .type = __type_integer(uint16_t, 0, 0, 0, __BIG_ENDIAN, 10, none), + }, +}; + +static struct lttng_event_field transport_fields[] = { + [0] = { + .name = "unknown", + .type = { + .atype = atype_struct, + .u._struct.nr_fields = ARRAY_SIZE(emptyfields), + .u._struct.fields = emptyfields, + }, + }, + [1] = { + .name = "tcp", + .type = { + .atype = atype_struct, + .u._struct.nr_fields = ARRAY_SIZE(tcpfields), + .u._struct.fields = tcpfields, + }, + }, +}; + +enum transport_header_types { + TH_NONE, + TH_TCP, +}; + +static inline unsigned char __get_transport_header_type(struct sk_buff *skb) +{ + if (__has_network_hdr(skb)) { + /* + * When both transport and network header are set, transport header + * is greater than network header, otherwise it points to head. + */ + if (skb->transport_header > skb->network_header) { + /* + * Get the transport protocol from the network header's data. + * This method works both for sent and received packets. + */ + if ((skb->protocol == htons(ETH_P_IP) && + ip_hdr(skb)->protocol == IPPROTO_TCP) || + (skb->protocol == htons(ETH_P_IPV6) && + ipv6_hdr(skb)->nexthdr == IPPROTO_TCP)) + return TH_TCP; + } + /* Fallthrough for other cases where header is not TCP. */ + } + return TH_NONE; +} + +static struct lttng_enum_entry transport_enum_entries[] = { + [0] = { + .start = { .value = 0, .signedness = 0, }, + .end = { .value = IPPROTO_TCP - 1, .signedness = 0, }, + .string = "_unknown", + }, + [1] = { + .start = { .value = IPPROTO_TCP, .signedness = 0, }, + .end = { .value = IPPROTO_TCP, .signedness = 0, }, + .string = "_tcp", + }, + [2] = { + .start = { .value = IPPROTO_TCP + 1, .signedness = 0, }, + .end = { .value = 255, .signedness = 0, }, + .string = "_unknown", + }, +}; + +static const struct lttng_enum_desc transport_header_type = { + .name = "transport_header_type", + .entries = transport_enum_entries, + .nr_entries = ARRAY_SIZE(transport_enum_entries), +}; + /* Structures for network headers. */ static struct lttng_event_field ipv4fields[] = { @@ -62,7 +178,18 @@ static struct lttng_event_field ipv4fields[] = { }, [7] = { .name = "protocol", - .type = __type_integer(uint8_t, 0, 0, 0, __BIG_ENDIAN, 10, none), + .type = { + .atype = atype_enum, + .u.basic.enumeration.desc = &transport_header_type, + .u.basic.enumeration.container_type = { + .size = 8, + .alignment = 8, + .signedness = 0, + .reverse_byte_order = __BIG_ENDIAN != __BYTE_ORDER, + .base = 10, + .encoding = lttng_encode_none, + }, + }, }, [8] = { .name = "checksum", @@ -86,6 +213,15 @@ static struct lttng_event_field ipv4fields[] = { .u.array.elem_alignment = lttng_alignof(uint8_t), }, }, + [11] = { + .name = "transport_header", + .type = { + .atype = atype_variant, + .u.variant.tag_name = "protocol", + .u.variant.choices = transport_fields, + .u.variant.nr_choices = ARRAY_SIZE(transport_fields), + }, + }, }; static struct lttng_event_field ipv6fields[] = { @@ -112,7 +248,18 @@ static struct lttng_event_field ipv6fields[] = { }, [4] = { .name = "nexthdr", - .type = __type_integer(uint8_t, 0, 0, 0, __BIG_ENDIAN, 10, none), + .type = { + .atype = atype_enum, + .u.basic.enumeration.desc = &transport_header_type, + .u.basic.enumeration.container_type = { + .size = 8, + .alignment = 8, + .signedness = 0, + .reverse_byte_order = __BIG_ENDIAN != __BYTE_ORDER, + .base = 10, + .encoding = lttng_encode_none, + }, + }, }, [5] = { .name = "hop_limit", @@ -136,6 +283,15 @@ static struct lttng_event_field ipv6fields[] = { .u.array.elem_alignment = lttng_alignof(uint16_t), }, }, + [8] = { + .name = "transport_header", + .type = { + .atype = atype_variant, + .u.variant.tag_name = "nexthdr", + .u.variant.choices = transport_fields, + .u.variant.nr_choices = ARRAY_SIZE(transport_fields), + }, + }, }; static struct lttng_event_field network_fields[] = { @@ -243,6 +399,7 @@ LTTNG_TRACEPOINT_EVENT_CLASS(net_dev_template, ), network_header, ctf_custom_code( + /* Copy the network header */ switch (__get_network_header_type(skb)) { case NH_IPV4: { ctf_align(uint16_t) @@ -260,6 +417,14 @@ LTTNG_TRACEPOINT_EVENT_CLASS(net_dev_template, /* For any other header type, there is nothing to do. */ break; } + + /* Copy the transport header */ + if (__get_transport_header_type(skb) == TH_TCP) { + ctf_align(uint32_t) + ctf_array_type(uint8_t, tcp_hdr(skb), + sizeof(struct tcphdr)) + } + /* For any other header type, there is nothing to do. */ ) ) ) -- 2.34.1