Fix: network instrumentation protocol enum
[lttng-modules.git] / instrumentation / events / lttng-module / net.h
1 #undef TRACE_SYSTEM
2 #define TRACE_SYSTEM net
3
4 #if !defined(LTTNG_TRACE_NET_H) || defined(TRACE_HEADER_MULTI_READ)
5 #define LTTNG_TRACE_NET_H
6
7 #include <probes/lttng-tracepoint-event.h>
8 #include <linux/skbuff.h>
9 #include <linux/netdevice.h>
10 #include <linux/ip.h>
11 #include <linux/ipv6.h>
12 #include <linux/tcp.h>
13 #include <linux/version.h>
14 #include <lttng-endian.h>
15 #include <net/sock.h>
16
17 #ifndef ONCE_LTTNG_NET_H
18 #define ONCE_LTTNG_NET_H
19
20 static inline unsigned char __has_network_hdr(struct sk_buff *skb)
21 {
22 /*
23 * If the header is not set yet, the network header will point
24 * to the head.
25 */
26 return skb_network_header(skb) != skb->head;
27 }
28
29 static struct lttng_event_field emptyfields[] = {
30 };
31
32 /* Structures for transport headers. */
33
34 static struct lttng_event_field tcpfields[] = {
35 [0] = {
36 .name = "source_port",
37 .type = __type_integer(uint16_t, 0, 0, 0,
38 __BIG_ENDIAN, 10, none),
39 },
40 [1] = {
41 .name = "dest_port",
42 .type = __type_integer(uint16_t, 0, 0, 0,
43 __BIG_ENDIAN, 10, none),
44 },
45 [2] = {
46 .name = "seq",
47 .type = __type_integer(uint32_t, 0, 0, 0,
48 __BIG_ENDIAN, 10, none),
49 },
50 [3] = {
51 .name = "ack_seq",
52 .type = __type_integer(uint32_t, 0, 0, 0,
53 __BIG_ENDIAN, 10, none),
54 },
55 [4] = {
56 .name = "data_offset",
57 .type = __type_integer(uint8_t, 4, 4, 0,
58 __BIG_ENDIAN, 10, none),
59 },
60 [5] = {
61 .name = "reserved",
62 .type = __type_integer(uint8_t, 3, 1, 0,
63 __BIG_ENDIAN, 10, none),
64 },
65 [6] = {
66 .name = "flags",
67 .type = __type_integer(uint8_t, 9, 1, 0,
68 __BIG_ENDIAN, 16, none),
69 },
70 [7] = {
71 .name = "window_size",
72 .type = __type_integer(uint16_t, 0, 0, 0,
73 __BIG_ENDIAN, 10, none),
74 },
75 [8] = {
76 .name = "checksum",
77 .type = __type_integer(uint16_t, 0, 0, 0,
78 __BIG_ENDIAN, 16, none),
79 },
80 [9] = {
81 .name = "urg_ptr",
82 .type = __type_integer(uint16_t, 0, 0, 0,
83 __BIG_ENDIAN, 10, none),
84 },
85 };
86
87 static 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
106 enum transport_header_types {
107 TH_NONE = 0,
108 TH_TCP = 1,
109 };
110
111 static inline enum transport_header_types __get_transport_header_type(struct sk_buff *skb)
112 {
113 if (__has_network_hdr(skb)) {
114 /*
115 * When both transport and network headers are set,
116 * transport header is greater than network header,
117 * otherwise it points to head.
118 */
119 if (skb->transport_header > skb->network_header) {
120 /*
121 * Get the transport protocol from the network
122 * header's data. This method works both for
123 * sent and received packets.
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
136 static 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
154 static 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
160 static struct lttng_enum_entry transport_enum_entries[] = {
161 [0] = {
162 .start = { .value = TH_NONE, .signedness = 0, },
163 .end = { .value = TH_NONE, .signedness = 0, },
164 .string = "_unknown",
165 },
166 [1] = {
167 .start = { .value = TH_TCP, .signedness = 0, },
168 .end = { .value = TH_TCP, .signedness = 0, },
169 .string = "_tcp",
170 },
171 };
172
173 static 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
179 /* Structures for network headers. */
180
181 static struct lttng_event_field ipv4fields[] = {
182 [0] = {
183 .name = "version",
184 .type = __type_integer(uint8_t, 4, 4, 0,
185 __BIG_ENDIAN, 10, none),
186 },
187 [1] = {
188 .name = "ihl",
189 .type = __type_integer(uint8_t, 4, 4, 0,
190 __BIG_ENDIAN, 10, none),
191 },
192 [2] = {
193 .name = "tos",
194 .type = __type_integer(uint8_t, 0, 0, 0,
195 __BIG_ENDIAN, 10, none),
196 },
197 [3] = {
198 .name = "tot_len",
199 .type = __type_integer(uint16_t, 0, 0, 0,
200 __BIG_ENDIAN, 10, none),
201 },
202 [4] = {
203 .name = "id",
204 .type = __type_integer(uint16_t, 0, 0, 0,
205 __BIG_ENDIAN, 16, none),
206 },
207 [5] = {
208 .name = "frag_off",
209 .type = __type_integer(uint16_t, 0, 0, 0,
210 __BIG_ENDIAN, 10, none),
211 },
212 [6] = {
213 .name = "ttl",
214 .type = __type_integer(uint8_t, 0, 0, 0,
215 __BIG_ENDIAN, 10, none),
216 },
217 [7] = {
218 .name = "protocol",
219 .type = {
220 .atype = atype_enum,
221 .u.basic.enumeration.desc =
222 &proto_transport_header_type,
223 .u.basic.enumeration.container_type = {
224 .size = 8,
225 .alignment = 8,
226 .signedness = 0,
227 .reverse_byte_order =
228 __BIG_ENDIAN != __BYTE_ORDER,
229 .base = 10,
230 .encoding = lttng_encode_none,
231 },
232 },
233 },
234 [8] = {
235 .name = "checksum",
236 .type = __type_integer(uint16_t, 0, 0, 0,
237 __BIG_ENDIAN, 16, none),
238 },
239 [9] = {
240 .name = "saddr",
241 .type = {
242 .atype = atype_array,
243 .u.array.elem_type =
244 __type_integer(uint8_t, 0, 0, 0,
245 __BIG_ENDIAN, 10, none),
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,
254 .u.array.elem_type =
255 __type_integer(uint8_t, 0, 0, 0,
256 __BIG_ENDIAN, 10, none),
257 .u.array.length = 4,
258 .u.array.elem_alignment = lttng_alignof(uint8_t),
259 },
260 },
261 [11] = {
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] = {
277 .name = "transport_header",
278 .type = {
279 .atype = atype_variant,
280 .u.variant.tag_name = "transport_header_type",
281 .u.variant.choices = transport_fields,
282 .u.variant.nr_choices = ARRAY_SIZE(transport_fields),
283 },
284 },
285 };
286
287 static struct lttng_event_field ipv6fields[] = {
288 [0] = {
289 .name = "version",
290 .type = __type_integer(uint8_t, 4, 4, 0,
291 __BIG_ENDIAN, 10, none),
292 },
293 [1] = {
294 .name = "prio",
295 .type = __type_integer(uint8_t, 4, 4, 0,
296 __BIG_ENDIAN, 10, none),
297 },
298 [2] = {
299 .name = "flow_lbl",
300 .type = {
301 .atype = atype_array,
302 .u.array.elem_type =
303 __type_integer(uint8_t, 0, 0, 0,
304 __BIG_ENDIAN, 16, none),
305 .u.array.length = 3,
306 .u.array.elem_alignment = lttng_alignof(uint8_t),
307 },
308 },
309 [3] = {
310 .name = "payload_len",
311 .type = __type_integer(uint16_t, 0, 0, 0,
312 __BIG_ENDIAN, 10, none),
313 },
314 [4] = {
315 .name = "nexthdr",
316 .type = {
317 .atype = atype_enum,
318 .u.basic.enumeration.desc =
319 &proto_transport_header_type,
320 .u.basic.enumeration.container_type = {
321 .size = 8,
322 .alignment = 8,
323 .signedness = 0,
324 .reverse_byte_order =
325 __BIG_ENDIAN != __BYTE_ORDER,
326 .base = 10,
327 .encoding = lttng_encode_none,
328 },
329 },
330 },
331 [5] = {
332 .name = "hop_limit",
333 .type = __type_integer(uint8_t, 0, 0, 0,
334 __BIG_ENDIAN, 10, none),
335 },
336 [6] = {
337 .name = "saddr",
338 .type = {
339 .atype = atype_array,
340 .u.array.elem_type =
341 __type_integer(uint16_t, 0, 0, 0,
342 __BIG_ENDIAN, 16, none),
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,
351 .u.array.elem_type =
352 __type_integer(uint16_t, 0, 0, 0,
353 __BIG_ENDIAN, 16, none),
354 .u.array.length = 8,
355 .u.array.elem_alignment = lttng_alignof(uint16_t),
356 },
357 },
358 [8] = {
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] = {
374 .name = "transport_header",
375 .type = {
376 .atype = atype_variant,
377 .u.variant.tag_name = "transport_header_type",
378 .u.variant.choices = transport_fields,
379 .u.variant.nr_choices = ARRAY_SIZE(transport_fields),
380 },
381 },
382 };
383
384 static 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
411 enum network_header_types {
412 NH_NONE,
413 NH_IPV4,
414 NH_IPV6,
415 };
416
417 static 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
431 LTTNG_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 )
438
439 LTTNG_TRACEPOINT_EVENT(net_dev_xmit,
440
441 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,40))
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 #else
449 TP_PROTO(struct sk_buff *skb,
450 int rc),
451
452 TP_ARGS(skb, rc),
453 #endif
454
455 TP_FIELDS(
456 ctf_integer_hex(void *, skbaddr, skb)
457 ctf_integer(int, rc, rc)
458 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,40))
459 ctf_integer(unsigned int, len, skb_len)
460 ctf_string(name, dev->name)
461 #else
462 ctf_integer(unsigned int, len, skb->len)
463 ctf_string(name, skb->dev->name)
464 #endif
465 )
466 )
467
468 LTTNG_TRACEPOINT_EVENT_CLASS(net_dev_template,
469
470 TP_PROTO(struct sk_buff *skb),
471
472 TP_ARGS(skb),
473
474 TP_FIELDS(
475 ctf_integer_hex(void *, skbaddr, skb)
476 ctf_integer(unsigned int, len, skb->len)
477 ctf_string(name, skb->dev->name)
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,
485 .u.variant.nr_choices =
486 ARRAY_SIZE(network_fields),
487 ),
488 network_header,
489 ctf_custom_code(
490 bool has_network_header = false;
491
492 /* Copy the network header. */
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))
498 has_network_header = true;
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))
505 has_network_header = true;
506 break;
507 }
508 default:
509 /*
510 * For any other network header
511 * type, there is nothing to do.
512 */
513 break;
514 }
515
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 */
533 }
534 )
535 )
536 )
537 )
538
539 LTTNG_TRACEPOINT_EVENT_INSTANCE(net_dev_template, net_dev_queue,
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_receive_skb,
549
550 net_if_receive_skb,
551
552 TP_PROTO(struct sk_buff *skb),
553
554 TP_ARGS(skb)
555 )
556
557 LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(net_dev_template,
558
559 netif_rx,
560
561 net_if_rx,
562
563 TP_PROTO(struct sk_buff *skb),
564
565 TP_ARGS(skb)
566 )
567 #endif /* LTTNG_TRACE_NET_H */
568
569 /* This part must be outside protection */
570 #include <probes/define_trace.h>
This page took 0.040636 seconds and 4 git commands to generate.