summaryrefslogtreecommitdiffstats
path: root/samples
diff options
context:
space:
mode:
authorBrenden Blanco <bblanco@plumgrid.com>2016-07-19 15:16:57 -0400
committerDavid S. Miller <davem@davemloft.net>2016-07-20 00:46:33 -0400
commit764cbccef8c9cb95e869ba2bb8371c42685c934a (patch)
treef776e9a5cb46b98c4148f83a3f960022dd3c142e /samples
parent4acf6c0b84c91243c705303cd9ff16421914150d (diff)
bpf: add sample for xdp forwarding and rewrite
Add a sample that rewrites and forwards packets out on the same interface. Observed single core forwarding performance of ~10Mpps. Since the mlx4 driver under test recycles every single packet page, the perf output shows almost exclusively just the ring management and bpf program work. Slowdowns are likely occurring due to cache misses. Signed-off-by: Brenden Blanco <bblanco@plumgrid.com> Acked-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'samples')
-rw-r--r--samples/bpf/Makefile5
-rw-r--r--samples/bpf/xdp2_kern.c114
2 files changed, 119 insertions, 0 deletions
diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile
index 0e4ab3a9dfa9..d2d2b35c67eb 100644
--- a/samples/bpf/Makefile
+++ b/samples/bpf/Makefile
@@ -22,6 +22,7 @@ hostprogs-y += map_perf_test
22hostprogs-y += test_overhead 22hostprogs-y += test_overhead
23hostprogs-y += test_cgrp2_array_pin 23hostprogs-y += test_cgrp2_array_pin
24hostprogs-y += xdp1 24hostprogs-y += xdp1
25hostprogs-y += xdp2
25 26
26test_verifier-objs := test_verifier.o libbpf.o 27test_verifier-objs := test_verifier.o libbpf.o
27test_maps-objs := test_maps.o libbpf.o 28test_maps-objs := test_maps.o libbpf.o
@@ -44,6 +45,8 @@ map_perf_test-objs := bpf_load.o libbpf.o map_perf_test_user.o
44test_overhead-objs := bpf_load.o libbpf.o test_overhead_user.o 45test_overhead-objs := bpf_load.o libbpf.o test_overhead_user.o
45test_cgrp2_array_pin-objs := libbpf.o test_cgrp2_array_pin.o 46test_cgrp2_array_pin-objs := libbpf.o test_cgrp2_array_pin.o
46xdp1-objs := bpf_load.o libbpf.o xdp1_user.o 47xdp1-objs := bpf_load.o libbpf.o xdp1_user.o
48# reuse xdp1 source intentionally
49xdp2-objs := bpf_load.o libbpf.o xdp1_user.o
47 50
48# Tell kbuild to always build the programs 51# Tell kbuild to always build the programs
49always := $(hostprogs-y) 52always := $(hostprogs-y)
@@ -67,6 +70,7 @@ always += test_overhead_kprobe_kern.o
67always += parse_varlen.o parse_simple.o parse_ldabs.o 70always += parse_varlen.o parse_simple.o parse_ldabs.o
68always += test_cgrp2_tc_kern.o 71always += test_cgrp2_tc_kern.o
69always += xdp1_kern.o 72always += xdp1_kern.o
73always += xdp2_kern.o
70 74
71HOSTCFLAGS += -I$(objtree)/usr/include 75HOSTCFLAGS += -I$(objtree)/usr/include
72 76
@@ -88,6 +92,7 @@ HOSTLOADLIBES_spintest += -lelf
88HOSTLOADLIBES_map_perf_test += -lelf -lrt 92HOSTLOADLIBES_map_perf_test += -lelf -lrt
89HOSTLOADLIBES_test_overhead += -lelf -lrt 93HOSTLOADLIBES_test_overhead += -lelf -lrt
90HOSTLOADLIBES_xdp1 += -lelf 94HOSTLOADLIBES_xdp1 += -lelf
95HOSTLOADLIBES_xdp2 += -lelf
91 96
92# Allows pointing LLC/CLANG to a LLVM backend with bpf support, redefine on cmdline: 97# Allows pointing LLC/CLANG to a LLVM backend with bpf support, redefine on cmdline:
93# make samples/bpf/ LLC=~/git/llvm/build/bin/llc CLANG=~/git/llvm/build/bin/clang 98# make samples/bpf/ LLC=~/git/llvm/build/bin/llc CLANG=~/git/llvm/build/bin/clang
diff --git a/samples/bpf/xdp2_kern.c b/samples/bpf/xdp2_kern.c
new file mode 100644
index 000000000000..38fe7e1d0db4
--- /dev/null
+++ b/samples/bpf/xdp2_kern.c
@@ -0,0 +1,114 @@
1/* Copyright (c) 2016 PLUMgrid
2 *
3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of version 2 of the GNU General Public
5 * License as published by the Free Software Foundation.
6 */
7#define KBUILD_MODNAME "foo"
8#include <uapi/linux/bpf.h>
9#include <linux/in.h>
10#include <linux/if_ether.h>
11#include <linux/if_packet.h>
12#include <linux/if_vlan.h>
13#include <linux/ip.h>
14#include <linux/ipv6.h>
15#include "bpf_helpers.h"
16
17struct bpf_map_def SEC("maps") dropcnt = {
18 .type = BPF_MAP_TYPE_PERCPU_ARRAY,
19 .key_size = sizeof(u32),
20 .value_size = sizeof(long),
21 .max_entries = 256,
22};
23
24static void swap_src_dst_mac(void *data)
25{
26 unsigned short *p = data;
27 unsigned short dst[3];
28
29 dst[0] = p[0];
30 dst[1] = p[1];
31 dst[2] = p[2];
32 p[0] = p[3];
33 p[1] = p[4];
34 p[2] = p[5];
35 p[3] = dst[0];
36 p[4] = dst[1];
37 p[5] = dst[2];
38}
39
40static int parse_ipv4(void *data, u64 nh_off, void *data_end)
41{
42 struct iphdr *iph = data + nh_off;
43
44 if (iph + 1 > data_end)
45 return 0;
46 return iph->protocol;
47}
48
49static int parse_ipv6(void *data, u64 nh_off, void *data_end)
50{
51 struct ipv6hdr *ip6h = data + nh_off;
52
53 if (ip6h + 1 > data_end)
54 return 0;
55 return ip6h->nexthdr;
56}
57
58SEC("xdp1")
59int xdp_prog1(struct xdp_md *ctx)
60{
61 void *data_end = (void *)(long)ctx->data_end;
62 void *data = (void *)(long)ctx->data;
63 struct ethhdr *eth = data;
64 int rc = XDP_DROP;
65 long *value;
66 u16 h_proto;
67 u64 nh_off;
68 u32 index;
69
70 nh_off = sizeof(*eth);
71 if (data + nh_off > data_end)
72 return rc;
73
74 h_proto = eth->h_proto;
75
76 if (h_proto == htons(ETH_P_8021Q) || h_proto == htons(ETH_P_8021AD)) {
77 struct vlan_hdr *vhdr;
78
79 vhdr = data + nh_off;
80 nh_off += sizeof(struct vlan_hdr);
81 if (data + nh_off > data_end)
82 return rc;
83 h_proto = vhdr->h_vlan_encapsulated_proto;
84 }
85 if (h_proto == htons(ETH_P_8021Q) || h_proto == htons(ETH_P_8021AD)) {
86 struct vlan_hdr *vhdr;
87
88 vhdr = data + nh_off;
89 nh_off += sizeof(struct vlan_hdr);
90 if (data + nh_off > data_end)
91 return rc;
92 h_proto = vhdr->h_vlan_encapsulated_proto;
93 }
94
95 if (h_proto == htons(ETH_P_IP))
96 index = parse_ipv4(data, nh_off, data_end);
97 else if (h_proto == htons(ETH_P_IPV6))
98 index = parse_ipv6(data, nh_off, data_end);
99 else
100 index = 0;
101
102 value = bpf_map_lookup_elem(&dropcnt, &index);
103 if (value)
104 *value += 1;
105
106 if (index == 17) {
107 swap_src_dst_mac(data);
108 rc = XDP_TX;
109 }
110
111 return rc;
112}
113
114char _license[] SEC("license") = "GPL";