diff mbox series

[bpf-next,v5,5/8] xdp: Provide extack messages when prog attachment failed

Message ID 20190201001954.4130-6-maciej.fijalkowski@intel.com
State Changes Requested
Delegated to: BPF Maintainers
Headers show
Series xdp: Avoid unloading xdp prog not attached by sample | expand

Commit Message

Maciej Fijalkowski Feb. 1, 2019, 12:19 a.m. UTC
In order to provide more meaningful messages to user when the process of
loading xdp program onto network interface failed, let's add extack
messages within dev_change_xdp_fd.

Suggested-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Signed-off-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
---
 net/core/dev.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

Comments

Jakub Kicinski Feb. 1, 2019, 12:32 a.m. UTC | #1
On Fri,  1 Feb 2019 01:19:51 +0100, Maciej Fijalkowski wrote:
> In order to provide more meaningful messages to user when the process of
> loading xdp program onto network interface failed, let's add extack
> messages within dev_change_xdp_fd.
> 
> Suggested-by: Jakub Kicinski <jakub.kicinski@netronome.com>
> Signed-off-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>

Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Jakub Kicinski Feb. 1, 2019, 3:11 a.m. UTC | #2
On Fri,  1 Feb 2019 01:19:51 +0100, Maciej Fijalkowski wrote:
>  		if (__dev_xdp_query(dev, bpf_chk, XDP_QUERY_PROG) ||
> -		    __dev_xdp_query(dev, bpf_chk, XDP_QUERY_PROG_HW))
> +		    __dev_xdp_query(dev, bpf_chk, XDP_QUERY_PROG_HW)) {
> +			NL_SET_ERR_MSG(extack, "native and generic XDP can't be active at the same time");
>  			return -EEXIST;
> +		}

This reminds me, since we allowed native/driver and offloaded XDP
programs to coexist in a25717d2b604 ("xdp: support simultaneous 
driver and hw XDP attachment") I got an internal feature request 
to also allow generic and native mode.  Would anyone object to that?

Apart from a touch up to test_offload.py I don't think anything 
would care.  netlink can already carry multiple IDs, iproute2
understands it, too..

(Obviously as a follow up after this set gets merged.)
Jesper Dangaard Brouer Feb. 1, 2019, 7:02 a.m. UTC | #3
On Thu, 31 Jan 2019 19:11:01 -0800
Jakub Kicinski <jakub.kicinski@netronome.com> wrote:

> On Fri,  1 Feb 2019 01:19:51 +0100, Maciej Fijalkowski wrote:
> >  		if (__dev_xdp_query(dev, bpf_chk, XDP_QUERY_PROG) ||
> > -		    __dev_xdp_query(dev, bpf_chk, XDP_QUERY_PROG_HW))
> > +		    __dev_xdp_query(dev, bpf_chk, XDP_QUERY_PROG_HW)) {
> > +			NL_SET_ERR_MSG(extack, "native and generic XDP can't be active at the same time");
> >  			return -EEXIST;
> > +		}  
> 
> This reminds me, since we allowed native/driver and offloaded XDP
> programs to coexist in a25717d2b604 ("xdp: support simultaneous 
> driver and hw XDP attachment") I got an internal feature request 
> to also allow generic and native mode.  Would anyone object to that?

Well, I will object ;-)

I have two refactor ideas [1] and [2], that depend on not allowing
XDP-native and XDP-generic to co-exist.   The general idea is to let
XDP-native use the same fields in net_device->rx[] as XDP-generic given
they (currently) cannot co-exist. 
 The goal is (1) to move stuff out of driver code, and (2) hopefully
make it easier to implement per RXq XDP progs.

These are only refactor ideas, so if you can argue why your internal
feature request for simultaneous generic and native make more sense,
then I'm open for allowing this ?

[1] https://github.com/xdp-project/xdp-project/blob/master/areas/core/xdp_per_rxq01.org#refactor-idea-move-xdp_rxq_info-to-net_devicenetdev_rx_queue

[2] https://github.com/xdp-project/xdp-project/blob/master/areas/core/xdp_per_rxq01.org#refactor-idea-xdpbpf_prog-into-netdev_rx_queuenet_device

> Apart from a touch up to test_offload.py I don't think anything 
> would care.  netlink can already carry multiple IDs, iproute2
> understands it, too..

And we did notice you added support for HW+native:
 [3] https://github.com/xdp-project/xdp-project/blob/master/areas/core/xdp_per_rxq01.org
Jesper Dangaard Brouer Feb. 1, 2019, 7:04 a.m. UTC | #4
On Fri,  1 Feb 2019 01:19:51 +0100
Maciej Fijalkowski <maciejromanfijalkowski@gmail.com> wrote:

> In order to provide more meaningful messages to user when the process of
> loading xdp program onto network interface failed, let's add extack
> messages within dev_change_xdp_fd.
> 
> Suggested-by: Jakub Kicinski <jakub.kicinski@netronome.com>
> Signed-off-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>

Acked-by: Jesper Dangaard Brouer <brouer@redhat.com>
Jakub Kicinski Feb. 1, 2019, 6:47 p.m. UTC | #5
On Fri, 1 Feb 2019 08:02:36 +0100, Jesper Dangaard Brouer wrote:
> On Thu, 31 Jan 2019 19:11:01 -0800
> Jakub Kicinski <jakub.kicinski@netronome.com> wrote:
> 
> > On Fri,  1 Feb 2019 01:19:51 +0100, Maciej Fijalkowski wrote:  
> > >  		if (__dev_xdp_query(dev, bpf_chk, XDP_QUERY_PROG) ||
> > > -		    __dev_xdp_query(dev, bpf_chk, XDP_QUERY_PROG_HW))
> > > +		    __dev_xdp_query(dev, bpf_chk, XDP_QUERY_PROG_HW)) {
> > > +			NL_SET_ERR_MSG(extack, "native and generic XDP can't be active at the same time");
> > >  			return -EEXIST;
> > > +		}    
> > 
> > This reminds me, since we allowed native/driver and offloaded XDP
> > programs to coexist in a25717d2b604 ("xdp: support simultaneous 
> > driver and hw XDP attachment") I got an internal feature request 
> > to also allow generic and native mode.  Would anyone object to that?  
> 
> Well, I will object ;-)
> 
> I have two refactor ideas [1] and [2], that depend on not allowing
> XDP-native and XDP-generic to co-exist.   The general idea is to let
> XDP-native use the same fields in net_device->rx[] as XDP-generic given
> they (currently) cannot co-exist. 
>  The goal is (1) to move stuff out of driver code, and (2) hopefully
> make it easier to implement per RXq XDP progs.

You mean you'd use one pointer to keep the prog in the RXQ structure?
Then some from from of an extra flag will be necessary to distinguish?
I.e.:
 if (rxq->prog && rxq->is_native)
	/* got_prog */

rather than:
 if (rxq->native_prog)
	/* got_prog */
 
The cost of this reuse would be a read-only cache line per-q when XDP is
not enabled.  Right now drivers have the ability to pack the XDP prog
into a structure which is in cache already, and don't need to bring the
entire RXQ structure out (which is cache line aligned so driver authors
can't do anything to place it cleverly).

No doubt, thought, that if we allow both to be enabled we will have to
bloat the data structures.

> These are only refactor ideas, so if you can argue why your internal
> feature request for simultaneous generic and native make more sense,
> then I'm open for allowing this ?

The request was actually to enable xdpoffload and xdpgeneric at the
same time.  I'm happy to have that as another HW offload exclusive
for now :)

> [1] https://github.com/xdp-project/xdp-project/blob/master/areas/core/xdp_per_rxq01.org#refactor-idea-move-xdp_rxq_info-to-net_devicenetdev_rx_queue
> 
> [2] https://github.com/xdp-project/xdp-project/blob/master/areas/core/xdp_per_rxq01.org#refactor-idea-xdpbpf_prog-into-netdev_rx_queuenet_device
> 
> > Apart from a touch up to test_offload.py I don't think anything 
> > would care.  netlink can already carry multiple IDs, iproute2
> > understands it, too..  
> 
> And we did notice you added support for HW+native:
>  [3] https://github.com/xdp-project/xdp-project/blob/master/areas/core/xdp_per_rxq01.org
Daniel Borkmann Feb. 1, 2019, 9:33 p.m. UTC | #6
On 02/01/2019 07:47 PM, Jakub Kicinski wrote:
[...]
>> These are only refactor ideas, so if you can argue why your internal
>> feature request for simultaneous generic and native make more sense,
>> then I'm open for allowing this ?
> 
> The request was actually to enable xdpoffload and xdpgeneric at the
> same time.  I'm happy to have that as another HW offload exclusive
> for now :)

The latter is probably fine, though what's the concrete use case? :)
Reason we kept native vs generic separate is mainly so that native XDP
drivers are discouraged to punt missing features to generic hook instead
of properly implementing them in native mode.

Thanks,
Daniel
Jakub Kicinski Feb. 1, 2019, 9:44 p.m. UTC | #7
On Fri, 1 Feb 2019 22:33:22 +0100, Daniel Borkmann wrote:
> On 02/01/2019 07:47 PM, Jakub Kicinski wrote:
> >> These are only refactor ideas, so if you can argue why your internal
> >> feature request for simultaneous generic and native make more sense,
> >> then I'm open for allowing this ?  
> > 
> > The request was actually to enable xdpoffload and xdpgeneric at the
> > same time.  I'm happy to have that as another HW offload exclusive
> > for now :)  
> 
> The latter is probably fine, though what's the concrete use case? :)

I think it was more of a "I expected this to work, since driver+offload
worked" than a feature request.  Looking back at it it was filed as bug
I converted it to feature.

> Reason we kept native vs generic separate is mainly so that native XDP
> drivers are discouraged to punt missing features to generic hook instead
> of properly implementing them in native mode.

Agreed, although one could make a counter argument that the
performance should be a strong enough incentive and we shouldn't stop
people for experimenting and prototyping :)  The code change looks
simple enough:

diff --git a/net/core/dev.c b/net/core/dev.c
index 8e276e0192a1..ce4880e5e95d 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -7976,11 +7976,13 @@ int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
        enum bpf_netdev_command query;
        struct bpf_prog *prog = NULL;
        bpf_op_t bpf_op, bpf_chk;
+       bool offload;
        int err;
 
        ASSERT_RTNL();
 
-       query = flags & XDP_FLAGS_HW_MODE ? XDP_QUERY_PROG_HW : XDP_QUERY_PROG;
+       offload = flags & XDP_FLAGS_HW_MODE;
+       query = offload ? XDP_QUERY_PROG_HW : XDP_QUERY_PROG;
 
        bpf_op = bpf_chk = ops->ndo_bpf;
        if (!bpf_op && (flags & (XDP_FLAGS_DRV_MODE | XDP_FLAGS_HW_MODE)))
@@ -7991,8 +7993,7 @@ int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
                bpf_chk = generic_xdp_install;
 
        if (fd >= 0) {
-               if (__dev_xdp_query(dev, bpf_chk, XDP_QUERY_PROG) ||
-                   __dev_xdp_query(dev, bpf_chk, XDP_QUERY_PROG_HW))
+               if (!offload && __dev_xdp_query(dev, bpf_chk, XDP_QUERY_PROG))
                        return -EEXIST;
                if ((flags & XDP_FLAGS_UPDATE_IF_NOEXIST) &&
                    __dev_xdp_query(dev, bpf_op, query))
@@ -8003,8 +8004,7 @@ int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
                if (IS_ERR(prog))
                        return PTR_ERR(prog);
 
-               if (!(flags & XDP_FLAGS_HW_MODE) &&
-                   bpf_prog_is_dev_bound(prog->aux)) {
+               if (!offload && bpf_prog_is_dev_bound(prog->aux)) {
                        NL_SET_ERR_MSG(extack, "using device-bound program without HW_MODE flag is not supported");
                        bpf_prog_put(prog);
                        return -EINVAL;

Do you think we shouldn't do it?
Daniel Borkmann Feb. 1, 2019, 11:14 p.m. UTC | #8
On 02/01/2019 10:44 PM, Jakub Kicinski wrote:
[...]
> diff --git a/net/core/dev.c b/net/core/dev.c
> index 8e276e0192a1..ce4880e5e95d 100644
> --- a/net/core/dev.c
> +++ b/net/core/dev.c
> @@ -7976,11 +7976,13 @@ int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
>         enum bpf_netdev_command query;
>         struct bpf_prog *prog = NULL;
>         bpf_op_t bpf_op, bpf_chk;
> +       bool offload;
>         int err;
>  
>         ASSERT_RTNL();
>  
> -       query = flags & XDP_FLAGS_HW_MODE ? XDP_QUERY_PROG_HW : XDP_QUERY_PROG;
> +       offload = flags & XDP_FLAGS_HW_MODE;
> +       query = offload ? XDP_QUERY_PROG_HW : XDP_QUERY_PROG;
>  
>         bpf_op = bpf_chk = ops->ndo_bpf;
>         if (!bpf_op && (flags & (XDP_FLAGS_DRV_MODE | XDP_FLAGS_HW_MODE)))
> @@ -7991,8 +7993,7 @@ int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
>                 bpf_chk = generic_xdp_install;
>  
>         if (fd >= 0) {
> -               if (__dev_xdp_query(dev, bpf_chk, XDP_QUERY_PROG) ||
> -                   __dev_xdp_query(dev, bpf_chk, XDP_QUERY_PROG_HW))
> +               if (!offload && __dev_xdp_query(dev, bpf_chk, XDP_QUERY_PROG))
>                         return -EEXIST;
>                 if ((flags & XDP_FLAGS_UPDATE_IF_NOEXIST) &&
>                     __dev_xdp_query(dev, bpf_op, query))
> @@ -8003,8 +8004,7 @@ int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
>                 if (IS_ERR(prog))
>                         return PTR_ERR(prog);
>  
> -               if (!(flags & XDP_FLAGS_HW_MODE) &&
> -                   bpf_prog_is_dev_bound(prog->aux)) {
> +               if (!offload && bpf_prog_is_dev_bound(prog->aux)) {
>                         NL_SET_ERR_MSG(extack, "using device-bound program without HW_MODE flag is not supported");
>                         bpf_prog_put(prog);
>                         return -EINVAL;
> 
> Do you think we shouldn't do it?

Yeah that looks good to me, lets do it. At least this would allow for
prototyping in combination with HW mode till full support of a feature
has landed properly in native mode.

Thanks,
Daniel
diff mbox series

Patch

diff --git a/net/core/dev.c b/net/core/dev.c
index 8e276e0192a1..bfa4be42afff 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -7983,8 +7983,10 @@  int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
 	query = flags & XDP_FLAGS_HW_MODE ? XDP_QUERY_PROG_HW : XDP_QUERY_PROG;
 
 	bpf_op = bpf_chk = ops->ndo_bpf;
-	if (!bpf_op && (flags & (XDP_FLAGS_DRV_MODE | XDP_FLAGS_HW_MODE)))
+	if (!bpf_op && (flags & (XDP_FLAGS_DRV_MODE | XDP_FLAGS_HW_MODE))) {
+		NL_SET_ERR_MSG(extack, "underlying driver does not support XDP in native mode");
 		return -EOPNOTSUPP;
+	}
 	if (!bpf_op || (flags & XDP_FLAGS_SKB_MODE))
 		bpf_op = generic_xdp_install;
 	if (bpf_op == bpf_chk)
@@ -7992,11 +7994,15 @@  int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
 
 	if (fd >= 0) {
 		if (__dev_xdp_query(dev, bpf_chk, XDP_QUERY_PROG) ||
-		    __dev_xdp_query(dev, bpf_chk, XDP_QUERY_PROG_HW))
+		    __dev_xdp_query(dev, bpf_chk, XDP_QUERY_PROG_HW)) {
+			NL_SET_ERR_MSG(extack, "native and generic XDP can't be active at the same time");
 			return -EEXIST;
+		}
 		if ((flags & XDP_FLAGS_UPDATE_IF_NOEXIST) &&
-		    __dev_xdp_query(dev, bpf_op, query))
+		    __dev_xdp_query(dev, bpf_op, query)) {
+			NL_SET_ERR_MSG(extack, "XDP program already attached");
 			return -EBUSY;
+		}
 
 		prog = bpf_prog_get_type_dev(fd, BPF_PROG_TYPE_XDP,
 					     bpf_op == ops->ndo_bpf);