FD.io VPP  v20.09-64-g4f7b92f0a
Vector Packet Processing
af_xdp.bpf.c
Go to the documentation of this file.
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 <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 
31 SEC("maps")
32 struct 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 
39 SEC("xdp_sock")
40 int 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 */
87 SEC("license")
88 char _license[] = "GPL";
#define ntohs(x)
Definition: af_xdp.bpf.c:29
u8 data[128]
Definition: ipsec_types.api:89
struct bpf_map_def xsks_map
Definition: af_xdp.bpf.c:32
long ctx[MAX_CONNS]
Definition: main.c:144
#define DEBUG_PRINT(fmt,...)
Definition: af_xdp.bpf.c:26
int xdp_sock_prog(struct xdp_md *ctx)
Definition: af_xdp.bpf.c:40
vl_api_address_t ip
Definition: l2.api:501