aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2017-06-23 13:42:21 -0400
committerDavid S. Miller <davem@davemloft.net>2017-06-23 13:42:21 -0400
commit1847d3d0a4de609523a685d68458529caacacdcc (patch)
tree00bbc360b28f362542756d7ca67f953d7394f2c3
parent9bd780f5e0663035d41a95a6b87eced011ba7e2a (diff)
parent149d7a572ae124385973bf1c8e4d80b3f07d8bd4 (diff)
Merge branch 'xdp-offload-mode'
Jakub Kicinski says: ==================== xdp: offload mode While we discuss the representors.. :) This set adds XDP flag for forcing offload and a attachment 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. The intended driver behaviour is: DRV mode offload no flags yes attempted DRV_MODE yes no HW_MODE no yes Where 'yes' means required, and error will be returned if setup fails. 'Attempted' means the offload will only happen automatically if HW is capable and offloading the program will cause no change in system behaviour (e.g. maps don't have to bound). Thanks to loading the program both to the driver and HW by default we can fallback to the driver mode without disruption in case user replaces the program with one which cannot be offloaded later. Note that the NFP driver currently claims XDP offload support but lacks most basic features like direct packet access. Only change compared to the RFC is fixing the double bpf_prog_put() which Daniel has spotted (patch 5). ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net.h5
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net_common.c62
-rw-r--r--include/linux/netdevice.h9
-rw-r--r--include/uapi/linux/if_link.h8
-rw-r--r--net/core/dev.c15
-rw-r--r--net/core/rtnetlink.c10
6 files changed, 73 insertions, 36 deletions
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net.h b/drivers/net/ethernet/netronome/nfp/nfp_net.h
index 02fd8d4e253c..b7446793106d 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net.h
@@ -541,6 +541,8 @@ struct nfp_net_dp {
541 * @rss_cfg: RSS configuration 541 * @rss_cfg: RSS configuration
542 * @rss_key: RSS secret key 542 * @rss_key: RSS secret key
543 * @rss_itbl: RSS indirection table 543 * @rss_itbl: RSS indirection table
544 * @xdp_flags: Flags with which XDP prog was loaded
545 * @xdp_prog: XDP prog (for ctrl path, both DRV and HW modes)
544 * @max_r_vecs: Number of allocated interrupt vectors for RX/TX 546 * @max_r_vecs: Number of allocated interrupt vectors for RX/TX
545 * @max_tx_rings: Maximum number of TX rings supported by the Firmware 547 * @max_tx_rings: Maximum number of TX rings supported by the Firmware
546 * @max_rx_rings: Maximum number of RX rings supported by the Firmware 548 * @max_rx_rings: Maximum number of RX rings supported by the Firmware
@@ -590,6 +592,9 @@ struct nfp_net {
590 u8 rss_key[NFP_NET_CFG_RSS_KEY_SZ]; 592 u8 rss_key[NFP_NET_CFG_RSS_KEY_SZ];
591 u8 rss_itbl[NFP_NET_CFG_RSS_ITBL_SZ]; 593 u8 rss_itbl[NFP_NET_CFG_RSS_ITBL_SZ];
592 594
595 u32 xdp_flags;
596 struct bpf_prog *xdp_prog;
597
593 unsigned int max_tx_rings; 598 unsigned int max_tx_rings;
594 unsigned int max_rx_rings; 599 unsigned int max_rx_rings;
595 600
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index 2bdddd1ae666..2134493ec8a8 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -3274,19 +3274,14 @@ static void nfp_net_del_vxlan_port(struct net_device *netdev,
3274 nfp_net_set_vxlan_port(nn, idx, 0); 3274 nfp_net_set_vxlan_port(nn, idx, 0);
3275} 3275}
3276 3276
3277static int nfp_net_xdp_setup(struct nfp_net *nn, struct netdev_xdp *xdp) 3277static int
3278nfp_net_xdp_setup_drv(struct nfp_net *nn, struct bpf_prog *prog,
3279 struct netlink_ext_ack *extack)
3278{ 3280{
3279 struct bpf_prog *old_prog = nn->dp.xdp_prog;
3280 struct bpf_prog *prog = xdp->prog;
3281 struct nfp_net_dp *dp; 3281 struct nfp_net_dp *dp;
3282 int err;
3283 3282
3284 if (!prog && !nn->dp.xdp_prog) 3283 if (!prog == !nn->dp.xdp_prog) {
3285 return 0; 3284 WRITE_ONCE(nn->dp.xdp_prog, prog);
3286 if (prog && nn->dp.xdp_prog) {
3287 prog = xchg(&nn->dp.xdp_prog, prog);
3288 bpf_prog_put(prog);
3289 nfp_app_xdp_offload(nn->app, nn, nn->dp.xdp_prog);
3290 return 0; 3285 return 0;
3291 } 3286 }
3292 3287
@@ -3300,14 +3295,37 @@ static int nfp_net_xdp_setup(struct nfp_net *nn, struct netdev_xdp *xdp)
3300 dp->rx_dma_off = prog ? XDP_PACKET_HEADROOM - nn->dp.rx_offset : 0; 3295 dp->rx_dma_off = prog ? XDP_PACKET_HEADROOM - nn->dp.rx_offset : 0;
3301 3296
3302 /* We need RX reconfig to remap the buffers (BIDIR vs FROM_DEV) */ 3297 /* We need RX reconfig to remap the buffers (BIDIR vs FROM_DEV) */
3303 err = nfp_net_ring_reconfig(nn, dp, xdp->extack); 3298 return nfp_net_ring_reconfig(nn, dp, extack);
3299}
3300
3301static int
3302nfp_net_xdp_setup(struct nfp_net *nn, struct bpf_prog *prog, u32 flags,
3303 struct netlink_ext_ack *extack)
3304{
3305 struct bpf_prog *drv_prog, *offload_prog;
3306 int err;
3307
3308 if (nn->xdp_prog && (flags ^ nn->xdp_flags) & XDP_FLAGS_MODES)
3309 return -EBUSY;
3310
3311 /* Load both when no flags set to allow easy activation of driver path
3312 * when program is replaced by one which can't be offloaded.
3313 */
3314 drv_prog = flags & XDP_FLAGS_HW_MODE ? NULL : prog;
3315 offload_prog = flags & XDP_FLAGS_DRV_MODE ? NULL : prog;
3316
3317 err = nfp_net_xdp_setup_drv(nn, drv_prog, extack);
3304 if (err) 3318 if (err)
3305 return err; 3319 return err;
3306 3320
3307 if (old_prog) 3321 err = nfp_app_xdp_offload(nn->app, nn, offload_prog);
3308 bpf_prog_put(old_prog); 3322 if (err && flags & XDP_FLAGS_HW_MODE)
3323 return err;
3309 3324
3310 nfp_app_xdp_offload(nn->app, nn, nn->dp.xdp_prog); 3325 if (nn->xdp_prog)
3326 bpf_prog_put(nn->xdp_prog);
3327 nn->xdp_prog = prog;
3328 nn->xdp_flags = flags;
3311 3329
3312 return 0; 3330 return 0;
3313} 3331}
@@ -3318,10 +3336,14 @@ static int nfp_net_xdp(struct net_device *netdev, struct netdev_xdp *xdp)
3318 3336
3319 switch (xdp->command) { 3337 switch (xdp->command) {
3320 case XDP_SETUP_PROG: 3338 case XDP_SETUP_PROG:
3321 return nfp_net_xdp_setup(nn, xdp); 3339 case XDP_SETUP_PROG_HW:
3340 return nfp_net_xdp_setup(nn, xdp->prog, xdp->flags,
3341 xdp->extack);
3322 case XDP_QUERY_PROG: 3342 case XDP_QUERY_PROG:
3323 xdp->prog_attached = !!nn->dp.xdp_prog; 3343 xdp->prog_attached = !!nn->xdp_prog;
3324 xdp->prog_id = nn->dp.xdp_prog ? nn->dp.xdp_prog->aux->id : 0; 3344 if (nn->dp.bpf_offload_xdp)
3345 xdp->prog_attached = XDP_ATTACHED_HW;
3346 xdp->prog_id = nn->xdp_prog ? nn->xdp_prog->aux->id : 0;
3325 return 0; 3347 return 0;
3326 default: 3348 default:
3327 return -EINVAL; 3349 return -EINVAL;
@@ -3479,6 +3501,9 @@ struct nfp_net *nfp_net_alloc(struct pci_dev *pdev, bool needs_netdev,
3479 */ 3501 */
3480void nfp_net_free(struct nfp_net *nn) 3502void nfp_net_free(struct nfp_net *nn)
3481{ 3503{
3504 if (nn->xdp_prog)
3505 bpf_prog_put(nn->xdp_prog);
3506
3482 if (nn->dp.netdev) 3507 if (nn->dp.netdev)
3483 free_netdev(nn->dp.netdev); 3508 free_netdev(nn->dp.netdev);
3484 else 3509 else
@@ -3736,7 +3761,4 @@ void nfp_net_clean(struct nfp_net *nn)
3736 return; 3761 return;
3737 3762
3738 unregister_netdev(nn->dp.netdev); 3763 unregister_netdev(nn->dp.netdev);
3739
3740 if (nn->dp.xdp_prog)
3741 bpf_prog_put(nn->dp.xdp_prog);
3742} 3764}
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 7c7118b3bd69..68f5d899d1e6 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -807,8 +807,10 @@ enum xdp_netdev_command {
807 * when it is no longer used. 807 * when it is no longer used.
808 */ 808 */
809 XDP_SETUP_PROG, 809 XDP_SETUP_PROG,
810 XDP_SETUP_PROG_HW,
810 /* Check if a bpf program is set on the device. The callee should 811 /* Check if a bpf program is set on the device. The callee should
811 * return true if a program is currently attached and running. 812 * set @prog_attached to one of XDP_ATTACHED_* values, note that "true"
813 * is equivalent to XDP_ATTACHED_DRV.
812 */ 814 */
813 XDP_QUERY_PROG, 815 XDP_QUERY_PROG,
814}; 816};
@@ -820,12 +822,13 @@ struct netdev_xdp {
820 union { 822 union {
821 /* XDP_SETUP_PROG */ 823 /* XDP_SETUP_PROG */
822 struct { 824 struct {
825 u32 flags;
823 struct bpf_prog *prog; 826 struct bpf_prog *prog;
824 struct netlink_ext_ack *extack; 827 struct netlink_ext_ack *extack;
825 }; 828 };
826 /* XDP_QUERY_PROG */ 829 /* XDP_QUERY_PROG */
827 struct { 830 struct {
828 bool prog_attached; 831 u8 prog_attached;
829 u32 prog_id; 832 u32 prog_id;
830 }; 833 };
831 }; 834 };
@@ -3305,7 +3308,7 @@ struct sk_buff *dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
3305typedef int (*xdp_op_t)(struct net_device *dev, struct netdev_xdp *xdp); 3308typedef int (*xdp_op_t)(struct net_device *dev, struct netdev_xdp *xdp);
3306int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack, 3309int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
3307 int fd, u32 flags); 3310 int fd, u32 flags);
3308bool __dev_xdp_attached(struct net_device *dev, xdp_op_t xdp_op, u32 *prog_id); 3311u8 __dev_xdp_attached(struct net_device *dev, xdp_op_t xdp_op, u32 *prog_id);
3309 3312
3310int __dev_forward_skb(struct net_device *dev, struct sk_buff *skb); 3313int __dev_forward_skb(struct net_device *dev, struct sk_buff *skb);
3311int dev_forward_skb(struct net_device *dev, struct sk_buff *skb); 3314int 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 dd88375a6580..8d062c58d5cb 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -891,15 +891,19 @@ enum {
891#define XDP_FLAGS_UPDATE_IF_NOEXIST (1U << 0) 891#define XDP_FLAGS_UPDATE_IF_NOEXIST (1U << 0)
892#define XDP_FLAGS_SKB_MODE (1U << 1) 892#define XDP_FLAGS_SKB_MODE (1U << 1)
893#define XDP_FLAGS_DRV_MODE (1U << 2) 893#define XDP_FLAGS_DRV_MODE (1U << 2)
894#define XDP_FLAGS_HW_MODE (1U << 3)
895#define XDP_FLAGS_MODES (XDP_FLAGS_SKB_MODE | \
896 XDP_FLAGS_DRV_MODE | \
897 XDP_FLAGS_HW_MODE)
894#define XDP_FLAGS_MASK (XDP_FLAGS_UPDATE_IF_NOEXIST | \ 898#define XDP_FLAGS_MASK (XDP_FLAGS_UPDATE_IF_NOEXIST | \
895 XDP_FLAGS_SKB_MODE | \ 899 XDP_FLAGS_MODES)
896 XDP_FLAGS_DRV_MODE)
897 900
898/* These are stored into IFLA_XDP_ATTACHED on dump. */ 901/* These are stored into IFLA_XDP_ATTACHED on dump. */
899enum { 902enum {
900 XDP_ATTACHED_NONE = 0, 903 XDP_ATTACHED_NONE = 0,
901 XDP_ATTACHED_DRV, 904 XDP_ATTACHED_DRV,
902 XDP_ATTACHED_SKB, 905 XDP_ATTACHED_SKB,
906 XDP_ATTACHED_HW,
903}; 907};
904 908
905enum { 909enum {
diff --git a/net/core/dev.c b/net/core/dev.c
index df7637733e3c..a91572aa73d5 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -6934,8 +6934,7 @@ int dev_change_proto_down(struct net_device *dev, bool proto_down)
6934} 6934}
6935EXPORT_SYMBOL(dev_change_proto_down); 6935EXPORT_SYMBOL(dev_change_proto_down);
6936 6936
6937bool __dev_xdp_attached(struct net_device *dev, xdp_op_t xdp_op, 6937u8 __dev_xdp_attached(struct net_device *dev, xdp_op_t xdp_op, u32 *prog_id)
6938 u32 *prog_id)
6939{ 6938{
6940 struct netdev_xdp xdp; 6939 struct netdev_xdp xdp;
6941 6940
@@ -6951,14 +6950,18 @@ bool __dev_xdp_attached(struct net_device *dev, xdp_op_t xdp_op,
6951} 6950}
6952 6951
6953static int dev_xdp_install(struct net_device *dev, xdp_op_t xdp_op, 6952static int dev_xdp_install(struct net_device *dev, xdp_op_t xdp_op,
6954 struct netlink_ext_ack *extack, 6953 struct netlink_ext_ack *extack, u32 flags,
6955 struct bpf_prog *prog) 6954 struct bpf_prog *prog)
6956{ 6955{
6957 struct netdev_xdp xdp; 6956 struct netdev_xdp xdp;
6958 6957
6959 memset(&xdp, 0, sizeof(xdp)); 6958 memset(&xdp, 0, sizeof(xdp));
6960 xdp.command = XDP_SETUP_PROG; 6959 if (flags & XDP_FLAGS_HW_MODE)
6960 xdp.command = XDP_SETUP_PROG_HW;
6961 else
6962 xdp.command = XDP_SETUP_PROG;
6961 xdp.extack = extack; 6963 xdp.extack = extack;
6964 xdp.flags = flags;
6962 xdp.prog = prog; 6965 xdp.prog = prog;
6963 6966
6964 return xdp_op(dev, &xdp); 6967 return xdp_op(dev, &xdp);
@@ -6984,7 +6987,7 @@ int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
6984 ASSERT_RTNL(); 6987 ASSERT_RTNL();
6985 6988
6986 xdp_op = xdp_chk = ops->ndo_xdp; 6989 xdp_op = xdp_chk = ops->ndo_xdp;
6987 if (!xdp_op && (flags & XDP_FLAGS_DRV_MODE)) 6990 if (!xdp_op && (flags & (XDP_FLAGS_DRV_MODE | XDP_FLAGS_HW_MODE)))
6988 return -EOPNOTSUPP; 6991 return -EOPNOTSUPP;
6989 if (!xdp_op || (flags & XDP_FLAGS_SKB_MODE)) 6992 if (!xdp_op || (flags & XDP_FLAGS_SKB_MODE))
6990 xdp_op = generic_xdp_install; 6993 xdp_op = generic_xdp_install;
@@ -7003,7 +7006,7 @@ int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
7003 return PTR_ERR(prog); 7006 return PTR_ERR(prog);
7004 } 7007 }
7005 7008
7006 err = dev_xdp_install(dev, xdp_op, extack, prog); 7009 err = dev_xdp_install(dev, xdp_op, extack, flags, prog);
7007 if (err < 0 && prog) 7010 if (err < 0 && prog)
7008 bpf_prog_put(prog); 7011 bpf_prog_put(prog);
7009 7012
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 8da89c1136e5..9a1bd510c812 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -16,6 +16,7 @@
16 * Vitaly E. Lavrov RTA_OK arithmetics was wrong. 16 * Vitaly E. Lavrov RTA_OK arithmetics was wrong.
17 */ 17 */
18 18
19#include <linux/bitops.h>
19#include <linux/errno.h> 20#include <linux/errno.h>
20#include <linux/module.h> 21#include <linux/module.h>
21#include <linux/types.h> 22#include <linux/types.h>
@@ -1264,10 +1265,10 @@ static u8 rtnl_xdp_attached_mode(struct net_device *dev, u32 *prog_id)
1264 *prog_id = generic_xdp_prog->aux->id; 1265 *prog_id = generic_xdp_prog->aux->id;
1265 return XDP_ATTACHED_SKB; 1266 return XDP_ATTACHED_SKB;
1266 } 1267 }
1267 if (ops->ndo_xdp && __dev_xdp_attached(dev, ops->ndo_xdp, prog_id)) 1268 if (!ops->ndo_xdp)
1268 return XDP_ATTACHED_DRV; 1269 return XDP_ATTACHED_NONE;
1269 1270
1270 return XDP_ATTACHED_NONE; 1271 return __dev_xdp_attached(dev, ops->ndo_xdp, prog_id);
1271} 1272}
1272 1273
1273static int rtnl_xdp_fill(struct sk_buff *skb, struct net_device *dev) 1274static int rtnl_xdp_fill(struct sk_buff *skb, struct net_device *dev)
@@ -2253,8 +2254,7 @@ static int do_setlink(const struct sk_buff *skb,
2253 err = -EINVAL; 2254 err = -EINVAL;
2254 goto errout; 2255 goto errout;
2255 } 2256 }
2256 if ((xdp_flags & XDP_FLAGS_SKB_MODE) && 2257 if (hweight32(xdp_flags & XDP_FLAGS_MODES) > 1) {
2257 (xdp_flags & XDP_FLAGS_DRV_MODE)) {
2258 err = -EINVAL; 2258 err = -EINVAL;
2259 goto errout; 2259 goto errout;
2260 } 2260 }