blob: c9ca0193ce5b073fc4437729dd17ada2b6eb15b8 [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>
Yulong Peia3f1b4c2023-01-25 08:05:03 +00007#include <bpf/bpf_helpers.h>
8#include <xdp/xdp_helpers.h>
Benoît Ganne4a76d6f2020-06-12 08:47:34 +02009#include <linux/in.h>
10#include <linux/if_ether.h>
11#include <linux/ip.h>
12#include <linux/udp.h>
Yulong Peia3f1b4c2023-01-25 08:05:03 +000013
14#define XDP_METADATA_SECTION "xdp_metadata"
15#define XSK_PROG_VERSION 1
Benoît Ganne4a76d6f2020-06-12 08:47:34 +020016
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 Peia3f1b4c2023-01-25 08:05:03 +000033#define ntohs(x) __constant_ntohs (x)
Benoît Ganne4a76d6f2020-06-12 08:47:34 +020034
Yulong Peia3f1b4c2023-01-25 08:05:03 +000035#define DEFAULT_QUEUE_IDS 64
Benoît Ganne4a76d6f2020-06-12 08:47:34 +020036
Yulong Peia3f1b4c2023-01-25 08:05:03 +000037struct
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 Ganne4a76d6f2020-06-12 08:47:34 +020044
Yulong Peia3f1b4c2023-01-25 08:05:03 +000045struct
46{
47 __uint (priority, 10);
48 __uint (XDP_PASS, 1);
49} XDP_RUN_CONFIG (xdp_sock_prog);
Benoît Ganne4a76d6f2020-06-12 08:47:34 +020050
Yulong Peia3f1b4c2023-01-25 08:05:03 +000051SEC ("xdp")
52int
53xdp_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 Ganne4a76d6f2020-06-12 08:47:34 +020065 }
66
Yulong Peia3f1b4c2023-01-25 08:05:03 +000067 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 Ganne4a76d6f2020-06-12 08:47:34 +020072 }
73
Yulong Peia3f1b4c2023-01-25 08:05:03 +000074 const struct iphdr *ip = (void *) (eth + 1);
75 switch (ip->protocol)
76 {
77 case IPPROTO_UDP:
Benoît Ganne4a76d6f2020-06-12 08:47:34 +020078 {
Yulong Peia3f1b4c2023-01-25 08:05:03 +000079 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 Ganne4a76d6f2020-06-12 08:47:34 +020085 }
Yulong Peia3f1b4c2023-01-25 08:05:03 +000086 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 Ganne4a76d6f2020-06-12 08:47:34 +020093
Yulong Peia3f1b4c2023-01-25 08:05:03 +000094 return bpf_redirect_map (&xsks_map, ctx->rx_queue_index, XDP_PASS);
Benoît Ganne4a76d6f2020-06-12 08:47:34 +020095}
96
97/* actually Dual GPLv2/Apache2, but GPLv2 as far as kernel is concerned */
Yulong Peia3f1b4c2023-01-25 08:05:03 +000098char _license[] SEC ("license") = "GPL";
99__uint (xsk_prog_version, XSK_PROG_VERSION) SEC (XDP_METADATA_SECTION);