Skip to content

Commit f74599f

Browse files
tgrafdavem330
authored andcommitted
bpf: Add tests and samples for LWT-BPF
Adds a series of tests to verify the functionality of attaching BPF programs at LWT hooks. Also adds a sample which collects a histogram of packet sizes which pass through an LWT hook. $ ./lwt_len_hist.sh Starting netserver with host 'IN(6)ADDR_ANY' port '12865' and family AF_UNSPEC MIGRATED TCP STREAM TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to 192.168.253.2 () port 0 AF_INET : demo Recv Send Send Socket Socket Message Elapsed Size Size Size Time Throughput bytes bytes bytes secs. 10^6bits/sec 87380 16384 16384 10.00 39857.69 1 -> 1 : 0 | | 2 -> 3 : 0 | | 4 -> 7 : 0 | | 8 -> 15 : 0 | | 16 -> 31 : 0 | | 32 -> 63 : 22 | | 64 -> 127 : 98 | | 128 -> 255 : 213 | | 256 -> 511 : 1444251 |******** | 512 -> 1023 : 660610 |*** | 1024 -> 2047 : 535241 |** | 2048 -> 4095 : 19 | | 4096 -> 8191 : 180 | | 8192 -> 16383 : 5578023 |************************************* | 16384 -> 32767 : 632099 |*** | 32768 -> 65535 : 6575 | | Signed-off-by: Thomas Graf <tgraf@suug.ch> Acked-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 3a0af8f commit f74599f

File tree

7 files changed

+855
-0
lines changed

7 files changed

+855
-0
lines changed

samples/bpf/Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ hostprogs-y += test_current_task_under_cgroup
2929
hostprogs-y += trace_event
3030
hostprogs-y += sampleip
3131
hostprogs-y += tc_l2_redirect
32+
hostprogs-y += lwt_len_hist
3233

3334
test_lru_dist-objs := test_lru_dist.o libbpf.o
3435
sock_example-objs := sock_example.o libbpf.o
@@ -59,6 +60,7 @@ test_current_task_under_cgroup-objs := bpf_load.o libbpf.o \
5960
trace_event-objs := bpf_load.o libbpf.o trace_event_user.o
6061
sampleip-objs := bpf_load.o libbpf.o sampleip_user.o
6162
tc_l2_redirect-objs := bpf_load.o libbpf.o tc_l2_redirect_user.o
63+
lwt_len_hist-objs := bpf_load.o libbpf.o lwt_len_hist_user.o
6264

6365
# Tell kbuild to always build the programs
6466
always := $(hostprogs-y)
@@ -89,6 +91,7 @@ always += xdp2_kern.o
8991
always += test_current_task_under_cgroup_kern.o
9092
always += trace_event_kern.o
9193
always += sampleip_kern.o
94+
always += lwt_len_hist_kern.o
9295

9396
HOSTCFLAGS += -I$(objtree)/usr/include
9497
HOSTCFLAGS += -I$(srctree)/tools/testing/selftests/bpf/
@@ -117,6 +120,7 @@ HOSTLOADLIBES_test_current_task_under_cgroup += -lelf
117120
HOSTLOADLIBES_trace_event += -lelf
118121
HOSTLOADLIBES_sampleip += -lelf
119122
HOSTLOADLIBES_tc_l2_redirect += -l elf
123+
HOSTLOADLIBES_lwt_len_hist += -l elf
120124

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

samples/bpf/bpf_helpers.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ struct bpf_map_def {
8080
unsigned int map_flags;
8181
};
8282

83+
static int (*bpf_skb_load_bytes)(void *ctx, int off, void *to, int len) =
84+
(void *) BPF_FUNC_skb_load_bytes;
8385
static int (*bpf_skb_store_bytes)(void *ctx, int off, void *from, int len, int flags) =
8486
(void *) BPF_FUNC_skb_store_bytes;
8587
static int (*bpf_l3_csum_replace)(void *ctx, int off, int from, int to, int flags) =
@@ -88,6 +90,8 @@ static int (*bpf_l4_csum_replace)(void *ctx, int off, int from, int to, int flag
8890
(void *) BPF_FUNC_l4_csum_replace;
8991
static int (*bpf_skb_under_cgroup)(void *ctx, void *map, int index) =
9092
(void *) BPF_FUNC_skb_under_cgroup;
93+
static int (*bpf_skb_change_head)(void *, int len, int flags) =
94+
(void *) BPF_FUNC_skb_change_head;
9195

9296
#if defined(__x86_64__)
9397

samples/bpf/lwt_len_hist.sh

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#!/bin/bash
2+
3+
NS1=lwt_ns1
4+
VETH0=tst_lwt1a
5+
VETH1=tst_lwt1b
6+
7+
TRACE_ROOT=/sys/kernel/debug/tracing
8+
9+
function cleanup {
10+
ip route del 192.168.253.2/32 dev $VETH0 2> /dev/null
11+
ip link del $VETH0 2> /dev/null
12+
ip link del $VETH1 2> /dev/null
13+
ip netns exec $NS1 killall netserver
14+
ip netns delete $NS1 2> /dev/null
15+
}
16+
17+
cleanup
18+
19+
ip netns add $NS1
20+
ip link add $VETH0 type veth peer name $VETH1
21+
ip link set dev $VETH0 up
22+
ip addr add 192.168.253.1/24 dev $VETH0
23+
ip link set $VETH1 netns $NS1
24+
ip netns exec $NS1 ip link set dev $VETH1 up
25+
ip netns exec $NS1 ip addr add 192.168.253.2/24 dev $VETH1
26+
ip netns exec $NS1 netserver
27+
28+
echo 1 > ${TRACE_ROOT}/tracing_on
29+
cp /dev/null ${TRACE_ROOT}/trace
30+
ip route add 192.168.253.2/32 encap bpf out obj lwt_len_hist_kern.o section len_hist dev $VETH0
31+
netperf -H 192.168.253.2 -t TCP_STREAM
32+
cat ${TRACE_ROOT}/trace | grep -v '^#'
33+
./lwt_len_hist
34+
cleanup
35+
echo 0 > ${TRACE_ROOT}/tracing_on
36+
37+
exit 0

samples/bpf/lwt_len_hist_kern.c

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/* Copyright (c) 2016 Thomas Graf <tgraf@tgraf.ch>
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+
13+
#include <uapi/linux/bpf.h>
14+
#include <uapi/linux/if_ether.h>
15+
#include <uapi/linux/ip.h>
16+
#include <uapi/linux/in.h>
17+
#include "bpf_helpers.h"
18+
19+
# define printk(fmt, ...) \
20+
({ \
21+
char ____fmt[] = fmt; \
22+
bpf_trace_printk(____fmt, sizeof(____fmt), \
23+
##__VA_ARGS__); \
24+
})
25+
26+
struct bpf_elf_map {
27+
__u32 type;
28+
__u32 size_key;
29+
__u32 size_value;
30+
__u32 max_elem;
31+
__u32 flags;
32+
__u32 id;
33+
__u32 pinning;
34+
};
35+
36+
struct bpf_elf_map SEC("maps") lwt_len_hist_map = {
37+
.type = BPF_MAP_TYPE_PERCPU_HASH,
38+
.size_key = sizeof(__u64),
39+
.size_value = sizeof(__u64),
40+
.pinning = 2,
41+
.max_elem = 1024,
42+
};
43+
44+
static unsigned int log2(unsigned int v)
45+
{
46+
unsigned int r;
47+
unsigned int shift;
48+
49+
r = (v > 0xFFFF) << 4; v >>= r;
50+
shift = (v > 0xFF) << 3; v >>= shift; r |= shift;
51+
shift = (v > 0xF) << 2; v >>= shift; r |= shift;
52+
shift = (v > 0x3) << 1; v >>= shift; r |= shift;
53+
r |= (v >> 1);
54+
return r;
55+
}
56+
57+
static unsigned int log2l(unsigned long v)
58+
{
59+
unsigned int hi = v >> 32;
60+
if (hi)
61+
return log2(hi) + 32;
62+
else
63+
return log2(v);
64+
}
65+
66+
SEC("len_hist")
67+
int do_len_hist(struct __sk_buff *skb)
68+
{
69+
__u64 *value, key, init_val = 1;
70+
71+
key = log2l(skb->len);
72+
73+
value = bpf_map_lookup_elem(&lwt_len_hist_map, &key);
74+
if (value)
75+
__sync_fetch_and_add(value, 1);
76+
else
77+
bpf_map_update_elem(&lwt_len_hist_map, &key, &init_val, BPF_ANY);
78+
79+
return BPF_OK;
80+
}
81+
82+
char _license[] SEC("license") = "GPL";

samples/bpf/lwt_len_hist_user.c

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#include <linux/unistd.h>
2+
#include <linux/bpf.h>
3+
4+
#include <stdlib.h>
5+
#include <stdio.h>
6+
#include <unistd.h>
7+
#include <string.h>
8+
#include <errno.h>
9+
#include <arpa/inet.h>
10+
11+
#include "libbpf.h"
12+
#include "bpf_util.h"
13+
14+
#define MAX_INDEX 64
15+
#define MAX_STARS 38
16+
17+
static void stars(char *str, long val, long max, int width)
18+
{
19+
int i;
20+
21+
for (i = 0; i < (width * val / max) - 1 && i < width - 1; i++)
22+
str[i] = '*';
23+
if (val > max)
24+
str[i - 1] = '+';
25+
str[i] = '\0';
26+
}
27+
28+
int main(int argc, char **argv)
29+
{
30+
unsigned int nr_cpus = bpf_num_possible_cpus();
31+
const char *map_filename = "/sys/fs/bpf/tc/globals/lwt_len_hist_map";
32+
uint64_t values[nr_cpus], sum, max_value = 0, data[MAX_INDEX] = {};
33+
uint64_t key = 0, next_key, max_key = 0;
34+
char starstr[MAX_STARS];
35+
int i, map_fd;
36+
37+
map_fd = bpf_obj_get(map_filename);
38+
if (map_fd < 0) {
39+
fprintf(stderr, "bpf_obj_get(%s): %s(%d)\n",
40+
map_filename, strerror(errno), errno);
41+
return -1;
42+
}
43+
44+
while (bpf_get_next_key(map_fd, &key, &next_key) == 0) {
45+
if (next_key >= MAX_INDEX) {
46+
fprintf(stderr, "Key %lu out of bounds\n", next_key);
47+
continue;
48+
}
49+
50+
bpf_lookup_elem(map_fd, &next_key, values);
51+
52+
sum = 0;
53+
for (i = 0; i < nr_cpus; i++)
54+
sum += values[i];
55+
56+
data[next_key] = sum;
57+
if (sum && next_key > max_key)
58+
max_key = next_key;
59+
60+
if (sum > max_value)
61+
max_value = sum;
62+
63+
key = next_key;
64+
}
65+
66+
for (i = 1; i <= max_key + 1; i++) {
67+
stars(starstr, data[i - 1], max_value, MAX_STARS);
68+
printf("%8ld -> %-8ld : %-8ld |%-*s|\n",
69+
(1l << i) >> 1, (1l << i) - 1, data[i - 1],
70+
MAX_STARS, starstr);
71+
}
72+
73+
close(map_fd);
74+
75+
return 0;
76+
}

0 commit comments

Comments
 (0)