Skip to content

Commit d4baa93

Browse files
anakryikoAlexei Starovoitov
authored and
Alexei Starovoitov
committed
bpf, xdp: Extract common XDP program attachment logic
Further refactor XDP attachment code. dev_change_xdp_fd() is split into two parts: getting bpf_progs from FDs and attachment logic, working with bpf_progs. This makes attachment logic a bit more straightforward and prepares code for bpf_xdp_link inclusion, which will share the common logic. Signed-off-by: Andrii Nakryiko <andriin@fb.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Link: https://lore.kernel.org/bpf/20200722064603.3350758-4-andriin@fb.com
1 parent 7f0a838 commit d4baa93

File tree

1 file changed

+91
-74
lines changed

1 file changed

+91
-74
lines changed

net/core/dev.c

+91-74
Original file line numberDiff line numberDiff line change
@@ -8815,111 +8815,128 @@ static void dev_xdp_uninstall(struct net_device *dev)
88158815
}
88168816
}
88178817

8818-
/**
8819-
* dev_change_xdp_fd - set or clear a bpf program for a device rx path
8820-
* @dev: device
8821-
* @extack: netlink extended ack
8822-
* @fd: new program fd or negative value to clear
8823-
* @expected_fd: old program fd that userspace expects to replace or clear
8824-
* @flags: xdp-related flags
8825-
*
8826-
* Set or clear a bpf program for a device
8827-
*/
8828-
int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
8829-
int fd, int expected_fd, u32 flags)
8818+
static int dev_xdp_attach(struct net_device *dev, struct netlink_ext_ack *extack,
8819+
struct bpf_prog *new_prog, struct bpf_prog *old_prog,
8820+
u32 flags)
88308821
{
8831-
const struct net_device_ops *ops = dev->netdev_ops;
8832-
enum bpf_xdp_mode mode = dev_xdp_mode(flags);
8833-
bool offload = mode == XDP_MODE_HW;
8834-
u32 prog_id, expected_id = 0;
8835-
struct bpf_prog *prog;
8822+
struct bpf_prog *cur_prog;
8823+
enum bpf_xdp_mode mode;
88368824
bpf_op_t bpf_op;
88378825
int err;
88388826

88398827
ASSERT_RTNL();
88408828

8841-
bpf_op = dev_xdp_bpf_op(dev, mode);
8842-
if (!bpf_op) {
8843-
NL_SET_ERR_MSG(extack, "underlying driver does not support XDP in native mode");
8844-
return -EOPNOTSUPP;
8829+
/* just one XDP mode bit should be set, zero defaults to SKB mode */
8830+
if (hweight32(flags & XDP_FLAGS_MODES) > 1) {
8831+
NL_SET_ERR_MSG(extack, "Only one XDP mode flag can be set");
8832+
return -EINVAL;
8833+
}
8834+
/* old_prog != NULL implies XDP_FLAGS_REPLACE is set */
8835+
if (old_prog && !(flags & XDP_FLAGS_REPLACE)) {
8836+
NL_SET_ERR_MSG(extack, "XDP_FLAGS_REPLACE is not specified");
8837+
return -EINVAL;
88458838
}
88468839

8847-
prog_id = dev_xdp_prog_id(dev, mode);
8848-
if (flags & XDP_FLAGS_REPLACE) {
8849-
if (expected_fd >= 0) {
8850-
prog = bpf_prog_get_type_dev(expected_fd,
8851-
BPF_PROG_TYPE_XDP,
8852-
bpf_op == ops->ndo_bpf);
8853-
if (IS_ERR(prog))
8854-
return PTR_ERR(prog);
8855-
expected_id = prog->aux->id;
8856-
bpf_prog_put(prog);
8857-
}
8858-
8859-
if (prog_id != expected_id) {
8860-
NL_SET_ERR_MSG(extack, "Active program does not match expected");
8861-
return -EEXIST;
8862-
}
8840+
mode = dev_xdp_mode(flags);
8841+
cur_prog = dev_xdp_prog(dev, mode);
8842+
if ((flags & XDP_FLAGS_REPLACE) && cur_prog != old_prog) {
8843+
NL_SET_ERR_MSG(extack, "Active program does not match expected");
8844+
return -EEXIST;
88638845
}
8864-
if (fd >= 0) {
8846+
if ((flags & XDP_FLAGS_UPDATE_IF_NOEXIST) && cur_prog) {
8847+
NL_SET_ERR_MSG(extack, "XDP program already attached");
8848+
return -EBUSY;
8849+
}
8850+
8851+
if (new_prog) {
8852+
bool offload = mode == XDP_MODE_HW;
88658853
enum bpf_xdp_mode other_mode = mode == XDP_MODE_SKB
88668854
? XDP_MODE_DRV : XDP_MODE_SKB;
88678855

8868-
if (!offload && dev_xdp_prog_id(dev, other_mode)) {
8856+
if (!offload && dev_xdp_prog(dev, other_mode)) {
88698857
NL_SET_ERR_MSG(extack, "Native and generic XDP can't be active at the same time");
88708858
return -EEXIST;
88718859
}
8872-
8873-
if ((flags & XDP_FLAGS_UPDATE_IF_NOEXIST) && prog_id) {
8874-
NL_SET_ERR_MSG(extack, "XDP program already attached");
8875-
return -EBUSY;
8876-
}
8877-
8878-
prog = bpf_prog_get_type_dev(fd, BPF_PROG_TYPE_XDP,
8879-
bpf_op == ops->ndo_bpf);
8880-
if (IS_ERR(prog))
8881-
return PTR_ERR(prog);
8882-
8883-
if (!offload && bpf_prog_is_dev_bound(prog->aux)) {
8860+
if (!offload && bpf_prog_is_dev_bound(new_prog->aux)) {
88848861
NL_SET_ERR_MSG(extack, "Using device-bound program without HW_MODE flag is not supported");
8885-
bpf_prog_put(prog);
88868862
return -EINVAL;
88878863
}
8888-
8889-
if (prog->expected_attach_type == BPF_XDP_DEVMAP) {
8864+
if (new_prog->expected_attach_type == BPF_XDP_DEVMAP) {
88908865
NL_SET_ERR_MSG(extack, "BPF_XDP_DEVMAP programs can not be attached to a device");
8891-
bpf_prog_put(prog);
88928866
return -EINVAL;
88938867
}
8894-
8895-
if (prog->expected_attach_type == BPF_XDP_CPUMAP) {
8896-
NL_SET_ERR_MSG(extack,
8897-
"BPF_XDP_CPUMAP programs can not be attached to a device");
8898-
bpf_prog_put(prog);
8868+
if (new_prog->expected_attach_type == BPF_XDP_CPUMAP) {
8869+
NL_SET_ERR_MSG(extack, "BPF_XDP_CPUMAP programs can not be attached to a device");
88998870
return -EINVAL;
89008871
}
8872+
}
89018873

8902-
/* prog->aux->id may be 0 for orphaned device-bound progs */
8903-
if (prog->aux->id && prog->aux->id == prog_id) {
8904-
bpf_prog_put(prog);
8905-
return 0;
8874+
/* don't call drivers if the effective program didn't change */
8875+
if (new_prog != cur_prog) {
8876+
bpf_op = dev_xdp_bpf_op(dev, mode);
8877+
if (!bpf_op) {
8878+
NL_SET_ERR_MSG(extack, "Underlying driver does not support XDP in native mode");
8879+
return -EOPNOTSUPP;
89068880
}
8907-
} else {
8908-
if (!prog_id)
8909-
return 0;
8910-
prog = NULL;
8911-
}
89128881

8913-
err = dev_xdp_install(dev, mode, bpf_op, extack, flags, prog);
8914-
if (err < 0 && prog) {
8915-
bpf_prog_put(prog);
8916-
return err;
8882+
err = dev_xdp_install(dev, mode, bpf_op, extack, flags, new_prog);
8883+
if (err)
8884+
return err;
89178885
}
8918-
dev_xdp_set_prog(dev, mode, prog);
8886+
8887+
dev_xdp_set_prog(dev, mode, new_prog);
8888+
if (cur_prog)
8889+
bpf_prog_put(cur_prog);
89198890

89208891
return 0;
89218892
}
89228893

8894+
/**
8895+
* dev_change_xdp_fd - set or clear a bpf program for a device rx path
8896+
* @dev: device
8897+
* @extack: netlink extended ack
8898+
* @fd: new program fd or negative value to clear
8899+
* @expected_fd: old program fd that userspace expects to replace or clear
8900+
* @flags: xdp-related flags
8901+
*
8902+
* Set or clear a bpf program for a device
8903+
*/
8904+
int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
8905+
int fd, int expected_fd, u32 flags)
8906+
{
8907+
enum bpf_xdp_mode mode = dev_xdp_mode(flags);
8908+
struct bpf_prog *new_prog = NULL, *old_prog = NULL;
8909+
int err;
8910+
8911+
ASSERT_RTNL();
8912+
8913+
if (fd >= 0) {
8914+
new_prog = bpf_prog_get_type_dev(fd, BPF_PROG_TYPE_XDP,
8915+
mode != XDP_MODE_SKB);
8916+
if (IS_ERR(new_prog))
8917+
return PTR_ERR(new_prog);
8918+
}
8919+
8920+
if (expected_fd >= 0) {
8921+
old_prog = bpf_prog_get_type_dev(expected_fd, BPF_PROG_TYPE_XDP,
8922+
mode != XDP_MODE_SKB);
8923+
if (IS_ERR(old_prog)) {
8924+
err = PTR_ERR(old_prog);
8925+
old_prog = NULL;
8926+
goto err_out;
8927+
}
8928+
}
8929+
8930+
err = dev_xdp_attach(dev, extack, new_prog, old_prog, flags);
8931+
8932+
err_out:
8933+
if (err && new_prog)
8934+
bpf_prog_put(new_prog);
8935+
if (old_prog)
8936+
bpf_prog_put(old_prog);
8937+
return err;
8938+
}
8939+
89238940
/**
89248941
* dev_new_index - allocate an ifindex
89258942
* @net: the applicable net namespace

0 commit comments

Comments
 (0)