bpf: offload: allow program and map sharing per-ASIC
authorJakub Kicinski <jakub.kicinski@netronome.com>
Tue, 17 Jul 2018 17:53:26 +0000 (10:53 -0700)
committerDaniel Borkmann <daniel@iogearbox.net>
Wed, 18 Jul 2018 13:10:34 +0000 (15:10 +0200)
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: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: Quentin Monnet <quentin.monnet@netronome.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
include/linux/bpf.h
kernel/bpf/offload.c

index 913465e450628e7d0e8c277619822275df7b3643..5b5ad95cf33950f46727f58b36feb2841069aa88 100644 (file)
@@ -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);
index 925575f64ff1d591d7ba3a46fd93fd92c1af0193..177a524363942e0c66079cf51b0f760c98bf8031 100644 (file)
@@ -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;