mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-23 20:53:53 +08:00
Daniel Borkmann says: ==================== pull-request: bpf 2021-11-05 We've added 15 non-merge commits during the last 3 day(s) which contain a total of 14 files changed, 199 insertions(+), 90 deletions(-). The main changes are: 1) Fix regression from stack spill/fill of <8 byte scalars, from Martin KaFai Lau. 2) Fix perf's build of bpftool's bootstrap version due to missing libbpf headers, from Quentin Monnet. 3) Fix riscv{32,64} BPF exception tables build errors and warnings, from Björn Töpel. 4) Fix bpf fs to allow RENAME_EXCHANGE support for atomic upgrades on sk_lookup control planes, from Lorenz Bauer. 5) Fix libbpf's error reporting in bpf_map_lookup_and_delete_elem_flags() due to missing libbpf_err_errno(), from Mehrdad Arshad Rad. 6) Various fixes to make xdp_redirect_multi selftest more reliable, from Hangbin Liu. 7) Fix netcnt selftest to make it run serial and thus avoid conflicts with other cgroup/skb selftests run in parallel that could cause flakes, from Andrii Nakryiko. 8) Fix reuseport_bpf_numa networking selftest to skip unavailable NUMA nodes, from Kleber Sacilotto de Souza. * https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf: riscv, bpf: Fix RV32 broken build, and silence RV64 warning selftests/bpf/xdp_redirect_multi: Limit the tests in netns selftests/bpf/xdp_redirect_multi: Give tcpdump a chance to terminate cleanly selftests/bpf/xdp_redirect_multi: Use arping to accurate the arp number selftests/bpf/xdp_redirect_multi: Put the logs to tmp folder libbpf: Fix lookup_and_delete_elem_flags error reporting bpftool: Install libbpf headers for the bootstrap version, too selftests/net: Fix reuseport_bpf_numa by skipping unavailable nodes selftests/bpf: Verifier test on refill from a smaller spill bpf: Do not reject when the stack read size is different from the tracked scalar size selftests/bpf: Make netcnt selftests serial to avoid spurious failures selftests/bpf: Test RENAME_EXCHANGE and RENAME_NOREPLACE on bpffs selftests/bpf: Convert test_bpffs to ASSERT macros libfs: Support RENAME_EXCHANGE in simple_rename() libfs: Move shmem_exchange to simple_rename_exchange ==================== Link: https://lore.kernel.org/r/20211105165803.29372-1-daniel@iogearbox.net Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
9bea6aa498
@ -11,7 +11,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#ifdef CONFIG_BPF_JIT
|
||||
#if defined(CONFIG_BPF_JIT) && defined(CONFIG_ARCH_RV64I)
|
||||
int rv_bpf_fixup_exception(const struct exception_table_entry *ex, struct pt_regs *regs);
|
||||
#endif
|
||||
|
||||
@ -23,7 +23,7 @@ int fixup_exception(struct pt_regs *regs)
|
||||
if (!fixup)
|
||||
return 0;
|
||||
|
||||
#ifdef CONFIG_BPF_JIT
|
||||
#if defined(CONFIG_BPF_JIT) && defined(CONFIG_ARCH_RV64I)
|
||||
if (regs->epc >= BPF_JIT_REGION_START && regs->epc < BPF_JIT_REGION_END)
|
||||
return rv_bpf_fixup_exception(fixup, regs);
|
||||
#endif
|
||||
|
@ -459,6 +459,8 @@ static int emit_call(bool fixed, u64 addr, struct rv_jit_context *ctx)
|
||||
#define BPF_FIXUP_OFFSET_MASK GENMASK(26, 0)
|
||||
#define BPF_FIXUP_REG_MASK GENMASK(31, 27)
|
||||
|
||||
int rv_bpf_fixup_exception(const struct exception_table_entry *ex,
|
||||
struct pt_regs *regs);
|
||||
int rv_bpf_fixup_exception(const struct exception_table_entry *ex,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
|
29
fs/libfs.c
29
fs/libfs.c
@ -448,6 +448,30 @@ int simple_rmdir(struct inode *dir, struct dentry *dentry)
|
||||
}
|
||||
EXPORT_SYMBOL(simple_rmdir);
|
||||
|
||||
int simple_rename_exchange(struct inode *old_dir, struct dentry *old_dentry,
|
||||
struct inode *new_dir, struct dentry *new_dentry)
|
||||
{
|
||||
bool old_is_dir = d_is_dir(old_dentry);
|
||||
bool new_is_dir = d_is_dir(new_dentry);
|
||||
|
||||
if (old_dir != new_dir && old_is_dir != new_is_dir) {
|
||||
if (old_is_dir) {
|
||||
drop_nlink(old_dir);
|
||||
inc_nlink(new_dir);
|
||||
} else {
|
||||
drop_nlink(new_dir);
|
||||
inc_nlink(old_dir);
|
||||
}
|
||||
}
|
||||
old_dir->i_ctime = old_dir->i_mtime =
|
||||
new_dir->i_ctime = new_dir->i_mtime =
|
||||
d_inode(old_dentry)->i_ctime =
|
||||
d_inode(new_dentry)->i_ctime = current_time(old_dir);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(simple_rename_exchange);
|
||||
|
||||
int simple_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
|
||||
struct dentry *old_dentry, struct inode *new_dir,
|
||||
struct dentry *new_dentry, unsigned int flags)
|
||||
@ -455,9 +479,12 @@ int simple_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
|
||||
struct inode *inode = d_inode(old_dentry);
|
||||
int they_are_dirs = d_is_dir(old_dentry);
|
||||
|
||||
if (flags & ~RENAME_NOREPLACE)
|
||||
if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE))
|
||||
return -EINVAL;
|
||||
|
||||
if (flags & RENAME_EXCHANGE)
|
||||
return simple_rename_exchange(old_dir, old_dentry, new_dir, new_dentry);
|
||||
|
||||
if (!simple_empty(new_dentry))
|
||||
return -ENOTEMPTY;
|
||||
|
||||
|
@ -3383,6 +3383,8 @@ extern int simple_open(struct inode *inode, struct file *file);
|
||||
extern int simple_link(struct dentry *, struct inode *, struct dentry *);
|
||||
extern int simple_unlink(struct inode *, struct dentry *);
|
||||
extern int simple_rmdir(struct inode *, struct dentry *);
|
||||
extern int simple_rename_exchange(struct inode *old_dir, struct dentry *old_dentry,
|
||||
struct inode *new_dir, struct dentry *new_dentry);
|
||||
extern int simple_rename(struct user_namespace *, struct inode *,
|
||||
struct dentry *, struct inode *, struct dentry *,
|
||||
unsigned int);
|
||||
|
@ -3088,9 +3088,12 @@ static int check_stack_read_fixed_off(struct bpf_verifier_env *env,
|
||||
reg = ®_state->stack[spi].spilled_ptr;
|
||||
|
||||
if (is_spilled_reg(®_state->stack[spi])) {
|
||||
if (size != BPF_REG_SIZE) {
|
||||
u8 scalar_size = 0;
|
||||
u8 spill_size = 1;
|
||||
|
||||
for (i = BPF_REG_SIZE - 1; i > 0 && stype[i - 1] == STACK_SPILL; i--)
|
||||
spill_size++;
|
||||
|
||||
if (size != BPF_REG_SIZE || spill_size != BPF_REG_SIZE) {
|
||||
if (reg->type != SCALAR_VALUE) {
|
||||
verbose_linfo(env, env->insn_idx, "; ");
|
||||
verbose(env, "invalid size of register fill\n");
|
||||
@ -3101,10 +3104,7 @@ static int check_stack_read_fixed_off(struct bpf_verifier_env *env,
|
||||
if (dst_regno < 0)
|
||||
return 0;
|
||||
|
||||
for (i = BPF_REG_SIZE; i > 0 && stype[i - 1] == STACK_SPILL; i--)
|
||||
scalar_size++;
|
||||
|
||||
if (!(off % BPF_REG_SIZE) && size == scalar_size) {
|
||||
if (!(off % BPF_REG_SIZE) && size == spill_size) {
|
||||
/* The earlier check_reg_arg() has decided the
|
||||
* subreg_def for this insn. Save it first.
|
||||
*/
|
||||
@ -3128,12 +3128,6 @@ static int check_stack_read_fixed_off(struct bpf_verifier_env *env,
|
||||
state->regs[dst_regno].live |= REG_LIVE_WRITTEN;
|
||||
return 0;
|
||||
}
|
||||
for (i = 1; i < BPF_REG_SIZE; i++) {
|
||||
if (stype[(slot - i) % BPF_REG_SIZE] != STACK_SPILL) {
|
||||
verbose(env, "corrupted spill memory\n");
|
||||
return -EACCES;
|
||||
}
|
||||
}
|
||||
|
||||
if (dst_regno >= 0) {
|
||||
/* restore register state from stack */
|
||||
|
24
mm/shmem.c
24
mm/shmem.c
@ -2947,28 +2947,6 @@ static int shmem_rmdir(struct inode *dir, struct dentry *dentry)
|
||||
return shmem_unlink(dir, dentry);
|
||||
}
|
||||
|
||||
static int shmem_exchange(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry)
|
||||
{
|
||||
bool old_is_dir = d_is_dir(old_dentry);
|
||||
bool new_is_dir = d_is_dir(new_dentry);
|
||||
|
||||
if (old_dir != new_dir && old_is_dir != new_is_dir) {
|
||||
if (old_is_dir) {
|
||||
drop_nlink(old_dir);
|
||||
inc_nlink(new_dir);
|
||||
} else {
|
||||
drop_nlink(new_dir);
|
||||
inc_nlink(old_dir);
|
||||
}
|
||||
}
|
||||
old_dir->i_ctime = old_dir->i_mtime =
|
||||
new_dir->i_ctime = new_dir->i_mtime =
|
||||
d_inode(old_dentry)->i_ctime =
|
||||
d_inode(new_dentry)->i_ctime = current_time(old_dir);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int shmem_whiteout(struct user_namespace *mnt_userns,
|
||||
struct inode *old_dir, struct dentry *old_dentry)
|
||||
{
|
||||
@ -3014,7 +2992,7 @@ static int shmem_rename2(struct user_namespace *mnt_userns,
|
||||
return -EINVAL;
|
||||
|
||||
if (flags & RENAME_EXCHANGE)
|
||||
return shmem_exchange(old_dir, old_dentry, new_dir, new_dentry);
|
||||
return simple_rename_exchange(old_dir, old_dentry, new_dir, new_dentry);
|
||||
|
||||
if (!simple_empty(new_dentry))
|
||||
return -ENOTEMPTY;
|
||||
|
@ -22,24 +22,29 @@ else
|
||||
_OUTPUT := $(CURDIR)
|
||||
endif
|
||||
BOOTSTRAP_OUTPUT := $(_OUTPUT)/bootstrap/
|
||||
|
||||
LIBBPF_OUTPUT := $(_OUTPUT)/libbpf/
|
||||
LIBBPF_DESTDIR := $(LIBBPF_OUTPUT)
|
||||
LIBBPF_INCLUDE := $(LIBBPF_DESTDIR)/include
|
||||
LIBBPF_HDRS_DIR := $(LIBBPF_INCLUDE)/bpf
|
||||
LIBBPF := $(LIBBPF_OUTPUT)libbpf.a
|
||||
|
||||
LIBBPF = $(LIBBPF_OUTPUT)libbpf.a
|
||||
LIBBPF_BOOTSTRAP_OUTPUT = $(BOOTSTRAP_OUTPUT)libbpf/
|
||||
LIBBPF_BOOTSTRAP = $(LIBBPF_BOOTSTRAP_OUTPUT)libbpf.a
|
||||
LIBBPF_BOOTSTRAP_OUTPUT := $(BOOTSTRAP_OUTPUT)libbpf/
|
||||
LIBBPF_BOOTSTRAP_DESTDIR := $(LIBBPF_BOOTSTRAP_OUTPUT)
|
||||
LIBBPF_BOOTSTRAP_INCLUDE := $(LIBBPF_BOOTSTRAP_DESTDIR)/include
|
||||
LIBBPF_BOOTSTRAP_HDRS_DIR := $(LIBBPF_BOOTSTRAP_INCLUDE)/bpf
|
||||
LIBBPF_BOOTSTRAP := $(LIBBPF_BOOTSTRAP_OUTPUT)libbpf.a
|
||||
|
||||
# We need to copy hashmap.h and nlattr.h which is not otherwise exported by
|
||||
# libbpf, but still required by bpftool.
|
||||
LIBBPF_INTERNAL_HDRS := $(addprefix $(LIBBPF_HDRS_DIR)/,hashmap.h nlattr.h)
|
||||
LIBBPF_BOOTSTRAP_INTERNAL_HDRS := $(addprefix $(LIBBPF_BOOTSTRAP_HDRS_DIR)/,hashmap.h)
|
||||
|
||||
ifeq ($(BPFTOOL_VERSION),)
|
||||
BPFTOOL_VERSION := $(shell make -rR --no-print-directory -sC ../../.. kernelversion)
|
||||
endif
|
||||
|
||||
$(LIBBPF_OUTPUT) $(BOOTSTRAP_OUTPUT) $(LIBBPF_BOOTSTRAP_OUTPUT) $(LIBBPF_HDRS_DIR):
|
||||
$(LIBBPF_OUTPUT) $(BOOTSTRAP_OUTPUT) $(LIBBPF_BOOTSTRAP_OUTPUT) $(LIBBPF_HDRS_DIR) $(LIBBPF_BOOTSTRAP_HDRS_DIR):
|
||||
$(QUIET_MKDIR)mkdir -p $@
|
||||
|
||||
$(LIBBPF): $(wildcard $(BPF_DIR)/*.[ch] $(BPF_DIR)/Makefile) | $(LIBBPF_OUTPUT)
|
||||
@ -52,7 +57,12 @@ $(LIBBPF_INTERNAL_HDRS): $(LIBBPF_HDRS_DIR)/%.h: $(BPF_DIR)/%.h | $(LIBBPF_HDRS_
|
||||
|
||||
$(LIBBPF_BOOTSTRAP): $(wildcard $(BPF_DIR)/*.[ch] $(BPF_DIR)/Makefile) | $(LIBBPF_BOOTSTRAP_OUTPUT)
|
||||
$(Q)$(MAKE) -C $(BPF_DIR) OUTPUT=$(LIBBPF_BOOTSTRAP_OUTPUT) \
|
||||
ARCH= CC=$(HOSTCC) LD=$(HOSTLD) $@
|
||||
DESTDIR=$(LIBBPF_BOOTSTRAP_DESTDIR) prefix= \
|
||||
ARCH= CC=$(HOSTCC) LD=$(HOSTLD) $@ install_headers
|
||||
|
||||
$(LIBBPF_BOOTSTRAP_INTERNAL_HDRS): $(LIBBPF_BOOTSTRAP_HDRS_DIR)/%.h: $(BPF_DIR)/%.h | $(LIBBPF_BOOTSTRAP_HDRS_DIR)
|
||||
$(call QUIET_INSTALL, $@)
|
||||
$(Q)install -m 644 -t $(LIBBPF_BOOTSTRAP_HDRS_DIR) $<
|
||||
|
||||
$(LIBBPF)-clean: FORCE | $(LIBBPF_OUTPUT)
|
||||
$(call QUIET_CLEAN, libbpf)
|
||||
@ -172,11 +182,11 @@ else
|
||||
$(Q)cp "$(VMLINUX_H)" $@
|
||||
endif
|
||||
|
||||
$(OUTPUT)%.bpf.o: skeleton/%.bpf.c $(OUTPUT)vmlinux.h $(LIBBPF)
|
||||
$(OUTPUT)%.bpf.o: skeleton/%.bpf.c $(OUTPUT)vmlinux.h $(LIBBPF_BOOTSTRAP)
|
||||
$(QUIET_CLANG)$(CLANG) \
|
||||
-I$(if $(OUTPUT),$(OUTPUT),.) \
|
||||
-I$(srctree)/tools/include/uapi/ \
|
||||
-I$(LIBBPF_INCLUDE) \
|
||||
-I$(LIBBPF_BOOTSTRAP_INCLUDE) \
|
||||
-g -O2 -Wall -target bpf -c $< -o $@ && $(LLVM_STRIP) -g $@
|
||||
|
||||
$(OUTPUT)%.skel.h: $(OUTPUT)%.bpf.o $(BPFTOOL_BOOTSTRAP)
|
||||
@ -209,8 +219,10 @@ $(BPFTOOL_BOOTSTRAP): $(BOOTSTRAP_OBJS) $(LIBBPF_BOOTSTRAP)
|
||||
$(OUTPUT)bpftool: $(OBJS) $(LIBBPF)
|
||||
$(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
|
||||
|
||||
$(BOOTSTRAP_OUTPUT)%.o: %.c $(LIBBPF_INTERNAL_HDRS) | $(BOOTSTRAP_OUTPUT)
|
||||
$(QUIET_CC)$(HOSTCC) $(CFLAGS) -c -MMD -o $@ $<
|
||||
$(BOOTSTRAP_OUTPUT)%.o: %.c $(LIBBPF_BOOTSTRAP_INTERNAL_HDRS) | $(BOOTSTRAP_OUTPUT)
|
||||
$(QUIET_CC)$(HOSTCC) \
|
||||
$(subst -I$(LIBBPF_INCLUDE),-I$(LIBBPF_BOOTSTRAP_INCLUDE),$(CFLAGS)) \
|
||||
-c -MMD -o $@ $<
|
||||
|
||||
$(OUTPUT)%.o: %.c
|
||||
$(QUIET_CC)$(CC) $(CFLAGS) -c -MMD -o $@ $<
|
||||
@ -257,6 +269,6 @@ doc-uninstall:
|
||||
FORCE:
|
||||
|
||||
.SECONDARY:
|
||||
.PHONY: all FORCE clean install-bin install uninstall
|
||||
.PHONY: all FORCE bootstrap clean install-bin install uninstall
|
||||
.PHONY: doc doc-clean doc-install doc-uninstall
|
||||
.DEFAULT_GOAL := all
|
||||
|
@ -515,6 +515,7 @@ int bpf_map_lookup_and_delete_elem(int fd, const void *key, void *value)
|
||||
int bpf_map_lookup_and_delete_elem_flags(int fd, const void *key, void *value, __u64 flags)
|
||||
{
|
||||
union bpf_attr attr;
|
||||
int ret;
|
||||
|
||||
memset(&attr, 0, sizeof(attr));
|
||||
attr.map_fd = fd;
|
||||
@ -522,7 +523,8 @@ int bpf_map_lookup_and_delete_elem_flags(int fd, const void *key, void *value, _
|
||||
attr.value = ptr_to_u64(value);
|
||||
attr.flags = flags;
|
||||
|
||||
return sys_bpf(BPF_MAP_LOOKUP_AND_DELETE_ELEM, &attr, sizeof(attr));
|
||||
ret = sys_bpf(BPF_MAP_LOOKUP_AND_DELETE_ELEM, &attr, sizeof(attr));
|
||||
return libbpf_err_errno(ret);
|
||||
}
|
||||
|
||||
int bpf_map_delete_elem(int fd, const void *key)
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
#define CG_NAME "/netcnt"
|
||||
|
||||
void test_netcnt(void)
|
||||
void serial_test_netcnt(void)
|
||||
{
|
||||
union percpu_net_cnt *percpu_netcnt = NULL;
|
||||
struct bpf_cgroup_storage_key key;
|
||||
|
@ -1,6 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (c) 2020 Facebook */
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <sched.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/stat.h>
|
||||
@ -29,44 +30,106 @@ static int read_iter(char *file)
|
||||
|
||||
static int fn(void)
|
||||
{
|
||||
int err, duration = 0;
|
||||
struct stat a, b, c;
|
||||
int err, map;
|
||||
|
||||
err = unshare(CLONE_NEWNS);
|
||||
if (CHECK(err, "unshare", "failed: %d\n", errno))
|
||||
if (!ASSERT_OK(err, "unshare"))
|
||||
goto out;
|
||||
|
||||
err = mount("", "/", "", MS_REC | MS_PRIVATE, NULL);
|
||||
if (CHECK(err, "mount /", "failed: %d\n", errno))
|
||||
if (!ASSERT_OK(err, "mount /"))
|
||||
goto out;
|
||||
|
||||
err = umount(TDIR);
|
||||
if (CHECK(err, "umount " TDIR, "failed: %d\n", errno))
|
||||
if (!ASSERT_OK(err, "umount " TDIR))
|
||||
goto out;
|
||||
|
||||
err = mount("none", TDIR, "tmpfs", 0, NULL);
|
||||
if (CHECK(err, "mount", "mount root failed: %d\n", errno))
|
||||
if (!ASSERT_OK(err, "mount tmpfs"))
|
||||
goto out;
|
||||
|
||||
err = mkdir(TDIR "/fs1", 0777);
|
||||
if (CHECK(err, "mkdir "TDIR"/fs1", "failed: %d\n", errno))
|
||||
if (!ASSERT_OK(err, "mkdir " TDIR "/fs1"))
|
||||
goto out;
|
||||
err = mkdir(TDIR "/fs2", 0777);
|
||||
if (CHECK(err, "mkdir "TDIR"/fs2", "failed: %d\n", errno))
|
||||
if (!ASSERT_OK(err, "mkdir " TDIR "/fs2"))
|
||||
goto out;
|
||||
|
||||
err = mount("bpf", TDIR "/fs1", "bpf", 0, NULL);
|
||||
if (CHECK(err, "mount bpffs "TDIR"/fs1", "failed: %d\n", errno))
|
||||
if (!ASSERT_OK(err, "mount bpffs " TDIR "/fs1"))
|
||||
goto out;
|
||||
err = mount("bpf", TDIR "/fs2", "bpf", 0, NULL);
|
||||
if (CHECK(err, "mount bpffs " TDIR "/fs2", "failed: %d\n", errno))
|
||||
if (!ASSERT_OK(err, "mount bpffs " TDIR "/fs2"))
|
||||
goto out;
|
||||
|
||||
err = read_iter(TDIR "/fs1/maps.debug");
|
||||
if (CHECK(err, "reading " TDIR "/fs1/maps.debug", "failed\n"))
|
||||
if (!ASSERT_OK(err, "reading " TDIR "/fs1/maps.debug"))
|
||||
goto out;
|
||||
err = read_iter(TDIR "/fs2/progs.debug");
|
||||
if (CHECK(err, "reading " TDIR "/fs2/progs.debug", "failed\n"))
|
||||
if (!ASSERT_OK(err, "reading " TDIR "/fs2/progs.debug"))
|
||||
goto out;
|
||||
|
||||
err = mkdir(TDIR "/fs1/a", 0777);
|
||||
if (!ASSERT_OK(err, "creating " TDIR "/fs1/a"))
|
||||
goto out;
|
||||
err = mkdir(TDIR "/fs1/a/1", 0777);
|
||||
if (!ASSERT_OK(err, "creating " TDIR "/fs1/a/1"))
|
||||
goto out;
|
||||
err = mkdir(TDIR "/fs1/b", 0777);
|
||||
if (!ASSERT_OK(err, "creating " TDIR "/fs1/b"))
|
||||
goto out;
|
||||
|
||||
map = bpf_create_map(BPF_MAP_TYPE_ARRAY, 4, 4, 1, 0);
|
||||
if (!ASSERT_GT(map, 0, "create_map(ARRAY)"))
|
||||
goto out;
|
||||
err = bpf_obj_pin(map, TDIR "/fs1/c");
|
||||
if (!ASSERT_OK(err, "pin map"))
|
||||
goto out;
|
||||
close(map);
|
||||
|
||||
/* Check that RENAME_EXCHANGE works for directories. */
|
||||
err = stat(TDIR "/fs1/a", &a);
|
||||
if (!ASSERT_OK(err, "stat(" TDIR "/fs1/a)"))
|
||||
goto out;
|
||||
err = renameat2(0, TDIR "/fs1/a", 0, TDIR "/fs1/b", RENAME_EXCHANGE);
|
||||
if (!ASSERT_OK(err, "renameat2(/fs1/a, /fs1/b, RENAME_EXCHANGE)"))
|
||||
goto out;
|
||||
err = stat(TDIR "/fs1/b", &b);
|
||||
if (!ASSERT_OK(err, "stat(" TDIR "/fs1/b)"))
|
||||
goto out;
|
||||
if (!ASSERT_EQ(a.st_ino, b.st_ino, "b should have a's inode"))
|
||||
goto out;
|
||||
err = access(TDIR "/fs1/b/1", F_OK);
|
||||
if (!ASSERT_OK(err, "access(" TDIR "/fs1/b/1)"))
|
||||
goto out;
|
||||
|
||||
/* Check that RENAME_EXCHANGE works for mixed file types. */
|
||||
err = stat(TDIR "/fs1/c", &c);
|
||||
if (!ASSERT_OK(err, "stat(" TDIR "/fs1/map)"))
|
||||
goto out;
|
||||
err = renameat2(0, TDIR "/fs1/c", 0, TDIR "/fs1/b", RENAME_EXCHANGE);
|
||||
if (!ASSERT_OK(err, "renameat2(/fs1/c, /fs1/b, RENAME_EXCHANGE)"))
|
||||
goto out;
|
||||
err = stat(TDIR "/fs1/b", &b);
|
||||
if (!ASSERT_OK(err, "stat(" TDIR "/fs1/b)"))
|
||||
goto out;
|
||||
if (!ASSERT_EQ(c.st_ino, b.st_ino, "b should have c's inode"))
|
||||
goto out;
|
||||
err = access(TDIR "/fs1/c/1", F_OK);
|
||||
if (!ASSERT_OK(err, "access(" TDIR "/fs1/c/1)"))
|
||||
goto out;
|
||||
|
||||
/* Check that RENAME_NOREPLACE works. */
|
||||
err = renameat2(0, TDIR "/fs1/b", 0, TDIR "/fs1/a", RENAME_NOREPLACE);
|
||||
if (!ASSERT_ERR(err, "renameat2(RENAME_NOREPLACE)")) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
err = access(TDIR "/fs1/b", F_OK);
|
||||
if (!ASSERT_OK(err, "access(" TDIR "/fs1/b)"))
|
||||
goto out;
|
||||
|
||||
out:
|
||||
umount(TDIR "/fs1");
|
||||
umount(TDIR "/fs2");
|
||||
|
@ -2,11 +2,11 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
# Test topology:
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# | veth1 veth2 veth3 | ... init net
|
||||
# - - - - - - - - - - - - - - - - - - -
|
||||
# | veth1 veth2 veth3 | ns0
|
||||
# - -| - - - - - - | - - - - - - | - -
|
||||
# --------- --------- ---------
|
||||
# | veth0 | | veth0 | | veth0 | ...
|
||||
# | veth0 | | veth0 | | veth0 |
|
||||
# --------- --------- ---------
|
||||
# ns1 ns2 ns3
|
||||
#
|
||||
@ -31,6 +31,7 @@ IFACES=""
|
||||
DRV_MODE="xdpgeneric xdpdrv xdpegress"
|
||||
PASS=0
|
||||
FAIL=0
|
||||
LOG_DIR=$(mktemp -d)
|
||||
|
||||
test_pass()
|
||||
{
|
||||
@ -50,6 +51,7 @@ clean_up()
|
||||
ip link del veth$i 2> /dev/null
|
||||
ip netns del ns$i 2> /dev/null
|
||||
done
|
||||
ip netns del ns0 2> /dev/null
|
||||
}
|
||||
|
||||
# Kselftest framework requirement - SKIP code is 4.
|
||||
@ -77,10 +79,12 @@ setup_ns()
|
||||
mode="xdpdrv"
|
||||
fi
|
||||
|
||||
ip netns add ns0
|
||||
for i in $(seq $NUM); do
|
||||
ip netns add ns$i
|
||||
ip link add veth$i type veth peer name veth0 netns ns$i
|
||||
ip link set veth$i up
|
||||
ip -n ns$i link add veth0 index 2 type veth \
|
||||
peer name veth$i netns ns0 index $((1 + $i))
|
||||
ip -n ns0 link set veth$i up
|
||||
ip -n ns$i link set veth0 up
|
||||
|
||||
ip -n ns$i addr add 192.0.2.$i/24 dev veth0
|
||||
@ -91,7 +95,7 @@ setup_ns()
|
||||
xdp_dummy.o sec xdp &> /dev/null || \
|
||||
{ test_fail "Unable to load dummy xdp" && exit 1; }
|
||||
IFACES="$IFACES veth$i"
|
||||
veth_mac[$i]=$(ip link show veth$i | awk '/link\/ether/ {print $2}')
|
||||
veth_mac[$i]=$(ip -n ns0 link show veth$i | awk '/link\/ether/ {print $2}')
|
||||
done
|
||||
}
|
||||
|
||||
@ -100,17 +104,17 @@ do_egress_tests()
|
||||
local mode=$1
|
||||
|
||||
# mac test
|
||||
ip netns exec ns2 tcpdump -e -i veth0 -nn -l -e &> mac_ns1-2_${mode}.log &
|
||||
ip netns exec ns3 tcpdump -e -i veth0 -nn -l -e &> mac_ns1-3_${mode}.log &
|
||||
ip netns exec ns2 tcpdump -e -i veth0 -nn -l -e &> ${LOG_DIR}/mac_ns1-2_${mode}.log &
|
||||
ip netns exec ns3 tcpdump -e -i veth0 -nn -l -e &> ${LOG_DIR}/mac_ns1-3_${mode}.log &
|
||||
sleep 0.5
|
||||
ip netns exec ns1 ping 192.0.2.254 -i 0.1 -c 4 &> /dev/null
|
||||
sleep 0.5
|
||||
pkill -9 tcpdump
|
||||
pkill tcpdump
|
||||
|
||||
# mac check
|
||||
grep -q "${veth_mac[2]} > ff:ff:ff:ff:ff:ff" mac_ns1-2_${mode}.log && \
|
||||
grep -q "${veth_mac[2]} > ff:ff:ff:ff:ff:ff" ${LOG_DIR}/mac_ns1-2_${mode}.log && \
|
||||
test_pass "$mode mac ns1-2" || test_fail "$mode mac ns1-2"
|
||||
grep -q "${veth_mac[3]} > ff:ff:ff:ff:ff:ff" mac_ns1-3_${mode}.log && \
|
||||
grep -q "${veth_mac[3]} > ff:ff:ff:ff:ff:ff" ${LOG_DIR}/mac_ns1-3_${mode}.log && \
|
||||
test_pass "$mode mac ns1-3" || test_fail "$mode mac ns1-3"
|
||||
}
|
||||
|
||||
@ -121,46 +125,46 @@ do_ping_tests()
|
||||
# ping6 test: echo request should be redirect back to itself, not others
|
||||
ip netns exec ns1 ip neigh add 2001:db8::2 dev veth0 lladdr 00:00:00:00:00:02
|
||||
|
||||
ip netns exec ns1 tcpdump -i veth0 -nn -l -e &> ns1-1_${mode}.log &
|
||||
ip netns exec ns2 tcpdump -i veth0 -nn -l -e &> ns1-2_${mode}.log &
|
||||
ip netns exec ns3 tcpdump -i veth0 -nn -l -e &> ns1-3_${mode}.log &
|
||||
ip netns exec ns1 tcpdump -i veth0 -nn -l -e &> ${LOG_DIR}/ns1-1_${mode}.log &
|
||||
ip netns exec ns2 tcpdump -i veth0 -nn -l -e &> ${LOG_DIR}/ns1-2_${mode}.log &
|
||||
ip netns exec ns3 tcpdump -i veth0 -nn -l -e &> ${LOG_DIR}/ns1-3_${mode}.log &
|
||||
sleep 0.5
|
||||
# ARP test
|
||||
ip netns exec ns1 ping 192.0.2.254 -i 0.1 -c 4 &> /dev/null
|
||||
ip netns exec ns1 arping -q -c 2 -I veth0 192.0.2.254
|
||||
# IPv4 test
|
||||
ip netns exec ns1 ping 192.0.2.253 -i 0.1 -c 4 &> /dev/null
|
||||
# IPv6 test
|
||||
ip netns exec ns1 ping6 2001:db8::2 -i 0.1 -c 2 &> /dev/null
|
||||
sleep 0.5
|
||||
pkill -9 tcpdump
|
||||
pkill tcpdump
|
||||
|
||||
# All netns should receive the redirect arp requests
|
||||
[ $(grep -c "who-has 192.0.2.254" ns1-1_${mode}.log) -gt 4 ] && \
|
||||
[ $(grep -cF "who-has 192.0.2.254" ${LOG_DIR}/ns1-1_${mode}.log) -eq 4 ] && \
|
||||
test_pass "$mode arp(F_BROADCAST) ns1-1" || \
|
||||
test_fail "$mode arp(F_BROADCAST) ns1-1"
|
||||
[ $(grep -c "who-has 192.0.2.254" ns1-2_${mode}.log) -le 4 ] && \
|
||||
[ $(grep -cF "who-has 192.0.2.254" ${LOG_DIR}/ns1-2_${mode}.log) -eq 2 ] && \
|
||||
test_pass "$mode arp(F_BROADCAST) ns1-2" || \
|
||||
test_fail "$mode arp(F_BROADCAST) ns1-2"
|
||||
[ $(grep -c "who-has 192.0.2.254" ns1-3_${mode}.log) -le 4 ] && \
|
||||
[ $(grep -cF "who-has 192.0.2.254" ${LOG_DIR}/ns1-3_${mode}.log) -eq 2 ] && \
|
||||
test_pass "$mode arp(F_BROADCAST) ns1-3" || \
|
||||
test_fail "$mode arp(F_BROADCAST) ns1-3"
|
||||
|
||||
# ns1 should not receive the redirect echo request, others should
|
||||
[ $(grep -c "ICMP echo request" ns1-1_${mode}.log) -eq 4 ] && \
|
||||
[ $(grep -c "ICMP echo request" ${LOG_DIR}/ns1-1_${mode}.log) -eq 4 ] && \
|
||||
test_pass "$mode IPv4 (F_BROADCAST|F_EXCLUDE_INGRESS) ns1-1" || \
|
||||
test_fail "$mode IPv4 (F_BROADCAST|F_EXCLUDE_INGRESS) ns1-1"
|
||||
[ $(grep -c "ICMP echo request" ns1-2_${mode}.log) -eq 4 ] && \
|
||||
[ $(grep -c "ICMP echo request" ${LOG_DIR}/ns1-2_${mode}.log) -eq 4 ] && \
|
||||
test_pass "$mode IPv4 (F_BROADCAST|F_EXCLUDE_INGRESS) ns1-2" || \
|
||||
test_fail "$mode IPv4 (F_BROADCAST|F_EXCLUDE_INGRESS) ns1-2"
|
||||
[ $(grep -c "ICMP echo request" ns1-3_${mode}.log) -eq 4 ] && \
|
||||
[ $(grep -c "ICMP echo request" ${LOG_DIR}/ns1-3_${mode}.log) -eq 4 ] && \
|
||||
test_pass "$mode IPv4 (F_BROADCAST|F_EXCLUDE_INGRESS) ns1-3" || \
|
||||
test_fail "$mode IPv4 (F_BROADCAST|F_EXCLUDE_INGRESS) ns1-3"
|
||||
|
||||
# ns1 should receive the echo request, ns2 should not
|
||||
[ $(grep -c "ICMP6, echo request" ns1-1_${mode}.log) -eq 4 ] && \
|
||||
[ $(grep -c "ICMP6, echo request" ${LOG_DIR}/ns1-1_${mode}.log) -eq 4 ] && \
|
||||
test_pass "$mode IPv6 (no flags) ns1-1" || \
|
||||
test_fail "$mode IPv6 (no flags) ns1-1"
|
||||
[ $(grep -c "ICMP6, echo request" ns1-2_${mode}.log) -eq 0 ] && \
|
||||
[ $(grep -c "ICMP6, echo request" ${LOG_DIR}/ns1-2_${mode}.log) -eq 0 ] && \
|
||||
test_pass "$mode IPv6 (no flags) ns1-2" || \
|
||||
test_fail "$mode IPv6 (no flags) ns1-2"
|
||||
}
|
||||
@ -176,9 +180,13 @@ do_tests()
|
||||
xdpgeneric) drv_p="-S";;
|
||||
esac
|
||||
|
||||
./xdp_redirect_multi $drv_p $IFACES &> xdp_redirect_${mode}.log &
|
||||
ip netns exec ns0 ./xdp_redirect_multi $drv_p $IFACES &> ${LOG_DIR}/xdp_redirect_${mode}.log &
|
||||
xdp_pid=$!
|
||||
sleep 1
|
||||
if ! ps -p $xdp_pid > /dev/null; then
|
||||
test_fail "$mode xdp_redirect_multi start failed"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ "$mode" = "xdpegress" ]; then
|
||||
do_egress_tests $mode
|
||||
@ -189,16 +197,16 @@ do_tests()
|
||||
kill $xdp_pid
|
||||
}
|
||||
|
||||
trap clean_up 0 2 3 6 9
|
||||
trap clean_up EXIT
|
||||
|
||||
check_env
|
||||
rm -f xdp_redirect_*.log ns*.log mac_ns*.log
|
||||
|
||||
for mode in ${DRV_MODE}; do
|
||||
setup_ns $mode
|
||||
do_tests $mode
|
||||
clean_up
|
||||
done
|
||||
rm -rf ${LOG_DIR}
|
||||
|
||||
echo "Summary: PASS $PASS, FAIL $FAIL"
|
||||
[ $FAIL -eq 0 ] && exit 0 || exit 1
|
||||
|
@ -265,3 +265,20 @@
|
||||
.result = ACCEPT,
|
||||
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
||||
},
|
||||
{
|
||||
"Spill a u32 scalar at fp-4 and then at fp-8",
|
||||
.insns = {
|
||||
/* r4 = 4321 */
|
||||
BPF_MOV32_IMM(BPF_REG_4, 4321),
|
||||
/* *(u32 *)(r10 -4) = r4 */
|
||||
BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_4, -4),
|
||||
/* *(u32 *)(r10 -8) = r4 */
|
||||
BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_4, -8),
|
||||
/* r4 = *(u64 *)(r10 -8) */
|
||||
BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_10, -8),
|
||||
BPF_MOV64_IMM(BPF_REG_0, 0),
|
||||
BPF_EXIT_INSN(),
|
||||
},
|
||||
.result = ACCEPT,
|
||||
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
||||
},
|
||||
|
@ -129,7 +129,7 @@ int main(int argc, char **argv)
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
printf("Get interfaces");
|
||||
printf("Get interfaces:");
|
||||
for (i = 0; i < MAX_IFACE_NUM && argv[optind + i]; i++) {
|
||||
ifaces[i] = if_nametoindex(argv[optind + i]);
|
||||
if (!ifaces[i])
|
||||
@ -139,7 +139,7 @@ int main(int argc, char **argv)
|
||||
goto err_out;
|
||||
}
|
||||
if (ifaces[i] > MAX_INDEX_NUM) {
|
||||
printf("Interface index to large\n");
|
||||
printf(" interface index too large\n");
|
||||
goto err_out;
|
||||
}
|
||||
printf(" %d", ifaces[i]);
|
||||
|
@ -211,12 +211,16 @@ static void test(int *rcv_fd, int len, int family, int proto)
|
||||
|
||||
/* Forward iterate */
|
||||
for (node = 0; node < len; ++node) {
|
||||
if (!numa_bitmask_isbitset(numa_nodes_ptr, node))
|
||||
continue;
|
||||
send_from_node(node, family, proto);
|
||||
receive_on_node(rcv_fd, len, epfd, node, proto);
|
||||
}
|
||||
|
||||
/* Reverse iterate */
|
||||
for (node = len - 1; node >= 0; --node) {
|
||||
if (!numa_bitmask_isbitset(numa_nodes_ptr, node))
|
||||
continue;
|
||||
send_from_node(node, family, proto);
|
||||
receive_on_node(rcv_fd, len, epfd, node, proto);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user