diff mbox series

[RFC,bpf-next,2/8] net: introduce XDP features flag

Message ID 43c340d440d8a87396198b301c5ffbf5ab56f304.1671462950.git.lorenzo@kernel.org
State RFC
Headers show
Series xdp: introduce xdp-feature support | expand

Commit Message

Lorenzo Bianconi Dec. 19, 2022, 3:41 p.m. UTC
From: Marek Majtyka <alardam@gmail.com>

Implement support for checking what kind of XDP features a netdev
supports. Previously, there was no way to do this other than to try to
create an AF_XDP socket on the interface or load an XDP program and see
if it worked. This commit changes this by adding a new variable which
describes all xdp supported functions on pretty detailed level:

 - aborted
 - drop
 - pass
 - tx
 - redirect
 - sock_zerocopy
 - hw_offload
 - redirect_target
 - tx_lock
 - frag_rx
 - frag_target

Zerocopy mode requires that redirect XDP operation is implemented in a
driver and the driver supports also zero copy mode. Full mode requires
that all XDP operation are implemented in the driver. Basic mode is just
full mode without redirect operation. Frag target requires
redirect_target one is supported by the driver.

Initially, these new flags are disabled for all drivers by default.

Co-developed-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Marek Majtyka <alardam@gmail.com>
---
 .../networking/netdev-xdp-features.rst        | 60 +++++++++++++++++
 include/linux/netdevice.h                     |  2 +
 include/linux/xdp_features.h                  | 64 +++++++++++++++++++
 include/uapi/linux/if_link.h                  |  7 ++
 include/uapi/linux/xdp_features.h             | 34 ++++++++++
 net/core/rtnetlink.c                          | 34 ++++++++++
 tools/include/uapi/linux/if_link.h            |  7 ++
 tools/include/uapi/linux/xdp_features.h       | 34 ++++++++++
 8 files changed, 242 insertions(+)
 create mode 100644 Documentation/networking/netdev-xdp-features.rst
 create mode 100644 include/linux/xdp_features.h
 create mode 100644 include/uapi/linux/xdp_features.h
 create mode 100644 tools/include/uapi/linux/xdp_features.h

Comments

Stanislav Fomichev Dec. 19, 2022, 8:03 p.m. UTC | #1
On 12/19, Lorenzo Bianconi wrote:
> From: Marek Majtyka <alardam@gmail.com>

> Implement support for checking what kind of XDP features a netdev
> supports. Previously, there was no way to do this other than to try to
> create an AF_XDP socket on the interface or load an XDP program and see
> if it worked. This commit changes this by adding a new variable which
> describes all xdp supported functions on pretty detailed level:

>   - aborted
>   - drop
>   - pass
>   - tx
>   - redirect
>   - sock_zerocopy
>   - hw_offload
>   - redirect_target
>   - tx_lock
>   - frag_rx
>   - frag_target

> Zerocopy mode requires that redirect XDP operation is implemented in a
> driver and the driver supports also zero copy mode. Full mode requires
> that all XDP operation are implemented in the driver. Basic mode is just
> full mode without redirect operation. Frag target requires
> redirect_target one is supported by the driver.

Can you share more about _why_ is it needed? If we can already obtain
most of these signals via probing, why export the flags?

> Initially, these new flags are disabled for all drivers by default.

> Co-developed-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
> Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
> Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org>
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> Signed-off-by: Marek Majtyka <alardam@gmail.com>
> ---
>   .../networking/netdev-xdp-features.rst        | 60 +++++++++++++++++
>   include/linux/netdevice.h                     |  2 +
>   include/linux/xdp_features.h                  | 64 +++++++++++++++++++
>   include/uapi/linux/if_link.h                  |  7 ++
>   include/uapi/linux/xdp_features.h             | 34 ++++++++++
>   net/core/rtnetlink.c                          | 34 ++++++++++
>   tools/include/uapi/linux/if_link.h            |  7 ++
>   tools/include/uapi/linux/xdp_features.h       | 34 ++++++++++
>   8 files changed, 242 insertions(+)
>   create mode 100644 Documentation/networking/netdev-xdp-features.rst
>   create mode 100644 include/linux/xdp_features.h
>   create mode 100644 include/uapi/linux/xdp_features.h
>   create mode 100644 tools/include/uapi/linux/xdp_features.h

> diff --git a/Documentation/networking/netdev-xdp-features.rst  
> b/Documentation/networking/netdev-xdp-features.rst
> new file mode 100644
> index 000000000000..1dc803fe72dd
> --- /dev/null
> +++ b/Documentation/networking/netdev-xdp-features.rst
> @@ -0,0 +1,60 @@
> +.. SPDX-License-Identifier: GPL-2.0
> +
> +=====================
> +Netdev XDP features
> +=====================
> +
> + * XDP FEATURES FLAGS
> +
> +Following netdev xdp features flags can be retrieved over route netlink
> +interface (compact form) - the same way as netdev feature flags.
> +These features flags are read only and cannot be change at runtime.
> +
> +*  XDP_ABORTED
> +
> +This feature informs if netdev supports xdp aborted action.
> +
> +*  XDP_DROP
> +
> +This feature informs if netdev supports xdp drop action.
> +
> +*  XDP_PASS
> +
> +This feature informs if netdev supports xdp pass action.
> +
> +*  XDP_TX
> +
> +This feature informs if netdev supports xdp tx action.
> +
> +*  XDP_REDIRECT
> +
> +This feature informs if netdev supports xdp redirect action.
> +It assumes the all beforehand mentioned flags are enabled.
> +
> +*  XDP_SOCK_ZEROCOPY
> +
> +This feature informs if netdev driver supports xdp zero copy.
> +It assumes the all beforehand mentioned flags are enabled.
> +
> +*  XDP_HW_OFFLOAD
> +
> +This feature informs if netdev driver supports xdp hw oflloading.
> +
> +*  XDP_TX_LOCK
> +
> +This feature informs if netdev ndo_xdp_xmit function requires locking.
> +
> +*  XDP_REDIRECT_TARGET
> +
> +This feature informs if netdev implements ndo_xdp_xmit callback.
> +
> +*  XDP_FRAG_RX
> +
> +This feature informs if netdev implements non-linear xdp buff support in
> +the driver napi callback.
> +
> +*  XDP_FRAG_TARGET
> +
> +This feature informs if netdev implements non-linear xdp buff support in
> +ndo_xdp_xmit callback. XDP_FRAG_TARGET requires XDP_REDIRECT_TARGET is  
> properly
> +supported.
> diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
> index aad12a179e54..ae5a8564383b 100644
> --- a/include/linux/netdevice.h
> +++ b/include/linux/netdevice.h
> @@ -43,6 +43,7 @@
>   #include <net/xdp.h>

>   #include <linux/netdev_features.h>
> +#include <linux/xdp_features.h>
>   #include <linux/neighbour.h>
>   #include <uapi/linux/netdevice.h>
>   #include <uapi/linux/if_bonding.h>
> @@ -2362,6 +2363,7 @@ struct net_device {
>   	struct rtnl_hw_stats64	*offload_xstats_l3;

>   	struct devlink_port	*devlink_port;
> +	xdp_features_t		xdp_features;
>   };
>   #define to_net_dev(d) container_of(d, struct net_device, dev)

> diff --git a/include/linux/xdp_features.h b/include/linux/xdp_features.h
> new file mode 100644
> index 000000000000..4e72a86ef329
> --- /dev/null
> +++ b/include/linux/xdp_features.h
> @@ -0,0 +1,64 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * Network device xdp features.
> + */
> +#ifndef _LINUX_XDP_FEATURES_H
> +#define _LINUX_XDP_FEATURES_H
> +
> +#include <linux/types.h>
> +#include <linux/bitops.h>
> +#include <asm/byteorder.h>
> +#include <uapi/linux/xdp_features.h>
> +
> +typedef u32 xdp_features_t;
> +
> +#define __XDP_F_BIT(bit)	((xdp_features_t)1 << (bit))
> +#define __XDP_F(name)		__XDP_F_BIT(XDP_F_##name##_BIT)
> +
> +#define XDP_F_ABORTED		__XDP_F(ABORTED)
> +#define XDP_F_DROP		__XDP_F(DROP)
> +#define XDP_F_PASS		__XDP_F(PASS)
> +#define XDP_F_TX		__XDP_F(TX)
> +#define XDP_F_REDIRECT		__XDP_F(REDIRECT)
> +#define XDP_F_REDIRECT_TARGET	__XDP_F(REDIRECT_TARGET)
> +#define XDP_F_SOCK_ZEROCOPY	__XDP_F(SOCK_ZEROCOPY)
> +#define XDP_F_HW_OFFLOAD	__XDP_F(HW_OFFLOAD)
> +#define XDP_F_TX_LOCK		__XDP_F(TX_LOCK)
> +#define XDP_F_FRAG_RX		__XDP_F(FRAG_RX)
> +#define XDP_F_FRAG_TARGET	__XDP_F(FRAG_TARGET)
> +
> +#define XDP_F_BASIC		(XDP_F_ABORTED | XDP_F_DROP |	\
> +				 XDP_F_PASS | XDP_F_TX)
> +
> +#define XDP_F_FULL		(XDP_F_BASIC | XDP_F_REDIRECT)
> +
> +#define XDP_F_FULL_ZC		(XDP_F_FULL | XDP_F_SOCK_ZEROCOPY)
> +
> +#define XDP_FEATURES_ABORTED_STR		"xdp-aborted"
> +#define XDP_FEATURES_DROP_STR			"xdp-drop"
> +#define XDP_FEATURES_PASS_STR			"xdp-pass"
> +#define XDP_FEATURES_TX_STR			"xdp-tx"
> +#define XDP_FEATURES_REDIRECT_STR		"xdp-redirect"
> +#define XDP_FEATURES_REDIRECT_TARGET_STR	"xdp-redirect-target"
> +#define XDP_FEATURES_SOCK_ZEROCOPY_STR		"xdp-sock-zerocopy"
> +#define XDP_FEATURES_HW_OFFLOAD_STR		"xdp-hw-offload"
> +#define XDP_FEATURES_TX_LOCK_STR		"xdp-tx-lock"
> +#define XDP_FEATURES_FRAG_RX_STR		"xdp-frag-rx"
> +#define XDP_FEATURES_FRAG_TARGET_STR		"xdp-frag-target"
> +
> +#define DECLARE_XDP_FEATURES_TABLE(name, length)				\
> +	const char name[][length] = {						\
> +		[XDP_F_ABORTED_BIT] = XDP_FEATURES_ABORTED_STR,			\
> +		[XDP_F_DROP_BIT] = XDP_FEATURES_DROP_STR,			\
> +		[XDP_F_PASS_BIT] = XDP_FEATURES_PASS_STR,			\
> +		[XDP_F_TX_BIT] = XDP_FEATURES_TX_STR,				\
> +		[XDP_F_REDIRECT_BIT] = XDP_FEATURES_REDIRECT_STR,		\
> +		[XDP_F_REDIRECT_TARGET_BIT] = XDP_FEATURES_REDIRECT_TARGET_STR,	\
> +		[XDP_F_SOCK_ZEROCOPY_BIT] = XDP_FEATURES_SOCK_ZEROCOPY_STR,	\
> +		[XDP_F_HW_OFFLOAD_BIT] = XDP_FEATURES_HW_OFFLOAD_STR,		\
> +		[XDP_F_TX_LOCK_BIT] = XDP_FEATURES_TX_LOCK_STR,			\
> +		[XDP_F_FRAG_RX_BIT] = XDP_FEATURES_FRAG_RX_STR,			\
> +		[XDP_F_FRAG_TARGET_BIT] = XDP_FEATURES_FRAG_TARGET_STR,		\
> +	}
> +
> +#endif /* _LINUX_XDP_FEATURES_H */
> diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
> index 1021a7e47a86..971c658ceaea 100644
> --- a/include/uapi/linux/if_link.h
> +++ b/include/uapi/linux/if_link.h
> @@ -374,6 +374,8 @@ enum {

>   	IFLA_DEVLINK_PORT,

> +	IFLA_XDP_FEATURES,
> +
>   	__IFLA_MAX
>   };

> @@ -1318,6 +1320,11 @@ enum {

>   #define IFLA_XDP_MAX (__IFLA_XDP_MAX - 1)

> +enum {
> +	IFLA_XDP_FEATURES_WORD_UNSPEC = 0,
> +	IFLA_XDP_FEATURES_BITS_WORD,
> +};
> +
>   enum {
>   	IFLA_EVENT_NONE,
>   	IFLA_EVENT_REBOOT,		/* internal reset / reboot */
> diff --git a/include/uapi/linux/xdp_features.h  
> b/include/uapi/linux/xdp_features.h
> new file mode 100644
> index 000000000000..48eb42069bcd
> --- /dev/null
> +++ b/include/uapi/linux/xdp_features.h
> @@ -0,0 +1,34 @@
> +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
> +/*
> + * Copyright (c) 2020 Intel
> + */
> +
> +#ifndef __UAPI_LINUX_XDP_FEATURES__
> +#define __UAPI_LINUX_XDP_FEATURES__
> +
> +enum {
> +	XDP_F_ABORTED_BIT,
> +	XDP_F_DROP_BIT,
> +	XDP_F_PASS_BIT,
> +	XDP_F_TX_BIT,
> +	XDP_F_REDIRECT_BIT,
> +	XDP_F_REDIRECT_TARGET_BIT,
> +	XDP_F_SOCK_ZEROCOPY_BIT,
> +	XDP_F_HW_OFFLOAD_BIT,
> +	XDP_F_TX_LOCK_BIT,
> +	XDP_F_FRAG_RX_BIT,
> +	XDP_F_FRAG_TARGET_BIT,
> +	/*
> +	 * Add your fresh new property above and remember to update
> +	 * documentation.
> +	 */
> +	XDP_FEATURES_COUNT,
> +};
> +
> +#define XDP_FEATURES_WORDS			((XDP_FEATURES_COUNT + 32 - 1) / 32)
> +#define XDP_FEATURES_WORD(blocks, index)	((blocks)[(index) / 32U])
> +#define XDP_FEATURES_FIELD_FLAG(index)		(1U << (index) % 32U)
> +#define XDP_FEATURES_BIT_IS_SET(blocks, index)        \
> +	(XDP_FEATURES_WORD(blocks, index) & XDP_FEATURES_FIELD_FLAG(index))
> +
> +#endif  /* __UAPI_LINUX_XDP_FEATURES__ */
> diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
> index 64289bc98887..1c299746b614 100644
> --- a/net/core/rtnetlink.c
> +++ b/net/core/rtnetlink.c
> @@ -1016,6 +1016,14 @@ static size_t rtnl_xdp_size(void)
>   	return xdp_size;
>   }

> +static size_t rtnl_xdp_features_size(void)
> +{
> +	size_t xdp_size = nla_total_size(0) +	/* nest IFLA_XDP_FEATURES */
> +			  XDP_FEATURES_WORDS * nla_total_size(4);
> +
> +	return xdp_size;
> +}
> +
>   static size_t rtnl_prop_list_size(const struct net_device *dev)
>   {
>   	struct netdev_name_node *name_node;
> @@ -1103,6 +1111,7 @@ static noinline size_t if_nlmsg_size(const struct  
> net_device *dev,
>   	       + rtnl_prop_list_size(dev)
>   	       + nla_total_size(MAX_ADDR_LEN) /* IFLA_PERM_ADDRESS */
>   	       + rtnl_devlink_port_size(dev)
> +	       + rtnl_xdp_features_size() /* IFLA_XDP_FEATURES */
>   	       + 0;
>   }

> @@ -1546,6 +1555,27 @@ static int rtnl_xdp_fill(struct sk_buff *skb,  
> struct net_device *dev)
>   	return err;
>   }

> +static int rtnl_xdp_features_fill(struct sk_buff *skb, struct net_device  
> *dev)
> +{
> +	struct nlattr *attr;
> +
> +	attr = nla_nest_start_noflag(skb, IFLA_XDP_FEATURES);
> +	if (!attr)
> +		return -EMSGSIZE;
> +
> +	BUILD_BUG_ON(XDP_FEATURES_WORDS != 1);
> +	if (nla_put_u32(skb, IFLA_XDP_FEATURES_BITS_WORD, dev->xdp_features))
> +		goto err_cancel;
> +
> +	nla_nest_end(skb, attr);
> +
> +	return 0;
> +
> +err_cancel:
> +	nla_nest_cancel(skb, attr);
> +	return -EMSGSIZE;
> +}
> +
>   static u32 rtnl_get_event(unsigned long event)
>   {
>   	u32 rtnl_event_type = IFLA_EVENT_NONE;
> @@ -1904,6 +1934,9 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb,
>   	if (rtnl_fill_devlink_port(skb, dev))
>   		goto nla_put_failure;

> +	if (rtnl_xdp_features_fill(skb, dev))
> +		goto nla_put_failure;
> +
>   	nlmsg_end(skb, nlh);
>   	return 0;

> @@ -1968,6 +2001,7 @@ static const struct nla_policy  
> ifla_policy[IFLA_MAX+1] = {
>   	[IFLA_TSO_MAX_SIZE]	= { .type = NLA_REJECT },
>   	[IFLA_TSO_MAX_SEGS]	= { .type = NLA_REJECT },
>   	[IFLA_ALLMULTI]		= { .type = NLA_REJECT },
> +	[IFLA_XDP_FEATURES]	= { .type = NLA_NESTED },
>   };

>   static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
> diff --git a/tools/include/uapi/linux/if_link.h  
> b/tools/include/uapi/linux/if_link.h
> index 82fe18f26db5..994228e9909a 100644
> --- a/tools/include/uapi/linux/if_link.h
> +++ b/tools/include/uapi/linux/if_link.h
> @@ -354,6 +354,8 @@ enum {

>   	IFLA_DEVLINK_PORT,

> +	IFLA_XDP_FEATURES,
> +
>   	__IFLA_MAX
>   };

> @@ -1222,6 +1224,11 @@ enum {

>   #define IFLA_XDP_MAX (__IFLA_XDP_MAX - 1)

> +enum {
> +	IFLA_XDP_FEATURES_WORD_UNSPEC = 0,
> +	IFLA_XDP_FEATURES_BITS_WORD,
> +};
> +
>   enum {
>   	IFLA_EVENT_NONE,
>   	IFLA_EVENT_REBOOT,		/* internal reset / reboot */
> diff --git a/tools/include/uapi/linux/xdp_features.h  
> b/tools/include/uapi/linux/xdp_features.h
> new file mode 100644
> index 000000000000..48eb42069bcd
> --- /dev/null
> +++ b/tools/include/uapi/linux/xdp_features.h
> @@ -0,0 +1,34 @@
> +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
> +/*
> + * Copyright (c) 2020 Intel
> + */
> +
> +#ifndef __UAPI_LINUX_XDP_FEATURES__
> +#define __UAPI_LINUX_XDP_FEATURES__
> +
> +enum {
> +	XDP_F_ABORTED_BIT,
> +	XDP_F_DROP_BIT,
> +	XDP_F_PASS_BIT,
> +	XDP_F_TX_BIT,
> +	XDP_F_REDIRECT_BIT,
> +	XDP_F_REDIRECT_TARGET_BIT,
> +	XDP_F_SOCK_ZEROCOPY_BIT,
> +	XDP_F_HW_OFFLOAD_BIT,
> +	XDP_F_TX_LOCK_BIT,
> +	XDP_F_FRAG_RX_BIT,
> +	XDP_F_FRAG_TARGET_BIT,
> +	/*
> +	 * Add your fresh new property above and remember to update
> +	 * documentation.
> +	 */
> +	XDP_FEATURES_COUNT,
> +};
> +
> +#define XDP_FEATURES_WORDS			((XDP_FEATURES_COUNT + 32 - 1) / 32)
> +#define XDP_FEATURES_WORD(blocks, index)	((blocks)[(index) / 32U])
> +#define XDP_FEATURES_FIELD_FLAG(index)		(1U << (index) % 32U)
> +#define XDP_FEATURES_BIT_IS_SET(blocks, index)        \
> +	(XDP_FEATURES_WORD(blocks, index) & XDP_FEATURES_FIELD_FLAG(index))
> +
> +#endif  /* __UAPI_LINUX_XDP_FEATURES__ */
> --
> 2.38.1
Marek Majtyka Dec. 19, 2022, 11:52 p.m. UTC | #2
At the time of writing, I wanted to be able to read additional information
about the XDP capabilities of each network interface using ethtool. This
change was intended for Linux users/admins, and not for XDP experts who
mostly don't need it and prefer tasting XDP with netlink and bpf rather
than reading network interface features with ethtool.



On Mon, Dec 19, 2022 at 9:03 PM <sdf@google.com> wrote:

> On 12/19, Lorenzo Bianconi wrote:
> > From: Marek Majtyka <alardam@gmail.com>
>
> > Implement support for checking what kind of XDP features a netdev
> > supports. Previously, there was no way to do this other than to try to
> > create an AF_XDP socket on the interface or load an XDP program and see
> > if it worked. This commit changes this by adding a new variable which
> > describes all xdp supported functions on pretty detailed level:
>
> >   - aborted
> >   - drop
> >   - pass
> >   - tx
> >   - redirect
> >   - sock_zerocopy
> >   - hw_offload
> >   - redirect_target
> >   - tx_lock
> >   - frag_rx
> >   - frag_target
>
> > Zerocopy mode requires that redirect XDP operation is implemented in a
> > driver and the driver supports also zero copy mode. Full mode requires
> > that all XDP operation are implemented in the driver. Basic mode is just
> > full mode without redirect operation. Frag target requires
> > redirect_target one is supported by the driver.
>
> Can you share more about _why_ is it needed? If we can already obtain
> most of these signals via probing, why export the flags?
>
> > Initially, these new flags are disabled for all drivers by default.
>
> > Co-developed-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
> > Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
> > Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org>
> > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> > Signed-off-by: Marek Majtyka <alardam@gmail.com>
> > ---
> >   .../networking/netdev-xdp-features.rst        | 60 +++++++++++++++++
> >   include/linux/netdevice.h                     |  2 +
> >   include/linux/xdp_features.h                  | 64 +++++++++++++++++++
> >   include/uapi/linux/if_link.h                  |  7 ++
> >   include/uapi/linux/xdp_features.h             | 34 ++++++++++
> >   net/core/rtnetlink.c                          | 34 ++++++++++
> >   tools/include/uapi/linux/if_link.h            |  7 ++
> >   tools/include/uapi/linux/xdp_features.h       | 34 ++++++++++
> >   8 files changed, 242 insertions(+)
> >   create mode 100644 Documentation/networking/netdev-xdp-features.rst
> >   create mode 100644 include/linux/xdp_features.h
> >   create mode 100644 include/uapi/linux/xdp_features.h
> >   create mode 100644 tools/include/uapi/linux/xdp_features.h
>
> > diff --git a/Documentation/networking/netdev-xdp-features.rst
> > b/Documentation/networking/netdev-xdp-features.rst
> > new file mode 100644
> > index 000000000000..1dc803fe72dd
> > --- /dev/null
> > +++ b/Documentation/networking/netdev-xdp-features.rst
> > @@ -0,0 +1,60 @@
> > +.. SPDX-License-Identifier: GPL-2.0
> > +
> > +=====================
> > +Netdev XDP features
> > +=====================
> > +
> > + * XDP FEATURES FLAGS
> > +
> > +Following netdev xdp features flags can be retrieved over route netlink
> > +interface (compact form) - the same way as netdev feature flags.
> > +These features flags are read only and cannot be change at runtime.
> > +
> > +*  XDP_ABORTED
> > +
> > +This feature informs if netdev supports xdp aborted action.
> > +
> > +*  XDP_DROP
> > +
> > +This feature informs if netdev supports xdp drop action.
> > +
> > +*  XDP_PASS
> > +
> > +This feature informs if netdev supports xdp pass action.
> > +
> > +*  XDP_TX
> > +
> > +This feature informs if netdev supports xdp tx action.
> > +
> > +*  XDP_REDIRECT
> > +
> > +This feature informs if netdev supports xdp redirect action.
> > +It assumes the all beforehand mentioned flags are enabled.
> > +
> > +*  XDP_SOCK_ZEROCOPY
> > +
> > +This feature informs if netdev driver supports xdp zero copy.
> > +It assumes the all beforehand mentioned flags are enabled.
> > +
> > +*  XDP_HW_OFFLOAD
> > +
> > +This feature informs if netdev driver supports xdp hw oflloading.
> > +
> > +*  XDP_TX_LOCK
> > +
> > +This feature informs if netdev ndo_xdp_xmit function requires locking.
> > +
> > +*  XDP_REDIRECT_TARGET
> > +
> > +This feature informs if netdev implements ndo_xdp_xmit callback.
> > +
> > +*  XDP_FRAG_RX
> > +
> > +This feature informs if netdev implements non-linear xdp buff support in
> > +the driver napi callback.
> > +
> > +*  XDP_FRAG_TARGET
> > +
> > +This feature informs if netdev implements non-linear xdp buff support in
> > +ndo_xdp_xmit callback. XDP_FRAG_TARGET requires XDP_REDIRECT_TARGET is
> > properly
> > +supported.
> > diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
> > index aad12a179e54..ae5a8564383b 100644
> > --- a/include/linux/netdevice.h
> > +++ b/include/linux/netdevice.h
> > @@ -43,6 +43,7 @@
> >   #include <net/xdp.h>
>
> >   #include <linux/netdev_features.h>
> > +#include <linux/xdp_features.h>
> >   #include <linux/neighbour.h>
> >   #include <uapi/linux/netdevice.h>
> >   #include <uapi/linux/if_bonding.h>
> > @@ -2362,6 +2363,7 @@ struct net_device {
> >       struct rtnl_hw_stats64  *offload_xstats_l3;
>
> >       struct devlink_port     *devlink_port;
> > +     xdp_features_t          xdp_features;
> >   };
> >   #define to_net_dev(d) container_of(d, struct net_device, dev)
>
> > diff --git a/include/linux/xdp_features.h b/include/linux/xdp_features.h
> > new file mode 100644
> > index 000000000000..4e72a86ef329
> > --- /dev/null
> > +++ b/include/linux/xdp_features.h
> > @@ -0,0 +1,64 @@
> > +/* SPDX-License-Identifier: GPL-2.0-or-later */
> > +/*
> > + * Network device xdp features.
> > + */
> > +#ifndef _LINUX_XDP_FEATURES_H
> > +#define _LINUX_XDP_FEATURES_H
> > +
> > +#include <linux/types.h>
> > +#include <linux/bitops.h>
> > +#include <asm/byteorder.h>
> > +#include <uapi/linux/xdp_features.h>
> > +
> > +typedef u32 xdp_features_t;
> > +
> > +#define __XDP_F_BIT(bit)     ((xdp_features_t)1 << (bit))
> > +#define __XDP_F(name)                __XDP_F_BIT(XDP_F_##name##_BIT)
> > +
> > +#define XDP_F_ABORTED                __XDP_F(ABORTED)
> > +#define XDP_F_DROP           __XDP_F(DROP)
> > +#define XDP_F_PASS           __XDP_F(PASS)
> > +#define XDP_F_TX             __XDP_F(TX)
> > +#define XDP_F_REDIRECT               __XDP_F(REDIRECT)
> > +#define XDP_F_REDIRECT_TARGET        __XDP_F(REDIRECT_TARGET)
> > +#define XDP_F_SOCK_ZEROCOPY  __XDP_F(SOCK_ZEROCOPY)
> > +#define XDP_F_HW_OFFLOAD     __XDP_F(HW_OFFLOAD)
> > +#define XDP_F_TX_LOCK                __XDP_F(TX_LOCK)
> > +#define XDP_F_FRAG_RX                __XDP_F(FRAG_RX)
> > +#define XDP_F_FRAG_TARGET    __XDP_F(FRAG_TARGET)
> > +
> > +#define XDP_F_BASIC          (XDP_F_ABORTED | XDP_F_DROP |   \
> > +                              XDP_F_PASS | XDP_F_TX)
> > +
> > +#define XDP_F_FULL           (XDP_F_BASIC | XDP_F_REDIRECT)
> > +
> > +#define XDP_F_FULL_ZC                (XDP_F_FULL | XDP_F_SOCK_ZEROCOPY)
> > +
> > +#define XDP_FEATURES_ABORTED_STR             "xdp-aborted"
> > +#define XDP_FEATURES_DROP_STR                        "xdp-drop"
> > +#define XDP_FEATURES_PASS_STR                        "xdp-pass"
> > +#define XDP_FEATURES_TX_STR                  "xdp-tx"
> > +#define XDP_FEATURES_REDIRECT_STR            "xdp-redirect"
> > +#define XDP_FEATURES_REDIRECT_TARGET_STR     "xdp-redirect-target"
> > +#define XDP_FEATURES_SOCK_ZEROCOPY_STR               "xdp-sock-zerocopy"
> > +#define XDP_FEATURES_HW_OFFLOAD_STR          "xdp-hw-offload"
> > +#define XDP_FEATURES_TX_LOCK_STR             "xdp-tx-lock"
> > +#define XDP_FEATURES_FRAG_RX_STR             "xdp-frag-rx"
> > +#define XDP_FEATURES_FRAG_TARGET_STR         "xdp-frag-target"
> > +
> > +#define DECLARE_XDP_FEATURES_TABLE(name, length)
>      \
> > +     const char name[][length] = {
>      \
> > +             [XDP_F_ABORTED_BIT] = XDP_FEATURES_ABORTED_STR,
>      \
> > +             [XDP_F_DROP_BIT] = XDP_FEATURES_DROP_STR,
>      \
> > +             [XDP_F_PASS_BIT] = XDP_FEATURES_PASS_STR,
>      \
> > +             [XDP_F_TX_BIT] = XDP_FEATURES_TX_STR,
>      \
> > +             [XDP_F_REDIRECT_BIT] = XDP_FEATURES_REDIRECT_STR,
>      \
> > +             [XDP_F_REDIRECT_TARGET_BIT] =
> XDP_FEATURES_REDIRECT_TARGET_STR, \
> > +             [XDP_F_SOCK_ZEROCOPY_BIT] =
> XDP_FEATURES_SOCK_ZEROCOPY_STR,     \
> > +             [XDP_F_HW_OFFLOAD_BIT] = XDP_FEATURES_HW_OFFLOAD_STR,
>      \
> > +             [XDP_F_TX_LOCK_BIT] = XDP_FEATURES_TX_LOCK_STR,
>      \
> > +             [XDP_F_FRAG_RX_BIT] = XDP_FEATURES_FRAG_RX_STR,
>      \
> > +             [XDP_F_FRAG_TARGET_BIT] = XDP_FEATURES_FRAG_TARGET_STR,
>      \
> > +     }
> > +
> > +#endif /* _LINUX_XDP_FEATURES_H */
> > diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
> > index 1021a7e47a86..971c658ceaea 100644
> > --- a/include/uapi/linux/if_link.h
> > +++ b/include/uapi/linux/if_link.h
> > @@ -374,6 +374,8 @@ enum {
>
> >       IFLA_DEVLINK_PORT,
>
> > +     IFLA_XDP_FEATURES,
> > +
> >       __IFLA_MAX
> >   };
>
> > @@ -1318,6 +1320,11 @@ enum {
>
> >   #define IFLA_XDP_MAX (__IFLA_XDP_MAX - 1)
>
> > +enum {
> > +     IFLA_XDP_FEATURES_WORD_UNSPEC = 0,
> > +     IFLA_XDP_FEATURES_BITS_WORD,
> > +};
> > +
> >   enum {
> >       IFLA_EVENT_NONE,
> >       IFLA_EVENT_REBOOT,              /* internal reset / reboot */
> > diff --git a/include/uapi/linux/xdp_features.h
> > b/include/uapi/linux/xdp_features.h
> > new file mode 100644
> > index 000000000000..48eb42069bcd
> > --- /dev/null
> > +++ b/include/uapi/linux/xdp_features.h
> > @@ -0,0 +1,34 @@
> > +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
> > +/*
> > + * Copyright (c) 2020 Intel
> > + */
> > +
> > +#ifndef __UAPI_LINUX_XDP_FEATURES__
> > +#define __UAPI_LINUX_XDP_FEATURES__
> > +
> > +enum {
> > +     XDP_F_ABORTED_BIT,
> > +     XDP_F_DROP_BIT,
> > +     XDP_F_PASS_BIT,
> > +     XDP_F_TX_BIT,
> > +     XDP_F_REDIRECT_BIT,
> > +     XDP_F_REDIRECT_TARGET_BIT,
> > +     XDP_F_SOCK_ZEROCOPY_BIT,
> > +     XDP_F_HW_OFFLOAD_BIT,
> > +     XDP_F_TX_LOCK_BIT,
> > +     XDP_F_FRAG_RX_BIT,
> > +     XDP_F_FRAG_TARGET_BIT,
> > +     /*
> > +      * Add your fresh new property above and remember to update
> > +      * documentation.
> > +      */
> > +     XDP_FEATURES_COUNT,
> > +};
> > +
> > +#define XDP_FEATURES_WORDS                   ((XDP_FEATURES_COUNT + 32
> - 1) / 32)
> > +#define XDP_FEATURES_WORD(blocks, index)     ((blocks)[(index) / 32U])
> > +#define XDP_FEATURES_FIELD_FLAG(index)               (1U << (index) %
> 32U)
> > +#define XDP_FEATURES_BIT_IS_SET(blocks, index)        \
> > +     (XDP_FEATURES_WORD(blocks, index) & XDP_FEATURES_FIELD_FLAG(index))
> > +
> > +#endif  /* __UAPI_LINUX_XDP_FEATURES__ */
> > diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
> > index 64289bc98887..1c299746b614 100644
> > --- a/net/core/rtnetlink.c
> > +++ b/net/core/rtnetlink.c
> > @@ -1016,6 +1016,14 @@ static size_t rtnl_xdp_size(void)
> >       return xdp_size;
> >   }
>
> > +static size_t rtnl_xdp_features_size(void)
> > +{
> > +     size_t xdp_size = nla_total_size(0) +   /* nest IFLA_XDP_FEATURES
> */
> > +                       XDP_FEATURES_WORDS * nla_total_size(4);
> > +
> > +     return xdp_size;
> > +}
> > +
> >   static size_t rtnl_prop_list_size(const struct net_device *dev)
> >   {
> >       struct netdev_name_node *name_node;
> > @@ -1103,6 +1111,7 @@ static noinline size_t if_nlmsg_size(const struct
> > net_device *dev,
> >              + rtnl_prop_list_size(dev)
> >              + nla_total_size(MAX_ADDR_LEN) /* IFLA_PERM_ADDRESS */
> >              + rtnl_devlink_port_size(dev)
> > +            + rtnl_xdp_features_size() /* IFLA_XDP_FEATURES */
> >              + 0;
> >   }
>
> > @@ -1546,6 +1555,27 @@ static int rtnl_xdp_fill(struct sk_buff *skb,
> > struct net_device *dev)
> >       return err;
> >   }
>
> > +static int rtnl_xdp_features_fill(struct sk_buff *skb, struct
> net_device
> > *dev)
> > +{
> > +     struct nlattr *attr;
> > +
> > +     attr = nla_nest_start_noflag(skb, IFLA_XDP_FEATURES);
> > +     if (!attr)
> > +             return -EMSGSIZE;
> > +
> > +     BUILD_BUG_ON(XDP_FEATURES_WORDS != 1);
> > +     if (nla_put_u32(skb, IFLA_XDP_FEATURES_BITS_WORD,
> dev->xdp_features))
> > +             goto err_cancel;
> > +
> > +     nla_nest_end(skb, attr);
> > +
> > +     return 0;
> > +
> > +err_cancel:
> > +     nla_nest_cancel(skb, attr);
> > +     return -EMSGSIZE;
> > +}
> > +
> >   static u32 rtnl_get_event(unsigned long event)
> >   {
> >       u32 rtnl_event_type = IFLA_EVENT_NONE;
> > @@ -1904,6 +1934,9 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb,
> >       if (rtnl_fill_devlink_port(skb, dev))
> >               goto nla_put_failure;
>
> > +     if (rtnl_xdp_features_fill(skb, dev))
> > +             goto nla_put_failure;
> > +
> >       nlmsg_end(skb, nlh);
> >       return 0;
>
> > @@ -1968,6 +2001,7 @@ static const struct nla_policy
> > ifla_policy[IFLA_MAX+1] = {
> >       [IFLA_TSO_MAX_SIZE]     = { .type = NLA_REJECT },
> >       [IFLA_TSO_MAX_SEGS]     = { .type = NLA_REJECT },
> >       [IFLA_ALLMULTI]         = { .type = NLA_REJECT },
> > +     [IFLA_XDP_FEATURES]     = { .type = NLA_NESTED },
> >   };
>
> >   static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
> > diff --git a/tools/include/uapi/linux/if_link.h
> > b/tools/include/uapi/linux/if_link.h
> > index 82fe18f26db5..994228e9909a 100644
> > --- a/tools/include/uapi/linux/if_link.h
> > +++ b/tools/include/uapi/linux/if_link.h
> > @@ -354,6 +354,8 @@ enum {
>
> >       IFLA_DEVLINK_PORT,
>
> > +     IFLA_XDP_FEATURES,
> > +
> >       __IFLA_MAX
> >   };
>
> > @@ -1222,6 +1224,11 @@ enum {
>
> >   #define IFLA_XDP_MAX (__IFLA_XDP_MAX - 1)
>
> > +enum {
> > +     IFLA_XDP_FEATURES_WORD_UNSPEC = 0,
> > +     IFLA_XDP_FEATURES_BITS_WORD,
> > +};
> > +
> >   enum {
> >       IFLA_EVENT_NONE,
> >       IFLA_EVENT_REBOOT,              /* internal reset / reboot */
> > diff --git a/tools/include/uapi/linux/xdp_features.h
> > b/tools/include/uapi/linux/xdp_features.h
> > new file mode 100644
> > index 000000000000..48eb42069bcd
> > --- /dev/null
> > +++ b/tools/include/uapi/linux/xdp_features.h
> > @@ -0,0 +1,34 @@
> > +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
> > +/*
> > + * Copyright (c) 2020 Intel
> > + */
> > +
> > +#ifndef __UAPI_LINUX_XDP_FEATURES__
> > +#define __UAPI_LINUX_XDP_FEATURES__
> > +
> > +enum {
> > +     XDP_F_ABORTED_BIT,
> > +     XDP_F_DROP_BIT,
> > +     XDP_F_PASS_BIT,
> > +     XDP_F_TX_BIT,
> > +     XDP_F_REDIRECT_BIT,
> > +     XDP_F_REDIRECT_TARGET_BIT,
> > +     XDP_F_SOCK_ZEROCOPY_BIT,
> > +     XDP_F_HW_OFFLOAD_BIT,
> > +     XDP_F_TX_LOCK_BIT,
> > +     XDP_F_FRAG_RX_BIT,
> > +     XDP_F_FRAG_TARGET_BIT,
> > +     /*
> > +      * Add your fresh new property above and remember to update
> > +      * documentation.
> > +      */
> > +     XDP_FEATURES_COUNT,
> > +};
> > +
> > +#define XDP_FEATURES_WORDS                   ((XDP_FEATURES_COUNT + 32
> - 1) / 32)
> > +#define XDP_FEATURES_WORD(blocks, index)     ((blocks)[(index) / 32U])
> > +#define XDP_FEATURES_FIELD_FLAG(index)               (1U << (index) %
> 32U)
> > +#define XDP_FEATURES_BIT_IS_SET(blocks, index)        \
> > +     (XDP_FEATURES_WORD(blocks, index) & XDP_FEATURES_FIELD_FLAG(index))
> > +
> > +#endif  /* __UAPI_LINUX_XDP_FEATURES__ */
> > --
> > 2.38.1
>
>
Stanislav Fomichev Dec. 20, 2022, 12:20 a.m. UTC | #3
On Mon, Dec 19, 2022 at 3:51 PM Marek Majtyka <alardam@gmail.com> wrote:
>
> At the time of writing, I wanted to be able to read additional information about the XDP capabilities of each network interface using ethtool. This change was intended for Linux users/admins, and not for XDP experts who mostly don't need it and prefer tasting XDP with netlink and bpf rather than reading network interface features with ethtool.

Anything preventing ethtool from doing probing similar to 'bpftool
feature probe'?
The problem with these feature bits is that they might diverge and/or
not work at all for the backported patches (where the fix/feature has
been backported, but the part that exports the bit hasn't) :-(
OTOH, I'm not sure we can probe everything from your list, but we
might try and see what's missing..

> On Mon, Dec 19, 2022 at 9:03 PM <sdf@google.com> wrote:
>>
>> On 12/19, Lorenzo Bianconi wrote:
>> > From: Marek Majtyka <alardam@gmail.com>
>>
>> > Implement support for checking what kind of XDP features a netdev
>> > supports. Previously, there was no way to do this other than to try to
>> > create an AF_XDP socket on the interface or load an XDP program and see
>> > if it worked. This commit changes this by adding a new variable which
>> > describes all xdp supported functions on pretty detailed level:
>>
>> >   - aborted
>> >   - drop
>> >   - pass
>> >   - tx
>> >   - redirect
>> >   - sock_zerocopy
>> >   - hw_offload
>> >   - redirect_target
>> >   - tx_lock
>> >   - frag_rx
>> >   - frag_target
>>
>> > Zerocopy mode requires that redirect XDP operation is implemented in a
>> > driver and the driver supports also zero copy mode. Full mode requires
>> > that all XDP operation are implemented in the driver. Basic mode is just
>> > full mode without redirect operation. Frag target requires
>> > redirect_target one is supported by the driver.
>>
>> Can you share more about _why_ is it needed? If we can already obtain
>> most of these signals via probing, why export the flags?
>>
>> > Initially, these new flags are disabled for all drivers by default.
>>
>> > Co-developed-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
>> > Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
>> > Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org>
>> > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
>> > Signed-off-by: Marek Majtyka <alardam@gmail.com>
>> > ---
>> >   .../networking/netdev-xdp-features.rst        | 60 +++++++++++++++++
>> >   include/linux/netdevice.h                     |  2 +
>> >   include/linux/xdp_features.h                  | 64 +++++++++++++++++++
>> >   include/uapi/linux/if_link.h                  |  7 ++
>> >   include/uapi/linux/xdp_features.h             | 34 ++++++++++
>> >   net/core/rtnetlink.c                          | 34 ++++++++++
>> >   tools/include/uapi/linux/if_link.h            |  7 ++
>> >   tools/include/uapi/linux/xdp_features.h       | 34 ++++++++++
>> >   8 files changed, 242 insertions(+)
>> >   create mode 100644 Documentation/networking/netdev-xdp-features.rst
>> >   create mode 100644 include/linux/xdp_features.h
>> >   create mode 100644 include/uapi/linux/xdp_features.h
>> >   create mode 100644 tools/include/uapi/linux/xdp_features.h
>>
>> > diff --git a/Documentation/networking/netdev-xdp-features.rst
>> > b/Documentation/networking/netdev-xdp-features.rst
>> > new file mode 100644
>> > index 000000000000..1dc803fe72dd
>> > --- /dev/null
>> > +++ b/Documentation/networking/netdev-xdp-features.rst
>> > @@ -0,0 +1,60 @@
>> > +.. SPDX-License-Identifier: GPL-2.0
>> > +
>> > +=====================
>> > +Netdev XDP features
>> > +=====================
>> > +
>> > + * XDP FEATURES FLAGS
>> > +
>> > +Following netdev xdp features flags can be retrieved over route netlink
>> > +interface (compact form) - the same way as netdev feature flags.
>> > +These features flags are read only and cannot be change at runtime.
>> > +
>> > +*  XDP_ABORTED
>> > +
>> > +This feature informs if netdev supports xdp aborted action.
>> > +
>> > +*  XDP_DROP
>> > +
>> > +This feature informs if netdev supports xdp drop action.
>> > +
>> > +*  XDP_PASS
>> > +
>> > +This feature informs if netdev supports xdp pass action.
>> > +
>> > +*  XDP_TX
>> > +
>> > +This feature informs if netdev supports xdp tx action.
>> > +
>> > +*  XDP_REDIRECT
>> > +
>> > +This feature informs if netdev supports xdp redirect action.
>> > +It assumes the all beforehand mentioned flags are enabled.
>> > +
>> > +*  XDP_SOCK_ZEROCOPY
>> > +
>> > +This feature informs if netdev driver supports xdp zero copy.
>> > +It assumes the all beforehand mentioned flags are enabled.
>> > +
>> > +*  XDP_HW_OFFLOAD
>> > +
>> > +This feature informs if netdev driver supports xdp hw oflloading.
>> > +
>> > +*  XDP_TX_LOCK
>> > +
>> > +This feature informs if netdev ndo_xdp_xmit function requires locking.
>> > +
>> > +*  XDP_REDIRECT_TARGET
>> > +
>> > +This feature informs if netdev implements ndo_xdp_xmit callback.
>> > +
>> > +*  XDP_FRAG_RX
>> > +
>> > +This feature informs if netdev implements non-linear xdp buff support in
>> > +the driver napi callback.
>> > +
>> > +*  XDP_FRAG_TARGET
>> > +
>> > +This feature informs if netdev implements non-linear xdp buff support in
>> > +ndo_xdp_xmit callback. XDP_FRAG_TARGET requires XDP_REDIRECT_TARGET is
>> > properly
>> > +supported.
>> > diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
>> > index aad12a179e54..ae5a8564383b 100644
>> > --- a/include/linux/netdevice.h
>> > +++ b/include/linux/netdevice.h
>> > @@ -43,6 +43,7 @@
>> >   #include <net/xdp.h>
>>
>> >   #include <linux/netdev_features.h>
>> > +#include <linux/xdp_features.h>
>> >   #include <linux/neighbour.h>
>> >   #include <uapi/linux/netdevice.h>
>> >   #include <uapi/linux/if_bonding.h>
>> > @@ -2362,6 +2363,7 @@ struct net_device {
>> >       struct rtnl_hw_stats64  *offload_xstats_l3;
>>
>> >       struct devlink_port     *devlink_port;
>> > +     xdp_features_t          xdp_features;
>> >   };
>> >   #define to_net_dev(d) container_of(d, struct net_device, dev)
>>
>> > diff --git a/include/linux/xdp_features.h b/include/linux/xdp_features.h
>> > new file mode 100644
>> > index 000000000000..4e72a86ef329
>> > --- /dev/null
>> > +++ b/include/linux/xdp_features.h
>> > @@ -0,0 +1,64 @@
>> > +/* SPDX-License-Identifier: GPL-2.0-or-later */
>> > +/*
>> > + * Network device xdp features.
>> > + */
>> > +#ifndef _LINUX_XDP_FEATURES_H
>> > +#define _LINUX_XDP_FEATURES_H
>> > +
>> > +#include <linux/types.h>
>> > +#include <linux/bitops.h>
>> > +#include <asm/byteorder.h>
>> > +#include <uapi/linux/xdp_features.h>
>> > +
>> > +typedef u32 xdp_features_t;
>> > +
>> > +#define __XDP_F_BIT(bit)     ((xdp_features_t)1 << (bit))
>> > +#define __XDP_F(name)                __XDP_F_BIT(XDP_F_##name##_BIT)
>> > +
>> > +#define XDP_F_ABORTED                __XDP_F(ABORTED)
>> > +#define XDP_F_DROP           __XDP_F(DROP)
>> > +#define XDP_F_PASS           __XDP_F(PASS)
>> > +#define XDP_F_TX             __XDP_F(TX)
>> > +#define XDP_F_REDIRECT               __XDP_F(REDIRECT)
>> > +#define XDP_F_REDIRECT_TARGET        __XDP_F(REDIRECT_TARGET)
>> > +#define XDP_F_SOCK_ZEROCOPY  __XDP_F(SOCK_ZEROCOPY)
>> > +#define XDP_F_HW_OFFLOAD     __XDP_F(HW_OFFLOAD)
>> > +#define XDP_F_TX_LOCK                __XDP_F(TX_LOCK)
>> > +#define XDP_F_FRAG_RX                __XDP_F(FRAG_RX)
>> > +#define XDP_F_FRAG_TARGET    __XDP_F(FRAG_TARGET)
>> > +
>> > +#define XDP_F_BASIC          (XDP_F_ABORTED | XDP_F_DROP |   \
>> > +                              XDP_F_PASS | XDP_F_TX)
>> > +
>> > +#define XDP_F_FULL           (XDP_F_BASIC | XDP_F_REDIRECT)
>> > +
>> > +#define XDP_F_FULL_ZC                (XDP_F_FULL | XDP_F_SOCK_ZEROCOPY)
>> > +
>> > +#define XDP_FEATURES_ABORTED_STR             "xdp-aborted"
>> > +#define XDP_FEATURES_DROP_STR                        "xdp-drop"
>> > +#define XDP_FEATURES_PASS_STR                        "xdp-pass"
>> > +#define XDP_FEATURES_TX_STR                  "xdp-tx"
>> > +#define XDP_FEATURES_REDIRECT_STR            "xdp-redirect"
>> > +#define XDP_FEATURES_REDIRECT_TARGET_STR     "xdp-redirect-target"
>> > +#define XDP_FEATURES_SOCK_ZEROCOPY_STR               "xdp-sock-zerocopy"
>> > +#define XDP_FEATURES_HW_OFFLOAD_STR          "xdp-hw-offload"
>> > +#define XDP_FEATURES_TX_LOCK_STR             "xdp-tx-lock"
>> > +#define XDP_FEATURES_FRAG_RX_STR             "xdp-frag-rx"
>> > +#define XDP_FEATURES_FRAG_TARGET_STR         "xdp-frag-target"
>> > +
>> > +#define DECLARE_XDP_FEATURES_TABLE(name, length)                             \
>> > +     const char name[][length] = {                                           \
>> > +             [XDP_F_ABORTED_BIT] = XDP_FEATURES_ABORTED_STR,                 \
>> > +             [XDP_F_DROP_BIT] = XDP_FEATURES_DROP_STR,                       \
>> > +             [XDP_F_PASS_BIT] = XDP_FEATURES_PASS_STR,                       \
>> > +             [XDP_F_TX_BIT] = XDP_FEATURES_TX_STR,                           \
>> > +             [XDP_F_REDIRECT_BIT] = XDP_FEATURES_REDIRECT_STR,               \
>> > +             [XDP_F_REDIRECT_TARGET_BIT] = XDP_FEATURES_REDIRECT_TARGET_STR, \
>> > +             [XDP_F_SOCK_ZEROCOPY_BIT] = XDP_FEATURES_SOCK_ZEROCOPY_STR,     \
>> > +             [XDP_F_HW_OFFLOAD_BIT] = XDP_FEATURES_HW_OFFLOAD_STR,           \
>> > +             [XDP_F_TX_LOCK_BIT] = XDP_FEATURES_TX_LOCK_STR,                 \
>> > +             [XDP_F_FRAG_RX_BIT] = XDP_FEATURES_FRAG_RX_STR,                 \
>> > +             [XDP_F_FRAG_TARGET_BIT] = XDP_FEATURES_FRAG_TARGET_STR,         \
>> > +     }
>> > +
>> > +#endif /* _LINUX_XDP_FEATURES_H */
>> > diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
>> > index 1021a7e47a86..971c658ceaea 100644
>> > --- a/include/uapi/linux/if_link.h
>> > +++ b/include/uapi/linux/if_link.h
>> > @@ -374,6 +374,8 @@ enum {
>>
>> >       IFLA_DEVLINK_PORT,
>>
>> > +     IFLA_XDP_FEATURES,
>> > +
>> >       __IFLA_MAX
>> >   };
>>
>> > @@ -1318,6 +1320,11 @@ enum {
>>
>> >   #define IFLA_XDP_MAX (__IFLA_XDP_MAX - 1)
>>
>> > +enum {
>> > +     IFLA_XDP_FEATURES_WORD_UNSPEC = 0,
>> > +     IFLA_XDP_FEATURES_BITS_WORD,
>> > +};
>> > +
>> >   enum {
>> >       IFLA_EVENT_NONE,
>> >       IFLA_EVENT_REBOOT,              /* internal reset / reboot */
>> > diff --git a/include/uapi/linux/xdp_features.h
>> > b/include/uapi/linux/xdp_features.h
>> > new file mode 100644
>> > index 000000000000..48eb42069bcd
>> > --- /dev/null
>> > +++ b/include/uapi/linux/xdp_features.h
>> > @@ -0,0 +1,34 @@
>> > +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
>> > +/*
>> > + * Copyright (c) 2020 Intel
>> > + */
>> > +
>> > +#ifndef __UAPI_LINUX_XDP_FEATURES__
>> > +#define __UAPI_LINUX_XDP_FEATURES__
>> > +
>> > +enum {
>> > +     XDP_F_ABORTED_BIT,
>> > +     XDP_F_DROP_BIT,
>> > +     XDP_F_PASS_BIT,
>> > +     XDP_F_TX_BIT,
>> > +     XDP_F_REDIRECT_BIT,
>> > +     XDP_F_REDIRECT_TARGET_BIT,
>> > +     XDP_F_SOCK_ZEROCOPY_BIT,
>> > +     XDP_F_HW_OFFLOAD_BIT,
>> > +     XDP_F_TX_LOCK_BIT,
>> > +     XDP_F_FRAG_RX_BIT,
>> > +     XDP_F_FRAG_TARGET_BIT,
>> > +     /*
>> > +      * Add your fresh new property above and remember to update
>> > +      * documentation.
>> > +      */
>> > +     XDP_FEATURES_COUNT,
>> > +};
>> > +
>> > +#define XDP_FEATURES_WORDS                   ((XDP_FEATURES_COUNT + 32 - 1) / 32)
>> > +#define XDP_FEATURES_WORD(blocks, index)     ((blocks)[(index) / 32U])
>> > +#define XDP_FEATURES_FIELD_FLAG(index)               (1U << (index) % 32U)
>> > +#define XDP_FEATURES_BIT_IS_SET(blocks, index)        \
>> > +     (XDP_FEATURES_WORD(blocks, index) & XDP_FEATURES_FIELD_FLAG(index))
>> > +
>> > +#endif  /* __UAPI_LINUX_XDP_FEATURES__ */
>> > diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
>> > index 64289bc98887..1c299746b614 100644
>> > --- a/net/core/rtnetlink.c
>> > +++ b/net/core/rtnetlink.c
>> > @@ -1016,6 +1016,14 @@ static size_t rtnl_xdp_size(void)
>> >       return xdp_size;
>> >   }
>>
>> > +static size_t rtnl_xdp_features_size(void)
>> > +{
>> > +     size_t xdp_size = nla_total_size(0) +   /* nest IFLA_XDP_FEATURES */
>> > +                       XDP_FEATURES_WORDS * nla_total_size(4);
>> > +
>> > +     return xdp_size;
>> > +}
>> > +
>> >   static size_t rtnl_prop_list_size(const struct net_device *dev)
>> >   {
>> >       struct netdev_name_node *name_node;
>> > @@ -1103,6 +1111,7 @@ static noinline size_t if_nlmsg_size(const struct
>> > net_device *dev,
>> >              + rtnl_prop_list_size(dev)
>> >              + nla_total_size(MAX_ADDR_LEN) /* IFLA_PERM_ADDRESS */
>> >              + rtnl_devlink_port_size(dev)
>> > +            + rtnl_xdp_features_size() /* IFLA_XDP_FEATURES */
>> >              + 0;
>> >   }
>>
>> > @@ -1546,6 +1555,27 @@ static int rtnl_xdp_fill(struct sk_buff *skb,
>> > struct net_device *dev)
>> >       return err;
>> >   }
>>
>> > +static int rtnl_xdp_features_fill(struct sk_buff *skb, struct net_device
>> > *dev)
>> > +{
>> > +     struct nlattr *attr;
>> > +
>> > +     attr = nla_nest_start_noflag(skb, IFLA_XDP_FEATURES);
>> > +     if (!attr)
>> > +             return -EMSGSIZE;
>> > +
>> > +     BUILD_BUG_ON(XDP_FEATURES_WORDS != 1);
>> > +     if (nla_put_u32(skb, IFLA_XDP_FEATURES_BITS_WORD, dev->xdp_features))
>> > +             goto err_cancel;
>> > +
>> > +     nla_nest_end(skb, attr);
>> > +
>> > +     return 0;
>> > +
>> > +err_cancel:
>> > +     nla_nest_cancel(skb, attr);
>> > +     return -EMSGSIZE;
>> > +}
>> > +
>> >   static u32 rtnl_get_event(unsigned long event)
>> >   {
>> >       u32 rtnl_event_type = IFLA_EVENT_NONE;
>> > @@ -1904,6 +1934,9 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb,
>> >       if (rtnl_fill_devlink_port(skb, dev))
>> >               goto nla_put_failure;
>>
>> > +     if (rtnl_xdp_features_fill(skb, dev))
>> > +             goto nla_put_failure;
>> > +
>> >       nlmsg_end(skb, nlh);
>> >       return 0;
>>
>> > @@ -1968,6 +2001,7 @@ static const struct nla_policy
>> > ifla_policy[IFLA_MAX+1] = {
>> >       [IFLA_TSO_MAX_SIZE]     = { .type = NLA_REJECT },
>> >       [IFLA_TSO_MAX_SEGS]     = { .type = NLA_REJECT },
>> >       [IFLA_ALLMULTI]         = { .type = NLA_REJECT },
>> > +     [IFLA_XDP_FEATURES]     = { .type = NLA_NESTED },
>> >   };
>>
>> >   static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
>> > diff --git a/tools/include/uapi/linux/if_link.h
>> > b/tools/include/uapi/linux/if_link.h
>> > index 82fe18f26db5..994228e9909a 100644
>> > --- a/tools/include/uapi/linux/if_link.h
>> > +++ b/tools/include/uapi/linux/if_link.h
>> > @@ -354,6 +354,8 @@ enum {
>>
>> >       IFLA_DEVLINK_PORT,
>>
>> > +     IFLA_XDP_FEATURES,
>> > +
>> >       __IFLA_MAX
>> >   };
>>
>> > @@ -1222,6 +1224,11 @@ enum {
>>
>> >   #define IFLA_XDP_MAX (__IFLA_XDP_MAX - 1)
>>
>> > +enum {
>> > +     IFLA_XDP_FEATURES_WORD_UNSPEC = 0,
>> > +     IFLA_XDP_FEATURES_BITS_WORD,
>> > +};
>> > +
>> >   enum {
>> >       IFLA_EVENT_NONE,
>> >       IFLA_EVENT_REBOOT,              /* internal reset / reboot */
>> > diff --git a/tools/include/uapi/linux/xdp_features.h
>> > b/tools/include/uapi/linux/xdp_features.h
>> > new file mode 100644
>> > index 000000000000..48eb42069bcd
>> > --- /dev/null
>> > +++ b/tools/include/uapi/linux/xdp_features.h
>> > @@ -0,0 +1,34 @@
>> > +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
>> > +/*
>> > + * Copyright (c) 2020 Intel
>> > + */
>> > +
>> > +#ifndef __UAPI_LINUX_XDP_FEATURES__
>> > +#define __UAPI_LINUX_XDP_FEATURES__
>> > +
>> > +enum {
>> > +     XDP_F_ABORTED_BIT,
>> > +     XDP_F_DROP_BIT,
>> > +     XDP_F_PASS_BIT,
>> > +     XDP_F_TX_BIT,
>> > +     XDP_F_REDIRECT_BIT,
>> > +     XDP_F_REDIRECT_TARGET_BIT,
>> > +     XDP_F_SOCK_ZEROCOPY_BIT,
>> > +     XDP_F_HW_OFFLOAD_BIT,
>> > +     XDP_F_TX_LOCK_BIT,
>> > +     XDP_F_FRAG_RX_BIT,
>> > +     XDP_F_FRAG_TARGET_BIT,
>> > +     /*
>> > +      * Add your fresh new property above and remember to update
>> > +      * documentation.
>> > +      */
>> > +     XDP_FEATURES_COUNT,
>> > +};
>> > +
>> > +#define XDP_FEATURES_WORDS                   ((XDP_FEATURES_COUNT + 32 - 1) / 32)
>> > +#define XDP_FEATURES_WORD(blocks, index)     ((blocks)[(index) / 32U])
>> > +#define XDP_FEATURES_FIELD_FLAG(index)               (1U << (index) % 32U)
>> > +#define XDP_FEATURES_BIT_IS_SET(blocks, index)        \
>> > +     (XDP_FEATURES_WORD(blocks, index) & XDP_FEATURES_FIELD_FLAG(index))
>> > +
>> > +#endif  /* __UAPI_LINUX_XDP_FEATURES__ */
>> > --
>> > 2.38.1
>>
Jakub Kicinski Dec. 20, 2022, 1:13 a.m. UTC | #4
On Mon, 19 Dec 2022 16:41:31 +0100 Lorenzo Bianconi wrote:
> +=====================
> +Netdev XDP features
> +=====================
> +
> + * XDP FEATURES FLAGS
> +
> +Following netdev xdp features flags can be retrieved over route netlink
> +interface (compact form) - the same way as netdev feature flags.

How likely is it that I'll be able to convince you that cramming more
stuff in rtnl is a bad idea? I can convert this for you to a YAML-
-compatible genetlink family for you in a jiffy, just say yes :S

rtnl is hard to parse, and already overloaded with random stuff.
And the messages are enormous.

> +These features flags are read only and cannot be change at runtime.
> +
> +*  XDP_ABORTED
> +
> +This feature informs if netdev supports xdp aborted action.
> +
> +*  XDP_DROP
> +
> +This feature informs if netdev supports xdp drop action.
> +
> +*  XDP_PASS
> +
> +This feature informs if netdev supports xdp pass action.
> +
> +*  XDP_TX
> +
> +This feature informs if netdev supports xdp tx action.
> +
> +*  XDP_REDIRECT
> +
> +This feature informs if netdev supports xdp redirect action.
> +It assumes the all beforehand mentioned flags are enabled.
> +
> +*  XDP_SOCK_ZEROCOPY
> +
> +This feature informs if netdev driver supports xdp zero copy.
> +It assumes the all beforehand mentioned flags are enabled.

Why is this "assumption" worth documenting?

> +*  XDP_HW_OFFLOAD
> +
> +This feature informs if netdev driver supports xdp hw oflloading.
> +
> +*  XDP_TX_LOCK
> +
> +This feature informs if netdev ndo_xdp_xmit function requires locking.

Why is it relevant to the user?

> +*  XDP_REDIRECT_TARGET
> +
> +This feature informs if netdev implements ndo_xdp_xmit callback.

Does it make sense to rename XDP_REDIRECT -> XDP_REDIRECT_SOURCE then?

> +*  XDP_FRAG_RX
> +
> +This feature informs if netdev implements non-linear xdp buff support in
> +the driver napi callback.

Who's the target audience? Maybe FRAG is not the best name?
Scatter-gather or multi-buf may be more widely understood.

> +*  XDP_FRAG_TARGET
> +
> +This feature informs if netdev implements non-linear xdp buff support in
> +ndo_xdp_xmit callback. XDP_FRAG_TARGET requires XDP_REDIRECT_TARGET is properly
> +supported.
Lorenzo Bianconi Dec. 20, 2022, 9:20 a.m. UTC | #5
> On Mon, 19 Dec 2022 16:41:31 +0100 Lorenzo Bianconi wrote:
> > +=====================
> > +Netdev XDP features
> > +=====================
> > +
> > + * XDP FEATURES FLAGS
> > +
> > +Following netdev xdp features flags can be retrieved over route netlink
> > +interface (compact form) - the same way as netdev feature flags.
> 
> How likely is it that I'll be able to convince you that cramming more
> stuff in rtnl is a bad idea? I can convert this for you to a YAML-
> -compatible genetlink family for you in a jiffy, just say yes :S
> 
> rtnl is hard to parse, and already overloaded with random stuff.
> And the messages are enormous.

Hi Jakub,

I am fine to use YAML for this, but I will let Marek comment since he is the
original author of this patch.

> 
> > +These features flags are read only and cannot be change at runtime.
> > +
> > +*  XDP_ABORTED
> > +
> > +This feature informs if netdev supports xdp aborted action.
> > +
> > +*  XDP_DROP
> > +
> > +This feature informs if netdev supports xdp drop action.
> > +
> > +*  XDP_PASS
> > +
> > +This feature informs if netdev supports xdp pass action.
> > +
> > +*  XDP_TX
> > +
> > +This feature informs if netdev supports xdp tx action.
> > +
> > +*  XDP_REDIRECT
> > +
> > +This feature informs if netdev supports xdp redirect action.
> > +It assumes the all beforehand mentioned flags are enabled.
> > +
> > +*  XDP_SOCK_ZEROCOPY
> > +
> > +This feature informs if netdev driver supports xdp zero copy.
> > +It assumes the all beforehand mentioned flags are enabled.
> 
> Why is this "assumption" worth documenting?

I guess we can remove it.
@Marek: any comment?

> 
> > +*  XDP_HW_OFFLOAD
> > +
> > +This feature informs if netdev driver supports xdp hw oflloading.
> > +
> > +*  XDP_TX_LOCK
> > +
> > +This feature informs if netdev ndo_xdp_xmit function requires locking.
> 
> Why is it relevant to the user?

Probably not, I kept it since it was in Marek's original patch.
@Marek: any comment?

> 
> > +*  XDP_REDIRECT_TARGET
> > +
> > +This feature informs if netdev implements ndo_xdp_xmit callback.
> 
> Does it make sense to rename XDP_REDIRECT -> XDP_REDIRECT_SOURCE then?

yes, naming is always hard :)

> 
> > +*  XDP_FRAG_RX
> > +
> > +This feature informs if netdev implements non-linear xdp buff support in
> > +the driver napi callback.
> 
> Who's the target audience? Maybe FRAG is not the best name?
> Scatter-gather or multi-buf may be more widely understood.

ack, fine. I will rename it in the formal series.

Regards,
Lorenzo

> 
> > +*  XDP_FRAG_TARGET
> > +
> > +This feature informs if netdev implements non-linear xdp buff support in
> > +ndo_xdp_xmit callback. XDP_FRAG_TARGET requires XDP_REDIRECT_TARGET is properly
> > +supported.
>
Lorenzo Bianconi Dec. 20, 2022, 10:11 a.m. UTC | #6
On Dec 19, Stanislav Fomichev wrote:
> On Mon, Dec 19, 2022 at 3:51 PM Marek Majtyka <alardam@gmail.com> wrote:
> >
> > At the time of writing, I wanted to be able to read additional information about the XDP capabilities of each network interface using ethtool. This change was intended for Linux users/admins, and not for XDP experts who mostly don't need it and prefer tasting XDP with netlink and bpf rather than reading network interface features with ethtool.
> 
> Anything preventing ethtool from doing probing similar to 'bpftool
> feature probe'?
> The problem with these feature bits is that they might diverge and/or
> not work at all for the backported patches (where the fix/feature has
> been backported, but the part that exports the bit hasn't) :-(
> OTOH, I'm not sure we can probe everything from your list, but we
> might try and see what's missing..

Hi Stanislav,

I have not added the ethtool support to this series yet since userspace part is
still missing but I think we can consider XDP as a sort of sw offload so it
would be nice for the user/sysadmin (not xdp or bpf developer) to check the NIC
XDP capabilities similar to what we can already do for other hw offload
features.
Moreover let's consider XDP_REDIRECT of a scatter-gather XDP frame into a
devmap. I do not think there is a way to test if the 'target' device supports
SG and so we are forced to disable this feature until all drivers support it.
Introducing XDP features we can enable it on per-driver basis.
I think the same apply for other capabilities as well and just assuming a given
feature is not supported if an e2e test is not working seems a bit inaccurate.

Regards,
Lorenzo

> 
> > On Mon, Dec 19, 2022 at 9:03 PM <sdf@google.com> wrote:
> >>
> >> On 12/19, Lorenzo Bianconi wrote:
> >> > From: Marek Majtyka <alardam@gmail.com>
> >>
> >> > Implement support for checking what kind of XDP features a netdev
> >> > supports. Previously, there was no way to do this other than to try to
> >> > create an AF_XDP socket on the interface or load an XDP program and see
> >> > if it worked. This commit changes this by adding a new variable which
> >> > describes all xdp supported functions on pretty detailed level:
> >>
> >> >   - aborted
> >> >   - drop
> >> >   - pass
> >> >   - tx
> >> >   - redirect
> >> >   - sock_zerocopy
> >> >   - hw_offload
> >> >   - redirect_target
> >> >   - tx_lock
> >> >   - frag_rx
> >> >   - frag_target
> >>
> >> > Zerocopy mode requires that redirect XDP operation is implemented in a
> >> > driver and the driver supports also zero copy mode. Full mode requires
> >> > that all XDP operation are implemented in the driver. Basic mode is just
> >> > full mode without redirect operation. Frag target requires
> >> > redirect_target one is supported by the driver.
> >>
> >> Can you share more about _why_ is it needed? If we can already obtain
> >> most of these signals via probing, why export the flags?
> >>
> >> > Initially, these new flags are disabled for all drivers by default.
> >>
> >> > Co-developed-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
> >> > Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
> >> > Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org>
> >> > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> >> > Signed-off-by: Marek Majtyka <alardam@gmail.com>
> >> > ---
> >> >   .../networking/netdev-xdp-features.rst        | 60 +++++++++++++++++
> >> >   include/linux/netdevice.h                     |  2 +
> >> >   include/linux/xdp_features.h                  | 64 +++++++++++++++++++
> >> >   include/uapi/linux/if_link.h                  |  7 ++
> >> >   include/uapi/linux/xdp_features.h             | 34 ++++++++++
> >> >   net/core/rtnetlink.c                          | 34 ++++++++++
> >> >   tools/include/uapi/linux/if_link.h            |  7 ++
> >> >   tools/include/uapi/linux/xdp_features.h       | 34 ++++++++++
> >> >   8 files changed, 242 insertions(+)
> >> >   create mode 100644 Documentation/networking/netdev-xdp-features.rst
> >> >   create mode 100644 include/linux/xdp_features.h
> >> >   create mode 100644 include/uapi/linux/xdp_features.h
> >> >   create mode 100644 tools/include/uapi/linux/xdp_features.h
> >>
> >> > diff --git a/Documentation/networking/netdev-xdp-features.rst
> >> > b/Documentation/networking/netdev-xdp-features.rst
> >> > new file mode 100644
> >> > index 000000000000..1dc803fe72dd
> >> > --- /dev/null
> >> > +++ b/Documentation/networking/netdev-xdp-features.rst
> >> > @@ -0,0 +1,60 @@
> >> > +.. SPDX-License-Identifier: GPL-2.0
> >> > +
> >> > +=====================
> >> > +Netdev XDP features
> >> > +=====================
> >> > +
> >> > + * XDP FEATURES FLAGS
> >> > +
> >> > +Following netdev xdp features flags can be retrieved over route netlink
> >> > +interface (compact form) - the same way as netdev feature flags.
> >> > +These features flags are read only and cannot be change at runtime.
> >> > +
> >> > +*  XDP_ABORTED
> >> > +
> >> > +This feature informs if netdev supports xdp aborted action.
> >> > +
> >> > +*  XDP_DROP
> >> > +
> >> > +This feature informs if netdev supports xdp drop action.
> >> > +
> >> > +*  XDP_PASS
> >> > +
> >> > +This feature informs if netdev supports xdp pass action.
> >> > +
> >> > +*  XDP_TX
> >> > +
> >> > +This feature informs if netdev supports xdp tx action.
> >> > +
> >> > +*  XDP_REDIRECT
> >> > +
> >> > +This feature informs if netdev supports xdp redirect action.
> >> > +It assumes the all beforehand mentioned flags are enabled.
> >> > +
> >> > +*  XDP_SOCK_ZEROCOPY
> >> > +
> >> > +This feature informs if netdev driver supports xdp zero copy.
> >> > +It assumes the all beforehand mentioned flags are enabled.
> >> > +
> >> > +*  XDP_HW_OFFLOAD
> >> > +
> >> > +This feature informs if netdev driver supports xdp hw oflloading.
> >> > +
> >> > +*  XDP_TX_LOCK
> >> > +
> >> > +This feature informs if netdev ndo_xdp_xmit function requires locking.
> >> > +
> >> > +*  XDP_REDIRECT_TARGET
> >> > +
> >> > +This feature informs if netdev implements ndo_xdp_xmit callback.
> >> > +
> >> > +*  XDP_FRAG_RX
> >> > +
> >> > +This feature informs if netdev implements non-linear xdp buff support in
> >> > +the driver napi callback.
> >> > +
> >> > +*  XDP_FRAG_TARGET
> >> > +
> >> > +This feature informs if netdev implements non-linear xdp buff support in
> >> > +ndo_xdp_xmit callback. XDP_FRAG_TARGET requires XDP_REDIRECT_TARGET is
> >> > properly
> >> > +supported.
> >> > diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
> >> > index aad12a179e54..ae5a8564383b 100644
> >> > --- a/include/linux/netdevice.h
> >> > +++ b/include/linux/netdevice.h
> >> > @@ -43,6 +43,7 @@
> >> >   #include <net/xdp.h>
> >>
> >> >   #include <linux/netdev_features.h>
> >> > +#include <linux/xdp_features.h>
> >> >   #include <linux/neighbour.h>
> >> >   #include <uapi/linux/netdevice.h>
> >> >   #include <uapi/linux/if_bonding.h>
> >> > @@ -2362,6 +2363,7 @@ struct net_device {
> >> >       struct rtnl_hw_stats64  *offload_xstats_l3;
> >>
> >> >       struct devlink_port     *devlink_port;
> >> > +     xdp_features_t          xdp_features;
> >> >   };
> >> >   #define to_net_dev(d) container_of(d, struct net_device, dev)
> >>
> >> > diff --git a/include/linux/xdp_features.h b/include/linux/xdp_features.h
> >> > new file mode 100644
> >> > index 000000000000..4e72a86ef329
> >> > --- /dev/null
> >> > +++ b/include/linux/xdp_features.h
> >> > @@ -0,0 +1,64 @@
> >> > +/* SPDX-License-Identifier: GPL-2.0-or-later */
> >> > +/*
> >> > + * Network device xdp features.
> >> > + */
> >> > +#ifndef _LINUX_XDP_FEATURES_H
> >> > +#define _LINUX_XDP_FEATURES_H
> >> > +
> >> > +#include <linux/types.h>
> >> > +#include <linux/bitops.h>
> >> > +#include <asm/byteorder.h>
> >> > +#include <uapi/linux/xdp_features.h>
> >> > +
> >> > +typedef u32 xdp_features_t;
> >> > +
> >> > +#define __XDP_F_BIT(bit)     ((xdp_features_t)1 << (bit))
> >> > +#define __XDP_F(name)                __XDP_F_BIT(XDP_F_##name##_BIT)
> >> > +
> >> > +#define XDP_F_ABORTED                __XDP_F(ABORTED)
> >> > +#define XDP_F_DROP           __XDP_F(DROP)
> >> > +#define XDP_F_PASS           __XDP_F(PASS)
> >> > +#define XDP_F_TX             __XDP_F(TX)
> >> > +#define XDP_F_REDIRECT               __XDP_F(REDIRECT)
> >> > +#define XDP_F_REDIRECT_TARGET        __XDP_F(REDIRECT_TARGET)
> >> > +#define XDP_F_SOCK_ZEROCOPY  __XDP_F(SOCK_ZEROCOPY)
> >> > +#define XDP_F_HW_OFFLOAD     __XDP_F(HW_OFFLOAD)
> >> > +#define XDP_F_TX_LOCK                __XDP_F(TX_LOCK)
> >> > +#define XDP_F_FRAG_RX                __XDP_F(FRAG_RX)
> >> > +#define XDP_F_FRAG_TARGET    __XDP_F(FRAG_TARGET)
> >> > +
> >> > +#define XDP_F_BASIC          (XDP_F_ABORTED | XDP_F_DROP |   \
> >> > +                              XDP_F_PASS | XDP_F_TX)
> >> > +
> >> > +#define XDP_F_FULL           (XDP_F_BASIC | XDP_F_REDIRECT)
> >> > +
> >> > +#define XDP_F_FULL_ZC                (XDP_F_FULL | XDP_F_SOCK_ZEROCOPY)
> >> > +
> >> > +#define XDP_FEATURES_ABORTED_STR             "xdp-aborted"
> >> > +#define XDP_FEATURES_DROP_STR                        "xdp-drop"
> >> > +#define XDP_FEATURES_PASS_STR                        "xdp-pass"
> >> > +#define XDP_FEATURES_TX_STR                  "xdp-tx"
> >> > +#define XDP_FEATURES_REDIRECT_STR            "xdp-redirect"
> >> > +#define XDP_FEATURES_REDIRECT_TARGET_STR     "xdp-redirect-target"
> >> > +#define XDP_FEATURES_SOCK_ZEROCOPY_STR               "xdp-sock-zerocopy"
> >> > +#define XDP_FEATURES_HW_OFFLOAD_STR          "xdp-hw-offload"
> >> > +#define XDP_FEATURES_TX_LOCK_STR             "xdp-tx-lock"
> >> > +#define XDP_FEATURES_FRAG_RX_STR             "xdp-frag-rx"
> >> > +#define XDP_FEATURES_FRAG_TARGET_STR         "xdp-frag-target"
> >> > +
> >> > +#define DECLARE_XDP_FEATURES_TABLE(name, length)                             \
> >> > +     const char name[][length] = {                                           \
> >> > +             [XDP_F_ABORTED_BIT] = XDP_FEATURES_ABORTED_STR,                 \
> >> > +             [XDP_F_DROP_BIT] = XDP_FEATURES_DROP_STR,                       \
> >> > +             [XDP_F_PASS_BIT] = XDP_FEATURES_PASS_STR,                       \
> >> > +             [XDP_F_TX_BIT] = XDP_FEATURES_TX_STR,                           \
> >> > +             [XDP_F_REDIRECT_BIT] = XDP_FEATURES_REDIRECT_STR,               \
> >> > +             [XDP_F_REDIRECT_TARGET_BIT] = XDP_FEATURES_REDIRECT_TARGET_STR, \
> >> > +             [XDP_F_SOCK_ZEROCOPY_BIT] = XDP_FEATURES_SOCK_ZEROCOPY_STR,     \
> >> > +             [XDP_F_HW_OFFLOAD_BIT] = XDP_FEATURES_HW_OFFLOAD_STR,           \
> >> > +             [XDP_F_TX_LOCK_BIT] = XDP_FEATURES_TX_LOCK_STR,                 \
> >> > +             [XDP_F_FRAG_RX_BIT] = XDP_FEATURES_FRAG_RX_STR,                 \
> >> > +             [XDP_F_FRAG_TARGET_BIT] = XDP_FEATURES_FRAG_TARGET_STR,         \
> >> > +     }
> >> > +
> >> > +#endif /* _LINUX_XDP_FEATURES_H */
> >> > diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
> >> > index 1021a7e47a86..971c658ceaea 100644
> >> > --- a/include/uapi/linux/if_link.h
> >> > +++ b/include/uapi/linux/if_link.h
> >> > @@ -374,6 +374,8 @@ enum {
> >>
> >> >       IFLA_DEVLINK_PORT,
> >>
> >> > +     IFLA_XDP_FEATURES,
> >> > +
> >> >       __IFLA_MAX
> >> >   };
> >>
> >> > @@ -1318,6 +1320,11 @@ enum {
> >>
> >> >   #define IFLA_XDP_MAX (__IFLA_XDP_MAX - 1)
> >>
> >> > +enum {
> >> > +     IFLA_XDP_FEATURES_WORD_UNSPEC = 0,
> >> > +     IFLA_XDP_FEATURES_BITS_WORD,
> >> > +};
> >> > +
> >> >   enum {
> >> >       IFLA_EVENT_NONE,
> >> >       IFLA_EVENT_REBOOT,              /* internal reset / reboot */
> >> > diff --git a/include/uapi/linux/xdp_features.h
> >> > b/include/uapi/linux/xdp_features.h
> >> > new file mode 100644
> >> > index 000000000000..48eb42069bcd
> >> > --- /dev/null
> >> > +++ b/include/uapi/linux/xdp_features.h
> >> > @@ -0,0 +1,34 @@
> >> > +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
> >> > +/*
> >> > + * Copyright (c) 2020 Intel
> >> > + */
> >> > +
> >> > +#ifndef __UAPI_LINUX_XDP_FEATURES__
> >> > +#define __UAPI_LINUX_XDP_FEATURES__
> >> > +
> >> > +enum {
> >> > +     XDP_F_ABORTED_BIT,
> >> > +     XDP_F_DROP_BIT,
> >> > +     XDP_F_PASS_BIT,
> >> > +     XDP_F_TX_BIT,
> >> > +     XDP_F_REDIRECT_BIT,
> >> > +     XDP_F_REDIRECT_TARGET_BIT,
> >> > +     XDP_F_SOCK_ZEROCOPY_BIT,
> >> > +     XDP_F_HW_OFFLOAD_BIT,
> >> > +     XDP_F_TX_LOCK_BIT,
> >> > +     XDP_F_FRAG_RX_BIT,
> >> > +     XDP_F_FRAG_TARGET_BIT,
> >> > +     /*
> >> > +      * Add your fresh new property above and remember to update
> >> > +      * documentation.
> >> > +      */
> >> > +     XDP_FEATURES_COUNT,
> >> > +};
> >> > +
> >> > +#define XDP_FEATURES_WORDS                   ((XDP_FEATURES_COUNT + 32 - 1) / 32)
> >> > +#define XDP_FEATURES_WORD(blocks, index)     ((blocks)[(index) / 32U])
> >> > +#define XDP_FEATURES_FIELD_FLAG(index)               (1U << (index) % 32U)
> >> > +#define XDP_FEATURES_BIT_IS_SET(blocks, index)        \
> >> > +     (XDP_FEATURES_WORD(blocks, index) & XDP_FEATURES_FIELD_FLAG(index))
> >> > +
> >> > +#endif  /* __UAPI_LINUX_XDP_FEATURES__ */
> >> > diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
> >> > index 64289bc98887..1c299746b614 100644
> >> > --- a/net/core/rtnetlink.c
> >> > +++ b/net/core/rtnetlink.c
> >> > @@ -1016,6 +1016,14 @@ static size_t rtnl_xdp_size(void)
> >> >       return xdp_size;
> >> >   }
> >>
> >> > +static size_t rtnl_xdp_features_size(void)
> >> > +{
> >> > +     size_t xdp_size = nla_total_size(0) +   /* nest IFLA_XDP_FEATURES */
> >> > +                       XDP_FEATURES_WORDS * nla_total_size(4);
> >> > +
> >> > +     return xdp_size;
> >> > +}
> >> > +
> >> >   static size_t rtnl_prop_list_size(const struct net_device *dev)
> >> >   {
> >> >       struct netdev_name_node *name_node;
> >> > @@ -1103,6 +1111,7 @@ static noinline size_t if_nlmsg_size(const struct
> >> > net_device *dev,
> >> >              + rtnl_prop_list_size(dev)
> >> >              + nla_total_size(MAX_ADDR_LEN) /* IFLA_PERM_ADDRESS */
> >> >              + rtnl_devlink_port_size(dev)
> >> > +            + rtnl_xdp_features_size() /* IFLA_XDP_FEATURES */
> >> >              + 0;
> >> >   }
> >>
> >> > @@ -1546,6 +1555,27 @@ static int rtnl_xdp_fill(struct sk_buff *skb,
> >> > struct net_device *dev)
> >> >       return err;
> >> >   }
> >>
> >> > +static int rtnl_xdp_features_fill(struct sk_buff *skb, struct net_device
> >> > *dev)
> >> > +{
> >> > +     struct nlattr *attr;
> >> > +
> >> > +     attr = nla_nest_start_noflag(skb, IFLA_XDP_FEATURES);
> >> > +     if (!attr)
> >> > +             return -EMSGSIZE;
> >> > +
> >> > +     BUILD_BUG_ON(XDP_FEATURES_WORDS != 1);
> >> > +     if (nla_put_u32(skb, IFLA_XDP_FEATURES_BITS_WORD, dev->xdp_features))
> >> > +             goto err_cancel;
> >> > +
> >> > +     nla_nest_end(skb, attr);
> >> > +
> >> > +     return 0;
> >> > +
> >> > +err_cancel:
> >> > +     nla_nest_cancel(skb, attr);
> >> > +     return -EMSGSIZE;
> >> > +}
> >> > +
> >> >   static u32 rtnl_get_event(unsigned long event)
> >> >   {
> >> >       u32 rtnl_event_type = IFLA_EVENT_NONE;
> >> > @@ -1904,6 +1934,9 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb,
> >> >       if (rtnl_fill_devlink_port(skb, dev))
> >> >               goto nla_put_failure;
> >>
> >> > +     if (rtnl_xdp_features_fill(skb, dev))
> >> > +             goto nla_put_failure;
> >> > +
> >> >       nlmsg_end(skb, nlh);
> >> >       return 0;
> >>
> >> > @@ -1968,6 +2001,7 @@ static const struct nla_policy
> >> > ifla_policy[IFLA_MAX+1] = {
> >> >       [IFLA_TSO_MAX_SIZE]     = { .type = NLA_REJECT },
> >> >       [IFLA_TSO_MAX_SEGS]     = { .type = NLA_REJECT },
> >> >       [IFLA_ALLMULTI]         = { .type = NLA_REJECT },
> >> > +     [IFLA_XDP_FEATURES]     = { .type = NLA_NESTED },
> >> >   };
> >>
> >> >   static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
> >> > diff --git a/tools/include/uapi/linux/if_link.h
> >> > b/tools/include/uapi/linux/if_link.h
> >> > index 82fe18f26db5..994228e9909a 100644
> >> > --- a/tools/include/uapi/linux/if_link.h
> >> > +++ b/tools/include/uapi/linux/if_link.h
> >> > @@ -354,6 +354,8 @@ enum {
> >>
> >> >       IFLA_DEVLINK_PORT,
> >>
> >> > +     IFLA_XDP_FEATURES,
> >> > +
> >> >       __IFLA_MAX
> >> >   };
> >>
> >> > @@ -1222,6 +1224,11 @@ enum {
> >>
> >> >   #define IFLA_XDP_MAX (__IFLA_XDP_MAX - 1)
> >>
> >> > +enum {
> >> > +     IFLA_XDP_FEATURES_WORD_UNSPEC = 0,
> >> > +     IFLA_XDP_FEATURES_BITS_WORD,
> >> > +};
> >> > +
> >> >   enum {
> >> >       IFLA_EVENT_NONE,
> >> >       IFLA_EVENT_REBOOT,              /* internal reset / reboot */
> >> > diff --git a/tools/include/uapi/linux/xdp_features.h
> >> > b/tools/include/uapi/linux/xdp_features.h
> >> > new file mode 100644
> >> > index 000000000000..48eb42069bcd
> >> > --- /dev/null
> >> > +++ b/tools/include/uapi/linux/xdp_features.h
> >> > @@ -0,0 +1,34 @@
> >> > +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
> >> > +/*
> >> > + * Copyright (c) 2020 Intel
> >> > + */
> >> > +
> >> > +#ifndef __UAPI_LINUX_XDP_FEATURES__
> >> > +#define __UAPI_LINUX_XDP_FEATURES__
> >> > +
> >> > +enum {
> >> > +     XDP_F_ABORTED_BIT,
> >> > +     XDP_F_DROP_BIT,
> >> > +     XDP_F_PASS_BIT,
> >> > +     XDP_F_TX_BIT,
> >> > +     XDP_F_REDIRECT_BIT,
> >> > +     XDP_F_REDIRECT_TARGET_BIT,
> >> > +     XDP_F_SOCK_ZEROCOPY_BIT,
> >> > +     XDP_F_HW_OFFLOAD_BIT,
> >> > +     XDP_F_TX_LOCK_BIT,
> >> > +     XDP_F_FRAG_RX_BIT,
> >> > +     XDP_F_FRAG_TARGET_BIT,
> >> > +     /*
> >> > +      * Add your fresh new property above and remember to update
> >> > +      * documentation.
> >> > +      */
> >> > +     XDP_FEATURES_COUNT,
> >> > +};
> >> > +
> >> > +#define XDP_FEATURES_WORDS                   ((XDP_FEATURES_COUNT + 32 - 1) / 32)
> >> > +#define XDP_FEATURES_WORD(blocks, index)     ((blocks)[(index) / 32U])
> >> > +#define XDP_FEATURES_FIELD_FLAG(index)               (1U << (index) % 32U)
> >> > +#define XDP_FEATURES_BIT_IS_SET(blocks, index)        \
> >> > +     (XDP_FEATURES_WORD(blocks, index) & XDP_FEATURES_FIELD_FLAG(index))
> >> > +
> >> > +#endif  /* __UAPI_LINUX_XDP_FEATURES__ */
> >> > --
> >> > 2.38.1
> >>
>
Stanislav Fomichev Dec. 20, 2022, 6:03 p.m. UTC | #7
On Tue, Dec 20, 2022 at 2:11 AM Lorenzo Bianconi
<lorenzo.bianconi@redhat.com> wrote:
>
> On Dec 19, Stanislav Fomichev wrote:
> > On Mon, Dec 19, 2022 at 3:51 PM Marek Majtyka <alardam@gmail.com> wrote:
> > >
> > > At the time of writing, I wanted to be able to read additional information about the XDP capabilities of each network interface using ethtool. This change was intended for Linux users/admins, and not for XDP experts who mostly don't need it and prefer tasting XDP with netlink and bpf rather than reading network interface features with ethtool.
> >
> > Anything preventing ethtool from doing probing similar to 'bpftool
> > feature probe'?
> > The problem with these feature bits is that they might diverge and/or
> > not work at all for the backported patches (where the fix/feature has
> > been backported, but the part that exports the bit hasn't) :-(
> > OTOH, I'm not sure we can probe everything from your list, but we
> > might try and see what's missing..
>
> Hi Stanislav,
>
> I have not added the ethtool support to this series yet since userspace part is
> still missing but I think we can consider XDP as a sort of sw offload so it
> would be nice for the user/sysadmin (not xdp or bpf developer) to check the NIC
> XDP capabilities similar to what we can already do for other hw offload
> features.

[..]

> Moreover let's consider XDP_REDIRECT of a scatter-gather XDP frame into a
> devmap. I do not think there is a way to test if the 'target' device supports
> SG and so we are forced to disable this feature until all drivers support it.

See below for more questions, but why "target device has prog
installed and the aux->xdp_has_frags == true" won't work for the
internal kernel consumers?

> Introducing XDP features we can enable it on per-driver basis.
> I think the same apply for other capabilities as well and just assuming a given
> feature is not supported if an e2e test is not working seems a bit inaccurate.

Ok, I see that these bits are used in the later patches in xsk and
devmap. But I guess I'm still confused about why we add all these
flags, but only use mostly XDP_F_REDIRECT_TARGET; maybe start with
that one? And why does it have to be exposed to the userspace?
(userspace can still probe per-device features by trying to load
different progs?)

Also, it seems like XDP_F_REDIRECT_TARGET really means "the bpf
program has been installed on this device". Instead of a flag, why not
explicitly check whether the target device has a prog installed (and,
if needed, whether the installed program has frags support)?

> Regards,
> Lorenzo
>
> >
> > > On Mon, Dec 19, 2022 at 9:03 PM <sdf@google.com> wrote:
> > >>
> > >> On 12/19, Lorenzo Bianconi wrote:
> > >> > From: Marek Majtyka <alardam@gmail.com>
> > >>
> > >> > Implement support for checking what kind of XDP features a netdev
> > >> > supports. Previously, there was no way to do this other than to try to
> > >> > create an AF_XDP socket on the interface or load an XDP program and see
> > >> > if it worked. This commit changes this by adding a new variable which
> > >> > describes all xdp supported functions on pretty detailed level:
> > >>
> > >> >   - aborted
> > >> >   - drop
> > >> >   - pass
> > >> >   - tx
> > >> >   - redirect
> > >> >   - sock_zerocopy
> > >> >   - hw_offload
> > >> >   - redirect_target
> > >> >   - tx_lock
> > >> >   - frag_rx
> > >> >   - frag_target
> > >>
> > >> > Zerocopy mode requires that redirect XDP operation is implemented in a
> > >> > driver and the driver supports also zero copy mode. Full mode requires
> > >> > that all XDP operation are implemented in the driver. Basic mode is just
> > >> > full mode without redirect operation. Frag target requires
> > >> > redirect_target one is supported by the driver.
> > >>
> > >> Can you share more about _why_ is it needed? If we can already obtain
> > >> most of these signals via probing, why export the flags?
> > >>
> > >> > Initially, these new flags are disabled for all drivers by default.
> > >>
> > >> > Co-developed-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
> > >> > Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
> > >> > Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org>
> > >> > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> > >> > Signed-off-by: Marek Majtyka <alardam@gmail.com>
> > >> > ---
> > >> >   .../networking/netdev-xdp-features.rst        | 60 +++++++++++++++++
> > >> >   include/linux/netdevice.h                     |  2 +
> > >> >   include/linux/xdp_features.h                  | 64 +++++++++++++++++++
> > >> >   include/uapi/linux/if_link.h                  |  7 ++
> > >> >   include/uapi/linux/xdp_features.h             | 34 ++++++++++
> > >> >   net/core/rtnetlink.c                          | 34 ++++++++++
> > >> >   tools/include/uapi/linux/if_link.h            |  7 ++
> > >> >   tools/include/uapi/linux/xdp_features.h       | 34 ++++++++++
> > >> >   8 files changed, 242 insertions(+)
> > >> >   create mode 100644 Documentation/networking/netdev-xdp-features.rst
> > >> >   create mode 100644 include/linux/xdp_features.h
> > >> >   create mode 100644 include/uapi/linux/xdp_features.h
> > >> >   create mode 100644 tools/include/uapi/linux/xdp_features.h
> > >>
> > >> > diff --git a/Documentation/networking/netdev-xdp-features.rst
> > >> > b/Documentation/networking/netdev-xdp-features.rst
> > >> > new file mode 100644
> > >> > index 000000000000..1dc803fe72dd
> > >> > --- /dev/null
> > >> > +++ b/Documentation/networking/netdev-xdp-features.rst
> > >> > @@ -0,0 +1,60 @@
> > >> > +.. SPDX-License-Identifier: GPL-2.0
> > >> > +
> > >> > +=====================
> > >> > +Netdev XDP features
> > >> > +=====================
> > >> > +
> > >> > + * XDP FEATURES FLAGS
> > >> > +
> > >> > +Following netdev xdp features flags can be retrieved over route netlink
> > >> > +interface (compact form) - the same way as netdev feature flags.
> > >> > +These features flags are read only and cannot be change at runtime.
> > >> > +
> > >> > +*  XDP_ABORTED
> > >> > +
> > >> > +This feature informs if netdev supports xdp aborted action.
> > >> > +
> > >> > +*  XDP_DROP
> > >> > +
> > >> > +This feature informs if netdev supports xdp drop action.
> > >> > +
> > >> > +*  XDP_PASS
> > >> > +
> > >> > +This feature informs if netdev supports xdp pass action.
> > >> > +
> > >> > +*  XDP_TX
> > >> > +
> > >> > +This feature informs if netdev supports xdp tx action.
> > >> > +
> > >> > +*  XDP_REDIRECT
> > >> > +
> > >> > +This feature informs if netdev supports xdp redirect action.
> > >> > +It assumes the all beforehand mentioned flags are enabled.
> > >> > +
> > >> > +*  XDP_SOCK_ZEROCOPY
> > >> > +
> > >> > +This feature informs if netdev driver supports xdp zero copy.
> > >> > +It assumes the all beforehand mentioned flags are enabled.
> > >> > +
> > >> > +*  XDP_HW_OFFLOAD
> > >> > +
> > >> > +This feature informs if netdev driver supports xdp hw oflloading.
> > >> > +
> > >> > +*  XDP_TX_LOCK
> > >> > +
> > >> > +This feature informs if netdev ndo_xdp_xmit function requires locking.
> > >> > +
> > >> > +*  XDP_REDIRECT_TARGET
> > >> > +
> > >> > +This feature informs if netdev implements ndo_xdp_xmit callback.
> > >> > +
> > >> > +*  XDP_FRAG_RX
> > >> > +
> > >> > +This feature informs if netdev implements non-linear xdp buff support in
> > >> > +the driver napi callback.
> > >> > +
> > >> > +*  XDP_FRAG_TARGET
> > >> > +
> > >> > +This feature informs if netdev implements non-linear xdp buff support in
> > >> > +ndo_xdp_xmit callback. XDP_FRAG_TARGET requires XDP_REDIRECT_TARGET is
> > >> > properly
> > >> > +supported.
> > >> > diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
> > >> > index aad12a179e54..ae5a8564383b 100644
> > >> > --- a/include/linux/netdevice.h
> > >> > +++ b/include/linux/netdevice.h
> > >> > @@ -43,6 +43,7 @@
> > >> >   #include <net/xdp.h>
> > >>
> > >> >   #include <linux/netdev_features.h>
> > >> > +#include <linux/xdp_features.h>
> > >> >   #include <linux/neighbour.h>
> > >> >   #include <uapi/linux/netdevice.h>
> > >> >   #include <uapi/linux/if_bonding.h>
> > >> > @@ -2362,6 +2363,7 @@ struct net_device {
> > >> >       struct rtnl_hw_stats64  *offload_xstats_l3;
> > >>
> > >> >       struct devlink_port     *devlink_port;
> > >> > +     xdp_features_t          xdp_features;
> > >> >   };
> > >> >   #define to_net_dev(d) container_of(d, struct net_device, dev)
> > >>
> > >> > diff --git a/include/linux/xdp_features.h b/include/linux/xdp_features.h
> > >> > new file mode 100644
> > >> > index 000000000000..4e72a86ef329
> > >> > --- /dev/null
> > >> > +++ b/include/linux/xdp_features.h
> > >> > @@ -0,0 +1,64 @@
> > >> > +/* SPDX-License-Identifier: GPL-2.0-or-later */
> > >> > +/*
> > >> > + * Network device xdp features.
> > >> > + */
> > >> > +#ifndef _LINUX_XDP_FEATURES_H
> > >> > +#define _LINUX_XDP_FEATURES_H
> > >> > +
> > >> > +#include <linux/types.h>
> > >> > +#include <linux/bitops.h>
> > >> > +#include <asm/byteorder.h>
> > >> > +#include <uapi/linux/xdp_features.h>
> > >> > +
> > >> > +typedef u32 xdp_features_t;
> > >> > +
> > >> > +#define __XDP_F_BIT(bit)     ((xdp_features_t)1 << (bit))
> > >> > +#define __XDP_F(name)                __XDP_F_BIT(XDP_F_##name##_BIT)
> > >> > +
> > >> > +#define XDP_F_ABORTED                __XDP_F(ABORTED)
> > >> > +#define XDP_F_DROP           __XDP_F(DROP)
> > >> > +#define XDP_F_PASS           __XDP_F(PASS)
> > >> > +#define XDP_F_TX             __XDP_F(TX)
> > >> > +#define XDP_F_REDIRECT               __XDP_F(REDIRECT)
> > >> > +#define XDP_F_REDIRECT_TARGET        __XDP_F(REDIRECT_TARGET)
> > >> > +#define XDP_F_SOCK_ZEROCOPY  __XDP_F(SOCK_ZEROCOPY)
> > >> > +#define XDP_F_HW_OFFLOAD     __XDP_F(HW_OFFLOAD)
> > >> > +#define XDP_F_TX_LOCK                __XDP_F(TX_LOCK)
> > >> > +#define XDP_F_FRAG_RX                __XDP_F(FRAG_RX)
> > >> > +#define XDP_F_FRAG_TARGET    __XDP_F(FRAG_TARGET)
> > >> > +
> > >> > +#define XDP_F_BASIC          (XDP_F_ABORTED | XDP_F_DROP |   \
> > >> > +                              XDP_F_PASS | XDP_F_TX)
> > >> > +
> > >> > +#define XDP_F_FULL           (XDP_F_BASIC | XDP_F_REDIRECT)
> > >> > +
> > >> > +#define XDP_F_FULL_ZC                (XDP_F_FULL | XDP_F_SOCK_ZEROCOPY)
> > >> > +
> > >> > +#define XDP_FEATURES_ABORTED_STR             "xdp-aborted"
> > >> > +#define XDP_FEATURES_DROP_STR                        "xdp-drop"
> > >> > +#define XDP_FEATURES_PASS_STR                        "xdp-pass"
> > >> > +#define XDP_FEATURES_TX_STR                  "xdp-tx"
> > >> > +#define XDP_FEATURES_REDIRECT_STR            "xdp-redirect"
> > >> > +#define XDP_FEATURES_REDIRECT_TARGET_STR     "xdp-redirect-target"
> > >> > +#define XDP_FEATURES_SOCK_ZEROCOPY_STR               "xdp-sock-zerocopy"
> > >> > +#define XDP_FEATURES_HW_OFFLOAD_STR          "xdp-hw-offload"
> > >> > +#define XDP_FEATURES_TX_LOCK_STR             "xdp-tx-lock"
> > >> > +#define XDP_FEATURES_FRAG_RX_STR             "xdp-frag-rx"
> > >> > +#define XDP_FEATURES_FRAG_TARGET_STR         "xdp-frag-target"
> > >> > +
> > >> > +#define DECLARE_XDP_FEATURES_TABLE(name, length)                             \
> > >> > +     const char name[][length] = {                                           \
> > >> > +             [XDP_F_ABORTED_BIT] = XDP_FEATURES_ABORTED_STR,                 \
> > >> > +             [XDP_F_DROP_BIT] = XDP_FEATURES_DROP_STR,                       \
> > >> > +             [XDP_F_PASS_BIT] = XDP_FEATURES_PASS_STR,                       \
> > >> > +             [XDP_F_TX_BIT] = XDP_FEATURES_TX_STR,                           \
> > >> > +             [XDP_F_REDIRECT_BIT] = XDP_FEATURES_REDIRECT_STR,               \
> > >> > +             [XDP_F_REDIRECT_TARGET_BIT] = XDP_FEATURES_REDIRECT_TARGET_STR, \
> > >> > +             [XDP_F_SOCK_ZEROCOPY_BIT] = XDP_FEATURES_SOCK_ZEROCOPY_STR,     \
> > >> > +             [XDP_F_HW_OFFLOAD_BIT] = XDP_FEATURES_HW_OFFLOAD_STR,           \
> > >> > +             [XDP_F_TX_LOCK_BIT] = XDP_FEATURES_TX_LOCK_STR,                 \
> > >> > +             [XDP_F_FRAG_RX_BIT] = XDP_FEATURES_FRAG_RX_STR,                 \
> > >> > +             [XDP_F_FRAG_TARGET_BIT] = XDP_FEATURES_FRAG_TARGET_STR,         \
> > >> > +     }
> > >> > +
> > >> > +#endif /* _LINUX_XDP_FEATURES_H */
> > >> > diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
> > >> > index 1021a7e47a86..971c658ceaea 100644
> > >> > --- a/include/uapi/linux/if_link.h
> > >> > +++ b/include/uapi/linux/if_link.h
> > >> > @@ -374,6 +374,8 @@ enum {
> > >>
> > >> >       IFLA_DEVLINK_PORT,
> > >>
> > >> > +     IFLA_XDP_FEATURES,
> > >> > +
> > >> >       __IFLA_MAX
> > >> >   };
> > >>
> > >> > @@ -1318,6 +1320,11 @@ enum {
> > >>
> > >> >   #define IFLA_XDP_MAX (__IFLA_XDP_MAX - 1)
> > >>
> > >> > +enum {
> > >> > +     IFLA_XDP_FEATURES_WORD_UNSPEC = 0,
> > >> > +     IFLA_XDP_FEATURES_BITS_WORD,
> > >> > +};
> > >> > +
> > >> >   enum {
> > >> >       IFLA_EVENT_NONE,
> > >> >       IFLA_EVENT_REBOOT,              /* internal reset / reboot */
> > >> > diff --git a/include/uapi/linux/xdp_features.h
> > >> > b/include/uapi/linux/xdp_features.h
> > >> > new file mode 100644
> > >> > index 000000000000..48eb42069bcd
> > >> > --- /dev/null
> > >> > +++ b/include/uapi/linux/xdp_features.h
> > >> > @@ -0,0 +1,34 @@
> > >> > +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
> > >> > +/*
> > >> > + * Copyright (c) 2020 Intel
> > >> > + */
> > >> > +
> > >> > +#ifndef __UAPI_LINUX_XDP_FEATURES__
> > >> > +#define __UAPI_LINUX_XDP_FEATURES__
> > >> > +
> > >> > +enum {
> > >> > +     XDP_F_ABORTED_BIT,
> > >> > +     XDP_F_DROP_BIT,
> > >> > +     XDP_F_PASS_BIT,
> > >> > +     XDP_F_TX_BIT,
> > >> > +     XDP_F_REDIRECT_BIT,
> > >> > +     XDP_F_REDIRECT_TARGET_BIT,
> > >> > +     XDP_F_SOCK_ZEROCOPY_BIT,
> > >> > +     XDP_F_HW_OFFLOAD_BIT,
> > >> > +     XDP_F_TX_LOCK_BIT,
> > >> > +     XDP_F_FRAG_RX_BIT,
> > >> > +     XDP_F_FRAG_TARGET_BIT,
> > >> > +     /*
> > >> > +      * Add your fresh new property above and remember to update
> > >> > +      * documentation.
> > >> > +      */
> > >> > +     XDP_FEATURES_COUNT,
> > >> > +};
> > >> > +
> > >> > +#define XDP_FEATURES_WORDS                   ((XDP_FEATURES_COUNT + 32 - 1) / 32)
> > >> > +#define XDP_FEATURES_WORD(blocks, index)     ((blocks)[(index) / 32U])
> > >> > +#define XDP_FEATURES_FIELD_FLAG(index)               (1U << (index) % 32U)
> > >> > +#define XDP_FEATURES_BIT_IS_SET(blocks, index)        \
> > >> > +     (XDP_FEATURES_WORD(blocks, index) & XDP_FEATURES_FIELD_FLAG(index))
> > >> > +
> > >> > +#endif  /* __UAPI_LINUX_XDP_FEATURES__ */
> > >> > diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
> > >> > index 64289bc98887..1c299746b614 100644
> > >> > --- a/net/core/rtnetlink.c
> > >> > +++ b/net/core/rtnetlink.c
> > >> > @@ -1016,6 +1016,14 @@ static size_t rtnl_xdp_size(void)
> > >> >       return xdp_size;
> > >> >   }
> > >>
> > >> > +static size_t rtnl_xdp_features_size(void)
> > >> > +{
> > >> > +     size_t xdp_size = nla_total_size(0) +   /* nest IFLA_XDP_FEATURES */
> > >> > +                       XDP_FEATURES_WORDS * nla_total_size(4);
> > >> > +
> > >> > +     return xdp_size;
> > >> > +}
> > >> > +
> > >> >   static size_t rtnl_prop_list_size(const struct net_device *dev)
> > >> >   {
> > >> >       struct netdev_name_node *name_node;
> > >> > @@ -1103,6 +1111,7 @@ static noinline size_t if_nlmsg_size(const struct
> > >> > net_device *dev,
> > >> >              + rtnl_prop_list_size(dev)
> > >> >              + nla_total_size(MAX_ADDR_LEN) /* IFLA_PERM_ADDRESS */
> > >> >              + rtnl_devlink_port_size(dev)
> > >> > +            + rtnl_xdp_features_size() /* IFLA_XDP_FEATURES */
> > >> >              + 0;
> > >> >   }
> > >>
> > >> > @@ -1546,6 +1555,27 @@ static int rtnl_xdp_fill(struct sk_buff *skb,
> > >> > struct net_device *dev)
> > >> >       return err;
> > >> >   }
> > >>
> > >> > +static int rtnl_xdp_features_fill(struct sk_buff *skb, struct net_device
> > >> > *dev)
> > >> > +{
> > >> > +     struct nlattr *attr;
> > >> > +
> > >> > +     attr = nla_nest_start_noflag(skb, IFLA_XDP_FEATURES);
> > >> > +     if (!attr)
> > >> > +             return -EMSGSIZE;
> > >> > +
> > >> > +     BUILD_BUG_ON(XDP_FEATURES_WORDS != 1);
> > >> > +     if (nla_put_u32(skb, IFLA_XDP_FEATURES_BITS_WORD, dev->xdp_features))
> > >> > +             goto err_cancel;
> > >> > +
> > >> > +     nla_nest_end(skb, attr);
> > >> > +
> > >> > +     return 0;
> > >> > +
> > >> > +err_cancel:
> > >> > +     nla_nest_cancel(skb, attr);
> > >> > +     return -EMSGSIZE;
> > >> > +}
> > >> > +
> > >> >   static u32 rtnl_get_event(unsigned long event)
> > >> >   {
> > >> >       u32 rtnl_event_type = IFLA_EVENT_NONE;
> > >> > @@ -1904,6 +1934,9 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb,
> > >> >       if (rtnl_fill_devlink_port(skb, dev))
> > >> >               goto nla_put_failure;
> > >>
> > >> > +     if (rtnl_xdp_features_fill(skb, dev))
> > >> > +             goto nla_put_failure;
> > >> > +
> > >> >       nlmsg_end(skb, nlh);
> > >> >       return 0;
> > >>
> > >> > @@ -1968,6 +2001,7 @@ static const struct nla_policy
> > >> > ifla_policy[IFLA_MAX+1] = {
> > >> >       [IFLA_TSO_MAX_SIZE]     = { .type = NLA_REJECT },
> > >> >       [IFLA_TSO_MAX_SEGS]     = { .type = NLA_REJECT },
> > >> >       [IFLA_ALLMULTI]         = { .type = NLA_REJECT },
> > >> > +     [IFLA_XDP_FEATURES]     = { .type = NLA_NESTED },
> > >> >   };
> > >>
> > >> >   static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
> > >> > diff --git a/tools/include/uapi/linux/if_link.h
> > >> > b/tools/include/uapi/linux/if_link.h
> > >> > index 82fe18f26db5..994228e9909a 100644
> > >> > --- a/tools/include/uapi/linux/if_link.h
> > >> > +++ b/tools/include/uapi/linux/if_link.h
> > >> > @@ -354,6 +354,8 @@ enum {
> > >>
> > >> >       IFLA_DEVLINK_PORT,
> > >>
> > >> > +     IFLA_XDP_FEATURES,
> > >> > +
> > >> >       __IFLA_MAX
> > >> >   };
> > >>
> > >> > @@ -1222,6 +1224,11 @@ enum {
> > >>
> > >> >   #define IFLA_XDP_MAX (__IFLA_XDP_MAX - 1)
> > >>
> > >> > +enum {
> > >> > +     IFLA_XDP_FEATURES_WORD_UNSPEC = 0,
> > >> > +     IFLA_XDP_FEATURES_BITS_WORD,
> > >> > +};
> > >> > +
> > >> >   enum {
> > >> >       IFLA_EVENT_NONE,
> > >> >       IFLA_EVENT_REBOOT,              /* internal reset / reboot */
> > >> > diff --git a/tools/include/uapi/linux/xdp_features.h
> > >> > b/tools/include/uapi/linux/xdp_features.h
> > >> > new file mode 100644
> > >> > index 000000000000..48eb42069bcd
> > >> > --- /dev/null
> > >> > +++ b/tools/include/uapi/linux/xdp_features.h
> > >> > @@ -0,0 +1,34 @@
> > >> > +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
> > >> > +/*
> > >> > + * Copyright (c) 2020 Intel
> > >> > + */
> > >> > +
> > >> > +#ifndef __UAPI_LINUX_XDP_FEATURES__
> > >> > +#define __UAPI_LINUX_XDP_FEATURES__
> > >> > +
> > >> > +enum {
> > >> > +     XDP_F_ABORTED_BIT,
> > >> > +     XDP_F_DROP_BIT,
> > >> > +     XDP_F_PASS_BIT,
> > >> > +     XDP_F_TX_BIT,
> > >> > +     XDP_F_REDIRECT_BIT,
> > >> > +     XDP_F_REDIRECT_TARGET_BIT,
> > >> > +     XDP_F_SOCK_ZEROCOPY_BIT,
> > >> > +     XDP_F_HW_OFFLOAD_BIT,
> > >> > +     XDP_F_TX_LOCK_BIT,
> > >> > +     XDP_F_FRAG_RX_BIT,
> > >> > +     XDP_F_FRAG_TARGET_BIT,
> > >> > +     /*
> > >> > +      * Add your fresh new property above and remember to update
> > >> > +      * documentation.
> > >> > +      */
> > >> > +     XDP_FEATURES_COUNT,
> > >> > +};
> > >> > +
> > >> > +#define XDP_FEATURES_WORDS                   ((XDP_FEATURES_COUNT + 32 - 1) / 32)
> > >> > +#define XDP_FEATURES_WORD(blocks, index)     ((blocks)[(index) / 32U])
> > >> > +#define XDP_FEATURES_FIELD_FLAG(index)               (1U << (index) % 32U)
> > >> > +#define XDP_FEATURES_BIT_IS_SET(blocks, index)        \
> > >> > +     (XDP_FEATURES_WORD(blocks, index) & XDP_FEATURES_FIELD_FLAG(index))
> > >> > +
> > >> > +#endif  /* __UAPI_LINUX_XDP_FEATURES__ */
> > >> > --
> > >> > 2.38.1
> > >>
> >
Lorenzo Bianconi Dec. 20, 2022, 10:25 p.m. UTC | #8
> On Tue, Dec 20, 2022 at 2:11 AM Lorenzo Bianconi
> <lorenzo.bianconi@redhat.com> wrote:
> >
> > On Dec 19, Stanislav Fomichev wrote:
> > > On Mon, Dec 19, 2022 at 3:51 PM Marek Majtyka <alardam@gmail.com> wrote:
> > > >
> > > > At the time of writing, I wanted to be able to read additional information about the XDP capabilities of each network interface using ethtool. This change was intended for Linux users/admins, and not for XDP experts who mostly don't need it and prefer tasting XDP with netlink and bpf rather than reading network interface features with ethtool.
> > >
> > > Anything preventing ethtool from doing probing similar to 'bpftool
> > > feature probe'?
> > > The problem with these feature bits is that they might diverge and/or
> > > not work at all for the backported patches (where the fix/feature has
> > > been backported, but the part that exports the bit hasn't) :-(
> > > OTOH, I'm not sure we can probe everything from your list, but we
> > > might try and see what's missing..
> >
> > Hi Stanislav,
> >
> > I have not added the ethtool support to this series yet since userspace part is
> > still missing but I think we can consider XDP as a sort of sw offload so it
> > would be nice for the user/sysadmin (not xdp or bpf developer) to check the NIC
> > XDP capabilities similar to what we can already do for other hw offload
> > features.
> 
> [..]
> 
> > Moreover let's consider XDP_REDIRECT of a scatter-gather XDP frame into a
> > devmap. I do not think there is a way to test if the 'target' device supports
> > SG and so we are forced to disable this feature until all drivers support it.
> 
> See below for more questions, but why "target device has prog
> installed and the aux->xdp_has_frags == true" won't work for the
> internal kernel consumers?

There are some drivers (e.g. all intel ones) that currently do not support
non-linear xdp buff in the driver napi callback (XDP_FRAG_RX) but implement
non-linear xdp buff support in ndo_xdp_xmit callback (XDP_FRAG_TARGET).
Moreover, I guess for a sysadmin it would be better to check NIC capabilities in
the same way he/she is used to with other features (e.g. ethool -k ...).

> 
> > Introducing XDP features we can enable it on per-driver basis.
> > I think the same apply for other capabilities as well and just assuming a given
> > feature is not supported if an e2e test is not working seems a bit inaccurate.
> 
> Ok, I see that these bits are used in the later patches in xsk and
> devmap. But I guess I'm still confused about why we add all these
> flags, but only use mostly XDP_F_REDIRECT_TARGET; maybe start with
> that one? And why does it have to be exposed to the userspace?
> (userspace can still probe per-device features by trying to load
> different progs?)

There are some drivers (e.g. ixgbevf or cavium thunder) that do not support
XDP_REDIRECT but just XDP_PASS, XDP_DROP and XDP_TX, so I think we should
differentiate between XDP_BASIC (XDP_PASS | XDP_DROP | XDP_TX) and XDP_FULL
(XDP_BASIC | XDP_REDIRECT).

> 
> Also, it seems like XDP_F_REDIRECT_TARGET really means "the bpf
> program has been installed on this device". Instead of a flag, why not
> explicitly check whether the target device has a prog installed (and,
> if needed, whether the installed program has frags support)?

XDP_F_REDIRECT_TARGET is used to inform if netdev implements ndo_xdp_xmit
callback (most of the XDP drivers do not require to load a bpf program to
XDP_REDIRECT into them).

Regards,
Lorenzo

> 
> > Regards,
> > Lorenzo
> >
> > >
> > > > On Mon, Dec 19, 2022 at 9:03 PM <sdf@google.com> wrote:
> > > >>
> > > >> On 12/19, Lorenzo Bianconi wrote:
> > > >> > From: Marek Majtyka <alardam@gmail.com>
> > > >>
> > > >> > Implement support for checking what kind of XDP features a netdev
> > > >> > supports. Previously, there was no way to do this other than to try to
> > > >> > create an AF_XDP socket on the interface or load an XDP program and see
> > > >> > if it worked. This commit changes this by adding a new variable which
> > > >> > describes all xdp supported functions on pretty detailed level:
> > > >>
> > > >> >   - aborted
> > > >> >   - drop
> > > >> >   - pass
> > > >> >   - tx
> > > >> >   - redirect
> > > >> >   - sock_zerocopy
> > > >> >   - hw_offload
> > > >> >   - redirect_target
> > > >> >   - tx_lock
> > > >> >   - frag_rx
> > > >> >   - frag_target
> > > >>
> > > >> > Zerocopy mode requires that redirect XDP operation is implemented in a
> > > >> > driver and the driver supports also zero copy mode. Full mode requires
> > > >> > that all XDP operation are implemented in the driver. Basic mode is just
> > > >> > full mode without redirect operation. Frag target requires
> > > >> > redirect_target one is supported by the driver.
> > > >>
> > > >> Can you share more about _why_ is it needed? If we can already obtain
> > > >> most of these signals via probing, why export the flags?
> > > >>
> > > >> > Initially, these new flags are disabled for all drivers by default.
> > > >>
> > > >> > Co-developed-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
> > > >> > Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
> > > >> > Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org>
> > > >> > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> > > >> > Signed-off-by: Marek Majtyka <alardam@gmail.com>
> > > >> > ---
> > > >> >   .../networking/netdev-xdp-features.rst        | 60 +++++++++++++++++
> > > >> >   include/linux/netdevice.h                     |  2 +
> > > >> >   include/linux/xdp_features.h                  | 64 +++++++++++++++++++
> > > >> >   include/uapi/linux/if_link.h                  |  7 ++
> > > >> >   include/uapi/linux/xdp_features.h             | 34 ++++++++++
> > > >> >   net/core/rtnetlink.c                          | 34 ++++++++++
> > > >> >   tools/include/uapi/linux/if_link.h            |  7 ++
> > > >> >   tools/include/uapi/linux/xdp_features.h       | 34 ++++++++++
> > > >> >   8 files changed, 242 insertions(+)
> > > >> >   create mode 100644 Documentation/networking/netdev-xdp-features.rst
> > > >> >   create mode 100644 include/linux/xdp_features.h
> > > >> >   create mode 100644 include/uapi/linux/xdp_features.h
> > > >> >   create mode 100644 tools/include/uapi/linux/xdp_features.h
> > > >>
> > > >> > diff --git a/Documentation/networking/netdev-xdp-features.rst
> > > >> > b/Documentation/networking/netdev-xdp-features.rst
> > > >> > new file mode 100644
> > > >> > index 000000000000..1dc803fe72dd
> > > >> > --- /dev/null
> > > >> > +++ b/Documentation/networking/netdev-xdp-features.rst
> > > >> > @@ -0,0 +1,60 @@
> > > >> > +.. SPDX-License-Identifier: GPL-2.0
> > > >> > +
> > > >> > +=====================
> > > >> > +Netdev XDP features
> > > >> > +=====================
> > > >> > +
> > > >> > + * XDP FEATURES FLAGS
> > > >> > +
> > > >> > +Following netdev xdp features flags can be retrieved over route netlink
> > > >> > +interface (compact form) - the same way as netdev feature flags.
> > > >> > +These features flags are read only and cannot be change at runtime.
> > > >> > +
> > > >> > +*  XDP_ABORTED
> > > >> > +
> > > >> > +This feature informs if netdev supports xdp aborted action.
> > > >> > +
> > > >> > +*  XDP_DROP
> > > >> > +
> > > >> > +This feature informs if netdev supports xdp drop action.
> > > >> > +
> > > >> > +*  XDP_PASS
> > > >> > +
> > > >> > +This feature informs if netdev supports xdp pass action.
> > > >> > +
> > > >> > +*  XDP_TX
> > > >> > +
> > > >> > +This feature informs if netdev supports xdp tx action.
> > > >> > +
> > > >> > +*  XDP_REDIRECT
> > > >> > +
> > > >> > +This feature informs if netdev supports xdp redirect action.
> > > >> > +It assumes the all beforehand mentioned flags are enabled.
> > > >> > +
> > > >> > +*  XDP_SOCK_ZEROCOPY
> > > >> > +
> > > >> > +This feature informs if netdev driver supports xdp zero copy.
> > > >> > +It assumes the all beforehand mentioned flags are enabled.
> > > >> > +
> > > >> > +*  XDP_HW_OFFLOAD
> > > >> > +
> > > >> > +This feature informs if netdev driver supports xdp hw oflloading.
> > > >> > +
> > > >> > +*  XDP_TX_LOCK
> > > >> > +
> > > >> > +This feature informs if netdev ndo_xdp_xmit function requires locking.
> > > >> > +
> > > >> > +*  XDP_REDIRECT_TARGET
> > > >> > +
> > > >> > +This feature informs if netdev implements ndo_xdp_xmit callback.
> > > >> > +
> > > >> > +*  XDP_FRAG_RX
> > > >> > +
> > > >> > +This feature informs if netdev implements non-linear xdp buff support in
> > > >> > +the driver napi callback.
> > > >> > +
> > > >> > +*  XDP_FRAG_TARGET
> > > >> > +
> > > >> > +This feature informs if netdev implements non-linear xdp buff support in
> > > >> > +ndo_xdp_xmit callback. XDP_FRAG_TARGET requires XDP_REDIRECT_TARGET is
> > > >> > properly
> > > >> > +supported.
> > > >> > diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
> > > >> > index aad12a179e54..ae5a8564383b 100644
> > > >> > --- a/include/linux/netdevice.h
> > > >> > +++ b/include/linux/netdevice.h
> > > >> > @@ -43,6 +43,7 @@
> > > >> >   #include <net/xdp.h>
> > > >>
> > > >> >   #include <linux/netdev_features.h>
> > > >> > +#include <linux/xdp_features.h>
> > > >> >   #include <linux/neighbour.h>
> > > >> >   #include <uapi/linux/netdevice.h>
> > > >> >   #include <uapi/linux/if_bonding.h>
> > > >> > @@ -2362,6 +2363,7 @@ struct net_device {
> > > >> >       struct rtnl_hw_stats64  *offload_xstats_l3;
> > > >>
> > > >> >       struct devlink_port     *devlink_port;
> > > >> > +     xdp_features_t          xdp_features;
> > > >> >   };
> > > >> >   #define to_net_dev(d) container_of(d, struct net_device, dev)
> > > >>
> > > >> > diff --git a/include/linux/xdp_features.h b/include/linux/xdp_features.h
> > > >> > new file mode 100644
> > > >> > index 000000000000..4e72a86ef329
> > > >> > --- /dev/null
> > > >> > +++ b/include/linux/xdp_features.h
> > > >> > @@ -0,0 +1,64 @@
> > > >> > +/* SPDX-License-Identifier: GPL-2.0-or-later */
> > > >> > +/*
> > > >> > + * Network device xdp features.
> > > >> > + */
> > > >> > +#ifndef _LINUX_XDP_FEATURES_H
> > > >> > +#define _LINUX_XDP_FEATURES_H
> > > >> > +
> > > >> > +#include <linux/types.h>
> > > >> > +#include <linux/bitops.h>
> > > >> > +#include <asm/byteorder.h>
> > > >> > +#include <uapi/linux/xdp_features.h>
> > > >> > +
> > > >> > +typedef u32 xdp_features_t;
> > > >> > +
> > > >> > +#define __XDP_F_BIT(bit)     ((xdp_features_t)1 << (bit))
> > > >> > +#define __XDP_F(name)                __XDP_F_BIT(XDP_F_##name##_BIT)
> > > >> > +
> > > >> > +#define XDP_F_ABORTED                __XDP_F(ABORTED)
> > > >> > +#define XDP_F_DROP           __XDP_F(DROP)
> > > >> > +#define XDP_F_PASS           __XDP_F(PASS)
> > > >> > +#define XDP_F_TX             __XDP_F(TX)
> > > >> > +#define XDP_F_REDIRECT               __XDP_F(REDIRECT)
> > > >> > +#define XDP_F_REDIRECT_TARGET        __XDP_F(REDIRECT_TARGET)
> > > >> > +#define XDP_F_SOCK_ZEROCOPY  __XDP_F(SOCK_ZEROCOPY)
> > > >> > +#define XDP_F_HW_OFFLOAD     __XDP_F(HW_OFFLOAD)
> > > >> > +#define XDP_F_TX_LOCK                __XDP_F(TX_LOCK)
> > > >> > +#define XDP_F_FRAG_RX                __XDP_F(FRAG_RX)
> > > >> > +#define XDP_F_FRAG_TARGET    __XDP_F(FRAG_TARGET)
> > > >> > +
> > > >> > +#define XDP_F_BASIC          (XDP_F_ABORTED | XDP_F_DROP |   \
> > > >> > +                              XDP_F_PASS | XDP_F_TX)
> > > >> > +
> > > >> > +#define XDP_F_FULL           (XDP_F_BASIC | XDP_F_REDIRECT)
> > > >> > +
> > > >> > +#define XDP_F_FULL_ZC                (XDP_F_FULL | XDP_F_SOCK_ZEROCOPY)
> > > >> > +
> > > >> > +#define XDP_FEATURES_ABORTED_STR             "xdp-aborted"
> > > >> > +#define XDP_FEATURES_DROP_STR                        "xdp-drop"
> > > >> > +#define XDP_FEATURES_PASS_STR                        "xdp-pass"
> > > >> > +#define XDP_FEATURES_TX_STR                  "xdp-tx"
> > > >> > +#define XDP_FEATURES_REDIRECT_STR            "xdp-redirect"
> > > >> > +#define XDP_FEATURES_REDIRECT_TARGET_STR     "xdp-redirect-target"
> > > >> > +#define XDP_FEATURES_SOCK_ZEROCOPY_STR               "xdp-sock-zerocopy"
> > > >> > +#define XDP_FEATURES_HW_OFFLOAD_STR          "xdp-hw-offload"
> > > >> > +#define XDP_FEATURES_TX_LOCK_STR             "xdp-tx-lock"
> > > >> > +#define XDP_FEATURES_FRAG_RX_STR             "xdp-frag-rx"
> > > >> > +#define XDP_FEATURES_FRAG_TARGET_STR         "xdp-frag-target"
> > > >> > +
> > > >> > +#define DECLARE_XDP_FEATURES_TABLE(name, length)                             \
> > > >> > +     const char name[][length] = {                                           \
> > > >> > +             [XDP_F_ABORTED_BIT] = XDP_FEATURES_ABORTED_STR,                 \
> > > >> > +             [XDP_F_DROP_BIT] = XDP_FEATURES_DROP_STR,                       \
> > > >> > +             [XDP_F_PASS_BIT] = XDP_FEATURES_PASS_STR,                       \
> > > >> > +             [XDP_F_TX_BIT] = XDP_FEATURES_TX_STR,                           \
> > > >> > +             [XDP_F_REDIRECT_BIT] = XDP_FEATURES_REDIRECT_STR,               \
> > > >> > +             [XDP_F_REDIRECT_TARGET_BIT] = XDP_FEATURES_REDIRECT_TARGET_STR, \
> > > >> > +             [XDP_F_SOCK_ZEROCOPY_BIT] = XDP_FEATURES_SOCK_ZEROCOPY_STR,     \
> > > >> > +             [XDP_F_HW_OFFLOAD_BIT] = XDP_FEATURES_HW_OFFLOAD_STR,           \
> > > >> > +             [XDP_F_TX_LOCK_BIT] = XDP_FEATURES_TX_LOCK_STR,                 \
> > > >> > +             [XDP_F_FRAG_RX_BIT] = XDP_FEATURES_FRAG_RX_STR,                 \
> > > >> > +             [XDP_F_FRAG_TARGET_BIT] = XDP_FEATURES_FRAG_TARGET_STR,         \
> > > >> > +     }
> > > >> > +
> > > >> > +#endif /* _LINUX_XDP_FEATURES_H */
> > > >> > diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
> > > >> > index 1021a7e47a86..971c658ceaea 100644
> > > >> > --- a/include/uapi/linux/if_link.h
> > > >> > +++ b/include/uapi/linux/if_link.h
> > > >> > @@ -374,6 +374,8 @@ enum {
> > > >>
> > > >> >       IFLA_DEVLINK_PORT,
> > > >>
> > > >> > +     IFLA_XDP_FEATURES,
> > > >> > +
> > > >> >       __IFLA_MAX
> > > >> >   };
> > > >>
> > > >> > @@ -1318,6 +1320,11 @@ enum {
> > > >>
> > > >> >   #define IFLA_XDP_MAX (__IFLA_XDP_MAX - 1)
> > > >>
> > > >> > +enum {
> > > >> > +     IFLA_XDP_FEATURES_WORD_UNSPEC = 0,
> > > >> > +     IFLA_XDP_FEATURES_BITS_WORD,
> > > >> > +};
> > > >> > +
> > > >> >   enum {
> > > >> >       IFLA_EVENT_NONE,
> > > >> >       IFLA_EVENT_REBOOT,              /* internal reset / reboot */
> > > >> > diff --git a/include/uapi/linux/xdp_features.h
> > > >> > b/include/uapi/linux/xdp_features.h
> > > >> > new file mode 100644
> > > >> > index 000000000000..48eb42069bcd
> > > >> > --- /dev/null
> > > >> > +++ b/include/uapi/linux/xdp_features.h
> > > >> > @@ -0,0 +1,34 @@
> > > >> > +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
> > > >> > +/*
> > > >> > + * Copyright (c) 2020 Intel
> > > >> > + */
> > > >> > +
> > > >> > +#ifndef __UAPI_LINUX_XDP_FEATURES__
> > > >> > +#define __UAPI_LINUX_XDP_FEATURES__
> > > >> > +
> > > >> > +enum {
> > > >> > +     XDP_F_ABORTED_BIT,
> > > >> > +     XDP_F_DROP_BIT,
> > > >> > +     XDP_F_PASS_BIT,
> > > >> > +     XDP_F_TX_BIT,
> > > >> > +     XDP_F_REDIRECT_BIT,
> > > >> > +     XDP_F_REDIRECT_TARGET_BIT,
> > > >> > +     XDP_F_SOCK_ZEROCOPY_BIT,
> > > >> > +     XDP_F_HW_OFFLOAD_BIT,
> > > >> > +     XDP_F_TX_LOCK_BIT,
> > > >> > +     XDP_F_FRAG_RX_BIT,
> > > >> > +     XDP_F_FRAG_TARGET_BIT,
> > > >> > +     /*
> > > >> > +      * Add your fresh new property above and remember to update
> > > >> > +      * documentation.
> > > >> > +      */
> > > >> > +     XDP_FEATURES_COUNT,
> > > >> > +};
> > > >> > +
> > > >> > +#define XDP_FEATURES_WORDS                   ((XDP_FEATURES_COUNT + 32 - 1) / 32)
> > > >> > +#define XDP_FEATURES_WORD(blocks, index)     ((blocks)[(index) / 32U])
> > > >> > +#define XDP_FEATURES_FIELD_FLAG(index)               (1U << (index) % 32U)
> > > >> > +#define XDP_FEATURES_BIT_IS_SET(blocks, index)        \
> > > >> > +     (XDP_FEATURES_WORD(blocks, index) & XDP_FEATURES_FIELD_FLAG(index))
> > > >> > +
> > > >> > +#endif  /* __UAPI_LINUX_XDP_FEATURES__ */
> > > >> > diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
> > > >> > index 64289bc98887..1c299746b614 100644
> > > >> > --- a/net/core/rtnetlink.c
> > > >> > +++ b/net/core/rtnetlink.c
> > > >> > @@ -1016,6 +1016,14 @@ static size_t rtnl_xdp_size(void)
> > > >> >       return xdp_size;
> > > >> >   }
> > > >>
> > > >> > +static size_t rtnl_xdp_features_size(void)
> > > >> > +{
> > > >> > +     size_t xdp_size = nla_total_size(0) +   /* nest IFLA_XDP_FEATURES */
> > > >> > +                       XDP_FEATURES_WORDS * nla_total_size(4);
> > > >> > +
> > > >> > +     return xdp_size;
> > > >> > +}
> > > >> > +
> > > >> >   static size_t rtnl_prop_list_size(const struct net_device *dev)
> > > >> >   {
> > > >> >       struct netdev_name_node *name_node;
> > > >> > @@ -1103,6 +1111,7 @@ static noinline size_t if_nlmsg_size(const struct
> > > >> > net_device *dev,
> > > >> >              + rtnl_prop_list_size(dev)
> > > >> >              + nla_total_size(MAX_ADDR_LEN) /* IFLA_PERM_ADDRESS */
> > > >> >              + rtnl_devlink_port_size(dev)
> > > >> > +            + rtnl_xdp_features_size() /* IFLA_XDP_FEATURES */
> > > >> >              + 0;
> > > >> >   }
> > > >>
> > > >> > @@ -1546,6 +1555,27 @@ static int rtnl_xdp_fill(struct sk_buff *skb,
> > > >> > struct net_device *dev)
> > > >> >       return err;
> > > >> >   }
> > > >>
> > > >> > +static int rtnl_xdp_features_fill(struct sk_buff *skb, struct net_device
> > > >> > *dev)
> > > >> > +{
> > > >> > +     struct nlattr *attr;
> > > >> > +
> > > >> > +     attr = nla_nest_start_noflag(skb, IFLA_XDP_FEATURES);
> > > >> > +     if (!attr)
> > > >> > +             return -EMSGSIZE;
> > > >> > +
> > > >> > +     BUILD_BUG_ON(XDP_FEATURES_WORDS != 1);
> > > >> > +     if (nla_put_u32(skb, IFLA_XDP_FEATURES_BITS_WORD, dev->xdp_features))
> > > >> > +             goto err_cancel;
> > > >> > +
> > > >> > +     nla_nest_end(skb, attr);
> > > >> > +
> > > >> > +     return 0;
> > > >> > +
> > > >> > +err_cancel:
> > > >> > +     nla_nest_cancel(skb, attr);
> > > >> > +     return -EMSGSIZE;
> > > >> > +}
> > > >> > +
> > > >> >   static u32 rtnl_get_event(unsigned long event)
> > > >> >   {
> > > >> >       u32 rtnl_event_type = IFLA_EVENT_NONE;
> > > >> > @@ -1904,6 +1934,9 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb,
> > > >> >       if (rtnl_fill_devlink_port(skb, dev))
> > > >> >               goto nla_put_failure;
> > > >>
> > > >> > +     if (rtnl_xdp_features_fill(skb, dev))
> > > >> > +             goto nla_put_failure;
> > > >> > +
> > > >> >       nlmsg_end(skb, nlh);
> > > >> >       return 0;
> > > >>
> > > >> > @@ -1968,6 +2001,7 @@ static const struct nla_policy
> > > >> > ifla_policy[IFLA_MAX+1] = {
> > > >> >       [IFLA_TSO_MAX_SIZE]     = { .type = NLA_REJECT },
> > > >> >       [IFLA_TSO_MAX_SEGS]     = { .type = NLA_REJECT },
> > > >> >       [IFLA_ALLMULTI]         = { .type = NLA_REJECT },
> > > >> > +     [IFLA_XDP_FEATURES]     = { .type = NLA_NESTED },
> > > >> >   };
> > > >>
> > > >> >   static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
> > > >> > diff --git a/tools/include/uapi/linux/if_link.h
> > > >> > b/tools/include/uapi/linux/if_link.h
> > > >> > index 82fe18f26db5..994228e9909a 100644
> > > >> > --- a/tools/include/uapi/linux/if_link.h
> > > >> > +++ b/tools/include/uapi/linux/if_link.h
> > > >> > @@ -354,6 +354,8 @@ enum {
> > > >>
> > > >> >       IFLA_DEVLINK_PORT,
> > > >>
> > > >> > +     IFLA_XDP_FEATURES,
> > > >> > +
> > > >> >       __IFLA_MAX
> > > >> >   };
> > > >>
> > > >> > @@ -1222,6 +1224,11 @@ enum {
> > > >>
> > > >> >   #define IFLA_XDP_MAX (__IFLA_XDP_MAX - 1)
> > > >>
> > > >> > +enum {
> > > >> > +     IFLA_XDP_FEATURES_WORD_UNSPEC = 0,
> > > >> > +     IFLA_XDP_FEATURES_BITS_WORD,
> > > >> > +};
> > > >> > +
> > > >> >   enum {
> > > >> >       IFLA_EVENT_NONE,
> > > >> >       IFLA_EVENT_REBOOT,              /* internal reset / reboot */
> > > >> > diff --git a/tools/include/uapi/linux/xdp_features.h
> > > >> > b/tools/include/uapi/linux/xdp_features.h
> > > >> > new file mode 100644
> > > >> > index 000000000000..48eb42069bcd
> > > >> > --- /dev/null
> > > >> > +++ b/tools/include/uapi/linux/xdp_features.h
> > > >> > @@ -0,0 +1,34 @@
> > > >> > +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
> > > >> > +/*
> > > >> > + * Copyright (c) 2020 Intel
> > > >> > + */
> > > >> > +
> > > >> > +#ifndef __UAPI_LINUX_XDP_FEATURES__
> > > >> > +#define __UAPI_LINUX_XDP_FEATURES__
> > > >> > +
> > > >> > +enum {
> > > >> > +     XDP_F_ABORTED_BIT,
> > > >> > +     XDP_F_DROP_BIT,
> > > >> > +     XDP_F_PASS_BIT,
> > > >> > +     XDP_F_TX_BIT,
> > > >> > +     XDP_F_REDIRECT_BIT,
> > > >> > +     XDP_F_REDIRECT_TARGET_BIT,
> > > >> > +     XDP_F_SOCK_ZEROCOPY_BIT,
> > > >> > +     XDP_F_HW_OFFLOAD_BIT,
> > > >> > +     XDP_F_TX_LOCK_BIT,
> > > >> > +     XDP_F_FRAG_RX_BIT,
> > > >> > +     XDP_F_FRAG_TARGET_BIT,
> > > >> > +     /*
> > > >> > +      * Add your fresh new property above and remember to update
> > > >> > +      * documentation.
> > > >> > +      */
> > > >> > +     XDP_FEATURES_COUNT,
> > > >> > +};
> > > >> > +
> > > >> > +#define XDP_FEATURES_WORDS                   ((XDP_FEATURES_COUNT + 32 - 1) / 32)
> > > >> > +#define XDP_FEATURES_WORD(blocks, index)     ((blocks)[(index) / 32U])
> > > >> > +#define XDP_FEATURES_FIELD_FLAG(index)               (1U << (index) % 32U)
> > > >> > +#define XDP_FEATURES_BIT_IS_SET(blocks, index)        \
> > > >> > +     (XDP_FEATURES_WORD(blocks, index) & XDP_FEATURES_FIELD_FLAG(index))
> > > >> > +
> > > >> > +#endif  /* __UAPI_LINUX_XDP_FEATURES__ */
> > > >> > --
> > > >> > 2.38.1
> > > >>
> > >
Marek Majtyka Dec. 20, 2022, 10:51 p.m. UTC | #9
On Tue, Dec 20, 2022 at 10:20 AM Lorenzo Bianconi
<lorenzo.bianconi@redhat.com> wrote:
>
> > On Mon, 19 Dec 2022 16:41:31 +0100 Lorenzo Bianconi wrote:
> > > +=====================
> > > +Netdev XDP features
> > > +=====================
> > > +
> > > + * XDP FEATURES FLAGS
> > > +
> > > +Following netdev xdp features flags can be retrieved over route netlink
> > > +interface (compact form) - the same way as netdev feature flags.
> >
> > How likely is it that I'll be able to convince you that cramming more
> > stuff in rtnl is a bad idea? I can convert this for you to a YAML-
> > -compatible genetlink family for you in a jiffy, just say yes :S
> >
> > rtnl is hard to parse, and already overloaded with random stuff.
> > And the messages are enormous.
>
> Hi Jakub,
>
> I am fine to use YAML for this, but I will let Marek comment since he is the
> original author of this patch.
>
> >
> > > +These features flags are read only and cannot be change at runtime.
> > > +
> > > +*  XDP_ABORTED
> > > +
> > > +This feature informs if netdev supports xdp aborted action.
> > > +
> > > +*  XDP_DROP
> > > +
> > > +This feature informs if netdev supports xdp drop action.
> > > +
> > > +*  XDP_PASS
> > > +
> > > +This feature informs if netdev supports xdp pass action.
> > > +
> > > +*  XDP_TX
> > > +
> > > +This feature informs if netdev supports xdp tx action.
> > > +
> > > +*  XDP_REDIRECT
> > > +
> > > +This feature informs if netdev supports xdp redirect action.
> > > +It assumes the all beforehand mentioned flags are enabled.
> > > +
> > > +*  XDP_SOCK_ZEROCOPY
> > > +
> > > +This feature informs if netdev driver supports xdp zero copy.
> > > +It assumes the all beforehand mentioned flags are enabled.
> >
> > Why is this "assumption" worth documenting?
>
> I guess we can remove it.
> @Marek: any comment?
>
> >
> > > +*  XDP_HW_OFFLOAD
> > > +
> > > +This feature informs if netdev driver supports xdp hw oflloading.
> > > +
> > > +*  XDP_TX_LOCK
> > > +
> > > +This feature informs if netdev ndo_xdp_xmit function requires locking.
> >
> > Why is it relevant to the user?
>
> Probably not, I kept it since it was in Marek's original patch.
> @Marek: any comment?
>
> >
> > > +*  XDP_REDIRECT_TARGET
> > > +
> > > +This feature informs if netdev implements ndo_xdp_xmit callback.
> >
> > Does it make sense to rename XDP_REDIRECT -> XDP_REDIRECT_SOURCE then?
>
> yes, naming is always hard :)
>
> >
> > > +*  XDP_FRAG_RX
> > > +
> > > +This feature informs if netdev implements non-linear xdp buff support in
> > > +the driver napi callback.
> >
> > Who's the target audience? Maybe FRAG is not the best name?
> > Scatter-gather or multi-buf may be more widely understood.
>
> ack, fine. I will rename it in the formal series.
>
> Regards,
> Lorenzo
>
> >
> > > +*  XDP_FRAG_TARGET
> > > +
> > > +This feature informs if netdev implements non-linear xdp buff support in
> > > +ndo_xdp_xmit callback. XDP_FRAG_TARGET requires XDP_REDIRECT_TARGET is properly
> > > +supported.
> >
Everybody is allowed to make a good use of it. Every improvement is
highly appreciated. Thanks Lorenzo for taking this over.
Regards
Marek
Stanislav Fomichev Dec. 20, 2022, 11:36 p.m. UTC | #10
On Tue, Dec 20, 2022 at 2:25 PM Lorenzo Bianconi <lorenzo@kernel.org> wrote:
>
> > On Tue, Dec 20, 2022 at 2:11 AM Lorenzo Bianconi
> > <lorenzo.bianconi@redhat.com> wrote:
> > >
> > > On Dec 19, Stanislav Fomichev wrote:
> > > > On Mon, Dec 19, 2022 at 3:51 PM Marek Majtyka <alardam@gmail.com> wrote:
> > > > >
> > > > > At the time of writing, I wanted to be able to read additional information about the XDP capabilities of each network interface using ethtool. This change was intended for Linux users/admins, and not for XDP experts who mostly don't need it and prefer tasting XDP with netlink and bpf rather than reading network interface features with ethtool.
> > > >
> > > > Anything preventing ethtool from doing probing similar to 'bpftool
> > > > feature probe'?
> > > > The problem with these feature bits is that they might diverge and/or
> > > > not work at all for the backported patches (where the fix/feature has
> > > > been backported, but the part that exports the bit hasn't) :-(
> > > > OTOH, I'm not sure we can probe everything from your list, but we
> > > > might try and see what's missing..
> > >
> > > Hi Stanislav,
> > >
> > > I have not added the ethtool support to this series yet since userspace part is
> > > still missing but I think we can consider XDP as a sort of sw offload so it
> > > would be nice for the user/sysadmin (not xdp or bpf developer) to check the NIC
> > > XDP capabilities similar to what we can already do for other hw offload
> > > features.
> >
> > [..]
> >
> > > Moreover let's consider XDP_REDIRECT of a scatter-gather XDP frame into a
> > > devmap. I do not think there is a way to test if the 'target' device supports
> > > SG and so we are forced to disable this feature until all drivers support it.
> >
> > See below for more questions, but why "target device has prog
> > installed and the aux->xdp_has_frags == true" won't work for the
> > internal kernel consumers?
>
> There are some drivers (e.g. all intel ones) that currently do not support
> non-linear xdp buff in the driver napi callback (XDP_FRAG_RX) but implement
> non-linear xdp buff support in ndo_xdp_xmit callback (XDP_FRAG_TARGET).
> Moreover, I guess for a sysadmin it would be better to check NIC capabilities in
> the same way he/she is used to with other features (e.g. ethool -k ...).
>
> >
> > > Introducing XDP features we can enable it on per-driver basis.
> > > I think the same apply for other capabilities as well and just assuming a given
> > > feature is not supported if an e2e test is not working seems a bit inaccurate.
> >
> > Ok, I see that these bits are used in the later patches in xsk and
> > devmap. But I guess I'm still confused about why we add all these
> > flags, but only use mostly XDP_F_REDIRECT_TARGET; maybe start with
> > that one? And why does it have to be exposed to the userspace?
> > (userspace can still probe per-device features by trying to load
> > different progs?)
>
> There are some drivers (e.g. ixgbevf or cavium thunder) that do not support
> XDP_REDIRECT but just XDP_PASS, XDP_DROP and XDP_TX, so I think we should
> differentiate between XDP_BASIC (XDP_PASS | XDP_DROP | XDP_TX) and XDP_FULL
> (XDP_BASIC | XDP_REDIRECT).
>
> >
> > Also, it seems like XDP_F_REDIRECT_TARGET really means "the bpf
> > program has been installed on this device". Instead of a flag, why not
> > explicitly check whether the target device has a prog installed (and,
> > if needed, whether the installed program has frags support)?
>
> XDP_F_REDIRECT_TARGET is used to inform if netdev implements ndo_xdp_xmit
> callback (most of the XDP drivers do not require to load a bpf program to
> XDP_REDIRECT into them).

All of the above makes sense, thanks for the details. In this case,
agreed that it's probably not possible to probe these easily without
explicit flags :-(

Let me bikeshed the names a bit as well, feel free to ignore...

1. Maybe group XDP_{ABORTED,DROP,PASS,TX,REDIRECT} with some common
prefix? XDP_ACT_xxx (ACT for action)? Or XDP_RET_xxx?

2. Maybe: XDP_SOCK_ZEROCOPY -> XSK_ZEROCOPY ?

3. XDP_HW_OFFLOAD we don't seem to set anywhere? nfp/netdevsim changes
are missing or out of scope?

4. Agree with Jakub, not sure XDP_TX_LOCK doesn't seem relevant?

5. XDP_REDIRECT_TARGET -> XDP_RCV_REDIRECT (can 'receive' and handle
redirects? in this case XDP_ACT_REDIRECT means can 'generate'
redirects)

6. For frags, maybe:

XDP_FRAG_RX     -> XDP_SG_RX
XDP_FRAG_TARGET -> XDP_SG_RCV_REDIRECT (so this is that same as
XDP_RCV_REDIRECT but can handle frags)

But also probably fine to keep FRAG instead of SG to match BPF_F_XDP_HAS_FRAGS?

> Regards,
> Lorenzo
>
> >
> > > Regards,
> > > Lorenzo
> > >
> > > >
> > > > > On Mon, Dec 19, 2022 at 9:03 PM <sdf@google.com> wrote:
> > > > >>
> > > > >> On 12/19, Lorenzo Bianconi wrote:
> > > > >> > From: Marek Majtyka <alardam@gmail.com>
> > > > >>
> > > > >> > Implement support for checking what kind of XDP features a netdev
> > > > >> > supports. Previously, there was no way to do this other than to try to
> > > > >> > create an AF_XDP socket on the interface or load an XDP program and see
> > > > >> > if it worked. This commit changes this by adding a new variable which
> > > > >> > describes all xdp supported functions on pretty detailed level:
> > > > >>
> > > > >> >   - aborted
> > > > >> >   - drop
> > > > >> >   - pass
> > > > >> >   - tx
> > > > >> >   - redirect
> > > > >> >   - sock_zerocopy
> > > > >> >   - hw_offload
> > > > >> >   - redirect_target
> > > > >> >   - tx_lock
> > > > >> >   - frag_rx
> > > > >> >   - frag_target
> > > > >>
> > > > >> > Zerocopy mode requires that redirect XDP operation is implemented in a
> > > > >> > driver and the driver supports also zero copy mode. Full mode requires
> > > > >> > that all XDP operation are implemented in the driver. Basic mode is just
> > > > >> > full mode without redirect operation. Frag target requires
> > > > >> > redirect_target one is supported by the driver.
> > > > >>
> > > > >> Can you share more about _why_ is it needed? If we can already obtain
> > > > >> most of these signals via probing, why export the flags?
> > > > >>
> > > > >> > Initially, these new flags are disabled for all drivers by default.
> > > > >>
> > > > >> > Co-developed-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
> > > > >> > Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
> > > > >> > Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org>
> > > > >> > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> > > > >> > Signed-off-by: Marek Majtyka <alardam@gmail.com>
> > > > >> > ---
> > > > >> >   .../networking/netdev-xdp-features.rst        | 60 +++++++++++++++++
> > > > >> >   include/linux/netdevice.h                     |  2 +
> > > > >> >   include/linux/xdp_features.h                  | 64 +++++++++++++++++++
> > > > >> >   include/uapi/linux/if_link.h                  |  7 ++
> > > > >> >   include/uapi/linux/xdp_features.h             | 34 ++++++++++
> > > > >> >   net/core/rtnetlink.c                          | 34 ++++++++++
> > > > >> >   tools/include/uapi/linux/if_link.h            |  7 ++
> > > > >> >   tools/include/uapi/linux/xdp_features.h       | 34 ++++++++++
> > > > >> >   8 files changed, 242 insertions(+)
> > > > >> >   create mode 100644 Documentation/networking/netdev-xdp-features.rst
> > > > >> >   create mode 100644 include/linux/xdp_features.h
> > > > >> >   create mode 100644 include/uapi/linux/xdp_features.h
> > > > >> >   create mode 100644 tools/include/uapi/linux/xdp_features.h
> > > > >>
> > > > >> > diff --git a/Documentation/networking/netdev-xdp-features.rst
> > > > >> > b/Documentation/networking/netdev-xdp-features.rst
> > > > >> > new file mode 100644
> > > > >> > index 000000000000..1dc803fe72dd
> > > > >> > --- /dev/null
> > > > >> > +++ b/Documentation/networking/netdev-xdp-features.rst
> > > > >> > @@ -0,0 +1,60 @@
> > > > >> > +.. SPDX-License-Identifier: GPL-2.0
> > > > >> > +
> > > > >> > +=====================
> > > > >> > +Netdev XDP features
> > > > >> > +=====================
> > > > >> > +
> > > > >> > + * XDP FEATURES FLAGS
> > > > >> > +
> > > > >> > +Following netdev xdp features flags can be retrieved over route netlink
> > > > >> > +interface (compact form) - the same way as netdev feature flags.
> > > > >> > +These features flags are read only and cannot be change at runtime.
> > > > >> > +
> > > > >> > +*  XDP_ABORTED
> > > > >> > +
> > > > >> > +This feature informs if netdev supports xdp aborted action.
> > > > >> > +
> > > > >> > +*  XDP_DROP
> > > > >> > +
> > > > >> > +This feature informs if netdev supports xdp drop action.
> > > > >> > +
> > > > >> > +*  XDP_PASS
> > > > >> > +
> > > > >> > +This feature informs if netdev supports xdp pass action.
> > > > >> > +
> > > > >> > +*  XDP_TX
> > > > >> > +
> > > > >> > +This feature informs if netdev supports xdp tx action.
> > > > >> > +
> > > > >> > +*  XDP_REDIRECT
> > > > >> > +
> > > > >> > +This feature informs if netdev supports xdp redirect action.
> > > > >> > +It assumes the all beforehand mentioned flags are enabled.
> > > > >> > +
> > > > >> > +*  XDP_SOCK_ZEROCOPY
> > > > >> > +
> > > > >> > +This feature informs if netdev driver supports xdp zero copy.
> > > > >> > +It assumes the all beforehand mentioned flags are enabled.
> > > > >> > +
> > > > >> > +*  XDP_HW_OFFLOAD
> > > > >> > +
> > > > >> > +This feature informs if netdev driver supports xdp hw oflloading.
> > > > >> > +
> > > > >> > +*  XDP_TX_LOCK
> > > > >> > +
> > > > >> > +This feature informs if netdev ndo_xdp_xmit function requires locking.
> > > > >> > +
> > > > >> > +*  XDP_REDIRECT_TARGET
> > > > >> > +
> > > > >> > +This feature informs if netdev implements ndo_xdp_xmit callback.
> > > > >> > +
> > > > >> > +*  XDP_FRAG_RX
> > > > >> > +
> > > > >> > +This feature informs if netdev implements non-linear xdp buff support in
> > > > >> > +the driver napi callback.
> > > > >> > +
> > > > >> > +*  XDP_FRAG_TARGET
> > > > >> > +
> > > > >> > +This feature informs if netdev implements non-linear xdp buff support in
> > > > >> > +ndo_xdp_xmit callback. XDP_FRAG_TARGET requires XDP_REDIRECT_TARGET is
> > > > >> > properly
> > > > >> > +supported.
> > > > >> > diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
> > > > >> > index aad12a179e54..ae5a8564383b 100644
> > > > >> > --- a/include/linux/netdevice.h
> > > > >> > +++ b/include/linux/netdevice.h
> > > > >> > @@ -43,6 +43,7 @@
> > > > >> >   #include <net/xdp.h>
> > > > >>
> > > > >> >   #include <linux/netdev_features.h>
> > > > >> > +#include <linux/xdp_features.h>
> > > > >> >   #include <linux/neighbour.h>
> > > > >> >   #include <uapi/linux/netdevice.h>
> > > > >> >   #include <uapi/linux/if_bonding.h>
> > > > >> > @@ -2362,6 +2363,7 @@ struct net_device {
> > > > >> >       struct rtnl_hw_stats64  *offload_xstats_l3;
> > > > >>
> > > > >> >       struct devlink_port     *devlink_port;
> > > > >> > +     xdp_features_t          xdp_features;
> > > > >> >   };
> > > > >> >   #define to_net_dev(d) container_of(d, struct net_device, dev)
> > > > >>
> > > > >> > diff --git a/include/linux/xdp_features.h b/include/linux/xdp_features.h
> > > > >> > new file mode 100644
> > > > >> > index 000000000000..4e72a86ef329
> > > > >> > --- /dev/null
> > > > >> > +++ b/include/linux/xdp_features.h
> > > > >> > @@ -0,0 +1,64 @@
> > > > >> > +/* SPDX-License-Identifier: GPL-2.0-or-later */
> > > > >> > +/*
> > > > >> > + * Network device xdp features.
> > > > >> > + */
> > > > >> > +#ifndef _LINUX_XDP_FEATURES_H
> > > > >> > +#define _LINUX_XDP_FEATURES_H
> > > > >> > +
> > > > >> > +#include <linux/types.h>
> > > > >> > +#include <linux/bitops.h>
> > > > >> > +#include <asm/byteorder.h>
> > > > >> > +#include <uapi/linux/xdp_features.h>
> > > > >> > +
> > > > >> > +typedef u32 xdp_features_t;
> > > > >> > +
> > > > >> > +#define __XDP_F_BIT(bit)     ((xdp_features_t)1 << (bit))
> > > > >> > +#define __XDP_F(name)                __XDP_F_BIT(XDP_F_##name##_BIT)
> > > > >> > +
> > > > >> > +#define XDP_F_ABORTED                __XDP_F(ABORTED)
> > > > >> > +#define XDP_F_DROP           __XDP_F(DROP)
> > > > >> > +#define XDP_F_PASS           __XDP_F(PASS)
> > > > >> > +#define XDP_F_TX             __XDP_F(TX)
> > > > >> > +#define XDP_F_REDIRECT               __XDP_F(REDIRECT)
> > > > >> > +#define XDP_F_REDIRECT_TARGET        __XDP_F(REDIRECT_TARGET)
> > > > >> > +#define XDP_F_SOCK_ZEROCOPY  __XDP_F(SOCK_ZEROCOPY)
> > > > >> > +#define XDP_F_HW_OFFLOAD     __XDP_F(HW_OFFLOAD)
> > > > >> > +#define XDP_F_TX_LOCK                __XDP_F(TX_LOCK)
> > > > >> > +#define XDP_F_FRAG_RX                __XDP_F(FRAG_RX)
> > > > >> > +#define XDP_F_FRAG_TARGET    __XDP_F(FRAG_TARGET)
> > > > >> > +
> > > > >> > +#define XDP_F_BASIC          (XDP_F_ABORTED | XDP_F_DROP |   \
> > > > >> > +                              XDP_F_PASS | XDP_F_TX)
> > > > >> > +
> > > > >> > +#define XDP_F_FULL           (XDP_F_BASIC | XDP_F_REDIRECT)
> > > > >> > +
> > > > >> > +#define XDP_F_FULL_ZC                (XDP_F_FULL | XDP_F_SOCK_ZEROCOPY)
> > > > >> > +
> > > > >> > +#define XDP_FEATURES_ABORTED_STR             "xdp-aborted"
> > > > >> > +#define XDP_FEATURES_DROP_STR                        "xdp-drop"
> > > > >> > +#define XDP_FEATURES_PASS_STR                        "xdp-pass"
> > > > >> > +#define XDP_FEATURES_TX_STR                  "xdp-tx"
> > > > >> > +#define XDP_FEATURES_REDIRECT_STR            "xdp-redirect"
> > > > >> > +#define XDP_FEATURES_REDIRECT_TARGET_STR     "xdp-redirect-target"
> > > > >> > +#define XDP_FEATURES_SOCK_ZEROCOPY_STR               "xdp-sock-zerocopy"
> > > > >> > +#define XDP_FEATURES_HW_OFFLOAD_STR          "xdp-hw-offload"
> > > > >> > +#define XDP_FEATURES_TX_LOCK_STR             "xdp-tx-lock"
> > > > >> > +#define XDP_FEATURES_FRAG_RX_STR             "xdp-frag-rx"
> > > > >> > +#define XDP_FEATURES_FRAG_TARGET_STR         "xdp-frag-target"
> > > > >> > +
> > > > >> > +#define DECLARE_XDP_FEATURES_TABLE(name, length)                             \
> > > > >> > +     const char name[][length] = {                                           \
> > > > >> > +             [XDP_F_ABORTED_BIT] = XDP_FEATURES_ABORTED_STR,                 \
> > > > >> > +             [XDP_F_DROP_BIT] = XDP_FEATURES_DROP_STR,                       \
> > > > >> > +             [XDP_F_PASS_BIT] = XDP_FEATURES_PASS_STR,                       \
> > > > >> > +             [XDP_F_TX_BIT] = XDP_FEATURES_TX_STR,                           \
> > > > >> > +             [XDP_F_REDIRECT_BIT] = XDP_FEATURES_REDIRECT_STR,               \
> > > > >> > +             [XDP_F_REDIRECT_TARGET_BIT] = XDP_FEATURES_REDIRECT_TARGET_STR, \
> > > > >> > +             [XDP_F_SOCK_ZEROCOPY_BIT] = XDP_FEATURES_SOCK_ZEROCOPY_STR,     \
> > > > >> > +             [XDP_F_HW_OFFLOAD_BIT] = XDP_FEATURES_HW_OFFLOAD_STR,           \
> > > > >> > +             [XDP_F_TX_LOCK_BIT] = XDP_FEATURES_TX_LOCK_STR,                 \
> > > > >> > +             [XDP_F_FRAG_RX_BIT] = XDP_FEATURES_FRAG_RX_STR,                 \
> > > > >> > +             [XDP_F_FRAG_TARGET_BIT] = XDP_FEATURES_FRAG_TARGET_STR,         \
> > > > >> > +     }
> > > > >> > +
> > > > >> > +#endif /* _LINUX_XDP_FEATURES_H */
> > > > >> > diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
> > > > >> > index 1021a7e47a86..971c658ceaea 100644
> > > > >> > --- a/include/uapi/linux/if_link.h
> > > > >> > +++ b/include/uapi/linux/if_link.h
> > > > >> > @@ -374,6 +374,8 @@ enum {
> > > > >>
> > > > >> >       IFLA_DEVLINK_PORT,
> > > > >>
> > > > >> > +     IFLA_XDP_FEATURES,
> > > > >> > +
> > > > >> >       __IFLA_MAX
> > > > >> >   };
> > > > >>
> > > > >> > @@ -1318,6 +1320,11 @@ enum {
> > > > >>
> > > > >> >   #define IFLA_XDP_MAX (__IFLA_XDP_MAX - 1)
> > > > >>
> > > > >> > +enum {
> > > > >> > +     IFLA_XDP_FEATURES_WORD_UNSPEC = 0,
> > > > >> > +     IFLA_XDP_FEATURES_BITS_WORD,
> > > > >> > +};
> > > > >> > +
> > > > >> >   enum {
> > > > >> >       IFLA_EVENT_NONE,
> > > > >> >       IFLA_EVENT_REBOOT,              /* internal reset / reboot */
> > > > >> > diff --git a/include/uapi/linux/xdp_features.h
> > > > >> > b/include/uapi/linux/xdp_features.h
> > > > >> > new file mode 100644
> > > > >> > index 000000000000..48eb42069bcd
> > > > >> > --- /dev/null
> > > > >> > +++ b/include/uapi/linux/xdp_features.h
> > > > >> > @@ -0,0 +1,34 @@
> > > > >> > +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
> > > > >> > +/*
> > > > >> > + * Copyright (c) 2020 Intel
> > > > >> > + */
> > > > >> > +
> > > > >> > +#ifndef __UAPI_LINUX_XDP_FEATURES__
> > > > >> > +#define __UAPI_LINUX_XDP_FEATURES__
> > > > >> > +
> > > > >> > +enum {
> > > > >> > +     XDP_F_ABORTED_BIT,
> > > > >> > +     XDP_F_DROP_BIT,
> > > > >> > +     XDP_F_PASS_BIT,
> > > > >> > +     XDP_F_TX_BIT,
> > > > >> > +     XDP_F_REDIRECT_BIT,
> > > > >> > +     XDP_F_REDIRECT_TARGET_BIT,
> > > > >> > +     XDP_F_SOCK_ZEROCOPY_BIT,
> > > > >> > +     XDP_F_HW_OFFLOAD_BIT,
> > > > >> > +     XDP_F_TX_LOCK_BIT,
> > > > >> > +     XDP_F_FRAG_RX_BIT,
> > > > >> > +     XDP_F_FRAG_TARGET_BIT,
> > > > >> > +     /*
> > > > >> > +      * Add your fresh new property above and remember to update
> > > > >> > +      * documentation.
> > > > >> > +      */
> > > > >> > +     XDP_FEATURES_COUNT,
> > > > >> > +};
> > > > >> > +
> > > > >> > +#define XDP_FEATURES_WORDS                   ((XDP_FEATURES_COUNT + 32 - 1) / 32)
> > > > >> > +#define XDP_FEATURES_WORD(blocks, index)     ((blocks)[(index) / 32U])
> > > > >> > +#define XDP_FEATURES_FIELD_FLAG(index)               (1U << (index) % 32U)
> > > > >> > +#define XDP_FEATURES_BIT_IS_SET(blocks, index)        \
> > > > >> > +     (XDP_FEATURES_WORD(blocks, index) & XDP_FEATURES_FIELD_FLAG(index))
> > > > >> > +
> > > > >> > +#endif  /* __UAPI_LINUX_XDP_FEATURES__ */
> > > > >> > diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
> > > > >> > index 64289bc98887..1c299746b614 100644
> > > > >> > --- a/net/core/rtnetlink.c
> > > > >> > +++ b/net/core/rtnetlink.c
> > > > >> > @@ -1016,6 +1016,14 @@ static size_t rtnl_xdp_size(void)
> > > > >> >       return xdp_size;
> > > > >> >   }
> > > > >>
> > > > >> > +static size_t rtnl_xdp_features_size(void)
> > > > >> > +{
> > > > >> > +     size_t xdp_size = nla_total_size(0) +   /* nest IFLA_XDP_FEATURES */
> > > > >> > +                       XDP_FEATURES_WORDS * nla_total_size(4);
> > > > >> > +
> > > > >> > +     return xdp_size;
> > > > >> > +}
> > > > >> > +
> > > > >> >   static size_t rtnl_prop_list_size(const struct net_device *dev)
> > > > >> >   {
> > > > >> >       struct netdev_name_node *name_node;
> > > > >> > @@ -1103,6 +1111,7 @@ static noinline size_t if_nlmsg_size(const struct
> > > > >> > net_device *dev,
> > > > >> >              + rtnl_prop_list_size(dev)
> > > > >> >              + nla_total_size(MAX_ADDR_LEN) /* IFLA_PERM_ADDRESS */
> > > > >> >              + rtnl_devlink_port_size(dev)
> > > > >> > +            + rtnl_xdp_features_size() /* IFLA_XDP_FEATURES */
> > > > >> >              + 0;
> > > > >> >   }
> > > > >>
> > > > >> > @@ -1546,6 +1555,27 @@ static int rtnl_xdp_fill(struct sk_buff *skb,
> > > > >> > struct net_device *dev)
> > > > >> >       return err;
> > > > >> >   }
> > > > >>
> > > > >> > +static int rtnl_xdp_features_fill(struct sk_buff *skb, struct net_device
> > > > >> > *dev)
> > > > >> > +{
> > > > >> > +     struct nlattr *attr;
> > > > >> > +
> > > > >> > +     attr = nla_nest_start_noflag(skb, IFLA_XDP_FEATURES);
> > > > >> > +     if (!attr)
> > > > >> > +             return -EMSGSIZE;
> > > > >> > +
> > > > >> > +     BUILD_BUG_ON(XDP_FEATURES_WORDS != 1);
> > > > >> > +     if (nla_put_u32(skb, IFLA_XDP_FEATURES_BITS_WORD, dev->xdp_features))
> > > > >> > +             goto err_cancel;
> > > > >> > +
> > > > >> > +     nla_nest_end(skb, attr);
> > > > >> > +
> > > > >> > +     return 0;
> > > > >> > +
> > > > >> > +err_cancel:
> > > > >> > +     nla_nest_cancel(skb, attr);
> > > > >> > +     return -EMSGSIZE;
> > > > >> > +}
> > > > >> > +
> > > > >> >   static u32 rtnl_get_event(unsigned long event)
> > > > >> >   {
> > > > >> >       u32 rtnl_event_type = IFLA_EVENT_NONE;
> > > > >> > @@ -1904,6 +1934,9 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb,
> > > > >> >       if (rtnl_fill_devlink_port(skb, dev))
> > > > >> >               goto nla_put_failure;
> > > > >>
> > > > >> > +     if (rtnl_xdp_features_fill(skb, dev))
> > > > >> > +             goto nla_put_failure;
> > > > >> > +
> > > > >> >       nlmsg_end(skb, nlh);
> > > > >> >       return 0;
> > > > >>
> > > > >> > @@ -1968,6 +2001,7 @@ static const struct nla_policy
> > > > >> > ifla_policy[IFLA_MAX+1] = {
> > > > >> >       [IFLA_TSO_MAX_SIZE]     = { .type = NLA_REJECT },
> > > > >> >       [IFLA_TSO_MAX_SEGS]     = { .type = NLA_REJECT },
> > > > >> >       [IFLA_ALLMULTI]         = { .type = NLA_REJECT },
> > > > >> > +     [IFLA_XDP_FEATURES]     = { .type = NLA_NESTED },
> > > > >> >   };
> > > > >>
> > > > >> >   static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
> > > > >> > diff --git a/tools/include/uapi/linux/if_link.h
> > > > >> > b/tools/include/uapi/linux/if_link.h
> > > > >> > index 82fe18f26db5..994228e9909a 100644
> > > > >> > --- a/tools/include/uapi/linux/if_link.h
> > > > >> > +++ b/tools/include/uapi/linux/if_link.h
> > > > >> > @@ -354,6 +354,8 @@ enum {
> > > > >>
> > > > >> >       IFLA_DEVLINK_PORT,
> > > > >>
> > > > >> > +     IFLA_XDP_FEATURES,
> > > > >> > +
> > > > >> >       __IFLA_MAX
> > > > >> >   };
> > > > >>
> > > > >> > @@ -1222,6 +1224,11 @@ enum {
> > > > >>
> > > > >> >   #define IFLA_XDP_MAX (__IFLA_XDP_MAX - 1)
> > > > >>
> > > > >> > +enum {
> > > > >> > +     IFLA_XDP_FEATURES_WORD_UNSPEC = 0,
> > > > >> > +     IFLA_XDP_FEATURES_BITS_WORD,
> > > > >> > +};
> > > > >> > +
> > > > >> >   enum {
> > > > >> >       IFLA_EVENT_NONE,
> > > > >> >       IFLA_EVENT_REBOOT,              /* internal reset / reboot */
> > > > >> > diff --git a/tools/include/uapi/linux/xdp_features.h
> > > > >> > b/tools/include/uapi/linux/xdp_features.h
> > > > >> > new file mode 100644
> > > > >> > index 000000000000..48eb42069bcd
> > > > >> > --- /dev/null
> > > > >> > +++ b/tools/include/uapi/linux/xdp_features.h
> > > > >> > @@ -0,0 +1,34 @@
> > > > >> > +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
> > > > >> > +/*
> > > > >> > + * Copyright (c) 2020 Intel
> > > > >> > + */
> > > > >> > +
> > > > >> > +#ifndef __UAPI_LINUX_XDP_FEATURES__
> > > > >> > +#define __UAPI_LINUX_XDP_FEATURES__
> > > > >> > +
> > > > >> > +enum {
> > > > >> > +     XDP_F_ABORTED_BIT,
> > > > >> > +     XDP_F_DROP_BIT,
> > > > >> > +     XDP_F_PASS_BIT,
> > > > >> > +     XDP_F_TX_BIT,
> > > > >> > +     XDP_F_REDIRECT_BIT,
> > > > >> > +     XDP_F_REDIRECT_TARGET_BIT,
> > > > >> > +     XDP_F_SOCK_ZEROCOPY_BIT,
> > > > >> > +     XDP_F_HW_OFFLOAD_BIT,
> > > > >> > +     XDP_F_TX_LOCK_BIT,
> > > > >> > +     XDP_F_FRAG_RX_BIT,
> > > > >> > +     XDP_F_FRAG_TARGET_BIT,
> > > > >> > +     /*
> > > > >> > +      * Add your fresh new property above and remember to update
> > > > >> > +      * documentation.
> > > > >> > +      */
> > > > >> > +     XDP_FEATURES_COUNT,
> > > > >> > +};
> > > > >> > +
> > > > >> > +#define XDP_FEATURES_WORDS                   ((XDP_FEATURES_COUNT + 32 - 1) / 32)
> > > > >> > +#define XDP_FEATURES_WORD(blocks, index)     ((blocks)[(index) / 32U])
> > > > >> > +#define XDP_FEATURES_FIELD_FLAG(index)               (1U << (index) % 32U)
> > > > >> > +#define XDP_FEATURES_BIT_IS_SET(blocks, index)        \
> > > > >> > +     (XDP_FEATURES_WORD(blocks, index) & XDP_FEATURES_FIELD_FLAG(index))
> > > > >> > +
> > > > >> > +#endif  /* __UAPI_LINUX_XDP_FEATURES__ */
> > > > >> > --
> > > > >> > 2.38.1
> > > > >>
> > > >
Jakub Kicinski Dec. 20, 2022, 11:39 p.m. UTC | #11
On Tue, 20 Dec 2022 23:51:31 +0100 Marek Majtyka wrote:
> Everybody is allowed to make a good use of it. Every improvement is
> highly appreciated. Thanks Lorenzo for taking this over.

IIUC this comment refers to the rtnl -> genl/yaml conversion.
In which case, unless someone objects, I'll take a stab at it 
in an hour or two and push the result out my kernel.org tree ...
Jakub Kicinski Dec. 21, 2022, 4:41 a.m. UTC | #12
On Tue, 20 Dec 2022 15:39:03 -0800 Jakub Kicinski wrote:
> On Tue, 20 Dec 2022 23:51:31 +0100 Marek Majtyka wrote:
> > Everybody is allowed to make a good use of it. Every improvement is
> > highly appreciated. Thanks Lorenzo for taking this over.  
> 
> IIUC this comment refers to the rtnl -> genl/yaml conversion.
> In which case, unless someone objects, I'll take a stab at it 
> in an hour or two and push the result out my kernel.org tree ...

I pushed something here:

https://github.com/kuba-moo/ynl/commits/xdp-features

without replacing all you have. But it should give enough of an idea 
to comment on.
Lorenzo Bianconi Dec. 21, 2022, 10:39 a.m. UTC | #13
[...]
> 
> All of the above makes sense, thanks for the details. In this case,
> agreed that it's probably not possible to probe these easily without
> explicit flags :-(
> 
> Let me bikeshed the names a bit as well, feel free to ignore...
> 
> 1. Maybe group XDP_{ABORTED,DROP,PASS,TX,REDIRECT} with some common
> prefix? XDP_ACT_xxx (ACT for action)? Or XDP_RET_xxx?
> 

ack, I am fine to add ACT prefix, something like:

- XDP_ACT_ABORTED
- XDP_ACT_DROP
...

- XDP_ACT_REDIRECT

> 2. Maybe: XDP_SOCK_ZEROCOPY -> XSK_ZEROCOPY ?

ack, agree

> 
> 3. XDP_HW_OFFLOAD we don't seem to set anywhere? nfp/netdevsim changes
> are missing or out of scope?

actually we set XDP_F_HW_OFFLOAD for netdevsim and nfp driver

> 
> 4. Agree with Jakub, not sure XDP_TX_LOCK doesn't seem relevant?

ack, I agree we can drop it

> 
> 5. XDP_REDIRECT_TARGET -> XDP_RCV_REDIRECT (can 'receive' and handle
> redirects? in this case XDP_ACT_REDIRECT means can 'generate'

naming is always hard :) what about XDP_NDO_XMIT instead of
XDP_REDIRECT_TARGET? (and rely on XDP_ACT_REDIRECT for XDP_F_REDIRECT)

> redirects)
> 
> 6. For frags, maybe:
> 
> XDP_FRAG_RX     -> XDP_SG_RX

fine

> XDP_FRAG_TARGET -> XDP_SG_RCV_REDIRECT (so this is that same as
> XDP_RCV_REDIRECT but can handle frags)

what about of XDP_NDO_XMIT_SG?

Regards,
Lorenzo

> 
> But also probably fine to keep FRAG instead of SG to match BPF_F_XDP_HAS_FRAGS?
> 
> > Regards,
> > Lorenzo
> >
> > >
> > > > Regards,
> > > > Lorenzo
> > > >
> > > > >
> > > > > > On Mon, Dec 19, 2022 at 9:03 PM <sdf@google.com> wrote:
> > > > > >>
> > > > > >> On 12/19, Lorenzo Bianconi wrote:
> > > > > >> > From: Marek Majtyka <alardam@gmail.com>
> > > > > >>
> > > > > >> > Implement support for checking what kind of XDP features a netdev
> > > > > >> > supports. Previously, there was no way to do this other than to try to
> > > > > >> > create an AF_XDP socket on the interface or load an XDP program and see
> > > > > >> > if it worked. This commit changes this by adding a new variable which
> > > > > >> > describes all xdp supported functions on pretty detailed level:
> > > > > >>
> > > > > >> >   - aborted
> > > > > >> >   - drop
> > > > > >> >   - pass
> > > > > >> >   - tx
> > > > > >> >   - redirect
> > > > > >> >   - sock_zerocopy
> > > > > >> >   - hw_offload
> > > > > >> >   - redirect_target
> > > > > >> >   - tx_lock
> > > > > >> >   - frag_rx
> > > > > >> >   - frag_target
> > > > > >>
> > > > > >> > Zerocopy mode requires that redirect XDP operation is implemented in a
> > > > > >> > driver and the driver supports also zero copy mode. Full mode requires
> > > > > >> > that all XDP operation are implemented in the driver. Basic mode is just
> > > > > >> > full mode without redirect operation. Frag target requires
> > > > > >> > redirect_target one is supported by the driver.
> > > > > >>
> > > > > >> Can you share more about _why_ is it needed? If we can already obtain
> > > > > >> most of these signals via probing, why export the flags?
> > > > > >>
> > > > > >> > Initially, these new flags are disabled for all drivers by default.
> > > > > >>
> > > > > >> > Co-developed-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
> > > > > >> > Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
> > > > > >> > Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org>
> > > > > >> > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> > > > > >> > Signed-off-by: Marek Majtyka <alardam@gmail.com>
> > > > > >> > ---
> > > > > >> >   .../networking/netdev-xdp-features.rst        | 60 +++++++++++++++++
> > > > > >> >   include/linux/netdevice.h                     |  2 +
> > > > > >> >   include/linux/xdp_features.h                  | 64 +++++++++++++++++++
> > > > > >> >   include/uapi/linux/if_link.h                  |  7 ++
> > > > > >> >   include/uapi/linux/xdp_features.h             | 34 ++++++++++
> > > > > >> >   net/core/rtnetlink.c                          | 34 ++++++++++
> > > > > >> >   tools/include/uapi/linux/if_link.h            |  7 ++
> > > > > >> >   tools/include/uapi/linux/xdp_features.h       | 34 ++++++++++
> > > > > >> >   8 files changed, 242 insertions(+)
> > > > > >> >   create mode 100644 Documentation/networking/netdev-xdp-features.rst
> > > > > >> >   create mode 100644 include/linux/xdp_features.h
> > > > > >> >   create mode 100644 include/uapi/linux/xdp_features.h
> > > > > >> >   create mode 100644 tools/include/uapi/linux/xdp_features.h
> > > > > >>
> > > > > >> > diff --git a/Documentation/networking/netdev-xdp-features.rst
> > > > > >> > b/Documentation/networking/netdev-xdp-features.rst
> > > > > >> > new file mode 100644
> > > > > >> > index 000000000000..1dc803fe72dd
> > > > > >> > --- /dev/null
> > > > > >> > +++ b/Documentation/networking/netdev-xdp-features.rst
> > > > > >> > @@ -0,0 +1,60 @@
> > > > > >> > +.. SPDX-License-Identifier: GPL-2.0
> > > > > >> > +
> > > > > >> > +=====================
> > > > > >> > +Netdev XDP features
> > > > > >> > +=====================
> > > > > >> > +
> > > > > >> > + * XDP FEATURES FLAGS
> > > > > >> > +
> > > > > >> > +Following netdev xdp features flags can be retrieved over route netlink
> > > > > >> > +interface (compact form) - the same way as netdev feature flags.
> > > > > >> > +These features flags are read only and cannot be change at runtime.
> > > > > >> > +
> > > > > >> > +*  XDP_ABORTED
> > > > > >> > +
> > > > > >> > +This feature informs if netdev supports xdp aborted action.
> > > > > >> > +
> > > > > >> > +*  XDP_DROP
> > > > > >> > +
> > > > > >> > +This feature informs if netdev supports xdp drop action.
> > > > > >> > +
> > > > > >> > +*  XDP_PASS
> > > > > >> > +
> > > > > >> > +This feature informs if netdev supports xdp pass action.
> > > > > >> > +
> > > > > >> > +*  XDP_TX
> > > > > >> > +
> > > > > >> > +This feature informs if netdev supports xdp tx action.
> > > > > >> > +
> > > > > >> > +*  XDP_REDIRECT
> > > > > >> > +
> > > > > >> > +This feature informs if netdev supports xdp redirect action.
> > > > > >> > +It assumes the all beforehand mentioned flags are enabled.
> > > > > >> > +
> > > > > >> > +*  XDP_SOCK_ZEROCOPY
> > > > > >> > +
> > > > > >> > +This feature informs if netdev driver supports xdp zero copy.
> > > > > >> > +It assumes the all beforehand mentioned flags are enabled.
> > > > > >> > +
> > > > > >> > +*  XDP_HW_OFFLOAD
> > > > > >> > +
> > > > > >> > +This feature informs if netdev driver supports xdp hw oflloading.
> > > > > >> > +
> > > > > >> > +*  XDP_TX_LOCK
> > > > > >> > +
> > > > > >> > +This feature informs if netdev ndo_xdp_xmit function requires locking.
> > > > > >> > +
> > > > > >> > +*  XDP_REDIRECT_TARGET
> > > > > >> > +
> > > > > >> > +This feature informs if netdev implements ndo_xdp_xmit callback.
> > > > > >> > +
> > > > > >> > +*  XDP_FRAG_RX
> > > > > >> > +
> > > > > >> > +This feature informs if netdev implements non-linear xdp buff support in
> > > > > >> > +the driver napi callback.
> > > > > >> > +
> > > > > >> > +*  XDP_FRAG_TARGET
> > > > > >> > +
> > > > > >> > +This feature informs if netdev implements non-linear xdp buff support in
> > > > > >> > +ndo_xdp_xmit callback. XDP_FRAG_TARGET requires XDP_REDIRECT_TARGET is
> > > > > >> > properly
> > > > > >> > +supported.
> > > > > >> > diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
> > > > > >> > index aad12a179e54..ae5a8564383b 100644
> > > > > >> > --- a/include/linux/netdevice.h
> > > > > >> > +++ b/include/linux/netdevice.h
> > > > > >> > @@ -43,6 +43,7 @@
> > > > > >> >   #include <net/xdp.h>
> > > > > >>
> > > > > >> >   #include <linux/netdev_features.h>
> > > > > >> > +#include <linux/xdp_features.h>
> > > > > >> >   #include <linux/neighbour.h>
> > > > > >> >   #include <uapi/linux/netdevice.h>
> > > > > >> >   #include <uapi/linux/if_bonding.h>
> > > > > >> > @@ -2362,6 +2363,7 @@ struct net_device {
> > > > > >> >       struct rtnl_hw_stats64  *offload_xstats_l3;
> > > > > >>
> > > > > >> >       struct devlink_port     *devlink_port;
> > > > > >> > +     xdp_features_t          xdp_features;
> > > > > >> >   };
> > > > > >> >   #define to_net_dev(d) container_of(d, struct net_device, dev)
> > > > > >>
> > > > > >> > diff --git a/include/linux/xdp_features.h b/include/linux/xdp_features.h
> > > > > >> > new file mode 100644
> > > > > >> > index 000000000000..4e72a86ef329
> > > > > >> > --- /dev/null
> > > > > >> > +++ b/include/linux/xdp_features.h
> > > > > >> > @@ -0,0 +1,64 @@
> > > > > >> > +/* SPDX-License-Identifier: GPL-2.0-or-later */
> > > > > >> > +/*
> > > > > >> > + * Network device xdp features.
> > > > > >> > + */
> > > > > >> > +#ifndef _LINUX_XDP_FEATURES_H
> > > > > >> > +#define _LINUX_XDP_FEATURES_H
> > > > > >> > +
> > > > > >> > +#include <linux/types.h>
> > > > > >> > +#include <linux/bitops.h>
> > > > > >> > +#include <asm/byteorder.h>
> > > > > >> > +#include <uapi/linux/xdp_features.h>
> > > > > >> > +
> > > > > >> > +typedef u32 xdp_features_t;
> > > > > >> > +
> > > > > >> > +#define __XDP_F_BIT(bit)     ((xdp_features_t)1 << (bit))
> > > > > >> > +#define __XDP_F(name)                __XDP_F_BIT(XDP_F_##name##_BIT)
> > > > > >> > +
> > > > > >> > +#define XDP_F_ABORTED                __XDP_F(ABORTED)
> > > > > >> > +#define XDP_F_DROP           __XDP_F(DROP)
> > > > > >> > +#define XDP_F_PASS           __XDP_F(PASS)
> > > > > >> > +#define XDP_F_TX             __XDP_F(TX)
> > > > > >> > +#define XDP_F_REDIRECT               __XDP_F(REDIRECT)
> > > > > >> > +#define XDP_F_REDIRECT_TARGET        __XDP_F(REDIRECT_TARGET)
> > > > > >> > +#define XDP_F_SOCK_ZEROCOPY  __XDP_F(SOCK_ZEROCOPY)
> > > > > >> > +#define XDP_F_HW_OFFLOAD     __XDP_F(HW_OFFLOAD)
> > > > > >> > +#define XDP_F_TX_LOCK                __XDP_F(TX_LOCK)
> > > > > >> > +#define XDP_F_FRAG_RX                __XDP_F(FRAG_RX)
> > > > > >> > +#define XDP_F_FRAG_TARGET    __XDP_F(FRAG_TARGET)
> > > > > >> > +
> > > > > >> > +#define XDP_F_BASIC          (XDP_F_ABORTED | XDP_F_DROP |   \
> > > > > >> > +                              XDP_F_PASS | XDP_F_TX)
> > > > > >> > +
> > > > > >> > +#define XDP_F_FULL           (XDP_F_BASIC | XDP_F_REDIRECT)
> > > > > >> > +
> > > > > >> > +#define XDP_F_FULL_ZC                (XDP_F_FULL | XDP_F_SOCK_ZEROCOPY)
> > > > > >> > +
> > > > > >> > +#define XDP_FEATURES_ABORTED_STR             "xdp-aborted"
> > > > > >> > +#define XDP_FEATURES_DROP_STR                        "xdp-drop"
> > > > > >> > +#define XDP_FEATURES_PASS_STR                        "xdp-pass"
> > > > > >> > +#define XDP_FEATURES_TX_STR                  "xdp-tx"
> > > > > >> > +#define XDP_FEATURES_REDIRECT_STR            "xdp-redirect"
> > > > > >> > +#define XDP_FEATURES_REDIRECT_TARGET_STR     "xdp-redirect-target"
> > > > > >> > +#define XDP_FEATURES_SOCK_ZEROCOPY_STR               "xdp-sock-zerocopy"
> > > > > >> > +#define XDP_FEATURES_HW_OFFLOAD_STR          "xdp-hw-offload"
> > > > > >> > +#define XDP_FEATURES_TX_LOCK_STR             "xdp-tx-lock"
> > > > > >> > +#define XDP_FEATURES_FRAG_RX_STR             "xdp-frag-rx"
> > > > > >> > +#define XDP_FEATURES_FRAG_TARGET_STR         "xdp-frag-target"
> > > > > >> > +
> > > > > >> > +#define DECLARE_XDP_FEATURES_TABLE(name, length)                             \
> > > > > >> > +     const char name[][length] = {                                           \
> > > > > >> > +             [XDP_F_ABORTED_BIT] = XDP_FEATURES_ABORTED_STR,                 \
> > > > > >> > +             [XDP_F_DROP_BIT] = XDP_FEATURES_DROP_STR,                       \
> > > > > >> > +             [XDP_F_PASS_BIT] = XDP_FEATURES_PASS_STR,                       \
> > > > > >> > +             [XDP_F_TX_BIT] = XDP_FEATURES_TX_STR,                           \
> > > > > >> > +             [XDP_F_REDIRECT_BIT] = XDP_FEATURES_REDIRECT_STR,               \
> > > > > >> > +             [XDP_F_REDIRECT_TARGET_BIT] = XDP_FEATURES_REDIRECT_TARGET_STR, \
> > > > > >> > +             [XDP_F_SOCK_ZEROCOPY_BIT] = XDP_FEATURES_SOCK_ZEROCOPY_STR,     \
> > > > > >> > +             [XDP_F_HW_OFFLOAD_BIT] = XDP_FEATURES_HW_OFFLOAD_STR,           \
> > > > > >> > +             [XDP_F_TX_LOCK_BIT] = XDP_FEATURES_TX_LOCK_STR,                 \
> > > > > >> > +             [XDP_F_FRAG_RX_BIT] = XDP_FEATURES_FRAG_RX_STR,                 \
> > > > > >> > +             [XDP_F_FRAG_TARGET_BIT] = XDP_FEATURES_FRAG_TARGET_STR,         \
> > > > > >> > +     }
> > > > > >> > +
> > > > > >> > +#endif /* _LINUX_XDP_FEATURES_H */
> > > > > >> > diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
> > > > > >> > index 1021a7e47a86..971c658ceaea 100644
> > > > > >> > --- a/include/uapi/linux/if_link.h
> > > > > >> > +++ b/include/uapi/linux/if_link.h
> > > > > >> > @@ -374,6 +374,8 @@ enum {
> > > > > >>
> > > > > >> >       IFLA_DEVLINK_PORT,
> > > > > >>
> > > > > >> > +     IFLA_XDP_FEATURES,
> > > > > >> > +
> > > > > >> >       __IFLA_MAX
> > > > > >> >   };
> > > > > >>
> > > > > >> > @@ -1318,6 +1320,11 @@ enum {
> > > > > >>
> > > > > >> >   #define IFLA_XDP_MAX (__IFLA_XDP_MAX - 1)
> > > > > >>
> > > > > >> > +enum {
> > > > > >> > +     IFLA_XDP_FEATURES_WORD_UNSPEC = 0,
> > > > > >> > +     IFLA_XDP_FEATURES_BITS_WORD,
> > > > > >> > +};
> > > > > >> > +
> > > > > >> >   enum {
> > > > > >> >       IFLA_EVENT_NONE,
> > > > > >> >       IFLA_EVENT_REBOOT,              /* internal reset / reboot */
> > > > > >> > diff --git a/include/uapi/linux/xdp_features.h
> > > > > >> > b/include/uapi/linux/xdp_features.h
> > > > > >> > new file mode 100644
> > > > > >> > index 000000000000..48eb42069bcd
> > > > > >> > --- /dev/null
> > > > > >> > +++ b/include/uapi/linux/xdp_features.h
> > > > > >> > @@ -0,0 +1,34 @@
> > > > > >> > +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
> > > > > >> > +/*
> > > > > >> > + * Copyright (c) 2020 Intel
> > > > > >> > + */
> > > > > >> > +
> > > > > >> > +#ifndef __UAPI_LINUX_XDP_FEATURES__
> > > > > >> > +#define __UAPI_LINUX_XDP_FEATURES__
> > > > > >> > +
> > > > > >> > +enum {
> > > > > >> > +     XDP_F_ABORTED_BIT,
> > > > > >> > +     XDP_F_DROP_BIT,
> > > > > >> > +     XDP_F_PASS_BIT,
> > > > > >> > +     XDP_F_TX_BIT,
> > > > > >> > +     XDP_F_REDIRECT_BIT,
> > > > > >> > +     XDP_F_REDIRECT_TARGET_BIT,
> > > > > >> > +     XDP_F_SOCK_ZEROCOPY_BIT,
> > > > > >> > +     XDP_F_HW_OFFLOAD_BIT,
> > > > > >> > +     XDP_F_TX_LOCK_BIT,
> > > > > >> > +     XDP_F_FRAG_RX_BIT,
> > > > > >> > +     XDP_F_FRAG_TARGET_BIT,
> > > > > >> > +     /*
> > > > > >> > +      * Add your fresh new property above and remember to update
> > > > > >> > +      * documentation.
> > > > > >> > +      */
> > > > > >> > +     XDP_FEATURES_COUNT,
> > > > > >> > +};
> > > > > >> > +
> > > > > >> > +#define XDP_FEATURES_WORDS                   ((XDP_FEATURES_COUNT + 32 - 1) / 32)
> > > > > >> > +#define XDP_FEATURES_WORD(blocks, index)     ((blocks)[(index) / 32U])
> > > > > >> > +#define XDP_FEATURES_FIELD_FLAG(index)               (1U << (index) % 32U)
> > > > > >> > +#define XDP_FEATURES_BIT_IS_SET(blocks, index)        \
> > > > > >> > +     (XDP_FEATURES_WORD(blocks, index) & XDP_FEATURES_FIELD_FLAG(index))
> > > > > >> > +
> > > > > >> > +#endif  /* __UAPI_LINUX_XDP_FEATURES__ */
> > > > > >> > diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
> > > > > >> > index 64289bc98887..1c299746b614 100644
> > > > > >> > --- a/net/core/rtnetlink.c
> > > > > >> > +++ b/net/core/rtnetlink.c
> > > > > >> > @@ -1016,6 +1016,14 @@ static size_t rtnl_xdp_size(void)
> > > > > >> >       return xdp_size;
> > > > > >> >   }
> > > > > >>
> > > > > >> > +static size_t rtnl_xdp_features_size(void)
> > > > > >> > +{
> > > > > >> > +     size_t xdp_size = nla_total_size(0) +   /* nest IFLA_XDP_FEATURES */
> > > > > >> > +                       XDP_FEATURES_WORDS * nla_total_size(4);
> > > > > >> > +
> > > > > >> > +     return xdp_size;
> > > > > >> > +}
> > > > > >> > +
> > > > > >> >   static size_t rtnl_prop_list_size(const struct net_device *dev)
> > > > > >> >   {
> > > > > >> >       struct netdev_name_node *name_node;
> > > > > >> > @@ -1103,6 +1111,7 @@ static noinline size_t if_nlmsg_size(const struct
> > > > > >> > net_device *dev,
> > > > > >> >              + rtnl_prop_list_size(dev)
> > > > > >> >              + nla_total_size(MAX_ADDR_LEN) /* IFLA_PERM_ADDRESS */
> > > > > >> >              + rtnl_devlink_port_size(dev)
> > > > > >> > +            + rtnl_xdp_features_size() /* IFLA_XDP_FEATURES */
> > > > > >> >              + 0;
> > > > > >> >   }
> > > > > >>
> > > > > >> > @@ -1546,6 +1555,27 @@ static int rtnl_xdp_fill(struct sk_buff *skb,
> > > > > >> > struct net_device *dev)
> > > > > >> >       return err;
> > > > > >> >   }
> > > > > >>
> > > > > >> > +static int rtnl_xdp_features_fill(struct sk_buff *skb, struct net_device
> > > > > >> > *dev)
> > > > > >> > +{
> > > > > >> > +     struct nlattr *attr;
> > > > > >> > +
> > > > > >> > +     attr = nla_nest_start_noflag(skb, IFLA_XDP_FEATURES);
> > > > > >> > +     if (!attr)
> > > > > >> > +             return -EMSGSIZE;
> > > > > >> > +
> > > > > >> > +     BUILD_BUG_ON(XDP_FEATURES_WORDS != 1);
> > > > > >> > +     if (nla_put_u32(skb, IFLA_XDP_FEATURES_BITS_WORD, dev->xdp_features))
> > > > > >> > +             goto err_cancel;
> > > > > >> > +
> > > > > >> > +     nla_nest_end(skb, attr);
> > > > > >> > +
> > > > > >> > +     return 0;
> > > > > >> > +
> > > > > >> > +err_cancel:
> > > > > >> > +     nla_nest_cancel(skb, attr);
> > > > > >> > +     return -EMSGSIZE;
> > > > > >> > +}
> > > > > >> > +
> > > > > >> >   static u32 rtnl_get_event(unsigned long event)
> > > > > >> >   {
> > > > > >> >       u32 rtnl_event_type = IFLA_EVENT_NONE;
> > > > > >> > @@ -1904,6 +1934,9 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb,
> > > > > >> >       if (rtnl_fill_devlink_port(skb, dev))
> > > > > >> >               goto nla_put_failure;
> > > > > >>
> > > > > >> > +     if (rtnl_xdp_features_fill(skb, dev))
> > > > > >> > +             goto nla_put_failure;
> > > > > >> > +
> > > > > >> >       nlmsg_end(skb, nlh);
> > > > > >> >       return 0;
> > > > > >>
> > > > > >> > @@ -1968,6 +2001,7 @@ static const struct nla_policy
> > > > > >> > ifla_policy[IFLA_MAX+1] = {
> > > > > >> >       [IFLA_TSO_MAX_SIZE]     = { .type = NLA_REJECT },
> > > > > >> >       [IFLA_TSO_MAX_SEGS]     = { .type = NLA_REJECT },
> > > > > >> >       [IFLA_ALLMULTI]         = { .type = NLA_REJECT },
> > > > > >> > +     [IFLA_XDP_FEATURES]     = { .type = NLA_NESTED },
> > > > > >> >   };
> > > > > >>
> > > > > >> >   static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
> > > > > >> > diff --git a/tools/include/uapi/linux/if_link.h
> > > > > >> > b/tools/include/uapi/linux/if_link.h
> > > > > >> > index 82fe18f26db5..994228e9909a 100644
> > > > > >> > --- a/tools/include/uapi/linux/if_link.h
> > > > > >> > +++ b/tools/include/uapi/linux/if_link.h
> > > > > >> > @@ -354,6 +354,8 @@ enum {
> > > > > >>
> > > > > >> >       IFLA_DEVLINK_PORT,
> > > > > >>
> > > > > >> > +     IFLA_XDP_FEATURES,
> > > > > >> > +
> > > > > >> >       __IFLA_MAX
> > > > > >> >   };
> > > > > >>
> > > > > >> > @@ -1222,6 +1224,11 @@ enum {
> > > > > >>
> > > > > >> >   #define IFLA_XDP_MAX (__IFLA_XDP_MAX - 1)
> > > > > >>
> > > > > >> > +enum {
> > > > > >> > +     IFLA_XDP_FEATURES_WORD_UNSPEC = 0,
> > > > > >> > +     IFLA_XDP_FEATURES_BITS_WORD,
> > > > > >> > +};
> > > > > >> > +
> > > > > >> >   enum {
> > > > > >> >       IFLA_EVENT_NONE,
> > > > > >> >       IFLA_EVENT_REBOOT,              /* internal reset / reboot */
> > > > > >> > diff --git a/tools/include/uapi/linux/xdp_features.h
> > > > > >> > b/tools/include/uapi/linux/xdp_features.h
> > > > > >> > new file mode 100644
> > > > > >> > index 000000000000..48eb42069bcd
> > > > > >> > --- /dev/null
> > > > > >> > +++ b/tools/include/uapi/linux/xdp_features.h
> > > > > >> > @@ -0,0 +1,34 @@
> > > > > >> > +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
> > > > > >> > +/*
> > > > > >> > + * Copyright (c) 2020 Intel
> > > > > >> > + */
> > > > > >> > +
> > > > > >> > +#ifndef __UAPI_LINUX_XDP_FEATURES__
> > > > > >> > +#define __UAPI_LINUX_XDP_FEATURES__
> > > > > >> > +
> > > > > >> > +enum {
> > > > > >> > +     XDP_F_ABORTED_BIT,
> > > > > >> > +     XDP_F_DROP_BIT,
> > > > > >> > +     XDP_F_PASS_BIT,
> > > > > >> > +     XDP_F_TX_BIT,
> > > > > >> > +     XDP_F_REDIRECT_BIT,
> > > > > >> > +     XDP_F_REDIRECT_TARGET_BIT,
> > > > > >> > +     XDP_F_SOCK_ZEROCOPY_BIT,
> > > > > >> > +     XDP_F_HW_OFFLOAD_BIT,
> > > > > >> > +     XDP_F_TX_LOCK_BIT,
> > > > > >> > +     XDP_F_FRAG_RX_BIT,
> > > > > >> > +     XDP_F_FRAG_TARGET_BIT,
> > > > > >> > +     /*
> > > > > >> > +      * Add your fresh new property above and remember to update
> > > > > >> > +      * documentation.
> > > > > >> > +      */
> > > > > >> > +     XDP_FEATURES_COUNT,
> > > > > >> > +};
> > > > > >> > +
> > > > > >> > +#define XDP_FEATURES_WORDS                   ((XDP_FEATURES_COUNT + 32 - 1) / 32)
> > > > > >> > +#define XDP_FEATURES_WORD(blocks, index)     ((blocks)[(index) / 32U])
> > > > > >> > +#define XDP_FEATURES_FIELD_FLAG(index)               (1U << (index) % 32U)
> > > > > >> > +#define XDP_FEATURES_BIT_IS_SET(blocks, index)        \
> > > > > >> > +     (XDP_FEATURES_WORD(blocks, index) & XDP_FEATURES_FIELD_FLAG(index))
> > > > > >> > +
> > > > > >> > +#endif  /* __UAPI_LINUX_XDP_FEATURES__ */
> > > > > >> > --
> > > > > >> > 2.38.1
> > > > > >>
> > > > >
Lorenzo Bianconi Dec. 21, 2022, 10:47 a.m. UTC | #14
> On Tue, 20 Dec 2022 15:39:03 -0800 Jakub Kicinski wrote:
> > On Tue, 20 Dec 2022 23:51:31 +0100 Marek Majtyka wrote:
> > > Everybody is allowed to make a good use of it. Every improvement is
> > > highly appreciated. Thanks Lorenzo for taking this over.  
> > 
> > IIUC this comment refers to the rtnl -> genl/yaml conversion.
> > In which case, unless someone objects, I'll take a stab at it 
> > in an hour or two and push the result out my kernel.org tree ...
> 
> I pushed something here:
> 
> https://github.com/kuba-moo/ynl/commits/xdp-features
> 
> without replacing all you have. But it should give enough of an idea 
> to comment on.

ack, thx. I will look into it.

Regards,
Lorenzo
Stanislav Fomichev Dec. 21, 2022, 5:50 p.m. UTC | #15
On Wed, Dec 21, 2022 at 2:39 AM Lorenzo Bianconi <lorenzo@kernel.org> wrote:
>
> [...]
> >
> > All of the above makes sense, thanks for the details. In this case,
> > agreed that it's probably not possible to probe these easily without
> > explicit flags :-(
> >
> > Let me bikeshed the names a bit as well, feel free to ignore...
> >
> > 1. Maybe group XDP_{ABORTED,DROP,PASS,TX,REDIRECT} with some common
> > prefix? XDP_ACT_xxx (ACT for action)? Or XDP_RET_xxx?
> >
>
> ack, I am fine to add ACT prefix, something like:
>
> - XDP_ACT_ABORTED
> - XDP_ACT_DROP
> ...
>
> - XDP_ACT_REDIRECT
>
> > 2. Maybe: XDP_SOCK_ZEROCOPY -> XSK_ZEROCOPY ?
>
> ack, agree
>
> >
> > 3. XDP_HW_OFFLOAD we don't seem to set anywhere? nfp/netdevsim changes
> > are missing or out of scope?
>
> actually we set XDP_F_HW_OFFLOAD for netdevsim and nfp driver
>
> >
> > 4. Agree with Jakub, not sure XDP_TX_LOCK doesn't seem relevant?
>
> ack, I agree we can drop it
>
> >
> > 5. XDP_REDIRECT_TARGET -> XDP_RCV_REDIRECT (can 'receive' and handle
> > redirects? in this case XDP_ACT_REDIRECT means can 'generate'
>
> naming is always hard :) what about XDP_NDO_XMIT instead of
> XDP_REDIRECT_TARGET? (and rely on XDP_ACT_REDIRECT for XDP_F_REDIRECT)

Sounds good!

> > redirects)
> >
> > 6. For frags, maybe:
> >
> > XDP_FRAG_RX     -> XDP_SG_RX
>
> fine
>
> > XDP_FRAG_TARGET -> XDP_SG_RCV_REDIRECT (so this is that same as
> > XDP_RCV_REDIRECT but can handle frags)
>
> what about of XDP_NDO_XMIT_SG?

Same here. I'm now getting quiet in order to not make it more complicated :-)


> Regards,
> Lorenzo
>
> >
> > But also probably fine to keep FRAG instead of SG to match BPF_F_XDP_HAS_FRAGS?
> >
> > > Regards,
> > > Lorenzo
> > >
> > > >
> > > > > Regards,
> > > > > Lorenzo
> > > > >
> > > > > >
> > > > > > > On Mon, Dec 19, 2022 at 9:03 PM <sdf@google.com> wrote:
> > > > > > >>
> > > > > > >> On 12/19, Lorenzo Bianconi wrote:
> > > > > > >> > From: Marek Majtyka <alardam@gmail.com>
> > > > > > >>
> > > > > > >> > Implement support for checking what kind of XDP features a netdev
> > > > > > >> > supports. Previously, there was no way to do this other than to try to
> > > > > > >> > create an AF_XDP socket on the interface or load an XDP program and see
> > > > > > >> > if it worked. This commit changes this by adding a new variable which
> > > > > > >> > describes all xdp supported functions on pretty detailed level:
> > > > > > >>
> > > > > > >> >   - aborted
> > > > > > >> >   - drop
> > > > > > >> >   - pass
> > > > > > >> >   - tx
> > > > > > >> >   - redirect
> > > > > > >> >   - sock_zerocopy
> > > > > > >> >   - hw_offload
> > > > > > >> >   - redirect_target
> > > > > > >> >   - tx_lock
> > > > > > >> >   - frag_rx
> > > > > > >> >   - frag_target
> > > > > > >>
> > > > > > >> > Zerocopy mode requires that redirect XDP operation is implemented in a
> > > > > > >> > driver and the driver supports also zero copy mode. Full mode requires
> > > > > > >> > that all XDP operation are implemented in the driver. Basic mode is just
> > > > > > >> > full mode without redirect operation. Frag target requires
> > > > > > >> > redirect_target one is supported by the driver.
> > > > > > >>
> > > > > > >> Can you share more about _why_ is it needed? If we can already obtain
> > > > > > >> most of these signals via probing, why export the flags?
> > > > > > >>
> > > > > > >> > Initially, these new flags are disabled for all drivers by default.
> > > > > > >>
> > > > > > >> > Co-developed-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
> > > > > > >> > Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
> > > > > > >> > Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org>
> > > > > > >> > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> > > > > > >> > Signed-off-by: Marek Majtyka <alardam@gmail.com>
> > > > > > >> > ---
> > > > > > >> >   .../networking/netdev-xdp-features.rst        | 60 +++++++++++++++++
> > > > > > >> >   include/linux/netdevice.h                     |  2 +
> > > > > > >> >   include/linux/xdp_features.h                  | 64 +++++++++++++++++++
> > > > > > >> >   include/uapi/linux/if_link.h                  |  7 ++
> > > > > > >> >   include/uapi/linux/xdp_features.h             | 34 ++++++++++
> > > > > > >> >   net/core/rtnetlink.c                          | 34 ++++++++++
> > > > > > >> >   tools/include/uapi/linux/if_link.h            |  7 ++
> > > > > > >> >   tools/include/uapi/linux/xdp_features.h       | 34 ++++++++++
> > > > > > >> >   8 files changed, 242 insertions(+)
> > > > > > >> >   create mode 100644 Documentation/networking/netdev-xdp-features.rst
> > > > > > >> >   create mode 100644 include/linux/xdp_features.h
> > > > > > >> >   create mode 100644 include/uapi/linux/xdp_features.h
> > > > > > >> >   create mode 100644 tools/include/uapi/linux/xdp_features.h
> > > > > > >>
> > > > > > >> > diff --git a/Documentation/networking/netdev-xdp-features.rst
> > > > > > >> > b/Documentation/networking/netdev-xdp-features.rst
> > > > > > >> > new file mode 100644
> > > > > > >> > index 000000000000..1dc803fe72dd
> > > > > > >> > --- /dev/null
> > > > > > >> > +++ b/Documentation/networking/netdev-xdp-features.rst
> > > > > > >> > @@ -0,0 +1,60 @@
> > > > > > >> > +.. SPDX-License-Identifier: GPL-2.0
> > > > > > >> > +
> > > > > > >> > +=====================
> > > > > > >> > +Netdev XDP features
> > > > > > >> > +=====================
> > > > > > >> > +
> > > > > > >> > + * XDP FEATURES FLAGS
> > > > > > >> > +
> > > > > > >> > +Following netdev xdp features flags can be retrieved over route netlink
> > > > > > >> > +interface (compact form) - the same way as netdev feature flags.
> > > > > > >> > +These features flags are read only and cannot be change at runtime.
> > > > > > >> > +
> > > > > > >> > +*  XDP_ABORTED
> > > > > > >> > +
> > > > > > >> > +This feature informs if netdev supports xdp aborted action.
> > > > > > >> > +
> > > > > > >> > +*  XDP_DROP
> > > > > > >> > +
> > > > > > >> > +This feature informs if netdev supports xdp drop action.
> > > > > > >> > +
> > > > > > >> > +*  XDP_PASS
> > > > > > >> > +
> > > > > > >> > +This feature informs if netdev supports xdp pass action.
> > > > > > >> > +
> > > > > > >> > +*  XDP_TX
> > > > > > >> > +
> > > > > > >> > +This feature informs if netdev supports xdp tx action.
> > > > > > >> > +
> > > > > > >> > +*  XDP_REDIRECT
> > > > > > >> > +
> > > > > > >> > +This feature informs if netdev supports xdp redirect action.
> > > > > > >> > +It assumes the all beforehand mentioned flags are enabled.
> > > > > > >> > +
> > > > > > >> > +*  XDP_SOCK_ZEROCOPY
> > > > > > >> > +
> > > > > > >> > +This feature informs if netdev driver supports xdp zero copy.
> > > > > > >> > +It assumes the all beforehand mentioned flags are enabled.
> > > > > > >> > +
> > > > > > >> > +*  XDP_HW_OFFLOAD
> > > > > > >> > +
> > > > > > >> > +This feature informs if netdev driver supports xdp hw oflloading.
> > > > > > >> > +
> > > > > > >> > +*  XDP_TX_LOCK
> > > > > > >> > +
> > > > > > >> > +This feature informs if netdev ndo_xdp_xmit function requires locking.
> > > > > > >> > +
> > > > > > >> > +*  XDP_REDIRECT_TARGET
> > > > > > >> > +
> > > > > > >> > +This feature informs if netdev implements ndo_xdp_xmit callback.
> > > > > > >> > +
> > > > > > >> > +*  XDP_FRAG_RX
> > > > > > >> > +
> > > > > > >> > +This feature informs if netdev implements non-linear xdp buff support in
> > > > > > >> > +the driver napi callback.
> > > > > > >> > +
> > > > > > >> > +*  XDP_FRAG_TARGET
> > > > > > >> > +
> > > > > > >> > +This feature informs if netdev implements non-linear xdp buff support in
> > > > > > >> > +ndo_xdp_xmit callback. XDP_FRAG_TARGET requires XDP_REDIRECT_TARGET is
> > > > > > >> > properly
> > > > > > >> > +supported.
> > > > > > >> > diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
> > > > > > >> > index aad12a179e54..ae5a8564383b 100644
> > > > > > >> > --- a/include/linux/netdevice.h
> > > > > > >> > +++ b/include/linux/netdevice.h
> > > > > > >> > @@ -43,6 +43,7 @@
> > > > > > >> >   #include <net/xdp.h>
> > > > > > >>
> > > > > > >> >   #include <linux/netdev_features.h>
> > > > > > >> > +#include <linux/xdp_features.h>
> > > > > > >> >   #include <linux/neighbour.h>
> > > > > > >> >   #include <uapi/linux/netdevice.h>
> > > > > > >> >   #include <uapi/linux/if_bonding.h>
> > > > > > >> > @@ -2362,6 +2363,7 @@ struct net_device {
> > > > > > >> >       struct rtnl_hw_stats64  *offload_xstats_l3;
> > > > > > >>
> > > > > > >> >       struct devlink_port     *devlink_port;
> > > > > > >> > +     xdp_features_t          xdp_features;
> > > > > > >> >   };
> > > > > > >> >   #define to_net_dev(d) container_of(d, struct net_device, dev)
> > > > > > >>
> > > > > > >> > diff --git a/include/linux/xdp_features.h b/include/linux/xdp_features.h
> > > > > > >> > new file mode 100644
> > > > > > >> > index 000000000000..4e72a86ef329
> > > > > > >> > --- /dev/null
> > > > > > >> > +++ b/include/linux/xdp_features.h
> > > > > > >> > @@ -0,0 +1,64 @@
> > > > > > >> > +/* SPDX-License-Identifier: GPL-2.0-or-later */
> > > > > > >> > +/*
> > > > > > >> > + * Network device xdp features.
> > > > > > >> > + */
> > > > > > >> > +#ifndef _LINUX_XDP_FEATURES_H
> > > > > > >> > +#define _LINUX_XDP_FEATURES_H
> > > > > > >> > +
> > > > > > >> > +#include <linux/types.h>
> > > > > > >> > +#include <linux/bitops.h>
> > > > > > >> > +#include <asm/byteorder.h>
> > > > > > >> > +#include <uapi/linux/xdp_features.h>
> > > > > > >> > +
> > > > > > >> > +typedef u32 xdp_features_t;
> > > > > > >> > +
> > > > > > >> > +#define __XDP_F_BIT(bit)     ((xdp_features_t)1 << (bit))
> > > > > > >> > +#define __XDP_F(name)                __XDP_F_BIT(XDP_F_##name##_BIT)
> > > > > > >> > +
> > > > > > >> > +#define XDP_F_ABORTED                __XDP_F(ABORTED)
> > > > > > >> > +#define XDP_F_DROP           __XDP_F(DROP)
> > > > > > >> > +#define XDP_F_PASS           __XDP_F(PASS)
> > > > > > >> > +#define XDP_F_TX             __XDP_F(TX)
> > > > > > >> > +#define XDP_F_REDIRECT               __XDP_F(REDIRECT)
> > > > > > >> > +#define XDP_F_REDIRECT_TARGET        __XDP_F(REDIRECT_TARGET)
> > > > > > >> > +#define XDP_F_SOCK_ZEROCOPY  __XDP_F(SOCK_ZEROCOPY)
> > > > > > >> > +#define XDP_F_HW_OFFLOAD     __XDP_F(HW_OFFLOAD)
> > > > > > >> > +#define XDP_F_TX_LOCK                __XDP_F(TX_LOCK)
> > > > > > >> > +#define XDP_F_FRAG_RX                __XDP_F(FRAG_RX)
> > > > > > >> > +#define XDP_F_FRAG_TARGET    __XDP_F(FRAG_TARGET)
> > > > > > >> > +
> > > > > > >> > +#define XDP_F_BASIC          (XDP_F_ABORTED | XDP_F_DROP |   \
> > > > > > >> > +                              XDP_F_PASS | XDP_F_TX)
> > > > > > >> > +
> > > > > > >> > +#define XDP_F_FULL           (XDP_F_BASIC | XDP_F_REDIRECT)
> > > > > > >> > +
> > > > > > >> > +#define XDP_F_FULL_ZC                (XDP_F_FULL | XDP_F_SOCK_ZEROCOPY)
> > > > > > >> > +
> > > > > > >> > +#define XDP_FEATURES_ABORTED_STR             "xdp-aborted"
> > > > > > >> > +#define XDP_FEATURES_DROP_STR                        "xdp-drop"
> > > > > > >> > +#define XDP_FEATURES_PASS_STR                        "xdp-pass"
> > > > > > >> > +#define XDP_FEATURES_TX_STR                  "xdp-tx"
> > > > > > >> > +#define XDP_FEATURES_REDIRECT_STR            "xdp-redirect"
> > > > > > >> > +#define XDP_FEATURES_REDIRECT_TARGET_STR     "xdp-redirect-target"
> > > > > > >> > +#define XDP_FEATURES_SOCK_ZEROCOPY_STR               "xdp-sock-zerocopy"
> > > > > > >> > +#define XDP_FEATURES_HW_OFFLOAD_STR          "xdp-hw-offload"
> > > > > > >> > +#define XDP_FEATURES_TX_LOCK_STR             "xdp-tx-lock"
> > > > > > >> > +#define XDP_FEATURES_FRAG_RX_STR             "xdp-frag-rx"
> > > > > > >> > +#define XDP_FEATURES_FRAG_TARGET_STR         "xdp-frag-target"
> > > > > > >> > +
> > > > > > >> > +#define DECLARE_XDP_FEATURES_TABLE(name, length)                             \
> > > > > > >> > +     const char name[][length] = {                                           \
> > > > > > >> > +             [XDP_F_ABORTED_BIT] = XDP_FEATURES_ABORTED_STR,                 \
> > > > > > >> > +             [XDP_F_DROP_BIT] = XDP_FEATURES_DROP_STR,                       \
> > > > > > >> > +             [XDP_F_PASS_BIT] = XDP_FEATURES_PASS_STR,                       \
> > > > > > >> > +             [XDP_F_TX_BIT] = XDP_FEATURES_TX_STR,                           \
> > > > > > >> > +             [XDP_F_REDIRECT_BIT] = XDP_FEATURES_REDIRECT_STR,               \
> > > > > > >> > +             [XDP_F_REDIRECT_TARGET_BIT] = XDP_FEATURES_REDIRECT_TARGET_STR, \
> > > > > > >> > +             [XDP_F_SOCK_ZEROCOPY_BIT] = XDP_FEATURES_SOCK_ZEROCOPY_STR,     \
> > > > > > >> > +             [XDP_F_HW_OFFLOAD_BIT] = XDP_FEATURES_HW_OFFLOAD_STR,           \
> > > > > > >> > +             [XDP_F_TX_LOCK_BIT] = XDP_FEATURES_TX_LOCK_STR,                 \
> > > > > > >> > +             [XDP_F_FRAG_RX_BIT] = XDP_FEATURES_FRAG_RX_STR,                 \
> > > > > > >> > +             [XDP_F_FRAG_TARGET_BIT] = XDP_FEATURES_FRAG_TARGET_STR,         \
> > > > > > >> > +     }
> > > > > > >> > +
> > > > > > >> > +#endif /* _LINUX_XDP_FEATURES_H */
> > > > > > >> > diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
> > > > > > >> > index 1021a7e47a86..971c658ceaea 100644
> > > > > > >> > --- a/include/uapi/linux/if_link.h
> > > > > > >> > +++ b/include/uapi/linux/if_link.h
> > > > > > >> > @@ -374,6 +374,8 @@ enum {
> > > > > > >>
> > > > > > >> >       IFLA_DEVLINK_PORT,
> > > > > > >>
> > > > > > >> > +     IFLA_XDP_FEATURES,
> > > > > > >> > +
> > > > > > >> >       __IFLA_MAX
> > > > > > >> >   };
> > > > > > >>
> > > > > > >> > @@ -1318,6 +1320,11 @@ enum {
> > > > > > >>
> > > > > > >> >   #define IFLA_XDP_MAX (__IFLA_XDP_MAX - 1)
> > > > > > >>
> > > > > > >> > +enum {
> > > > > > >> > +     IFLA_XDP_FEATURES_WORD_UNSPEC = 0,
> > > > > > >> > +     IFLA_XDP_FEATURES_BITS_WORD,
> > > > > > >> > +};
> > > > > > >> > +
> > > > > > >> >   enum {
> > > > > > >> >       IFLA_EVENT_NONE,
> > > > > > >> >       IFLA_EVENT_REBOOT,              /* internal reset / reboot */
> > > > > > >> > diff --git a/include/uapi/linux/xdp_features.h
> > > > > > >> > b/include/uapi/linux/xdp_features.h
> > > > > > >> > new file mode 100644
> > > > > > >> > index 000000000000..48eb42069bcd
> > > > > > >> > --- /dev/null
> > > > > > >> > +++ b/include/uapi/linux/xdp_features.h
> > > > > > >> > @@ -0,0 +1,34 @@
> > > > > > >> > +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
> > > > > > >> > +/*
> > > > > > >> > + * Copyright (c) 2020 Intel
> > > > > > >> > + */
> > > > > > >> > +
> > > > > > >> > +#ifndef __UAPI_LINUX_XDP_FEATURES__
> > > > > > >> > +#define __UAPI_LINUX_XDP_FEATURES__
> > > > > > >> > +
> > > > > > >> > +enum {
> > > > > > >> > +     XDP_F_ABORTED_BIT,
> > > > > > >> > +     XDP_F_DROP_BIT,
> > > > > > >> > +     XDP_F_PASS_BIT,
> > > > > > >> > +     XDP_F_TX_BIT,
> > > > > > >> > +     XDP_F_REDIRECT_BIT,
> > > > > > >> > +     XDP_F_REDIRECT_TARGET_BIT,
> > > > > > >> > +     XDP_F_SOCK_ZEROCOPY_BIT,
> > > > > > >> > +     XDP_F_HW_OFFLOAD_BIT,
> > > > > > >> > +     XDP_F_TX_LOCK_BIT,
> > > > > > >> > +     XDP_F_FRAG_RX_BIT,
> > > > > > >> > +     XDP_F_FRAG_TARGET_BIT,
> > > > > > >> > +     /*
> > > > > > >> > +      * Add your fresh new property above and remember to update
> > > > > > >> > +      * documentation.
> > > > > > >> > +      */
> > > > > > >> > +     XDP_FEATURES_COUNT,
> > > > > > >> > +};
> > > > > > >> > +
> > > > > > >> > +#define XDP_FEATURES_WORDS                   ((XDP_FEATURES_COUNT + 32 - 1) / 32)
> > > > > > >> > +#define XDP_FEATURES_WORD(blocks, index)     ((blocks)[(index) / 32U])
> > > > > > >> > +#define XDP_FEATURES_FIELD_FLAG(index)               (1U << (index) % 32U)
> > > > > > >> > +#define XDP_FEATURES_BIT_IS_SET(blocks, index)        \
> > > > > > >> > +     (XDP_FEATURES_WORD(blocks, index) & XDP_FEATURES_FIELD_FLAG(index))
> > > > > > >> > +
> > > > > > >> > +#endif  /* __UAPI_LINUX_XDP_FEATURES__ */
> > > > > > >> > diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
> > > > > > >> > index 64289bc98887..1c299746b614 100644
> > > > > > >> > --- a/net/core/rtnetlink.c
> > > > > > >> > +++ b/net/core/rtnetlink.c
> > > > > > >> > @@ -1016,6 +1016,14 @@ static size_t rtnl_xdp_size(void)
> > > > > > >> >       return xdp_size;
> > > > > > >> >   }
> > > > > > >>
> > > > > > >> > +static size_t rtnl_xdp_features_size(void)
> > > > > > >> > +{
> > > > > > >> > +     size_t xdp_size = nla_total_size(0) +   /* nest IFLA_XDP_FEATURES */
> > > > > > >> > +                       XDP_FEATURES_WORDS * nla_total_size(4);
> > > > > > >> > +
> > > > > > >> > +     return xdp_size;
> > > > > > >> > +}
> > > > > > >> > +
> > > > > > >> >   static size_t rtnl_prop_list_size(const struct net_device *dev)
> > > > > > >> >   {
> > > > > > >> >       struct netdev_name_node *name_node;
> > > > > > >> > @@ -1103,6 +1111,7 @@ static noinline size_t if_nlmsg_size(const struct
> > > > > > >> > net_device *dev,
> > > > > > >> >              + rtnl_prop_list_size(dev)
> > > > > > >> >              + nla_total_size(MAX_ADDR_LEN) /* IFLA_PERM_ADDRESS */
> > > > > > >> >              + rtnl_devlink_port_size(dev)
> > > > > > >> > +            + rtnl_xdp_features_size() /* IFLA_XDP_FEATURES */
> > > > > > >> >              + 0;
> > > > > > >> >   }
> > > > > > >>
> > > > > > >> > @@ -1546,6 +1555,27 @@ static int rtnl_xdp_fill(struct sk_buff *skb,
> > > > > > >> > struct net_device *dev)
> > > > > > >> >       return err;
> > > > > > >> >   }
> > > > > > >>
> > > > > > >> > +static int rtnl_xdp_features_fill(struct sk_buff *skb, struct net_device
> > > > > > >> > *dev)
> > > > > > >> > +{
> > > > > > >> > +     struct nlattr *attr;
> > > > > > >> > +
> > > > > > >> > +     attr = nla_nest_start_noflag(skb, IFLA_XDP_FEATURES);
> > > > > > >> > +     if (!attr)
> > > > > > >> > +             return -EMSGSIZE;
> > > > > > >> > +
> > > > > > >> > +     BUILD_BUG_ON(XDP_FEATURES_WORDS != 1);
> > > > > > >> > +     if (nla_put_u32(skb, IFLA_XDP_FEATURES_BITS_WORD, dev->xdp_features))
> > > > > > >> > +             goto err_cancel;
> > > > > > >> > +
> > > > > > >> > +     nla_nest_end(skb, attr);
> > > > > > >> > +
> > > > > > >> > +     return 0;
> > > > > > >> > +
> > > > > > >> > +err_cancel:
> > > > > > >> > +     nla_nest_cancel(skb, attr);
> > > > > > >> > +     return -EMSGSIZE;
> > > > > > >> > +}
> > > > > > >> > +
> > > > > > >> >   static u32 rtnl_get_event(unsigned long event)
> > > > > > >> >   {
> > > > > > >> >       u32 rtnl_event_type = IFLA_EVENT_NONE;
> > > > > > >> > @@ -1904,6 +1934,9 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb,
> > > > > > >> >       if (rtnl_fill_devlink_port(skb, dev))
> > > > > > >> >               goto nla_put_failure;
> > > > > > >>
> > > > > > >> > +     if (rtnl_xdp_features_fill(skb, dev))
> > > > > > >> > +             goto nla_put_failure;
> > > > > > >> > +
> > > > > > >> >       nlmsg_end(skb, nlh);
> > > > > > >> >       return 0;
> > > > > > >>
> > > > > > >> > @@ -1968,6 +2001,7 @@ static const struct nla_policy
> > > > > > >> > ifla_policy[IFLA_MAX+1] = {
> > > > > > >> >       [IFLA_TSO_MAX_SIZE]     = { .type = NLA_REJECT },
> > > > > > >> >       [IFLA_TSO_MAX_SEGS]     = { .type = NLA_REJECT },
> > > > > > >> >       [IFLA_ALLMULTI]         = { .type = NLA_REJECT },
> > > > > > >> > +     [IFLA_XDP_FEATURES]     = { .type = NLA_NESTED },
> > > > > > >> >   };
> > > > > > >>
> > > > > > >> >   static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
> > > > > > >> > diff --git a/tools/include/uapi/linux/if_link.h
> > > > > > >> > b/tools/include/uapi/linux/if_link.h
> > > > > > >> > index 82fe18f26db5..994228e9909a 100644
> > > > > > >> > --- a/tools/include/uapi/linux/if_link.h
> > > > > > >> > +++ b/tools/include/uapi/linux/if_link.h
> > > > > > >> > @@ -354,6 +354,8 @@ enum {
> > > > > > >>
> > > > > > >> >       IFLA_DEVLINK_PORT,
> > > > > > >>
> > > > > > >> > +     IFLA_XDP_FEATURES,
> > > > > > >> > +
> > > > > > >> >       __IFLA_MAX
> > > > > > >> >   };
> > > > > > >>
> > > > > > >> > @@ -1222,6 +1224,11 @@ enum {
> > > > > > >>
> > > > > > >> >   #define IFLA_XDP_MAX (__IFLA_XDP_MAX - 1)
> > > > > > >>
> > > > > > >> > +enum {
> > > > > > >> > +     IFLA_XDP_FEATURES_WORD_UNSPEC = 0,
> > > > > > >> > +     IFLA_XDP_FEATURES_BITS_WORD,
> > > > > > >> > +};
> > > > > > >> > +
> > > > > > >> >   enum {
> > > > > > >> >       IFLA_EVENT_NONE,
> > > > > > >> >       IFLA_EVENT_REBOOT,              /* internal reset / reboot */
> > > > > > >> > diff --git a/tools/include/uapi/linux/xdp_features.h
> > > > > > >> > b/tools/include/uapi/linux/xdp_features.h
> > > > > > >> > new file mode 100644
> > > > > > >> > index 000000000000..48eb42069bcd
> > > > > > >> > --- /dev/null
> > > > > > >> > +++ b/tools/include/uapi/linux/xdp_features.h
> > > > > > >> > @@ -0,0 +1,34 @@
> > > > > > >> > +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
> > > > > > >> > +/*
> > > > > > >> > + * Copyright (c) 2020 Intel
> > > > > > >> > + */
> > > > > > >> > +
> > > > > > >> > +#ifndef __UAPI_LINUX_XDP_FEATURES__
> > > > > > >> > +#define __UAPI_LINUX_XDP_FEATURES__
> > > > > > >> > +
> > > > > > >> > +enum {
> > > > > > >> > +     XDP_F_ABORTED_BIT,
> > > > > > >> > +     XDP_F_DROP_BIT,
> > > > > > >> > +     XDP_F_PASS_BIT,
> > > > > > >> > +     XDP_F_TX_BIT,
> > > > > > >> > +     XDP_F_REDIRECT_BIT,
> > > > > > >> > +     XDP_F_REDIRECT_TARGET_BIT,
> > > > > > >> > +     XDP_F_SOCK_ZEROCOPY_BIT,
> > > > > > >> > +     XDP_F_HW_OFFLOAD_BIT,
> > > > > > >> > +     XDP_F_TX_LOCK_BIT,
> > > > > > >> > +     XDP_F_FRAG_RX_BIT,
> > > > > > >> > +     XDP_F_FRAG_TARGET_BIT,
> > > > > > >> > +     /*
> > > > > > >> > +      * Add your fresh new property above and remember to update
> > > > > > >> > +      * documentation.
> > > > > > >> > +      */
> > > > > > >> > +     XDP_FEATURES_COUNT,
> > > > > > >> > +};
> > > > > > >> > +
> > > > > > >> > +#define XDP_FEATURES_WORDS                   ((XDP_FEATURES_COUNT + 32 - 1) / 32)
> > > > > > >> > +#define XDP_FEATURES_WORD(blocks, index)     ((blocks)[(index) / 32U])
> > > > > > >> > +#define XDP_FEATURES_FIELD_FLAG(index)               (1U << (index) % 32U)
> > > > > > >> > +#define XDP_FEATURES_BIT_IS_SET(blocks, index)        \
> > > > > > >> > +     (XDP_FEATURES_WORD(blocks, index) & XDP_FEATURES_FIELD_FLAG(index))
> > > > > > >> > +
> > > > > > >> > +#endif  /* __UAPI_LINUX_XDP_FEATURES__ */
> > > > > > >> > --
> > > > > > >> > 2.38.1
> > > > > > >>
> > > > > >
diff mbox series

Patch

diff --git a/Documentation/networking/netdev-xdp-features.rst b/Documentation/networking/netdev-xdp-features.rst
new file mode 100644
index 000000000000..1dc803fe72dd
--- /dev/null
+++ b/Documentation/networking/netdev-xdp-features.rst
@@ -0,0 +1,60 @@ 
+.. SPDX-License-Identifier: GPL-2.0
+
+=====================
+Netdev XDP features
+=====================
+
+ * XDP FEATURES FLAGS
+
+Following netdev xdp features flags can be retrieved over route netlink
+interface (compact form) - the same way as netdev feature flags.
+These features flags are read only and cannot be change at runtime.
+
+*  XDP_ABORTED
+
+This feature informs if netdev supports xdp aborted action.
+
+*  XDP_DROP
+
+This feature informs if netdev supports xdp drop action.
+
+*  XDP_PASS
+
+This feature informs if netdev supports xdp pass action.
+
+*  XDP_TX
+
+This feature informs if netdev supports xdp tx action.
+
+*  XDP_REDIRECT
+
+This feature informs if netdev supports xdp redirect action.
+It assumes the all beforehand mentioned flags are enabled.
+
+*  XDP_SOCK_ZEROCOPY
+
+This feature informs if netdev driver supports xdp zero copy.
+It assumes the all beforehand mentioned flags are enabled.
+
+*  XDP_HW_OFFLOAD
+
+This feature informs if netdev driver supports xdp hw oflloading.
+
+*  XDP_TX_LOCK
+
+This feature informs if netdev ndo_xdp_xmit function requires locking.
+
+*  XDP_REDIRECT_TARGET
+
+This feature informs if netdev implements ndo_xdp_xmit callback.
+
+*  XDP_FRAG_RX
+
+This feature informs if netdev implements non-linear xdp buff support in
+the driver napi callback.
+
+*  XDP_FRAG_TARGET
+
+This feature informs if netdev implements non-linear xdp buff support in
+ndo_xdp_xmit callback. XDP_FRAG_TARGET requires XDP_REDIRECT_TARGET is properly
+supported.
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index aad12a179e54..ae5a8564383b 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -43,6 +43,7 @@ 
 #include <net/xdp.h>
 
 #include <linux/netdev_features.h>
+#include <linux/xdp_features.h>
 #include <linux/neighbour.h>
 #include <uapi/linux/netdevice.h>
 #include <uapi/linux/if_bonding.h>
@@ -2362,6 +2363,7 @@  struct net_device {
 	struct rtnl_hw_stats64	*offload_xstats_l3;
 
 	struct devlink_port	*devlink_port;
+	xdp_features_t		xdp_features;
 };
 #define to_net_dev(d) container_of(d, struct net_device, dev)
 
diff --git a/include/linux/xdp_features.h b/include/linux/xdp_features.h
new file mode 100644
index 000000000000..4e72a86ef329
--- /dev/null
+++ b/include/linux/xdp_features.h
@@ -0,0 +1,64 @@ 
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Network device xdp features.
+ */
+#ifndef _LINUX_XDP_FEATURES_H
+#define _LINUX_XDP_FEATURES_H
+
+#include <linux/types.h>
+#include <linux/bitops.h>
+#include <asm/byteorder.h>
+#include <uapi/linux/xdp_features.h>
+
+typedef u32 xdp_features_t;
+
+#define __XDP_F_BIT(bit)	((xdp_features_t)1 << (bit))
+#define __XDP_F(name)		__XDP_F_BIT(XDP_F_##name##_BIT)
+
+#define XDP_F_ABORTED		__XDP_F(ABORTED)
+#define XDP_F_DROP		__XDP_F(DROP)
+#define XDP_F_PASS		__XDP_F(PASS)
+#define XDP_F_TX		__XDP_F(TX)
+#define XDP_F_REDIRECT		__XDP_F(REDIRECT)
+#define XDP_F_REDIRECT_TARGET	__XDP_F(REDIRECT_TARGET)
+#define XDP_F_SOCK_ZEROCOPY	__XDP_F(SOCK_ZEROCOPY)
+#define XDP_F_HW_OFFLOAD	__XDP_F(HW_OFFLOAD)
+#define XDP_F_TX_LOCK		__XDP_F(TX_LOCK)
+#define XDP_F_FRAG_RX		__XDP_F(FRAG_RX)
+#define XDP_F_FRAG_TARGET	__XDP_F(FRAG_TARGET)
+
+#define XDP_F_BASIC		(XDP_F_ABORTED | XDP_F_DROP |	\
+				 XDP_F_PASS | XDP_F_TX)
+
+#define XDP_F_FULL		(XDP_F_BASIC | XDP_F_REDIRECT)
+
+#define XDP_F_FULL_ZC		(XDP_F_FULL | XDP_F_SOCK_ZEROCOPY)
+
+#define XDP_FEATURES_ABORTED_STR		"xdp-aborted"
+#define XDP_FEATURES_DROP_STR			"xdp-drop"
+#define XDP_FEATURES_PASS_STR			"xdp-pass"
+#define XDP_FEATURES_TX_STR			"xdp-tx"
+#define XDP_FEATURES_REDIRECT_STR		"xdp-redirect"
+#define XDP_FEATURES_REDIRECT_TARGET_STR	"xdp-redirect-target"
+#define XDP_FEATURES_SOCK_ZEROCOPY_STR		"xdp-sock-zerocopy"
+#define XDP_FEATURES_HW_OFFLOAD_STR		"xdp-hw-offload"
+#define XDP_FEATURES_TX_LOCK_STR		"xdp-tx-lock"
+#define XDP_FEATURES_FRAG_RX_STR		"xdp-frag-rx"
+#define XDP_FEATURES_FRAG_TARGET_STR		"xdp-frag-target"
+
+#define DECLARE_XDP_FEATURES_TABLE(name, length)				\
+	const char name[][length] = {						\
+		[XDP_F_ABORTED_BIT] = XDP_FEATURES_ABORTED_STR,			\
+		[XDP_F_DROP_BIT] = XDP_FEATURES_DROP_STR,			\
+		[XDP_F_PASS_BIT] = XDP_FEATURES_PASS_STR,			\
+		[XDP_F_TX_BIT] = XDP_FEATURES_TX_STR,				\
+		[XDP_F_REDIRECT_BIT] = XDP_FEATURES_REDIRECT_STR,		\
+		[XDP_F_REDIRECT_TARGET_BIT] = XDP_FEATURES_REDIRECT_TARGET_STR,	\
+		[XDP_F_SOCK_ZEROCOPY_BIT] = XDP_FEATURES_SOCK_ZEROCOPY_STR,	\
+		[XDP_F_HW_OFFLOAD_BIT] = XDP_FEATURES_HW_OFFLOAD_STR,		\
+		[XDP_F_TX_LOCK_BIT] = XDP_FEATURES_TX_LOCK_STR,			\
+		[XDP_F_FRAG_RX_BIT] = XDP_FEATURES_FRAG_RX_STR,			\
+		[XDP_F_FRAG_TARGET_BIT] = XDP_FEATURES_FRAG_TARGET_STR,		\
+	}
+
+#endif /* _LINUX_XDP_FEATURES_H */
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index 1021a7e47a86..971c658ceaea 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -374,6 +374,8 @@  enum {
 
 	IFLA_DEVLINK_PORT,
 
+	IFLA_XDP_FEATURES,
+
 	__IFLA_MAX
 };
 
@@ -1318,6 +1320,11 @@  enum {
 
 #define IFLA_XDP_MAX (__IFLA_XDP_MAX - 1)
 
+enum {
+	IFLA_XDP_FEATURES_WORD_UNSPEC = 0,
+	IFLA_XDP_FEATURES_BITS_WORD,
+};
+
 enum {
 	IFLA_EVENT_NONE,
 	IFLA_EVENT_REBOOT,		/* internal reset / reboot */
diff --git a/include/uapi/linux/xdp_features.h b/include/uapi/linux/xdp_features.h
new file mode 100644
index 000000000000..48eb42069bcd
--- /dev/null
+++ b/include/uapi/linux/xdp_features.h
@@ -0,0 +1,34 @@ 
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * Copyright (c) 2020 Intel
+ */
+
+#ifndef __UAPI_LINUX_XDP_FEATURES__
+#define __UAPI_LINUX_XDP_FEATURES__
+
+enum {
+	XDP_F_ABORTED_BIT,
+	XDP_F_DROP_BIT,
+	XDP_F_PASS_BIT,
+	XDP_F_TX_BIT,
+	XDP_F_REDIRECT_BIT,
+	XDP_F_REDIRECT_TARGET_BIT,
+	XDP_F_SOCK_ZEROCOPY_BIT,
+	XDP_F_HW_OFFLOAD_BIT,
+	XDP_F_TX_LOCK_BIT,
+	XDP_F_FRAG_RX_BIT,
+	XDP_F_FRAG_TARGET_BIT,
+	/*
+	 * Add your fresh new property above and remember to update
+	 * documentation.
+	 */
+	XDP_FEATURES_COUNT,
+};
+
+#define XDP_FEATURES_WORDS			((XDP_FEATURES_COUNT + 32 - 1) / 32)
+#define XDP_FEATURES_WORD(blocks, index)	((blocks)[(index) / 32U])
+#define XDP_FEATURES_FIELD_FLAG(index)		(1U << (index) % 32U)
+#define XDP_FEATURES_BIT_IS_SET(blocks, index)        \
+	(XDP_FEATURES_WORD(blocks, index) & XDP_FEATURES_FIELD_FLAG(index))
+
+#endif  /* __UAPI_LINUX_XDP_FEATURES__ */
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 64289bc98887..1c299746b614 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1016,6 +1016,14 @@  static size_t rtnl_xdp_size(void)
 	return xdp_size;
 }
 
+static size_t rtnl_xdp_features_size(void)
+{
+	size_t xdp_size = nla_total_size(0) +	/* nest IFLA_XDP_FEATURES */
+			  XDP_FEATURES_WORDS * nla_total_size(4);
+
+	return xdp_size;
+}
+
 static size_t rtnl_prop_list_size(const struct net_device *dev)
 {
 	struct netdev_name_node *name_node;
@@ -1103,6 +1111,7 @@  static noinline size_t if_nlmsg_size(const struct net_device *dev,
 	       + rtnl_prop_list_size(dev)
 	       + nla_total_size(MAX_ADDR_LEN) /* IFLA_PERM_ADDRESS */
 	       + rtnl_devlink_port_size(dev)
+	       + rtnl_xdp_features_size() /* IFLA_XDP_FEATURES */
 	       + 0;
 }
 
@@ -1546,6 +1555,27 @@  static int rtnl_xdp_fill(struct sk_buff *skb, struct net_device *dev)
 	return err;
 }
 
+static int rtnl_xdp_features_fill(struct sk_buff *skb, struct net_device *dev)
+{
+	struct nlattr *attr;
+
+	attr = nla_nest_start_noflag(skb, IFLA_XDP_FEATURES);
+	if (!attr)
+		return -EMSGSIZE;
+
+	BUILD_BUG_ON(XDP_FEATURES_WORDS != 1);
+	if (nla_put_u32(skb, IFLA_XDP_FEATURES_BITS_WORD, dev->xdp_features))
+		goto err_cancel;
+
+	nla_nest_end(skb, attr);
+
+	return 0;
+
+err_cancel:
+	nla_nest_cancel(skb, attr);
+	return -EMSGSIZE;
+}
+
 static u32 rtnl_get_event(unsigned long event)
 {
 	u32 rtnl_event_type = IFLA_EVENT_NONE;
@@ -1904,6 +1934,9 @@  static int rtnl_fill_ifinfo(struct sk_buff *skb,
 	if (rtnl_fill_devlink_port(skb, dev))
 		goto nla_put_failure;
 
+	if (rtnl_xdp_features_fill(skb, dev))
+		goto nla_put_failure;
+
 	nlmsg_end(skb, nlh);
 	return 0;
 
@@ -1968,6 +2001,7 @@  static const struct nla_policy ifla_policy[IFLA_MAX+1] = {
 	[IFLA_TSO_MAX_SIZE]	= { .type = NLA_REJECT },
 	[IFLA_TSO_MAX_SEGS]	= { .type = NLA_REJECT },
 	[IFLA_ALLMULTI]		= { .type = NLA_REJECT },
+	[IFLA_XDP_FEATURES]	= { .type = NLA_NESTED },
 };
 
 static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
diff --git a/tools/include/uapi/linux/if_link.h b/tools/include/uapi/linux/if_link.h
index 82fe18f26db5..994228e9909a 100644
--- a/tools/include/uapi/linux/if_link.h
+++ b/tools/include/uapi/linux/if_link.h
@@ -354,6 +354,8 @@  enum {
 
 	IFLA_DEVLINK_PORT,
 
+	IFLA_XDP_FEATURES,
+
 	__IFLA_MAX
 };
 
@@ -1222,6 +1224,11 @@  enum {
 
 #define IFLA_XDP_MAX (__IFLA_XDP_MAX - 1)
 
+enum {
+	IFLA_XDP_FEATURES_WORD_UNSPEC = 0,
+	IFLA_XDP_FEATURES_BITS_WORD,
+};
+
 enum {
 	IFLA_EVENT_NONE,
 	IFLA_EVENT_REBOOT,		/* internal reset / reboot */
diff --git a/tools/include/uapi/linux/xdp_features.h b/tools/include/uapi/linux/xdp_features.h
new file mode 100644
index 000000000000..48eb42069bcd
--- /dev/null
+++ b/tools/include/uapi/linux/xdp_features.h
@@ -0,0 +1,34 @@ 
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * Copyright (c) 2020 Intel
+ */
+
+#ifndef __UAPI_LINUX_XDP_FEATURES__
+#define __UAPI_LINUX_XDP_FEATURES__
+
+enum {
+	XDP_F_ABORTED_BIT,
+	XDP_F_DROP_BIT,
+	XDP_F_PASS_BIT,
+	XDP_F_TX_BIT,
+	XDP_F_REDIRECT_BIT,
+	XDP_F_REDIRECT_TARGET_BIT,
+	XDP_F_SOCK_ZEROCOPY_BIT,
+	XDP_F_HW_OFFLOAD_BIT,
+	XDP_F_TX_LOCK_BIT,
+	XDP_F_FRAG_RX_BIT,
+	XDP_F_FRAG_TARGET_BIT,
+	/*
+	 * Add your fresh new property above and remember to update
+	 * documentation.
+	 */
+	XDP_FEATURES_COUNT,
+};
+
+#define XDP_FEATURES_WORDS			((XDP_FEATURES_COUNT + 32 - 1) / 32)
+#define XDP_FEATURES_WORD(blocks, index)	((blocks)[(index) / 32U])
+#define XDP_FEATURES_FIELD_FLAG(index)		(1U << (index) % 32U)
+#define XDP_FEATURES_BIT_IS_SET(blocks, index)        \
+	(XDP_FEATURES_WORD(blocks, index) & XDP_FEATURES_FIELD_FLAG(index))
+
+#endif  /* __UAPI_LINUX_XDP_FEATURES__ */