diff --git a/extras/bpf/Makefile b/extras/bpf/Makefile index 77b06434237..9ad26eaacb1 100644 --- a/extras/bpf/Makefile +++ b/extras/bpf/Makefile @@ -1,13 +1,14 @@ -CC?=clang -# where to find bpf includes? -BPF_ROOT?=/usr/include -#BPF_ROOT?=/opt/vpp/external/x86_64/include +CC := $(shell which clang) -CFLAGS:=-O3 -g -Wextra -Wall -target bpf +# where to find bpf includes? +BPF_ROOT ?= /usr/include +#BPF_ROOT ?= /opt/vpp/external/x86_64/include + +CFLAGS := -O3 -g -Wextra -Wall -target bpf # Workaround for Ubuntu/Debian for asm/types.h -CFLAGS+= -I/usr/include/x86_64-linux-gnu -CFLAGS+= -I$(BPF_ROOT) -#CFLAGS+= -DDEBUG +CFLAGS += -I/usr/include/x86_64-linux-gnu +CFLAGS += -I$(BPF_ROOT) +#CFLAGS += -DDEBUG all: af_xdp.bpf.o diff --git a/extras/bpf/af_xdp.bpf.c b/extras/bpf/af_xdp.bpf.c index eddd2b0e509..c9ca0193ce5 100644 --- a/extras/bpf/af_xdp.bpf.c +++ b/extras/bpf/af_xdp.bpf.c @@ -4,11 +4,15 @@ * Copyright (c) 2020 Cisco and/or its affiliates. */ #include +#include +#include #include #include #include #include -#include + +#define XDP_METADATA_SECTION "xdp_metadata" +#define XSK_PROG_VERSION 1 /* * when compiled, debug print can be viewed with eg. @@ -26,63 +30,70 @@ #define DEBUG_PRINT(fmt, ...) #endif /* DEBUG */ -#define ntohs(x) __constant_ntohs(x) +#define ntohs(x) __constant_ntohs (x) -SEC("maps") -struct bpf_map_def xsks_map = { - .type = BPF_MAP_TYPE_XSKMAP, - .key_size = sizeof(int), - .value_size = sizeof(int), - .max_entries = 64, /* max 64 queues per device */ -}; +#define DEFAULT_QUEUE_IDS 64 -SEC("xdp_sock") -int xdp_sock_prog(struct xdp_md *ctx) { - const void *data = (void *)(long)ctx->data; - const void *data_end = (void *)(long)ctx->data_end; +struct +{ + __uint (type, BPF_MAP_TYPE_XSKMAP); + __uint (key_size, sizeof (int)); + __uint (value_size, sizeof (int)); + __uint (max_entries, DEFAULT_QUEUE_IDS); +} xsks_map SEC (".maps"); - DEBUG_PRINT("rx %ld bytes packet", (long)data_end - (long)data); +struct +{ + __uint (priority, 10); + __uint (XDP_PASS, 1); +} XDP_RUN_CONFIG (xdp_sock_prog); - /* smallest packet we are interesting in is ip-ip */ - if (data + sizeof(struct ethhdr) + 2 * sizeof(struct iphdr) > data_end) { - DEBUG_PRINT("packet too small"); - return XDP_PASS; +SEC ("xdp") +int +xdp_sock_prog (struct xdp_md *ctx) +{ + const void *data = (void *) (long) ctx->data; + const void *data_end = (void *) (long) ctx->data_end; + + DEBUG_PRINT ("rx %ld bytes packet", (long) data_end - (long) data); + + /* smallest packet we are interesting in is ip-ip */ + if (data + sizeof (struct ethhdr) + 2 * sizeof (struct iphdr) > data_end) + { + DEBUG_PRINT ("packet too small"); + return XDP_PASS; } - const struct ethhdr *eth = data; - if (eth->h_proto != ntohs(ETH_P_IP)) { - DEBUG_PRINT("unsupported eth proto %x", (int)eth->h_proto); - return XDP_PASS; + const struct ethhdr *eth = data; + if (eth->h_proto != ntohs (ETH_P_IP)) + { + DEBUG_PRINT ("unsupported eth proto %x", (int) eth->h_proto); + return XDP_PASS; } - const struct iphdr *ip = (void *)(eth + 1); - switch (ip->protocol) { - case IPPROTO_UDP: { - const struct udphdr *udp = (void *)(ip + 1); - if (udp->dest != ntohs(4789)) { /* VxLAN dest port */ - DEBUG_PRINT("unsupported udp dst port %x", (int)udp->dest); - return XDP_PASS; - } - } - case IPPROTO_IPIP: - case IPPROTO_ESP: - break; - default: - DEBUG_PRINT("unsupported ip proto %x", (int)ip->protocol); - return XDP_PASS; - } - - int qid = ctx->rx_queue_index; - if (!bpf_map_lookup_elem(&xsks_map, &qid)) + const struct iphdr *ip = (void *) (eth + 1); + switch (ip->protocol) + { + case IPPROTO_UDP: { - DEBUG_PRINT("no socket found"); - return XDP_PASS; + const struct udphdr *udp = (void *) (ip + 1); + if (udp->dest != ntohs (4789)) /* VxLAN dest port */ + { + DEBUG_PRINT ("unsupported udp dst port %x", (int) udp->dest); + return XDP_PASS; + } } + case IPPROTO_IPIP: + case IPPROTO_ESP: + break; + default: + DEBUG_PRINT ("unsupported ip proto %x", (int) ip->protocol); + return XDP_PASS; + } - DEBUG_PRINT("going to socket %d", qid); - return bpf_redirect_map(&xsks_map, qid, 0); + return bpf_redirect_map (&xsks_map, ctx->rx_queue_index, XDP_PASS); } /* actually Dual GPLv2/Apache2, but GPLv2 as far as kernel is concerned */ -SEC("license") -char _license[] = "GPL"; +char _license[] SEC ("license") = "GPL"; +__uint (xsk_prog_version, XSK_PROG_VERSION) SEC (XDP_METADATA_SECTION);