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:
Jakub Kicinski 2021-11-05 14:13:40 -07:00
commit 9bea6aa498
14 changed files with 199 additions and 90 deletions

View File

@ -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

View File

@ -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)
{

View File

@ -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;

View File

@ -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);

View File

@ -3088,9 +3088,12 @@ static int check_stack_read_fixed_off(struct bpf_verifier_env *env,
reg = &reg_state->stack[spi].spilled_ptr;
if (is_spilled_reg(&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 */

View File

@ -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;

View File

@ -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

View File

@ -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)

View File

@ -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;

View File

@ -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");

View File

@ -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

View File

@ -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,
},

View File

@ -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]);

View File

@ -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);
}