19a22a844e9d046e318d03b6eb95326d55bdc105
[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,
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 /*
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 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
160 /* Structures for network headers. */
161
162 static struct lttng_event_field ipv4fields[] = {
163 [0] = {
164 .name = "version",
165 .type = __type_integer(uint8_t, 4, 4, 0,
166 __BIG_ENDIAN, 10, none),
167 },
168 [1] = {
169 .name = "ihl",
170 .type = __type_integer(uint8_t, 4, 4, 0,
171 __BIG_ENDIAN, 10, none),
172 },
173 [2] = {
174 .name = "tos",
175 .type = __type_integer(uint8_t, 0, 0, 0,
176 __BIG_ENDIAN, 10, none),
177 },
178 [3] = {
179 .name = "tot_len",
180 .type = __type_integer(uint16_t, 0, 0, 0,
181 __BIG_ENDIAN, 10, none),
182 },
183 [4] = {
184 .name = "id",
185 .type = __type_integer(uint16_t, 0, 0, 0,
186 __BIG_ENDIAN, 16, none),
187 },
188 [5] = {
189 .name = "frag_off",
190 .type = __type_integer(uint16_t, 0, 0, 0,
191 __BIG_ENDIAN, 10, none),
192 },
193 [6] = {
194 .name = "ttl",
195 .type = __type_integer(uint8_t, 0, 0, 0,
196 __BIG_ENDIAN, 10, none),
197 },
198 [7] = {
199 .name = "protocol",
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,
207 .reverse_byte_order =
208 __BIG_ENDIAN != __BYTE_ORDER,
209 .base = 10,
210 .encoding = lttng_encode_none,
211 },
212 },
213 },
214 [8] = {
215 .name = "checksum",
216 .type = __type_integer(uint16_t, 0, 0, 0,
217 __BIG_ENDIAN, 16, none),
218 },
219 [9] = {
220 .name = "saddr",
221 .type = {
222 .atype = atype_array,
223 .u.array.elem_type =
224 __type_integer(uint8_t, 0, 0, 0,
225 __BIG_ENDIAN, 10, none),
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,
234 .u.array.elem_type =
235 __type_integer(uint8_t, 0, 0, 0,
236 __BIG_ENDIAN, 10, none),
237 .u.array.length = 4,
238 .u.array.elem_alignment = lttng_alignof(uint8_t),
239 },
240 },
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 },
250 };
251
252 static struct lttng_event_field ipv6fields[] = {
253 [0] = {
254 .name = "version",
255 .type = __type_integer(uint8_t, 4, 4, 0,
256 __BIG_ENDIAN, 10, none),
257 },
258 [1] = {
259 .name = "prio",
260 .type = __type_integer(uint8_t, 4, 4, 0,
261 __BIG_ENDIAN, 10, none),
262 },
263 [2] = {
264 .name = "flow_lbl",
265 .type = {
266 .atype = atype_array,
267 .u.array.elem_type =
268 __type_integer(uint8_t, 0, 0, 0,
269 __BIG_ENDIAN, 16, none),
270 .u.array.length = 3,
271 .u.array.elem_alignment = lttng_alignof(uint8_t),
272 },
273 },
274 [3] = {
275 .name = "payload_len",
276 .type = __type_integer(uint16_t, 0, 0, 0,
277 __BIG_ENDIAN, 10, none),
278 },
279 [4] = {
280 .name = "nexthdr",
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,
288 .reverse_byte_order =
289 __BIG_ENDIAN != __BYTE_ORDER,
290 .base = 10,
291 .encoding = lttng_encode_none,
292 },
293 },
294 },
295 [5] = {
296 .name = "hop_limit",
297 .type = __type_integer(uint8_t, 0, 0, 0,
298 __BIG_ENDIAN, 10, none),
299 },
300 [6] = {
301 .name = "saddr",
302 .type = {
303 .atype = atype_array,
304 .u.array.elem_type =
305 __type_integer(uint16_t, 0, 0, 0,
306 __BIG_ENDIAN, 16, none),
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,
315 .u.array.elem_type =
316 __type_integer(uint16_t, 0, 0, 0,
317 __BIG_ENDIAN, 16, none),
318 .u.array.length = 8,
319 .u.array.elem_alignment = lttng_alignof(uint16_t),
320 },
321 },
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 },
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 )
387
388 LTTNG_TRACEPOINT_EVENT(net_dev_xmit,
389
390 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,40))
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),
397 #else
398 TP_PROTO(struct sk_buff *skb,
399 int rc),
400
401 TP_ARGS(skb, rc),
402 #endif
403
404 TP_FIELDS(
405 ctf_integer_hex(void *, skbaddr, skb)
406 ctf_integer(int, rc, rc)
407 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,40))
408 ctf_integer(unsigned int, len, skb_len)
409 ctf_string(name, dev->name)
410 #else
411 ctf_integer(unsigned int, len, skb->len)
412 ctf_string(name, skb->dev->name)
413 #endif
414 )
415 )
416
417 LTTNG_TRACEPOINT_EVENT_CLASS(net_dev_template,
418
419 TP_PROTO(struct sk_buff *skb),
420
421 TP_ARGS(skb),
422
423 TP_FIELDS(
424 ctf_integer_hex(void *, skbaddr, skb)
425 ctf_integer(unsigned int, len, skb->len)
426 ctf_string(name, skb->dev->name)
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,
434 .u.variant.nr_choices =
435 ARRAY_SIZE(network_fields),
436 ),
437 network_header,
438 ctf_custom_code(
439 /* Copy the network header. */
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:
454 /*
455 * For any other network header
456 * type, there is nothing to do.
457 */
458 break;
459 }
460
461 /* Copy the transport header. */
462 if (__get_transport_header_type(skb)
463 == TH_TCP) {
464 ctf_align(uint32_t)
465 ctf_array_type(uint8_t, tcp_hdr(skb),
466 sizeof(struct tcphdr))
467 }
468 /*
469 * For any other transport header type,
470 * there is nothing to do.
471 */
472 )
473 )
474 )
475 )
476
477 LTTNG_TRACEPOINT_EVENT_INSTANCE(net_dev_template, net_dev_queue,
478
479 TP_PROTO(struct sk_buff *skb),
480
481 TP_ARGS(skb)
482 )
483
484 LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(net_dev_template,
485
486 netif_receive_skb,
487
488 net_if_receive_skb,
489
490 TP_PROTO(struct sk_buff *skb),
491
492 TP_ARGS(skb)
493 )
494
495 LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(net_dev_template,
496
497 netif_rx,
498
499 net_if_rx,
500
501 TP_PROTO(struct sk_buff *skb),
502
503 TP_ARGS(skb)
504 )
505 #endif /* LTTNG_TRACE_NET_H */
506
507 /* This part must be outside protection */
508 #include <probes/define_trace.h>
This page took 0.038622 seconds and 3 git commands to generate.