Commit e90b1fd8 authored by David S. Miller's avatar David S. Miller

Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next

Daniel Borkmann says:

====================
pull-request: bpf-next 2019-02-07

The following pull-request contains BPF updates for your *net-next* tree.

The main changes are:

1) Add a riscv64 JIT for BPF, from Björn.

2) Implement BTF deduplication algorithm for libbpf which takes BTF type
   information containing duplicate per-compilation unit information and
   reduces it to an equivalent set of BTF types with no duplication and
   without loss of information, from Andrii.

3) Offloaded and native BPF XDP programs can coexist today, enable also
   offloaded and generic ones as well, from Jakub.

4) Expose various BTF related helper functions in libbpf as API which
   are in particular helpful for JITed programs, from Yonghong.

5) Fix the recently added JMP32 code emission in s390x JIT, from Heiko.

6) Fix BPF kselftests' tcp_{server,client}.py to be able to run inside
   a network namespace, also add a fix for libbpf to get libbpf_print()
   working, from Stanislav.

7) Fixes for bpftool documentation, from Prashant.

8) Type cleanup in BPF kselftests' test_maps.c to silence a gcc8 warning,
   from Breno.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 907bea9c dd9cef43
......@@ -464,10 +464,11 @@ breakpoints: 0 1
JIT compiler
------------
The Linux kernel has a built-in BPF JIT compiler for x86_64, SPARC, PowerPC,
ARM, ARM64, MIPS and s390 and can be enabled through CONFIG_BPF_JIT. The JIT
compiler is transparently invoked for each attached filter from user space
or for internal kernel users if it has been previously enabled by root:
The Linux kernel has a built-in BPF JIT compiler for x86_64, SPARC,
PowerPC, ARM, ARM64, MIPS, RISC-V and s390 and can be enabled through
CONFIG_BPF_JIT. The JIT compiler is transparently invoked for each
attached filter from user space or for internal kernel users if it has
been previously enabled by root:
echo 1 > /proc/sys/net/core/bpf_jit_enable
......@@ -603,9 +604,10 @@ got from bpf_prog_create(), and 'ctx' the given context (e.g.
skb pointer). All constraints and restrictions from bpf_check_classic() apply
before a conversion to the new layout is being done behind the scenes!
Currently, the classic BPF format is being used for JITing on most 32-bit
architectures, whereas x86-64, aarch64, s390x, powerpc64, sparc64, arm32 perform
JIT compilation from eBPF instruction set.
Currently, the classic BPF format is being used for JITing on most
32-bit architectures, whereas x86-64, aarch64, s390x, powerpc64,
sparc64, arm32, riscv (RV64G) perform JIT compilation from eBPF
instruction set.
Some core changes of the new internal format:
......
......@@ -52,6 +52,7 @@ two flavors of JITs, the newer eBPF JIT currently supported on:
- sparc64
- mips64
- s390x
- riscv
And the older cBPF JIT supported on the following archs:
- mips
......
......@@ -2907,6 +2907,12 @@ L: netdev@vger.kernel.org
S: Maintained
F: arch/powerpc/net/
BPF JIT for RISC-V (RV64G)
M: Björn Töpel <bjorn.topel@gmail.com>
L: netdev@vger.kernel.org
S: Maintained
F: arch/riscv/net/
BPF JIT for S390
M: Martin Schwidefsky <schwidefsky@de.ibm.com>
M: Heiko Carstens <heiko.carstens@de.ibm.com>
......
......@@ -49,6 +49,7 @@ config RISCV
select RISCV_TIMER
select GENERIC_IRQ_MULTI_HANDLER
select ARCH_HAS_PTE_SPECIAL
select HAVE_EBPF_JIT if 64BIT
config MMU
def_bool y
......
......@@ -77,7 +77,7 @@ KBUILD_IMAGE := $(boot)/Image.gz
head-y := arch/riscv/kernel/head.o
core-y += arch/riscv/kernel/ arch/riscv/mm/
core-y += arch/riscv/kernel/ arch/riscv/mm/ arch/riscv/net/
libs-y += arch/riscv/lib/
......
obj-$(CONFIG_BPF_JIT) += bpf_jit_comp.o
This diff is collapsed.
......@@ -1154,7 +1154,7 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i
mask = 0x7000; /* jnz */
if (BPF_CLASS(insn->code) == BPF_JMP32) {
/* llilf %w1,imm (load zero extend imm) */
EMIT6_IMM(0xc0010000, REG_W1, imm);
EMIT6_IMM(0xc00f0000, REG_W1, imm);
/* nr %w1,%dst */
EMIT2(0x1400, REG_W1, dst_reg);
} else {
......@@ -1216,6 +1216,7 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i
REG_W1, dst_reg, src_reg);
goto branch_oc;
branch_ks:
is_jmp32 = BPF_CLASS(insn->code) == BPF_JMP32;
/* lgfi %w1,imm (load sign extend imm) */
EMIT6_IMM(0xc0010000, REG_W1, imm);
/* crj or cgrj %dst,%w1,mask,off */
......@@ -1223,6 +1224,7 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i
dst_reg, REG_W1, i, off, mask);
break;
branch_ku:
is_jmp32 = BPF_CLASS(insn->code) == BPF_JMP32;
/* lgfi %w1,imm (load sign extend imm) */
EMIT6_IMM(0xc0010000, REG_W1, imm);
/* clrj or clgrj %dst,%w1,mask,off */
......@@ -1230,11 +1232,13 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i
dst_reg, REG_W1, i, off, mask);
break;
branch_xs:
is_jmp32 = BPF_CLASS(insn->code) == BPF_JMP32;
/* crj or cgrj %dst,%src,mask,off */
EMIT6_PCREL(0xec000000, (is_jmp32 ? 0x0076 : 0x0064),
dst_reg, src_reg, i, off, mask);
break;
branch_xu:
is_jmp32 = BPF_CLASS(insn->code) == BPF_JMP32;
/* clrj or clgrj %dst,%src,mask,off */
EMIT6_PCREL(0xec000000, (is_jmp32 ? 0x0077 : 0x0065),
dst_reg, src_reg, i, off, mask);
......
......@@ -8033,11 +8033,13 @@ int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
enum bpf_netdev_command query;
struct bpf_prog *prog = NULL;
bpf_op_t bpf_op, bpf_chk;
bool offload;
int err;
ASSERT_RTNL();
query = flags & XDP_FLAGS_HW_MODE ? XDP_QUERY_PROG_HW : XDP_QUERY_PROG;
offload = flags & XDP_FLAGS_HW_MODE;
query = offload ? XDP_QUERY_PROG_HW : XDP_QUERY_PROG;
bpf_op = bpf_chk = ops->ndo_bpf;
if (!bpf_op && (flags & (XDP_FLAGS_DRV_MODE | XDP_FLAGS_HW_MODE))) {
......@@ -8050,8 +8052,7 @@ int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
bpf_chk = generic_xdp_install;
if (fd >= 0) {
if (__dev_xdp_query(dev, bpf_chk, XDP_QUERY_PROG) ||
__dev_xdp_query(dev, bpf_chk, XDP_QUERY_PROG_HW)) {
if (!offload && __dev_xdp_query(dev, bpf_chk, XDP_QUERY_PROG)) {
NL_SET_ERR_MSG(extack, "native and generic XDP can't be active at the same time");
return -EEXIST;
}
......@@ -8066,8 +8067,7 @@ int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
if (IS_ERR(prog))
return PTR_ERR(prog);
if (!(flags & XDP_FLAGS_HW_MODE) &&
bpf_prog_is_dev_bound(prog->aux)) {
if (!offload && bpf_prog_is_dev_bound(prog->aux)) {
NL_SET_ERR_MSG(extack, "using device-bound program without HW_MODE flag is not supported");
bpf_prog_put(prog);
return -EINVAL;
......
......@@ -17,8 +17,8 @@ SYNOPSIS
*COMMANDS* :=
{ **show** | **list** | **tree** | **attach** | **detach** | **help** }
MAP COMMANDS
=============
CGROUP COMMANDS
===============
| **bpftool** **cgroup { show | list }** *CGROUP*
| **bpftool** **cgroup tree** [*CGROUP_ROOT*]
......
......@@ -16,8 +16,8 @@ SYNOPSIS
*COMMANDS* := { **probe** | **help** }
MAP COMMANDS
=============
FEATURE COMMANDS
================
| **bpftool** **feature probe** [*COMPONENT*] [**macros** [**prefix** *PREFIX*]]
| **bpftool** **feature help**
......
......@@ -18,7 +18,7 @@ SYNOPSIS
{ **show** | **list** | **dump xlated** | **dump jited** | **pin** | **load**
| **loadall** | **help** }
MAP COMMANDS
PROG COMMANDS
=============
| **bpftool** **prog { show | list }** [*PROG*]
......
This diff is collapsed.
......@@ -55,33 +55,44 @@ struct btf_ext_header {
__u32 line_info_len;
};
typedef int (*btf_print_fn_t)(const char *, ...)
__attribute__((format(printf, 1, 2)));
LIBBPF_API void btf__free(struct btf *btf);
LIBBPF_API struct btf *btf__new(__u8 *data, __u32 size, btf_print_fn_t err_log);
LIBBPF_API struct btf *btf__new(__u8 *data, __u32 size);
LIBBPF_API __s32 btf__find_by_name(const struct btf *btf,
const char *type_name);
LIBBPF_API __u32 btf__get_nr_types(const struct btf *btf);
LIBBPF_API const struct btf_type *btf__type_by_id(const struct btf *btf,
__u32 id);
LIBBPF_API __s64 btf__resolve_size(const struct btf *btf, __u32 type_id);
LIBBPF_API int btf__resolve_type(const struct btf *btf, __u32 type_id);
LIBBPF_API int btf__fd(const struct btf *btf);
LIBBPF_API void btf__get_strings(const struct btf *btf, const char **strings,
__u32 *str_len);
LIBBPF_API const char *btf__name_by_offset(const struct btf *btf, __u32 offset);
LIBBPF_API int btf__get_from_id(__u32 id, struct btf **btf);
LIBBPF_API int btf__get_map_kv_tids(const struct btf *btf, const char *map_name,
__u32 expected_key_size,
__u32 expected_value_size,
__u32 *key_type_id, __u32 *value_type_id);
LIBBPF_API struct btf_ext *btf_ext__new(__u8 *data, __u32 size);
LIBBPF_API void btf_ext__free(struct btf_ext *btf_ext);
LIBBPF_API int btf_ext__reloc_func_info(const struct btf *btf,
const struct btf_ext *btf_ext,
const char *sec_name, __u32 insns_cnt,
void **func_info, __u32 *cnt);
LIBBPF_API int btf_ext__reloc_line_info(const struct btf *btf,
const struct btf_ext *btf_ext,
const char *sec_name, __u32 insns_cnt,
void **line_info, __u32 *cnt);
LIBBPF_API __u32 btf_ext__func_info_rec_size(const struct btf_ext *btf_ext);
LIBBPF_API __u32 btf_ext__line_info_rec_size(const struct btf_ext *btf_ext);
struct btf_dedup_opts {
bool dont_resolve_fwds;
};
struct btf_ext *btf_ext__new(__u8 *data, __u32 size, btf_print_fn_t err_log);
void btf_ext__free(struct btf_ext *btf_ext);
int btf_ext__reloc_func_info(const struct btf *btf,
const struct btf_ext *btf_ext,
const char *sec_name, __u32 insns_cnt,
void **func_info, __u32 *func_info_len);
int btf_ext__reloc_line_info(const struct btf *btf,
const struct btf_ext *btf_ext,
const char *sec_name, __u32 insns_cnt,
void **line_info, __u32 *cnt);
__u32 btf_ext__func_info_rec_size(const struct btf_ext *btf_ext);
__u32 btf_ext__line_info_rec_size(const struct btf_ext *btf_ext);
LIBBPF_API int btf__dedup(struct btf *btf, struct btf_ext *btf_ext,
const struct btf_dedup_opts *opts);
#ifdef __cplusplus
} /* extern "C" */
......
......@@ -42,6 +42,7 @@
#include "bpf.h"
#include "btf.h"
#include "str_error.h"
#include "libbpf_util.h"
#ifndef EM_BPF
#define EM_BPF 247
......@@ -53,39 +54,33 @@
#define __printf(a, b) __attribute__((format(printf, a, b)))
__printf(1, 2)
static int __base_pr(const char *format, ...)
static int __base_pr(enum libbpf_print_level level, const char *format,
va_list args)
{
va_list args;
int err;
if (level == LIBBPF_DEBUG)
return 0;
va_start(args, format);
err = vfprintf(stderr, format, args);
va_end(args);
return err;
return vfprintf(stderr, format, args);
}
static __printf(1, 2) libbpf_print_fn_t __pr_warning = __base_pr;
static __printf(1, 2) libbpf_print_fn_t __pr_info = __base_pr;
static __printf(1, 2) libbpf_print_fn_t __pr_debug;
#define __pr(func, fmt, ...) \
do { \
if ((func)) \
(func)("libbpf: " fmt, ##__VA_ARGS__); \
} while (0)
static libbpf_print_fn_t __libbpf_pr = __base_pr;
#define pr_warning(fmt, ...) __pr(__pr_warning, fmt, ##__VA_ARGS__)
#define pr_info(fmt, ...) __pr(__pr_info, fmt, ##__VA_ARGS__)
#define pr_debug(fmt, ...) __pr(__pr_debug, fmt, ##__VA_ARGS__)
void libbpf_set_print(libbpf_print_fn_t fn)
{
__libbpf_pr = fn;
}
void libbpf_set_print(libbpf_print_fn_t warn,
libbpf_print_fn_t info,
libbpf_print_fn_t debug)
__printf(2, 3)
void libbpf_print(enum libbpf_print_level level, const char *format, ...)
{
__pr_warning = warn;
__pr_info = info;
__pr_debug = debug;
va_list args;
if (!__libbpf_pr)
return;
va_start(args, format);
__libbpf_pr(level, format, args);
va_end(args);
}
#define STRERR_BUFSIZE 128
......@@ -839,8 +834,7 @@ static int bpf_object__elf_collect(struct bpf_object *obj, int flags)
else if (strcmp(name, "maps") == 0)
obj->efile.maps_shndx = idx;
else if (strcmp(name, BTF_ELF_SEC) == 0) {
obj->btf = btf__new(data->d_buf, data->d_size,
__pr_debug);
obj->btf = btf__new(data->d_buf, data->d_size);
if (IS_ERR(obj->btf)) {
pr_warning("Error loading ELF section %s: %ld. Ignored and continue.\n",
BTF_ELF_SEC, PTR_ERR(obj->btf));
......@@ -915,8 +909,7 @@ static int bpf_object__elf_collect(struct bpf_object *obj, int flags)
BTF_EXT_ELF_SEC, BTF_ELF_SEC);
} else {
obj->btf_ext = btf_ext__new(btf_ext_data->d_buf,
btf_ext_data->d_size,
__pr_debug);
btf_ext_data->d_size);
if (IS_ERR(obj->btf_ext)) {
pr_warning("Error loading ELF section %s: %ld. Ignored and continue.\n",
BTF_EXT_ELF_SEC,
......@@ -1057,72 +1050,18 @@ bpf_program__collect_reloc(struct bpf_program *prog, GElf_Shdr *shdr,
static int bpf_map_find_btf_info(struct bpf_map *map, const struct btf *btf)
{
const struct btf_type *container_type;
const struct btf_member *key, *value;
struct bpf_map_def *def = &map->def;
const size_t max_name = 256;
char container_name[max_name];
__s64 key_size, value_size;
__s32 container_id;
if (snprintf(container_name, max_name, "____btf_map_%s", map->name) ==
max_name) {
pr_warning("map:%s length of '____btf_map_%s' is too long\n",
map->name, map->name);
return -EINVAL;
}
container_id = btf__find_by_name(btf, container_name);
if (container_id < 0) {
pr_debug("map:%s container_name:%s cannot be found in BTF. Missing BPF_ANNOTATE_KV_PAIR?\n",
map->name, container_name);
return container_id;
}
container_type = btf__type_by_id(btf, container_id);
if (!container_type) {
pr_warning("map:%s cannot find BTF type for container_id:%u\n",
map->name, container_id);
return -EINVAL;
}
if (BTF_INFO_KIND(container_type->info) != BTF_KIND_STRUCT ||
BTF_INFO_VLEN(container_type->info) < 2) {
pr_warning("map:%s container_name:%s is an invalid container struct\n",
map->name, container_name);
return -EINVAL;
}
key = (struct btf_member *)(container_type + 1);
value = key + 1;
key_size = btf__resolve_size(btf, key->type);
if (key_size < 0) {
pr_warning("map:%s invalid BTF key_type_size\n",
map->name);
return key_size;
}
if (def->key_size != key_size) {
pr_warning("map:%s btf_key_type_size:%u != map_def_key_size:%u\n",
map->name, (__u32)key_size, def->key_size);
return -EINVAL;
}
value_size = btf__resolve_size(btf, value->type);
if (value_size < 0) {
pr_warning("map:%s invalid BTF value_type_size\n", map->name);
return value_size;
}
__u32 key_type_id, value_type_id;
int ret;
if (def->value_size != value_size) {
pr_warning("map:%s btf_value_type_size:%u != map_def_value_size:%u\n",
map->name, (__u32)value_size, def->value_size);
return -EINVAL;
}
ret = btf__get_map_kv_tids(btf, map->name, def->key_size,
def->value_size, &key_type_id,
&value_type_id);
if (ret)
return ret;
map->btf_key_type_id = key->type;
map->btf_value_type_id = value->type;
map->btf_key_type_id = key_type_id;
map->btf_value_type_id = value_type_id;
return 0;
}
......
......@@ -47,17 +47,16 @@ enum libbpf_errno {
LIBBPF_API int libbpf_strerror(int err, char *buf, size_t size);
/*
* __printf is defined in include/linux/compiler-gcc.h. However,
* it would be better if libbpf.h didn't depend on Linux header files.
* So instead of __printf, here we use gcc attribute directly.
*/
typedef int (*libbpf_print_fn_t)(const char *, ...)
__attribute__((format(printf, 1, 2)));
enum libbpf_print_level {
LIBBPF_WARN,
LIBBPF_INFO,
LIBBPF_DEBUG,
};
typedef int (*libbpf_print_fn_t)(enum libbpf_print_level level,
const char *, va_list ap);
LIBBPF_API void libbpf_set_print(libbpf_print_fn_t warn,
libbpf_print_fn_t info,
libbpf_print_fn_t debug);
LIBBPF_API void libbpf_set_print(libbpf_print_fn_t fn);
/* Hide internal to user */
struct bpf_object;
......
......@@ -133,4 +133,14 @@ LIBBPF_0.0.2 {
bpf_map_lookup_elem_flags;
bpf_object__find_map_fd_by_name;
bpf_get_link_xdp_id;
btf__dedup;
btf__get_map_kv_tids;
btf__get_nr_types;
btf__get_strings;
btf_ext__free;
btf_ext__func_info_rec_size;
btf_ext__line_info_rec_size;
btf_ext__new;
btf_ext__reloc_func_info;
btf_ext__reloc_line_info;
} LIBBPF_0.0.1;
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
/* Copyright (c) 2019 Facebook */
#ifndef __LIBBPF_LIBBPF_UTIL_H
#define __LIBBPF_LIBBPF_UTIL_H
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
extern void libbpf_print(enum libbpf_print_level level,
const char *format, ...)
__attribute__((format(printf, 2, 3)));
#define __pr(level, fmt, ...) \
do { \
libbpf_print(level, "libbpf: " fmt, ##__VA_ARGS__); \
} while (0)
#define pr_warning(fmt, ...) __pr(LIBBPF_WARN, fmt, ##__VA_ARGS__)
#define pr_info(fmt, ...) __pr(LIBBPF_INFO, fmt, ##__VA_ARGS__)
#define pr_debug(fmt, ...) __pr(LIBBPF_DEBUG, fmt, ##__VA_ARGS__)
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif
......@@ -8,11 +8,11 @@
int main(int argc, char *argv[])
{
/* libbpf.h */
libbpf_set_print(NULL, NULL, NULL);
libbpf_set_print(NULL);
/* bpf.h */
bpf_prog_get_fd_by_id(0);
/* btf.h */
btf__new(NULL, 0, NULL);
btf__new(NULL, 0);
}
......@@ -24,22 +24,12 @@
#include "llvm-utils.h"
#include "c++/clang-c.h"
#define DEFINE_PRINT_FN(name, level) \
static int libbpf_##name(const char *fmt, ...) \
{ \
va_list args; \
int ret; \
\
va_start(args, fmt); \
ret = veprintf(level, verbose, pr_fmt(fmt), args);\
va_end(args); \
return ret; \
static int libbpf_perf_print(enum libbpf_print_level level __attribute__((unused)),
const char *fmt, va_list args)
{
return veprintf(1, verbose, pr_fmt(fmt), args);
}
DEFINE_PRINT_FN(warning, 1)
DEFINE_PRINT_FN(info, 1)
DEFINE_PRINT_FN(debug, 1)
struct bpf_prog_priv {
bool is_tp;
char *sys_name;
......@@ -59,9 +49,7 @@ bpf__prepare_load_buffer(void *obj_buf, size_t obj_buf_sz, const char *name)
struct bpf_object *obj;
if (!libbpf_initialized) {
libbpf_set_print(libbpf_warning,
libbpf_info,
libbpf_debug);
libbpf_set_print(libbpf_perf_print);
libbpf_initialized = true;
}
......@@ -79,9 +67,7 @@ struct bpf_object *bpf__prepare_load(const char *filename, bool source)
struct bpf_object *obj;
if (!libbpf_initialized) {
libbpf_set_print(libbpf_warning,
libbpf_info,
libbpf_debug);
libbpf_set_print(libbpf_perf_print);
libbpf_initialized = true;
}
......
......@@ -30,12 +30,11 @@ def send(sock, s):
serverPort = int(sys.argv[1])
HostName = socket.gethostname()
# create active socket
sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
try:
sock.connect((HostName, serverPort))
sock.connect(('localhost', serverPort))
except socket.error as e:
sys.exit(1)
......
......@@ -35,13 +35,10 @@ MAX_PORTS = 2
serverPort = SERVER_PORT
serverSocket = None
HostName = socket.gethostname()
# create passive socket
serverSocket = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
host = socket.gethostname()
try: serverSocket.bind((host, 0))
try: serverSocket.bind(('localhost', 0))
except socket.error as msg:
print('bind fails: ' + str(msg))
......
This diff is collapsed.
......@@ -34,23 +34,16 @@ static void usage(char *argv[])
printf("\n");
}
#define DEFINE_PRINT_FN(name, enabled) \
static int libbpf_##name(const char *fmt, ...) \
{ \
va_list args; \
int ret; \
\
va_start(args, fmt); \
if (enabled) { \
fprintf(stderr, "[" #name "] "); \
ret = vfprintf(stderr, fmt, args); \
} \
va_end(args); \
return ret; \
static bool debug = 0;
static int libbpf_debug_print(enum libbpf_print_level level,
const char *fmt, va_list args)
{
if (level == LIBBPF_DEBUG && !debug)
return 0;
fprintf(stderr, "[%d] ", level);
return vfprintf(stderr, fmt, args);
}
DEFINE_PRINT_FN(warning, 1)
DEFINE_PRINT_FN(info, 1)
DEFINE_PRINT_FN(debug, 1)
#define EXIT_FAIL_LIBBPF EXIT_FAILURE
#define EXIT_FAIL_OPTION 2
......@@ -120,15 +113,14 @@ int main(int argc, char **argv)
int longindex = 0;
int opt;
libbpf_set_print(libbpf_warning, libbpf_info, NULL);
libbpf_set_print(libbpf_debug_print);
/* Parse commands line args */
while ((opt = getopt_long(argc, argv, "hDq",
long_options, &longindex)) != -1) {
switch (opt) {
case 'D':
libbpf_set_print(libbpf_warning, libbpf_info,
libbpf_debug);
debug = 1;
break;
case 'q': /* Use in scripting mode */
verbose = 0;
......
......@@ -45,7 +45,7 @@ static int map_flags;
} \
})
static void test_hashmap(int task, void *data)
static void test_hashmap(unsigned int task, void *data)
{
long long key, next_key, first_key, value;
int fd;
......@@ -135,7 +135,7 @@ static void test_hashmap(int task, void *data)
close(fd);
}
static void test_hashmap_sizes(int task, void *data)
static void test_hashmap_sizes(unsigned int task, void *data)
{
int fd, i, j;
......@@ -155,7 +155,7 @@ static void test_hashmap_sizes(int task, void *data)
}
}
static void test_hashmap_percpu(int task, void *data)
static void test_hashmap_percpu(unsigned int task, void *data)
{
unsigned int nr_cpus = bpf_num_possible_cpus();
BPF_DECLARE_PERCPU(long, value);
......@@ -282,7 +282,7 @@ static int helper_fill_hashmap(int max_entries)
return fd;
}
static void test_hashmap_walk(int task, void *data)
static void test_hashmap_walk(unsigned int task, void *data)
{
int fd, i, max_entries = 1000;
long long key, value, next_key;
......@@ -353,7 +353,7 @@ static void test_hashmap_zero_seed(void)
close(second);
}
static void test_arraymap(int task, void *data)
static void test_arraymap(unsigned int task, void *data)
{
int key, next_key, fd;
long long value;
......@@ -408,7 +408,7 @@ static void test_arraymap(int task, void *data)
close(fd);
}
static void test_arraymap_percpu(int task, void *data)
static void test_arraymap_percpu(unsigned int task, void *data)
{
unsigned int nr_cpus = bpf_num_possible_cpus();
BPF_DECLARE_PERCPU(long, values);
......@@ -504,7 +504,7 @@ static void test_arraymap_percpu_many_keys(void)
close(fd);
}
static void test_devmap(int task, void *data)
static void test_devmap(unsigned int task, void *data)
{
int fd;
__u32 key, value;
......@@ -519,7 +519,7 @@ static void test_devmap(int task, void *data)
close(fd);
}
static void test_queuemap(int task, void *data)
static void test_queuemap(unsigned int task, void *data)
{
const int MAP_SIZE = 32;
__u32 vals[MAP_SIZE + MAP_SIZE/2], val;
......@@ -577,7 +577,7 @@ static void test_queuemap(int task, void *data)
close(fd);
}
static void test_stackmap(int task, void *data)
static void test_stackmap(unsigned int task, void *data)
{
const int MAP_SIZE = 32;
__u32 vals[MAP_SIZE + MAP_SIZE/2], val;
......@@ -642,7 +642,7 @@ static void test_stackmap(int task, void *data)
#define SOCKMAP_PARSE_PROG "./sockmap_parse_prog.o"
#define SOCKMAP_VERDICT_PROG "./sockmap_verdict_prog.o"
#define SOCKMAP_TCP_MSG_PROG "./sockmap_tcp_msg_prog.o"
static void test_sockmap(int tasks, void *data)
static void test_sockmap(unsigned int tasks, void *data)
{
struct bpf_map *bpf_map_rx, *bpf_map_tx, *bpf_map_msg, *bpf_map_break;
int map_fd_msg = 0, map_fd_rx = 0, map_fd_tx = 0, map_fd_break;
......@@ -1268,10 +1268,11 @@ static void test_map_large(void)
}
#define run_parallel(N, FN, DATA) \
printf("Fork %d tasks to '" #FN "'\n", N); \
printf("Fork %u tasks to '" #FN "'\n", N); \
__run_parallel(N, FN, DATA)
static void __run_parallel(int tasks, void (*fn)(int task, void *data),
static void __run_parallel(unsigned int tasks,
void (*fn)(unsigned int task, void *data),
void *data)
{
pid_t pid[tasks];
......@@ -1312,7 +1313,7 @@ static void test_map_stress(void)
#define DO_UPDATE 1
#define DO_DELETE 0
static void test_update_delete(int fn, void *data)
static void test_update_delete(unsigned int fn, void *data)
{
int do_update = ((int *)data)[1];
int fd = ((int *)data)[0];
......
......@@ -23,6 +23,7 @@ import string
import struct
import subprocess
import time
import traceback
logfile = None
log_level = 1
......@@ -78,7 +79,9 @@ def fail(cond, msg):
if not cond:
return
print("FAIL: " + msg)
log("FAIL: " + msg, "", level=1)
tb = "".join(traceback.extract_stack().format())
print(tb)
log("FAIL: " + msg, tb, level=1)
os.sys.exit(1)
def start_test(msg):
......@@ -589,6 +592,15 @@ def check_verifier_log(output, reference):
return
fail(True, "Missing or incorrect message from netdevsim in verifier log")
def check_multi_basic(two_xdps):
fail(two_xdps["mode"] != 4, "Bad mode reported with multiple programs")
fail("prog" in two_xdps, "Base program reported in multi program mode")
fail(len(two_xdps["attached"]) != 2,
"Wrong attached program count with two programs")
fail(two_xdps["attached"][0]["prog"]["id"] ==
two_xdps["attached"][1]["prog"]["id"],
"Offloaded and other programs have the same id")
def test_spurios_extack(sim, obj, skip_hw, needle):
res = sim.cls_bpf_add_filter(obj, prio=1, handle=1, skip_hw=skip_hw,
include_stderr=True)
......@@ -600,6 +612,67 @@ def test_spurios_extack(sim, obj, skip_hw, needle):
include_stderr=True)
check_no_extack(res, needle)
def test_multi_prog(sim, obj, modename, modeid):
start_test("Test multi-attachment XDP - %s + offload..." %
(modename or "default", ))
sim.set_xdp(obj, "offload")
xdp = sim.ip_link_show(xdp=True)["xdp"]
offloaded = sim.dfs_read("bpf_offloaded_id")
fail("prog" not in xdp, "Base program not reported in single program mode")
fail(len(xdp["attached"]) != 1,
"Wrong attached program count with one program")
sim.set_xdp(obj, modename)
two_xdps = sim.ip_link_show(xdp=True)["xdp"]
fail(xdp["attached"][0] not in two_xdps["attached"],
"Offload program not reported after other activated")
check_multi_basic(two_xdps)
offloaded2 = sim.dfs_read("bpf_offloaded_id")
fail(offloaded != offloaded2,
"Offload ID changed after loading other program")
start_test("Test multi-attachment XDP - replace...")
ret, _, err = sim.set_xdp(obj, "offload", fail=False, include_stderr=True)
fail(ret == 0, "Replaced one of programs without -force")
check_extack(err, "XDP program already attached.", args)
if modename == "" or modename == "drv":
othermode = "" if modename == "drv" else "drv"
start_test("Test multi-attachment XDP - detach...")
ret, _, err = sim.unset_xdp(othermode, force=True,
fail=False, include_stderr=True)
fail(ret == 0, "Removed program with a bad mode")
check_extack(err, "program loaded with different flags.", args)
sim.unset_xdp("offload")
xdp = sim.ip_link_show(xdp=True)["xdp"]
offloaded = sim.dfs_read("bpf_offloaded_id")
fail(xdp["mode"] != modeid, "Bad mode reported after multiple programs")
fail("prog" not in xdp,
"Base program not reported after multi program mode")
fail(xdp["attached"][0] not in two_xdps["attached"],
"Offload program not reported after other activated")
fail(len(xdp["attached"]) != 1,
"Wrong attached program count with remaining programs")
fail(offloaded != "0", "Offload ID reported with only other program left")
start_test("Test multi-attachment XDP - reattach...")
sim.set_xdp(obj, "offload")
two_xdps = sim.ip_link_show(xdp=True)["xdp"]
fail(xdp["attached"][0] not in two_xdps["attached"],
"Other program not reported after offload activated")
check_multi_basic(two_xdps)
start_test("Test multi-attachment XDP - device remove...")
sim.remove()
sim = NetdevSim()
sim.set_ethtool_tc_offloads(True)
return sim
# Parse command line
parser = argparse.ArgumentParser()
......@@ -842,7 +915,9 @@ try:
ret, _, err = sim.set_xdp(obj, "generic", force=True,
fail=False, include_stderr=True)
fail(ret == 0, "Replaced XDP program with a program in different mode")
fail(err.count("File exists") != 1, "Replaced driver XDP with generic")
check_extack(err,
"native and generic XDP can't be active at the same time.",
args)
ret, _, err = sim.set_xdp(obj, "", force=True,
fail=False, include_stderr=True)
fail(ret == 0, "Replaced XDP program with a program in different mode")
......@@ -931,59 +1006,9 @@ try:
rm(pin_file)
bpftool_prog_list_wait(expected=0)
start_test("Test multi-attachment XDP - attach...")
sim.set_xdp(obj, "offload")
xdp = sim.ip_link_show(xdp=True)["xdp"]
offloaded = sim.dfs_read("bpf_offloaded_id")
fail("prog" not in xdp, "Base program not reported in single program mode")
fail(len(ipl["xdp"]["attached"]) != 1,
"Wrong attached program count with one program")
sim.set_xdp(obj, "")
two_xdps = sim.ip_link_show(xdp=True)["xdp"]
offloaded2 = sim.dfs_read("bpf_offloaded_id")
fail(two_xdps["mode"] != 4, "Bad mode reported with multiple programs")
fail("prog" in two_xdps, "Base program reported in multi program mode")
fail(xdp["attached"][0] not in two_xdps["attached"],
"Offload program not reported after driver activated")
fail(len(two_xdps["attached"]) != 2,
"Wrong attached program count with two programs")
fail(two_xdps["attached"][0]["prog"]["id"] ==
two_xdps["attached"][1]["prog"]["id"],
"offloaded and drv programs have the same id")
fail(offloaded != offloaded2,
"offload ID changed after loading driver program")
start_test("Test multi-attachment XDP - replace...")
ret, _, err = sim.set_xdp(obj, "offload", fail=False, include_stderr=True)
fail(err.count("busy") != 1, "Replaced one of programs without -force")
start_test("Test multi-attachment XDP - detach...")
ret, _, err = sim.unset_xdp("drv", force=True,
fail=False, include_stderr=True)
fail(ret == 0, "Removed program with a bad mode")
check_extack(err, "program loaded with different flags.", args)
sim.unset_xdp("offload")
xdp = sim.ip_link_show(xdp=True)["xdp"]
offloaded = sim.dfs_read("bpf_offloaded_id")
fail(xdp["mode"] != 1, "Bad mode reported after multiple programs")
fail("prog" not in xdp,
"Base program not reported after multi program mode")
fail(xdp["attached"][0] not in two_xdps["attached"],
"Offload program not reported after driver activated")
fail(len(ipl["xdp"]["attached"]) != 1,
"Wrong attached program count with remaining programs")
fail(offloaded != "0", "offload ID reported with only driver program left")
start_test("Test multi-attachment XDP - device remove...")
sim.set_xdp(obj, "offload")
sim.remove()
sim = NetdevSim()
sim.set_ethtool_tc_offloads(True)
sim = test_multi_prog(sim, obj, "", 1)
sim = test_multi_prog(sim, obj, "drv", 1)
sim = test_multi_prog(sim, obj, "generic", 2)
start_test("Test mixing of TC and XDP...")
sim.tc_add_ingress()
......
......@@ -10,6 +10,7 @@
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include <stdarg.h>
#include <time.h>
#include <linux/types.h>
......@@ -1783,6 +1784,15 @@ static void test_task_fd_query_tp(void)
"sys_enter_read");
}
static int libbpf_debug_print(enum libbpf_print_level level,
const char *format, va_list args)
{
if (level == LIBBPF_DEBUG)
return 0;
return vfprintf(stderr, format, args);
}
static void test_reference_tracking()
{
const char *file = "./test_sk_lookup_kern.o";
......@@ -1809,9 +1819,9 @@ static void test_reference_tracking()
/* Expect verifier failure if test name has 'fail' */
if (strstr(title, "fail") != NULL) {
libbpf_set_print(NULL, NULL, NULL);
libbpf_set_print(NULL);
err = !bpf_program__load(prog, "GPL", 0);
libbpf_set_print(printf, printf, NULL);
libbpf_set_print(libbpf_debug_print);
} else {
err = bpf_program__load(prog, "GPL", 0);
}
......
......@@ -100,6 +100,7 @@
.errstr = "invalid bpf_context access",
.result = REJECT,
.prog_type = BPF_PROG_TYPE_SK_MSG,
.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
},
{
"invalid read past end of SK_MSG",
......
......@@ -687,6 +687,7 @@
},
.errstr = "invalid bpf_context access",
.result = REJECT,
.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
},
{
"check skb->hash half load not permitted, unaligned 3",
......
......@@ -27,6 +27,7 @@
.data64 = { 1ULL << 63 | 1, }
},
},
.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
},
{
"jset32: BPF_X",
......@@ -58,6 +59,7 @@
.data64 = { 1ULL << 63 | 1, }
},
},
.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
},
{
"jset32: min/max deduction",
......@@ -93,6 +95,7 @@
.data64 = { -1, }
},
},
.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
},
{
"jeq32: BPF_X",
......@@ -119,6 +122,7 @@
.data64 = { 1ULL << 63 | 1, }
},
},
.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
},
{
"jeq32: min/max deduction",
......@@ -154,6 +158,7 @@
.data64 = { -1, }
},
},
.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
},
{
"jne32: BPF_X",
......@@ -180,6 +185,7 @@
.data64 = { 1ULL << 63 | 2, }
},
},
.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
},
{
"jne32: min/max deduction",
......@@ -218,6 +224,7 @@
.data64 = { 0, }
},
},
.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
},
{
"jge32: BPF_X",
......@@ -244,6 +251,7 @@
.data64 = { (UINT_MAX - 1) | 2ULL << 32, }
},
},
.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
},
{
"jge32: min/max deduction",
......@@ -284,6 +292,7 @@
.data64 = { 0, }
},
},
.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
},
{
"jgt32: BPF_X",
......@@ -310,6 +319,7 @@
.data64 = { (UINT_MAX - 1) | 2ULL << 32, }
},
},
.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
},
{
"jgt32: min/max deduction",
......@@ -350,6 +360,7 @@
.data64 = { INT_MAX, }
},
},
.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
},
{
"jle32: BPF_X",
......@@ -376,6 +387,7 @@
.data64 = { UINT_MAX, }
},
},
.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
},
{
"jle32: min/max deduction",
......@@ -416,6 +428,7 @@
.data64 = { INT_MAX - 1, }
},
},
.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
},
{
"jlt32: BPF_X",
......@@ -442,6 +455,7 @@
.data64 = { (INT_MAX - 1) | 3ULL << 32, }
},
},
.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
},
{
"jlt32: min/max deduction",
......@@ -482,6 +496,7 @@
.data64 = { -2, }
},
},
.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
},
{
"jsge32: BPF_X",
......@@ -508,6 +523,7 @@
.data64 = { -2, }
},
},
.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
},
{
"jsge32: min/max deduction",
......@@ -548,6 +564,7 @@
.data64 = { 1, }
},
},
.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
},
{
"jsgt32: BPF_X",
......@@ -574,6 +591,7 @@
.data64 = { 0x7fffffff, }
},
},
.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
},
{
"jsgt32: min/max deduction",
......@@ -614,6 +632,7 @@
.data64 = { 1, }
},
},
.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
},
{
"jsle32: BPF_X",
......@@ -640,6 +659,7 @@
.data64 = { 0x7fffffff | 2ULL << 32, }
},
},
.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
},
{
"jsle32: min/max deduction",
......@@ -680,6 +700,7 @@
.data64 = { 1, }
},
},
.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
},
{
"jslt32: BPF_X",
......@@ -706,6 +727,7 @@
.data64 = { 0x7fffffff | 2ULL << 32, }
},
},
.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
},
{
"jslt32: min/max deduction",
......
......@@ -53,6 +53,7 @@
.data64 = { ~0ULL, }
},
},
.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
},
{
"jset: sign-extend",
......@@ -70,6 +71,7 @@
.result = ACCEPT,
.retval = 2,
.data = { 1, 0, 0, 0, 0, 0, 0, 1, },
.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
},
{
"jset: known const compare",
......
......@@ -46,6 +46,7 @@
.errstr_unpriv = "attempt to corrupt spilled",
.errstr = "R0 invalid mem access 'inv",
.result = REJECT,
.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
},
{
"check corrupted spill/fill, LSB",
......
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