Commit c5815ac7 authored by Daniel T. Lee's avatar Daniel T. Lee Committed by Andrii Nakryiko

samples: bpf: Refactor hbm program with libbpf

This commit refactors the existing cgroup programs with libbpf
bpf loader. Since bpf_program__attach doesn't support cgroup program
attachment, this explicitly attaches cgroup bpf program with
bpf_program__attach_cgroup(bpf_prog, cg1).

Also, to change attach_type of bpf program, this uses libbpf's
bpf_program__set_expected_attach_type helper to switch EGRESS to
INGRESS. To keep bpf program attached to the cgroup hierarchy even
after the exit, this commit uses the BPF_LINK_PINNING to pin the link
attachment even after it is closed.

Besides, this program was broken due to the typo of BPF MAP definition.
But this commit solves the problem by fixing this from 'queue_stats' map
struct hvm_queue_stats -> hbm_queue_stats.

Fixes: 36b5d471 ("selftests/bpf: samples/bpf: Split off legacy stuff from bpf_helpers.h")
Signed-off-by: default avatarDaniel T. Lee <danieltimlee@gmail.com>
Signed-off-by: default avatarAndrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20201124090310.24374-2-danieltimlee@gmail.com
parent fb355812
...@@ -52,3 +52,6 @@ xdp_tx_iptunnel ...@@ -52,3 +52,6 @@ xdp_tx_iptunnel
xdpsock xdpsock
xsk_fwd xsk_fwd
testfile.img testfile.img
hbm_out.log
iperf.*
*.out
...@@ -110,7 +110,7 @@ xdp_fwd-objs := xdp_fwd_user.o ...@@ -110,7 +110,7 @@ xdp_fwd-objs := xdp_fwd_user.o
task_fd_query-objs := bpf_load.o task_fd_query_user.o $(TRACE_HELPERS) task_fd_query-objs := bpf_load.o task_fd_query_user.o $(TRACE_HELPERS)
xdp_sample_pkts-objs := xdp_sample_pkts_user.o $(TRACE_HELPERS) xdp_sample_pkts-objs := xdp_sample_pkts_user.o $(TRACE_HELPERS)
ibumad-objs := bpf_load.o ibumad_user.o $(TRACE_HELPERS) ibumad-objs := bpf_load.o ibumad_user.o $(TRACE_HELPERS)
hbm-objs := bpf_load.o hbm.o $(CGROUP_HELPERS) hbm-objs := hbm.o $(CGROUP_HELPERS)
# Tell kbuild to always build the programs # Tell kbuild to always build the programs
always-y := $(tprogs-y) always-y := $(tprogs-y)
......
...@@ -91,6 +91,16 @@ qdisc="" ...@@ -91,6 +91,16 @@ qdisc=""
flags="" flags=""
do_stats=0 do_stats=0
BPFFS=/sys/fs/bpf
function config_bpffs () {
if mount | grep $BPFFS > /dev/null; then
echo "bpffs already mounted"
else
echo "bpffs not mounted. Mounting..."
mount -t bpf none $BPFFS
fi
}
function start_hbm () { function start_hbm () {
rm -f hbm.out rm -f hbm.out
echo "./hbm $dir -n $id -r $rate -t $dur $flags $dbg $prog" > hbm.out echo "./hbm $dir -n $id -r $rate -t $dur $flags $dbg $prog" > hbm.out
...@@ -192,6 +202,7 @@ processArgs () { ...@@ -192,6 +202,7 @@ processArgs () {
} }
processArgs processArgs
config_bpffs
if [ $debug_flag -eq 1 ] ; then if [ $debug_flag -eq 1 ] ; then
rm -f hbm_out.log rm -f hbm_out.log
...@@ -201,7 +212,7 @@ hbm_pid=$(start_hbm) ...@@ -201,7 +212,7 @@ hbm_pid=$(start_hbm)
usleep 100000 usleep 100000
host=`hostname` host=`hostname`
cg_base_dir=/sys/fs/cgroup cg_base_dir=/sys/fs/cgroup/unified
cg_dir="$cg_base_dir/cgroup-test-work-dir/hbm$id" cg_dir="$cg_base_dir/cgroup-test-work-dir/hbm$id"
echo $$ >> $cg_dir/cgroup.procs echo $$ >> $cg_dir/cgroup.procs
...@@ -411,23 +422,8 @@ fi ...@@ -411,23 +422,8 @@ fi
sleep 1 sleep 1
# Detach any BPF programs that may have lingered # Detach any pinned BPF programs that may have lingered
ttx=`bpftool cgroup tree | grep hbm` rm -rf $BPFFS/hbm*
v=2
for x in $ttx ; do
if [ "${x:0:36}" == "/sys/fs/cgroup/cgroup-test-work-dir/" ] ; then
cg=$x ; v=0
else
if [ $v -eq 0 ] ; then
id=$x ; v=1
else
if [ $v -eq 1 ] ; then
type=$x ; bpftool cgroup detach $cg $type id $id
v=0
fi
fi
fi
done
if [ $use_netperf -ne 0 ] ; then if [ $use_netperf -ne 0 ] ; then
if [ "$server" == "" ] ; then if [ "$server" == "" ] ; then
......
...@@ -46,7 +46,6 @@ ...@@ -46,7 +46,6 @@
#include <bpf/bpf.h> #include <bpf/bpf.h>
#include <getopt.h> #include <getopt.h>
#include "bpf_load.h"
#include "bpf_rlimit.h" #include "bpf_rlimit.h"
#include "cgroup_helpers.h" #include "cgroup_helpers.h"
#include "hbm.h" #include "hbm.h"
...@@ -70,9 +69,9 @@ static void do_error(char *msg, bool errno_flag); ...@@ -70,9 +69,9 @@ static void do_error(char *msg, bool errno_flag);
#define DEBUGFS "/sys/kernel/debug/tracing/" #define DEBUGFS "/sys/kernel/debug/tracing/"
struct bpf_object *obj; static struct bpf_program *bpf_prog;
int bpfprog_fd; static struct bpf_object *obj;
int cgroup_storage_fd; static int queue_stats_fd;
static void read_trace_pipe2(void) static void read_trace_pipe2(void)
{ {
...@@ -121,56 +120,50 @@ static void do_error(char *msg, bool errno_flag) ...@@ -121,56 +120,50 @@ static void do_error(char *msg, bool errno_flag)
static int prog_load(char *prog) static int prog_load(char *prog)
{ {
struct bpf_prog_load_attr prog_load_attr = { obj = bpf_object__open_file(prog, NULL);
.prog_type = BPF_PROG_TYPE_CGROUP_SKB, if (libbpf_get_error(obj)) {
.file = prog, printf("ERROR: opening BPF object file failed\n");
.expected_attach_type = BPF_CGROUP_INET_EGRESS,
};
int map_fd;
struct bpf_map *map;
int ret = 0;
if (access(prog, O_RDONLY) < 0) {
printf("Error accessing file %s: %s\n", prog, strerror(errno));
return 1; return 1;
} }
if (bpf_prog_load_xattr(&prog_load_attr, &obj, &bpfprog_fd))
ret = 1; /* load BPF program */
if (!ret) { if (bpf_object__load(obj)) {
map = bpf_object__find_map_by_name(obj, "queue_stats"); printf("ERROR: loading BPF object file failed\n");
map_fd = bpf_map__fd(map); goto err;
if (map_fd < 0) {
printf("Map not found: %s\n", strerror(map_fd));
ret = 1;
} }
bpf_prog = bpf_object__find_program_by_title(obj, "cgroup_skb/egress");
if (!bpf_prog) {
printf("ERROR: finding a prog in obj file failed\n");
goto err;
} }
if (ret) { queue_stats_fd = bpf_object__find_map_fd_by_name(obj, "queue_stats");
printf("ERROR: bpf_prog_load_xattr failed for: %s\n", prog); if (queue_stats_fd < 0) {
printf(" Output from verifier:\n%s\n------\n", bpf_log_buf); printf("ERROR: finding a map in obj file failed\n");
ret = -1; goto err;
} else {
ret = map_fd;
} }
return ret; return 0;
err:
bpf_object__close(obj);
return 1;
} }
static int run_bpf_prog(char *prog, int cg_id) static int run_bpf_prog(char *prog, int cg_id)
{ {
int map_fd; struct hbm_queue_stats qstats = {0};
int rc = 0; char cg_dir[100], cg_pin_path[100];
struct bpf_link *link = NULL;
int key = 0; int key = 0;
int cg1 = 0; int cg1 = 0;
int type = BPF_CGROUP_INET_EGRESS; int rc = 0;
char cg_dir[100];
struct hbm_queue_stats qstats = {0};
sprintf(cg_dir, "/hbm%d", cg_id); sprintf(cg_dir, "/hbm%d", cg_id);
map_fd = prog_load(prog); rc = prog_load(prog);
if (map_fd == -1) if (rc != 0)
return 1; return rc;
if (setup_cgroup_environment()) { if (setup_cgroup_environment()) {
printf("ERROR: setting cgroup environment\n"); printf("ERROR: setting cgroup environment\n");
...@@ -190,16 +183,24 @@ static int run_bpf_prog(char *prog, int cg_id) ...@@ -190,16 +183,24 @@ static int run_bpf_prog(char *prog, int cg_id)
qstats.stats = stats_flag ? 1 : 0; qstats.stats = stats_flag ? 1 : 0;
qstats.loopback = loopback_flag ? 1 : 0; qstats.loopback = loopback_flag ? 1 : 0;
qstats.no_cn = no_cn_flag ? 1 : 0; qstats.no_cn = no_cn_flag ? 1 : 0;
if (bpf_map_update_elem(map_fd, &key, &qstats, BPF_ANY)) { if (bpf_map_update_elem(queue_stats_fd, &key, &qstats, BPF_ANY)) {
printf("ERROR: Could not update map element\n"); printf("ERROR: Could not update map element\n");
goto err; goto err;
} }
if (!outFlag) if (!outFlag)
type = BPF_CGROUP_INET_INGRESS; bpf_program__set_expected_attach_type(bpf_prog, BPF_CGROUP_INET_INGRESS);
if (bpf_prog_attach(bpfprog_fd, cg1, type, 0)) {
printf("ERROR: bpf_prog_attach fails!\n"); link = bpf_program__attach_cgroup(bpf_prog, cg1);
log_err("Attaching prog"); if (libbpf_get_error(link)) {
fprintf(stderr, "ERROR: bpf_program__attach_cgroup failed\n");
goto err;
}
sprintf(cg_pin_path, "/sys/fs/bpf/hbm%d", cg_id);
rc = bpf_link__pin(link, cg_pin_path);
if (rc < 0) {
printf("ERROR: bpf_link__pin failed: %d\n", rc);
goto err; goto err;
} }
...@@ -213,7 +214,7 @@ static int run_bpf_prog(char *prog, int cg_id) ...@@ -213,7 +214,7 @@ static int run_bpf_prog(char *prog, int cg_id)
#define DELTA_RATE_CHECK 10000 /* in us */ #define DELTA_RATE_CHECK 10000 /* in us */
#define RATE_THRESHOLD 9500000000 /* 9.5 Gbps */ #define RATE_THRESHOLD 9500000000 /* 9.5 Gbps */
bpf_map_lookup_elem(map_fd, &key, &qstats); bpf_map_lookup_elem(queue_stats_fd, &key, &qstats);
if (gettimeofday(&t0, NULL) < 0) if (gettimeofday(&t0, NULL) < 0)
do_error("gettimeofday failed", true); do_error("gettimeofday failed", true);
t_last = t0; t_last = t0;
...@@ -242,7 +243,7 @@ static int run_bpf_prog(char *prog, int cg_id) ...@@ -242,7 +243,7 @@ static int run_bpf_prog(char *prog, int cg_id)
fclose(fin); fclose(fin);
printf(" new_eth_tx_bytes:%llu\n", printf(" new_eth_tx_bytes:%llu\n",
new_eth_tx_bytes); new_eth_tx_bytes);
bpf_map_lookup_elem(map_fd, &key, &qstats); bpf_map_lookup_elem(queue_stats_fd, &key, &qstats);
new_cg_tx_bytes = qstats.bytes_total; new_cg_tx_bytes = qstats.bytes_total;
delta_bytes = new_eth_tx_bytes - last_eth_tx_bytes; delta_bytes = new_eth_tx_bytes - last_eth_tx_bytes;
last_eth_tx_bytes = new_eth_tx_bytes; last_eth_tx_bytes = new_eth_tx_bytes;
...@@ -289,14 +290,14 @@ static int run_bpf_prog(char *prog, int cg_id) ...@@ -289,14 +290,14 @@ static int run_bpf_prog(char *prog, int cg_id)
rate = minRate; rate = minRate;
qstats.rate = rate; qstats.rate = rate;
} }
if (bpf_map_update_elem(map_fd, &key, &qstats, BPF_ANY)) if (bpf_map_update_elem(queue_stats_fd, &key, &qstats, BPF_ANY))
do_error("update map element fails", false); do_error("update map element fails", false);
} }
} else { } else {
sleep(dur); sleep(dur);
} }
// Get stats! // Get stats!
if (stats_flag && bpf_map_lookup_elem(map_fd, &key, &qstats)) { if (stats_flag && bpf_map_lookup_elem(queue_stats_fd, &key, &qstats)) {
char fname[100]; char fname[100];
FILE *fout; FILE *fout;
...@@ -394,14 +395,20 @@ static int run_bpf_prog(char *prog, int cg_id) ...@@ -394,14 +395,20 @@ static int run_bpf_prog(char *prog, int cg_id)
if (debugFlag) if (debugFlag)
read_trace_pipe2(); read_trace_pipe2();
return rc; goto cleanup;
err: err:
rc = 1; rc = 1;
if (cg1) cleanup:
bpf_link__destroy(link);
bpf_object__close(obj);
if (cg1 != -1)
close(cg1); close(cg1);
cleanup_cgroup_environment();
if (rc != 0)
cleanup_cgroup_environment();
return rc; return rc;
} }
......
...@@ -69,7 +69,7 @@ struct { ...@@ -69,7 +69,7 @@ struct {
__uint(type, BPF_MAP_TYPE_ARRAY); __uint(type, BPF_MAP_TYPE_ARRAY);
__uint(max_entries, 1); __uint(max_entries, 1);
__type(key, u32); __type(key, u32);
__type(value, struct hvm_queue_stats); __type(value, struct hbm_queue_stats);
} queue_stats SEC(".maps"); } queue_stats SEC(".maps");
struct hbm_pkt_info { struct hbm_pkt_info {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment