aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/core/dev.c')
-rw-r--r--net/core/dev.c57
1 files changed, 38 insertions, 19 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 96cf83da0d66..fca407b4a6ea 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -6852,6 +6852,32 @@ int dev_change_proto_down(struct net_device *dev, bool proto_down)
6852} 6852}
6853EXPORT_SYMBOL(dev_change_proto_down); 6853EXPORT_SYMBOL(dev_change_proto_down);
6854 6854
6855bool __dev_xdp_attached(struct net_device *dev, xdp_op_t xdp_op)
6856{
6857 struct netdev_xdp xdp;
6858
6859 memset(&xdp, 0, sizeof(xdp));
6860 xdp.command = XDP_QUERY_PROG;
6861
6862 /* Query must always succeed. */
6863 WARN_ON(xdp_op(dev, &xdp) < 0);
6864 return xdp.prog_attached;
6865}
6866
6867static int dev_xdp_install(struct net_device *dev, xdp_op_t xdp_op,
6868 struct netlink_ext_ack *extack,
6869 struct bpf_prog *prog)
6870{
6871 struct netdev_xdp xdp;
6872
6873 memset(&xdp, 0, sizeof(xdp));
6874 xdp.command = XDP_SETUP_PROG;
6875 xdp.extack = extack;
6876 xdp.prog = prog;
6877
6878 return xdp_op(dev, &xdp);
6879}
6880
6855/** 6881/**
6856 * dev_change_xdp_fd - set or clear a bpf program for a device rx path 6882 * dev_change_xdp_fd - set or clear a bpf program for a device rx path
6857 * @dev: device 6883 * @dev: device
@@ -6864,41 +6890,34 @@ EXPORT_SYMBOL(dev_change_proto_down);
6864int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack, 6890int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
6865 int fd, u32 flags) 6891 int fd, u32 flags)
6866{ 6892{
6867 int (*xdp_op)(struct net_device *dev, struct netdev_xdp *xdp);
6868 const struct net_device_ops *ops = dev->netdev_ops; 6893 const struct net_device_ops *ops = dev->netdev_ops;
6869 struct bpf_prog *prog = NULL; 6894 struct bpf_prog *prog = NULL;
6870 struct netdev_xdp xdp; 6895 xdp_op_t xdp_op, xdp_chk;
6871 int err; 6896 int err;
6872 6897
6873 ASSERT_RTNL(); 6898 ASSERT_RTNL();
6874 6899
6875 xdp_op = ops->ndo_xdp; 6900 xdp_op = xdp_chk = ops->ndo_xdp;
6901 if (!xdp_op && (flags & XDP_FLAGS_DRV_MODE))
6902 return -EOPNOTSUPP;
6876 if (!xdp_op || (flags & XDP_FLAGS_SKB_MODE)) 6903 if (!xdp_op || (flags & XDP_FLAGS_SKB_MODE))
6877 xdp_op = generic_xdp_install; 6904 xdp_op = generic_xdp_install;
6905 if (xdp_op == xdp_chk)
6906 xdp_chk = generic_xdp_install;
6878 6907
6879 if (fd >= 0) { 6908 if (fd >= 0) {
6880 if (flags & XDP_FLAGS_UPDATE_IF_NOEXIST) { 6909 if (xdp_chk && __dev_xdp_attached(dev, xdp_chk))
6881 memset(&xdp, 0, sizeof(xdp)); 6910 return -EEXIST;
6882 xdp.command = XDP_QUERY_PROG; 6911 if ((flags & XDP_FLAGS_UPDATE_IF_NOEXIST) &&
6883 6912 __dev_xdp_attached(dev, xdp_op))
6884 err = xdp_op(dev, &xdp); 6913 return -EBUSY;
6885 if (err < 0)
6886 return err;
6887 if (xdp.prog_attached)
6888 return -EBUSY;
6889 }
6890 6914
6891 prog = bpf_prog_get_type(fd, BPF_PROG_TYPE_XDP); 6915 prog = bpf_prog_get_type(fd, BPF_PROG_TYPE_XDP);
6892 if (IS_ERR(prog)) 6916 if (IS_ERR(prog))
6893 return PTR_ERR(prog); 6917 return PTR_ERR(prog);
6894 } 6918 }
6895 6919
6896 memset(&xdp, 0, sizeof(xdp)); 6920 err = dev_xdp_install(dev, xdp_op, extack, prog);
6897 xdp.command = XDP_SETUP_PROG;
6898 xdp.extack = extack;
6899 xdp.prog = prog;
6900
6901 err = xdp_op(dev, &xdp);
6902 if (err < 0 && prog) 6921 if (err < 0 && prog)
6903 bpf_prog_put(prog); 6922 bpf_prog_put(prog);
6904 6923