Commit | Line | Data |
---|---|---|
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 | ||
20 | static 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 | ||
29 | static struct lttng_event_field emptyfields[] = { | |
30 | }; | |
31 | ||
9cf9736a GB |
32 | /* Structures for transport headers. */ |
33 | ||
34 | static 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 | ||
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, | |
108 | TH_TCP, | |
109 | }; | |
110 | ||
111 | static inline unsigned char __get_transport_header_type(struct sk_buff *skb) | |
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 | ||
136 | static struct lttng_enum_entry 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 transport_header_type = { | |
155 | .name = "transport_header_type", | |
156 | .entries = transport_enum_entries, | |
157 | .nr_entries = ARRAY_SIZE(transport_enum_entries), | |
158 | }; | |
159 | ||
e5990fd4 GB |
160 | /* Structures for network headers. */ |
161 | ||
162 | static struct lttng_event_field ipv4fields[] = { | |
163 | [0] = { | |
164 | .name = "version", | |
aa900596 MD |
165 | .type = __type_integer(uint8_t, 4, 4, 0, |
166 | __BIG_ENDIAN, 10, none), | |
e5990fd4 GB |
167 | }, |
168 | [1] = { | |
169 | .name = "ihl", | |
aa900596 MD |
170 | .type = __type_integer(uint8_t, 4, 4, 0, |
171 | __BIG_ENDIAN, 10, none), | |
e5990fd4 GB |
172 | }, |
173 | [2] = { | |
174 | .name = "tos", | |
aa900596 MD |
175 | .type = __type_integer(uint8_t, 0, 0, 0, |
176 | __BIG_ENDIAN, 10, none), | |
e5990fd4 GB |
177 | }, |
178 | [3] = { | |
179 | .name = "tot_len", | |
aa900596 MD |
180 | .type = __type_integer(uint16_t, 0, 0, 0, |
181 | __BIG_ENDIAN, 10, none), | |
e5990fd4 GB |
182 | }, |
183 | [4] = { | |
184 | .name = "id", | |
aa900596 MD |
185 | .type = __type_integer(uint16_t, 0, 0, 0, |
186 | __BIG_ENDIAN, 16, none), | |
e5990fd4 GB |
187 | }, |
188 | [5] = { | |
189 | .name = "frag_off", | |
aa900596 MD |
190 | .type = __type_integer(uint16_t, 0, 0, 0, |
191 | __BIG_ENDIAN, 10, none), | |
e5990fd4 GB |
192 | }, |
193 | [6] = { | |
194 | .name = "ttl", | |
aa900596 MD |
195 | .type = __type_integer(uint8_t, 0, 0, 0, |
196 | __BIG_ENDIAN, 10, none), | |
e5990fd4 GB |
197 | }, |
198 | [7] = { | |
199 | .name = "protocol", | |
9cf9736a GB |
200 | .type = { |
201 | .atype = atype_enum, | |
202 | .u.basic.enumeration.desc = &transport_header_type, | |
203 | .u.basic.enumeration.container_type = { | |
204 | .size = 8, | |
205 | .alignment = 8, | |
206 | .signedness = 0, | |
aa900596 MD |
207 | .reverse_byte_order = |
208 | __BIG_ENDIAN != __BYTE_ORDER, | |
9cf9736a GB |
209 | .base = 10, |
210 | .encoding = lttng_encode_none, | |
211 | }, | |
212 | }, | |
e5990fd4 GB |
213 | }, |
214 | [8] = { | |
215 | .name = "checksum", | |
aa900596 MD |
216 | .type = __type_integer(uint16_t, 0, 0, 0, |
217 | __BIG_ENDIAN, 16, none), | |
e5990fd4 GB |
218 | }, |
219 | [9] = { | |
220 | .name = "saddr", | |
221 | .type = { | |
222 | .atype = atype_array, | |
aa900596 MD |
223 | .u.array.elem_type = |
224 | __type_integer(uint8_t, 0, 0, 0, | |
225 | __BIG_ENDIAN, 10, none), | |
e5990fd4 GB |
226 | .u.array.length = 4, |
227 | .u.array.elem_alignment = lttng_alignof(uint8_t), | |
228 | }, | |
229 | }, | |
230 | [10] = { | |
231 | .name = "daddr", | |
232 | .type = { | |
233 | .atype = atype_array, | |
aa900596 MD |
234 | .u.array.elem_type = |
235 | __type_integer(uint8_t, 0, 0, 0, | |
236 | __BIG_ENDIAN, 10, none), | |
e5990fd4 GB |
237 | .u.array.length = 4, |
238 | .u.array.elem_alignment = lttng_alignof(uint8_t), | |
239 | }, | |
240 | }, | |
9cf9736a GB |
241 | [11] = { |
242 | .name = "transport_header", | |
243 | .type = { | |
244 | .atype = atype_variant, | |
245 | .u.variant.tag_name = "protocol", | |
246 | .u.variant.choices = transport_fields, | |
247 | .u.variant.nr_choices = ARRAY_SIZE(transport_fields), | |
248 | }, | |
249 | }, | |
e5990fd4 GB |
250 | }; |
251 | ||
252 | static struct lttng_event_field ipv6fields[] = { | |
253 | [0] = { | |
254 | .name = "version", | |
aa900596 MD |
255 | .type = __type_integer(uint8_t, 4, 4, 0, |
256 | __BIG_ENDIAN, 10, none), | |
e5990fd4 GB |
257 | }, |
258 | [1] = { | |
259 | .name = "prio", | |
aa900596 MD |
260 | .type = __type_integer(uint8_t, 4, 4, 0, |
261 | __BIG_ENDIAN, 10, none), | |
e5990fd4 GB |
262 | }, |
263 | [2] = { | |
264 | .name = "flow_lbl", | |
265 | .type = { | |
266 | .atype = atype_array, | |
aa900596 MD |
267 | .u.array.elem_type = |
268 | __type_integer(uint8_t, 0, 0, 0, | |
269 | __BIG_ENDIAN, 16, none), | |
e5990fd4 GB |
270 | .u.array.length = 3, |
271 | .u.array.elem_alignment = lttng_alignof(uint8_t), | |
272 | }, | |
273 | }, | |
274 | [3] = { | |
275 | .name = "payload_len", | |
aa900596 MD |
276 | .type = __type_integer(uint16_t, 0, 0, 0, |
277 | __BIG_ENDIAN, 10, none), | |
e5990fd4 GB |
278 | }, |
279 | [4] = { | |
280 | .name = "nexthdr", | |
9cf9736a GB |
281 | .type = { |
282 | .atype = atype_enum, | |
283 | .u.basic.enumeration.desc = &transport_header_type, | |
284 | .u.basic.enumeration.container_type = { | |
285 | .size = 8, | |
286 | .alignment = 8, | |
287 | .signedness = 0, | |
aa900596 MD |
288 | .reverse_byte_order = |
289 | __BIG_ENDIAN != __BYTE_ORDER, | |
9cf9736a GB |
290 | .base = 10, |
291 | .encoding = lttng_encode_none, | |
292 | }, | |
293 | }, | |
e5990fd4 GB |
294 | }, |
295 | [5] = { | |
296 | .name = "hop_limit", | |
aa900596 MD |
297 | .type = __type_integer(uint8_t, 0, 0, 0, |
298 | __BIG_ENDIAN, 10, none), | |
e5990fd4 GB |
299 | }, |
300 | [6] = { | |
301 | .name = "saddr", | |
302 | .type = { | |
303 | .atype = atype_array, | |
aa900596 MD |
304 | .u.array.elem_type = |
305 | __type_integer(uint16_t, 0, 0, 0, | |
306 | __BIG_ENDIAN, 16, none), | |
e5990fd4 GB |
307 | .u.array.length = 8, |
308 | .u.array.elem_alignment = lttng_alignof(uint16_t), | |
309 | }, | |
310 | }, | |
311 | [7] = { | |
312 | .name = "daddr", | |
313 | .type = { | |
314 | .atype = atype_array, | |
aa900596 MD |
315 | .u.array.elem_type = |
316 | __type_integer(uint16_t, 0, 0, 0, | |
317 | __BIG_ENDIAN, 16, none), | |
e5990fd4 GB |
318 | .u.array.length = 8, |
319 | .u.array.elem_alignment = lttng_alignof(uint16_t), | |
320 | }, | |
321 | }, | |
9cf9736a GB |
322 | [8] = { |
323 | .name = "transport_header", | |
324 | .type = { | |
325 | .atype = atype_variant, | |
326 | .u.variant.tag_name = "nexthdr", | |
327 | .u.variant.choices = transport_fields, | |
328 | .u.variant.nr_choices = ARRAY_SIZE(transport_fields), | |
329 | }, | |
330 | }, | |
e5990fd4 GB |
331 | }; |
332 | ||
333 | static struct lttng_event_field network_fields[] = { | |
334 | [0] = { | |
335 | .name = "unknown", | |
336 | .type = { | |
337 | .atype = atype_struct, | |
338 | .u._struct.nr_fields = 0, | |
339 | .u._struct.fields = emptyfields, | |
340 | }, | |
341 | }, | |
342 | [1] = { | |
343 | .name = "ipv4", | |
344 | .type = { | |
345 | .atype = atype_struct, | |
346 | .u._struct.nr_fields = ARRAY_SIZE(ipv4fields), | |
347 | .u._struct.fields = ipv4fields, | |
348 | }, | |
349 | }, | |
350 | [2] = { | |
351 | .name = "ipv6", | |
352 | .type = { | |
353 | .atype = atype_struct, | |
354 | .u._struct.nr_fields = ARRAY_SIZE(ipv6fields), | |
355 | .u._struct.fields = ipv6fields, | |
356 | }, | |
357 | }, | |
358 | }; | |
359 | ||
360 | enum network_header_types { | |
361 | NH_NONE, | |
362 | NH_IPV4, | |
363 | NH_IPV6, | |
364 | }; | |
365 | ||
366 | static inline unsigned char __get_network_header_type(struct sk_buff *skb) | |
367 | { | |
368 | if (__has_network_hdr(skb)) { | |
369 | if (skb->protocol == htons(ETH_P_IPV6)) | |
370 | return NH_IPV6; | |
371 | else if (skb->protocol == htons(ETH_P_IP)) | |
372 | return NH_IPV4; | |
373 | /* Fallthrough for other header types. */ | |
374 | } | |
375 | return NH_NONE; | |
376 | } | |
377 | ||
378 | #endif | |
379 | ||
380 | LTTNG_TRACEPOINT_ENUM(net_network_header, | |
381 | TP_ENUM_VALUES( | |
382 | ctf_enum_value("_unknown", NH_NONE) | |
383 | ctf_enum_value("_ipv4", NH_IPV4) | |
384 | ctf_enum_value("_ipv6", NH_IPV6) | |
385 | ) | |
386 | ) | |
b283666f | 387 | |
3bc29f0a | 388 | LTTNG_TRACEPOINT_EVENT(net_dev_xmit, |
b283666f | 389 | |
f95480cf | 390 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,40)) |
b283666f PW |
391 | TP_PROTO(struct sk_buff *skb, |
392 | int rc, | |
393 | struct net_device *dev, | |
394 | unsigned int skb_len), | |
395 | ||
396 | TP_ARGS(skb, rc, dev, skb_len), | |
4a7363f7 PW |
397 | #else |
398 | TP_PROTO(struct sk_buff *skb, | |
399 | int rc), | |
aa900596 | 400 | |
4a7363f7 PW |
401 | TP_ARGS(skb, rc), |
402 | #endif | |
b283666f | 403 | |
f127e61e | 404 | TP_FIELDS( |
fa91fcac | 405 | ctf_integer_hex(void *, skbaddr, skb) |
f127e61e | 406 | ctf_integer(int, rc, rc) |
f95480cf | 407 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,40)) |
974c0969 | 408 | ctf_integer(unsigned int, len, skb_len) |
f127e61e | 409 | ctf_string(name, dev->name) |
4a7363f7 | 410 | #else |
974c0969 | 411 | ctf_integer(unsigned int, len, skb->len) |
f127e61e | 412 | ctf_string(name, skb->dev->name) |
4a7363f7 | 413 | #endif |
f127e61e | 414 | ) |
b283666f PW |
415 | ) |
416 | ||
3bc29f0a | 417 | LTTNG_TRACEPOINT_EVENT_CLASS(net_dev_template, |
b283666f PW |
418 | |
419 | TP_PROTO(struct sk_buff *skb), | |
420 | ||
421 | TP_ARGS(skb), | |
422 | ||
f127e61e | 423 | TP_FIELDS( |
fa91fcac | 424 | ctf_integer_hex(void *, skbaddr, skb) |
f127e61e MD |
425 | ctf_integer(unsigned int, len, skb->len) |
426 | ctf_string(name, skb->dev->name) | |
e5990fd4 GB |
427 | ctf_enum(net_network_header, unsigned char, |
428 | network_header_type, __get_network_header_type(skb)) | |
429 | ctf_custom_field( | |
430 | ctf_custom_type( | |
431 | .atype = atype_variant, | |
432 | .u.variant.tag_name = "network_header_type", | |
433 | .u.variant.choices = network_fields, | |
aa900596 MD |
434 | .u.variant.nr_choices = |
435 | ARRAY_SIZE(network_fields), | |
e5990fd4 GB |
436 | ), |
437 | network_header, | |
438 | ctf_custom_code( | |
aa900596 | 439 | /* Copy the network header. */ |
e5990fd4 GB |
440 | switch (__get_network_header_type(skb)) { |
441 | case NH_IPV4: { | |
442 | ctf_align(uint16_t) | |
443 | ctf_array_type(uint8_t, ip_hdr(skb), | |
444 | sizeof(struct iphdr)) | |
445 | break; | |
446 | } | |
447 | case NH_IPV6: { | |
448 | ctf_align(uint16_t) | |
449 | ctf_array_type(uint8_t, ipv6_hdr(skb), | |
450 | sizeof(struct ipv6hdr)) | |
451 | break; | |
452 | } | |
453 | default: | |
aa900596 MD |
454 | /* |
455 | * For any other network header | |
456 | * type, there is nothing to do. | |
457 | */ | |
e5990fd4 GB |
458 | break; |
459 | } | |
9cf9736a | 460 | |
aa900596 MD |
461 | /* Copy the transport header. */ |
462 | if (__get_transport_header_type(skb) | |
463 | == TH_TCP) { | |
9cf9736a GB |
464 | ctf_align(uint32_t) |
465 | ctf_array_type(uint8_t, tcp_hdr(skb), | |
466 | sizeof(struct tcphdr)) | |
467 | } | |
aa900596 MD |
468 | /* |
469 | * For any other transport header type, | |
470 | * there is nothing to do. | |
471 | */ | |
e5990fd4 GB |
472 | ) |
473 | ) | |
f127e61e | 474 | ) |
b283666f PW |
475 | ) |
476 | ||
3bc29f0a | 477 | LTTNG_TRACEPOINT_EVENT_INSTANCE(net_dev_template, net_dev_queue, |
b283666f PW |
478 | |
479 | TP_PROTO(struct sk_buff *skb), | |
480 | ||
481 | TP_ARGS(skb) | |
482 | ) | |
483 | ||
b7f5408a MD |
484 | LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(net_dev_template, |
485 | ||
486 | netif_receive_skb, | |
487 | ||
488 | net_if_receive_skb, | |
b283666f PW |
489 | |
490 | TP_PROTO(struct sk_buff *skb), | |
491 | ||
492 | TP_ARGS(skb) | |
493 | ) | |
494 | ||
b7f5408a MD |
495 | LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(net_dev_template, |
496 | ||
497 | netif_rx, | |
498 | ||
499 | net_if_rx, | |
b283666f PW |
500 | |
501 | TP_PROTO(struct sk_buff *skb), | |
502 | ||
503 | TP_ARGS(skb) | |
504 | ) | |
3bc29f0a | 505 | #endif /* LTTNG_TRACE_NET_H */ |
b283666f PW |
506 | |
507 | /* This part must be outside protection */ | |
6ec43db8 | 508 | #include <probes/define_trace.h> |