aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2018-07-21 02:58:30 -0400
committerDavid S. Miller <davem@davemloft.net>2018-07-21 02:58:30 -0400
commiteae249b27f0447a92b3f8c72cc45fcc4609ae00d (patch)
tree76a0df9c4ada3520bd654968afdfc8ea2b3e653a
parentc59e18b876da3e466abe5fa066aa69050f5be17c (diff)
parent8ae71e76cf1f7b8de5c75356a00840e54c93e7a5 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next
Daniel Borkmann says: ==================== pull-request: bpf-next 2018-07-20 The following pull-request contains BPF updates for your *net-next* tree. The main changes are: 1) Add sharing of BPF objects within one ASIC: this allows for reuse of the same program on multiple ports of a device, and therefore gains better code store utilization. On top of that, this now also enables sharing of maps between programs attached to different ports of a device, from Jakub. 2) Cleanup in libbpf and bpftool's Makefile to reduce unneeded feature detections and unused variable exports, also from Jakub. 3) First batch of RCU annotation fixes in prog array handling, i.e. there are several __rcu markers which are not correct as well as some of the RCU handling, from Roman. 4) Two fixes in BPF sample files related to checking of the prog_cnt upper limit from sample loader, from Dan. 5) Minor cleanup in sockmap to remove a set but not used variable, from Colin. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-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: