return rhashtable_lookup_fast(&offdevs, &netdev, offdevs_params);
  }
  
- int bpf_prog_offload_init(struct bpf_prog *prog, union bpf_attr *attr)
+ static int __bpf_offload_dev_netdev_register(struct bpf_offload_dev *offdev,
+                                            struct net_device *netdev)
  {
        struct bpf_offload_netdev *ondev;
-       struct bpf_prog_offload *offload;
        int err;
  
-       if (attr->prog_type != BPF_PROG_TYPE_SCHED_CLS &&
-           attr->prog_type != BPF_PROG_TYPE_XDP)
-               return -EINVAL;
+       ondev = kzalloc(sizeof(*ondev), GFP_KERNEL);
+       if (!ondev)
+               return -ENOMEM;
  
-       if (attr->prog_flags)
-               return -EINVAL;
+       ondev->netdev = netdev;
+       ondev->offdev = offdev;
+       INIT_LIST_HEAD(&ondev->progs);
+       INIT_LIST_HEAD(&ondev->maps);
+ 
+       err = rhashtable_insert_fast(&offdevs, &ondev->l, offdevs_params);
+       if (err) {
+               netdev_warn(netdev, "failed to register for BPF offload\n");
+               goto err_free;
+       }
+ 
+       if (offdev)
+               list_add(&ondev->offdev_netdevs, &offdev->netdevs);
+       return 0;
+ 
+ err_free:
+       kfree(ondev);
+       return err;
+ }
+ 
+ static void __bpf_prog_offload_destroy(struct bpf_prog *prog)
+ {
+       struct bpf_prog_offload *offload = prog->aux->offload;
+ 
+       if (offload->dev_state)
+               offload->offdev->ops->destroy(prog);
+ 
 -      /* Make sure BPF_PROG_GET_NEXT_ID can't find this dead program */
 -      bpf_prog_free_id(prog, true);
 -
+       list_del_init(&offload->offloads);
+       kfree(offload);
+       prog->aux->offload = NULL;
+ }
+ 
+ static int bpf_map_offload_ndo(struct bpf_offloaded_map *offmap,
+                              enum bpf_netdev_command cmd)
+ {
+       struct netdev_bpf data = {};
+       struct net_device *netdev;
+ 
+       ASSERT_RTNL();
+ 
+       data.command = cmd;
+       data.offmap = offmap;
+       /* Caller must make sure netdev is valid */
+       netdev = offmap->netdev;
+ 
+       return netdev->netdev_ops->ndo_bpf(netdev, &data);
+ }
+ 
+ static void __bpf_map_offload_destroy(struct bpf_offloaded_map *offmap)
+ {
+       WARN_ON(bpf_map_offload_ndo(offmap, BPF_OFFLOAD_MAP_FREE));
+       /* Make sure BPF_MAP_GET_NEXT_ID can't find this dead map */
+       bpf_map_free_id(&offmap->map, true);
+       list_del_init(&offmap->offloads);
+       offmap->netdev = NULL;
+ }
+ 
+ static void __bpf_offload_dev_netdev_unregister(struct bpf_offload_dev *offdev,
+                                               struct net_device *netdev)
+ {
+       struct bpf_offload_netdev *ondev, *altdev = NULL;
+       struct bpf_offloaded_map *offmap, *mtmp;
+       struct bpf_prog_offload *offload, *ptmp;
+ 
+       ASSERT_RTNL();
+ 
+       ondev = rhashtable_lookup_fast(&offdevs, &netdev, offdevs_params);
+       if (WARN_ON(!ondev))
+               return;
+ 
+       WARN_ON(rhashtable_remove_fast(&offdevs, &ondev->l, offdevs_params));
+ 
+       /* Try to move the objects to another netdev of the device */
+       if (offdev) {
+               list_del(&ondev->offdev_netdevs);
+               altdev = list_first_entry_or_null(&offdev->netdevs,
+                                                 struct bpf_offload_netdev,
+                                                 offdev_netdevs);
+       }
+ 
+       if (altdev) {
+               list_for_each_entry(offload, &ondev->progs, offloads)
+                       offload->netdev = altdev->netdev;
+               list_splice_init(&ondev->progs, &altdev->progs);
+ 
+               list_for_each_entry(offmap, &ondev->maps, offloads)
+                       offmap->netdev = altdev->netdev;
+               list_splice_init(&ondev->maps, &altdev->maps);
+       } else {
+               list_for_each_entry_safe(offload, ptmp, &ondev->progs, offloads)
+                       __bpf_prog_offload_destroy(offload->prog);
+               list_for_each_entry_safe(offmap, mtmp, &ondev->maps, offloads)
+                       __bpf_map_offload_destroy(offmap);
+       }
+ 
+       WARN_ON(!list_empty(&ondev->progs));
+       WARN_ON(!list_empty(&ondev->maps));
+       kfree(ondev);
+ }
+ 
+ static int __bpf_prog_dev_bound_init(struct bpf_prog *prog, struct net_device *netdev)
+ {
+       struct bpf_offload_netdev *ondev;
+       struct bpf_prog_offload *offload;
+       int err;
  
        offload = kzalloc(sizeof(*offload), GFP_USER);
        if (!offload)