net: Add TCP header data to net_* tracepoints
authorGeneviève Bastien <gbastien+lttng@versatic.net>
Tue, 12 Jul 2016 17:26:14 +0000 (13:26 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Thu, 14 Jul 2016 15:47:53 +0000 (11:47 -0400)
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 <gbastien+lttng@versatic.net>
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
instrumentation/events/lttng-module/net.h

index e33959a2efa1a1d30788417027231dcc8af2b530..b3b050738898b8f6db63d3bb3b77927316b80c7a 100644 (file)
@@ -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. */
                        )
                )
        )
This page took 0.028525 seconds and 5 git commands to generate.