blob: eddd2b0e509204666d25c833155f080c0b6607cc [file] [log] [blame]
BenoƮt Ganne4a76d6f2020-06-12 08:47:34 +02001/*
2 * SPDX-License-Identifier: GPL-2.0 OR Apache-2.0
3 * Dual-licensed under GPL version 2.0 or Apache License version 2.0
4 * Copyright (c) 2020 Cisco and/or its affiliates.
5 */
6#include <linux/bpf.h>
7#include <linux/in.h>
8#include <linux/if_ether.h>
9#include <linux/ip.h>
10#include <linux/udp.h>
11#include <bpf/bpf_helpers.h>
12
13/*
14 * when compiled, debug print can be viewed with eg.
15 * sudo cat /sys/kernel/debug/tracing/trace_pipe
16 */
17#ifdef DEBUG
18#define s__(n) # n
19#define s_(n) s__(n)
20#define x_(fmt) __FILE__ ":" s_(__LINE__) ": " fmt "\n"
21#define DEBUG_PRINT_(fmt, ...) do { \
22 const char fmt__[] = fmt; \
23 bpf_trace_printk(fmt__, sizeof(fmt), ## __VA_ARGS__); } while(0)
24#define DEBUG_PRINT(fmt, ...) DEBUG_PRINT_ (x_(fmt), ## __VA_ARGS__)
25#else /* DEBUG */
26#define DEBUG_PRINT(fmt, ...)
27#endif /* DEBUG */
28
29#define ntohs(x) __constant_ntohs(x)
30
31SEC("maps")
32struct bpf_map_def xsks_map = {
33 .type = BPF_MAP_TYPE_XSKMAP,
34 .key_size = sizeof(int),
35 .value_size = sizeof(int),
36 .max_entries = 64, /* max 64 queues per device */
37};
38
39SEC("xdp_sock")
40int xdp_sock_prog(struct xdp_md *ctx) {
41 const void *data = (void *)(long)ctx->data;
42 const void *data_end = (void *)(long)ctx->data_end;
43
44 DEBUG_PRINT("rx %ld bytes packet", (long)data_end - (long)data);
45
46 /* smallest packet we are interesting in is ip-ip */
47 if (data + sizeof(struct ethhdr) + 2 * sizeof(struct iphdr) > data_end) {
48 DEBUG_PRINT("packet too small");
49 return XDP_PASS;
50 }
51
52 const struct ethhdr *eth = data;
53 if (eth->h_proto != ntohs(ETH_P_IP)) {
54 DEBUG_PRINT("unsupported eth proto %x", (int)eth->h_proto);
55 return XDP_PASS;
56 }
57
58 const struct iphdr *ip = (void *)(eth + 1);
59 switch (ip->protocol) {
60 case IPPROTO_UDP: {
61 const struct udphdr *udp = (void *)(ip + 1);
62 if (udp->dest != ntohs(4789)) { /* VxLAN dest port */
63 DEBUG_PRINT("unsupported udp dst port %x", (int)udp->dest);
64 return XDP_PASS;
65 }
66 }
67 case IPPROTO_IPIP:
68 case IPPROTO_ESP:
69 break;
70 default:
71 DEBUG_PRINT("unsupported ip proto %x", (int)ip->protocol);
72 return XDP_PASS;
73 }
74
75 int qid = ctx->rx_queue_index;
76 if (!bpf_map_lookup_elem(&xsks_map, &qid))
77 {
78 DEBUG_PRINT("no socket found");
79 return XDP_PASS;
80 }
81
82 DEBUG_PRINT("going to socket %d", qid);
83 return bpf_redirect_map(&xsks_map, qid, 0);
84}
85
86/* actually Dual GPLv2/Apache2, but GPLv2 as far as kernel is concerned */
87SEC("license")
88char _license[] = "GPL";