Skip to content

Commit

Permalink
Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf
Browse files Browse the repository at this point in the history
Alexei Starovoitov says:

====================
pull-request: bpf 2020-09-15

The following pull-request contains BPF updates for your *net* tree.

We've added 12 non-merge commits during the last 19 day(s) which contain
a total of 10 files changed, 47 insertions(+), 38 deletions(-).

The main changes are:

1) docs/bpf fixes, from Andrii.

2) ld_abs fix, from Daniel.

3) socket casting helpers fix, from Martin.

4) hash iterator fixes, from Yonghong.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Sep 16, 2020
2 parents 2fbc6e8 + ce880cb commit d5d325e
Show file tree
Hide file tree
Showing 10 changed files with 47 additions and 38 deletions.
5 changes: 1 addition & 4 deletions Documentation/bpf/ringbuf.rst
Original file line number Diff line number Diff line change
Expand Up @@ -182,9 +182,6 @@ in the order of reservations, but only after all previous records where
already committed. It is thus possible for slow producers to temporarily hold
off submitted records, that were reserved later.

Reservation/commit/consumer protocol is verified by litmus tests in
Documentation/litmus_tests/bpf-rb/_.

One interesting implementation bit, that significantly simplifies (and thus
speeds up as well) implementation of both producers and consumers is how data
area is mapped twice contiguously back-to-back in the virtual memory. This
Expand All @@ -200,7 +197,7 @@ a self-pacing notifications of new data being availability.
being available after commit only if consumer has already caught up right up to
the record being committed. If not, consumer still has to catch up and thus
will see new data anyways without needing an extra poll notification.
Benchmarks (see tools/testing/selftests/bpf/benchs/bench_ringbuf.c_) show that
Benchmarks (see tools/testing/selftests/bpf/benchs/bench_ringbufs.c) show that
this allows to achieve a very high throughput without having to resort to
tricks like "notify only every Nth sample", which are necessary with perf
buffer. For extreme cases, when BPF program wants more manual control of
Expand Down
15 changes: 4 additions & 11 deletions kernel/bpf/hashtab.c
Original file line number Diff line number Diff line change
Expand Up @@ -1622,7 +1622,6 @@ struct bpf_iter_seq_hash_map_info {
struct bpf_map *map;
struct bpf_htab *htab;
void *percpu_value_buf; // non-zero means percpu hash
unsigned long flags;
u32 bucket_id;
u32 skip_elems;
};
Expand All @@ -1632,7 +1631,6 @@ bpf_hash_map_seq_find_next(struct bpf_iter_seq_hash_map_info *info,
struct htab_elem *prev_elem)
{
const struct bpf_htab *htab = info->htab;
unsigned long flags = info->flags;
u32 skip_elems = info->skip_elems;
u32 bucket_id = info->bucket_id;
struct hlist_nulls_head *head;
Expand All @@ -1656,27 +1654,26 @@ bpf_hash_map_seq_find_next(struct bpf_iter_seq_hash_map_info *info,

/* not found, unlock and go to the next bucket */
b = &htab->buckets[bucket_id++];
htab_unlock_bucket(htab, b, flags);
rcu_read_unlock();
skip_elems = 0;
}

for (i = bucket_id; i < htab->n_buckets; i++) {
b = &htab->buckets[i];
flags = htab_lock_bucket(htab, b);
rcu_read_lock();

count = 0;
head = &b->head;
hlist_nulls_for_each_entry_rcu(elem, n, head, hash_node) {
if (count >= skip_elems) {
info->flags = flags;
info->bucket_id = i;
info->skip_elems = count;
return elem;
}
count++;
}

htab_unlock_bucket(htab, b, flags);
rcu_read_unlock();
skip_elems = 0;
}

Expand Down Expand Up @@ -1754,14 +1751,10 @@ static int bpf_hash_map_seq_show(struct seq_file *seq, void *v)

static void bpf_hash_map_seq_stop(struct seq_file *seq, void *v)
{
struct bpf_iter_seq_hash_map_info *info = seq->private;

if (!v)
(void)__bpf_hash_map_seq_show(seq, NULL);
else
htab_unlock_bucket(info->htab,
&info->htab->buckets[info->bucket_id],
info->flags);
rcu_read_unlock();
}

static int bpf_iter_init_hash_map(void *priv_data,
Expand Down
4 changes: 3 additions & 1 deletion kernel/bpf/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -226,10 +226,12 @@ static void *map_seq_next(struct seq_file *m, void *v, loff_t *pos)
else
prev_key = key;

rcu_read_lock();
if (map->ops->map_get_next_key(map, prev_key, key)) {
map_iter(m)->done = true;
return NULL;
key = NULL;
}
rcu_read_unlock();
return key;
}

Expand Down
18 changes: 9 additions & 9 deletions net/core/filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -7066,15 +7066,15 @@ static int bpf_gen_ld_abs(const struct bpf_insn *orig,
bool indirect = BPF_MODE(orig->code) == BPF_IND;
struct bpf_insn *insn = insn_buf;

/* We're guaranteed here that CTX is in R6. */
*insn++ = BPF_MOV64_REG(BPF_REG_1, BPF_REG_CTX);
if (!indirect) {
*insn++ = BPF_MOV64_IMM(BPF_REG_2, orig->imm);
} else {
*insn++ = BPF_MOV64_REG(BPF_REG_2, orig->src_reg);
if (orig->imm)
*insn++ = BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, orig->imm);
}
/* We're guaranteed here that CTX is in R6. */
*insn++ = BPF_MOV64_REG(BPF_REG_1, BPF_REG_CTX);

switch (BPF_SIZE(orig->code)) {
case BPF_B:
Expand Down Expand Up @@ -9523,7 +9523,7 @@ BPF_CALL_1(bpf_skc_to_tcp6_sock, struct sock *, sk)
* trigger an explicit type generation here.
*/
BTF_TYPE_EMIT(struct tcp6_sock);
if (sk_fullsock(sk) && sk->sk_protocol == IPPROTO_TCP &&
if (sk && sk_fullsock(sk) && sk->sk_protocol == IPPROTO_TCP &&
sk->sk_family == AF_INET6)
return (unsigned long)sk;

Expand All @@ -9541,7 +9541,7 @@ const struct bpf_func_proto bpf_skc_to_tcp6_sock_proto = {

BPF_CALL_1(bpf_skc_to_tcp_sock, struct sock *, sk)
{
if (sk_fullsock(sk) && sk->sk_protocol == IPPROTO_TCP)
if (sk && sk_fullsock(sk) && sk->sk_protocol == IPPROTO_TCP)
return (unsigned long)sk;

return (unsigned long)NULL;
Expand All @@ -9559,12 +9559,12 @@ const struct bpf_func_proto bpf_skc_to_tcp_sock_proto = {
BPF_CALL_1(bpf_skc_to_tcp_timewait_sock, struct sock *, sk)
{
#ifdef CONFIG_INET
if (sk->sk_prot == &tcp_prot && sk->sk_state == TCP_TIME_WAIT)
if (sk && sk->sk_prot == &tcp_prot && sk->sk_state == TCP_TIME_WAIT)
return (unsigned long)sk;
#endif

#if IS_BUILTIN(CONFIG_IPV6)
if (sk->sk_prot == &tcpv6_prot && sk->sk_state == TCP_TIME_WAIT)
if (sk && sk->sk_prot == &tcpv6_prot && sk->sk_state == TCP_TIME_WAIT)
return (unsigned long)sk;
#endif

Expand All @@ -9583,12 +9583,12 @@ const struct bpf_func_proto bpf_skc_to_tcp_timewait_sock_proto = {
BPF_CALL_1(bpf_skc_to_tcp_request_sock, struct sock *, sk)
{
#ifdef CONFIG_INET
if (sk->sk_prot == &tcp_prot && sk->sk_state == TCP_NEW_SYN_RECV)
if (sk && sk->sk_prot == &tcp_prot && sk->sk_state == TCP_NEW_SYN_RECV)
return (unsigned long)sk;
#endif

#if IS_BUILTIN(CONFIG_IPV6)
if (sk->sk_prot == &tcpv6_prot && sk->sk_state == TCP_NEW_SYN_RECV)
if (sk && sk->sk_prot == &tcpv6_prot && sk->sk_state == TCP_NEW_SYN_RECV)
return (unsigned long)sk;
#endif

Expand All @@ -9610,7 +9610,7 @@ BPF_CALL_1(bpf_skc_to_udp6_sock, struct sock *, sk)
* trigger an explicit type generation here.
*/
BTF_TYPE_EMIT(struct udp6_sock);
if (sk_fullsock(sk) && sk->sk_protocol == IPPROTO_UDP &&
if (sk && sk_fullsock(sk) && sk->sk_protocol == IPPROTO_UDP &&
sk->sk_type == SOCK_DGRAM && sk->sk_family == AF_INET6)
return (unsigned long)sk;

Expand Down
17 changes: 8 additions & 9 deletions net/xdp/xdp_umem.c
Original file line number Diff line number Diff line change
Expand Up @@ -303,10 +303,10 @@ static int xdp_umem_account_pages(struct xdp_umem *umem)

static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr)
{
u32 npgs_rem, chunk_size = mr->chunk_size, headroom = mr->headroom;
bool unaligned_chunks = mr->flags & XDP_UMEM_UNALIGNED_CHUNK_FLAG;
u32 chunk_size = mr->chunk_size, headroom = mr->headroom;
u64 npgs, addr = mr->addr, size = mr->len;
unsigned int chunks, chunks_per_page;
unsigned int chunks, chunks_rem;
int err;

if (chunk_size < XDP_UMEM_MIN_CHUNK_SIZE || chunk_size > PAGE_SIZE) {
Expand Down Expand Up @@ -336,19 +336,18 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr)
if ((addr + size) < addr)
return -EINVAL;

npgs = size >> PAGE_SHIFT;
npgs = div_u64_rem(size, PAGE_SIZE, &npgs_rem);
if (npgs_rem)
npgs++;
if (npgs > U32_MAX)
return -EINVAL;

chunks = (unsigned int)div_u64(size, chunk_size);
chunks = (unsigned int)div_u64_rem(size, chunk_size, &chunks_rem);
if (chunks == 0)
return -EINVAL;

if (!unaligned_chunks) {
chunks_per_page = PAGE_SIZE / chunk_size;
if (chunks < chunks_per_page || chunks % chunks_per_page)
return -EINVAL;
}
if (!unaligned_chunks && chunks_rem)
return -EINVAL;

if (headroom >= chunk_size - XDP_PACKET_HEADROOM)
return -EINVAL;
Expand Down
4 changes: 2 additions & 2 deletions tools/bpf/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ FEATURE_TESTS = libbfd disassembler-four-args
FEATURE_DISPLAY = libbfd disassembler-four-args

check_feat := 1
NON_CHECK_FEAT_TARGETS := clean bpftool_clean runqslower_clean
NON_CHECK_FEAT_TARGETS := clean bpftool_clean runqslower_clean resolve_btfids_clean
ifdef MAKECMDGOALS
ifeq ($(filter-out $(NON_CHECK_FEAT_TARGETS),$(MAKECMDGOALS)),)
check_feat := 0
Expand Down Expand Up @@ -89,7 +89,7 @@ $(OUTPUT)bpf_exp.lex.c: $(OUTPUT)bpf_exp.yacc.c
$(OUTPUT)bpf_exp.yacc.o: $(OUTPUT)bpf_exp.yacc.c
$(OUTPUT)bpf_exp.lex.o: $(OUTPUT)bpf_exp.lex.c

clean: bpftool_clean runqslower_clean
clean: bpftool_clean runqslower_clean resolve_btfids_clean
$(call QUIET_CLEAN, bpf-progs)
$(Q)$(RM) -r -- $(OUTPUT)*.o $(OUTPUT)bpf_jit_disasm $(OUTPUT)bpf_dbg \
$(OUTPUT)bpf_asm $(OUTPUT)bpf_exp.yacc.* $(OUTPUT)bpf_exp.lex.*
Expand Down
1 change: 1 addition & 0 deletions tools/bpf/resolve_btfids/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ libbpf-clean:
clean: libsubcmd-clean libbpf-clean fixdep-clean
$(call msg,CLEAN,$(BINARY))
$(Q)$(RM) -f $(BINARY); \
$(RM) -rf $(if $(OUTPUT),$(OUTPUT),.)/feature; \
find $(if $(OUTPUT),$(OUTPUT),.) -name \*.o -or -name \*.o.cmd -or -name \*.o.d | xargs $(RM)

tags:
Expand Down
4 changes: 3 additions & 1 deletion tools/lib/bpf/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ FEATURE_USER = .libbpf
FEATURE_TESTS = libelf libelf-mmap zlib bpf reallocarray
FEATURE_DISPLAY = libelf zlib bpf

INCLUDES = -I. -I$(srctree)/tools/include -I$(srctree)/tools/arch/$(ARCH)/include/uapi -I$(srctree)/tools/include/uapi
INCLUDES = -I. -I$(srctree)/tools/include -I$(srctree)/tools/include/uapi
FEATURE_CHECK_CFLAGS-bpf = $(INCLUDES)

check_feat := 1
Expand Down Expand Up @@ -152,6 +152,7 @@ GLOBAL_SYM_COUNT = $(shell readelf -s --wide $(BPF_IN_SHARED) | \
awk '/GLOBAL/ && /DEFAULT/ && !/UND/ {print $$NF}' | \
sort -u | wc -l)
VERSIONED_SYM_COUNT = $(shell readelf --dyn-syms --wide $(OUTPUT)libbpf.so | \
awk '/GLOBAL/ && /DEFAULT/ && !/UND/ {print $$NF}' | \
grep -Eo '[^ ]+@LIBBPF_' | cut -d@ -f1 | sort -u | wc -l)

CMD_TARGETS = $(LIB_TARGET) $(PC_FILE)
Expand Down Expand Up @@ -219,6 +220,7 @@ check_abi: $(OUTPUT)libbpf.so
awk '/GLOBAL/ && /DEFAULT/ && !/UND/ {print $$NF}'| \
sort -u > $(OUTPUT)libbpf_global_syms.tmp; \
readelf --dyn-syms --wide $(OUTPUT)libbpf.so | \
awk '/GLOBAL/ && /DEFAULT/ && !/UND/ {print $$NF}'| \
grep -Eo '[^ ]+@LIBBPF_' | cut -d@ -f1 | \
sort -u > $(OUTPUT)libbpf_versioned_syms.tmp; \
diff -u $(OUTPUT)libbpf_global_syms.tmp \
Expand Down
2 changes: 1 addition & 1 deletion tools/lib/bpf/libbpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -5203,8 +5203,8 @@ static int bpf_object__collect_map_relos(struct bpf_object *obj,
int i, j, nrels, new_sz;
const struct btf_var_secinfo *vi = NULL;
const struct btf_type *sec, *var, *def;
struct bpf_map *map = NULL, *targ_map;
const struct btf_member *member;
struct bpf_map *map, *targ_map;
const char *name, *mname;
Elf_Data *symbols;
unsigned int moff;
Expand Down
15 changes: 15 additions & 0 deletions tools/testing/selftests/bpf/progs/bpf_iter_bpf_hash_map.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,10 @@ int dump_bpf_hash_map(struct bpf_iter__bpf_map_elem *ctx)
__u32 seq_num = ctx->meta->seq_num;
struct bpf_map *map = ctx->map;
struct key_t *key = ctx->key;
struct key_t tmp_key;
__u64 *val = ctx->value;
__u64 tmp_val = 0;
int ret;

if (in_test_mode) {
/* test mode is used by selftests to
Expand All @@ -61,6 +64,18 @@ int dump_bpf_hash_map(struct bpf_iter__bpf_map_elem *ctx)
if (key == (void *)0 || val == (void *)0)
return 0;

/* update the value and then delete the <key, value> pair.
* it should not impact the existing 'val' which is still
* accessible under rcu.
*/
__builtin_memcpy(&tmp_key, key, sizeof(struct key_t));
ret = bpf_map_update_elem(&hashmap1, &tmp_key, &tmp_val, 0);
if (ret)
return 0;
ret = bpf_map_delete_elem(&hashmap1, &tmp_key);
if (ret)
return 0;

key_sum_a += key->a;
key_sum_b += key->b;
key_sum_c += key->c;
Expand Down

0 comments on commit d5d325e

Please sign in to comment.