Benoît Ganne | 4a76d6f | 2020-06-12 08:47:34 +0200 | [diff] [blame] | 1 | /* |
| 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> |
Yulong Pei | a3f1b4c | 2023-01-25 08:05:03 +0000 | [diff] [blame] | 7 | #include <bpf/bpf_helpers.h> |
| 8 | #include <xdp/xdp_helpers.h> |
Benoît Ganne | 4a76d6f | 2020-06-12 08:47:34 +0200 | [diff] [blame] | 9 | #include <linux/in.h> |
| 10 | #include <linux/if_ether.h> |
| 11 | #include <linux/ip.h> |
| 12 | #include <linux/udp.h> |
Yulong Pei | a3f1b4c | 2023-01-25 08:05:03 +0000 | [diff] [blame] | 13 | |
| 14 | #define XDP_METADATA_SECTION "xdp_metadata" |
| 15 | #define XSK_PROG_VERSION 1 |
Benoît Ganne | 4a76d6f | 2020-06-12 08:47:34 +0200 | [diff] [blame] | 16 | |
| 17 | /* |
| 18 | * when compiled, debug print can be viewed with eg. |
| 19 | * sudo cat /sys/kernel/debug/tracing/trace_pipe |
| 20 | */ |
| 21 | #ifdef DEBUG |
| 22 | #define s__(n) # n |
| 23 | #define s_(n) s__(n) |
| 24 | #define x_(fmt) __FILE__ ":" s_(__LINE__) ": " fmt "\n" |
| 25 | #define DEBUG_PRINT_(fmt, ...) do { \ |
| 26 | const char fmt__[] = fmt; \ |
| 27 | bpf_trace_printk(fmt__, sizeof(fmt), ## __VA_ARGS__); } while(0) |
| 28 | #define DEBUG_PRINT(fmt, ...) DEBUG_PRINT_ (x_(fmt), ## __VA_ARGS__) |
| 29 | #else /* DEBUG */ |
| 30 | #define DEBUG_PRINT(fmt, ...) |
| 31 | #endif /* DEBUG */ |
| 32 | |
Yulong Pei | a3f1b4c | 2023-01-25 08:05:03 +0000 | [diff] [blame] | 33 | #define ntohs(x) __constant_ntohs (x) |
Benoît Ganne | 4a76d6f | 2020-06-12 08:47:34 +0200 | [diff] [blame] | 34 | |
Yulong Pei | a3f1b4c | 2023-01-25 08:05:03 +0000 | [diff] [blame] | 35 | #define DEFAULT_QUEUE_IDS 64 |
Benoît Ganne | 4a76d6f | 2020-06-12 08:47:34 +0200 | [diff] [blame] | 36 | |
Yulong Pei | a3f1b4c | 2023-01-25 08:05:03 +0000 | [diff] [blame] | 37 | struct |
| 38 | { |
| 39 | __uint (type, BPF_MAP_TYPE_XSKMAP); |
| 40 | __uint (key_size, sizeof (int)); |
| 41 | __uint (value_size, sizeof (int)); |
| 42 | __uint (max_entries, DEFAULT_QUEUE_IDS); |
| 43 | } xsks_map SEC (".maps"); |
Benoît Ganne | 4a76d6f | 2020-06-12 08:47:34 +0200 | [diff] [blame] | 44 | |
Yulong Pei | a3f1b4c | 2023-01-25 08:05:03 +0000 | [diff] [blame] | 45 | struct |
| 46 | { |
| 47 | __uint (priority, 10); |
| 48 | __uint (XDP_PASS, 1); |
| 49 | } XDP_RUN_CONFIG (xdp_sock_prog); |
Benoît Ganne | 4a76d6f | 2020-06-12 08:47:34 +0200 | [diff] [blame] | 50 | |
Yulong Pei | a3f1b4c | 2023-01-25 08:05:03 +0000 | [diff] [blame] | 51 | SEC ("xdp") |
| 52 | int |
| 53 | xdp_sock_prog (struct xdp_md *ctx) |
| 54 | { |
| 55 | const void *data = (void *) (long) ctx->data; |
| 56 | const void *data_end = (void *) (long) ctx->data_end; |
| 57 | |
| 58 | DEBUG_PRINT ("rx %ld bytes packet", (long) data_end - (long) data); |
| 59 | |
| 60 | /* smallest packet we are interesting in is ip-ip */ |
| 61 | if (data + sizeof (struct ethhdr) + 2 * sizeof (struct iphdr) > data_end) |
| 62 | { |
| 63 | DEBUG_PRINT ("packet too small"); |
| 64 | return XDP_PASS; |
Benoît Ganne | 4a76d6f | 2020-06-12 08:47:34 +0200 | [diff] [blame] | 65 | } |
| 66 | |
Yulong Pei | a3f1b4c | 2023-01-25 08:05:03 +0000 | [diff] [blame] | 67 | const struct ethhdr *eth = data; |
| 68 | if (eth->h_proto != ntohs (ETH_P_IP)) |
| 69 | { |
| 70 | DEBUG_PRINT ("unsupported eth proto %x", (int) eth->h_proto); |
| 71 | return XDP_PASS; |
Benoît Ganne | 4a76d6f | 2020-06-12 08:47:34 +0200 | [diff] [blame] | 72 | } |
| 73 | |
Yulong Pei | a3f1b4c | 2023-01-25 08:05:03 +0000 | [diff] [blame] | 74 | const struct iphdr *ip = (void *) (eth + 1); |
| 75 | switch (ip->protocol) |
| 76 | { |
| 77 | case IPPROTO_UDP: |
Benoît Ganne | 4a76d6f | 2020-06-12 08:47:34 +0200 | [diff] [blame] | 78 | { |
Yulong Pei | a3f1b4c | 2023-01-25 08:05:03 +0000 | [diff] [blame] | 79 | const struct udphdr *udp = (void *) (ip + 1); |
| 80 | if (udp->dest != ntohs (4789)) /* VxLAN dest port */ |
| 81 | { |
| 82 | DEBUG_PRINT ("unsupported udp dst port %x", (int) udp->dest); |
| 83 | return XDP_PASS; |
| 84 | } |
Benoît Ganne | 4a76d6f | 2020-06-12 08:47:34 +0200 | [diff] [blame] | 85 | } |
Yulong Pei | a3f1b4c | 2023-01-25 08:05:03 +0000 | [diff] [blame] | 86 | case IPPROTO_IPIP: |
| 87 | case IPPROTO_ESP: |
| 88 | break; |
| 89 | default: |
| 90 | DEBUG_PRINT ("unsupported ip proto %x", (int) ip->protocol); |
| 91 | return XDP_PASS; |
| 92 | } |
Benoît Ganne | 4a76d6f | 2020-06-12 08:47:34 +0200 | [diff] [blame] | 93 | |
Yulong Pei | a3f1b4c | 2023-01-25 08:05:03 +0000 | [diff] [blame] | 94 | return bpf_redirect_map (&xsks_map, ctx->rx_queue_index, XDP_PASS); |
Benoît Ganne | 4a76d6f | 2020-06-12 08:47:34 +0200 | [diff] [blame] | 95 | } |
| 96 | |
| 97 | /* actually Dual GPLv2/Apache2, but GPLv2 as far as kernel is concerned */ |
Yulong Pei | a3f1b4c | 2023-01-25 08:05:03 +0000 | [diff] [blame] | 98 | char _license[] SEC ("license") = "GPL"; |
| 99 | __uint (xsk_prog_version, XSK_PROG_VERSION) SEC (XDP_METADATA_SECTION); |