net: Add entry/exit tracepoints for all receive paths
[lttng-modules.git] / instrumentation / events / lttng-module / net.h
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #undef TRACE_SYSTEM
3 #define TRACE_SYSTEM net
4
5 #if !defined(LTTNG_TRACE_NET_H) || defined(TRACE_HEADER_MULTI_READ)
6 #define LTTNG_TRACE_NET_H
7
8 #include <probes/lttng-tracepoint-event.h>
9 #include <linux/skbuff.h>
10 #include <linux/netdevice.h>
11 #include <linux/ip.h>
12 #include <linux/ipv6.h>
13 #include <linux/tcp.h>
14 #include <linux/version.h>
15 #include <lttng-endian.h>
16 #include <net/sock.h>
17
18 #ifndef ONCE_LTTNG_NET_H
19 #define ONCE_LTTNG_NET_H
20
21 static inline unsigned char __has_network_hdr(struct sk_buff *skb)
22 {
23 /*
24 * If the header is not set yet, the network header will point
25 * to the head.
26 */
27 return skb_network_header(skb) != skb->head;
28 }
29
30 static struct lttng_event_field emptyfields[] = {
31 };
32
33 /* Structures for transport headers. */
34
35 static struct lttng_event_field tcpfields[] = {
36 [0] = {
37 .name = "source_port",
38 .type = __type_integer(uint16_t, 0, 0, 0,
39 __BIG_ENDIAN, 10, none),
40 },
41 [1] = {
42 .name = "dest_port",
43 .type = __type_integer(uint16_t, 0, 0, 0,
44 __BIG_ENDIAN, 10, none),
45 },
46 [2] = {
47 .name = "seq",
48 .type = __type_integer(uint32_t, 0, 0, 0,
49 __BIG_ENDIAN, 10, none),
50 },
51 [3] = {
52 .name = "ack_seq",
53 .type = __type_integer(uint32_t, 0, 0, 0,
54 __BIG_ENDIAN, 10, none),
55 },
56 [4] = {
57 .name = "data_offset",
58 .type = __type_integer(uint8_t, 4, 4, 0,
59 __BIG_ENDIAN, 10, none),
60 },
61 [5] = {
62 .name = "reserved",
63 .type = __type_integer(uint8_t, 3, 1, 0,
64 __BIG_ENDIAN, 10, none),
65 },
66 [6] = {
67 .name = "flags",
68 .type = __type_integer(uint8_t, 9, 1, 0,
69 __BIG_ENDIAN, 16, none),
70 },
71 [7] = {
72 .name = "window_size",
73 .type = __type_integer(uint16_t, 0, 0, 0,
74 __BIG_ENDIAN, 10, none),
75 },
76 [8] = {
77 .name = "checksum",
78 .type = __type_integer(uint16_t, 0, 0, 0,
79 __BIG_ENDIAN, 16, none),
80 },
81 [9] = {
82 .name = "urg_ptr",
83 .type = __type_integer(uint16_t, 0, 0, 0,
84 __BIG_ENDIAN, 10, none),
85 },
86 };
87
88 static struct lttng_event_field transport_fields[] = {
89 [0] = {
90 .name = "unknown",
91 .type = {
92 .atype = atype_struct,
93 .u._struct.nr_fields = ARRAY_SIZE(emptyfields),
94 .u._struct.fields = emptyfields,
95 },
96 },
97 [1] = {
98 .name = "tcp",
99 .type = {
100 .atype = atype_struct,
101 .u._struct.nr_fields = ARRAY_SIZE(tcpfields),
102 .u._struct.fields = tcpfields,
103 },
104 },
105 };
106
107 enum transport_header_types {
108 TH_NONE = 0,
109 TH_TCP = 1,
110 };
111
112 static inline enum transport_header_types __get_transport_header_type(struct sk_buff *skb)
113 {
114 if (__has_network_hdr(skb)) {
115 /*
116 * When both transport and network headers are set,
117 * transport header is greater than network header,
118 * otherwise it points to head.
119 */
120 if (skb->transport_header > skb->network_header) {
121 /*
122 * Get the transport protocol from the network
123 * header's data. This method works both for
124 * sent and received packets.
125 */
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))
130 return TH_TCP;
131 }
132 /* Fallthrough for other cases where header is not TCP. */
133 }
134 return TH_NONE;
135 }
136
137 static struct lttng_enum_entry proto_transport_enum_entries[] = {
138 [0] = {
139 .start = { .value = 0, .signedness = 0, },
140 .end = { .value = IPPROTO_TCP - 1, .signedness = 0, },
141 .string = "_unknown",
142 },
143 [1] = {
144 .start = { .value = IPPROTO_TCP, .signedness = 0, },
145 .end = { .value = IPPROTO_TCP, .signedness = 0, },
146 .string = "_tcp",
147 },
148 [2] = {
149 .start = { .value = IPPROTO_TCP + 1, .signedness = 0, },
150 .end = { .value = 255, .signedness = 0, },
151 .string = "_unknown",
152 },
153 };
154
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),
159 };
160
161 static struct lttng_enum_entry transport_enum_entries[] = {
162 [0] = {
163 .start = { .value = TH_NONE, .signedness = 0, },
164 .end = { .value = TH_NONE, .signedness = 0, },
165 .string = "_unknown",
166 },
167 [1] = {
168 .start = { .value = TH_TCP, .signedness = 0, },
169 .end = { .value = TH_TCP, .signedness = 0, },
170 .string = "_tcp",
171 },
172 };
173
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),
178 };
179
180 /* Structures for network headers. */
181
182 static struct lttng_event_field ipv4fields[] = {
183 [0] = {
184 .name = "version",
185 .type = __type_integer(uint8_t, 4, 4, 0,
186 __BIG_ENDIAN, 10, none),
187 },
188 [1] = {
189 .name = "ihl",
190 .type = __type_integer(uint8_t, 4, 4, 0,
191 __BIG_ENDIAN, 10, none),
192 },
193 [2] = {
194 .name = "tos",
195 .type = __type_integer(uint8_t, 0, 0, 0,
196 __BIG_ENDIAN, 10, none),
197 },
198 [3] = {
199 .name = "tot_len",
200 .type = __type_integer(uint16_t, 0, 0, 0,
201 __BIG_ENDIAN, 10, none),
202 },
203 [4] = {
204 .name = "id",
205 .type = __type_integer(uint16_t, 0, 0, 0,
206 __BIG_ENDIAN, 16, none),
207 },
208 [5] = {
209 .name = "frag_off",
210 .type = __type_integer(uint16_t, 0, 0, 0,
211 __BIG_ENDIAN, 10, none),
212 },
213 [6] = {
214 .name = "ttl",
215 .type = __type_integer(uint8_t, 0, 0, 0,
216 __BIG_ENDIAN, 10, none),
217 },
218 [7] = {
219 .name = "protocol",
220 .type = {
221 .atype = atype_enum,
222 .u.basic.enumeration.desc =
223 &proto_transport_header_type,
224 .u.basic.enumeration.container_type = {
225 .size = 8,
226 .alignment = 8,
227 .signedness = 0,
228 .reverse_byte_order =
229 __BIG_ENDIAN != __BYTE_ORDER,
230 .base = 10,
231 .encoding = lttng_encode_none,
232 },
233 },
234 },
235 [8] = {
236 .name = "checksum",
237 .type = __type_integer(uint16_t, 0, 0, 0,
238 __BIG_ENDIAN, 16, none),
239 },
240 [9] = {
241 .name = "saddr",
242 .type = {
243 .atype = atype_array,
244 .u.array.elem_type =
245 __type_integer(uint8_t, 0, 0, 0,
246 __BIG_ENDIAN, 10, none),
247 .u.array.length = 4,
248 .u.array.elem_alignment = lttng_alignof(uint8_t),
249 },
250 },
251 [10] = {
252 .name = "daddr",
253 .type = {
254 .atype = atype_array,
255 .u.array.elem_type =
256 __type_integer(uint8_t, 0, 0, 0,
257 __BIG_ENDIAN, 10, none),
258 .u.array.length = 4,
259 .u.array.elem_alignment = lttng_alignof(uint8_t),
260 },
261 },
262 [11] = {
263 .name = "transport_header_type",
264 .type = {
265 .atype = atype_enum,
266 .u.basic.enumeration.desc = &transport_header_type,
267 .u.basic.enumeration.container_type = {
268 .size = 8,
269 .alignment = 8,
270 .signedness = 0,
271 .reverse_byte_order = 0,
272 .base = 10,
273 .encoding = lttng_encode_none,
274 },
275 },
276 },
277 [12] = {
278 .name = "transport_header",
279 .type = {
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),
284 },
285 },
286 };
287
288 static struct lttng_event_field ipv6fields[] = {
289 [0] = {
290 .name = "version",
291 .type = __type_integer(uint8_t, 4, 4, 0,
292 __BIG_ENDIAN, 10, none),
293 },
294 [1] = {
295 .name = "prio",
296 .type = __type_integer(uint8_t, 4, 4, 0,
297 __BIG_ENDIAN, 10, none),
298 },
299 [2] = {
300 .name = "flow_lbl",
301 .type = {
302 .atype = atype_array,
303 .u.array.elem_type =
304 __type_integer(uint8_t, 0, 0, 0,
305 __BIG_ENDIAN, 16, none),
306 .u.array.length = 3,
307 .u.array.elem_alignment = lttng_alignof(uint8_t),
308 },
309 },
310 [3] = {
311 .name = "payload_len",
312 .type = __type_integer(uint16_t, 0, 0, 0,
313 __BIG_ENDIAN, 10, none),
314 },
315 [4] = {
316 .name = "nexthdr",
317 .type = {
318 .atype = atype_enum,
319 .u.basic.enumeration.desc =
320 &proto_transport_header_type,
321 .u.basic.enumeration.container_type = {
322 .size = 8,
323 .alignment = 8,
324 .signedness = 0,
325 .reverse_byte_order =
326 __BIG_ENDIAN != __BYTE_ORDER,
327 .base = 10,
328 .encoding = lttng_encode_none,
329 },
330 },
331 },
332 [5] = {
333 .name = "hop_limit",
334 .type = __type_integer(uint8_t, 0, 0, 0,
335 __BIG_ENDIAN, 10, none),
336 },
337 [6] = {
338 .name = "saddr",
339 .type = {
340 .atype = atype_array,
341 .u.array.elem_type =
342 __type_integer(uint16_t, 0, 0, 0,
343 __BIG_ENDIAN, 16, none),
344 .u.array.length = 8,
345 .u.array.elem_alignment = lttng_alignof(uint16_t),
346 },
347 },
348 [7] = {
349 .name = "daddr",
350 .type = {
351 .atype = atype_array,
352 .u.array.elem_type =
353 __type_integer(uint16_t, 0, 0, 0,
354 __BIG_ENDIAN, 16, none),
355 .u.array.length = 8,
356 .u.array.elem_alignment = lttng_alignof(uint16_t),
357 },
358 },
359 [8] = {
360 .name = "transport_header_type",
361 .type = {
362 .atype = atype_enum,
363 .u.basic.enumeration.desc = &transport_header_type,
364 .u.basic.enumeration.container_type = {
365 .size = 8,
366 .alignment = 8,
367 .signedness = 0,
368 .reverse_byte_order = 0,
369 .base = 10,
370 .encoding = lttng_encode_none,
371 },
372 },
373 },
374 [9] = {
375 .name = "transport_header",
376 .type = {
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),
381 },
382 },
383 };
384
385 static struct lttng_event_field network_fields[] = {
386 [0] = {
387 .name = "unknown",
388 .type = {
389 .atype = atype_struct,
390 .u._struct.nr_fields = 0,
391 .u._struct.fields = emptyfields,
392 },
393 },
394 [1] = {
395 .name = "ipv4",
396 .type = {
397 .atype = atype_struct,
398 .u._struct.nr_fields = ARRAY_SIZE(ipv4fields),
399 .u._struct.fields = ipv4fields,
400 },
401 },
402 [2] = {
403 .name = "ipv6",
404 .type = {
405 .atype = atype_struct,
406 .u._struct.nr_fields = ARRAY_SIZE(ipv6fields),
407 .u._struct.fields = ipv6fields,
408 },
409 },
410 };
411
412 enum network_header_types {
413 NH_NONE,
414 NH_IPV4,
415 NH_IPV6,
416 };
417
418 static inline unsigned char __get_network_header_type(struct sk_buff *skb)
419 {
420 if (__has_network_hdr(skb)) {
421 if (skb->protocol == htons(ETH_P_IPV6))
422 return NH_IPV6;
423 else if (skb->protocol == htons(ETH_P_IP))
424 return NH_IPV4;
425 /* Fallthrough for other header types. */
426 }
427 return NH_NONE;
428 }
429
430 #endif
431
432 LTTNG_TRACEPOINT_ENUM(net_network_header,
433 TP_ENUM_VALUES(
434 ctf_enum_value("_unknown", NH_NONE)
435 ctf_enum_value("_ipv4", NH_IPV4)
436 ctf_enum_value("_ipv6", NH_IPV6)
437 )
438 )
439
440 LTTNG_TRACEPOINT_EVENT(net_dev_xmit,
441
442 TP_PROTO(struct sk_buff *skb,
443 int rc,
444 struct net_device *dev,
445 unsigned int skb_len),
446
447 TP_ARGS(skb, rc, dev, skb_len),
448
449 TP_FIELDS(
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)
454 )
455 )
456
457 LTTNG_TRACEPOINT_EVENT_CLASS(net_dev_template,
458
459 TP_PROTO(struct sk_buff *skb),
460
461 TP_ARGS(skb),
462
463 TP_FIELDS(
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))
469 ctf_custom_field(
470 ctf_custom_type(
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),
476 ),
477 network_header,
478 ctf_custom_code(
479 bool has_network_header = false;
480
481 /* Copy the network header. */
482 switch (__get_network_header_type(skb)) {
483 case NH_IPV4: {
484 ctf_align(uint16_t)
485 ctf_array_type(uint8_t, ip_hdr(skb),
486 sizeof(struct iphdr))
487 has_network_header = true;
488 break;
489 }
490 case NH_IPV6: {
491 ctf_align(uint16_t)
492 ctf_array_type(uint8_t, ipv6_hdr(skb),
493 sizeof(struct ipv6hdr))
494 has_network_header = true;
495 break;
496 }
497 default:
498 /*
499 * For any other network header
500 * type, there is nothing to do.
501 */
502 break;
503 }
504
505 if (has_network_header) {
506 enum transport_header_types th_type =
507 __get_transport_header_type(skb);
508
509 /* Transport header type field. */
510 ctf_integer_type(unsigned char, th_type)
511
512 /* Copy the transport header. */
513 if (th_type == TH_TCP) {
514 ctf_align(uint32_t)
515 ctf_array_type(uint8_t, tcp_hdr(skb),
516 sizeof(struct tcphdr))
517 }
518 /*
519 * For any other transport header type,
520 * there is nothing to do.
521 */
522 }
523 )
524 )
525 )
526 )
527
528 LTTNG_TRACEPOINT_EVENT_INSTANCE(net_dev_template, net_dev_queue,
529
530 TP_PROTO(struct sk_buff *skb),
531
532 TP_ARGS(skb)
533 )
534
535 LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(net_dev_template,
536
537 netif_receive_skb,
538
539 net_if_receive_skb,
540
541 TP_PROTO(struct sk_buff *skb),
542
543 TP_ARGS(skb)
544 )
545
546 LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(net_dev_template,
547
548 netif_rx,
549
550 net_if_rx,
551
552 TP_PROTO(struct sk_buff *skb),
553
554 TP_ARGS(skb)
555 )
556
557 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
558
559 /* Trace events for the receive entry points */
560 LTTNG_TRACEPOINT_EVENT_CLASS(net_dev_receive_entry_template,
561
562 TP_PROTO(const struct sk_buff *skb),
563
564 TP_ARGS(skb),
565
566 TP_FIELDS(
567 ctf_integer_hex(const void *, skbaddr, skb)
568 )
569 )
570
571 LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(net_dev_receive_entry_template,
572
573 napi_gro_frags_entry,
574
575 net_napi_gro_frags_entry,
576
577 TP_PROTO(const struct sk_buff *skb),
578
579 TP_ARGS(skb)
580 )
581
582 LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(net_dev_receive_entry_template,
583
584 napi_gro_receive_entry,
585
586 net_napi_gro_receive_entry,
587
588 TP_PROTO(const struct sk_buff *skb),
589
590 TP_ARGS(skb)
591 )
592
593 LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(net_dev_receive_entry_template,
594
595 netif_receive_skb_entry,
596
597 net_if_receive_skb_entry,
598
599 TP_PROTO(const struct sk_buff *skb),
600
601 TP_ARGS(skb)
602 )
603
604 LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(net_dev_receive_entry_template,
605
606 netif_rx_entry,
607
608 net_if_rx_entry,
609
610 TP_PROTO(const struct sk_buff *skb),
611
612 TP_ARGS(skb)
613 )
614
615 LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(net_dev_receive_entry_template,
616
617 netif_rx_ni_entry,
618
619 net_if_rx_ni_entry,
620
621 TP_PROTO(const struct sk_buff *skb),
622
623 TP_ARGS(skb)
624 )
625
626 #endif /* kernel > 3.14 */
627
628 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,19,0))
629
630 LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(net_dev_receive_entry_template,
631
632 netif_receive_skb_list_entry,
633
634 net_if_receive_skb_list_entry,
635
636 TP_PROTO(const struct sk_buff *skb),
637
638 TP_ARGS(skb)
639 )
640
641 #endif /* kernel > 4.19 */
642
643 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0))
644
645 /* Trace events for the receive exit points */
646 LTTNG_TRACEPOINT_EVENT_CLASS(net_dev_receive_exit_template,
647
648 TP_PROTO(int ret),
649
650 TP_ARGS(ret),
651
652 TP_FIELDS(
653 ctf_integer(int, ret, ret)
654 )
655 )
656
657 LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(net_dev_receive_exit_template,
658
659 napi_gro_frags_exit,
660
661 net_napi_gro_frags_exit,
662
663 TP_PROTO(int ret),
664
665 TP_ARGS(ret)
666 )
667
668 LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(net_dev_receive_exit_template,
669
670 napi_gro_receive_exit,
671
672 net_napi_gro_receive_exit,
673
674 TP_PROTO(int ret),
675
676 TP_ARGS(ret)
677 )
678
679 LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(net_dev_receive_exit_template,
680
681 netif_receive_skb_exit,
682
683 net_if_receive_skb_exit,
684
685 TP_PROTO(int ret),
686
687 TP_ARGS(ret)
688 )
689
690 LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(net_dev_receive_exit_template,
691
692 netif_rx_exit,
693
694 net_if_rx_exit,
695
696 TP_PROTO(int ret),
697
698 TP_ARGS(ret)
699 )
700
701 LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(net_dev_receive_exit_template,
702
703 netif_rx_ni_exit,
704
705 net_if_rx_ni_exit,
706
707 TP_PROTO(int ret),
708
709 TP_ARGS(ret)
710 )
711
712 LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(net_dev_receive_exit_template,
713
714 netif_receive_skb_list_exit,
715
716 net_if_receive_skb_list_exit,
717
718 TP_PROTO(int ret),
719
720 TP_ARGS(ret)
721 )
722
723 #endif /* kernel > 5.0.0 */
724
725 #endif /* LTTNG_TRACE_NET_H */
726
727 /* This part must be outside protection */
728 #include <probes/define_trace.h>
This page took 0.049481 seconds and 4 git commands to generate.