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

Commit fd4f227d authored by Jakub Kicinski's avatar Jakub Kicinski Committed by Daniel Borkmann
Browse files

bpf: offload: allow program and map sharing per-ASIC



Allow programs and maps to be re-used across different netdevs,
as long as they belong to the same struct bpf_offload_dev.
Update the bpf_offload_prog_map_match() helper for the verifier
and export a new helper for the drivers to use when checking
programs at attachment time.

Signed-off-by: default avatarJakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: default avatarQuentin Monnet <quentin.monnet@netronome.com>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
parent 602144c2
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -657,6 +657,7 @@ int bpf_offload_dev_netdev_register(struct bpf_offload_dev *offdev,
				    struct net_device *netdev);
void bpf_offload_dev_netdev_unregister(struct bpf_offload_dev *offdev,
				       struct net_device *netdev);
bool bpf_offload_dev_match(struct bpf_prog *prog, struct net_device *netdev);

#if defined(CONFIG_NET) && defined(CONFIG_BPF_SYSCALL)
int bpf_prog_offload_init(struct bpf_prog *prog, union bpf_attr *attr);
+35 −7
Original line number Diff line number Diff line
@@ -511,22 +511,50 @@ int bpf_map_offload_info_fill(struct bpf_map_info *info, struct bpf_map *map)
	return 0;
}

bool bpf_offload_prog_map_match(struct bpf_prog *prog, struct bpf_map *map)
static bool __bpf_offload_dev_match(struct bpf_prog *prog,
				    struct net_device *netdev)
{
	struct bpf_offloaded_map *offmap;
	struct bpf_offload_netdev *ondev1, *ondev2;
	struct bpf_prog_offload *offload;
	bool ret;

	if (!bpf_prog_is_dev_bound(prog->aux))
		return false;
	if (!bpf_map_is_dev_bound(map))
		return bpf_map_offload_neutral(map);

	down_read(&bpf_devs_lock);
	offload = prog->aux->offload;
	if (!offload)
		return false;
	if (offload->netdev == netdev)
		return true;

	ondev1 = bpf_offload_find_netdev(offload->netdev);
	ondev2 = bpf_offload_find_netdev(netdev);

	return ondev1 && ondev2 && ondev1->offdev == ondev2->offdev;
}

bool bpf_offload_dev_match(struct bpf_prog *prog, struct net_device *netdev)
{
	bool ret;

	down_read(&bpf_devs_lock);
	ret = __bpf_offload_dev_match(prog, netdev);
	up_read(&bpf_devs_lock);

	return ret;
}
EXPORT_SYMBOL_GPL(bpf_offload_dev_match);

bool bpf_offload_prog_map_match(struct bpf_prog *prog, struct bpf_map *map)
{
	struct bpf_offloaded_map *offmap;
	bool ret;

	if (!bpf_map_is_dev_bound(map))
		return bpf_map_offload_neutral(map);
	offmap = map_to_offmap(map);

	ret = offload && offload->netdev == offmap->netdev;
	down_read(&bpf_devs_lock);
	ret = __bpf_offload_dev_match(prog, offmap->netdev);
	up_read(&bpf_devs_lock);

	return ret;