Commit ddf9f970 authored by Jakub Kicinski's avatar Jakub Kicinski Committed by David S. Miller

xdp: propagate extended ack to XDP setup

Drivers usually have a number of restrictions for running XDP
- most common being buffer sizes, LRO and number of rings.
Even though some drivers try to be helpful and print error
messages experience shows that users don't often consult
kernel logs on netlink errors.  Try to use the new extended
ack mechanism to carry the message back to user space.
Signed-off-by: default avatarJakub Kicinski <jakub.kicinski@netronome.com>
Acked-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 45d9b378
...@@ -813,11 +813,16 @@ enum xdp_netdev_command { ...@@ -813,11 +813,16 @@ enum xdp_netdev_command {
XDP_QUERY_PROG, XDP_QUERY_PROG,
}; };
struct netlink_ext_ack;
struct netdev_xdp { struct netdev_xdp {
enum xdp_netdev_command command; enum xdp_netdev_command command;
union { union {
/* XDP_SETUP_PROG */ /* XDP_SETUP_PROG */
struct {
struct bpf_prog *prog; struct bpf_prog *prog;
struct netlink_ext_ack *extack;
};
/* XDP_QUERY_PROG */ /* XDP_QUERY_PROG */
bool prog_attached; bool prog_attached;
}; };
...@@ -3291,7 +3296,8 @@ int dev_get_phys_port_id(struct net_device *dev, ...@@ -3291,7 +3296,8 @@ int dev_get_phys_port_id(struct net_device *dev,
int dev_get_phys_port_name(struct net_device *dev, int dev_get_phys_port_name(struct net_device *dev,
char *name, size_t len); char *name, size_t len);
int dev_change_proto_down(struct net_device *dev, bool proto_down); int dev_change_proto_down(struct net_device *dev, bool proto_down);
int dev_change_xdp_fd(struct net_device *dev, int fd, u32 flags); int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
int fd, u32 flags);
struct sk_buff *validate_xmit_skb_list(struct sk_buff *skb, struct net_device *dev); struct sk_buff *validate_xmit_skb_list(struct sk_buff *skb, struct net_device *dev);
struct sk_buff *dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, struct sk_buff *dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
struct netdev_queue *txq, int *ret); struct netdev_queue *txq, int *ret);
......
...@@ -6854,12 +6854,14 @@ EXPORT_SYMBOL(dev_change_proto_down); ...@@ -6854,12 +6854,14 @@ EXPORT_SYMBOL(dev_change_proto_down);
/** /**
* dev_change_xdp_fd - set or clear a bpf program for a device rx path * dev_change_xdp_fd - set or clear a bpf program for a device rx path
* @dev: device * @dev: device
* @extact: netlink extended ack
* @fd: new program fd or negative value to clear * @fd: new program fd or negative value to clear
* @flags: xdp-related flags * @flags: xdp-related flags
* *
* Set or clear a bpf program for a device * Set or clear a bpf program for a device
*/ */
int dev_change_xdp_fd(struct net_device *dev, int fd, u32 flags) int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
int fd, u32 flags)
{ {
int (*xdp_op)(struct net_device *dev, struct netdev_xdp *xdp); int (*xdp_op)(struct net_device *dev, struct netdev_xdp *xdp);
const struct net_device_ops *ops = dev->netdev_ops; const struct net_device_ops *ops = dev->netdev_ops;
...@@ -6892,6 +6894,7 @@ int dev_change_xdp_fd(struct net_device *dev, int fd, u32 flags) ...@@ -6892,6 +6894,7 @@ int dev_change_xdp_fd(struct net_device *dev, int fd, u32 flags)
memset(&xdp, 0, sizeof(xdp)); memset(&xdp, 0, sizeof(xdp));
xdp.command = XDP_SETUP_PROG; xdp.command = XDP_SETUP_PROG;
xdp.extack = extack;
xdp.prog = prog; xdp.prog = prog;
err = xdp_op(dev, &xdp); err = xdp_op(dev, &xdp);
......
...@@ -1919,6 +1919,7 @@ static int do_set_master(struct net_device *dev, int ifindex) ...@@ -1919,6 +1919,7 @@ static int do_set_master(struct net_device *dev, int ifindex)
#define DO_SETLINK_NOTIFY 0x03 #define DO_SETLINK_NOTIFY 0x03
static int do_setlink(const struct sk_buff *skb, static int do_setlink(const struct sk_buff *skb,
struct net_device *dev, struct ifinfomsg *ifm, struct net_device *dev, struct ifinfomsg *ifm,
struct netlink_ext_ack *extack,
struct nlattr **tb, char *ifname, int status) struct nlattr **tb, char *ifname, int status)
{ {
const struct net_device_ops *ops = dev->netdev_ops; const struct net_device_ops *ops = dev->netdev_ops;
...@@ -2201,7 +2202,7 @@ static int do_setlink(const struct sk_buff *skb, ...@@ -2201,7 +2202,7 @@ static int do_setlink(const struct sk_buff *skb,
} }
if (xdp[IFLA_XDP_FD]) { if (xdp[IFLA_XDP_FD]) {
err = dev_change_xdp_fd(dev, err = dev_change_xdp_fd(dev, extack,
nla_get_s32(xdp[IFLA_XDP_FD]), nla_get_s32(xdp[IFLA_XDP_FD]),
xdp_flags); xdp_flags);
if (err) if (err)
...@@ -2261,7 +2262,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -2261,7 +2262,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh,
if (err < 0) if (err < 0)
goto errout; goto errout;
err = do_setlink(skb, dev, ifm, tb, ifname, 0); err = do_setlink(skb, dev, ifm, extack, tb, ifname, 0);
errout: errout:
return err; return err;
} }
...@@ -2423,6 +2424,7 @@ EXPORT_SYMBOL(rtnl_create_link); ...@@ -2423,6 +2424,7 @@ EXPORT_SYMBOL(rtnl_create_link);
static int rtnl_group_changelink(const struct sk_buff *skb, static int rtnl_group_changelink(const struct sk_buff *skb,
struct net *net, int group, struct net *net, int group,
struct ifinfomsg *ifm, struct ifinfomsg *ifm,
struct netlink_ext_ack *extack,
struct nlattr **tb) struct nlattr **tb)
{ {
struct net_device *dev, *aux; struct net_device *dev, *aux;
...@@ -2430,7 +2432,7 @@ static int rtnl_group_changelink(const struct sk_buff *skb, ...@@ -2430,7 +2432,7 @@ static int rtnl_group_changelink(const struct sk_buff *skb,
for_each_netdev_safe(net, dev, aux) { for_each_netdev_safe(net, dev, aux) {
if (dev->group == group) { if (dev->group == group) {
err = do_setlink(skb, dev, ifm, tb, NULL, 0); err = do_setlink(skb, dev, ifm, extack, tb, NULL, 0);
if (err < 0) if (err < 0)
return err; return err;
} }
...@@ -2576,14 +2578,15 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -2576,14 +2578,15 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh,
status |= DO_SETLINK_NOTIFY; status |= DO_SETLINK_NOTIFY;
} }
return do_setlink(skb, dev, ifm, tb, ifname, status); return do_setlink(skb, dev, ifm, extack, tb, ifname,
status);
} }
if (!(nlh->nlmsg_flags & NLM_F_CREATE)) { if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
if (ifm->ifi_index == 0 && tb[IFLA_GROUP]) if (ifm->ifi_index == 0 && tb[IFLA_GROUP])
return rtnl_group_changelink(skb, net, return rtnl_group_changelink(skb, net,
nla_get_u32(tb[IFLA_GROUP]), nla_get_u32(tb[IFLA_GROUP]),
ifm, tb); ifm, extack, tb);
return -ENODEV; return -ENODEV;
} }
......
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