@@ -52,6 +52,12 @@ struct vxlanhdr {
52
52
u32 vni ;
53
53
};
54
54
55
+ // Only include the first byte to save stack space.
56
+ struct genevehdr {
57
+ u8 flags :2 ;
58
+ u8 opt_len :6 ;
59
+ };
60
+
55
61
struct skb_meta {
56
62
u32 netns ;
57
63
u32 mark ;
@@ -277,6 +283,38 @@ filter_pcap_ebpf_tunnel_l3(void *_skb, void *__skb, void *___skb, void *data, vo
277
283
return data != data_end && _skb == __skb && __skb == ___skb ;
278
284
}
279
285
286
+ #define VXLAN_PORT1_NET 6177 // 8472 in net byte order.
287
+ #define VXLAN_PORT2_NET 46354 // 4789 in net byte order.
288
+ #define GENEVE_PORT_NET 49431 // 6081 in net byte order.
289
+
290
+ // Attempts to detect tunnel header length for either vxlan or geneve.
291
+ // This is based on tuple source/dest ports. If no tunnel header is
292
+ // detected then -1 is returned.
293
+ static __always_inline s16
294
+ __tunnel_hdr_len (void * skb_head , u16 sport , u16 dport , u16 l4_data_off ) {
295
+ u16 tunnel_l2_off ;
296
+ if (dport == GENEVE_PORT_NET || sport == GENEVE_PORT_NET ) {
297
+ struct genevehdr gh ;
298
+ if (bpf_probe_read_kernel (& gh , sizeof (struct genevehdr ), skb_head + l4_data_off ) != 0 ) {
299
+ return -1 ;
300
+ }
301
+ tunnel_l2_off = gh .opt_len * 4 + 8 ;
302
+ } else if (dport == VXLAN_PORT1_NET || sport == VXLAN_PORT1_NET ||
303
+ dport == VXLAN_PORT2_NET || sport == VXLAN_PORT2_NET ) {
304
+ struct vxlanhdr vxh = {};
305
+ if (bpf_probe_read_kernel (& vxh , sizeof (struct vxlanhdr ), skb_head + l4_data_off ) != 0 ) {
306
+ return -1 ;
307
+ }
308
+ tunnel_l2_off = sizeof (struct vxlanhdr );
309
+ if (vxh .flags != 0x8 ) {
310
+ return -1 ;
311
+ }
312
+ } else {
313
+ return -1 ;
314
+ }
315
+ return tunnel_l2_off ;
316
+ }
317
+
280
318
static __always_inline bool
281
319
filter_pcap_tunnel_l2 (struct sk_buff * skb )
282
320
{
@@ -290,17 +328,18 @@ filter_pcap_tunnel_l2(struct sk_buff *skb)
290
328
if (BPF_CORE_READ (ip4 , protocol ) != IPPROTO_UDP ) {
291
329
return true;
292
330
}
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 ) {
331
+
332
+ struct udphdr * udp = (struct udphdr * ) (data + l4_off );
333
+ s16 tunnel_hdr_len = __tunnel_hdr_len (
334
+ skb_head ,
335
+ BPF_CORE_READ (udp , source ),
336
+ BPF_CORE_READ (udp , dest ),
337
+ l4_off + sizeof (struct udphdr ));
338
+
339
+ if (tunnel_hdr_len == -1 )
300
340
return true;
301
- }
302
341
303
- data = (void * ) (data + l4_off + 8 + 8 );
342
+ data = (void * ) (data + l4_off + sizeof ( struct udphdr ) + tunnel_hdr_len );
304
343
struct ethhdr * eth = (struct ethhdr * ) data ;
305
344
if (BPF_CORE_READ (eth , h_proto ) != bpf_htons (ETH_P_IP ))
306
345
return false;
@@ -423,15 +462,13 @@ set_tuple(struct sk_buff *skb, struct tuple *tpl, struct tuple *tunnel_tpl) {
423
462
static __always_inline void
424
463
set_tunnel (struct sk_buff * skb , struct tuple * tpl , struct tuple * tunnel_tpl , u16 l4_data_off ) {
425
464
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
465
431
- if (vxh .flags != 0x8 )
466
+ s16 tunnel_hdr_len = __tunnel_hdr_len (skb_head , tpl -> sport , tpl -> dport , l4_data_off );
467
+
468
+ if (tunnel_hdr_len == -1 )
432
469
return ;
433
470
434
- struct ethhdr * inner = (struct ethhdr * ) (skb_head + l4_data_off + sizeof ( struct vxlanhdr ) );
471
+ struct ethhdr * inner = (struct ethhdr * ) (skb_head + l4_data_off + tunnel_hdr_len );
435
472
if (BPF_CORE_READ (inner , h_proto ) != bpf_htons (ETH_P_IP ))
436
473
return ;
437
474
0 commit comments