Skip to content

Commit 698e31d

Browse files
committed
add support for geneve tunnel type.
When reading optional tunnel data, look at ports to try to determine the tunnel type. We now use this to get a header length based on the expected tunnel header type allowing us to read into the tunnel l{2,3} data. Signed-off-by: Tom Hadlaw <[email protected]>
1 parent a54bcbe commit 698e31d

File tree

1 file changed

+52
-15
lines changed

1 file changed

+52
-15
lines changed

bpf/kprobe_pwru.c

+52-15
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,12 @@ struct vxlanhdr {
5252
u32 vni;
5353
};
5454

55+
// Only include the first byte to save stack space.
56+
struct genevehdr {
57+
u8 flags:2;
58+
u8 opt_len:6;
59+
};
60+
5561
struct skb_meta {
5662
u32 netns;
5763
u32 mark;
@@ -277,6 +283,38 @@ filter_pcap_ebpf_tunnel_l3(void *_skb, void *__skb, void *___skb, void *data, vo
277283
return data != data_end && _skb == __skb && __skb == ___skb;
278284
}
279285

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+
280318
static __always_inline bool
281319
filter_pcap_tunnel_l2(struct sk_buff *skb)
282320
{
@@ -290,17 +328,18 @@ filter_pcap_tunnel_l2(struct sk_buff *skb)
290328
if (BPF_CORE_READ(ip4, protocol) != IPPROTO_UDP) {
291329
return true;
292330
}
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)
300340
return true;
301-
}
302341

303-
data = (void*) (data + l4_off + 8 + 8);
342+
data = (void*) (data + l4_off + sizeof(struct udphdr) + tunnel_hdr_len);
304343
struct ethhdr *eth = (struct ethhdr*) data;
305344
if (BPF_CORE_READ(eth, h_proto) != bpf_htons(ETH_P_IP))
306345
return false;
@@ -423,15 +462,13 @@ set_tuple(struct sk_buff *skb, struct tuple *tpl, struct tuple *tunnel_tpl) {
423462
static __always_inline void
424463
set_tunnel(struct sk_buff *skb, struct tuple *tpl, struct tuple *tunnel_tpl, u16 l4_data_off) {
425464
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-
}
430465

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)
432469
return;
433470

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);
435472
if (BPF_CORE_READ(inner, h_proto) != bpf_htons(ETH_P_IP))
436473
return;
437474

0 commit comments

Comments
 (0)