samples/bpf: Add a "force" flag to XDP samples

Make xdp samples consistent with iproute2 behavior and set the
XDP_FLAGS_UPDATE_IF_NOEXIST by default when setting the xdp program on
interface. Provide an option for user to force the program loading,
which as a result will not include the mentioned flag in
bpf_set_link_xdp_fd call.

Signed-off-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
This commit is contained in:
Maciej Fijalkowski 2019-02-01 22:42:28 +01:00 committed by Daniel Borkmann
parent 01dde20ce0
commit 743e568c15
10 changed files with 119 additions and 40 deletions

View File

@ -22,7 +22,7 @@
#include "bpf/libbpf.h" #include "bpf/libbpf.h"
static int ifindex; static int ifindex;
static __u32 xdp_flags; static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
static void int_exit(int sig) static void int_exit(int sig)
{ {
@ -63,7 +63,8 @@ static void usage(const char *prog)
"usage: %s [OPTS] IFACE\n\n" "usage: %s [OPTS] IFACE\n\n"
"OPTS:\n" "OPTS:\n"
" -S use skb-mode\n" " -S use skb-mode\n"
" -N enforce native mode\n", " -N enforce native mode\n"
" -F force loading prog\n",
prog); prog);
} }
@ -73,7 +74,7 @@ int main(int argc, char **argv)
struct bpf_prog_load_attr prog_load_attr = { struct bpf_prog_load_attr prog_load_attr = {
.prog_type = BPF_PROG_TYPE_XDP, .prog_type = BPF_PROG_TYPE_XDP,
}; };
const char *optstr = "SN"; const char *optstr = "FSN";
int prog_fd, map_fd, opt; int prog_fd, map_fd, opt;
struct bpf_object *obj; struct bpf_object *obj;
struct bpf_map *map; struct bpf_map *map;
@ -87,6 +88,9 @@ int main(int argc, char **argv)
case 'N': case 'N':
xdp_flags |= XDP_FLAGS_DRV_MODE; xdp_flags |= XDP_FLAGS_DRV_MODE;
break; break;
case 'F':
xdp_flags &= ~XDP_FLAGS_UPDATE_IF_NOEXIST;
break;
default: default:
usage(basename(argv[0])); usage(basename(argv[0]));
return 1; return 1;

View File

@ -24,7 +24,7 @@
#define STATS_INTERVAL_S 2U #define STATS_INTERVAL_S 2U
static int ifindex = -1; static int ifindex = -1;
static __u32 xdp_flags; static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
static void int_exit(int sig) static void int_exit(int sig)
{ {
@ -60,6 +60,7 @@ static void usage(const char *cmd)
printf(" -T <stop-after-X-seconds> Default: 0 (forever)\n"); printf(" -T <stop-after-X-seconds> Default: 0 (forever)\n");
printf(" -S use skb-mode\n"); printf(" -S use skb-mode\n");
printf(" -N enforce native mode\n"); printf(" -N enforce native mode\n");
printf(" -F force loading prog\n");
printf(" -h Display this help\n"); printf(" -h Display this help\n");
} }
@ -70,8 +71,8 @@ int main(int argc, char **argv)
.prog_type = BPF_PROG_TYPE_XDP, .prog_type = BPF_PROG_TYPE_XDP,
}; };
unsigned char opt_flags[256] = {}; unsigned char opt_flags[256] = {};
const char *optstr = "i:T:SNFh";
unsigned int kill_after_s = 0; unsigned int kill_after_s = 0;
const char *optstr = "i:T:SNh";
int i, prog_fd, map_fd, opt; int i, prog_fd, map_fd, opt;
struct bpf_object *obj; struct bpf_object *obj;
struct bpf_map *map; struct bpf_map *map;
@ -96,6 +97,9 @@ int main(int argc, char **argv)
case 'N': case 'N':
xdp_flags |= XDP_FLAGS_DRV_MODE; xdp_flags |= XDP_FLAGS_DRV_MODE;
break; break;
case 'F':
xdp_flags &= ~XDP_FLAGS_UPDATE_IF_NOEXIST;
break;
default: default:
usage(argv[0]); usage(argv[0]);
return 1; return 1;

View File

@ -33,7 +33,7 @@ static int ifindex = -1;
static char ifname_buf[IF_NAMESIZE]; static char ifname_buf[IF_NAMESIZE];
static char *ifname; static char *ifname;
static __u32 xdp_flags; static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
static int cpu_map_fd; static int cpu_map_fd;
static int rx_cnt_map_fd; static int rx_cnt_map_fd;
static int redirect_err_cnt_map_fd; static int redirect_err_cnt_map_fd;
@ -62,6 +62,7 @@ static const struct option long_options[] = {
{"cpu", required_argument, NULL, 'c' }, {"cpu", required_argument, NULL, 'c' },
{"stress-mode", no_argument, NULL, 'x' }, {"stress-mode", no_argument, NULL, 'x' },
{"no-separators", no_argument, NULL, 'z' }, {"no-separators", no_argument, NULL, 'z' },
{"force", no_argument, NULL, 'F' },
{0, 0, NULL, 0 } {0, 0, NULL, 0 }
}; };
@ -651,7 +652,7 @@ int main(int argc, char **argv)
mark_cpus_unavailable(); mark_cpus_unavailable();
/* Parse commands line args */ /* Parse commands line args */
while ((opt = getopt_long(argc, argv, "hSd:", while ((opt = getopt_long(argc, argv, "hSd:s:p:q:c:xzF",
long_options, &longindex)) != -1) { long_options, &longindex)) != -1) {
switch (opt) { switch (opt) {
case 'd': case 'd':
@ -700,6 +701,9 @@ int main(int argc, char **argv)
case 'q': case 'q':
qsize = atoi(optarg); qsize = atoi(optarg);
break; break;
case 'F':
xdp_flags &= ~XDP_FLAGS_UPDATE_IF_NOEXIST;
break;
case 'h': case 'h':
error: error:
default: default:

View File

@ -30,7 +30,7 @@ static int ifindex_in;
static int ifindex_out; static int ifindex_out;
static bool ifindex_out_xdp_dummy_attached = true; static bool ifindex_out_xdp_dummy_attached = true;
static __u32 xdp_flags; static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
static int rxcnt_map_fd; static int rxcnt_map_fd;
static void int_exit(int sig) static void int_exit(int sig)
@ -70,7 +70,8 @@ static void usage(const char *prog)
"usage: %s [OPTS] IFINDEX_IN IFINDEX_OUT\n\n" "usage: %s [OPTS] IFINDEX_IN IFINDEX_OUT\n\n"
"OPTS:\n" "OPTS:\n"
" -S use skb-mode\n" " -S use skb-mode\n"
" -N enforce native mode\n", " -N enforce native mode\n"
" -F force loading prog\n",
prog); prog);
} }
@ -82,7 +83,7 @@ int main(int argc, char **argv)
}; };
struct bpf_program *prog, *dummy_prog; struct bpf_program *prog, *dummy_prog;
int prog_fd, dummy_prog_fd; int prog_fd, dummy_prog_fd;
const char *optstr = "SN"; const char *optstr = "FSN";
struct bpf_object *obj; struct bpf_object *obj;
int ret, opt, key = 0; int ret, opt, key = 0;
char filename[256]; char filename[256];
@ -96,6 +97,9 @@ int main(int argc, char **argv)
case 'N': case 'N':
xdp_flags |= XDP_FLAGS_DRV_MODE; xdp_flags |= XDP_FLAGS_DRV_MODE;
break; break;
case 'F':
xdp_flags &= ~XDP_FLAGS_UPDATE_IF_NOEXIST;
break;
default: default:
usage(basename(argv[0])); usage(basename(argv[0]));
return 1; return 1;

View File

@ -30,7 +30,7 @@ static int ifindex_in;
static int ifindex_out; static int ifindex_out;
static bool ifindex_out_xdp_dummy_attached = true; static bool ifindex_out_xdp_dummy_attached = true;
static __u32 xdp_flags; static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
static int rxcnt_map_fd; static int rxcnt_map_fd;
static void int_exit(int sig) static void int_exit(int sig)
@ -70,7 +70,8 @@ static void usage(const char *prog)
"usage: %s [OPTS] IFINDEX_IN IFINDEX_OUT\n\n" "usage: %s [OPTS] IFINDEX_IN IFINDEX_OUT\n\n"
"OPTS:\n" "OPTS:\n"
" -S use skb-mode\n" " -S use skb-mode\n"
" -N enforce native mode\n", " -N enforce native mode\n"
" -F force loading prog\n",
prog); prog);
} }
@ -83,7 +84,7 @@ int main(int argc, char **argv)
}; };
struct bpf_program *prog, *dummy_prog; struct bpf_program *prog, *dummy_prog;
int prog_fd, tx_port_map_fd, opt; int prog_fd, tx_port_map_fd, opt;
const char *optstr = "SN"; const char *optstr = "FSN";
struct bpf_object *obj; struct bpf_object *obj;
char filename[256]; char filename[256];
int dummy_prog_fd; int dummy_prog_fd;
@ -97,6 +98,9 @@ int main(int argc, char **argv)
case 'N': case 'N':
xdp_flags |= XDP_FLAGS_DRV_MODE; xdp_flags |= XDP_FLAGS_DRV_MODE;
break; break;
case 'F':
xdp_flags &= ~XDP_FLAGS_UPDATE_IF_NOEXIST;
break;
default: default:
usage(basename(argv[0])); usage(basename(argv[0]));
return 1; return 1;

View File

@ -26,8 +26,9 @@
#include "bpf_util.h" #include "bpf_util.h"
#include "bpf/libbpf.h" #include "bpf/libbpf.h"
#include <sys/resource.h> #include <sys/resource.h>
#include <libgen.h>
int sock, sock_arp, flags = 0; int sock, sock_arp, flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
static int total_ifindex; static int total_ifindex;
int *ifindex_list; int *ifindex_list;
char buf[8192]; char buf[8192];
@ -608,33 +609,56 @@ cleanup:
return ret; return ret;
} }
static void usage(const char *prog)
{
fprintf(stderr,
"%s: %s [OPTS] interface name list\n\n"
"OPTS:\n"
" -S use skb-mode\n"
" -F force loading prog\n",
__func__, prog);
}
int main(int ac, char **argv) int main(int ac, char **argv)
{ {
struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY}; struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
struct bpf_prog_load_attr prog_load_attr = { struct bpf_prog_load_attr prog_load_attr = {
.prog_type = BPF_PROG_TYPE_XDP, .prog_type = BPF_PROG_TYPE_XDP,
}; };
const char *optstr = "SF";
struct bpf_object *obj; struct bpf_object *obj;
char filename[256]; char filename[256];
char **ifname_list; char **ifname_list;
int prog_fd; int prog_fd, opt;
int i = 1; int i = 1;
snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
prog_load_attr.file = filename; prog_load_attr.file = filename;
if (ac < 2) { total_ifindex = ac - 1;
printf("usage: %s [-S] Interface name list\n", argv[0]); ifname_list = (argv + 1);
return 1;
while ((opt = getopt(ac, argv, optstr)) != -1) {
switch (opt) {
case 'S':
flags |= XDP_FLAGS_SKB_MODE;
total_ifindex--;
ifname_list++;
break;
case 'F':
flags &= ~XDP_FLAGS_UPDATE_IF_NOEXIST;
total_ifindex--;
ifname_list++;
break;
default:
usage(basename(argv[0]));
return 1;
}
} }
if (!strcmp(argv[1], "-S")) {
flags = XDP_FLAGS_SKB_MODE; if (optind == ac) {
total_ifindex = ac - 2; usage(basename(argv[0]));
ifname_list = (argv + 2); return 1;
} else {
flags = 0;
total_ifindex = ac - 1;
ifname_list = (argv + 1);
} }
if (setrlimit(RLIMIT_MEMLOCK, &r)) { if (setrlimit(RLIMIT_MEMLOCK, &r)) {

View File

@ -30,7 +30,7 @@ static int ifindex = -1;
static char ifname_buf[IF_NAMESIZE]; static char ifname_buf[IF_NAMESIZE];
static char *ifname; static char *ifname;
static __u32 xdp_flags; static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
static struct bpf_map *stats_global_map; static struct bpf_map *stats_global_map;
static struct bpf_map *rx_queue_index_map; static struct bpf_map *rx_queue_index_map;
@ -52,6 +52,7 @@ static const struct option long_options[] = {
{"action", required_argument, NULL, 'a' }, {"action", required_argument, NULL, 'a' },
{"readmem", no_argument, NULL, 'r' }, {"readmem", no_argument, NULL, 'r' },
{"swapmac", no_argument, NULL, 'm' }, {"swapmac", no_argument, NULL, 'm' },
{"force", no_argument, NULL, 'F' },
{0, 0, NULL, 0 } {0, 0, NULL, 0 }
}; };
@ -487,7 +488,7 @@ int main(int argc, char **argv)
} }
/* Parse commands line args */ /* Parse commands line args */
while ((opt = getopt_long(argc, argv, "hSd:", while ((opt = getopt_long(argc, argv, "FhSrmzd:s:a:",
long_options, &longindex)) != -1) { long_options, &longindex)) != -1) {
switch (opt) { switch (opt) {
case 'd': case 'd':
@ -524,6 +525,9 @@ int main(int argc, char **argv)
case 'm': case 'm':
cfg_options |= SWAP_MAC; cfg_options |= SWAP_MAC;
break; break;
case 'F':
xdp_flags &= ~XDP_FLAGS_UPDATE_IF_NOEXIST;
break;
case 'h': case 'h':
error: error:
default: default:

View File

@ -13,6 +13,8 @@
#include <libbpf.h> #include <libbpf.h>
#include <bpf/bpf.h> #include <bpf/bpf.h>
#include <sys/resource.h> #include <sys/resource.h>
#include <libgen.h>
#include <linux/if_link.h>
#include "perf-sys.h" #include "perf-sys.h"
#include "trace_helpers.h" #include "trace_helpers.h"
@ -21,12 +23,13 @@
static int pmu_fds[MAX_CPUS], if_idx; static int pmu_fds[MAX_CPUS], if_idx;
static struct perf_event_mmap_page *headers[MAX_CPUS]; static struct perf_event_mmap_page *headers[MAX_CPUS];
static char *if_name; static char *if_name;
static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
static int do_attach(int idx, int fd, const char *name) static int do_attach(int idx, int fd, const char *name)
{ {
int err; int err;
err = bpf_set_link_xdp_fd(idx, fd, 0); err = bpf_set_link_xdp_fd(idx, fd, xdp_flags);
if (err < 0) if (err < 0)
printf("ERROR: failed to attach program to %s\n", name); printf("ERROR: failed to attach program to %s\n", name);
@ -98,21 +101,42 @@ static void sig_handler(int signo)
exit(0); exit(0);
} }
static void usage(const char *prog)
{
fprintf(stderr,
"%s: %s [OPTS] <ifname|ifindex>\n\n"
"OPTS:\n"
" -F force loading prog\n",
__func__, 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 = { struct bpf_prog_load_attr prog_load_attr = {
.prog_type = BPF_PROG_TYPE_XDP, .prog_type = BPF_PROG_TYPE_XDP,
}; };
const char *optstr = "F";
int prog_fd, map_fd, opt;
struct bpf_object *obj; struct bpf_object *obj;
struct bpf_map *map; struct bpf_map *map;
int prog_fd, map_fd;
char filename[256]; char filename[256];
int ret, err, i; int ret, err, i;
int numcpus; int numcpus;
if (argc < 2) { while ((opt = getopt(argc, argv, optstr)) != -1) {
printf("Usage: %s <ifname>\n", argv[0]); switch (opt) {
case 'F':
xdp_flags &= ~XDP_FLAGS_UPDATE_IF_NOEXIST;
break;
default:
usage(basename(argv[0]));
return 1;
}
}
if (optind == argc) {
usage(basename(argv[0]));
return 1; return 1;
} }
@ -143,16 +167,16 @@ int main(int argc, char **argv)
} }
map_fd = bpf_map__fd(map); map_fd = bpf_map__fd(map);
if_idx = if_nametoindex(argv[1]); if_idx = if_nametoindex(argv[optind]);
if (!if_idx) if (!if_idx)
if_idx = strtoul(argv[1], NULL, 0); if_idx = strtoul(argv[optind], NULL, 0);
if (!if_idx) { if (!if_idx) {
fprintf(stderr, "Invalid ifname\n"); fprintf(stderr, "Invalid ifname\n");
return 1; return 1;
} }
if_name = argv[1]; if_name = argv[optind];
err = do_attach(if_idx, prog_fd, argv[1]); err = do_attach(if_idx, prog_fd, if_name);
if (err) if (err)
return err; return err;

View File

@ -25,7 +25,7 @@
#define STATS_INTERVAL_S 2U #define STATS_INTERVAL_S 2U
static int ifindex = -1; static int ifindex = -1;
static __u32 xdp_flags = 0; static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
static int rxcnt_map_fd; static int rxcnt_map_fd;
static void int_exit(int sig) static void int_exit(int sig)
@ -83,6 +83,7 @@ static void usage(const char *cmd)
printf(" -P <IP-Protocol> Default is TCP\n"); printf(" -P <IP-Protocol> Default is TCP\n");
printf(" -S use skb-mode\n"); printf(" -S use skb-mode\n");
printf(" -N enforce native mode\n"); printf(" -N enforce native mode\n");
printf(" -F Force loading the XDP prog\n");
printf(" -h Display this help\n"); printf(" -h Display this help\n");
} }
@ -145,7 +146,7 @@ int main(int argc, char **argv)
}; };
struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY}; struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
int min_port = 0, max_port = 0, vip2tnl_map_fd; int min_port = 0, max_port = 0, vip2tnl_map_fd;
const char *optstr = "i:a:p:s:d:m:T:P:SNh"; const char *optstr = "i:a:p:s:d:m:T:P:FSNh";
unsigned char opt_flags[256] = {}; unsigned char opt_flags[256] = {};
unsigned int kill_after_s = 0; unsigned int kill_after_s = 0;
struct iptnl_info tnl = {}; struct iptnl_info tnl = {};
@ -217,6 +218,9 @@ int main(int argc, char **argv)
case 'N': case 'N':
xdp_flags |= XDP_FLAGS_DRV_MODE; xdp_flags |= XDP_FLAGS_DRV_MODE;
break; break;
case 'F':
xdp_flags &= ~XDP_FLAGS_UPDATE_IF_NOEXIST;
break;
default: default:
usage(argv[0]); usage(argv[0]);
return 1; return 1;

View File

@ -68,7 +68,7 @@ enum benchmark_type {
}; };
static enum benchmark_type opt_bench = BENCH_RXDROP; static enum benchmark_type opt_bench = BENCH_RXDROP;
static u32 opt_xdp_flags; static u32 opt_xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
static const char *opt_if = ""; static const char *opt_if = "";
static int opt_ifindex; static int opt_ifindex;
static int opt_queue; static int opt_queue;
@ -682,7 +682,7 @@ static void parse_command_line(int argc, char **argv)
opterr = 0; opterr = 0;
for (;;) { for (;;) {
c = getopt_long(argc, argv, "rtli:q:psSNn:cz", long_options, c = getopt_long(argc, argv, "Frtli:q:psSNn:cz", long_options,
&option_index); &option_index);
if (c == -1) if (c == -1)
break; break;
@ -725,6 +725,9 @@ static void parse_command_line(int argc, char **argv)
case 'c': case 'c':
opt_xdp_bind_flags |= XDP_COPY; opt_xdp_bind_flags |= XDP_COPY;
break; break;
case 'F':
opt_xdp_flags &= ~XDP_FLAGS_UPDATE_IF_NOEXIST;
break;
default: default:
usage(basename(argv[0])); usage(basename(argv[0]));
} }