Fix: network instrumentation protocol enum
[lttng-modules.git] / instrumentation / events / lttng-module / net.h
CommitLineData
b283666f
PW
1#undef TRACE_SYSTEM
2#define TRACE_SYSTEM net
3
3bc29f0a
MD
4#if !defined(LTTNG_TRACE_NET_H) || defined(TRACE_HEADER_MULTI_READ)
5#define LTTNG_TRACE_NET_H
b283666f 6
6ec43db8 7#include <probes/lttng-tracepoint-event.h>
b283666f
PW
8#include <linux/skbuff.h>
9#include <linux/netdevice.h>
10#include <linux/ip.h>
e5990fd4
GB
11#include <linux/ipv6.h>
12#include <linux/tcp.h>
4a7363f7 13#include <linux/version.h>
e5990fd4
GB
14#include <lttng-endian.h>
15#include <net/sock.h>
16
17#ifndef ONCE_LTTNG_NET_H
18#define ONCE_LTTNG_NET_H
19
20static inline unsigned char __has_network_hdr(struct sk_buff *skb)
21{
22 /*
aa900596
MD
23 * If the header is not set yet, the network header will point
24 * to the head.
e5990fd4
GB
25 */
26 return skb_network_header(skb) != skb->head;
27}
28
29static struct lttng_event_field emptyfields[] = {
30};
31
9cf9736a
GB
32/* Structures for transport headers. */
33
34static struct lttng_event_field tcpfields[] = {
35 [0] = {
36 .name = "source_port",
aa900596
MD
37 .type = __type_integer(uint16_t, 0, 0, 0,
38 __BIG_ENDIAN, 10, none),
9cf9736a
GB
39 },
40 [1] = {
41 .name = "dest_port",
aa900596
MD
42 .type = __type_integer(uint16_t, 0, 0, 0,
43 __BIG_ENDIAN, 10, none),
9cf9736a
GB
44 },
45 [2] = {
46 .name = "seq",
aa900596
MD
47 .type = __type_integer(uint32_t, 0, 0, 0,
48 __BIG_ENDIAN, 10, none),
9cf9736a
GB
49 },
50 [3] = {
51 .name = "ack_seq",
aa900596
MD
52 .type = __type_integer(uint32_t, 0, 0, 0,
53 __BIG_ENDIAN, 10, none),
9cf9736a
GB
54 },
55 [4] = {
56 .name = "data_offset",
aa900596
MD
57 .type = __type_integer(uint8_t, 4, 4, 0,
58 __BIG_ENDIAN, 10, none),
9cf9736a
GB
59 },
60 [5] = {
61 .name = "reserved",
aa900596
MD
62 .type = __type_integer(uint8_t, 3, 1, 0,
63 __BIG_ENDIAN, 10, none),
9cf9736a
GB
64 },
65 [6] = {
66 .name = "flags",
aa900596
MD
67 .type = __type_integer(uint8_t, 9, 1, 0,
68 __BIG_ENDIAN, 16, none),
9cf9736a
GB
69 },
70 [7] = {
71 .name = "window_size",
aa900596
MD
72 .type = __type_integer(uint16_t, 0, 0, 0,
73 __BIG_ENDIAN, 10, none),
9cf9736a
GB
74 },
75 [8] = {
76 .name = "checksum",
aa900596
MD
77 .type = __type_integer(uint16_t, 0, 0, 0,
78 __BIG_ENDIAN, 16, none),
9cf9736a
GB
79 },
80 [9] = {
81 .name = "urg_ptr",
aa900596
MD
82 .type = __type_integer(uint16_t, 0, 0, 0,
83 __BIG_ENDIAN, 10, none),
9cf9736a
GB
84 },
85};
86
87static struct lttng_event_field transport_fields[] = {
88 [0] = {
89 .name = "unknown",
90 .type = {
91 .atype = atype_struct,
92 .u._struct.nr_fields = ARRAY_SIZE(emptyfields),
93 .u._struct.fields = emptyfields,
94 },
95 },
96 [1] = {
97 .name = "tcp",
98 .type = {
99 .atype = atype_struct,
100 .u._struct.nr_fields = ARRAY_SIZE(tcpfields),
101 .u._struct.fields = tcpfields,
102 },
103 },
104};
105
106enum transport_header_types {
0910ab71
MD
107 TH_NONE = 0,
108 TH_TCP = 1,
9cf9736a
GB
109};
110
0910ab71 111static inline enum transport_header_types __get_transport_header_type(struct sk_buff *skb)
9cf9736a
GB
112{
113 if (__has_network_hdr(skb)) {
114 /*
aa900596
MD
115 * When both transport and network headers are set,
116 * transport header is greater than network header,
117 * otherwise it points to head.
9cf9736a
GB
118 */
119 if (skb->transport_header > skb->network_header) {
120 /*
aa900596
MD
121 * Get the transport protocol from the network
122 * header's data. This method works both for
123 * sent and received packets.
9cf9736a
GB
124 */
125 if ((skb->protocol == htons(ETH_P_IP) &&
126 ip_hdr(skb)->protocol == IPPROTO_TCP) ||
127 (skb->protocol == htons(ETH_P_IPV6) &&
128 ipv6_hdr(skb)->nexthdr == IPPROTO_TCP))
129 return TH_TCP;
130 }
131 /* Fallthrough for other cases where header is not TCP. */
132 }
133 return TH_NONE;
134}
135
7299e758
MD
136static struct lttng_enum_entry proto_transport_enum_entries[] = {
137 [0] = {
138 .start = { .value = 0, .signedness = 0, },
139 .end = { .value = IPPROTO_TCP - 1, .signedness = 0, },
140 .string = "_unknown",
141 },
142 [1] = {
143 .start = { .value = IPPROTO_TCP, .signedness = 0, },
144 .end = { .value = IPPROTO_TCP, .signedness = 0, },
145 .string = "_tcp",
146 },
147 [2] = {
148 .start = { .value = IPPROTO_TCP + 1, .signedness = 0, },
149 .end = { .value = 255, .signedness = 0, },
150 .string = "_unknown",
151 },
152};
153
154static const struct lttng_enum_desc proto_transport_header_type = {
155 .name = "proto_transport_header_type",
156 .entries = proto_transport_enum_entries,
157 .nr_entries = ARRAY_SIZE(proto_transport_enum_entries),
158};
159
9cf9736a
GB
160static struct lttng_enum_entry transport_enum_entries[] = {
161 [0] = {
0910ab71
MD
162 .start = { .value = TH_NONE, .signedness = 0, },
163 .end = { .value = TH_NONE, .signedness = 0, },
9cf9736a
GB
164 .string = "_unknown",
165 },
166 [1] = {
0910ab71
MD
167 .start = { .value = TH_TCP, .signedness = 0, },
168 .end = { .value = TH_TCP, .signedness = 0, },
9cf9736a
GB
169 .string = "_tcp",
170 },
9cf9736a
GB
171};
172
173static const struct lttng_enum_desc transport_header_type = {
174 .name = "transport_header_type",
175 .entries = transport_enum_entries,
176 .nr_entries = ARRAY_SIZE(transport_enum_entries),
177};
178
e5990fd4
GB
179/* Structures for network headers. */
180
181static struct lttng_event_field ipv4fields[] = {
182 [0] = {
183 .name = "version",
aa900596
MD
184 .type = __type_integer(uint8_t, 4, 4, 0,
185 __BIG_ENDIAN, 10, none),
e5990fd4
GB
186 },
187 [1] = {
188 .name = "ihl",
aa900596
MD
189 .type = __type_integer(uint8_t, 4, 4, 0,
190 __BIG_ENDIAN, 10, none),
e5990fd4
GB
191 },
192 [2] = {
193 .name = "tos",
aa900596
MD
194 .type = __type_integer(uint8_t, 0, 0, 0,
195 __BIG_ENDIAN, 10, none),
e5990fd4
GB
196 },
197 [3] = {
198 .name = "tot_len",
aa900596
MD
199 .type = __type_integer(uint16_t, 0, 0, 0,
200 __BIG_ENDIAN, 10, none),
e5990fd4
GB
201 },
202 [4] = {
203 .name = "id",
aa900596
MD
204 .type = __type_integer(uint16_t, 0, 0, 0,
205 __BIG_ENDIAN, 16, none),
e5990fd4
GB
206 },
207 [5] = {
208 .name = "frag_off",
aa900596
MD
209 .type = __type_integer(uint16_t, 0, 0, 0,
210 __BIG_ENDIAN, 10, none),
e5990fd4
GB
211 },
212 [6] = {
213 .name = "ttl",
aa900596
MD
214 .type = __type_integer(uint8_t, 0, 0, 0,
215 __BIG_ENDIAN, 10, none),
e5990fd4
GB
216 },
217 [7] = {
218 .name = "protocol",
9cf9736a
GB
219 .type = {
220 .atype = atype_enum,
7299e758
MD
221 .u.basic.enumeration.desc =
222 &proto_transport_header_type,
9cf9736a
GB
223 .u.basic.enumeration.container_type = {
224 .size = 8,
225 .alignment = 8,
226 .signedness = 0,
aa900596
MD
227 .reverse_byte_order =
228 __BIG_ENDIAN != __BYTE_ORDER,
9cf9736a
GB
229 .base = 10,
230 .encoding = lttng_encode_none,
231 },
232 },
e5990fd4
GB
233 },
234 [8] = {
235 .name = "checksum",
aa900596
MD
236 .type = __type_integer(uint16_t, 0, 0, 0,
237 __BIG_ENDIAN, 16, none),
e5990fd4
GB
238 },
239 [9] = {
240 .name = "saddr",
241 .type = {
242 .atype = atype_array,
aa900596
MD
243 .u.array.elem_type =
244 __type_integer(uint8_t, 0, 0, 0,
245 __BIG_ENDIAN, 10, none),
e5990fd4
GB
246 .u.array.length = 4,
247 .u.array.elem_alignment = lttng_alignof(uint8_t),
248 },
249 },
250 [10] = {
251 .name = "daddr",
252 .type = {
253 .atype = atype_array,
aa900596
MD
254 .u.array.elem_type =
255 __type_integer(uint8_t, 0, 0, 0,
256 __BIG_ENDIAN, 10, none),
e5990fd4
GB
257 .u.array.length = 4,
258 .u.array.elem_alignment = lttng_alignof(uint8_t),
259 },
260 },
9cf9736a 261 [11] = {
0910ab71
MD
262 .name = "transport_header_type",
263 .type = {
264 .atype = atype_enum,
265 .u.basic.enumeration.desc = &transport_header_type,
266 .u.basic.enumeration.container_type = {
267 .size = 8,
268 .alignment = 8,
269 .signedness = 0,
270 .reverse_byte_order = 0,
271 .base = 10,
272 .encoding = lttng_encode_none,
273 },
274 },
275 },
276 [12] = {
9cf9736a
GB
277 .name = "transport_header",
278 .type = {
279 .atype = atype_variant,
0910ab71 280 .u.variant.tag_name = "transport_header_type",
9cf9736a
GB
281 .u.variant.choices = transport_fields,
282 .u.variant.nr_choices = ARRAY_SIZE(transport_fields),
283 },
284 },
e5990fd4
GB
285};
286
287static struct lttng_event_field ipv6fields[] = {
288 [0] = {
289 .name = "version",
aa900596
MD
290 .type = __type_integer(uint8_t, 4, 4, 0,
291 __BIG_ENDIAN, 10, none),
e5990fd4
GB
292 },
293 [1] = {
294 .name = "prio",
aa900596
MD
295 .type = __type_integer(uint8_t, 4, 4, 0,
296 __BIG_ENDIAN, 10, none),
e5990fd4
GB
297 },
298 [2] = {
299 .name = "flow_lbl",
300 .type = {
301 .atype = atype_array,
aa900596
MD
302 .u.array.elem_type =
303 __type_integer(uint8_t, 0, 0, 0,
304 __BIG_ENDIAN, 16, none),
e5990fd4
GB
305 .u.array.length = 3,
306 .u.array.elem_alignment = lttng_alignof(uint8_t),
307 },
308 },
309 [3] = {
310 .name = "payload_len",
aa900596
MD
311 .type = __type_integer(uint16_t, 0, 0, 0,
312 __BIG_ENDIAN, 10, none),
e5990fd4
GB
313 },
314 [4] = {
315 .name = "nexthdr",
9cf9736a
GB
316 .type = {
317 .atype = atype_enum,
7299e758
MD
318 .u.basic.enumeration.desc =
319 &proto_transport_header_type,
9cf9736a
GB
320 .u.basic.enumeration.container_type = {
321 .size = 8,
322 .alignment = 8,
323 .signedness = 0,
aa900596
MD
324 .reverse_byte_order =
325 __BIG_ENDIAN != __BYTE_ORDER,
9cf9736a
GB
326 .base = 10,
327 .encoding = lttng_encode_none,
328 },
329 },
e5990fd4
GB
330 },
331 [5] = {
332 .name = "hop_limit",
aa900596
MD
333 .type = __type_integer(uint8_t, 0, 0, 0,
334 __BIG_ENDIAN, 10, none),
e5990fd4
GB
335 },
336 [6] = {
337 .name = "saddr",
338 .type = {
339 .atype = atype_array,
aa900596
MD
340 .u.array.elem_type =
341 __type_integer(uint16_t, 0, 0, 0,
342 __BIG_ENDIAN, 16, none),
e5990fd4
GB
343 .u.array.length = 8,
344 .u.array.elem_alignment = lttng_alignof(uint16_t),
345 },
346 },
347 [7] = {
348 .name = "daddr",
349 .type = {
350 .atype = atype_array,
aa900596
MD
351 .u.array.elem_type =
352 __type_integer(uint16_t, 0, 0, 0,
353 __BIG_ENDIAN, 16, none),
e5990fd4
GB
354 .u.array.length = 8,
355 .u.array.elem_alignment = lttng_alignof(uint16_t),
356 },
357 },
9cf9736a 358 [8] = {
0910ab71
MD
359 .name = "transport_header_type",
360 .type = {
361 .atype = atype_enum,
362 .u.basic.enumeration.desc = &transport_header_type,
363 .u.basic.enumeration.container_type = {
364 .size = 8,
365 .alignment = 8,
366 .signedness = 0,
367 .reverse_byte_order = 0,
368 .base = 10,
369 .encoding = lttng_encode_none,
370 },
371 },
372 },
373 [9] = {
9cf9736a
GB
374 .name = "transport_header",
375 .type = {
376 .atype = atype_variant,
0910ab71 377 .u.variant.tag_name = "transport_header_type",
9cf9736a
GB
378 .u.variant.choices = transport_fields,
379 .u.variant.nr_choices = ARRAY_SIZE(transport_fields),
380 },
381 },
e5990fd4
GB
382};
383
384static struct lttng_event_field network_fields[] = {
385 [0] = {
386 .name = "unknown",
387 .type = {
388 .atype = atype_struct,
389 .u._struct.nr_fields = 0,
390 .u._struct.fields = emptyfields,
391 },
392 },
393 [1] = {
394 .name = "ipv4",
395 .type = {
396 .atype = atype_struct,
397 .u._struct.nr_fields = ARRAY_SIZE(ipv4fields),
398 .u._struct.fields = ipv4fields,
399 },
400 },
401 [2] = {
402 .name = "ipv6",
403 .type = {
404 .atype = atype_struct,
405 .u._struct.nr_fields = ARRAY_SIZE(ipv6fields),
406 .u._struct.fields = ipv6fields,
407 },
408 },
409};
410
411enum network_header_types {
412 NH_NONE,
413 NH_IPV4,
414 NH_IPV6,
415};
416
417static inline unsigned char __get_network_header_type(struct sk_buff *skb)
418{
419 if (__has_network_hdr(skb)) {
420 if (skb->protocol == htons(ETH_P_IPV6))
421 return NH_IPV6;
422 else if (skb->protocol == htons(ETH_P_IP))
423 return NH_IPV4;
424 /* Fallthrough for other header types. */
425 }
426 return NH_NONE;
427}
428
429#endif
430
431LTTNG_TRACEPOINT_ENUM(net_network_header,
432 TP_ENUM_VALUES(
433 ctf_enum_value("_unknown", NH_NONE)
434 ctf_enum_value("_ipv4", NH_IPV4)
435 ctf_enum_value("_ipv6", NH_IPV6)
436 )
437)
b283666f 438
3bc29f0a 439LTTNG_TRACEPOINT_EVENT(net_dev_xmit,
b283666f 440
f95480cf 441#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,40))
b283666f
PW
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),
4a7363f7
PW
448#else
449 TP_PROTO(struct sk_buff *skb,
450 int rc),
aa900596 451
4a7363f7
PW
452 TP_ARGS(skb, rc),
453#endif
b283666f 454
f127e61e 455 TP_FIELDS(
fa91fcac 456 ctf_integer_hex(void *, skbaddr, skb)
f127e61e 457 ctf_integer(int, rc, rc)
f95480cf 458#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,40))
974c0969 459 ctf_integer(unsigned int, len, skb_len)
f127e61e 460 ctf_string(name, dev->name)
4a7363f7 461#else
974c0969 462 ctf_integer(unsigned int, len, skb->len)
f127e61e 463 ctf_string(name, skb->dev->name)
4a7363f7 464#endif
f127e61e 465 )
b283666f
PW
466)
467
3bc29f0a 468LTTNG_TRACEPOINT_EVENT_CLASS(net_dev_template,
b283666f
PW
469
470 TP_PROTO(struct sk_buff *skb),
471
472 TP_ARGS(skb),
473
f127e61e 474 TP_FIELDS(
fa91fcac 475 ctf_integer_hex(void *, skbaddr, skb)
f127e61e
MD
476 ctf_integer(unsigned int, len, skb->len)
477 ctf_string(name, skb->dev->name)
e5990fd4
GB
478 ctf_enum(net_network_header, unsigned char,
479 network_header_type, __get_network_header_type(skb))
480 ctf_custom_field(
481 ctf_custom_type(
482 .atype = atype_variant,
483 .u.variant.tag_name = "network_header_type",
484 .u.variant.choices = network_fields,
aa900596
MD
485 .u.variant.nr_choices =
486 ARRAY_SIZE(network_fields),
e5990fd4
GB
487 ),
488 network_header,
489 ctf_custom_code(
0910ab71
MD
490 bool has_network_header = false;
491
aa900596 492 /* Copy the network header. */
e5990fd4
GB
493 switch (__get_network_header_type(skb)) {
494 case NH_IPV4: {
495 ctf_align(uint16_t)
496 ctf_array_type(uint8_t, ip_hdr(skb),
497 sizeof(struct iphdr))
0910ab71 498 has_network_header = true;
e5990fd4
GB
499 break;
500 }
501 case NH_IPV6: {
502 ctf_align(uint16_t)
503 ctf_array_type(uint8_t, ipv6_hdr(skb),
504 sizeof(struct ipv6hdr))
0910ab71 505 has_network_header = true;
e5990fd4
GB
506 break;
507 }
508 default:
aa900596
MD
509 /*
510 * For any other network header
511 * type, there is nothing to do.
512 */
e5990fd4
GB
513 break;
514 }
9cf9736a 515
0910ab71
MD
516 if (has_network_header) {
517 enum transport_header_types th_type =
518 __get_transport_header_type(skb);
519
520 /* Transport header type field. */
521 ctf_integer_type(unsigned char, th_type)
522
523 /* Copy the transport header. */
524 if (th_type == TH_TCP) {
525 ctf_align(uint32_t)
526 ctf_array_type(uint8_t, tcp_hdr(skb),
527 sizeof(struct tcphdr))
528 }
529 /*
530 * For any other transport header type,
531 * there is nothing to do.
532 */
9cf9736a 533 }
e5990fd4
GB
534 )
535 )
f127e61e 536 )
b283666f
PW
537)
538
3bc29f0a 539LTTNG_TRACEPOINT_EVENT_INSTANCE(net_dev_template, net_dev_queue,
b283666f
PW
540
541 TP_PROTO(struct sk_buff *skb),
542
543 TP_ARGS(skb)
544)
545
b7f5408a
MD
546LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(net_dev_template,
547
548 netif_receive_skb,
549
550 net_if_receive_skb,
b283666f
PW
551
552 TP_PROTO(struct sk_buff *skb),
553
554 TP_ARGS(skb)
555)
556
b7f5408a
MD
557LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(net_dev_template,
558
559 netif_rx,
560
561 net_if_rx,
b283666f
PW
562
563 TP_PROTO(struct sk_buff *skb),
564
565 TP_ARGS(skb)
566)
3bc29f0a 567#endif /* LTTNG_TRACE_NET_H */
b283666f
PW
568
569/* This part must be outside protection */
6ec43db8 570#include <probes/define_trace.h>
This page took 0.059091 seconds and 4 git commands to generate.