netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC bpf-next 0/8] xdp: introduce xdp-feature support
@ 2022-12-19 15:41 Lorenzo Bianconi
  2022-12-19 15:41 ` [RFC bpf-next 1/8] tools: uapi: align if_link.h Lorenzo Bianconi
                   ` (7 more replies)
  0 siblings, 8 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2022-12-19 15:41 UTC (permalink / raw)
  To: bpf
  Cc: netdev, ast, daniel, andrii, davem, kuba, hawk, pabeni, edumazet,
	toke, memxor, alardam, saeedm, anthony.l.nguyen, gospo,
	vladimir.oltean, nbd, john, leon, simon.horman, aelior,
	christophe.jaillet, ecree.xilinx, grygorii.strashko, mst, bjorn,
	magnus.karlsson, maciej.fijalkowski, intel-wired-lan,
	lorenzo.bianconi

Introduce the capability to export the XDP features supported by the NIC.
Introduce a XDP compliance test tool (xdp_features) to check the features
exported by the NIC match the real features supported by the driver.
Allow XDP_REDIRECT of non-linear XDP frames into a devmap.
Export XDP features for each XDP capable driver.

Kumar Kartikeya Dwivedi (1):
  libbpf: add API to get XDP/XSK supported features

Lorenzo Bianconi (3):
  tools: uapi: align if_link.h
  bpf: devmap: check XDP features in bpf_map_update_elem and
    __xdp_enqueue
  selftests/bpf: introduce XDP compliance test tool

Marek Majtyka (4):
  net: introduce XDP features flag
  drivers: net: turn on XDP features
  xsk: add usage of XDP features flags
  xsk: add check for full support of XDP in bind

 .../networking/netdev-xdp-features.rst        |  60 ++
 drivers/net/ethernet/amazon/ena/ena_netdev.c  |   5 +
 .../net/ethernet/aquantia/atlantic/aq_nic.c   |   3 +
 drivers/net/ethernet/broadcom/bnxt/bnxt.c     |   2 +
 drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c |   2 +
 .../net/ethernet/cavium/thunder/nicvf_main.c  |   2 +
 .../net/ethernet/freescale/dpaa/dpaa_eth.c    |   2 +
 .../net/ethernet/freescale/dpaa2/dpaa2-eth.c  |   1 +
 .../net/ethernet/freescale/enetc/enetc_pf.c   |   3 +
 .../ethernet/fungible/funeth/funeth_main.c    |   6 +
 drivers/net/ethernet/intel/i40e/i40e_main.c   |   9 +-
 drivers/net/ethernet/intel/ice/ice_main.c     |   5 +
 drivers/net/ethernet/intel/igb/igb_main.c     |   9 +-
 drivers/net/ethernet/intel/igc/igc_main.c     |   2 +
 drivers/net/ethernet/intel/igc/igc_xdp.c      |   5 +
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c |   5 +
 .../net/ethernet/intel/ixgbevf/ixgbevf_main.c |   1 +
 drivers/net/ethernet/marvell/mvneta.c         |   3 +
 .../net/ethernet/marvell/mvpp2/mvpp2_main.c   |   3 +
 .../ethernet/marvell/octeontx2/nic/otx2_pf.c  |   9 +-
 drivers/net/ethernet/mediatek/mtk_eth_soc.c   |   5 +
 .../net/ethernet/mellanox/mlx4/en_netdev.c    |   2 +
 .../net/ethernet/mellanox/mlx5/core/en_main.c |   9 +
 drivers/net/ethernet/microsoft/mana/mana_en.c |   2 +
 .../ethernet/netronome/nfp/nfp_net_common.c   |   3 +
 drivers/net/ethernet/qlogic/qede/qede_main.c  |   2 +
 drivers/net/ethernet/sfc/efx.c                |   2 +
 drivers/net/ethernet/sfc/siena/efx.c          |   2 +
 drivers/net/ethernet/socionext/netsec.c       |   2 +
 .../net/ethernet/stmicro/stmmac/stmmac_main.c |   1 +
 drivers/net/ethernet/ti/cpsw.c                |   2 +
 drivers/net/ethernet/ti/cpsw_new.c            |   2 +
 drivers/net/hyperv/netvsc_drv.c               |   2 +
 drivers/net/netdevsim/netdev.c                |   1 +
 drivers/net/tun.c                             |   3 +
 drivers/net/veth.c                            |   4 +
 drivers/net/virtio_net.c                      |   5 +
 drivers/net/xen-netfront.c                    |   1 +
 include/linux/netdevice.h                     |   2 +
 include/linux/xdp_features.h                  |  64 ++
 include/net/xdp.h                             |  39 +
 include/uapi/linux/if_link.h                  |   7 +
 include/uapi/linux/if_xdp.h                   |   1 +
 include/uapi/linux/xdp_features.h             |  34 +
 kernel/bpf/devmap.c                           |  25 +-
 net/core/filter.c                             |  13 +-
 net/core/rtnetlink.c                          |  34 +
 net/xdp/xsk.c                                 |   4 +-
 net/xdp/xsk_buff_pool.c                       |  20 +-
 tools/include/uapi/linux/if_link.h            |  10 +
 tools/include/uapi/linux/if_xdp.h             |   1 +
 tools/include/uapi/linux/xdp_features.h       |  34 +
 tools/lib/bpf/libbpf.h                        |   1 +
 tools/lib/bpf/libbpf.map                      |   1 +
 tools/lib/bpf/netlink.c                       |  62 ++
 tools/testing/selftests/bpf/Makefile          |   5 +-
 .../selftests/bpf/progs/test_xdp_features.c   | 235 ++++++
 .../selftests/bpf/test_xdp_features.sh        |  99 +++
 tools/testing/selftests/bpf/xdp_features.c    | 745 ++++++++++++++++++
 tools/testing/selftests/bpf/xsk.c             |   3 +
 60 files changed, 1602 insertions(+), 24 deletions(-)
 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
 create mode 100644 tools/testing/selftests/bpf/progs/test_xdp_features.c
 create mode 100755 tools/testing/selftests/bpf/test_xdp_features.sh
 create mode 100644 tools/testing/selftests/bpf/xdp_features.c

-- 
2.38.1


^ permalink raw reply	[flat|nested] 27+ messages in thread

* [RFC bpf-next 1/8] tools: uapi: align if_link.h
  2022-12-19 15:41 [RFC bpf-next 0/8] xdp: introduce xdp-feature support Lorenzo Bianconi
@ 2022-12-19 15:41 ` Lorenzo Bianconi
  2022-12-19 15:41 ` [RFC bpf-next 2/8] net: introduce XDP features flag Lorenzo Bianconi
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2022-12-19 15:41 UTC (permalink / raw)
  To: bpf
  Cc: netdev, ast, daniel, andrii, davem, kuba, hawk, pabeni, edumazet,
	toke, memxor, alardam, saeedm, anthony.l.nguyen, gospo,
	vladimir.oltean, nbd, john, leon, simon.horman, aelior,
	christophe.jaillet, ecree.xilinx, grygorii.strashko, mst, bjorn,
	magnus.karlsson, maciej.fijalkowski, intel-wired-lan,
	lorenzo.bianconi

Align IFLA enum definitions in tools/include/uapi/linux/if_link.h to
include/uapi/linux/if_link.h after the following commits:
- '7e6e1b57162e ("rtnetlink: advertise allmulti counter")'
- 'dca56c3038c3 ("net: expose devlink port over rtnetlink")'

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 tools/include/uapi/linux/if_link.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/tools/include/uapi/linux/if_link.h b/tools/include/uapi/linux/if_link.h
index 901d98b865a1..82fe18f26db5 100644
--- a/tools/include/uapi/linux/if_link.h
+++ b/tools/include/uapi/linux/if_link.h
@@ -350,6 +350,9 @@ enum {
 	IFLA_GRO_MAX_SIZE,
 	IFLA_TSO_MAX_SIZE,
 	IFLA_TSO_MAX_SEGS,
+	IFLA_ALLMULTI,		/* Allmulti count: > 0 means acts ALLMULTI */
+
+	IFLA_DEVLINK_PORT,
 
 	__IFLA_MAX
 };
-- 
2.38.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [RFC bpf-next 2/8] net: introduce XDP features flag
  2022-12-19 15:41 [RFC bpf-next 0/8] xdp: introduce xdp-feature support Lorenzo Bianconi
  2022-12-19 15:41 ` [RFC bpf-next 1/8] tools: uapi: align if_link.h Lorenzo Bianconi
@ 2022-12-19 15:41 ` Lorenzo Bianconi
  2022-12-19 20:03   ` sdf
  2022-12-20  1:13   ` Jakub Kicinski
  2022-12-19 15:41 ` [RFC bpf-next 3/8] drivers: net: turn on XDP features Lorenzo Bianconi
                   ` (5 subsequent siblings)
  7 siblings, 2 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2022-12-19 15:41 UTC (permalink / raw)
  To: bpf
  Cc: netdev, ast, daniel, andrii, davem, kuba, hawk, pabeni, edumazet,
	toke, memxor, alardam, saeedm, anthony.l.nguyen, gospo,
	vladimir.oltean, nbd, john, leon, simon.horman, aelior,
	christophe.jaillet, ecree.xilinx, grygorii.strashko, mst, bjorn,
	magnus.karlsson, maciej.fijalkowski, intel-wired-lan,
	lorenzo.bianconi

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

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


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [RFC bpf-next 3/8] drivers: net: turn on XDP features
  2022-12-19 15:41 [RFC bpf-next 0/8] xdp: introduce xdp-feature support Lorenzo Bianconi
  2022-12-19 15:41 ` [RFC bpf-next 1/8] tools: uapi: align if_link.h Lorenzo Bianconi
  2022-12-19 15:41 ` [RFC bpf-next 2/8] net: introduce XDP features flag Lorenzo Bianconi
@ 2022-12-19 15:41 ` Lorenzo Bianconi
  2022-12-19 15:41 ` [RFC bpf-next 4/8] xsk: add usage of XDP features flags Lorenzo Bianconi
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2022-12-19 15:41 UTC (permalink / raw)
  To: bpf
  Cc: netdev, ast, daniel, andrii, davem, kuba, hawk, pabeni, edumazet,
	toke, memxor, alardam, saeedm, anthony.l.nguyen, gospo,
	vladimir.oltean, nbd, john, leon, simon.horman, aelior,
	christophe.jaillet, ecree.xilinx, grygorii.strashko, mst, bjorn,
	magnus.karlsson, maciej.fijalkowski, intel-wired-lan,
	lorenzo.bianconi

From: Marek Majtyka <alardam@gmail.com>

A summary of the flags being set for various drivers is given below.
Note that XDP_F_REDIRECT_TARGET and XDP_F_FRAG_TARGET are features
that can be turned off and on at runtime. This means that these flags
may be set and unset under RTNL lock protection by the driver. Hence,
READ_ONCE must be used by code loading the flag value.

Also, these flags are not used for synchronization against the availability
of XDP resources on a device. It is merely a hint, and hence the read
may race with the actual teardown of XDP resources on the device. This
may change in the future, e.g. operations taking a reference on the XDP
resources of the driver, and in turn inhibiting turning off this flag.
However, for now, it can only be used as a hint to check whether device
supports becoming a redirection target.

Turn 'hw-offload' feature flag on for:
 - netronome (nfp)
 - netdevsim.

Turn 'native' and 'zerocopy' features flags on for:
 - intel (i40e, ice, ixgbe, igc)
 - mellanox (mlx5).
 - stmmac

Turn 'native' features flags on for:
 - amazon (ena)
 - broadcom (bnxt)
 - freescale (dpaa, dpaa2, enetc)
 - funeth
 - intel (igb)
 - marvell (mvneta, mvpp2, octeontx2)
 - mellanox (mlx4)
 - qlogic (qede)
 - sfc
 - socionext (netsec)
 - ti (cpsw)
 - tap
 - veth
 - xen
 - virtio_net.

Turn 'basic' (tx, pass, aborted and drop) features flags on for:
 - netronome (nfp)
 - cavium (thunder)
 - hyperv.

Turn 'tx_lock' feature flag on for:
 - aquantia
 - freescale (dpaa2)
 - intel (igb)
 - marvell (mvneta, mvpp2)
 - microsoft (mana)
 - mediatek
 - qlogic (qede)
 - socionext (netsec)
 - ti (cpsw)
 - tap
 - veth
 - xen

Turn 'redirect_target' feature flag on for:
 - amanzon (ena)
 - broadcom (bnxt)
 - freescale (dpaa, dpaa2)
 - intel (i40e, ice, igb, ixgbe)
 - ti (cpsw)
 - marvell (mvneta, mvpp2)
 - sfc
 - socionext (netsec)
 - qlogic (qede)
 - mellanox (mlx5)
 - tap
 - veth
 - virtio_net
 - xen

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>
---
 drivers/net/ethernet/amazon/ena/ena_netdev.c  |  5 +++
 .../net/ethernet/aquantia/atlantic/aq_nic.c   |  3 ++
 drivers/net/ethernet/broadcom/bnxt/bnxt.c     |  2 +
 drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c |  2 +
 .../net/ethernet/cavium/thunder/nicvf_main.c  |  2 +
 .../net/ethernet/freescale/dpaa/dpaa_eth.c    |  2 +
 .../net/ethernet/freescale/dpaa2/dpaa2-eth.c  |  1 +
 .../net/ethernet/freescale/enetc/enetc_pf.c   |  3 ++
 .../ethernet/fungible/funeth/funeth_main.c    |  6 +++
 drivers/net/ethernet/intel/i40e/i40e_main.c   |  9 ++++-
 drivers/net/ethernet/intel/ice/ice_main.c     |  5 +++
 drivers/net/ethernet/intel/igb/igb_main.c     |  9 ++++-
 drivers/net/ethernet/intel/igc/igc_main.c     |  2 +
 drivers/net/ethernet/intel/igc/igc_xdp.c      |  5 +++
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c |  5 +++
 .../net/ethernet/intel/ixgbevf/ixgbevf_main.c |  1 +
 drivers/net/ethernet/marvell/mvneta.c         |  3 ++
 .../net/ethernet/marvell/mvpp2/mvpp2_main.c   |  3 ++
 .../ethernet/marvell/octeontx2/nic/otx2_pf.c  |  9 ++++-
 drivers/net/ethernet/mediatek/mtk_eth_soc.c   |  5 +++
 .../net/ethernet/mellanox/mlx4/en_netdev.c    |  2 +
 .../net/ethernet/mellanox/mlx5/core/en_main.c |  9 +++++
 drivers/net/ethernet/microsoft/mana/mana_en.c |  2 +
 .../ethernet/netronome/nfp/nfp_net_common.c   |  3 ++
 drivers/net/ethernet/qlogic/qede/qede_main.c  |  2 +
 drivers/net/ethernet/sfc/efx.c                |  2 +
 drivers/net/ethernet/sfc/siena/efx.c          |  2 +
 drivers/net/ethernet/socionext/netsec.c       |  2 +
 .../net/ethernet/stmicro/stmmac/stmmac_main.c |  1 +
 drivers/net/ethernet/ti/cpsw.c                |  2 +
 drivers/net/ethernet/ti/cpsw_new.c            |  2 +
 drivers/net/hyperv/netvsc_drv.c               |  2 +
 drivers/net/netdevsim/netdev.c                |  1 +
 drivers/net/tun.c                             |  3 ++
 drivers/net/veth.c                            |  4 ++
 drivers/net/virtio_net.c                      |  5 +++
 drivers/net/xen-netfront.c                    |  1 +
 include/net/xdp.h                             | 39 +++++++++++++++++++
 38 files changed, 161 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c
index a95529a69cbb..679d75b69870 100644
--- a/drivers/net/ethernet/amazon/ena/ena_netdev.c
+++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c
@@ -589,7 +589,10 @@ static int ena_xdp_set(struct net_device *netdev, struct netdev_bpf *bpf)
 				if (rc)
 					return rc;
 			}
+			__xdp_features_set_redirect_target(&netdev->xdp_features,
+							   XDP_F_REDIRECT_TARGET);
 		} else if (old_bpf_prog) {
+			xdp_features_clear_redirect_target(&netdev->xdp_features);
 			rc = ena_destroy_and_free_all_xdp_queues(adapter);
 			if (rc)
 				return rc;
@@ -4066,6 +4069,8 @@ static void ena_set_conf_feat_params(struct ena_adapter *adapter,
 	/* Set offload features */
 	ena_set_dev_offloads(feat, netdev);
 
+	netdev->xdp_features = XDP_F_FULL | XDP_F_TX_LOCK;
+
 	adapter->max_mtu = feat->dev_attr.max_mtu;
 	netdev->max_mtu = adapter->max_mtu;
 	netdev->min_mtu = ENA_MIN_MTU;
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
index 06508eebb585..db4cf1c977d7 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
@@ -384,6 +384,9 @@ void aq_nic_ndev_init(struct aq_nic_s *self)
 	self->ndev->mtu = aq_nic_cfg->mtu - ETH_HLEN;
 	self->ndev->max_mtu = aq_hw_caps->mtu - ETH_FCS_LEN - ETH_HLEN;
 
+	self->ndev->xdp_features = XDP_F_FULL | XDP_F_TX_LOCK |
+				   XDP_F_REDIRECT_TARGET | XDP_F_FRAG_RX |
+				   XDP_F_FRAG_TARGET;
 }
 
 void aq_nic_set_tx_ring(struct aq_nic_s *self, unsigned int idx,
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index 4c7d07c684c4..2c02833b5bdf 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -13681,6 +13681,8 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	netif_set_tso_max_size(dev, GSO_MAX_SIZE);
 
+	dev->xdp_features = XDP_F_FULL | XDP_F_FRAG_RX;
+
 #ifdef CONFIG_BNXT_SRIOV
 	init_waitqueue_head(&bp->sriov_cfg_wait);
 #endif
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
index c3065ec0a479..3c1b1ee7a37b 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
@@ -424,9 +424,11 @@ static int bnxt_xdp_set(struct bnxt *bp, struct bpf_prog *prog)
 
 	if (prog) {
 		bnxt_set_rx_skb_mode(bp, true);
+		xdp_features_set_redirect_target(&dev->xdp_features);
 	} else {
 		int rx, tx;
 
+		xdp_features_clear_redirect_target(&dev->xdp_features);
 		bnxt_set_rx_skb_mode(bp, false);
 		bnxt_get_max_rings(bp, &rx, &tx, true);
 		if (rx > 1) {
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
index f2f95493ec89..067bdd20aec8 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
@@ -2218,6 +2218,8 @@ static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	netdev->netdev_ops = &nicvf_netdev_ops;
 	netdev->watchdog_timeo = NICVF_TX_TIMEOUT;
 
+	netdev->xdp_features = XDP_F_BASIC;
+
 	/* MTU range: 64 - 9200 */
 	netdev->min_mtu = NIC_HW_MIN_FRS;
 	netdev->max_mtu = NIC_HW_MAX_FRS;
diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
index 3f8032947d86..24faa37a9a04 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
@@ -244,6 +244,8 @@ static int dpaa_netdev_init(struct net_device *net_dev,
 	net_dev->features |= net_dev->hw_features;
 	net_dev->vlan_features = net_dev->features;
 
+	net_dev->xdp_features = XDP_F_FULL | XDP_F_REDIRECT_TARGET;
+
 	if (is_valid_ether_addr(mac_addr)) {
 		memcpy(net_dev->perm_addr, mac_addr, net_dev->addr_len);
 		eth_hw_addr_set(net_dev, mac_addr);
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
index 0c35abb7d065..99eb7bbb8ca1 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
@@ -4593,6 +4593,7 @@ static int dpaa2_eth_netdev_init(struct net_device *net_dev)
 			    NETIF_F_LLTX | NETIF_F_HW_TC | NETIF_F_TSO;
 	net_dev->gso_max_segs = DPAA2_ETH_ENQUEUE_MAX_FDS;
 	net_dev->hw_features = net_dev->features;
+	net_dev->xdp_features = XDP_F_FULL_ZC | XDP_F_TX_LOCK | XDP_F_REDIRECT_TARGET;
 
 	if (priv->dpni_attrs.vlan_filter_entries)
 		net_dev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index 9f6c4f5c0a6c..e83062e780e5 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -825,6 +825,9 @@ static void enetc_pf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
 		ndev->hw_features |= NETIF_F_RXHASH;
 
 	ndev->priv_flags |= IFF_UNICAST_FLT;
+	ndev->xdp_features = XDP_F_FULL | XDP_F_TX_LOCK |
+			     XDP_F_REDIRECT_TARGET | XDP_F_FRAG_RX |
+			     XDP_F_FRAG_TARGET;
 
 	if (si->hw_features & ENETC_SI_F_PSFP && !enetc_psfp_enable(priv)) {
 		priv->active_offloads |= ENETC_F_QCI;
diff --git a/drivers/net/ethernet/fungible/funeth/funeth_main.c b/drivers/net/ethernet/fungible/funeth/funeth_main.c
index b4cce30e526a..1ba7e51cce8d 100644
--- a/drivers/net/ethernet/fungible/funeth/funeth_main.c
+++ b/drivers/net/ethernet/fungible/funeth/funeth_main.c
@@ -1160,6 +1160,11 @@ static int fun_xdp_setup(struct net_device *dev, struct netdev_bpf *xdp)
 			WRITE_ONCE(rxqs[i]->xdp_prog, prog);
 	}
 
+	if (prog)
+		xdp_features_set_redirect_target(&dev->xdp_features);
+	else
+		xdp_features_clear_redirect_target(&dev->xdp_features);
+
 	dev->max_mtu = prog ? XDP_MAX_MTU : FUN_MAX_MTU;
 	old_prog = xchg(&fp->xdp_prog, prog);
 	if (old_prog)
@@ -1765,6 +1770,7 @@ static int fun_create_netdev(struct fun_ethdev *ed, unsigned int portid)
 	netdev->vlan_features = netdev->features & VLAN_FEAT;
 	netdev->mpls_features = netdev->vlan_features;
 	netdev->hw_enc_features = netdev->hw_features;
+	netdev->xdp_features = XDP_F_FULL;
 
 	netdev->min_mtu = ETH_MIN_MTU;
 	netdev->max_mtu = FUN_MAX_MTU;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 94feea3b2599..e71a53677f06 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -13339,9 +13339,11 @@ static int i40e_xdp_setup(struct i40e_vsi *vsi, struct bpf_prog *prog,
 	old_prog = xchg(&vsi->xdp_prog, prog);
 
 	if (need_reset) {
-		if (!prog)
+		if (!prog) {
+			xdp_features_clear_redirect_target(&vsi->netdev->xdp_features);
 			/* Wait until ndo_xsk_wakeup completes. */
 			synchronize_rcu();
+		}
 		i40e_reset_and_rebuild(pf, true, true);
 	}
 
@@ -13362,11 +13364,13 @@ static int i40e_xdp_setup(struct i40e_vsi *vsi, struct bpf_prog *prog,
 	/* Kick start the NAPI context if there is an AF_XDP socket open
 	 * on that queue id. This so that receiving will start.
 	 */
-	if (need_reset && prog)
+	if (need_reset && prog) {
 		for (i = 0; i < vsi->num_queue_pairs; i++)
 			if (vsi->xdp_rings[i]->xsk_pool)
 				(void)i40e_xsk_wakeup(vsi->netdev, i,
 						      XDP_WAKEUP_RX);
+		xdp_features_set_redirect_target(&vsi->netdev->xdp_features);
+	}
 
 	return 0;
 }
@@ -13783,6 +13787,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
 	netdev->hw_enc_features |= NETIF_F_TSO_MANGLEID;
 
 	netdev->features &= ~NETIF_F_HW_TC;
+	netdev->xdp_features = XDP_F_FULL_ZC;
 
 	if (vsi->type == I40E_VSI_MAIN) {
 		SET_NETDEV_DEV(netdev, &pf->pdev->dev);
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index a9a7f8b52140..07f1d0fd0571 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -22,6 +22,7 @@
 #include "ice_eswitch.h"
 #include "ice_tc_lib.h"
 #include "ice_vsi_vlan_ops.h"
+#include <net/xdp_sock_drv.h>
 
 #define DRV_SUMMARY	"Intel(R) Ethernet Connection E800 Series Linux Driver"
 static const char ice_driver_string[] = DRV_SUMMARY;
@@ -2899,11 +2900,14 @@ ice_xdp_setup_prog(struct ice_vsi *vsi, struct bpf_prog *prog,
 			if (xdp_ring_err)
 				NL_SET_ERR_MSG_MOD(extack, "Setting up XDP Tx resources failed");
 		}
+		__xdp_features_set_redirect_target(&vsi->netdev->xdp_features,
+						   XDP_F_REDIRECT_TARGET);
 		/* reallocate Rx queues that are used for zero-copy */
 		xdp_ring_err = ice_realloc_zc_buf(vsi, true);
 		if (xdp_ring_err)
 			NL_SET_ERR_MSG_MOD(extack, "Setting up XDP Rx resources failed");
 	} else if (ice_is_xdp_ena_vsi(vsi) && !prog) {
+		xdp_features_clear_redirect_target(&vsi->netdev->xdp_features);
 		xdp_ring_err = ice_destroy_xdp_rings(vsi);
 		if (xdp_ring_err)
 			NL_SET_ERR_MSG_MOD(extack, "Freeing XDP Tx resources failed");
@@ -3446,6 +3450,7 @@ static int ice_cfg_netdev(struct ice_vsi *vsi)
 	np->vsi = vsi;
 
 	ice_set_netdev_features(netdev);
+	netdev->xdp_features = XDP_F_FULL_ZC;
 
 	ice_set_ops(netdev);
 
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index 97290fc0fddd..2834b6e9f604 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -2871,8 +2871,14 @@ static int igb_xdp_setup(struct net_device *dev, struct netdev_bpf *bpf)
 		bpf_prog_put(old_prog);
 
 	/* bpf is just replaced, RXQ and MTU are already setup */
-	if (!need_reset)
+	if (!need_reset) {
 		return 0;
+	} else {
+		if (prog)
+			xdp_features_set_redirect_target(&dev->xdp_features);
+		else
+			xdp_features_clear_redirect_target(&dev->xdp_features);
+	}
 
 	if (running)
 		igb_open(dev);
@@ -3317,6 +3323,7 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	netdev->priv_flags |= IFF_SUPP_NOFCS;
 
 	netdev->priv_flags |= IFF_UNICAST_FLT;
+	netdev->xdp_features = XDP_F_FULL | XDP_F_TX_LOCK;
 
 	/* MTU range: 68 - 9216 */
 	netdev->min_mtu = ETH_MIN_MTU;
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
index 1586e1e435c6..64917a272cf4 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -6379,6 +6379,8 @@ static int igc_probe(struct pci_dev *pdev,
 	netdev->mpls_features |= NETIF_F_HW_CSUM;
 	netdev->hw_enc_features |= netdev->vlan_features;
 
+	netdev->xdp_features = XDP_F_FULL_ZC;
+
 	/* MTU range: 68 - 9216 */
 	netdev->min_mtu = ETH_MIN_MTU;
 	netdev->max_mtu = MAX_STD_JUMBO_FRAME_SIZE;
diff --git a/drivers/net/ethernet/intel/igc/igc_xdp.c b/drivers/net/ethernet/intel/igc/igc_xdp.c
index aeeb34e64610..570170a29e3a 100644
--- a/drivers/net/ethernet/intel/igc/igc_xdp.c
+++ b/drivers/net/ethernet/intel/igc/igc_xdp.c
@@ -29,6 +29,11 @@ int igc_xdp_set_prog(struct igc_adapter *adapter, struct bpf_prog *prog,
 	if (old_prog)
 		bpf_prog_put(old_prog);
 
+	if (prog)
+		xdp_features_set_redirect_target(&dev->xdp_features);
+	else
+		xdp_features_clear_redirect_target(&dev->xdp_features);
+
 	if (if_running)
 		igc_open(dev);
 
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index ab8370c413f3..4550b80f4ebd 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -10301,6 +10301,8 @@ static int ixgbe_xdp_setup(struct net_device *dev, struct bpf_prog *prog)
 			rcu_assign_pointer(adapter->xdp_prog, old_prog);
 			return -EINVAL;
 		}
+		if (!prog)
+			xdp_features_clear_redirect_target(&dev->xdp_features);
 	} else {
 		for (i = 0; i < adapter->num_rx_queues; i++)
 			(void)xchg(&adapter->rx_ring[i]->xdp_prog,
@@ -10320,6 +10322,7 @@ static int ixgbe_xdp_setup(struct net_device *dev, struct bpf_prog *prog)
 			if (adapter->xdp_ring[i]->xsk_pool)
 				(void)ixgbe_xsk_wakeup(adapter->netdev, i,
 						       XDP_WAKEUP_RX);
+		xdp_features_set_redirect_target(&dev->xdp_features);
 	}
 
 	return 0;
@@ -11017,6 +11020,8 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	netdev->priv_flags |= IFF_UNICAST_FLT;
 	netdev->priv_flags |= IFF_SUPP_NOFCS;
 
+	netdev->xdp_features = XDP_F_FULL_ZC;
+
 	/* MTU range: 68 - 9710 */
 	netdev->min_mtu = ETH_MIN_MTU;
 	netdev->max_mtu = IXGBE_MAX_JUMBO_FRAME_SIZE - (ETH_HLEN + ETH_FCS_LEN);
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
index ea0a230c1153..8bc32ab2c2dd 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -4634,6 +4634,7 @@ static int ixgbevf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 			    NETIF_F_HW_VLAN_CTAG_TX;
 
 	netdev->priv_flags |= IFF_UNICAST_FLT;
+	netdev->xdp_features = XDP_F_BASIC;
 
 	/* MTU range: 68 - 1504 or 9710 */
 	netdev->min_mtu = ETH_MIN_MTU;
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index f8925cac61e4..e3928a534308 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -5612,6 +5612,9 @@ static int mvneta_probe(struct platform_device *pdev)
 			NETIF_F_TSO | NETIF_F_RXCSUM;
 	dev->hw_features |= dev->features;
 	dev->vlan_features |= dev->features;
+	dev->xdp_features = XDP_F_FULL | XDP_F_TX_LOCK |
+			    XDP_F_REDIRECT_TARGET | XDP_F_FRAG_RX |
+			    XDP_F_FRAG_TARGET;
 	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
 	netif_set_tso_max_segs(dev, MVNETA_MAX_TSO_SEGS);
 
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
index 4da45c5abba5..6bfe28aafb4f 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
@@ -6866,6 +6866,9 @@ static int mvpp2_port_probe(struct platform_device *pdev,
 
 	dev->vlan_features |= features;
 	netif_set_tso_max_segs(dev, MVPP2_MAX_TSO_SEGS);
+
+	dev->xdp_features = XDP_F_FULL | XDP_F_TX_LOCK | XDP_F_REDIRECT_TARGET;
+
 	dev->priv_flags |= IFF_UNICAST_FLT;
 
 	/* MTU range: 68 - 9704 */
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
index c1ea60bc2630..3c7fc7bf8339 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
@@ -2512,10 +2512,14 @@ static int otx2_xdp_setup(struct otx2_nic *pf, struct bpf_prog *prog)
 	/* Network stack and XDP shared same rx queues.
 	 * Use separate tx queues for XDP and network stack.
 	 */
-	if (pf->xdp_prog)
+	if (pf->xdp_prog) {
 		pf->hw.xdp_queues = pf->hw.rx_queues;
-	else
+		__xdp_features_set_redirect_target(&dev->xdp_features,
+						   XDP_F_REDIRECT_TARGET);
+	} else {
 		pf->hw.xdp_queues = 0;
+		xdp_features_clear_redirect_target(&dev->xdp_features);
+	}
 
 	pf->hw.tot_tx_queues += pf->hw.xdp_queues;
 
@@ -2878,6 +2882,7 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	netdev->watchdog_timeo = OTX2_TX_TIMEOUT;
 
 	netdev->netdev_ops = &otx2_netdev_ops;
+	netdev->xdp_features = XDP_F_FULL;
 
 	netdev->min_mtu = OTX2_MIN_MTU;
 	netdev->max_mtu = otx2_get_max_mtu(pf);
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index e3de9a53b2d9..17831770b494 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -4186,6 +4186,11 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
 		register_netdevice_notifier(&mac->device_notifier);
 	}
 
+	if (mtk_page_pool_enabled(eth))
+		eth->netdev[id]->xdp_features = XDP_F_FULL | XDP_F_TX_LOCK |
+						XDP_F_REDIRECT_TARGET |
+						XDP_F_FRAG_TARGET;
+
 	return 0;
 
 free_netdev:
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index 8800d3f1f55c..3c7b011de300 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -3410,6 +3410,8 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
 		priv->rss_hash_fn = ETH_RSS_HASH_TOP;
 	}
 
+	dev->xdp_features = XDP_F_FULL;
+
 	/* MTU range: 68 - hw-specific max */
 	dev->min_mtu = ETH_MIN_MTU;
 	dev->max_mtu = priv->max_mtu;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index 8d36e2de53a9..2a406dddae84 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -4776,6 +4776,13 @@ static int mlx5e_xdp_set(struct net_device *netdev, struct bpf_prog *prog)
 	if (old_prog)
 		bpf_prog_put(old_prog);
 
+	if (reset) {
+		if (prog)
+			xdp_features_set_redirect_target(&netdev->xdp_features);
+		else
+			xdp_features_clear_redirect_target(&netdev->xdp_features);
+	}
+
 	if (!test_bit(MLX5E_STATE_OPENED, &priv->state) || reset)
 		goto unlock;
 
@@ -5170,6 +5177,8 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
 	netdev->features         |= NETIF_F_HIGHDMA;
 	netdev->features         |= NETIF_F_HW_VLAN_STAG_FILTER;
 
+	netdev->xdp_features = XDP_F_FULL_ZC | XDP_F_FRAG_RX;
+
 	netdev->priv_flags       |= IFF_UNICAST_FLT;
 
 	netif_set_tso_max_size(netdev, GSO_MAX_SIZE);
diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
index 2f6a048dee90..61955359931b 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
@@ -2160,6 +2160,8 @@ static int mana_probe_port(struct mana_context *ac, int port_idx,
 	ndev->hw_features |= NETIF_F_RXHASH;
 	ndev->features = ndev->hw_features;
 	ndev->vlan_features = 0;
+	ndev->xdp_features = XDP_F_FULL | XDP_F_TX_LOCK |
+			     XDP_F_REDIRECT_TARGET;
 
 	err = register_netdev(ndev);
 	if (err) {
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index 2314cf55e821..f704b4ad5702 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -2482,10 +2482,13 @@ static void nfp_net_netdev_init(struct nfp_net *nn)
 	netdev->features &= ~NETIF_F_HW_VLAN_STAG_RX;
 	nn->dp.ctrl &= ~NFP_NET_CFG_CTRL_RXQINQ;
 
+	nn->dp.netdev->xdp_features = XDP_F_BASIC | XDP_F_HW_OFFLOAD;
+
 	/* Finalise the netdev setup */
 	switch (nn->dp.ops->version) {
 	case NFP_NFD_VER_NFD3:
 		netdev->netdev_ops = &nfp_nfd3_netdev_ops;
+		nn->dp.netdev->xdp_features |= XDP_F_SOCK_ZEROCOPY;
 		break;
 	case NFP_NFD_VER_NFDK:
 		netdev->netdev_ops = &nfp_nfdk_netdev_ops;
diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c
index 953f304b8588..f090ce57befd 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_main.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_main.c
@@ -892,6 +892,8 @@ static void qede_init_ndev(struct qede_dev *edev)
 
 	ndev->hw_features = hw_features;
 
+	ndev->xdp_features = XDP_F_FULL | XDP_F_TX_LOCK | XDP_F_REDIRECT_TARGET;
+
 	/* MTU range: 46 - 9600 */
 	ndev->min_mtu = ETH_ZLEN - ETH_HLEN;
 	ndev->max_mtu = QEDE_MAX_JUMBO_PACKET_SIZE;
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index 0556542d7a6b..bc624c2ea016 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -1078,6 +1078,8 @@ static int efx_pci_probe(struct pci_dev *pci_dev,
 
 	pci_info(pci_dev, "Solarflare NIC detected\n");
 
+	efx->net_dev->xdp_features = XDP_F_FULL | XDP_F_REDIRECT_TARGET;
+
 	if (!efx->type->is_vf)
 		efx_probe_vpd_strings(efx);
 
diff --git a/drivers/net/ethernet/sfc/siena/efx.c b/drivers/net/ethernet/sfc/siena/efx.c
index 60e5b7c8ccf9..0872e075ea3a 100644
--- a/drivers/net/ethernet/sfc/siena/efx.c
+++ b/drivers/net/ethernet/sfc/siena/efx.c
@@ -1048,6 +1048,8 @@ static int efx_pci_probe(struct pci_dev *pci_dev,
 
 	pci_info(pci_dev, "Solarflare NIC detected\n");
 
+	efx->net_dev->xdp_features = XDP_F_FULL | XDP_F_REDIRECT_TARGET;
+
 	if (!efx->type->is_vf)
 		efx_probe_vpd_strings(efx);
 
diff --git a/drivers/net/ethernet/socionext/netsec.c b/drivers/net/ethernet/socionext/netsec.c
index 9b46579b5a10..e4586c49f5b8 100644
--- a/drivers/net/ethernet/socionext/netsec.c
+++ b/drivers/net/ethernet/socionext/netsec.c
@@ -2104,6 +2104,8 @@ static int netsec_probe(struct platform_device *pdev)
 				NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
 	ndev->hw_features = ndev->features;
 
+	ndev->xdp_features = XDP_F_FULL | XDP_F_TX_LOCK | XDP_F_REDIRECT_TARGET;
+
 	priv->rx_cksum_offload_flag = true;
 
 	ret = netsec_register_mdio(priv, phy_addr);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index ec64b65dee34..4b759cb1a9ff 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -7144,6 +7144,7 @@ int stmmac_dvr_probe(struct device *device,
 
 	ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
 			    NETIF_F_RXCSUM;
+	ndev->xdp_features = XDP_F_FULL | XDP_F_TX_LOCK | XDP_F_REDIRECT_TARGET;
 
 	ret = stmmac_tc_init(priv, priv);
 	if (!ret) {
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 13c9c2d6b79b..6e76345a0d46 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -1458,6 +1458,7 @@ static int cpsw_probe_dual_emac(struct cpsw_priv *priv)
 	priv_sl2->emac_port = 1;
 	cpsw->slaves[1].ndev = ndev;
 	ndev->features |= NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_CTAG_RX;
+	ndev->xdp_features = XDP_F_FULL | XDP_F_TX_LOCK | XDP_F_REDIRECT_TARGET;
 
 	ndev->netdev_ops = &cpsw_netdev_ops;
 	ndev->ethtool_ops = &cpsw_ethtool_ops;
@@ -1635,6 +1636,7 @@ static int cpsw_probe(struct platform_device *pdev)
 	cpsw->slaves[0].ndev = ndev;
 
 	ndev->features |= NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_CTAG_RX;
+	ndev->xdp_features = XDP_F_FULL | XDP_F_TX_LOCK | XDP_F_REDIRECT_TARGET;
 
 	ndev->netdev_ops = &cpsw_netdev_ops;
 	ndev->ethtool_ops = &cpsw_ethtool_ops;
diff --git a/drivers/net/ethernet/ti/cpsw_new.c b/drivers/net/ethernet/ti/cpsw_new.c
index 83596ec0c7cb..a8a20840a05a 100644
--- a/drivers/net/ethernet/ti/cpsw_new.c
+++ b/drivers/net/ethernet/ti/cpsw_new.c
@@ -1405,6 +1405,8 @@ static int cpsw_create_ports(struct cpsw_common *cpsw)
 		ndev->features |= NETIF_F_HW_VLAN_CTAG_FILTER |
 				  NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_NETNS_LOCAL | NETIF_F_HW_TC;
 
+		ndev->xdp_features = XDP_F_FULL | XDP_F_TX_LOCK | XDP_F_REDIRECT_TARGET;
+
 		ndev->netdev_ops = &cpsw_netdev_ops;
 		ndev->ethtool_ops = &cpsw_ethtool_ops;
 		SET_NETDEV_DEV(ndev, dev);
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index f9b219e6cd58..4bb09de440b2 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -2559,6 +2559,8 @@ static int netvsc_probe(struct hv_device *dev,
 
 	netdev_lockdep_set_classes(net);
 
+	net->xdp_features = XDP_F_FULL;
+
 	/* MTU range: 68 - 1500 or 65521 */
 	net->min_mtu = NETVSC_MTU_MIN;
 	if (nvdev->nvsp_version >= NVSP_PROTOCOL_VERSION_2)
diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c
index 6db6a75ff9b9..20962dd54bac 100644
--- a/drivers/net/netdevsim/netdev.c
+++ b/drivers/net/netdevsim/netdev.c
@@ -286,6 +286,7 @@ static void nsim_setup(struct net_device *dev)
 			 NETIF_F_TSO;
 	dev->hw_features |= NETIF_F_HW_TC;
 	dev->max_mtu = ETH_MAX_MTU;
+	dev->xdp_features = XDP_F_HW_OFFLOAD;
 }
 
 static int nsim_init_netdevsim(struct netdevsim *ns)
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index a7d17c680f4a..b35210a6371b 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -1401,6 +1401,9 @@ static void tun_net_initialize(struct net_device *dev)
 
 		eth_hw_addr_random(dev);
 
+		/* Currently tun does not support XDP, only tap does. */
+		dev->xdp_features = XDP_F_FULL | XDP_F_TX_LOCK | XDP_F_REDIRECT_TARGET;
+
 		break;
 	}
 
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index ac7c0653695f..e2518ed81dc5 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -1648,6 +1648,10 @@ static void veth_setup(struct net_device *dev)
 	dev->hw_enc_features = VETH_FEATURES;
 	dev->mpls_features = NETIF_F_HW_CSUM | NETIF_F_GSO_SOFTWARE;
 	netif_set_tso_max_size(dev, GSO_MAX_SIZE);
+
+	dev->xdp_features = XDP_F_FULL | XDP_F_TX_LOCK |
+			    XDP_F_REDIRECT_TARGET | XDP_F_FRAG_RX |
+			    XDP_F_FRAG_TARGET;
 }
 
 /*
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 7723b2a49d8e..bbd0e306c098 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -3155,7 +3155,11 @@ static int virtnet_xdp_set(struct net_device *dev, struct bpf_prog *prog,
 			if (i == 0 && !old_prog)
 				virtnet_clear_guest_offloads(vi);
 		}
+		if (!old_prog)
+			__xdp_features_set_redirect_target(&dev->xdp_features,
+							   XDP_F_REDIRECT_TARGET);
 	} else {
+		xdp_features_clear_redirect_target(&dev->xdp_features);
 		vi->xdp_enabled = false;
 	}
 
@@ -3785,6 +3789,7 @@ static int virtnet_probe(struct virtio_device *vdev)
 		dev->hw_features |= NETIF_F_GRO_HW;
 
 	dev->vlan_features = dev->features;
+	dev->xdp_features = XDP_F_FULL;
 
 	/* MTU range: 68 - 65535 */
 	dev->min_mtu = MIN_MTU;
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index 14aec417fa06..65820489bb9a 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -1741,6 +1741,7 @@ static struct net_device *xennet_create_dev(struct xenbus_device *dev)
          * negotiate with the backend regarding supported features.
          */
 	netdev->features |= netdev->hw_features;
+	netdev->xdp_features = XDP_F_FULL | XDP_F_TX_LOCK | XDP_F_REDIRECT_TARGET;
 
 	netdev->ethtool_ops = &xennet_ethtool_ops;
 	netdev->min_mtu = ETH_MIN_MTU;
diff --git a/include/net/xdp.h b/include/net/xdp.h
index 55dbc68bfffc..68b322735b5c 100644
--- a/include/net/xdp.h
+++ b/include/net/xdp.h
@@ -7,6 +7,7 @@
 #define __LINUX_NET_XDP_H__
 
 #include <linux/skbuff.h> /* skb_shared_info */
+#include <linux/xdp_features.h>
 
 /**
  * DOC: XDP RX-queue information
@@ -407,6 +408,44 @@ struct netdev_bpf;
 void xdp_attachment_setup(struct xdp_attachment_info *info,
 			  struct netdev_bpf *bpf);
 
+#if defined(CONFIG_NET) && defined(CONFIG_BPF_SYSCALL)
+
+static inline void
+__xdp_features_set_redirect_target(xdp_features_t *xdp_features, u32 flags)
+{
+	flags &= (XDP_F_REDIRECT_TARGET | XDP_F_FRAG_TARGET);
+	WRITE_ONCE(*xdp_features, *xdp_features | flags);
+}
+
+static inline void
+xdp_features_clear_redirect_target(xdp_features_t *xdp_features)
+{
+	WRITE_ONCE(*xdp_features,
+		   *xdp_features & ~(XDP_F_REDIRECT_TARGET | XDP_F_FRAG_TARGET));
+}
+
+#else
+
+static inline void
+__xdp_features_set_redirect_target(xdp_features_t *xdp_features, u32 flags)
+{
+}
+
+static inline void
+xdp_features_clear_redirect_target(xdp_features_t *xdp_features)
+{
+}
+
+#endif
+
+static inline void
+xdp_features_set_redirect_target(xdp_features_t *xdp_features)
+{
+	__xdp_features_set_redirect_target(xdp_features,
+					   XDP_F_REDIRECT_TARGET |
+					   XDP_F_FRAG_TARGET);
+}
+
 #define DEV_MAP_BULK_SIZE XDP_BULK_QUEUE_SIZE
 
 #endif /* __LINUX_NET_XDP_H__ */
-- 
2.38.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [RFC bpf-next 4/8] xsk: add usage of XDP features flags
  2022-12-19 15:41 [RFC bpf-next 0/8] xdp: introduce xdp-feature support Lorenzo Bianconi
                   ` (2 preceding siblings ...)
  2022-12-19 15:41 ` [RFC bpf-next 3/8] drivers: net: turn on XDP features Lorenzo Bianconi
@ 2022-12-19 15:41 ` Lorenzo Bianconi
  2022-12-19 15:41 ` [RFC bpf-next 5/8] xsk: add check for full support of XDP in bind Lorenzo Bianconi
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2022-12-19 15:41 UTC (permalink / raw)
  To: bpf
  Cc: netdev, ast, daniel, andrii, davem, kuba, hawk, pabeni, edumazet,
	toke, memxor, alardam, saeedm, anthony.l.nguyen, gospo,
	vladimir.oltean, nbd, john, leon, simon.horman, aelior,
	christophe.jaillet, ecree.xilinx, grygorii.strashko, mst, bjorn,
	magnus.karlsson, maciej.fijalkowski, intel-wired-lan,
	lorenzo.bianconi

From: Marek Majtyka <alardam@gmail.com>

Change necessary condition check for XSK from ndo functions to
xdp features flags.

Signed-off-by: Marek Majtyka <alardam@gmail.com>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 net/xdp/xsk_buff_pool.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/net/xdp/xsk_buff_pool.c b/net/xdp/xsk_buff_pool.c
index ed6c71826d31..7afd12dd69cc 100644
--- a/net/xdp/xsk_buff_pool.c
+++ b/net/xdp/xsk_buff_pool.c
@@ -178,8 +178,7 @@ int xp_assign_dev(struct xsk_buff_pool *pool,
 		/* For copy-mode, we are done. */
 		return 0;
 
-	if (!netdev->netdev_ops->ndo_bpf ||
-	    !netdev->netdev_ops->ndo_xsk_wakeup) {
+	if ((netdev->xdp_features & XDP_F_FULL_ZC) != XDP_F_FULL_ZC) {
 		err = -EOPNOTSUPP;
 		goto err_unreg_pool;
 	}
-- 
2.38.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [RFC bpf-next 5/8] xsk: add check for full support of XDP in bind
  2022-12-19 15:41 [RFC bpf-next 0/8] xdp: introduce xdp-feature support Lorenzo Bianconi
                   ` (3 preceding siblings ...)
  2022-12-19 15:41 ` [RFC bpf-next 4/8] xsk: add usage of XDP features flags Lorenzo Bianconi
@ 2022-12-19 15:41 ` Lorenzo Bianconi
  2022-12-19 15:41 ` [RFC bpf-next 6/8] libbpf: add API to get XDP/XSK supported features Lorenzo Bianconi
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2022-12-19 15:41 UTC (permalink / raw)
  To: bpf
  Cc: netdev, ast, daniel, andrii, davem, kuba, hawk, pabeni, edumazet,
	toke, memxor, alardam, saeedm, anthony.l.nguyen, gospo,
	vladimir.oltean, nbd, john, leon, simon.horman, aelior,
	christophe.jaillet, ecree.xilinx, grygorii.strashko, mst, bjorn,
	magnus.karlsson, maciej.fijalkowski, intel-wired-lan,
	lorenzo.bianconi

From: Marek Majtyka <alardam@gmail.com>

Add check for full support of XDP in AF_XDP socket bind.

To be able to use an AF_XDP socket with zero-copy, there needs to be
support for both XDP_REDIRECT in the driver (XDP native mode) and the
driver needs to support zero-copy. The problem is that there are drivers
out there that only support XDP partially, so it is possible to
successfully load the XDP program in native mode, but it will still not
be able to support zero-copy as it does not have XDP_REDIRECT support.
We can now alleviate this problem by using the new XDP netdev capability
that signifies if full XDP support is indeed present. This check can be
triggered by a new bind flag called XDP_CHECK_NATIVE_MODE.

To simplify usage, this check is triggered automatically from inside
libbpf library via turning on the new XDP_CHECK_NATIVE_MODE flag if and
only if the driver mode is selected for the socket. As a result, the
xsk_bind function decides if the native mode for a given interface makes
sense or not using xdp netdev feature flags. Eventually the xsk socket
is bound or an error is returned. Apart from this change and to catch
all invalid inputs in a single place, an additional check is set to
forbid skb mode and zero copy settings at the same time as that
combination makes no sense.

Signed-off-by: Marek Majtyka <alardam@gmail.com>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 include/uapi/linux/if_xdp.h       |  1 +
 net/xdp/xsk.c                     |  4 ++--
 net/xdp/xsk_buff_pool.c           | 17 ++++++++++++++++-
 tools/include/uapi/linux/if_xdp.h |  1 +
 tools/testing/selftests/bpf/xsk.c |  3 +++
 5 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/include/uapi/linux/if_xdp.h b/include/uapi/linux/if_xdp.h
index a78a8096f4ce..8f47754dacce 100644
--- a/include/uapi/linux/if_xdp.h
+++ b/include/uapi/linux/if_xdp.h
@@ -25,6 +25,7 @@
  * application.
  */
 #define XDP_USE_NEED_WAKEUP (1 << 3)
+#define XDP_CHECK_NATIVE_MODE (1 << 4)
 
 /* Flags for xsk_umem_config flags */
 #define XDP_UMEM_UNALIGNED_CHUNK_FLAG (1 << 0)
diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c
index 9f0561b67c12..76e9a9e99559 100644
--- a/net/xdp/xsk.c
+++ b/net/xdp/xsk.c
@@ -889,7 +889,7 @@ static int xsk_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
 
 	flags = sxdp->sxdp_flags;
 	if (flags & ~(XDP_SHARED_UMEM | XDP_COPY | XDP_ZEROCOPY |
-		      XDP_USE_NEED_WAKEUP))
+		      XDP_USE_NEED_WAKEUP | XDP_CHECK_NATIVE_MODE))
 		return -EINVAL;
 
 	rtnl_lock();
@@ -917,7 +917,7 @@ static int xsk_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
 		struct socket *sock;
 
 		if ((flags & XDP_COPY) || (flags & XDP_ZEROCOPY) ||
-		    (flags & XDP_USE_NEED_WAKEUP)) {
+		    (flags & XDP_USE_NEED_WAKEUP) || (flags & XDP_CHECK_NATIVE_MODE)) {
 			/* Cannot specify flags for shared sockets. */
 			err = -EINVAL;
 			goto out_unlock;
diff --git a/net/xdp/xsk_buff_pool.c b/net/xdp/xsk_buff_pool.c
index 7afd12dd69cc..02f569893c02 100644
--- a/net/xdp/xsk_buff_pool.c
+++ b/net/xdp/xsk_buff_pool.c
@@ -143,7 +143,7 @@ static void xp_disable_drv_zc(struct xsk_buff_pool *pool)
 int xp_assign_dev(struct xsk_buff_pool *pool,
 		  struct net_device *netdev, u16 queue_id, u16 flags)
 {
-	bool force_zc, force_copy;
+	bool force_zc, force_copy, force_check;
 	struct netdev_bpf bpf;
 	int err = 0;
 
@@ -151,10 +151,24 @@ int xp_assign_dev(struct xsk_buff_pool *pool,
 
 	force_zc = flags & XDP_ZEROCOPY;
 	force_copy = flags & XDP_COPY;
+	force_check = flags & XDP_CHECK_NATIVE_MODE;
+
 
 	if (force_zc && force_copy)
 		return -EINVAL;
 
+	if (!(flags & XDP_SHARED_UMEM)) {
+		if (force_check) {
+			/* forbid driver mode without full XDP support */
+			if (!(XDP_F_REDIRECT & netdev->xdp_features))
+				return -EOPNOTSUPP;
+		} else {
+			/* forbid skb mode and zero copy */
+			if (force_zc)
+				return -EINVAL;
+		}
+	}
+
 	if (xsk_get_pool_from_qid(netdev, queue_id))
 		return -EBUSY;
 
@@ -222,6 +236,7 @@ int xp_assign_dev_shared(struct xsk_buff_pool *pool, struct xdp_sock *umem_xs,
 		return -EINVAL;
 
 	flags = umem->zc ? XDP_ZEROCOPY : XDP_COPY;
+	flags |= XDP_SHARED_UMEM;
 	if (umem_xs->pool->uses_need_wakeup)
 		flags |= XDP_USE_NEED_WAKEUP;
 
diff --git a/tools/include/uapi/linux/if_xdp.h b/tools/include/uapi/linux/if_xdp.h
index a78a8096f4ce..8f47754dacce 100644
--- a/tools/include/uapi/linux/if_xdp.h
+++ b/tools/include/uapi/linux/if_xdp.h
@@ -25,6 +25,7 @@
  * application.
  */
 #define XDP_USE_NEED_WAKEUP (1 << 3)
+#define XDP_CHECK_NATIVE_MODE (1 << 4)
 
 /* Flags for xsk_umem_config flags */
 #define XDP_UMEM_UNALIGNED_CHUNK_FLAG (1 << 0)
diff --git a/tools/testing/selftests/bpf/xsk.c b/tools/testing/selftests/bpf/xsk.c
index 39d349509ba4..d6b9349000d2 100644
--- a/tools/testing/selftests/bpf/xsk.c
+++ b/tools/testing/selftests/bpf/xsk.c
@@ -18,6 +18,7 @@
 #include <linux/ethtool.h>
 #include <linux/filter.h>
 #include <linux/if_ether.h>
+#include <linux/if_link.h>
 #include <linux/if_packet.h>
 #include <linux/if_xdp.h>
 #include <linux/kernel.h>
@@ -1130,6 +1131,8 @@ int xsk_socket__create_shared(struct xsk_socket **xsk_ptr,
 		sxdp.sxdp_shared_umem_fd = umem->fd;
 	} else {
 		sxdp.sxdp_flags = xsk->config.bind_flags;
+		if (xsk->config.xdp_flags & XDP_FLAGS_DRV_MODE)
+			sxdp.sxdp_flags |= XDP_CHECK_NATIVE_MODE;
 	}
 
 	err = bind(xsk->fd, (struct sockaddr *)&sxdp, sizeof(sxdp));
-- 
2.38.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [RFC bpf-next 6/8] libbpf: add API to get XDP/XSK supported features
  2022-12-19 15:41 [RFC bpf-next 0/8] xdp: introduce xdp-feature support Lorenzo Bianconi
                   ` (4 preceding siblings ...)
  2022-12-19 15:41 ` [RFC bpf-next 5/8] xsk: add check for full support of XDP in bind Lorenzo Bianconi
@ 2022-12-19 15:41 ` Lorenzo Bianconi
  2022-12-21  0:18   ` Andrii Nakryiko
  2022-12-19 15:41 ` [RFC bpf-next 7/8] bpf: devmap: check XDP features in bpf_map_update_elem and __xdp_enqueue Lorenzo Bianconi
  2022-12-19 15:41 ` [RFC bpf-next 8/8] selftests/bpf: introduce XDP compliance test tool Lorenzo Bianconi
  7 siblings, 1 reply; 27+ messages in thread
From: Lorenzo Bianconi @ 2022-12-19 15:41 UTC (permalink / raw)
  To: bpf
  Cc: netdev, ast, daniel, andrii, davem, kuba, hawk, pabeni, edumazet,
	toke, memxor, alardam, saeedm, anthony.l.nguyen, gospo,
	vladimir.oltean, nbd, john, leon, simon.horman, aelior,
	christophe.jaillet, ecree.xilinx, grygorii.strashko, mst, bjorn,
	magnus.karlsson, maciej.fijalkowski, intel-wired-lan,
	lorenzo.bianconi

From: Kumar Kartikeya Dwivedi <memxor@gmail.com>

Add functions to get XDP/XSK supported function of netdev over route
netlink interface. These functions provide functionalities that are
going to be used in upcoming change.

The newly added bpf_xdp_query_features takes a fflags_cnt parameter,
which denotes the number of elements in the output fflags array. This
must be at least 1 and maybe greater than XDP_FEATURES_WORDS. The
function only writes to words which is min of fflags_cnt and
XDP_FEATURES_WORDS.

Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Co-developed-by: Marek Majtyka <alardam@gmail.com>
Signed-off-by: Marek Majtyka <alardam@gmail.com>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
---
 tools/lib/bpf/libbpf.h   |  1 +
 tools/lib/bpf/libbpf.map |  1 +
 tools/lib/bpf/netlink.c  | 62 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 64 insertions(+)

diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index eee883f007f9..9d102eb5007e 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -967,6 +967,7 @@ LIBBPF_API int bpf_xdp_detach(int ifindex, __u32 flags,
 			      const struct bpf_xdp_attach_opts *opts);
 LIBBPF_API int bpf_xdp_query(int ifindex, int flags, struct bpf_xdp_query_opts *opts);
 LIBBPF_API int bpf_xdp_query_id(int ifindex, int flags, __u32 *prog_id);
+LIBBPF_API int bpf_xdp_query_features(int ifindex, __u32 *fflags, __u32 *fflags_cnt);
 
 /* TC related API */
 enum bpf_tc_attach_point {
diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map
index 71bf5691a689..9c2abb58fa4b 100644
--- a/tools/lib/bpf/libbpf.map
+++ b/tools/lib/bpf/libbpf.map
@@ -362,6 +362,7 @@ LIBBPF_1.0.0 {
 		bpf_program__set_autoattach;
 		btf__add_enum64;
 		btf__add_enum64_value;
+		bpf_xdp_query_features;
 		libbpf_bpf_attach_type_str;
 		libbpf_bpf_link_type_str;
 		libbpf_bpf_map_type_str;
diff --git a/tools/lib/bpf/netlink.c b/tools/lib/bpf/netlink.c
index 35104580870c..6fd424cde58b 100644
--- a/tools/lib/bpf/netlink.c
+++ b/tools/lib/bpf/netlink.c
@@ -9,6 +9,7 @@
 #include <linux/if_ether.h>
 #include <linux/pkt_cls.h>
 #include <linux/rtnetlink.h>
+#include <linux/xdp_features.h>
 #include <sys/socket.h>
 #include <errno.h>
 #include <time.h>
@@ -41,6 +42,12 @@ struct xdp_id_md {
 	struct xdp_link_info info;
 };
 
+struct xdp_features_md {
+	int ifindex;
+	__u32 *flags;
+	__u32 *flags_cnt;
+};
+
 static int libbpf_netlink_open(__u32 *nl_pid)
 {
 	struct sockaddr_nl sa;
@@ -357,6 +364,39 @@ static int get_xdp_info(void *cookie, void *msg, struct nlattr **tb)
 	return 0;
 }
 
+static int bpf_get_xdp_features(void *cookie, void *msg, struct nlattr **tb)
+{
+	struct nlattr *xdp_tb[IFLA_XDP_FEATURES_BITS_WORD + 1];
+	struct xdp_features_md *md = cookie;
+	struct ifinfomsg *ifinfo = msg;
+	int ret, i, words;
+
+	if (md->ifindex && md->ifindex != ifinfo->ifi_index)
+		return 0;
+
+	if (!tb[IFLA_XDP_FEATURES])
+		return 0;
+
+	words = min(XDP_FEATURES_WORDS, *md->flags_cnt);
+	for (i = 0; i < words; ++i)
+		md->flags[i] = 0;
+
+	ret = libbpf_nla_parse_nested(xdp_tb, XDP_FEATURES_WORDS,
+				      tb[IFLA_XDP_FEATURES], NULL);
+	if (ret)
+		return ret;
+
+	*md->flags_cnt = words;
+	for (i = 0; i < words; ++i) {
+		if (!xdp_tb[IFLA_XDP_FEATURES_BITS_WORD])
+			continue;
+
+		md->flags[i] = libbpf_nla_getattr_u32(xdp_tb[IFLA_XDP_FEATURES_BITS_WORD]);
+	}
+
+	return 0;
+}
+
 int bpf_xdp_query(int ifindex, int xdp_flags, struct bpf_xdp_query_opts *opts)
 {
 	struct libbpf_nla_req req = {
@@ -421,6 +461,28 @@ int bpf_xdp_query_id(int ifindex, int flags, __u32 *prog_id)
 	return 0;
 }
 
+int bpf_xdp_query_features(int ifindex, __u32 *xdp_fflags, __u32 *fflags_cnt)
+{
+	struct libbpf_nla_req req = {
+		.nh.nlmsg_len		= NLMSG_LENGTH(sizeof(struct ifinfomsg)),
+		.nh.nlmsg_type		= RTM_GETLINK,
+		.nh.nlmsg_flags		= NLM_F_DUMP | NLM_F_REQUEST,
+		.ifinfo.ifi_family	= AF_PACKET,
+	};
+	struct xdp_features_md md = {};
+	int ret;
+
+	if (!xdp_fflags || !fflags_cnt)
+		return -EINVAL;
+
+	md.ifindex = ifindex;
+	md.flags = xdp_fflags;
+	md.flags_cnt = fflags_cnt;
+
+	ret = libbpf_netlink_send_recv(&req, __dump_link_nlmsg,
+				       bpf_get_xdp_features, &md);
+	return libbpf_err(ret);
+}
 
 typedef int (*qdisc_config_t)(struct libbpf_nla_req *req);
 
-- 
2.38.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [RFC bpf-next 7/8] bpf: devmap: check XDP features in bpf_map_update_elem and __xdp_enqueue
  2022-12-19 15:41 [RFC bpf-next 0/8] xdp: introduce xdp-feature support Lorenzo Bianconi
                   ` (5 preceding siblings ...)
  2022-12-19 15:41 ` [RFC bpf-next 6/8] libbpf: add API to get XDP/XSK supported features Lorenzo Bianconi
@ 2022-12-19 15:41 ` Lorenzo Bianconi
  2022-12-19 15:41 ` [RFC bpf-next 8/8] selftests/bpf: introduce XDP compliance test tool Lorenzo Bianconi
  7 siblings, 0 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2022-12-19 15:41 UTC (permalink / raw)
  To: bpf
  Cc: netdev, ast, daniel, andrii, davem, kuba, hawk, pabeni, edumazet,
	toke, memxor, alardam, saeedm, anthony.l.nguyen, gospo,
	vladimir.oltean, nbd, john, leon, simon.horman, aelior,
	christophe.jaillet, ecree.xilinx, grygorii.strashko, mst, bjorn,
	magnus.karlsson, maciej.fijalkowski, intel-wired-lan,
	lorenzo.bianconi

When we update devmap element, the net_device whose ifindex is specified
in map value must support ndo_xdp_xmit callback, which is indicated by
the presence of XDP_F_REDIRECT_TARGET feature. Let's check for
this feature and return an error if device cannot be used as a redirect
target.

Moreover check the device support xdp non-linear frame in __xdp_enqueue
and is_valid_dst routines. This patch allows to perfrom XDP_REDIRECT on
non-linear xdp buffers.

Co-developed-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 kernel/bpf/devmap.c | 25 +++++++++++++++++++++----
 net/core/filter.c   | 13 +++++--------
 2 files changed, 26 insertions(+), 12 deletions(-)

diff --git a/kernel/bpf/devmap.c b/kernel/bpf/devmap.c
index d01e4c55b376..16199eb5c7a6 100644
--- a/kernel/bpf/devmap.c
+++ b/kernel/bpf/devmap.c
@@ -474,7 +474,11 @@ static inline int __xdp_enqueue(struct net_device *dev, struct xdp_frame *xdpf,
 {
 	int err;
 
-	if (!dev->netdev_ops->ndo_xdp_xmit)
+	if (!(dev->xdp_features & XDP_F_REDIRECT_TARGET))
+		return -EOPNOTSUPP;
+
+	if (unlikely(!(dev->xdp_features & XDP_F_FRAG_TARGET) &&
+		     xdp_frame_has_frags(xdpf)))
 		return -EOPNOTSUPP;
 
 	err = xdp_ok_fwd_dev(dev, xdp_get_frame_len(xdpf));
@@ -532,8 +536,14 @@ int dev_map_enqueue(struct bpf_dtab_netdev *dst, struct xdp_frame *xdpf,
 
 static bool is_valid_dst(struct bpf_dtab_netdev *obj, struct xdp_frame *xdpf)
 {
-	if (!obj ||
-	    !obj->dev->netdev_ops->ndo_xdp_xmit)
+	if (!obj)
+		return false;
+
+	if (!(obj->dev->xdp_features & XDP_F_REDIRECT_TARGET))
+		return false;
+
+	if (unlikely(!(obj->dev->xdp_features & XDP_F_FRAG_TARGET) &&
+		     xdp_frame_has_frags(xdpf)))
 		return false;
 
 	if (xdp_ok_fwd_dev(obj->dev, xdp_get_frame_len(xdpf)))
@@ -843,6 +853,7 @@ static struct bpf_dtab_netdev *__dev_map_alloc_node(struct net *net,
 {
 	struct bpf_prog *prog = NULL;
 	struct bpf_dtab_netdev *dev;
+	int ret = -EINVAL;
 
 	dev = bpf_map_kmalloc_node(&dtab->map, sizeof(*dev),
 				   GFP_NOWAIT | __GFP_NOWARN,
@@ -854,6 +865,12 @@ static struct bpf_dtab_netdev *__dev_map_alloc_node(struct net *net,
 	if (!dev->dev)
 		goto err_out;
 
+	/* Check if net_device can be used as a redirect target */
+	if (!(READ_ONCE(dev->dev->xdp_features) & XDP_F_REDIRECT_TARGET)) {
+		ret = -EOPNOTSUPP;
+		goto err_put_dev;
+	}
+
 	if (val->bpf_prog.fd > 0) {
 		prog = bpf_prog_get_type_dev(val->bpf_prog.fd,
 					     BPF_PROG_TYPE_XDP, false);
@@ -882,7 +899,7 @@ static struct bpf_dtab_netdev *__dev_map_alloc_node(struct net *net,
 	dev_put(dev->dev);
 err_out:
 	kfree(dev);
-	return ERR_PTR(-EINVAL);
+	return ERR_PTR(ret);
 }
 
 static int __dev_map_update_elem(struct net *net, struct bpf_map *map,
diff --git a/net/core/filter.c b/net/core/filter.c
index 929358677183..c2bd1935b55a 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -4282,16 +4282,13 @@ int xdp_do_redirect(struct net_device *dev, struct xdp_buff *xdp,
 	struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
 	enum bpf_map_type map_type = ri->map_type;
 
-	/* XDP_REDIRECT is not fully supported yet for xdp frags since
-	 * not all XDP capable drivers can map non-linear xdp_frame in
-	 * ndo_xdp_xmit.
-	 */
-	if (unlikely(xdp_buff_has_frags(xdp) &&
-		     map_type != BPF_MAP_TYPE_CPUMAP))
-		return -EOPNOTSUPP;
+	if (map_type == BPF_MAP_TYPE_XSKMAP) {
+		/* XDP_REDIRECT is not supported AF_XDP yet. */
+		if (unlikely(xdp_buff_has_frags(xdp)))
+			return -EOPNOTSUPP;
 
-	if (map_type == BPF_MAP_TYPE_XSKMAP)
 		return __xdp_do_redirect_xsk(ri, dev, xdp, xdp_prog);
+	}
 
 	return __xdp_do_redirect_frame(ri, dev, xdp_convert_buff_to_frame(xdp),
 				       xdp_prog);
-- 
2.38.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [RFC bpf-next 8/8] selftests/bpf: introduce XDP compliance test tool
  2022-12-19 15:41 [RFC bpf-next 0/8] xdp: introduce xdp-feature support Lorenzo Bianconi
                   ` (6 preceding siblings ...)
  2022-12-19 15:41 ` [RFC bpf-next 7/8] bpf: devmap: check XDP features in bpf_map_update_elem and __xdp_enqueue Lorenzo Bianconi
@ 2022-12-19 15:41 ` Lorenzo Bianconi
  7 siblings, 0 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2022-12-19 15:41 UTC (permalink / raw)
  To: bpf
  Cc: netdev, ast, daniel, andrii, davem, kuba, hawk, pabeni, edumazet,
	toke, memxor, alardam, saeedm, anthony.l.nguyen, gospo,
	vladimir.oltean, nbd, john, leon, simon.horman, aelior,
	christophe.jaillet, ecree.xilinx, grygorii.strashko, mst, bjorn,
	magnus.karlsson, maciej.fijalkowski, intel-wired-lan,
	lorenzo.bianconi

Introduce xdp_features tool in order to test XDP features supported by
the NIC and match them against advertised ones.
In order to test supported/advertised XDP features, xdp_features must
run on the Device Under Test (DUT) and on a Tester device.
xdp_features opens a control TCP channel between DUT and Tester devices
to send control commands from Tester to the DUT and a UDP data channel
where the Tester sends UDP 'echo' packets and the DUT is expected to
reply back with the same packet. DUT installs multiple XDP programs on the
NIC to test XDP capabilities and reports back to the Tester some XDP stats.
Currently xdp_features supports the following XDP features:
- XDP_DROP
- XDP_PASS
- XDP_TX
- XDP_REDIRECT
- XDP_REDIRECT_TARGET

Co-developed-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 tools/testing/selftests/bpf/Makefile          |   5 +-
 .../selftests/bpf/progs/test_xdp_features.c   | 235 ++++++
 .../selftests/bpf/test_xdp_features.sh        |  99 +++
 tools/testing/selftests/bpf/xdp_features.c    | 745 ++++++++++++++++++
 4 files changed, 1082 insertions(+), 2 deletions(-)
 create mode 100644 tools/testing/selftests/bpf/progs/test_xdp_features.c
 create mode 100755 tools/testing/selftests/bpf/test_xdp_features.sh
 create mode 100644 tools/testing/selftests/bpf/xdp_features.c

diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index c22c43bbee19..c485739dd452 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -73,7 +73,8 @@ TEST_PROGS := test_kmod.sh \
 	test_bpftool.sh \
 	test_bpftool_metadata.sh \
 	test_doc_build.sh \
-	test_xsk.sh
+	test_xsk.sh \
+	test_xdp_features.sh
 
 TEST_PROGS_EXTENDED := with_addr.sh \
 	with_tunnels.sh ima_setup.sh verify_sig_setup.sh \
@@ -83,7 +84,7 @@ TEST_PROGS_EXTENDED := with_addr.sh \
 TEST_GEN_PROGS_EXTENDED = test_sock_addr test_skb_cgroup_id_user \
 	flow_dissector_load test_flow_dissector test_tcp_check_syncookie_user \
 	test_lirc_mode2_user xdping test_cpp runqslower bench bpf_testmod.ko \
-	xskxceiver xdp_redirect_multi xdp_synproxy veristat
+	xskxceiver xdp_redirect_multi xdp_synproxy veristat xdp_features
 
 TEST_CUSTOM_PROGS = $(OUTPUT)/urandom_read $(OUTPUT)/sign-file
 TEST_GEN_FILES += liburandom_read.so
diff --git a/tools/testing/selftests/bpf/progs/test_xdp_features.c b/tools/testing/selftests/bpf/progs/test_xdp_features.c
new file mode 100644
index 000000000000..6542364693c9
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/test_xdp_features.c
@@ -0,0 +1,235 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <stdbool.h>
+#include <linux/bpf.h>
+#include <linux/xdp_features.h>
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_endian.h>
+#include <bpf/bpf_tracing.h>
+#include <linux/if_ether.h>
+#include <linux/ip.h>
+#include <linux/in.h>
+#include <linux/udp.h>
+#include <asm-generic/errno-base.h>
+
+struct xdp_cpumap_stats {
+	unsigned int redirect;
+	unsigned int pass;
+	unsigned int drop;
+};
+
+struct {
+	__uint(type, BPF_MAP_TYPE_ARRAY);
+	__type(key, __u32);
+	__type(value, __u32);
+	__uint(max_entries, 1);
+} stats SEC(".maps");
+
+struct {
+	__uint(type, BPF_MAP_TYPE_ARRAY);
+	__type(key, __u32);
+	__type(value, __u32);
+	__uint(max_entries, 1);
+} dut_stats SEC(".maps");
+
+struct {
+	__uint(type, BPF_MAP_TYPE_CPUMAP);
+	__uint(key_size, sizeof(__u32));
+	__uint(value_size, sizeof(struct bpf_cpumap_val));
+	__uint(max_entries, 1);
+} cpu_map SEC(".maps");
+
+struct {
+	__uint(type, BPF_MAP_TYPE_DEVMAP);
+	__uint(key_size, sizeof(__u32));
+	__uint(value_size, sizeof(struct bpf_devmap_val));
+	__uint(max_entries, 1);
+} dev_map SEC(".maps");
+
+const volatile __u32 expected_feature = XDP_FEATURES_FIELD_FLAG(XDP_F_PASS_BIT);
+const volatile __be32 tester_ip;
+const volatile __be32 dut_ip;
+
+#define ECHO_PORT	12346
+
+/* test commands */
+enum test_commands {
+	CMD_STOP,		/* CMD */
+	CMD_START,		/* CMD + xdp feature */
+	CMD_ECHO,		/* CMD */
+	CMD_ACK,		/* CMD + data */
+	CMD_GET_XDP_CAP,	/* CMD */
+	CMD_GET_STATS,		/* CMD */
+};
+
+struct tlv_hdr {
+	__be16 type;
+	__be16 len;
+	__be32 data[];
+};
+
+static __always_inline int xdp_process_echo_packet(struct xdp_md *xdp, bool dut)
+{
+	void *data_end = (void *)(long)xdp->data_end;
+	__be32 saddr = dut ? tester_ip : dut_ip;
+	__be32 daddr = dut ? dut_ip : tester_ip;
+	void *data = (void *)(long)xdp->data;
+	struct ethhdr *eh = data;
+	struct tlv_hdr *tlv;
+	struct udphdr *uh;
+	struct iphdr *ih;
+	__be16 port;
+	__u8 *cmd;
+
+	if (eh + 1 > (struct ethhdr *)data_end)
+		return -EINVAL;
+
+	if (eh->h_proto != bpf_htons(ETH_P_IP))
+		return -EINVAL;
+
+	ih = (struct iphdr *)(eh + 1);
+	if (ih + 1 > (struct iphdr *)data_end)
+		return -EINVAL;
+
+	if (saddr != ih->saddr)
+		return -EINVAL;
+
+	if (daddr != ih->daddr)
+		return -EINVAL;
+
+	if (ih->protocol != IPPROTO_UDP)
+		return -EINVAL;
+
+	uh = (struct udphdr *)(ih + 1);
+	if (uh + 1 > (struct udphdr *)data_end)
+		return -EINVAL;
+
+	port = dut ? uh->dest : uh->source;
+	if (port != bpf_htons(ECHO_PORT))
+		return -EINVAL;
+
+	tlv = (struct tlv_hdr *)(uh + 1);
+	if (tlv + 1 > data_end)
+		return -EINVAL;
+
+	return bpf_htons(tlv->type) == CMD_ECHO ? 0 : -EINVAL;
+}
+
+SEC("xdp")
+int xdp_tester(struct xdp_md *xdp)
+{
+	__u32 *val, key = 0;
+
+	switch (expected_feature) {
+	case XDP_FEATURES_FIELD_FLAG(XDP_F_REDIRECT_TARGET_BIT):
+	case XDP_FEATURES_FIELD_FLAG(XDP_F_TX_BIT):
+		if (xdp_process_echo_packet(xdp, true))
+			goto out;
+		break;
+	case XDP_FEATURES_FIELD_FLAG(XDP_F_DROP_BIT):
+	case XDP_FEATURES_FIELD_FLAG(XDP_F_PASS_BIT):
+	case XDP_FEATURES_FIELD_FLAG(XDP_F_REDIRECT_BIT):
+		if (xdp_process_echo_packet(xdp, false))
+			goto out;
+		break;
+	default:
+		goto out;
+	}
+
+	val = bpf_map_lookup_elem(&stats, &key);
+	if (val)
+		__sync_add_and_fetch(val, 1);
+
+out:
+	return XDP_PASS;
+}
+
+SEC("xdp")
+int xdp_do_pass(struct xdp_md *xdp)
+{
+	__u32 *val, key = 0;
+
+	val = bpf_map_lookup_elem(&dut_stats, &key);
+	if (val)
+		__sync_add_and_fetch(val, 1);
+
+	return XDP_PASS;
+}
+
+SEC("xdp")
+int xdp_do_drop(struct xdp_md *xdp)
+{
+	__u32 *val, key = 0;
+
+	if (xdp_process_echo_packet(xdp, true))
+		return XDP_PASS;
+
+	val = bpf_map_lookup_elem(&dut_stats, &key);
+	if (val)
+		__sync_add_and_fetch(val, 1);
+
+	return XDP_DROP;
+}
+
+SEC("xdp")
+int xdp_do_tx(struct xdp_md *xdp)
+{
+	void *data = (void *)(long)xdp->data;
+	struct ethhdr *eh = data;
+	__u8 tmp_mac[ETH_ALEN];
+	__u32 *val, key = 0;
+
+	if (xdp_process_echo_packet(xdp, true))
+		return XDP_PASS;
+
+	__builtin_memcpy(tmp_mac, eh->h_source, ETH_ALEN);
+	__builtin_memcpy(eh->h_source, eh->h_dest, ETH_ALEN);
+	__builtin_memcpy(eh->h_dest, tmp_mac, ETH_ALEN);
+
+	val = bpf_map_lookup_elem(&dut_stats, &key);
+	if (val)
+		__sync_add_and_fetch(val, 1);
+
+	return XDP_TX;
+}
+
+SEC("xdp")
+int xdp_do_redirect(struct xdp_md *xdp)
+{
+	if (xdp_process_echo_packet(xdp, true))
+		return XDP_PASS;
+
+	return bpf_redirect_map(&cpu_map, 0, 0);
+}
+
+SEC("tp_btf/xdp_cpumap_kthread")
+int BPF_PROG(tp_xdp_cpumap_kthread, int map_id, unsigned int processed,
+	     unsigned int drops, int sched, struct xdp_cpumap_stats *xdp_stats)
+{
+	__u32 *val, key = 0;
+
+	val = bpf_map_lookup_elem(&dut_stats, &key);
+	if (val)
+		__sync_add_and_fetch(val, 1);
+
+	return 0;
+}
+
+SEC("xdp/cpumap")
+int xdp_do_redirect_cpumap(struct xdp_md *xdp)
+{
+	void *data = (void *)(long)xdp->data;
+	struct ethhdr *eh = data;
+	__u8 tmp_mac[ETH_ALEN];
+
+	if (xdp_process_echo_packet(xdp, true))
+		return XDP_PASS;
+
+	__builtin_memcpy(tmp_mac, eh->h_source, ETH_ALEN);
+	__builtin_memcpy(eh->h_source, eh->h_dest, ETH_ALEN);
+	__builtin_memcpy(eh->h_dest, tmp_mac, ETH_ALEN);
+
+	return bpf_redirect_map(&dev_map, 0, 0);
+}
+
+char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/test_xdp_features.sh b/tools/testing/selftests/bpf/test_xdp_features.sh
new file mode 100755
index 000000000000..2f6e9c879432
--- /dev/null
+++ b/tools/testing/selftests/bpf/test_xdp_features.sh
@@ -0,0 +1,99 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+# Create 2 namespaces with two veth peers, and
+# check reported and detected XDP capabilities
+#
+#   NS0(v00)              NS1(v11)
+#       |                     |
+#       |                     |
+# (v01, id:111)  ------  (v10,id:222)
+
+readonly NS0="ns1-$(mktemp -u XXXXXX)"
+readonly NS1="ns2-$(mktemp -u XXXXXX)"
+ret=1
+
+setup() {
+	{
+		ip netns add ${NS0}
+		ip netns add ${NS1}
+
+		ip link add v01 index 111 type veth peer name v00 netns ${NS0}
+		ip link add v10 index 222 type veth peer name v11 netns ${NS1}
+
+		ip link set v01 up
+		ip addr add 10.10.0.1/24 dev v01
+		ip link set v01 address 00:11:22:33:44:55
+		ip -n ${NS0} link set dev v00 up
+		ip -n ${NS0} addr add 10.10.0.11/24 dev v00
+		ip -n ${NS0} route add default via 10.10.0.1
+		ip -n ${NS0} link set v00 address 00:12:22:33:44:55
+
+		ip link set v10 up
+		ip addr add 10.10.1.1/24 dev v10
+		ip link set v10 address 00:13:22:33:44:55
+		ip -n ${NS1} link set dev v11 up
+		ip -n ${NS1} addr add 10.10.1.11/24 dev v11
+		ip -n ${NS1} route add default via 10.10.1.1
+		ip -n ${NS1} link set v11 address 00:14:22:33:44:55
+
+		sysctl -w net.ipv4.ip_forward=1
+		# Enable XDP mode
+		ethtool -K v01 gro on
+		ethtool -K v01 tx-checksumming off
+		ip netns exec ${NS0} ethtool -K v00 gro on
+		ip netns exec ${NS0} ethtool -K v00 tx-checksumming off
+		ethtool -K v10 gro on
+		ethtool -K v10 tx-checksumming off
+		ip netns exec ${NS1} ethtool -K v11 gro on
+		ip netns exec ${NS1} ethtool -K v11 tx-checksumming off
+	} > /dev/null 2>&1
+}
+
+cleanup() {
+	ip link del v01 2> /dev/null
+	ip link del v10 2> /dev/null
+	ip netns del ${NS0} 2> /dev/null
+	ip netns del ${NS1} 2> /dev/null
+	[ "$(pidof xdp_features)" = "" ] || kill $(pidof xdp_features) 2> /dev/null
+}
+
+test_xdp_features() {
+	setup
+
+	## XDP_PASS
+	ip netns exec ${NS1} ./xdp_features -f XDP_PASS -D 10.10.1.11 -T 10.10.0.11 v11 &
+	ip netns exec ${NS0} ./xdp_features -t -f XDP_PASS -D 10.10.1.11 -C 10.10.1.11 -T 10.10.0.11 v00
+
+	[ $? -ne 0 ] && exit
+
+	# XDP_DROP
+	ip netns exec ${NS1} ./xdp_features -f XDP_DROP -D 10.10.1.11 -T 10.10.0.11 v11 &
+	ip netns exec ${NS0} ./xdp_features -t -f XDP_DROP -D 10.10.1.11 -C 10.10.1.11 -T 10.10.0.11 v00
+
+	[ $? -ne 0 ] && exit
+
+	## XDP_TX
+	./xdp_features -f XDP_TX -D 10.10.0.1 -T 10.10.0.11 v01 &
+	ip netns exec ${NS0} ./xdp_features -t -f XDP_TX -D 10.10.0.1 -C 10.10.0.1 -T 10.10.0.11 v00
+
+	## XDP_REDIRECT
+	ip netns exec ${NS1} ./xdp_features -f XDP_REDIRECT -D 10.10.1.11 -T 10.10.0.11 v11 &
+	ip netns exec ${NS0} ./xdp_features -t -f XDP_REDIRECT -D 10.10.1.11 -C 10.10.1.11 -T 10.10.0.11 v00
+
+	[ $? -ne 0 ] && exit
+
+	## XDP_REDIRECT_TARGET
+	./xdp_features -f XDP_REDIRECT_TARGET -D 10.10.0.1 -T 10.10.0.11 v01 &
+	ip netns exec ${NS0} ./xdp_features -t -f XDP_REDIRECT_TARGET -D 10.10.0.1 -C 10.10.0.1 -T 10.10.0.11 v00
+
+	ret=$?
+	cleanup
+}
+
+set -e
+trap cleanup 2 3 6 9
+
+test_xdp_features
+
+exit $ret
diff --git a/tools/testing/selftests/bpf/xdp_features.c b/tools/testing/selftests/bpf/xdp_features.c
new file mode 100644
index 000000000000..8345a160308f
--- /dev/null
+++ b/tools/testing/selftests/bpf/xdp_features.c
@@ -0,0 +1,745 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <uapi/linux/bpf.h>
+#include <uapi/linux/xdp_features.h>
+#include <linux/if_link.h>
+#include <signal.h>
+#include <argp.h>
+#include <net/if.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#include <bpf/bpf.h>
+#include <bpf/libbpf.h>
+#include <pthread.h>
+
+#include "test_xdp_features.skel.h"
+
+#define RED(str)	"\033[0;31m" str "\033[0m"
+#define GREEN(str)	"\033[0;32m" str "\033[0m"
+#define YELLOW(str)	"\033[0;33m" str "\033[0m"
+
+static struct env {
+	bool verbosity;
+	int ifindex;
+	unsigned int feature;
+	bool tester;
+	in_addr_t dut_ctrl_ip;
+	in_addr_t dut_ip;
+	in_addr_t tester_ip;
+} env;
+
+#define DUT_CTRL_PORT	12345
+#define DUT_ECHO_PORT	12346
+
+/* test commands */
+enum test_commands {
+	CMD_STOP,		/* CMD */
+	CMD_START,		/* CMD + xdp feature */
+	CMD_ECHO,		/* CMD */
+	CMD_ACK,		/* CMD + data */
+	CMD_GET_XDP_CAP,	/* CMD */
+	CMD_GET_STATS,		/* CMD */
+};
+
+struct tlv_hdr {
+	__be16 type;
+	__be16 len;
+	__be32 data[];
+};
+
+#define BUFSIZE		128
+
+static int libbpf_print_fn(enum libbpf_print_level level,
+			   const char *format, va_list args)
+{
+	if (level == LIBBPF_DEBUG && !env.verbosity)
+		return 0;
+	return vfprintf(stderr, format, args);
+}
+
+static volatile bool exiting;
+
+static void sig_handler(int sig)
+{
+	exiting = true;
+}
+
+const char *argp_program_version = "xdp-features 0.0";
+const char argp_program_doc[] =
+"XDP features detecion application.\n"
+"\n"
+"XDP features application checks the XDP advertised features match detected ones.\n"
+"\n"
+"USAGE: ./xdp-features [-vt] [-f <xdp-feature>] [-D <dut-data-ip>] [-T <tester-data-ip>] [-C <dut-ctrl-ip>] <iface-name>\n"
+"\n"
+"XDP features\n:"
+"- XDP_PASS\n"
+"- XDP_DROP\n"
+"- XDP_ABORTED\n"
+"- XDP_REDIRECT\n"
+"- XDP_REDIRECT_TARGET\n"
+"- XDP_TX\n";
+
+static const struct argp_option opts[] = {
+	{ "verbose", 'v', NULL, 0, "Verbose debug output" },
+	{ "tester", 't', NULL, 0, "Tester mode" },
+	{ "feature", 'f', "XDP-FEATURE", 0, "XDP feature to test" },
+	{ "dut_data_ip", 'D', "DUT-DATA-IP", 0, "DUT IP data channel" },
+	{ "dut_ctrl_ip", 'C', "DUT-CTRL-IP", 0, "DUT IP control channel" },
+	{ "tester_data_ip", 'T', "TESTER-DATA-IP", 0, "Tester IP data channel" },
+	{},
+};
+
+static int get_xdp_feature(const char *arg)
+{
+	if (!strcmp(arg, "XDP_PASS"))
+		return XDP_FEATURES_FIELD_FLAG(XDP_F_PASS_BIT);
+	else if (!strcmp(arg, "XDP_DROP"))
+		return XDP_FEATURES_FIELD_FLAG(XDP_F_DROP_BIT);
+	else if (!strcmp(arg, "XDP_ABORTED"))
+		return XDP_FEATURES_FIELD_FLAG(XDP_F_ABORTED_BIT);
+	else if (!strcmp(arg, "XDP_REDIRECT"))
+		return XDP_FEATURES_FIELD_FLAG(XDP_F_REDIRECT_BIT);
+	else if (!strcmp(arg, "XDP_REDIRECT_TARGET"))
+		return XDP_FEATURES_FIELD_FLAG(XDP_F_REDIRECT_TARGET_BIT);
+	else if (!strcmp(arg, "XDP_TX"))
+		return XDP_FEATURES_FIELD_FLAG(XDP_F_TX_BIT);
+
+	return -EINVAL;
+}
+
+static char *get_xdp_feature_str(int feature)
+{
+	switch (feature) {
+	case XDP_FEATURES_FIELD_FLAG(XDP_F_PASS_BIT):
+		return YELLOW("XDP_PASS");
+	case XDP_FEATURES_FIELD_FLAG(XDP_F_DROP_BIT):
+		return YELLOW("XDP_DROP");
+	case XDP_FEATURES_FIELD_FLAG(XDP_F_ABORTED_BIT):
+		return YELLOW("XDP_ABORTED");
+	case XDP_FEATURES_FIELD_FLAG(XDP_F_TX_BIT):
+		return YELLOW("XDP_TX");
+	case XDP_FEATURES_FIELD_FLAG(XDP_F_REDIRECT_BIT):
+		return YELLOW("XDP_REDIRECT");
+	case XDP_FEATURES_FIELD_FLAG(XDP_F_REDIRECT_TARGET_BIT):
+		return YELLOW("XDP_REDIRECT_TARGET");
+	default:
+		return "";
+	}
+}
+
+static error_t parse_arg(int key, char *arg, struct argp_state *state)
+{
+	switch (key) {
+	case 'v':
+		env.verbosity = true;
+		break;
+	case 't':
+		env.tester = true;
+		break;
+	case 'f':
+		env.feature = get_xdp_feature(arg);
+		if (env.feature < 0) {
+			fprintf(stderr, "Invalid xdp feature: %s\n", arg);
+			argp_usage(state);
+			return ARGP_ERR_UNKNOWN;
+		}
+		break;
+	case 'D':
+		env.dut_ip = inet_addr(arg);
+		if (env.dut_ip < 0)
+			return ARGP_ERR_UNKNOWN;
+		break;
+	case 'C':
+		env.dut_ctrl_ip = inet_addr(arg);
+		if (env.dut_ctrl_ip < 0)
+			return ARGP_ERR_UNKNOWN;
+		break;
+	case 'T':
+		env.tester_ip = inet_addr(arg);
+		if (env.tester_ip < 0)
+			return ARGP_ERR_UNKNOWN;
+		break;
+	case ARGP_KEY_ARG:
+		errno = 0;
+		if (strlen(arg) >= IF_NAMESIZE) {
+			fprintf(stderr, "Invalid device name: %s\n", arg);
+			argp_usage(state);
+			return ARGP_ERR_UNKNOWN;
+		}
+
+		env.ifindex = if_nametoindex(arg);
+		if (!env.ifindex)
+			env.ifindex = strtoul(arg, NULL, 0);
+		if (!env.ifindex) {
+			fprintf(stderr,
+				"Bad interface index or name (%d): %s\n",
+				errno, strerror(errno));
+			argp_usage(state);
+			return ARGP_ERR_UNKNOWN;
+		}
+		break;
+	default:
+		return ARGP_ERR_UNKNOWN;
+	}
+
+	return 0;
+}
+
+static const struct argp argp = {
+	.options = opts,
+	.parser = parse_arg,
+	.doc = argp_program_doc,
+};
+
+static void set_env_defaul(void)
+{
+	env.feature = XDP_FEATURES_FIELD_FLAG(XDP_F_PASS_BIT);
+	env.ifindex = -ENODEV;
+	env.dut_ctrl_ip = inet_addr("127.0.0.1");
+	env.dut_ip = inet_addr("127.0.0.1");
+	env.tester_ip = inet_addr("127.0.0.1");
+}
+
+static void *dut_echo_thread(void *arg)
+{
+	unsigned char buf[sizeof(struct tlv_hdr)];
+	int sockfd = *(int *)arg;
+
+	while (!exiting) {
+		unsigned int len = sizeof(struct sockaddr_in);
+		struct sockaddr_in addr;
+		struct tlv_hdr *tlv = (struct tlv_hdr *)buf;
+		size_t n;
+
+		n = recvfrom(sockfd, buf, sizeof(buf), MSG_WAITALL,
+			     (struct sockaddr *)&addr, &len);
+		if (n != ntohs(tlv->len))
+			continue;
+
+		if (ntohs(tlv->type) != CMD_ECHO)
+			continue;
+
+		sendto(sockfd, buf, sizeof(buf), MSG_NOSIGNAL | MSG_CONFIRM,
+		       (struct sockaddr *)&addr, sizeof(addr));
+	}
+
+	pthread_exit((void *)0);
+	close(sockfd);
+
+	return NULL;
+}
+
+static int dut_run_echo_thread(pthread_t *t, int *echo_sockfd)
+{
+	struct sockaddr_in addr = {
+		.sin_family = AF_INET,
+		.sin_addr.s_addr = htonl(INADDR_ANY),
+		.sin_port = htons(DUT_ECHO_PORT),
+	};
+	int err, sockfd, optval = 1;
+
+	sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+	if (sockfd < 0) {
+		fprintf(stderr, "Failed to create echo socket\n");
+		return -errno;
+	}
+
+	err = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval,
+			 sizeof(optval));
+	if (err < 0) {
+		fprintf(stderr, "Failed sockopt on echo socket\n");
+		return -errno;
+	}
+
+	err = bind(sockfd, (struct sockaddr *)&addr, sizeof(addr));
+	if (err) {
+		fprintf(stderr, "Failed to bind echo socket\n");
+		return -errno;
+	}
+
+	/* start echo channel */
+	*echo_sockfd = sockfd;
+	err = pthread_create(t, NULL, dut_echo_thread, echo_sockfd);
+	if (err) {
+		fprintf(stderr, "Failed creating dut_echo thread: %s\n",
+			strerror(-err));
+		close(sockfd);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int dut_attach_xdp_prog(struct test_xdp_features *skel, int feature,
+			       int flags)
+{
+	struct bpf_program *prog;
+	unsigned int key = 0;
+	int err, fd = 0;
+
+	switch (feature) {
+	case XDP_FEATURES_FIELD_FLAG(XDP_F_TX_BIT):
+		prog = skel->progs.xdp_do_tx;
+		break;
+	case XDP_FEATURES_FIELD_FLAG(XDP_F_DROP_BIT):
+	case XDP_FEATURES_FIELD_FLAG(XDP_F_ABORTED_BIT):
+		prog = skel->progs.xdp_do_drop;
+		break;
+	case XDP_FEATURES_FIELD_FLAG(XDP_F_PASS_BIT):
+		prog = skel->progs.xdp_do_pass;
+		break;
+	case XDP_FEATURES_FIELD_FLAG(XDP_F_REDIRECT_TARGET_BIT): {
+		struct bpf_devmap_val entry = {
+			.ifindex = env.ifindex,
+		};
+
+		err = bpf_map__update_elem(skel->maps.dev_map,
+					   &key, sizeof(key),
+					   &entry, sizeof(entry), 0);
+		if (err < 0)
+			return err;
+
+		fd = bpf_program__fd(skel->progs.xdp_do_redirect_cpumap);
+	}
+	case XDP_FEATURES_FIELD_FLAG(XDP_F_REDIRECT_BIT): {
+		struct bpf_cpumap_val entry = {
+			.qsize = 2048,
+			.bpf_prog.fd = fd,
+		};
+
+		err = bpf_map__update_elem(skel->maps.cpu_map,
+					   &key, sizeof(key),
+					   &entry, sizeof(entry), 0);
+		if (err < 0)
+			return err;
+
+		prog = skel->progs.xdp_do_redirect;
+		break;
+	}
+	default:
+		return -EINVAL;
+	}
+
+	err = bpf_xdp_attach(env.ifindex, bpf_program__fd(prog), flags, NULL);
+	if (err)
+		fprintf(stderr,
+			"Failed to attach XDP program to ifindex %d\n",
+			env.ifindex);
+	return err;
+}
+
+static int __recv_msg(int sockfd, void *buf, size_t bufsize,
+		      unsigned int *val, unsigned int val_size)
+{
+	struct tlv_hdr *tlv = (struct tlv_hdr *)buf;
+	int len, n = sizeof(*tlv), i = 0;
+
+	len = recv(sockfd, buf, bufsize, 0);
+	if (len != ntohs(tlv->len))
+		return -EINVAL;
+
+	while (n < len && i < val_size) {
+		val[i] = ntohl(tlv->data[i]);
+		n += sizeof(tlv->data[0]);
+		i++;
+	}
+
+	return i;
+}
+
+static int recv_msg(int sockfd, void *buf, size_t bufsize)
+{
+	return __recv_msg(sockfd, buf, bufsize, NULL, 0);
+}
+
+static int dut_run(struct test_xdp_features *skel)
+{
+	int flags = XDP_FLAGS_UPDATE_IF_NOEXIST | XDP_FLAGS_DRV_MODE;
+	int state, err, sockfd, ctrl_sockfd, echo_sockfd, optval = 1;
+	struct sockaddr_in ctrl_addr, addr = {
+		.sin_family = AF_INET,
+		.sin_addr.s_addr = htonl(INADDR_ANY),
+		.sin_port = htons(DUT_CTRL_PORT),
+	};
+	unsigned int len = sizeof(ctrl_addr);
+	pthread_t dut_thread;
+
+	sockfd = socket(AF_INET, SOCK_STREAM, 0);
+	if (sockfd < 0) {
+		fprintf(stderr, "Failed to create DUT socket\n");
+		return -errno;
+	}
+
+	err = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval,
+			 sizeof(optval));
+	if (err < 0) {
+		fprintf(stderr, "Failed sockopt on DUT socket\n");
+		return -errno;
+	}
+
+	err = bind(sockfd, (struct sockaddr *)&addr, sizeof(addr));
+	if (err < 0) {
+		fprintf(stderr, "Failed to bind DUT socket\n");
+		return -errno;
+	}
+
+	err = listen(sockfd, 5);
+	if (err) {
+		fprintf(stderr, "Failed to listen DUT socket\n");
+		return -errno;
+	}
+
+	ctrl_sockfd = accept(sockfd, (struct sockaddr *)&ctrl_addr, &len);
+	if (ctrl_sockfd < 0) {
+		fprintf(stderr, "Failed to accept connection on DUT socket\n");
+		close(sockfd);
+		return -errno;
+	}
+
+	/* CTRL loop */
+	while (!exiting) {
+		unsigned char buf[BUFSIZE] = {};
+		struct tlv_hdr *tlv = (struct tlv_hdr *)buf;
+
+		err = recv_msg(ctrl_sockfd, buf, BUFSIZE);
+		if (err)
+			continue;
+
+		switch (ntohs(tlv->type)) {
+		case CMD_START: {
+			if (state == CMD_START)
+				continue;
+
+			state = CMD_START;
+			/* Load the XDP program on the DUT */
+			err = dut_attach_xdp_prog(skel, ntohl(tlv->data[0]), flags);
+			if (err)
+				goto out;
+
+			err = dut_run_echo_thread(&dut_thread, &echo_sockfd);
+			if (err < 0)
+				goto out;
+
+			tlv->type = htons(CMD_ACK);
+			tlv->len = htons(sizeof(*tlv));
+			err = send(ctrl_sockfd, buf, sizeof(*tlv), 0);
+			if (err < 0)
+				goto end_thread;
+			break;
+		}
+		case CMD_STOP:
+			if (state != CMD_START)
+				break;
+
+			state = CMD_STOP;
+
+			exiting = true;
+			bpf_xdp_detach(env.ifindex, flags, NULL);
+
+			tlv->type = htons(CMD_ACK);
+			tlv->len = htons(sizeof(*tlv));
+			err = send(ctrl_sockfd, buf, sizeof(*tlv), 0);
+			goto end_thread;
+		case CMD_GET_XDP_CAP: {
+			unsigned int xdp_cap[XDP_FEATURES_WORDS] = {};
+			unsigned int xdp_cap_size = ARRAY_SIZE(xdp_cap);
+			size_t n;
+			int i;
+
+			err = bpf_xdp_query_features(env.ifindex, xdp_cap,
+						     &xdp_cap_size);
+			if (err < 0) {
+				fprintf(stderr,
+					"Failed to query XDP cap for ifindex %d\n",
+					env.ifindex);
+				goto end_thread;
+			}
+
+			tlv->type = htons(CMD_ACK);
+			n = sizeof(*tlv) + xdp_cap_size * sizeof(xdp_cap[0]);
+			tlv->len = htons(n);
+			for (i = 0; i < xdp_cap_size; i++)
+				tlv->data[i] = htonl(xdp_cap[i]);
+
+			err = send(ctrl_sockfd, buf, n, 0);
+			if (err < 0)
+				goto end_thread;
+			break;
+		}
+		case CMD_GET_STATS: {
+			unsigned int key = 0, val;
+			size_t n;
+
+			err = bpf_map__lookup_elem(skel->maps.dut_stats,
+						   &key, sizeof(key),
+						   &val, sizeof(val), 0);
+			if (err) {
+				fprintf(stderr, "bpf_map_lookup_elem failed\n");
+				goto end_thread;
+			}
+
+			tlv->type = htons(CMD_ACK);
+			n = sizeof(*tlv) + sizeof(val);
+			tlv->len = htons(n);
+			tlv->data[0] = htonl(val);
+
+			err = send(ctrl_sockfd, buf, n, 0);
+			if (err < 0)
+				goto end_thread;
+			break;
+		}
+		default:
+			break;
+		}
+	}
+
+end_thread:
+	pthread_join(dut_thread, NULL);
+out:
+	bpf_xdp_detach(env.ifindex, flags, NULL);
+	close(ctrl_sockfd);
+	close(sockfd);
+
+	return err;
+}
+
+static bool tester_collect_advertised_cap(unsigned int cap)
+{
+	return cap & env.feature;
+}
+
+static bool tester_collect_detected_cap(struct test_xdp_features *skel,
+					unsigned int dut_stats)
+{
+	unsigned int err, key = 0, val;
+
+	if (!dut_stats)
+		return false;
+
+	err = bpf_map__lookup_elem(skel->maps.stats, &key, sizeof(key),
+				   &val, sizeof(val), 0);
+	if (err) {
+		fprintf(stderr, "bpf_map_lookup_elem failed\n");
+		return false;
+	}
+
+	switch (env.feature) {
+	case XDP_FEATURES_FIELD_FLAG(XDP_F_PASS_BIT):
+	case XDP_FEATURES_FIELD_FLAG(XDP_F_TX_BIT):
+	case XDP_FEATURES_FIELD_FLAG(XDP_F_REDIRECT_BIT):
+	case XDP_FEATURES_FIELD_FLAG(XDP_F_REDIRECT_TARGET_BIT):
+		return val > 0;
+	case XDP_FEATURES_FIELD_FLAG(XDP_F_DROP_BIT):
+	case XDP_FEATURES_FIELD_FLAG(XDP_F_ABORTED_BIT):
+		return val == 0;
+	default:
+		return false;
+	}
+}
+
+static int __send_and_recv_msg(int sockfd, enum test_commands cmd,
+			       unsigned int *val, unsigned int val_size)
+{
+	unsigned char buf[BUFSIZE] = {};
+	struct tlv_hdr *tlv = (struct tlv_hdr *)buf;
+	int n = sizeof(*tlv), err;
+
+	tlv->type = htons(cmd);
+	switch (cmd) {
+	case CMD_START:
+		tlv->data[0] = htonl(env.feature);
+		n += sizeof(*val);
+		break;
+	default:
+		break;
+	}
+	tlv->len = htons(n);
+
+	err = send(sockfd, buf, n, 0);
+	if (err < 0)
+		return err;
+
+	err = __recv_msg(sockfd, buf, BUFSIZE, val, val_size);
+	if (err < 0)
+		return err;
+
+	return ntohs(tlv->type) == CMD_ACK ? 0 : -EINVAL;
+}
+
+static int send_and_recv_msg(int sockfd, enum test_commands cmd)
+{
+	return __send_and_recv_msg(sockfd, cmd, NULL, 0);
+}
+
+static int send_echo_msg(void)
+{
+	struct sockaddr_in addr = {
+		.sin_family = AF_INET,
+		.sin_addr.s_addr = env.dut_ip,
+		.sin_port = htons(DUT_ECHO_PORT),
+	};
+	unsigned char buf[sizeof(struct tlv_hdr)];
+	struct tlv_hdr *tlv = (struct tlv_hdr *)buf;
+	int sockfd, n;
+
+	sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+	if (sockfd < 0) {
+		fprintf(stderr, "Failed to create echo socket\n");
+		return -errno;
+	}
+
+	tlv->type = htons(CMD_ECHO);
+	tlv->len = htons(sizeof(*tlv));
+
+	n = sendto(sockfd, buf, sizeof(*tlv), MSG_NOSIGNAL | MSG_CONFIRM,
+		   (struct sockaddr *)&addr, sizeof(addr));
+	close(sockfd);
+
+	return n == ntohs(tlv->len) ? 0 : -EINVAL;
+}
+
+static int tester_run(struct test_xdp_features *skel)
+{
+	int flags = XDP_FLAGS_UPDATE_IF_NOEXIST | XDP_FLAGS_DRV_MODE;
+	struct sockaddr_in addr = {
+		.sin_family = AF_INET,
+		.sin_addr.s_addr = env.dut_ctrl_ip,
+		.sin_port = htons(DUT_CTRL_PORT),
+	};
+	bool advertised_cap;
+	int i, err, sockfd;
+	bool detected_cap;
+	unsigned int val[1];
+
+	sockfd = socket(AF_INET, SOCK_STREAM, 0);
+	if (sockfd < 0) {
+		fprintf(stderr, "Failed to create tester socket\n");
+		return -errno;
+	}
+
+	for (i = 0; i < 10; i++) {
+		/* connect ctrl channel */
+		if (!connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)))
+			break;
+		sleep(1);
+	}
+
+	if (i == 10) {
+		fprintf(stderr, "Failed to connect to the DUT\n");
+		return -ETIMEDOUT;
+	}
+
+	err = __send_and_recv_msg(sockfd, CMD_GET_XDP_CAP, val, ARRAY_SIZE(val));
+	if (err < 0) {
+		close(sockfd);
+		return err;
+	}
+
+	advertised_cap = tester_collect_advertised_cap(val[0]);
+
+	err = bpf_xdp_attach(env.ifindex,
+			     bpf_program__fd(skel->progs.xdp_tester),
+			     flags, NULL);
+	if (err) {
+		fprintf(stderr, "Failed to attach XDP program to ifindex %d\n",
+			env.ifindex);
+		goto out;
+	}
+
+	err = send_and_recv_msg(sockfd, CMD_START);
+	if (err)
+		goto out;
+
+	for (i = 0; i < 10 && !exiting; i++) {
+		err = send_echo_msg();
+		if (err < 0)
+			goto out;
+
+		sleep(1);
+	}
+
+	err = __send_and_recv_msg(sockfd, CMD_GET_STATS, val, ARRAY_SIZE(val));
+	if (err)
+		goto out;
+
+	/* stop the test */
+	err = send_and_recv_msg(sockfd, CMD_STOP);
+	/* send a new echo message to wake echo thread of the dut */
+	send_echo_msg();
+
+	detected_cap = tester_collect_detected_cap(skel, val[0]);
+
+	fprintf(stdout, "Feature %s: [%s][%s]\n", get_xdp_feature_str(env.feature),
+		detected_cap ? GREEN("DETECTED") : RED("NOT DETECTED"),
+		advertised_cap ? GREEN("ADVERTISED") : RED("NOT ADVERTISED"));
+out:
+	bpf_xdp_detach(env.ifindex, flags, NULL);
+	close(sockfd);
+	return err < 0 ? err : 0;
+}
+
+int main(int argc, char **argv)
+{
+	struct test_xdp_features *skel;
+	int err;
+
+	libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
+	libbpf_set_print(libbpf_print_fn);
+
+	signal(SIGINT, sig_handler);
+	signal(SIGTERM, sig_handler);
+
+	set_env_defaul();
+
+	/* Parse command line arguments */
+	err = argp_parse(&argp, argc, argv, 0, NULL, NULL);
+	if (err)
+		return err;
+
+	if (env.ifindex < 0) {
+		fprintf(stderr, "Invalid ifindex\n");
+		return -ENODEV;
+	}
+
+	/* Load and verify BPF application */
+	skel = test_xdp_features__open();
+	if (!skel) {
+		fprintf(stderr, "Failed to open and load BPF skeleton\n");
+		return -EINVAL;
+	}
+
+	skel->rodata->expected_feature = env.feature;
+	skel->rodata->dut_ip = env.dut_ip;
+	skel->rodata->tester_ip = env.tester_ip;
+
+	/* Load & verify BPF programs */
+	err = test_xdp_features__load(skel);
+	if (err) {
+		fprintf(stderr, "Failed to load and verify BPF skeleton\n");
+		goto cleanup;
+	}
+
+	err = test_xdp_features__attach(skel);
+	if (err) {
+		fprintf(stderr, "Failed to attach BPF skeleton\n");
+		goto cleanup;
+	}
+
+	if (env.tester) {
+		/* Tester */
+		fprintf(stdout, "Starting tester on device %d\n", env.ifindex);
+		err = tester_run(skel);
+	} else {
+		/* DUT */
+		fprintf(stdout, "Starting DUT on device %d\n", env.ifindex);
+		err = dut_run(skel);
+	}
+
+cleanup:
+	test_xdp_features__destroy(skel);
+
+	return err < 0 ? -err : 0;
+}
-- 
2.38.1


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: [RFC bpf-next 2/8] net: introduce XDP features flag
  2022-12-19 15:41 ` [RFC bpf-next 2/8] net: introduce XDP features flag Lorenzo Bianconi
@ 2022-12-19 20:03   ` sdf
       [not found]     ` <CAAOQfrFGArAYPyBX_kw4ZvFrTjKXf-jG-2F2y69nOs-oQ8Onwg@mail.gmail.com>
  2022-12-20  1:13   ` Jakub Kicinski
  1 sibling, 1 reply; 27+ messages in thread
From: sdf @ 2022-12-19 20:03 UTC (permalink / raw)
  To: Lorenzo Bianconi
  Cc: bpf, netdev, ast, daniel, andrii, davem, kuba, hawk, pabeni,
	edumazet, toke, memxor, alardam, saeedm, anthony.l.nguyen, gospo,
	vladimir.oltean, nbd, john, leon, simon.horman, aelior,
	christophe.jaillet, ecree.xilinx, grygorii.strashko, mst, bjorn,
	magnus.karlsson, maciej.fijalkowski, intel-wired-lan,
	lorenzo.bianconi

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


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [RFC bpf-next 2/8] net: introduce XDP features flag
       [not found]     ` <CAAOQfrFGArAYPyBX_kw4ZvFrTjKXf-jG-2F2y69nOs-oQ8Onwg@mail.gmail.com>
@ 2022-12-20  0:20       ` Stanislav Fomichev
  2022-12-20 10:11         ` Lorenzo Bianconi
  0 siblings, 1 reply; 27+ messages in thread
From: Stanislav Fomichev @ 2022-12-20  0:20 UTC (permalink / raw)
  To: Marek Majtyka
  Cc: Lorenzo Bianconi, bpf, netdev, ast, daniel, andrii, davem, kuba,
	hawk, pabeni, edumazet, toke, memxor, saeedm, anthony.l.nguyen,
	gospo, vladimir.oltean, nbd, john, leon, simon.horman, aelior,
	christophe.jaillet, ecree.xilinx, grygorii.strashko, mst, bjorn,
	magnus.karlsson, maciej.fijalkowski, intel-wired-lan,
	lorenzo.bianconi

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
>>

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [RFC bpf-next 2/8] net: introduce XDP features flag
  2022-12-19 15:41 ` [RFC bpf-next 2/8] net: introduce XDP features flag Lorenzo Bianconi
  2022-12-19 20:03   ` sdf
@ 2022-12-20  1:13   ` Jakub Kicinski
  2022-12-20  9:20     ` Lorenzo Bianconi
  1 sibling, 1 reply; 27+ messages in thread
From: Jakub Kicinski @ 2022-12-20  1:13 UTC (permalink / raw)
  To: Lorenzo Bianconi
  Cc: bpf, netdev, ast, daniel, andrii, davem, hawk, pabeni, edumazet,
	toke, memxor, alardam, saeedm, anthony.l.nguyen, gospo,
	vladimir.oltean, nbd, john, leon, simon.horman, aelior,
	christophe.jaillet, ecree.xilinx, grygorii.strashko, mst, bjorn,
	magnus.karlsson, maciej.fijalkowski, intel-wired-lan,
	lorenzo.bianconi

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.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [RFC bpf-next 2/8] net: introduce XDP features flag
  2022-12-20  1:13   ` Jakub Kicinski
@ 2022-12-20  9:20     ` Lorenzo Bianconi
  2022-12-20 22:51       ` Marek Majtyka
  0 siblings, 1 reply; 27+ messages in thread
From: Lorenzo Bianconi @ 2022-12-20  9:20 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: Lorenzo Bianconi, bpf, netdev, ast, daniel, andrii, davem, hawk,
	pabeni, edumazet, toke, memxor, alardam, saeedm, anthony.l.nguyen,
	gospo, vladimir.oltean, nbd, john, leon, simon.horman, aelior,
	christophe.jaillet, ecree.xilinx, grygorii.strashko, mst, bjorn,
	magnus.karlsson, maciej.fijalkowski, intel-wired-lan

[-- Attachment #1: Type: text/plain, Size: 2832 bytes --]

> 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.
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [RFC bpf-next 2/8] net: introduce XDP features flag
  2022-12-20  0:20       ` Stanislav Fomichev
@ 2022-12-20 10:11         ` Lorenzo Bianconi
  2022-12-20 18:03           ` Stanislav Fomichev
  0 siblings, 1 reply; 27+ messages in thread
From: Lorenzo Bianconi @ 2022-12-20 10:11 UTC (permalink / raw)
  To: Stanislav Fomichev
  Cc: Marek Majtyka, Lorenzo Bianconi, bpf, netdev, ast, daniel, andrii,
	davem, kuba, hawk, pabeni, edumazet, toke, memxor, saeedm,
	anthony.l.nguyen, gospo, vladimir.oltean, nbd, john, leon,
	simon.horman, aelior, christophe.jaillet, ecree.xilinx,
	grygorii.strashko, mst, bjorn, magnus.karlsson,
	maciej.fijalkowski, intel-wired-lan

[-- Attachment #1: Type: text/plain, Size: 18761 bytes --]

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
> >>
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [RFC bpf-next 2/8] net: introduce XDP features flag
  2022-12-20 10:11         ` Lorenzo Bianconi
@ 2022-12-20 18:03           ` Stanislav Fomichev
  2022-12-20 22:25             ` Lorenzo Bianconi
  0 siblings, 1 reply; 27+ messages in thread
From: Stanislav Fomichev @ 2022-12-20 18:03 UTC (permalink / raw)
  To: Lorenzo Bianconi
  Cc: Marek Majtyka, Lorenzo Bianconi, bpf, netdev, ast, daniel, andrii,
	davem, kuba, hawk, pabeni, edumazet, toke, memxor, saeedm,
	anthony.l.nguyen, gospo, vladimir.oltean, nbd, john, leon,
	simon.horman, aelior, christophe.jaillet, ecree.xilinx,
	grygorii.strashko, mst, bjorn, magnus.karlsson,
	maciej.fijalkowski, intel-wired-lan

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
> > >>
> >

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [RFC bpf-next 2/8] net: introduce XDP features flag
  2022-12-20 18:03           ` Stanislav Fomichev
@ 2022-12-20 22:25             ` Lorenzo Bianconi
  2022-12-20 23:36               ` Stanislav Fomichev
  0 siblings, 1 reply; 27+ messages in thread
From: Lorenzo Bianconi @ 2022-12-20 22:25 UTC (permalink / raw)
  To: Stanislav Fomichev
  Cc: Lorenzo Bianconi, Marek Majtyka, bpf, netdev, ast, daniel, andrii,
	davem, kuba, hawk, pabeni, edumazet, toke, memxor, saeedm,
	anthony.l.nguyen, gospo, vladimir.oltean, nbd, john, leon,
	simon.horman, aelior, christophe.jaillet, ecree.xilinx,
	grygorii.strashko, mst, bjorn, magnus.karlsson,
	maciej.fijalkowski, intel-wired-lan

[-- Attachment #1: Type: text/plain, Size: 22364 bytes --]

> 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
> > > >>
> > >

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [RFC bpf-next 2/8] net: introduce XDP features flag
  2022-12-20  9:20     ` Lorenzo Bianconi
@ 2022-12-20 22:51       ` Marek Majtyka
  2022-12-20 23:39         ` Jakub Kicinski
  0 siblings, 1 reply; 27+ messages in thread
From: Marek Majtyka @ 2022-12-20 22:51 UTC (permalink / raw)
  To: Lorenzo Bianconi
  Cc: Jakub Kicinski, Lorenzo Bianconi, bpf, netdev, ast, daniel,
	andrii, davem, hawk, pabeni, edumazet, toke, memxor, saeedm,
	anthony.l.nguyen, gospo, vladimir.oltean, nbd, john, leon,
	simon.horman, aelior, christophe.jaillet, ecree.xilinx,
	grygorii.strashko, mst, bjorn, magnus.karlsson,
	maciej.fijalkowski, intel-wired-lan

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

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [RFC bpf-next 2/8] net: introduce XDP features flag
  2022-12-20 22:25             ` Lorenzo Bianconi
@ 2022-12-20 23:36               ` Stanislav Fomichev
  2022-12-21 10:39                 ` Lorenzo Bianconi
  0 siblings, 1 reply; 27+ messages in thread
From: Stanislav Fomichev @ 2022-12-20 23:36 UTC (permalink / raw)
  To: Lorenzo Bianconi
  Cc: Lorenzo Bianconi, Marek Majtyka, bpf, netdev, ast, daniel, andrii,
	davem, kuba, hawk, pabeni, edumazet, toke, memxor, saeedm,
	anthony.l.nguyen, gospo, vladimir.oltean, nbd, john, leon,
	simon.horman, aelior, christophe.jaillet, ecree.xilinx,
	grygorii.strashko, mst, bjorn, magnus.karlsson,
	maciej.fijalkowski, intel-wired-lan

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
> > > > >>
> > > >

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [RFC bpf-next 2/8] net: introduce XDP features flag
  2022-12-20 22:51       ` Marek Majtyka
@ 2022-12-20 23:39         ` Jakub Kicinski
  2022-12-21  4:41           ` Jakub Kicinski
  0 siblings, 1 reply; 27+ messages in thread
From: Jakub Kicinski @ 2022-12-20 23:39 UTC (permalink / raw)
  To: Marek Majtyka
  Cc: Lorenzo Bianconi, Lorenzo Bianconi, bpf, netdev, ast, daniel,
	andrii, davem, hawk, pabeni, edumazet, toke, memxor, saeedm,
	anthony.l.nguyen, gospo, vladimir.oltean, nbd, john, leon,
	simon.horman, aelior, christophe.jaillet, ecree.xilinx,
	grygorii.strashko, mst, bjorn, magnus.karlsson,
	maciej.fijalkowski, intel-wired-lan

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 ...

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [RFC bpf-next 6/8] libbpf: add API to get XDP/XSK supported features
  2022-12-19 15:41 ` [RFC bpf-next 6/8] libbpf: add API to get XDP/XSK supported features Lorenzo Bianconi
@ 2022-12-21  0:18   ` Andrii Nakryiko
  2023-01-10 17:26     ` Lorenzo Bianconi
  0 siblings, 1 reply; 27+ messages in thread
From: Andrii Nakryiko @ 2022-12-21  0:18 UTC (permalink / raw)
  To: Lorenzo Bianconi
  Cc: bpf, netdev, ast, daniel, andrii, davem, kuba, hawk, pabeni,
	edumazet, toke, memxor, alardam, saeedm, anthony.l.nguyen, gospo,
	vladimir.oltean, nbd, john, leon, simon.horman, aelior,
	christophe.jaillet, ecree.xilinx, grygorii.strashko, mst, bjorn,
	magnus.karlsson, maciej.fijalkowski, intel-wired-lan,
	lorenzo.bianconi

On Mon, Dec 19, 2022 at 7:42 AM Lorenzo Bianconi <lorenzo@kernel.org> wrote:
>
> From: Kumar Kartikeya Dwivedi <memxor@gmail.com>
>
> Add functions to get XDP/XSK supported function of netdev over route
> netlink interface. These functions provide functionalities that are
> going to be used in upcoming change.
>
> The newly added bpf_xdp_query_features takes a fflags_cnt parameter,
> which denotes the number of elements in the output fflags array. This
> must be at least 1 and maybe greater than XDP_FEATURES_WORDS. The
> function only writes to words which is min of fflags_cnt and
> XDP_FEATURES_WORDS.
>
> Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org>
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> Co-developed-by: Marek Majtyka <alardam@gmail.com>
> Signed-off-by: Marek Majtyka <alardam@gmail.com>
> Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
> ---
>  tools/lib/bpf/libbpf.h   |  1 +
>  tools/lib/bpf/libbpf.map |  1 +
>  tools/lib/bpf/netlink.c  | 62 ++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 64 insertions(+)
>
> diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
> index eee883f007f9..9d102eb5007e 100644
> --- a/tools/lib/bpf/libbpf.h
> +++ b/tools/lib/bpf/libbpf.h
> @@ -967,6 +967,7 @@ LIBBPF_API int bpf_xdp_detach(int ifindex, __u32 flags,
>                               const struct bpf_xdp_attach_opts *opts);
>  LIBBPF_API int bpf_xdp_query(int ifindex, int flags, struct bpf_xdp_query_opts *opts);
>  LIBBPF_API int bpf_xdp_query_id(int ifindex, int flags, __u32 *prog_id);
> +LIBBPF_API int bpf_xdp_query_features(int ifindex, __u32 *fflags, __u32 *fflags_cnt);

no need to add new API, just extend bpf_xdp_query()?

>
>  /* TC related API */
>  enum bpf_tc_attach_point {
> diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map
> index 71bf5691a689..9c2abb58fa4b 100644
> --- a/tools/lib/bpf/libbpf.map
> +++ b/tools/lib/bpf/libbpf.map
> @@ -362,6 +362,7 @@ LIBBPF_1.0.0 {
>                 bpf_program__set_autoattach;
>                 btf__add_enum64;
>                 btf__add_enum64_value;
> +               bpf_xdp_query_features;
>                 libbpf_bpf_attach_type_str;
>                 libbpf_bpf_link_type_str;
>                 libbpf_bpf_map_type_str;

[...]

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [RFC bpf-next 2/8] net: introduce XDP features flag
  2022-12-20 23:39         ` Jakub Kicinski
@ 2022-12-21  4:41           ` Jakub Kicinski
  2022-12-21 10:47             ` Lorenzo Bianconi
  0 siblings, 1 reply; 27+ messages in thread
From: Jakub Kicinski @ 2022-12-21  4:41 UTC (permalink / raw)
  To: Marek Majtyka, Lorenzo Bianconi
  Cc: Lorenzo Bianconi, bpf, netdev, ast, daniel, andrii, davem, hawk,
	pabeni, edumazet, toke, memxor, saeedm, anthony.l.nguyen, gospo,
	vladimir.oltean, nbd, john, leon, simon.horman, aelior,
	christophe.jaillet, ecree.xilinx, grygorii.strashko, mst, bjorn,
	magnus.karlsson, maciej.fijalkowski, intel-wired-lan

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.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [RFC bpf-next 2/8] net: introduce XDP features flag
  2022-12-20 23:36               ` Stanislav Fomichev
@ 2022-12-21 10:39                 ` Lorenzo Bianconi
  2022-12-21 17:50                   ` Stanislav Fomichev
  0 siblings, 1 reply; 27+ messages in thread
From: Lorenzo Bianconi @ 2022-12-21 10:39 UTC (permalink / raw)
  To: Stanislav Fomichev
  Cc: Lorenzo Bianconi, Marek Majtyka, bpf, netdev, ast, daniel, andrii,
	davem, kuba, hawk, pabeni, edumazet, toke, memxor, saeedm,
	anthony.l.nguyen, gospo, vladimir.oltean, nbd, john, leon,
	simon.horman, aelior, christophe.jaillet, ecree.xilinx,
	grygorii.strashko, mst, bjorn, magnus.karlsson,
	maciej.fijalkowski, intel-wired-lan

[-- Attachment #1: Type: text/plain, Size: 22025 bytes --]

[...]
> 
> 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
> > > > > >>
> > > > >

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [RFC bpf-next 2/8] net: introduce XDP features flag
  2022-12-21  4:41           ` Jakub Kicinski
@ 2022-12-21 10:47             ` Lorenzo Bianconi
  0 siblings, 0 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2022-12-21 10:47 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: Marek Majtyka, Lorenzo Bianconi, bpf, netdev, ast, daniel, andrii,
	davem, hawk, pabeni, edumazet, toke, memxor, saeedm,
	anthony.l.nguyen, gospo, vladimir.oltean, nbd, john, leon,
	simon.horman, aelior, christophe.jaillet, ecree.xilinx,
	grygorii.strashko, mst, bjorn, magnus.karlsson,
	maciej.fijalkowski, intel-wired-lan

[-- Attachment #1: Type: text/plain, Size: 715 bytes --]

> 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

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [RFC bpf-next 2/8] net: introduce XDP features flag
  2022-12-21 10:39                 ` Lorenzo Bianconi
@ 2022-12-21 17:50                   ` Stanislav Fomichev
  0 siblings, 0 replies; 27+ messages in thread
From: Stanislav Fomichev @ 2022-12-21 17:50 UTC (permalink / raw)
  To: Lorenzo Bianconi
  Cc: Lorenzo Bianconi, Marek Majtyka, bpf, netdev, ast, daniel, andrii,
	davem, kuba, hawk, pabeni, edumazet, toke, memxor, saeedm,
	anthony.l.nguyen, gospo, vladimir.oltean, nbd, john, leon,
	simon.horman, aelior, christophe.jaillet, ecree.xilinx,
	grygorii.strashko, mst, bjorn, magnus.karlsson,
	maciej.fijalkowski, intel-wired-lan

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
> > > > > > >>
> > > > > >

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [RFC bpf-next 6/8] libbpf: add API to get XDP/XSK supported features
  2022-12-21  0:18   ` Andrii Nakryiko
@ 2023-01-10 17:26     ` Lorenzo Bianconi
  2023-01-13 18:22       ` Andrii Nakryiko
  0 siblings, 1 reply; 27+ messages in thread
From: Lorenzo Bianconi @ 2023-01-10 17:26 UTC (permalink / raw)
  To: Andrii Nakryiko
  Cc: bpf, netdev, ast, daniel, andrii, davem, kuba, hawk, pabeni,
	edumazet, toke, memxor, alardam, saeedm, anthony.l.nguyen, gospo,
	vladimir.oltean, nbd, john, leon, simon.horman, aelior,
	christophe.jaillet, ecree.xilinx, grygorii.strashko, mst, bjorn,
	magnus.karlsson, maciej.fijalkowski, intel-wired-lan,
	lorenzo.bianconi

[-- Attachment #1: Type: text/plain, Size: 2924 bytes --]

> On Mon, Dec 19, 2022 at 7:42 AM Lorenzo Bianconi <lorenzo@kernel.org> wrote:
> >
> > From: Kumar Kartikeya Dwivedi <memxor@gmail.com>
> >
> > Add functions to get XDP/XSK supported function of netdev over route
> > netlink interface. These functions provide functionalities that are
> > going to be used in upcoming change.
> >
> > The newly added bpf_xdp_query_features takes a fflags_cnt parameter,
> > which denotes the number of elements in the output fflags array. This
> > must be at least 1 and maybe greater than XDP_FEATURES_WORDS. The
> > function only writes to words which is min of fflags_cnt and
> > XDP_FEATURES_WORDS.
> >
> > Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org>
> > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> > Co-developed-by: Marek Majtyka <alardam@gmail.com>
> > Signed-off-by: Marek Majtyka <alardam@gmail.com>
> > Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
> > ---
> >  tools/lib/bpf/libbpf.h   |  1 +
> >  tools/lib/bpf/libbpf.map |  1 +
> >  tools/lib/bpf/netlink.c  | 62 ++++++++++++++++++++++++++++++++++++++++
> >  3 files changed, 64 insertions(+)
> >
> > diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
> > index eee883f007f9..9d102eb5007e 100644
> > --- a/tools/lib/bpf/libbpf.h
> > +++ b/tools/lib/bpf/libbpf.h
> > @@ -967,6 +967,7 @@ LIBBPF_API int bpf_xdp_detach(int ifindex, __u32 flags,
> >                               const struct bpf_xdp_attach_opts *opts);
> >  LIBBPF_API int bpf_xdp_query(int ifindex, int flags, struct bpf_xdp_query_opts *opts);
> >  LIBBPF_API int bpf_xdp_query_id(int ifindex, int flags, __u32 *prog_id);
> > +LIBBPF_API int bpf_xdp_query_features(int ifindex, __u32 *fflags, __u32 *fflags_cnt);
> 
> no need to add new API, just extend bpf_xdp_query()?

Hi Andrii,

AFAIK libbpf supports just NETLINK_ROUTE protocol. In order to connect with the
genl family code shared by Jakub we need to add NETLINK_GENERIC protocol support
to libbf. Is it ok to introduce a libmnl or libnl dependency in libbpf or do you
prefer to add open code to just what we need?
I guess we should have a dedicated API to dump xdp features in this case since
all the other code relies on NETLINK_ROUTE protocol. What do you think?

Regards,
Lorenzo

> 
> >
> >  /* TC related API */
> >  enum bpf_tc_attach_point {
> > diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map
> > index 71bf5691a689..9c2abb58fa4b 100644
> > --- a/tools/lib/bpf/libbpf.map
> > +++ b/tools/lib/bpf/libbpf.map
> > @@ -362,6 +362,7 @@ LIBBPF_1.0.0 {
> >                 bpf_program__set_autoattach;
> >                 btf__add_enum64;
> >                 btf__add_enum64_value;
> > +               bpf_xdp_query_features;
> >                 libbpf_bpf_attach_type_str;
> >                 libbpf_bpf_link_type_str;
> >                 libbpf_bpf_map_type_str;
> 
> [...]

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [RFC bpf-next 6/8] libbpf: add API to get XDP/XSK supported features
  2023-01-10 17:26     ` Lorenzo Bianconi
@ 2023-01-13 18:22       ` Andrii Nakryiko
  2023-01-14 15:33         ` Lorenzo Bianconi
  0 siblings, 1 reply; 27+ messages in thread
From: Andrii Nakryiko @ 2023-01-13 18:22 UTC (permalink / raw)
  To: Lorenzo Bianconi
  Cc: bpf, netdev, ast, daniel, andrii, davem, kuba, hawk, pabeni,
	edumazet, toke, memxor, alardam, saeedm, anthony.l.nguyen, gospo,
	vladimir.oltean, nbd, john, leon, simon.horman, aelior,
	christophe.jaillet, ecree.xilinx, grygorii.strashko, mst, bjorn,
	magnus.karlsson, maciej.fijalkowski, intel-wired-lan,
	lorenzo.bianconi

On Tue, Jan 10, 2023 at 9:26 AM Lorenzo Bianconi <lorenzo@kernel.org> wrote:
>
> > On Mon, Dec 19, 2022 at 7:42 AM Lorenzo Bianconi <lorenzo@kernel.org> wrote:
> > >
> > > From: Kumar Kartikeya Dwivedi <memxor@gmail.com>
> > >
> > > Add functions to get XDP/XSK supported function of netdev over route
> > > netlink interface. These functions provide functionalities that are
> > > going to be used in upcoming change.
> > >
> > > The newly added bpf_xdp_query_features takes a fflags_cnt parameter,
> > > which denotes the number of elements in the output fflags array. This
> > > must be at least 1 and maybe greater than XDP_FEATURES_WORDS. The
> > > function only writes to words which is min of fflags_cnt and
> > > XDP_FEATURES_WORDS.
> > >
> > > Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org>
> > > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> > > Co-developed-by: Marek Majtyka <alardam@gmail.com>
> > > Signed-off-by: Marek Majtyka <alardam@gmail.com>
> > > Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
> > > ---
> > >  tools/lib/bpf/libbpf.h   |  1 +
> > >  tools/lib/bpf/libbpf.map |  1 +
> > >  tools/lib/bpf/netlink.c  | 62 ++++++++++++++++++++++++++++++++++++++++
> > >  3 files changed, 64 insertions(+)
> > >
> > > diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
> > > index eee883f007f9..9d102eb5007e 100644
> > > --- a/tools/lib/bpf/libbpf.h
> > > +++ b/tools/lib/bpf/libbpf.h
> > > @@ -967,6 +967,7 @@ LIBBPF_API int bpf_xdp_detach(int ifindex, __u32 flags,
> > >                               const struct bpf_xdp_attach_opts *opts);
> > >  LIBBPF_API int bpf_xdp_query(int ifindex, int flags, struct bpf_xdp_query_opts *opts);
> > >  LIBBPF_API int bpf_xdp_query_id(int ifindex, int flags, __u32 *prog_id);
> > > +LIBBPF_API int bpf_xdp_query_features(int ifindex, __u32 *fflags, __u32 *fflags_cnt);
> >
> > no need to add new API, just extend bpf_xdp_query()?
>
> Hi Andrii,
>
> AFAIK libbpf supports just NETLINK_ROUTE protocol. In order to connect with the
> genl family code shared by Jakub we need to add NETLINK_GENERIC protocol support
> to libbf. Is it ok to introduce a libmnl or libnl dependency in libbpf or do you
> prefer to add open code to just what we need?

I'd very much like to avoid any extra dependencies. But I also have no
clue how much new code we are talking about, tbh. Either way, the less
dependencies, the better, if the result is an acceptable amount of
extra code to maintain.

> I guess we should have a dedicated API to dump xdp features in this case since
> all the other code relies on NETLINK_ROUTE protocol. What do you think?
>

From API standpoint it looks like an extension to bpf_xdp_query()
family of APIs, which is already extendable through opts. Which is why
I suggested that there is no need for new API. NETLINK_ROUTE vs
NETLINK_GENERIC seems like an internal implementation detail (but
again, I spent literally zero time trying to understand what's going
on here).

> Regards,
> Lorenzo
>
> >
> > >
> > >  /* TC related API */
> > >  enum bpf_tc_attach_point {
> > > diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map
> > > index 71bf5691a689..9c2abb58fa4b 100644
> > > --- a/tools/lib/bpf/libbpf.map
> > > +++ b/tools/lib/bpf/libbpf.map
> > > @@ -362,6 +362,7 @@ LIBBPF_1.0.0 {
> > >                 bpf_program__set_autoattach;
> > >                 btf__add_enum64;
> > >                 btf__add_enum64_value;
> > > +               bpf_xdp_query_features;
> > >                 libbpf_bpf_attach_type_str;
> > >                 libbpf_bpf_link_type_str;
> > >                 libbpf_bpf_map_type_str;
> >
> > [...]

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [RFC bpf-next 6/8] libbpf: add API to get XDP/XSK supported features
  2023-01-13 18:22       ` Andrii Nakryiko
@ 2023-01-14 15:33         ` Lorenzo Bianconi
  0 siblings, 0 replies; 27+ messages in thread
From: Lorenzo Bianconi @ 2023-01-14 15:33 UTC (permalink / raw)
  To: Andrii Nakryiko
  Cc: Lorenzo Bianconi, bpf, netdev, ast, daniel, andrii, davem, kuba,
	hawk, pabeni, edumazet, toke, memxor, alardam, saeedm,
	anthony.l.nguyen, gospo, vladimir.oltean, nbd, john, leon,
	simon.horman, aelior, christophe.jaillet, ecree.xilinx,
	grygorii.strashko, mst, bjorn, magnus.karlsson,
	maciej.fijalkowski, intel-wired-lan

[-- Attachment #1: Type: text/plain, Size: 4135 bytes --]

> On Tue, Jan 10, 2023 at 9:26 AM Lorenzo Bianconi <lorenzo@kernel.org> wrote:
> >
> > > On Mon, Dec 19, 2022 at 7:42 AM Lorenzo Bianconi <lorenzo@kernel.org> wrote:
> > > >
> > > > From: Kumar Kartikeya Dwivedi <memxor@gmail.com>
> > > >
> > > > Add functions to get XDP/XSK supported function of netdev over route
> > > > netlink interface. These functions provide functionalities that are
> > > > going to be used in upcoming change.
> > > >
> > > > The newly added bpf_xdp_query_features takes a fflags_cnt parameter,
> > > > which denotes the number of elements in the output fflags array. This
> > > > must be at least 1 and maybe greater than XDP_FEATURES_WORDS. The
> > > > function only writes to words which is min of fflags_cnt and
> > > > XDP_FEATURES_WORDS.
> > > >
> > > > Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org>
> > > > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> > > > Co-developed-by: Marek Majtyka <alardam@gmail.com>
> > > > Signed-off-by: Marek Majtyka <alardam@gmail.com>
> > > > Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
> > > > ---
> > > >  tools/lib/bpf/libbpf.h   |  1 +
> > > >  tools/lib/bpf/libbpf.map |  1 +
> > > >  tools/lib/bpf/netlink.c  | 62 ++++++++++++++++++++++++++++++++++++++++
> > > >  3 files changed, 64 insertions(+)
> > > >
> > > > diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
> > > > index eee883f007f9..9d102eb5007e 100644
> > > > --- a/tools/lib/bpf/libbpf.h
> > > > +++ b/tools/lib/bpf/libbpf.h
> > > > @@ -967,6 +967,7 @@ LIBBPF_API int bpf_xdp_detach(int ifindex, __u32 flags,
> > > >                               const struct bpf_xdp_attach_opts *opts);
> > > >  LIBBPF_API int bpf_xdp_query(int ifindex, int flags, struct bpf_xdp_query_opts *opts);
> > > >  LIBBPF_API int bpf_xdp_query_id(int ifindex, int flags, __u32 *prog_id);
> > > > +LIBBPF_API int bpf_xdp_query_features(int ifindex, __u32 *fflags, __u32 *fflags_cnt);
> > >
> > > no need to add new API, just extend bpf_xdp_query()?
> >
> > Hi Andrii,
> >
> > AFAIK libbpf supports just NETLINK_ROUTE protocol. In order to connect with the
> > genl family code shared by Jakub we need to add NETLINK_GENERIC protocol support
> > to libbf. Is it ok to introduce a libmnl or libnl dependency in libbpf or do you
> > prefer to add open code to just what we need?
> 
> I'd very much like to avoid any extra dependencies. But I also have no
> clue how much new code we are talking about, tbh. Either way, the less
> dependencies, the better, if the result is an acceptable amount of
> extra code to maintain.

ack, I avoided to introduce an extra dependencies since most of the protocol
is already implemented in libbpf and I added just few code.

> 
> > I guess we should have a dedicated API to dump xdp features in this case since
> > all the other code relies on NETLINK_ROUTE protocol. What do you think?
> >
> 
> From API standpoint it looks like an extension to bpf_xdp_query()
> family of APIs, which is already extendable through opts. Which is why
> I suggested that there is no need for new API. NETLINK_ROUTE vs
> NETLINK_GENERIC seems like an internal implementation detail (but
> again, I spent literally zero time trying to understand what's going
> on here).

ack, I extended bpf_xdp_query routine instead of adding a new API.

Regards,
Lorenzo

> 
> > Regards,
> > Lorenzo
> >
> > >
> > > >
> > > >  /* TC related API */
> > > >  enum bpf_tc_attach_point {
> > > > diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map
> > > > index 71bf5691a689..9c2abb58fa4b 100644
> > > > --- a/tools/lib/bpf/libbpf.map
> > > > +++ b/tools/lib/bpf/libbpf.map
> > > > @@ -362,6 +362,7 @@ LIBBPF_1.0.0 {
> > > >                 bpf_program__set_autoattach;
> > > >                 btf__add_enum64;
> > > >                 btf__add_enum64_value;
> > > > +               bpf_xdp_query_features;
> > > >                 libbpf_bpf_attach_type_str;
> > > >                 libbpf_bpf_link_type_str;
> > > >                 libbpf_bpf_map_type_str;
> > >
> > > [...]
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2023-01-14 15:33 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-12-19 15:41 [RFC bpf-next 0/8] xdp: introduce xdp-feature support Lorenzo Bianconi
2022-12-19 15:41 ` [RFC bpf-next 1/8] tools: uapi: align if_link.h Lorenzo Bianconi
2022-12-19 15:41 ` [RFC bpf-next 2/8] net: introduce XDP features flag Lorenzo Bianconi
2022-12-19 20:03   ` sdf
     [not found]     ` <CAAOQfrFGArAYPyBX_kw4ZvFrTjKXf-jG-2F2y69nOs-oQ8Onwg@mail.gmail.com>
2022-12-20  0:20       ` Stanislav Fomichev
2022-12-20 10:11         ` Lorenzo Bianconi
2022-12-20 18:03           ` Stanislav Fomichev
2022-12-20 22:25             ` Lorenzo Bianconi
2022-12-20 23:36               ` Stanislav Fomichev
2022-12-21 10:39                 ` Lorenzo Bianconi
2022-12-21 17:50                   ` Stanislav Fomichev
2022-12-20  1:13   ` Jakub Kicinski
2022-12-20  9:20     ` Lorenzo Bianconi
2022-12-20 22:51       ` Marek Majtyka
2022-12-20 23:39         ` Jakub Kicinski
2022-12-21  4:41           ` Jakub Kicinski
2022-12-21 10:47             ` Lorenzo Bianconi
2022-12-19 15:41 ` [RFC bpf-next 3/8] drivers: net: turn on XDP features Lorenzo Bianconi
2022-12-19 15:41 ` [RFC bpf-next 4/8] xsk: add usage of XDP features flags Lorenzo Bianconi
2022-12-19 15:41 ` [RFC bpf-next 5/8] xsk: add check for full support of XDP in bind Lorenzo Bianconi
2022-12-19 15:41 ` [RFC bpf-next 6/8] libbpf: add API to get XDP/XSK supported features Lorenzo Bianconi
2022-12-21  0:18   ` Andrii Nakryiko
2023-01-10 17:26     ` Lorenzo Bianconi
2023-01-13 18:22       ` Andrii Nakryiko
2023-01-14 15:33         ` Lorenzo Bianconi
2022-12-19 15:41 ` [RFC bpf-next 7/8] bpf: devmap: check XDP features in bpf_map_update_elem and __xdp_enqueue Lorenzo Bianconi
2022-12-19 15:41 ` [RFC bpf-next 8/8] selftests/bpf: introduce XDP compliance test tool Lorenzo Bianconi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).