net: Add TCP header data to net_* tracepoints
[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 /*
23 * If the header is not set yet,
24 * the network header will point to the head.
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",
37 .type = __type_integer(uint16_t, 0, 0, 0, __BIG_ENDIAN, 10, none),
38 },
39 [1] = {
40 .name = "dest_port",
41 .type = __type_integer(uint16_t, 0, 0, 0, __BIG_ENDIAN, 10, none),
42 },
43 [2] = {
44 .name = "seq",
45 .type = __type_integer(uint32_t, 0, 0, 0, __BIG_ENDIAN, 10, none),
46 },
47 [3] = {
48 .name = "ack_seq",
49 .type = __type_integer(uint32_t, 0, 0, 0, __BIG_ENDIAN, 10, none),
50 },
51 [4] = {
52 .name = "data_offset",
53 .type = __type_integer(uint8_t, 4, 4, 0, __BIG_ENDIAN, 10, none),
54 },
55 [5] = {
56 .name = "reserved",
57 .type = __type_integer(uint8_t, 3, 1, 0, __BIG_ENDIAN, 10, none),
58 },
59 [6] = {
60 .name = "flags",
61 .type = __type_integer(uint8_t, 9, 1, 0, __BIG_ENDIAN, 16, none),
62 },
63 [7] = {
64 .name = "window_size",
65 .type = __type_integer(uint16_t, 0, 0, 0, __BIG_ENDIAN, 10, none),
66 },
67 [8] = {
68 .name = "checksum",
69 .type = __type_integer(uint16_t, 0, 0, 0, __BIG_ENDIAN, 16, none),
70 },
71 [9] = {
72 .name = "urg_ptr",
73 .type = __type_integer(uint16_t, 0, 0, 0, __BIG_ENDIAN, 10, none),
74 },
75};
76
77static struct lttng_event_field transport_fields[] = {
78 [0] = {
79 .name = "unknown",
80 .type = {
81 .atype = atype_struct,
82 .u._struct.nr_fields = ARRAY_SIZE(emptyfields),
83 .u._struct.fields = emptyfields,
84 },
85 },
86 [1] = {
87 .name = "tcp",
88 .type = {
89 .atype = atype_struct,
90 .u._struct.nr_fields = ARRAY_SIZE(tcpfields),
91 .u._struct.fields = tcpfields,
92 },
93 },
94};
95
96enum transport_header_types {
97 TH_NONE,
98 TH_TCP,
99};
100
101static inline unsigned char __get_transport_header_type(struct sk_buff *skb)
102{
103 if (__has_network_hdr(skb)) {
104 /*
105 * When both transport and network header are set, transport header
106 * is greater than network header, otherwise it points to head.
107 */
108 if (skb->transport_header > skb->network_header) {
109 /*
110 * Get the transport protocol from the network header's data.
111 * This method works both for sent and received packets.
112 */
113 if ((skb->protocol == htons(ETH_P_IP) &&
114 ip_hdr(skb)->protocol == IPPROTO_TCP) ||
115 (skb->protocol == htons(ETH_P_IPV6) &&
116 ipv6_hdr(skb)->nexthdr == IPPROTO_TCP))
117 return TH_TCP;
118 }
119 /* Fallthrough for other cases where header is not TCP. */
120 }
121 return TH_NONE;
122}
123
124static struct lttng_enum_entry transport_enum_entries[] = {
125 [0] = {
126 .start = { .value = 0, .signedness = 0, },
127 .end = { .value = IPPROTO_TCP - 1, .signedness = 0, },
128 .string = "_unknown",
129 },
130 [1] = {
131 .start = { .value = IPPROTO_TCP, .signedness = 0, },
132 .end = { .value = IPPROTO_TCP, .signedness = 0, },
133 .string = "_tcp",
134 },
135 [2] = {
136 .start = { .value = IPPROTO_TCP + 1, .signedness = 0, },
137 .end = { .value = 255, .signedness = 0, },
138 .string = "_unknown",
139 },
140};
141
142static const struct lttng_enum_desc transport_header_type = {
143 .name = "transport_header_type",
144 .entries = transport_enum_entries,
145 .nr_entries = ARRAY_SIZE(transport_enum_entries),
146};
147
e5990fd4
GB
148/* Structures for network headers. */
149
150static struct lttng_event_field ipv4fields[] = {
151 [0] = {
152 .name = "version",
153 .type = __type_integer(uint8_t, 4, 4, 0, __BIG_ENDIAN, 10, none),
154 },
155 [1] = {
156 .name = "ihl",
157 .type = __type_integer(uint8_t, 4, 4, 0, __BIG_ENDIAN, 10, none),
158 },
159 [2] = {
160 .name = "tos",
161 .type = __type_integer(uint8_t, 0, 0, 0, __BIG_ENDIAN, 10, none),
162 },
163 [3] = {
164 .name = "tot_len",
165 .type = __type_integer(uint16_t, 0, 0, 0, __BIG_ENDIAN, 10, none),
166 },
167 [4] = {
168 .name = "id",
169 .type = __type_integer(uint16_t, 0, 0, 0, __BIG_ENDIAN, 16, none),
170 },
171 [5] = {
172 .name = "frag_off",
173 .type = __type_integer(uint16_t, 0, 0, 0, __BIG_ENDIAN, 10, none),
174 },
175 [6] = {
176 .name = "ttl",
177 .type = __type_integer(uint8_t, 0, 0, 0, __BIG_ENDIAN, 10, none),
178 },
179 [7] = {
180 .name = "protocol",
9cf9736a
GB
181 .type = {
182 .atype = atype_enum,
183 .u.basic.enumeration.desc = &transport_header_type,
184 .u.basic.enumeration.container_type = {
185 .size = 8,
186 .alignment = 8,
187 .signedness = 0,
188 .reverse_byte_order = __BIG_ENDIAN != __BYTE_ORDER,
189 .base = 10,
190 .encoding = lttng_encode_none,
191 },
192 },
e5990fd4
GB
193 },
194 [8] = {
195 .name = "checksum",
196 .type = __type_integer(uint16_t, 0, 0, 0, __BIG_ENDIAN, 16, none),
197 },
198 [9] = {
199 .name = "saddr",
200 .type = {
201 .atype = atype_array,
202 .u.array.elem_type = __type_integer(uint8_t, 0, 0, 0, __BIG_ENDIAN, 10, none),
203 .u.array.length = 4,
204 .u.array.elem_alignment = lttng_alignof(uint8_t),
205 },
206 },
207 [10] = {
208 .name = "daddr",
209 .type = {
210 .atype = atype_array,
211 .u.array.elem_type = __type_integer(uint8_t, 0, 0, 0, __BIG_ENDIAN, 10, none),
212 .u.array.length = 4,
213 .u.array.elem_alignment = lttng_alignof(uint8_t),
214 },
215 },
9cf9736a
GB
216 [11] = {
217 .name = "transport_header",
218 .type = {
219 .atype = atype_variant,
220 .u.variant.tag_name = "protocol",
221 .u.variant.choices = transport_fields,
222 .u.variant.nr_choices = ARRAY_SIZE(transport_fields),
223 },
224 },
e5990fd4
GB
225};
226
227static struct lttng_event_field ipv6fields[] = {
228 [0] = {
229 .name = "version",
230 .type = __type_integer(uint8_t, 4, 4, 0, __BIG_ENDIAN, 10, none),
231 },
232 [1] = {
233 .name = "prio",
234 .type = __type_integer(uint8_t, 4, 4, 0, __BIG_ENDIAN, 10, none),
235 },
236 [2] = {
237 .name = "flow_lbl",
238 .type = {
239 .atype = atype_array,
240 .u.array.elem_type = __type_integer(uint8_t, 0, 0, 0, __BIG_ENDIAN, 16, none),
241 .u.array.length = 3,
242 .u.array.elem_alignment = lttng_alignof(uint8_t),
243 },
244 },
245 [3] = {
246 .name = "payload_len",
247 .type = __type_integer(uint16_t, 0, 0, 0, __BIG_ENDIAN, 10, none),
248 },
249 [4] = {
250 .name = "nexthdr",
9cf9736a
GB
251 .type = {
252 .atype = atype_enum,
253 .u.basic.enumeration.desc = &transport_header_type,
254 .u.basic.enumeration.container_type = {
255 .size = 8,
256 .alignment = 8,
257 .signedness = 0,
258 .reverse_byte_order = __BIG_ENDIAN != __BYTE_ORDER,
259 .base = 10,
260 .encoding = lttng_encode_none,
261 },
262 },
e5990fd4
GB
263 },
264 [5] = {
265 .name = "hop_limit",
266 .type = __type_integer(uint8_t, 0, 0, 0, __BIG_ENDIAN, 10, none),
267 },
268 [6] = {
269 .name = "saddr",
270 .type = {
271 .atype = atype_array,
272 .u.array.elem_type = __type_integer(uint16_t, 0, 0, 0, __BIG_ENDIAN, 16, none),
273 .u.array.length = 8,
274 .u.array.elem_alignment = lttng_alignof(uint16_t),
275 },
276 },
277 [7] = {
278 .name = "daddr",
279 .type = {
280 .atype = atype_array,
281 .u.array.elem_type = __type_integer(uint16_t, 0, 0, 0, __BIG_ENDIAN, 16, none),
282 .u.array.length = 8,
283 .u.array.elem_alignment = lttng_alignof(uint16_t),
284 },
285 },
9cf9736a
GB
286 [8] = {
287 .name = "transport_header",
288 .type = {
289 .atype = atype_variant,
290 .u.variant.tag_name = "nexthdr",
291 .u.variant.choices = transport_fields,
292 .u.variant.nr_choices = ARRAY_SIZE(transport_fields),
293 },
294 },
e5990fd4
GB
295};
296
297static struct lttng_event_field network_fields[] = {
298 [0] = {
299 .name = "unknown",
300 .type = {
301 .atype = atype_struct,
302 .u._struct.nr_fields = 0,
303 .u._struct.fields = emptyfields,
304 },
305 },
306 [1] = {
307 .name = "ipv4",
308 .type = {
309 .atype = atype_struct,
310 .u._struct.nr_fields = ARRAY_SIZE(ipv4fields),
311 .u._struct.fields = ipv4fields,
312 },
313 },
314 [2] = {
315 .name = "ipv6",
316 .type = {
317 .atype = atype_struct,
318 .u._struct.nr_fields = ARRAY_SIZE(ipv6fields),
319 .u._struct.fields = ipv6fields,
320 },
321 },
322};
323
324enum network_header_types {
325 NH_NONE,
326 NH_IPV4,
327 NH_IPV6,
328};
329
330static inline unsigned char __get_network_header_type(struct sk_buff *skb)
331{
332 if (__has_network_hdr(skb)) {
333 if (skb->protocol == htons(ETH_P_IPV6))
334 return NH_IPV6;
335 else if (skb->protocol == htons(ETH_P_IP))
336 return NH_IPV4;
337 /* Fallthrough for other header types. */
338 }
339 return NH_NONE;
340}
341
342#endif
343
344LTTNG_TRACEPOINT_ENUM(net_network_header,
345 TP_ENUM_VALUES(
346 ctf_enum_value("_unknown", NH_NONE)
347 ctf_enum_value("_ipv4", NH_IPV4)
348 ctf_enum_value("_ipv6", NH_IPV6)
349 )
350)
b283666f 351
3bc29f0a 352LTTNG_TRACEPOINT_EVENT(net_dev_xmit,
b283666f 353
f95480cf 354#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,40))
b283666f
PW
355 TP_PROTO(struct sk_buff *skb,
356 int rc,
357 struct net_device *dev,
358 unsigned int skb_len),
359
360 TP_ARGS(skb, rc, dev, skb_len),
4a7363f7
PW
361#else
362 TP_PROTO(struct sk_buff *skb,
363 int rc),
364
365 TP_ARGS(skb, rc),
366#endif
b283666f 367
f127e61e 368 TP_FIELDS(
fa91fcac 369 ctf_integer_hex(void *, skbaddr, skb)
f127e61e 370 ctf_integer(int, rc, rc)
f95480cf 371#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,40))
974c0969 372 ctf_integer(unsigned int, len, skb_len)
f127e61e 373 ctf_string(name, dev->name)
4a7363f7 374#else
974c0969 375 ctf_integer(unsigned int, len, skb->len)
f127e61e 376 ctf_string(name, skb->dev->name)
4a7363f7 377#endif
f127e61e 378 )
b283666f
PW
379)
380
3bc29f0a 381LTTNG_TRACEPOINT_EVENT_CLASS(net_dev_template,
b283666f
PW
382
383 TP_PROTO(struct sk_buff *skb),
384
385 TP_ARGS(skb),
386
f127e61e 387 TP_FIELDS(
fa91fcac 388 ctf_integer_hex(void *, skbaddr, skb)
f127e61e
MD
389 ctf_integer(unsigned int, len, skb->len)
390 ctf_string(name, skb->dev->name)
e5990fd4
GB
391 ctf_enum(net_network_header, unsigned char,
392 network_header_type, __get_network_header_type(skb))
393 ctf_custom_field(
394 ctf_custom_type(
395 .atype = atype_variant,
396 .u.variant.tag_name = "network_header_type",
397 .u.variant.choices = network_fields,
398 .u.variant.nr_choices = ARRAY_SIZE(network_fields),
399 ),
400 network_header,
401 ctf_custom_code(
9cf9736a 402 /* Copy the network header */
e5990fd4
GB
403 switch (__get_network_header_type(skb)) {
404 case NH_IPV4: {
405 ctf_align(uint16_t)
406 ctf_array_type(uint8_t, ip_hdr(skb),
407 sizeof(struct iphdr))
408 break;
409 }
410 case NH_IPV6: {
411 ctf_align(uint16_t)
412 ctf_array_type(uint8_t, ipv6_hdr(skb),
413 sizeof(struct ipv6hdr))
414 break;
415 }
416 default:
417 /* For any other header type, there is nothing to do. */
418 break;
419 }
9cf9736a
GB
420
421 /* Copy the transport header */
422 if (__get_transport_header_type(skb) == TH_TCP) {
423 ctf_align(uint32_t)
424 ctf_array_type(uint8_t, tcp_hdr(skb),
425 sizeof(struct tcphdr))
426 }
427 /* For any other header type, there is nothing to do. */
e5990fd4
GB
428 )
429 )
f127e61e 430 )
b283666f
PW
431)
432
3bc29f0a 433LTTNG_TRACEPOINT_EVENT_INSTANCE(net_dev_template, net_dev_queue,
b283666f
PW
434
435 TP_PROTO(struct sk_buff *skb),
436
437 TP_ARGS(skb)
438)
439
b7f5408a
MD
440LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(net_dev_template,
441
442 netif_receive_skb,
443
444 net_if_receive_skb,
b283666f
PW
445
446 TP_PROTO(struct sk_buff *skb),
447
448 TP_ARGS(skb)
449)
450
b7f5408a
MD
451LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(net_dev_template,
452
453 netif_rx,
454
455 net_if_rx,
b283666f
PW
456
457 TP_PROTO(struct sk_buff *skb),
458
459 TP_ARGS(skb)
460)
3bc29f0a 461#endif /* LTTNG_TRACE_NET_H */
b283666f
PW
462
463/* This part must be outside protection */
6ec43db8 464#include <probes/define_trace.h>
This page took 0.047445 seconds and 4 git commands to generate.