Commit be5bca44 authored by Jakub Kicinski's avatar Jakub Kicinski Committed by Daniel Borkmann

samples: bpf: convert some XDP samples from bpf_load to libbpf

Now that we can use full powers of libbpf in BPF samples, we
should perhaps make the simplest XDP programs not depend on
bpf_load helpers.  This way newcomers will be exposed to the
recommended library from the start.

Use of bpf_prog_load_xattr() will also make it trivial to later
on request offload of the programs by simply adding ifindex to
the xattr.
Signed-off-by: default avatarJakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: default avatarQuentin Monnet <quentin.monnet@netronome.com>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
parent 17387dd5
...@@ -79,9 +79,9 @@ test_cgrp2_attach-objs := test_cgrp2_attach.o $(LIBBPF) ...@@ -79,9 +79,9 @@ test_cgrp2_attach-objs := test_cgrp2_attach.o $(LIBBPF)
test_cgrp2_attach2-objs := test_cgrp2_attach2.o $(LIBBPF) $(CGROUP_HELPERS) test_cgrp2_attach2-objs := test_cgrp2_attach2.o $(LIBBPF) $(CGROUP_HELPERS)
test_cgrp2_sock-objs := test_cgrp2_sock.o $(LIBBPF) test_cgrp2_sock-objs := test_cgrp2_sock.o $(LIBBPF)
test_cgrp2_sock2-objs := bpf_load.o $(LIBBPF) test_cgrp2_sock2.o test_cgrp2_sock2-objs := bpf_load.o $(LIBBPF) test_cgrp2_sock2.o
xdp1-objs := bpf_load.o $(LIBBPF) xdp1_user.o xdp1-objs := xdp1_user.o $(LIBBPF)
# reuse xdp1 source intentionally # reuse xdp1 source intentionally
xdp2-objs := bpf_load.o $(LIBBPF) xdp1_user.o xdp2-objs := xdp1_user.o $(LIBBPF)
xdp_router_ipv4-objs := bpf_load.o $(LIBBPF) xdp_router_ipv4_user.o xdp_router_ipv4-objs := bpf_load.o $(LIBBPF) xdp_router_ipv4_user.o
test_current_task_under_cgroup-objs := bpf_load.o $(LIBBPF) $(CGROUP_HELPERS) \ test_current_task_under_cgroup-objs := bpf_load.o $(LIBBPF) $(CGROUP_HELPERS) \
test_current_task_under_cgroup_user.o test_current_task_under_cgroup_user.o
...@@ -96,10 +96,10 @@ xdp_redirect-objs := bpf_load.o $(LIBBPF) xdp_redirect_user.o ...@@ -96,10 +96,10 @@ xdp_redirect-objs := bpf_load.o $(LIBBPF) xdp_redirect_user.o
xdp_redirect_map-objs := bpf_load.o $(LIBBPF) xdp_redirect_map_user.o xdp_redirect_map-objs := bpf_load.o $(LIBBPF) xdp_redirect_map_user.o
xdp_redirect_cpu-objs := bpf_load.o $(LIBBPF) xdp_redirect_cpu_user.o xdp_redirect_cpu-objs := bpf_load.o $(LIBBPF) xdp_redirect_cpu_user.o
xdp_monitor-objs := bpf_load.o $(LIBBPF) xdp_monitor_user.o xdp_monitor-objs := bpf_load.o $(LIBBPF) xdp_monitor_user.o
xdp_rxq_info-objs := bpf_load.o $(LIBBPF) xdp_rxq_info_user.o xdp_rxq_info-objs := xdp_rxq_info_user.o $(LIBBPF)
syscall_tp-objs := bpf_load.o $(LIBBPF) syscall_tp_user.o syscall_tp-objs := bpf_load.o $(LIBBPF) syscall_tp_user.o
cpustat-objs := bpf_load.o $(LIBBPF) cpustat_user.o cpustat-objs := bpf_load.o $(LIBBPF) cpustat_user.o
xdp_adjust_tail-objs := bpf_load.o $(LIBBPF) xdp_adjust_tail_user.o xdp_adjust_tail-objs := xdp_adjust_tail_user.o $(LIBBPF)
xdpsock-objs := bpf_load.o $(LIBBPF) xdpsock_user.o xdpsock-objs := bpf_load.o $(LIBBPF) xdpsock_user.o
xdp_fwd-objs := bpf_load.o $(LIBBPF) xdp_fwd_user.o xdp_fwd-objs := bpf_load.o $(LIBBPF) xdp_fwd_user.o
......
...@@ -16,9 +16,9 @@ ...@@ -16,9 +16,9 @@
#include <libgen.h> #include <libgen.h>
#include <sys/resource.h> #include <sys/resource.h>
#include "bpf_load.h"
#include "bpf_util.h" #include "bpf_util.h"
#include "libbpf.h" #include "bpf/bpf.h"
#include "bpf/libbpf.h"
static int ifindex; static int ifindex;
static __u32 xdp_flags; static __u32 xdp_flags;
...@@ -31,7 +31,7 @@ static void int_exit(int sig) ...@@ -31,7 +31,7 @@ static void int_exit(int sig)
/* simple per-protocol drop counter /* simple per-protocol drop counter
*/ */
static void poll_stats(int interval) static void poll_stats(int map_fd, int interval)
{ {
unsigned int nr_cpus = bpf_num_possible_cpus(); unsigned int nr_cpus = bpf_num_possible_cpus();
const unsigned int nr_keys = 256; const unsigned int nr_keys = 256;
...@@ -47,7 +47,7 @@ static void poll_stats(int interval) ...@@ -47,7 +47,7 @@ static void poll_stats(int interval)
for (key = 0; key < nr_keys; key++) { for (key = 0; key < nr_keys; key++) {
__u64 sum = 0; __u64 sum = 0;
assert(bpf_map_lookup_elem(map_fd[0], &key, values) == 0); assert(bpf_map_lookup_elem(map_fd, &key, values) == 0);
for (i = 0; i < nr_cpus; i++) for (i = 0; i < nr_cpus; i++)
sum += (values[i] - prev[key][i]); sum += (values[i] - prev[key][i]);
if (sum) if (sum)
...@@ -71,9 +71,14 @@ static void usage(const char *prog) ...@@ -71,9 +71,14 @@ static void usage(const char *prog)
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY}; struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
struct bpf_prog_load_attr prog_load_attr = {
.prog_type = BPF_PROG_TYPE_XDP,
};
const char *optstr = "SN"; const char *optstr = "SN";
int prog_fd, map_fd, opt;
struct bpf_object *obj;
struct bpf_map *map;
char filename[256]; char filename[256];
int opt;
while ((opt = getopt(argc, argv, optstr)) != -1) { while ((opt = getopt(argc, argv, optstr)) != -1) {
switch (opt) { switch (opt) {
...@@ -102,13 +107,19 @@ int main(int argc, char **argv) ...@@ -102,13 +107,19 @@ int main(int argc, char **argv)
ifindex = strtoul(argv[optind], NULL, 0); ifindex = strtoul(argv[optind], NULL, 0);
snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
prog_load_attr.file = filename;
if (load_bpf_file(filename)) { if (bpf_prog_load_xattr(&prog_load_attr, &obj, &prog_fd))
printf("%s", bpf_log_buf); return 1;
map = bpf_map__next(NULL, obj);
if (!map) {
printf("finding a map in obj file failed\n");
return 1; return 1;
} }
map_fd = bpf_map__fd(map);
if (!prog_fd[0]) { if (!prog_fd) {
printf("load_bpf_file: %s\n", strerror(errno)); printf("load_bpf_file: %s\n", strerror(errno));
return 1; return 1;
} }
...@@ -116,12 +127,12 @@ int main(int argc, char **argv) ...@@ -116,12 +127,12 @@ int main(int argc, char **argv)
signal(SIGINT, int_exit); signal(SIGINT, int_exit);
signal(SIGTERM, int_exit); signal(SIGTERM, int_exit);
if (bpf_set_link_xdp_fd(ifindex, prog_fd[0], xdp_flags) < 0) { if (bpf_set_link_xdp_fd(ifindex, prog_fd, xdp_flags) < 0) {
printf("link set xdp fd failed\n"); printf("link set xdp fd failed\n");
return 1; return 1;
} }
poll_stats(2); poll_stats(map_fd, 2);
return 0; return 0;
} }
...@@ -18,9 +18,8 @@ ...@@ -18,9 +18,8 @@
#include <netinet/ether.h> #include <netinet/ether.h>
#include <unistd.h> #include <unistd.h>
#include <time.h> #include <time.h>
#include "bpf_load.h" #include "bpf/bpf.h"
#include "libbpf.h" #include "bpf/libbpf.h"
#include "bpf_util.h"
#define STATS_INTERVAL_S 2U #define STATS_INTERVAL_S 2U
...@@ -36,7 +35,7 @@ static void int_exit(int sig) ...@@ -36,7 +35,7 @@ static void int_exit(int sig)
/* simple "icmp packet too big sent" counter /* simple "icmp packet too big sent" counter
*/ */
static void poll_stats(unsigned int kill_after_s) static void poll_stats(unsigned int map_fd, unsigned int kill_after_s)
{ {
time_t started_at = time(NULL); time_t started_at = time(NULL);
__u64 value = 0; __u64 value = 0;
...@@ -46,7 +45,7 @@ static void poll_stats(unsigned int kill_after_s) ...@@ -46,7 +45,7 @@ static void poll_stats(unsigned int kill_after_s)
while (!kill_after_s || time(NULL) - started_at <= kill_after_s) { while (!kill_after_s || time(NULL) - started_at <= kill_after_s) {
sleep(STATS_INTERVAL_S); sleep(STATS_INTERVAL_S);
assert(bpf_map_lookup_elem(map_fd[0], &key, &value) == 0); assert(bpf_map_lookup_elem(map_fd, &key, &value) == 0);
printf("icmp \"packet too big\" sent: %10llu pkts\n", value); printf("icmp \"packet too big\" sent: %10llu pkts\n", value);
} }
...@@ -66,14 +65,17 @@ static void usage(const char *cmd) ...@@ -66,14 +65,17 @@ static void usage(const char *cmd)
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
struct bpf_prog_load_attr prog_load_attr = {
.prog_type = BPF_PROG_TYPE_XDP,
};
unsigned char opt_flags[256] = {}; unsigned char opt_flags[256] = {};
unsigned int kill_after_s = 0; unsigned int kill_after_s = 0;
const char *optstr = "i:T:SNh"; const char *optstr = "i:T:SNh";
struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY}; int i, prog_fd, map_fd, opt;
struct bpf_object *obj;
struct bpf_map *map;
char filename[256]; char filename[256];
int opt;
int i;
for (i = 0; i < strlen(optstr); i++) for (i = 0; i < strlen(optstr); i++)
if (optstr[i] != 'h' && 'a' <= optstr[i] && optstr[i] <= 'z') if (optstr[i] != 'h' && 'a' <= optstr[i] && optstr[i] <= 'z')
...@@ -115,13 +117,19 @@ int main(int argc, char **argv) ...@@ -115,13 +117,19 @@ int main(int argc, char **argv)
} }
snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
prog_load_attr.file = filename;
if (bpf_prog_load_xattr(&prog_load_attr, &obj, &prog_fd))
return 1;
if (load_bpf_file(filename)) { map = bpf_map__next(NULL, obj);
printf("%s", bpf_log_buf); if (!map) {
printf("finding a map in obj file failed\n");
return 1; return 1;
} }
map_fd = bpf_map__fd(map);
if (!prog_fd[0]) { if (!prog_fd) {
printf("load_bpf_file: %s\n", strerror(errno)); printf("load_bpf_file: %s\n", strerror(errno));
return 1; return 1;
} }
...@@ -129,12 +137,12 @@ int main(int argc, char **argv) ...@@ -129,12 +137,12 @@ int main(int argc, char **argv)
signal(SIGINT, int_exit); signal(SIGINT, int_exit);
signal(SIGTERM, int_exit); signal(SIGTERM, int_exit);
if (bpf_set_link_xdp_fd(ifindex, prog_fd[0], xdp_flags) < 0) { if (bpf_set_link_xdp_fd(ifindex, prog_fd, xdp_flags) < 0) {
printf("link set xdp fd failed\n"); printf("link set xdp fd failed\n");
return 1; return 1;
} }
poll_stats(kill_after_s); poll_stats(map_fd, kill_after_s);
bpf_set_link_xdp_fd(ifindex, -1, xdp_flags); bpf_set_link_xdp_fd(ifindex, -1, xdp_flags);
......
...@@ -22,8 +22,8 @@ static const char *__doc__ = " XDP RX-queue info extract example\n\n" ...@@ -22,8 +22,8 @@ static const char *__doc__ = " XDP RX-queue info extract example\n\n"
#include <arpa/inet.h> #include <arpa/inet.h>
#include <linux/if_link.h> #include <linux/if_link.h>
#include "libbpf.h" #include "bpf/bpf.h"
#include "bpf_load.h" #include "bpf/libbpf.h"
#include "bpf_util.h" #include "bpf_util.h"
static int ifindex = -1; static int ifindex = -1;
...@@ -32,6 +32,9 @@ static char *ifname; ...@@ -32,6 +32,9 @@ static char *ifname;
static __u32 xdp_flags; static __u32 xdp_flags;
static struct bpf_map *stats_global_map;
static struct bpf_map *rx_queue_index_map;
/* Exit return codes */ /* Exit return codes */
#define EXIT_OK 0 #define EXIT_OK 0
#define EXIT_FAIL 1 #define EXIT_FAIL 1
...@@ -174,7 +177,7 @@ static struct datarec *alloc_record_per_cpu(void) ...@@ -174,7 +177,7 @@ static struct datarec *alloc_record_per_cpu(void)
static struct record *alloc_record_per_rxq(void) static struct record *alloc_record_per_rxq(void)
{ {
unsigned int nr_rxqs = map_data[2].def.max_entries; unsigned int nr_rxqs = bpf_map__def(rx_queue_index_map)->max_entries;
struct record *array; struct record *array;
size_t size; size_t size;
...@@ -190,7 +193,7 @@ static struct record *alloc_record_per_rxq(void) ...@@ -190,7 +193,7 @@ static struct record *alloc_record_per_rxq(void)
static struct stats_record *alloc_stats_record(void) static struct stats_record *alloc_stats_record(void)
{ {
unsigned int nr_rxqs = map_data[2].def.max_entries; unsigned int nr_rxqs = bpf_map__def(rx_queue_index_map)->max_entries;
struct stats_record *rec; struct stats_record *rec;
int i; int i;
...@@ -210,7 +213,7 @@ static struct stats_record *alloc_stats_record(void) ...@@ -210,7 +213,7 @@ static struct stats_record *alloc_stats_record(void)
static void free_stats_record(struct stats_record *r) static void free_stats_record(struct stats_record *r)
{ {
unsigned int nr_rxqs = map_data[2].def.max_entries; unsigned int nr_rxqs = bpf_map__def(rx_queue_index_map)->max_entries;
int i; int i;
for (i = 0; i < nr_rxqs; i++) for (i = 0; i < nr_rxqs; i++)
...@@ -254,11 +257,11 @@ static void stats_collect(struct stats_record *rec) ...@@ -254,11 +257,11 @@ static void stats_collect(struct stats_record *rec)
{ {
int fd, i, max_rxqs; int fd, i, max_rxqs;
fd = map_data[1].fd; /* map: stats_global_map */ fd = bpf_map__fd(stats_global_map);
map_collect_percpu(fd, 0, &rec->stats); map_collect_percpu(fd, 0, &rec->stats);
fd = map_data[2].fd; /* map: rx_queue_index_map */ fd = bpf_map__fd(rx_queue_index_map);
max_rxqs = map_data[2].def.max_entries; max_rxqs = bpf_map__def(rx_queue_index_map)->max_entries;
for (i = 0; i < max_rxqs; i++) for (i = 0; i < max_rxqs; i++)
map_collect_percpu(fd, i, &rec->rxq[i]); map_collect_percpu(fd, i, &rec->rxq[i]);
} }
...@@ -304,8 +307,8 @@ static void stats_print(struct stats_record *stats_rec, ...@@ -304,8 +307,8 @@ static void stats_print(struct stats_record *stats_rec,
struct stats_record *stats_prev, struct stats_record *stats_prev,
int action) int action)
{ {
unsigned int nr_rxqs = bpf_map__def(rx_queue_index_map)->max_entries;
unsigned int nr_cpus = bpf_num_possible_cpus(); unsigned int nr_cpus = bpf_num_possible_cpus();
unsigned int nr_rxqs = map_data[2].def.max_entries;
double pps = 0, err = 0; double pps = 0, err = 0;
struct record *rec, *prev; struct record *rec, *prev;
double t; double t;
...@@ -419,31 +422,44 @@ static void stats_poll(int interval, int action) ...@@ -419,31 +422,44 @@ static void stats_poll(int interval, int action)
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
struct rlimit r = {10 * 1024 * 1024, RLIM_INFINITY}; struct rlimit r = {10 * 1024 * 1024, RLIM_INFINITY};
struct bpf_prog_load_attr prog_load_attr = {
.prog_type = BPF_PROG_TYPE_XDP,
};
int prog_fd, map_fd, opt, err;
bool use_separators = true; bool use_separators = true;
struct config cfg = { 0 }; struct config cfg = { 0 };
struct bpf_object *obj;
struct bpf_map *map;
char filename[256]; char filename[256];
int longindex = 0; int longindex = 0;
int interval = 2; int interval = 2;
__u32 key = 0; __u32 key = 0;
int opt, err;
char action_str_buf[XDP_ACTION_MAX_STRLEN + 1 /* for \0 */] = { 0 }; char action_str_buf[XDP_ACTION_MAX_STRLEN + 1 /* for \0 */] = { 0 };
int action = XDP_PASS; /* Default action */ int action = XDP_PASS; /* Default action */
char *action_str = NULL; char *action_str = NULL;
snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
prog_load_attr.file = filename;
if (setrlimit(RLIMIT_MEMLOCK, &r)) { if (setrlimit(RLIMIT_MEMLOCK, &r)) {
perror("setrlimit(RLIMIT_MEMLOCK)"); perror("setrlimit(RLIMIT_MEMLOCK)");
return 1; return 1;
} }
if (load_bpf_file(filename)) { if (bpf_prog_load_xattr(&prog_load_attr, &obj, &prog_fd))
fprintf(stderr, "ERR in load_bpf_file(): %s", bpf_log_buf); return EXIT_FAIL;
map = bpf_map__next(NULL, obj);
stats_global_map = bpf_map__next(map, obj);
rx_queue_index_map = bpf_map__next(stats_global_map, obj);
if (!map || !stats_global_map || !rx_queue_index_map) {
printf("finding a map in obj file failed\n");
return EXIT_FAIL; return EXIT_FAIL;
} }
map_fd = bpf_map__fd(map);
if (!prog_fd[0]) { if (!prog_fd) {
fprintf(stderr, "ERR: load_bpf_file: %s\n", strerror(errno)); fprintf(stderr, "ERR: load_bpf_file: %s\n", strerror(errno));
return EXIT_FAIL; return EXIT_FAIL;
} }
...@@ -512,7 +528,7 @@ int main(int argc, char **argv) ...@@ -512,7 +528,7 @@ int main(int argc, char **argv)
setlocale(LC_NUMERIC, "en_US"); setlocale(LC_NUMERIC, "en_US");
/* User-side setup ifindex in config_map */ /* User-side setup ifindex in config_map */
err = bpf_map_update_elem(map_fd[0], &key, &cfg, 0); err = bpf_map_update_elem(map_fd, &key, &cfg, 0);
if (err) { if (err) {
fprintf(stderr, "Store config failed (err:%d)\n", err); fprintf(stderr, "Store config failed (err:%d)\n", err);
exit(EXIT_FAIL_BPF); exit(EXIT_FAIL_BPF);
...@@ -521,7 +537,7 @@ int main(int argc, char **argv) ...@@ -521,7 +537,7 @@ int main(int argc, char **argv)
/* Remove XDP program when program is interrupted */ /* Remove XDP program when program is interrupted */
signal(SIGINT, int_exit); signal(SIGINT, int_exit);
if (bpf_set_link_xdp_fd(ifindex, prog_fd[0], xdp_flags) < 0) { if (bpf_set_link_xdp_fd(ifindex, prog_fd, xdp_flags) < 0) {
fprintf(stderr, "link set xdp fd failed\n"); fprintf(stderr, "link set xdp fd failed\n");
return EXIT_FAIL_XDP; return EXIT_FAIL_XDP;
} }
......
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