1 /* SPDX-License-Identifier: GPL-2.0 */
3 #define TRACE_SYSTEM net
5 #if !defined(LTTNG_TRACE_NET_H) || defined(TRACE_HEADER_MULTI_READ)
6 #define LTTNG_TRACE_NET_H
8 #include <probes/lttng-tracepoint-event.h>
9 #include <linux/skbuff.h>
10 #include <linux/netdevice.h>
12 #include <linux/ipv6.h>
13 #include <linux/tcp.h>
14 #include <linux/udp.h>
15 #include <linux/icmp.h>
16 #include <linux/version.h>
17 #include <lttng-endian.h>
20 #ifndef ONCE_LTTNG_NET_H
21 #define ONCE_LTTNG_NET_H
23 static inline unsigned char __has_network_hdr(struct sk_buff
*skb
)
26 * If the header is not set yet, the network header will point
29 return skb_network_header(skb
) != skb
->head
;
32 static struct lttng_event_field emptyfields
[] = {
35 /* Structures for transport headers. */
37 static struct lttng_event_field tcpfields
[] = {
39 .name
= "source_port",
40 .type
= __type_integer(uint16_t, 0, 0, 0,
41 __BIG_ENDIAN
, 10, none
),
45 .type
= __type_integer(uint16_t, 0, 0, 0,
46 __BIG_ENDIAN
, 10, none
),
50 .type
= __type_integer(uint32_t, 0, 0, 0,
51 __BIG_ENDIAN
, 10, none
),
55 .type
= __type_integer(uint32_t, 0, 0, 0,
56 __BIG_ENDIAN
, 10, none
),
59 .name
= "data_offset",
60 .type
= __type_integer(uint8_t, 4, 4, 0,
61 __BIG_ENDIAN
, 10, none
),
65 .type
= __type_integer(uint8_t, 3, 1, 0,
66 __BIG_ENDIAN
, 10, none
),
70 .type
= __type_integer(uint8_t, 9, 1, 0,
71 __BIG_ENDIAN
, 16, none
),
74 .name
= "window_size",
75 .type
= __type_integer(uint16_t, 0, 0, 0,
76 __BIG_ENDIAN
, 10, none
),
80 .type
= __type_integer(uint16_t, 0, 0, 0,
81 __BIG_ENDIAN
, 16, none
),
85 .type
= __type_integer(uint16_t, 0, 0, 0,
86 __BIG_ENDIAN
, 10, none
),
90 static struct lttng_event_field udpfields
[] = {
92 .name
= "source_port",
93 .type
= __type_integer(uint16_t, 0, 0, 0,
94 __BIG_ENDIAN
, 10, none
),
98 .type
= __type_integer(uint16_t, 0, 0, 0,
99 __BIG_ENDIAN
, 10, none
),
103 .type
= __type_integer(uint16_t, 0, 0, 0,
104 __BIG_ENDIAN
, 10, none
),
108 .type
= __type_integer(uint16_t, 0, 0, 0,
109 __BIG_ENDIAN
, 10, none
),
113 static struct lttng_event_field icmpfields
[] = {
116 .type
= __type_integer(uint8_t, 0, 0, 0,
117 __BIG_ENDIAN
, 10, none
),
121 .type
= __type_integer(uint8_t, 0, 0, 0,
122 __BIG_ENDIAN
, 10, none
),
126 .type
= __type_integer(uint16_t, 0, 0, 0,
127 __BIG_ENDIAN
, 10, none
),
131 .type
= __type_integer(uint32_t, 0, 0, 0,
132 __BIG_ENDIAN
, 10, none
),
137 static struct lttng_event_field transport_fields
[] = {
141 .atype
= atype_struct
,
142 .u
._struct
.nr_fields
= ARRAY_SIZE(emptyfields
),
143 .u
._struct
.fields
= emptyfields
,
149 .atype
= atype_struct
,
150 .u
._struct
.nr_fields
= ARRAY_SIZE(tcpfields
),
151 .u
._struct
.fields
= tcpfields
,
157 .atype
= atype_struct
,
158 .u
._struct
.nr_fields
= ARRAY_SIZE(udpfields
),
159 .u
._struct
.fields
= udpfields
,
165 .atype
= atype_struct
,
166 .u
._struct
.nr_fields
= ARRAY_SIZE(icmpfields
),
167 .u
._struct
.fields
= icmpfields
,
172 enum transport_header_types
{
179 static inline enum transport_header_types
__get_transport_header_type_ip(struct sk_buff
*skb
)
181 switch (ip_hdr(skb
)->protocol
) {
192 static inline enum transport_header_types
__get_transport_header_type_ipv6(struct sk_buff
*skb
)
194 switch (ipv6_hdr(skb
)->nexthdr
) {
205 static inline enum transport_header_types
__get_transport_header_type(struct sk_buff
*skb
)
207 if (__has_network_hdr(skb
)) {
209 * When both transport and network headers are set,
210 * transport header is greater than network header,
211 * otherwise it points to head.
213 if (skb
->transport_header
> skb
->network_header
) {
215 * Get the transport protocol from the network
216 * header's data. This method works both for
217 * sent and received packets.
219 if (skb
->protocol
== htons(ETH_P_IP
)) {
220 return __get_transport_header_type_ip(skb
);
221 } else if(skb
->protocol
== htons(ETH_P_IPV6
)) {
222 return __get_transport_header_type_ipv6(skb
);
225 /* Fallthrough for other cases where header is not recognized. */
230 static struct lttng_enum_entry proto_transport_enum_entries
[] = {
232 .start
= { .value
= 0, .signedness
= 0, },
233 .end
= { .value
= IPPROTO_ICMP
- 1, .signedness
= 0, },
234 .string
= "_unknown",
237 .start
= { .value
= IPPROTO_ICMP
, .signedness
= 0, },
238 .end
= { .value
= IPPROTO_ICMP
, .signedness
= 0, },
242 .start
= { .value
= IPPROTO_ICMP
+ 1, .signedness
= 0, },
243 .end
= { .value
= IPPROTO_TCP
- 1, .signedness
= 0, },
244 .string
= "_unknown",
247 .start
= { .value
= IPPROTO_TCP
, .signedness
= 0, },
248 .end
= { .value
= IPPROTO_TCP
, .signedness
= 0, },
252 .start
= { .value
= IPPROTO_TCP
+ 1, .signedness
= 0, },
253 .end
= { .value
= IPPROTO_UDP
- 1, .signedness
= 0, },
254 .string
= "_unknown",
257 .start
= { .value
= IPPROTO_UDP
, .signedness
= 0, },
258 .end
= { .value
= IPPROTO_UDP
, .signedness
= 0, },
262 .start
= { .value
= IPPROTO_UDP
+ 1, .signedness
= 0, },
263 .end
= { .value
= 255, .signedness
= 0, },
264 .string
= "_unknown",
268 static const struct lttng_enum_desc proto_transport_header_type
= {
269 .name
= "proto_transport_header_type",
270 .entries
= proto_transport_enum_entries
,
271 .nr_entries
= ARRAY_SIZE(proto_transport_enum_entries
),
274 static struct lttng_enum_entry transport_enum_entries
[] = {
276 .start
= { .value
= TH_NONE
, .signedness
= 0, },
277 .end
= { .value
= TH_NONE
, .signedness
= 0, },
278 .string
= "_unknown",
281 .start
= { .value
= TH_TCP
, .signedness
= 0, },
282 .end
= { .value
= TH_TCP
, .signedness
= 0, },
286 .start
= { .value
= TH_UDP
, .signedness
= 0, },
287 .end
= { .value
= TH_UDP
, .signedness
= 0, },
291 .start
= { .value
= TH_ICMP
, .signedness
= 0, },
292 .end
= { .value
= TH_ICMP
, .signedness
= 0, },
297 static const struct lttng_enum_desc transport_header_type
= {
298 .name
= "transport_header_type",
299 .entries
= transport_enum_entries
,
300 .nr_entries
= ARRAY_SIZE(transport_enum_entries
),
303 /* Structures for network headers. */
305 static struct lttng_event_field ipv4fields
[] = {
308 .type
= __type_integer(uint8_t, 4, 4, 0,
309 __BIG_ENDIAN
, 10, none
),
313 .type
= __type_integer(uint8_t, 4, 4, 0,
314 __BIG_ENDIAN
, 10, none
),
318 .type
= __type_integer(uint8_t, 0, 0, 0,
319 __BIG_ENDIAN
, 10, none
),
323 .type
= __type_integer(uint16_t, 0, 0, 0,
324 __BIG_ENDIAN
, 10, none
),
328 .type
= __type_integer(uint16_t, 0, 0, 0,
329 __BIG_ENDIAN
, 16, none
),
333 .type
= __type_integer(uint16_t, 0, 0, 0,
334 __BIG_ENDIAN
, 10, none
),
338 .type
= __type_integer(uint8_t, 0, 0, 0,
339 __BIG_ENDIAN
, 10, none
),
345 .u
.basic
.enumeration
.desc
=
346 &proto_transport_header_type
,
347 .u
.basic
.enumeration
.container_type
= {
351 .reverse_byte_order
=
352 __BIG_ENDIAN
!= __BYTE_ORDER
,
354 .encoding
= lttng_encode_none
,
360 .type
= __type_integer(uint16_t, 0, 0, 0,
361 __BIG_ENDIAN
, 16, none
),
366 .atype
= atype_array
,
368 __type_integer(uint8_t, 0, 0, 0,
369 __BIG_ENDIAN
, 10, none
),
371 .u
.array
.elem_alignment
= lttng_alignof(uint8_t),
377 .atype
= atype_array
,
379 __type_integer(uint8_t, 0, 0, 0,
380 __BIG_ENDIAN
, 10, none
),
382 .u
.array
.elem_alignment
= lttng_alignof(uint8_t),
386 .name
= "transport_header_type",
389 .u
.basic
.enumeration
.desc
= &transport_header_type
,
390 .u
.basic
.enumeration
.container_type
= {
394 .reverse_byte_order
= 0,
396 .encoding
= lttng_encode_none
,
401 .name
= "transport_header",
403 .atype
= atype_variant
,
404 .u
.variant
.tag_name
= "transport_header_type",
405 .u
.variant
.choices
= transport_fields
,
406 .u
.variant
.nr_choices
= ARRAY_SIZE(transport_fields
),
411 static struct lttng_event_field ipv6fields
[] = {
414 .type
= __type_integer(uint8_t, 4, 4, 0,
415 __BIG_ENDIAN
, 10, none
),
419 .type
= __type_integer(uint8_t, 4, 4, 0,
420 __BIG_ENDIAN
, 10, none
),
425 .atype
= atype_array
,
427 __type_integer(uint8_t, 0, 0, 0,
428 __BIG_ENDIAN
, 16, none
),
430 .u
.array
.elem_alignment
= lttng_alignof(uint8_t),
434 .name
= "payload_len",
435 .type
= __type_integer(uint16_t, 0, 0, 0,
436 __BIG_ENDIAN
, 10, none
),
442 .u
.basic
.enumeration
.desc
=
443 &proto_transport_header_type
,
444 .u
.basic
.enumeration
.container_type
= {
448 .reverse_byte_order
=
449 __BIG_ENDIAN
!= __BYTE_ORDER
,
451 .encoding
= lttng_encode_none
,
457 .type
= __type_integer(uint8_t, 0, 0, 0,
458 __BIG_ENDIAN
, 10, none
),
463 .atype
= atype_array
,
465 __type_integer(uint16_t, 0, 0, 0,
466 __BIG_ENDIAN
, 16, none
),
468 .u
.array
.elem_alignment
= lttng_alignof(uint16_t),
474 .atype
= atype_array
,
476 __type_integer(uint16_t, 0, 0, 0,
477 __BIG_ENDIAN
, 16, none
),
479 .u
.array
.elem_alignment
= lttng_alignof(uint16_t),
483 .name
= "transport_header_type",
486 .u
.basic
.enumeration
.desc
= &transport_header_type
,
487 .u
.basic
.enumeration
.container_type
= {
491 .reverse_byte_order
= 0,
493 .encoding
= lttng_encode_none
,
498 .name
= "transport_header",
500 .atype
= atype_variant
,
501 .u
.variant
.tag_name
= "transport_header_type",
502 .u
.variant
.choices
= transport_fields
,
503 .u
.variant
.nr_choices
= ARRAY_SIZE(transport_fields
),
508 static struct lttng_event_field network_fields
[] = {
512 .atype
= atype_struct
,
513 .u
._struct
.nr_fields
= 0,
514 .u
._struct
.fields
= emptyfields
,
520 .atype
= atype_struct
,
521 .u
._struct
.nr_fields
= ARRAY_SIZE(ipv4fields
),
522 .u
._struct
.fields
= ipv4fields
,
528 .atype
= atype_struct
,
529 .u
._struct
.nr_fields
= ARRAY_SIZE(ipv6fields
),
530 .u
._struct
.fields
= ipv6fields
,
535 enum network_header_types
{
541 static inline unsigned char __get_network_header_type(struct sk_buff
*skb
)
543 if (__has_network_hdr(skb
)) {
544 if (skb
->protocol
== htons(ETH_P_IPV6
))
546 else if (skb
->protocol
== htons(ETH_P_IP
))
548 /* Fallthrough for other header types. */
555 LTTNG_TRACEPOINT_ENUM(net_network_header
,
557 ctf_enum_value("_unknown", NH_NONE
)
558 ctf_enum_value("_ipv4", NH_IPV4
)
559 ctf_enum_value("_ipv6", NH_IPV6
)
563 LTTNG_TRACEPOINT_EVENT(net_dev_xmit
,
565 TP_PROTO(struct sk_buff
*skb
,
567 struct net_device
*dev
,
568 unsigned int skb_len
),
570 TP_ARGS(skb
, rc
, dev
, skb_len
),
573 ctf_integer_hex(void *, skbaddr
, skb
)
574 ctf_integer(int, rc
, rc
)
575 ctf_integer(unsigned int, len
, skb_len
)
576 ctf_string(name
, dev
->name
)
580 LTTNG_TRACEPOINT_EVENT_CLASS(net_dev_template
,
582 TP_PROTO(struct sk_buff
*skb
),
587 ctf_integer_hex(void *, skbaddr
, skb
)
588 ctf_integer(unsigned int, len
, skb
->len
)
589 ctf_string(name
, skb
->dev
->name
)
590 ctf_enum(net_network_header
, unsigned char,
591 network_header_type
, __get_network_header_type(skb
))
594 .atype
= atype_variant
,
595 .u
.variant
.tag_name
= "network_header_type",
596 .u
.variant
.choices
= network_fields
,
597 .u
.variant
.nr_choices
=
598 ARRAY_SIZE(network_fields
),
602 bool has_network_header
= false;
604 /* Copy the network header. */
605 switch (__get_network_header_type(skb
)) {
608 ctf_array_type(uint8_t, ip_hdr(skb
),
609 sizeof(struct iphdr
))
610 has_network_header
= true;
615 ctf_array_type(uint8_t, ipv6_hdr(skb
),
616 sizeof(struct ipv6hdr
))
617 has_network_header
= true;
622 * For any other network header
623 * type, there is nothing to do.
628 if (has_network_header
) {
629 enum transport_header_types th_type
=
630 __get_transport_header_type(skb
);
632 /* Transport header type field. */
633 ctf_integer_type(unsigned char, th_type
)
635 /* Copy the transport header. */
639 ctf_array_type(uint8_t, tcp_hdr(skb
),
640 sizeof(struct tcphdr
))
645 ctf_array_type(uint8_t, udp_hdr(skb
),
646 sizeof(struct udphdr
))
651 ctf_array_type(uint8_t, icmp_hdr(skb
),
652 sizeof(struct icmphdr
))
657 * For any other transport header type,
658 * there is nothing to do.
668 LTTNG_TRACEPOINT_EVENT_INSTANCE(net_dev_template
, net_dev_queue
,
670 TP_PROTO(struct sk_buff
*skb
),
675 LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(net_dev_template
,
681 TP_PROTO(struct sk_buff
*skb
),
686 LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(net_dev_template
,
692 TP_PROTO(struct sk_buff
*skb
),
697 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
699 /* Trace events for the receive entry points */
700 LTTNG_TRACEPOINT_EVENT_CLASS(net_dev_receive_entry_template
,
702 TP_PROTO(const struct sk_buff
*skb
),
707 ctf_integer_hex(const void *, skbaddr
, skb
)
711 LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(net_dev_receive_entry_template
,
713 napi_gro_frags_entry
,
715 net_napi_gro_frags_entry
,
717 TP_PROTO(const struct sk_buff
*skb
),
722 LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(net_dev_receive_entry_template
,
724 napi_gro_receive_entry
,
726 net_napi_gro_receive_entry
,
728 TP_PROTO(const struct sk_buff
*skb
),
733 LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(net_dev_receive_entry_template
,
735 netif_receive_skb_entry
,
737 net_if_receive_skb_entry
,
739 TP_PROTO(const struct sk_buff
*skb
),
744 LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(net_dev_receive_entry_template
,
750 TP_PROTO(const struct sk_buff
*skb
),
755 LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(net_dev_receive_entry_template
,
761 TP_PROTO(const struct sk_buff
*skb
),
766 #endif /* kernel > 3.14 */
768 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,19,0))
770 LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(net_dev_receive_entry_template
,
772 netif_receive_skb_list_entry
,
774 net_if_receive_skb_list_entry
,
776 TP_PROTO(const struct sk_buff
*skb
),
781 #endif /* kernel > 4.19 */
783 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0))
785 /* Trace events for the receive exit points */
786 LTTNG_TRACEPOINT_EVENT_CLASS(net_dev_receive_exit_template
,
793 ctf_integer(int, ret
, ret
)
797 LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(net_dev_receive_exit_template
,
801 net_napi_gro_frags_exit
,
808 LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(net_dev_receive_exit_template
,
810 napi_gro_receive_exit
,
812 net_napi_gro_receive_exit
,
819 LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(net_dev_receive_exit_template
,
821 netif_receive_skb_exit
,
823 net_if_receive_skb_exit
,
830 LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(net_dev_receive_exit_template
,
841 LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(net_dev_receive_exit_template
,
852 LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(net_dev_receive_exit_template
,
854 netif_receive_skb_list_exit
,
856 net_if_receive_skb_list_exit
,
863 #endif /* kernel > 5.0.0 */
865 #endif /* LTTNG_TRACE_NET_H */
867 /* This part must be outside protection */
868 #include <probes/define_trace.h>