Merge branch 'for-6.10-fixes' into for-6.11
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/sizes.h>
|
||||
|
@@ -1,7 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
|
||||
CFLAGS += $(shell pkg-config --cflags alsa)
|
||||
CFLAGS += $(shell pkg-config --cflags alsa) $(KHDR_INCLUDES)
|
||||
LDLIBS += $(shell pkg-config --libs alsa)
|
||||
ifeq ($(LDLIBS),)
|
||||
LDLIBS += -lasound
|
||||
|
@@ -73,6 +73,16 @@ static int create_netkit(int mode, int policy, int peer_policy, int *ifindex,
|
||||
"up primary");
|
||||
ASSERT_OK(system("ip addr add dev " netkit_name " 10.0.0.1/24"),
|
||||
"addr primary");
|
||||
|
||||
if (mode == NETKIT_L3) {
|
||||
ASSERT_EQ(system("ip link set dev " netkit_name
|
||||
" addr ee:ff:bb:cc:aa:dd 2> /dev/null"), 512,
|
||||
"set hwaddress");
|
||||
} else {
|
||||
ASSERT_OK(system("ip link set dev " netkit_name
|
||||
" addr ee:ff:bb:cc:aa:dd"),
|
||||
"set hwaddress");
|
||||
}
|
||||
if (same_netns) {
|
||||
ASSERT_OK(system("ip link set dev " netkit_peer " up"),
|
||||
"up peer");
|
||||
@@ -89,6 +99,16 @@ static int create_netkit(int mode, int policy, int peer_policy, int *ifindex,
|
||||
return err;
|
||||
}
|
||||
|
||||
static void move_netkit(void)
|
||||
{
|
||||
ASSERT_OK(system("ip link set " netkit_peer " netns foo"),
|
||||
"move peer");
|
||||
ASSERT_OK(system("ip netns exec foo ip link set dev "
|
||||
netkit_peer " up"), "up peer");
|
||||
ASSERT_OK(system("ip netns exec foo ip addr add dev "
|
||||
netkit_peer " 10.0.0.2/24"), "addr peer");
|
||||
}
|
||||
|
||||
static void destroy_netkit(void)
|
||||
{
|
||||
ASSERT_OK(system("ip link del dev " netkit_name), "del primary");
|
||||
@@ -685,3 +705,77 @@ void serial_test_tc_netkit_neigh_links(void)
|
||||
serial_test_tc_netkit_neigh_links_target(NETKIT_L2, BPF_NETKIT_PRIMARY);
|
||||
serial_test_tc_netkit_neigh_links_target(NETKIT_L3, BPF_NETKIT_PRIMARY);
|
||||
}
|
||||
|
||||
static void serial_test_tc_netkit_pkt_type_mode(int mode)
|
||||
{
|
||||
LIBBPF_OPTS(bpf_netkit_opts, optl_nk);
|
||||
LIBBPF_OPTS(bpf_tcx_opts, optl_tcx);
|
||||
int err, ifindex, ifindex2;
|
||||
struct test_tc_link *skel;
|
||||
struct bpf_link *link;
|
||||
|
||||
err = create_netkit(mode, NETKIT_PASS, NETKIT_PASS,
|
||||
&ifindex, true);
|
||||
if (err)
|
||||
return;
|
||||
|
||||
ifindex2 = if_nametoindex(netkit_peer);
|
||||
ASSERT_NEQ(ifindex, ifindex2, "ifindex_1_2");
|
||||
|
||||
skel = test_tc_link__open();
|
||||
if (!ASSERT_OK_PTR(skel, "skel_open"))
|
||||
goto cleanup;
|
||||
|
||||
ASSERT_EQ(bpf_program__set_expected_attach_type(skel->progs.tc1,
|
||||
BPF_NETKIT_PRIMARY), 0, "tc1_attach_type");
|
||||
ASSERT_EQ(bpf_program__set_expected_attach_type(skel->progs.tc7,
|
||||
BPF_TCX_INGRESS), 0, "tc7_attach_type");
|
||||
|
||||
err = test_tc_link__load(skel);
|
||||
if (!ASSERT_OK(err, "skel_load"))
|
||||
goto cleanup;
|
||||
|
||||
assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 0);
|
||||
assert_mprog_count_ifindex(ifindex2, BPF_TCX_INGRESS, 0);
|
||||
|
||||
link = bpf_program__attach_netkit(skel->progs.tc1, ifindex, &optl_nk);
|
||||
if (!ASSERT_OK_PTR(link, "link_attach"))
|
||||
goto cleanup;
|
||||
|
||||
skel->links.tc1 = link;
|
||||
|
||||
assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 1);
|
||||
assert_mprog_count_ifindex(ifindex2, BPF_TCX_INGRESS, 0);
|
||||
|
||||
link = bpf_program__attach_tcx(skel->progs.tc7, ifindex2, &optl_tcx);
|
||||
if (!ASSERT_OK_PTR(link, "link_attach"))
|
||||
goto cleanup;
|
||||
|
||||
skel->links.tc7 = link;
|
||||
|
||||
assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 1);
|
||||
assert_mprog_count_ifindex(ifindex2, BPF_TCX_INGRESS, 1);
|
||||
|
||||
move_netkit();
|
||||
|
||||
tc_skel_reset_all_seen(skel);
|
||||
skel->bss->set_type = true;
|
||||
ASSERT_EQ(send_icmp(), 0, "icmp_pkt");
|
||||
|
||||
ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
|
||||
ASSERT_EQ(skel->bss->seen_tc7, true, "seen_tc7");
|
||||
|
||||
ASSERT_EQ(skel->bss->seen_host, true, "seen_host");
|
||||
ASSERT_EQ(skel->bss->seen_mcast, true, "seen_mcast");
|
||||
cleanup:
|
||||
test_tc_link__destroy(skel);
|
||||
|
||||
assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 0);
|
||||
destroy_netkit();
|
||||
}
|
||||
|
||||
void serial_test_tc_netkit_pkt_type(void)
|
||||
{
|
||||
serial_test_tc_netkit_pkt_type_mode(NETKIT_L2);
|
||||
serial_test_tc_netkit_pkt_type_mode(NETKIT_L3);
|
||||
}
|
||||
|
@@ -1,12 +1,14 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#include <test_progs.h>
|
||||
#include "uprobe_multi.skel.h"
|
||||
#include "uprobe_multi_bench.skel.h"
|
||||
#include "uprobe_multi_usdt.skel.h"
|
||||
#include "bpf/libbpf_internal.h"
|
||||
#include "testing_helpers.h"
|
||||
#include "../sdt.h"
|
||||
|
||||
static char test_data[] = "test_data";
|
||||
|
||||
@@ -25,9 +27,17 @@ noinline void uprobe_multi_func_3(void)
|
||||
asm volatile ("");
|
||||
}
|
||||
|
||||
noinline void usdt_trigger(void)
|
||||
{
|
||||
STAP_PROBE(test, pid_filter_usdt);
|
||||
}
|
||||
|
||||
struct child {
|
||||
int go[2];
|
||||
int c2p[2]; /* child -> parent channel */
|
||||
int pid;
|
||||
int tid;
|
||||
pthread_t thread;
|
||||
};
|
||||
|
||||
static void release_child(struct child *child)
|
||||
@@ -38,6 +48,10 @@ static void release_child(struct child *child)
|
||||
return;
|
||||
close(child->go[1]);
|
||||
close(child->go[0]);
|
||||
if (child->thread)
|
||||
pthread_join(child->thread, NULL);
|
||||
close(child->c2p[0]);
|
||||
close(child->c2p[1]);
|
||||
if (child->pid > 0)
|
||||
waitpid(child->pid, &child_status, 0);
|
||||
}
|
||||
@@ -63,7 +77,7 @@ static struct child *spawn_child(void)
|
||||
if (pipe(child.go))
|
||||
return NULL;
|
||||
|
||||
child.pid = fork();
|
||||
child.pid = child.tid = fork();
|
||||
if (child.pid < 0) {
|
||||
release_child(&child);
|
||||
errno = EINVAL;
|
||||
@@ -82,6 +96,7 @@ static struct child *spawn_child(void)
|
||||
uprobe_multi_func_1();
|
||||
uprobe_multi_func_2();
|
||||
uprobe_multi_func_3();
|
||||
usdt_trigger();
|
||||
|
||||
exit(errno);
|
||||
}
|
||||
@@ -89,6 +104,67 @@ static struct child *spawn_child(void)
|
||||
return &child;
|
||||
}
|
||||
|
||||
static void *child_thread(void *ctx)
|
||||
{
|
||||
struct child *child = ctx;
|
||||
int c = 0, err;
|
||||
|
||||
child->tid = syscall(SYS_gettid);
|
||||
|
||||
/* let parent know we are ready */
|
||||
err = write(child->c2p[1], &c, 1);
|
||||
if (err != 1)
|
||||
pthread_exit(&err);
|
||||
|
||||
/* wait for parent's kick */
|
||||
err = read(child->go[0], &c, 1);
|
||||
if (err != 1)
|
||||
pthread_exit(&err);
|
||||
|
||||
uprobe_multi_func_1();
|
||||
uprobe_multi_func_2();
|
||||
uprobe_multi_func_3();
|
||||
usdt_trigger();
|
||||
|
||||
err = 0;
|
||||
pthread_exit(&err);
|
||||
}
|
||||
|
||||
static struct child *spawn_thread(void)
|
||||
{
|
||||
static struct child child;
|
||||
int c, err;
|
||||
|
||||
/* pipe to notify child to execute the trigger functions */
|
||||
if (pipe(child.go))
|
||||
return NULL;
|
||||
/* pipe to notify parent that child thread is ready */
|
||||
if (pipe(child.c2p)) {
|
||||
close(child.go[0]);
|
||||
close(child.go[1]);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
child.pid = getpid();
|
||||
|
||||
err = pthread_create(&child.thread, NULL, child_thread, &child);
|
||||
if (err) {
|
||||
err = -errno;
|
||||
close(child.go[0]);
|
||||
close(child.go[1]);
|
||||
close(child.c2p[0]);
|
||||
close(child.c2p[1]);
|
||||
errno = -err;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
err = read(child.c2p[0], &c, 1);
|
||||
if (!ASSERT_EQ(err, 1, "child_thread_ready"))
|
||||
return NULL;
|
||||
|
||||
return &child;
|
||||
}
|
||||
|
||||
static void uprobe_multi_test_run(struct uprobe_multi *skel, struct child *child)
|
||||
{
|
||||
skel->bss->uprobe_multi_func_1_addr = (__u64) uprobe_multi_func_1;
|
||||
@@ -103,15 +179,23 @@ static void uprobe_multi_test_run(struct uprobe_multi *skel, struct child *child
|
||||
* passed at the probe attach.
|
||||
*/
|
||||
skel->bss->pid = child ? 0 : getpid();
|
||||
skel->bss->expect_pid = child ? child->pid : 0;
|
||||
|
||||
/* trigger all probes, if we are testing child *process*, just to make
|
||||
* sure that PID filtering doesn't let through activations from wrong
|
||||
* PIDs; when we test child *thread*, we don't want to do this to
|
||||
* avoid double counting number of triggering events
|
||||
*/
|
||||
if (!child || !child->thread) {
|
||||
uprobe_multi_func_1();
|
||||
uprobe_multi_func_2();
|
||||
uprobe_multi_func_3();
|
||||
usdt_trigger();
|
||||
}
|
||||
|
||||
if (child)
|
||||
kick_child(child);
|
||||
|
||||
/* trigger all probes */
|
||||
uprobe_multi_func_1();
|
||||
uprobe_multi_func_2();
|
||||
uprobe_multi_func_3();
|
||||
|
||||
/*
|
||||
* There are 2 entry and 2 exit probe called for each uprobe_multi_func_[123]
|
||||
* function and each slepable probe (6) increments uprobe_multi_sleep_result.
|
||||
@@ -126,8 +210,12 @@ static void uprobe_multi_test_run(struct uprobe_multi *skel, struct child *child
|
||||
|
||||
ASSERT_EQ(skel->bss->uprobe_multi_sleep_result, 6, "uprobe_multi_sleep_result");
|
||||
|
||||
if (child)
|
||||
ASSERT_FALSE(skel->bss->bad_pid_seen, "bad_pid_seen");
|
||||
|
||||
if (child) {
|
||||
ASSERT_EQ(skel->bss->child_pid, child->pid, "uprobe_multi_child_pid");
|
||||
ASSERT_EQ(skel->bss->child_tid, child->tid, "uprobe_multi_child_tid");
|
||||
}
|
||||
}
|
||||
|
||||
static void test_skel_api(void)
|
||||
@@ -190,8 +278,24 @@ __test_attach_api(const char *binary, const char *pattern, struct bpf_uprobe_mul
|
||||
if (!ASSERT_OK_PTR(skel->links.uprobe_extra, "bpf_program__attach_uprobe_multi"))
|
||||
goto cleanup;
|
||||
|
||||
/* Attach (uprobe-backed) USDTs */
|
||||
skel->links.usdt_pid = bpf_program__attach_usdt(skel->progs.usdt_pid, pid, binary,
|
||||
"test", "pid_filter_usdt", NULL);
|
||||
if (!ASSERT_OK_PTR(skel->links.usdt_pid, "attach_usdt_pid"))
|
||||
goto cleanup;
|
||||
|
||||
skel->links.usdt_extra = bpf_program__attach_usdt(skel->progs.usdt_extra, -1, binary,
|
||||
"test", "pid_filter_usdt", NULL);
|
||||
if (!ASSERT_OK_PTR(skel->links.usdt_extra, "attach_usdt_extra"))
|
||||
goto cleanup;
|
||||
|
||||
uprobe_multi_test_run(skel, child);
|
||||
|
||||
ASSERT_FALSE(skel->bss->bad_pid_seen_usdt, "bad_pid_seen_usdt");
|
||||
if (child) {
|
||||
ASSERT_EQ(skel->bss->child_pid_usdt, child->pid, "usdt_multi_child_pid");
|
||||
ASSERT_EQ(skel->bss->child_tid_usdt, child->tid, "usdt_multi_child_tid");
|
||||
}
|
||||
cleanup:
|
||||
uprobe_multi__destroy(skel);
|
||||
}
|
||||
@@ -210,6 +314,13 @@ test_attach_api(const char *binary, const char *pattern, struct bpf_uprobe_multi
|
||||
return;
|
||||
|
||||
__test_attach_api(binary, pattern, opts, child);
|
||||
|
||||
/* pid filter (thread) */
|
||||
child = spawn_thread();
|
||||
if (!ASSERT_OK_PTR(child, "spawn_thread"))
|
||||
return;
|
||||
|
||||
__test_attach_api(binary, pattern, opts, child);
|
||||
}
|
||||
|
||||
static void test_attach_api_pattern(void)
|
||||
@@ -397,7 +508,7 @@ static void test_attach_api_fails(void)
|
||||
link_fd = bpf_link_create(prog_fd, 0, BPF_TRACE_UPROBE_MULTI, &opts);
|
||||
if (!ASSERT_ERR(link_fd, "link_fd"))
|
||||
goto cleanup;
|
||||
ASSERT_EQ(link_fd, -ESRCH, "pid_is_wrong");
|
||||
ASSERT_EQ(link_fd, -EINVAL, "pid_is_wrong");
|
||||
|
||||
cleanup:
|
||||
if (link_fd >= 0)
|
||||
@@ -495,6 +606,13 @@ static void test_link_api(void)
|
||||
return;
|
||||
|
||||
__test_link_api(child);
|
||||
|
||||
/* pid filter (thread) */
|
||||
child = spawn_thread();
|
||||
if (!ASSERT_OK_PTR(child, "spawn_thread"))
|
||||
return;
|
||||
|
||||
__test_link_api(child);
|
||||
}
|
||||
|
||||
static void test_bench_attach_uprobe(void)
|
||||
|
@@ -53,6 +53,7 @@
|
||||
#include "verifier_movsx.skel.h"
|
||||
#include "verifier_netfilter_ctx.skel.h"
|
||||
#include "verifier_netfilter_retcode.skel.h"
|
||||
#include "verifier_or_jmp32_k.skel.h"
|
||||
#include "verifier_precision.skel.h"
|
||||
#include "verifier_prevent_map_lookup.skel.h"
|
||||
#include "verifier_raw_stack.skel.h"
|
||||
@@ -67,6 +68,7 @@
|
||||
#include "verifier_search_pruning.skel.h"
|
||||
#include "verifier_sock.skel.h"
|
||||
#include "verifier_sock_addr.skel.h"
|
||||
#include "verifier_sockmap_mutate.skel.h"
|
||||
#include "verifier_spill_fill.skel.h"
|
||||
#include "verifier_spin_lock.skel.h"
|
||||
#include "verifier_stack_ptr.skel.h"
|
||||
@@ -169,6 +171,7 @@ void test_verifier_meta_access(void) { RUN(verifier_meta_access); }
|
||||
void test_verifier_movsx(void) { RUN(verifier_movsx); }
|
||||
void test_verifier_netfilter_ctx(void) { RUN(verifier_netfilter_ctx); }
|
||||
void test_verifier_netfilter_retcode(void) { RUN(verifier_netfilter_retcode); }
|
||||
void test_verifier_or_jmp32_k(void) { RUN(verifier_or_jmp32_k); }
|
||||
void test_verifier_precision(void) { RUN(verifier_precision); }
|
||||
void test_verifier_prevent_map_lookup(void) { RUN(verifier_prevent_map_lookup); }
|
||||
void test_verifier_raw_stack(void) { RUN(verifier_raw_stack); }
|
||||
@@ -183,6 +186,7 @@ void test_verifier_sdiv(void) { RUN(verifier_sdiv); }
|
||||
void test_verifier_search_pruning(void) { RUN(verifier_search_pruning); }
|
||||
void test_verifier_sock(void) { RUN(verifier_sock); }
|
||||
void test_verifier_sock_addr(void) { RUN(verifier_sock_addr); }
|
||||
void test_verifier_sockmap_mutate(void) { RUN(verifier_sockmap_mutate); }
|
||||
void test_verifier_spill_fill(void) { RUN(verifier_spill_fill); }
|
||||
void test_verifier_spin_lock(void) { RUN(verifier_spin_lock); }
|
||||
void test_verifier_stack_ptr(void) { RUN(verifier_stack_ptr); }
|
||||
|
@@ -84,7 +84,7 @@ int BPF_PROG(trace_tcp_connect, struct sock *sk)
|
||||
}
|
||||
|
||||
SEC("fexit/inet_csk_accept")
|
||||
int BPF_PROG(inet_csk_accept, struct sock *sk, int flags, int *err, bool kern,
|
||||
int BPF_PROG(inet_csk_accept, struct sock *sk, struct proto_accept_arg *arg,
|
||||
struct sock *accepted_sk)
|
||||
{
|
||||
set_task_info(accepted_sk);
|
||||
|
@@ -4,7 +4,8 @@
|
||||
|
||||
#include <linux/bpf.h>
|
||||
#include <linux/if_ether.h>
|
||||
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/if_packet.h>
|
||||
#include <bpf/bpf_endian.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
|
||||
@@ -16,7 +17,13 @@ bool seen_tc3;
|
||||
bool seen_tc4;
|
||||
bool seen_tc5;
|
||||
bool seen_tc6;
|
||||
bool seen_tc7;
|
||||
|
||||
bool set_type;
|
||||
|
||||
bool seen_eth;
|
||||
bool seen_host;
|
||||
bool seen_mcast;
|
||||
|
||||
SEC("tc/ingress")
|
||||
int tc1(struct __sk_buff *skb)
|
||||
@@ -28,8 +35,16 @@ int tc1(struct __sk_buff *skb)
|
||||
if (bpf_skb_load_bytes(skb, 0, ð, sizeof(eth)))
|
||||
goto out;
|
||||
seen_eth = eth.h_proto == bpf_htons(ETH_P_IP);
|
||||
seen_host = skb->pkt_type == PACKET_HOST;
|
||||
if (seen_host && set_type) {
|
||||
eth.h_dest[0] = 4;
|
||||
if (bpf_skb_store_bytes(skb, 0, ð, sizeof(eth), 0))
|
||||
goto fail;
|
||||
bpf_skb_change_type(skb, PACKET_MULTICAST);
|
||||
}
|
||||
out:
|
||||
seen_tc1 = true;
|
||||
fail:
|
||||
return TCX_NEXT;
|
||||
}
|
||||
|
||||
@@ -67,3 +82,21 @@ int tc6(struct __sk_buff *skb)
|
||||
seen_tc6 = true;
|
||||
return TCX_PASS;
|
||||
}
|
||||
|
||||
SEC("tc/ingress")
|
||||
int tc7(struct __sk_buff *skb)
|
||||
{
|
||||
struct ethhdr eth = {};
|
||||
|
||||
if (skb->protocol != __bpf_constant_htons(ETH_P_IP))
|
||||
goto out;
|
||||
if (bpf_skb_load_bytes(skb, 0, ð, sizeof(eth)))
|
||||
goto out;
|
||||
if (eth.h_dest[0] == 4 && set_type) {
|
||||
seen_mcast = skb->pkt_type == PACKET_MULTICAST;
|
||||
bpf_skb_change_type(skb, PACKET_HOST);
|
||||
}
|
||||
out:
|
||||
seen_tc7 = true;
|
||||
return TCX_PASS;
|
||||
}
|
||||
|
@@ -1,8 +1,8 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <linux/bpf.h>
|
||||
#include "vmlinux.h"
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include <bpf/bpf_tracing.h>
|
||||
#include <stdbool.h>
|
||||
#include <bpf/usdt.bpf.h>
|
||||
|
||||
char _license[] SEC("license") = "GPL";
|
||||
|
||||
@@ -22,6 +22,13 @@ __u64 uprobe_multi_sleep_result = 0;
|
||||
|
||||
int pid = 0;
|
||||
int child_pid = 0;
|
||||
int child_tid = 0;
|
||||
int child_pid_usdt = 0;
|
||||
int child_tid_usdt = 0;
|
||||
|
||||
int expect_pid = 0;
|
||||
bool bad_pid_seen = false;
|
||||
bool bad_pid_seen_usdt = false;
|
||||
|
||||
bool test_cookie = false;
|
||||
void *user_ptr = 0;
|
||||
@@ -36,11 +43,19 @@ static __always_inline bool verify_sleepable_user_copy(void)
|
||||
|
||||
static void uprobe_multi_check(void *ctx, bool is_return, bool is_sleep)
|
||||
{
|
||||
child_pid = bpf_get_current_pid_tgid() >> 32;
|
||||
__u64 cur_pid_tgid = bpf_get_current_pid_tgid();
|
||||
__u32 cur_pid;
|
||||
|
||||
if (pid && child_pid != pid)
|
||||
cur_pid = cur_pid_tgid >> 32;
|
||||
if (pid && cur_pid != pid)
|
||||
return;
|
||||
|
||||
if (expect_pid && cur_pid != expect_pid)
|
||||
bad_pid_seen = true;
|
||||
|
||||
child_pid = cur_pid_tgid >> 32;
|
||||
child_tid = (__u32)cur_pid_tgid;
|
||||
|
||||
__u64 cookie = test_cookie ? bpf_get_attach_cookie(ctx) : 0;
|
||||
__u64 addr = bpf_get_func_ip(ctx);
|
||||
|
||||
@@ -97,5 +112,32 @@ int uretprobe_sleep(struct pt_regs *ctx)
|
||||
SEC("uprobe.multi//proc/self/exe:uprobe_multi_func_*")
|
||||
int uprobe_extra(struct pt_regs *ctx)
|
||||
{
|
||||
/* we need this one just to mix PID-filtered and global uprobes */
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("usdt")
|
||||
int usdt_pid(struct pt_regs *ctx)
|
||||
{
|
||||
__u64 cur_pid_tgid = bpf_get_current_pid_tgid();
|
||||
__u32 cur_pid;
|
||||
|
||||
cur_pid = cur_pid_tgid >> 32;
|
||||
if (pid && cur_pid != pid)
|
||||
return 0;
|
||||
|
||||
if (expect_pid && cur_pid != expect_pid)
|
||||
bad_pid_seen_usdt = true;
|
||||
|
||||
child_pid_usdt = cur_pid_tgid >> 32;
|
||||
child_tid_usdt = (__u32)cur_pid_tgid;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("usdt")
|
||||
int usdt_extra(struct pt_regs *ctx)
|
||||
{
|
||||
/* we need this one just to mix PID-filtered and global USDT probes */
|
||||
return 0;
|
||||
}
|
||||
|
41
tools/testing/selftests/bpf/progs/verifier_or_jmp32_k.c
Normal file
41
tools/testing/selftests/bpf/progs/verifier_or_jmp32_k.c
Normal file
@@ -0,0 +1,41 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <linux/bpf.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include "bpf_misc.h"
|
||||
|
||||
SEC("socket")
|
||||
__description("or_jmp32_k: bit ops + branch on unknown value")
|
||||
__failure
|
||||
__msg("R0 invalid mem access 'scalar'")
|
||||
__naked void or_jmp32_k(void)
|
||||
{
|
||||
asm volatile (" \
|
||||
r0 = 0xffffffff; \
|
||||
r0 /= 1; \
|
||||
r1 = 0; \
|
||||
w1 = -1; \
|
||||
w1 >>= 1; \
|
||||
w0 &= w1; \
|
||||
w0 |= 2; \
|
||||
if w0 != 0x7ffffffd goto l1; \
|
||||
r0 = 1; \
|
||||
exit; \
|
||||
l3: \
|
||||
r0 = 5; \
|
||||
*(u64*)(r0 - 8) = r0; \
|
||||
exit; \
|
||||
l2: \
|
||||
w0 -= 0xe; \
|
||||
if w0 == 1 goto l3; \
|
||||
r0 = 4; \
|
||||
exit; \
|
||||
l1: \
|
||||
w0 -= 0x7ffffff0; \
|
||||
if w0 s>= 0xe goto l2; \
|
||||
r0 = 3; \
|
||||
exit; \
|
||||
" ::: __clobber_all);
|
||||
}
|
||||
|
||||
char _license[] SEC("license") = "GPL";
|
187
tools/testing/selftests/bpf/progs/verifier_sockmap_mutate.c
Normal file
187
tools/testing/selftests/bpf/progs/verifier_sockmap_mutate.c
Normal file
@@ -0,0 +1,187 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <linux/bpf.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include <bpf/bpf_tracing.h>
|
||||
|
||||
#include "bpf_misc.h"
|
||||
|
||||
#define __always_unused __attribute__((unused))
|
||||
|
||||
char _license[] SEC("license") = "GPL";
|
||||
|
||||
struct sock {
|
||||
} __attribute__((preserve_access_index));
|
||||
|
||||
struct bpf_iter__sockmap {
|
||||
union {
|
||||
struct sock *sk;
|
||||
};
|
||||
} __attribute__((preserve_access_index));
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_SOCKHASH);
|
||||
__uint(max_entries, 1);
|
||||
__type(key, int);
|
||||
__type(value, int);
|
||||
} sockhash SEC(".maps");
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_SOCKMAP);
|
||||
__uint(max_entries, 1);
|
||||
__type(key, int);
|
||||
__type(value, int);
|
||||
} sockmap SEC(".maps");
|
||||
|
||||
enum { CG_OK = 1 };
|
||||
|
||||
int zero = 0;
|
||||
|
||||
static __always_inline void test_sockmap_delete(void)
|
||||
{
|
||||
bpf_map_delete_elem(&sockmap, &zero);
|
||||
bpf_map_delete_elem(&sockhash, &zero);
|
||||
}
|
||||
|
||||
static __always_inline void test_sockmap_update(void *sk)
|
||||
{
|
||||
if (sk) {
|
||||
bpf_map_update_elem(&sockmap, &zero, sk, BPF_ANY);
|
||||
bpf_map_update_elem(&sockhash, &zero, sk, BPF_ANY);
|
||||
}
|
||||
}
|
||||
|
||||
static __always_inline void test_sockmap_lookup_and_update(void)
|
||||
{
|
||||
struct bpf_sock *sk = bpf_map_lookup_elem(&sockmap, &zero);
|
||||
|
||||
if (sk) {
|
||||
test_sockmap_update(sk);
|
||||
bpf_sk_release(sk);
|
||||
}
|
||||
}
|
||||
|
||||
static __always_inline void test_sockmap_mutate(void *sk)
|
||||
{
|
||||
test_sockmap_delete();
|
||||
test_sockmap_update(sk);
|
||||
}
|
||||
|
||||
static __always_inline void test_sockmap_lookup_and_mutate(void)
|
||||
{
|
||||
test_sockmap_delete();
|
||||
test_sockmap_lookup_and_update();
|
||||
}
|
||||
|
||||
SEC("action")
|
||||
__success
|
||||
int test_sched_act(struct __sk_buff *skb)
|
||||
{
|
||||
test_sockmap_mutate(skb->sk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("classifier")
|
||||
__success
|
||||
int test_sched_cls(struct __sk_buff *skb)
|
||||
{
|
||||
test_sockmap_mutate(skb->sk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("flow_dissector")
|
||||
__success
|
||||
int test_flow_dissector_delete(struct __sk_buff *skb __always_unused)
|
||||
{
|
||||
test_sockmap_delete();
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("flow_dissector")
|
||||
__failure __msg("program of this type cannot use helper bpf_sk_release")
|
||||
int test_flow_dissector_update(struct __sk_buff *skb __always_unused)
|
||||
{
|
||||
test_sockmap_lookup_and_update(); /* no access to skb->sk */
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("iter/sockmap")
|
||||
__success
|
||||
int test_trace_iter(struct bpf_iter__sockmap *ctx)
|
||||
{
|
||||
test_sockmap_mutate(ctx->sk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("raw_tp/kfree")
|
||||
__failure __msg("cannot update sockmap in this context")
|
||||
int test_raw_tp_delete(const void *ctx __always_unused)
|
||||
{
|
||||
test_sockmap_delete();
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("raw_tp/kfree")
|
||||
__failure __msg("cannot update sockmap in this context")
|
||||
int test_raw_tp_update(const void *ctx __always_unused)
|
||||
{
|
||||
test_sockmap_lookup_and_update();
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("sk_lookup")
|
||||
__success
|
||||
int test_sk_lookup(struct bpf_sk_lookup *ctx)
|
||||
{
|
||||
test_sockmap_mutate(ctx->sk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("sk_reuseport")
|
||||
__success
|
||||
int test_sk_reuseport(struct sk_reuseport_md *ctx)
|
||||
{
|
||||
test_sockmap_mutate(ctx->sk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("socket")
|
||||
__success
|
||||
int test_socket_filter(struct __sk_buff *skb)
|
||||
{
|
||||
test_sockmap_mutate(skb->sk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("sockops")
|
||||
__success
|
||||
int test_sockops_delete(struct bpf_sock_ops *ctx __always_unused)
|
||||
{
|
||||
test_sockmap_delete();
|
||||
return CG_OK;
|
||||
}
|
||||
|
||||
SEC("sockops")
|
||||
__failure __msg("cannot update sockmap in this context")
|
||||
int test_sockops_update(struct bpf_sock_ops *ctx)
|
||||
{
|
||||
test_sockmap_update(ctx->sk);
|
||||
return CG_OK;
|
||||
}
|
||||
|
||||
SEC("sockops")
|
||||
__success
|
||||
int test_sockops_update_dedicated(struct bpf_sock_ops *ctx)
|
||||
{
|
||||
bpf_sock_map_update(ctx, &sockmap, &zero, BPF_ANY);
|
||||
bpf_sock_hash_update(ctx, &sockhash, &zero, BPF_ANY);
|
||||
return CG_OK;
|
||||
}
|
||||
|
||||
SEC("xdp")
|
||||
__success
|
||||
int test_xdp(struct xdp_md *ctx __always_unused)
|
||||
{
|
||||
test_sockmap_lookup_and_mutate();
|
||||
return XDP_PASS;
|
||||
}
|
@@ -1,5 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#define _GNU_SOURCE
|
||||
#define __SANE_USERSPACE_TYPES__ // Use ll64
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
|
@@ -1,2 +1,8 @@
|
||||
CONFIG_VIRTIO_NET=y
|
||||
CONFIG_BPF_SYSCALL=y
|
||||
CONFIG_CGROUP_BPF=y
|
||||
CONFIG_IPV6=y
|
||||
CONFIG_IPV6_MULTIPLE_TABLES=y
|
||||
CONFIG_NET_L3_MASTER_DEV=y
|
||||
CONFIG_NET_VRF=m
|
||||
CONFIG_VIRTIO_DEBUG=y
|
||||
CONFIG_VIRTIO_NET=y
|
||||
|
@@ -1,6 +1,15 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
CFLAGS += -Wall -O2 -g -fsanitize=address -fsanitize=undefined -static-libasan $(KHDR_INCLUDES)
|
||||
CFLAGS += -Wall -O2 -g -fsanitize=address -fsanitize=undefined $(KHDR_INCLUDES)
|
||||
|
||||
# gcc requires -static-libasan in order to ensure that Address Sanitizer's
|
||||
# library is the first one loaded. However, clang already statically links the
|
||||
# Address Sanitizer if -fsanitize is specified. Therefore, simply omit
|
||||
# -static-libasan for clang builds.
|
||||
ifeq ($(LLVM),)
|
||||
CFLAGS += -static-libasan
|
||||
endif
|
||||
|
||||
TEST_GEN_PROGS := fchmodat2_test
|
||||
|
||||
include ../lib.mk
|
||||
|
@@ -1,5 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#define _GNU_SOURCE
|
||||
#define __SANE_USERSPACE_TYPES__ // Use ll64
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <unistd.h>
|
||||
|
@@ -125,8 +125,16 @@ static uint32_t old_root_id, old_parent_id;
|
||||
|
||||
static void cleanup_namespace(void)
|
||||
{
|
||||
fchdir(orig_root);
|
||||
chroot(".");
|
||||
int ret;
|
||||
|
||||
ret = fchdir(orig_root);
|
||||
if (ret == -1)
|
||||
ksft_perror("fchdir to original root");
|
||||
|
||||
ret = chroot(".");
|
||||
if (ret == -1)
|
||||
ksft_perror("chroot to original root");
|
||||
|
||||
umount2(root_mntpoint, MNT_DETACH);
|
||||
rmdir(root_mntpoint);
|
||||
}
|
||||
|
@@ -1,16 +1,28 @@
|
||||
CONFIG_KPROBES=y
|
||||
CONFIG_BPF_SYSCALL=y
|
||||
CONFIG_DEBUG_INFO_BTF=y
|
||||
CONFIG_DEBUG_INFO_DWARF4=y
|
||||
CONFIG_EPROBE_EVENTS=y
|
||||
CONFIG_FPROBE=y
|
||||
CONFIG_FPROBE_EVENTS=y
|
||||
CONFIG_FTRACE=y
|
||||
CONFIG_FTRACE_SYSCALLS=y
|
||||
CONFIG_FUNCTION_GRAPH_RETVAL=y
|
||||
CONFIG_FUNCTION_PROFILER=y
|
||||
CONFIG_TRACER_SNAPSHOT=y
|
||||
CONFIG_STACK_TRACER=y
|
||||
CONFIG_HIST_TRIGGERS=y
|
||||
CONFIG_SCHED_TRACER=y
|
||||
CONFIG_PREEMPT_TRACER=y
|
||||
CONFIG_IRQSOFF_TRACER=y
|
||||
CONFIG_PREEMPTIRQ_DELAY_TEST=m
|
||||
CONFIG_KALLSYMS_ALL=y
|
||||
CONFIG_KPROBES=y
|
||||
CONFIG_KPROBE_EVENTS=y
|
||||
CONFIG_MODULES=y
|
||||
CONFIG_MODULE_UNLOAD=y
|
||||
CONFIG_PREEMPTIRQ_DELAY_TEST=m
|
||||
CONFIG_PREEMPT_TRACER=y
|
||||
CONFIG_PROBE_EVENTS_BTF_ARGS=y
|
||||
CONFIG_SAMPLES=y
|
||||
CONFIG_SAMPLE_FTRACE_DIRECT=m
|
||||
CONFIG_SAMPLE_TRACE_PRINTK=m
|
||||
CONFIG_KALLSYMS_ALL=y
|
||||
CONFIG_SCHED_TRACER=y
|
||||
CONFIG_STACK_TRACER=y
|
||||
CONFIG_TRACER_SNAPSHOT=y
|
||||
CONFIG_UPROBES=y
|
||||
CONFIG_UPROBE_EVENTS=y
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# description: Generic dynamic event - check if duplicate events are caught
|
||||
# requires: dynamic_events "e[:[<group>/][<event>]] <attached-group>.<attached-event> [<args>]":README
|
||||
# requires: dynamic_events "e[:[<group>/][<event>]] <attached-group>.<attached-event> [<args>]":README events/syscalls/sys_enter_openat
|
||||
|
||||
echo 0 > events/enable
|
||||
|
||||
|
@@ -10,7 +10,6 @@ fail() { #msg
|
||||
}
|
||||
|
||||
sample_events() {
|
||||
echo > trace
|
||||
echo 1 > events/kmem/kmem_cache_free/enable
|
||||
echo 1 > tracing_on
|
||||
ls > /dev/null
|
||||
@@ -22,6 +21,7 @@ echo 0 > tracing_on
|
||||
echo 0 > events/enable
|
||||
|
||||
echo "Get the most frequently calling function"
|
||||
echo > trace
|
||||
sample_events
|
||||
|
||||
target_func=`cat trace | grep -o 'call_site=\([^+]*\)' | sed 's/call_site=//' | sort | uniq -c | sort | tail -n 1 | sed 's/^[ 0-9]*//'`
|
||||
@@ -32,7 +32,16 @@ echo > trace
|
||||
|
||||
echo "Test event filter function name"
|
||||
echo "call_site.function == $target_func" > events/kmem/kmem_cache_free/filter
|
||||
|
||||
sample_events
|
||||
max_retry=10
|
||||
while [ `grep kmem_cache_free trace| wc -l` -eq 0 ]; do
|
||||
sample_events
|
||||
max_retry=$((max_retry - 1))
|
||||
if [ $max_retry -eq 0 ]; then
|
||||
exit_fail
|
||||
fi
|
||||
done
|
||||
|
||||
hitcnt=`grep kmem_cache_free trace| grep $target_func | wc -l`
|
||||
misscnt=`grep kmem_cache_free trace| grep -v $target_func | wc -l`
|
||||
@@ -49,7 +58,16 @@ address=`grep " ${target_func}\$" /proc/kallsyms | cut -d' ' -f1`
|
||||
|
||||
echo "Test event filter function address"
|
||||
echo "call_site.function == 0x$address" > events/kmem/kmem_cache_free/filter
|
||||
echo > trace
|
||||
sample_events
|
||||
max_retry=10
|
||||
while [ `grep kmem_cache_free trace| wc -l` -eq 0 ]; do
|
||||
sample_events
|
||||
max_retry=$((max_retry - 1))
|
||||
if [ $max_retry -eq 0 ]; then
|
||||
exit_fail
|
||||
fi
|
||||
done
|
||||
|
||||
hitcnt=`grep kmem_cache_free trace| grep $target_func | wc -l`
|
||||
misscnt=`grep kmem_cache_free trace| grep -v $target_func | wc -l`
|
||||
|
@@ -30,7 +30,8 @@ find_dot_func() {
|
||||
fi
|
||||
|
||||
grep " [tT] .*\.isra\..*" /proc/kallsyms | cut -f 3 -d " " | while read f; do
|
||||
if grep -s $f available_filter_functions; then
|
||||
cnt=`grep -s $f available_filter_functions | wc -l`;
|
||||
if [ $cnt -eq 1 ]; then
|
||||
echo $f
|
||||
break
|
||||
fi
|
||||
|
@@ -3,8 +3,6 @@ SUBDIRS := functional
|
||||
|
||||
TEST_PROGS := run.sh
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
include ../lib.mk
|
||||
|
||||
all:
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
INCLUDES := -I../include -I../../ $(KHDR_INCLUDES)
|
||||
CFLAGS := $(CFLAGS) -g -O2 -Wall -D_GNU_SOURCE -pthread $(INCLUDES) $(KHDR_INCLUDES)
|
||||
CFLAGS := $(CFLAGS) -g -O2 -Wall -D_GNU_SOURCE= -pthread $(INCLUDES) $(KHDR_INCLUDES)
|
||||
LDLIBS := -lpthread -lrt
|
||||
|
||||
LOCAL_HDRS := \
|
||||
|
@@ -360,7 +360,7 @@ out:
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
const char *test_name;
|
||||
char *test_name;
|
||||
int c, ret;
|
||||
|
||||
while ((c = getopt(argc, argv, "bchlot:v:")) != -1) {
|
||||
|
@@ -183,6 +183,7 @@ TEST_GEN_PROGS_s390x += s390x/sync_regs_test
|
||||
TEST_GEN_PROGS_s390x += s390x/tprot
|
||||
TEST_GEN_PROGS_s390x += s390x/cmma_test
|
||||
TEST_GEN_PROGS_s390x += s390x/debug_test
|
||||
TEST_GEN_PROGS_s390x += s390x/shared_zeropage_test
|
||||
TEST_GEN_PROGS_s390x += demand_paging_test
|
||||
TEST_GEN_PROGS_s390x += dirty_log_test
|
||||
TEST_GEN_PROGS_s390x += guest_print_test
|
||||
|
@@ -277,6 +277,7 @@ struct kvm_x86_cpu_property {
|
||||
#define X86_PROPERTY_MAX_EXT_LEAF KVM_X86_CPU_PROPERTY(0x80000000, 0, EAX, 0, 31)
|
||||
#define X86_PROPERTY_MAX_PHY_ADDR KVM_X86_CPU_PROPERTY(0x80000008, 0, EAX, 0, 7)
|
||||
#define X86_PROPERTY_MAX_VIRT_ADDR KVM_X86_CPU_PROPERTY(0x80000008, 0, EAX, 8, 15)
|
||||
#define X86_PROPERTY_GUEST_MAX_PHY_ADDR KVM_X86_CPU_PROPERTY(0x80000008, 0, EAX, 16, 23)
|
||||
#define X86_PROPERTY_SEV_C_BIT KVM_X86_CPU_PROPERTY(0x8000001F, 0, EBX, 0, 5)
|
||||
#define X86_PROPERTY_PHYS_ADDR_REDUCTION KVM_X86_CPU_PROPERTY(0x8000001F, 0, EBX, 6, 11)
|
||||
|
||||
|
@@ -9,6 +9,7 @@
|
||||
|
||||
#include "kvm_util.h"
|
||||
#include "processor.h"
|
||||
#include "sbi.h"
|
||||
|
||||
void *ucall_arch_get_ucall(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
|
@@ -1247,9 +1247,20 @@ unsigned long vm_compute_max_gfn(struct kvm_vm *vm)
|
||||
{
|
||||
const unsigned long num_ht_pages = 12 << (30 - vm->page_shift); /* 12 GiB */
|
||||
unsigned long ht_gfn, max_gfn, max_pfn;
|
||||
uint8_t maxphyaddr;
|
||||
uint8_t maxphyaddr, guest_maxphyaddr;
|
||||
|
||||
max_gfn = (1ULL << (vm->pa_bits - vm->page_shift)) - 1;
|
||||
/*
|
||||
* Use "guest MAXPHYADDR" from KVM if it's available. Guest MAXPHYADDR
|
||||
* enumerates the max _mappable_ GPA, which can be less than the raw
|
||||
* MAXPHYADDR, e.g. if MAXPHYADDR=52, KVM is using TDP, and the CPU
|
||||
* doesn't support 5-level TDP.
|
||||
*/
|
||||
guest_maxphyaddr = kvm_cpu_property(X86_PROPERTY_GUEST_MAX_PHY_ADDR);
|
||||
guest_maxphyaddr = guest_maxphyaddr ?: vm->pa_bits;
|
||||
TEST_ASSERT(guest_maxphyaddr <= vm->pa_bits,
|
||||
"Guest MAXPHYADDR should never be greater than raw MAXPHYADDR");
|
||||
|
||||
max_gfn = (1ULL << (guest_maxphyaddr - vm->page_shift)) - 1;
|
||||
|
||||
/* Avoid reserved HyperTransport region on AMD processors. */
|
||||
if (!host_cpu_is_amd)
|
||||
|
@@ -6,6 +6,7 @@
|
||||
*
|
||||
*/
|
||||
#include "kvm_util.h"
|
||||
#include "ucall_common.h"
|
||||
|
||||
#define LABEL_ADDRESS(v) ((uint64_t)&(v))
|
||||
|
||||
|
@@ -15,6 +15,7 @@
|
||||
#include "processor.h"
|
||||
#include "sbi.h"
|
||||
#include "arch_timer.h"
|
||||
#include "ucall_common.h"
|
||||
|
||||
/* Maximum counters(firmware + hardware) */
|
||||
#define RISCV_MAX_PMU_COUNTERS 64
|
||||
|
111
tools/testing/selftests/kvm/s390x/shared_zeropage_test.c
Normal file
111
tools/testing/selftests/kvm/s390x/shared_zeropage_test.c
Normal file
@@ -0,0 +1,111 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Test shared zeropage handling (with/without storage keys)
|
||||
*
|
||||
* Copyright (C) 2024, Red Hat, Inc.
|
||||
*/
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include <linux/fs.h>
|
||||
|
||||
#include "test_util.h"
|
||||
#include "kvm_util.h"
|
||||
#include "kselftest.h"
|
||||
#include "ucall_common.h"
|
||||
|
||||
static void set_storage_key(void *addr, uint8_t skey)
|
||||
{
|
||||
asm volatile("sske %0,%1" : : "d" (skey), "a" (addr));
|
||||
}
|
||||
|
||||
static void guest_code(void)
|
||||
{
|
||||
/* Issue some storage key instruction. */
|
||||
set_storage_key((void *)0, 0x98);
|
||||
GUEST_DONE();
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns 1 if the shared zeropage is mapped, 0 if something else is mapped.
|
||||
* Returns < 0 on error or if nothing is mapped.
|
||||
*/
|
||||
static int maps_shared_zeropage(int pagemap_fd, void *addr)
|
||||
{
|
||||
struct page_region region;
|
||||
struct pm_scan_arg arg = {
|
||||
.start = (uintptr_t)addr,
|
||||
.end = (uintptr_t)addr + 4096,
|
||||
.vec = (uintptr_t)®ion,
|
||||
.vec_len = 1,
|
||||
.size = sizeof(struct pm_scan_arg),
|
||||
.category_mask = PAGE_IS_PFNZERO,
|
||||
.category_anyof_mask = PAGE_IS_PRESENT,
|
||||
.return_mask = PAGE_IS_PFNZERO,
|
||||
};
|
||||
return ioctl(pagemap_fd, PAGEMAP_SCAN, &arg);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *mem, *page0, *page1, *page2, tmp;
|
||||
const size_t pagesize = getpagesize();
|
||||
struct kvm_vcpu *vcpu;
|
||||
struct kvm_vm *vm;
|
||||
struct ucall uc;
|
||||
int pagemap_fd;
|
||||
|
||||
ksft_print_header();
|
||||
ksft_set_plan(3);
|
||||
|
||||
/*
|
||||
* We'll use memory that is not mapped into the VM for simplicity.
|
||||
* Shared zeropages are enabled/disabled per-process.
|
||||
*/
|
||||
mem = mmap(0, 3 * pagesize, PROT_READ, MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
TEST_ASSERT(mem != MAP_FAILED, "mmap() failed");
|
||||
|
||||
/* Disable THP. Ignore errors on older kernels. */
|
||||
madvise(mem, 3 * pagesize, MADV_NOHUGEPAGE);
|
||||
|
||||
page0 = mem;
|
||||
page1 = page0 + pagesize;
|
||||
page2 = page1 + pagesize;
|
||||
|
||||
/* Can we even detect shared zeropages? */
|
||||
pagemap_fd = open("/proc/self/pagemap", O_RDONLY);
|
||||
TEST_REQUIRE(pagemap_fd >= 0);
|
||||
|
||||
tmp = *page0;
|
||||
asm volatile("" : "+r" (tmp));
|
||||
TEST_REQUIRE(maps_shared_zeropage(pagemap_fd, page0) == 1);
|
||||
|
||||
vm = vm_create_with_one_vcpu(&vcpu, guest_code);
|
||||
|
||||
/* Verify that we get the shared zeropage after VM creation. */
|
||||
tmp = *page1;
|
||||
asm volatile("" : "+r" (tmp));
|
||||
ksft_test_result(maps_shared_zeropage(pagemap_fd, page1) == 1,
|
||||
"Shared zeropages should be enabled\n");
|
||||
|
||||
/*
|
||||
* Let our VM execute a storage key instruction that should
|
||||
* unshare all shared zeropages.
|
||||
*/
|
||||
vcpu_run(vcpu);
|
||||
get_ucall(vcpu, &uc);
|
||||
TEST_ASSERT_EQ(uc.cmd, UCALL_DONE);
|
||||
|
||||
/* Verify that we don't have a shared zeropage anymore. */
|
||||
ksft_test_result(!maps_shared_zeropage(pagemap_fd, page1),
|
||||
"Shared zeropage should be gone\n");
|
||||
|
||||
/* Verify that we don't get any new shared zeropages. */
|
||||
tmp = *page2;
|
||||
asm volatile("" : "+r" (tmp));
|
||||
ksft_test_result(!maps_shared_zeropage(pagemap_fd, page2),
|
||||
"Shared zeropages should be disabled\n");
|
||||
|
||||
kvm_vm_free(vm);
|
||||
|
||||
ksft_finished();
|
||||
}
|
@@ -105,11 +105,11 @@ void test_features(uint32_t vm_type, uint64_t supported_features)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 64; i++) {
|
||||
if (!(supported_features & (1u << i)))
|
||||
if (!(supported_features & BIT_ULL(i)))
|
||||
test_init2_invalid(vm_type,
|
||||
&(struct kvm_sev_init){ .vmsa_features = BIT_ULL(i) },
|
||||
"unknown feature");
|
||||
else if (KNOWN_FEATURES & (1u << i))
|
||||
else if (KNOWN_FEATURES & BIT_ULL(i))
|
||||
test_init2(vm_type,
|
||||
&(struct kvm_sev_init){ .vmsa_features = BIT_ULL(i) });
|
||||
}
|
||||
|
@@ -35,6 +35,7 @@
|
||||
* See https://sourceware.org/glibc/wiki/Synchronizing_Headers.
|
||||
*/
|
||||
#include <linux/fs.h>
|
||||
#include <linux/mount.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
@@ -47,6 +48,13 @@ int renameat2(int olddirfd, const char *oldpath, int newdirfd,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef open_tree
|
||||
int open_tree(int dfd, const char *filename, unsigned int flags)
|
||||
{
|
||||
return syscall(__NR_open_tree, dfd, filename, flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef RENAME_EXCHANGE
|
||||
#define RENAME_EXCHANGE (1 << 1)
|
||||
#endif
|
||||
@@ -2400,6 +2408,43 @@ TEST_F_FORK(layout1, refer_denied_by_default4)
|
||||
layer_dir_s1d1_refer);
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests walking through a denied root mount.
|
||||
*/
|
||||
TEST_F_FORK(layout1, refer_mount_root_deny)
|
||||
{
|
||||
const struct landlock_ruleset_attr ruleset_attr = {
|
||||
.handled_access_fs = LANDLOCK_ACCESS_FS_MAKE_DIR,
|
||||
};
|
||||
int root_fd, ruleset_fd;
|
||||
|
||||
/* Creates a mount object from a non-mount point. */
|
||||
set_cap(_metadata, CAP_SYS_ADMIN);
|
||||
root_fd =
|
||||
open_tree(AT_FDCWD, dir_s1d1,
|
||||
AT_EMPTY_PATH | OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC);
|
||||
clear_cap(_metadata, CAP_SYS_ADMIN);
|
||||
ASSERT_LE(0, root_fd);
|
||||
|
||||
ruleset_fd =
|
||||
landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
|
||||
ASSERT_LE(0, ruleset_fd);
|
||||
|
||||
ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
|
||||
ASSERT_EQ(0, landlock_restrict_self(ruleset_fd, 0));
|
||||
EXPECT_EQ(0, close(ruleset_fd));
|
||||
|
||||
/* Link denied by Landlock: EACCES. */
|
||||
EXPECT_EQ(-1, linkat(root_fd, ".", root_fd, "does_not_exist", 0));
|
||||
EXPECT_EQ(EACCES, errno);
|
||||
|
||||
/* renameat2() always returns EBUSY. */
|
||||
EXPECT_EQ(-1, renameat2(root_fd, ".", root_fd, "does_not_exist", 0));
|
||||
EXPECT_EQ(EBUSY, errno);
|
||||
|
||||
EXPECT_EQ(0, close(root_fd));
|
||||
}
|
||||
|
||||
TEST_F_FORK(layout1, reparent_link)
|
||||
{
|
||||
const struct rule layer1[] = {
|
||||
|
@@ -67,7 +67,8 @@ int main(void)
|
||||
dump_maps();
|
||||
ksft_exit_fail_msg("Error: munmap failed!?\n");
|
||||
}
|
||||
ksft_test_result_pass("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
|
||||
ksft_print_msg("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
|
||||
ksft_test_result_pass("mmap() 5*PAGE_SIZE at base\n");
|
||||
|
||||
addr = base_addr + page_size;
|
||||
size = 3 * page_size;
|
||||
@@ -76,7 +77,8 @@ int main(void)
|
||||
dump_maps();
|
||||
ksft_exit_fail_msg("Error: first mmap() failed unexpectedly\n");
|
||||
}
|
||||
ksft_test_result_pass("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
|
||||
ksft_print_msg("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
|
||||
ksft_test_result_pass("mmap() 3*PAGE_SIZE at base+PAGE_SIZE\n");
|
||||
|
||||
/*
|
||||
* Exact same mapping again:
|
||||
@@ -93,7 +95,8 @@ int main(void)
|
||||
dump_maps();
|
||||
ksft_exit_fail_msg("Error:1: mmap() succeeded when it shouldn't have\n");
|
||||
}
|
||||
ksft_test_result_pass("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
|
||||
ksft_print_msg("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
|
||||
ksft_test_result_pass("mmap() 5*PAGE_SIZE at base\n");
|
||||
|
||||
/*
|
||||
* Second mapping contained within first:
|
||||
@@ -111,7 +114,8 @@ int main(void)
|
||||
dump_maps();
|
||||
ksft_exit_fail_msg("Error:2: mmap() succeeded when it shouldn't have\n");
|
||||
}
|
||||
ksft_test_result_pass("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
|
||||
ksft_print_msg("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
|
||||
ksft_test_result_pass("mmap() 2*PAGE_SIZE at base+PAGE_SIZE\n");
|
||||
|
||||
/*
|
||||
* Overlap end of existing mapping:
|
||||
@@ -128,7 +132,8 @@ int main(void)
|
||||
dump_maps();
|
||||
ksft_exit_fail_msg("Error:3: mmap() succeeded when it shouldn't have\n");
|
||||
}
|
||||
ksft_test_result_pass("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
|
||||
ksft_print_msg("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
|
||||
ksft_test_result_pass("mmap() 2*PAGE_SIZE at base+(3*PAGE_SIZE)\n");
|
||||
|
||||
/*
|
||||
* Overlap start of existing mapping:
|
||||
@@ -145,7 +150,8 @@ int main(void)
|
||||
dump_maps();
|
||||
ksft_exit_fail_msg("Error:4: mmap() succeeded when it shouldn't have\n");
|
||||
}
|
||||
ksft_test_result_pass("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
|
||||
ksft_print_msg("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
|
||||
ksft_test_result_pass("mmap() 2*PAGE_SIZE bytes at base\n");
|
||||
|
||||
/*
|
||||
* Adjacent to start of existing mapping:
|
||||
@@ -162,7 +168,8 @@ int main(void)
|
||||
dump_maps();
|
||||
ksft_exit_fail_msg("Error:5: mmap() failed when it shouldn't have\n");
|
||||
}
|
||||
ksft_test_result_pass("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
|
||||
ksft_print_msg("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
|
||||
ksft_test_result_pass("mmap() PAGE_SIZE at base\n");
|
||||
|
||||
/*
|
||||
* Adjacent to end of existing mapping:
|
||||
@@ -179,7 +186,8 @@ int main(void)
|
||||
dump_maps();
|
||||
ksft_exit_fail_msg("Error:6: mmap() failed when it shouldn't have\n");
|
||||
}
|
||||
ksft_test_result_pass("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
|
||||
ksft_print_msg("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
|
||||
ksft_test_result_pass("mmap() PAGE_SIZE at base+(4*PAGE_SIZE)\n");
|
||||
|
||||
addr = base_addr;
|
||||
size = 5 * page_size;
|
||||
|
@@ -43,6 +43,8 @@ TEST_PROGS += srv6_hl2encap_red_l2vpn_test.sh
|
||||
TEST_PROGS += srv6_end_next_csid_l3vpn_test.sh
|
||||
TEST_PROGS += srv6_end_x_next_csid_l3vpn_test.sh
|
||||
TEST_PROGS += srv6_end_flavors_test.sh
|
||||
TEST_PROGS += srv6_end_dx4_netfilter_test.sh
|
||||
TEST_PROGS += srv6_end_dx6_netfilter_test.sh
|
||||
TEST_PROGS += vrf_strict_mode_test.sh
|
||||
TEST_PROGS += arp_ndisc_evict_nocarrier.sh
|
||||
TEST_PROGS += ndisc_unsolicited_na_test.sh
|
||||
|
@@ -101,3 +101,5 @@ CONFIG_NETFILTER_XT_MATCH_POLICY=m
|
||||
CONFIG_CRYPTO_ARIA=y
|
||||
CONFIG_XFRM_INTERFACE=m
|
||||
CONFIG_XFRM_USER=m
|
||||
CONFIG_IP_NF_MATCH_RPFILTER=m
|
||||
CONFIG_IP6_NF_MATCH_RPFILTER=m
|
||||
|
@@ -2,3 +2,4 @@ CONFIG_IPV6=y
|
||||
CONFIG_NET_SCH_NETEM=m
|
||||
CONFIG_HSR=y
|
||||
CONFIG_VETH=y
|
||||
CONFIG_BRIDGE=y
|
||||
|
@@ -174,6 +174,8 @@ trap cleanup_all_ns EXIT
|
||||
setup_hsr_interfaces 0
|
||||
do_complete_ping_test
|
||||
|
||||
setup_ns ns1 ns2 ns3
|
||||
|
||||
setup_hsr_interfaces 1
|
||||
do_complete_ping_test
|
||||
|
||||
|
@@ -15,7 +15,7 @@ ksft_xfail=2
|
||||
ksft_skip=4
|
||||
|
||||
# namespace list created by setup_ns
|
||||
NS_LIST=""
|
||||
NS_LIST=()
|
||||
|
||||
##############################################################################
|
||||
# Helpers
|
||||
@@ -27,6 +27,7 @@ __ksft_status_merge()
|
||||
local -A weights
|
||||
local weight=0
|
||||
|
||||
local i
|
||||
for i in "$@"; do
|
||||
weights[$i]=$((weight++))
|
||||
done
|
||||
@@ -67,9 +68,7 @@ loopy_wait()
|
||||
while true
|
||||
do
|
||||
local out
|
||||
out=$("$@")
|
||||
local ret=$?
|
||||
if ((!ret)); then
|
||||
if out=$("$@"); then
|
||||
echo -n "$out"
|
||||
return 0
|
||||
fi
|
||||
@@ -139,6 +138,7 @@ cleanup_ns()
|
||||
fi
|
||||
|
||||
for ns in "$@"; do
|
||||
[ -z "${ns}" ] && continue
|
||||
ip netns delete "${ns}" &> /dev/null
|
||||
if ! busywait $BUSYWAIT_TIMEOUT ip netns list \| grep -vq "^$ns$" &> /dev/null; then
|
||||
echo "Warn: Failed to remove namespace $ns"
|
||||
@@ -152,7 +152,7 @@ cleanup_ns()
|
||||
|
||||
cleanup_all_ns()
|
||||
{
|
||||
cleanup_ns $NS_LIST
|
||||
cleanup_ns "${NS_LIST[@]}"
|
||||
}
|
||||
|
||||
# setup netns with given names as prefix. e.g
|
||||
@@ -161,7 +161,7 @@ setup_ns()
|
||||
{
|
||||
local ns=""
|
||||
local ns_name=""
|
||||
local ns_list=""
|
||||
local ns_list=()
|
||||
local ns_exist=
|
||||
for ns_name in "$@"; do
|
||||
# Some test may setup/remove same netns multi times
|
||||
@@ -177,13 +177,13 @@ setup_ns()
|
||||
|
||||
if ! ip netns add "$ns"; then
|
||||
echo "Failed to create namespace $ns_name"
|
||||
cleanup_ns "$ns_list"
|
||||
cleanup_ns "${ns_list[@]}"
|
||||
return $ksft_skip
|
||||
fi
|
||||
ip -n "$ns" link set lo up
|
||||
! $ns_exist && ns_list="$ns_list $ns"
|
||||
! $ns_exist && ns_list+=("$ns")
|
||||
done
|
||||
NS_LIST="$NS_LIST $ns_list"
|
||||
NS_LIST+=("${ns_list[@]}")
|
||||
}
|
||||
|
||||
tc_rule_stats_get()
|
||||
|
@@ -261,6 +261,8 @@ reset()
|
||||
|
||||
TEST_NAME="${1}"
|
||||
|
||||
MPTCP_LIB_SUBTEST_FLAKY=0 # reset if modified
|
||||
|
||||
if skip_test; then
|
||||
MPTCP_LIB_TEST_COUNTER=$((MPTCP_LIB_TEST_COUNTER+1))
|
||||
last_test_ignored=1
|
||||
@@ -448,7 +450,9 @@ reset_with_tcp_filter()
|
||||
# $1: err msg
|
||||
fail_test()
|
||||
{
|
||||
ret=${KSFT_FAIL}
|
||||
if ! mptcp_lib_subtest_is_flaky; then
|
||||
ret=${KSFT_FAIL}
|
||||
fi
|
||||
|
||||
if [ ${#} -gt 0 ]; then
|
||||
print_fail "${@}"
|
||||
@@ -2245,9 +2249,10 @@ remove_tests()
|
||||
if reset "remove invalid addresses"; then
|
||||
pm_nl_set_limits $ns1 3 3
|
||||
pm_nl_add_endpoint $ns1 10.0.12.1 flags signal
|
||||
# broadcast IP: no packet for this address will be received on ns1
|
||||
pm_nl_add_endpoint $ns1 224.0.0.1 flags signal
|
||||
pm_nl_add_endpoint $ns1 10.0.3.1 flags signal
|
||||
pm_nl_add_endpoint $ns1 10.0.14.1 flags signal
|
||||
pm_nl_set_limits $ns2 3 3
|
||||
pm_nl_set_limits $ns2 2 2
|
||||
addr_nr_ns1=-3 speed=10 \
|
||||
run_tests $ns1 $ns2 10.0.1.1
|
||||
chk_join_nr 1 1 1
|
||||
@@ -3069,6 +3074,7 @@ fullmesh_tests()
|
||||
fastclose_tests()
|
||||
{
|
||||
if reset_check_counter "fastclose test" "MPTcpExtMPFastcloseTx"; then
|
||||
MPTCP_LIB_SUBTEST_FLAKY=1
|
||||
test_linkfail=1024 fastclose=client \
|
||||
run_tests $ns1 $ns2 10.0.1.1
|
||||
chk_join_nr 0 0 0
|
||||
@@ -3077,6 +3083,7 @@ fastclose_tests()
|
||||
fi
|
||||
|
||||
if reset_check_counter "fastclose server test" "MPTcpExtMPFastcloseRx"; then
|
||||
MPTCP_LIB_SUBTEST_FLAKY=1
|
||||
test_linkfail=1024 fastclose=server \
|
||||
run_tests $ns1 $ns2 10.0.1.1
|
||||
chk_join_nr 0 0 0 0 0 0 1
|
||||
@@ -3095,6 +3102,7 @@ fail_tests()
|
||||
{
|
||||
# single subflow
|
||||
if reset_with_fail "Infinite map" 1; then
|
||||
MPTCP_LIB_SUBTEST_FLAKY=1
|
||||
test_linkfail=128 \
|
||||
run_tests $ns1 $ns2 10.0.1.1
|
||||
chk_join_nr 0 0 0 +1 +0 1 0 1 "$(pedit_action_pkts)"
|
||||
@@ -3103,6 +3111,7 @@ fail_tests()
|
||||
|
||||
# multiple subflows
|
||||
if reset_with_fail "MP_FAIL MP_RST" 2; then
|
||||
MPTCP_LIB_SUBTEST_FLAKY=1
|
||||
tc -n $ns2 qdisc add dev ns2eth1 root netem rate 1mbit delay 5ms
|
||||
pm_nl_set_limits $ns1 0 1
|
||||
pm_nl_set_limits $ns2 0 1
|
||||
|
@@ -21,6 +21,7 @@ declare -rx MPTCP_LIB_AF_INET6=10
|
||||
|
||||
MPTCP_LIB_SUBTESTS=()
|
||||
MPTCP_LIB_SUBTESTS_DUPLICATED=0
|
||||
MPTCP_LIB_SUBTEST_FLAKY=0
|
||||
MPTCP_LIB_TEST_COUNTER=0
|
||||
MPTCP_LIB_TEST_FORMAT="%02u %-50s"
|
||||
MPTCP_LIB_IP_MPTCP=0
|
||||
@@ -41,6 +42,16 @@ else
|
||||
readonly MPTCP_LIB_COLOR_RESET=
|
||||
fi
|
||||
|
||||
# SELFTESTS_MPTCP_LIB_OVERRIDE_FLAKY env var can be set not to ignore errors
|
||||
# from subtests marked as flaky
|
||||
mptcp_lib_override_flaky() {
|
||||
[ "${SELFTESTS_MPTCP_LIB_OVERRIDE_FLAKY:-}" = 1 ]
|
||||
}
|
||||
|
||||
mptcp_lib_subtest_is_flaky() {
|
||||
[ "${MPTCP_LIB_SUBTEST_FLAKY}" = 1 ] && ! mptcp_lib_override_flaky
|
||||
}
|
||||
|
||||
# $1: color, $2: text
|
||||
mptcp_lib_print_color() {
|
||||
echo -e "${MPTCP_LIB_START_PRINT:-}${*}${MPTCP_LIB_COLOR_RESET}"
|
||||
@@ -72,7 +83,16 @@ mptcp_lib_pr_skip() {
|
||||
}
|
||||
|
||||
mptcp_lib_pr_fail() {
|
||||
mptcp_lib_print_err "[FAIL]${1:+ ${*}}"
|
||||
local title cmt
|
||||
|
||||
if mptcp_lib_subtest_is_flaky; then
|
||||
title="IGNO"
|
||||
cmt=" (flaky)"
|
||||
else
|
||||
title="FAIL"
|
||||
fi
|
||||
|
||||
mptcp_lib_print_err "[${title}]${cmt}${1:+ ${*}}"
|
||||
}
|
||||
|
||||
mptcp_lib_pr_info() {
|
||||
@@ -208,7 +228,13 @@ mptcp_lib_result_pass() {
|
||||
|
||||
# $1: test name
|
||||
mptcp_lib_result_fail() {
|
||||
__mptcp_lib_result_add "not ok" "${1}"
|
||||
if mptcp_lib_subtest_is_flaky; then
|
||||
# It might sound better to use 'not ok # TODO' or 'ok # SKIP',
|
||||
# but some CIs don't understand 'TODO' and treat SKIP as errors.
|
||||
__mptcp_lib_result_add "ok" "${1} # IGNORE Flaky"
|
||||
else
|
||||
__mptcp_lib_result_add "not ok" "${1}"
|
||||
fi
|
||||
}
|
||||
|
||||
# $1: test name
|
||||
|
@@ -244,7 +244,7 @@ run_test()
|
||||
do_transfer $small $large $time
|
||||
lret=$?
|
||||
mptcp_lib_result_code "${lret}" "${msg}"
|
||||
if [ $lret -ne 0 ]; then
|
||||
if [ $lret -ne 0 ] && ! mptcp_lib_subtest_is_flaky; then
|
||||
ret=$lret
|
||||
[ $bail -eq 0 ] || exit $ret
|
||||
fi
|
||||
@@ -254,7 +254,7 @@ run_test()
|
||||
do_transfer $large $small $time
|
||||
lret=$?
|
||||
mptcp_lib_result_code "${lret}" "${msg}"
|
||||
if [ $lret -ne 0 ]; then
|
||||
if [ $lret -ne 0 ] && ! mptcp_lib_subtest_is_flaky; then
|
||||
ret=$lret
|
||||
[ $bail -eq 0 ] || exit $ret
|
||||
fi
|
||||
@@ -290,7 +290,7 @@ run_test 10 10 0 0 "balanced bwidth"
|
||||
run_test 10 10 1 25 "balanced bwidth with unbalanced delay"
|
||||
|
||||
# we still need some additional infrastructure to pass the following test-cases
|
||||
run_test 10 3 0 0 "unbalanced bwidth"
|
||||
MPTCP_LIB_SUBTEST_FLAKY=1 run_test 10 3 0 0 "unbalanced bwidth"
|
||||
run_test 10 3 1 25 "unbalanced bwidth with unbalanced delay"
|
||||
run_test 10 3 25 1 "unbalanced bwidth with opposed, unbalanced delay"
|
||||
|
||||
|
@@ -160,10 +160,12 @@ make_connection()
|
||||
local is_v6=$1
|
||||
local app_port=$app4_port
|
||||
local connect_addr="10.0.1.1"
|
||||
local client_addr="10.0.1.2"
|
||||
local listen_addr="0.0.0.0"
|
||||
if [ "$is_v6" = "v6" ]
|
||||
then
|
||||
connect_addr="dead:beef:1::1"
|
||||
client_addr="dead:beef:1::2"
|
||||
listen_addr="::"
|
||||
app_port=$app6_port
|
||||
else
|
||||
@@ -206,6 +208,7 @@ make_connection()
|
||||
[ "$server_serverside" = 1 ]
|
||||
then
|
||||
test_pass
|
||||
print_title "Connection info: ${client_addr}:${client_port} -> ${connect_addr}:${app_port}"
|
||||
else
|
||||
test_fail "Expected tokens (c:${client_token} - s:${server_token}) and server (c:${client_serverside} - s:${server_serverside})"
|
||||
mptcp_lib_result_print_all_tap
|
||||
@@ -297,7 +300,7 @@ test_announce()
|
||||
ip netns exec "$ns2"\
|
||||
./pm_nl_ctl ann 10.0.2.2 token "$client4_token" id $client_addr_id dev\
|
||||
ns2eth1
|
||||
print_test "ADD_ADDR id:${client_addr_id} 10.0.2.2 (ns2) => ns1, reuse port"
|
||||
print_test "ADD_ADDR id:client 10.0.2.2 (ns2) => ns1, reuse port"
|
||||
sleep 0.5
|
||||
verify_announce_event $server_evts $ANNOUNCED $server4_token "10.0.2.2" $client_addr_id \
|
||||
"$client4_port"
|
||||
@@ -306,7 +309,7 @@ test_announce()
|
||||
:>"$server_evts"
|
||||
ip netns exec "$ns2" ./pm_nl_ctl ann\
|
||||
dead:beef:2::2 token "$client6_token" id $client_addr_id dev ns2eth1
|
||||
print_test "ADD_ADDR6 id:${client_addr_id} dead:beef:2::2 (ns2) => ns1, reuse port"
|
||||
print_test "ADD_ADDR6 id:client dead:beef:2::2 (ns2) => ns1, reuse port"
|
||||
sleep 0.5
|
||||
verify_announce_event "$server_evts" "$ANNOUNCED" "$server6_token" "dead:beef:2::2"\
|
||||
"$client_addr_id" "$client6_port" "v6"
|
||||
@@ -316,7 +319,7 @@ test_announce()
|
||||
client_addr_id=$((client_addr_id+1))
|
||||
ip netns exec "$ns2" ./pm_nl_ctl ann 10.0.2.2 token "$client4_token" id\
|
||||
$client_addr_id dev ns2eth1 port $new4_port
|
||||
print_test "ADD_ADDR id:${client_addr_id} 10.0.2.2 (ns2) => ns1, new port"
|
||||
print_test "ADD_ADDR id:client+1 10.0.2.2 (ns2) => ns1, new port"
|
||||
sleep 0.5
|
||||
verify_announce_event "$server_evts" "$ANNOUNCED" "$server4_token" "10.0.2.2"\
|
||||
"$client_addr_id" "$new4_port"
|
||||
@@ -327,7 +330,7 @@ test_announce()
|
||||
# ADD_ADDR from the server to client machine reusing the subflow port
|
||||
ip netns exec "$ns1" ./pm_nl_ctl ann 10.0.2.1 token "$server4_token" id\
|
||||
$server_addr_id dev ns1eth2
|
||||
print_test "ADD_ADDR id:${server_addr_id} 10.0.2.1 (ns1) => ns2, reuse port"
|
||||
print_test "ADD_ADDR id:server 10.0.2.1 (ns1) => ns2, reuse port"
|
||||
sleep 0.5
|
||||
verify_announce_event "$client_evts" "$ANNOUNCED" "$client4_token" "10.0.2.1"\
|
||||
"$server_addr_id" "$app4_port"
|
||||
@@ -336,7 +339,7 @@ test_announce()
|
||||
:>"$client_evts"
|
||||
ip netns exec "$ns1" ./pm_nl_ctl ann dead:beef:2::1 token "$server6_token" id\
|
||||
$server_addr_id dev ns1eth2
|
||||
print_test "ADD_ADDR6 id:${server_addr_id} dead:beef:2::1 (ns1) => ns2, reuse port"
|
||||
print_test "ADD_ADDR6 id:server dead:beef:2::1 (ns1) => ns2, reuse port"
|
||||
sleep 0.5
|
||||
verify_announce_event "$client_evts" "$ANNOUNCED" "$client6_token" "dead:beef:2::1"\
|
||||
"$server_addr_id" "$app6_port" "v6"
|
||||
@@ -346,7 +349,7 @@ test_announce()
|
||||
server_addr_id=$((server_addr_id+1))
|
||||
ip netns exec "$ns1" ./pm_nl_ctl ann 10.0.2.1 token "$server4_token" id\
|
||||
$server_addr_id dev ns1eth2 port $new4_port
|
||||
print_test "ADD_ADDR id:${server_addr_id} 10.0.2.1 (ns1) => ns2, new port"
|
||||
print_test "ADD_ADDR id:server+1 10.0.2.1 (ns1) => ns2, new port"
|
||||
sleep 0.5
|
||||
verify_announce_event "$client_evts" "$ANNOUNCED" "$client4_token" "10.0.2.1"\
|
||||
"$server_addr_id" "$new4_port"
|
||||
@@ -380,7 +383,7 @@ test_remove()
|
||||
local invalid_token=$(( client4_token - 1 ))
|
||||
ip netns exec "$ns2" ./pm_nl_ctl rem token $invalid_token id\
|
||||
$client_addr_id > /dev/null 2>&1
|
||||
print_test "RM_ADDR id:${client_addr_id} ns2 => ns1, invalid token"
|
||||
print_test "RM_ADDR id:client ns2 => ns1, invalid token"
|
||||
local type
|
||||
type=$(mptcp_lib_evts_get_info type "$server_evts")
|
||||
if [ "$type" = "" ]
|
||||
@@ -394,7 +397,7 @@ test_remove()
|
||||
local invalid_id=$(( client_addr_id + 1 ))
|
||||
ip netns exec "$ns2" ./pm_nl_ctl rem token "$client4_token" id\
|
||||
$invalid_id > /dev/null 2>&1
|
||||
print_test "RM_ADDR id:${invalid_id} ns2 => ns1, invalid id"
|
||||
print_test "RM_ADDR id:client+1 ns2 => ns1, invalid id"
|
||||
type=$(mptcp_lib_evts_get_info type "$server_evts")
|
||||
if [ "$type" = "" ]
|
||||
then
|
||||
@@ -407,7 +410,7 @@ test_remove()
|
||||
:>"$server_evts"
|
||||
ip netns exec "$ns2" ./pm_nl_ctl rem token "$client4_token" id\
|
||||
$client_addr_id
|
||||
print_test "RM_ADDR id:${client_addr_id} ns2 => ns1"
|
||||
print_test "RM_ADDR id:client ns2 => ns1"
|
||||
sleep 0.5
|
||||
verify_remove_event "$server_evts" "$REMOVED" "$server4_token" "$client_addr_id"
|
||||
|
||||
@@ -416,7 +419,7 @@ test_remove()
|
||||
client_addr_id=$(( client_addr_id - 1 ))
|
||||
ip netns exec "$ns2" ./pm_nl_ctl rem token "$client4_token" id\
|
||||
$client_addr_id
|
||||
print_test "RM_ADDR id:${client_addr_id} ns2 => ns1"
|
||||
print_test "RM_ADDR id:client-1 ns2 => ns1"
|
||||
sleep 0.5
|
||||
verify_remove_event "$server_evts" "$REMOVED" "$server4_token" "$client_addr_id"
|
||||
|
||||
@@ -424,7 +427,7 @@ test_remove()
|
||||
:>"$server_evts"
|
||||
ip netns exec "$ns2" ./pm_nl_ctl rem token "$client6_token" id\
|
||||
$client_addr_id
|
||||
print_test "RM_ADDR6 id:${client_addr_id} ns2 => ns1"
|
||||
print_test "RM_ADDR6 id:client-1 ns2 => ns1"
|
||||
sleep 0.5
|
||||
verify_remove_event "$server_evts" "$REMOVED" "$server6_token" "$client_addr_id"
|
||||
|
||||
@@ -434,7 +437,7 @@ test_remove()
|
||||
# RM_ADDR from the server to client machine
|
||||
ip netns exec "$ns1" ./pm_nl_ctl rem token "$server4_token" id\
|
||||
$server_addr_id
|
||||
print_test "RM_ADDR id:${server_addr_id} ns1 => ns2"
|
||||
print_test "RM_ADDR id:server ns1 => ns2"
|
||||
sleep 0.5
|
||||
verify_remove_event "$client_evts" "$REMOVED" "$client4_token" "$server_addr_id"
|
||||
|
||||
@@ -443,7 +446,7 @@ test_remove()
|
||||
server_addr_id=$(( server_addr_id - 1 ))
|
||||
ip netns exec "$ns1" ./pm_nl_ctl rem token "$server4_token" id\
|
||||
$server_addr_id
|
||||
print_test "RM_ADDR id:${server_addr_id} ns1 => ns2"
|
||||
print_test "RM_ADDR id:server-1 ns1 => ns2"
|
||||
sleep 0.5
|
||||
verify_remove_event "$client_evts" "$REMOVED" "$client4_token" "$server_addr_id"
|
||||
|
||||
@@ -451,7 +454,7 @@ test_remove()
|
||||
:>"$client_evts"
|
||||
ip netns exec "$ns1" ./pm_nl_ctl rem token "$server6_token" id\
|
||||
$server_addr_id
|
||||
print_test "RM_ADDR6 id:${server_addr_id} ns1 => ns2"
|
||||
print_test "RM_ADDR6 id:server-1 ns1 => ns2"
|
||||
sleep 0.5
|
||||
verify_remove_event "$client_evts" "$REMOVED" "$client6_token" "$server_addr_id"
|
||||
}
|
||||
@@ -479,8 +482,14 @@ verify_subflow_events()
|
||||
local locid
|
||||
local remid
|
||||
local info
|
||||
local e_dport_txt
|
||||
|
||||
info="${e_saddr} (${e_from}) => ${e_daddr}:${e_dport} (${e_to})"
|
||||
# only display the fixed ports
|
||||
if [ "${e_dport}" -ge "${app4_port}" ] && [ "${e_dport}" -le "${app6_port}" ]; then
|
||||
e_dport_txt=":${e_dport}"
|
||||
fi
|
||||
|
||||
info="${e_saddr} (${e_from}) => ${e_daddr}${e_dport_txt} (${e_to})"
|
||||
|
||||
if [ "$e_type" = "$SUB_ESTABLISHED" ]
|
||||
then
|
||||
@@ -766,7 +775,7 @@ test_subflows_v4_v6_mix()
|
||||
:>"$client_evts"
|
||||
ip netns exec "$ns1" ./pm_nl_ctl ann 10.0.2.1 token "$server6_token" id\
|
||||
$server_addr_id dev ns1eth2
|
||||
print_test "ADD_ADDR4 id:${server_addr_id} 10.0.2.1 (ns1) => ns2, reuse port"
|
||||
print_test "ADD_ADDR4 id:server 10.0.2.1 (ns1) => ns2, reuse port"
|
||||
sleep 0.5
|
||||
verify_announce_event "$client_evts" "$ANNOUNCED" "$client6_token" "10.0.2.1"\
|
||||
"$server_addr_id" "$app6_port"
|
||||
@@ -861,7 +870,7 @@ test_listener()
|
||||
local listener_pid=$!
|
||||
|
||||
sleep 0.5
|
||||
print_test "CREATE_LISTENER 10.0.2.2:$client4_port"
|
||||
print_test "CREATE_LISTENER 10.0.2.2 (client port)"
|
||||
verify_listener_events $client_evts $LISTENER_CREATED $AF_INET 10.0.2.2 $client4_port
|
||||
|
||||
# ADD_ADDR from client to server machine reusing the subflow port
|
||||
@@ -878,13 +887,14 @@ test_listener()
|
||||
mptcp_lib_kill_wait $listener_pid
|
||||
|
||||
sleep 0.5
|
||||
print_test "CLOSE_LISTENER 10.0.2.2:$client4_port"
|
||||
print_test "CLOSE_LISTENER 10.0.2.2 (client port)"
|
||||
verify_listener_events $client_evts $LISTENER_CLOSED $AF_INET 10.0.2.2 $client4_port
|
||||
}
|
||||
|
||||
print_title "Make connections"
|
||||
make_connection
|
||||
make_connection "v6"
|
||||
print_title "Will be using address IDs ${client_addr_id} (client) and ${server_addr_id} (server)"
|
||||
|
||||
test_announce
|
||||
test_remove
|
||||
|
@@ -1,4 +1,4 @@
|
||||
#!/bin/sh
|
||||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
# OVS kernel module self tests
|
||||
|
@@ -531,7 +531,7 @@ class ovsactions(nla):
|
||||
for flat_act in parse_flat_map:
|
||||
if parse_starts_block(actstr, flat_act[0], False):
|
||||
actstr = actstr[len(flat_act[0]):]
|
||||
self["attrs"].append([flat_act[1]])
|
||||
self["attrs"].append([flat_act[1], True])
|
||||
actstr = actstr[strspn(actstr, ", ") :]
|
||||
parsed = True
|
||||
|
||||
|
335
tools/testing/selftests/net/srv6_end_dx4_netfilter_test.sh
Executable file
335
tools/testing/selftests/net/srv6_end_dx4_netfilter_test.sh
Executable file
@@ -0,0 +1,335 @@
|
||||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
# author: Jianguo Wu <wujianguo@chinatelecom.cn>
|
||||
#
|
||||
# Mostly copied from tools/testing/selftests/net/srv6_end_dt4_l3vpn_test.sh.
|
||||
#
|
||||
# This script is designed for testing the support of netfilter hooks for
|
||||
# SRv6 End.DX4 behavior.
|
||||
#
|
||||
# Hereafter a network diagram is shown, where one tenants (named 100) offer
|
||||
# IPv4 L3 VPN services allowing hosts to communicate with each other across
|
||||
# an IPv6 network.
|
||||
#
|
||||
# Routers rt-1 and rt-2 implement IPv4 L3 VPN services leveraging the SRv6
|
||||
# architecture. The key components for such VPNs are: a) SRv6 Encap behavior,
|
||||
# b) SRv6 End.DX4 behavior.
|
||||
#
|
||||
# To explain how an IPv4 L3 VPN based on SRv6 works, let us briefly consider an
|
||||
# example where, within the same domain of tenant 100, the host hs-1 pings
|
||||
# the host hs-2.
|
||||
#
|
||||
# First of all, L2 reachability of the host hs-2 is taken into account by
|
||||
# the router rt-1 which acts as an arp proxy.
|
||||
#
|
||||
# When the host hs-1 sends an IPv4 packet destined to hs-2, the router rt-1
|
||||
# receives the packet on the internal veth-t100 interface, rt-1 contains the
|
||||
# SRv6 Encap route for encapsulating the IPv4 packet in a IPv6 plus the Segment
|
||||
# Routing Header (SRH) packet. This packet is sent through the (IPv6) core
|
||||
# network up to the router rt-2 that receives it on veth0 interface.
|
||||
#
|
||||
# The rt-2 router uses the 'localsid' routing table to process incoming
|
||||
# IPv6+SRH packets which belong to the VPN of the tenant 100. For each of these
|
||||
# packets, the SRv6 End.DX4 behavior removes the outer IPv6+SRH headers and
|
||||
# routs the packet to the specified nexthop. Afterwards, the packet is sent to
|
||||
# the host hs-2 through the veth-t100 interface.
|
||||
#
|
||||
# The ping response follows the same processing but this time the role of rt-1
|
||||
# and rt-2 are swapped.
|
||||
#
|
||||
# And when net.netfilter.nf_hooks_lwtunnel is set to 1 in rt-1 or rt-2, and a
|
||||
# rpfilter iptables rule is added, SRv6 packets will go through netfilter PREROUTING
|
||||
# hooks.
|
||||
#
|
||||
#
|
||||
# +-------------------+ +-------------------+
|
||||
# | | | |
|
||||
# | hs-1 netns | | hs-2 netns |
|
||||
# | | | |
|
||||
# | +-------------+ | | +-------------+ |
|
||||
# | | veth0 | | | | veth0 | |
|
||||
# | | 10.0.0.1/24 | | | | 10.0.0.2/24 | |
|
||||
# | +-------------+ | | +-------------+ |
|
||||
# | . | | . |
|
||||
# +-------------------+ +-------------------+
|
||||
# . .
|
||||
# . .
|
||||
# . .
|
||||
# +-----------------------------------+ +-----------------------------------+
|
||||
# | . | | . |
|
||||
# | +---------------+ | | +---------------- |
|
||||
# | | veth-t100 | | | | veth-t100 | |
|
||||
# | | 10.0.0.11/24 | +----------+ | | +----------+ | 10.0.0.22/24 | |
|
||||
# | +-------+-------+ | route | | | | route | +-------+-------- |
|
||||
# | | table | | | | table | |
|
||||
# | +----------+ | | +----------+ |
|
||||
# | +--------------+ | | +--------------+ |
|
||||
# | | veth0 | | | | veth0 | |
|
||||
# | | 2001:11::1/64 |.|...|.| 2001:11::2/64 | |
|
||||
# | +--------------+ | | +--------------+ |
|
||||
# | | | |
|
||||
# | rt-1 netns | | rt-2 netns |
|
||||
# | | | |
|
||||
# +-----------------------------------+ +-----------------------------------+
|
||||
#
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# | Network configuration |
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
#
|
||||
# rt-1: localsid table
|
||||
# +----------------------------------------------------------------+
|
||||
# |SID |Action |
|
||||
# +----------------------------------------------------------------+
|
||||
# |fc00:21:100::6004|apply SRv6 End.DX4 nh4 10.0.0.1 dev veth-t100 |
|
||||
# +----------------------------------------------------------------+
|
||||
#
|
||||
# rt-1: route table
|
||||
# +---------------------------------------------------+
|
||||
# |host |Action |
|
||||
# +---------------------------------------------------+
|
||||
# |10.0.0.2 |apply seg6 encap segs fc00:12:100::6004|
|
||||
# +---------------------------------------------------+
|
||||
# |10.0.0.0/24|forward to dev veth_t100 |
|
||||
# +---------------------------------------------------+
|
||||
#
|
||||
#
|
||||
# rt-2: localsid table
|
||||
# +---------------------------------------------------------------+
|
||||
# |SID |Action |
|
||||
# +---------------------------------------------------------------+
|
||||
# |fc00:12:100::6004|apply SRv6 End.DX4 nh4 10.0.0.2 dev veth-t100|
|
||||
# +---------------------------------------------------------------+
|
||||
#
|
||||
# rt-2: route table
|
||||
# +---------------------------------------------------+
|
||||
# |host |Action |
|
||||
# +---------------------------------------------------+
|
||||
# |10.0.0.1 |apply seg6 encap segs fc00:21:100::6004|
|
||||
# +---------------------------------------------------+
|
||||
# |10.0.0.0/24|forward to dev veth_t100 |
|
||||
# +---------------------------------------------------+
|
||||
#
|
||||
|
||||
# Kselftest framework requirement - SKIP code is 4.
|
||||
ksft_skip=4
|
||||
|
||||
readonly IPv6_RT_NETWORK=2001:11
|
||||
readonly IPv4_HS_NETWORK=10.0.0
|
||||
readonly SID_LOCATOR=fc00
|
||||
|
||||
PING_TIMEOUT_SEC=4
|
||||
|
||||
ret=0
|
||||
|
||||
PAUSE_ON_FAIL=${PAUSE_ON_FAIL:=no}
|
||||
|
||||
log_test()
|
||||
{
|
||||
local rc=$1
|
||||
local expected=$2
|
||||
local msg="$3"
|
||||
|
||||
if [ ${rc} -eq ${expected} ]; then
|
||||
nsuccess=$((nsuccess+1))
|
||||
printf "\n TEST: %-60s [ OK ]\n" "${msg}"
|
||||
else
|
||||
ret=1
|
||||
nfail=$((nfail+1))
|
||||
printf "\n TEST: %-60s [FAIL]\n" "${msg}"
|
||||
if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
|
||||
echo
|
||||
echo "hit enter to continue, 'q' to quit"
|
||||
read a
|
||||
[ "$a" = "q" ] && exit 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
print_log_test_results()
|
||||
{
|
||||
if [ "$TESTS" != "none" ]; then
|
||||
printf "\nTests passed: %3d\n" ${nsuccess}
|
||||
printf "Tests failed: %3d\n" ${nfail}
|
||||
fi
|
||||
}
|
||||
|
||||
log_section()
|
||||
{
|
||||
echo
|
||||
echo "################################################################################"
|
||||
echo "TEST SECTION: $*"
|
||||
echo "################################################################################"
|
||||
}
|
||||
|
||||
cleanup()
|
||||
{
|
||||
ip link del veth-rt-1 2>/dev/null || true
|
||||
ip link del veth-rt-2 2>/dev/null || true
|
||||
|
||||
# destroy routers rt-* and hosts hs-*
|
||||
for ns in $(ip netns show | grep -E 'rt-*|hs-*'); do
|
||||
ip netns del ${ns} || true
|
||||
done
|
||||
}
|
||||
|
||||
# Setup the basic networking for the routers
|
||||
setup_rt_networking()
|
||||
{
|
||||
local rt=$1
|
||||
local nsname=rt-${rt}
|
||||
|
||||
ip netns add ${nsname}
|
||||
|
||||
ip netns exec ${nsname} sysctl -wq net.ipv6.conf.all.accept_dad=0
|
||||
ip netns exec ${nsname} sysctl -wq net.ipv6.conf.default.accept_dad=0
|
||||
|
||||
ip link set veth-rt-${rt} netns ${nsname}
|
||||
ip -netns ${nsname} link set veth-rt-${rt} name veth0
|
||||
|
||||
ip -netns ${nsname} addr add ${IPv6_RT_NETWORK}::${rt}/64 dev veth0 nodad
|
||||
ip -netns ${nsname} link set veth0 up
|
||||
ip -netns ${nsname} link set lo up
|
||||
|
||||
ip netns exec ${nsname} sysctl -wq net.ipv4.ip_forward=1
|
||||
ip netns exec ${nsname} sysctl -wq net.ipv6.conf.all.forwarding=1
|
||||
}
|
||||
|
||||
setup_rt_netfilter()
|
||||
{
|
||||
local rt=$1
|
||||
local nsname=rt-${rt}
|
||||
|
||||
ip netns exec ${nsname} sysctl -wq net.netfilter.nf_hooks_lwtunnel=1
|
||||
ip netns exec ${nsname} iptables -t raw -A PREROUTING -m rpfilter --invert -j DROP
|
||||
}
|
||||
|
||||
setup_hs()
|
||||
{
|
||||
local hs=$1
|
||||
local rt=$2
|
||||
local tid=$3
|
||||
local hsname=hs-${hs}
|
||||
local rtname=rt-${rt}
|
||||
local rtveth=veth-t${tid}
|
||||
|
||||
# set the networking for the host
|
||||
ip netns add ${hsname}
|
||||
|
||||
ip -netns ${hsname} link add veth0 type veth peer name ${rtveth}
|
||||
ip -netns ${hsname} link set ${rtveth} netns ${rtname}
|
||||
ip -netns ${hsname} addr add ${IPv4_HS_NETWORK}.${hs}/24 dev veth0
|
||||
ip -netns ${hsname} link set veth0 up
|
||||
ip -netns ${hsname} link set lo up
|
||||
|
||||
ip -netns ${rtname} addr add ${IPv4_HS_NETWORK}.${rt}${hs}/24 dev ${rtveth}
|
||||
ip -netns ${rtname} link set ${rtveth} up
|
||||
|
||||
ip netns exec ${rtname} sysctl -wq net.ipv4.conf.${rtveth}.proxy_arp=1
|
||||
}
|
||||
|
||||
setup_vpn_config()
|
||||
{
|
||||
local hssrc=$1
|
||||
local rtsrc=$2
|
||||
local hsdst=$3
|
||||
local rtdst=$4
|
||||
local tid=$5
|
||||
|
||||
local hssrc_name=hs-t${tid}-${hssrc}
|
||||
local hsdst_name=hs-t${tid}-${hsdst}
|
||||
local rtsrc_name=rt-${rtsrc}
|
||||
local rtdst_name=rt-${rtdst}
|
||||
local vpn_sid=${SID_LOCATOR}:${hssrc}${hsdst}:${tid}::6004
|
||||
|
||||
# set the encap route for encapsulating packets which arrive from the
|
||||
# host hssrc and destined to the access router rtsrc.
|
||||
ip -netns ${rtsrc_name} -4 route add ${IPv4_HS_NETWORK}.${hsdst}/32 \
|
||||
encap seg6 mode encap segs ${vpn_sid} dev veth0
|
||||
ip -netns ${rtsrc_name} -6 route add ${vpn_sid}/128 \
|
||||
via 2001:11::${rtdst} dev veth0
|
||||
|
||||
# set the decap route for decapsulating packets which arrive from
|
||||
# the rtdst router and destined to the hsdst host.
|
||||
ip -netns ${rtdst_name} -6 route add ${vpn_sid}/128 \
|
||||
encap seg6local action End.DX4 nh4 ${IPv4_HS_NETWORK}.${hsdst} dev veth-t${tid}
|
||||
}
|
||||
|
||||
setup()
|
||||
{
|
||||
ip link add veth-rt-1 type veth peer name veth-rt-2
|
||||
# setup the networking for router rt-1 and router rt-2
|
||||
setup_rt_networking 1
|
||||
setup_rt_networking 2
|
||||
|
||||
# setup two hosts for the tenant 100.
|
||||
# - host hs-1 is directly connected to the router rt-1;
|
||||
# - host hs-2 is directly connected to the router rt-2.
|
||||
setup_hs 1 1 100
|
||||
setup_hs 2 2 100
|
||||
|
||||
# setup the IPv4 L3 VPN which connects the host hs-1 and host hs-2.
|
||||
setup_vpn_config 1 1 2 2 100 #args: src_host src_router dst_host dst_router tenant
|
||||
setup_vpn_config 2 2 1 1 100
|
||||
}
|
||||
|
||||
check_hs_connectivity()
|
||||
{
|
||||
local hssrc=$1
|
||||
local hsdst=$2
|
||||
local tid=$3
|
||||
|
||||
ip netns exec hs-${hssrc} ping -c 1 -W ${PING_TIMEOUT_SEC} \
|
||||
${IPv4_HS_NETWORK}.${hsdst} >/dev/null 2>&1
|
||||
}
|
||||
|
||||
check_and_log_hs_connectivity()
|
||||
{
|
||||
local hssrc=$1
|
||||
local hsdst=$2
|
||||
local tid=$3
|
||||
|
||||
check_hs_connectivity ${hssrc} ${hsdst} ${tid}
|
||||
log_test $? 0 "Hosts connectivity: hs-${hssrc} -> hs-${hsdst} (tenant ${tid})"
|
||||
}
|
||||
|
||||
host_tests()
|
||||
{
|
||||
log_section "SRv6 VPN connectivity test among hosts in the same tenant"
|
||||
|
||||
check_and_log_hs_connectivity 1 2 100
|
||||
check_and_log_hs_connectivity 2 1 100
|
||||
}
|
||||
|
||||
router_netfilter_tests()
|
||||
{
|
||||
log_section "SRv6 VPN connectivity test with netfilter enabled in routers"
|
||||
setup_rt_netfilter 1
|
||||
setup_rt_netfilter 2
|
||||
|
||||
check_and_log_hs_connectivity 1 2 100
|
||||
check_and_log_hs_connectivity 2 1 100
|
||||
}
|
||||
|
||||
if [ "$(id -u)" -ne 0 ];then
|
||||
echo "SKIP: Need root privileges"
|
||||
exit $ksft_skip
|
||||
fi
|
||||
|
||||
if [ ! -x "$(command -v ip)" ]; then
|
||||
echo "SKIP: Could not run test without ip tool"
|
||||
exit $ksft_skip
|
||||
fi
|
||||
|
||||
cleanup &>/dev/null
|
||||
|
||||
setup
|
||||
|
||||
host_tests
|
||||
router_netfilter_tests
|
||||
|
||||
print_log_test_results
|
||||
|
||||
cleanup &>/dev/null
|
||||
|
||||
exit ${ret}
|
340
tools/testing/selftests/net/srv6_end_dx6_netfilter_test.sh
Executable file
340
tools/testing/selftests/net/srv6_end_dx6_netfilter_test.sh
Executable file
@@ -0,0 +1,340 @@
|
||||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
# author: Jianguo Wu <wujianguo@chinatelecom.cn>
|
||||
#
|
||||
# Mostly copied from tools/testing/selftests/net/srv6_end_dt6_l3vpn_test.sh.
|
||||
#
|
||||
# This script is designed for testing the support of netfilter hooks for
|
||||
# SRv6 End.DX4 behavior.
|
||||
#
|
||||
# Hereafter a network diagram is shown, where one tenants (named 100) offer
|
||||
# IPv6 L3 VPN services allowing hosts to communicate with each other across
|
||||
# an IPv6 network.
|
||||
#
|
||||
# Routers rt-1 and rt-2 implement IPv6 L3 VPN services leveraging the SRv6
|
||||
# architecture. The key components for such VPNs are: a) SRv6 Encap behavior,
|
||||
# b) SRv6 End.DX4 behavior.
|
||||
#
|
||||
# To explain how an IPv6 L3 VPN based on SRv6 works, let us briefly consider an
|
||||
# example where, within the same domain of tenant 100, the host hs-1 pings
|
||||
# the host hs-2.
|
||||
#
|
||||
# First of all, L2 reachability of the host hs-2 is taken into account by
|
||||
# the router rt-1 which acts as an arp proxy.
|
||||
#
|
||||
# When the host hs-1 sends an IPv6 packet destined to hs-2, the router rt-1
|
||||
# receives the packet on the internal veth-t100 interface, rt-1 contains the
|
||||
# SRv6 Encap route for encapsulating the IPv6 packet in a IPv6 plus the Segment
|
||||
# Routing Header (SRH) packet. This packet is sent through the (IPv6) core
|
||||
# network up to the router rt-2 that receives it on veth0 interface.
|
||||
#
|
||||
# The rt-2 router uses the 'localsid' routing table to process incoming
|
||||
# IPv6+SRH packets which belong to the VPN of the tenant 100. For each of these
|
||||
# packets, the SRv6 End.DX4 behavior removes the outer IPv6+SRH headers and
|
||||
# routs the packet to the specified nexthop. Afterwards, the packet is sent to
|
||||
# the host hs-2 through the veth-t100 interface.
|
||||
#
|
||||
# The ping response follows the same processing but this time the role of rt-1
|
||||
# and rt-2 are swapped.
|
||||
#
|
||||
# And when net.netfilter.nf_hooks_lwtunnel is set to 1 in rt-1 or rt-2, and a
|
||||
# rpfilter iptables rule is added, SRv6 packets will go through netfilter PREROUTING
|
||||
# hooks.
|
||||
#
|
||||
#
|
||||
# +-------------------+ +-------------------+
|
||||
# | | | |
|
||||
# | hs-1 netns | | hs-2 netns |
|
||||
# | | | |
|
||||
# | +-------------+ | | +-------------+ |
|
||||
# | | veth0 | | | | veth0 | |
|
||||
# | | cafe::1/64 | | | | cafe::2/64 | |
|
||||
# | +-------------+ | | +-------------+ |
|
||||
# | . | | . |
|
||||
# +-------------------+ +-------------------+
|
||||
# . .
|
||||
# . .
|
||||
# . .
|
||||
# +-----------------------------------+ +-----------------------------------+
|
||||
# | . | | . |
|
||||
# | +---------------+ | | +---------------- |
|
||||
# | | veth-t100 | | | | veth-t100 | |
|
||||
# | | cafe::11/64 | +----------+ | | +----------+ | cafe::22/64 | |
|
||||
# | +-------+-------+ | route | | | | route | +-------+-------- |
|
||||
# | | table | | | | table | |
|
||||
# | +----------+ | | +----------+ |
|
||||
# | +--------------+ | | +--------------+ |
|
||||
# | | veth0 | | | | veth0 | |
|
||||
# | | 2001:11::1/64 |.|...|.| 2001:11::2/64 | |
|
||||
# | +--------------+ | | +--------------+ |
|
||||
# | | | |
|
||||
# | rt-1 netns | | rt-2 netns |
|
||||
# | | | |
|
||||
# +-----------------------------------+ +-----------------------------------+
|
||||
#
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# | Network configuration |
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
#
|
||||
# rt-1: localsid table
|
||||
# +----------------------------------------------------------------+
|
||||
# |SID |Action |
|
||||
# +----------------------------------------------------------------+
|
||||
# |fc00:21:100::6004|apply SRv6 End.DX6 nh6 cafe::1 dev veth-t100 |
|
||||
# +----------------------------------------------------------------+
|
||||
#
|
||||
# rt-1: route table
|
||||
# +---------------------------------------------------+
|
||||
# |host |Action |
|
||||
# +---------------------------------------------------+
|
||||
# |cafe::2 |apply seg6 encap segs fc00:12:100::6004|
|
||||
# +---------------------------------------------------+
|
||||
# |cafe::/64 |forward to dev veth_t100 |
|
||||
# +---------------------------------------------------+
|
||||
#
|
||||
#
|
||||
# rt-2: localsid table
|
||||
# +---------------------------------------------------------------+
|
||||
# |SID |Action |
|
||||
# +---------------------------------------------------------------+
|
||||
# |fc00:12:100::6004|apply SRv6 End.DX6 nh6 cafe::2 dev veth-t100 |
|
||||
# +---------------------------------------------------------------+
|
||||
#
|
||||
# rt-2: route table
|
||||
# +---------------------------------------------------+
|
||||
# |host |Action |
|
||||
# +---------------------------------------------------+
|
||||
# |cafe::1 |apply seg6 encap segs fc00:21:100::6004|
|
||||
# +---------------------------------------------------+
|
||||
# |cafe::/64 |forward to dev veth_t100 |
|
||||
# +---------------------------------------------------+
|
||||
#
|
||||
|
||||
# Kselftest framework requirement - SKIP code is 4.
|
||||
ksft_skip=4
|
||||
|
||||
readonly IPv6_RT_NETWORK=2001:11
|
||||
readonly IPv6_HS_NETWORK=cafe
|
||||
readonly SID_LOCATOR=fc00
|
||||
|
||||
PING_TIMEOUT_SEC=4
|
||||
|
||||
ret=0
|
||||
|
||||
PAUSE_ON_FAIL=${PAUSE_ON_FAIL:=no}
|
||||
|
||||
log_test()
|
||||
{
|
||||
local rc=$1
|
||||
local expected=$2
|
||||
local msg="$3"
|
||||
|
||||
if [ ${rc} -eq ${expected} ]; then
|
||||
nsuccess=$((nsuccess+1))
|
||||
printf "\n TEST: %-60s [ OK ]\n" "${msg}"
|
||||
else
|
||||
ret=1
|
||||
nfail=$((nfail+1))
|
||||
printf "\n TEST: %-60s [FAIL]\n" "${msg}"
|
||||
if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
|
||||
echo
|
||||
echo "hit enter to continue, 'q' to quit"
|
||||
read a
|
||||
[ "$a" = "q" ] && exit 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
print_log_test_results()
|
||||
{
|
||||
if [ "$TESTS" != "none" ]; then
|
||||
printf "\nTests passed: %3d\n" ${nsuccess}
|
||||
printf "Tests failed: %3d\n" ${nfail}
|
||||
fi
|
||||
}
|
||||
|
||||
log_section()
|
||||
{
|
||||
echo
|
||||
echo "################################################################################"
|
||||
echo "TEST SECTION: $*"
|
||||
echo "################################################################################"
|
||||
}
|
||||
|
||||
cleanup()
|
||||
{
|
||||
ip link del veth-rt-1 2>/dev/null || true
|
||||
ip link del veth-rt-2 2>/dev/null || true
|
||||
|
||||
# destroy routers rt-* and hosts hs-*
|
||||
for ns in $(ip netns show | grep -E 'rt-*|hs-*'); do
|
||||
ip netns del ${ns} || true
|
||||
done
|
||||
}
|
||||
|
||||
# Setup the basic networking for the routers
|
||||
setup_rt_networking()
|
||||
{
|
||||
local rt=$1
|
||||
local nsname=rt-${rt}
|
||||
|
||||
ip netns add ${nsname}
|
||||
|
||||
ip netns exec ${nsname} sysctl -wq net.ipv6.conf.all.accept_dad=0
|
||||
ip netns exec ${nsname} sysctl -wq net.ipv6.conf.default.accept_dad=0
|
||||
|
||||
ip link set veth-rt-${rt} netns ${nsname}
|
||||
ip -netns ${nsname} link set veth-rt-${rt} name veth0
|
||||
|
||||
ip -netns ${nsname} addr add ${IPv6_RT_NETWORK}::${rt}/64 dev veth0 nodad
|
||||
ip -netns ${nsname} link set veth0 up
|
||||
ip -netns ${nsname} link set lo up
|
||||
|
||||
ip netns exec ${nsname} sysctl -wq net.ipv6.conf.all.forwarding=1
|
||||
}
|
||||
|
||||
setup_rt_netfilter()
|
||||
{
|
||||
local rt=$1
|
||||
local nsname=rt-${rt}
|
||||
|
||||
ip netns exec ${nsname} sysctl -wq net.netfilter.nf_hooks_lwtunnel=1
|
||||
ip netns exec ${nsname} ip6tables -t raw -A PREROUTING -m rpfilter --invert -j DROP
|
||||
}
|
||||
|
||||
setup_hs()
|
||||
{
|
||||
local hs=$1
|
||||
local rt=$2
|
||||
local tid=$3
|
||||
local hsname=hs-${hs}
|
||||
local rtname=rt-${rt}
|
||||
local rtveth=veth-t${tid}
|
||||
|
||||
# set the networking for the host
|
||||
ip netns add ${hsname}
|
||||
|
||||
ip -netns ${hsname} link add veth0 type veth peer name ${rtveth}
|
||||
ip -netns ${hsname} link set ${rtveth} netns ${rtname}
|
||||
ip -netns ${hsname} addr add ${IPv6_HS_NETWORK}::${hs}/64 dev veth0 nodad
|
||||
ip -netns ${hsname} link set veth0 up
|
||||
ip -netns ${hsname} link set lo up
|
||||
|
||||
ip -netns ${rtname} addr add ${IPv6_HS_NETWORK}::${rt}${hs}/64 dev ${rtveth}
|
||||
ip -netns ${rtname} link set ${rtveth} up
|
||||
|
||||
ip netns exec ${rtname} sysctl -wq net.ipv6.conf.all.accept_dad=0
|
||||
ip netns exec ${rtname} sysctl -wq net.ipv6.conf.default.accept_dad=0
|
||||
|
||||
ip netns exec ${rtname} sysctl -wq net.ipv6.conf.${rtveth}.proxy_ndp=1
|
||||
}
|
||||
|
||||
setup_vpn_config()
|
||||
{
|
||||
local hssrc=$1
|
||||
local rtsrc=$2
|
||||
local hsdst=$3
|
||||
local rtdst=$4
|
||||
local tid=$5
|
||||
|
||||
local hssrc_name=hs-t${tid}-${hssrc}
|
||||
local hsdst_name=hs-t${tid}-${hsdst}
|
||||
local rtsrc_name=rt-${rtsrc}
|
||||
local rtdst_name=rt-${rtdst}
|
||||
local rtveth=veth-t${tid}
|
||||
local vpn_sid=${SID_LOCATOR}:${hssrc}${hsdst}:${tid}::6004
|
||||
|
||||
ip -netns ${rtsrc_name} -6 neigh add proxy ${IPv6_HS_NETWORK}::${hsdst} dev ${rtveth}
|
||||
|
||||
# set the encap route for encapsulating packets which arrive from the
|
||||
# host hssrc and destined to the access router rtsrc.
|
||||
ip -netns ${rtsrc_name} -6 route add ${IPv6_HS_NETWORK}::${hsdst}/128 \
|
||||
encap seg6 mode encap segs ${vpn_sid} dev veth0
|
||||
ip -netns ${rtsrc_name} -6 route add ${vpn_sid}/128 \
|
||||
via 2001:11::${rtdst} dev veth0
|
||||
|
||||
# set the decap route for decapsulating packets which arrive from
|
||||
# the rtdst router and destined to the hsdst host.
|
||||
ip -netns ${rtdst_name} -6 route add ${vpn_sid}/128 \
|
||||
encap seg6local action End.DX6 nh6 ${IPv6_HS_NETWORK}::${hsdst} dev veth-t${tid}
|
||||
}
|
||||
|
||||
setup()
|
||||
{
|
||||
ip link add veth-rt-1 type veth peer name veth-rt-2
|
||||
# setup the networking for router rt-1 and router rt-2
|
||||
setup_rt_networking 1
|
||||
setup_rt_networking 2
|
||||
|
||||
# setup two hosts for the tenant 100.
|
||||
# - host hs-1 is directly connected to the router rt-1;
|
||||
# - host hs-2 is directly connected to the router rt-2.
|
||||
setup_hs 1 1 100
|
||||
setup_hs 2 2 100
|
||||
|
||||
# setup the IPv4 L3 VPN which connects the host hs-1 and host hs-2.
|
||||
setup_vpn_config 1 1 2 2 100 #args: src_host src_router dst_host dst_router tenant
|
||||
setup_vpn_config 2 2 1 1 100
|
||||
}
|
||||
|
||||
check_hs_connectivity()
|
||||
{
|
||||
local hssrc=$1
|
||||
local hsdst=$2
|
||||
local tid=$3
|
||||
|
||||
ip netns exec hs-${hssrc} ping -6 -c 1 -W ${PING_TIMEOUT_SEC} \
|
||||
${IPv6_HS_NETWORK}::${hsdst} >/dev/null 2>&1
|
||||
}
|
||||
|
||||
check_and_log_hs_connectivity()
|
||||
{
|
||||
local hssrc=$1
|
||||
local hsdst=$2
|
||||
local tid=$3
|
||||
|
||||
check_hs_connectivity ${hssrc} ${hsdst} ${tid}
|
||||
log_test $? 0 "Hosts connectivity: hs-${hssrc} -> hs-${hsdst} (tenant ${tid})"
|
||||
}
|
||||
|
||||
host_tests()
|
||||
{
|
||||
log_section "SRv6 VPN connectivity test among hosts in the same tenant"
|
||||
|
||||
check_and_log_hs_connectivity 1 2 100
|
||||
check_and_log_hs_connectivity 2 1 100
|
||||
}
|
||||
|
||||
router_netfilter_tests()
|
||||
{
|
||||
log_section "SRv6 VPN connectivity test with netfilter enabled in routers"
|
||||
setup_rt_netfilter 1
|
||||
setup_rt_netfilter 2
|
||||
|
||||
check_and_log_hs_connectivity 1 2 100
|
||||
check_and_log_hs_connectivity 2 1 100
|
||||
}
|
||||
|
||||
if [ "$(id -u)" -ne 0 ];then
|
||||
echo "SKIP: Need root privileges"
|
||||
exit $ksft_skip
|
||||
fi
|
||||
|
||||
if [ ! -x "$(command -v ip)" ]; then
|
||||
echo "SKIP: Could not run test without ip tool"
|
||||
exit $ksft_skip
|
||||
fi
|
||||
|
||||
cleanup &>/dev/null
|
||||
|
||||
setup
|
||||
|
||||
host_tests
|
||||
router_netfilter_tests
|
||||
|
||||
print_log_test_results
|
||||
|
||||
cleanup &>/dev/null
|
||||
|
||||
exit ${ret}
|
@@ -1,8 +1,18 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
CFLAGS += -Wall -O2 -g -fsanitize=address -fsanitize=undefined -static-libasan
|
||||
CFLAGS += -Wall -O2 -g -fsanitize=address -fsanitize=undefined
|
||||
TEST_GEN_PROGS := openat2_test resolve_test rename_attack_test
|
||||
|
||||
# gcc requires -static-libasan in order to ensure that Address Sanitizer's
|
||||
# library is the first one loaded. However, clang already statically links the
|
||||
# Address Sanitizer if -fsanitize is specified. Therefore, simply omit
|
||||
# -static-libasan for clang builds.
|
||||
ifeq ($(LLVM),)
|
||||
CFLAGS += -static-libasan
|
||||
endif
|
||||
|
||||
LOCAL_HDRS += helpers.h
|
||||
|
||||
include ../lib.mk
|
||||
|
||||
$(TEST_GEN_PROGS): helpers.c helpers.h
|
||||
$(TEST_GEN_PROGS): helpers.c
|
||||
|
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#define __SANE_USERSPACE_TYPES__ // Use ll64
|
||||
#include <fcntl.h>
|
||||
#include <sched.h>
|
||||
#include <sys/stat.h>
|
||||
|
@@ -194,14 +194,14 @@ int main(int argc, char *argv[])
|
||||
ksft_set_plan(7);
|
||||
|
||||
ksft_print_msg("Running on:\n");
|
||||
ksft_print_msg("");
|
||||
ksft_print_msg("%s", "");
|
||||
system("uname -a");
|
||||
|
||||
ksft_print_msg("Current BPF sysctl settings:\n");
|
||||
/* Avoid using "sysctl" which may not be installed. */
|
||||
ksft_print_msg("");
|
||||
ksft_print_msg("%s", "");
|
||||
system("grep -H . /proc/sys/net/core/bpf_jit_enable");
|
||||
ksft_print_msg("");
|
||||
ksft_print_msg("%s", "");
|
||||
system("grep -H . /proc/sys/net/core/bpf_jit_harden");
|
||||
|
||||
affinity();
|
||||
|
@@ -132,6 +132,50 @@
|
||||
"echo \"1\" > /sys/bus/netdevsim/del_device"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "6f62",
|
||||
"name": "Add taprio Qdisc with too short interval",
|
||||
"category": [
|
||||
"qdisc",
|
||||
"taprio"
|
||||
],
|
||||
"plugins": {
|
||||
"requires": "nsPlugin"
|
||||
},
|
||||
"setup": [
|
||||
"echo \"1 1 8\" > /sys/bus/netdevsim/new_device"
|
||||
],
|
||||
"cmdUnderTest": "$TC qdisc add dev $ETH root handle 1: taprio num_tc 2 queues 1@0 1@1 sched-entry S 01 300 sched-entry S 02 1700 clockid CLOCK_TAI",
|
||||
"expExitCode": "2",
|
||||
"verifyCmd": "$TC qdisc show dev $ETH",
|
||||
"matchPattern": "qdisc taprio 1: root refcnt",
|
||||
"matchCount": "0",
|
||||
"teardown": [
|
||||
"echo \"1\" > /sys/bus/netdevsim/del_device"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "831f",
|
||||
"name": "Add taprio Qdisc with too short cycle-time",
|
||||
"category": [
|
||||
"qdisc",
|
||||
"taprio"
|
||||
],
|
||||
"plugins": {
|
||||
"requires": "nsPlugin"
|
||||
},
|
||||
"setup": [
|
||||
"echo \"1 1 8\" > /sys/bus/netdevsim/new_device"
|
||||
],
|
||||
"cmdUnderTest": "$TC qdisc add dev $ETH root handle 1: taprio num_tc 2 queues 1@0 1@1 sched-entry S 01 200000 sched-entry S 02 200000 cycle-time 100 clockid CLOCK_TAI",
|
||||
"expExitCode": "2",
|
||||
"verifyCmd": "$TC qdisc show dev $ETH",
|
||||
"matchPattern": "qdisc taprio 1: root refcnt",
|
||||
"matchCount": "0",
|
||||
"teardown": [
|
||||
"echo \"1\" > /sys/bus/netdevsim/del_device"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "3e1e",
|
||||
"name": "Add taprio Qdisc with an invalid cycle-time",
|
||||
|
Reference in New Issue
Block a user