Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit af2d1134 authored by Jakub Kicinski's avatar Jakub Kicinski Committed by Harshit Jain
Browse files

BACKPORT: bpf: offload: add infrastructure for loading programs for a specific netdev



The fact that we don't know which device the program is going
to be used on is quite limiting in current eBPF infrastructure.
We have to reverse or limit the changes which kernel makes to
the loaded bytecode if we want it to be offloaded to a networking
device.  We also have to invent new APIs for debugging and
troubleshooting support.

Make it possible to load programs for a specific netdev.  This
helps us to bring the debug information closer to the core
eBPF infrastructure (e.g. we will be able to reuse the verifer
log in device JIT).  It allows device JITs to perform translation
on the original bytecode.

__bpf_prog_get() when called to get a reference for an attachment
point will now refuse to give it if program has a device assigned.
Following patches will add a version of that function which passes
the expected netdev in. @type argument in __bpf_prog_get() is
renamed to attach_type to make it clearer that it's only set on
attachment.

All calls to ndo_bpf are protected by rtnl, only verifier callbacks
are not.  We need a wait queue to make sure netdev doesn't get
destroyed while verifier is still running and calling its driver.

Change-Id: Iba7b96574abc005ad3351d6db2528eb534e47561
Signed-off-by: default avatarJakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: default avatarSimon Horman <simon.horman@netronome.com>
Reviewed-by: default avatarQuentin Monnet <quentin.monnet@netronome.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarCyber Knight <cyberknight755@gmail.com>
parent 1cd34878
Loading
Loading
Loading
Loading
+37 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
#include <linux/err.h>
#include <linux/rbtree_latch.h>
#include <linux/numa.h>
#include <linux/wait.h>

struct perf_event;
struct bpf_prog;
@@ -193,6 +194,16 @@ struct bpf_verifier_ops {
			union bpf_attr __user *uattr);
};

struct bpf_dev_offload {
	struct bpf_prog		*prog;
	struct net_device	*netdev;
	void			*dev_priv;
	struct list_head	offloads;
	bool			dev_state;
	bool			verifier_running;
	wait_queue_head_t	verifier_done;
};

struct bpf_prog_aux {
	atomic_t refcnt;
	u32 used_map_cnt;
@@ -210,6 +221,7 @@ struct bpf_prog_aux {
#endif
	u64 load_time; /* ns since boottime */
	char name[BPF_OBJ_NAME_LEN];
	struct bpf_dev_offload *offload;
	union {
		struct work_struct work;
		struct rcu_head	rcu;
@@ -328,6 +340,8 @@ extern const struct file_operations bpf_prog_fops;
#undef BPF_PROG_TYPE
#undef BPF_MAP_TYPE

extern const struct bpf_verifier_ops bpf_offload_prog_ops;

struct bpf_prog *bpf_prog_get(u32 ufd);
struct bpf_prog *bpf_prog_get_type(u32 ufd, enum bpf_prog_type type);
struct bpf_prog * __must_check bpf_prog_add(struct bpf_prog *prog, int i);
@@ -488,6 +502,29 @@ static inline bool unprivileged_ebpf_enabled(void)

#endif /* CONFIG_BPF_SYSCALL */

int bpf_prog_offload_compile(struct bpf_prog *prog);
void bpf_prog_offload_destroy(struct bpf_prog *prog);

#if defined(CONFIG_NET) && defined(CONFIG_BPF_SYSCALL)
int bpf_prog_offload_init(struct bpf_prog *prog, union bpf_attr *attr);

static inline bool bpf_prog_is_dev_bound(struct bpf_prog_aux *aux)
{
	return aux->offload;
}
#else
static inline int bpf_prog_offload_init(struct bpf_prog *prog,
					union bpf_attr *attr)
{
	return -EOPNOTSUPP;
}

static inline bool bpf_prog_is_dev_bound(struct bpf_prog_aux *aux)
{
	return false;
}
#endif /* CONFIG_NET && CONFIG_BPF_SYSCALL */

#if defined(CONFIG_STREAM_PARSER) && defined(CONFIG_BPF_SYSCALL)
struct sock  *__sock_map_lookup_elem(struct bpf_map *map, u32 key);
int sock_map_prog(struct bpf_map *map, struct bpf_prog *prog, u32 type);
+10 −0
Original line number Diff line number Diff line
@@ -181,6 +181,7 @@ struct bpf_verifier_env {
	struct bpf_verifier_state *cur_state; /* current verifier state */
	struct bpf_verifier_state_list **explored_states; /* search pruning optimization */
	const struct bpf_ext_analyzer_ops *analyzer_ops; /* external analyzer ops */
	const struct bpf_ext_analyzer_ops *dev_ops; /* device analyzer ops */
	void *analyzer_priv; /* pointer to external analyzer's private data */
	struct bpf_map *used_maps[MAX_USED_MAPS]; /* array of map's used by eBPF program */
	u32 used_map_cnt;		/* number of used maps */
@@ -195,6 +196,15 @@ static inline struct bpf_reg_state *cur_regs(struct bpf_verifier_env *env)
	return env->cur_state->regs;
}

#if defined(CONFIG_NET) && defined(CONFIG_BPF_SYSCALL)
int bpf_prog_offload_verifier_prep(struct bpf_verifier_env *env);
#else
int bpf_prog_offload_verifier_prep(struct bpf_verifier_env *env)
{
	return -EOPNOTSUPP;
}
#endif

int bpf_analyzer(struct bpf_prog *prog, const struct bpf_ext_analyzer_ops *ops,
		 void *priv);

+14 −0
Original line number Diff line number Diff line
@@ -809,8 +809,13 @@ enum bpf_netdev_command {
	 * is equivalent to XDP_ATTACHED_DRV.
	 */
	XDP_QUERY_PROG,
	/* BPF program for offload callbacks, invoked at program load time. */
	BPF_OFFLOAD_VERIFIER_PREP,
	BPF_OFFLOAD_TRANSLATE,
	BPF_OFFLOAD_DESTROY,
};

struct bpf_ext_analyzer_ops;
struct netlink_ext_ack;

struct netdev_bpf {
@@ -827,6 +832,15 @@ struct netdev_bpf {
			u8 prog_attached;
			u32 prog_id;
		};
		/* BPF_OFFLOAD_VERIFIER_PREP */
		struct {
			struct bpf_prog *prog;
			const struct bpf_ext_analyzer_ops *ops; /* callee set */
		} verifier;
		/* BPF_OFFLOAD_TRANSLATE, BPF_OFFLOAD_DESTROY */
		struct {
			struct bpf_prog *prog;
		} offload;
	};
};

+1 −0
Original line number Diff line number Diff line
@@ -256,6 +256,7 @@ union bpf_attr {
		__u32		kern_version;	/* checked when prog_type=kprobe */
		__u32		prog_flags;
		char		prog_name[BPF_OBJ_NAME_LEN];
		__u32		prog_target_ifindex;	/* ifindex of netdev to prep for */
	};

	struct { /* anonymous struct used by BPF_OBJ_* commands */
+1 −0
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@ obj-$(CONFIG_BPF_SYSCALL) += hashtab.o arraymap.o percpu_freelist.o bpf_lru_list
obj-$(CONFIG_BPF_SYSCALL) += btf.o
ifeq ($(CONFIG_NET),y)
obj-$(CONFIG_BPF_SYSCALL) += devmap.o
obj-$(CONFIG_BPF_SYSCALL) += offload.o
ifeq ($(CONFIG_STREAM_PARSER),y)
obj-$(CONFIG_BPF_SYSCALL) += sockmap.o
endif
Loading