@@ -47,6 +47,11 @@ union addr {
47
47
} v6addr ;
48
48
} __attribute__((packed ));
49
49
50
+ struct vxlanhdr {
51
+ u32 flags ;
52
+ u32 vni ;
53
+ };
54
+
50
55
struct skb_meta {
51
56
u32 netns ;
52
57
u32 mark ;
@@ -85,6 +90,7 @@ struct event_t {
85
90
u64 print_shinfo_id ;
86
91
struct skb_meta meta ;
87
92
struct tuple tuple ;
93
+ struct tuple tunnel_tuple ;
88
94
s64 print_stack_id ;
89
95
u64 param_second ;
90
96
u64 param_third ;
@@ -146,7 +152,7 @@ struct config {
146
152
u8 output_stack : 1 ;
147
153
u8 output_caller : 1 ;
148
154
u8 output_cb : 1 ;
149
- u8 output_unused : 1 ;
155
+ u8 output_tunnel : 1 ;
150
156
u8 is_set : 1 ;
151
157
u8 track_skb : 1 ;
152
158
u8 track_skb_by_stackid : 1 ;
@@ -259,8 +265,59 @@ filter_pcap_l2(struct sk_buff *skb)
259
265
return filter_pcap_ebpf_l2 ((void * )skb , (void * )skb , (void * )skb , data , data_end );
260
266
}
261
267
268
+ static __noinline bool
269
+ filter_pcap_ebpf_tunnel_l2 (void * _skb , void * __skb , void * ___skb , void * data , void * data_end )
270
+ {
271
+ return data != data_end && _skb == __skb && __skb == ___skb ;
272
+ }
273
+
274
+ static __noinline bool
275
+ filter_pcap_ebpf_tunnel_l3 (void * _skb , void * __skb , void * ___skb , void * data , void * data_end )
276
+ {
277
+ return data != data_end && _skb == __skb && __skb == ___skb ;
278
+ }
279
+
280
+ static __always_inline bool
281
+ filter_pcap_tunnel_l2 (struct sk_buff * skb )
282
+ {
283
+ void * skb_head = BPF_CORE_READ (skb , head );
284
+ void * data = skb_head ;
285
+ void * data_end = skb_head + BPF_CORE_READ (skb , tail );
286
+ u16 l3_off = BPF_CORE_READ (skb , network_header );
287
+ struct iphdr * ip4 = (struct iphdr * ) (data + l3_off );
288
+ u16 l4_off = l3_off + BPF_CORE_READ_BITFIELD_PROBED (ip4 , ihl ) * 4 ;
289
+ // For VXLAN, we only care about udp packets.
290
+ if (BPF_CORE_READ (ip4 , protocol ) != IPPROTO_UDP ) {
291
+ return true;
292
+ }
293
+
294
+ struct vxlanhdr vxh = {};
295
+ if (bpf_probe_read_kernel (& vxh , sizeof (struct vxlanhdr ), data + l4_off + 8 ) != 0 ) {
296
+ return true;
297
+ }
298
+
299
+ if (vxh .flags != 8 ) {
300
+ return true;
301
+ }
302
+
303
+ data = (void * ) (data + l4_off + 8 + 8 );
304
+ struct ethhdr * eth = (struct ethhdr * ) data ;
305
+ if (BPF_CORE_READ (eth , h_proto ) != bpf_htons (ETH_P_IP ))
306
+ return false;
307
+ if (!filter_pcap_ebpf_tunnel_l2 ((void * )skb , (void * )skb , (void * )skb , data , data_end )) {
308
+ return false;
309
+ }
310
+ struct iphdr * iph = (struct iphdr * ) (data + sizeof (struct ethhdr ));
311
+ u32 saddr = BPF_CORE_READ (iph , saddr );
312
+ data = (void * ) (data + sizeof (struct ethhdr ));
313
+ return filter_pcap_ebpf_tunnel_l3 ((void * )skb , (void * )skb , (void * )skb , data , data_end );
314
+ }
315
+
262
316
static __always_inline bool
263
317
filter_pcap (struct sk_buff * skb ) {
318
+ if (!filter_pcap_tunnel_l2 (skb )) {
319
+ return false;
320
+ }
264
321
if (BPF_CORE_READ (skb , mac_len ) == 0 )
265
322
return filter_pcap_l3 (skb );
266
323
return filter_pcap_l2 (skb );
@@ -288,7 +345,31 @@ set_meta(struct sk_buff *skb, struct skb_meta *meta) {
288
345
}
289
346
}
290
347
291
- static __always_inline void
348
+ // Returns l4 offset
349
+ static __always_inline u16
350
+ __set_l3_tuple (void * data , u16 l3_off , bool is_ipv4 , union addr * saddr , union addr * daddr , u16 * l3_proto , u8 * l4_proto )
351
+ {
352
+ u16 l4_off ;
353
+ if (is_ipv4 ) {
354
+ struct iphdr * ip4 = (struct iphdr * ) (data + l3_off );
355
+ BPF_CORE_READ_INTO (saddr , ip4 , saddr );
356
+ BPF_CORE_READ_INTO (daddr , ip4 , daddr );
357
+ BPF_CORE_READ_INTO (l4_proto , ip4 , protocol );
358
+ * l3_proto = ETH_P_IP ;
359
+ l4_off = l3_off + BPF_CORE_READ_BITFIELD_PROBED (ip4 , ihl ) * 4 ;
360
+
361
+ } else {
362
+ struct ipv6hdr * ip6 = (struct ipv6hdr * ) (data + l3_off );
363
+ BPF_CORE_READ_INTO (saddr , ip6 , saddr );
364
+ BPF_CORE_READ_INTO (daddr , ip6 , daddr );
365
+ BPF_CORE_READ_INTO (l4_proto , ip6 , nexthdr );
366
+ * l3_proto = ETH_P_IPV6 ;
367
+ l4_off = l3_off + ipv6_hdrlen (ip6 );
368
+ }
369
+ return l4_off ;
370
+ }
371
+
372
+ static __always_inline u16
292
373
__set_tuple (struct tuple * tpl , void * data , u16 l3_off , bool is_ipv4 ) {
293
374
u16 l4_off ;
294
375
@@ -314,26 +395,51 @@ __set_tuple(struct tuple *tpl, void *data, u16 l3_off, bool is_ipv4) {
314
395
tpl -> sport = BPF_CORE_READ (tcp , source );
315
396
tpl -> dport = BPF_CORE_READ (tcp , dest );
316
397
bpf_probe_read_kernel (& tpl -> tcp_flags , sizeof (tpl -> tcp_flags ), (void * )tcp + offsetof(struct tcphdr , window ) - 1 );
398
+ return l4_off + sizeof (* tcp );
317
399
} else if (tpl -> l4_proto == IPPROTO_UDP ) {
318
400
struct udphdr * udp = (struct udphdr * ) (data + l4_off );
319
401
tpl -> sport = BPF_CORE_READ (udp , source );
320
402
tpl -> dport = BPF_CORE_READ (udp , dest );
403
+ return l4_off + sizeof (* udp );
321
404
}
405
+ return l4_off ;
322
406
}
323
407
324
- static __always_inline void
325
- set_tuple (struct sk_buff * skb , struct tuple * tpl ) {
408
+ static __always_inline s16
409
+ set_tuple (struct sk_buff * skb , struct tuple * tpl , struct tuple * tunnel_tpl ) {
326
410
void * skb_head = BPF_CORE_READ (skb , head );
327
411
u16 l3_off = BPF_CORE_READ (skb , network_header );
328
412
329
413
struct iphdr * l3_hdr = (struct iphdr * ) (skb_head + l3_off );
330
414
u8 ip_vsn = BPF_CORE_READ_BITFIELD_PROBED (l3_hdr , version );
331
415
332
416
if (ip_vsn != 4 && ip_vsn != 6 )
417
+ return -1 ;
418
+
419
+ bool is_ipv4 = ip_vsn == 4 ;
420
+ return __set_tuple (tpl , skb_head , l3_off , is_ipv4 );
421
+ }
422
+
423
+ static __always_inline void
424
+ set_tunnel (struct sk_buff * skb , struct tuple * tpl , struct tuple * tunnel_tpl , u16 l4_data_off ) {
425
+ void * skb_head = BPF_CORE_READ (skb , head );
426
+ struct vxlanhdr vxh = {};
427
+ if (bpf_probe_read_kernel (& vxh , sizeof (struct vxlanhdr ), skb_head + l4_data_off ) != 0 ) {
428
+ return ;
429
+ }
430
+
431
+ if (vxh .flags != 0x8 )
333
432
return ;
334
433
434
+ struct ethhdr * inner = (struct ethhdr * ) (skb_head + l4_data_off + sizeof (struct vxlanhdr ));
435
+ if (BPF_CORE_READ (inner , h_proto ) != bpf_htons (ETH_P_IP ))
436
+ return ;
437
+
438
+ struct iphdr * l3_hdr = (struct iphdr * ) (skb_head + l4_data_off + sizeof (struct vxlanhdr ) + sizeof (struct ethhdr ));
439
+ u8 ip_vsn = BPF_CORE_READ_BITFIELD_PROBED (l3_hdr , version );
335
440
bool is_ipv4 = ip_vsn == 4 ;
336
- __set_tuple (tpl , skb_head , l3_off , is_ipv4 );
441
+ u16 l3_off = l4_data_off + sizeof (struct vxlanhdr ) + sizeof (struct ethhdr );
442
+ __set_tuple (tunnel_tpl , skb_head , l3_off , is_ipv4 );
337
443
}
338
444
339
445
static __always_inline u64
@@ -433,7 +539,10 @@ set_output(void *ctx, struct sk_buff *skb, struct event_t *event) {
433
539
}
434
540
435
541
if (cfg -> output_tuple ) {
436
- set_tuple (skb , & event -> tuple );
542
+ s16 l4_off = set_tuple (skb , & event -> tuple , & event -> tunnel_tuple );
543
+ if (cfg -> output_tunnel && l4_off != -1 && event -> tuple .l4_proto == IPPROTO_UDP ) {
544
+ set_tunnel (skb , & event -> tuple , & event -> tunnel_tuple , l4_off );
545
+ }
437
546
}
438
547
439
548
if (cfg -> output_skb ) {
0 commit comments