aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJakub Kicinski <jakub.kicinski@netronome.com>2018-07-11 23:36:40 -0400
committerDaniel Borkmann <daniel@iogearbox.net>2018-07-13 14:26:35 -0400
commit05296620f6d14dce0030b87e1e57891a770fb65c (patch)
treef66b194fc4fd081abce58cd6dd97c2bd95ffa842
parent6b8675897338f874c41612655a85d8e10cdb23d8 (diff)
xdp: factor out common program/flags handling from drivers
Basic operations drivers perform during xdp setup and query can be moved to helpers in the core. Encapsulate program and flags into a structure and add helpers. Note that the structure is intended as the "main" program information source in the driver. Most drivers will additionally place the program pointer in their fast path or ring structures. The helpers don't have a huge impact now, but they will decrease the code duplication when programs can be installed in HW and driver at the same time. Encapsulating the basic operations in helpers will hopefully also reduce the number of changes to drivers which adopt them. Helpers could really be static inline, but they depend on definition of struct netdev_bpf which means they'd have to be placed in netdevice.h, an already 4500 line header. Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com> Reviewed-by: Quentin Monnet <quentin.monnet@netronome.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net.h6
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net_common.c28
-rw-r--r--drivers/net/netdevsim/bpf.c16
-rw-r--r--drivers/net/netdevsim/netdevsim.h4
-rw-r--r--include/net/xdp.h13
-rw-r--r--net/core/xdp.c34
-rwxr-xr-xtools/testing/selftests/bpf/test_offload.py4
7 files changed, 67 insertions, 38 deletions
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net.h b/drivers/net/ethernet/netronome/nfp/nfp_net.h
index 2a71a9ffd095..2021dda595b7 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net.h
@@ -553,8 +553,7 @@ struct nfp_net_dp {
553 * @rss_cfg: RSS configuration 553 * @rss_cfg: RSS configuration
554 * @rss_key: RSS secret key 554 * @rss_key: RSS secret key
555 * @rss_itbl: RSS indirection table 555 * @rss_itbl: RSS indirection table
556 * @xdp_flags: Flags with which XDP prog was loaded 556 * @xdp: Information about the attached XDP program
557 * @xdp_prog: XDP prog (for ctrl path, both DRV and HW modes)
558 * @max_r_vecs: Number of allocated interrupt vectors for RX/TX 557 * @max_r_vecs: Number of allocated interrupt vectors for RX/TX
559 * @max_tx_rings: Maximum number of TX rings supported by the Firmware 558 * @max_tx_rings: Maximum number of TX rings supported by the Firmware
560 * @max_rx_rings: Maximum number of RX rings supported by the Firmware 559 * @max_rx_rings: Maximum number of RX rings supported by the Firmware
@@ -610,8 +609,7 @@ struct nfp_net {
610 u8 rss_key[NFP_NET_CFG_RSS_KEY_SZ]; 609 u8 rss_key[NFP_NET_CFG_RSS_KEY_SZ];
611 u8 rss_itbl[NFP_NET_CFG_RSS_ITBL_SZ]; 610 u8 rss_itbl[NFP_NET_CFG_RSS_ITBL_SZ];
612 611
613 u32 xdp_flags; 612 struct xdp_attachment_info xdp;
614 struct bpf_prog *xdp_prog;
615 613
616 unsigned int max_tx_rings; 614 unsigned int max_tx_rings;
617 unsigned int max_rx_rings; 615 unsigned int max_rx_rings;
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index d20714598613..4bb589dbffbc 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -3417,34 +3417,29 @@ nfp_net_xdp_setup_drv(struct nfp_net *nn, struct bpf_prog *prog,
3417 return nfp_net_ring_reconfig(nn, dp, extack); 3417 return nfp_net_ring_reconfig(nn, dp, extack);
3418} 3418}
3419 3419
3420static int 3420static int nfp_net_xdp_setup(struct nfp_net *nn, struct netdev_bpf *bpf)
3421nfp_net_xdp_setup(struct nfp_net *nn, struct bpf_prog *prog, u32 flags,
3422 struct netlink_ext_ack *extack)
3423{ 3421{
3424 struct bpf_prog *drv_prog, *offload_prog; 3422 struct bpf_prog *drv_prog, *offload_prog;
3425 int err; 3423 int err;
3426 3424
3427 if (nn->xdp_prog && (flags ^ nn->xdp_flags) & XDP_FLAGS_MODES) 3425 if (!xdp_attachment_flags_ok(&nn->xdp, bpf))
3428 return -EBUSY; 3426 return -EBUSY;
3429 3427
3430 /* Load both when no flags set to allow easy activation of driver path 3428 /* Load both when no flags set to allow easy activation of driver path
3431 * when program is replaced by one which can't be offloaded. 3429 * when program is replaced by one which can't be offloaded.
3432 */ 3430 */
3433 drv_prog = flags & XDP_FLAGS_HW_MODE ? NULL : prog; 3431 drv_prog = bpf->flags & XDP_FLAGS_HW_MODE ? NULL : bpf->prog;
3434 offload_prog = flags & XDP_FLAGS_DRV_MODE ? NULL : prog; 3432 offload_prog = bpf->flags & XDP_FLAGS_DRV_MODE ? NULL : bpf->prog;
3435 3433
3436 err = nfp_net_xdp_setup_drv(nn, drv_prog, extack); 3434 err = nfp_net_xdp_setup_drv(nn, drv_prog, bpf->extack);
3437 if (err) 3435 if (err)
3438 return err; 3436 return err;
3439 3437
3440 err = nfp_app_xdp_offload(nn->app, nn, offload_prog, extack); 3438 err = nfp_app_xdp_offload(nn->app, nn, offload_prog, bpf->extack);
3441 if (err && flags & XDP_FLAGS_HW_MODE) 3439 if (err && bpf->flags & XDP_FLAGS_HW_MODE)
3442 return err; 3440 return err;
3443 3441
3444 if (nn->xdp_prog) 3442 xdp_attachment_setup(&nn->xdp, bpf);
3445 bpf_prog_put(nn->xdp_prog);
3446 nn->xdp_prog = prog;
3447 nn->xdp_flags = flags;
3448 3443
3449 return 0; 3444 return 0;
3450} 3445}
@@ -3456,12 +3451,9 @@ static int nfp_net_xdp(struct net_device *netdev, struct netdev_bpf *xdp)
3456 switch (xdp->command) { 3451 switch (xdp->command) {
3457 case XDP_SETUP_PROG: 3452 case XDP_SETUP_PROG:
3458 case XDP_SETUP_PROG_HW: 3453 case XDP_SETUP_PROG_HW:
3459 return nfp_net_xdp_setup(nn, xdp->prog, xdp->flags, 3454 return nfp_net_xdp_setup(nn, xdp);
3460 xdp->extack);
3461 case XDP_QUERY_PROG: 3455 case XDP_QUERY_PROG:
3462 xdp->prog_id = nn->xdp_prog ? nn->xdp_prog->aux->id : 0; 3456 return xdp_attachment_query(&nn->xdp, xdp);
3463 xdp->prog_flags = nn->xdp_prog ? nn->xdp_flags : 0;
3464 return 0;
3465 default: 3457 default:
3466 return nfp_app_bpf(nn->app, nn, xdp); 3458 return nfp_app_bpf(nn->app, nn, xdp);
3467 } 3459 }
diff --git a/drivers/net/netdevsim/bpf.c b/drivers/net/netdevsim/bpf.c
index 712e6f918065..c485d97b5df4 100644
--- a/drivers/net/netdevsim/bpf.c
+++ b/drivers/net/netdevsim/bpf.c
@@ -199,10 +199,8 @@ static int nsim_xdp_set_prog(struct netdevsim *ns, struct netdev_bpf *bpf)
199{ 199{
200 int err; 200 int err;
201 201
202 if (ns->xdp_prog && (bpf->flags ^ ns->xdp_flags) & XDP_FLAGS_MODES) { 202 if (!xdp_attachment_flags_ok(&ns->xdp, bpf))
203 NSIM_EA(bpf->extack, "program loaded with different flags");
204 return -EBUSY; 203 return -EBUSY;
205 }
206 204
207 if (bpf->command == XDP_SETUP_PROG && !ns->bpf_xdpdrv_accept) { 205 if (bpf->command == XDP_SETUP_PROG && !ns->bpf_xdpdrv_accept) {
208 NSIM_EA(bpf->extack, "driver XDP disabled in DebugFS"); 206 NSIM_EA(bpf->extack, "driver XDP disabled in DebugFS");
@@ -219,11 +217,7 @@ static int nsim_xdp_set_prog(struct netdevsim *ns, struct netdev_bpf *bpf)
219 return err; 217 return err;
220 } 218 }
221 219
222 if (ns->xdp_prog) 220 xdp_attachment_setup(&ns->xdp, bpf);
223 bpf_prog_put(ns->xdp_prog);
224
225 ns->xdp_prog = bpf->prog;
226 ns->xdp_flags = bpf->flags;
227 221
228 if (!bpf->prog) 222 if (!bpf->prog)
229 ns->xdp_prog_mode = XDP_ATTACHED_NONE; 223 ns->xdp_prog_mode = XDP_ATTACHED_NONE;
@@ -567,9 +561,7 @@ int nsim_bpf(struct net_device *dev, struct netdev_bpf *bpf)
567 nsim_bpf_destroy_prog(bpf->offload.prog); 561 nsim_bpf_destroy_prog(bpf->offload.prog);
568 return 0; 562 return 0;
569 case XDP_QUERY_PROG: 563 case XDP_QUERY_PROG:
570 bpf->prog_id = ns->xdp_prog ? ns->xdp_prog->aux->id : 0; 564 return xdp_attachment_query(&ns->xdp, bpf);
571 bpf->prog_flags = ns->xdp_prog ? ns->xdp_flags : 0;
572 return 0;
573 case XDP_SETUP_PROG: 565 case XDP_SETUP_PROG:
574 err = nsim_setup_prog_checks(ns, bpf); 566 err = nsim_setup_prog_checks(ns, bpf);
575 if (err) 567 if (err)
@@ -636,6 +628,6 @@ void nsim_bpf_uninit(struct netdevsim *ns)
636{ 628{
637 WARN_ON(!list_empty(&ns->bpf_bound_progs)); 629 WARN_ON(!list_empty(&ns->bpf_bound_progs));
638 WARN_ON(!list_empty(&ns->bpf_bound_maps)); 630 WARN_ON(!list_empty(&ns->bpf_bound_maps));
639 WARN_ON(ns->xdp_prog); 631 WARN_ON(ns->xdp.prog);
640 WARN_ON(ns->bpf_offloaded); 632 WARN_ON(ns->bpf_offloaded);
641} 633}
diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h
index d8a7cc995e88..69ffb4a2d14b 100644
--- a/drivers/net/netdevsim/netdevsim.h
+++ b/drivers/net/netdevsim/netdevsim.h
@@ -18,6 +18,7 @@
18#include <linux/list.h> 18#include <linux/list.h>
19#include <linux/netdevice.h> 19#include <linux/netdevice.h>
20#include <linux/u64_stats_sync.h> 20#include <linux/u64_stats_sync.h>
21#include <net/xdp.h>
21 22
22#define DRV_NAME "netdevsim" 23#define DRV_NAME "netdevsim"
23 24
@@ -67,9 +68,8 @@ struct netdevsim {
67 struct bpf_prog *bpf_offloaded; 68 struct bpf_prog *bpf_offloaded;
68 u32 bpf_offloaded_id; 69 u32 bpf_offloaded_id;
69 70
70 u32 xdp_flags; 71 struct xdp_attachment_info xdp;
71 int xdp_prog_mode; 72 int xdp_prog_mode;
72 struct bpf_prog *xdp_prog;
73 73
74 u32 prog_id_gen; 74 u32 prog_id_gen;
75 75
diff --git a/include/net/xdp.h b/include/net/xdp.h
index 2deea7166a34..fcb033f51d8c 100644
--- a/include/net/xdp.h
+++ b/include/net/xdp.h
@@ -144,4 +144,17 @@ xdp_data_meta_unsupported(const struct xdp_buff *xdp)
144 return unlikely(xdp->data_meta > xdp->data); 144 return unlikely(xdp->data_meta > xdp->data);
145} 145}
146 146
147struct xdp_attachment_info {
148 struct bpf_prog *prog;
149 u32 flags;
150};
151
152struct netdev_bpf;
153int xdp_attachment_query(struct xdp_attachment_info *info,
154 struct netdev_bpf *bpf);
155bool xdp_attachment_flags_ok(struct xdp_attachment_info *info,
156 struct netdev_bpf *bpf);
157void xdp_attachment_setup(struct xdp_attachment_info *info,
158 struct netdev_bpf *bpf);
159
147#endif /* __LINUX_NET_XDP_H__ */ 160#endif /* __LINUX_NET_XDP_H__ */
diff --git a/net/core/xdp.c b/net/core/xdp.c
index 31c58719b5a9..57285383ed00 100644
--- a/net/core/xdp.c
+++ b/net/core/xdp.c
@@ -3,8 +3,11 @@
3 * Copyright (c) 2017 Jesper Dangaard Brouer, Red Hat Inc. 3 * Copyright (c) 2017 Jesper Dangaard Brouer, Red Hat Inc.
4 * Released under terms in GPL version 2. See COPYING. 4 * Released under terms in GPL version 2. See COPYING.
5 */ 5 */
6#include <linux/bpf.h>
7#include <linux/filter.h>
6#include <linux/types.h> 8#include <linux/types.h>
7#include <linux/mm.h> 9#include <linux/mm.h>
10#include <linux/netdevice.h>
8#include <linux/slab.h> 11#include <linux/slab.h>
9#include <linux/idr.h> 12#include <linux/idr.h>
10#include <linux/rhashtable.h> 13#include <linux/rhashtable.h>
@@ -370,3 +373,34 @@ void xdp_return_buff(struct xdp_buff *xdp)
370 __xdp_return(xdp->data, &xdp->rxq->mem, true, xdp->handle); 373 __xdp_return(xdp->data, &xdp->rxq->mem, true, xdp->handle);
371} 374}
372EXPORT_SYMBOL_GPL(xdp_return_buff); 375EXPORT_SYMBOL_GPL(xdp_return_buff);
376
377int xdp_attachment_query(struct xdp_attachment_info *info,
378 struct netdev_bpf *bpf)
379{
380 bpf->prog_id = info->prog ? info->prog->aux->id : 0;
381 bpf->prog_flags = info->prog ? info->flags : 0;
382 return 0;
383}
384EXPORT_SYMBOL_GPL(xdp_attachment_query);
385
386bool xdp_attachment_flags_ok(struct xdp_attachment_info *info,
387 struct netdev_bpf *bpf)
388{
389 if (info->prog && (bpf->flags ^ info->flags) & XDP_FLAGS_MODES) {
390 NL_SET_ERR_MSG(bpf->extack,
391 "program loaded with different flags");
392 return false;
393 }
394 return true;
395}
396EXPORT_SYMBOL_GPL(xdp_attachment_flags_ok);
397
398void xdp_attachment_setup(struct xdp_attachment_info *info,
399 struct netdev_bpf *bpf)
400{
401 if (info->prog)
402 bpf_prog_put(info->prog);
403 info->prog = bpf->prog;
404 info->flags = bpf->flags;
405}
406EXPORT_SYMBOL_GPL(xdp_attachment_setup);
diff --git a/tools/testing/selftests/bpf/test_offload.py b/tools/testing/selftests/bpf/test_offload.py
index f8d9bd81d9a4..40401e9e9351 100755
--- a/tools/testing/selftests/bpf/test_offload.py
+++ b/tools/testing/selftests/bpf/test_offload.py
@@ -821,7 +821,7 @@ try:
821 ret, _, err = sim.set_xdp(obj, "", force=True, 821 ret, _, err = sim.set_xdp(obj, "", force=True,
822 fail=False, include_stderr=True) 822 fail=False, include_stderr=True)
823 fail(ret == 0, "Replaced XDP program with a program in different mode") 823 fail(ret == 0, "Replaced XDP program with a program in different mode")
824 check_extack_nsim(err, "program loaded with different flags.", args) 824 check_extack(err, "program loaded with different flags.", args)
825 825
826 start_test("Test XDP prog remove with bad flags...") 826 start_test("Test XDP prog remove with bad flags...")
827 ret, _, err = sim.unset_xdp("offload", force=True, 827 ret, _, err = sim.unset_xdp("offload", force=True,
@@ -831,7 +831,7 @@ try:
831 ret, _, err = sim.unset_xdp("", force=True, 831 ret, _, err = sim.unset_xdp("", force=True,
832 fail=False, include_stderr=True) 832 fail=False, include_stderr=True)
833 fail(ret == 0, "Removed program with a bad mode") 833 fail(ret == 0, "Removed program with a bad mode")
834 check_extack_nsim(err, "program loaded with different flags.", args) 834 check_extack(err, "program loaded with different flags.", args)
835 835
836 start_test("Test MTU restrictions...") 836 start_test("Test MTU restrictions...")
837 ret, _ = sim.set_mtu(9000, fail=False) 837 ret, _ = sim.set_mtu(9000, fail=False)