Skip to content

Instantly share code, notes, and snippets.

@higebu
Created January 19, 2019 13:07
Show Gist options
  • Save higebu/d3f61b01545c62a2a0a043f5c8416850 to your computer and use it in GitHub Desktop.
Save higebu/d3f61b01545c62a2a0a043f5c8416850 to your computer and use it in GitHub Desktop.
Simple XDP example
LLVM_PREFIX ?= /usr/bin
CLANG ?= $(LLVM_PREFIX)/clang
LLC ?= $(LLVM_PREFIX)/llc
INCLUDEFLAGS = -I/usr/include
all: xdp_prog.elf
clean:
-$(RM) *.elf
%.elf : %.o
$(LLC) -march=bpf -filetype=obj -o $@ $<
%.o : %.c
$(CLANG) $(INCLUDEFLAGS) -target bpf -O2 -emit-llvm -g \
-Wall -Werror \
-Wno-unused-variable \
-Wno-compare-distinct-pointer-types \
-Wno-implicit-function-declaration \
-c $< -o $@
#include <linux/bpf.h>
#include <linux/in.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long u64;
#define BPF_FUNC_map_lookup_elem 1
static void *(*bpf_map_lookup_elem)(void *map, void *key) =
(void *) BPF_FUNC_map_lookup_elem;
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
# define __bpf_htons(x) __builtin_bswap16(x)
# define __bpf_constant_htons(x) ___constant_swab16(x)
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
# define __bpf_htons(x) (x)
# define __bpf_constant_htons(x) (x)
#else
# error "Fix your compiler's __BYTE_ORDER__?!"
#endif
# define bpf_htons(x) \
(__builtin_constant_p(x) ? \
__bpf_constant_htons(x) : __bpf_htons(x))
struct bpf_map_def {
u32 type;
u32 key_size;
u32 value_size;
u32 max_entries;
u32 flags;
u32 inner_map_idx;
};
#define SEC(NAME) __attribute__((section(NAME), used))
struct bpf_map_def SEC("maps") rxcnt = {
.type = BPF_MAP_TYPE_ARRAY,
.key_size = sizeof(u32),
.value_size = sizeof(long),
.max_entries = 256,
};
static int parse_ipv4(void *data, u64 nh_off, void *data_end)
{
struct iphdr *iph = data + nh_off;
if (iph + 1 > data_end)
return 0;
return iph->protocol;
}
static int parse_ipv6(void *data, u64 nh_off, void *data_end)
{
struct ipv6hdr *ip6h = data + nh_off;
if (ip6h + 1 > data_end)
return 0;
return ip6h->nexthdr;
}
SEC("xdp")
int xdp_prog(struct xdp_md *ctx)
{
void *data_end = (void *)(long)ctx->data_end;
void *data = (void *)(long)ctx->data;
struct ethhdr *eth = data;
long *value;
u16 h_proto;
u64 nh_off;
u32 ipproto;
nh_off = sizeof(*eth);
if (data + nh_off > data_end)
return XDP_DROP;
h_proto = eth->h_proto;
if (h_proto == bpf_htons(ETH_P_IP))
ipproto = parse_ipv4(data, nh_off, data_end);
else if (h_proto == bpf_htons(ETH_P_IPV6))
ipproto = parse_ipv6(data, nh_off, data_end);
else
ipproto = 0;
value = bpf_map_lookup_elem(&rxcnt, &ipproto);
if (value)
*value += 1;
return XDP_PASS;
}
char _license[] SEC("license") = "MIT";
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment