Commit c8a36f19 authored by Andrii Nakryiko's avatar Andrii Nakryiko Committed by Alexei Starovoitov

bpf: xdp: Fix XDP mode when no mode flags specified

7f0a8382 ("bpf, xdp: Maintain info on attached XDP BPF programs in net_device")
inadvertently changed which XDP mode is assumed when no mode flags are
specified explicitly. Previously, driver mode was preferred, if driver
supported it. If not, generic SKB mode was chosen. That commit changed default
to SKB mode always. This patch fixes the issue and restores the original
logic.

Fixes: 7f0a8382 ("bpf, xdp: Maintain info on attached XDP BPF programs in net_device")
Reported-by: default avatarLorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: default avatarAndrii Nakryiko <andriin@fb.com>
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
Tested-by: default avatarLorenzo Bianconi <lorenzo@kernel.org>
Link: https://lore.kernel.org/bpf/20200820052841.1559757-1-andriin@fb.com
parent 5597432d
...@@ -8742,13 +8742,15 @@ struct bpf_xdp_link { ...@@ -8742,13 +8742,15 @@ struct bpf_xdp_link {
int flags; int flags;
}; };
static enum bpf_xdp_mode dev_xdp_mode(u32 flags) static enum bpf_xdp_mode dev_xdp_mode(struct net_device *dev, u32 flags)
{ {
if (flags & XDP_FLAGS_HW_MODE) if (flags & XDP_FLAGS_HW_MODE)
return XDP_MODE_HW; return XDP_MODE_HW;
if (flags & XDP_FLAGS_DRV_MODE) if (flags & XDP_FLAGS_DRV_MODE)
return XDP_MODE_DRV; return XDP_MODE_DRV;
return XDP_MODE_SKB; if (flags & XDP_FLAGS_SKB_MODE)
return XDP_MODE_SKB;
return dev->netdev_ops->ndo_bpf ? XDP_MODE_DRV : XDP_MODE_SKB;
} }
static bpf_op_t dev_xdp_bpf_op(struct net_device *dev, enum bpf_xdp_mode mode) static bpf_op_t dev_xdp_bpf_op(struct net_device *dev, enum bpf_xdp_mode mode)
...@@ -8896,7 +8898,7 @@ static int dev_xdp_attach(struct net_device *dev, struct netlink_ext_ack *extack ...@@ -8896,7 +8898,7 @@ static int dev_xdp_attach(struct net_device *dev, struct netlink_ext_ack *extack
return -EINVAL; return -EINVAL;
} }
mode = dev_xdp_mode(flags); mode = dev_xdp_mode(dev, flags);
/* can't replace attached link */ /* can't replace attached link */
if (dev_xdp_link(dev, mode)) { if (dev_xdp_link(dev, mode)) {
NL_SET_ERR_MSG(extack, "Can't replace active BPF XDP link"); NL_SET_ERR_MSG(extack, "Can't replace active BPF XDP link");
...@@ -8984,7 +8986,7 @@ static int dev_xdp_detach_link(struct net_device *dev, ...@@ -8984,7 +8986,7 @@ static int dev_xdp_detach_link(struct net_device *dev,
ASSERT_RTNL(); ASSERT_RTNL();
mode = dev_xdp_mode(link->flags); mode = dev_xdp_mode(dev, link->flags);
if (dev_xdp_link(dev, mode) != link) if (dev_xdp_link(dev, mode) != link)
return -EINVAL; return -EINVAL;
...@@ -9080,7 +9082,7 @@ static int bpf_xdp_link_update(struct bpf_link *link, struct bpf_prog *new_prog, ...@@ -9080,7 +9082,7 @@ static int bpf_xdp_link_update(struct bpf_link *link, struct bpf_prog *new_prog,
goto out_unlock; goto out_unlock;
} }
mode = dev_xdp_mode(xdp_link->flags); mode = dev_xdp_mode(xdp_link->dev, xdp_link->flags);
bpf_op = dev_xdp_bpf_op(xdp_link->dev, mode); bpf_op = dev_xdp_bpf_op(xdp_link->dev, mode);
err = dev_xdp_install(xdp_link->dev, mode, bpf_op, NULL, err = dev_xdp_install(xdp_link->dev, mode, bpf_op, NULL,
xdp_link->flags, new_prog); xdp_link->flags, new_prog);
...@@ -9164,7 +9166,7 @@ int bpf_xdp_link_attach(const union bpf_attr *attr, struct bpf_prog *prog) ...@@ -9164,7 +9166,7 @@ int bpf_xdp_link_attach(const union bpf_attr *attr, struct bpf_prog *prog)
int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack, int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
int fd, int expected_fd, u32 flags) int fd, int expected_fd, u32 flags)
{ {
enum bpf_xdp_mode mode = dev_xdp_mode(flags); enum bpf_xdp_mode mode = dev_xdp_mode(dev, flags);
struct bpf_prog *new_prog = NULL, *old_prog = NULL; struct bpf_prog *new_prog = NULL, *old_prog = NULL;
int err; int err;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment