mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-15 11:47:47 +00:00
Merge branch 'bpf-next/master' into for-next
No conflict. Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
This commit is contained in:
commit
cb451fc2e1
@ -302,6 +302,7 @@ static bool func_add_bb_edges(struct func_node *func)
|
||||
|
||||
insn = bb->tail;
|
||||
if (!is_jmp_insn(insn->code) ||
|
||||
BPF_OP(insn->code) == BPF_CALL ||
|
||||
BPF_OP(insn->code) == BPF_EXIT) {
|
||||
e->dst = bb_next(bb);
|
||||
e->flags |= EDGE_FLAG_FALLTHROUGH;
|
||||
|
@ -11534,7 +11534,7 @@ bpf_program__attach_kprobe_multi_opts(const struct bpf_program *prog,
|
||||
struct bpf_link *link = NULL;
|
||||
const unsigned long *addrs;
|
||||
int err, link_fd, prog_fd;
|
||||
bool retprobe, session;
|
||||
bool retprobe, session, unique_match;
|
||||
const __u64 *cookies;
|
||||
const char **syms;
|
||||
size_t cnt;
|
||||
@ -11553,6 +11553,7 @@ bpf_program__attach_kprobe_multi_opts(const struct bpf_program *prog,
|
||||
addrs = OPTS_GET(opts, addrs, false);
|
||||
cnt = OPTS_GET(opts, cnt, false);
|
||||
cookies = OPTS_GET(opts, cookies, false);
|
||||
unique_match = OPTS_GET(opts, unique_match, false);
|
||||
|
||||
if (!pattern && !addrs && !syms)
|
||||
return libbpf_err_ptr(-EINVAL);
|
||||
@ -11560,6 +11561,8 @@ bpf_program__attach_kprobe_multi_opts(const struct bpf_program *prog,
|
||||
return libbpf_err_ptr(-EINVAL);
|
||||
if (!pattern && !cnt)
|
||||
return libbpf_err_ptr(-EINVAL);
|
||||
if (!pattern && unique_match)
|
||||
return libbpf_err_ptr(-EINVAL);
|
||||
if (addrs && syms)
|
||||
return libbpf_err_ptr(-EINVAL);
|
||||
|
||||
@ -11570,6 +11573,14 @@ bpf_program__attach_kprobe_multi_opts(const struct bpf_program *prog,
|
||||
err = libbpf_available_kallsyms_parse(&res);
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
if (unique_match && res.cnt != 1) {
|
||||
pr_warn("prog '%s': failed to find a unique match for '%s' (%zu matches)\n",
|
||||
prog->name, pattern, res.cnt);
|
||||
err = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
addrs = res.addrs;
|
||||
cnt = res.cnt;
|
||||
}
|
||||
|
@ -552,10 +552,12 @@ struct bpf_kprobe_multi_opts {
|
||||
bool retprobe;
|
||||
/* create session kprobes */
|
||||
bool session;
|
||||
/* enforce unique match */
|
||||
bool unique_match;
|
||||
size_t :0;
|
||||
};
|
||||
|
||||
#define bpf_kprobe_multi_opts__last_field session
|
||||
#define bpf_kprobe_multi_opts__last_field unique_match
|
||||
|
||||
LIBBPF_API struct bpf_link *
|
||||
bpf_program__attach_kprobe_multi_opts(const struct bpf_program *prog,
|
||||
|
@ -100,7 +100,6 @@ TEST_FILES = xsk_prereqs.sh $(wildcard progs/btf_dump_test_case_*.c)
|
||||
|
||||
# Order correspond to 'make run_tests' order
|
||||
TEST_PROGS := test_kmod.sh \
|
||||
test_xdp_redirect.sh \
|
||||
test_xdp_redirect_multi.sh \
|
||||
test_tunnel.sh \
|
||||
test_lwt_seg6local.sh \
|
||||
|
@ -397,6 +397,31 @@ cleanup:
|
||||
kprobe_multi_session_cookie__destroy(skel);
|
||||
}
|
||||
|
||||
static void test_unique_match(void)
|
||||
{
|
||||
LIBBPF_OPTS(bpf_kprobe_multi_opts, opts);
|
||||
struct kprobe_multi *skel = NULL;
|
||||
struct bpf_link *link = NULL;
|
||||
|
||||
skel = kprobe_multi__open_and_load();
|
||||
if (!ASSERT_OK_PTR(skel, "kprobe_multi__open_and_load"))
|
||||
return;
|
||||
|
||||
opts.unique_match = true;
|
||||
skel->bss->pid = getpid();
|
||||
link = bpf_program__attach_kprobe_multi_opts(skel->progs.test_kprobe_manual,
|
||||
"bpf_fentry_test*", &opts);
|
||||
if (!ASSERT_ERR_PTR(link, "bpf_program__attach_kprobe_multi_opts"))
|
||||
bpf_link__destroy(link);
|
||||
|
||||
link = bpf_program__attach_kprobe_multi_opts(skel->progs.test_kprobe_manual,
|
||||
"bpf_fentry_test8*", &opts);
|
||||
if (ASSERT_OK_PTR(link, "bpf_program__attach_kprobe_multi_opts"))
|
||||
bpf_link__destroy(link);
|
||||
|
||||
kprobe_multi__destroy(skel);
|
||||
}
|
||||
|
||||
static size_t symbol_hash(long key, void *ctx __maybe_unused)
|
||||
{
|
||||
return str_hash((const char *) key);
|
||||
@ -765,5 +790,7 @@ void test_kprobe_multi_test(void)
|
||||
test_session_skel_api();
|
||||
if (test__start_subtest("session_cookie"))
|
||||
test_session_cookie_skel_api();
|
||||
if (test__start_subtest("unique_match"))
|
||||
test_unique_match();
|
||||
RUN_TESTS(kprobe_multi_verifier);
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <bpf/bpf_endian.h>
|
||||
#include <uapi/linux/netdev.h>
|
||||
#include "test_xdp_do_redirect.skel.h"
|
||||
#include "xdp_dummy.skel.h"
|
||||
|
||||
struct udp_packet {
|
||||
struct ethhdr eth;
|
||||
@ -246,3 +247,166 @@ out:
|
||||
SYS_NOFAIL("ip netns del testns");
|
||||
test_xdp_do_redirect__destroy(skel);
|
||||
}
|
||||
|
||||
#define NS_NB 3
|
||||
#define NS0 "NS0"
|
||||
#define NS1 "NS1"
|
||||
#define NS2 "NS2"
|
||||
#define IPV4_NETWORK "10.1.1"
|
||||
#define VETH1_INDEX 111
|
||||
#define VETH2_INDEX 222
|
||||
|
||||
struct test_data {
|
||||
struct netns_obj *ns[NS_NB];
|
||||
u32 xdp_flags;
|
||||
};
|
||||
|
||||
static void cleanup(struct test_data *data)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NS_NB; i++)
|
||||
netns_free(data->ns[i]);
|
||||
}
|
||||
|
||||
/**
|
||||
* ping_setup -
|
||||
* Create two veth peers and forward packets in-between using XDP
|
||||
*
|
||||
* ------------ ------------
|
||||
* | NS1 | | NS2 |
|
||||
* | veth0 | | veth0 |
|
||||
* | 10.1.1.1 | | 10.1.1.2 |
|
||||
* -----|------ ------|-----
|
||||
* | |
|
||||
* | |
|
||||
* -----|-----------------------|-------
|
||||
* | veth1 veth2 |
|
||||
* | (id:111) (id:222) |
|
||||
* | | | |
|
||||
* | ----- xdp forwarding ----- |
|
||||
* | |
|
||||
* | NS0 |
|
||||
* -------------------------------------
|
||||
*/
|
||||
static int ping_setup(struct test_data *data)
|
||||
{
|
||||
int i;
|
||||
|
||||
data->ns[0] = netns_new(NS0, false);
|
||||
if (!ASSERT_OK_PTR(data->ns[0], "create ns"))
|
||||
return -1;
|
||||
|
||||
for (i = 1; i < NS_NB; i++) {
|
||||
char ns_name[4] = {};
|
||||
|
||||
snprintf(ns_name, 4, "NS%d", i);
|
||||
data->ns[i] = netns_new(ns_name, false);
|
||||
if (!ASSERT_OK_PTR(data->ns[i], "create ns"))
|
||||
goto fail;
|
||||
|
||||
SYS(fail,
|
||||
"ip -n %s link add veth%d index %d%d%d type veth peer name veth0 netns %s",
|
||||
NS0, i, i, i, i, ns_name);
|
||||
SYS(fail, "ip -n %s link set veth%d up", NS0, i);
|
||||
|
||||
SYS(fail, "ip -n %s addr add %s.%d/24 dev veth0", ns_name, IPV4_NETWORK, i);
|
||||
SYS(fail, "ip -n %s link set veth0 up", ns_name);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
cleanup(data);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void ping_test(struct test_data *data)
|
||||
{
|
||||
struct test_xdp_do_redirect *skel = NULL;
|
||||
struct xdp_dummy *skel_dummy = NULL;
|
||||
struct nstoken *nstoken = NULL;
|
||||
int i, ret;
|
||||
|
||||
skel_dummy = xdp_dummy__open_and_load();
|
||||
if (!ASSERT_OK_PTR(skel_dummy, "open and load xdp_dummy skeleton"))
|
||||
goto close;
|
||||
|
||||
for (i = 1; i < NS_NB; i++) {
|
||||
char ns_name[4] = {};
|
||||
|
||||
snprintf(ns_name, 4, "NS%d", i);
|
||||
nstoken = open_netns(ns_name);
|
||||
if (!ASSERT_OK_PTR(nstoken, "open ns"))
|
||||
goto close;
|
||||
|
||||
ret = bpf_xdp_attach(if_nametoindex("veth0"),
|
||||
bpf_program__fd(skel_dummy->progs.xdp_dummy_prog),
|
||||
data->xdp_flags, NULL);
|
||||
if (!ASSERT_GE(ret, 0, "bpf_xdp_attach dummy_prog"))
|
||||
goto close;
|
||||
|
||||
close_netns(nstoken);
|
||||
nstoken = NULL;
|
||||
}
|
||||
|
||||
skel = test_xdp_do_redirect__open_and_load();
|
||||
if (!ASSERT_OK_PTR(skel, "open and load skeleton"))
|
||||
goto close;
|
||||
|
||||
nstoken = open_netns(NS0);
|
||||
if (!ASSERT_OK_PTR(nstoken, "open NS0"))
|
||||
goto close;
|
||||
|
||||
ret = bpf_xdp_attach(VETH2_INDEX,
|
||||
bpf_program__fd(skel->progs.xdp_redirect_to_111),
|
||||
data->xdp_flags, NULL);
|
||||
if (!ASSERT_GE(ret, 0, "bpf_xdp_attach"))
|
||||
goto close;
|
||||
|
||||
ret = bpf_xdp_attach(VETH1_INDEX,
|
||||
bpf_program__fd(skel->progs.xdp_redirect_to_222),
|
||||
data->xdp_flags, NULL);
|
||||
if (!ASSERT_GE(ret, 0, "bpf_xdp_attach"))
|
||||
goto close;
|
||||
|
||||
close_netns(nstoken);
|
||||
nstoken = NULL;
|
||||
|
||||
nstoken = open_netns(NS1);
|
||||
if (!ASSERT_OK_PTR(nstoken, "open NS1"))
|
||||
goto close;
|
||||
|
||||
SYS(close, "ping -c 1 %s.2 > /dev/null", IPV4_NETWORK);
|
||||
|
||||
close:
|
||||
close_netns(nstoken);
|
||||
xdp_dummy__destroy(skel_dummy);
|
||||
test_xdp_do_redirect__destroy(skel);
|
||||
}
|
||||
|
||||
|
||||
static void xdp_redirect_ping(u32 xdp_flags)
|
||||
{
|
||||
struct test_data data = {};
|
||||
|
||||
if (ping_setup(&data) < 0)
|
||||
return;
|
||||
|
||||
data.xdp_flags = xdp_flags;
|
||||
ping_test(&data);
|
||||
cleanup(&data);
|
||||
}
|
||||
|
||||
void test_xdp_index_redirect(void)
|
||||
{
|
||||
if (test__start_subtest("noflag"))
|
||||
xdp_redirect_ping(0);
|
||||
|
||||
if (test__start_subtest("drvflag"))
|
||||
xdp_redirect_ping(XDP_FLAGS_DRV_MODE);
|
||||
|
||||
if (test__start_subtest("skbflag"))
|
||||
xdp_redirect_ping(XDP_FLAGS_SKB_MODE);
|
||||
}
|
||||
|
||||
|
@ -98,6 +98,18 @@ int xdp_count_pkts(struct xdp_md *xdp)
|
||||
return XDP_DROP;
|
||||
}
|
||||
|
||||
SEC("xdp")
|
||||
int xdp_redirect_to_111(struct xdp_md *xdp)
|
||||
{
|
||||
return bpf_redirect(111, 0);
|
||||
}
|
||||
|
||||
SEC("xdp")
|
||||
int xdp_redirect_to_222(struct xdp_md *xdp)
|
||||
{
|
||||
return bpf_redirect(222, 0);
|
||||
}
|
||||
|
||||
SEC("tc")
|
||||
int tc_count_pkts(struct __sk_buff *skb)
|
||||
{
|
||||
|
@ -1,26 +0,0 @@
|
||||
/* Copyright (c) 2017 VMware
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2 of the GNU General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*/
|
||||
#include <linux/bpf.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
|
||||
SEC("redirect_to_111")
|
||||
int xdp_redirect_to_111(struct xdp_md *xdp)
|
||||
{
|
||||
return bpf_redirect(111, 0);
|
||||
}
|
||||
SEC("redirect_to_222")
|
||||
int xdp_redirect_to_222(struct xdp_md *xdp)
|
||||
{
|
||||
return bpf_redirect(222, 0);
|
||||
}
|
||||
|
||||
char _license[] SEC("license") = "GPL";
|
@ -1,79 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Create 2 namespaces with two veth peers, and
|
||||
# forward packets in-between using generic XDP
|
||||
#
|
||||
# NS1(veth11) NS2(veth22)
|
||||
# | |
|
||||
# | |
|
||||
# (veth1, ------ (veth2,
|
||||
# id:111) id:222)
|
||||
# | xdp forwarding |
|
||||
# ------------------
|
||||
|
||||
readonly NS1="ns1-$(mktemp -u XXXXXX)"
|
||||
readonly NS2="ns2-$(mktemp -u XXXXXX)"
|
||||
ret=0
|
||||
|
||||
setup()
|
||||
{
|
||||
|
||||
local xdpmode=$1
|
||||
|
||||
ip netns add ${NS1}
|
||||
ip netns add ${NS2}
|
||||
|
||||
ip link add veth1 index 111 type veth peer name veth11 netns ${NS1}
|
||||
ip link add veth2 index 222 type veth peer name veth22 netns ${NS2}
|
||||
|
||||
ip link set veth1 up
|
||||
ip link set veth2 up
|
||||
ip -n ${NS1} link set dev veth11 up
|
||||
ip -n ${NS2} link set dev veth22 up
|
||||
|
||||
ip -n ${NS1} addr add 10.1.1.11/24 dev veth11
|
||||
ip -n ${NS2} addr add 10.1.1.22/24 dev veth22
|
||||
}
|
||||
|
||||
cleanup()
|
||||
{
|
||||
ip link del veth1 2> /dev/null
|
||||
ip link del veth2 2> /dev/null
|
||||
ip netns del ${NS1} 2> /dev/null
|
||||
ip netns del ${NS2} 2> /dev/null
|
||||
}
|
||||
|
||||
test_xdp_redirect()
|
||||
{
|
||||
local xdpmode=$1
|
||||
|
||||
setup
|
||||
|
||||
ip link set dev veth1 $xdpmode off &> /dev/null
|
||||
if [ $? -ne 0 ];then
|
||||
echo "selftests: test_xdp_redirect $xdpmode [SKIP]"
|
||||
return 0
|
||||
fi
|
||||
|
||||
ip -n ${NS1} link set veth11 $xdpmode obj xdp_dummy.bpf.o sec xdp &> /dev/null
|
||||
ip -n ${NS2} link set veth22 $xdpmode obj xdp_dummy.bpf.o sec xdp &> /dev/null
|
||||
ip link set dev veth1 $xdpmode obj test_xdp_redirect.bpf.o sec redirect_to_222 &> /dev/null
|
||||
ip link set dev veth2 $xdpmode obj test_xdp_redirect.bpf.o sec redirect_to_111 &> /dev/null
|
||||
|
||||
if ip netns exec ${NS1} ping -c 1 10.1.1.22 &> /dev/null &&
|
||||
ip netns exec ${NS2} ping -c 1 10.1.1.11 &> /dev/null; then
|
||||
echo "selftests: test_xdp_redirect $xdpmode [PASS]";
|
||||
else
|
||||
ret=1
|
||||
echo "selftests: test_xdp_redirect $xdpmode [FAILED]";
|
||||
fi
|
||||
|
||||
cleanup
|
||||
}
|
||||
|
||||
set -e
|
||||
trap cleanup 2 3 6 9
|
||||
|
||||
test_xdp_redirect xdpgeneric
|
||||
test_xdp_redirect xdpdrv
|
||||
|
||||
exit $ret
|
@ -216,7 +216,8 @@ const char argp_program_doc[] =
|
||||
"\n"
|
||||
"USAGE: veristat <obj-file> [<obj-file>...]\n"
|
||||
" OR: veristat -C <baseline.csv> <comparison.csv>\n"
|
||||
" OR: veristat -R <results.csv>\n";
|
||||
" OR: veristat -R <results.csv>\n"
|
||||
" OR: veristat -vl2 <to_analyze.bpf.o>\n";
|
||||
|
||||
enum {
|
||||
OPT_LOG_FIXED = 1000,
|
||||
@ -228,7 +229,7 @@ static const struct argp_option opts[] = {
|
||||
{ "version", 'V', NULL, 0, "Print version" },
|
||||
{ "verbose", 'v', NULL, 0, "Verbose mode" },
|
||||
{ "debug", 'd', NULL, 0, "Debug mode (turns on libbpf debug logging)" },
|
||||
{ "log-level", 'l', "LEVEL", 0, "Verifier log level (default 0 for normal mode, 1 for verbose mode)" },
|
||||
{ "log-level", 'l', "LEVEL", 0, "Verifier log level (default 0 for normal mode, 1 for verbose mode, 2 for full verification log)" },
|
||||
{ "log-fixed", OPT_LOG_FIXED, NULL, 0, "Disable verifier log rotation" },
|
||||
{ "log-size", OPT_LOG_SIZE, "BYTES", 0, "Customize verifier log size (default to 16MB)" },
|
||||
{ "top-n", 'n', "N", 0, "Emit only up to first N results." },
|
||||
|
Loading…
x
Reference in New Issue
Block a user