aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/netronome/nfp/bpf/main.c23
-rw-r--r--drivers/net/ethernet/netronome/nfp/bpf/main.h4
-rw-r--r--drivers/net/ethernet/netronome/nfp/bpf/offload.c10
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_app.c17
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_app.h8
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net_common.c2
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net_repr.c2
-rw-r--r--drivers/net/netdevsim/bpf.c50
-rw-r--r--drivers/net/netdevsim/netdev.c103
-rw-r--r--drivers/net/netdevsim/netdevsim.h23
-rw-r--r--include/linux/bpf.h13
-rw-r--r--kernel/bpf/cgroup.c7
-rw-r--r--kernel/bpf/core.c2
-rw-r--r--kernel/bpf/offload.c223
-rw-r--r--kernel/bpf/sockmap.c3
-rw-r--r--kernel/bpf/verifier.c2
-rw-r--r--samples/bpf/bpf_load.c3
-rw-r--r--samples/bpf/test_cgrp2_sock2.c2
-rw-r--r--tools/bpf/bpftool/Makefile2
-rw-r--r--tools/lib/bpf/Makefile6
-rwxr-xr-xtools/testing/selftests/bpf/test_offload.py151
21 files changed, 555 insertions, 101 deletions
diff --git a/drivers/net/ethernet/netronome/nfp/bpf/main.c b/drivers/net/ethernet/netronome/nfp/bpf/main.c
index b95b94d008cf..458f49235d06 100644
--- a/drivers/net/ethernet/netronome/nfp/bpf/main.c
+++ b/drivers/net/ethernet/netronome/nfp/bpf/main.c
@@ -404,6 +404,20 @@ err_release_free:
404 return -EINVAL; 404 return -EINVAL;
405} 405}
406 406
407static int nfp_bpf_ndo_init(struct nfp_app *app, struct net_device *netdev)
408{
409 struct nfp_app_bpf *bpf = app->priv;
410
411 return bpf_offload_dev_netdev_register(bpf->bpf_dev, netdev);
412}
413
414static void nfp_bpf_ndo_uninit(struct nfp_app *app, struct net_device *netdev)
415{
416 struct nfp_app_bpf *bpf = app->priv;
417
418 bpf_offload_dev_netdev_unregister(bpf->bpf_dev, netdev);
419}
420
407static int nfp_bpf_init(struct nfp_app *app) 421static int nfp_bpf_init(struct nfp_app *app)
408{ 422{
409 struct nfp_app_bpf *bpf; 423 struct nfp_app_bpf *bpf;
@@ -427,6 +441,11 @@ static int nfp_bpf_init(struct nfp_app *app)
427 if (err) 441 if (err)
428 goto err_free_neutral_maps; 442 goto err_free_neutral_maps;
429 443
444 bpf->bpf_dev = bpf_offload_dev_create();
445 err = PTR_ERR_OR_ZERO(bpf->bpf_dev);
446 if (err)
447 goto err_free_neutral_maps;
448
430 return 0; 449 return 0;
431 450
432err_free_neutral_maps: 451err_free_neutral_maps:
@@ -445,6 +464,7 @@ static void nfp_bpf_clean(struct nfp_app *app)
445{ 464{
446 struct nfp_app_bpf *bpf = app->priv; 465 struct nfp_app_bpf *bpf = app->priv;
447 466
467 bpf_offload_dev_destroy(bpf->bpf_dev);
448 WARN_ON(!skb_queue_empty(&bpf->cmsg_replies)); 468 WARN_ON(!skb_queue_empty(&bpf->cmsg_replies));
449 WARN_ON(!list_empty(&bpf->map_list)); 469 WARN_ON(!list_empty(&bpf->map_list));
450 WARN_ON(bpf->maps_in_use || bpf->map_elems_in_use); 470 WARN_ON(bpf->maps_in_use || bpf->map_elems_in_use);
@@ -466,6 +486,9 @@ const struct nfp_app_type app_bpf = {
466 486
467 .extra_cap = nfp_bpf_extra_cap, 487 .extra_cap = nfp_bpf_extra_cap,
468 488
489 .ndo_init = nfp_bpf_ndo_init,
490 .ndo_uninit = nfp_bpf_ndo_uninit,
491
469 .vnic_alloc = nfp_bpf_vnic_alloc, 492 .vnic_alloc = nfp_bpf_vnic_alloc,
470 .vnic_free = nfp_bpf_vnic_free, 493 .vnic_free = nfp_bpf_vnic_free,
471 494
diff --git a/drivers/net/ethernet/netronome/nfp/bpf/main.h b/drivers/net/ethernet/netronome/nfp/bpf/main.h
index 9845c1a2d4c2..bec935468f90 100644
--- a/drivers/net/ethernet/netronome/nfp/bpf/main.h
+++ b/drivers/net/ethernet/netronome/nfp/bpf/main.h
@@ -110,6 +110,8 @@ enum pkt_vec {
110 * struct nfp_app_bpf - bpf app priv structure 110 * struct nfp_app_bpf - bpf app priv structure
111 * @app: backpointer to the app 111 * @app: backpointer to the app
112 * 112 *
113 * @bpf_dev: BPF offload device handle
114 *
113 * @tag_allocator: bitmap of control message tags in use 115 * @tag_allocator: bitmap of control message tags in use
114 * @tag_alloc_next: next tag bit to allocate 116 * @tag_alloc_next: next tag bit to allocate
115 * @tag_alloc_last: next tag bit to be freed 117 * @tag_alloc_last: next tag bit to be freed
@@ -150,6 +152,8 @@ enum pkt_vec {
150struct nfp_app_bpf { 152struct nfp_app_bpf {
151 struct nfp_app *app; 153 struct nfp_app *app;
152 154
155 struct bpf_offload_dev *bpf_dev;
156
153 DECLARE_BITMAP(tag_allocator, U16_MAX + 1); 157 DECLARE_BITMAP(tag_allocator, U16_MAX + 1);
154 u16 tag_alloc_next; 158 u16 tag_alloc_next;
155 u16 tag_alloc_last; 159 u16 tag_alloc_last;
diff --git a/drivers/net/ethernet/netronome/nfp/bpf/offload.c b/drivers/net/ethernet/netronome/nfp/bpf/offload.c
index 78f44c4d95b4..49b03f7dbf46 100644
--- a/drivers/net/ethernet/netronome/nfp/bpf/offload.c
+++ b/drivers/net/ethernet/netronome/nfp/bpf/offload.c
@@ -566,14 +566,8 @@ int nfp_net_bpf_offload(struct nfp_net *nn, struct bpf_prog *prog,
566{ 566{
567 int err; 567 int err;
568 568
569 if (prog) { 569 if (prog && !bpf_offload_dev_match(prog, nn->dp.netdev))
570 struct bpf_prog_offload *offload = prog->aux->offload; 570 return -EINVAL;
571
572 if (!offload)
573 return -EINVAL;
574 if (offload->netdev != nn->dp.netdev)
575 return -EINVAL;
576 }
577 571
578 if (prog && old_prog) { 572 if (prog && old_prog) {
579 u8 cap; 573 u8 cap;
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_app.c b/drivers/net/ethernet/netronome/nfp/nfp_app.c
index f28b244f4ee7..69d4ae7a61f3 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_app.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_app.c
@@ -86,6 +86,23 @@ const char *nfp_app_mip_name(struct nfp_app *app)
86 return nfp_mip_name(app->pf->mip); 86 return nfp_mip_name(app->pf->mip);
87} 87}
88 88
89int nfp_app_ndo_init(struct net_device *netdev)
90{
91 struct nfp_app *app = nfp_app_from_netdev(netdev);
92
93 if (!app || !app->type->ndo_init)
94 return 0;
95 return app->type->ndo_init(app, netdev);
96}
97
98void nfp_app_ndo_uninit(struct net_device *netdev)
99{
100 struct nfp_app *app = nfp_app_from_netdev(netdev);
101
102 if (app && app->type->ndo_uninit)
103 app->type->ndo_uninit(app, netdev);
104}
105
89u64 *nfp_app_port_get_stats(struct nfp_port *port, u64 *data) 106u64 *nfp_app_port_get_stats(struct nfp_port *port, u64 *data)
90{ 107{
91 if (!port || !port->app || !port->app->type->port_get_stats) 108 if (!port || !port->app || !port->app->type->port_get_stats)
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_app.h b/drivers/net/ethernet/netronome/nfp/nfp_app.h
index ee74caacb015..afbc19aa66a8 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_app.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_app.h
@@ -78,6 +78,8 @@ extern const struct nfp_app_type app_abm;
78 * @init: perform basic app checks and init 78 * @init: perform basic app checks and init
79 * @clean: clean app state 79 * @clean: clean app state
80 * @extra_cap: extra capabilities string 80 * @extra_cap: extra capabilities string
81 * @ndo_init: vNIC and repr netdev .ndo_init
82 * @ndo_uninit: vNIC and repr netdev .ndo_unint
81 * @vnic_alloc: allocate vNICs (assign port types, etc.) 83 * @vnic_alloc: allocate vNICs (assign port types, etc.)
82 * @vnic_free: free up app's vNIC state 84 * @vnic_free: free up app's vNIC state
83 * @vnic_init: vNIC netdev was registered 85 * @vnic_init: vNIC netdev was registered
@@ -117,6 +119,9 @@ struct nfp_app_type {
117 119
118 const char *(*extra_cap)(struct nfp_app *app, struct nfp_net *nn); 120 const char *(*extra_cap)(struct nfp_app *app, struct nfp_net *nn);
119 121
122 int (*ndo_init)(struct nfp_app *app, struct net_device *netdev);
123 void (*ndo_uninit)(struct nfp_app *app, struct net_device *netdev);
124
120 int (*vnic_alloc)(struct nfp_app *app, struct nfp_net *nn, 125 int (*vnic_alloc)(struct nfp_app *app, struct nfp_net *nn,
121 unsigned int id); 126 unsigned int id);
122 void (*vnic_free)(struct nfp_app *app, struct nfp_net *nn); 127 void (*vnic_free)(struct nfp_app *app, struct nfp_net *nn);
@@ -200,6 +205,9 @@ static inline void nfp_app_clean(struct nfp_app *app)
200 app->type->clean(app); 205 app->type->clean(app);
201} 206}
202 207
208int nfp_app_ndo_init(struct net_device *netdev);
209void nfp_app_ndo_uninit(struct net_device *netdev);
210
203static inline int nfp_app_vnic_alloc(struct nfp_app *app, struct nfp_net *nn, 211static inline int nfp_app_vnic_alloc(struct nfp_app *app, struct nfp_net *nn,
204 unsigned int id) 212 unsigned int id)
205{ 213{
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index a712e83c3f0f..279b8ab8a17b 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -3480,6 +3480,8 @@ static int nfp_net_set_mac_address(struct net_device *netdev, void *addr)
3480} 3480}
3481 3481
3482const struct net_device_ops nfp_net_netdev_ops = { 3482const struct net_device_ops nfp_net_netdev_ops = {
3483 .ndo_init = nfp_app_ndo_init,
3484 .ndo_uninit = nfp_app_ndo_uninit,
3483 .ndo_open = nfp_net_netdev_open, 3485 .ndo_open = nfp_net_netdev_open,
3484 .ndo_stop = nfp_net_netdev_close, 3486 .ndo_stop = nfp_net_netdev_close,
3485 .ndo_start_xmit = nfp_net_tx, 3487 .ndo_start_xmit = nfp_net_tx,
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
index d7b712f6362f..18a09cdcd9c6 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
@@ -262,6 +262,8 @@ err_port_disable:
262} 262}
263 263
264const struct net_device_ops nfp_repr_netdev_ops = { 264const struct net_device_ops nfp_repr_netdev_ops = {
265 .ndo_init = nfp_app_ndo_init,
266 .ndo_uninit = nfp_app_ndo_uninit,
265 .ndo_open = nfp_repr_open, 267 .ndo_open = nfp_repr_open,
266 .ndo_stop = nfp_repr_stop, 268 .ndo_stop = nfp_repr_stop,
267 .ndo_start_xmit = nfp_repr_xmit, 269 .ndo_start_xmit = nfp_repr_xmit,
diff --git a/drivers/net/netdevsim/bpf.c b/drivers/net/netdevsim/bpf.c
index c36d2a768202..81444208b216 100644
--- a/drivers/net/netdevsim/bpf.c
+++ b/drivers/net/netdevsim/bpf.c
@@ -238,8 +238,8 @@ static int nsim_bpf_create_prog(struct netdevsim *ns, struct bpf_prog *prog)
238 state->state = "verify"; 238 state->state = "verify";
239 239
240 /* Program id is not populated yet when we create the state. */ 240 /* Program id is not populated yet when we create the state. */
241 sprintf(name, "%u", ns->prog_id_gen++); 241 sprintf(name, "%u", ns->sdev->prog_id_gen++);
242 state->ddir = debugfs_create_dir(name, ns->ddir_bpf_bound_progs); 242 state->ddir = debugfs_create_dir(name, ns->sdev->ddir_bpf_bound_progs);
243 if (IS_ERR_OR_NULL(state->ddir)) { 243 if (IS_ERR_OR_NULL(state->ddir)) {
244 kfree(state); 244 kfree(state);
245 return -ENOMEM; 245 return -ENOMEM;
@@ -250,7 +250,7 @@ static int nsim_bpf_create_prog(struct netdevsim *ns, struct bpf_prog *prog)
250 &state->state, &nsim_bpf_string_fops); 250 &state->state, &nsim_bpf_string_fops);
251 debugfs_create_bool("loaded", 0400, state->ddir, &state->is_loaded); 251 debugfs_create_bool("loaded", 0400, state->ddir, &state->is_loaded);
252 252
253 list_add_tail(&state->l, &ns->bpf_bound_progs); 253 list_add_tail(&state->l, &ns->sdev->bpf_bound_progs);
254 254
255 prog->aux->offload->dev_priv = state; 255 prog->aux->offload->dev_priv = state;
256 256
@@ -294,7 +294,7 @@ nsim_setup_prog_hw_checks(struct netdevsim *ns, struct netdev_bpf *bpf)
294 NSIM_EA(bpf->extack, "xdpoffload of non-bound program"); 294 NSIM_EA(bpf->extack, "xdpoffload of non-bound program");
295 return -EINVAL; 295 return -EINVAL;
296 } 296 }
297 if (bpf->prog->aux->offload->netdev != ns->netdev) { 297 if (!bpf_offload_dev_match(bpf->prog, ns->netdev)) {
298 NSIM_EA(bpf->extack, "program bound to different dev"); 298 NSIM_EA(bpf->extack, "program bound to different dev");
299 return -EINVAL; 299 return -EINVAL;
300 } 300 }
@@ -497,7 +497,7 @@ nsim_bpf_map_alloc(struct netdevsim *ns, struct bpf_offloaded_map *offmap)
497 } 497 }
498 498
499 offmap->dev_ops = &nsim_bpf_map_ops; 499 offmap->dev_ops = &nsim_bpf_map_ops;
500 list_add_tail(&nmap->l, &ns->bpf_bound_maps); 500 list_add_tail(&nmap->l, &ns->sdev->bpf_bound_maps);
501 501
502 return 0; 502 return 0;
503 503
@@ -582,8 +582,26 @@ int nsim_bpf(struct net_device *dev, struct netdev_bpf *bpf)
582 582
583int nsim_bpf_init(struct netdevsim *ns) 583int nsim_bpf_init(struct netdevsim *ns)
584{ 584{
585 INIT_LIST_HEAD(&ns->bpf_bound_progs); 585 int err;
586 INIT_LIST_HEAD(&ns->bpf_bound_maps); 586
587 if (ns->sdev->refcnt == 1) {
588 INIT_LIST_HEAD(&ns->sdev->bpf_bound_progs);
589 INIT_LIST_HEAD(&ns->sdev->bpf_bound_maps);
590
591 ns->sdev->ddir_bpf_bound_progs =
592 debugfs_create_dir("bpf_bound_progs", ns->sdev->ddir);
593 if (IS_ERR_OR_NULL(ns->sdev->ddir_bpf_bound_progs))
594 return -ENOMEM;
595
596 ns->sdev->bpf_dev = bpf_offload_dev_create();
597 err = PTR_ERR_OR_ZERO(ns->sdev->bpf_dev);
598 if (err)
599 return err;
600 }
601
602 err = bpf_offload_dev_netdev_register(ns->sdev->bpf_dev, ns->netdev);
603 if (err)
604 goto err_destroy_bdev;
587 605
588 debugfs_create_u32("bpf_offloaded_id", 0400, ns->ddir, 606 debugfs_create_u32("bpf_offloaded_id", 0400, ns->ddir,
589 &ns->bpf_offloaded_id); 607 &ns->bpf_offloaded_id);
@@ -593,10 +611,6 @@ int nsim_bpf_init(struct netdevsim *ns)
593 &ns->bpf_bind_accept); 611 &ns->bpf_bind_accept);
594 debugfs_create_u32("bpf_bind_verifier_delay", 0600, ns->ddir, 612 debugfs_create_u32("bpf_bind_verifier_delay", 0600, ns->ddir,
595 &ns->bpf_bind_verifier_delay); 613 &ns->bpf_bind_verifier_delay);
596 ns->ddir_bpf_bound_progs =
597 debugfs_create_dir("bpf_bound_progs", ns->ddir);
598 if (IS_ERR_OR_NULL(ns->ddir_bpf_bound_progs))
599 return -ENOMEM;
600 614
601 ns->bpf_tc_accept = true; 615 ns->bpf_tc_accept = true;
602 debugfs_create_bool("bpf_tc_accept", 0600, ns->ddir, 616 debugfs_create_bool("bpf_tc_accept", 0600, ns->ddir,
@@ -615,13 +629,23 @@ int nsim_bpf_init(struct netdevsim *ns)
615 &ns->bpf_map_accept); 629 &ns->bpf_map_accept);
616 630
617 return 0; 631 return 0;
632
633err_destroy_bdev:
634 if (ns->sdev->refcnt == 1)
635 bpf_offload_dev_destroy(ns->sdev->bpf_dev);
636 return err;
618} 637}
619 638
620void nsim_bpf_uninit(struct netdevsim *ns) 639void nsim_bpf_uninit(struct netdevsim *ns)
621{ 640{
622 WARN_ON(!list_empty(&ns->bpf_bound_progs));
623 WARN_ON(!list_empty(&ns->bpf_bound_maps));
624 WARN_ON(ns->xdp.prog); 641 WARN_ON(ns->xdp.prog);
625 WARN_ON(ns->xdp_hw.prog); 642 WARN_ON(ns->xdp_hw.prog);
626 WARN_ON(ns->bpf_offloaded); 643 WARN_ON(ns->bpf_offloaded);
644 bpf_offload_dev_netdev_unregister(ns->sdev->bpf_dev, ns->netdev);
645
646 if (ns->sdev->refcnt == 1) {
647 WARN_ON(!list_empty(&ns->sdev->bpf_bound_progs));
648 WARN_ON(!list_empty(&ns->sdev->bpf_bound_maps));
649 bpf_offload_dev_destroy(ns->sdev->bpf_dev);
650 }
627} 651}
diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c
index a7b179f0d954..2d244551298b 100644
--- a/drivers/net/netdevsim/netdev.c
+++ b/drivers/net/netdevsim/netdev.c
@@ -22,6 +22,7 @@
22#include <net/netlink.h> 22#include <net/netlink.h>
23#include <net/pkt_cls.h> 23#include <net/pkt_cls.h>
24#include <net/rtnetlink.h> 24#include <net/rtnetlink.h>
25#include <net/switchdev.h>
25 26
26#include "netdevsim.h" 27#include "netdevsim.h"
27 28
@@ -144,8 +145,29 @@ static struct device_type nsim_dev_type = {
144 .release = nsim_dev_release, 145 .release = nsim_dev_release,
145}; 146};
146 147
148static int
149nsim_port_attr_get(struct net_device *dev, struct switchdev_attr *attr)
150{
151 struct netdevsim *ns = netdev_priv(dev);
152
153 switch (attr->id) {
154 case SWITCHDEV_ATTR_ID_PORT_PARENT_ID:
155 attr->u.ppid.id_len = sizeof(ns->sdev->switch_id);
156 memcpy(&attr->u.ppid.id, &ns->sdev->switch_id,
157 attr->u.ppid.id_len);
158 return 0;
159 default:
160 return -EOPNOTSUPP;
161 }
162}
163
164static const struct switchdev_ops nsim_switchdev_ops = {
165 .switchdev_port_attr_get = nsim_port_attr_get,
166};
167
147static int nsim_init(struct net_device *dev) 168static int nsim_init(struct net_device *dev)
148{ 169{
170 char sdev_ddir_name[10], sdev_link_name[32];
149 struct netdevsim *ns = netdev_priv(dev); 171 struct netdevsim *ns = netdev_priv(dev);
150 int err; 172 int err;
151 173
@@ -154,9 +176,32 @@ static int nsim_init(struct net_device *dev)
154 if (IS_ERR_OR_NULL(ns->ddir)) 176 if (IS_ERR_OR_NULL(ns->ddir))
155 return -ENOMEM; 177 return -ENOMEM;
156 178
179 if (!ns->sdev) {
180 ns->sdev = kzalloc(sizeof(*ns->sdev), GFP_KERNEL);
181 if (!ns->sdev) {
182 err = -ENOMEM;
183 goto err_debugfs_destroy;
184 }
185 ns->sdev->refcnt = 1;
186 ns->sdev->switch_id = nsim_dev_id;
187 sprintf(sdev_ddir_name, "%u", ns->sdev->switch_id);
188 ns->sdev->ddir = debugfs_create_dir(sdev_ddir_name,
189 nsim_sdev_ddir);
190 if (IS_ERR_OR_NULL(ns->sdev->ddir)) {
191 err = PTR_ERR_OR_ZERO(ns->sdev->ddir) ?: -EINVAL;
192 goto err_sdev_free;
193 }
194 } else {
195 sprintf(sdev_ddir_name, "%u", ns->sdev->switch_id);
196 ns->sdev->refcnt++;
197 }
198
199 sprintf(sdev_link_name, "../../" DRV_NAME "_sdev/%s", sdev_ddir_name);
200 debugfs_create_symlink("sdev", ns->ddir, sdev_link_name);
201
157 err = nsim_bpf_init(ns); 202 err = nsim_bpf_init(ns);
158 if (err) 203 if (err)
159 goto err_debugfs_destroy; 204 goto err_sdev_destroy;
160 205
161 ns->dev.id = nsim_dev_id++; 206 ns->dev.id = nsim_dev_id++;
162 ns->dev.bus = &nsim_bus; 207 ns->dev.bus = &nsim_bus;
@@ -166,6 +211,7 @@ static int nsim_init(struct net_device *dev)
166 goto err_bpf_uninit; 211 goto err_bpf_uninit;
167 212
168 SET_NETDEV_DEV(dev, &ns->dev); 213 SET_NETDEV_DEV(dev, &ns->dev);
214 SWITCHDEV_SET_OPS(dev, &nsim_switchdev_ops);
169 215
170 err = nsim_devlink_setup(ns); 216 err = nsim_devlink_setup(ns);
171 if (err) 217 if (err)
@@ -179,6 +225,12 @@ err_unreg_dev:
179 device_unregister(&ns->dev); 225 device_unregister(&ns->dev);
180err_bpf_uninit: 226err_bpf_uninit:
181 nsim_bpf_uninit(ns); 227 nsim_bpf_uninit(ns);
228err_sdev_destroy:
229 if (!--ns->sdev->refcnt) {
230 debugfs_remove_recursive(ns->sdev->ddir);
231err_sdev_free:
232 kfree(ns->sdev);
233 }
182err_debugfs_destroy: 234err_debugfs_destroy:
183 debugfs_remove_recursive(ns->ddir); 235 debugfs_remove_recursive(ns->ddir);
184 return err; 236 return err;
@@ -192,6 +244,10 @@ static void nsim_uninit(struct net_device *dev)
192 nsim_devlink_teardown(ns); 244 nsim_devlink_teardown(ns);
193 debugfs_remove_recursive(ns->ddir); 245 debugfs_remove_recursive(ns->ddir);
194 nsim_bpf_uninit(ns); 246 nsim_bpf_uninit(ns);
247 if (!--ns->sdev->refcnt) {
248 debugfs_remove_recursive(ns->sdev->ddir);
249 kfree(ns->sdev);
250 }
195} 251}
196 252
197static void nsim_free(struct net_device *dev) 253static void nsim_free(struct net_device *dev)
@@ -470,14 +526,48 @@ static int nsim_validate(struct nlattr *tb[], struct nlattr *data[],
470 return 0; 526 return 0;
471} 527}
472 528
529static int nsim_newlink(struct net *src_net, struct net_device *dev,
530 struct nlattr *tb[], struct nlattr *data[],
531 struct netlink_ext_ack *extack)
532{
533 struct netdevsim *ns = netdev_priv(dev);
534
535 if (tb[IFLA_LINK]) {
536 struct net_device *joindev;
537 struct netdevsim *joinns;
538
539 joindev = __dev_get_by_index(src_net,
540 nla_get_u32(tb[IFLA_LINK]));
541 if (!joindev)
542 return -ENODEV;
543 if (joindev->netdev_ops != &nsim_netdev_ops)
544 return -EINVAL;
545
546 joinns = netdev_priv(joindev);
547 if (!joinns->sdev || !joinns->sdev->refcnt)
548 return -EINVAL;
549 ns->sdev = joinns->sdev;
550 }
551
552 return register_netdevice(dev);
553}
554
555static void nsim_dellink(struct net_device *dev, struct list_head *head)
556{
557 unregister_netdevice_queue(dev, head);
558}
559
473static struct rtnl_link_ops nsim_link_ops __read_mostly = { 560static struct rtnl_link_ops nsim_link_ops __read_mostly = {
474 .kind = DRV_NAME, 561 .kind = DRV_NAME,
475 .priv_size = sizeof(struct netdevsim), 562 .priv_size = sizeof(struct netdevsim),
476 .setup = nsim_setup, 563 .setup = nsim_setup,
477 .validate = nsim_validate, 564 .validate = nsim_validate,
565 .newlink = nsim_newlink,
566 .dellink = nsim_dellink,
478}; 567};
479 568
480struct dentry *nsim_ddir; 569struct dentry *nsim_ddir;
570struct dentry *nsim_sdev_ddir;
481 571
482static int __init nsim_module_init(void) 572static int __init nsim_module_init(void)
483{ 573{
@@ -487,9 +577,15 @@ static int __init nsim_module_init(void)
487 if (IS_ERR_OR_NULL(nsim_ddir)) 577 if (IS_ERR_OR_NULL(nsim_ddir))
488 return -ENOMEM; 578 return -ENOMEM;
489 579
580 nsim_sdev_ddir = debugfs_create_dir(DRV_NAME "_sdev", NULL);
581 if (IS_ERR_OR_NULL(nsim_sdev_ddir)) {
582 err = -ENOMEM;
583 goto err_debugfs_destroy;
584 }
585
490 err = bus_register(&nsim_bus); 586 err = bus_register(&nsim_bus);
491 if (err) 587 if (err)
492 goto err_debugfs_destroy; 588 goto err_sdir_destroy;
493 589
494 err = nsim_devlink_init(); 590 err = nsim_devlink_init();
495 if (err) 591 if (err)
@@ -505,6 +601,8 @@ err_dl_fini:
505 nsim_devlink_exit(); 601 nsim_devlink_exit();
506err_unreg_bus: 602err_unreg_bus:
507 bus_unregister(&nsim_bus); 603 bus_unregister(&nsim_bus);
604err_sdir_destroy:
605 debugfs_remove_recursive(nsim_sdev_ddir);
508err_debugfs_destroy: 606err_debugfs_destroy:
509 debugfs_remove_recursive(nsim_ddir); 607 debugfs_remove_recursive(nsim_ddir);
510 return err; 608 return err;
@@ -515,6 +613,7 @@ static void __exit nsim_module_exit(void)
515 rtnl_link_unregister(&nsim_link_ops); 613 rtnl_link_unregister(&nsim_link_ops);
516 nsim_devlink_exit(); 614 nsim_devlink_exit();
517 bus_unregister(&nsim_bus); 615 bus_unregister(&nsim_bus);
616 debugfs_remove_recursive(nsim_sdev_ddir);
518 debugfs_remove_recursive(nsim_ddir); 617 debugfs_remove_recursive(nsim_ddir);
519} 618}
520 619
diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h
index 0aeabbe81cc6..02be199eb005 100644
--- a/drivers/net/netdevsim/netdevsim.h
+++ b/drivers/net/netdevsim/netdevsim.h
@@ -27,9 +27,25 @@
27#define NSIM_EA(extack, msg) NL_SET_ERR_MSG_MOD((extack), msg) 27#define NSIM_EA(extack, msg) NL_SET_ERR_MSG_MOD((extack), msg)
28 28
29struct bpf_prog; 29struct bpf_prog;
30struct bpf_offload_dev;
30struct dentry; 31struct dentry;
31struct nsim_vf_config; 32struct nsim_vf_config;
32 33
34struct netdevsim_shared_dev {
35 unsigned int refcnt;
36 u32 switch_id;
37
38 struct dentry *ddir;
39
40 struct bpf_offload_dev *bpf_dev;
41
42 struct dentry *ddir_bpf_bound_progs;
43 u32 prog_id_gen;
44
45 struct list_head bpf_bound_progs;
46 struct list_head bpf_bound_maps;
47};
48
33#define NSIM_IPSEC_MAX_SA_COUNT 33 49#define NSIM_IPSEC_MAX_SA_COUNT 33
34#define NSIM_IPSEC_VALID BIT(31) 50#define NSIM_IPSEC_VALID BIT(31)
35 51
@@ -59,6 +75,7 @@ struct netdevsim {
59 struct u64_stats_sync syncp; 75 struct u64_stats_sync syncp;
60 76
61 struct device dev; 77 struct device dev;
78 struct netdevsim_shared_dev *sdev;
62 79
63 struct dentry *ddir; 80 struct dentry *ddir;
64 81
@@ -71,12 +88,8 @@ struct netdevsim {
71 struct xdp_attachment_info xdp; 88 struct xdp_attachment_info xdp;
72 struct xdp_attachment_info xdp_hw; 89 struct xdp_attachment_info xdp_hw;
73 90
74 u32 prog_id_gen;
75
76 bool bpf_bind_accept; 91 bool bpf_bind_accept;
77 u32 bpf_bind_verifier_delay; 92 u32 bpf_bind_verifier_delay;
78 struct dentry *ddir_bpf_bound_progs;
79 struct list_head bpf_bound_progs;
80 93
81 bool bpf_tc_accept; 94 bool bpf_tc_accept;
82 bool bpf_tc_non_bound_accept; 95 bool bpf_tc_non_bound_accept;
@@ -84,7 +97,6 @@ struct netdevsim {
84 bool bpf_xdpoffload_accept; 97 bool bpf_xdpoffload_accept;
85 98
86 bool bpf_map_accept; 99 bool bpf_map_accept;
87 struct list_head bpf_bound_maps;
88#if IS_ENABLED(CONFIG_NET_DEVLINK) 100#if IS_ENABLED(CONFIG_NET_DEVLINK)
89 struct devlink *devlink; 101 struct devlink *devlink;
90#endif 102#endif
@@ -92,6 +104,7 @@ struct netdevsim {
92}; 104};
93 105
94extern struct dentry *nsim_ddir; 106extern struct dentry *nsim_ddir;
107extern struct dentry *nsim_sdev_ddir;
95 108
96#ifdef CONFIG_BPF_SYSCALL 109#ifdef CONFIG_BPF_SYSCALL
97int nsim_bpf_init(struct netdevsim *ns); 110int nsim_bpf_init(struct netdevsim *ns);
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 8827e797ff97..5b5ad95cf339 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -85,6 +85,7 @@ struct bpf_map {
85 char name[BPF_OBJ_NAME_LEN]; 85 char name[BPF_OBJ_NAME_LEN];
86}; 86};
87 87
88struct bpf_offload_dev;
88struct bpf_offloaded_map; 89struct bpf_offloaded_map;
89 90
90struct bpf_map_dev_ops { 91struct bpf_map_dev_ops {
@@ -352,7 +353,7 @@ struct bpf_prog_array {
352 struct bpf_prog *progs[0]; 353 struct bpf_prog *progs[0];
353}; 354};
354 355
355struct bpf_prog_array __rcu *bpf_prog_array_alloc(u32 prog_cnt, gfp_t flags); 356struct bpf_prog_array *bpf_prog_array_alloc(u32 prog_cnt, gfp_t flags);
356void bpf_prog_array_free(struct bpf_prog_array __rcu *progs); 357void bpf_prog_array_free(struct bpf_prog_array __rcu *progs);
357int bpf_prog_array_length(struct bpf_prog_array __rcu *progs); 358int bpf_prog_array_length(struct bpf_prog_array __rcu *progs);
358int bpf_prog_array_copy_to_user(struct bpf_prog_array __rcu *progs, 359int bpf_prog_array_copy_to_user(struct bpf_prog_array __rcu *progs,
@@ -648,7 +649,15 @@ int bpf_map_offload_delete_elem(struct bpf_map *map, void *key);
648int bpf_map_offload_get_next_key(struct bpf_map *map, 649int bpf_map_offload_get_next_key(struct bpf_map *map,
649 void *key, void *next_key); 650 void *key, void *next_key);
650 651
651bool bpf_offload_dev_match(struct bpf_prog *prog, struct bpf_map *map); 652bool bpf_offload_prog_map_match(struct bpf_prog *prog, struct bpf_map *map);
653
654struct bpf_offload_dev *bpf_offload_dev_create(void);
655void bpf_offload_dev_destroy(struct bpf_offload_dev *offdev);
656int bpf_offload_dev_netdev_register(struct bpf_offload_dev *offdev,
657 struct net_device *netdev);
658void bpf_offload_dev_netdev_unregister(struct bpf_offload_dev *offdev,
659 struct net_device *netdev);
660bool bpf_offload_dev_match(struct bpf_prog *prog, struct net_device *netdev);
652 661
653#if defined(CONFIG_NET) && defined(CONFIG_BPF_SYSCALL) 662#if defined(CONFIG_NET) && defined(CONFIG_BPF_SYSCALL)
654int bpf_prog_offload_init(struct bpf_prog *prog, union bpf_attr *attr); 663int bpf_prog_offload_init(struct bpf_prog *prog, union bpf_attr *attr);
diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c
index 3d83ee7df381..badabb0b435c 100644
--- a/kernel/bpf/cgroup.c
+++ b/kernel/bpf/cgroup.c
@@ -95,7 +95,7 @@ static int compute_effective_progs(struct cgroup *cgrp,
95 enum bpf_attach_type type, 95 enum bpf_attach_type type,
96 struct bpf_prog_array __rcu **array) 96 struct bpf_prog_array __rcu **array)
97{ 97{
98 struct bpf_prog_array __rcu *progs; 98 struct bpf_prog_array *progs;
99 struct bpf_prog_list *pl; 99 struct bpf_prog_list *pl;
100 struct cgroup *p = cgrp; 100 struct cgroup *p = cgrp;
101 int cnt = 0; 101 int cnt = 0;
@@ -120,13 +120,12 @@ static int compute_effective_progs(struct cgroup *cgrp,
120 &p->bpf.progs[type], node) { 120 &p->bpf.progs[type], node) {
121 if (!pl->prog) 121 if (!pl->prog)
122 continue; 122 continue;
123 rcu_dereference_protected(progs, 1)-> 123 progs->progs[cnt++] = pl->prog;
124 progs[cnt++] = pl->prog;
125 } 124 }
126 p = cgroup_parent(p); 125 p = cgroup_parent(p);
127 } while (p); 126 } while (p);
128 127
129 *array = progs; 128 rcu_assign_pointer(*array, progs);
130 return 0; 129 return 0;
131} 130}
132 131
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index 1e5625d46414..253aa8e79c7b 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -1538,7 +1538,7 @@ static struct {
1538 .null_prog = NULL, 1538 .null_prog = NULL,
1539}; 1539};
1540 1540
1541struct bpf_prog_array __rcu *bpf_prog_array_alloc(u32 prog_cnt, gfp_t flags) 1541struct bpf_prog_array *bpf_prog_array_alloc(u32 prog_cnt, gfp_t flags)
1542{ 1542{
1543 if (prog_cnt) 1543 if (prog_cnt)
1544 return kzalloc(sizeof(struct bpf_prog_array) + 1544 return kzalloc(sizeof(struct bpf_prog_array) +
diff --git a/kernel/bpf/offload.c b/kernel/bpf/offload.c
index ac747d5cf7c6..177a52436394 100644
--- a/kernel/bpf/offload.c
+++ b/kernel/bpf/offload.c
@@ -18,19 +18,43 @@
18#include <linux/bug.h> 18#include <linux/bug.h>
19#include <linux/kdev_t.h> 19#include <linux/kdev_t.h>
20#include <linux/list.h> 20#include <linux/list.h>
21#include <linux/lockdep.h>
21#include <linux/netdevice.h> 22#include <linux/netdevice.h>
22#include <linux/printk.h> 23#include <linux/printk.h>
23#include <linux/proc_ns.h> 24#include <linux/proc_ns.h>
25#include <linux/rhashtable.h>
24#include <linux/rtnetlink.h> 26#include <linux/rtnetlink.h>
25#include <linux/rwsem.h> 27#include <linux/rwsem.h>
26 28
27/* Protects bpf_prog_offload_devs, bpf_map_offload_devs and offload members 29/* Protects offdevs, members of bpf_offload_netdev and offload members
28 * of all progs. 30 * of all progs.
29 * RTNL lock cannot be taken when holding this lock. 31 * RTNL lock cannot be taken when holding this lock.
30 */ 32 */
31static DECLARE_RWSEM(bpf_devs_lock); 33static DECLARE_RWSEM(bpf_devs_lock);
32static LIST_HEAD(bpf_prog_offload_devs); 34
33static LIST_HEAD(bpf_map_offload_devs); 35struct bpf_offload_dev {
36 struct list_head netdevs;
37};
38
39struct bpf_offload_netdev {
40 struct rhash_head l;
41 struct net_device *netdev;
42 struct bpf_offload_dev *offdev;
43 struct list_head progs;
44 struct list_head maps;
45 struct list_head offdev_netdevs;
46};
47
48static const struct rhashtable_params offdevs_params = {
49 .nelem_hint = 4,
50 .key_len = sizeof(struct net_device *),
51 .key_offset = offsetof(struct bpf_offload_netdev, netdev),
52 .head_offset = offsetof(struct bpf_offload_netdev, l),
53 .automatic_shrinking = true,
54};
55
56static struct rhashtable offdevs;
57static bool offdevs_inited;
34 58
35static int bpf_dev_offload_check(struct net_device *netdev) 59static int bpf_dev_offload_check(struct net_device *netdev)
36{ 60{
@@ -41,8 +65,19 @@ static int bpf_dev_offload_check(struct net_device *netdev)
41 return 0; 65 return 0;
42} 66}
43 67
68static struct bpf_offload_netdev *
69bpf_offload_find_netdev(struct net_device *netdev)
70{
71 lockdep_assert_held(&bpf_devs_lock);
72
73 if (!offdevs_inited)
74 return NULL;
75 return rhashtable_lookup_fast(&offdevs, &netdev, offdevs_params);
76}
77
44int bpf_prog_offload_init(struct bpf_prog *prog, union bpf_attr *attr) 78int bpf_prog_offload_init(struct bpf_prog *prog, union bpf_attr *attr)
45{ 79{
80 struct bpf_offload_netdev *ondev;
46 struct bpf_prog_offload *offload; 81 struct bpf_prog_offload *offload;
47 int err; 82 int err;
48 83
@@ -66,12 +101,13 @@ int bpf_prog_offload_init(struct bpf_prog *prog, union bpf_attr *attr)
66 goto err_maybe_put; 101 goto err_maybe_put;
67 102
68 down_write(&bpf_devs_lock); 103 down_write(&bpf_devs_lock);
69 if (offload->netdev->reg_state != NETREG_REGISTERED) { 104 ondev = bpf_offload_find_netdev(offload->netdev);
105 if (!ondev) {
70 err = -EINVAL; 106 err = -EINVAL;
71 goto err_unlock; 107 goto err_unlock;
72 } 108 }
73 prog->aux->offload = offload; 109 prog->aux->offload = offload;
74 list_add_tail(&offload->offloads, &bpf_prog_offload_devs); 110 list_add_tail(&offload->offloads, &ondev->progs);
75 dev_put(offload->netdev); 111 dev_put(offload->netdev);
76 up_write(&bpf_devs_lock); 112 up_write(&bpf_devs_lock);
77 113
@@ -294,6 +330,7 @@ static int bpf_map_offload_ndo(struct bpf_offloaded_map *offmap,
294struct bpf_map *bpf_map_offload_map_alloc(union bpf_attr *attr) 330struct bpf_map *bpf_map_offload_map_alloc(union bpf_attr *attr)
295{ 331{
296 struct net *net = current->nsproxy->net_ns; 332 struct net *net = current->nsproxy->net_ns;
333 struct bpf_offload_netdev *ondev;
297 struct bpf_offloaded_map *offmap; 334 struct bpf_offloaded_map *offmap;
298 int err; 335 int err;
299 336
@@ -316,11 +353,17 @@ struct bpf_map *bpf_map_offload_map_alloc(union bpf_attr *attr)
316 if (err) 353 if (err)
317 goto err_unlock; 354 goto err_unlock;
318 355
356 ondev = bpf_offload_find_netdev(offmap->netdev);
357 if (!ondev) {
358 err = -EINVAL;
359 goto err_unlock;
360 }
361
319 err = bpf_map_offload_ndo(offmap, BPF_OFFLOAD_MAP_ALLOC); 362 err = bpf_map_offload_ndo(offmap, BPF_OFFLOAD_MAP_ALLOC);
320 if (err) 363 if (err)
321 goto err_unlock; 364 goto err_unlock;
322 365
323 list_add_tail(&offmap->offloads, &bpf_map_offload_devs); 366 list_add_tail(&offmap->offloads, &ondev->maps);
324 up_write(&bpf_devs_lock); 367 up_write(&bpf_devs_lock);
325 rtnl_unlock(); 368 rtnl_unlock();
326 369
@@ -468,77 +511,159 @@ int bpf_map_offload_info_fill(struct bpf_map_info *info, struct bpf_map *map)
468 return 0; 511 return 0;
469} 512}
470 513
471bool bpf_offload_dev_match(struct bpf_prog *prog, struct bpf_map *map) 514static bool __bpf_offload_dev_match(struct bpf_prog *prog,
515 struct net_device *netdev)
472{ 516{
473 struct bpf_offloaded_map *offmap; 517 struct bpf_offload_netdev *ondev1, *ondev2;
474 struct bpf_prog_offload *offload; 518 struct bpf_prog_offload *offload;
475 bool ret;
476 519
477 if (!bpf_prog_is_dev_bound(prog->aux)) 520 if (!bpf_prog_is_dev_bound(prog->aux))
478 return false; 521 return false;
479 if (!bpf_map_is_dev_bound(map))
480 return bpf_map_offload_neutral(map);
481 522
482 down_read(&bpf_devs_lock);
483 offload = prog->aux->offload; 523 offload = prog->aux->offload;
484 offmap = map_to_offmap(map); 524 if (!offload)
525 return false;
526 if (offload->netdev == netdev)
527 return true;
485 528
486 ret = offload && offload->netdev == offmap->netdev; 529 ondev1 = bpf_offload_find_netdev(offload->netdev);
530 ondev2 = bpf_offload_find_netdev(netdev);
531
532 return ondev1 && ondev2 && ondev1->offdev == ondev2->offdev;
533}
534
535bool bpf_offload_dev_match(struct bpf_prog *prog, struct net_device *netdev)
536{
537 bool ret;
538
539 down_read(&bpf_devs_lock);
540 ret = __bpf_offload_dev_match(prog, netdev);
487 up_read(&bpf_devs_lock); 541 up_read(&bpf_devs_lock);
488 542
489 return ret; 543 return ret;
490} 544}
545EXPORT_SYMBOL_GPL(bpf_offload_dev_match);
491 546
492static void bpf_offload_orphan_all_progs(struct net_device *netdev) 547bool bpf_offload_prog_map_match(struct bpf_prog *prog, struct bpf_map *map)
493{ 548{
494 struct bpf_prog_offload *offload, *tmp; 549 struct bpf_offloaded_map *offmap;
550 bool ret;
495 551
496 list_for_each_entry_safe(offload, tmp, &bpf_prog_offload_devs, offloads) 552 if (!bpf_map_is_dev_bound(map))
497 if (offload->netdev == netdev) 553 return bpf_map_offload_neutral(map);
498 __bpf_prog_offload_destroy(offload->prog); 554 offmap = map_to_offmap(map);
555
556 down_read(&bpf_devs_lock);
557 ret = __bpf_offload_dev_match(prog, offmap->netdev);
558 up_read(&bpf_devs_lock);
559
560 return ret;
499} 561}
500 562
501static void bpf_offload_orphan_all_maps(struct net_device *netdev) 563int bpf_offload_dev_netdev_register(struct bpf_offload_dev *offdev,
564 struct net_device *netdev)
502{ 565{
503 struct bpf_offloaded_map *offmap, *tmp; 566 struct bpf_offload_netdev *ondev;
567 int err;
504 568
505 list_for_each_entry_safe(offmap, tmp, &bpf_map_offload_devs, offloads) 569 ondev = kzalloc(sizeof(*ondev), GFP_KERNEL);
506 if (offmap->netdev == netdev) 570 if (!ondev)
507 __bpf_map_offload_destroy(offmap); 571 return -ENOMEM;
572
573 ondev->netdev = netdev;
574 ondev->offdev = offdev;
575 INIT_LIST_HEAD(&ondev->progs);
576 INIT_LIST_HEAD(&ondev->maps);
577
578 down_write(&bpf_devs_lock);
579 err = rhashtable_insert_fast(&offdevs, &ondev->l, offdevs_params);
580 if (err) {
581 netdev_warn(netdev, "failed to register for BPF offload\n");
582 goto err_unlock_free;
583 }
584
585 list_add(&ondev->offdev_netdevs, &offdev->netdevs);
586 up_write(&bpf_devs_lock);
587 return 0;
588
589err_unlock_free:
590 up_write(&bpf_devs_lock);
591 kfree(ondev);
592 return err;
508} 593}
594EXPORT_SYMBOL_GPL(bpf_offload_dev_netdev_register);
509 595
510static int bpf_offload_notification(struct notifier_block *notifier, 596void bpf_offload_dev_netdev_unregister(struct bpf_offload_dev *offdev,
511 ulong event, void *ptr) 597 struct net_device *netdev)
512{ 598{
513 struct net_device *netdev = netdev_notifier_info_to_dev(ptr); 599 struct bpf_offload_netdev *ondev, *altdev;
600 struct bpf_offloaded_map *offmap, *mtmp;
601 struct bpf_prog_offload *offload, *ptmp;
514 602
515 ASSERT_RTNL(); 603 ASSERT_RTNL();
516 604
517 switch (event) { 605 down_write(&bpf_devs_lock);
518 case NETDEV_UNREGISTER: 606 ondev = rhashtable_lookup_fast(&offdevs, &netdev, offdevs_params);
519 /* ignore namespace changes */ 607 if (WARN_ON(!ondev))
520 if (netdev->reg_state != NETREG_UNREGISTERING) 608 goto unlock;
521 break; 609
522 610 WARN_ON(rhashtable_remove_fast(&offdevs, &ondev->l, offdevs_params));
523 down_write(&bpf_devs_lock); 611 list_del(&ondev->offdev_netdevs);
524 bpf_offload_orphan_all_progs(netdev); 612
525 bpf_offload_orphan_all_maps(netdev); 613 /* Try to move the objects to another netdev of the device */
526 up_write(&bpf_devs_lock); 614 altdev = list_first_entry_or_null(&offdev->netdevs,
527 break; 615 struct bpf_offload_netdev,
528 default: 616 offdev_netdevs);
529 break; 617 if (altdev) {
618 list_for_each_entry(offload, &ondev->progs, offloads)
619 offload->netdev = altdev->netdev;
620 list_splice_init(&ondev->progs, &altdev->progs);
621
622 list_for_each_entry(offmap, &ondev->maps, offloads)
623 offmap->netdev = altdev->netdev;
624 list_splice_init(&ondev->maps, &altdev->maps);
625 } else {
626 list_for_each_entry_safe(offload, ptmp, &ondev->progs, offloads)
627 __bpf_prog_offload_destroy(offload->prog);
628 list_for_each_entry_safe(offmap, mtmp, &ondev->maps, offloads)
629 __bpf_map_offload_destroy(offmap);
530 } 630 }
531 return NOTIFY_OK;
532}
533 631
534static struct notifier_block bpf_offload_notifier = { 632 WARN_ON(!list_empty(&ondev->progs));
535 .notifier_call = bpf_offload_notification, 633 WARN_ON(!list_empty(&ondev->maps));
536}; 634 kfree(ondev);
635unlock:
636 up_write(&bpf_devs_lock);
637}
638EXPORT_SYMBOL_GPL(bpf_offload_dev_netdev_unregister);
537 639
538static int __init bpf_offload_init(void) 640struct bpf_offload_dev *bpf_offload_dev_create(void)
539{ 641{
540 register_netdevice_notifier(&bpf_offload_notifier); 642 struct bpf_offload_dev *offdev;
541 return 0; 643 int err;
644
645 down_write(&bpf_devs_lock);
646 if (!offdevs_inited) {
647 err = rhashtable_init(&offdevs, &offdevs_params);
648 if (err)
649 return ERR_PTR(err);
650 offdevs_inited = true;
651 }
652 up_write(&bpf_devs_lock);
653
654 offdev = kzalloc(sizeof(*offdev), GFP_KERNEL);
655 if (!offdev)
656 return ERR_PTR(-ENOMEM);
657
658 INIT_LIST_HEAD(&offdev->netdevs);
659
660 return offdev;
542} 661}
662EXPORT_SYMBOL_GPL(bpf_offload_dev_create);
543 663
544subsys_initcall(bpf_offload_init); 664void bpf_offload_dev_destroy(struct bpf_offload_dev *offdev)
665{
666 WARN_ON(!list_empty(&offdev->netdevs));
667 kfree(offdev);
668}
669EXPORT_SYMBOL_GPL(bpf_offload_dev_destroy);
diff --git a/kernel/bpf/sockmap.c b/kernel/bpf/sockmap.c
index 98fb7938beea..0b38be5a955c 100644
--- a/kernel/bpf/sockmap.c
+++ b/kernel/bpf/sockmap.c
@@ -725,11 +725,8 @@ static int bpf_tcp_sendmsg_do_redirect(struct sock *sk, int send,
725{ 725{
726 bool ingress = !!(md->flags & BPF_F_INGRESS); 726 bool ingress = !!(md->flags & BPF_F_INGRESS);
727 struct smap_psock *psock; 727 struct smap_psock *psock;
728 struct scatterlist *sg;
729 int err = 0; 728 int err = 0;
730 729
731 sg = md->sg_data;
732
733 rcu_read_lock(); 730 rcu_read_lock();
734 psock = smap_psock_sk(sk); 731 psock = smap_psock_sk(sk);
735 if (unlikely(!psock)) 732 if (unlikely(!psock))
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 63aaac52a265..25e47c195874 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -5054,7 +5054,7 @@ static int check_map_prog_compatibility(struct bpf_verifier_env *env,
5054 } 5054 }
5055 5055
5056 if ((bpf_prog_is_dev_bound(prog->aux) || bpf_map_is_dev_bound(map)) && 5056 if ((bpf_prog_is_dev_bound(prog->aux) || bpf_map_is_dev_bound(map)) &&
5057 !bpf_offload_dev_match(prog, map)) { 5057 !bpf_offload_prog_map_match(prog, map)) {
5058 verbose(env, "offload device mismatch between prog and map\n"); 5058 verbose(env, "offload device mismatch between prog and map\n");
5059 return -EINVAL; 5059 return -EINVAL;
5060 } 5060 }
diff --git a/samples/bpf/bpf_load.c b/samples/bpf/bpf_load.c
index 89161c9ed466..904e775d1a44 100644
--- a/samples/bpf/bpf_load.c
+++ b/samples/bpf/bpf_load.c
@@ -107,6 +107,9 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size)
107 return -1; 107 return -1;
108 } 108 }
109 109
110 if (prog_cnt == MAX_PROGS)
111 return -1;
112
110 fd = bpf_load_program(prog_type, prog, insns_cnt, license, kern_version, 113 fd = bpf_load_program(prog_type, prog, insns_cnt, license, kern_version,
111 bpf_log_buf, BPF_LOG_BUF_SIZE); 114 bpf_log_buf, BPF_LOG_BUF_SIZE);
112 if (fd < 0) { 115 if (fd < 0) {
diff --git a/samples/bpf/test_cgrp2_sock2.c b/samples/bpf/test_cgrp2_sock2.c
index 3b5be2364975..a9277b118c33 100644
--- a/samples/bpf/test_cgrp2_sock2.c
+++ b/samples/bpf/test_cgrp2_sock2.c
@@ -51,7 +51,7 @@ int main(int argc, char **argv)
51 if (argc > 3) 51 if (argc > 3)
52 filter_id = atoi(argv[3]); 52 filter_id = atoi(argv[3]);
53 53
54 if (filter_id > prog_cnt) { 54 if (filter_id >= prog_cnt) {
55 printf("Invalid program id; program not found in file\n"); 55 printf("Invalid program id; program not found in file\n");
56 return EXIT_FAILURE; 56 return EXIT_FAILURE;
57 } 57 }
diff --git a/tools/bpf/bpftool/Makefile b/tools/bpf/bpftool/Makefile
index 6c4830e18879..74288a2197ab 100644
--- a/tools/bpf/bpftool/Makefile
+++ b/tools/bpf/bpftool/Makefile
@@ -26,7 +26,7 @@ LIBBPF = $(BPF_PATH)libbpf.a
26BPFTOOL_VERSION := $(shell make --no-print-directory -sC ../../.. kernelversion) 26BPFTOOL_VERSION := $(shell make --no-print-directory -sC ../../.. kernelversion)
27 27
28$(LIBBPF): FORCE 28$(LIBBPF): FORCE
29 $(Q)$(MAKE) -C $(BPF_DIR) OUTPUT=$(OUTPUT) $(OUTPUT)libbpf.a FEATURES_DUMP=$(FEATURE_DUMP_EXPORT) 29 $(Q)$(MAKE) -C $(BPF_DIR) OUTPUT=$(OUTPUT) $(OUTPUT)libbpf.a
30 30
31$(LIBBPF)-clean: 31$(LIBBPF)-clean:
32 $(call QUIET_CLEAN, libbpf) 32 $(call QUIET_CLEAN, libbpf)
diff --git a/tools/lib/bpf/Makefile b/tools/lib/bpf/Makefile
index 7a8e4c98ef1a..d49902e818b5 100644
--- a/tools/lib/bpf/Makefile
+++ b/tools/lib/bpf/Makefile
@@ -66,7 +66,7 @@ ifndef VERBOSE
66endif 66endif
67 67
68FEATURE_USER = .libbpf 68FEATURE_USER = .libbpf
69FEATURE_TESTS = libelf libelf-getphdrnum libelf-mmap bpf reallocarray 69FEATURE_TESTS = libelf libelf-mmap bpf reallocarray
70FEATURE_DISPLAY = libelf bpf 70FEATURE_DISPLAY = libelf bpf
71 71
72INCLUDES = -I. -I$(srctree)/tools/include -I$(srctree)/tools/arch/$(ARCH)/include/uapi -I$(srctree)/tools/include/uapi -I$(srctree)/tools/perf 72INCLUDES = -I. -I$(srctree)/tools/include -I$(srctree)/tools/arch/$(ARCH)/include/uapi -I$(srctree)/tools/include/uapi -I$(srctree)/tools/perf
@@ -116,10 +116,6 @@ ifeq ($(feature-libelf-mmap), 1)
116 override CFLAGS += -DHAVE_LIBELF_MMAP_SUPPORT 116 override CFLAGS += -DHAVE_LIBELF_MMAP_SUPPORT
117endif 117endif
118 118
119ifeq ($(feature-libelf-getphdrnum), 1)
120 override CFLAGS += -DHAVE_ELF_GETPHDRNUM_SUPPORT
121endif
122
123ifeq ($(feature-reallocarray), 0) 119ifeq ($(feature-reallocarray), 0)
124 override CFLAGS += -DCOMPAT_NEED_REALLOCARRAY 120 override CFLAGS += -DCOMPAT_NEED_REALLOCARRAY
125endif 121endif
diff --git a/tools/testing/selftests/bpf/test_offload.py b/tools/testing/selftests/bpf/test_offload.py
index b746227eaff2..d59642e70f56 100755
--- a/tools/testing/selftests/bpf/test_offload.py
+++ b/tools/testing/selftests/bpf/test_offload.py
@@ -158,8 +158,9 @@ def tool(name, args, flags, JSON=True, ns="", fail=True, include_stderr=False):
158 else: 158 else:
159 return ret, out 159 return ret, out
160 160
161def bpftool(args, JSON=True, ns="", fail=True): 161def bpftool(args, JSON=True, ns="", fail=True, include_stderr=False):
162 return tool("bpftool", args, {"json":"-p"}, JSON=JSON, ns=ns, fail=fail) 162 return tool("bpftool", args, {"json":"-p"}, JSON=JSON, ns=ns,
163 fail=fail, include_stderr=include_stderr)
163 164
164def bpftool_prog_list(expected=None, ns=""): 165def bpftool_prog_list(expected=None, ns=""):
165 _, progs = bpftool("prog show", JSON=True, ns=ns, fail=True) 166 _, progs = bpftool("prog show", JSON=True, ns=ns, fail=True)
@@ -201,6 +202,21 @@ def bpftool_map_list_wait(expected=0, n_retry=20):
201 time.sleep(0.05) 202 time.sleep(0.05)
202 raise Exception("Time out waiting for map counts to stabilize want %d, have %d" % (expected, nmaps)) 203 raise Exception("Time out waiting for map counts to stabilize want %d, have %d" % (expected, nmaps))
203 204
205def bpftool_prog_load(sample, file_name, maps=[], prog_type="xdp", dev=None,
206 fail=True, include_stderr=False):
207 args = "prog load %s %s" % (os.path.join(bpf_test_dir, sample), file_name)
208 if prog_type is not None:
209 args += " type " + prog_type
210 if dev is not None:
211 args += " dev " + dev
212 if len(maps):
213 args += " map " + " map ".join(maps)
214
215 res = bpftool(args, fail=fail, include_stderr=include_stderr)
216 if res[0] == 0:
217 files.append(file_name)
218 return res
219
204def ip(args, force=False, JSON=True, ns="", fail=True, include_stderr=False): 220def ip(args, force=False, JSON=True, ns="", fail=True, include_stderr=False):
205 if force: 221 if force:
206 args = "-force " + args 222 args = "-force " + args
@@ -307,21 +323,25 @@ class NetdevSim:
307 Class for netdevsim netdevice and its attributes. 323 Class for netdevsim netdevice and its attributes.
308 """ 324 """
309 325
310 def __init__(self): 326 def __init__(self, link=None):
327 self.link = link
328
311 self.dev = self._netdevsim_create() 329 self.dev = self._netdevsim_create()
312 devs.append(self) 330 devs.append(self)
313 331
314 self.ns = "" 332 self.ns = ""
315 333
316 self.dfs_dir = '/sys/kernel/debug/netdevsim/%s' % (self.dev['ifname']) 334 self.dfs_dir = '/sys/kernel/debug/netdevsim/%s' % (self.dev['ifname'])
335 self.sdev_dir = self.dfs_dir + '/sdev/'
317 self.dfs_refresh() 336 self.dfs_refresh()
318 337
319 def __getitem__(self, key): 338 def __getitem__(self, key):
320 return self.dev[key] 339 return self.dev[key]
321 340
322 def _netdevsim_create(self): 341 def _netdevsim_create(self):
342 link = "" if self.link is None else "link " + self.link.dev['ifname']
323 _, old = ip("link show") 343 _, old = ip("link show")
324 ip("link add sim%d type netdevsim") 344 ip("link add sim%d {link} type netdevsim".format(link=link))
325 _, new = ip("link show") 345 _, new = ip("link show")
326 346
327 for dev in new: 347 for dev in new:
@@ -345,12 +365,12 @@ class NetdevSim:
345 return data.strip() 365 return data.strip()
346 366
347 def dfs_num_bound_progs(self): 367 def dfs_num_bound_progs(self):
348 path = os.path.join(self.dfs_dir, "bpf_bound_progs") 368 path = os.path.join(self.sdev_dir, "bpf_bound_progs")
349 _, progs = cmd('ls %s' % (path)) 369 _, progs = cmd('ls %s' % (path))
350 return len(progs.split()) 370 return len(progs.split())
351 371
352 def dfs_get_bound_progs(self, expected): 372 def dfs_get_bound_progs(self, expected):
353 progs = DebugfsDir(os.path.join(self.dfs_dir, "bpf_bound_progs")) 373 progs = DebugfsDir(os.path.join(self.sdev_dir, "bpf_bound_progs"))
354 if expected is not None: 374 if expected is not None:
355 if len(progs) != expected: 375 if len(progs) != expected:
356 fail(True, "%d BPF programs bound, expected %d" % 376 fail(True, "%d BPF programs bound, expected %d" %
@@ -847,6 +867,25 @@ try:
847 sim.set_mtu(1500) 867 sim.set_mtu(1500)
848 868
849 sim.wait_for_flush() 869 sim.wait_for_flush()
870 start_test("Test non-offload XDP attaching to HW...")
871 bpftool_prog_load("sample_ret0.o", "/sys/fs/bpf/nooffload")
872 nooffload = bpf_pinned("/sys/fs/bpf/nooffload")
873 ret, _, err = sim.set_xdp(nooffload, "offload",
874 fail=False, include_stderr=True)
875 fail(ret == 0, "attached non-offloaded XDP program to HW")
876 check_extack_nsim(err, "xdpoffload of non-bound program.", args)
877 rm("/sys/fs/bpf/nooffload")
878
879 start_test("Test offload XDP attaching to drv...")
880 bpftool_prog_load("sample_ret0.o", "/sys/fs/bpf/offload",
881 dev=sim['ifname'])
882 offload = bpf_pinned("/sys/fs/bpf/offload")
883 ret, _, err = sim.set_xdp(offload, "drv", fail=False, include_stderr=True)
884 fail(ret == 0, "attached offloaded XDP program to drv")
885 check_extack(err, "using device-bound program without HW_MODE flag is not supported.", args)
886 rm("/sys/fs/bpf/offload")
887 sim.wait_for_flush()
888
850 start_test("Test XDP offload...") 889 start_test("Test XDP offload...")
851 _, _, err = sim.set_xdp(obj, "offload", verbose=True, include_stderr=True) 890 _, _, err = sim.set_xdp(obj, "offload", verbose=True, include_stderr=True)
852 ipl = sim.ip_link_show(xdp=True) 891 ipl = sim.ip_link_show(xdp=True)
@@ -1140,6 +1179,106 @@ try:
1140 fail(ret == 0, 1179 fail(ret == 0,
1141 "netdevsim didn't refuse to create a map with offload disabled") 1180 "netdevsim didn't refuse to create a map with offload disabled")
1142 1181
1182 sim.remove()
1183
1184 start_test("Test multi-dev ASIC program reuse...")
1185 simA = NetdevSim()
1186 simB1 = NetdevSim()
1187 simB2 = NetdevSim(link=simB1)
1188 simB3 = NetdevSim(link=simB1)
1189 sims = (simA, simB1, simB2, simB3)
1190 simB = (simB1, simB2, simB3)
1191
1192 bpftool_prog_load("sample_map_ret0.o", "/sys/fs/bpf/nsimA",
1193 dev=simA['ifname'])
1194 progA = bpf_pinned("/sys/fs/bpf/nsimA")
1195 bpftool_prog_load("sample_map_ret0.o", "/sys/fs/bpf/nsimB",
1196 dev=simB1['ifname'])
1197 progB = bpf_pinned("/sys/fs/bpf/nsimB")
1198
1199 simA.set_xdp(progA, "offload", JSON=False)
1200 for d in simB:
1201 d.set_xdp(progB, "offload", JSON=False)
1202
1203 start_test("Test multi-dev ASIC cross-dev replace...")
1204 ret, _ = simA.set_xdp(progB, "offload", force=True, JSON=False, fail=False)
1205 fail(ret == 0, "cross-ASIC program allowed")
1206 for d in simB:
1207 ret, _ = d.set_xdp(progA, "offload", force=True, JSON=False, fail=False)
1208 fail(ret == 0, "cross-ASIC program allowed")
1209
1210 start_test("Test multi-dev ASIC cross-dev install...")
1211 for d in sims:
1212 d.unset_xdp("offload")
1213
1214 ret, _, err = simA.set_xdp(progB, "offload", force=True, JSON=False,
1215 fail=False, include_stderr=True)
1216 fail(ret == 0, "cross-ASIC program allowed")
1217 check_extack_nsim(err, "program bound to different dev.", args)
1218 for d in simB:
1219 ret, _, err = d.set_xdp(progA, "offload", force=True, JSON=False,
1220 fail=False, include_stderr=True)
1221 fail(ret == 0, "cross-ASIC program allowed")
1222 check_extack_nsim(err, "program bound to different dev.", args)
1223
1224 start_test("Test multi-dev ASIC cross-dev map reuse...")
1225
1226 mapA = bpftool("prog show %s" % (progA))[1]["map_ids"][0]
1227 mapB = bpftool("prog show %s" % (progB))[1]["map_ids"][0]
1228
1229 ret, _ = bpftool_prog_load("sample_map_ret0.o", "/sys/fs/bpf/nsimB_",
1230 dev=simB3['ifname'],
1231 maps=["idx 0 id %d" % (mapB)],
1232 fail=False)
1233 fail(ret != 0, "couldn't reuse a map on the same ASIC")
1234 rm("/sys/fs/bpf/nsimB_")
1235
1236 ret, _, err = bpftool_prog_load("sample_map_ret0.o", "/sys/fs/bpf/nsimA_",
1237 dev=simA['ifname'],
1238 maps=["idx 0 id %d" % (mapB)],
1239 fail=False, include_stderr=True)
1240 fail(ret == 0, "could reuse a map on a different ASIC")
1241 fail(err.count("offload device mismatch between prog and map") == 0,
1242 "error message missing for cross-ASIC map")
1243
1244 ret, _, err = bpftool_prog_load("sample_map_ret0.o", "/sys/fs/bpf/nsimB_",
1245 dev=simB1['ifname'],
1246 maps=["idx 0 id %d" % (mapA)],
1247 fail=False, include_stderr=True)
1248 fail(ret == 0, "could reuse a map on a different ASIC")
1249 fail(err.count("offload device mismatch between prog and map") == 0,
1250 "error message missing for cross-ASIC map")
1251
1252 start_test("Test multi-dev ASIC cross-dev destruction...")
1253 bpftool_prog_list_wait(expected=2)
1254
1255 simA.remove()
1256 bpftool_prog_list_wait(expected=1)
1257
1258 ifnameB = bpftool("prog show %s" % (progB))[1]["dev"]["ifname"]
1259 fail(ifnameB != simB1['ifname'], "program not bound to originial device")
1260 simB1.remove()
1261 bpftool_prog_list_wait(expected=1)
1262
1263 start_test("Test multi-dev ASIC cross-dev destruction - move...")
1264 ifnameB = bpftool("prog show %s" % (progB))[1]["dev"]["ifname"]
1265 fail(ifnameB not in (simB2['ifname'], simB3['ifname']),
1266 "program not bound to remaining devices")
1267
1268 simB2.remove()
1269 ifnameB = bpftool("prog show %s" % (progB))[1]["dev"]["ifname"]
1270 fail(ifnameB != simB3['ifname'], "program not bound to remaining device")
1271
1272 simB3.remove()
1273 bpftool_prog_list_wait(expected=0)
1274
1275 start_test("Test multi-dev ASIC cross-dev destruction - orphaned...")
1276 ret, out = bpftool("prog show %s" % (progB), fail=False)
1277 fail(ret == 0, "got information about orphaned program")
1278 fail("error" not in out, "no error reported for get info on orphaned")
1279 fail(out["error"] != "can't get prog info: No such device",
1280 "wrong error for get info on orphaned")
1281
1143 print("%s: OK" % (os.path.basename(__file__))) 1282 print("%s: OK" % (os.path.basename(__file__)))
1144 1283
1145finally: 1284finally: