net: Add IPv4/IPv6 header data to net_* tracepoints
[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,
24 * the network header will point 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 network headers. */
33
34 static struct lttng_event_field ipv4fields[] = {
35 [0] = {
36 .name = "version",
37 .type = __type_integer(uint8_t, 4, 4, 0, __BIG_ENDIAN, 10, none),
38 },
39 [1] = {
40 .name = "ihl",
41 .type = __type_integer(uint8_t, 4, 4, 0, __BIG_ENDIAN, 10, none),
42 },
43 [2] = {
44 .name = "tos",
45 .type = __type_integer(uint8_t, 0, 0, 0, __BIG_ENDIAN, 10, none),
46 },
47 [3] = {
48 .name = "tot_len",
49 .type = __type_integer(uint16_t, 0, 0, 0, __BIG_ENDIAN, 10, none),
50 },
51 [4] = {
52 .name = "id",
53 .type = __type_integer(uint16_t, 0, 0, 0, __BIG_ENDIAN, 16, none),
54 },
55 [5] = {
56 .name = "frag_off",
57 .type = __type_integer(uint16_t, 0, 0, 0, __BIG_ENDIAN, 10, none),
58 },
59 [6] = {
60 .name = "ttl",
61 .type = __type_integer(uint8_t, 0, 0, 0, __BIG_ENDIAN, 10, none),
62 },
63 [7] = {
64 .name = "protocol",
65 .type = __type_integer(uint8_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 = "saddr",
73 .type = {
74 .atype = atype_array,
75 .u.array.elem_type = __type_integer(uint8_t, 0, 0, 0, __BIG_ENDIAN, 10, none),
76 .u.array.length = 4,
77 .u.array.elem_alignment = lttng_alignof(uint8_t),
78 },
79 },
80 [10] = {
81 .name = "daddr",
82 .type = {
83 .atype = atype_array,
84 .u.array.elem_type = __type_integer(uint8_t, 0, 0, 0, __BIG_ENDIAN, 10, none),
85 .u.array.length = 4,
86 .u.array.elem_alignment = lttng_alignof(uint8_t),
87 },
88 },
89 };
90
91 static struct lttng_event_field ipv6fields[] = {
92 [0] = {
93 .name = "version",
94 .type = __type_integer(uint8_t, 4, 4, 0, __BIG_ENDIAN, 10, none),
95 },
96 [1] = {
97 .name = "prio",
98 .type = __type_integer(uint8_t, 4, 4, 0, __BIG_ENDIAN, 10, none),
99 },
100 [2] = {
101 .name = "flow_lbl",
102 .type = {
103 .atype = atype_array,
104 .u.array.elem_type = __type_integer(uint8_t, 0, 0, 0, __BIG_ENDIAN, 16, none),
105 .u.array.length = 3,
106 .u.array.elem_alignment = lttng_alignof(uint8_t),
107 },
108 },
109 [3] = {
110 .name = "payload_len",
111 .type = __type_integer(uint16_t, 0, 0, 0, __BIG_ENDIAN, 10, none),
112 },
113 [4] = {
114 .name = "nexthdr",
115 .type = __type_integer(uint8_t, 0, 0, 0, __BIG_ENDIAN, 10, none),
116 },
117 [5] = {
118 .name = "hop_limit",
119 .type = __type_integer(uint8_t, 0, 0, 0, __BIG_ENDIAN, 10, none),
120 },
121 [6] = {
122 .name = "saddr",
123 .type = {
124 .atype = atype_array,
125 .u.array.elem_type = __type_integer(uint16_t, 0, 0, 0, __BIG_ENDIAN, 16, none),
126 .u.array.length = 8,
127 .u.array.elem_alignment = lttng_alignof(uint16_t),
128 },
129 },
130 [7] = {
131 .name = "daddr",
132 .type = {
133 .atype = atype_array,
134 .u.array.elem_type = __type_integer(uint16_t, 0, 0, 0, __BIG_ENDIAN, 16, none),
135 .u.array.length = 8,
136 .u.array.elem_alignment = lttng_alignof(uint16_t),
137 },
138 },
139 };
140
141 static struct lttng_event_field network_fields[] = {
142 [0] = {
143 .name = "unknown",
144 .type = {
145 .atype = atype_struct,
146 .u._struct.nr_fields = 0,
147 .u._struct.fields = emptyfields,
148 },
149 },
150 [1] = {
151 .name = "ipv4",
152 .type = {
153 .atype = atype_struct,
154 .u._struct.nr_fields = ARRAY_SIZE(ipv4fields),
155 .u._struct.fields = ipv4fields,
156 },
157 },
158 [2] = {
159 .name = "ipv6",
160 .type = {
161 .atype = atype_struct,
162 .u._struct.nr_fields = ARRAY_SIZE(ipv6fields),
163 .u._struct.fields = ipv6fields,
164 },
165 },
166 };
167
168 enum network_header_types {
169 NH_NONE,
170 NH_IPV4,
171 NH_IPV6,
172 };
173
174 static inline unsigned char __get_network_header_type(struct sk_buff *skb)
175 {
176 if (__has_network_hdr(skb)) {
177 if (skb->protocol == htons(ETH_P_IPV6))
178 return NH_IPV6;
179 else if (skb->protocol == htons(ETH_P_IP))
180 return NH_IPV4;
181 /* Fallthrough for other header types. */
182 }
183 return NH_NONE;
184 }
185
186 #endif
187
188 LTTNG_TRACEPOINT_ENUM(net_network_header,
189 TP_ENUM_VALUES(
190 ctf_enum_value("_unknown", NH_NONE)
191 ctf_enum_value("_ipv4", NH_IPV4)
192 ctf_enum_value("_ipv6", NH_IPV6)
193 )
194 )
195
196 LTTNG_TRACEPOINT_EVENT(net_dev_xmit,
197
198 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,40))
199 TP_PROTO(struct sk_buff *skb,
200 int rc,
201 struct net_device *dev,
202 unsigned int skb_len),
203
204 TP_ARGS(skb, rc, dev, skb_len),
205 #else
206 TP_PROTO(struct sk_buff *skb,
207 int rc),
208
209 TP_ARGS(skb, rc),
210 #endif
211
212 TP_FIELDS(
213 ctf_integer_hex(void *, skbaddr, skb)
214 ctf_integer(int, rc, rc)
215 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,40))
216 ctf_integer(unsigned int, len, skb_len)
217 ctf_string(name, dev->name)
218 #else
219 ctf_integer(unsigned int, len, skb->len)
220 ctf_string(name, skb->dev->name)
221 #endif
222 )
223 )
224
225 LTTNG_TRACEPOINT_EVENT_CLASS(net_dev_template,
226
227 TP_PROTO(struct sk_buff *skb),
228
229 TP_ARGS(skb),
230
231 TP_FIELDS(
232 ctf_integer_hex(void *, skbaddr, skb)
233 ctf_integer(unsigned int, len, skb->len)
234 ctf_string(name, skb->dev->name)
235 ctf_enum(net_network_header, unsigned char,
236 network_header_type, __get_network_header_type(skb))
237 ctf_custom_field(
238 ctf_custom_type(
239 .atype = atype_variant,
240 .u.variant.tag_name = "network_header_type",
241 .u.variant.choices = network_fields,
242 .u.variant.nr_choices = ARRAY_SIZE(network_fields),
243 ),
244 network_header,
245 ctf_custom_code(
246 switch (__get_network_header_type(skb)) {
247 case NH_IPV4: {
248 ctf_align(uint16_t)
249 ctf_array_type(uint8_t, ip_hdr(skb),
250 sizeof(struct iphdr))
251 break;
252 }
253 case NH_IPV6: {
254 ctf_align(uint16_t)
255 ctf_array_type(uint8_t, ipv6_hdr(skb),
256 sizeof(struct ipv6hdr))
257 break;
258 }
259 default:
260 /* For any other header type, there is nothing to do. */
261 break;
262 }
263 )
264 )
265 )
266 )
267
268 LTTNG_TRACEPOINT_EVENT_INSTANCE(net_dev_template, net_dev_queue,
269
270 TP_PROTO(struct sk_buff *skb),
271
272 TP_ARGS(skb)
273 )
274
275 LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(net_dev_template,
276
277 netif_receive_skb,
278
279 net_if_receive_skb,
280
281 TP_PROTO(struct sk_buff *skb),
282
283 TP_ARGS(skb)
284 )
285
286 LTTNG_TRACEPOINT_EVENT_INSTANCE_MAP(net_dev_template,
287
288 netif_rx,
289
290 net_if_rx,
291
292 TP_PROTO(struct sk_buff *skb),
293
294 TP_ARGS(skb)
295 )
296 #endif /* LTTNG_TRACE_NET_H */
297
298 /* This part must be outside protection */
299 #include <probes/define_trace.h>
This page took 0.035874 seconds and 5 git commands to generate.