From: Geneviève Bastien Date: Mon, 11 Jul 2016 13:34:02 +0000 (-0400) Subject: net: Add IPv4/IPv6 header data to net_* tracepoints X-Git-Tag: v2.9.0-rc1~42 X-Git-Url: https://git.lttng.org./?a=commitdiff_plain;h=e5990fd415d46da69523dfe7943bc3168664fde8;p=lttng-modules.git net: Add IPv4/IPv6 header data to net_* tracepoints This patch adds an enum field for the type of network header and a variant field for the details of IPv4 and IPv6 headers. Any other network header is empty. Example babeltrace output: [16:04:07.443810277] (+0.110633000) host0 net_dev_queue: { cpu_id = 0 }, { skbaddr = 0xFFFF88003D9F4B00, len = 1462, name = "ens3", network_header_type = ( "_ipv4" : container = 1 ), network_header = { ipv4 = { version = 4, ihl = 5, tos = 0, tot_len = 1448, id = 0x0, frag_off = 16384, ttl = 64, protocol = 6, checksum = 0xB04, saddr_padding = { }, saddr = [ [0] = 10, [1] = 0, [2] = 10, [3] = 24 ], daddr_padding = { }, daddr = [ [0] = 10, [1] = 0, [2] = 12, [3] = 42 ] } } } [16:04:10.452192462] (+0.000283214) host0 net_if_receive_skb: { cpu_id = 0 }, { skbaddr = 0xFFFF88003D9F4900, len = 118, name = "ens3", network_header_type = ( "_ipv6" : container = 2 ), network_header = { ipv6 = { version = 6, prio = 0, flow_lbl_padding = { }, flow_lbl = [ [0] = 0x88, [1] = 0x41, [2] = 0x6F ], payload_len = 64, nexthdr = 58, 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] = 0x40C, [5] = 0xA9FF, [6] = 0xFEB5, [7] = 0xA75B ] } } } Signed-off-by: Geneviève Bastien Signed-off-by: Mathieu Desnoyers --- diff --git a/instrumentation/events/lttng-module/net.h b/instrumentation/events/lttng-module/net.h index 4f4b817a..e33959a2 100644 --- a/instrumentation/events/lttng-module/net.h +++ b/instrumentation/events/lttng-module/net.h @@ -8,7 +8,190 @@ #include #include #include +#include +#include #include +#include +#include + +#ifndef ONCE_LTTNG_NET_H +#define ONCE_LTTNG_NET_H + +static inline unsigned char __has_network_hdr(struct sk_buff *skb) +{ + /* + * If the header is not set yet, + * the network header will point to the head. + */ + return skb_network_header(skb) != skb->head; +} + +static struct lttng_event_field emptyfields[] = { +}; + +/* Structures for network headers. */ + +static struct lttng_event_field ipv4fields[] = { + [0] = { + .name = "version", + .type = __type_integer(uint8_t, 4, 4, 0, __BIG_ENDIAN, 10, none), + }, + [1] = { + .name = "ihl", + .type = __type_integer(uint8_t, 4, 4, 0, __BIG_ENDIAN, 10, none), + }, + [2] = { + .name = "tos", + .type = __type_integer(uint8_t, 0, 0, 0, __BIG_ENDIAN, 10, none), + }, + [3] = { + .name = "tot_len", + .type = __type_integer(uint16_t, 0, 0, 0, __BIG_ENDIAN, 10, none), + }, + [4] = { + .name = "id", + .type = __type_integer(uint16_t, 0, 0, 0, __BIG_ENDIAN, 16, none), + }, + [5] = { + .name = "frag_off", + .type = __type_integer(uint16_t, 0, 0, 0, __BIG_ENDIAN, 10, none), + }, + [6] = { + .name = "ttl", + .type = __type_integer(uint8_t, 0, 0, 0, __BIG_ENDIAN, 10, none), + }, + [7] = { + .name = "protocol", + .type = __type_integer(uint8_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 = "saddr", + .type = { + .atype = atype_array, + .u.array.elem_type = __type_integer(uint8_t, 0, 0, 0, __BIG_ENDIAN, 10, none), + .u.array.length = 4, + .u.array.elem_alignment = lttng_alignof(uint8_t), + }, + }, + [10] = { + .name = "daddr", + .type = { + .atype = atype_array, + .u.array.elem_type = __type_integer(uint8_t, 0, 0, 0, __BIG_ENDIAN, 10, none), + .u.array.length = 4, + .u.array.elem_alignment = lttng_alignof(uint8_t), + }, + }, +}; + +static struct lttng_event_field ipv6fields[] = { + [0] = { + .name = "version", + .type = __type_integer(uint8_t, 4, 4, 0, __BIG_ENDIAN, 10, none), + }, + [1] = { + .name = "prio", + .type = __type_integer(uint8_t, 4, 4, 0, __BIG_ENDIAN, 10, none), + }, + [2] = { + .name = "flow_lbl", + .type = { + .atype = atype_array, + .u.array.elem_type = __type_integer(uint8_t, 0, 0, 0, __BIG_ENDIAN, 16, none), + .u.array.length = 3, + .u.array.elem_alignment = lttng_alignof(uint8_t), + }, + }, + [3] = { + .name = "payload_len", + .type = __type_integer(uint16_t, 0, 0, 0, __BIG_ENDIAN, 10, none), + }, + [4] = { + .name = "nexthdr", + .type = __type_integer(uint8_t, 0, 0, 0, __BIG_ENDIAN, 10, none), + }, + [5] = { + .name = "hop_limit", + .type = __type_integer(uint8_t, 0, 0, 0, __BIG_ENDIAN, 10, none), + }, + [6] = { + .name = "saddr", + .type = { + .atype = atype_array, + .u.array.elem_type = __type_integer(uint16_t, 0, 0, 0, __BIG_ENDIAN, 16, none), + .u.array.length = 8, + .u.array.elem_alignment = lttng_alignof(uint16_t), + }, + }, + [7] = { + .name = "daddr", + .type = { + .atype = atype_array, + .u.array.elem_type = __type_integer(uint16_t, 0, 0, 0, __BIG_ENDIAN, 16, none), + .u.array.length = 8, + .u.array.elem_alignment = lttng_alignof(uint16_t), + }, + }, +}; + +static struct lttng_event_field network_fields[] = { + [0] = { + .name = "unknown", + .type = { + .atype = atype_struct, + .u._struct.nr_fields = 0, + .u._struct.fields = emptyfields, + }, + }, + [1] = { + .name = "ipv4", + .type = { + .atype = atype_struct, + .u._struct.nr_fields = ARRAY_SIZE(ipv4fields), + .u._struct.fields = ipv4fields, + }, + }, + [2] = { + .name = "ipv6", + .type = { + .atype = atype_struct, + .u._struct.nr_fields = ARRAY_SIZE(ipv6fields), + .u._struct.fields = ipv6fields, + }, + }, +}; + +enum network_header_types { + NH_NONE, + NH_IPV4, + NH_IPV6, +}; + +static inline unsigned char __get_network_header_type(struct sk_buff *skb) +{ + if (__has_network_hdr(skb)) { + if (skb->protocol == htons(ETH_P_IPV6)) + return NH_IPV6; + else if (skb->protocol == htons(ETH_P_IP)) + return NH_IPV4; + /* Fallthrough for other header types. */ + } + return NH_NONE; +} + +#endif + +LTTNG_TRACEPOINT_ENUM(net_network_header, + TP_ENUM_VALUES( + ctf_enum_value("_unknown", NH_NONE) + ctf_enum_value("_ipv4", NH_IPV4) + ctf_enum_value("_ipv6", NH_IPV6) + ) +) LTTNG_TRACEPOINT_EVENT(net_dev_xmit, @@ -49,6 +232,36 @@ LTTNG_TRACEPOINT_EVENT_CLASS(net_dev_template, ctf_integer_hex(void *, skbaddr, skb) ctf_integer(unsigned int, len, skb->len) ctf_string(name, skb->dev->name) + ctf_enum(net_network_header, unsigned char, + network_header_type, __get_network_header_type(skb)) + ctf_custom_field( + ctf_custom_type( + .atype = atype_variant, + .u.variant.tag_name = "network_header_type", + .u.variant.choices = network_fields, + .u.variant.nr_choices = ARRAY_SIZE(network_fields), + ), + network_header, + ctf_custom_code( + switch (__get_network_header_type(skb)) { + case NH_IPV4: { + ctf_align(uint16_t) + ctf_array_type(uint8_t, ip_hdr(skb), + sizeof(struct iphdr)) + break; + } + case NH_IPV6: { + ctf_align(uint16_t) + ctf_array_type(uint8_t, ipv6_hdr(skb), + sizeof(struct ipv6hdr)) + break; + } + default: + /* For any other header type, there is nothing to do. */ + break; + } + ) + ) ) )