Skip to content

Commit 9d6e005

Browse files
jrfastabdavem330
authored andcommitted
xdp: bpf redirect with map sample program
Signed-off-by: John Fastabend <[email protected]> Tested-by: Andy Gospodarek <[email protected]> Acked-by: Daniel Borkmann <[email protected]> Acked-by: Jesper Dangaard Brouer <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 2ddf71e commit 9d6e005

File tree

4 files changed

+194
-0
lines changed

4 files changed

+194
-0
lines changed

samples/bpf/Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ hostprogs-y += test_map_in_map
3838
hostprogs-y += per_socket_stats_example
3939
hostprogs-y += load_sock_ops
4040
hostprogs-y += xdp_redirect
41+
hostprogs-y += xdp_redirect_map
4142

4243
# Libbpf dependencies
4344
LIBBPF := ../../tools/lib/bpf/bpf.o
@@ -80,6 +81,7 @@ xdp_tx_iptunnel-objs := bpf_load.o $(LIBBPF) xdp_tx_iptunnel_user.o
8081
test_map_in_map-objs := bpf_load.o $(LIBBPF) test_map_in_map_user.o
8182
per_socket_stats_example-objs := $(LIBBPF) cookie_uid_helper_example.o
8283
xdp_redirect-objs := bpf_load.o $(LIBBPF) xdp_redirect_user.o
84+
xdp_redirect_map-objs := bpf_load.o $(LIBBPF) xdp_redirect_map_user.o
8385

8486
# Tell kbuild to always build the programs
8587
always := $(hostprogs-y)
@@ -122,6 +124,7 @@ always += tcp_cong_kern.o
122124
always += tcp_iw_kern.o
123125
always += tcp_clamp_kern.o
124126
always += xdp_redirect_kern.o
127+
always += xdp_redirect_map_kern.o
125128

126129
HOSTCFLAGS += -I$(objtree)/usr/include
127130
HOSTCFLAGS += -I$(srctree)/tools/lib/
@@ -159,6 +162,7 @@ HOSTLOADLIBES_lwt_len_hist += -l elf
159162
HOSTLOADLIBES_xdp_tx_iptunnel += -lelf
160163
HOSTLOADLIBES_test_map_in_map += -lelf
161164
HOSTLOADLIBES_xdp_redirect += -lelf
165+
HOSTLOADLIBES_xdp_redirect_map += -lelf
162166

163167
# Allows pointing LLC/CLANG to a LLVM backend with bpf support, redefine on cmdline:
164168
# make samples/bpf/ LLC=~/git/llvm/build/bin/llc CLANG=~/git/llvm/build/bin/clang

samples/bpf/xdp_redirect_map_kern.c

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/* Copyright (c) 2017 Covalent IO, Inc. http://covalent.io
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+
* This program is distributed in the hope that it will be useful, but
8+
* WITHOUT ANY WARRANTY; without even the implied warranty of
9+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10+
* General Public License for more details.
11+
*/
12+
#define KBUILD_MODNAME "foo"
13+
#include <uapi/linux/bpf.h>
14+
#include <linux/in.h>
15+
#include <linux/if_ether.h>
16+
#include <linux/if_packet.h>
17+
#include <linux/if_vlan.h>
18+
#include <linux/ip.h>
19+
#include <linux/ipv6.h>
20+
#include "bpf_helpers.h"
21+
22+
struct bpf_map_def SEC("maps") tx_port = {
23+
.type = BPF_MAP_TYPE_DEVMAP,
24+
.key_size = sizeof(int),
25+
.value_size = sizeof(int),
26+
.max_entries = 100,
27+
};
28+
29+
struct bpf_map_def SEC("maps") rxcnt = {
30+
.type = BPF_MAP_TYPE_PERCPU_ARRAY,
31+
.key_size = sizeof(u32),
32+
.value_size = sizeof(long),
33+
.max_entries = 1,
34+
};
35+
36+
37+
static void swap_src_dst_mac(void *data)
38+
{
39+
unsigned short *p = data;
40+
unsigned short dst[3];
41+
42+
dst[0] = p[0];
43+
dst[1] = p[1];
44+
dst[2] = p[2];
45+
p[0] = p[3];
46+
p[1] = p[4];
47+
p[2] = p[5];
48+
p[3] = dst[0];
49+
p[4] = dst[1];
50+
p[5] = dst[2];
51+
}
52+
53+
SEC("xdp_redirect_map")
54+
int xdp_redirect_map_prog(struct xdp_md *ctx)
55+
{
56+
void *data_end = (void *)(long)ctx->data_end;
57+
void *data = (void *)(long)ctx->data;
58+
struct ethhdr *eth = data;
59+
int rc = XDP_DROP;
60+
int vport, port = 0, m = 0;
61+
long *value;
62+
u32 key = 0;
63+
u64 nh_off;
64+
65+
nh_off = sizeof(*eth);
66+
if (data + nh_off > data_end)
67+
return rc;
68+
69+
/* constant virtual port */
70+
vport = 0;
71+
72+
/* count packet in global counter */
73+
value = bpf_map_lookup_elem(&rxcnt, &key);
74+
if (value)
75+
*value += 1;
76+
77+
swap_src_dst_mac(data);
78+
79+
/* send packet out physical port */
80+
return bpf_redirect_map(&tx_port, vport, 0);
81+
}
82+
83+
char _license[] SEC("license") = "GPL";

samples/bpf/xdp_redirect_map_user.c

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/* Copyright (c) 2017 Covalent IO, Inc. http://covalent.io
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+
* This program is distributed in the hope that it will be useful, but
8+
* WITHOUT ANY WARRANTY; without even the implied warranty of
9+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10+
* General Public License for more details.
11+
*/
12+
#include <linux/bpf.h>
13+
#include <assert.h>
14+
#include <errno.h>
15+
#include <signal.h>
16+
#include <stdio.h>
17+
#include <stdlib.h>
18+
#include <string.h>
19+
#include <unistd.h>
20+
21+
#include "bpf_load.h"
22+
#include "bpf_util.h"
23+
#include "libbpf.h"
24+
25+
static int ifindex_in;
26+
static int ifindex_out;
27+
28+
static void int_exit(int sig)
29+
{
30+
set_link_xdp_fd(ifindex_in, -1, 0);
31+
exit(0);
32+
}
33+
34+
/* simple per-protocol drop counter
35+
*/
36+
static void poll_stats(int interval, int ifindex)
37+
{
38+
unsigned int nr_cpus = bpf_num_possible_cpus();
39+
__u64 values[nr_cpus], prev[nr_cpus];
40+
41+
memset(prev, 0, sizeof(prev));
42+
43+
while (1) {
44+
__u64 sum = 0;
45+
__u32 key = 0;
46+
int i;
47+
48+
sleep(interval);
49+
assert(bpf_map_lookup_elem(map_fd[1], &key, values) == 0);
50+
for (i = 0; i < nr_cpus; i++)
51+
sum += (values[i] - prev[i]);
52+
if (sum)
53+
printf("ifindex %i: %10llu pkt/s\n",
54+
ifindex, sum / interval);
55+
memcpy(prev, values, sizeof(values));
56+
}
57+
}
58+
59+
int main(int ac, char **argv)
60+
{
61+
char filename[256];
62+
int ret, key = 0;
63+
64+
snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
65+
66+
if (ac != 3) {
67+
printf("usage: %s IFINDEX_IN IFINDEX_OUT\n", argv[0]);
68+
return 1;
69+
}
70+
71+
ifindex_in = strtoul(argv[1], NULL, 0);
72+
ifindex_out = strtoul(argv[2], NULL, 0);
73+
74+
if (load_bpf_file(filename)) {
75+
printf("%s", bpf_log_buf);
76+
return 1;
77+
}
78+
79+
if (!prog_fd[0]) {
80+
printf("load_bpf_file: %s\n", strerror(errno));
81+
return 1;
82+
}
83+
84+
signal(SIGINT, int_exit);
85+
86+
if (set_link_xdp_fd(ifindex_in, prog_fd[0], 0) < 0) {
87+
printf("link set xdp fd failed\n");
88+
return 1;
89+
}
90+
91+
printf("map[0] (vports) = %i, map[1] (map) = %i, map[2] (count) = %i\n",
92+
map_fd[0], map_fd[1], map_fd[2]);
93+
94+
/* populate virtual to physical port map */
95+
ret = bpf_map_update_elem(map_fd[0], &key, &ifindex_out, 0);
96+
if (ret) {
97+
perror("bpf_update_elem");
98+
goto out;
99+
}
100+
101+
poll_stats(2, ifindex_out);
102+
103+
out:
104+
return 0;
105+
}

tools/testing/selftests/bpf/bpf_helpers.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ static int (*bpf_clone_redirect)(void *ctx, int ifindex, int flags) =
3838
(void *) BPF_FUNC_clone_redirect;
3939
static int (*bpf_redirect)(int ifindex, int flags) =
4040
(void *) BPF_FUNC_redirect;
41+
static int (*bpf_redirect_map)(void *map, int key, int flags) =
42+
(void *) BPF_FUNC_redirect_map;
4143
static int (*bpf_perf_event_output)(void *ctx, void *map,
4244
unsigned long long flags, void *data,
4345
int size) =

0 commit comments

Comments
 (0)