[RFC net-next 0/8] xdp: offload mode

STALE3409d

Revision rfc of 2 in this series.

20 messages, 3 authors, 2017-06-20 · open the first message on its own page

[RFC net-next 0/8] xdp: offload mode

From: Jakub Kicinski <hidden>
Date: 2017-06-16 23:58:24

Hi!

This set adds XDP flag for forcing offload and a attachement mode
for reporting to user space that program has been offloaded.  The
nfp driver is modified to make use of the new flags, but also to
adhere to the DRV_MODE flag which should disable the HW offload.

Note that the NFP driver currently claims XDP offload support but 
lacks most basic features like direct packet access.

Jakub Kicinski (8):
  xdp: pass XDP flags into install handlers
  xdp: add HW offload mode flag for installing programs
  nfp: xdp: move driver XDP setup into a separate function
  nfp: bpf: don't offload XDP programs in DRV_MODE
  nfp: bpf: take a reference on offloaded programs
  nfp: bpf: add support for XDP_FLAGS_HW_MODE
  xdp: add reporting of offload mode
  nfp: xdp: report if program is offloaded

 drivers/net/ethernet/netronome/nfp/nfp_net.h       |  5 ++
 .../net/ethernet/netronome/nfp/nfp_net_common.c    | 53 ++++++++++++++++------
 include/linux/netdevice.h                          |  8 ++--
 include/uapi/linux/if_link.h                       |  8 +++-
 net/core/dev.c                                     | 10 ++--
 net/core/rtnetlink.c                               | 10 ++--
 6 files changed, 66 insertions(+), 28 deletions(-)

-- 
2.11.0

[RFC net-next 1/8] xdp: pass XDP flags into install handlers

From: Jakub Kicinski <hidden>
Date: 2017-06-16 23:58:25

Pass XDP flags to the xdp ndo.  This will allow drivers to look
at the mode flags and make decisions about offload.

Signed-off-by: Jakub Kicinski <redacted>
---
 include/linux/netdevice.h | 1 +
 net/core/dev.c            | 5 +++--
 2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 7c7118b3bd69..b194817631de 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -820,6 +820,7 @@ struct netdev_xdp {
 	union {
 		/* XDP_SETUP_PROG */
 		struct {
+			u32 flags;
 			struct bpf_prog *prog;
 			struct netlink_ext_ack *extack;
 		};
diff --git a/net/core/dev.c b/net/core/dev.c
index b8d6dd9e8b5c..a04db264aa1c 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -6953,7 +6953,7 @@ bool __dev_xdp_attached(struct net_device *dev, xdp_op_t xdp_op,
 }
 
 static int dev_xdp_install(struct net_device *dev, xdp_op_t xdp_op,
-			   struct netlink_ext_ack *extack,
+			   struct netlink_ext_ack *extack, u32 flags,
 			   struct bpf_prog *prog)
 {
 	struct netdev_xdp xdp;
@@ -6961,6 +6961,7 @@ static int dev_xdp_install(struct net_device *dev, xdp_op_t xdp_op,
 	memset(&xdp, 0, sizeof(xdp));
 	xdp.command = XDP_SETUP_PROG;
 	xdp.extack = extack;
+	xdp.flags = flags;
 	xdp.prog = prog;
 
 	return xdp_op(dev, &xdp);
@@ -7005,7 +7006,7 @@ int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
 			return PTR_ERR(prog);
 	}
 
-	err = dev_xdp_install(dev, xdp_op, extack, prog);
+	err = dev_xdp_install(dev, xdp_op, extack, flags, prog);
 	if (err < 0 && prog)
 		bpf_prog_put(prog);
 
-- 
2.11.0

[RFC net-next 2/8] xdp: add HW offload mode flag for installing programs

From: Jakub Kicinski <hidden>
Date: 2017-06-16 23:58:25

Add an installation-time flag for requesting that the program
be installed only if it can be offloaded to HW.

Internally new command for ndo_xdp is added, this way we avoid
putting checks into drivers since they all return -EINVAL on
an unknown command.

Signed-off-by: Jakub Kicinski <redacted>
---
 include/linux/netdevice.h    | 1 +
 include/uapi/linux/if_link.h | 7 +++++--
 net/core/dev.c               | 7 +++++--
 net/core/rtnetlink.c         | 4 ++--
 4 files changed, 13 insertions(+), 6 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index b194817631de..a838591aad28 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -807,6 +807,7 @@ enum xdp_netdev_command {
 	 * when it is no longer used.
 	 */
 	XDP_SETUP_PROG,
+	XDP_SETUP_PROG_HW,
 	/* Check if a bpf program is set on the device.  The callee should
 	 * return true if a program is currently attached and running.
 	 */
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index dd88375a6580..ce777ec88e1e 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -891,9 +891,12 @@ enum {
 #define XDP_FLAGS_UPDATE_IF_NOEXIST	(1U << 0)
 #define XDP_FLAGS_SKB_MODE		(1U << 1)
 #define XDP_FLAGS_DRV_MODE		(1U << 2)
+#define XDP_FLAGS_HW_MODE		(1U << 3)
+#define XDP_FLAGS_MODES			(XDP_FLAGS_SKB_MODE | \
+					 XDP_FLAGS_DRV_MODE | \
+					 XDP_FLAGS_HW_MODE)
 #define XDP_FLAGS_MASK			(XDP_FLAGS_UPDATE_IF_NOEXIST | \
-					 XDP_FLAGS_SKB_MODE | \
-					 XDP_FLAGS_DRV_MODE)
+					 XDP_FLAGS_MODES)
 
 /* These are stored into IFLA_XDP_ATTACHED on dump. */
 enum {
diff --git a/net/core/dev.c b/net/core/dev.c
index a04db264aa1c..05cec8e2cd82 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -6959,7 +6959,10 @@ static int dev_xdp_install(struct net_device *dev, xdp_op_t xdp_op,
 	struct netdev_xdp xdp;
 
 	memset(&xdp, 0, sizeof(xdp));
-	xdp.command = XDP_SETUP_PROG;
+	if (flags & XDP_FLAGS_HW_MODE)
+		xdp.command = XDP_SETUP_PROG_HW;
+	else
+		xdp.command = XDP_SETUP_PROG;
 	xdp.extack = extack;
 	xdp.flags = flags;
 	xdp.prog = prog;
@@ -6987,7 +6990,7 @@ int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
 	ASSERT_RTNL();
 
 	xdp_op = xdp_chk = ops->ndo_xdp;
-	if (!xdp_op && (flags & XDP_FLAGS_DRV_MODE))
+	if (!xdp_op && (flags & (XDP_FLAGS_DRV_MODE | XDP_FLAGS_HW_MODE)))
 		return -EOPNOTSUPP;
 	if (!xdp_op || (flags & XDP_FLAGS_SKB_MODE))
 		xdp_op = generic_xdp_install;
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 3aa57848a895..daf3b39be649 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -16,6 +16,7 @@
  *	Vitaly E. Lavrov		RTA_OK arithmetics was wrong.
  */
 
+#include <linux/bitops.h>
 #include <linux/errno.h>
 #include <linux/module.h>
 #include <linux/types.h>
@@ -2251,8 +2252,7 @@ static int do_setlink(const struct sk_buff *skb,
 				err = -EINVAL;
 				goto errout;
 			}
-			if ((xdp_flags & XDP_FLAGS_SKB_MODE) &&
-			    (xdp_flags & XDP_FLAGS_DRV_MODE)) {
+			if (hweight32(xdp_flags & XDP_FLAGS_MODES) > 1) {
 				err = -EINVAL;
 				goto errout;
 			}
-- 
2.11.0

[RFC net-next 3/8] nfp: xdp: move driver XDP setup into a separate function

From: Jakub Kicinski <hidden>
Date: 2017-06-16 23:58:27

In preparation of XDP offload flags move the driver setup into
a function.  Otherwise the number of conditions in one function
would make it slightly hard to follow.  The offload handler may
now be called with NULL prog, even if no offload is currently
active, but that's fine, offload code can handle that.

Signed-off-by: Jakub Kicinski <redacted>
---
 .../net/ethernet/netronome/nfp/nfp_net_common.c    | 23 +++++++++++++++++-----
 1 file changed, 18 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index 2bdddd1ae666..f2188b9c3628 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -3274,10 +3274,11 @@ static void nfp_net_del_vxlan_port(struct net_device *netdev,
 		nfp_net_set_vxlan_port(nn, idx, 0);
 }
 
-static int nfp_net_xdp_setup(struct nfp_net *nn, struct netdev_xdp *xdp)
+static int
+nfp_net_xdp_setup_drv(struct nfp_net *nn, struct bpf_prog *prog,
+		      struct netlink_ext_ack *extack)
 {
 	struct bpf_prog *old_prog = nn->dp.xdp_prog;
-	struct bpf_prog *prog = xdp->prog;
 	struct nfp_net_dp *dp;
 	int err;
 
@@ -3286,7 +3287,6 @@ static int nfp_net_xdp_setup(struct nfp_net *nn, struct netdev_xdp *xdp)
 	if (prog && nn->dp.xdp_prog) {
 		prog = xchg(&nn->dp.xdp_prog, prog);
 		bpf_prog_put(prog);
-		nfp_app_xdp_offload(nn->app, nn, nn->dp.xdp_prog);
 		return 0;
 	}
 
@@ -3300,13 +3300,26 @@ static int nfp_net_xdp_setup(struct nfp_net *nn, struct netdev_xdp *xdp)
 	dp->rx_dma_off = prog ? XDP_PACKET_HEADROOM - nn->dp.rx_offset : 0;
 
 	/* We need RX reconfig to remap the buffers (BIDIR vs FROM_DEV) */
-	err = nfp_net_ring_reconfig(nn, dp, xdp->extack);
+	err = nfp_net_ring_reconfig(nn, dp, extack);
 	if (err)
 		return err;
 
 	if (old_prog)
 		bpf_prog_put(old_prog);
 
+	return 0;
+}
+
+static int
+nfp_net_xdp_setup(struct nfp_net *nn, struct bpf_prog *prog,
+		  struct netlink_ext_ack *extack)
+{
+	int err;
+
+	err = nfp_net_xdp_setup_drv(nn, prog, extack);
+	if (err)
+		return err;
+
 	nfp_app_xdp_offload(nn->app, nn, nn->dp.xdp_prog);
 
 	return 0;
@@ -3318,7 +3331,7 @@ static int nfp_net_xdp(struct net_device *netdev, struct netdev_xdp *xdp)
 
 	switch (xdp->command) {
 	case XDP_SETUP_PROG:
-		return nfp_net_xdp_setup(nn, xdp);
+		return nfp_net_xdp_setup(nn, xdp->prog, xdp->extack);
 	case XDP_QUERY_PROG:
 		xdp->prog_attached = !!nn->dp.xdp_prog;
 		xdp->prog_id = nn->dp.xdp_prog ? nn->dp.xdp_prog->aux->id : 0;
-- 
2.11.0

[RFC net-next 4/8] nfp: bpf: don't offload XDP programs in DRV_MODE

From: Jakub Kicinski <hidden>
Date: 2017-06-16 23:58:27

DRV_MODE means that user space wants the program to be run in
the driver.  Do not try to offload.  Only offload if no mode
flags have been specified.

Remember what the mode is when the program is installed and refuse
new setup requests if there is already a program loaded in a
different mode.  This should leave it open for us to implement
simultaneous loading of two programs - one in the drv path and
another to the NIC later.

Signed-off-by: Jakub Kicinski <redacted>
---
 drivers/net/ethernet/netronome/nfp/nfp_net.h        |  3 +++
 drivers/net/ethernet/netronome/nfp/nfp_net_common.c | 14 +++++++++++---
 2 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net.h b/drivers/net/ethernet/netronome/nfp/nfp_net.h
index 02fd8d4e253c..7952fbfb94d6 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net.h
@@ -541,6 +541,7 @@ struct nfp_net_dp {
  * @rss_cfg:            RSS configuration
  * @rss_key:            RSS secret key
  * @rss_itbl:           RSS indirection table
+ * @xdp_flags:		Flags with which XDP prog was loaded
  * @max_r_vecs:		Number of allocated interrupt vectors for RX/TX
  * @max_tx_rings:       Maximum number of TX rings supported by the Firmware
  * @max_rx_rings:       Maximum number of RX rings supported by the Firmware
@@ -590,6 +591,8 @@ struct nfp_net {
 	u8 rss_key[NFP_NET_CFG_RSS_KEY_SZ];
 	u8 rss_itbl[NFP_NET_CFG_RSS_ITBL_SZ];
 
+	u32 xdp_flags;
+
 	unsigned int max_tx_rings;
 	unsigned int max_rx_rings;
 
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index f2188b9c3628..9563615cf4b7 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -3311,16 +3311,23 @@ nfp_net_xdp_setup_drv(struct nfp_net *nn, struct bpf_prog *prog,
 }
 
 static int
-nfp_net_xdp_setup(struct nfp_net *nn, struct bpf_prog *prog,
+nfp_net_xdp_setup(struct nfp_net *nn, struct bpf_prog *prog, u32 flags,
 		  struct netlink_ext_ack *extack)
 {
+	struct bpf_prog *offload_prog;
 	int err;
 
+	if (nn->dp.xdp_prog && (flags ^ nn->xdp_flags) & XDP_FLAGS_MODES)
+		return -EBUSY;
+
+	offload_prog = flags & XDP_FLAGS_DRV_MODE ? NULL : prog;
+
 	err = nfp_net_xdp_setup_drv(nn, prog, extack);
 	if (err)
 		return err;
 
-	nfp_app_xdp_offload(nn->app, nn, nn->dp.xdp_prog);
+	nfp_app_xdp_offload(nn->app, nn, offload_prog);
+	nn->xdp_flags = flags;
 
 	return 0;
 }
@@ -3331,7 +3338,8 @@ static int nfp_net_xdp(struct net_device *netdev, struct netdev_xdp *xdp)
 
 	switch (xdp->command) {
 	case XDP_SETUP_PROG:
-		return nfp_net_xdp_setup(nn, xdp->prog, xdp->extack);
+		return nfp_net_xdp_setup(nn, xdp->prog, xdp->flags,
+					 xdp->extack);
 	case XDP_QUERY_PROG:
 		xdp->prog_attached = !!nn->dp.xdp_prog;
 		xdp->prog_id = nn->dp.xdp_prog ? nn->dp.xdp_prog->aux->id : 0;
-- 
2.11.0

[RFC net-next 5/8] nfp: bpf: take a reference on offloaded programs

From: Jakub Kicinski <hidden>
Date: 2017-06-16 23:58:28

The xdp_prog member of the adapter's data path structure is used
for XDP in driver mode.  In case a XDP program is loaded with in
HW-only mode, we need to store it somewhere else.  Add a new XDP
prog pointer in the main structure and use that when we need to
know whether any XDP program is loaded, not only a driver mode
one.  Only release our reference on adapter free instead of
immediately after netdev unregister to allow offload to be disabled
first.

Signed-off-by: Jakub Kicinski <redacted>
---
 drivers/net/ethernet/netronome/nfp/nfp_net.h        |  2 ++
 drivers/net/ethernet/netronome/nfp/nfp_net_common.c | 20 ++++++++++----------
 2 files changed, 12 insertions(+), 10 deletions(-)
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net.h b/drivers/net/ethernet/netronome/nfp/nfp_net.h
index 7952fbfb94d6..b7446793106d 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net.h
@@ -542,6 +542,7 @@ struct nfp_net_dp {
  * @rss_key:            RSS secret key
  * @rss_itbl:           RSS indirection table
  * @xdp_flags:		Flags with which XDP prog was loaded
+ * @xdp_prog:		XDP prog (for ctrl path, both DRV and HW modes)
  * @max_r_vecs:		Number of allocated interrupt vectors for RX/TX
  * @max_tx_rings:       Maximum number of TX rings supported by the Firmware
  * @max_rx_rings:       Maximum number of RX rings supported by the Firmware
@@ -592,6 +593,7 @@ struct nfp_net {
 	u8 rss_itbl[NFP_NET_CFG_RSS_ITBL_SZ];
 
 	u32 xdp_flags;
+	struct bpf_prog *xdp_prog;
 
 	unsigned int max_tx_rings;
 	unsigned int max_rx_rings;
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index 9563615cf4b7..68648e312129 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -3278,7 +3278,6 @@ static int
 nfp_net_xdp_setup_drv(struct nfp_net *nn, struct bpf_prog *prog,
 		      struct netlink_ext_ack *extack)
 {
-	struct bpf_prog *old_prog = nn->dp.xdp_prog;
 	struct nfp_net_dp *dp;
 	int err;
 
@@ -3304,9 +3303,6 @@ nfp_net_xdp_setup_drv(struct nfp_net *nn, struct bpf_prog *prog,
 	if (err)
 		return err;
 
-	if (old_prog)
-		bpf_prog_put(old_prog);
-
 	return 0;
 }
 
@@ -3317,7 +3313,7 @@ nfp_net_xdp_setup(struct nfp_net *nn, struct bpf_prog *prog, u32 flags,
 	struct bpf_prog *offload_prog;
 	int err;
 
-	if (nn->dp.xdp_prog && (flags ^ nn->xdp_flags) & XDP_FLAGS_MODES)
+	if (nn->xdp_prog && (flags ^ nn->xdp_flags) & XDP_FLAGS_MODES)
 		return -EBUSY;
 
 	offload_prog = flags & XDP_FLAGS_DRV_MODE ? NULL : prog;
@@ -3327,6 +3323,10 @@ nfp_net_xdp_setup(struct nfp_net *nn, struct bpf_prog *prog, u32 flags,
 		return err;
 
 	nfp_app_xdp_offload(nn->app, nn, offload_prog);
+
+	if (nn->xdp_prog)
+		bpf_prog_put(nn->xdp_prog);
+	nn->xdp_prog = prog;
 	nn->xdp_flags = flags;
 
 	return 0;
@@ -3341,8 +3341,8 @@ static int nfp_net_xdp(struct net_device *netdev, struct netdev_xdp *xdp)
 		return nfp_net_xdp_setup(nn, xdp->prog, xdp->flags,
 					 xdp->extack);
 	case XDP_QUERY_PROG:
-		xdp->prog_attached = !!nn->dp.xdp_prog;
-		xdp->prog_id = nn->dp.xdp_prog ? nn->dp.xdp_prog->aux->id : 0;
+		xdp->prog_attached = !!nn->xdp_prog;
+		xdp->prog_id = nn->xdp_prog ? nn->xdp_prog->aux->id : 0;
 		return 0;
 	default:
 		return -EINVAL;
@@ -3500,6 +3500,9 @@ struct nfp_net *nfp_net_alloc(struct pci_dev *pdev, bool needs_netdev,
  */
 void nfp_net_free(struct nfp_net *nn)
 {
+	if (nn->xdp_prog)
+		bpf_prog_put(nn->xdp_prog);
+
 	if (nn->dp.netdev)
 		free_netdev(nn->dp.netdev);
 	else
@@ -3757,7 +3760,4 @@ void nfp_net_clean(struct nfp_net *nn)
 		return;
 
 	unregister_netdev(nn->dp.netdev);
-
-	if (nn->dp.xdp_prog)
-		bpf_prog_put(nn->dp.xdp_prog);
 }
-- 
2.11.0

[RFC net-next 6/8] nfp: bpf: add support for XDP_FLAGS_HW_MODE

From: Jakub Kicinski <hidden>
Date: 2017-06-16 23:58:29

Respect the XDP_FLAGS_HW_MODE.  When it's set install the program
on the NIC and skip enabling XDP in the driver.

Signed-off-by: Jakub Kicinski <redacted>
---
 drivers/net/ethernet/netronome/nfp/nfp_net_common.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index 68648e312129..c5903b6e58c5 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -3310,19 +3310,22 @@ static int
 nfp_net_xdp_setup(struct nfp_net *nn, struct bpf_prog *prog, u32 flags,
 		  struct netlink_ext_ack *extack)
 {
-	struct bpf_prog *offload_prog;
+	struct bpf_prog *drv_prog, *offload_prog;
 	int err;
 
 	if (nn->xdp_prog && (flags ^ nn->xdp_flags) & XDP_FLAGS_MODES)
 		return -EBUSY;
 
+	drv_prog     = flags & XDP_FLAGS_HW_MODE  ? NULL : prog;
 	offload_prog = flags & XDP_FLAGS_DRV_MODE ? NULL : prog;
 
-	err = nfp_net_xdp_setup_drv(nn, prog, extack);
+	err = nfp_net_xdp_setup_drv(nn, drv_prog, extack);
 	if (err)
 		return err;
 
-	nfp_app_xdp_offload(nn->app, nn, offload_prog);
+	err = nfp_app_xdp_offload(nn->app, nn, offload_prog);
+	if (err && flags & XDP_FLAGS_HW_MODE)
+		return err;
 
 	if (nn->xdp_prog)
 		bpf_prog_put(nn->xdp_prog);
@@ -3338,6 +3341,7 @@ static int nfp_net_xdp(struct net_device *netdev, struct netdev_xdp *xdp)
 
 	switch (xdp->command) {
 	case XDP_SETUP_PROG:
+	case XDP_SETUP_PROG_HW:
 		return nfp_net_xdp_setup(nn, xdp->prog, xdp->flags,
 					 xdp->extack);
 	case XDP_QUERY_PROG:
-- 
2.11.0

[RFC net-next 8/8] nfp: xdp: report if program is offloaded

From: Jakub Kicinski <hidden>
Date: 2017-06-16 23:58:31

Make use of just added XDP_ATTACHED_HW.

Signed-off-by: Jakub Kicinski <redacted>
---
 drivers/net/ethernet/netronome/nfp/nfp_net_common.c | 2 ++
 1 file changed, 2 insertions(+)
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index c5903b6e58c5..cabd117303e1 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -3346,6 +3346,8 @@ static int nfp_net_xdp(struct net_device *netdev, struct netdev_xdp *xdp)
 					 xdp->extack);
 	case XDP_QUERY_PROG:
 		xdp->prog_attached = !!nn->xdp_prog;
+		if (nn->dp.bpf_offload_xdp)
+			xdp->prog_attached = XDP_ATTACHED_HW;
 		xdp->prog_id = nn->xdp_prog ? nn->xdp_prog->aux->id : 0;
 		return 0;
 	default:
-- 
2.11.0

[RFC net-next 7/8] xdp: add reporting of offload mode

From: Jakub Kicinski <hidden>
Date: 2017-06-16 23:58:35

Extend the XDP_ATTACHED_* values to include offloaded mode.
Let drivers report whether program is installed in the driver
or the HW by changing the prog_attached field from bool to
u8 (type of the netlink attribute).

Exploit the fact that the value of XDP_ATTACHED_DRV is 1,
therefore since all drivers currently assign the mode with
double negation:
       mode = !!xdp_prog;
no drivers have to be modified.

Signed-off-by: Jakub Kicinski <redacted>
---
 include/linux/netdevice.h    | 7 ++++---
 include/uapi/linux/if_link.h | 1 +
 net/core/dev.c               | 3 +--
 net/core/rtnetlink.c         | 6 +++---
 4 files changed, 9 insertions(+), 8 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index a838591aad28..68f5d899d1e6 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -809,7 +809,8 @@ enum xdp_netdev_command {
 	XDP_SETUP_PROG,
 	XDP_SETUP_PROG_HW,
 	/* Check if a bpf program is set on the device.  The callee should
-	 * return true if a program is currently attached and running.
+	 * set @prog_attached to one of XDP_ATTACHED_* values, note that "true"
+	 * is equivalent to XDP_ATTACHED_DRV.
 	 */
 	XDP_QUERY_PROG,
 };
@@ -827,7 +828,7 @@ struct netdev_xdp {
 		};
 		/* XDP_QUERY_PROG */
 		struct {
-			bool prog_attached;
+			u8 prog_attached;
 			u32 prog_id;
 		};
 	};
@@ -3307,7 +3308,7 @@ struct sk_buff *dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
 typedef int (*xdp_op_t)(struct net_device *dev, struct netdev_xdp *xdp);
 int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
 		      int fd, u32 flags);
-bool __dev_xdp_attached(struct net_device *dev, xdp_op_t xdp_op, u32 *prog_id);
+u8 __dev_xdp_attached(struct net_device *dev, xdp_op_t xdp_op, u32 *prog_id);
 
 int __dev_forward_skb(struct net_device *dev, struct sk_buff *skb);
 int dev_forward_skb(struct net_device *dev, struct sk_buff *skb);
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index ce777ec88e1e..8d062c58d5cb 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -903,6 +903,7 @@ enum {
 	XDP_ATTACHED_NONE = 0,
 	XDP_ATTACHED_DRV,
 	XDP_ATTACHED_SKB,
+	XDP_ATTACHED_HW,
 };
 
 enum {
diff --git a/net/core/dev.c b/net/core/dev.c
index 05cec8e2cd82..ad1ecb26e9fa 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -6936,8 +6936,7 @@ int dev_change_proto_down(struct net_device *dev, bool proto_down)
 }
 EXPORT_SYMBOL(dev_change_proto_down);
 
-bool __dev_xdp_attached(struct net_device *dev, xdp_op_t xdp_op,
-			u32 *prog_id)
+u8 __dev_xdp_attached(struct net_device *dev, xdp_op_t xdp_op, u32 *prog_id)
 {
 	struct netdev_xdp xdp;
 
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index daf3b39be649..f0f5b418e52d 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1264,10 +1264,10 @@ static u8 rtnl_xdp_attached_mode(struct net_device *dev, u32 *prog_id)
 		*prog_id = generic_xdp_prog->aux->id;
 		return XDP_ATTACHED_SKB;
 	}
-	if (ops->ndo_xdp && __dev_xdp_attached(dev, ops->ndo_xdp, prog_id))
-		return XDP_ATTACHED_DRV;
+	if (!ops->ndo_xdp)
+		return XDP_ATTACHED_NONE;
 
-	return XDP_ATTACHED_NONE;
+	return __dev_xdp_attached(dev, ops->ndo_xdp, prog_id);
 }
 
 static int rtnl_xdp_fill(struct sk_buff *skb, struct net_device *dev)
-- 
2.11.0

Re: [RFC net-next 2/8] xdp: add HW offload mode flag for installing programs

From: Daniel Borkmann <daniel@iogearbox.net>
Date: 2017-06-19 22:55:46

On 06/17/2017 01:57 AM, Jakub Kicinski wrote:
Add an installation-time flag for requesting that the program
be installed only if it can be offloaded to HW.

Internally new command for ndo_xdp is added, this way we avoid
putting checks into drivers since they all return -EINVAL on
an unknown command.

Signed-off-by: Jakub Kicinski <redacted>
[...]
quoted hunk
diff --git a/net/core/dev.c b/net/core/dev.c
index a04db264aa1c..05cec8e2cd82 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -6959,7 +6959,10 @@ static int dev_xdp_install(struct net_device *dev, xdp_op_t xdp_op,
  	struct netdev_xdp xdp;

  	memset(&xdp, 0, sizeof(xdp));
-	xdp.command = XDP_SETUP_PROG;
+	if (flags & XDP_FLAGS_HW_MODE)
+		xdp.command = XDP_SETUP_PROG_HW;
+	else
+		xdp.command = XDP_SETUP_PROG;
  	xdp.extack = extack;
  	xdp.flags = flags;
  	xdp.prog = prog;
One thing I'm not sure I follow is that while you pass flags to the ndo
in patch 1, add a new XDP_SETUP_PROG_HW command here in patch 2 based on
the flags, and later on in patch 6, you don't really make use of it, but
look at the flags anyway? Then, why adding separate XDP_SETUP_PROG_HW
in the first place?

[patch 6:]
@@ -3338,6 +3341,7 @@ static int nfp_net_xdp(struct net_device *netdev, struct netdev_xdp *xdp)

 	switch (xdp->command) {
 	case XDP_SETUP_PROG:
+	case XDP_SETUP_PROG_HW:
 		return nfp_net_xdp_setup(nn, xdp->prog, xdp->flags,
 					 xdp->extack);

Re: [RFC net-next 5/8] nfp: bpf: take a reference on offloaded programs

From: Daniel Borkmann <daniel@iogearbox.net>
Date: 2017-06-19 23:23:11

On 06/17/2017 01:57 AM, Jakub Kicinski wrote:
The xdp_prog member of the adapter's data path structure is used
for XDP in driver mode.  In case a XDP program is loaded with in
HW-only mode, we need to store it somewhere else.  Add a new XDP
prog pointer in the main structure and use that when we need to
know whether any XDP program is loaded, not only a driver mode
one.  Only release our reference on adapter free instead of
immediately after netdev unregister to allow offload to be disabled
first.

Signed-off-by: Jakub Kicinski <redacted>
[...]
quoted hunk
@@ -3327,6 +3323,10 @@ nfp_net_xdp_setup(struct nfp_net *nn, struct bpf_prog *prog, u32 flags,
  		return err;

  	nfp_app_xdp_offload(nn->app, nn, offload_prog);
+
+	if (nn->xdp_prog)
+		bpf_prog_put(nn->xdp_prog);
+	nn->xdp_prog = prog;
  	nn->xdp_flags = flags;

  	return 0;
Can you elaborate on the extra reference on the prog? So in
nfp_net_xdp_setup(), assuming a prog was already loaded on
driver side: after your set, nfp_net_xdp_setup_drv() will then
do the xchg() on nn->dp.xdp_prog, bpf_prog_put() this one and
later back in nfp_net_xdp_setup() we check nn->xdp_prog and
bpf_prog_put() it if it existed before and update nn->xdp_prog
to the current prog. So you end up with two puts on the same
program, but I don't see where you take the one additional ref
aside from the ref that you already get from dev_change_xdp_fd().
What am I missing?

Re: [RFC net-next 2/8] xdp: add HW offload mode flag for installing programs

From: Jakub Kicinski <hidden>
Date: 2017-06-19 23:25:04

On Tue, 20 Jun 2017 00:55:41 +0200, Daniel Borkmann wrote:
quoted hunk
On 06/17/2017 01:57 AM, Jakub Kicinski wrote:
quoted
Add an installation-time flag for requesting that the program
be installed only if it can be offloaded to HW.

Internally new command for ndo_xdp is added, this way we avoid
putting checks into drivers since they all return -EINVAL on
an unknown command.

Signed-off-by: Jakub Kicinski <redacted>  
[...]
quoted
diff --git a/net/core/dev.c b/net/core/dev.c
index a04db264aa1c..05cec8e2cd82 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -6959,7 +6959,10 @@ static int dev_xdp_install(struct net_device *dev, xdp_op_t xdp_op,
  	struct netdev_xdp xdp;

  	memset(&xdp, 0, sizeof(xdp));
-	xdp.command = XDP_SETUP_PROG;
+	if (flags & XDP_FLAGS_HW_MODE)
+		xdp.command = XDP_SETUP_PROG_HW;
+	else
+		xdp.command = XDP_SETUP_PROG;
  	xdp.extack = extack;
  	xdp.flags = flags;
  	xdp.prog = prog;  
One thing I'm not sure I follow is that while you pass flags to the ndo
in patch 1, add a new XDP_SETUP_PROG_HW command here in patch 2 based on
the flags, and later on in patch 6, you don't really make use of it, but
look at the flags anyway? Then, why adding separate XDP_SETUP_PROG_HW
in the first place?

[patch 6:]
@@ -3338,6 +3341,7 @@ static int nfp_net_xdp(struct net_device *netdev, struct netdev_xdp *xdp)

  	switch (xdp->command) {
  	case XDP_SETUP_PROG:
+	case XDP_SETUP_PROG_HW:
  		return nfp_net_xdp_setup(nn, xdp->prog, xdp->flags,
  					 xdp->extack);
We still need the flags to be able to differentiate between default/no
flags case where we load to the driver and the HW ("both"), and when
the DRV_MODE flag is set, in which case we disable the HW offload and
only load to the driver.  We have three cases:

           drv     offload
 no flag   yes    attempted
DRV_MODE   yes        no
 HW_MODE    no       yes

The XDP_SETUP_PROG_HW command is purely for convenience of drivers
without an offload.  I felt it's not appropriate to burden all drivers
with:

if (xdp->flags & XDP_FLAGS_HW_MODE)
	return -EOPNOTSUPP;

But, I do have a patch which does it, so I'm happy to drop the new
command if it's preferred.

Re: [RFC net-next 5/8] nfp: bpf: take a reference on offloaded programs

From: Jakub Kicinski <hidden>
Date: 2017-06-19 23:34:44

On Tue, 20 Jun 2017 01:23:05 +0200, Daniel Borkmann wrote:
On 06/17/2017 01:57 AM, Jakub Kicinski wrote:
quoted
The xdp_prog member of the adapter's data path structure is used
for XDP in driver mode.  In case a XDP program is loaded with in
HW-only mode, we need to store it somewhere else.  Add a new XDP
prog pointer in the main structure and use that when we need to
know whether any XDP program is loaded, not only a driver mode
one.  Only release our reference on adapter free instead of
immediately after netdev unregister to allow offload to be disabled
first.

Signed-off-by: Jakub Kicinski <redacted>  
[...]
quoted
@@ -3327,6 +3323,10 @@ nfp_net_xdp_setup(struct nfp_net *nn, struct bpf_prog 
  		return err;

  	nfp_app_xdp_offload(nn->app, nn, offload_prog);
+
+	if (nn->xdp_prog)
+		bpf_prog_put(nn->xdp_prog);
+	nn->xdp_prog = prog;
  	nn->xdp_flags = flags;

  	return 0;  
Can you elaborate on the extra reference on the prog? 
Sorry, this patch went through a few revisions and the subject doesn't
express the intent too well any more :S  Originally it was about making
sure we have a reference on the program when it's offloaded but not
loaded in the driver, but I realized the we have the reference from 
dev_change_xdp_fd() already, so now the patch just releases the
reference on the offloaded program.
So in nfp_net_xdp_setup(), assuming a prog was already loaded on
driver side: after your set, nfp_net_xdp_setup_drv() will then
do the xchg() on nn->dp.xdp_prog, bpf_prog_put() this one and
later back in nfp_net_xdp_setup() we check nn->xdp_prog and
bpf_prog_put() it if it existed before and update nn->xdp_prog
to the current prog. So you end up with two puts on the same
program, but I don't see where you take the one additional ref
aside from the ref that you already get from dev_change_xdp_fd().
What am I missing?
You are right, I missed there were two spots where I was doing a
bpf_prog_put() in nfp_net_xdp_setup_drv(), thanks!

Re: [RFC net-next 2/8] xdp: add HW offload mode flag for installing programs

From: Daniel Borkmann <daniel@iogearbox.net>
Date: 2017-06-19 23:36:29

On 06/20/2017 01:24 AM, Jakub Kicinski wrote:
[...]
The XDP_SETUP_PROG_HW command is purely for convenience of drivers
without an offload.  I felt it's not appropriate to burden all drivers
with:

if (xdp->flags & XDP_FLAGS_HW_MODE)
	return -EOPNOTSUPP;

But, I do have a patch which does it, so I'm happy to drop the new
command if it's preferred.
Ahh, that makes sense, yep. I was only focused on reviewing this in
the context of nfp driver. Lack of coffee. ;)

Re: [RFC net-next 1/8] xdp: pass XDP flags into install handlers

From: Daniel Borkmann <daniel@iogearbox.net>
Date: 2017-06-19 23:38:41

On 06/17/2017 01:57 AM, Jakub Kicinski wrote:
Pass XDP flags to the xdp ndo.  This will allow drivers to look
at the mode flags and make decisions about offload.

Signed-off-by: Jakub Kicinski <redacted>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>

Re: [RFC net-next 2/8] xdp: add HW offload mode flag for installing programs

From: Daniel Borkmann <daniel@iogearbox.net>
Date: 2017-06-19 23:39:22

On 06/17/2017 01:57 AM, Jakub Kicinski wrote:
Add an installation-time flag for requesting that the program
be installed only if it can be offloaded to HW.

Internally new command for ndo_xdp is added, this way we avoid
putting checks into drivers since they all return -EINVAL on
an unknown command.

Signed-off-by: Jakub Kicinski <redacted>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>

Re: [RFC net-next 7/8] xdp: add reporting of offload mode

From: Daniel Borkmann <daniel@iogearbox.net>
Date: 2017-06-19 23:40:19

On 06/17/2017 01:57 AM, Jakub Kicinski wrote:
Extend the XDP_ATTACHED_* values to include offloaded mode.
Let drivers report whether program is installed in the driver
or the HW by changing the prog_attached field from bool to
u8 (type of the netlink attribute).

Exploit the fact that the value of XDP_ATTACHED_DRV is 1,
therefore since all drivers currently assign the mode with
double negation:
        mode = !!xdp_prog;
no drivers have to be modified.

Signed-off-by: Jakub Kicinski <redacted>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>

Re: [RFC net-next 6/8] nfp: bpf: add support for XDP_FLAGS_HW_MODE

From: Daniel Borkmann <daniel@iogearbox.net>
Date: 2017-06-19 23:50:23

On 06/17/2017 01:57 AM, Jakub Kicinski wrote:
quoted hunk
Respect the XDP_FLAGS_HW_MODE.  When it's set install the program
on the NIC and skip enabling XDP in the driver.

Signed-off-by: Jakub Kicinski <redacted>
---
  drivers/net/ethernet/netronome/nfp/nfp_net_common.c | 10 +++++++---
  1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index 68648e312129..c5903b6e58c5 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -3310,19 +3310,22 @@ static int
  nfp_net_xdp_setup(struct nfp_net *nn, struct bpf_prog *prog, u32 flags,
  		  struct netlink_ext_ack *extack)
  {
-	struct bpf_prog *offload_prog;
+	struct bpf_prog *drv_prog, *offload_prog;
  	int err;

  	if (nn->xdp_prog && (flags ^ nn->xdp_flags) & XDP_FLAGS_MODES)
  		return -EBUSY;

+	drv_prog     = flags & XDP_FLAGS_HW_MODE  ? NULL : prog;
  	offload_prog = flags & XDP_FLAGS_DRV_MODE ? NULL : prog;
Can you make this assumption here? If dev_change_xdp_fd() is called
without XDP_FLAGS_HW_MODE or XDP_FLAGS_DRV_MODE flags, then we set prog
to both, drv_prog and offload_prog. Is this expected?

Maybe in nfp_net_xdp_setup() check for !hweight32(xdp_flags & XDP_FLAGS_MODES)
and then set flags |= XDP_FLAGS_DRV_MODE before both assignments?
quoted hunk
-	err = nfp_net_xdp_setup_drv(nn, prog, extack);
+	err = nfp_net_xdp_setup_drv(nn, drv_prog, extack);
  	if (err)
  		return err;

-	nfp_app_xdp_offload(nn->app, nn, offload_prog);
+	err = nfp_app_xdp_offload(nn->app, nn, offload_prog);
+	if (err && flags & XDP_FLAGS_HW_MODE)
+		return err;

  	if (nn->xdp_prog)
  		bpf_prog_put(nn->xdp_prog);
@@ -3338,6 +3341,7 @@ static int nfp_net_xdp(struct net_device *netdev, struct netdev_xdp *xdp)

  	switch (xdp->command) {
  	case XDP_SETUP_PROG:
+	case XDP_SETUP_PROG_HW:
  		return nfp_net_xdp_setup(nn, xdp->prog, xdp->flags,
  					 xdp->extack);
  	case XDP_QUERY_PROG:

Re: [RFC net-next 6/8] nfp: bpf: add support for XDP_FLAGS_HW_MODE

From: Jakub Kicinski <hidden>
Date: 2017-06-20 00:01:31

On Tue, 20 Jun 2017 01:50:17 +0200, Daniel Borkmann wrote:
On 06/17/2017 01:57 AM, Jakub Kicinski wrote:
quoted
Respect the XDP_FLAGS_HW_MODE.  When it's set install the program
on the NIC and skip enabling XDP in the driver.

Signed-off-by: Jakub Kicinski <redacted>
---
  drivers/net/ethernet/netronome/nfp/nfp_net_common.c | 10 +++++++---
  1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index 68648e312129..c5903b6e58c5 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -3310,19 +3310,22 @@ static int
  nfp_net_xdp_setup(struct nfp_net *nn, struct bpf_prog *prog, u32 flags,
  		  struct netlink_ext_ack *extack)
  {
-	struct bpf_prog *offload_prog;
+	struct bpf_prog *drv_prog, *offload_prog;
  	int err;

  	if (nn->xdp_prog && (flags ^ nn->xdp_flags) & XDP_FLAGS_MODES)
  		return -EBUSY;

+	drv_prog     = flags & XDP_FLAGS_HW_MODE  ? NULL : prog;
  	offload_prog = flags & XDP_FLAGS_DRV_MODE ? NULL : prog;  
Can you make this assumption here? If dev_change_xdp_fd() is called
without XDP_FLAGS_HW_MODE or XDP_FLAGS_DRV_MODE flags, then we set prog
to both, drv_prog and offload_prog. Is this expected?

Maybe in nfp_net_xdp_setup() check for !hweight32(xdp_flags & XDP_FLAGS_MODES)
and then set flags |= XDP_FLAGS_DRV_MODE before both assignments?
I thought we did want both.  In case the program is loaded to both the
HW/FW will mark the packets with BPF bit in the descriptor so that they
are not processed twice.  But the driver path will be configured for
running bpf and when user replaces the program with one which cannot be
offloaded the driver will not have to reconfigure itself.

Re: [RFC net-next 6/8] nfp: bpf: add support for XDP_FLAGS_HW_MODE

From: Daniel Borkmann <daniel@iogearbox.net>
Date: 2017-06-20 00:09:59

On 06/20/2017 02:01 AM, Jakub Kicinski wrote:
On Tue, 20 Jun 2017 01:50:17 +0200, Daniel Borkmann wrote:
quoted
On 06/17/2017 01:57 AM, Jakub Kicinski wrote:
quoted
Respect the XDP_FLAGS_HW_MODE.  When it's set install the program
on the NIC and skip enabling XDP in the driver.

Signed-off-by: Jakub Kicinski <redacted>
---
   drivers/net/ethernet/netronome/nfp/nfp_net_common.c | 10 +++++++---
   1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index 68648e312129..c5903b6e58c5 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -3310,19 +3310,22 @@ static int
   nfp_net_xdp_setup(struct nfp_net *nn, struct bpf_prog *prog, u32 flags,
   		  struct netlink_ext_ack *extack)
   {
-	struct bpf_prog *offload_prog;
+	struct bpf_prog *drv_prog, *offload_prog;
   	int err;

   	if (nn->xdp_prog && (flags ^ nn->xdp_flags) & XDP_FLAGS_MODES)
   		return -EBUSY;

+	drv_prog     = flags & XDP_FLAGS_HW_MODE  ? NULL : prog;
   	offload_prog = flags & XDP_FLAGS_DRV_MODE ? NULL : prog;
Can you make this assumption here? If dev_change_xdp_fd() is called
without XDP_FLAGS_HW_MODE or XDP_FLAGS_DRV_MODE flags, then we set prog
to both, drv_prog and offload_prog. Is this expected?

Maybe in nfp_net_xdp_setup() check for !hweight32(xdp_flags & XDP_FLAGS_MODES)
and then set flags |= XDP_FLAGS_DRV_MODE before both assignments?
I thought we did want both.  In case the program is loaded to both the
HW/FW will mark the packets with BPF bit in the descriptor so that they
are not processed twice.  But the driver path will be configured for
running bpf and when user replaces the program with one which cannot be
offloaded the driver will not have to reconfigure itself.
Okay, that's a good point ... so that you can just use xchg() later on.
Probably worth explaining this rationale in a short comment.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help