aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 }