diff options
Diffstat (limited to 'tools')
42 files changed, 2213 insertions, 543 deletions
diff --git a/tools/bpf/bpftool/Makefile b/tools/bpf/bpftool/Makefile index f897cb5fb12d..45ac2f9e0aa9 100644 --- a/tools/bpf/bpftool/Makefile +++ b/tools/bpf/bpftool/Makefile @@ -166,7 +166,7 @@ $(OUTPUT)%.bpf.o: skeleton/%.bpf.c $(OUTPUT)vmlinux.h $(LIBBPF) -I$(srctree)/tools/include/uapi/ \ -I$(LIBBPF_PATH) \ -I$(srctree)/tools/lib \ - -g -O2 -target bpf -c $< -o $@ && $(LLVM_STRIP) -g $@ + -g -O2 -Wall -target bpf -c $< -o $@ && $(LLVM_STRIP) -g $@ $(OUTPUT)%.skel.h: $(OUTPUT)%.bpf.o $(BPFTOOL_BOOTSTRAP) $(QUIET_GEN)$(BPFTOOL_BOOTSTRAP) gen skeleton $< > $@ diff --git a/tools/include/linux/filter.h b/tools/include/linux/filter.h index ca28b6ab8db7..736bdeccdfe4 100644 --- a/tools/include/linux/filter.h +++ b/tools/include/linux/filter.h @@ -169,15 +169,31 @@ .off = OFF, \ .imm = 0 }) -/* Atomic memory add, *(uint *)(dst_reg + off16) += src_reg */ +/* + * Atomic operations: + * + * BPF_ADD *(uint *) (dst_reg + off16) += src_reg + * BPF_AND *(uint *) (dst_reg + off16) &= src_reg + * BPF_OR *(uint *) (dst_reg + off16) |= src_reg + * BPF_XOR *(uint *) (dst_reg + off16) ^= src_reg + * BPF_ADD | BPF_FETCH src_reg = atomic_fetch_add(dst_reg + off16, src_reg); + * BPF_AND | BPF_FETCH src_reg = atomic_fetch_and(dst_reg + off16, src_reg); + * BPF_OR | BPF_FETCH src_reg = atomic_fetch_or(dst_reg + off16, src_reg); + * BPF_XOR | BPF_FETCH src_reg = atomic_fetch_xor(dst_reg + off16, src_reg); + * BPF_XCHG src_reg = atomic_xchg(dst_reg + off16, src_reg) + * BPF_CMPXCHG r0 = atomic_cmpxchg(dst_reg + off16, r0, src_reg) + */ -#define BPF_STX_XADD(SIZE, DST, SRC, OFF) \ +#define BPF_ATOMIC_OP(SIZE, OP, DST, SRC, OFF) \ ((struct bpf_insn) { \ - .code = BPF_STX | BPF_SIZE(SIZE) | BPF_XADD, \ + .code = BPF_STX | BPF_SIZE(SIZE) | BPF_ATOMIC, \ .dst_reg = DST, \ .src_reg = SRC, \ .off = OFF, \ - .imm = 0 }) + .imm = OP }) + +/* Legacy alias */ +#define BPF_STX_XADD(SIZE, DST, SRC, OFF) BPF_ATOMIC_OP(SIZE, BPF_ADD, DST, SRC, OFF) /* Memory store, *(uint *) (dst_reg + off16) = imm32 */ diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 77d7c1bb2923..c001766adcbc 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -19,7 +19,8 @@ /* ld/ldx fields */ #define BPF_DW 0x18 /* double word (64-bit) */ -#define BPF_XADD 0xc0 /* exclusive add */ +#define BPF_ATOMIC 0xc0 /* atomic memory ops - op type in immediate */ +#define BPF_XADD 0xc0 /* exclusive add - legacy name */ /* alu/jmp fields */ #define BPF_MOV 0xb0 /* mov reg to reg */ @@ -43,6 +44,11 @@ #define BPF_CALL 0x80 /* function call */ #define BPF_EXIT 0x90 /* function return */ +/* atomic op type fields (stored in immediate) */ +#define BPF_FETCH 0x01 /* not an opcode on its own, used to build others */ +#define BPF_XCHG (0xe0 | BPF_FETCH) /* atomic exchange */ +#define BPF_CMPXCHG (0xf0 | BPF_FETCH) /* atomic compare-and-write */ + /* Register numbers */ enum { BPF_REG_0 = 0, @@ -2448,7 +2454,7 @@ union bpf_attr { * running simultaneously. * * A user should care about the synchronization by himself. - * For example, by using the **BPF_STX_XADD** instruction to alter + * For example, by using the **BPF_ATOMIC** instructions to alter * the shared data. * Return * A pointer to the local storage area. @@ -2993,10 +2999,10 @@ union bpf_attr { * string length is larger than *size*, just *size*-1 bytes are * copied and the last byte is set to NUL. * - * On success, the length of the copied string is returned. This - * makes this helper useful in tracing programs for reading - * strings, and more importantly to get its length at runtime. See - * the following snippet: + * On success, returns the number of bytes that were written, + * including the terminal NUL. This makes this helper useful in + * tracing programs for reading strings, and more importantly to + * get its length at runtime. See the following snippet: * * :: * @@ -3024,7 +3030,7 @@ union bpf_attr { * **->mm->env_start**: using this helper and the return value, * one can quickly iterate at the right offset of the memory area. * Return - * On success, the strictly positive length of the string, + * On success, the strictly positive length of the output string, * including the trailing NUL character. On error, a negative * value. * diff --git a/tools/include/uapi/linux/if_link.h b/tools/include/uapi/linux/if_link.h index d208b2af697f..28d649bda686 100644 --- a/tools/include/uapi/linux/if_link.h +++ b/tools/include/uapi/linux/if_link.h @@ -617,6 +617,7 @@ enum { IFLA_GTP_FD1, IFLA_GTP_PDP_HASHSIZE, IFLA_GTP_ROLE, + IFLA_GTP_COLLECT_METADATA, __IFLA_GTP_MAX, }; #define IFLA_GTP_MAX (__IFLA_GTP_MAX - 1) diff --git a/tools/lib/bpf/bpf_core_read.h b/tools/lib/bpf/bpf_core_read.h index bbcefb3ff5a5..53b3e199fb25 100644 --- a/tools/lib/bpf/bpf_core_read.h +++ b/tools/lib/bpf/bpf_core_read.h @@ -195,17 +195,22 @@ enum bpf_enum_value_kind { * (local) BTF, used to record relocation. */ #define bpf_core_read(dst, sz, src) \ - bpf_probe_read_kernel(dst, sz, \ - (const void *)__builtin_preserve_access_index(src)) + bpf_probe_read_kernel(dst, sz, (const void *)__builtin_preserve_access_index(src)) +/* NOTE: see comments for BPF_CORE_READ_USER() about the proper types use. */ +#define bpf_core_read_user(dst, sz, src) \ + bpf_probe_read_user(dst, sz, (const void *)__builtin_preserve_access_index(src)) /* * bpf_core_read_str() is a thin wrapper around bpf_probe_read_str() * additionally emitting BPF CO-RE field relocation for specified source * argument. */ #define bpf_core_read_str(dst, sz, src) \ - bpf_probe_read_kernel_str(dst, sz, \ - (const void *)__builtin_preserve_access_index(src)) + bpf_probe_read_kernel_str(dst, sz, (const void *)__builtin_preserve_access_index(src)) + +/* NOTE: see comments for BPF_CORE_READ_USER() about the proper types use. */ +#define bpf_core_read_user_str(dst, sz, src) \ + bpf_probe_read_user_str(dst, sz, (const void *)__builtin_preserve_access_index(src)) #define ___concat(a, b) a ## b #define ___apply(fn, n) ___concat(fn, n) @@ -264,30 +269,29 @@ enum bpf_enum_value_kind { read_fn((void *)(dst), sizeof(*(dst)), &((src_type)(src))->accessor) /* "recursively" read a sequence of inner pointers using local __t var */ -#define ___rd_first(src, a) ___read(bpf_core_read, &__t, ___type(src), src, a); -#define ___rd_last(...) \ - ___read(bpf_core_read, &__t, \ - ___type(___nolast(__VA_ARGS__)), __t, ___last(__VA_ARGS__)); -#define ___rd_p1(...) const void *__t; ___rd_first(__VA_ARGS__) -#define ___rd_p2(...) ___rd_p1(___nolast(__VA_ARGS__)) ___rd_last(__VA_ARGS__) -#define ___rd_p3(...) ___rd_p2(___nolast(__VA_ARGS__)) ___rd_last(__VA_ARGS__) -#define ___rd_p4(...) ___rd_p3(___nolast(__VA_ARGS__)) ___rd_last(__VA_ARGS__) -#define ___rd_p5(...) ___rd_p4(___nolast(__VA_ARGS__)) ___rd_last(__VA_ARGS__) -#define ___rd_p6(...) ___rd_p5(___nolast(__VA_ARGS__)) ___rd_last(__VA_ARGS__) -#define ___rd_p7(...) ___rd_p6(___nolast(__VA_ARGS__)) ___rd_last(__VA_ARGS__) -#define ___rd_p8(...) ___rd_p7(___nolast(__VA_ARGS__)) ___rd_last(__VA_ARGS__) -#define ___rd_p9(...) ___rd_p8(___nolast(__VA_ARGS__)) ___rd_last(__VA_ARGS__) -#define ___read_ptrs(src, ...) \ - ___apply(___rd_p, ___narg(__VA_ARGS__))(src, __VA_ARGS__) - -#define ___core_read0(fn, dst, src, a) \ +#define ___rd_first(fn, src, a) ___read(fn, &__t, ___type(src), src, a); +#define ___rd_last(fn, ...) \ + ___read(fn, &__t, ___type(___nolast(__VA_ARGS__)), __t, ___last(__VA_ARGS__)); +#define ___rd_p1(fn, ...) const void *__t; ___rd_first(fn, __VA_ARGS__) +#define ___rd_p2(fn, ...) ___rd_p1(fn, ___nolast(__VA_ARGS__)) ___rd_last(fn, __VA_ARGS__) +#define ___rd_p3(fn, ...) ___rd_p2(fn, ___nolast(__VA_ARGS__)) ___rd_last(fn, __VA_ARGS__) +#define ___rd_p4(fn, ...) ___rd_p3(fn, ___nolast(__VA_ARGS__)) ___rd_last(fn, __VA_ARGS__) +#define ___rd_p5(fn, ...) ___rd_p4(fn, ___nolast(__VA_ARGS__)) ___rd_last(fn, __VA_ARGS__) +#define ___rd_p6(fn, ...) ___rd_p5(fn, ___nolast(__VA_ARGS__)) ___rd_last(fn, __VA_ARGS__) +#define ___rd_p7(fn, ...) ___rd_p6(fn, ___nolast(__VA_ARGS__)) ___rd_last(fn, __VA_ARGS__) +#define ___rd_p8(fn, ...) ___rd_p7(fn, ___nolast(__VA_ARGS__)) ___rd_last(fn, __VA_ARGS__) +#define ___rd_p9(fn, ...) ___rd_p8(fn, ___nolast(__VA_ARGS__)) ___rd_last(fn, __VA_ARGS__) +#define ___read_ptrs(fn, src, ...) \ + ___apply(___rd_p, ___narg(__VA_ARGS__))(fn, src, __VA_ARGS__) + +#define ___core_read0(fn, fn_ptr, dst, src, a) \ ___read(fn, dst, ___type(src), src, a); -#define ___core_readN(fn, dst, src, ...) \ - ___read_ptrs(src, ___nolast(__VA_ARGS__)) \ +#define ___core_readN(fn, fn_ptr, dst, src, ...) \ + ___read_ptrs(fn_ptr, src, ___nolast(__VA_ARGS__)) \ ___read(fn, dst, ___type(src, ___nolast(__VA_ARGS__)), __t, \ ___last(__VA_ARGS__)); -#define ___core_read(fn, dst, src, a, ...) \ - ___apply(___core_read, ___empty(__VA_ARGS__))(fn, dst, \ +#define ___core_read(fn, fn_ptr, dst, src, a, ...) \ + ___apply(___core_read, ___empty(__VA_ARGS__))(fn, fn_ptr, dst, \ src, a, ##__VA_ARGS__) /* @@ -295,20 +299,73 @@ enum bpf_enum_value_kind { * BPF_CORE_READ(), in which final field is read into user-provided storage. * See BPF_CORE_READ() below for more details on general usage. */ -#define BPF_CORE_READ_INTO(dst, src, a, ...) \ - ({ \ - ___core_read(bpf_core_read, dst, (src), a, ##__VA_ARGS__) \ - }) +#define BPF_CORE_READ_INTO(dst, src, a, ...) ({ \ + ___core_read(bpf_core_read, bpf_core_read, \ + dst, (src), a, ##__VA_ARGS__) \ +}) + +/* + * Variant of BPF_CORE_READ_INTO() for reading from user-space memory. + * + * NOTE: see comments for BPF_CORE_READ_USER() about the proper types use. + */ +#define BPF_CORE_READ_USER_INTO(dst, src, a, ...) ({ \ + ___core_read(bpf_core_read_user, bpf_core_read_user, \ + dst, (src), a, ##__VA_ARGS__) \ +}) + +/* Non-CO-RE variant of BPF_CORE_READ_INTO() */ +#define BPF_PROBE_READ_INTO(dst, src, a, ...) ({ \ + ___core_read(bpf_probe_read, bpf_probe_read, \ + dst, (src), a, ##__VA_ARGS__) \ +}) + +/* Non-CO-RE variant of BPF_CORE_READ_USER_INTO(). + * + * As no CO-RE relocations are emitted, source types can be arbitrary and are + * not restricted to kernel types only. + */ +#define BPF_PROBE_READ_USER_INTO(dst, src, a, ...) ({ \ + ___core_read(bpf_probe_read_user, bpf_probe_read_user, \ + dst, (src), a, ##__VA_ARGS__) \ +}) /* * BPF_CORE_READ_STR_INTO() does same "pointer chasing" as * BPF_CORE_READ() for intermediate pointers, but then executes (and returns * corresponding error code) bpf_core_read_str() for final string read. */ -#define BPF_CORE_READ_STR_INTO(dst, src, a, ...) \ - ({ \ - ___core_read(bpf_core_read_str, dst, (src), a, ##__VA_ARGS__)\ - }) +#define BPF_CORE_READ_STR_INTO(dst, src, a, ...) ({ \ + ___core_read(bpf_core_read_str, bpf_core_read, \ + dst, (src), a, ##__VA_ARGS__) \ +}) + +/* + * Variant of BPF_CORE_READ_STR_INTO() for reading from user-space memory. + * + * NOTE: see comments for BPF_CORE_READ_USER() about the proper types use. + */ +#define BPF_CORE_READ_USER_STR_INTO(dst, src, a, ...) ({ \ + ___core_read(bpf_core_read_user_str, bpf_core_read_user, \ + dst, (src), a, ##__VA_ARGS__) \ +}) + +/* Non-CO-RE variant of BPF_CORE_READ_STR_INTO() */ +#define BPF_PROBE_READ_STR_INTO(dst, src, a, ...) ({ \ + ___core_read(bpf_probe_read_str, bpf_probe_read, \ + dst, (src), a, ##__VA_ARGS__) \ +}) + +/* + * Non-CO-RE variant of BPF_CORE_READ_USER_STR_INTO(). + * + * As no CO-RE relocations are emitted, source types can be arbitrary and are + * not restricted to kernel types only. + */ +#define BPF_PROBE_READ_USER_STR_INTO(dst, src, a, ...) ({ \ + ___core_read(bpf_probe_read_user_str, bpf_probe_read_user, \ + dst, (src), a, ##__VA_ARGS__) \ +}) /* * BPF_CORE_READ() is used to simplify BPF CO-RE relocatable read, especially @@ -334,12 +391,46 @@ enum bpf_enum_value_kind { * N.B. Only up to 9 "field accessors" are supported, which should be more * than enough for any practical purpose. */ -#define BPF_CORE_READ(src, a, ...) \ - ({ \ - ___type((src), a, ##__VA_ARGS__) __r; \ - BPF_CORE_READ_INTO(&__r, (src), a, ##__VA_ARGS__); \ - __r; \ - }) +#define BPF_CORE_READ(src, a, ...) ({ \ + ___type((src), a, ##__VA_ARGS__) __r; \ + BPF_CORE_READ_INTO(&__r, (src), a, ##__VA_ARGS__); \ + __r; \ +}) + +/* + * Variant of BPF_CORE_READ() for reading from user-space memory. + * + * NOTE: all the source types involved are still *kernel types* and need to + * exist in kernel (or kernel module) BTF, otherwise CO-RE relocation will + * fail. Custom user types are not relocatable with CO-RE. + * The typical situation in which BPF_CORE_READ_USER() might be used is to + * read kernel UAPI types from the user-space memory passed in as a syscall + * input argument. + */ +#define BPF_CORE_READ_USER(src, a, ...) ({ \ + ___type((src), a, ##__VA_ARGS__) __r; \ + BPF_CORE_READ_USER_INTO(&__r, (src), a, ##__VA_ARGS__); \ + __r; \ +}) + +/* Non-CO-RE variant of BPF_CORE_READ() */ +#define BPF_PROBE_READ(src, a, ...) ({ \ + ___type((src), a, ##__VA_ARGS__) __r; \ + BPF_PROBE_READ_INTO(&__r, (src), a, ##__VA_ARGS__); \ + __r; \ +}) + +/* + * Non-CO-RE variant of BPF_CORE_READ_USER(). + * + * As no CO-RE relocations are emitted, source types can be arbitrary and are + * not restricted to kernel types only. + */ +#define BPF_PROBE_READ_USER(src, a, ...) ({ \ + ___type((src), a, ##__VA_ARGS__) __r; \ + BPF_PROBE_READ_USER_INTO(&__r, (src), a, ##__VA_ARGS__); \ + __r; \ +}) #endif diff --git a/tools/lib/bpf/bpf_helpers.h b/tools/lib/bpf/bpf_helpers.h index 72b251110c4d..ae6c975e0b87 100644 --- a/tools/lib/bpf/bpf_helpers.h +++ b/tools/lib/bpf/bpf_helpers.h @@ -30,7 +30,7 @@ #define SEC(NAME) __attribute__((section(NAME), used)) #ifndef __always_inline -#define __always_inline __attribute__((always_inline)) +#define __always_inline inline __attribute__((always_inline)) #endif #ifndef __noinline #define __noinline __attribute__((noinline)) diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 6ae748f6ea11..2abbc3800568 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -395,7 +395,8 @@ struct extern_desc { unsigned long long addr; /* target btf_id of the corresponding kernel var. */ - int vmlinux_btf_id; + int kernel_btf_obj_fd; + int kernel_btf_id; /* local btf_id of the ksym extern's type. */ __u32 type_id; @@ -6162,7 +6163,8 @@ bpf_object__relocate_data(struct bpf_object *obj, struct bpf_program *prog) } else /* EXT_KSYM */ { if (ext->ksym.type_id) { /* typed ksyms */ insn[0].src_reg = BPF_PSEUDO_BTF_ID; - insn[0].imm = ext->ksym.vmlinux_btf_id; + insn[0].imm = ext->ksym.kernel_btf_id; + insn[1].imm = ext->ksym.kernel_btf_obj_fd; } else { /* typeless ksyms */ insn[0].imm = (__u32)ext->ksym.addr; insn[1].imm = ext->ksym.addr >> 32; @@ -7319,7 +7321,8 @@ out: static int bpf_object__resolve_ksyms_btf_id(struct bpf_object *obj) { struct extern_desc *ext; - int i, id; + struct btf *btf; + int i, j, id, btf_fd, err; for (i = 0; i < obj->nr_extern; i++) { const struct btf_type *targ_var, *targ_type; @@ -7331,10 +7334,25 @@ static int bpf_object__resolve_ksyms_btf_id(struct bpf_object *obj) if (ext->type != EXT_KSYM || !ext->ksym.type_id) continue; - id = btf__find_by_name_kind(obj->btf_vmlinux, ext->name, - BTF_KIND_VAR); + btf = obj->btf_vmlinux; + btf_fd = 0; + id = btf__find_by_name_kind(btf, ext->name, BTF_KIND_VAR); + if (id == -ENOENT) { + err = load_module_btfs(obj); + if (err) + return err; + + for (j = 0; j < obj->btf_module_cnt; j++) { + btf = obj->btf_modules[j].btf; + /* we assume module BTF FD is always >0 */ + btf_fd = obj->btf_modules[j].fd; + id = btf__find_by_name_kind(btf, ext->name, BTF_KIND_VAR); + if (id != -ENOENT) + break; + } + } if (id <= 0) { - pr_warn("extern (ksym) '%s': failed to find BTF ID in vmlinux BTF.\n", + pr_warn("extern (ksym) '%s': failed to find BTF ID in kernel BTF(s).\n", ext->name); return -ESRCH; } @@ -7343,24 +7361,19 @@ static int bpf_object__resolve_ksyms_btf_id(struct bpf_object *obj) local_type_id = ext->ksym.type_id; /* find target type_id */ - targ_var = btf__type_by_id(obj->btf_vmlinux, id); - targ_var_name = btf__name_by_offset(obj->btf_vmlinux, - targ_var->name_off); - targ_type = skip_mods_and_typedefs(obj->btf_vmlinux, - targ_var->type, - &targ_type_id); + targ_var = btf__type_by_id(btf, id); + targ_var_name = btf__name_by_offset(btf, targ_var->name_off); + targ_type = skip_mods_and_typedefs(btf, targ_var->type, &targ_type_id); ret = bpf_core_types_are_compat(obj->btf, local_type_id, - obj->btf_vmlinux, targ_type_id); + btf, targ_type_id); if (ret <= 0) { const struct btf_type *local_type; const char *targ_name, *local_name; local_type = btf__type_by_id(obj->btf, local_type_id); - local_name = btf__name_by_offset(obj->btf, - local_type->name_off); - targ_name = btf__name_by_offset(obj->btf_vmlinux, - targ_type->name_off); + local_name = btf__name_by_offset(obj->btf, local_type->name_off); + targ_name = btf__name_by_offset(btf, targ_type->name_off); pr_warn("extern (ksym) '%s': incompatible types, expected [%d] %s %s, but kernel has [%d] %s %s\n", ext->name, local_type_id, @@ -7370,7 +7383,8 @@ static int bpf_object__resolve_ksyms_btf_id(struct bpf_object *obj) } ext->is_set = true; - ext->ksym.vmlinux_btf_id = id; + ext->ksym.kernel_btf_obj_fd = btf_fd; + ext->ksym.kernel_btf_id = id; pr_debug("extern (ksym) '%s': resolved to [%d] %s %s\n", ext->name, id, btf_kind_str(targ_var), targ_var_name); } diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile index c51df6b91bef..0552b07717b6 100644 --- a/tools/testing/selftests/bpf/Makefile +++ b/tools/testing/selftests/bpf/Makefile @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 include ../../../../scripts/Kbuild.include include ../../../scripts/Makefile.arch +include ../../../scripts/Makefile.include CXX ?= $(CROSS_COMPILE)g++ @@ -24,7 +25,7 @@ BPF_GCC ?= $(shell command -v bpf-gcc;) SAN_CFLAGS ?= CFLAGS += -g -rdynamic -Wall -O2 $(GENFLAGS) $(SAN_CFLAGS) \ -I$(CURDIR) -I$(INCLUDE_DIR) -I$(GENDIR) -I$(LIBDIR) \ - -I$(TOOLSINCDIR) -I$(APIDIR) \ + -I$(TOOLSINCDIR) -I$(APIDIR) -I$(OUTPUT) \ -Dbpf_prog_load=bpf_prog_test_load \ -Dbpf_load_program=bpf_test_load_program LDLIBS += -lcap -lelf -lz -lrt -lpthread @@ -43,10 +44,10 @@ ifneq ($(BPF_GCC),) TEST_GEN_PROGS += test_progs-bpf_gcc endif -TEST_GEN_FILES = -TEST_FILES = test_lwt_ip_encap.o \ - test_tc_edt.o \ - xsk_prereqs.sh +TEST_GEN_FILES = test_lwt_ip_encap.o \ + test_tc_edt.o +TEST_FILES = xsk_prereqs.sh \ + $(wildcard progs/btf_dump_test_case_*.c) # Order correspond to 'make run_tests' order TEST_PROGS := test_kmod.sh \ @@ -82,7 +83,7 @@ TEST_GEN_PROGS_EXTENDED = test_sock_addr test_skb_cgroup_id_user \ test_lirc_mode2_user xdping test_cpp runqslower bench bpf_testmod.ko \ xdpxceiver -TEST_CUSTOM_PROGS = urandom_read +TEST_CUSTOM_PROGS = $(OUTPUT)/urandom_read # Emit succinct information message describing current building step # $1 - generic step name (e.g., CC, LINK, etc); @@ -113,7 +114,15 @@ SCRATCH_DIR := $(OUTPUT)/tools BUILD_DIR := $(SCRATCH_DIR)/build INCLUDE_DIR := $(SCRATCH_DIR)/include BPFOBJ := $(BUILD_DIR)/libbpf/libbpf.a -RESOLVE_BTFIDS := $(BUILD_DIR)/resolve_btfids/resolve_btfids +ifneq ($(CROSS_COMPILE),) +HOST_BUILD_DIR := $(BUILD_DIR)/host +HOST_SCRATCH_DIR := $(OUTPUT)/host-tools +else +HOST_BUILD_DIR := $(BUILD_DIR) +HOST_SCRATCH_DIR := $(SCRATCH_DIR) +endif +HOST_BPFOBJ := $(HOST_BUILD_DIR)/libbpf/libbpf.a +RESOLVE_BTFIDS := $(HOST_BUILD_DIR)/resolve_btfids/resolve_btfids VMLINUX_BTF_PATHS ?= $(if $(O),$(O)/vmlinux) \ $(if $(KBUILD_OUTPUT),$(KBUILD_OUTPUT)/vmlinux) \ @@ -135,6 +144,14 @@ $(notdir $(TEST_GEN_PROGS) \ $(TEST_GEN_PROGS_EXTENDED) \ $(TEST_CUSTOM_PROGS)): %: $(OUTPUT)/% ; +# sort removes libbpf duplicates when not cross-building +MAKE_DIRS := $(sort $(BUILD_DIR)/libbpf $(HOST_BUILD_DIR)/libbpf \ + $(HOST_BUILD_DIR)/bpftool $(HOST_BUILD_DIR)/resolve_btfids \ + $(INCLUDE_DIR)) +$(MAKE_DIRS): + $(call msg,MKDIR,,$@) + $(Q)mkdir -p $@ + $(OUTPUT)/%.o: %.c $(call msg,CC,,$@) $(Q)$(CC) $(CFLAGS) -c $(filter %.c,$^) $(LDLIBS) -o $@ @@ -157,7 +174,7 @@ $(OUTPUT)/test_stub.o: test_stub.c $(BPFOBJ) $(call msg,CC,,$@) $(Q)$(CC) -c $(CFLAGS) -o $@ $< -DEFAULT_BPFTOOL := $(SCRATCH_DIR)/sbin/bpftool +DEFAULT_BPFTOOL := $(HOST_SCRATCH_DIR)/sbin/bpftool $(OUTPUT)/runqslower: $(BPFOBJ) | $(DEFAULT_BPFTOOL) $(Q)$(MAKE) $(submake_extras) -C $(TOOLSDIR)/bpf/runqslower \ @@ -182,10 +199,11 @@ $(OUTPUT)/test_sysctl: cgroup_helpers.c BPFTOOL ?= $(DEFAULT_BPFTOOL) $(DEFAULT_BPFTOOL): $(wildcard $(BPFTOOLDIR)/*.[ch] $(BPFTOOLDIR)/Makefile) \ - $(BPFOBJ) | $(BUILD_DIR)/bpftool + $(HOST_BPFOBJ) | $(HOST_BUILD_DIR)/bpftool $(Q)$(MAKE) $(submake_extras) -C $(BPFTOOLDIR) \ - OUTPUT=$(BUILD_DIR)/bpftool/ \ - prefix= DESTDIR=$(SCRATCH_DIR)/ install + CC=$(HOSTCC) LD=$(HOSTLD) \ + OUTPUT=$(HOST_BUILD_DIR)/bpftool/ \ + prefix= DESTDIR=$(HOST_SCRATCH_DIR)/ install $(Q)mkdir -p $(BUILD_DIR)/bpftool/Documentation $(Q)RST2MAN_OPTS="--exit-status=1" $(MAKE) $(submake_extras) \ -C $(BPFTOOLDIR)/Documentation \ @@ -198,9 +216,14 @@ $(BPFOBJ): $(wildcard $(BPFDIR)/*.[ch] $(BPFDIR)/Makefile) \ $(Q)$(MAKE) $(submake_extras) -C $(BPFDIR) OUTPUT=$(BUILD_DIR)/libbpf/ \ DESTDIR=$(SCRATCH_DIR) prefix= all install_headers -$(BUILD_DIR)/libbpf $(BUILD_DIR)/bpftool $(BUILD_DIR)/resolve_btfids $(INCLUDE_DIR): - $(call msg,MKDIR,,$@) - $(Q)mkdir -p $@ +ifneq ($(BPFOBJ),$(HOST_BPFOBJ)) +$(HOST_BPFOBJ): $(wildcard $(BPFDIR)/*.[ch] $(BPFDIR)/Makefile) \ + ../../../include/uapi/linux/bpf.h \ + | $(INCLUDE_DIR) $(HOST_BUILD_DIR)/libbpf + $(Q)$(MAKE) $(submake_extras) -C $(BPFDIR) \ + OUTPUT=$(HOST_BUILD_DIR)/libbpf/ CC=$(HOSTCC) LD=$(HOSTLD) \ + DESTDIR=$(HOST_SCRATCH_DIR)/ prefix= all install_headers +endif $(INCLUDE_DIR)/vmlinux.h: $(VMLINUX_BTF) | $(BPFTOOL) $(INCLUDE_DIR) ifeq ($(VMLINUX_H),) @@ -211,7 +234,7 @@ else $(Q)cp "$(VMLINUX_H)" $@ endif -$(RESOLVE_BTFIDS): $(BPFOBJ) | $(BUILD_DIR)/resolve_btfids \ +$(RESOLVE_BTFIDS): $(HOST_BPFOBJ) | $(HOST_BUILD_DIR)/resolve_btfids \ $(TOOLSDIR)/bpf/resolve_btfids/main.c \ $(TOOLSDIR)/lib/rbtree.c \ $(TOOLSDIR)/lib/zalloc.c \ @@ -219,7 +242,8 @@ $(RESOLVE_BTFIDS): $(BPFOBJ) | $(BUILD_DIR)/resolve_btfids \ $(TOOLSDIR)/lib/ctype.c \ $(TOOLSDIR)/lib/str_error_r.c $(Q)$(MAKE) $(submake_extras) -C $(TOOLSDIR)/bpf/resolve_btfids \ - OUTPUT=$(BUILD_DIR)/resolve_btfids/ BPFOBJ=$(BPFOBJ) + CC=$(HOSTCC) LD=$(HOSTLD) AR=$(HOSTAR) \ + OUTPUT=$(HOST_BUILD_DIR)/resolve_btfids/ BPFOBJ=$(HOST_BPFOBJ) # Get Clang's default includes on this system, as opposed to those seen by # '-target bpf'. This fixes "missing" files on some architectures/distros, @@ -390,10 +414,12 @@ TRUNNER_EXTRA_FILES := $(OUTPUT)/urandom_read $(OUTPUT)/bpf_testmod.ko \ $(wildcard progs/btf_dump_test_case_*.c) TRUNNER_BPF_BUILD_RULE := CLANG_BPF_BUILD_RULE TRUNNER_BPF_CFLAGS := $(BPF_CFLAGS) $(CLANG_CFLAGS) +TRUNNER_BPF_CFLAGS += -DENABLE_ATOMICS_TESTS $(eval $(call DEFINE_TEST_RUNNER,test_progs)) # Define test_progs-no_alu32 test runner. TRUNNER_BPF_BUILD_RULE := CLANG_NOALU32_BPF_BUILD_RULE +TRUNNER_BPF_CFLAGS := $(BPF_CFLAGS) $(CLANG_CFLAGS) $(eval $(call DEFINE_TEST_RUNNER,test_progs,no_alu32)) # Define test_progs BPF-GCC-flavored test runner. @@ -450,7 +476,7 @@ $(OUTPUT)/bench: $(OUTPUT)/bench.o $(OUTPUT)/testing_helpers.o \ $(call msg,BINARY,,$@) $(Q)$(CC) $(LDFLAGS) -o $@ $(filter %.a %.o,$^) $(LDLIBS) -EXTRA_CLEAN := $(TEST_CUSTOM_PROGS) $(SCRATCH_DIR) \ +EXTRA_CLEAN := $(TEST_CUSTOM_PROGS) $(SCRATCH_DIR) $(HOST_SCRATCH_DIR) \ prog_tests/tests.h map_tests/tests.h verifier/tests.h \ feature \ $(addprefix $(OUTPUT)/,*.o *.skel.h no_alu32 bpf_gcc bpf_testmod.ko) diff --git a/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c b/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c index 2df19d73ca49..0b991e115d1f 100644 --- a/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c +++ b/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c @@ -3,6 +3,7 @@ #include <linux/error-injection.h> #include <linux/init.h> #include <linux/module.h> +#include <linux/percpu-defs.h> #include <linux/sysfs.h> #include <linux/tracepoint.h> #include "bpf_testmod.h" @@ -10,6 +11,8 @@ #define CREATE_TRACE_POINTS #include "bpf_testmod-events.h" +DEFINE_PER_CPU(int, bpf_testmod_ksym_percpu) = 123; + noinline ssize_t bpf_testmod_test_read(struct file *file, struct kobject *kobj, struct bin_attribute *bin_attr, diff --git a/tools/testing/selftests/bpf/prog_tests/atomics.c b/tools/testing/selftests/bpf/prog_tests/atomics.c new file mode 100644 index 000000000000..21efe7bbf10d --- /dev/null +++ b/tools/testing/selftests/bpf/prog_tests/atomics.c @@ -0,0 +1,246 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <test_progs.h> + +#include "atomics.skel.h" + +static void test_add(struct atomics *skel) +{ + int err, prog_fd; + __u32 duration = 0, retval; + struct bpf_link *link; + + link = bpf_program__attach(skel->progs.add); + if (CHECK(IS_ERR(link), "attach(add)", "err: %ld\n", PTR_ERR(link))) + return; + + prog_fd = bpf_program__fd(skel->progs.add); + err = bpf_prog_test_run(prog_fd, 1, NULL, 0, + NULL, NULL, &retval, &duration); + if (CHECK(err || retval, "test_run add", + "err %d errno %d retval %d duration %d\n", err, errno, retval, duration)) + goto cleanup; + + ASSERT_EQ(skel->data->add64_value, 3, "add64_value"); + ASSERT_EQ(skel->bss->add64_result, 1, "add64_result"); + + ASSERT_EQ(skel->data->add32_value, 3, "add32_value"); + ASSERT_EQ(skel->bss->add32_result, 1, "add32_result"); + + ASSERT_EQ(skel->bss->add_stack_value_copy, 3, "add_stack_value"); + ASSERT_EQ(skel->bss->add_stack_result, 1, "add_stack_result"); + + ASSERT_EQ(skel->data->add_noreturn_value, 3, "add_noreturn_value"); + +cleanup: + bpf_link__destroy(link); +} + +static void test_sub(struct atomics *skel) +{ + int err, prog_fd; + __u32 duration = 0, retval; + struct bpf_link *link; + + link = bpf_program__attach(skel->progs.sub); + if (CHECK(IS_ERR(link), "attach(sub)", "err: %ld\n", PTR_ERR(link))) + return; + + prog_fd = bpf_program__fd(skel->progs.sub); + err = bpf_prog_test_run(prog_fd, 1, NULL, 0, + NULL, NULL, &retval, &duration); + if (CHECK(err || retval, "test_run sub", + "err %d errno %d retval %d duration %d\n", + err, errno, retval, duration)) + goto cleanup; + + ASSERT_EQ(skel->data->sub64_value, -1, "sub64_value"); + ASSERT_EQ(skel->bss->sub64_result, 1, "sub64_result"); + + ASSERT_EQ(skel->data->sub32_value, -1, "sub32_value"); + ASSERT_EQ(skel->bss->sub32_result, 1, "sub32_result"); + + ASSERT_EQ(skel->bss->sub_stack_value_copy, -1, "sub_stack_value"); + ASSERT_EQ(skel->bss->sub_stack_result, 1, "sub_stack_result"); + + ASSERT_EQ(skel->data->sub_noreturn_value, -1, "sub_noreturn_value"); + +cleanup: + bpf_link__destroy(link); +} + +static void test_and(struct atomics *skel) +{ + int err, prog_fd; + __u32 duration = 0, retval; + struct bpf_link *link; + + link = bpf_program__attach(skel->progs.and); + if (CHECK(IS_ERR(link), "attach(and)", "err: %ld\n", PTR_ERR(link))) + return; + + prog_fd = bpf_program__fd(skel->progs.and); + err = bpf_prog_test_run(prog_fd, 1, NULL, 0, + NULL, NULL, &retval, &duration); + if (CHECK(err || retval, "test_run and", + "err %d errno %d retval %d duration %d\n", err, errno, retval, duration)) + goto cleanup; + + ASSERT_EQ(skel->data->and64_value, 0x010ull << 32, "and64_value"); + ASSERT_EQ(skel->bss->and64_result, 0x110ull << 32, "and64_result"); + + ASSERT_EQ(skel->data->and32_value, 0x010, "and32_value"); + ASSERT_EQ(skel->bss->and32_result, 0x110, "and32_result"); + + ASSERT_EQ(skel->data->and_noreturn_value, 0x010ull << 32, "and_noreturn_value"); +cleanup: + bpf_link__destroy(link); +} + +static void test_or(struct atomics *skel) +{ + int err, prog_fd; + __u32 duration = 0, retval; + struct bpf_link *link; + + link = bpf_program__attach(skel->progs.or); + if (CHECK(IS_ERR(link), "attach(or)", "err: %ld\n", PTR_ERR(link))) + return; + + prog_fd = bpf_program__fd(skel->progs.or); + err = bpf_prog_test_run(prog_fd, 1, NULL, 0, + NULL, NULL, &retval, &duration); + if (CHECK(err || retval, "test_run or", + "err %d errno %d retval %d duration %d\n", + err, errno, retval, duration)) + goto cleanup; + + ASSERT_EQ(skel->data->or64_value, 0x111ull << 32, "or64_value"); + ASSERT_EQ(skel->bss->or64_result, 0x110ull << 32, "or64_result"); + + ASSERT_EQ(skel->data->or32_value, 0x111, "or32_value"); + ASSERT_EQ(skel->bss->or32_result, 0x110, "or32_result"); + + ASSERT_EQ(skel->data->or_noreturn_value, 0x111ull << 32, "or_noreturn_value"); +cleanup: + bpf_link__destroy(link); +} + +static void test_xor(struct atomics *skel) +{ + int err, prog_fd; + __u32 duration = 0, retval; + struct bpf_link *link; + + link = bpf_program__attach(skel->progs.xor); + if (CHECK(IS_ERR(link), "attach(xor)", "err: %ld\n", PTR_ERR(link))) + return; + + prog_fd = bpf_program__fd(skel->progs.xor); + err = bpf_prog_test_run(prog_fd, 1, NULL, 0, + NULL, NULL, &retval, &duration); + if (CHECK(err || retval, "test_run xor", + "err %d errno %d retval %d duration %d\n", err, errno, retval, duration)) + goto cleanup; + + ASSERT_EQ(skel->data->xor64_value, 0x101ull << 32, "xor64_value"); + ASSERT_EQ(skel->bss->xor64_result, 0x110ull << 32, "xor64_result"); + + ASSERT_EQ(skel->data->xor32_value, 0x101, "xor32_value"); + ASSERT_EQ(skel->bss->xor32_result, 0x110, "xor32_result"); + + ASSERT_EQ(skel->data->xor_noreturn_value, 0x101ull << 32, "xor_nxoreturn_value"); +cleanup: + bpf_link__destroy(link); +} + +static void test_cmpxchg(struct atomics *skel) +{ + int err, prog_fd; + __u32 duration = 0, retval; + struct bpf_link *link; + + link = bpf_program__attach(skel->progs.cmpxchg); + if (CHECK(IS_ERR(link), "attach(cmpxchg)", "err: %ld\n", PTR_ERR(link))) + return; + + prog_fd = bpf_program__fd(skel->progs.cmpxchg); + err = bpf_prog_test_run(prog_fd, 1, NULL, 0, + NULL, NULL, &retval, &duration); + if (CHECK(err || retval, "test_run add", + "err %d errno %d retval %d duration %d\n", err, errno, retval, duration)) + goto cleanup; + + ASSERT_EQ(skel->data->cmpxchg64_value, 2, "cmpxchg64_value"); + ASSERT_EQ(skel->bss->cmpxchg64_result_fail, 1, "cmpxchg_result_fail"); + ASSERT_EQ(skel->bss->cmpxchg64_result_succeed, 1, "cmpxchg_result_succeed"); + + ASSERT_EQ(skel->data->cmpxchg32_value, 2, "lcmpxchg32_value"); + ASSERT_EQ(skel->bss->cmpxchg32_result_fail, 1, "cmpxchg_result_fail"); + ASSERT_EQ(skel->bss->cmpxchg32_result_succeed, 1, "cmpxchg_result_succeed"); + +cleanup: + bpf_link__destroy(link); +} + +static void test_xchg(struct atomics *skel) +{ + int err, prog_fd; + __u32 duration = 0, retval; + struct bpf_link *link; + + link = bpf_program__attach(skel->progs.xchg); + if (CHECK(IS_ERR(link), "attach(xchg)", "err: %ld\n", PTR_ERR(link))) + return; + + prog_fd = bpf_program__fd(skel->progs.xchg); + err = bpf_prog_test_run(prog_fd, 1, NULL, 0, + NULL, NULL, &retval, &duration); + if (CHECK(err || retval, "test_run add", + "err %d errno %d retval %d duration %d\n", err, errno, retval, duration)) + goto cleanup; + + ASSERT_EQ(skel->data->xchg64_value, 2, "xchg64_value"); + ASSERT_EQ(skel->bss->xchg64_result, 1, "xchg64_result"); + + ASSERT_EQ(skel->data->xchg32_value, 2, "xchg32_value"); + ASSERT_EQ(skel->bss->xchg32_result, 1, "xchg32_result"); + +cleanup: + bpf_link__destroy(link); +} + +void test_atomics(void) +{ + struct atomics *skel; + __u32 duration = 0; + + skel = atomics__open_and_load(); + if (CHECK(!skel, "skel_load", "atomics skeleton failed\n")) + return; + + if (skel->data->skip_tests) { + printf("%s:SKIP:no ENABLE_ATOMICS_TESTS (missing Clang BPF atomics support)", + __func__); + test__skip(); + goto cleanup; + } + + if (test__start_subtest("add")) + test_add(skel); + if (test__start_subtest("sub")) + test_sub(skel); + if (test__start_subtest("and")) + test_and(skel); + if (test__start_subtest("or")) + test_or(skel); + if (test__start_subtest("xor")) + test_xor(skel); + if (test__start_subtest("cmpxchg")) + test_cmpxchg(skel); + if (test__start_subtest("xchg")) + test_xchg(skel); + +cleanup: + atomics__destroy(skel); +} diff --git a/tools/testing/selftests/bpf/prog_tests/btf_map_in_map.c b/tools/testing/selftests/bpf/prog_tests/btf_map_in_map.c index 76ebe4c250f1..eb90a6b8850d 100644 --- a/tools/testing/selftests/bpf/prog_tests/btf_map_in_map.c +++ b/tools/testing/selftests/bpf/prog_tests/btf_map_in_map.c @@ -20,39 +20,6 @@ static __u32 bpf_map_id(struct bpf_map *map) return info.id; } -/* - * Trigger synchronize_rcu() in kernel. - * - * ARRAY_OF_MAPS/HASH_OF_MAPS lookup/update operations trigger synchronize_rcu() - * if looking up an existing non-NULL element or updating the map with a valid - * inner map FD. Use this fact to trigger synchronize_rcu(): create map-in-map, - * create a trivial ARRAY map, update map-in-map with ARRAY inner map. Then - * cleanup. At the end, at least one synchronize_rcu() would be called. - */ -static int kern_sync_rcu(void) -{ - int inner_map_fd, outer_map_fd, err, zero = 0; - - inner_map_fd = bpf_create_map(BPF_MAP_TYPE_ARRAY, 4, 4, 1, 0); - if (CHECK(inner_map_fd < 0, "inner_map_create", "failed %d\n", -errno)) - return -1; - - outer_map_fd = bpf_create_map_in_map(BPF_MAP_TYPE_ARRAY_OF_MAPS, NULL, - sizeof(int), inner_map_fd, 1, 0); - if (CHECK(outer_map_fd < 0, "outer_map_create", "failed %d\n", -errno)) { - close(inner_map_fd); - return -1; - } - - err = bpf_map_update_elem(outer_map_fd, &zero, &inner_map_fd, 0); - if (err) - err = -errno; - CHECK(err, "outer_map_update", "failed %d\n", err); - close(inner_map_fd); - close(outer_map_fd); - return err; -} - static void test_lookup_update(void) { int map1_fd, map2_fd, map3_fd, map4_fd, map5_fd, map1_id, map2_id; diff --git a/tools/testing/selftests/bpf/prog_tests/cgroup_attach_multi.c b/tools/testing/selftests/bpf/prog_tests/cgroup_attach_multi.c index b549fcfacc0b..0a1fc9816cef 100644 --- a/tools/testing/selftests/bpf/prog_tests/cgroup_attach_multi.c +++ b/tools/testing/selftests/bpf/prog_tests/cgroup_attach_multi.c @@ -45,13 +45,13 @@ static int prog_load_cnt(int verdict, int val) BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2), BPF_MOV64_IMM(BPF_REG_1, val), /* r1 = 1 */ - BPF_RAW_INSN(BPF_STX | BPF_XADD | BPF_DW, BPF_REG_0, BPF_REG_1, 0, 0), /* xadd r0 += r1 */ + BPF_ATOMIC_OP(BPF_DW, BPF_ADD, BPF_REG_0, BPF_REG_1, 0), BPF_LD_MAP_FD(BPF_REG_1, cgroup_storage_fd), BPF_MOV64_IMM(BPF_REG_2, 0), BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_local_storage), BPF_MOV64_IMM(BPF_REG_1, val), - BPF_RAW_INSN(BPF_STX | BPF_XADD | BPF_W, BPF_REG_0, BPF_REG_1, 0, 0), + BPF_ATOMIC_OP(BPF_W, BPF_ADD, BPF_REG_0, BPF_REG_1, 0), BPF_LD_MAP_FD(BPF_REG_1, percpu_cgroup_storage_fd), BPF_MOV64_IMM(BPF_REG_2, 0), diff --git a/tools/testing/selftests/bpf/prog_tests/core_read_macros.c b/tools/testing/selftests/bpf/prog_tests/core_read_macros.c new file mode 100644 index 000000000000..96f5cf3c6fa2 --- /dev/null +++ b/tools/testing/selftests/bpf/prog_tests/core_read_macros.c @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2020 Facebook */ + +#include <test_progs.h> + +struct callback_head { + struct callback_head *next; + void (*func)(struct callback_head *head); +}; + +/* ___shuffled flavor is just an illusion for BPF code, it doesn't really + * exist and user-space needs to provide data in the memory layout that + * matches callback_head. We just defined ___shuffled flavor to make it easier + * to work with the skeleton + */ +struct callback_head___shuffled { + struct callback_head___shuffled *next; + void (*func)(struct callback_head *head); +}; + +#include "test_core_read_macros.skel.h" + +void test_core_read_macros(void) +{ + int duration = 0, err; + struct test_core_read_macros* skel; + struct test_core_read_macros__bss *bss; + struct callback_head u_probe_in; + struct callback_head___shuffled u_core_in; + + skel = test_core_read_macros__open_and_load(); + if (CHECK(!skel, "skel_open", "failed to open skeleton\n")) + return; + bss = skel->bss; + bss->my_pid = getpid(); + + /* next pointers have to be set from the kernel side */ + bss->k_probe_in.func = (void *)(long)0x1234; + bss->k_core_in.func = (void *)(long)0xabcd; + + u_probe_in.next = &u_probe_in; + u_probe_in.func = (void *)(long)0x5678; + bss->u_probe_in = &u_probe_in; + + u_core_in.next = &u_core_in; + u_core_in.func = (void *)(long)0xdbca; + bss->u_core_in = &u_core_in; + + err = test_core_read_macros__attach(skel); + if (CHECK(err, "skel_attach", "skeleton attach failed: %d\n", err)) + goto cleanup; + + /* trigger tracepoint */ + usleep(1); + + ASSERT_EQ(bss->k_probe_out, 0x1234, "k_probe_out"); + ASSERT_EQ(bss->k_core_out, 0xabcd, "k_core_out"); + + ASSERT_EQ(bss->u_probe_out, 0x5678, "u_probe_out"); + ASSERT_EQ(bss->u_core_out, 0xdbca, "u_core_out"); + +cleanup: + test_core_read_macros__destroy(skel); +} diff --git a/tools/testing/selftests/bpf/prog_tests/ksyms_module.c b/tools/testing/selftests/bpf/prog_tests/ksyms_module.c new file mode 100644 index 000000000000..4c232b456479 --- /dev/null +++ b/tools/testing/selftests/bpf/prog_tests/ksyms_module.c @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2021 Facebook */ + +#include <test_progs.h> +#include <bpf/libbpf.h> +#include <bpf/btf.h> +#include "test_ksyms_module.skel.h" + +static int duration; + +void test_ksyms_module(void) +{ + struct test_ksyms_module* skel; + int err; + + skel = test_ksyms_module__open_and_load(); + if (CHECK(!skel, "skel_open", "failed to open skeleton\n")) + return; + + err = test_ksyms_module__attach(skel); + if (CHECK(err, "skel_attach", "skeleton attach failed: %d\n", err)) + goto cleanup; + + usleep(1); + + ASSERT_EQ(skel->bss->triggered, true, "triggered"); + ASSERT_EQ(skel->bss->out_mod_ksym_global, 123, "global_ksym_val"); + +cleanup: + test_ksyms_module__destroy(skel); +} diff --git a/tools/testing/selftests/bpf/prog_tests/test_lsm.c b/tools/testing/selftests/bpf/prog_tests/test_lsm.c index 6ab29226c99b..2755e4f81499 100644 --- a/tools/testing/selftests/bpf/prog_tests/test_lsm.c +++ b/tools/testing/selftests/bpf/prog_tests/test_lsm.c @@ -10,7 +10,6 @@ #include <unistd.h> #include <malloc.h> #include <stdlib.h> -#include <unistd.h> #include "lsm.skel.h" diff --git a/tools/testing/selftests/bpf/progs/atomics.c b/tools/testing/selftests/bpf/progs/atomics.c new file mode 100644 index 000000000000..c245345e41ca --- /dev/null +++ b/tools/testing/selftests/bpf/progs/atomics.c @@ -0,0 +1,154 @@ +// SPDX-License-Identifier: GPL-2.0 +#include <linux/bpf.h> +#include <bpf/bpf_helpers.h> +#include <bpf/bpf_tracing.h> +#include <stdbool.h> + +#ifdef ENABLE_ATOMICS_TESTS +bool skip_tests __attribute((__section__(".data"))) = false; +#else +bool skip_tests = true; +#endif + +__u64 add64_value = 1; +__u64 add64_result = 0; +__u32 add32_value = 1; +__u32 add32_result = 0; +__u64 add_stack_value_copy = 0; +__u64 add_stack_result = 0; +__u64 add_noreturn_value = 1; + +SEC("fentry/bpf_fentry_test1") +int BPF_PROG(add, int a) +{ +#ifdef ENABLE_ATOMICS_TESTS + __u64 add_stack_value = 1; + + add64_result = __sync_fetch_and_add(&add64_value, 2); + add32_result = __sync_fetch_and_add(&add32_value, 2); + add_stack_result = __sync_fetch_and_add(&add_stack_value, 2); + add_stack_value_copy = add_stack_value; + __sync_fetch_and_add(&add_noreturn_value, 2); +#endif + + return 0; +} + +__s64 sub64_value = 1; +__s64 sub64_result = 0; +__s32 sub32_value = 1; +__s32 sub32_result = 0; +__s64 sub_stack_value_copy = 0; +__s64 sub_stack_result = 0; +__s64 sub_noreturn_value = 1; + +SEC("fentry/bpf_fentry_test1") +int BPF_PROG(sub, int a) +{ +#ifdef ENABLE_ATOMICS_TESTS + __u64 sub_stack_value = 1; + + sub64_result = __sync_fetch_and_sub(&sub64_value, 2); + sub32_result = __sync_fetch_and_sub(&sub32_value, 2); + sub_stack_result = __sync_fetch_and_sub(&sub_stack_value, 2); + sub_stack_value_copy = sub_stack_value; + __sync_fetch_and_sub(&sub_noreturn_value, 2); +#endif + + return 0; +} + +__u64 and64_value = (0x110ull << 32); +__u64 and64_result = 0; +__u32 and32_value = 0x110; +__u32 and32_result = 0; +__u64 and_noreturn_value = (0x110ull << 32); + +SEC("fentry/bpf_fentry_test1") +int BPF_PROG(and, int a) +{ +#ifdef ENABLE_ATOMICS_TESTS + + and64_result = __sync_fetch_and_and(&and64_value, 0x011ull << 32); + and32_result = __sync_fetch_and_and(&and32_value, 0x011); + __sync_fetch_and_and(&and_noreturn_value, 0x011ull << 32); +#endif + + return 0; +} + +__u64 or64_value = (0x110ull << 32); +__u64 or64_result = 0; +__u32 or32_value = 0x110; +__u32 or32_result = 0; +__u64 or_noreturn_value = (0x110ull << 32); + +SEC("fentry/bpf_fentry_test1") +int BPF_PROG(or, int a) +{ +#ifdef ENABLE_ATOMICS_TESTS + or64_result = __sync_fetch_and_or(&or64_value, 0x011ull << 32); + or32_result = __sync_fetch_and_or(&or32_value, 0x011); + __sync_fetch_and_or(&or_noreturn_value, 0x011ull << 32); +#endif + + return 0; +} + +__u64 xor64_value = (0x110ull << 32); +__u64 xor64_result = 0; +__u32 xor32_value = 0x110; +__u32 xor32_result = 0; +__u64 xor_noreturn_value = (0x110ull << 32); + +SEC("fentry/bpf_fentry_test1") +int BPF_PROG(xor, int a) +{ +#ifdef ENABLE_ATOMICS_TESTS + xor64_result = __sync_fetch_and_xor(&xor64_value, 0x011ull << 32); + xor32_result = __sync_fetch_and_xor(&xor32_value, 0x011); + __sync_fetch_and_xor(&xor_noreturn_value, 0x011ull << 32); +#endif + + return 0; +} + +__u64 cmpxchg64_value = 1; +__u64 cmpxchg64_result_fail = 0; +__u64 cmpxchg64_result_succeed = 0; +__u32 cmpxchg32_value = 1; +__u32 cmpxchg32_result_fail = 0; +__u32 cmpxchg32_result_succeed = 0; + +SEC("fentry/bpf_fentry_test1") +int BPF_PROG(cmpxchg, int a) +{ +#ifdef ENABLE_ATOMICS_TESTS + cmpxchg64_result_fail = __sync_val_compare_and_swap(&cmpxchg64_value, 0, 3); + cmpxchg64_result_succeed = __sync_val_compare_and_swap(&cmpxchg64_value, 1, 2); + + cmpxchg32_result_fail = __sync_val_compare_and_swap(&cmpxchg32_value, 0, 3); + cmpxchg32_result_succeed = __sync_val_compare_and_swap(&cmpxchg32_value, 1, 2); +#endif + + return 0; +} + +__u64 xchg64_value = 1; +__u64 xchg64_result = 0; +__u32 xchg32_value = 1; +__u32 xchg32_result = 0; + +SEC("fentry/bpf_fentry_test1") +int BPF_PROG(xchg, int a) +{ +#ifdef ENABLE_ATOMICS_TESTS + __u64 val64 = 2; + __u32 val32 = 2; + + xchg64_result = __sync_lock_test_and_set(&xchg64_value, val64); + xchg32_result = __sync_lock_test_and_set(&xchg32_value, val32); +#endif + + return 0; +} diff --git a/tools/testing/selftests/bpf/progs/bind4_prog.c b/tools/testing/selftests/bpf/progs/bind4_prog.c index c6520f21f5f5..115a3b0ad984 100644 --- a/tools/testing/selftests/bpf/progs/bind4_prog.c +++ b/tools/testing/selftests/bpf/progs/bind4_prog.c @@ -29,18 +29,48 @@ static __inline int bind_to_device(struct bpf_sock_addr *ctx) char veth2[IFNAMSIZ] = "test_sock_addr2"; char missing[IFNAMSIZ] = "nonexistent_dev"; char del_bind[IFNAMSIZ] = ""; + int veth1_idx, veth2_idx; if (bpf_setsockopt(ctx, SOL_SOCKET, SO_BINDTODEVICE, - &veth1, sizeof(veth1))) + &veth1, sizeof(veth1))) + return 1; + if (bpf_getsockopt(ctx, SOL_SOCKET, SO_BINDTOIFINDEX, + &veth1_idx, sizeof(veth1_idx)) || !veth1_idx) return 1; if (bpf_setsockopt(ctx, SOL_SOCKET, SO_BINDTODEVICE, - &veth2, sizeof(veth2))) + &veth2, sizeof(veth2))) + return 1; + if (bpf_getsockopt(ctx, SOL_SOCKET, SO_BINDTOIFINDEX, + &veth2_idx, sizeof(veth2_idx)) || !veth2_idx || + veth1_idx == veth2_idx) return 1; if (bpf_setsockopt(ctx, SOL_SOCKET, SO_BINDTODEVICE, - &missing, sizeof(missing)) != -ENODEV) + &missing, sizeof(missing)) != -ENODEV) + return 1; + if (bpf_setsockopt(ctx, SOL_SOCKET, SO_BINDTOIFINDEX, + &veth1_idx, sizeof(veth1_idx))) return 1; if (bpf_setsockopt(ctx, SOL_SOCKET, SO_BINDTODEVICE, - &del_bind, sizeof(del_bind))) + &del_bind, sizeof(del_bind))) + return 1; + + return 0; +} + +static __inline int misc_opts(struct bpf_sock_addr *ctx, int opt) +{ + int old, tmp, new = 0xeb9f; + + /* Socket in test case has guarantee that old never equals to new. */ + if (bpf_getsockopt(ctx, SOL_SOCKET, opt, &old, sizeof(old)) || + old == new) + return 1; + if (bpf_setsockopt(ctx, SOL_SOCKET, opt, &new, sizeof(new))) + return 1; + if (bpf_getsockopt(ctx, SOL_SOCKET, opt, &tmp, sizeof(tmp)) || + tmp != new) + return 1; + if (bpf_setsockopt(ctx, SOL_SOCKET, opt, &old, sizeof(old))) return 1; return 0; @@ -93,6 +123,10 @@ int bind_v4_prog(struct bpf_sock_addr *ctx) if (bind_to_device(ctx)) return 0; + /* Test for misc socket options. */ + if (misc_opts(ctx, SO_MARK) || misc_opts(ctx, SO_PRIORITY)) + return 0; + ctx->user_ip4 = bpf_htonl(SERV4_REWRITE_IP); ctx->user_port = bpf_htons(SERV4_REWRITE_PORT); diff --git a/tools/testing/selftests/bpf/progs/bind6_prog.c b/tools/testing/selftests/bpf/progs/bind6_prog.c index 4358e44dcf47..4c0d348034b9 100644 --- a/tools/testing/selftests/bpf/progs/bind6_prog.c +++ b/tools/testing/selftests/bpf/progs/bind6_prog.c @@ -35,18 +35,48 @@ static __inline int bind_to_device(struct bpf_sock_addr *ctx) char veth2[IFNAMSIZ] = "test_sock_addr2"; char missing[IFNAMSIZ] = "nonexistent_dev"; char del_bind[IFNAMSIZ] = ""; + int veth1_idx, veth2_idx; if (bpf_setsockopt(ctx, SOL_SOCKET, SO_BINDTODEVICE, - &veth1, sizeof(veth1))) + &veth1, sizeof(veth1))) + return 1; + if (bpf_getsockopt(ctx, SOL_SOCKET, SO_BINDTOIFINDEX, + &veth1_idx, sizeof(veth1_idx)) || !veth1_idx) return 1; if (bpf_setsockopt(ctx, SOL_SOCKET, SO_BINDTODEVICE, - &veth2, sizeof(veth2))) + &veth2, sizeof(veth2))) + return 1; + if (bpf_getsockopt(ctx, SOL_SOCKET, SO_BINDTOIFINDEX, + &veth2_idx, sizeof(veth2_idx)) || !veth2_idx || + veth1_idx == veth2_idx) return 1; if (bpf_setsockopt(ctx, SOL_SOCKET, SO_BINDTODEVICE, - &missing, sizeof(missing)) != -ENODEV) + &missing, sizeof(missing)) != -ENODEV) + return 1; + if (bpf_setsockopt(ctx, SOL_SOCKET, SO_BINDTOIFINDEX, + &veth1_idx, sizeof(veth1_idx))) return 1; if (bpf_setsockopt(ctx, SOL_SOCKET, SO_BINDTODEVICE, - &del_bind, sizeof(del_bind))) + &del_bind, sizeof(del_bind))) + return 1; + + return 0; +} + +static __inline int misc_opts(struct bpf_sock_addr *ctx, int opt) +{ + int old, tmp, new = 0xeb9f; + + /* Socket in test case has guarantee that old never equals to new. */ + if (bpf_getsockopt(ctx, SOL_SOCKET, opt, &old, sizeof(old)) || + old == new) + return 1; + if (bpf_setsockopt(ctx, SOL_SOCKET, opt, &new, sizeof(new))) + return 1; + if (bpf_getsockopt(ctx, SOL_SOCKET, opt, &tmp, sizeof(tmp)) || + tmp != new) + return 1; + if (bpf_setsockopt(ctx, SOL_SOCKET, opt, &old, sizeof(old))) return 1; return 0; @@ -107,6 +137,10 @@ int bind_v6_prog(struct bpf_sock_addr *ctx) if (bind_to_device(ctx)) return 0; + /* Test for misc socket options. */ + if (misc_opts(ctx, SO_MARK) || misc_opts(ctx, SO_PRIORITY)) + return 0; + ctx->user_ip6[0] = bpf_htonl(SERV6_REWRITE_IP_0); ctx->user_ip6[1] = bpf_htonl(SERV6_REWRITE_IP_1); ctx->user_ip6[2] = bpf_htonl(SERV6_REWRITE_IP_2); diff --git a/tools/testing/selftests/bpf/progs/test_core_read_macros.c b/tools/testing/selftests/bpf/progs/test_core_read_macros.c new file mode 100644 index 000000000000..fd54caa17319 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/test_core_read_macros.c @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2020 Facebook + +#include "vmlinux.h" +#include <bpf/bpf_helpers.h> +#include <bpf/bpf_core_read.h> + +char _license[] SEC("license") = "GPL"; + +/* shuffled layout for relocatable (CO-RE) reads */ +struct callback_head___shuffled { + void (*func)(struct callback_head___shuffled *head); + struct callback_head___shuffled *next; +}; + +struct callback_head k_probe_in = {}; +struct callback_head___shuffled k_core_in = {}; + +struct callback_head *u_probe_in = 0; +struct callback_head___shuffled *u_core_in = 0; + +long k_probe_out = 0; +long u_probe_out = 0; + +long k_core_out = 0; +long u_core_out = 0; + +int my_pid = 0; + +SEC("raw_tracepoint/sys_enter") +int handler(void *ctx) +{ + int pid = bpf_get_current_pid_tgid() >> 32; + + if (my_pid != pid) + return 0; + + /* next pointers for kernel address space have to be initialized from + * BPF side, user-space mmaped addresses are stil user-space addresses + */ + k_probe_in.next = &k_probe_in; + __builtin_preserve_access_index(({k_core_in.next = &k_core_in;})); + + k_probe_out = (long)BPF_PROBE_READ(&k_probe_in, next, next, func); + k_core_out = (long)BPF_CORE_READ(&k_core_in, next, next, func); + u_probe_out = (long)BPF_PROBE_READ_USER(u_probe_in, next, next, func); + u_core_out = (long)BPF_CORE_READ_USER(u_core_in, next, next, func); + + return 0; +} diff --git a/tools/testing/selftests/bpf/progs/test_ksyms_module.c b/tools/testing/selftests/bpf/progs/test_ksyms_module.c new file mode 100644 index 000000000000..d6a0b3086b90 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/test_ksyms_module.c @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2021 Facebook */ + +#include "vmlinux.h" + +#include <bpf/bpf_helpers.h> + +extern const int bpf_testmod_ksym_percpu __ksym; + +int out_mod_ksym_global = 0; +bool triggered = false; + +SEC("raw_tp/sys_enter") +int handler(const void *ctx) +{ + int *val; + __u32 cpu; + + val = (int *)bpf_this_cpu_ptr(&bpf_testmod_ksym_percpu); + out_mod_ksym_global = *val; + triggered = true; + + return 0; +} + +char LICENSE[] SEC("license") = "GPL"; diff --git a/tools/testing/selftests/bpf/test_cgroup_storage.c b/tools/testing/selftests/bpf/test_cgroup_storage.c index d946252a25bb..0cda61da5d39 100644 --- a/tools/testing/selftests/bpf/test_cgroup_storage.c +++ b/tools/testing/selftests/bpf/test_cgroup_storage.c @@ -29,7 +29,7 @@ int main(int argc, char **argv) BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_local_storage), BPF_MOV64_IMM(BPF_REG_1, 1), - BPF_STX_XADD(BPF_DW, BPF_REG_0, BPF_REG_1, 0), + BPF_ATOMIC_OP(BPF_DW, BPF_ADD, BPF_REG_0, BPF_REG_1, 0), BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0), BPF_ALU64_IMM(BPF_AND, BPF_REG_1, 0x1), BPF_MOV64_REG(BPF_REG_0, BPF_REG_1), diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c index 7d077d48cadd..213628ee721c 100644 --- a/tools/testing/selftests/bpf/test_progs.c +++ b/tools/testing/selftests/bpf/test_progs.c @@ -11,6 +11,7 @@ #include <signal.h> #include <string.h> #include <execinfo.h> /* backtrace */ +#include <linux/membarrier.h> #define EXIT_NO_TEST 2 #define EXIT_ERR_SETUP_INFRA 3 @@ -370,8 +371,18 @@ static int delete_module(const char *name, int flags) return syscall(__NR_delete_module, name, flags); } +/* + * Trigger synchronize_rcu() in kernel. + */ +int kern_sync_rcu(void) +{ + return syscall(__NR_membarrier, MEMBARRIER_CMD_SHARED, 0, 0); +} + static void unload_bpf_testmod(void) { + if (kern_sync_rcu()) + fprintf(env.stderr, "Failed to trigger kernel-side RCU sync!\n"); if (delete_module("bpf_testmod", 0)) { if (errno == ENOENT) { if (env.verbosity > VERBOSE_NONE) diff --git a/tools/testing/selftests/bpf/test_progs.h b/tools/testing/selftests/bpf/test_progs.h index 115953243f62..e49e2fdde942 100644 --- a/tools/testing/selftests/bpf/test_progs.h +++ b/tools/testing/selftests/bpf/test_progs.h @@ -219,6 +219,7 @@ int bpf_find_map(const char *test, struct bpf_object *obj, const char *name); int compare_map_keys(int map1_fd, int map2_fd); int compare_stack_ips(int smap_fd, int amap_fd, int stack_trace_len); int extract_build_id(char *build_id, size_t size); +int kern_sync_rcu(void); #ifdef __x86_64__ #define SYS_NANOSLEEP_KPROBE_NAME "__x64_sys_nanosleep" diff --git a/tools/testing/selftests/bpf/verifier/atomic_and.c b/tools/testing/selftests/bpf/verifier/atomic_and.c new file mode 100644 index 000000000000..600bc5e0f143 --- /dev/null +++ b/tools/testing/selftests/bpf/verifier/atomic_and.c @@ -0,0 +1,77 @@ +{ + "BPF_ATOMIC_AND without fetch", + .insns = { + /* val = 0x110; */ + BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0x110), + /* atomic_and(&val, 0x011); */ + BPF_MOV64_IMM(BPF_REG_1, 0x011), + BPF_ATOMIC_OP(BPF_DW, BPF_AND, BPF_REG_10, BPF_REG_1, -8), + /* if (val != 0x010) exit(2); */ + BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_10, -8), + BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0x010, 2), + BPF_MOV64_IMM(BPF_REG_0, 2), + BPF_EXIT_INSN(), + /* r1 should not be clobbered, no BPF_FETCH flag */ + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0x011, 1), + BPF_MOV64_IMM(BPF_REG_0, 1), + BPF_EXIT_INSN(), + }, + .result = ACCEPT, +}, +{ + "BPF_ATOMIC_AND with fetch", + .insns = { + BPF_MOV64_IMM(BPF_REG_0, 123), + /* val = 0x110; */ + BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0x110), + /* old = atomic_fetch_and(&val, 0x011); */ + BPF_MOV64_IMM(BPF_REG_1, 0x011), + BPF_ATOMIC_OP(BPF_DW, BPF_AND | BPF_FETCH, BPF_REG_10, BPF_REG_1, -8), + /* if (old != 0x110) exit(3); */ + BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0x110, 2), + BPF_MOV64_IMM(BPF_REG_0, 3), + BPF_EXIT_INSN(), + /* if (val != 0x010) exit(2); */ + BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -8), + BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0x010, 2), + BPF_MOV64_IMM(BPF_REG_1, 2), + BPF_EXIT_INSN(), + /* Check R0 wasn't clobbered (for fear of x86 JIT bug) */ + BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 123, 2), + BPF_MOV64_IMM(BPF_REG_0, 1), + BPF_EXIT_INSN(), + /* exit(0); */ + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_EXIT_INSN(), + }, + .result = ACCEPT, +}, +{ + "BPF_ATOMIC_AND with fetch 32bit", + .insns = { + /* r0 = (s64) -1 */ + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_ALU64_IMM(BPF_SUB, BPF_REG_0, 1), + /* val = 0x110; */ + BPF_ST_MEM(BPF_W, BPF_REG_10, -4, 0x110), + /* old = atomic_fetch_and(&val, 0x011); */ + BPF_MOV32_IMM(BPF_REG_1, 0x011), + BPF_ATOMIC_OP(BPF_W, BPF_AND | BPF_FETCH, BPF_REG_10, BPF_REG_1, -4), + /* if (old != 0x110) exit(3); */ + BPF_JMP32_IMM(BPF_JEQ, BPF_REG_1, 0x110, 2), + BPF_MOV32_IMM(BPF_REG_0, 3), + BPF_EXIT_INSN(), + /* if (val != 0x010) exit(2); */ + BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_10, -4), + BPF_JMP32_IMM(BPF_JEQ, BPF_REG_1, 0x010, 2), + BPF_MOV32_IMM(BPF_REG_1, 2), + BPF_EXIT_INSN(), + /* Check R0 wasn't clobbered (for fear of x86 JIT bug) + * It should be -1 so add 1 to get exit code. + */ + BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1), + BPF_EXIT_INSN(), + }, + .result = ACCEPT, +}, diff --git a/tools/testing/selftests/bpf/verifier/atomic_cmpxchg.c b/tools/testing/selftests/bpf/verifier/atomic_cmpxchg.c new file mode 100644 index 000000000000..2efd8bcf57a1 --- /dev/null +++ b/tools/testing/selftests/bpf/verifier/atomic_cmpxchg.c @@ -0,0 +1,96 @@ +{ + "atomic compare-and-exchange smoketest - 64bit", + .insns = { + /* val = 3; */ + BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 3), + /* old = atomic_cmpxchg(&val, 2, 4); */ + BPF_MOV64_IMM(BPF_REG_1, 4), + BPF_MOV64_IMM(BPF_REG_0, 2), + BPF_ATOMIC_OP(BPF_DW, BPF_CMPXCHG, BPF_REG_10, BPF_REG_1, -8), + /* if (old != 3) exit(2); */ + BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 3, 2), + BPF_MOV64_IMM(BPF_REG_0, 2), + BPF_EXIT_INSN(), + /* if (val != 3) exit(3); */ + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_10, -8), + BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 3, 2), + BPF_MOV64_IMM(BPF_REG_0, 3), + BPF_EXIT_INSN(), + /* old = atomic_cmpxchg(&val, 3, 4); */ + BPF_MOV64_IMM(BPF_REG_1, 4), + BPF_MOV64_IMM(BPF_REG_0, 3), + BPF_ATOMIC_OP(BPF_DW, BPF_CMPXCHG, BPF_REG_10, BPF_REG_1, -8), + /* if (old != 3) exit(4); */ + BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 3, 2), + BPF_MOV64_IMM(BPF_REG_0, 4), + BPF_EXIT_INSN(), + /* if (val != 4) exit(5); */ + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_10, -8), + BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 4, 2), + BPF_MOV64_IMM(BPF_REG_0, 5), + BPF_EXIT_INSN(), + /* exit(0); */ + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_EXIT_INSN(), + }, + .result = ACCEPT, +}, +{ + "atomic compare-and-exchange smoketest - 32bit", + .insns = { + /* val = 3; */ + BPF_ST_MEM(BPF_W, BPF_REG_10, -4, 3), + /* old = atomic_cmpxchg(&val, 2, 4); */ + BPF_MOV32_IMM(BPF_REG_1, 4), + BPF_MOV32_IMM(BPF_REG_0, 2), + BPF_ATOMIC_OP(BPF_W, BPF_CMPXCHG, BPF_REG_10, BPF_REG_1, -4), + /* if (old != 3) exit(2); */ + BPF_JMP32_IMM(BPF_JEQ, BPF_REG_0, 3, 2), + BPF_MOV32_IMM(BPF_REG_0, 2), + BPF_EXIT_INSN(), + /* if (val != 3) exit(3); */ + BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_10, -4), + BPF_JMP32_IMM(BPF_JEQ, BPF_REG_0, 3, 2), + BPF_MOV32_IMM(BPF_REG_0, 3), + BPF_EXIT_INSN(), + /* old = atomic_cmpxchg(&val, 3, 4); */ + BPF_MOV32_IMM(BPF_REG_1, 4), + BPF_MOV32_IMM(BPF_REG_0, 3), + BPF_ATOMIC_OP(BPF_W, BPF_CMPXCHG, BPF_REG_10, BPF_REG_1, -4), + /* if (old != 3) exit(4); */ + BPF_JMP32_IMM(BPF_JEQ, BPF_REG_0, 3, 2), + BPF_MOV32_IMM(BPF_REG_0, 4), + BPF_EXIT_INSN(), + /* if (val != 4) exit(5); */ + BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_10, -4), + BPF_JMP32_IMM(BPF_JEQ, BPF_REG_0, 4, 2), + BPF_MOV32_IMM(BPF_REG_0, 5), + BPF_EXIT_INSN(), + /* exit(0); */ + BPF_MOV32_IMM(BPF_REG_0, 0), + BPF_EXIT_INSN(), + }, + .result = ACCEPT, +}, +{ + "Can't use cmpxchg on uninit src reg", + .insns = { + BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 3), + BPF_MOV64_IMM(BPF_REG_0, 3), + BPF_ATOMIC_OP(BPF_DW, BPF_CMPXCHG, BPF_REG_10, BPF_REG_2, -8), + BPF_EXIT_INSN(), + }, + .result = REJECT, + .errstr = "!read_ok", +}, +{ + "Can't use cmpxchg on uninit memory", + .insns = { + BPF_MOV64_IMM(BPF_REG_0, 3), + BPF_MOV64_IMM(BPF_REG_2, 4), + BPF_ATOMIC_OP(BPF_DW, BPF_CMPXCHG, BPF_REG_10, BPF_REG_2, -8), + BPF_EXIT_INSN(), + }, + .result = REJECT, + .errstr = "invalid read from stack", +}, diff --git a/tools/testing/selftests/bpf/verifier/atomic_fetch_add.c b/tools/testing/selftests/bpf/verifier/atomic_fetch_add.c new file mode 100644 index 000000000000..a91de8cd9def --- /dev/null +++ b/tools/testing/selftests/bpf/verifier/atomic_fetch_add.c @@ -0,0 +1,106 @@ +{ + "BPF_ATOMIC_FETCH_ADD smoketest - 64bit", + .insns = { + BPF_MOV64_IMM(BPF_REG_0, 0), + /* Write 3 to stack */ + BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 3), + /* Put a 1 in R1, add it to the 3 on the stack, and load the value back into R1 */ + BPF_MOV64_IMM(BPF_REG_1, 1), + BPF_ATOMIC_OP(BPF_DW, BPF_ADD | BPF_FETCH, BPF_REG_10, BPF_REG_1, -8), + /* Check the value we loaded back was 3 */ + BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 3, 2), + BPF_MOV64_IMM(BPF_REG_0, 1), + BPF_EXIT_INSN(), + /* Load value from stack */ + BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -8), + /* Check value loaded from stack was 4 */ + BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 4, 1), + BPF_MOV64_IMM(BPF_REG_0, 2), + BPF_EXIT_INSN(), + }, + .result = ACCEPT, +}, +{ + "BPF_ATOMIC_FETCH_ADD smoketest - 32bit", + .insns = { + BPF_MOV64_IMM(BPF_REG_0, 0), + /* Write 3 to stack */ + BPF_ST_MEM(BPF_W, BPF_REG_10, -4, 3), + /* Put a 1 in R1, add it to the 3 on the stack, and load the value back into R1 */ + BPF_MOV32_IMM(BPF_REG_1, 1), + BPF_ATOMIC_OP(BPF_W, BPF_ADD | BPF_FETCH, BPF_REG_10, BPF_REG_1, -4), + /* Check the value we loaded back was 3 */ + BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 3, 2), + BPF_MOV64_IMM(BPF_REG_0, 1), + BPF_EXIT_INSN(), + /* Load value from stack */ + BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_10, -4), + /* Check value loaded from stack was 4 */ + BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 4, 1), + BPF_MOV64_IMM(BPF_REG_0, 2), + BPF_EXIT_INSN(), + }, + .result = ACCEPT, +}, +{ + "Can't use ATM_FETCH_ADD on frame pointer", + .insns = { + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 3), + BPF_ATOMIC_OP(BPF_DW, BPF_ADD | BPF_FETCH, BPF_REG_10, BPF_REG_10, -8), + BPF_EXIT_INSN(), + }, + .result = REJECT, + .errstr_unpriv = "R10 leaks addr into mem", + .errstr = "frame pointer is read only", +}, +{ + "Can't use ATM_FETCH_ADD on uninit src reg", + .insns = { + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 3), + BPF_ATOMIC_OP(BPF_DW, BPF_ADD | BPF_FETCH, BPF_REG_10, BPF_REG_2, -8), + BPF_EXIT_INSN(), + }, + .result = REJECT, + /* It happens that the address leak check is first, but it would also be + * complain about the fact that we're trying to modify R10. + */ + .errstr = "!read_ok", +}, +{ + "Can't use ATM_FETCH_ADD on uninit dst reg", + .insns = { + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_ATOMIC_OP(BPF_DW, BPF_ADD | BPF_FETCH, BPF_REG_2, BPF_REG_0, -8), + BPF_EXIT_INSN(), + }, + .result = REJECT, + /* It happens that the address leak check is first, but it would also be + * complain about the fact that we're trying to modify R10. + */ + .errstr = "!read_ok", +}, +{ + "Can't use ATM_FETCH_ADD on kernel memory", + .insns = { + /* This is an fentry prog, context is array of the args of the + * kernel function being called. Load first arg into R2. + */ + BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, 0), + /* First arg of bpf_fentry_test7 is a pointer to a struct. + * Attempt to modify that struct. Verifier shouldn't let us + * because it's kernel memory. + */ + BPF_MOV64_IMM(BPF_REG_3, 1), + BPF_ATOMIC_OP(BPF_DW, BPF_ADD | BPF_FETCH, BPF_REG_2, BPF_REG_3, 0), + /* Done */ + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_EXIT_INSN(), + }, + .prog_type = BPF_PROG_TYPE_TRACING, + .expected_attach_type = BPF_TRACE_FENTRY, + .kfunc = "bpf_fentry_test7", + .result = REJECT, + .errstr = "only read is supported", +}, diff --git a/tools/testing/selftests/bpf/verifier/atomic_or.c b/tools/testing/selftests/bpf/verifier/atomic_or.c new file mode 100644 index 000000000000..ebe6e51455ba --- /dev/null +++ b/tools/testing/selftests/bpf/verifier/atomic_or.c @@ -0,0 +1,77 @@ +{ + "BPF_ATOMIC OR without fetch", + .insns = { + /* val = 0x110; */ + BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0x110), + /* atomic_or(&val, 0x011); */ + BPF_MOV64_IMM(BPF_REG_1, 0x011), + BPF_ATOMIC_OP(BPF_DW, BPF_OR, BPF_REG_10, BPF_REG_1, -8), + /* if (val != 0x111) exit(2); */ + BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_10, -8), + BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0x111, 2), + BPF_MOV64_IMM(BPF_REG_0, 2), + BPF_EXIT_INSN(), + /* r1 should not be clobbered, no BPF_FETCH flag */ + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0x011, 1), + BPF_MOV64_IMM(BPF_REG_0, 1), + BPF_EXIT_INSN(), + }, + .result = ACCEPT, +}, +{ + "BPF_ATOMIC OR with fetch", + .insns = { + BPF_MOV64_IMM(BPF_REG_0, 123), + /* val = 0x110; */ + BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0x110), + /* old = atomic_fetch_or(&val, 0x011); */ + BPF_MOV64_IMM(BPF_REG_1, 0x011), + BPF_ATOMIC_OP(BPF_DW, BPF_OR | BPF_FETCH, BPF_REG_10, BPF_REG_1, -8), + /* if (old != 0x110) exit(3); */ + BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0x110, 2), + BPF_MOV64_IMM(BPF_REG_0, 3), + BPF_EXIT_INSN(), + /* if (val != 0x111) exit(2); */ + BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -8), + BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0x111, 2), + BPF_MOV64_IMM(BPF_REG_1, 2), + BPF_EXIT_INSN(), + /* Check R0 wasn't clobbered (for fear of x86 JIT bug) */ + BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 123, 2), + BPF_MOV64_IMM(BPF_REG_0, 1), + BPF_EXIT_INSN(), + /* exit(0); */ + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_EXIT_INSN(), + }, + .result = ACCEPT, +}, +{ + "BPF_ATOMIC OR with fetch 32bit", + .insns = { + /* r0 = (s64) -1 */ + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_ALU64_IMM(BPF_SUB, BPF_REG_0, 1), + /* val = 0x110; */ + BPF_ST_MEM(BPF_W, BPF_REG_10, -4, 0x110), + /* old = atomic_fetch_or(&val, 0x011); */ + BPF_MOV32_IMM(BPF_REG_1, 0x011), + BPF_ATOMIC_OP(BPF_W, BPF_OR | BPF_FETCH, BPF_REG_10, BPF_REG_1, -4), + /* if (old != 0x110) exit(3); */ + BPF_JMP32_IMM(BPF_JEQ, BPF_REG_1, 0x110, 2), + BPF_MOV32_IMM(BPF_REG_0, 3), + BPF_EXIT_INSN(), + /* if (val != 0x111) exit(2); */ + BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_10, -4), + BPF_JMP32_IMM(BPF_JEQ, BPF_REG_1, 0x111, 2), + BPF_MOV32_IMM(BPF_REG_1, 2), + BPF_EXIT_INSN(), + /* Check R0 wasn't clobbered (for fear of x86 JIT bug) + * It should be -1 so add 1 to get exit code. + */ + BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1), + BPF_EXIT_INSN(), + }, + .result = ACCEPT, +}, diff --git a/tools/testing/selftests/bpf/verifier/atomic_xchg.c b/tools/testing/selftests/bpf/verifier/atomic_xchg.c new file mode 100644 index 000000000000..33e2d6c973ee --- /dev/null +++ b/tools/testing/selftests/bpf/verifier/atomic_xchg.c @@ -0,0 +1,46 @@ +{ + "atomic exchange smoketest - 64bit", + .insns = { + /* val = 3; */ + BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 3), + /* old = atomic_xchg(&val, 4); */ + BPF_MOV64_IMM(BPF_REG_1, 4), + BPF_ATOMIC_OP(BPF_DW, BPF_XCHG, BPF_REG_10, BPF_REG_1, -8), + /* if (old != 3) exit(1); */ + BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 3, 2), + BPF_MOV64_IMM(BPF_REG_0, 1), + BPF_EXIT_INSN(), + /* if (val != 4) exit(2); */ + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_10, -8), + BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 4, 2), + BPF_MOV64_IMM(BPF_REG_0, 2), + BPF_EXIT_INSN(), + /* exit(0); */ + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_EXIT_INSN(), + }, + .result = ACCEPT, +}, +{ + "atomic exchange smoketest - 32bit", + .insns = { + /* val = 3; */ + BPF_ST_MEM(BPF_W, BPF_REG_10, -4, 3), + /* old = atomic_xchg(&val, 4); */ + BPF_MOV32_IMM(BPF_REG_1, 4), + BPF_ATOMIC_OP(BPF_W, BPF_XCHG, BPF_REG_10, BPF_REG_1, -4), + /* if (old != 3) exit(1); */ + BPF_JMP32_IMM(BPF_JEQ, BPF_REG_1, 3, 2), + BPF_MOV32_IMM(BPF_REG_0, 1), + BPF_EXIT_INSN(), + /* if (val != 4) exit(2); */ + BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_10, -4), + BPF_JMP32_IMM(BPF_JEQ, BPF_REG_0, 4, 2), + BPF_MOV32_IMM(BPF_REG_0, 2), + BPF_EXIT_INSN(), + /* exit(0); */ + BPF_MOV32_IMM(BPF_REG_0, 0), + BPF_EXIT_INSN(), + }, + .result = ACCEPT, +}, diff --git a/tools/testing/selftests/bpf/verifier/atomic_xor.c b/tools/testing/selftests/bpf/verifier/atomic_xor.c new file mode 100644 index 000000000000..eb791e547b47 --- /dev/null +++ b/tools/testing/selftests/bpf/verifier/atomic_xor.c @@ -0,0 +1,77 @@ +{ + "BPF_ATOMIC XOR without fetch", + .insns = { + /* val = 0x110; */ + BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0x110), + /* atomic_xor(&val, 0x011); */ + BPF_MOV64_IMM(BPF_REG_1, 0x011), + BPF_ATOMIC_OP(BPF_DW, BPF_XOR, BPF_REG_10, BPF_REG_1, -8), + /* if (val != 0x101) exit(2); */ + BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_10, -8), + BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0x101, 2), + BPF_MOV64_IMM(BPF_REG_0, 2), + BPF_EXIT_INSN(), + /* r1 should not be clobbered, no BPF_FETCH flag */ + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0x011, 1), + BPF_MOV64_IMM(BPF_REG_0, 1), + BPF_EXIT_INSN(), + }, + .result = ACCEPT, +}, +{ + "BPF_ATOMIC XOR with fetch", + .insns = { + BPF_MOV64_IMM(BPF_REG_0, 123), + /* val = 0x110; */ + BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0x110), + /* old = atomic_fetch_xor(&val, 0x011); */ + BPF_MOV64_IMM(BPF_REG_1, 0x011), + BPF_ATOMIC_OP(BPF_DW, BPF_XOR | BPF_FETCH, BPF_REG_10, BPF_REG_1, -8), + /* if (old != 0x110) exit(3); */ + BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0x110, 2), + BPF_MOV64_IMM(BPF_REG_0, 3), + BPF_EXIT_INSN(), + /* if (val != 0x101) exit(2); */ + BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -8), + BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0x101, 2), + BPF_MOV64_IMM(BPF_REG_1, 2), + BPF_EXIT_INSN(), + /* Check R0 wasn't clobbered (fxor fear of x86 JIT bug) */ + BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 123, 2), + BPF_MOV64_IMM(BPF_REG_0, 1), + BPF_EXIT_INSN(), + /* exit(0); */ + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_EXIT_INSN(), + }, + .result = ACCEPT, +}, +{ + "BPF_ATOMIC XOR with fetch 32bit", + .insns = { + /* r0 = (s64) -1 */ + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_ALU64_IMM(BPF_SUB, BPF_REG_0, 1), + /* val = 0x110; */ + BPF_ST_MEM(BPF_W, BPF_REG_10, -4, 0x110), + /* old = atomic_fetch_xor(&val, 0x011); */ + BPF_MOV32_IMM(BPF_REG_1, 0x011), + BPF_ATOMIC_OP(BPF_W, BPF_XOR | BPF_FETCH, BPF_REG_10, BPF_REG_1, -4), + /* if (old != 0x110) exit(3); */ + BPF_JMP32_IMM(BPF_JEQ, BPF_REG_1, 0x110, 2), + BPF_MOV32_IMM(BPF_REG_0, 3), + BPF_EXIT_INSN(), + /* if (val != 0x101) exit(2); */ + BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_10, -4), + BPF_JMP32_IMM(BPF_JEQ, BPF_REG_1, 0x101, 2), + BPF_MOV32_IMM(BPF_REG_1, 2), + BPF_EXIT_INSN(), + /* Check R0 wasn't clobbered (fxor fear of x86 JIT bug) + * It should be -1 so add 1 to get exit code. + */ + BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1), + BPF_EXIT_INSN(), + }, + .result = ACCEPT, +}, diff --git a/tools/testing/selftests/bpf/verifier/ctx.c b/tools/testing/selftests/bpf/verifier/ctx.c index 93d6b1641481..23080862aafd 100644 --- a/tools/testing/selftests/bpf/verifier/ctx.c +++ b/tools/testing/selftests/bpf/verifier/ctx.c @@ -10,14 +10,13 @@ .prog_type = BPF_PROG_TYPE_SCHED_CLS, }, { - "context stores via XADD", + "context stores via BPF_ATOMIC", .insns = { BPF_MOV64_IMM(BPF_REG_0, 0), - BPF_RAW_INSN(BPF_STX | BPF_XADD | BPF_W, BPF_REG_1, - BPF_REG_0, offsetof(struct __sk_buff, mark), 0), + BPF_ATOMIC_OP(BPF_W, BPF_ADD, BPF_REG_1, BPF_REG_0, offsetof(struct __sk_buff, mark)), BPF_EXIT_INSN(), }, - .errstr = "BPF_XADD stores into R1 ctx is not allowed", + .errstr = "BPF_ATOMIC stores into R1 ctx is not allowed", .result = REJECT, .prog_type = BPF_PROG_TYPE_SCHED_CLS, }, diff --git a/tools/testing/selftests/bpf/verifier/direct_packet_access.c b/tools/testing/selftests/bpf/verifier/direct_packet_access.c index ae72536603fe..ac1e19d0f520 100644 --- a/tools/testing/selftests/bpf/verifier/direct_packet_access.c +++ b/tools/testing/selftests/bpf/verifier/direct_packet_access.c @@ -333,7 +333,7 @@ BPF_MOV64_REG(BPF_REG_4, BPF_REG_10), BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, -8), BPF_STX_MEM(BPF_DW, BPF_REG_4, BPF_REG_2, 0), - BPF_STX_XADD(BPF_DW, BPF_REG_4, BPF_REG_5, 0), + BPF_ATOMIC_OP(BPF_DW, BPF_ADD, BPF_REG_4, BPF_REG_5, 0), BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_4, 0), BPF_STX_MEM(BPF_W, BPF_REG_2, BPF_REG_5, 0), BPF_MOV64_IMM(BPF_REG_0, 0), @@ -488,7 +488,7 @@ BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 11), BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_10, -8), BPF_MOV64_IMM(BPF_REG_4, 0xffffffff), - BPF_STX_XADD(BPF_DW, BPF_REG_10, BPF_REG_4, -8), + BPF_ATOMIC_OP(BPF_DW, BPF_ADD, BPF_REG_10, BPF_REG_4, -8), BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_10, -8), BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 49), BPF_ALU64_REG(BPF_ADD, BPF_REG_4, BPF_REG_2), diff --git a/tools/testing/selftests/bpf/verifier/leak_ptr.c b/tools/testing/selftests/bpf/verifier/leak_ptr.c index d6eec17f2cd2..73f0dea95546 100644 --- a/tools/testing/selftests/bpf/verifier/leak_ptr.c +++ b/tools/testing/selftests/bpf/verifier/leak_ptr.c @@ -5,7 +5,7 @@ BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, offsetof(struct __sk_buff, cb[0])), BPF_LD_MAP_FD(BPF_REG_2, 0), - BPF_STX_XADD(BPF_DW, BPF_REG_1, BPF_REG_2, + BPF_ATOMIC_OP(BPF_DW, BPF_ADD, BPF_REG_1, BPF_REG_2, offsetof(struct __sk_buff, cb[0])), BPF_EXIT_INSN(), }, @@ -13,7 +13,7 @@ .errstr_unpriv = "R2 leaks addr into mem", .result_unpriv = REJECT, .result = REJECT, - .errstr = "BPF_XADD stores into R1 ctx is not allowed", + .errstr = "BPF_ATOMIC stores into R1 ctx is not allowed", }, { "leak pointer into ctx 2", @@ -21,14 +21,14 @@ BPF_MOV64_IMM(BPF_REG_0, 0), BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, offsetof(struct __sk_buff, cb[0])), - BPF_STX_XADD(BPF_DW, BPF_REG_1, BPF_REG_10, + BPF_ATOMIC_OP(BPF_DW, BPF_ADD, BPF_REG_1, BPF_REG_10, offsetof(struct __sk_buff, cb[0])), BPF_EXIT_INSN(), }, .errstr_unpriv = "R10 leaks addr into mem", .result_unpriv = REJECT, .result = REJECT, - .errstr = "BPF_XADD stores into R1 ctx is not allowed", + .errstr = "BPF_ATOMIC stores into R1 ctx is not allowed", }, { "leak pointer into ctx 3", @@ -56,7 +56,7 @@ BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3), BPF_MOV64_IMM(BPF_REG_3, 0), BPF_STX_MEM(BPF_DW, BPF_REG_0, BPF_REG_3, 0), - BPF_STX_XADD(BPF_DW, BPF_REG_0, BPF_REG_6, 0), + BPF_ATOMIC_OP(BPF_DW, BPF_ADD, BPF_REG_0, BPF_REG_6, 0), BPF_MOV64_IMM(BPF_REG_0, 0), BPF_EXIT_INSN(), }, diff --git a/tools/testing/selftests/bpf/verifier/meta_access.c b/tools/testing/selftests/bpf/verifier/meta_access.c index 205292b8dd65..b45e8af41420 100644 --- a/tools/testing/selftests/bpf/verifier/meta_access.c +++ b/tools/testing/selftests/bpf/verifier/meta_access.c @@ -171,7 +171,7 @@ BPF_MOV64_IMM(BPF_REG_5, 42), BPF_MOV64_IMM(BPF_REG_6, 24), BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_5, -8), - BPF_STX_XADD(BPF_DW, BPF_REG_10, BPF_REG_6, -8), + BPF_ATOMIC_OP(BPF_DW, BPF_ADD, BPF_REG_10, BPF_REG_6, -8), BPF_LDX_MEM(BPF_DW, BPF_REG_5, BPF_REG_10, -8), BPF_JMP_IMM(BPF_JGT, BPF_REG_5, 100, 6), BPF_ALU64_REG(BPF_ADD, BPF_REG_3, BPF_REG_5), @@ -196,7 +196,7 @@ BPF_MOV64_IMM(BPF_REG_5, 42), BPF_MOV64_IMM(BPF_REG_6, 24), BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_5, -8), - BPF_STX_XADD(BPF_DW, BPF_REG_10, BPF_REG_6, -8), + BPF_ATOMIC_OP(BPF_DW, BPF_ADD, BPF_REG_10, BPF_REG_6, -8), BPF_LDX_MEM(BPF_DW, BPF_REG_5, BPF_REG_10, -8), BPF_JMP_IMM(BPF_JGT, BPF_REG_5, 100, 6), BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_5), diff --git a/tools/testing/selftests/bpf/verifier/unpriv.c b/tools/testing/selftests/bpf/verifier/unpriv.c index a3fe0fbaed41..ee298627abae 100644 --- a/tools/testing/selftests/bpf/verifier/unpriv.c +++ b/tools/testing/selftests/bpf/verifier/unpriv.c @@ -207,7 +207,8 @@ BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, -8), BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, 0), BPF_MOV64_IMM(BPF_REG_0, 1), - BPF_RAW_INSN(BPF_STX | BPF_XADD | BPF_DW, BPF_REG_10, BPF_REG_0, -8, 0), + BPF_RAW_INSN(BPF_STX | BPF_ATOMIC | BPF_DW, + BPF_REG_10, BPF_REG_0, -8, BPF_ADD), BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_6, 0), BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_hash_recalc), BPF_EXIT_INSN(), diff --git a/tools/testing/selftests/bpf/verifier/value_illegal_alu.c b/tools/testing/selftests/bpf/verifier/value_illegal_alu.c index ed1c2cea1dea..489062867218 100644 --- a/tools/testing/selftests/bpf/verifier/value_illegal_alu.c +++ b/tools/testing/selftests/bpf/verifier/value_illegal_alu.c @@ -82,7 +82,7 @@ BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_0, 0), - BPF_STX_XADD(BPF_DW, BPF_REG_2, BPF_REG_3, 0), + BPF_ATOMIC_OP(BPF_DW, BPF_ADD, BPF_REG_2, BPF_REG_3, 0), BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_2, 0), BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, 22), BPF_EXIT_INSN(), diff --git a/tools/testing/selftests/bpf/verifier/xadd.c b/tools/testing/selftests/bpf/verifier/xadd.c index c5de2e62cc8b..b96ef3526815 100644 --- a/tools/testing/selftests/bpf/verifier/xadd.c +++ b/tools/testing/selftests/bpf/verifier/xadd.c @@ -3,7 +3,7 @@ .insns = { BPF_MOV64_IMM(BPF_REG_0, 1), BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8), - BPF_STX_XADD(BPF_W, BPF_REG_10, BPF_REG_0, -7), + BPF_ATOMIC_OP(BPF_W, BPF_ADD, BPF_REG_10, BPF_REG_0, -7), BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_10, -8), BPF_EXIT_INSN(), }, @@ -22,7 +22,7 @@ BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), BPF_EXIT_INSN(), BPF_MOV64_IMM(BPF_REG_1, 1), - BPF_STX_XADD(BPF_W, BPF_REG_0, BPF_REG_1, 3), + BPF_ATOMIC_OP(BPF_W, BPF_ADD, BPF_REG_0, BPF_REG_1, 3), BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_0, 3), BPF_EXIT_INSN(), }, @@ -45,13 +45,13 @@ BPF_MOV64_IMM(BPF_REG_0, 1), BPF_ST_MEM(BPF_W, BPF_REG_2, 0, 0), BPF_ST_MEM(BPF_W, BPF_REG_2, 3, 0), - BPF_STX_XADD(BPF_W, BPF_REG_2, BPF_REG_0, 1), - BPF_STX_XADD(BPF_W, BPF_REG_2, BPF_REG_0, 2), + BPF_ATOMIC_OP(BPF_W, BPF_ADD, BPF_REG_2, BPF_REG_0, 1), + BPF_ATOMIC_OP(BPF_W, BPF_ADD, BPF_REG_2, BPF_REG_0, 2), BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_2, 1), BPF_EXIT_INSN(), }, .result = REJECT, - .errstr = "BPF_XADD stores into R2 pkt is not allowed", + .errstr = "BPF_ATOMIC stores into R2 pkt is not allowed", .prog_type = BPF_PROG_TYPE_XDP, .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, }, @@ -62,8 +62,8 @@ BPF_MOV64_REG(BPF_REG_6, BPF_REG_0), BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8), - BPF_STX_XADD(BPF_DW, BPF_REG_10, BPF_REG_0, -8), - BPF_STX_XADD(BPF_DW, BPF_REG_10, BPF_REG_0, -8), + BPF_ATOMIC_OP(BPF_DW, BPF_ADD, BPF_REG_10, BPF_REG_0, -8), + BPF_ATOMIC_OP(BPF_DW, BPF_ADD, BPF_REG_10, BPF_REG_0, -8), BPF_JMP_REG(BPF_JNE, BPF_REG_6, BPF_REG_0, 3), BPF_JMP_REG(BPF_JNE, BPF_REG_7, BPF_REG_10, 2), BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_10, -8), @@ -82,8 +82,8 @@ BPF_MOV64_REG(BPF_REG_6, BPF_REG_0), BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_0, -8), - BPF_STX_XADD(BPF_W, BPF_REG_10, BPF_REG_0, -8), - BPF_STX_XADD(BPF_W, BPF_REG_10, BPF_REG_0, -8), + BPF_ATOMIC_OP(BPF_W, BPF_ADD, BPF_REG_10, BPF_REG_0, -8), + BPF_ATOMIC_OP(BPF_W, BPF_ADD, BPF_REG_10, BPF_REG_0, -8), BPF_JMP_REG(BPF_JNE, BPF_REG_6, BPF_REG_0, 3), BPF_JMP_REG(BPF_JNE, BPF_REG_7, BPF_REG_10, 2), BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_10, -8), diff --git a/tools/testing/selftests/net/fcnal-test.sh b/tools/testing/selftests/net/fcnal-test.sh index 02b0b9ead40b..a8ad92850e63 100755 --- a/tools/testing/selftests/net/fcnal-test.sh +++ b/tools/testing/selftests/net/fcnal-test.sh @@ -801,9 +801,9 @@ ipv4_tcp_md5_novrf() # basic use case log_start - run_cmd nettest -s -M ${MD5_PW} -r ${NSB_IP} & + run_cmd nettest -s -M ${MD5_PW} -m ${NSB_IP} & sleep 1 - run_cmd_nsb nettest -r ${NSA_IP} -M ${MD5_PW} + run_cmd_nsb nettest -r ${NSA_IP} -X ${MD5_PW} log_test $? 0 "MD5: Single address config" # client sends MD5, server not configured @@ -811,23 +811,23 @@ ipv4_tcp_md5_novrf() show_hint "Should timeout due to MD5 mismatch" run_cmd nettest -s & sleep 1 - run_cmd_nsb nettest -r ${NSA_IP} -M ${MD5_PW} + run_cmd_nsb nettest -r ${NSA_IP} -X ${MD5_PW} log_test $? 2 "MD5: Server no config, client uses password" # wrong password log_start show_hint "Should timeout since client uses wrong password" - run_cmd nettest -s -M ${MD5_PW} -r ${NSB_IP} & + run_cmd nettest -s -M ${MD5_PW} -m ${NSB_IP} & sleep 1 - run_cmd_nsb nettest -r ${NSA_IP} -M ${MD5_WRONG_PW} + run_cmd_nsb nettest -r ${NSA_IP} -X ${MD5_WRONG_PW} log_test $? 2 "MD5: Client uses wrong password" # client from different address log_start show_hint "Should timeout due to MD5 mismatch" - run_cmd nettest -s -M ${MD5_PW} -r ${NSB_LO_IP} & + run_cmd nettest -s -M ${MD5_PW} -m ${NSB_LO_IP} & sleep 1 - run_cmd_nsb nettest -r ${NSA_IP} -M ${MD5_PW} + run_cmd_nsb nettest -r ${NSA_IP} -X ${MD5_PW} log_test $? 2 "MD5: Client address does not match address configured with password" # @@ -838,7 +838,7 @@ ipv4_tcp_md5_novrf() log_start run_cmd nettest -s -M ${MD5_PW} -m ${NS_NET} & sleep 1 - run_cmd_nsb nettest -r ${NSA_IP} -M ${MD5_PW} + run_cmd_nsb nettest -r ${NSA_IP} -X ${MD5_PW} log_test $? 0 "MD5: Prefix config" # client in prefix, wrong password @@ -846,7 +846,7 @@ ipv4_tcp_md5_novrf() show_hint "Should timeout since client uses wrong password" run_cmd nettest -s -M ${MD5_PW} -m ${NS_NET} & sleep 1 - run_cmd_nsb nettest -r ${NSA_IP} -M ${MD5_WRONG_PW} + run_cmd_nsb nettest -r ${NSA_IP} -X ${MD5_WRONG_PW} log_test $? 2 "MD5: Prefix config, client uses wrong password" # client outside of prefix @@ -854,7 +854,7 @@ ipv4_tcp_md5_novrf() show_hint "Should timeout due to MD5 mismatch" run_cmd nettest -s -M ${MD5_PW} -m ${NS_NET} & sleep 1 - run_cmd_nsb nettest -l ${NSB_LO_IP} -r ${NSA_IP} -M ${MD5_PW} + run_cmd_nsb nettest -c ${NSB_LO_IP} -r ${NSA_IP} -X ${MD5_PW} log_test $? 2 "MD5: Prefix config, client address not in configured prefix" } @@ -869,33 +869,33 @@ ipv4_tcp_md5() # basic use case log_start - run_cmd nettest -s -d ${VRF} -M ${MD5_PW} -r ${NSB_IP} & + run_cmd nettest -s -I ${VRF} -M ${MD5_PW} -m ${NSB_IP} & sleep 1 - run_cmd_nsb nettest -r ${NSA_IP} -M ${MD5_PW} + run_cmd_nsb nettest -r ${NSA_IP} -X ${MD5_PW} log_test $? 0 "MD5: VRF: Single address config" # client sends MD5, server not configured log_start show_hint "Should timeout since server does not have MD5 auth" - run_cmd nettest -s -d ${VRF} & + run_cmd nettest -s -I ${VRF} & sleep 1 - run_cmd_nsb nettest -r ${NSA_IP} -M ${MD5_PW} + run_cmd_nsb nettest -r ${NSA_IP} -X ${MD5_PW} log_test $? 2 "MD5: VRF: Server no config, client uses password" # wrong password log_start show_hint "Should timeout since client uses wrong password" - run_cmd nettest -s -d ${VRF} -M ${MD5_PW} -r ${NSB_IP} & + run_cmd nettest -s -I ${VRF} -M ${MD5_PW} -m ${NSB_IP} & sleep 1 - run_cmd_nsb nettest -r ${NSA_IP} -M ${MD5_WRONG_PW} + run_cmd_nsb nettest -r ${NSA_IP} -X ${MD5_WRONG_PW} log_test $? 2 "MD5: VRF: Client uses wrong password" # client from different address log_start show_hint "Should timeout since server config differs from client" - run_cmd nettest -s -d ${VRF} -M ${MD5_PW} -r ${NSB_LO_IP} & + run_cmd nettest -s -I ${VRF} -M ${MD5_PW} -m ${NSB_LO_IP} & sleep 1 - run_cmd_nsb nettest -r ${NSA_IP} -M ${MD5_PW} + run_cmd_nsb nettest -r ${NSA_IP} -X ${MD5_PW} log_test $? 2 "MD5: VRF: Client address does not match address configured with password" # @@ -904,25 +904,25 @@ ipv4_tcp_md5() # client in prefix log_start - run_cmd nettest -s -d ${VRF} -M ${MD5_PW} -m ${NS_NET} & + run_cmd nettest -s -I ${VRF} -M ${MD5_PW} -m ${NS_NET} & sleep 1 - run_cmd_nsb nettest -r ${NSA_IP} -M ${MD5_PW} + run_cmd_nsb nettest -r ${NSA_IP} -X ${MD5_PW} log_test $? 0 "MD5: VRF: Prefix config" # client in prefix, wrong password log_start show_hint "Should timeout since client uses wrong password" - run_cmd nettest -s -d ${VRF} -M ${MD5_PW} -m ${NS_NET} & + run_cmd nettest -s -I ${VRF} -M ${MD5_PW} -m ${NS_NET} & sleep 1 - run_cmd_nsb nettest -r ${NSA_IP} -M ${MD5_WRONG_PW} + run_cmd_nsb nettest -r ${NSA_IP} -X ${MD5_WRONG_PW} log_test $? 2 "MD5: VRF: Prefix config, client uses wrong password" # client outside of prefix log_start show_hint "Should timeout since client address is outside of prefix" - run_cmd nettest -s -d ${VRF} -M ${MD5_PW} -m ${NS_NET} & + run_cmd nettest -s -I ${VRF} -M ${MD5_PW} -m ${NS_NET} & sleep 1 - run_cmd_nsb nettest -l ${NSB_LO_IP} -r ${NSA_IP} -M ${MD5_PW} + run_cmd_nsb nettest -c ${NSB_LO_IP} -r ${NSA_IP} -X ${MD5_PW} log_test $? 2 "MD5: VRF: Prefix config, client address not in configured prefix" # @@ -930,74 +930,74 @@ ipv4_tcp_md5() # log_start - run_cmd nettest -s -d ${VRF} -M ${MD5_PW} -r ${NSB_IP} & - run_cmd nettest -s -M ${MD5_WRONG_PW} -r ${NSB_IP} & + run_cmd nettest -s -I ${VRF} -M ${MD5_PW} -m ${NSB_IP} & + run_cmd nettest -s -M ${MD5_WRONG_PW} -m ${NSB_IP} & sleep 1 - run_cmd_nsb nettest -r ${NSA_IP} -M ${MD5_PW} + run_cmd_nsb nettest -r ${NSA_IP} -X ${MD5_PW} log_test $? 0 "MD5: VRF: Single address config in default VRF and VRF, conn in VRF" log_start - run_cmd nettest -s -d ${VRF} -M ${MD5_PW} -r ${NSB_IP} & - run_cmd nettest -s -M ${MD5_WRONG_PW} -r ${NSB_IP} & + run_cmd nettest -s -I ${VRF} -M ${MD5_PW} -m ${NSB_IP} & + run_cmd nettest -s -M ${MD5_WRONG_PW} -m ${NSB_IP} & sleep 1 - run_cmd_nsc nettest -r ${NSA_IP} -M ${MD5_WRONG_PW} + run_cmd_nsc nettest -r ${NSA_IP} -X ${MD5_WRONG_PW} log_test $? 0 "MD5: VRF: Single address config in default VRF and VRF, conn in default VRF" log_start show_hint "Should timeout since client in default VRF uses VRF password" - run_cmd nettest -s -d ${VRF} -M ${MD5_PW} -r ${NSB_IP} & - run_cmd nettest -s -M ${MD5_WRONG_PW} -r ${NSB_IP} & + run_cmd nettest -s -I ${VRF} -M ${MD5_PW} -m ${NSB_IP} & + run_cmd nettest -s -M ${MD5_WRONG_PW} -m ${NSB_IP} & sleep 1 - run_cmd_nsc nettest -r ${NSA_IP} -M ${MD5_PW} + run_cmd_nsc nettest -r ${NSA_IP} -X ${MD5_PW} log_test $? 2 "MD5: VRF: Single address config in default VRF and VRF, conn in default VRF with VRF pw" log_start show_hint "Should timeout since client in VRF uses default VRF password" - run_cmd nettest -s -d ${VRF} -M ${MD5_PW} -r ${NSB_IP} & - run_cmd nettest -s -M ${MD5_WRONG_PW} -r ${NSB_IP} & + run_cmd nettest -s -I ${VRF} -M ${MD5_PW} -m ${NSB_IP} & + run_cmd nettest -s -M ${MD5_WRONG_PW} -m ${NSB_IP} & sleep 1 - run_cmd_nsb nettest -r ${NSA_IP} -M ${MD5_WRONG_PW} + run_cmd_nsb nettest -r ${NSA_IP} -X ${MD5_WRONG_PW} log_test $? 2 "MD5: VRF: Single address config in default VRF and VRF, conn in VRF with default VRF pw" log_start - run_cmd nettest -s -d ${VRF} -M ${MD5_PW} -m ${NS_NET} & + run_cmd nettest -s -I ${VRF} -M ${MD5_PW} -m ${NS_NET} & run_cmd nettest -s -M ${MD5_WRONG_PW} -m ${NS_NET} & sleep 1 - run_cmd_nsb nettest -r ${NSA_IP} -M ${MD5_PW} + run_cmd_nsb nettest -r ${NSA_IP} -X ${MD5_PW} log_test $? 0 "MD5: VRF: Prefix config in default VRF and VRF, conn in VRF" log_start - run_cmd nettest -s -d ${VRF} -M ${MD5_PW} -m ${NS_NET} & + run_cmd nettest -s -I ${VRF} -M ${MD5_PW} -m ${NS_NET} & run_cmd nettest -s -M ${MD5_WRONG_PW} -m ${NS_NET} & sleep 1 - run_cmd_nsc nettest -r ${NSA_IP} -M ${MD5_WRONG_PW} + run_cmd_nsc nettest -r ${NSA_IP} -X ${MD5_WRONG_PW} log_test $? 0 "MD5: VRF: Prefix config in default VRF and VRF, conn in default VRF" log_start show_hint "Should timeout since client in default VRF uses VRF password" - run_cmd nettest -s -d ${VRF} -M ${MD5_PW} -m ${NS_NET} & + run_cmd nettest -s -I ${VRF} -M ${MD5_PW} -m ${NS_NET} & run_cmd nettest -s -M ${MD5_WRONG_PW} -m ${NS_NET} & sleep 1 - run_cmd_nsc nettest -r ${NSA_IP} -M ${MD5_PW} + run_cmd_nsc nettest -r ${NSA_IP} -X ${MD5_PW} log_test $? 2 "MD5: VRF: Prefix config in default VRF and VRF, conn in default VRF with VRF pw" log_start show_hint "Should timeout since client in VRF uses default VRF password" - run_cmd nettest -s -d ${VRF} -M ${MD5_PW} -m ${NS_NET} & + run_cmd nettest -s -I ${VRF} -M ${MD5_PW} -m ${NS_NET} & run_cmd nettest -s -M ${MD5_WRONG_PW} -m ${NS_NET} & sleep 1 - run_cmd_nsb nettest -r ${NSA_IP} -M ${MD5_WRONG_PW} + run_cmd_nsb nettest -r ${NSA_IP} -X ${MD5_WRONG_PW} log_test $? 2 "MD5: VRF: Prefix config in default VRF and VRF, conn in VRF with default VRF pw" # # negative tests # log_start - run_cmd nettest -s -d ${NSA_DEV} -M ${MD5_PW} -r ${NSB_IP} + run_cmd nettest -s -I ${NSA_DEV} -M ${MD5_PW} -m ${NSB_IP} log_test $? 1 "MD5: VRF: Device must be a VRF - single address" log_start - run_cmd nettest -s -d ${NSA_DEV} -M ${MD5_PW} -m ${NS_NET} + run_cmd nettest -s -I ${NSA_DEV} -M ${MD5_PW} -m ${NS_NET} log_test $? 1 "MD5: VRF: Device must be a VRF - prefix" } @@ -1020,7 +1020,7 @@ ipv4_tcp_novrf() a=${NSA_IP} log_start - run_cmd nettest -s -d ${NSA_DEV} & + run_cmd nettest -s -I ${NSA_DEV} & sleep 1 run_cmd_nsb nettest -r ${a} log_test_addr ${a} $? 0 "Device server" @@ -1076,7 +1076,7 @@ ipv4_tcp_novrf() a=${NSA_IP} log_start - run_cmd nettest -s -d ${NSA_DEV} & + run_cmd nettest -s -I ${NSA_DEV} & sleep 1 run_cmd nettest -r ${a} -0 ${a} log_test_addr ${a} $? 0 "Device server, unbound client, local connection" @@ -1085,7 +1085,7 @@ ipv4_tcp_novrf() do log_start show_hint "Should fail 'Connection refused' since addresses on loopback are out of device scope" - run_cmd nettest -s -d ${NSA_DEV} & + run_cmd nettest -s -I ${NSA_DEV} & sleep 1 run_cmd nettest -r ${a} log_test_addr ${a} $? 1 "Device server, unbound client, local connection" @@ -1110,7 +1110,7 @@ ipv4_tcp_novrf() a=${NSA_IP} log_start - run_cmd nettest -s -d ${NSA_DEV} -2 ${NSA_DEV} & + run_cmd nettest -s -I ${NSA_DEV} -3 ${NSA_DEV} & sleep 1 run_cmd nettest -d ${NSA_DEV} -r ${a} -0 ${a} log_test_addr ${a} $? 0 "Device server, device client, local connection" @@ -1145,13 +1145,13 @@ ipv4_tcp_vrf() log_test_addr ${a} $? 1 "Global server" log_start - run_cmd nettest -s -d ${VRF} -2 ${VRF} & + run_cmd nettest -s -I ${VRF} -3 ${VRF} & sleep 1 run_cmd_nsb nettest -r ${a} log_test_addr ${a} $? 0 "VRF server" log_start - run_cmd nettest -s -d ${NSA_DEV} -2 ${NSA_DEV} & + run_cmd nettest -s -I ${NSA_DEV} -3 ${NSA_DEV} & sleep 1 run_cmd_nsb nettest -r ${a} log_test_addr ${a} $? 0 "Device server" @@ -1186,14 +1186,14 @@ ipv4_tcp_vrf() do log_start show_hint "client socket should be bound to VRF" - run_cmd nettest -s -2 ${VRF} & + run_cmd nettest -s -3 ${VRF} & sleep 1 run_cmd_nsb nettest -r ${a} log_test_addr ${a} $? 0 "Global server" log_start show_hint "client socket should be bound to VRF" - run_cmd nettest -s -d ${VRF} -2 ${VRF} & + run_cmd nettest -s -I ${VRF} -3 ${VRF} & sleep 1 run_cmd_nsb nettest -r ${a} log_test_addr ${a} $? 0 "VRF server" @@ -1208,7 +1208,7 @@ ipv4_tcp_vrf() a=${NSA_IP} log_start show_hint "client socket should be bound to device" - run_cmd nettest -s -d ${NSA_DEV} -2 ${NSA_DEV} & + run_cmd nettest -s -I ${NSA_DEV} -3 ${NSA_DEV} & sleep 1 run_cmd_nsb nettest -r ${a} log_test_addr ${a} $? 0 "Device server" @@ -1218,7 +1218,7 @@ ipv4_tcp_vrf() do log_start show_hint "Should fail 'Connection refused' since client is not bound to VRF" - run_cmd nettest -s -d ${VRF} & + run_cmd nettest -s -I ${VRF} & sleep 1 run_cmd nettest -r ${a} log_test_addr ${a} $? 1 "Global server, local connection" @@ -1255,7 +1255,7 @@ ipv4_tcp_vrf() for a in ${NSA_IP} ${VRF_IP} 127.0.0.1 do log_start - run_cmd nettest -s -d ${VRF} -2 ${VRF} & + run_cmd nettest -s -I ${VRF} -3 ${VRF} & sleep 1 run_cmd nettest -r ${a} -d ${VRF} -0 ${a} log_test_addr ${a} $? 0 "VRF server, VRF client, local connection" @@ -1263,26 +1263,26 @@ ipv4_tcp_vrf() a=${NSA_IP} log_start - run_cmd nettest -s -d ${VRF} -2 ${VRF} & + run_cmd nettest -s -I ${VRF} -3 ${VRF} & sleep 1 run_cmd nettest -r ${a} -d ${NSA_DEV} -0 ${a} log_test_addr ${a} $? 0 "VRF server, device client, local connection" log_start show_hint "Should fail 'No route to host' since client is out of VRF scope" - run_cmd nettest -s -d ${VRF} & + run_cmd nettest -s -I ${VRF} & sleep 1 run_cmd nettest -r ${a} log_test_addr ${a} $? 1 "VRF server, unbound client, local connection" log_start - run_cmd nettest -s -d ${NSA_DEV} -2 ${NSA_DEV} & + run_cmd nettest -s -I ${NSA_DEV} -3 ${NSA_DEV} & sleep 1 run_cmd nettest -r ${a} -d ${VRF} -0 ${a} log_test_addr ${a} $? 0 "Device server, VRF client, local connection" log_start - run_cmd nettest -s -d ${NSA_DEV} -2 ${NSA_DEV} & + run_cmd nettest -s -I ${NSA_DEV} -3 ${NSA_DEV} & sleep 1 run_cmd nettest -r ${a} -d ${NSA_DEV} -0 ${a} log_test_addr ${a} $? 0 "Device server, device client, local connection" @@ -1321,7 +1321,7 @@ ipv4_udp_novrf() for a in ${NSA_IP} ${NSA_LO_IP} do log_start - run_cmd nettest -D -s -2 ${NSA_DEV} & + run_cmd nettest -D -s -3 ${NSA_DEV} & sleep 1 run_cmd_nsb nettest -D -r ${a} log_test_addr ${a} $? 0 "Global server" @@ -1334,7 +1334,7 @@ ipv4_udp_novrf() a=${NSA_IP} log_start - run_cmd nettest -D -d ${NSA_DEV} -s -2 ${NSA_DEV} & + run_cmd nettest -D -I ${NSA_DEV} -s -3 ${NSA_DEV} & sleep 1 run_cmd_nsb nettest -D -r ${a} log_test_addr ${a} $? 0 "Device server" @@ -1393,7 +1393,7 @@ ipv4_udp_novrf() a=${NSA_IP} log_start - run_cmd nettest -s -D -d ${NSA_DEV} -2 ${NSA_DEV} & + run_cmd nettest -s -D -I ${NSA_DEV} -3 ${NSA_DEV} & sleep 1 run_cmd nettest -D -r ${a} log_test_addr ${a} $? 0 "Device server, unbound client, local connection" @@ -1402,7 +1402,7 @@ ipv4_udp_novrf() do log_start show_hint "Should fail 'Connection refused' since address is out of device scope" - run_cmd nettest -s -D -d ${NSA_DEV} & + run_cmd nettest -s -D -I ${NSA_DEV} & sleep 1 run_cmd nettest -D -r ${a} log_test_addr ${a} $? 1 "Device server, unbound client, local connection" @@ -1456,7 +1456,7 @@ ipv4_udp_novrf() a=${NSA_IP} log_start - run_cmd nettest -D -s -d ${NSA_DEV} -2 ${NSA_DEV} & + run_cmd nettest -D -s -I ${NSA_DEV} -3 ${NSA_DEV} & sleep 1 run_cmd nettest -D -d ${NSA_DEV} -r ${a} -0 ${a} log_test_addr ${a} $? 0 "Device server, device client, local conn" @@ -1487,13 +1487,13 @@ ipv4_udp_vrf() log_test_addr ${a} $? 1 "Global server" log_start - run_cmd nettest -D -d ${VRF} -s -2 ${NSA_DEV} & + run_cmd nettest -D -I ${VRF} -s -3 ${NSA_DEV} & sleep 1 run_cmd_nsb nettest -D -r ${a} log_test_addr ${a} $? 0 "VRF server" log_start - run_cmd nettest -D -d ${NSA_DEV} -s -2 ${NSA_DEV} & + run_cmd nettest -D -I ${NSA_DEV} -s -3 ${NSA_DEV} & sleep 1 run_cmd_nsb nettest -D -r ${a} log_test_addr ${a} $? 0 "Enslaved device server" @@ -1513,26 +1513,26 @@ ipv4_udp_vrf() a=${NSA_IP} log_start - run_cmd nettest -s -D -d ${VRF} -2 ${NSA_DEV} & + run_cmd nettest -s -D -I ${VRF} -3 ${NSA_DEV} & sleep 1 run_cmd nettest -D -d ${VRF} -r ${a} log_test_addr ${a} $? 0 "VRF server, VRF client, local conn" log_start - run_cmd nettest -s -D -d ${VRF} -2 ${NSA_DEV} & + run_cmd nettest -s -D -I ${VRF} -3 ${NSA_DEV} & sleep 1 run_cmd nettest -D -d ${NSA_DEV} -r ${a} log_test_addr ${a} $? 0 "VRF server, enslaved device client, local connection" a=${NSA_IP} log_start - run_cmd nettest -s -D -d ${NSA_DEV} -2 ${NSA_DEV} & + run_cmd nettest -s -D -I ${NSA_DEV} -3 ${NSA_DEV} & sleep 1 run_cmd nettest -D -d ${VRF} -r ${a} log_test_addr ${a} $? 0 "Enslaved device server, VRF client, local conn" log_start - run_cmd nettest -s -D -d ${NSA_DEV} -2 ${NSA_DEV} & + run_cmd nettest -s -D -I ${NSA_DEV} -3 ${NSA_DEV} & sleep 1 run_cmd nettest -D -d ${NSA_DEV} -r ${a} log_test_addr ${a} $? 0 "Enslaved device server, device client, local conn" @@ -1547,19 +1547,19 @@ ipv4_udp_vrf() for a in ${NSA_IP} ${VRF_IP} do log_start - run_cmd nettest -D -s -2 ${NSA_DEV} & + run_cmd nettest -D -s -3 ${NSA_DEV} & sleep 1 run_cmd_nsb nettest -D -r ${a} log_test_addr ${a} $? 0 "Global server" log_start - run_cmd nettest -D -d ${VRF} -s -2 ${NSA_DEV} & + run_cmd nettest -D -I ${VRF} -s -3 ${NSA_DEV} & sleep 1 run_cmd_nsb nettest -D -r ${a} log_test_addr ${a} $? 0 "VRF server" log_start - run_cmd nettest -D -d ${NSA_DEV} -s -2 ${NSA_DEV} & + run_cmd nettest -D -I ${NSA_DEV} -s -3 ${NSA_DEV} & sleep 1 run_cmd_nsb nettest -D -r ${a} log_test_addr ${a} $? 0 "Enslaved device server" @@ -1601,31 +1601,31 @@ ipv4_udp_vrf() # a=${NSA_IP} log_start - run_cmd nettest -D -s -2 ${NSA_DEV} & + run_cmd nettest -D -s -3 ${NSA_DEV} & sleep 1 run_cmd nettest -D -d ${VRF} -r ${a} log_test_addr ${a} $? 0 "Global server, VRF client, local conn" log_start - run_cmd nettest -s -D -d ${VRF} -2 ${NSA_DEV} & + run_cmd nettest -s -D -I ${VRF} -3 ${NSA_DEV} & sleep 1 run_cmd nettest -D -d ${VRF} -r ${a} log_test_addr ${a} $? 0 "VRF server, VRF client, local conn" log_start - run_cmd nettest -s -D -d ${VRF} -2 ${NSA_DEV} & + run_cmd nettest -s -D -I ${VRF} -3 ${NSA_DEV} & sleep 1 run_cmd nettest -D -d ${NSA_DEV} -r ${a} log_test_addr ${a} $? 0 "VRF server, device client, local conn" log_start - run_cmd nettest -s -D -d ${NSA_DEV} -2 ${NSA_DEV} & + run_cmd nettest -s -D -I ${NSA_DEV} -3 ${NSA_DEV} & sleep 1 run_cmd nettest -D -d ${VRF} -r ${a} log_test_addr ${a} $? 0 "Enslaved device server, VRF client, local conn" log_start - run_cmd nettest -s -D -d ${NSA_DEV} -2 ${NSA_DEV} & + run_cmd nettest -s -D -I ${NSA_DEV} -3 ${NSA_DEV} & sleep 1 run_cmd nettest -D -d ${NSA_DEV} -r ${a} log_test_addr ${a} $? 0 "Enslaved device server, device client, local conn" @@ -1633,7 +1633,7 @@ ipv4_udp_vrf() for a in ${VRF_IP} 127.0.0.1 do log_start - run_cmd nettest -D -s -2 ${VRF} & + run_cmd nettest -D -s -3 ${VRF} & sleep 1 run_cmd nettest -D -d ${VRF} -r ${a} log_test_addr ${a} $? 0 "Global server, VRF client, local conn" @@ -1642,7 +1642,7 @@ ipv4_udp_vrf() for a in ${VRF_IP} 127.0.0.1 do log_start - run_cmd nettest -s -D -d ${VRF} -2 ${VRF} & + run_cmd nettest -s -D -I ${VRF} -3 ${VRF} & sleep 1 run_cmd nettest -D -d ${VRF} -r ${a} log_test_addr ${a} $? 0 "VRF server, VRF client, local conn" @@ -1697,7 +1697,7 @@ ipv4_addr_bind_novrf() log_test_addr ${a} $? 0 "Raw socket bind to local address" log_start - run_cmd nettest -s -R -P icmp -l ${a} -d ${NSA_DEV} -b + run_cmd nettest -s -R -P icmp -l ${a} -I ${NSA_DEV} -b log_test_addr ${a} $? 0 "Raw socket bind to local address after device bind" done @@ -1706,11 +1706,11 @@ ipv4_addr_bind_novrf() # a=${NSA_IP} log_start - run_cmd nettest -l ${a} -r ${NSB_IP} -t1 -b + run_cmd nettest -c ${a} -r ${NSB_IP} -t1 -b log_test_addr ${a} $? 0 "TCP socket bind to local address" log_start - run_cmd nettest -l ${a} -r ${NSB_IP} -d ${NSA_DEV} -t1 -b + run_cmd nettest -c ${a} -r ${NSB_IP} -d ${NSA_DEV} -t1 -b log_test_addr ${a} $? 0 "TCP socket bind to local address after device bind" # Sadly, the kernel allows binding a socket to a device and then @@ -1720,7 +1720,7 @@ ipv4_addr_bind_novrf() #a=${NSA_LO_IP} #log_start #show_hint "Should fail with 'Cannot assign requested address'" - #run_cmd nettest -s -l ${a} -d ${NSA_DEV} -t1 -b + #run_cmd nettest -s -l ${a} -I ${NSA_DEV} -t1 -b #log_test_addr ${a} $? 1 "TCP socket bind to out of scope local address" } @@ -1736,17 +1736,17 @@ ipv4_addr_bind_vrf() log_test_addr ${a} $? 0 "Raw socket bind to local address" log_start - run_cmd nettest -s -R -P icmp -l ${a} -d ${NSA_DEV} -b + run_cmd nettest -s -R -P icmp -l ${a} -I ${NSA_DEV} -b log_test_addr ${a} $? 0 "Raw socket bind to local address after device bind" log_start - run_cmd nettest -s -R -P icmp -l ${a} -d ${VRF} -b + run_cmd nettest -s -R -P icmp -l ${a} -I ${VRF} -b log_test_addr ${a} $? 0 "Raw socket bind to local address after VRF bind" done a=${NSA_LO_IP} log_start show_hint "Address on loopback is out of VRF scope" - run_cmd nettest -s -R -P icmp -l ${a} -d ${VRF} -b + run_cmd nettest -s -R -P icmp -l ${a} -I ${VRF} -b log_test_addr ${a} $? 1 "Raw socket bind to out of scope address after VRF bind" # @@ -1755,23 +1755,23 @@ ipv4_addr_bind_vrf() for a in ${NSA_IP} ${VRF_IP} do log_start - run_cmd nettest -s -l ${a} -d ${VRF} -t1 -b + run_cmd nettest -s -l ${a} -I ${VRF} -t1 -b log_test_addr ${a} $? 0 "TCP socket bind to local address" log_start - run_cmd nettest -s -l ${a} -d ${NSA_DEV} -t1 -b + run_cmd nettest -s -l ${a} -I ${NSA_DEV} -t1 -b log_test_addr ${a} $? 0 "TCP socket bind to local address after device bind" done a=${NSA_LO_IP} log_start show_hint "Address on loopback out of scope for VRF" - run_cmd nettest -s -l ${a} -d ${VRF} -t1 -b + run_cmd nettest -s -l ${a} -I ${VRF} -t1 -b log_test_addr ${a} $? 1 "TCP socket bind to invalid local address for VRF" log_start show_hint "Address on loopback out of scope for device in VRF" - run_cmd nettest -s -l ${a} -d ${NSA_DEV} -t1 -b + run_cmd nettest -s -l ${a} -I ${NSA_DEV} -t1 -b log_test_addr ${a} $? 1 "TCP socket bind to invalid local address for device bind" } @@ -1818,7 +1818,7 @@ ipv4_rt() for a in ${NSA_IP} ${VRF_IP} do log_start - run_cmd nettest ${varg} -s -d ${VRF} & + run_cmd nettest ${varg} -s -I ${VRF} & sleep 1 run_cmd_nsb nettest ${varg} -r ${a} & sleep 3 @@ -1831,7 +1831,7 @@ ipv4_rt() a=${NSA_IP} log_start - run_cmd nettest ${varg} -s -d ${NSA_DEV} & + run_cmd nettest ${varg} -s -I ${NSA_DEV} & sleep 1 run_cmd_nsb nettest ${varg} -r ${a} & sleep 3 @@ -1886,7 +1886,7 @@ ipv4_rt() for a in ${NSA_IP} ${VRF_IP} do log_start - run_cmd nettest ${varg} -d ${VRF} -s & + run_cmd nettest ${varg} -I ${VRF} -s & sleep 1 run_cmd nettest ${varg} -d ${VRF} -r ${a} & sleep 3 @@ -1910,7 +1910,7 @@ ipv4_rt() setup ${with_vrf} log_start - run_cmd nettest ${varg} -d ${VRF} -s & + run_cmd nettest ${varg} -I ${VRF} -s & sleep 1 run_cmd nettest ${varg} -d ${NSA_DEV} -r ${a} & sleep 3 @@ -1921,7 +1921,7 @@ ipv4_rt() setup ${with_vrf} log_start - run_cmd nettest ${varg} -d ${NSA_DEV} -s & + run_cmd nettest ${varg} -I ${NSA_DEV} -s & sleep 1 run_cmd nettest ${varg} -d ${NSA_DEV} -r ${a} & sleep 3 @@ -2265,9 +2265,9 @@ ipv6_tcp_md5_novrf() # basic use case log_start - run_cmd nettest -6 -s -M ${MD5_PW} -r ${NSB_IP6} & + run_cmd nettest -6 -s -M ${MD5_PW} -m ${NSB_IP6} & sleep 1 - run_cmd_nsb nettest -6 -r ${NSA_IP6} -M ${MD5_PW} + run_cmd_nsb nettest -6 -r ${NSA_IP6} -X ${MD5_PW} log_test $? 0 "MD5: Single address config" # client sends MD5, server not configured @@ -2275,23 +2275,23 @@ ipv6_tcp_md5_novrf() show_hint "Should timeout due to MD5 mismatch" run_cmd nettest -6 -s & sleep 1 - run_cmd_nsb nettest -6 -r ${NSA_IP6} -M ${MD5_PW} + run_cmd_nsb nettest -6 -r ${NSA_IP6} -X ${MD5_PW} log_test $? 2 "MD5: Server no config, client uses password" # wrong password log_start show_hint "Should timeout since client uses wrong password" - run_cmd nettest -6 -s -M ${MD5_PW} -r ${NSB_IP6} & + run_cmd nettest -6 -s -M ${MD5_PW} -m ${NSB_IP6} & sleep 1 - run_cmd_nsb nettest -6 -r ${NSA_IP6} -M ${MD5_WRONG_PW} + run_cmd_nsb nettest -6 -r ${NSA_IP6} -X ${MD5_WRONG_PW} log_test $? 2 "MD5: Client uses wrong password" # client from different address log_start show_hint "Should timeout due to MD5 mismatch" - run_cmd nettest -6 -s -M ${MD5_PW} -r ${NSB_LO_IP6} & + run_cmd nettest -6 -s -M ${MD5_PW} -m ${NSB_LO_IP6} & sleep 1 - run_cmd_nsb nettest -6 -r ${NSA_IP6} -M ${MD5_PW} + run_cmd_nsb nettest -6 -r ${NSA_IP6} -X ${MD5_PW} log_test $? 2 "MD5: Client address does not match address configured with password" # @@ -2302,7 +2302,7 @@ ipv6_tcp_md5_novrf() log_start run_cmd nettest -6 -s -M ${MD5_PW} -m ${NS_NET6} & sleep 1 - run_cmd_nsb nettest -6 -r ${NSA_IP6} -M ${MD5_PW} + run_cmd_nsb nettest -6 -r ${NSA_IP6} -X ${MD5_PW} log_test $? 0 "MD5: Prefix config" # client in prefix, wrong password @@ -2310,7 +2310,7 @@ ipv6_tcp_md5_novrf() show_hint "Should timeout since client uses wrong password" run_cmd nettest -6 -s -M ${MD5_PW} -m ${NS_NET6} & sleep 1 - run_cmd_nsb nettest -6 -r ${NSA_IP6} -M ${MD5_WRONG_PW} + run_cmd_nsb nettest -6 -r ${NSA_IP6} -X ${MD5_WRONG_PW} log_test $? 2 "MD5: Prefix config, client uses wrong password" # client outside of prefix @@ -2318,7 +2318,7 @@ ipv6_tcp_md5_novrf() show_hint "Should timeout due to MD5 mismatch" run_cmd nettest -6 -s -M ${MD5_PW} -m ${NS_NET6} & sleep 1 - run_cmd_nsb nettest -6 -l ${NSB_LO_IP6} -r ${NSA_IP6} -M ${MD5_PW} + run_cmd_nsb nettest -6 -c ${NSB_LO_IP6} -r ${NSA_IP6} -X ${MD5_PW} log_test $? 2 "MD5: Prefix config, client address not in configured prefix" } @@ -2333,33 +2333,33 @@ ipv6_tcp_md5() # basic use case log_start - run_cmd nettest -6 -s -d ${VRF} -M ${MD5_PW} -r ${NSB_IP6} & + run_cmd nettest -6 -s -I ${VRF} -M ${MD5_PW} -m ${NSB_IP6} & sleep 1 - run_cmd_nsb nettest -6 -r ${NSA_IP6} -M ${MD5_PW} + run_cmd_nsb nettest -6 -r ${NSA_IP6} -X ${MD5_PW} log_test $? 0 "MD5: VRF: Single address config" # client sends MD5, server not configured log_start show_hint "Should timeout since server does not have MD5 auth" - run_cmd nettest -6 -s -d ${VRF} & + run_cmd nettest -6 -s -I ${VRF} & sleep 1 - run_cmd_nsb nettest -6 -r ${NSA_IP6} -M ${MD5_PW} + run_cmd_nsb nettest -6 -r ${NSA_IP6} -X ${MD5_PW} log_test $? 2 "MD5: VRF: Server no config, client uses password" # wrong password log_start show_hint "Should timeout since client uses wrong password" - run_cmd nettest -6 -s -d ${VRF} -M ${MD5_PW} -r ${NSB_IP6} & + run_cmd nettest -6 -s -I ${VRF} -M ${MD5_PW} -m ${NSB_IP6} & sleep 1 - run_cmd_nsb nettest -6 -r ${NSA_IP6} -M ${MD5_WRONG_PW} + run_cmd_nsb nettest -6 -r ${NSA_IP6} -X ${MD5_WRONG_PW} log_test $? 2 "MD5: VRF: Client uses wrong password" # client from different address log_start show_hint "Should timeout since server config differs from client" - run_cmd nettest -6 -s -d ${VRF} -M ${MD5_PW} -r ${NSB_LO_IP6} & + run_cmd nettest -6 -s -I ${VRF} -M ${MD5_PW} -m ${NSB_LO_IP6} & sleep 1 - run_cmd_nsb nettest -6 -r ${NSA_IP6} -M ${MD5_PW} + run_cmd_nsb nettest -6 -r ${NSA_IP6} -X ${MD5_PW} log_test $? 2 "MD5: VRF: Client address does not match address configured with password" # @@ -2368,25 +2368,25 @@ ipv6_tcp_md5() # client in prefix log_start - run_cmd nettest -6 -s -d ${VRF} -M ${MD5_PW} -m ${NS_NET6} & + run_cmd nettest -6 -s -I ${VRF} -M ${MD5_PW} -m ${NS_NET6} & sleep 1 - run_cmd_nsb nettest -6 -r ${NSA_IP6} -M ${MD5_PW} + run_cmd_nsb nettest -6 -r ${NSA_IP6} -X ${MD5_PW} log_test $? 0 "MD5: VRF: Prefix config" # client in prefix, wrong password log_start show_hint "Should timeout since client uses wrong password" - run_cmd nettest -6 -s -d ${VRF} -M ${MD5_PW} -m ${NS_NET6} & + run_cmd nettest -6 -s -I ${VRF} -M ${MD5_PW} -m ${NS_NET6} & sleep 1 - run_cmd_nsb nettest -6 -r ${NSA_IP6} -M ${MD5_WRONG_PW} + run_cmd_nsb nettest -6 -r ${NSA_IP6} -X ${MD5_WRONG_PW} log_test $? 2 "MD5: VRF: Prefix config, client uses wrong password" # client outside of prefix log_start show_hint "Should timeout since client address is outside of prefix" - run_cmd nettest -6 -s -d ${VRF} -M ${MD5_PW} -m ${NS_NET6} & + run_cmd nettest -6 -s -I ${VRF} -M ${MD5_PW} -m ${NS_NET6} & sleep 1 - run_cmd_nsb nettest -6 -l ${NSB_LO_IP6} -r ${NSA_IP6} -M ${MD5_PW} + run_cmd_nsb nettest -6 -c ${NSB_LO_IP6} -r ${NSA_IP6} -X ${MD5_PW} log_test $? 2 "MD5: VRF: Prefix config, client address not in configured prefix" # @@ -2394,74 +2394,74 @@ ipv6_tcp_md5() # log_start - run_cmd nettest -6 -s -d ${VRF} -M ${MD5_PW} -r ${NSB_IP6} & - run_cmd nettest -6 -s -M ${MD5_WRONG_PW} -r ${NSB_IP6} & + run_cmd nettest -6 -s -I ${VRF} -M ${MD5_PW} -m ${NSB_IP6} & + run_cmd nettest -6 -s -M ${MD5_WRONG_PW} -m ${NSB_IP6} & sleep 1 - run_cmd_nsb nettest -6 -r ${NSA_IP6} -M ${MD5_PW} + run_cmd_nsb nettest -6 -r ${NSA_IP6} -X ${MD5_PW} log_test $? 0 "MD5: VRF: Single address config in default VRF and VRF, conn in VRF" log_start - run_cmd nettest -6 -s -d ${VRF} -M ${MD5_PW} -r ${NSB_IP6} & - run_cmd nettest -6 -s -M ${MD5_WRONG_PW} -r ${NSB_IP6} & + run_cmd nettest -6 -s -I ${VRF} -M ${MD5_PW} -m ${NSB_IP6} & + run_cmd nettest -6 -s -M ${MD5_WRONG_PW} -m ${NSB_IP6} & sleep 1 - run_cmd_nsc nettest -6 -r ${NSA_IP6} -M ${MD5_WRONG_PW} + run_cmd_nsc nettest -6 -r ${NSA_IP6} -X ${MD5_WRONG_PW} log_test $? 0 "MD5: VRF: Single address config in default VRF and VRF, conn in default VRF" log_start show_hint "Should timeout since client in default VRF uses VRF password" - run_cmd nettest -6 -s -d ${VRF} -M ${MD5_PW} -r ${NSB_IP6} & - run_cmd nettest -6 -s -M ${MD5_WRONG_PW} -r ${NSB_IP6} & + run_cmd nettest -6 -s -I ${VRF} -M ${MD5_PW} -m ${NSB_IP6} & + run_cmd nettest -6 -s -M ${MD5_WRONG_PW} -m ${NSB_IP6} & sleep 1 - run_cmd_nsc nettest -6 -r ${NSA_IP6} -M ${MD5_PW} + run_cmd_nsc nettest -6 -r ${NSA_IP6} -X ${MD5_PW} log_test $? 2 "MD5: VRF: Single address config in default VRF and VRF, conn in default VRF with VRF pw" log_start show_hint "Should timeout since client in VRF uses default VRF password" - run_cmd nettest -6 -s -d ${VRF} -M ${MD5_PW} -r ${NSB_IP6} & - run_cmd nettest -6 -s -M ${MD5_WRONG_PW} -r ${NSB_IP6} & + run_cmd nettest -6 -s -I ${VRF} -M ${MD5_PW} -m ${NSB_IP6} & + run_cmd nettest -6 -s -M ${MD5_WRONG_PW} -m ${NSB_IP6} & sleep 1 - run_cmd_nsb nettest -6 -r ${NSA_IP6} -M ${MD5_WRONG_PW} + run_cmd_nsb nettest -6 -r ${NSA_IP6} -X ${MD5_WRONG_PW} log_test $? 2 "MD5: VRF: Single address config in default VRF and VRF, conn in VRF with default VRF pw" log_start - run_cmd nettest -6 -s -d ${VRF} -M ${MD5_PW} -m ${NS_NET6} & + run_cmd nettest -6 -s -I ${VRF} -M ${MD5_PW} -m ${NS_NET6} & run_cmd nettest -6 -s -M ${MD5_WRONG_PW} -m ${NS_NET6} & sleep 1 - run_cmd_nsb nettest -6 -r ${NSA_IP6} -M ${MD5_PW} + run_cmd_nsb nettest -6 -r ${NSA_IP6} -X ${MD5_PW} log_test $? 0 "MD5: VRF: Prefix config in default VRF and VRF, conn in VRF" log_start - run_cmd nettest -6 -s -d ${VRF} -M ${MD5_PW} -m ${NS_NET6} & + run_cmd nettest -6 -s -I ${VRF} -M ${MD5_PW} -m ${NS_NET6} & run_cmd nettest -6 -s -M ${MD5_WRONG_PW} -m ${NS_NET6} & sleep 1 - run_cmd_nsc nettest -6 -r ${NSA_IP6} -M ${MD5_WRONG_PW} + run_cmd_nsc nettest -6 -r ${NSA_IP6} -X ${MD5_WRONG_PW} log_test $? 0 "MD5: VRF: Prefix config in default VRF and VRF, conn in default VRF" log_start show_hint "Should timeout since client in default VRF uses VRF password" - run_cmd nettest -6 -s -d ${VRF} -M ${MD5_PW} -m ${NS_NET6} & + run_cmd nettest -6 -s -I ${VRF} -M ${MD5_PW} -m ${NS_NET6} & run_cmd nettest -6 -s -M ${MD5_WRONG_PW} -m ${NS_NET6} & sleep 1 - run_cmd_nsc nettest -6 -r ${NSA_IP6} -M ${MD5_PW} + run_cmd_nsc nettest -6 -r ${NSA_IP6} -X ${MD5_PW} log_test $? 2 "MD5: VRF: Prefix config in default VRF and VRF, conn in default VRF with VRF pw" log_start show_hint "Should timeout since client in VRF uses default VRF password" - run_cmd nettest -6 -s -d ${VRF} -M ${MD5_PW} -m ${NS_NET6} & + run_cmd nettest -6 -s -I ${VRF} -M ${MD5_PW} -m ${NS_NET6} & run_cmd nettest -6 -s -M ${MD5_WRONG_PW} -m ${NS_NET6} & sleep 1 - run_cmd_nsb nettest -6 -r ${NSA_IP6} -M ${MD5_WRONG_PW} + run_cmd_nsb nettest -6 -r ${NSA_IP6} -X ${MD5_WRONG_PW} log_test $? 2 "MD5: VRF: Prefix config in default VRF and VRF, conn in VRF with default VRF pw" # # negative tests # log_start - run_cmd nettest -6 -s -d ${NSA_DEV} -M ${MD5_PW} -r ${NSB_IP6} + run_cmd nettest -6 -s -I ${NSA_DEV} -M ${MD5_PW} -m ${NSB_IP6} log_test $? 1 "MD5: VRF: Device must be a VRF - single address" log_start - run_cmd nettest -6 -s -d ${NSA_DEV} -M ${MD5_PW} -m ${NS_NET6} + run_cmd nettest -6 -s -I ${NSA_DEV} -M ${MD5_PW} -m ${NS_NET6} log_test $? 1 "MD5: VRF: Device must be a VRF - prefix" } @@ -2534,7 +2534,7 @@ ipv6_tcp_novrf() a=${NSA_IP6} log_start - run_cmd nettest -6 -s -d ${NSA_DEV} -2 ${NSA_DEV} & + run_cmd nettest -6 -s -I ${NSA_DEV} -3 ${NSA_DEV} & sleep 1 run_cmd nettest -6 -r ${a} -0 ${a} log_test_addr ${a} $? 0 "Device server, unbound client, local connection" @@ -2543,7 +2543,7 @@ ipv6_tcp_novrf() do log_start show_hint "Should fail 'Connection refused' since addresses on loopback are out of device scope" - run_cmd nettest -6 -s -d ${NSA_DEV} & + run_cmd nettest -6 -s -I ${NSA_DEV} & sleep 1 run_cmd nettest -6 -r ${a} log_test_addr ${a} $? 1 "Device server, unbound client, local connection" @@ -2569,7 +2569,7 @@ ipv6_tcp_novrf() for a in ${NSA_IP6} ${NSA_LINKIP6} do log_start - run_cmd nettest -6 -s -d ${NSA_DEV} -2 ${NSA_DEV} & + run_cmd nettest -6 -s -I ${NSA_DEV} -3 ${NSA_DEV} & sleep 1 run_cmd nettest -6 -d ${NSA_DEV} -r ${a} log_test_addr ${a} $? 0 "Device server, device client, local conn" @@ -2611,7 +2611,7 @@ ipv6_tcp_vrf() for a in ${NSA_IP6} ${VRF_IP6} do log_start - run_cmd nettest -6 -s -d ${VRF} -2 ${VRF} & + run_cmd nettest -6 -s -I ${VRF} -3 ${VRF} & sleep 1 run_cmd_nsb nettest -6 -r ${a} log_test_addr ${a} $? 0 "VRF server" @@ -2620,7 +2620,7 @@ ipv6_tcp_vrf() # link local is always bound to ingress device a=${NSA_LINKIP6}%${NSB_DEV} log_start - run_cmd nettest -6 -s -d ${VRF} -2 ${NSA_DEV} & + run_cmd nettest -6 -s -I ${VRF} -3 ${NSA_DEV} & sleep 1 run_cmd_nsb nettest -6 -r ${a} log_test_addr ${a} $? 0 "VRF server" @@ -2628,7 +2628,7 @@ ipv6_tcp_vrf() for a in ${NSA_IP6} ${VRF_IP6} ${NSA_LINKIP6}%${NSB_DEV} do log_start - run_cmd nettest -6 -s -d ${NSA_DEV} -2 ${NSA_DEV} & + run_cmd nettest -6 -s -I ${NSA_DEV} -3 ${NSA_DEV} & sleep 1 run_cmd_nsb nettest -6 -r ${a} log_test_addr ${a} $? 0 "Device server" @@ -2664,7 +2664,7 @@ ipv6_tcp_vrf() for a in ${NSA_IP6} ${VRF_IP6} do log_start - run_cmd nettest -6 -s -2 ${VRF} & + run_cmd nettest -6 -s -3 ${VRF} & sleep 1 run_cmd_nsb nettest -6 -r ${a} log_test_addr ${a} $? 0 "Global server" @@ -2673,7 +2673,7 @@ ipv6_tcp_vrf() for a in ${NSA_IP6} ${VRF_IP6} do log_start - run_cmd nettest -6 -s -d ${VRF} -2 ${VRF} & + run_cmd nettest -6 -s -I ${VRF} -3 ${VRF} & sleep 1 run_cmd_nsb nettest -6 -r ${a} log_test_addr ${a} $? 0 "VRF server" @@ -2682,13 +2682,13 @@ ipv6_tcp_vrf() # For LLA, child socket is bound to device a=${NSA_LINKIP6}%${NSB_DEV} log_start - run_cmd nettest -6 -s -2 ${NSA_DEV} & + run_cmd nettest -6 -s -3 ${NSA_DEV} & sleep 1 run_cmd_nsb nettest -6 -r ${a} log_test_addr ${a} $? 0 "Global server" log_start - run_cmd nettest -6 -s -d ${VRF} -2 ${NSA_DEV} & + run_cmd nettest -6 -s -I ${VRF} -3 ${NSA_DEV} & sleep 1 run_cmd_nsb nettest -6 -r ${a} log_test_addr ${a} $? 0 "VRF server" @@ -2696,7 +2696,7 @@ ipv6_tcp_vrf() for a in ${NSA_IP6} ${NSA_LINKIP6}%${NSB_DEV} do log_start - run_cmd nettest -6 -s -d ${NSA_DEV} -2 ${NSA_DEV} & + run_cmd nettest -6 -s -I ${NSA_DEV} -3 ${NSA_DEV} & sleep 1 run_cmd_nsb nettest -6 -r ${a} log_test_addr ${a} $? 0 "Device server" @@ -2716,7 +2716,7 @@ ipv6_tcp_vrf() do log_start show_hint "Fails 'Connection refused' since client is not in VRF" - run_cmd nettest -6 -s -d ${VRF} & + run_cmd nettest -6 -s -I ${VRF} & sleep 1 run_cmd nettest -6 -r ${a} log_test_addr ${a} $? 1 "Global server, local connection" @@ -2771,7 +2771,7 @@ ipv6_tcp_vrf() for a in ${NSA_IP6} ${VRF_IP6} ::1 do log_start - run_cmd nettest -6 -s -d ${VRF} -2 ${VRF} & + run_cmd nettest -6 -s -I ${VRF} -3 ${VRF} & sleep 1 run_cmd nettest -6 -r ${a} -d ${VRF} -0 ${a} log_test_addr ${a} $? 0 "VRF server, VRF client, local connection" @@ -2779,7 +2779,7 @@ ipv6_tcp_vrf() a=${NSA_IP6} log_start - run_cmd nettest -6 -s -d ${VRF} -2 ${VRF} & + run_cmd nettest -6 -s -I ${VRF} -3 ${VRF} & sleep 1 run_cmd nettest -6 -r ${a} -d ${NSA_DEV} -0 ${a} log_test_addr ${a} $? 0 "VRF server, device client, local connection" @@ -2787,13 +2787,13 @@ ipv6_tcp_vrf() a=${NSA_IP6} log_start show_hint "Should fail since unbound client is out of VRF scope" - run_cmd nettest -6 -s -d ${VRF} & + run_cmd nettest -6 -s -I ${VRF} & sleep 1 run_cmd nettest -6 -r ${a} log_test_addr ${a} $? 1 "VRF server, unbound client, local connection" log_start - run_cmd nettest -6 -s -d ${NSA_DEV} -2 ${NSA_DEV} & + run_cmd nettest -6 -s -I ${NSA_DEV} -3 ${NSA_DEV} & sleep 1 run_cmd nettest -6 -r ${a} -d ${VRF} -0 ${a} log_test_addr ${a} $? 0 "Device server, VRF client, local connection" @@ -2801,7 +2801,7 @@ ipv6_tcp_vrf() for a in ${NSA_IP6} ${NSA_LINKIP6} do log_start - run_cmd nettest -6 -s -d ${NSA_DEV} -2 ${NSA_DEV} & + run_cmd nettest -6 -s -I ${NSA_DEV} -3 ${NSA_DEV} & sleep 1 run_cmd nettest -6 -r ${a} -d ${NSA_DEV} -0 ${a} log_test_addr ${a} $? 0 "Device server, device client, local connection" @@ -2841,13 +2841,13 @@ ipv6_udp_novrf() for a in ${NSA_IP6} ${NSA_LINKIP6}%${NSB_DEV} do log_start - run_cmd nettest -6 -D -s -2 ${NSA_DEV} & + run_cmd nettest -6 -D -s -3 ${NSA_DEV} & sleep 1 run_cmd_nsb nettest -6 -D -r ${a} log_test_addr ${a} $? 0 "Global server" log_start - run_cmd nettest -6 -D -d ${NSA_DEV} -s -2 ${NSA_DEV} & + run_cmd nettest -6 -D -I ${NSA_DEV} -s -3 ${NSA_DEV} & sleep 1 run_cmd_nsb nettest -6 -D -r ${a} log_test_addr ${a} $? 0 "Device server" @@ -2855,7 +2855,7 @@ ipv6_udp_novrf() a=${NSA_LO_IP6} log_start - run_cmd nettest -6 -D -s -2 ${NSA_DEV} & + run_cmd nettest -6 -D -s -3 ${NSA_DEV} & sleep 1 run_cmd_nsb nettest -6 -D -r ${a} log_test_addr ${a} $? 0 "Global server" @@ -2865,7 +2865,7 @@ ipv6_udp_novrf() # behavior. #log_start #show_hint "Should fail since loopback address is out of scope" - #run_cmd nettest -6 -D -d ${NSA_DEV} -s -2 ${NSA_DEV} & + #run_cmd nettest -6 -D -I ${NSA_DEV} -s -3 ${NSA_DEV} & #sleep 1 #run_cmd_nsb nettest -6 -D -r ${a} #log_test_addr ${a} $? 1 "Device server" @@ -2933,7 +2933,7 @@ ipv6_udp_novrf() a=${NSA_IP6} log_start - run_cmd nettest -6 -s -D -d ${NSA_DEV} -2 ${NSA_DEV} & + run_cmd nettest -6 -s -D -I ${NSA_DEV} -3 ${NSA_DEV} & sleep 1 run_cmd nettest -6 -D -r ${a} log_test_addr ${a} $? 0 "Device server, unbound client, local connection" @@ -2942,7 +2942,7 @@ ipv6_udp_novrf() do log_start show_hint "Should fail 'Connection refused' since address is out of device scope" - run_cmd nettest -6 -s -D -d ${NSA_DEV} & + run_cmd nettest -6 -s -D -I ${NSA_DEV} & sleep 1 run_cmd nettest -6 -D -r ${a} log_test_addr ${a} $? 1 "Device server, local connection" @@ -2993,7 +2993,7 @@ ipv6_udp_novrf() a=${NSA_IP6} log_start - run_cmd nettest -6 -D -s -d ${NSA_DEV} -2 ${NSA_DEV} & + run_cmd nettest -6 -D -s -I ${NSA_DEV} -3 ${NSA_DEV} & sleep 1 run_cmd nettest -6 -D -d ${NSA_DEV} -r ${a} -0 ${a} log_test_addr ${a} $? 0 "Device server, device client, local conn" @@ -3040,7 +3040,7 @@ ipv6_udp_vrf() for a in ${NSA_IP6} ${VRF_IP6} do log_start - run_cmd nettest -6 -D -d ${VRF} -s -2 ${NSA_DEV} & + run_cmd nettest -6 -D -I ${VRF} -s -3 ${NSA_DEV} & sleep 1 run_cmd_nsb nettest -6 -D -r ${a} log_test_addr ${a} $? 0 "VRF server" @@ -3049,7 +3049,7 @@ ipv6_udp_vrf() for a in ${NSA_IP6} ${VRF_IP6} do log_start - run_cmd nettest -6 -D -d ${NSA_DEV} -s -2 ${NSA_DEV} & + run_cmd nettest -6 -D -I ${NSA_DEV} -s -3 ${NSA_DEV} & sleep 1 run_cmd_nsb nettest -6 -D -r ${a} log_test_addr ${a} $? 0 "Enslaved device server" @@ -3080,7 +3080,7 @@ ipv6_udp_vrf() for a in ${NSA_IP6} ${VRF_IP6} do log_start - run_cmd nettest -6 -D -d ${VRF} -s & + run_cmd nettest -6 -D -I ${VRF} -s & sleep 1 run_cmd nettest -6 -D -d ${VRF} -r ${a} log_test_addr ${a} $? 0 "VRF server, VRF client, local conn" @@ -3095,19 +3095,19 @@ ipv6_udp_vrf() log_test_addr ${a} $? 1 "Global server, device client, local conn" log_start - run_cmd nettest -6 -D -d ${VRF} -s -2 ${NSA_DEV} & + run_cmd nettest -6 -D -I ${VRF} -s -3 ${NSA_DEV} & sleep 1 run_cmd nettest -6 -D -d ${NSA_DEV} -r ${a} log_test_addr ${a} $? 0 "VRF server, device client, local conn" log_start - run_cmd nettest -6 -D -d ${NSA_DEV} -s -2 ${NSA_DEV} & + run_cmd nettest -6 -D -I ${NSA_DEV} -s -3 ${NSA_DEV} & sleep 1 run_cmd nettest -6 -D -d ${VRF} -r ${a} log_test_addr ${a} $? 0 "Enslaved device server, VRF client, local conn" log_start - run_cmd nettest -6 -D -d ${NSA_DEV} -s -2 ${NSA_DEV} & + run_cmd nettest -6 -D -I ${NSA_DEV} -s -3 ${NSA_DEV} & sleep 1 run_cmd nettest -6 -D -d ${NSA_DEV} -r ${a} log_test_addr ${a} $? 0 "Enslaved device server, device client, local conn" @@ -3122,7 +3122,7 @@ ipv6_udp_vrf() for a in ${NSA_IP6} ${VRF_IP6} do log_start - run_cmd nettest -6 -D -s -2 ${NSA_DEV} & + run_cmd nettest -6 -D -s -3 ${NSA_DEV} & sleep 1 run_cmd_nsb nettest -6 -D -r ${a} log_test_addr ${a} $? 0 "Global server" @@ -3131,7 +3131,7 @@ ipv6_udp_vrf() for a in ${NSA_IP6} ${VRF_IP6} do log_start - run_cmd nettest -6 -D -d ${VRF} -s -2 ${NSA_DEV} & + run_cmd nettest -6 -D -I ${VRF} -s -3 ${NSA_DEV} & sleep 1 run_cmd_nsb nettest -6 -D -r ${a} log_test_addr ${a} $? 0 "VRF server" @@ -3140,7 +3140,7 @@ ipv6_udp_vrf() for a in ${NSA_IP6} ${VRF_IP6} do log_start - run_cmd nettest -6 -D -d ${NSA_DEV} -s -2 ${NSA_DEV} & + run_cmd nettest -6 -D -I ${NSA_DEV} -s -3 ${NSA_DEV} & sleep 1 run_cmd_nsb nettest -6 -D -r ${a} log_test_addr ${a} $? 0 "Enslaved device server" @@ -3184,13 +3184,13 @@ ipv6_udp_vrf() # a=${NSA_IP6} log_start - run_cmd nettest -6 -D -s -2 ${NSA_DEV} & + run_cmd nettest -6 -D -s -3 ${NSA_DEV} & sleep 1 run_cmd nettest -6 -D -d ${VRF} -r ${a} log_test_addr ${a} $? 0 "Global server, VRF client, local conn" #log_start - run_cmd nettest -6 -D -d ${VRF} -s -2 ${NSA_DEV} & + run_cmd nettest -6 -D -I ${VRF} -s -3 ${NSA_DEV} & sleep 1 run_cmd nettest -6 -D -d ${VRF} -r ${a} log_test_addr ${a} $? 0 "VRF server, VRF client, local conn" @@ -3198,13 +3198,13 @@ ipv6_udp_vrf() a=${VRF_IP6} log_start - run_cmd nettest -6 -D -s -2 ${VRF} & + run_cmd nettest -6 -D -s -3 ${VRF} & sleep 1 run_cmd nettest -6 -D -d ${VRF} -r ${a} log_test_addr ${a} $? 0 "Global server, VRF client, local conn" log_start - run_cmd nettest -6 -D -d ${VRF} -s -2 ${VRF} & + run_cmd nettest -6 -D -I ${VRF} -s -3 ${VRF} & sleep 1 run_cmd nettest -6 -D -d ${VRF} -r ${a} log_test_addr ${a} $? 0 "VRF server, VRF client, local conn" @@ -3220,25 +3220,25 @@ ipv6_udp_vrf() # device to global IP a=${NSA_IP6} log_start - run_cmd nettest -6 -D -s -2 ${NSA_DEV} & + run_cmd nettest -6 -D -s -3 ${NSA_DEV} & sleep 1 run_cmd nettest -6 -D -d ${NSA_DEV} -r ${a} log_test_addr ${a} $? 0 "Global server, device client, local conn" log_start - run_cmd nettest -6 -D -d ${VRF} -s -2 ${NSA_DEV} & + run_cmd nettest -6 -D -I ${VRF} -s -3 ${NSA_DEV} & sleep 1 run_cmd nettest -6 -D -d ${NSA_DEV} -r ${a} log_test_addr ${a} $? 0 "VRF server, device client, local conn" log_start - run_cmd nettest -6 -D -d ${NSA_DEV} -s -2 ${NSA_DEV} & + run_cmd nettest -6 -D -I ${NSA_DEV} -s -3 ${NSA_DEV} & sleep 1 run_cmd nettest -6 -D -d ${VRF} -r ${a} log_test_addr ${a} $? 0 "Device server, VRF client, local conn" log_start - run_cmd nettest -6 -D -d ${NSA_DEV} -s -2 ${NSA_DEV} & + run_cmd nettest -6 -D -I ${NSA_DEV} -s -3 ${NSA_DEV} & sleep 1 run_cmd nettest -6 -D -d ${NSA_DEV} -r ${a} log_test_addr ${a} $? 0 "Device server, device client, local conn" @@ -3332,7 +3332,7 @@ ipv6_addr_bind_novrf() log_test_addr ${a} $? 0 "Raw socket bind to local address" log_start - run_cmd nettest -6 -s -R -P ipv6-icmp -l ${a} -d ${NSA_DEV} -b + run_cmd nettest -6 -s -R -P ipv6-icmp -l ${a} -I ${NSA_DEV} -b log_test_addr ${a} $? 0 "Raw socket bind to local address after device bind" done @@ -3345,13 +3345,13 @@ ipv6_addr_bind_novrf() log_test_addr ${a} $? 0 "TCP socket bind to local address" log_start - run_cmd nettest -6 -s -l ${a} -d ${NSA_DEV} -t1 -b + run_cmd nettest -6 -s -l ${a} -I ${NSA_DEV} -t1 -b log_test_addr ${a} $? 0 "TCP socket bind to local address after device bind" a=${NSA_LO_IP6} log_start show_hint "Should fail with 'Cannot assign requested address'" - run_cmd nettest -6 -s -l ${a} -d ${NSA_DEV} -t1 -b + run_cmd nettest -6 -s -l ${a} -I ${NSA_DEV} -t1 -b log_test_addr ${a} $? 1 "TCP socket bind to out of scope local address" } @@ -3363,18 +3363,18 @@ ipv6_addr_bind_vrf() for a in ${NSA_IP6} ${VRF_IP6} do log_start - run_cmd nettest -6 -s -R -P ipv6-icmp -l ${a} -d ${VRF} -b + run_cmd nettest -6 -s -R -P ipv6-icmp -l ${a} -I ${VRF} -b log_test_addr ${a} $? 0 "Raw socket bind to local address after vrf bind" log_start - run_cmd nettest -6 -s -R -P ipv6-icmp -l ${a} -d ${NSA_DEV} -b + run_cmd nettest -6 -s -R -P ipv6-icmp -l ${a} -I ${NSA_DEV} -b log_test_addr ${a} $? 0 "Raw socket bind to local address after device bind" done a=${NSA_LO_IP6} log_start show_hint "Address on loopback is out of VRF scope" - run_cmd nettest -6 -s -R -P ipv6-icmp -l ${a} -d ${VRF} -b + run_cmd nettest -6 -s -R -P ipv6-icmp -l ${a} -I ${VRF} -b log_test_addr ${a} $? 1 "Raw socket bind to invalid local address after vrf bind" # @@ -3384,29 +3384,29 @@ ipv6_addr_bind_vrf() for a in ${NSA_IP6} ${VRF_IP6} do log_start - run_cmd nettest -6 -s -l ${a} -d ${VRF} -t1 -b + run_cmd nettest -6 -s -l ${a} -I ${VRF} -t1 -b log_test_addr ${a} $? 0 "TCP socket bind to local address with VRF bind" done a=${NSA_IP6} log_start - run_cmd nettest -6 -s -l ${a} -d ${NSA_DEV} -t1 -b + run_cmd nettest -6 -s -l ${a} -I ${NSA_DEV} -t1 -b log_test_addr ${a} $? 0 "TCP socket bind to local address with device bind" a=${VRF_IP6} log_start - run_cmd nettest -6 -s -l ${a} -d ${NSA_DEV} -t1 -b + run_cmd nettest -6 -s -l ${a} -I ${NSA_DEV} -t1 -b log_test_addr ${a} $? 1 "TCP socket bind to VRF address with device bind" a=${NSA_LO_IP6} log_start show_hint "Address on loopback out of scope for VRF" - run_cmd nettest -6 -s -l ${a} -d ${VRF} -t1 -b + run_cmd nettest -6 -s -l ${a} -I ${VRF} -t1 -b log_test_addr ${a} $? 1 "TCP socket bind to invalid local address for VRF" log_start show_hint "Address on loopback out of scope for device in VRF" - run_cmd nettest -6 -s -l ${a} -d ${NSA_DEV} -t1 -b + run_cmd nettest -6 -s -l ${a} -I ${NSA_DEV} -t1 -b log_test_addr ${a} $? 1 "TCP socket bind to invalid local address for device bind" } @@ -3454,7 +3454,7 @@ ipv6_rt() for a in ${NSA_IP6} ${VRF_IP6} do log_start - run_cmd nettest ${varg} -d ${VRF} -s & + run_cmd nettest ${varg} -I ${VRF} -s & sleep 1 run_cmd_nsb nettest ${varg} -r ${a} & sleep 3 @@ -3468,7 +3468,7 @@ ipv6_rt() for a in ${NSA_IP6} ${VRF_IP6} do log_start - run_cmd nettest ${varg} -d ${NSA_DEV} -s & + run_cmd nettest ${varg} -I ${NSA_DEV} -s & sleep 1 run_cmd_nsb nettest ${varg} -r ${a} & sleep 3 @@ -3525,7 +3525,7 @@ ipv6_rt() for a in ${NSA_IP6} ${VRF_IP6} do log_start - run_cmd nettest ${varg} -d ${VRF} -s & + run_cmd nettest ${varg} -I ${VRF} -s & sleep 1 run_cmd nettest ${varg} -d ${VRF} -r ${a} & sleep 3 @@ -3549,7 +3549,7 @@ ipv6_rt() setup ${with_vrf} log_start - run_cmd nettest ${varg} -d ${VRF} -s & + run_cmd nettest ${varg} -I ${VRF} -s & sleep 1 run_cmd nettest ${varg} -d ${NSA_DEV} -r ${a} & sleep 3 @@ -3560,7 +3560,7 @@ ipv6_rt() setup ${with_vrf} log_start - run_cmd nettest ${varg} -d ${NSA_DEV} -s & + run_cmd nettest ${varg} -I ${NSA_DEV} -s & sleep 1 run_cmd nettest ${varg} -d ${NSA_DEV} -r ${a} & sleep 3 diff --git a/tools/testing/selftests/net/forwarding/tc_chains.sh b/tools/testing/selftests/net/forwarding/tc_chains.sh index 2934fb5ed2a2..b95de0463ebd 100755 --- a/tools/testing/selftests/net/forwarding/tc_chains.sh +++ b/tools/testing/selftests/net/forwarding/tc_chains.sh @@ -136,7 +136,7 @@ template_filter_fits() tc filter add dev $h2 ingress protocol ip pref 1 handle 1102 \ flower src_mac $h2mac action drop &> /dev/null - check_fail $? "Incorrectly succeded to insert filter which does not template" + check_fail $? "Incorrectly succeeded to insert filter which does not template" tc filter add dev $h2 ingress chain 1 protocol ip pref 1 handle 1101 \ flower src_mac $h2mac action drop @@ -144,7 +144,7 @@ template_filter_fits() tc filter add dev $h2 ingress chain 1 protocol ip pref 1 handle 1102 \ flower dst_mac $h2mac action drop &> /dev/null - check_fail $? "Incorrectly succeded to insert filter which does not template" + check_fail $? "Incorrectly succeeded to insert filter which does not template" tc filter del dev $h2 ingress chain 1 protocol ip pref 1 handle 1102 \ flower &> /dev/null diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testing/selftests/net/mptcp/mptcp_join.sh index 9aa9624cff97..f74cd993b168 100755 --- a/tools/testing/selftests/net/mptcp/mptcp_join.sh +++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh @@ -212,6 +212,7 @@ do_transfer() rm_nr_ns1="$7" rm_nr_ns2="$8" speed="$9" + bkup="${10}" port=$((10000+$TEST_COUNT)) TEST_COUNT=$((TEST_COUNT+1)) @@ -297,6 +298,18 @@ do_transfer() fi fi + if [ ! -z $bkup ]; then + sleep 1 + for netns in "$ns1" "$ns2"; do + dump=(`ip netns exec $netns ./pm_nl_ctl dump`) + if [ ${#dump[@]} -gt 0 ]; then + addr=${dump[${#dump[@]} - 1]} + backup="ip netns exec $netns ./pm_nl_ctl set $addr flags $bkup" + $backup + fi + done + fi + wait $cpid retc=$? wait $spid @@ -358,6 +371,7 @@ run_tests() rm_nr_ns1="${5:-0}" rm_nr_ns2="${6:-0}" speed="${7:-fast}" + bkup="${8:-""}" lret=0 oldin="" @@ -372,7 +386,7 @@ run_tests() fi do_transfer ${listener_ns} ${connector_ns} MPTCP MPTCP ${connect_addr} \ - ${test_linkfail} ${rm_nr_ns1} ${rm_nr_ns2} ${speed} + ${test_linkfail} ${rm_nr_ns1} ${rm_nr_ns2} ${speed} ${bkup} lret=$? if [ "$test_linkfail" -eq 1 ];then @@ -509,6 +523,43 @@ chk_rm_nr() fi } +chk_prio_nr() +{ + local mp_prio_nr_tx=$1 + local mp_prio_nr_rx=$2 + local count + local dump_stats + + printf "%-39s %s" " " "ptx" + count=`ip netns exec $ns1 nstat -as | grep MPTcpExtMPPrioTx | awk '{print $2}'` + [ -z "$count" ] && count=0 + if [ "$count" != "$mp_prio_nr_tx" ]; then + echo "[fail] got $count MP_PRIO[s] TX expected $mp_prio_nr_tx" + ret=1 + dump_stats=1 + else + echo -n "[ ok ]" + fi + + echo -n " - prx " + count=`ip netns exec $ns1 nstat -as | grep MPTcpExtMPPrioRx | awk '{print $2}'` + [ -z "$count" ] && count=0 + if [ "$count" != "$mp_prio_nr_rx" ]; then + echo "[fail] got $count MP_PRIO[s] RX expected $mp_prio_nr_rx" + ret=1 + dump_stats=1 + else + echo "[ ok ]" + fi + + if [ "${dump_stats}" = 1 ]; then + echo Server ns stats + ip netns exec $ns1 nstat -as | grep MPTcp + echo Client ns stats + ip netns exec $ns2 nstat -as | grep MPTcp + fi +} + sin=$(mktemp) sout=$(mktemp) cin=$(mktemp) @@ -739,6 +790,25 @@ chk_join_nr "remove subflow and signal IPv6" 2 2 2 chk_add_nr 1 1 chk_rm_nr 1 1 +# single subflow, backup +reset +ip netns exec $ns1 ./pm_nl_ctl limits 0 1 +ip netns exec $ns2 ./pm_nl_ctl limits 0 1 +ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags subflow,backup +run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow nobackup +chk_join_nr "single subflow, backup" 1 1 1 +chk_prio_nr 0 1 + +# single address, backup +reset +ip netns exec $ns1 ./pm_nl_ctl limits 0 1 +ip netns exec $ns1 ./pm_nl_ctl add 10.0.2.1 flags signal +ip netns exec $ns2 ./pm_nl_ctl limits 1 1 +run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow backup +chk_join_nr "single address, backup" 1 1 1 +chk_add_nr 1 1 +chk_prio_nr 1 0 + # single subflow, syncookies reset_with_cookies ip netns exec $ns1 ./pm_nl_ctl limits 0 1 diff --git a/tools/testing/selftests/net/mptcp/pm_netlink.sh b/tools/testing/selftests/net/mptcp/pm_netlink.sh index 15f4f46ca3a9..a617e293734c 100755 --- a/tools/testing/selftests/net/mptcp/pm_netlink.sh +++ b/tools/testing/selftests/net/mptcp/pm_netlink.sh @@ -91,7 +91,7 @@ id 3 flags signal,backup 10.0.1.3" "dump addrs after del" ip netns exec $ns1 ./pm_nl_ctl add 10.0.1.3 check "ip netns exec $ns1 ./pm_nl_ctl get 4" "" "duplicate addr" -ip netns exec $ns1 ./pm_nl_ctl add 10.0.1.4 id 10 flags signal +ip netns exec $ns1 ./pm_nl_ctl add 10.0.1.4 flags signal check "ip netns exec $ns1 ./pm_nl_ctl get 4" "id 4 flags signal 10.0.1.4" "id addr increment" for i in `seq 5 9`; do @@ -102,9 +102,10 @@ check "ip netns exec $ns1 ./pm_nl_ctl get 10" "" "above hard addr limit" for i in `seq 9 256`; do ip netns exec $ns1 ./pm_nl_ctl del $i - ip netns exec $ns1 ./pm_nl_ctl add 10.0.0.9 + ip netns exec $ns1 ./pm_nl_ctl add 10.0.0.9 id $((i+1)) done check "ip netns exec $ns1 ./pm_nl_ctl dump" "id 1 flags 10.0.1.1 +id 2 flags 10.0.0.9 id 3 flags signal,backup 10.0.1.3 id 4 flags signal 10.0.1.4 id 5 flags signal 10.0.1.5 @@ -127,4 +128,40 @@ ip netns exec $ns1 ./pm_nl_ctl limits 8 8 check "ip netns exec $ns1 ./pm_nl_ctl limits" "accept 8 subflows 8" "set limits" +ip netns exec $ns1 ./pm_nl_ctl flush +ip netns exec $ns1 ./pm_nl_ctl add 10.0.1.1 +ip netns exec $ns1 ./pm_nl_ctl add 10.0.1.2 +ip netns exec $ns1 ./pm_nl_ctl add 10.0.1.3 id 100 +ip netns exec $ns1 ./pm_nl_ctl add 10.0.1.4 +ip netns exec $ns1 ./pm_nl_ctl add 10.0.1.5 id 254 +ip netns exec $ns1 ./pm_nl_ctl add 10.0.1.6 +ip netns exec $ns1 ./pm_nl_ctl add 10.0.1.7 +ip netns exec $ns1 ./pm_nl_ctl add 10.0.1.8 +check "ip netns exec $ns1 ./pm_nl_ctl dump" "id 1 flags 10.0.1.1 +id 2 flags 10.0.1.2 +id 3 flags 10.0.1.7 +id 4 flags 10.0.1.8 +id 100 flags 10.0.1.3 +id 101 flags 10.0.1.4 +id 254 flags 10.0.1.5 +id 255 flags 10.0.1.6" "set ids" + +ip netns exec $ns1 ./pm_nl_ctl flush +ip netns exec $ns1 ./pm_nl_ctl add 10.0.0.1 +ip netns exec $ns1 ./pm_nl_ctl add 10.0.0.2 id 254 +ip netns exec $ns1 ./pm_nl_ctl add 10.0.0.3 +ip netns exec $ns1 ./pm_nl_ctl add 10.0.0.4 +ip netns exec $ns1 ./pm_nl_ctl add 10.0.0.5 id 253 +ip netns exec $ns1 ./pm_nl_ctl add 10.0.0.6 +ip netns exec $ns1 ./pm_nl_ctl add 10.0.0.7 +ip netns exec $ns1 ./pm_nl_ctl add 10.0.0.8 +check "ip netns exec $ns1 ./pm_nl_ctl dump" "id 1 flags 10.0.0.1 +id 2 flags 10.0.0.4 +id 3 flags 10.0.0.6 +id 4 flags 10.0.0.7 +id 5 flags 10.0.0.8 +id 253 flags 10.0.0.5 +id 254 flags 10.0.0.2 +id 255 flags 10.0.0.3" "wrap-around ids" + exit $ret diff --git a/tools/testing/selftests/net/mptcp/pm_nl_ctl.c b/tools/testing/selftests/net/mptcp/pm_nl_ctl.c index b24a2f17d415..abc269e96a07 100644 --- a/tools/testing/selftests/net/mptcp/pm_nl_ctl.c +++ b/tools/testing/selftests/net/mptcp/pm_nl_ctl.c @@ -24,10 +24,11 @@ static void syntax(char *argv[]) { - fprintf(stderr, "%s add|get|del|flush|dump|accept [<args>]\n", argv[0]); + fprintf(stderr, "%s add|get|set|del|flush|dump|accept [<args>]\n", argv[0]); fprintf(stderr, "\tadd [flags signal|subflow|backup] [id <nr>] [dev <name>] <ip>\n"); fprintf(stderr, "\tdel <id>\n"); fprintf(stderr, "\tget <id>\n"); + fprintf(stderr, "\tset <ip> [flags backup|nobackup]\n"); fprintf(stderr, "\tflush\n"); fprintf(stderr, "\tdump\n"); fprintf(stderr, "\tlimits [<rcv addr max> <subflow max>]\n"); @@ -584,6 +585,88 @@ int get_set_limits(int fd, int pm_family, int argc, char *argv[]) return 0; } +int set_flags(int fd, int pm_family, int argc, char *argv[]) +{ + char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) + + NLMSG_ALIGN(sizeof(struct genlmsghdr)) + + 1024]; + struct rtattr *rta, *nest; + struct nlmsghdr *nh; + u_int32_t flags = 0; + u_int16_t family; + int nest_start; + int off = 0; + int arg; + + memset(data, 0, sizeof(data)); + nh = (void *)data; + off = init_genl_req(data, pm_family, MPTCP_PM_CMD_SET_FLAGS, + MPTCP_PM_VER); + + if (argc < 3) + syntax(argv); + + nest_start = off; + nest = (void *)(data + off); + nest->rta_type = NLA_F_NESTED | MPTCP_PM_ATTR_ADDR; + nest->rta_len = RTA_LENGTH(0); + off += NLMSG_ALIGN(nest->rta_len); + + /* addr data */ + rta = (void *)(data + off); + if (inet_pton(AF_INET, argv[2], RTA_DATA(rta))) { + family = AF_INET; + rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR4; + rta->rta_len = RTA_LENGTH(4); + } else if (inet_pton(AF_INET6, argv[2], RTA_DATA(rta))) { + family = AF_INET6; + rta->rta_type = MPTCP_PM_ADDR_ATTR_ADDR6; + rta->rta_len = RTA_LENGTH(16); + } else { + error(1, errno, "can't parse ip %s", argv[2]); + } + off += NLMSG_ALIGN(rta->rta_len); + + /* family */ + rta = (void *)(data + off); + rta->rta_type = MPTCP_PM_ADDR_ATTR_FAMILY; + rta->rta_len = RTA_LENGTH(2); + memcpy(RTA_DATA(rta), &family, 2); + off += NLMSG_ALIGN(rta->rta_len); + + for (arg = 3; arg < argc; arg++) { + if (!strcmp(argv[arg], "flags")) { + char *tok, *str; + + /* flags */ + if (++arg >= argc) + error(1, 0, " missing flags value"); + + /* do not support flag list yet */ + for (str = argv[arg]; (tok = strtok(str, ",")); + str = NULL) { + if (!strcmp(tok, "backup")) + flags |= MPTCP_PM_ADDR_FLAG_BACKUP; + else if (strcmp(tok, "nobackup")) + error(1, errno, + "unknown flag %s", argv[arg]); + } + + rta = (void *)(data + off); + rta->rta_type = MPTCP_PM_ADDR_ATTR_FLAGS; + rta->rta_len = RTA_LENGTH(4); + memcpy(RTA_DATA(rta), &flags, 4); + off += NLMSG_ALIGN(rta->rta_len); + } else { + error(1, 0, "unknown keyword %s", argv[arg]); + } + } + nest->rta_len = off - nest_start; + + do_nl_req(fd, nh, off, 0); + return 0; +} + int main(int argc, char *argv[]) { int fd, pm_family; @@ -609,6 +692,8 @@ int main(int argc, char *argv[]) return dump_addrs(fd, pm_family, argc, argv); else if (!strcmp(argv[1], "limits")) return get_set_limits(fd, pm_family, argc, argv); + else if (!strcmp(argv[1], "set")) + return set_flags(fd, pm_family, argc, argv); fprintf(stderr, "unknown sub-command: %s", argv[1]); syntax(argv); diff --git a/tools/testing/selftests/net/nettest.c b/tools/testing/selftests/net/nettest.c index f75c53ce0a2d..6365c7fd1262 100644 --- a/tools/testing/selftests/net/nettest.c +++ b/tools/testing/selftests/net/nettest.c @@ -9,6 +9,7 @@ #include <sys/types.h> #include <sys/ioctl.h> #include <sys/socket.h> +#include <sys/wait.h> #include <linux/tcp.h> #include <arpa/inet.h> #include <net/if.h> @@ -17,6 +18,7 @@ #include <fcntl.h> #include <libgen.h> #include <limits.h> +#include <sched.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> @@ -34,6 +36,8 @@ #define DEFAULT_PORT 12345 +#define NS_PREFIX "/run/netns/" + #ifndef MAX #define MAX(a, b) ((a) > (b) ? (a) : (b)) #endif @@ -43,12 +47,15 @@ struct sock_args { /* local address */ + const char *local_addr_str; + const char *client_local_addr_str; union { struct in_addr in; struct in6_addr in6; } local_addr; /* remote address */ + const char *remote_addr_str; union { struct in_addr in; struct in6_addr in6; @@ -73,10 +80,16 @@ struct sock_args { int use_setsockopt; int use_cmsg; const char *dev; + const char *server_dev; int ifindex; + const char *clientns; + const char *serverns; + const char *password; + const char *client_pw; /* prefix for MD5 password */ + const char *md5_prefix_str; union { struct sockaddr_in v4; struct sockaddr_in6 v6; @@ -84,15 +97,19 @@ struct sock_args { unsigned int prefix_len; /* expected addresses and device index for connection */ + const char *expected_dev; + const char *expected_server_dev; int expected_ifindex; /* local address */ + const char *expected_laddr_str; union { struct in_addr in; struct in6_addr in6; } expected_laddr; /* remote address */ + const char *expected_raddr_str; union { struct in_addr in; struct in6_addr in6; @@ -186,7 +203,7 @@ static void log_address(const char *desc, struct sockaddr *sa) if (sa->sa_family == AF_INET) { struct sockaddr_in *s = (struct sockaddr_in *) sa; - log_msg("%s %s:%d", + log_msg("%s %s:%d\n", desc, inet_ntop(AF_INET, &s->sin_addr, addrstr, sizeof(addrstr)), @@ -195,18 +212,37 @@ static void log_address(const char *desc, struct sockaddr *sa) } else if (sa->sa_family == AF_INET6) { struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) sa; - log_msg("%s [%s]:%d", + log_msg("%s [%s]:%d\n", desc, inet_ntop(AF_INET6, &s6->sin6_addr, addrstr, sizeof(addrstr)), ntohs(s6->sin6_port)); } - printf("\n"); - fflush(stdout); } +static int switch_ns(const char *ns) +{ + char path[PATH_MAX]; + int fd, ret; + + if (geteuid()) + log_error("warning: likely need root to set netns %s!\n", ns); + + snprintf(path, sizeof(path), "%s%s", NS_PREFIX, ns); + fd = open(path, 0); + if (fd < 0) { + log_err_errno("Failed to open netns path; can not switch netns"); + return 1; + } + + ret = setns(fd, CLONE_NEWNET); + close(fd); + + return ret; +} + static int tcp_md5sig(int sd, void *addr, socklen_t alen, struct sock_args *args) { int keylen = strlen(args->password); @@ -259,13 +295,13 @@ static int tcp_md5_remote(int sd, struct sock_args *args) switch (args->version) { case AF_INET: sin.sin_port = htons(args->port); - sin.sin_addr = args->remote_addr.in; + sin.sin_addr = args->md5_prefix.v4.sin_addr; addr = &sin; alen = sizeof(sin); break; case AF_INET6: sin6.sin6_port = htons(args->port); - sin6.sin6_addr = args->remote_addr.in6; + sin6.sin6_addr = args->md5_prefix.v6.sin6_addr; addr = &sin6; alen = sizeof(sin6); break; @@ -522,6 +558,33 @@ static int str_to_uint(const char *str, int min, int max, unsigned int *value) return -1; } +static int resolve_devices(struct sock_args *args) +{ + if (args->dev) { + args->ifindex = get_ifidx(args->dev); + if (args->ifindex < 0) { + log_error("Invalid device name\n"); + return 1; + } + } + + if (args->expected_dev) { + unsigned int tmp; + + if (str_to_uint(args->expected_dev, 0, INT_MAX, &tmp) == 0) { + args->expected_ifindex = (int)tmp; + } else { + args->expected_ifindex = get_ifidx(args->expected_dev); + if (args->expected_ifindex < 0) { + fprintf(stderr, "Invalid expected device\n"); + return 1; + } + } + } + + return 0; +} + static int expected_addr_match(struct sockaddr *sa, void *expected, const char *desc) { @@ -533,7 +596,7 @@ static int expected_addr_match(struct sockaddr *sa, void *expected, struct in_addr *exp_in = (struct in_addr *) expected; if (s->sin_addr.s_addr != exp_in->s_addr) { - log_error("%s address does not match expected %s", + log_error("%s address does not match expected %s\n", desc, inet_ntop(AF_INET, exp_in, addrstr, sizeof(addrstr))); @@ -544,14 +607,14 @@ static int expected_addr_match(struct sockaddr *sa, void *expected, struct in6_addr *exp_in = (struct in6_addr *) expected; if (memcmp(&s6->sin6_addr, exp_in, sizeof(*exp_in))) { - log_error("%s address does not match expected %s", + log_error("%s address does not match expected %s\n", desc, inet_ntop(AF_INET6, exp_in, addrstr, sizeof(addrstr))); rc = 1; } } else { - log_error("%s address does not match expected - unknown family", + log_error("%s address does not match expected - unknown family\n", desc); rc = 1; } @@ -599,6 +662,160 @@ static int show_sockstat(int sd, struct sock_args *args) return rc; } +enum addr_type { + ADDR_TYPE_LOCAL, + ADDR_TYPE_REMOTE, + ADDR_TYPE_MCAST, + ADDR_TYPE_EXPECTED_LOCAL, + ADDR_TYPE_EXPECTED_REMOTE, + ADDR_TYPE_MD5_PREFIX, +}; + +static int convert_addr(struct sock_args *args, const char *_str, + enum addr_type atype) +{ + int pfx_len_max = args->version == AF_INET6 ? 128 : 32; + int family = args->version; + char *str, *dev, *sep; + struct in6_addr *in6; + struct in_addr *in; + const char *desc; + void *addr; + int rc = 0; + + str = strdup(_str); + if (!str) + return -ENOMEM; + + switch (atype) { + case ADDR_TYPE_LOCAL: + desc = "local"; + addr = &args->local_addr; + break; + case ADDR_TYPE_REMOTE: + desc = "remote"; + addr = &args->remote_addr; + break; + case ADDR_TYPE_MCAST: + desc = "mcast grp"; + addr = &args->grp; + break; + case ADDR_TYPE_EXPECTED_LOCAL: + desc = "expected local"; + addr = &args->expected_laddr; + break; + case ADDR_TYPE_EXPECTED_REMOTE: + desc = "expected remote"; + addr = &args->expected_raddr; + break; + case ADDR_TYPE_MD5_PREFIX: + desc = "md5 prefix"; + if (family == AF_INET) { + args->md5_prefix.v4.sin_family = AF_INET; + addr = &args->md5_prefix.v4.sin_addr; + } else if (family == AF_INET6) { + args->md5_prefix.v6.sin6_family = AF_INET6; + addr = &args->md5_prefix.v6.sin6_addr; + } else + return 1; + + sep = strchr(str, '/'); + if (sep) { + *sep = '\0'; + sep++; + if (str_to_uint(sep, 1, pfx_len_max, + &args->prefix_len) != 0) { + fprintf(stderr, "Invalid port\n"); + return 1; + } + } else { + args->prefix_len = 0; + } + break; + default: + log_error("unknown address type\n"); + exit(1); + } + + switch (family) { + case AF_INET: + in = (struct in_addr *) addr; + if (str) { + if (inet_pton(AF_INET, str, in) == 0) { + log_error("Invalid %s IP address\n", desc); + rc = -1; + goto out; + } + } else { + in->s_addr = htonl(INADDR_ANY); + } + break; + + case AF_INET6: + dev = strchr(str, '%'); + if (dev) { + *dev = '\0'; + dev++; + } + + in6 = (struct in6_addr *) addr; + if (str) { + if (inet_pton(AF_INET6, str, in6) == 0) { + log_error("Invalid %s IPv6 address\n", desc); + rc = -1; + goto out; + } + } else { + *in6 = in6addr_any; + } + if (dev) { + args->scope_id = get_ifidx(dev); + if (args->scope_id < 0) { + log_error("Invalid scope on %s IPv6 address\n", + desc); + rc = -1; + goto out; + } + } + break; + + default: + log_error("Invalid address family\n"); + } + +out: + free(str); + return rc; +} + +static int validate_addresses(struct sock_args *args) +{ + if (args->local_addr_str && + convert_addr(args, args->local_addr_str, ADDR_TYPE_LOCAL) < 0) + return 1; + + if (args->remote_addr_str && + convert_addr(args, args->remote_addr_str, ADDR_TYPE_REMOTE) < 0) + return 1; + + if (args->md5_prefix_str && + convert_addr(args, args->md5_prefix_str, + ADDR_TYPE_MD5_PREFIX) < 0) + return 1; + + if (args->expected_laddr_str && + convert_addr(args, args->expected_laddr_str, + ADDR_TYPE_EXPECTED_LOCAL)) + return 1; + + if (args->expected_raddr_str && + convert_addr(args, args->expected_raddr_str, + ADDR_TYPE_EXPECTED_REMOTE)) + return 1; + + return 0; +} + static int get_index_from_cmsg(struct msghdr *m) { struct cmsghdr *cm; @@ -1180,8 +1397,19 @@ err: return -1; } -static int do_server(struct sock_args *args) +static void ipc_write(int fd, int message) +{ + /* Not in both_mode, so there's no process to signal */ + if (fd < 0) + return; + + if (write(fd, &message, sizeof(message)) < 0) + log_err_errno("Failed to send client status"); +} + +static int do_server(struct sock_args *args, int ipc_fd) { + /* ipc_fd = -1 if no parent process to signal */ struct timeval timeout = { .tv_sec = prog_timeout }, *ptval = NULL; unsigned char addr[sizeof(struct sockaddr_in6)] = {}; socklen_t alen = sizeof(addr); @@ -1190,6 +1418,20 @@ static int do_server(struct sock_args *args) fd_set rfds; int rc; + if (args->serverns) { + if (switch_ns(args->serverns)) { + log_error("Could not set server netns to %s\n", + args->serverns); + goto err_exit; + } + log_msg("Switched server netns\n"); + } + + args->dev = args->server_dev; + args->expected_dev = args->expected_server_dev; + if (resolve_devices(args) || validate_addresses(args)) + goto err_exit; + if (prog_timeout) ptval = &timeout; @@ -1199,14 +1441,16 @@ static int do_server(struct sock_args *args) lsd = lsock_init(args); if (lsd < 0) - return 1; + goto err_exit; if (args->bind_test_only) { close(lsd); + ipc_write(ipc_fd, 1); return 0; } if (args->type != SOCK_STREAM) { + ipc_write(ipc_fd, 1); rc = msg_loop(0, lsd, (void *) addr, alen, args); close(lsd); return rc; @@ -1214,11 +1458,11 @@ static int do_server(struct sock_args *args) if (args->password && tcp_md5_remote(lsd, args)) { close(lsd); - return 1; + goto err_exit; } + ipc_write(ipc_fd, 1); while (1) { - log_msg("\n"); log_msg("waiting for client connection.\n"); FD_ZERO(&rfds); FD_SET(lsd, &rfds); @@ -1264,6 +1508,9 @@ static int do_server(struct sock_args *args) close(lsd); return rc; +err_exit: + ipc_write(ipc_fd, 0); + return 1; } static int wait_for_connect(int sd) @@ -1375,6 +1622,26 @@ static int do_client(struct sock_args *args) return 1; } + if (args->clientns) { + if (switch_ns(args->clientns)) { + log_error("Could not set client netns to %s\n", + args->clientns); + return 1; + } + log_msg("Switched client netns\n"); + } + + args->local_addr_str = args->client_local_addr_str; + if (resolve_devices(args) || validate_addresses(args)) + return 1; + + if ((args->use_setsockopt || args->use_cmsg) && !args->ifindex) { + fprintf(stderr, "Device binding not specified\n"); + return 1; + } + if (args->use_setsockopt || args->use_cmsg) + args->dev = NULL; + switch (args->version) { case AF_INET: sin.sin_port = htons(args->port); @@ -1394,6 +1661,8 @@ static int do_client(struct sock_args *args) break; } + args->password = args->client_pw; + if (args->has_grp) sd = msock_client(args); else @@ -1419,132 +1688,6 @@ out: return rc; } -enum addr_type { - ADDR_TYPE_LOCAL, - ADDR_TYPE_REMOTE, - ADDR_TYPE_MCAST, - ADDR_TYPE_EXPECTED_LOCAL, - ADDR_TYPE_EXPECTED_REMOTE, - ADDR_TYPE_MD5_PREFIX, -}; - -static int convert_addr(struct sock_args *args, const char *_str, - enum addr_type atype) -{ - int pfx_len_max = args->version == AF_INET6 ? 128 : 32; - int family = args->version; - char *str, *dev, *sep; - struct in6_addr *in6; - struct in_addr *in; - const char *desc; - void *addr; - int rc = 0; - - str = strdup(_str); - if (!str) - return -ENOMEM; - - switch (atype) { - case ADDR_TYPE_LOCAL: - desc = "local"; - addr = &args->local_addr; - break; - case ADDR_TYPE_REMOTE: - desc = "remote"; - addr = &args->remote_addr; - break; - case ADDR_TYPE_MCAST: - desc = "mcast grp"; - addr = &args->grp; - break; - case ADDR_TYPE_EXPECTED_LOCAL: - desc = "expected local"; - addr = &args->expected_laddr; - break; - case ADDR_TYPE_EXPECTED_REMOTE: - desc = "expected remote"; - addr = &args->expected_raddr; - break; - case ADDR_TYPE_MD5_PREFIX: - desc = "md5 prefix"; - if (family == AF_INET) { - args->md5_prefix.v4.sin_family = AF_INET; - addr = &args->md5_prefix.v4.sin_addr; - } else if (family == AF_INET6) { - args->md5_prefix.v6.sin6_family = AF_INET6; - addr = &args->md5_prefix.v6.sin6_addr; - } else - return 1; - - sep = strchr(str, '/'); - if (sep) { - *sep = '\0'; - sep++; - if (str_to_uint(sep, 1, pfx_len_max, - &args->prefix_len) != 0) { - fprintf(stderr, "Invalid port\n"); - return 1; - } - } else { - args->prefix_len = pfx_len_max; - } - break; - default: - log_error("unknown address type"); - exit(1); - } - - switch (family) { - case AF_INET: - in = (struct in_addr *) addr; - if (str) { - if (inet_pton(AF_INET, str, in) == 0) { - log_error("Invalid %s IP address\n", desc); - rc = -1; - goto out; - } - } else { - in->s_addr = htonl(INADDR_ANY); - } - break; - - case AF_INET6: - dev = strchr(str, '%'); - if (dev) { - *dev = '\0'; - dev++; - } - - in6 = (struct in6_addr *) addr; - if (str) { - if (inet_pton(AF_INET6, str, in6) == 0) { - log_error("Invalid %s IPv6 address\n", desc); - rc = -1; - goto out; - } - } else { - *in6 = in6addr_any; - } - if (dev) { - args->scope_id = get_ifidx(dev); - if (args->scope_id < 0) { - log_error("Invalid scope on %s IPv6 address\n", - desc); - rc = -1; - goto out; - } - } - break; - - default: - log_error("Invalid address family\n"); - } - -out: - free(str); - return rc; -} - static char *random_msg(int len) { int i, n = 0, olen = len + 1; @@ -1568,7 +1711,68 @@ static char *random_msg(int len) return m; } -#define GETOPT_STR "sr:l:p:t:g:P:DRn:M:m:d:SCi6L:0:1:2:Fbq" +static int ipc_child(int fd, struct sock_args *args) +{ + char *outbuf, *errbuf; + int rc = 1; + + outbuf = malloc(4096); + errbuf = malloc(4096); + if (!outbuf || !errbuf) { + fprintf(stderr, "server: Failed to allocate buffers for stdout and stderr\n"); + goto out; + } + + setbuffer(stdout, outbuf, 4096); + setbuffer(stderr, errbuf, 4096); + + server_mode = 1; /* to tell log_msg in case we are in both_mode */ + + /* when running in both mode, address validation applies + * solely to client side + */ + args->has_expected_laddr = 0; + args->has_expected_raddr = 0; + + rc = do_server(args, fd); + +out: + free(outbuf); + free(errbuf); + + return rc; +} + +static int ipc_parent(int cpid, int fd, struct sock_args *args) +{ + int client_status; + int status; + int buf; + + /* do the client-side function here in the parent process, + * waiting to be told when to continue + */ + if (read(fd, &buf, sizeof(buf)) <= 0) { + log_err_errno("Failed to read IPC status from status"); + return 1; + } + if (!buf) { + log_error("Server failed; can not continue\n"); + return 1; + } + log_msg("Server is ready\n"); + + client_status = do_client(args); + log_msg("parent is done!\n"); + + if (kill(cpid, 0) == 0) + kill(cpid, SIGKILL); + + wait(&status); + return client_status; +} + +#define GETOPT_STR "sr:l:c:p:t:g:P:DRn:M:X:m:d:I:BN:O:SCi6L:0:1:2:3:Fbq" static void print_usage(char *prog) { @@ -1582,13 +1786,18 @@ static void print_usage(char *prog) " -t timeout seconds (default: none)\n" "\n" "Optional:\n" + " -B do both client and server via fork and IPC\n" + " -N ns set client to network namespace ns (requires root)\n" + " -O ns set server to network namespace ns (requires root)\n" " -F Restart server loop\n" " -6 IPv6 (default is IPv4)\n" " -P proto protocol for socket: icmp, ospf (default: none)\n" " -D|R datagram (D) / raw (R) socket (default stream)\n" - " -l addr local address to bind to\n" + " -l addr local address to bind to in server mode\n" + " -c addr local address to bind to in client mode\n" "\n" " -d dev bind socket to given device name\n" + " -I dev bind socket to given device name - server mode\n" " -S use setsockopt (IP_UNICAST_IF or IP_MULTICAST_IF)\n" " to set device binding\n" " -C use cmsg and IP_PKTINFO to specify device binding\n" @@ -1597,6 +1806,7 @@ static void print_usage(char *prog) " -n num number of times to send message\n" "\n" " -M password use MD5 sum protection\n" + " -X password MD5 password for client mode\n" " -m prefix/len prefix and length to use for MD5 key\n" " -g grp multicast group (e.g., 239.1.1.1)\n" " -i interactive mode (default is echo and terminate)\n" @@ -1604,6 +1814,7 @@ static void print_usage(char *prog) " -0 addr Expected local address\n" " -1 addr Expected remote address\n" " -2 dev Expected device name (or index) to receive packet\n" + " -3 dev Expected device name (or index) to receive packets - server mode\n" "\n" " -b Bind test only.\n" " -q Be quiet. Run test without printing anything.\n" @@ -1618,8 +1829,11 @@ int main(int argc, char *argv[]) .port = DEFAULT_PORT, }; struct protoent *pe; + int both_mode = 0; unsigned int tmp; int forever = 0; + int fd[2]; + int cpid; /* process inputs */ extern char *optarg; @@ -1631,6 +1845,9 @@ int main(int argc, char *argv[]) while ((rc = getopt(argc, argv, GETOPT_STR)) != -1) { switch (rc) { + case 'B': + both_mode = 1; + break; case 's': server_mode = 1; break; @@ -1639,13 +1856,15 @@ int main(int argc, char *argv[]) break; case 'l': args.has_local_ip = 1; - if (convert_addr(&args, optarg, ADDR_TYPE_LOCAL) < 0) - return 1; + args.local_addr_str = optarg; break; case 'r': args.has_remote_ip = 1; - if (convert_addr(&args, optarg, ADDR_TYPE_REMOTE) < 0) - return 1; + args.remote_addr_str = optarg; + break; + case 'c': + args.has_local_ip = 1; + args.client_local_addr_str = optarg; break; case 'p': if (str_to_uint(optarg, 1, 65535, &tmp) != 0) { @@ -1685,15 +1904,23 @@ int main(int argc, char *argv[]) case 'n': iter = atoi(optarg); break; + case 'N': + args.clientns = optarg; + break; + case 'O': + args.serverns = optarg; + break; case 'L': msg = random_msg(atoi(optarg)); break; case 'M': args.password = optarg; break; + case 'X': + args.client_pw = optarg; + break; case 'm': - if (convert_addr(&args, optarg, ADDR_TYPE_MD5_PREFIX) < 0) - return 1; + args.md5_prefix_str = optarg; break; case 'S': args.use_setsockopt = 1; @@ -1703,11 +1930,9 @@ int main(int argc, char *argv[]) break; case 'd': args.dev = optarg; - args.ifindex = get_ifidx(optarg); - if (args.ifindex < 0) { - fprintf(stderr, "Invalid device name\n"); - return 1; - } + break; + case 'I': + args.server_dev = optarg; break; case 'i': interactive = 1; @@ -1726,28 +1951,17 @@ int main(int argc, char *argv[]) break; case '0': args.has_expected_laddr = 1; - if (convert_addr(&args, optarg, - ADDR_TYPE_EXPECTED_LOCAL)) - return 1; + args.expected_laddr_str = optarg; break; case '1': args.has_expected_raddr = 1; - if (convert_addr(&args, optarg, - ADDR_TYPE_EXPECTED_REMOTE)) - return 1; - + args.expected_raddr_str = optarg; break; case '2': - if (str_to_uint(optarg, 0, INT_MAX, &tmp) == 0) { - args.expected_ifindex = (int)tmp; - } else { - args.expected_ifindex = get_ifidx(optarg); - if (args.expected_ifindex < 0) { - fprintf(stderr, - "Invalid expected device\n"); - return 1; - } - } + args.expected_dev = optarg; + break; + case '3': + args.expected_server_dev = optarg; break; case 'q': quiet = 1; @@ -1759,23 +1973,17 @@ int main(int argc, char *argv[]) } if (args.password && - ((!args.has_remote_ip && !args.prefix_len) || args.type != SOCK_STREAM)) { + ((!args.has_remote_ip && !args.md5_prefix_str) || + args.type != SOCK_STREAM)) { log_error("MD5 passwords apply to TCP only and require a remote ip for the password\n"); return 1; } - if (args.prefix_len && !args.password) { + if (args.md5_prefix_str && !args.password) { log_error("Prefix range for MD5 protection specified without a password\n"); return 1; } - if ((args.use_setsockopt || args.use_cmsg) && !args.ifindex) { - fprintf(stderr, "Device binding not specified\n"); - return 1; - } - if (args.use_setsockopt || args.use_cmsg) - args.dev = NULL; - if (iter == 0) { fprintf(stderr, "Invalid number of messages to send\n"); return 1; @@ -1792,7 +2000,7 @@ int main(int argc, char *argv[]) return 1; } - if (!server_mode && !args.has_grp && + if ((both_mode || !server_mode) && !args.has_grp && !args.has_remote_ip && !args.has_local_ip) { fprintf(stderr, "Local (server mode) or remote IP (client IP) required\n"); @@ -1804,9 +2012,26 @@ int main(int argc, char *argv[]) msg = NULL; } + if (both_mode) { + if (pipe(fd) < 0) { + perror("pipe"); + exit(1); + } + + cpid = fork(); + if (cpid < 0) { + perror("fork"); + exit(1); + } + if (cpid) + return ipc_parent(cpid, fd[0], &args); + + return ipc_child(fd[1], &args); + } + if (server_mode) { do { - rc = do_server(&args); + rc = do_server(&args, -1); } while (forever); return rc; |