hs-test: added interrupt mode tests
[vpp.git] / extras / bpf / af_xdp.bpf.c
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>
7 #include <bpf/bpf_helpers.h>
8 #include <xdp/xdp_helpers.h>
9 #include <linux/in.h>
10 #include <linux/if_ether.h>
11 #include <linux/ip.h>
12 #include <linux/udp.h>
13
14 #define XDP_METADATA_SECTION "xdp_metadata"
15 #define XSK_PROG_VERSION     1
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
33 #define ntohs(x) __constant_ntohs (x)
34
35 #define DEFAULT_QUEUE_IDS 64
36
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");
44
45 struct
46 {
47   __uint (priority, 10);
48   __uint (XDP_PASS, 1);
49 } XDP_RUN_CONFIG (xdp_sock_prog);
50
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;
65     }
66
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;
72     }
73
74   const struct iphdr *ip = (void *) (eth + 1);
75   switch (ip->protocol)
76     {
77     case IPPROTO_UDP:
78       {
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           }
85       }
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     }
93
94   return bpf_redirect_map (&xsks_map, ctx->rx_queue_index, XDP_PASS);
95 }
96
97 /* actually Dual GPLv2/Apache2, but GPLv2 as far as kernel is concerned */
98 char _license[] SEC ("license") = "GPL";
99 __uint (xsk_prog_version, XSK_PROG_VERSION) SEC (XDP_METADATA_SECTION);