mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-18 15:16:56 +07:00
Merge branch 'bpf-misc-updates'
Daniel Borkmann says: ==================== Misc BPF updates This set contains a couple of misc updates: stack usage reduction for perf_sample_data in tracing progs, reduction of stale data in verifier on register state transitions that I still had in my queue and few selftest improvements as well as bpf_set_hash() helper for tc programs. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
9fd7aca2c6
@ -513,6 +513,11 @@ union bpf_attr {
|
||||
* Get the owner uid of the socket stored inside sk_buff.
|
||||
* @skb: pointer to skb
|
||||
* Return: uid of the socket owner on success or overflowuid if failed.
|
||||
*
|
||||
* u32 bpf_set_hash(skb, hash)
|
||||
* Set full skb->hash.
|
||||
* @skb: pointer to skb
|
||||
* @hash: hash to set
|
||||
*/
|
||||
#define __BPF_FUNC_MAPPER(FN) \
|
||||
FN(unspec), \
|
||||
@ -562,7 +567,8 @@ union bpf_attr {
|
||||
FN(xdp_adjust_head), \
|
||||
FN(probe_read_str), \
|
||||
FN(get_socket_cookie), \
|
||||
FN(get_socket_uid),
|
||||
FN(get_socket_uid), \
|
||||
FN(set_hash),
|
||||
|
||||
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
|
||||
* function eBPF program intends to call
|
||||
|
@ -1346,8 +1346,8 @@ static void clear_all_pkt_pointers(struct bpf_verifier_env *env)
|
||||
if (reg->type != PTR_TO_PACKET &&
|
||||
reg->type != PTR_TO_PACKET_END)
|
||||
continue;
|
||||
reg->type = UNKNOWN_VALUE;
|
||||
reg->imm = 0;
|
||||
__mark_reg_unknown_value(state->spilled_regs,
|
||||
i / BPF_REG_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1952,6 +1952,7 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn)
|
||||
*/
|
||||
regs[insn->dst_reg].type = CONST_IMM;
|
||||
regs[insn->dst_reg].imm = insn->imm;
|
||||
regs[insn->dst_reg].id = 0;
|
||||
regs[insn->dst_reg].max_value = insn->imm;
|
||||
regs[insn->dst_reg].min_value = insn->imm;
|
||||
regs[insn->dst_reg].min_align = calc_align(insn->imm);
|
||||
@ -2409,6 +2410,7 @@ static int check_ld_imm(struct bpf_verifier_env *env, struct bpf_insn *insn)
|
||||
|
||||
regs[insn->dst_reg].type = CONST_IMM;
|
||||
regs[insn->dst_reg].imm = imm;
|
||||
regs[insn->dst_reg].id = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2828,6 +2830,8 @@ static bool states_equal(struct bpf_verifier_env *env,
|
||||
return false;
|
||||
if (i % BPF_REG_SIZE)
|
||||
continue;
|
||||
if (old->stack_slot_type[i] != STACK_SPILL)
|
||||
continue;
|
||||
if (memcmp(&old->spilled_regs[i / BPF_REG_SIZE],
|
||||
&cur->spilled_regs[i / BPF_REG_SIZE],
|
||||
sizeof(old->spilled_regs[0])))
|
||||
|
@ -266,14 +266,16 @@ static const struct bpf_func_proto bpf_perf_event_read_proto = {
|
||||
.arg2_type = ARG_ANYTHING,
|
||||
};
|
||||
|
||||
static DEFINE_PER_CPU(struct perf_sample_data, bpf_sd);
|
||||
|
||||
static __always_inline u64
|
||||
__bpf_perf_event_output(struct pt_regs *regs, struct bpf_map *map,
|
||||
u64 flags, struct perf_raw_record *raw)
|
||||
{
|
||||
struct bpf_array *array = container_of(map, struct bpf_array, map);
|
||||
struct perf_sample_data *sd = this_cpu_ptr(&bpf_sd);
|
||||
unsigned int cpu = smp_processor_id();
|
||||
u64 index = flags & BPF_F_INDEX_MASK;
|
||||
struct perf_sample_data sample_data;
|
||||
struct bpf_event_entry *ee;
|
||||
struct perf_event *event;
|
||||
|
||||
@ -294,9 +296,9 @@ __bpf_perf_event_output(struct pt_regs *regs, struct bpf_map *map,
|
||||
if (unlikely(event->oncpu != cpu))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
perf_sample_data_init(&sample_data, 0, 0);
|
||||
sample_data.raw = raw;
|
||||
perf_event_output(event, &sample_data, regs);
|
||||
perf_sample_data_init(sd, 0, 0);
|
||||
sd->raw = raw;
|
||||
perf_event_output(event, sd, regs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1874,6 +1874,24 @@ static const struct bpf_func_proto bpf_set_hash_invalid_proto = {
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
};
|
||||
|
||||
BPF_CALL_2(bpf_set_hash, struct sk_buff *, skb, u32, hash)
|
||||
{
|
||||
/* Set user specified hash as L4(+), so that it gets returned
|
||||
* on skb_get_hash() call unless BPF prog later on triggers a
|
||||
* skb_clear_hash().
|
||||
*/
|
||||
__skb_set_sw_hash(skb, hash, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct bpf_func_proto bpf_set_hash_proto = {
|
||||
.func = bpf_set_hash,
|
||||
.gpl_only = false,
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_ANYTHING,
|
||||
};
|
||||
|
||||
BPF_CALL_3(bpf_skb_vlan_push, struct sk_buff *, skb, __be16, vlan_proto,
|
||||
u16, vlan_tci)
|
||||
{
|
||||
@ -2744,6 +2762,8 @@ tc_cls_act_func_proto(enum bpf_func_id func_id)
|
||||
return &bpf_get_hash_recalc_proto;
|
||||
case BPF_FUNC_set_hash_invalid:
|
||||
return &bpf_set_hash_invalid_proto;
|
||||
case BPF_FUNC_set_hash:
|
||||
return &bpf_set_hash_proto;
|
||||
case BPF_FUNC_perf_event_output:
|
||||
return &bpf_skb_event_output_proto;
|
||||
case BPF_FUNC_get_smp_processor_id:
|
||||
@ -2774,12 +2794,6 @@ xdp_func_proto(enum bpf_func_id func_id)
|
||||
}
|
||||
}
|
||||
|
||||
static const struct bpf_func_proto *
|
||||
cg_skb_func_proto(enum bpf_func_id func_id)
|
||||
{
|
||||
return sk_filter_func_proto(func_id);
|
||||
}
|
||||
|
||||
static const struct bpf_func_proto *
|
||||
lwt_inout_func_proto(enum bpf_func_id func_id)
|
||||
{
|
||||
@ -3344,7 +3358,7 @@ const struct bpf_verifier_ops xdp_prog_ops = {
|
||||
};
|
||||
|
||||
const struct bpf_verifier_ops cg_skb_prog_ops = {
|
||||
.get_func_proto = cg_skb_func_proto,
|
||||
.get_func_proto = sk_filter_func_proto,
|
||||
.is_valid_access = sk_filter_is_valid_access,
|
||||
.convert_ctx_access = bpf_convert_ctx_access,
|
||||
.test_run = bpf_prog_test_run_skb,
|
||||
|
@ -513,6 +513,11 @@ union bpf_attr {
|
||||
* Get the owner uid of the socket stored inside sk_buff.
|
||||
* @skb: pointer to skb
|
||||
* Return: uid of the socket owner on success or overflowuid if failed.
|
||||
*
|
||||
* u32 bpf_set_hash(skb, hash)
|
||||
* Set full skb->hash.
|
||||
* @skb: pointer to skb
|
||||
* @hash: hash to set
|
||||
*/
|
||||
#define __BPF_FUNC_MAPPER(FN) \
|
||||
FN(unspec), \
|
||||
@ -562,7 +567,8 @@ union bpf_attr {
|
||||
FN(xdp_adjust_head), \
|
||||
FN(probe_read_str), \
|
||||
FN(get_socket_cookie), \
|
||||
FN(get_socket_uid),
|
||||
FN(get_socket_uid), \
|
||||
FN(set_hash),
|
||||
|
||||
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
|
||||
* function eBPF program intends to call
|
||||
|
@ -9,6 +9,8 @@
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <sys/resource.h>
|
||||
|
||||
#include <linux/unistd.h>
|
||||
#include <linux/filter.h>
|
||||
#include <linux/bpf_perf_event.h>
|
||||
@ -432,6 +434,9 @@ static int do_test(unsigned int from, unsigned int to)
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
unsigned int from = 0, to = ARRAY_SIZE(tests);
|
||||
struct rlimit rinf = { RLIM_INFINITY, RLIM_INFINITY };
|
||||
|
||||
setrlimit(RLIMIT_MEMLOCK, &rinf);
|
||||
|
||||
if (argc == 3) {
|
||||
unsigned int l = atoi(argv[argc - 2]);
|
||||
|
@ -239,6 +239,54 @@ static void test_hashmap_percpu(int task, void *data)
|
||||
close(fd);
|
||||
}
|
||||
|
||||
static void test_hashmap_walk(int task, void *data)
|
||||
{
|
||||
int fd, i, max_entries = 100000;
|
||||
long long key, value, next_key;
|
||||
bool next_key_valid = true;
|
||||
|
||||
fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
|
||||
max_entries, map_flags);
|
||||
if (fd < 0) {
|
||||
printf("Failed to create hashmap '%s'!\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (i = 0; i < max_entries; i++) {
|
||||
key = i; value = key;
|
||||
assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == 0);
|
||||
}
|
||||
|
||||
for (i = 0; bpf_map_get_next_key(fd, !i ? NULL : &key,
|
||||
&next_key) == 0; i++) {
|
||||
key = next_key;
|
||||
assert(bpf_map_lookup_elem(fd, &key, &value) == 0);
|
||||
}
|
||||
|
||||
assert(i == max_entries);
|
||||
|
||||
assert(bpf_map_get_next_key(fd, NULL, &key) == 0);
|
||||
for (i = 0; next_key_valid; i++) {
|
||||
next_key_valid = bpf_map_get_next_key(fd, &key, &next_key) == 0;
|
||||
assert(bpf_map_lookup_elem(fd, &key, &value) == 0);
|
||||
value++;
|
||||
assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == 0);
|
||||
key = next_key;
|
||||
}
|
||||
|
||||
assert(i == max_entries);
|
||||
|
||||
for (i = 0; bpf_map_get_next_key(fd, !i ? NULL : &key,
|
||||
&next_key) == 0; i++) {
|
||||
key = next_key;
|
||||
assert(bpf_map_lookup_elem(fd, &key, &value) == 0);
|
||||
assert(value - 1 == key);
|
||||
}
|
||||
|
||||
assert(i == max_entries);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
static void test_arraymap(int task, void *data)
|
||||
{
|
||||
int key, next_key, fd;
|
||||
@ -464,6 +512,7 @@ static void test_map_stress(void)
|
||||
run_parallel(100, test_hashmap, NULL);
|
||||
run_parallel(100, test_hashmap_percpu, NULL);
|
||||
run_parallel(100, test_hashmap_sizes, NULL);
|
||||
run_parallel(100, test_hashmap_walk, NULL);
|
||||
|
||||
run_parallel(100, test_arraymap, NULL);
|
||||
run_parallel(100, test_arraymap_percpu, NULL);
|
||||
@ -549,6 +598,7 @@ static void run_all_tests(void)
|
||||
{
|
||||
test_hashmap(0, NULL);
|
||||
test_hashmap_percpu(0, NULL);
|
||||
test_hashmap_walk(0, NULL);
|
||||
|
||||
test_arraymap(0, NULL);
|
||||
test_arraymap_percpu(0, NULL);
|
||||
|
Loading…
Reference in New Issue
Block a user