The current way of passing parameters from userland/rtnetlink (do_set_link()) to dev_change_xdp_fd() and in the end to the drivers separately does not scale a lot: each new parameter/argument requires changing the prototypes of several functions at once. To be able to pass more, derive them into a structure which for now will contain: * dev, the actual netdevice, * extack, Netlink extack to pass arbitrary messages to userland, * flags, XDP install flags passed from the user. and use it in the following functions instead of the separate arguments: dev_change_xdp_fd(), dev_xdp_attach() and dev_xdp_install(). Adjust the rest accordingly. Those three are being used in the whole chain 'user -> driver', the rest can {,dis}appear later, thus not included. Signed-off-by: Alexander Lobakin <alexandr.lobakin@xxxxxxxxx> --- include/linux/netdevice.h | 10 +++++-- net/bpf/dev.c | 61 ++++++++++++++++++++++++--------------- net/core/rtnetlink.c | 10 +++++-- 3 files changed, 53 insertions(+), 28 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 0b8169c23f22..1e342c285f48 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -3848,11 +3848,17 @@ struct sk_buff *validate_xmit_skb_list(struct sk_buff *skb, struct net_device *d struct sk_buff *dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, struct netdev_queue *txq, int *ret); +struct xdp_install_args { + struct net_device *dev; + struct netlink_ext_ack *extack; + u32 flags; +}; + DECLARE_STATIC_KEY_FALSE(generic_xdp_needed_key); 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 fd, int expected_fd, u32 flags); +int dev_change_xdp_fd(const struct xdp_install_args *args, int fd, + int expected_fd); void dev_xdp_uninstall(struct net_device *dev); u8 dev_xdp_prog_count(struct net_device *dev); u32 dev_xdp_prog_id(struct net_device *dev, enum bpf_xdp_mode mode); diff --git a/net/bpf/dev.c b/net/bpf/dev.c index 0010b20719e8..7df42bb886ad 100644 --- a/net/bpf/dev.c +++ b/net/bpf/dev.c @@ -350,17 +350,17 @@ static void dev_xdp_set_prog(struct net_device *dev, enum bpf_xdp_mode mode, dev->xdp_state[mode].prog = prog; } -static int dev_xdp_install(struct net_device *dev, enum bpf_xdp_mode mode, - bpf_op_t bpf_op, struct netlink_ext_ack *extack, - u32 flags, struct bpf_prog *prog) +static int dev_xdp_install(const struct xdp_install_args *args, + enum bpf_xdp_mode mode, bpf_op_t bpf_op, + struct bpf_prog *prog) { struct netdev_bpf xdp; int err; memset(&xdp, 0, sizeof(xdp)); xdp.command = mode == XDP_MODE_HW ? XDP_SETUP_PROG_HW : XDP_SETUP_PROG; - xdp.extack = extack; - xdp.flags = flags; + xdp.extack = args->extack; + xdp.flags = args->flags; xdp.prog = prog; /* Drivers assume refcnt is already incremented (i.e, prog pointer is @@ -371,7 +371,7 @@ static int dev_xdp_install(struct net_device *dev, enum bpf_xdp_mode mode, */ if (prog) bpf_prog_inc(prog); - err = bpf_op(dev, &xdp); + err = bpf_op(args->dev, &xdp); if (err) { if (prog) bpf_prog_put(prog); @@ -379,13 +379,16 @@ static int dev_xdp_install(struct net_device *dev, enum bpf_xdp_mode mode, } if (mode != XDP_MODE_HW) - bpf_prog_change_xdp(dev_xdp_prog(dev, mode), prog); + bpf_prog_change_xdp(dev_xdp_prog(args->dev, mode), prog); return 0; } void dev_xdp_uninstall(struct net_device *dev) { + struct xdp_install_args args = { + .dev = dev, + }; struct bpf_xdp_link *link; struct bpf_prog *prog; enum bpf_xdp_mode mode; @@ -402,7 +405,7 @@ void dev_xdp_uninstall(struct net_device *dev) if (!bpf_op) continue; - WARN_ON(dev_xdp_install(dev, mode, bpf_op, NULL, 0, NULL)); + WARN_ON(dev_xdp_install(&args, mode, bpf_op, NULL)); /* auto-detach link from net device */ link = dev_xdp_link(dev, mode); @@ -415,13 +418,16 @@ void dev_xdp_uninstall(struct net_device *dev) } } -static int dev_xdp_attach(struct net_device *dev, struct netlink_ext_ack *extack, +static int dev_xdp_attach(const struct xdp_install_args *args, struct bpf_xdp_link *link, struct bpf_prog *new_prog, - struct bpf_prog *old_prog, u32 flags) + struct bpf_prog *old_prog) { - unsigned int num_modes = hweight32(flags & XDP_FLAGS_MODES); + unsigned int num_modes = hweight32(args->flags & XDP_FLAGS_MODES); + struct netlink_ext_ack *extack = args->extack; + struct net_device *dev = args->dev; struct bpf_prog *cur_prog; struct net_device *upper; + u32 flags = args->flags; struct list_head *iter; enum bpf_xdp_mode mode; bpf_op_t bpf_op; @@ -519,7 +525,7 @@ static int dev_xdp_attach(struct net_device *dev, struct netlink_ext_ack *extack return -EOPNOTSUPP; } - err = dev_xdp_install(dev, mode, bpf_op, extack, flags, new_prog); + err = dev_xdp_install(args, mode, bpf_op, new_prog); if (err) return err; } @@ -536,12 +542,20 @@ static int dev_xdp_attach(struct net_device *dev, struct netlink_ext_ack *extack static int dev_xdp_attach_link(struct bpf_xdp_link *link) { - return dev_xdp_attach(link->dev, NULL, link, NULL, NULL, link->flags); + struct xdp_install_args args = { + .dev = link->dev, + .flags = link->flags, + }; + + return dev_xdp_attach(&args, link, NULL, NULL); } static int dev_xdp_detach_link(struct bpf_xdp_link *link) { struct net_device *dev = link->dev; + struct xdp_install_args args = { + .dev = dev, + }; enum bpf_xdp_mode mode; bpf_op_t bpf_op; @@ -552,7 +566,7 @@ static int dev_xdp_detach_link(struct bpf_xdp_link *link) return -EINVAL; bpf_op = dev_xdp_bpf_op(dev, mode); - WARN_ON(dev_xdp_install(dev, mode, bpf_op, NULL, 0, NULL)); + WARN_ON(dev_xdp_install(&args, mode, bpf_op, NULL)); dev_xdp_set_link(dev, mode, NULL); return 0; } @@ -622,6 +636,10 @@ static int bpf_xdp_link_update(struct bpf_link *link, struct bpf_prog *old_prog) { struct bpf_xdp_link *xdp_link = container_of(link, struct bpf_xdp_link, link); + struct xdp_install_args args = { + .dev = xdp_link->dev, + .flags = xdp_link->flags, + }; enum bpf_xdp_mode mode; bpf_op_t bpf_op; int err = 0; @@ -653,8 +671,7 @@ static int bpf_xdp_link_update(struct bpf_link *link, mode = dev_xdp_mode(xdp_link->dev, xdp_link->flags); bpf_op = dev_xdp_bpf_op(xdp_link->dev, mode); - err = dev_xdp_install(xdp_link->dev, mode, bpf_op, NULL, - xdp_link->flags, new_prog); + err = dev_xdp_install(&args, mode, bpf_op, new_prog); if (err) goto out_unlock; @@ -730,18 +747,16 @@ int bpf_xdp_link_attach(const union bpf_attr *attr, struct bpf_prog *prog) /** * dev_change_xdp_fd - set or clear a bpf program for a device rx path - * @dev: device - * @extack: netlink extended ack + * @args: common XDP arguments (device, extended ack, flags etc.) * @fd: new program fd or negative value to clear * @expected_fd: old program fd that userspace expects to replace or clear - * @flags: xdp-related flags * * Set or clear a bpf program for a device */ -int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack, - int fd, int expected_fd, u32 flags) +int dev_change_xdp_fd(const struct xdp_install_args *args, int fd, + int expected_fd) { - enum bpf_xdp_mode mode = dev_xdp_mode(dev, flags); + enum bpf_xdp_mode mode = dev_xdp_mode(args->dev, args->flags); struct bpf_prog *new_prog = NULL, *old_prog = NULL; int err; @@ -764,7 +779,7 @@ int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack, } } - err = dev_xdp_attach(dev, extack, NULL, new_prog, old_prog, flags); + err = dev_xdp_attach(args, NULL, new_prog, old_prog); err_out: if (err && new_prog) diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index ac45328607f7..5b06ded689b2 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -2987,6 +2987,11 @@ static int do_setlink(const struct sk_buff *skb, } if (xdp[IFLA_XDP_FD]) { + struct xdp_install_args args = { + .dev = dev, + .extack = extack, + .flags = xdp_flags, + }; int expected_fd = -1; if (xdp_flags & XDP_FLAGS_REPLACE) { @@ -2998,10 +3003,9 @@ static int do_setlink(const struct sk_buff *skb, nla_get_s32(xdp[IFLA_XDP_EXPECTED_FD]); } - err = dev_change_xdp_fd(dev, extack, + err = dev_change_xdp_fd(&args, nla_get_s32(xdp[IFLA_XDP_FD]), - expected_fd, - xdp_flags); + expected_fd); if (err) goto errout; status |= DO_SETLINK_NOTIFY; -- 2.36.1