Skip to content

Commit

Permalink
Merge branch 'bpf_iter-BTF_ID-at-build-time'
Browse files Browse the repository at this point in the history
Yonghong Song says:

====================
Commit 5a2798a
("bpf: Add BTF_ID_LIST/BTF_ID/BTF_ID_UNUSED macros")
implemented a mechanism to compute btf_ids at kernel build
time which can simplify kernel implementation and reduce
runtime overhead by removing in-kernel btf_id calculation.

This patch set tried to use this mechanism to compute
btf_ids for bpf_skc_to_*() helpers and for btf_id_or_null ctx
arguments specified during bpf iterator registration.
Please see individual patch for details.

Changelogs:
  v1 -> v2:
    - v1 ([1]) is only for bpf_skc_to_*() helpers. This version
      expanded it to cover ctx btf_id_or_null arguments
    - abandoned the change of "extern u32 name[]" to
      "static u32 name[]" for BPF_ID_LIST local "name" definition.
      gcc 9 incurred a compilation error.

 [1]: https://lore.kernel.org/bpf/20200717184706.3476992-1-yhs@fb.com/T
====================

Signed-off-by: Alexei Starovoitov <ast@kernel.org>
  • Loading branch information
Alexei Starovoitov committed Jul 21, 2020
2 parents e4d9c23 + 951cf36 commit 8fca4f9
Show file tree
Hide file tree
Showing 12 changed files with 153 additions and 73 deletions.
5 changes: 1 addition & 4 deletions include/linux/bpf.h
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,7 @@ struct bpf_jit_poke_descriptor {
struct bpf_ctx_arg_aux {
u32 offset;
enum bpf_reg_type reg_type;
u32 btf_id;
};

struct bpf_prog_aux {
Expand Down Expand Up @@ -1541,7 +1542,6 @@ static inline bool bpf_map_is_dev_bound(struct bpf_map *map)

struct bpf_map *bpf_map_offload_map_alloc(union bpf_attr *attr);
void bpf_map_offload_map_free(struct bpf_map *map);
void init_btf_sock_ids(struct btf *btf);
#else
static inline int bpf_prog_offload_init(struct bpf_prog *prog,
union bpf_attr *attr)
Expand All @@ -1567,9 +1567,6 @@ static inline struct bpf_map *bpf_map_offload_map_alloc(union bpf_attr *attr)
static inline void bpf_map_offload_map_free(struct bpf_map *map)
{
}
static inline void init_btf_sock_ids(struct btf *btf)
{
}
#endif /* CONFIG_NET && CONFIG_BPF_SYSCALL */

#if defined(CONFIG_BPF_STREAM_PARSER)
Expand Down
40 changes: 37 additions & 3 deletions include/linux/btf_ids.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,20 @@ asm( \
* .zero 4
*
*/
#define __BTF_ID_LIST(name) \
#define __BTF_ID_LIST(name, scope) \
asm( \
".pushsection " BTF_IDS_SECTION ",\"a\"; \n" \
".local " #name "; \n" \
"." #scope " " #name "; \n" \
#name ":; \n" \
".popsection; \n"); \

#define BTF_ID_LIST(name) \
__BTF_ID_LIST(name) \
__BTF_ID_LIST(name, local) \
extern u32 name[];

#define BTF_ID_LIST_GLOBAL(name) \
__BTF_ID_LIST(name, globl)

/*
* The BTF_ID_UNUSED macro defines 4 zero bytes.
* It's used when we want to define 'unused' entry
Expand All @@ -90,7 +93,38 @@ asm( \
#define BTF_ID_LIST(name) static u32 name[5];
#define BTF_ID(prefix, name)
#define BTF_ID_UNUSED
#define BTF_ID_LIST_GLOBAL(name) u32 name[1];

#endif /* CONFIG_DEBUG_INFO_BTF */

#ifdef CONFIG_NET
/* Define a list of socket types which can be the argument for
* skc_to_*_sock() helpers. All these sockets should have
* sock_common as the first argument in its memory layout.
*/
#define BTF_SOCK_TYPE_xxx \
BTF_SOCK_TYPE(BTF_SOCK_TYPE_INET, inet_sock) \
BTF_SOCK_TYPE(BTF_SOCK_TYPE_INET_CONN, inet_connection_sock) \
BTF_SOCK_TYPE(BTF_SOCK_TYPE_INET_REQ, inet_request_sock) \
BTF_SOCK_TYPE(BTF_SOCK_TYPE_INET_TW, inet_timewait_sock) \
BTF_SOCK_TYPE(BTF_SOCK_TYPE_REQ, request_sock) \
BTF_SOCK_TYPE(BTF_SOCK_TYPE_SOCK, sock) \
BTF_SOCK_TYPE(BTF_SOCK_TYPE_SOCK_COMMON, sock_common) \
BTF_SOCK_TYPE(BTF_SOCK_TYPE_TCP, tcp_sock) \
BTF_SOCK_TYPE(BTF_SOCK_TYPE_TCP_REQ, tcp_request_sock) \
BTF_SOCK_TYPE(BTF_SOCK_TYPE_TCP_TW, tcp_timewait_sock) \
BTF_SOCK_TYPE(BTF_SOCK_TYPE_TCP6, tcp6_sock) \
BTF_SOCK_TYPE(BTF_SOCK_TYPE_UDP, udp_sock) \
BTF_SOCK_TYPE(BTF_SOCK_TYPE_UDP6, udp6_sock)

enum {
#define BTF_SOCK_TYPE(name, str) name,
BTF_SOCK_TYPE_xxx
#undef BTF_SOCK_TYPE
MAX_BTF_SOCK_TYPE,
};

extern u32 btf_sock_ids[];
#endif

#endif
6 changes: 3 additions & 3 deletions kernel/bpf/btf.c
Original file line number Diff line number Diff line change
Expand Up @@ -3672,7 +3672,6 @@ struct btf *btf_parse_vmlinux(void)
goto errout;

bpf_struct_ops_init(btf, log);
init_btf_sock_ids(btf);

btf_verifier_env_free(env);
refcount_set(&btf->refcnt, 1);
Expand Down Expand Up @@ -3818,16 +3817,17 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type,
return true;

/* this is a pointer to another type */
info->reg_type = PTR_TO_BTF_ID;
for (i = 0; i < prog->aux->ctx_arg_info_size; i++) {
const struct bpf_ctx_arg_aux *ctx_arg_info = &prog->aux->ctx_arg_info[i];

if (ctx_arg_info->offset == off) {
info->reg_type = ctx_arg_info->reg_type;
break;
info->btf_id = ctx_arg_info->btf_id;
return true;
}
}

info->reg_type = PTR_TO_BTF_ID;
if (tgt_prog) {
ret = btf_translate_to_vmlinux(log, btf, t, tgt_prog->type, arg);
if (ret > 0) {
Expand Down
7 changes: 6 additions & 1 deletion kernel/bpf/map_iter.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <linux/fs.h>
#include <linux/filter.h>
#include <linux/kernel.h>
#include <linux/btf_ids.h>

struct bpf_iter_seq_map_info {
u32 mid;
Expand Down Expand Up @@ -81,7 +82,10 @@ static const struct seq_operations bpf_map_seq_ops = {
.show = bpf_map_seq_show,
};

static const struct bpf_iter_reg bpf_map_reg_info = {
BTF_ID_LIST(btf_bpf_map_id)
BTF_ID(struct, bpf_map)

static struct bpf_iter_reg bpf_map_reg_info = {
.target = "bpf_map",
.seq_ops = &bpf_map_seq_ops,
.init_seq_private = NULL,
Expand All @@ -96,6 +100,7 @@ static const struct bpf_iter_reg bpf_map_reg_info = {

static int __init bpf_map_iter_init(void)
{
bpf_map_reg_info.ctx_arg_info[0].btf_id = *btf_bpf_map_id;
return bpf_iter_reg_target(&bpf_map_reg_info);
}

Expand Down
12 changes: 10 additions & 2 deletions kernel/bpf/task_iter.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <linux/fs.h>
#include <linux/fdtable.h>
#include <linux/filter.h>
#include <linux/btf_ids.h>

struct bpf_iter_seq_task_common {
struct pid_namespace *ns;
Expand Down Expand Up @@ -312,7 +313,11 @@ static const struct seq_operations task_file_seq_ops = {
.show = task_file_seq_show,
};

static const struct bpf_iter_reg task_reg_info = {
BTF_ID_LIST(btf_task_file_ids)
BTF_ID(struct, task_struct)
BTF_ID(struct, file)

static struct bpf_iter_reg task_reg_info = {
.target = "task",
.seq_ops = &task_seq_ops,
.init_seq_private = init_seq_pidns,
Expand All @@ -325,7 +330,7 @@ static const struct bpf_iter_reg task_reg_info = {
},
};

static const struct bpf_iter_reg task_file_reg_info = {
static struct bpf_iter_reg task_file_reg_info = {
.target = "task_file",
.seq_ops = &task_file_seq_ops,
.init_seq_private = init_seq_pidns,
Expand All @@ -344,10 +349,13 @@ static int __init task_iter_init(void)
{
int ret;

task_reg_info.ctx_arg_info[0].btf_id = btf_task_file_ids[0];
ret = bpf_iter_reg_target(&task_reg_info);
if (ret)
return ret;

task_file_reg_info.ctx_arg_info[0].btf_id = btf_task_file_ids[0];
task_file_reg_info.ctx_arg_info[1].btf_id = btf_task_file_ids[1];
return bpf_iter_reg_target(&task_file_reg_info);
}
late_initcall(task_iter_init);
49 changes: 5 additions & 44 deletions net/core/filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -9421,52 +9421,13 @@ void bpf_prog_change_xdp(struct bpf_prog *prev_prog, struct bpf_prog *prog)
bpf_dispatcher_change_prog(BPF_DISPATCHER_PTR(xdp), prev_prog, prog);
}

/* Define a list of socket types which can be the argument for
* skc_to_*_sock() helpers. All these sockets should have
* sock_common as the first argument in its memory layout.
*/
#define BTF_SOCK_TYPE_xxx \
BTF_SOCK_TYPE(BTF_SOCK_TYPE_INET, "inet_sock") \
BTF_SOCK_TYPE(BTF_SOCK_TYPE_INET_CONN, "inet_connection_sock") \
BTF_SOCK_TYPE(BTF_SOCK_TYPE_INET_REQ, "inet_request_sock") \
BTF_SOCK_TYPE(BTF_SOCK_TYPE_INET_TW, "inet_timewait_sock") \
BTF_SOCK_TYPE(BTF_SOCK_TYPE_REQ, "request_sock") \
BTF_SOCK_TYPE(BTF_SOCK_TYPE_SOCK, "sock") \
BTF_SOCK_TYPE(BTF_SOCK_TYPE_SOCK_COMMON, "sock_common") \
BTF_SOCK_TYPE(BTF_SOCK_TYPE_TCP, "tcp_sock") \
BTF_SOCK_TYPE(BTF_SOCK_TYPE_TCP_REQ, "tcp_request_sock") \
BTF_SOCK_TYPE(BTF_SOCK_TYPE_TCP_TW, "tcp_timewait_sock") \
BTF_SOCK_TYPE(BTF_SOCK_TYPE_TCP6, "tcp6_sock") \
BTF_SOCK_TYPE(BTF_SOCK_TYPE_UDP, "udp_sock") \
BTF_SOCK_TYPE(BTF_SOCK_TYPE_UDP6, "udp6_sock")

enum {
#define BTF_SOCK_TYPE(name, str) name,
#ifdef CONFIG_DEBUG_INFO_BTF
BTF_ID_LIST_GLOBAL(btf_sock_ids)
#define BTF_SOCK_TYPE(name, type) BTF_ID(struct, type)
BTF_SOCK_TYPE_xxx
#undef BTF_SOCK_TYPE
MAX_BTF_SOCK_TYPE,
};

static int btf_sock_ids[MAX_BTF_SOCK_TYPE];

#ifdef CONFIG_BPF_SYSCALL
static const char *bpf_sock_types[] = {
#define BTF_SOCK_TYPE(name, str) str,
BTF_SOCK_TYPE_xxx
#undef BTF_SOCK_TYPE
};

void init_btf_sock_ids(struct btf *btf)
{
int i, btf_id;

for (i = 0; i < MAX_BTF_SOCK_TYPE; i++) {
btf_id = btf_find_by_name_kind(btf, bpf_sock_types[i],
BTF_KIND_STRUCT);
if (btf_id > 0)
btf_sock_ids[i] = btf_id;
}
}
#else
u32 btf_sock_ids[MAX_BTF_SOCK_TYPE];
#endif

static bool check_arg_btf_id(u32 btf_id, u32 arg)
Expand Down
4 changes: 3 additions & 1 deletion net/ipv4/tcp_ipv4.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/inetdevice.h>
#include <linux/btf_ids.h>

#include <crypto/hash.h>
#include <linux/scatterlist.h>
Expand Down Expand Up @@ -2954,7 +2955,7 @@ static void bpf_iter_fini_tcp(void *priv_data)
bpf_iter_fini_seq_net(priv_data);
}

static const struct bpf_iter_reg tcp_reg_info = {
static struct bpf_iter_reg tcp_reg_info = {
.target = "tcp",
.seq_ops = &bpf_iter_tcp_seq_ops,
.init_seq_private = bpf_iter_init_tcp,
Expand All @@ -2969,6 +2970,7 @@ static const struct bpf_iter_reg tcp_reg_info = {

static void __init bpf_iter_register(void)
{
tcp_reg_info.ctx_arg_info[0].btf_id = btf_sock_ids[BTF_SOCK_TYPE_SOCK_COMMON];
if (bpf_iter_reg_target(&tcp_reg_info))
pr_warn("Warning: could not register bpf iterator tcp\n");
}
Expand Down
4 changes: 3 additions & 1 deletion net/ipv4/udp.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@
#include <net/xfrm.h>
#include <trace/events/udp.h>
#include <linux/static_key.h>
#include <linux/btf_ids.h>
#include <trace/events/skb.h>
#include <net/busy_poll.h>
#include "udp_impl.h"
Expand Down Expand Up @@ -3232,7 +3233,7 @@ static void bpf_iter_fini_udp(void *priv_data)
bpf_iter_fini_seq_net(priv_data);
}

static const struct bpf_iter_reg udp_reg_info = {
static struct bpf_iter_reg udp_reg_info = {
.target = "udp",
.seq_ops = &bpf_iter_udp_seq_ops,
.init_seq_private = bpf_iter_init_udp,
Expand All @@ -3247,6 +3248,7 @@ static const struct bpf_iter_reg udp_reg_info = {

static void __init bpf_iter_register(void)
{
udp_reg_info.ctx_arg_info[0].btf_id = btf_sock_ids[BTF_SOCK_TYPE_UDP];
if (bpf_iter_reg_target(&udp_reg_info))
pr_warn("Warning: could not register bpf iterator udp\n");
}
Expand Down
7 changes: 6 additions & 1 deletion net/ipv6/route.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
#include <net/l3mdev.h>
#include <net/ip.h>
#include <linux/uaccess.h>
#include <linux/btf_ids.h>

#ifdef CONFIG_SYSCTL
#include <linux/sysctl.h>
Expand Down Expand Up @@ -6423,7 +6424,10 @@ void __init ip6_route_init_special_entries(void)
#if defined(CONFIG_BPF_SYSCALL) && defined(CONFIG_PROC_FS)
DEFINE_BPF_ITER_FUNC(ipv6_route, struct bpf_iter_meta *meta, struct fib6_info *rt)

static const struct bpf_iter_reg ipv6_route_reg_info = {
BTF_ID_LIST(btf_fib6_info_id)
BTF_ID(struct, fib6_info)

static struct bpf_iter_reg ipv6_route_reg_info = {
.target = "ipv6_route",
.seq_ops = &ipv6_route_seq_ops,
.init_seq_private = bpf_iter_init_seq_net,
Expand All @@ -6438,6 +6442,7 @@ static const struct bpf_iter_reg ipv6_route_reg_info = {

static int __init bpf_iter_register(void)
{
ipv6_route_reg_info.ctx_arg_info[0].btf_id = *btf_fib6_info_id;
return bpf_iter_reg_target(&ipv6_route_reg_info);
}

Expand Down
7 changes: 6 additions & 1 deletion net/netlink/af_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
#include <linux/genetlink.h>
#include <linux/net_namespace.h>
#include <linux/nospec.h>
#include <linux/btf_ids.h>

#include <net/net_namespace.h>
#include <net/netns/generic.h>
Expand Down Expand Up @@ -2803,7 +2804,10 @@ static const struct rhashtable_params netlink_rhashtable_params = {
};

#if defined(CONFIG_BPF_SYSCALL) && defined(CONFIG_PROC_FS)
static const struct bpf_iter_reg netlink_reg_info = {
BTF_ID_LIST(btf_netlink_sock_id)
BTF_ID(struct, netlink_sock)

static struct bpf_iter_reg netlink_reg_info = {
.target = "netlink",
.seq_ops = &netlink_seq_ops,
.init_seq_private = bpf_iter_init_seq_net,
Expand All @@ -2818,6 +2822,7 @@ static const struct bpf_iter_reg netlink_reg_info = {

static int __init bpf_iter_register(void)
{
netlink_reg_info.ctx_arg_info[0].btf_id = *btf_netlink_sock_id;
return bpf_iter_reg_target(&netlink_reg_info);
}
#endif
Expand Down
Loading

0 comments on commit 8fca4f9

Please sign in to comment.