forked from Minki/linux
samples/bpf: Convert XDP samples to libbpf usage
Some of XDP samples that are attaching the bpf program to the interface via libbpf's bpf_set_link_xdp_fd are still using the bpf_load.c for loading and manipulating the ebpf program and maps. Convert them to do this through libbpf usage and remove bpf_load from the picture. While at it remove what looks like debug leftover in xdp_redirect_map_user.c In xdp_redirect_cpu, change the way that the program to be loaded onto interface is chosen - user now needs to pass the program's section name instead of the relative number. In case of typo print out the section names to choose from. Signed-off-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com> Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com> Acked-by: Jesper Dangaard Brouer <brouer@redhat.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
This commit is contained in:
parent
7313798b14
commit
bbaf6029c4
@ -87,18 +87,18 @@ test_cgrp2_sock2-objs := bpf_load.o test_cgrp2_sock2.o
|
||||
xdp1-objs := xdp1_user.o
|
||||
# reuse xdp1 source intentionally
|
||||
xdp2-objs := xdp1_user.o
|
||||
xdp_router_ipv4-objs := bpf_load.o xdp_router_ipv4_user.o
|
||||
xdp_router_ipv4-objs := xdp_router_ipv4_user.o
|
||||
test_current_task_under_cgroup-objs := bpf_load.o $(CGROUP_HELPERS) \
|
||||
test_current_task_under_cgroup_user.o
|
||||
trace_event-objs := bpf_load.o trace_event_user.o $(TRACE_HELPERS)
|
||||
sampleip-objs := bpf_load.o sampleip_user.o $(TRACE_HELPERS)
|
||||
tc_l2_redirect-objs := bpf_load.o tc_l2_redirect_user.o
|
||||
lwt_len_hist-objs := bpf_load.o lwt_len_hist_user.o
|
||||
xdp_tx_iptunnel-objs := bpf_load.o xdp_tx_iptunnel_user.o
|
||||
xdp_tx_iptunnel-objs := xdp_tx_iptunnel_user.o
|
||||
test_map_in_map-objs := bpf_load.o test_map_in_map_user.o
|
||||
per_socket_stats_example-objs := cookie_uid_helper_example.o
|
||||
xdp_redirect-objs := bpf_load.o xdp_redirect_user.o
|
||||
xdp_redirect_map-objs := bpf_load.o xdp_redirect_map_user.o
|
||||
xdp_redirect-objs := xdp_redirect_user.o
|
||||
xdp_redirect_map-objs := xdp_redirect_map_user.o
|
||||
xdp_redirect_cpu-objs := bpf_load.o xdp_redirect_cpu_user.o
|
||||
xdp_monitor-objs := bpf_load.o xdp_monitor_user.o
|
||||
xdp_rxq_info-objs := xdp_rxq_info_user.o
|
||||
|
@ -24,12 +24,8 @@ static const char *__doc__ =
|
||||
/* How many xdp_progs are defined in _kern.c */
|
||||
#define MAX_PROG 6
|
||||
|
||||
/* Wanted to get rid of bpf_load.h and fake-"libbpf.h" (and instead
|
||||
* use bpf/libbpf.h), but cannot as (currently) needed for XDP
|
||||
* attaching to a device via bpf_set_link_xdp_fd()
|
||||
*/
|
||||
#include <bpf/bpf.h>
|
||||
#include "bpf_load.h"
|
||||
#include "bpf/libbpf.h"
|
||||
|
||||
#include "bpf_util.h"
|
||||
|
||||
@ -38,6 +34,15 @@ static char ifname_buf[IF_NAMESIZE];
|
||||
static char *ifname;
|
||||
|
||||
static __u32 xdp_flags;
|
||||
static int cpu_map_fd;
|
||||
static int rx_cnt_map_fd;
|
||||
static int redirect_err_cnt_map_fd;
|
||||
static int cpumap_enqueue_cnt_map_fd;
|
||||
static int cpumap_kthread_cnt_map_fd;
|
||||
static int cpus_available_map_fd;
|
||||
static int cpus_count_map_fd;
|
||||
static int cpus_iterator_map_fd;
|
||||
static int exception_cnt_map_fd;
|
||||
|
||||
/* Exit return codes */
|
||||
#define EXIT_OK 0
|
||||
@ -52,7 +57,7 @@ static const struct option long_options[] = {
|
||||
{"dev", required_argument, NULL, 'd' },
|
||||
{"skb-mode", no_argument, NULL, 'S' },
|
||||
{"sec", required_argument, NULL, 's' },
|
||||
{"prognum", required_argument, NULL, 'p' },
|
||||
{"progname", required_argument, NULL, 'p' },
|
||||
{"qsize", required_argument, NULL, 'q' },
|
||||
{"cpu", required_argument, NULL, 'c' },
|
||||
{"stress-mode", no_argument, NULL, 'x' },
|
||||
@ -70,7 +75,17 @@ static void int_exit(int sig)
|
||||
exit(EXIT_OK);
|
||||
}
|
||||
|
||||
static void usage(char *argv[])
|
||||
static void print_avail_progs(struct bpf_object *obj)
|
||||
{
|
||||
struct bpf_program *pos;
|
||||
|
||||
bpf_object__for_each_program(pos, obj) {
|
||||
if (bpf_program__is_xdp(pos))
|
||||
printf(" %s\n", bpf_program__title(pos, false));
|
||||
}
|
||||
}
|
||||
|
||||
static void usage(char *argv[], struct bpf_object *obj)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -88,6 +103,8 @@ static void usage(char *argv[])
|
||||
long_options[i].val);
|
||||
printf("\n");
|
||||
}
|
||||
printf("\n Programs to be used for --progname:\n");
|
||||
print_avail_progs(obj);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
@ -262,7 +279,7 @@ static __u64 calc_errs_pps(struct datarec *r,
|
||||
|
||||
static void stats_print(struct stats_record *stats_rec,
|
||||
struct stats_record *stats_prev,
|
||||
int prog_num)
|
||||
char *prog_name)
|
||||
{
|
||||
unsigned int nr_cpus = bpf_num_possible_cpus();
|
||||
double pps = 0, drop = 0, err = 0;
|
||||
@ -272,7 +289,7 @@ static void stats_print(struct stats_record *stats_rec,
|
||||
int i;
|
||||
|
||||
/* Header */
|
||||
printf("Running XDP/eBPF prog_num:%d\n", prog_num);
|
||||
printf("Running XDP/eBPF prog_name:%s\n", prog_name);
|
||||
printf("%-15s %-7s %-14s %-11s %-9s\n",
|
||||
"XDP-cpumap", "CPU:to", "pps", "drop-pps", "extra-info");
|
||||
|
||||
@ -423,20 +440,20 @@ static void stats_collect(struct stats_record *rec)
|
||||
{
|
||||
int fd, i;
|
||||
|
||||
fd = map_fd[1]; /* map: rx_cnt */
|
||||
fd = rx_cnt_map_fd;
|
||||
map_collect_percpu(fd, 0, &rec->rx_cnt);
|
||||
|
||||
fd = map_fd[2]; /* map: redirect_err_cnt */
|
||||
fd = redirect_err_cnt_map_fd;
|
||||
map_collect_percpu(fd, 1, &rec->redir_err);
|
||||
|
||||
fd = map_fd[3]; /* map: cpumap_enqueue_cnt */
|
||||
fd = cpumap_enqueue_cnt_map_fd;
|
||||
for (i = 0; i < MAX_CPUS; i++)
|
||||
map_collect_percpu(fd, i, &rec->enq[i]);
|
||||
|
||||
fd = map_fd[4]; /* map: cpumap_kthread_cnt */
|
||||
fd = cpumap_kthread_cnt_map_fd;
|
||||
map_collect_percpu(fd, 0, &rec->kthread);
|
||||
|
||||
fd = map_fd[8]; /* map: exception_cnt */
|
||||
fd = exception_cnt_map_fd;
|
||||
map_collect_percpu(fd, 0, &rec->exception);
|
||||
}
|
||||
|
||||
@ -461,7 +478,7 @@ static int create_cpu_entry(__u32 cpu, __u32 queue_size,
|
||||
/* Add a CPU entry to cpumap, as this allocate a cpu entry in
|
||||
* the kernel for the cpu.
|
||||
*/
|
||||
ret = bpf_map_update_elem(map_fd[0], &cpu, &queue_size, 0);
|
||||
ret = bpf_map_update_elem(cpu_map_fd, &cpu, &queue_size, 0);
|
||||
if (ret) {
|
||||
fprintf(stderr, "Create CPU entry failed (err:%d)\n", ret);
|
||||
exit(EXIT_FAIL_BPF);
|
||||
@ -470,23 +487,22 @@ static int create_cpu_entry(__u32 cpu, __u32 queue_size,
|
||||
/* Inform bpf_prog's that a new CPU is available to select
|
||||
* from via some control maps.
|
||||
*/
|
||||
/* map_fd[5] = cpus_available */
|
||||
ret = bpf_map_update_elem(map_fd[5], &avail_idx, &cpu, 0);
|
||||
ret = bpf_map_update_elem(cpus_available_map_fd, &avail_idx, &cpu, 0);
|
||||
if (ret) {
|
||||
fprintf(stderr, "Add to avail CPUs failed\n");
|
||||
exit(EXIT_FAIL_BPF);
|
||||
}
|
||||
|
||||
/* When not replacing/updating existing entry, bump the count */
|
||||
/* map_fd[6] = cpus_count */
|
||||
ret = bpf_map_lookup_elem(map_fd[6], &key, &curr_cpus_count);
|
||||
ret = bpf_map_lookup_elem(cpus_count_map_fd, &key, &curr_cpus_count);
|
||||
if (ret) {
|
||||
fprintf(stderr, "Failed reading curr cpus_count\n");
|
||||
exit(EXIT_FAIL_BPF);
|
||||
}
|
||||
if (new) {
|
||||
curr_cpus_count++;
|
||||
ret = bpf_map_update_elem(map_fd[6], &key, &curr_cpus_count, 0);
|
||||
ret = bpf_map_update_elem(cpus_count_map_fd, &key,
|
||||
&curr_cpus_count, 0);
|
||||
if (ret) {
|
||||
fprintf(stderr, "Failed write curr cpus_count\n");
|
||||
exit(EXIT_FAIL_BPF);
|
||||
@ -509,8 +525,8 @@ static void mark_cpus_unavailable(void)
|
||||
int ret, i;
|
||||
|
||||
for (i = 0; i < MAX_CPUS; i++) {
|
||||
/* map_fd[5] = cpus_available */
|
||||
ret = bpf_map_update_elem(map_fd[5], &i, &invalid_cpu, 0);
|
||||
ret = bpf_map_update_elem(cpus_available_map_fd, &i,
|
||||
&invalid_cpu, 0);
|
||||
if (ret) {
|
||||
fprintf(stderr, "Failed marking CPU unavailable\n");
|
||||
exit(EXIT_FAIL_BPF);
|
||||
@ -530,7 +546,7 @@ static void stress_cpumap(void)
|
||||
create_cpu_entry(1, 16000, 0, false);
|
||||
}
|
||||
|
||||
static void stats_poll(int interval, bool use_separators, int prog_num,
|
||||
static void stats_poll(int interval, bool use_separators, char *prog_name,
|
||||
bool stress_mode)
|
||||
{
|
||||
struct stats_record *record, *prev;
|
||||
@ -546,7 +562,7 @@ static void stats_poll(int interval, bool use_separators, int prog_num,
|
||||
while (1) {
|
||||
swap(&prev, &record);
|
||||
stats_collect(record);
|
||||
stats_print(record, prev, prog_num);
|
||||
stats_print(record, prev, prog_name);
|
||||
sleep(interval);
|
||||
if (stress_mode)
|
||||
stress_cpumap();
|
||||
@ -556,17 +572,51 @@ static void stats_poll(int interval, bool use_separators, int prog_num,
|
||||
free_stats_record(prev);
|
||||
}
|
||||
|
||||
static int init_map_fds(struct bpf_object *obj)
|
||||
{
|
||||
cpu_map_fd = bpf_object__find_map_fd_by_name(obj, "cpu_map");
|
||||
rx_cnt_map_fd = bpf_object__find_map_fd_by_name(obj, "rx_cnt");
|
||||
redirect_err_cnt_map_fd =
|
||||
bpf_object__find_map_fd_by_name(obj, "redirect_err_cnt");
|
||||
cpumap_enqueue_cnt_map_fd =
|
||||
bpf_object__find_map_fd_by_name(obj, "cpumap_enqueue_cnt");
|
||||
cpumap_kthread_cnt_map_fd =
|
||||
bpf_object__find_map_fd_by_name(obj, "cpumap_kthread_cnt");
|
||||
cpus_available_map_fd =
|
||||
bpf_object__find_map_fd_by_name(obj, "cpus_available");
|
||||
cpus_count_map_fd = bpf_object__find_map_fd_by_name(obj, "cpus_count");
|
||||
cpus_iterator_map_fd =
|
||||
bpf_object__find_map_fd_by_name(obj, "cpus_iterator");
|
||||
exception_cnt_map_fd =
|
||||
bpf_object__find_map_fd_by_name(obj, "exception_cnt");
|
||||
|
||||
if (cpu_map_fd < 0 || rx_cnt_map_fd < 0 ||
|
||||
redirect_err_cnt_map_fd < 0 || cpumap_enqueue_cnt_map_fd < 0 ||
|
||||
cpumap_kthread_cnt_map_fd < 0 || cpus_available_map_fd < 0 ||
|
||||
cpus_count_map_fd < 0 || cpus_iterator_map_fd < 0 ||
|
||||
exception_cnt_map_fd < 0)
|
||||
return -ENOENT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct rlimit r = {10 * 1024 * 1024, RLIM_INFINITY};
|
||||
char *prog_name = "xdp_cpu_map5_lb_hash_ip_pairs";
|
||||
struct bpf_prog_load_attr prog_load_attr = {
|
||||
.prog_type = BPF_PROG_TYPE_UNSPEC,
|
||||
};
|
||||
bool use_separators = true;
|
||||
bool stress_mode = false;
|
||||
struct bpf_program *prog;
|
||||
struct bpf_object *obj;
|
||||
char filename[256];
|
||||
int added_cpus = 0;
|
||||
int longindex = 0;
|
||||
int interval = 2;
|
||||
int prog_num = 5;
|
||||
int add_cpu = -1;
|
||||
int prog_fd;
|
||||
__u32 qsize;
|
||||
int opt;
|
||||
|
||||
@ -579,22 +629,25 @@ int main(int argc, char **argv)
|
||||
qsize = 128+64;
|
||||
|
||||
snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
|
||||
prog_load_attr.file = filename;
|
||||
|
||||
if (setrlimit(RLIMIT_MEMLOCK, &r)) {
|
||||
perror("setrlimit(RLIMIT_MEMLOCK)");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (load_bpf_file(filename)) {
|
||||
fprintf(stderr, "ERR in load_bpf_file(): %s", bpf_log_buf);
|
||||
if (bpf_prog_load_xattr(&prog_load_attr, &obj, &prog_fd))
|
||||
return EXIT_FAIL;
|
||||
|
||||
if (prog_fd < 0) {
|
||||
fprintf(stderr, "ERR: bpf_prog_load_xattr: %s\n",
|
||||
strerror(errno));
|
||||
return EXIT_FAIL;
|
||||
}
|
||||
|
||||
if (!prog_fd[0]) {
|
||||
fprintf(stderr, "ERR: load_bpf_file: %s\n", strerror(errno));
|
||||
if (init_map_fds(obj) < 0) {
|
||||
fprintf(stderr, "bpf_object__find_map_fd_by_name failed\n");
|
||||
return EXIT_FAIL;
|
||||
}
|
||||
|
||||
mark_cpus_unavailable();
|
||||
|
||||
/* Parse commands line args */
|
||||
@ -630,13 +683,7 @@ int main(int argc, char **argv)
|
||||
break;
|
||||
case 'p':
|
||||
/* Selecting eBPF prog to load */
|
||||
prog_num = atoi(optarg);
|
||||
if (prog_num < 0 || prog_num >= MAX_PROG) {
|
||||
fprintf(stderr,
|
||||
"--prognum too large err(%d):%s\n",
|
||||
errno, strerror(errno));
|
||||
goto error;
|
||||
}
|
||||
prog_name = optarg;
|
||||
break;
|
||||
case 'c':
|
||||
/* Add multiple CPUs */
|
||||
@ -656,21 +703,21 @@ int main(int argc, char **argv)
|
||||
case 'h':
|
||||
error:
|
||||
default:
|
||||
usage(argv);
|
||||
usage(argv, obj);
|
||||
return EXIT_FAIL_OPTION;
|
||||
}
|
||||
}
|
||||
/* Required option */
|
||||
if (ifindex == -1) {
|
||||
fprintf(stderr, "ERR: required option --dev missing\n");
|
||||
usage(argv);
|
||||
usage(argv, obj);
|
||||
return EXIT_FAIL_OPTION;
|
||||
}
|
||||
/* Required option */
|
||||
if (add_cpu == -1) {
|
||||
fprintf(stderr, "ERR: required option --cpu missing\n");
|
||||
fprintf(stderr, " Specify multiple --cpu option to add more\n");
|
||||
usage(argv);
|
||||
usage(argv, obj);
|
||||
return EXIT_FAIL_OPTION;
|
||||
}
|
||||
|
||||
@ -678,11 +725,23 @@ int main(int argc, char **argv)
|
||||
signal(SIGINT, int_exit);
|
||||
signal(SIGTERM, int_exit);
|
||||
|
||||
if (bpf_set_link_xdp_fd(ifindex, prog_fd[prog_num], xdp_flags) < 0) {
|
||||
prog = bpf_object__find_program_by_title(obj, prog_name);
|
||||
if (!prog) {
|
||||
fprintf(stderr, "bpf_object__find_program_by_title failed\n");
|
||||
return EXIT_FAIL;
|
||||
}
|
||||
|
||||
prog_fd = bpf_program__fd(prog);
|
||||
if (prog_fd < 0) {
|
||||
fprintf(stderr, "bpf_program__fd failed\n");
|
||||
return EXIT_FAIL;
|
||||
}
|
||||
|
||||
if (bpf_set_link_xdp_fd(ifindex, prog_fd, xdp_flags) < 0) {
|
||||
fprintf(stderr, "link set xdp fd failed\n");
|
||||
return EXIT_FAIL_XDP;
|
||||
}
|
||||
|
||||
stats_poll(interval, use_separators, prog_num, stress_mode);
|
||||
stats_poll(interval, use_separators, prog_name, stress_mode);
|
||||
return EXIT_OK;
|
||||
}
|
||||
|
@ -22,15 +22,16 @@
|
||||
#include <libgen.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
#include "bpf_load.h"
|
||||
#include "bpf_util.h"
|
||||
#include <bpf/bpf.h>
|
||||
#include "bpf/libbpf.h"
|
||||
|
||||
static int ifindex_in;
|
||||
static int ifindex_out;
|
||||
static bool ifindex_out_xdp_dummy_attached = true;
|
||||
|
||||
static __u32 xdp_flags;
|
||||
static int rxcnt_map_fd;
|
||||
|
||||
static void int_exit(int sig)
|
||||
{
|
||||
@ -53,7 +54,7 @@ static void poll_stats(int interval, int ifindex)
|
||||
int i;
|
||||
|
||||
sleep(interval);
|
||||
assert(bpf_map_lookup_elem(map_fd[1], &key, values) == 0);
|
||||
assert(bpf_map_lookup_elem(rxcnt_map_fd, &key, values) == 0);
|
||||
for (i = 0; i < nr_cpus; i++)
|
||||
sum += (values[i] - prev[i]);
|
||||
if (sum)
|
||||
@ -76,9 +77,16 @@ static void usage(const char *prog)
|
||||
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,
|
||||
};
|
||||
struct bpf_program *prog, *dummy_prog;
|
||||
int prog_fd, dummy_prog_fd;
|
||||
const char *optstr = "SN";
|
||||
char filename[256];
|
||||
struct bpf_object *obj;
|
||||
int ret, opt, key = 0;
|
||||
char filename[256];
|
||||
int tx_port_map_fd;
|
||||
|
||||
while ((opt = getopt(argc, argv, optstr)) != -1) {
|
||||
switch (opt) {
|
||||
@ -109,24 +117,40 @@ int main(int argc, char **argv)
|
||||
printf("input: %d output: %d\n", ifindex_in, ifindex_out);
|
||||
|
||||
snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
|
||||
prog_load_attr.file = filename;
|
||||
|
||||
if (load_bpf_file(filename)) {
|
||||
printf("%s", bpf_log_buf);
|
||||
if (bpf_prog_load_xattr(&prog_load_attr, &obj, &prog_fd))
|
||||
return 1;
|
||||
|
||||
prog = bpf_program__next(NULL, obj);
|
||||
dummy_prog = bpf_program__next(prog, obj);
|
||||
if (!prog || !dummy_prog) {
|
||||
printf("finding a prog in obj file failed\n");
|
||||
return 1;
|
||||
}
|
||||
/* bpf_prog_load_xattr gives us the pointer to first prog's fd,
|
||||
* so we're missing only the fd for dummy prog
|
||||
*/
|
||||
dummy_prog_fd = bpf_program__fd(dummy_prog);
|
||||
if (prog_fd < 0 || dummy_prog_fd < 0) {
|
||||
printf("bpf_prog_load_xattr: %s\n", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!prog_fd[0]) {
|
||||
printf("load_bpf_file: %s\n", strerror(errno));
|
||||
tx_port_map_fd = bpf_object__find_map_fd_by_name(obj, "tx_port");
|
||||
rxcnt_map_fd = bpf_object__find_map_fd_by_name(obj, "rxcnt");
|
||||
if (tx_port_map_fd < 0 || rxcnt_map_fd < 0) {
|
||||
printf("bpf_object__find_map_fd_by_name failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (bpf_set_link_xdp_fd(ifindex_in, prog_fd[0], xdp_flags) < 0) {
|
||||
if (bpf_set_link_xdp_fd(ifindex_in, prog_fd, xdp_flags) < 0) {
|
||||
printf("ERROR: link set xdp fd failed on %d\n", ifindex_in);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Loading dummy XDP prog on out-device */
|
||||
if (bpf_set_link_xdp_fd(ifindex_out, prog_fd[1],
|
||||
if (bpf_set_link_xdp_fd(ifindex_out, dummy_prog_fd,
|
||||
(xdp_flags | XDP_FLAGS_UPDATE_IF_NOEXIST)) < 0) {
|
||||
printf("WARN: link set xdp fd failed on %d\n", ifindex_out);
|
||||
ifindex_out_xdp_dummy_attached = false;
|
||||
@ -135,11 +159,8 @@ int main(int argc, char **argv)
|
||||
signal(SIGINT, int_exit);
|
||||
signal(SIGTERM, int_exit);
|
||||
|
||||
printf("map[0] (vports) = %i, map[1] (map) = %i, map[2] (count) = %i\n",
|
||||
map_fd[0], map_fd[1], map_fd[2]);
|
||||
|
||||
/* populate virtual to physical port map */
|
||||
ret = bpf_map_update_elem(map_fd[0], &key, &ifindex_out, 0);
|
||||
ret = bpf_map_update_elem(tx_port_map_fd, &key, &ifindex_out, 0);
|
||||
if (ret) {
|
||||
perror("bpf_update_elem");
|
||||
goto out;
|
||||
|
@ -22,15 +22,16 @@
|
||||
#include <libgen.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
#include "bpf_load.h"
|
||||
#include "bpf_util.h"
|
||||
#include <bpf/bpf.h>
|
||||
#include "bpf/libbpf.h"
|
||||
|
||||
static int ifindex_in;
|
||||
static int ifindex_out;
|
||||
static bool ifindex_out_xdp_dummy_attached = true;
|
||||
|
||||
static __u32 xdp_flags;
|
||||
static int rxcnt_map_fd;
|
||||
|
||||
static void int_exit(int sig)
|
||||
{
|
||||
@ -53,7 +54,7 @@ static void poll_stats(int interval, int ifindex)
|
||||
int i;
|
||||
|
||||
sleep(interval);
|
||||
assert(bpf_map_lookup_elem(map_fd[1], &key, values) == 0);
|
||||
assert(bpf_map_lookup_elem(rxcnt_map_fd, &key, values) == 0);
|
||||
for (i = 0; i < nr_cpus; i++)
|
||||
sum += (values[i] - prev[i]);
|
||||
if (sum)
|
||||
@ -77,9 +78,16 @@ static void usage(const char *prog)
|
||||
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,
|
||||
};
|
||||
struct bpf_program *prog, *dummy_prog;
|
||||
int prog_fd, tx_port_map_fd, opt;
|
||||
const char *optstr = "SN";
|
||||
struct bpf_object *obj;
|
||||
char filename[256];
|
||||
int ret, opt, key = 0;
|
||||
int dummy_prog_fd;
|
||||
int ret, key = 0;
|
||||
|
||||
while ((opt = getopt(argc, argv, optstr)) != -1) {
|
||||
switch (opt) {
|
||||
@ -110,24 +118,40 @@ int main(int argc, char **argv)
|
||||
printf("input: %d output: %d\n", ifindex_in, ifindex_out);
|
||||
|
||||
snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
|
||||
prog_load_attr.file = filename;
|
||||
|
||||
if (load_bpf_file(filename)) {
|
||||
printf("%s", bpf_log_buf);
|
||||
if (bpf_prog_load_xattr(&prog_load_attr, &obj, &prog_fd))
|
||||
return 1;
|
||||
|
||||
prog = bpf_program__next(NULL, obj);
|
||||
dummy_prog = bpf_program__next(prog, obj);
|
||||
if (!prog || !dummy_prog) {
|
||||
printf("finding a prog in obj file failed\n");
|
||||
return 1;
|
||||
}
|
||||
/* bpf_prog_load_xattr gives us the pointer to first prog's fd,
|
||||
* so we're missing only the fd for dummy prog
|
||||
*/
|
||||
dummy_prog_fd = bpf_program__fd(dummy_prog);
|
||||
if (prog_fd < 0 || dummy_prog_fd < 0) {
|
||||
printf("bpf_prog_load_xattr: %s\n", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!prog_fd[0]) {
|
||||
printf("load_bpf_file: %s\n", strerror(errno));
|
||||
tx_port_map_fd = bpf_object__find_map_fd_by_name(obj, "tx_port");
|
||||
rxcnt_map_fd = bpf_object__find_map_fd_by_name(obj, "rxcnt");
|
||||
if (tx_port_map_fd < 0 || rxcnt_map_fd < 0) {
|
||||
printf("bpf_object__find_map_fd_by_name failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (bpf_set_link_xdp_fd(ifindex_in, prog_fd[0], xdp_flags) < 0) {
|
||||
if (bpf_set_link_xdp_fd(ifindex_in, prog_fd, xdp_flags) < 0) {
|
||||
printf("ERROR: link set xdp fd failed on %d\n", ifindex_in);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Loading dummy XDP prog on out-device */
|
||||
if (bpf_set_link_xdp_fd(ifindex_out, prog_fd[1],
|
||||
if (bpf_set_link_xdp_fd(ifindex_out, dummy_prog_fd,
|
||||
(xdp_flags | XDP_FLAGS_UPDATE_IF_NOEXIST)) < 0) {
|
||||
printf("WARN: link set xdp fd failed on %d\n", ifindex_out);
|
||||
ifindex_out_xdp_dummy_attached = false;
|
||||
@ -137,7 +161,7 @@ int main(int argc, char **argv)
|
||||
signal(SIGTERM, int_exit);
|
||||
|
||||
/* bpf redirect port */
|
||||
ret = bpf_map_update_elem(map_fd[0], &key, &ifindex_out, 0);
|
||||
ret = bpf_map_update_elem(tx_port_map_fd, &key, &ifindex_out, 0);
|
||||
if (ret) {
|
||||
perror("bpf_update_elem");
|
||||
goto out;
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#include "bpf_load.h"
|
||||
#include <bpf/bpf.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <fcntl.h>
|
||||
@ -25,11 +24,17 @@
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/syscall.h>
|
||||
#include "bpf_util.h"
|
||||
#include "bpf/libbpf.h"
|
||||
|
||||
int sock, sock_arp, flags = 0;
|
||||
static int total_ifindex;
|
||||
int *ifindex_list;
|
||||
char buf[8192];
|
||||
static int lpm_map_fd;
|
||||
static int rxcnt_map_fd;
|
||||
static int arp_table_map_fd;
|
||||
static int exact_match_map_fd;
|
||||
static int tx_port_map_fd;
|
||||
|
||||
static int get_route_table(int rtm_family);
|
||||
static void int_exit(int sig)
|
||||
@ -186,7 +191,8 @@ static void read_route(struct nlmsghdr *nh, int nll)
|
||||
bpf_set_link_xdp_fd(ifindex_list[i], -1, flags);
|
||||
exit(0);
|
||||
}
|
||||
assert(bpf_map_update_elem(map_fd[4], &route.iface, &route.iface, 0) == 0);
|
||||
assert(bpf_map_update_elem(tx_port_map_fd,
|
||||
&route.iface, &route.iface, 0) == 0);
|
||||
if (rtm_family == AF_INET) {
|
||||
struct trie_value {
|
||||
__u8 prefix[4];
|
||||
@ -207,11 +213,16 @@ static void read_route(struct nlmsghdr *nh, int nll)
|
||||
direct_entry.arp.dst = 0;
|
||||
if (route.dst_len == 32) {
|
||||
if (nh->nlmsg_type == RTM_DELROUTE) {
|
||||
assert(bpf_map_delete_elem(map_fd[3], &route.dst) == 0);
|
||||
assert(bpf_map_delete_elem(exact_match_map_fd,
|
||||
&route.dst) == 0);
|
||||
} else {
|
||||
if (bpf_map_lookup_elem(map_fd[2], &route.dst, &direct_entry.arp.mac) == 0)
|
||||
if (bpf_map_lookup_elem(arp_table_map_fd,
|
||||
&route.dst,
|
||||
&direct_entry.arp.mac) == 0)
|
||||
direct_entry.arp.dst = route.dst;
|
||||
assert(bpf_map_update_elem(map_fd[3], &route.dst, &direct_entry, 0) == 0);
|
||||
assert(bpf_map_update_elem(exact_match_map_fd,
|
||||
&route.dst,
|
||||
&direct_entry, 0) == 0);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 4; i++)
|
||||
@ -225,7 +236,7 @@ static void read_route(struct nlmsghdr *nh, int nll)
|
||||
route.gw, route.dst_len,
|
||||
route.metric,
|
||||
route.iface_name);
|
||||
if (bpf_map_lookup_elem(map_fd[0], prefix_key,
|
||||
if (bpf_map_lookup_elem(lpm_map_fd, prefix_key,
|
||||
prefix_value) < 0) {
|
||||
for (i = 0; i < 4; i++)
|
||||
prefix_value->prefix[i] = prefix_key->data[i];
|
||||
@ -234,7 +245,7 @@ static void read_route(struct nlmsghdr *nh, int nll)
|
||||
prefix_value->gw = route.gw;
|
||||
prefix_value->metric = route.metric;
|
||||
|
||||
assert(bpf_map_update_elem(map_fd[0],
|
||||
assert(bpf_map_update_elem(lpm_map_fd,
|
||||
prefix_key,
|
||||
prefix_value, 0
|
||||
) == 0);
|
||||
@ -247,7 +258,7 @@ static void read_route(struct nlmsghdr *nh, int nll)
|
||||
prefix_key->data[2],
|
||||
prefix_key->data[3],
|
||||
prefix_key->prefixlen);
|
||||
assert(bpf_map_delete_elem(map_fd[0],
|
||||
assert(bpf_map_delete_elem(lpm_map_fd,
|
||||
prefix_key
|
||||
) == 0);
|
||||
/* Rereading the route table to check if
|
||||
@ -275,8 +286,7 @@ static void read_route(struct nlmsghdr *nh, int nll)
|
||||
prefix_value->ifindex = route.iface;
|
||||
prefix_value->gw = route.gw;
|
||||
prefix_value->metric = route.metric;
|
||||
assert(bpf_map_update_elem(
|
||||
map_fd[0],
|
||||
assert(bpf_map_update_elem(lpm_map_fd,
|
||||
prefix_key,
|
||||
prefix_value,
|
||||
0) == 0);
|
||||
@ -401,7 +411,8 @@ static void read_arp(struct nlmsghdr *nh, int nll)
|
||||
arp_entry.mac = atol(mac);
|
||||
printf("%x\t\t%llx\n", arp_entry.dst, arp_entry.mac);
|
||||
if (ndm_family == AF_INET) {
|
||||
if (bpf_map_lookup_elem(map_fd[3], &arp_entry.dst,
|
||||
if (bpf_map_lookup_elem(exact_match_map_fd,
|
||||
&arp_entry.dst,
|
||||
&direct_entry) == 0) {
|
||||
if (nh->nlmsg_type == RTM_DELNEIGH) {
|
||||
direct_entry.arp.dst = 0;
|
||||
@ -410,16 +421,17 @@ static void read_arp(struct nlmsghdr *nh, int nll)
|
||||
direct_entry.arp.dst = arp_entry.dst;
|
||||
direct_entry.arp.mac = arp_entry.mac;
|
||||
}
|
||||
assert(bpf_map_update_elem(map_fd[3],
|
||||
assert(bpf_map_update_elem(exact_match_map_fd,
|
||||
&arp_entry.dst,
|
||||
&direct_entry, 0
|
||||
) == 0);
|
||||
memset(&direct_entry, 0, sizeof(direct_entry));
|
||||
}
|
||||
if (nh->nlmsg_type == RTM_DELNEIGH) {
|
||||
assert(bpf_map_delete_elem(map_fd[2], &arp_entry.dst) == 0);
|
||||
assert(bpf_map_delete_elem(arp_table_map_fd,
|
||||
&arp_entry.dst) == 0);
|
||||
} else if (nh->nlmsg_type == RTM_NEWNEIGH) {
|
||||
assert(bpf_map_update_elem(map_fd[2],
|
||||
assert(bpf_map_update_elem(arp_table_map_fd,
|
||||
&arp_entry.dst,
|
||||
&arp_entry.mac, 0
|
||||
) == 0);
|
||||
@ -553,7 +565,8 @@ static int monitor_route(void)
|
||||
for (key = 0; key < nr_keys; key++) {
|
||||
__u64 sum = 0;
|
||||
|
||||
assert(bpf_map_lookup_elem(map_fd[1], &key, values) == 0);
|
||||
assert(bpf_map_lookup_elem(rxcnt_map_fd,
|
||||
&key, values) == 0);
|
||||
for (i = 0; i < nr_cpus; i++)
|
||||
sum += (values[i] - prev[key][i]);
|
||||
if (sum)
|
||||
@ -596,11 +609,18 @@ cleanup:
|
||||
|
||||
int main(int ac, char **argv)
|
||||
{
|
||||
struct bpf_prog_load_attr prog_load_attr = {
|
||||
.prog_type = BPF_PROG_TYPE_XDP,
|
||||
};
|
||||
struct bpf_object *obj;
|
||||
char filename[256];
|
||||
char **ifname_list;
|
||||
int prog_fd;
|
||||
int i = 1;
|
||||
|
||||
snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
|
||||
prog_load_attr.file = filename;
|
||||
|
||||
if (ac < 2) {
|
||||
printf("usage: %s [-S] Interface name list\n", argv[0]);
|
||||
return 1;
|
||||
@ -614,15 +634,28 @@ int main(int ac, char **argv)
|
||||
total_ifindex = ac - 1;
|
||||
ifname_list = (argv + 1);
|
||||
}
|
||||
if (load_bpf_file(filename)) {
|
||||
printf("%s", bpf_log_buf);
|
||||
|
||||
if (bpf_prog_load_xattr(&prog_load_attr, &obj, &prog_fd))
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("\n**************loading bpf file*********************\n\n\n");
|
||||
if (!prog_fd[0]) {
|
||||
printf("load_bpf_file: %s\n", strerror(errno));
|
||||
if (!prog_fd) {
|
||||
printf("bpf_prog_load_xattr: %s\n", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
lpm_map_fd = bpf_object__find_map_fd_by_name(obj, "lpm_map");
|
||||
rxcnt_map_fd = bpf_object__find_map_fd_by_name(obj, "rxcnt");
|
||||
arp_table_map_fd = bpf_object__find_map_fd_by_name(obj, "arp_table");
|
||||
exact_match_map_fd = bpf_object__find_map_fd_by_name(obj,
|
||||
"exact_match");
|
||||
tx_port_map_fd = bpf_object__find_map_fd_by_name(obj, "tx_port");
|
||||
if (lpm_map_fd < 0 || rxcnt_map_fd < 0 || arp_table_map_fd < 0 ||
|
||||
exact_match_map_fd < 0 || tx_port_map_fd < 0) {
|
||||
printf("bpf_object__find_map_fd_by_name failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
ifindex_list = (int *)malloc(total_ifindex * sizeof(int *));
|
||||
for (i = 0; i < total_ifindex; i++) {
|
||||
ifindex_list[i] = if_nametoindex(ifname_list[i]);
|
||||
@ -633,7 +666,7 @@ int main(int ac, char **argv)
|
||||
}
|
||||
}
|
||||
for (i = 0; i < total_ifindex; i++) {
|
||||
if (bpf_set_link_xdp_fd(ifindex_list[i], prog_fd[0], flags) < 0) {
|
||||
if (bpf_set_link_xdp_fd(ifindex_list[i], prog_fd, flags) < 0) {
|
||||
printf("link set xdp fd failed\n");
|
||||
int recovery_index = i;
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
#include <netinet/ether.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include "bpf_load.h"
|
||||
#include "bpf/libbpf.h"
|
||||
#include <bpf/bpf.h>
|
||||
#include "bpf_util.h"
|
||||
#include "xdp_tx_iptunnel_common.h"
|
||||
@ -26,6 +26,7 @@
|
||||
|
||||
static int ifindex = -1;
|
||||
static __u32 xdp_flags = 0;
|
||||
static int rxcnt_map_fd;
|
||||
|
||||
static void int_exit(int sig)
|
||||
{
|
||||
@ -53,7 +54,8 @@ static void poll_stats(unsigned int kill_after_s)
|
||||
for (proto = 0; proto < nr_protos; proto++) {
|
||||
__u64 sum = 0;
|
||||
|
||||
assert(bpf_map_lookup_elem(map_fd[0], &proto, values) == 0);
|
||||
assert(bpf_map_lookup_elem(rxcnt_map_fd, &proto,
|
||||
values) == 0);
|
||||
for (i = 0; i < nr_cpus; i++)
|
||||
sum += (values[i] - prev[proto][i]);
|
||||
|
||||
@ -138,15 +140,19 @@ static int parse_ports(const char *port_str, int *min_port, int *max_port)
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct bpf_prog_load_attr prog_load_attr = {
|
||||
.prog_type = BPF_PROG_TYPE_XDP,
|
||||
};
|
||||
struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
|
||||
int min_port = 0, max_port = 0, vip2tnl_map_fd;
|
||||
const char *optstr = "i:a:p:s:d:m:T:P:SNh";
|
||||
unsigned char opt_flags[256] = {};
|
||||
unsigned int kill_after_s = 0;
|
||||
const char *optstr = "i:a:p:s:d:m:T:P:SNh";
|
||||
int min_port = 0, max_port = 0;
|
||||
struct iptnl_info tnl = {};
|
||||
struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
|
||||
struct bpf_object *obj;
|
||||
struct vip vip = {};
|
||||
char filename[256];
|
||||
int opt;
|
||||
int opt, prog_fd;
|
||||
int i;
|
||||
|
||||
tnl.family = AF_UNSPEC;
|
||||
@ -232,14 +238,20 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
|
||||
prog_load_attr.file = filename;
|
||||
|
||||
if (load_bpf_file(filename)) {
|
||||
printf("%s", bpf_log_buf);
|
||||
if (bpf_prog_load_xattr(&prog_load_attr, &obj, &prog_fd))
|
||||
return 1;
|
||||
|
||||
if (!prog_fd) {
|
||||
printf("load_bpf_file: %s\n", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!prog_fd[0]) {
|
||||
printf("load_bpf_file: %s\n", strerror(errno));
|
||||
rxcnt_map_fd = bpf_object__find_map_fd_by_name(obj, "rxcnt");
|
||||
vip2tnl_map_fd = bpf_object__find_map_fd_by_name(obj, "vip2tnl");
|
||||
if (vip2tnl_map_fd < 0 || rxcnt_map_fd < 0) {
|
||||
printf("bpf_object__find_map_fd_by_name failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -248,13 +260,14 @@ int main(int argc, char **argv)
|
||||
|
||||
while (min_port <= max_port) {
|
||||
vip.dport = htons(min_port++);
|
||||
if (bpf_map_update_elem(map_fd[1], &vip, &tnl, BPF_NOEXIST)) {
|
||||
if (bpf_map_update_elem(vip2tnl_map_fd, &vip, &tnl,
|
||||
BPF_NOEXIST)) {
|
||||
perror("bpf_map_update_elem(&vip2tnl)");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
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");
|
||||
return 1;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user