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/version.h>
15 #include <lttng-endian.h>
18 #ifndef ONCE_LTTNG_NET_H
19 #define ONCE_LTTNG_NET_H
21 static inline unsigned char __has_network_hdr(struct sk_buff
*skb
)
24 * If the header is not set yet, the network header will point
27 return skb_network_header(skb
) != skb
->head
;
30 static struct lttng_event_field emptyfields
[] = {
33 /* Structures for transport headers. */
35 static struct lttng_event_field tcpfields
[] = {
37 .name
= "source_port",
38 .type
= __type_integer(uint16_t, 0, 0, 0,
39 __BIG_ENDIAN
, 10, none
),
43 .type
= __type_integer(uint16_t, 0, 0, 0,
44 __BIG_ENDIAN
, 10, none
),
48 .type
= __type_integer(uint32_t, 0, 0, 0,
49 __BIG_ENDIAN
, 10, none
),
53 .type
= __type_integer(uint32_t, 0, 0, 0,
54 __BIG_ENDIAN
, 10, none
),
57 .name
= "data_offset",
58 .type
= __type_integer(uint8_t, 4, 4, 0,
59 __BIG_ENDIAN
, 10, none
),
63 .type
= __type_integer(uint8_t, 3, 1, 0,
64 __BIG_ENDIAN
, 10, none
),
68 .type
= __type_integer(uint8_t, 9, 1, 0,
69 __BIG_ENDIAN
, 16, none
),
72 .name
= "window_size",
73 .type
= __type_integer(uint16_t, 0, 0, 0,
74 __BIG_ENDIAN
, 10, none
),
78 .type
= __type_integer(uint16_t, 0, 0, 0,
79 __BIG_ENDIAN
, 16, none
),
83 .type
= __type_integer(uint16_t, 0, 0, 0,
84 __BIG_ENDIAN
, 10, none
),
88 static struct lttng_event_field transport_fields
[] = {
92 .atype
= atype_struct
,
93 .u
._struct
.nr_fields
= ARRAY_SIZE(emptyfields
),
94 .u
._struct
.fields
= emptyfields
,
100 .atype
= atype_struct
,
101 .u
._struct
.nr_fields
= ARRAY_SIZE(tcpfields
),
102 .u
._struct
.fields
= tcpfields
,
107 enum transport_header_types
{
112 static inline enum transport_header_types
__get_transport_header_type(struct sk_buff
*skb
)
114 if (__has_network_hdr(skb
)) {
116 * When both transport and network headers are set,
117 * transport header is greater than network header,
118 * otherwise it points to head.
120 if (skb
->transport_header
> skb
->network_header
) {
122 * Get the transport protocol from the network
123 * header's data. This method works both for
124 * sent and received packets.
126 if ((skb
->protocol
== htons(ETH_P_IP
) &&
127 ip_hdr(skb
)->protocol
== IPPROTO_TCP
) ||
128 (skb
->protocol
== htons(ETH_P_IPV6
) &&
129 ipv6_hdr(skb
)->nexthdr
== IPPROTO_TCP
))
132 /* Fallthrough for other cases where header is not TCP. */
137 static struct lttng_enum_entry proto_transport_enum_entries
[] = {
139 .start
= { .value
= 0, .signedness
= 0, },
140 .end
= { .value
= IPPROTO_TCP
- 1, .signedness
= 0, },
141 .string
= "_unknown",
144 .start
= { .value
= IPPROTO_TCP
, .signedness
= 0, },
145 .end
= { .value
= IPPROTO_TCP
, .signedness
= 0, },
149 .start
= { .value
= IPPROTO_TCP
+ 1, .signedness
= 0, },
150 .end
= { .value
= 255, .signedness
= 0, },
151 .string
= "_unknown",
155 static const struct lttng_enum_desc proto_transport_header_type
= {
156 .name
= "proto_transport_header_type",
157 .entries
= proto_transport_enum_entries
,
158 .nr_entries
= ARRAY_SIZE(proto_transport_enum_entries
),
161 static struct lttng_enum_entry transport_enum_entries
[] = {
163 .start
= { .value
= TH_NONE
, .signedness
= 0, },
164 .end
= { .value
= TH_NONE
, .signedness
= 0, },
165 .string
= "_unknown",
168 .start
= { .value
= TH_TCP
, .signedness
= 0, },
169 .end
= { .value
= TH_TCP
, .signedness
= 0, },
174 static const struct lttng_enum_desc transport_header_type
= {
175 .name
= "transport_header_type",
176 .entries
= transport_enum_entries
,
177 .nr_entries
= ARRAY_SIZE(transport_enum_entries
),
180 /* Structures for network headers. */
182 static struct lttng_event_field ipv4fields
[] = {
185 .type
= __type_integer(uint8_t, 4, 4, 0,
186 __BIG_ENDIAN
, 10, none
),
190 .type
= __type_integer(uint8_t, 4, 4, 0,
191 __BIG_ENDIAN
, 10, none
),
195 .type
= __type_integer(uint8_t, 0, 0, 0,
196 __BIG_ENDIAN
, 10, none
),
200 .type
= __type_integer(uint16_t, 0, 0, 0,
201 __BIG_ENDIAN
, 10, none
),
205 .type
= __type_integer(uint16_t, 0, 0, 0,
206 __BIG_ENDIAN
, 16, none
),
210 .type
= __type_integer(uint16_t, 0, 0, 0,
211 __BIG_ENDIAN
, 10, none
),
215 .type
= __type_integer(uint8_t, 0, 0, 0,
216 __BIG_ENDIAN
, 10, none
),
222 .u
.basic
.enumeration
.desc
=
223 &proto_transport_header_type
,
224 .u
.basic
.enumeration
.container_type
= {
228 .reverse_byte_order
=
229 __BIG_ENDIAN
!= __BYTE_ORDER
,
231 .encoding
= lttng_encode_none
,
237 .type
= __type_integer(uint16_t, 0, 0, 0,
238 __BIG_ENDIAN
, 16, none
),
243 .atype
= atype_array
,
245 __type_integer(uint8_t, 0, 0, 0,
246 __BIG_ENDIAN
, 10, none
),
248 .u
.array
.elem_alignment
= lttng_alignof(uint8_t),
254 .atype
= atype_array
,
256 __type_integer(uint8_t, 0, 0, 0,
257 __BIG_ENDIAN
, 10, none
),
259 .u
.array
.elem_alignment
= lttng_alignof(uint8_t),
263 .name
= "transport_header_type",
266 .u
.basic
.enumeration
.desc
= &transport_header_type
,
267 .u
.basic
.enumeration
.container_type
= {
271 .reverse_byte_order
= 0,
273 .encoding
= lttng_encode_none
,
278 .name
= "transport_header",
280 .atype
= atype_variant
,
281 .u
.variant
.tag_name
= "transport_header_type",
282 .u
.variant
.choices
= transport_fields
,
283 .u
.variant
.nr_choices
= ARRAY_SIZE(transport_fields
),
288 static struct lttng_event_field ipv6fields
[] = {
291 .type
= __type_integer(uint8_t, 4, 4, 0,
292 __BIG_ENDIAN
, 10, none
),
296 .type
= __type_integer(uint8_t, 4, 4, 0,
297 __BIG_ENDIAN
, 10, none
),
302 .atype
= atype_array
,
304 __type_integer(uint8_t, 0, 0, 0,
305 __BIG_ENDIAN
, 16, none
),
307 .u
.array
.elem_alignment
= lttng_alignof(uint8_t),
311 .name
= "payload_len",
312 .type
= __type_integer(uint16_t, 0, 0, 0,
313 __BIG_ENDIAN
, 10, none
),
319 .u
.basic
.enumeration
.desc
=
320 &proto_transport_header_type
,
321 .u
.basic
.enumeration
.container_type
= {
325 .reverse_byte_order
=
326 __BIG_ENDIAN
!= __BYTE_ORDER
,
328 .encoding
= lttng_encode_none
,
334 .type
= __type_integer(uint8_t, 0, 0, 0,
335 __BIG_ENDIAN
, 10, none
),
340 .atype
= atype_array
,
342 __type_integer(uint16_t, 0, 0, 0,
343 __BIG_ENDIAN
, 16, none
),
345 .u
.array
.elem_alignment
= lttng_alignof(uint16_t),
351 .atype
= atype_array
,
353 __type_integer(uint16_t, 0, 0, 0,
354 __BIG_ENDIAN
, 16, none
),
356 .u
.array
.elem_alignment
= lttng_alignof(uint16_t),
360 .name
= "transport_header_type",
363 .u
.basic
.enumeration
.desc
= &transport_header_type
,
364 .u
.basic
.enumeration
.container_type
= {
368 .reverse_byte_order
= 0,
370 .encoding
= lttng_encode_none
,
375 .name
= "transport_header",
377 .atype
= atype_variant
,
378 .u
.variant
.tag_name
= "transport_header_type",
379 .u
.variant
.choices
= transport_fields
,
380 .u
.variant
.nr_choices
= ARRAY_SIZE(transport_fields
),
385 static struct lttng_event_field network_fields
[] = {
389 .atype
= atype_struct
,
390 .u
._struct
.nr_fields
= 0,
391 .u
._struct
.fields
= emptyfields
,
397 .atype
= atype_struct
,
398 .u
._struct
.nr_fields
= ARRAY_SIZE(ipv4fields
),
399 .u
._struct
.fields
= ipv4fields
,
405 .atype
= atype_struct
,
406 .u
._struct
.nr_fields
= ARRAY_SIZE(ipv6fields
),
407 .u
._struct
.fields
= ipv6fields
,
412 enum network_header_types
{
418 static inline unsigned char __get_network_header_type(struct sk_buff
*skb
)
420 if (__has_network_hdr(skb
)) {
421 if (skb
->protocol
== htons(ETH_P_IPV6
))
423 else if (skb
->protocol
== htons(ETH_P_IP
))
425 /* Fallthrough for other header types. */
432 LTTNG_TRACEPOINT_ENUM(net_network_header
,
434 ctf_enum_value("_unknown", NH_NONE
)
435 ctf_enum_value("_ipv4", NH_IPV4
)
436 ctf_enum_value("_ipv6", NH_IPV6
)
440 LTTNG_TRACEPOINT_EVENT(net_dev_xmit
,
442 TP_PROTO(struct sk_buff
*skb
,
444 struct net_device
*dev
,
445 unsigned int skb_len
),
447 TP_ARGS(skb
, rc
, dev
, skb_len
),
450 ctf_integer_hex(void *, skbaddr
, skb
)
451 ctf_integer(int, rc
, rc
)
452 ctf_integer(unsigned int, len
, skb_len
)
453 ctf_string(name
, dev
->name
)
457 LTTNG_TRACEPOINT_EVENT_CLASS(net_dev_template
,
459 TP_PROTO(struct sk_buff
*skb
),
464 ctf_integer_hex(void *, skbaddr
, skb
)
465 ctf_integer(unsigned int, len
, skb
->len
)
466 ctf_string(name
, skb
->dev
->name
)
467 ctf_enum(net_network_header
, unsigned char,
468 network_header_type
, __get_network_header_type(skb
))
471 .atype
= atype_variant
,
472 .u
.variant
.tag_name
= "network_header_type",
473 .u
.variant
.choices
= network_fields
,
474 .u
.variant
.nr_choices
=
475 ARRAY_SIZE(network_fields
),
479 bool has_network_header
= false;
481 /* Copy the network header. */
482 switch (__get_network_header_type(skb
)) {
485 ctf_array_type(uint8_t, ip_hdr(skb
),
486 sizeof(struct iphdr
))
487 has_network_header
= true;
492 ctf_array_type(uint8_t, ipv6_hdr(skb
),
493 sizeof(struct ipv6hdr
))
494 has_network_header
= true;
499 * For any other network header
500 * type, there is nothing to do.
505 if (has_network_header
) {
506 enum transport_header_types th_type
=
507 __get_transport_header_type(skb
);
509 /* Transport header type field. */
510 ctf_integer_type(unsigned char, th_type
)
512 /* Copy the transport header. */
513 if (th_type
== TH_TCP
) {
515 ctf_array_type(uint8_t, tcp_hdr(skb
),
516 sizeof(struct tcphdr
))
519 * For any other transport header type,
520 * there is nothing to do.
528 LTTNG_TRACEPOINT_EVENT_INSTANCE(net_dev_template
, net_dev_queue
,
530 TP_PROTO(struct sk_buff
*skb
),
535 LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(net_dev_template
,
541 TP_PROTO(struct sk_buff
*skb
),
546 LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(net_dev_template
,
552 TP_PROTO(struct sk_buff
*skb
),
556 #endif /* LTTNG_TRACE_NET_H */
558 /* This part must be outside protection */
559 #include <probes/define_trace.h>